| 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() ) { |