Index: trunk/phase3/maintenance/importDump.php |
— | — | @@ -38,6 +38,7 @@ |
39 | 39 | var $dryRun = false; |
40 | 40 | var $debug = false; |
41 | 41 | var $uploads = false; |
| 42 | + var $imageBasePath = false; |
42 | 43 | var $nsFilter = false; |
43 | 44 | |
44 | 45 | function __construct() { |
— | — | @@ -201,6 +202,12 @@ |
202 | 203 | array( &$this, 'handleUpload' ) ); |
203 | 204 | $this->logItemCallback = $importer->setLogItemCallback( |
204 | 205 | array( &$this, 'handleLogItem' ) ); |
| 206 | + if ( $this->uploads ) { |
| 207 | + $importer->setImportUploads( true ); |
| 208 | + } |
| 209 | + if ( $this->imageBasePath ) { |
| 210 | + $importer->setImageBasePath( $this->imageBasePath ); |
| 211 | + } |
205 | 212 | |
206 | 213 | if ( $this->dryRun ) { |
207 | 214 | $importer->setPageOutCallback( null ); |
— | — | @@ -230,6 +237,7 @@ |
231 | 238 | echo " --dry-run Parse dump without actually importing pages.\n"; |
232 | 239 | echo " --debug Output extra verbose debug information\n"; |
233 | 240 | echo " --uploads Process file upload data if included (experimental)\n"; |
| 241 | + echo " --image-base-path=path Import files from a specified path\n"; |
234 | 242 | echo "\n"; |
235 | 243 | echo "Compressed XML files may be read directly:\n"; |
236 | 244 | echo " .gz $gz\n"; |
— | — | @@ -259,6 +267,9 @@ |
260 | 268 | if ( isset( $options['uploads'] ) ) { |
261 | 269 | $reader->uploads = true; // experimental! |
262 | 270 | } |
| 271 | +if ( isset( $options['image-base-path'] ) ) { |
| 272 | + $reader->imageBasePath = $options['image-base-path']; |
| 273 | +} |
263 | 274 | if ( isset( $options['namespaces'] ) ) { |
264 | 275 | $reader->setNsfilter( explode( '|', $options['namespaces'] ) ); |
265 | 276 | } |
Index: trunk/phase3/RELEASE-NOTES-1.19 |
— | — | @@ -25,6 +25,9 @@ |
26 | 26 | * (bug 28503) Support for ircs:// URL protocols |
27 | 27 | * (bug 26033) It is now possible to count all non-redirect pages in content |
28 | 28 | namespaces as articles |
| 29 | +* Images can now be embedded in an XML dump stream using backupDump.php |
| 30 | + --include-files and can be imported using importDump.php --uploads; |
| 31 | + furthermore, it can import files from the filesystem using --image-base-path |
29 | 32 | |
30 | 33 | === Bug fixes in 1.19 === |
31 | 34 | * (bug 10154) Don't allow user to specify days beyond $wgRCMaxAge. |
Index: trunk/phase3/includes/Import.php |
— | — | @@ -177,6 +177,9 @@ |
178 | 178 | public function setImageBasePath( $dir ) { |
179 | 179 | $this->mImageBasePath = $dir; |
180 | 180 | } |
| 181 | + public function setImportUploads( $import ) { |
| 182 | + $this->mImportUploads = $import; |
| 183 | + } |
181 | 184 | |
182 | 185 | /** |
183 | 186 | * Default per-revision callback, performs the import. |
— | — | @@ -612,6 +615,7 @@ |
613 | 616 | $encoding = $this->reader->getAttribute( 'encoding' ); |
614 | 617 | if ( $encoding === 'base64' ) { |
615 | 618 | $uploadInfo['fileSrc'] = $this->dumpTemp( base64_decode( $contents ) ); |
| 619 | + $uploadInfo['isTempSrc'] = true; |
616 | 620 | } |
617 | 621 | } elseif ( $tag != '#text' ) { |
618 | 622 | $this->warn( "Unhandled upload XML tag $tag" ); |
— | — | @@ -623,6 +627,7 @@ |
624 | 628 | $path = "{$this->mImageBasePath}/{$uploadInfo['rel']}"; |
625 | 629 | if ( file_exists( $path ) ) { |
626 | 630 | $uploadInfo['fileSrc'] = $path; |
| 631 | + $uploadInfo['isTempSrc'] = false; |
627 | 632 | } |
628 | 633 | } |
629 | 634 | |
— | — | @@ -652,8 +657,12 @@ |
653 | 658 | } |
654 | 659 | $revision->setSrc( $uploadInfo['src'] ); |
655 | 660 | if ( isset( $uploadInfo['fileSrc'] ) ) { |
656 | | - $revision->setFileSrc( $uploadInfo['fileSrc'] ); |
| 661 | + $revision->setFileSrc( $uploadInfo['fileSrc'], |
| 662 | + !empty( $uploadInfo['isTempSrc'] ) ); |
657 | 663 | } |
| 664 | + if ( isset( $uploadInfo['sha1base36'] ) ) { |
| 665 | + $revision->setSha1Base36( $uploadInfo['sha1base36'] ); |
| 666 | + } |
658 | 667 | $revision->setSize( intval( $uploadInfo['size'] ) ); |
659 | 668 | $revision->setComment( $uploadInfo['comment'] ); |
660 | 669 | |
— | — | @@ -836,6 +845,8 @@ |
837 | 846 | var $action = ""; |
838 | 847 | var $params = ""; |
839 | 848 | var $fileSrc = ''; |
| 849 | + var $sha1base36 = false; |
| 850 | + var $isTemp = false; |
840 | 851 | var $archiveName = ''; |
841 | 852 | |
842 | 853 | function setTitle( $title ) { |
— | — | @@ -880,9 +891,13 @@ |
881 | 892 | function setSrc( $src ) { |
882 | 893 | $this->src = $src; |
883 | 894 | } |
884 | | - function setFileSrc( $src ) { |
| 895 | + function setFileSrc( $src, $isTemp ) { |
885 | 896 | $this->fileSrc = $src; |
| 897 | + $this->fileIsTemp = $isTemp; |
886 | 898 | } |
| 899 | + function setSha1Base36( $sha1base36 ) { |
| 900 | + $this->sha1base36 = $sha1base36; |
| 901 | + } |
887 | 902 | |
888 | 903 | function setFilename( $filename ) { |
889 | 904 | $this->filename = $filename; |
— | — | @@ -941,9 +956,18 @@ |
942 | 957 | function getSrc() { |
943 | 958 | return $this->src; |
944 | 959 | } |
| 960 | + function getSha1() { |
| 961 | + if ( $this->sha1base36 ) { |
| 962 | + return wfBaseConvert( $this->sha1base36, 36, 16 ); |
| 963 | + } |
| 964 | + return false; |
| 965 | + } |
945 | 966 | function getFileSrc() { |
946 | 967 | return $this->fileSrc; |
947 | 968 | } |
| 969 | + function isTempSrc() { |
| 970 | + return $this->isTemp; |
| 971 | + } |
948 | 972 | |
949 | 973 | function getFilename() { |
950 | 974 | return $this->filename; |
— | — | @@ -1118,23 +1142,30 @@ |
1119 | 1143 | |
1120 | 1144 | # Get the file source or download if necessary |
1121 | 1145 | $source = $this->getFileSrc(); |
| 1146 | + $flags = $this->isTempSrc() ? File::DELETE_SOURCE : 0; |
1122 | 1147 | if ( !$source ) { |
1123 | 1148 | $source = $this->downloadSource(); |
| 1149 | + $flags |= File::DELETE_SOURCE; |
1124 | 1150 | } |
1125 | 1151 | if( !$source ) { |
1126 | 1152 | wfDebug( __METHOD__ . ": Could not fetch remote file.\n" ); |
1127 | 1153 | return false; |
1128 | 1154 | } |
| 1155 | + $sha1 = $this->getSha1(); |
| 1156 | + if ( $sha1 && ( $sha1 !== sha1_file( $source ) ) ) { |
| 1157 | + wfDebug( __METHOD__ . ": Corrupt file $source.\n" ); |
| 1158 | + return false; |
| 1159 | + } |
1129 | 1160 | |
1130 | 1161 | $user = User::newFromName( $this->user_text ); |
1131 | 1162 | |
1132 | 1163 | # Do the actual upload |
1133 | 1164 | if ( $archiveName ) { |
1134 | 1165 | $status = $file->uploadOld( $source, $archiveName, |
1135 | | - $this->getTimestamp(), $this->getComment(), $user, File::DELETE_SOURCE ); |
| 1166 | + $this->getTimestamp(), $this->getComment(), $user, $flags ); |
1136 | 1167 | } else { |
1137 | 1168 | $status = $file->upload( $source, $this->getComment(), $this->getComment(), |
1138 | | - File::DELETE_SOURCE, false, $this->getTimestamp(), $user ); |
| 1169 | + $flags, false, $this->getTimestamp(), $user ); |
1139 | 1170 | } |
1140 | 1171 | |
1141 | 1172 | if ( $status->isGood() ) { |