package GCBackend::GCBackendXmlCommon; ################################################### # # Copyright 2005-2010 Christian Jodar # # This file is part of GCstar. # # GCstar is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # GCstar is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GCstar; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA # ################################################### use strict; use utf8; use filetest 'access'; { package GCBackend::GCBeXmlBase; use File::Temp qw/ tempfile /; use File::Copy; my %xmlConv = ( '&' => '&', '"' => '"', '<' => '<', '>' => '>', '' => '', ); my $toBeReplaced = join '', keys %xmlConv; sub new { my ($proto, $modelLoader) = @_; my $class = ref($proto) || $proto; my $self = {modelLoader => $modelLoader}; bless $self, $class; return $self; } sub getVersion { my $self = shift; my $version = undef; return $version if (! -r $self->{file}); open DATA, $self->{file}; binmode(DATA, ':utf8'); while () { next if ! /^\s*) { if (/type="(.*?)"/) { $model = $1; last; } } close COLLECTION; $self->{modelLoader}->preloadModel($model); } sub setParameters { my ($self, %options) = @_; $self->{$_} = $options{$_} foreach keys %options; } sub hashToXMLString { my %hash = @_; my $result = ''; foreach (keys %hash) { $result .= " $_=\"".$hash{$_}.'"'; } return $result; } sub listToXml { my $value = shift; my $xml = ''; my $col; foreach (@{$value}) { $xml .= ' '; foreach $col(@{$_}) { (my $newCol = $col) =~ s/([$toBeReplaced])/$xmlConv{$1}/go; #" $xml .= " $newCol\n"; } $xml .= ' '; } return $xml; } sub setHistories { my ($self, $histories) = @_; $self->{histories} = $histories; } sub save { my ($self, $data, $info, $splash, $keepCurrentValueForDate) = @_; # Save into a new file to prevent crashes during saving (my ($tmpFd, $tmpFile)) = tempfile(); if (!$tmpFd) { my @error = ('SaveError', ''); return {error => \@error}; } binmode($tmpFd, ':utf8'); my $xmlModel = ''; my $xmlPreferences = ''; my $collectionType; my $versionString = ''; if (exists $self->{version}) { $versionString = ' version="'.$self->{version}.'"'; } if (($self->{modelLoader}->{model}->isInline) || ($self->{modelLoader}->{model}->isPersonal && $self->{standAlone})) { $xmlModel = $self->{modelLoader}->{model}->toString('collectionInlineDescription', 1); $xmlPreferences = $self->{modelLoader}->{model}->{preferences}->toXmlString; $collectionType = 'inline'; } else { $collectionType = $self->{modelLoader}->{model}->getName; $xmlModel = $self->{modelLoader}->{model}->toStringAddedFields('userCollection'); } my $information = ' '; $information .= " <$_>".GCUtils::encodeEntities($info->{$_})."\n" foreach (sort keys %{$info}); $information .= ' '; # Change this to 1 to save history. Not fully functional yet # Because we don't remove item that are no more present in data. my $withHistory = 0; my $histories; if ($withHistory) { $histories = ' '; foreach (keys %{$self->{histories}}) { $histories .= " \n"; foreach my $value(@{$self->{histories}->{$_}}) { if (ref($value) eq 'ARRAY') { $histories .= ' '; foreach my $entry(@$value) { next if $entry eq ''; $entry =~ GCUtils::encodeEntities($entry); $histories .= " $entry\n"; } $histories .= ' '; } else { next if $value eq ''; $histories .= ' '.GCUtils::encodeEntities($value)."\n"; } } $histories .= ' '; } $histories .= ' '; } my $number = 0; $number = scalar @$data; print $tmpFd ' ',$information,' ',$xmlModel,' ',$xmlPreferences,' ',$histories,' '; my $i = 1; foreach (@$data) { #Perform the transformation for each image value foreach my $pic(@{$self->{modelLoader}->{model}->{managedImages}}) { $_->{$pic} = $self->{modelLoader}->transformPicturePath($_->{$pic}, undef, $_, $pic); } print $tmpFd ' {modelLoader}->{model}->{fieldsNames}}) { if (ref($_->{$field}) eq 'ARRAY') { push @complexFields, $field; } elsif ($self->{modelLoader}->{model}->{fieldsInfo}->{$field}->{type} eq 'long text') { push @longFields, $field; } else { (my $data = $_->{$field}) =~ s/([$toBeReplaced])/$xmlConv{$1}/go; if (($self->{modelLoader}->{model}->{fieldsInfo}->{$field}->{type} eq 'date') && ($data eq 'current') && (!$keepCurrentValueForDate)) { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $data = sprintf('%02d/%02d/%4d', $mday, $mon+1, 1900+$year); } print $tmpFd ' ', $field, '="', $data, '" '; } } print $tmpFd ' > '; foreach my $field(@longFields) { #(my $data = $_->{$field}) =~ s/&/&/g; #$data =~ s//>/g; #$data =~ s/"/"/g; (my $data = $_->{$field}) =~ s/([$toBeReplaced])/$xmlConv{$1}/go; #" print $tmpFd ' <', $field, '>', $data, ' '; } foreach my $field(@complexFields) { print $tmpFd ' <', $field, '> ', listToXml($_->{$field}), ' '; } print $tmpFd ' '; $splash->setProgressForItemsDisplay($i) if $splash; $self->{modelLoader}->restoreInfo($_) if $self->{wantRestore}; $i++; } print $tmpFd ' '; close $tmpFd; # Now everything is OK, we move the temporary file over the correct one if (!move($tmpFile, $self->{file})) { my @error = ('SaveError', $!); return {error => \@error}; } return {error => undef}; } } 1;