Index: trunk/phase3/includes/Export.php |
— | — | @@ -35,6 +35,8 @@ |
36 | 36 | var $author_list = "" ; |
37 | 37 | |
38 | 38 | var $dumpUploads = false; |
| 39 | + var $multiPart = false; |
| 40 | + var $files = array(); |
39 | 41 | |
40 | 42 | const FULL = 1; |
41 | 43 | const CURRENT = 2; |
— | — | @@ -86,12 +88,23 @@ |
87 | 89 | |
88 | 90 | public function openStream() { |
89 | 91 | $output = $this->writer->openStream(); |
90 | | - $this->sink->writeOpenStream( $output ); |
| 92 | + |
| 93 | + if ( $this->multiPart ) { |
| 94 | + $this->openMultipart(); |
| 95 | + $this->sink->write( $output ); |
| 96 | + } else { |
| 97 | + $this->sink->writeOpenStream( $output ); |
| 98 | + } |
91 | 99 | } |
92 | 100 | |
93 | 101 | public function closeStream() { |
94 | 102 | $output = $this->writer->closeStream(); |
95 | | - $this->sink->writeCloseStream( $output ); |
| 103 | + if ( $this->multiPart ) { |
| 104 | + $this->sink->write( $output ); |
| 105 | + $this->closeMultipart(); |
| 106 | + } else { |
| 107 | + $this->sink->writeCloseStream( $output ); |
| 108 | + } |
96 | 109 | } |
97 | 110 | |
98 | 111 | /** |
— | — | @@ -314,6 +327,7 @@ |
315 | 328 | $output = ''; |
316 | 329 | if ( $this->dumpUploads ) { |
317 | 330 | $output .= $this->writer->writeUploads( $last ); |
| 331 | + $this->attachUploads( $last ); |
318 | 332 | } |
319 | 333 | $output .= $this->writer->closePage(); |
320 | 334 | $this->sink->writeClosePage( $output ); |
— | — | @@ -329,6 +343,7 @@ |
330 | 344 | $output = ''; |
331 | 345 | if ( $this->dumpUploads ) { |
332 | 346 | $output .= $this->writer->writeUploads( $last ); |
| 347 | + $this->attachUploads( $last ); |
333 | 348 | } |
334 | 349 | $output .= $this->author_list; |
335 | 350 | $output .= $this->writer->closePage(); |
— | — | @@ -342,6 +357,38 @@ |
343 | 358 | $this->sink->writeLogItem( $row, $output ); |
344 | 359 | } |
345 | 360 | } |
| 361 | + |
| 362 | + protected function attachUploads( $row ) { |
| 363 | + $title = Title::newFromRow( $row ); |
| 364 | + $file = wfLocalFile( $title ); |
| 365 | + $this->files[] = $file; |
| 366 | + $this->files = array_merge( $this->files, $file->getHistory() ); |
| 367 | + } |
| 368 | + |
| 369 | + protected function openMultipart() { |
| 370 | + # Multipart boundary purposely invalid XML |
| 371 | + $this->boundary = '<' . dechex( mt_rand() ) . dechex( mt_rand() ) . '<'; |
| 372 | + $this->sink->writeOpenStream( |
| 373 | + "Content-Type: multipart/related; boundary={$this->boundary};" . |
| 374 | + " type=text/xml\n\n" . |
| 375 | + "--{$this->boundary}\nContent-Type: text/xml\n\n" |
| 376 | + ); |
| 377 | + } |
| 378 | + |
| 379 | + protected function closeMultipart() { |
| 380 | + $output = ''; |
| 381 | + |
| 382 | + foreach ( $this->files as $file ) { |
| 383 | + $output .= "\n--{$this->boundary}\n" . |
| 384 | + 'Content-Type: ' . $file->getMimeType() . "\n" . |
| 385 | + 'Content-ID: ' . $file->getRel() . "\n" . |
| 386 | + 'Content-Length: ' . $file->getSize() . "\n" . |
| 387 | + 'X-Sha1Base36: ' . $file->getSha1() . "\n\n"; |
| 388 | + $this->sink->write( $output ); |
| 389 | + $this->sink->write( file_get_contents( $file->getPath() ) ); |
| 390 | + } |
| 391 | + $this->sink->writeCloseStream( "\n--{$this->boundary}\n" ); |
| 392 | + } |
346 | 393 | } |
347 | 394 | |
348 | 395 | /** |