Go to the documentation of this file.
92 return $zdr->execute();
148 $this->
file = fopen( $this->fileName,
'r' );
150 if ( !$this->
file ) {
157 if ( $this->zip64 ) {
161 if ( $this->eocdr[
'CD size'] == 0xffffffff
162 || $this->eocdr[
'CD offset'] == 0xffffffff
163 || $this->eocdr[
'CD entries total'] == 0xffff
165 $this->
error(
'zip-unsupported',
'Central directory header indicates ZIP64, ' .
166 'but we are in legacy mode. Rejecting this upload is necessary to avoid ' .
167 'opening vulnerabilities on clients using OpenJDK 7 or later.' );
174 $status->fatal(
$e->getErrorCode() );
177 fclose( $this->
file );
185 function error( $code, $debugMessage ) {
186 wfDebug( __CLASS__ .
": Fatal error: $debugMessage\n" );
199 'CD start disk' => 2,
200 'CD entries this disk' => 2,
201 'CD entries total' => 2,
204 'file comment length' => 2,
208 if ( $startPos < 0 ) {
212 $block = $this->
getBlock( $startPos );
213 $sigPos = strrpos( $block,
"PK\x05\x06" );
214 if ( $sigPos ===
false ) {
215 $this->
error(
'zip-wrong-format',
216 "zip file lacks EOCDR signature. It probably isn't a zip file." );
219 $this->eocdr = $this->
unpack( substr( $block, $sigPos ), $info );
220 $this->eocdr[
'EOCDR size'] = $structSize + $this->eocdr[
'file comment length'];
222 if ( $structSize + $this->eocdr[
'file comment length'] != strlen( $block ) - $sigPos ) {
223 $this->
error(
'zip-bad',
'trailing bytes after the end of the file comment' );
225 if ( $this->eocdr[
'disk'] !== 0
226 || $this->eocdr[
'CD start disk'] !== 0
228 $this->
error(
'zip-unsupported',
'more than one disk (in EOCDR)' );
230 $this->eocdr += $this->
unpack(
232 array(
'file comment' =>
array(
'string', $this->eocdr[
'file comment length'] ) ),
233 $sigPos + $structSize );
234 $this->eocdr[
'position'] = $startPos + $sigPos;
243 'signature' =>
array(
'string', 4 ),
244 'eocdr64 start disk' => 4,
245 'eocdr64 offset' => 8,
246 'number of disks' => 4,
250 $start = $this->
getFileLength() - $this->eocdr[
'EOCDR size'] - $structSize;
251 $block = $this->
getBlock( $start, $structSize );
252 $this->eocdr64Locator =
$data = $this->
unpack( $block, $info );
254 if (
$data[
'signature'] !==
"PK\x06\x07" ) {
258 $this->
error(
'zip-bad',
'wrong signature on Zip64 end of central directory locator' );
267 if ( $this->eocdr64Locator[
'eocdr64 start disk'] != 0
268 || $this->eocdr64Locator[
'number of disks'] != 0
270 $this->
error(
'zip-unsupported',
'more than one disk (in EOCDR64 locator)' );
274 'signature' =>
array(
'string', 4 ),
276 'version made by' => 2,
277 'version needed' => 2,
279 'CD start disk' => 4,
280 'CD entries this disk' => 8,
281 'CD entries total' => 8,
286 $block = $this->
getBlock( $this->eocdr64Locator[
'eocdr64 offset'], $structSize );
287 $this->eocdr64 =
$data = $this->
unpack( $block, $info );
288 if (
$data[
'signature'] !==
"PK\x06\x06" ) {
289 $this->
error(
'zip-bad',
'wrong signature on Zip64 end of central directory record' );
291 if (
$data[
'disk'] !== 0
292 ||
$data[
'CD start disk'] !== 0
294 $this->
error(
'zip-unsupported',
'more than one disk (in EOCDR64)' );
305 $size = $this->eocdr[
'CD size'];
306 $offset = $this->eocdr[
'CD offset'];
307 $endPos = $this->eocdr[
'position'];
311 if ( $offset +
$size != $endPos ) {
312 $this->
error(
'zip-bad',
'the central directory does not immediately precede the end ' .
313 'of central directory record' );
329 $size = $this->eocdr[
'CD size'];
330 $offset = $this->eocdr[
'CD offset'];
331 $numEntries = $this->eocdr[
'CD entries total'];
332 $endPos = $this->eocdr[
'position'];
333 if (
$size == 0xffffffff
334 || $offset == 0xffffffff
335 || $numEntries == 0xffff
339 if ( isset( $this->eocdr64Locator[
'eocdr64 offset'] ) ) {
341 if ( isset( $this->eocdr64[
'CD offset'] ) ) {
342 $size = $this->eocdr64[
'CD size'];
343 $offset = $this->eocdr64[
'CD offset'];
344 $endPos = $this->eocdr64Locator[
'eocdr64 offset'];
350 if ( $offset +
$size != $endPos ) {
351 $this->
error(
'zip-bad',
'the central directory does not immediately precede the end ' .
352 'of central directory record' );
365 'signature' =>
array(
'string', 4 ),
366 'version made by' => 2,
367 'version needed' => 2,
369 'compression method' => 2,
373 'compressed size' => 4,
374 'uncompressed size' => 4,
376 'extra field length' => 2,
377 'comment length' => 2,
378 'disk number start' => 2,
379 'internal attrs' => 2,
380 'external attrs' => 4,
381 'local header offset' => 4,
386 while ( $pos <
$size ) {
390 if (
$data[
'signature'] !==
"PK\x01\x02" ) {
391 $this->
error(
'zip-bad',
'Invalid signature found in directory entry' );
394 $variableInfo =
array(
395 'name' =>
array(
'string',
$data[
'name length'] ),
396 'extra field' =>
array(
'string',
$data[
'extra field length'] ),
397 'comment' =>
array(
'string',
$data[
'comment length'] ),
399 $data += $this->
unpack( $block, $variableInfo, $pos );
402 if ( $this->zip64 && (
403 $data[
'compressed size'] == 0xffffffff
404 ||
$data[
'uncompressed size'] == 0xffffffff
405 ||
$data[
'local header offset'] == 0xffffffff )
413 if ( $this->
testBit(
$data[
'general bits'], self::GENERAL_CD_ENCRYPTED ) ) {
414 $this->
error(
'zip-unsupported',
'central directory encryption is not supported' );
421 $date =
$data[
'mod date'];
423 $year = 1980 + ( $date >> 9 );
424 $month = ( $date >> 5 ) & 15;
426 $hour = (
$time >> 11 ) & 31;
427 $minute = (
$time >> 5 ) & 63;
428 $second = (
$time & 31 ) * 2;
429 $timestamp = sprintf(
"%04d%02d%02d%02d%02d%02d",
430 $year, $month, $day, $hour, $minute, $second );
433 if ( !function_exists(
'iconv' )
434 || $this->
testBit(
$data[
'general bits'], self::GENERAL_UTF8 )
438 $name = iconv(
'CP437',
'UTF-8',
$data[
'name'] );
445 'size' =>
$data[
'uncompressed size'],
447 call_user_func( $this->callback, $userData );
456 $extraHeaderInfo =
array(
462 $zip64ExtraInfo =
array(
463 'uncompressed size' => 8,
464 'compressed size' => 8,
465 'local header offset' => 8,
466 'disk number start' => 4,
470 while ( $extraPos < strlen( $extraField ) ) {
471 $extra = $this->
unpack( $extraField, $extraHeaderInfo, $extraPos );
472 $extraPos += $extraHeaderSize;
473 $extra += $this->
unpack( $extraField,
474 array(
'data' =>
array(
'string', $extra[
'size'] ) ),
476 $extraPos += $extra[
'size'];
478 if ( $extra[
'id'] == self::ZIP64_EXTRA_HEADER ) {
479 return $this->
unpack( $extra[
'data'], $zip64ExtraInfo );
490 if ( $this->fileLength ===
null ) {
491 $stat = fstat( $this->
file );
492 $this->fileLength = $stat[
'size'];
511 $this->
error(
'zip-bad',
"getBlock() requested position $start, " .
512 "file length is $fileLength" );
514 if ( $length ===
null ) {
517 $end = $start + $length;
519 $this->
error(
'zip-bad',
"getBlock() requested end position $end, " .
520 "file length is $fileLength" );
522 $startSeg = floor( $start / self::SEGSIZE );
523 $endSeg = ceil( $end / self::SEGSIZE );
526 for ( $segIndex = $startSeg; $segIndex <= $endSeg; $segIndex++ ) {
530 $block = substr( $block,
531 $start - $startSeg * self::SEGSIZE,
534 if ( strlen( $block ) < $length ) {
535 $this->
error(
'zip-bad',
'getBlock() returned an unexpectedly small amount of data' );
552 if ( !isset( $this->buffer[$segIndex] ) ) {
555 $this->buffer[$segIndex] =
'';
559 if ( fseek( $this->
file, $bytePos ) ) {
560 $this->
error(
'zip-bad',
"seek to $bytePos failed" );
562 $seg = fread( $this->
file, self::SEGSIZE );
563 if ( $seg ===
false ) {
564 $this->
error(
'zip-bad',
"read from $bytePos failed" );
566 $this->buffer[$segIndex] = $seg;
569 return $this->buffer[$segIndex];
579 if ( is_array(
$type ) ) {
612 function unpack( $string, $struct, $offset = 0 ) {
614 if ( $offset +
$size > strlen( $string ) ) {
615 $this->
error(
'zip-bad',
'unpack() would run past the end of the supplied string' );
620 foreach ( $struct
as $key =>
$type ) {
621 if ( is_array(
$type ) ) {
623 switch ( $typeName ) {
625 $data[$key] = substr( $string, $pos, $fieldSize );
629 throw new MWException( __METHOD__ .
": invalid type \"$typeName\"" );
633 $length = intval(
$type );
638 for ( $i = $length - 1; $i >= 0; $i-- ) {
640 $value += ord( $string[$pos + $i] );
644 if (
$value > pow( 2, 52 ) ) {
645 $this->
error(
'zip-unsupported',
'number too large to be stored in a double. ' .
646 'This could happen if we tried to unpack a 64-bit structure ' .
647 'at an invalid location.' );
666 return (
bool)( (
$value >> $bitIndex ) & 1 );
674 for ( $i = 0; $i <
$n; $i += 16 ) {
675 printf(
"%08X ", $i );
676 for ( $j = 0; $j < 16; $j++ ) {
681 if ( $i + $j >=
$n ) {
684 printf(
"%02X", ord(
$s[$i + $j] ) );
689 for ( $j = 0; $j < 16; $j++ ) {
690 if ( $i + $j >=
$n ) {
692 } elseif ( ctype_print(
$s[$i + $j] ) ) {
710 $this->errorCode = $code;
711 parent::__construct(
"ZipDirectoryReader error: $code" );
getBlock( $start, $length=null)
Get the file contents from a given offset.
see documentation in includes Linker php for Linker::makeImageLink & $time
readZip64EndOfCentralDirectoryLocator()
Read the header called the "ZIP64 end of central directory locator".
getFileLength()
Get the length of the file.
and how to run hooks for an and one after Each event has a preferably in CamelCase For ArticleDelete hook A clump of code and data that should be run when an event happens This can be either a function and a chunk of data
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
static newGood( $value=null)
Factory function for good results.
findZip64CentralDirectory()
Find the location of the central directory, as would be seen by a ZIP64-compliant reader.
unpack( $string, $struct, $offset=0)
Unpack a binary structure.
findOldCentralDirectory()
Find the location of the central directory, as would be seen by a non-ZIP64 reader.
const ZIP64_EXTRA_HEADER
The "extra field" ID for ZIP64 central directory entries.
unpackZip64Extra( $extraField)
Interpret ZIP64 "extra field" data and return an associative array.
$buffer
A segmented cache of the file contents.
testBit( $value, $bitIndex)
Returns a bit from a given position in an integer value, converted to boolean.
A class for reading ZIP file directories, for the purposes of upload verification.
We ve cleaned up the code here by removing clumps of infrequently used code and moving them off somewhere else It s much easier for someone working with this code to see what s _really_ going and make changes or fix bugs In we can take all the code that deals with the little used title reversing we can concentrate it all in an extension file
$file
The opened file resource.
hexDump( $s)
Debugging helper function which dumps a string in hexdump -C format.
execute()
Read the directory according to settings in $this.
__construct( $fileName, $callback, $options)
Private constructor.
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
getStructSize( $struct)
Get the size of a structure in bytes.
readZip64EndOfCentralDirectoryRecord()
Read the header called the "ZIP64 end of central directory record".
error( $code, $debugMessage)
Throw an error, and log a debug message.
$callback
The file data callback.
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
wfDebug( $text, $dest='all')
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Allows to change the fields on the form that will be generated $name
const GENERAL_UTF8
The index of the "general field" bit for UTF-8 file names.
getSegment( $segIndex)
Get a section of the file starting at position $segIndex * self::SEGSIZE, of length self::SEGSIZE.
readEndOfCentralDirectoryRecord()
Read the header which is at the end of the central directory, unimaginatively called the "end of cent...
readCentralDirectory( $offset, $size)
Read the central directory at the given location.
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
$fileLength
The cached length of the file, or null if it has not been loaded yet.
const GENERAL_CD_ENCRYPTED
The index of the "general field" bit for central directory encryption.
static read( $fileName, $callback, $options=array())
Read a ZIP file and call a function for each file discovered in it.
const SEGSIZE
The segment size for the file contents cache.
static newFatal( $message)
Factory function for fatal errors.
Internal exception class.