X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/mediawiki.git/blobdiff_plain/005c63129390e462618d69b42e7fd90eb81f8b9e..HEAD:/includes/media/GIFMetadataExtractor.php diff --git a/includes/media/GIFMetadataExtractor.php b/includes/media/GIFMetadataExtractor.php index fac9012b..ac5fc81c 100644 --- a/includes/media/GIFMetadataExtractor.php +++ b/includes/media/GIFMetadataExtractor.php @@ -1,175 +1,347 @@ $frameCount, 'looped' => $isLooped, - 'duration' => $duration - ); - + 'duration' => $duration, + 'xmp' => $xmp, + 'comment' => $comment, + ]; } - + + /** + * @param resource $fh + * @param int $bpp + * @return void + */ static function readGCT( $fh, $bpp ) { - if ($bpp > 0) { - for( $i=1; $i<=pow(2,$bpp); ++$i ) { + if ( $bpp > 0 ) { + $max = pow( 2, $bpp ); + for ( $i = 1; $i <= $max; ++$i ) { fread( $fh, 3 ); } } } - + + /** + * @param string $data + * @throws Exception + * @return int + */ static function decodeBPP( $data ) { - $buf = unpack( 'C', $data ); - $buf = $buf[1]; + if ( strlen( $data ) < 1 ) { + throw new Exception( "Ran out of input" ); + } + $buf = unpack( 'C', $data )[1]; $bpp = ( $buf & 7 ) + 1; $buf >>= 7; - + $have_map = $buf & 1; - + return $have_map ? $bpp : 0; } - + + /** + * @param resource $fh + * @throws Exception + */ static function skipBlock( $fh ) { while ( !feof( $fh ) ) { $buf = fread( $fh, 1 ); - $block_len = unpack( 'C', $buf ); - $block_len = $block_len[1]; - if ($block_len == 0) + if ( strlen( $buf ) < 1 ) { + throw new Exception( "Ran out of input" ); + } + $block_len = unpack( 'C', $buf )[1]; + if ( $block_len == 0 ) { return; + } fread( $fh, $block_len ); } } + /** + * Read a block. In the GIF format, a block is made up of + * several sub-blocks. Each sub block starts with one byte + * saying how long the sub-block is, followed by the sub-block. + * The entire block is terminated by a sub-block of length + * 0. + * @param resource $fh File handle + * @param bool $includeLengths Include the length bytes of the + * sub-blocks in the returned value. Normally this is false, + * except XMP is weird and does a hack where you need to keep + * these length bytes. + * @throws Exception + * @return string The data. + */ + static function readBlock( $fh, $includeLengths = false ) { + $data = ''; + $subLength = fread( $fh, 1 ); + $blocks = 0; + + while ( $subLength !== "\0" ) { + $blocks++; + if ( $blocks > self::MAX_SUBBLOCKS ) { + throw new Exception( "MAX_SUBBLOCKS exceeded (over $blocks sub-blocks)" ); + } + if ( feof( $fh ) ) { + throw new Exception( "Read error: Unexpected EOF." ); + } + if ( $includeLengths ) { + $data .= $subLength; + } + + $data .= fread( $fh, ord( $subLength ) ); + $subLength = fread( $fh, 1 ); + } + + return $data; + } }