Changeset 809
- Timestamp:
- 11/30/06 12:21:06 (2 years ago)
- Files:
-
- branches/wheeljack/lib/MT/App/CMS.pm (modified) (24 diffs)
- branches/wheeljack/tmpl/cms/backup_files.tmpl (modified) (1 diff)
- branches/wheeljack/tmpl/cms/dialog_restore_end.tmpl (modified) (1 diff)
- branches/wheeljack/tmpl/cms/dialog_restore_upload.tmpl (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/wheeljack/lib/MT/App/CMS.pm
r806 r809 152 152 'backup' => \&backup, 153 153 'restore' => \&restore, 154 'backup_download' => \&backup_download,155 154 'restore_upload_manifest' => \&restore_upload_manifest, 156 155 'dialog_restore_upload' => \&dialog_restore_upload, … … 10825 10824 sub _loop_through_objects { 10826 10825 my $app = shift; 10827 my ($printer, $splitter, $number, $obj_to_backup ) = @_;10826 my ($printer, $splitter, $number, $obj_to_backup, $files) = @_; 10828 10827 10829 10828 my $counter = 0; … … 10845 10844 $splitter->(int($counter / $number + 1)); 10846 10845 } 10847 $printer->($object->to_xml . "\n") if $object->to_backup; 10846 if ($class eq 'MT::Asset') { 10847 $printer->($object->to_xml . "\n") if $object->to_backup; 10848 $files->{$object->id} = [$object->url, $object->file_path, $object->file_name]; 10849 } else { 10850 $printer->($object->to_xml . "\n") if $object->to_backup; 10851 } 10848 10852 my $xml = MT->run_callbacks('CMSBackup.' . $object->datasource, $app, $object) 10849 10853 or $printer->($app->error(MT->errstr())); … … 10882 10886 } 10883 10887 10888 require MT::Asset; 10889 my $num_assets = MT::Asset->count(); 10884 10890 my $printer; 10885 10891 my $splitter; … … 10887 10893 my $fh; 10888 10894 my $arc_buf; 10889 if (! $number) {10895 if (!($number || $num_assets)) { 10890 10896 $app->{no_print_body} = 1; 10891 10897 $splitter = sub {}; … … 10895 10901 : 'text/xml'); 10896 10902 $printer = sub { $app->print(@_); }; 10897 $finisher = sub { };10903 $finisher = sub { my ($asset_files) = @_; 1; }; 10898 10904 } elsif ('1' eq $archive) { # tar.gz 10899 10905 require Archive::Tar; … … 10903 10909 $printer = sub { $arc_buf .= $_[0]; }; 10904 10910 $finisher = sub { 10911 my ($asset_files) = @_; 10905 10912 my $arc = Archive::Tar->new; 10906 10913 $arc->add_data("$file.xml", $arc_buf); 10914 $arc->add_data( 10915 "$file.manifest", 10916 "<manifest xmlns='" . NS_MOVABLETYPE . "'><file type='backup' name='$file.xml' /></manifest>"); 10907 10917 require Compress::Zlib; 10908 10918 my $dest = Compress::Zlib::memGzip($arc->write); … … 10915 10925 $printer = sub { $arc_buf .= $_[0]; }; 10916 10926 $finisher = sub { 10927 my ($asset_files) = @_; 10917 10928 my $arc = Archive::Zip->new; 10918 10929 $arc->addString($arc_buf, "$file.xml"); 10930 $arc->addString( 10931 "<manifest xmlns='" . NS_MOVABLETYPE . "'><file type='backup' name='$file.xml' /></manifest>", 10932 "$file.manifest"); 10919 10933 my $buf; 10920 10934 require IO::String; … … 10945 10959 }; 10946 10960 $finisher = sub { 10961 my ($asset_files) = @_; 10947 10962 close $fh; 10948 10963 my $filename = File::Spec->catfile($temp_dir, "$file.manifest"); … … 10953 10968 my $name = $file->{filename}; 10954 10969 print $fh "<file type='backup' name='$name' />\n"; 10970 } 10971 for my $id (keys %$asset_files) { 10972 print $fh "<file type='asset' name='$asset_files->{$id}->[2]' asset_id='" . $id . "' />\n"; 10973 push @files, { 10974 filename => $asset_files->{$id}->[2], 10975 url=> $asset_files->{$id}->[0], 10976 path => $asset_files->{$id}->[1], 10977 asset_id => $id, 10978 }; 10955 10979 } 10956 10980 print $fh "</manifest>\n"; … … 10970 10994 my $arc = Archive::Tar->new; 10971 10995 for my $f (@files) { 10972 $arc->add_files(File::Spec->catfile($temp_dir, $f->{filename})); 10996 if (defined $f->{path}) { 10997 my @arc_files = $arc->add_files($f->{path}); 10998 $arc_files[0]->rename($f->{asset_id} . '-' . $f->{filename}) if scalar(@arc_files); 10999 } else { 11000 my $tmp_filename = File::Spec->catfile($temp_dir, $f->{filename}); 11001 my @arc_files = $arc->add_files($tmp_filename); 11002 $arc_files[0]->rename($f->{filename}); 11003 unlink $tmp_filename; 11004 } 10973 11005 } 10974 11006 require Compress::Zlib; … … 10985 11017 $app->send_http_header('application/zip'); 10986 11018 for my $f (@files) { 10987 $arc->addFile(File::Spec->catfile($temp_dir, $f->{filename}), $f->{filename}); 11019 if (defined $f->{path}) { 11020 $arc->addFile($f->{path}, $f->{asset_id} . '-' . $f->{filename}); 11021 } else { 11022 my $tmp_filename = File::Spec->catfile($temp_dir, $f->{filename}); 11023 $arc->addFile($tmp_filename, $f->{filename}); 11024 } 10988 11025 } 10989 11026 my $buf; … … 10991 11028 my $ios = IO::String->new(\$buf); 10992 11029 $arc->writeToFileHandle($ios); 11030 for my $f (@files) { 11031 unlink File::Spec->catfile($temp_dir, $f->{filename}) if !defined($f->{path}); 11032 } 10993 11033 $app->print($buf); 10994 11034 } … … 11010 11050 $printer->($header); 11011 11051 11012 $app->_loop_through_objects($printer, $splitter, $number, \@obj_to_backup); 11052 my $files = {}; 11053 $app->_loop_through_objects($printer, $splitter, $number, \@obj_to_backup, $files); 11013 11054 11014 11055 $printer->('</movabletype>'); 11015 $finisher->( );11056 $finisher->($files); 11016 11057 } 11017 11058 … … 11032 11073 11033 11074 $app->errtrans("Not implemented yet"); 11034 }11035 11036 sub backup_download {11037 my $app = shift;11038 my $user = $app->user;11039 11040 return $app->errtrans("Permission denied.") if !$user->is_superuser;11041 $app->validate_magic() or return;11042 11043 my $file = $app->param('file');11044 return $app->errtrans("Filename is needed to download.") if !defined($file) || !$file;11045 my $temp_dir = $app->config('TempDir');11046 my $filename = File::Spec->catfile($temp_dir, $file);11047 11048 return $app->errtrans("[_1] is not found.", $file) if (!(-f $filename));11049 11050 my $enc = $app->config('PublishCharset') || 'utf-8';11051 $app->{no_print_body} = 1;11052 $app->set_header("Content-Disposition" => "attachment; filename=$file");11053 $app->send_http_header($enc ? "text/xml; charset=$enc"11054 : 'text/xml');11055 my $fh = gensym();11056 open $fh, "<$filename";11057 my $data;11058 binmode $fh;11059 while (read $fh, my($chunk), 8192) {11060 $data .= $chunk;11061 }11062 close $fh;11063 $app->print($data);11064 1;11065 11075 } 11066 11076 … … 11134 11144 my $tar = Archive::Tar->new($ios); 11135 11145 for my $file ($tar->list_files) { 11136 my ($vol, $dir, $fn) = File::Spec->splitpath($file); 11137 my $f = File::Spec->catfile($tmp, $fn); 11146 my $f = File::Spec->catfile($tmp, $file); 11138 11147 $tar->extract_file($file, $f); 11139 11148 } … … 11286 11295 } 11287 11296 11297 sub _restore_asset { 11298 my $app = shift; 11299 my ($tmp, $asset_element, $objects, $errors) = @_; 11300 11301 my $id = $asset_element->{asset_id}; 11302 next if !defined($id); 11303 next if !(exists $objects->{"MT::Asset#$id"}); 11304 my $asset = $objects->{"MT::Asset#$id"}; 11305 my $path = $asset->file_path; 11306 next if !defined($path); 11307 my ($vol, $dir, $fn) = File::Spec->splitpath($path); 11308 if (!-w "$vol$dir") { 11309 $errors->{$id} = $app->translate('[_1] is not writable.', "$vol$dir"); 11310 next; 11311 } 11312 my $filename = "$id-" . $asset_element->{name}; 11313 $app->print($app->translate("Copying [_1] to [_2]...", $filename, $path)); 11314 my $file; 11315 if (defined($tmp)) { 11316 $file = File::Spec->catfile($tmp, $filename) if defined($tmp); 11317 } else { 11318 $file = $asset_element->{fh}; 11319 } 11320 copy($file, $path) 11321 or $errors->{$id} = $!; 11322 $app->print(exists($errors->{$id}) ? 11323 $app->translate("Failed: [_1]\n", $errors->{$id}) : 11324 $app->translate("Done.\n") 11325 ); 11326 } 11327 11328 sub _restore_assets { 11329 my $app = shift; 11330 my ($tmp, $backups, $objects) = @_; 11331 my $assets = $backups->{assets}; 11332 my $errors = {}; 11333 return $errors if !defined($assets); 11334 use File::Copy; 11335 require File::Spec; 11336 for my $asset_element (@$assets) { 11337 $app->_restore_asset($tmp, $asset_element, $objects, $errors); 11338 } 11339 $errors; 11340 } 11341 11288 11342 sub restore_directory { 11289 11343 my $app = shift; … … 11348 11402 close $fh; 11349 11403 } 11404 11405 my $error_assets = $app->_restore_assets($dir, $backups, \%objects) if defined($backups->{assets}); 11406 11407 if (defined($error_assets) && scalar(keys %$error_assets)) { 11408 my $data; 11409 while (my ($key, $value) = each %$error_assets) { 11410 $data .= $app->translate("Actual file for an asset (ID: [_1]) could not be restored: [_2]\n", $key, $value); 11411 } 11412 my $message = 'Some of the actual files for assets could not be restored.'; 11413 $app->log({ 11414 message => $message, 11415 level => MT::Log::WARNING(), 11416 class => 'system', 11417 category => 'restore', 11418 metadata => $data, 11419 }); 11420 $$error .= $message; 11421 } 11350 11422 11351 11423 if (scalar(keys %deferred)) { … … 11363 11435 }); 11364 11436 my $log_url = $app->uri(mode => 'view_log', args => {}); 11365 $$error = $message . ' '11437 $$error .= $message . ' ' 11366 11438 . $app->translate('Detailed information is in the <a href="[_1]">activity log</a>.', $log_url); 11367 return 0; 11368 } 11439 } 11440 11441 return 0 if $$error; 11369 11442 11370 11443 $app->log({ … … 11402 11475 push @{$backups->{files}}, $node->getAttribute('name'); 11403 11476 } elsif ('asset' eq $node->getAttribute('type')) { 11404 push @{$backups->{assets}}, $node->getAttribute('name'); 11477 push @{$backups->{assets}}, { 11478 name => $node->getAttribute('name'), 11479 asset_id => $node->getAttribute('asset_id'), 11480 }; 11405 11481 } 11406 11482 } … … 11441 11517 my $assets = $backups->{assets}; 11442 11518 my $file_next = shift @$files if defined($files) && scalar(@$files); 11519 my $assets_json; 11520 my $param = {}; 11443 11521 if (!defined($file_next)) { 11444 $file_next = shift @$assets if defined($assets) && scalar(@$assets); 11445 } 11446 my $param = { 11447 'files' => join(',', @$files), 11448 'assets' => join(',', @$assets), 11449 'filename' => $file_next, 11450 'open_dialog' => 1, 11451 }; 11522 if (scalar(@$assets)) { 11523 my $asset = shift @$assets; 11524 $file_next = $asset->{name}; 11525 $param->{is_asset} = 1; 11526 } 11527 } 11528 require JSON; 11529 $assets_json = MT::Util::encode_html(JSON::objToJson($assets)) if scalar(@$assets); 11530 $param->{files} = join(',', @$files); 11531 $param->{assets} = $assets_json; 11532 $param->{filename} = $file_next; 11533 $param->{open_dialog} = 1; 11534 11452 11535 $app->build_page('backup_restore.tmpl', $param); 11453 11536 #close $fh if !$no_upload; … … 11465 11548 my $last = $q->param('last'); 11466 11549 my $files = $q->param('files'); 11467 my $assets = $q->param('assets'); 11550 my $assets_json = $q->param('assets'); 11551 my $is_asset = $q->param('is_asset') || 0; 11468 11552 11469 11553 my $objects = {}; … … 11488 11572 11489 11573 my $param = {}; 11574 $param->{is_asset} = $is_asset; 11490 11575 $param->{name} = $current; 11491 11576 $param->{files} = $files; 11492 $param->{assets} = $assets; 11493 $param->{name} = $current; 11577 $param->{assets} = $assets_json; 11494 11578 $param->{last} = $last; 11495 11579 $param->{redirect} = 1; … … 11560 11644 } 11561 11645 11562 my $result = $app->_restore_process_single_file( 11563 $fh, \@obj_to_restore, $objects, $deferred, \$error); 11646 my $assets = JSON::jsonToObj(MT::Util::decode_html($assets_json)) if defined($assets_json); 11647 my $asset; 11648 if ($is_asset) { 11649 $asset = shift @$assets; 11650 my $error_assets = {}; 11651 $asset->{fh} = $fh; 11652 $app->_restore_asset(undef, $asset, $objects, $error_assets); 11653 if (defined($error_assets->{$asset->{asset_id}})) { 11654 $app->log({ 11655 message => $app->translate('Restoring an actual file for an asset failed: [_1]', $error_assets->{$asset->{asset_id}}), 11656 level => MT::Log::WARNING(), 11657 class => 'system', 11658 category => 'restore', 11659 }); 11660 } 11661 } else { 11662 $app->_restore_process_single_file( 11663 $fh, \@obj_to_restore, $objects, $deferred, \$error); 11664 } 11564 11665 11565 11666 my @files = split(',', $files); 11566 my @assets;11567 11667 my $file_next = shift @files if scalar(@files); 11568 11668 if (!defined($file_next)) { 11569 @assets = split(',', $assets); 11570 $file_next = shift @assets if scalar(@assets); 11669 if (scalar(@$assets)) { 11670 $asset = $assets->[0]; 11671 $file_next = $asset->{asset_id} . '-' . $asset->{name}; 11672 $param->{is_asset} = 1; 11673 } 11571 11674 } 11572 11675 11573 11676 $param->{files} = join(',', @files); 11574 $param->{assets} = join(',', @assets);11677 $param->{assets} = MT::Util::encode_html(JSON::objToJson($assets)); 11575 11678 $param->{name} = $file_next; 11576 $param->{last} = (scalar(@files) || scalar(@assets)) ? 0 : 1;11679 $param->{last} = (scalar(@files) || (scalar(@$assets) - 1)) ? 0 : 1; 11577 11680 $param->{is_dirty} = scalar(keys %$deferred); 11578 11681 if ($last) { branches/wheeljack/tmpl/cms/backup_files.tmpl
r795 r809 28 28 <tr class="<TMPL_IF __ODD__>odd<TMPL_ELSE>even</TMPL_IF>"> 29 29 <td><TMPL_VAR NAME=FILENAME></td> 30 <td class="status-view">< a href="<TMPL_VAR NAME=SCRIPT_URL>?__mode=backup_download&magic_token=<TMPL_VAR NAME=MAGIC_TOKEN>&file=<TMPL_VAR NAME=FILENAME ESCAPE=URL>" target="<MT_TRANS phrase="_external_link_target">" title="<MT_TRANS phrase="Download This File">"><img src="<TMPL_VAR NAME=STATIC_URI>images/spacer.gif" alt="<MT_TRANS phrase="Download This File">" width="13" height="9" /></a></td>30 <td class="status-view"><TMPL_IF NAME=URL><a href="<TMPL_VAR NAME=URL>" target="<MT_TRANS phrase="_external_link_target">" title="<MT_TRANS phrase="Download This File">"><img src="<TMPL_VAR NAME=STATIC_URI>images/spacer.gif" alt="<MT_TRANS phrase="Download This File">" width="13" height="9" /></a><TMPL_ELSE> </TMPL_IF></td> 31 31 </tr> 32 32 </TMPL_LOOP> branches/wheeljack/tmpl/cms/dialog_restore_end.tmpl
r800 r809 38 38 <input type="hidden" name="redirect" value="1" /> 39 39 <input type="hidden" name="is_dirty" value="<TMPL_VAR NAME=IS_DIRTY>" /> 40 <input type="hidden" name="is_asset" value="<TMPL_VAR NAME=IS_ASSET>" /> 40 41 <input type="hidden" name="objects_json" value="<TMPL_VAR NAME=OBJECTS_JSON ESCAPE=HTML>" /> 41 42 <input type="hidden" name="deferred_json" value="<TMPL_VAR NAME=DEFERRED_JSON ESCAPE=HTML>" /> branches/wheeljack/tmpl/cms/dialog_restore_upload.tmpl
r800 r809 57 57 <input type="hidden" name="magic_token" value="<TMPL_VAR NAME=MAGIC_TOKEN>" /> 58 58 <input type="hidden" name="files" value="<TMPL_VAR NAME=FILES>" /> 59 <input type="hidden" name="assets" value="<TMPL_VAR NAME=ASSETS >" />59 <input type="hidden" name="assets" value="<TMPL_VAR NAME=ASSETS ESCAPE=HTML>" /> 60 60 <input type="hidden" name="current_file" value="<TMPL_VAR NAME=NAME>" /> 61 61 <input type="hidden" name="last" value="<TMPL_VAR NAME=LAST>" /> 62 62 <input type="hidden" name="is_dirty" value="<TMPL_VAR NAME=IS_DIRTY>" /> 63 <input type="hidden" name="is_asset" value="<TMPL_VAR NAME=IS_ASSET>" /> 63 64 <input type="hidden" name="objects_json" value="<TMPL_VAR NAME=OBJECTS_JSON ESCAPE=HTML>" /> 64 65 <input type="hidden" name="deferred_json" value="<TMPL_VAR NAME=DEFERRED_JSON ESCAPE=HTML>" />
