summaryrefslogtreecommitdiff
path: root/includes/media/PNGMetadataExtractor.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/media/PNGMetadataExtractor.php')
-rw-r--r--includes/media/PNGMetadataExtractor.php92
1 files changed, 46 insertions, 46 deletions
diff --git a/includes/media/PNGMetadataExtractor.php b/includes/media/PNGMetadataExtractor.php
index 845d212a..bccd36c1 100644
--- a/includes/media/PNGMetadataExtractor.php
+++ b/includes/media/PNGMetadataExtractor.php
@@ -31,40 +31,45 @@
* @ingroup Media
*/
class PNGMetadataExtractor {
- static $png_sig;
- static $CRC_size;
- static $text_chunks;
+ /** @var string */
+ private static $pngSig;
+
+ /** @var int */
+ private static $crcSize;
+
+ /** @var array */
+ private static $textChunks;
const VERSION = 1;
const MAX_CHUNK_SIZE = 3145728; // 3 megabytes
static function getMetadata( $filename ) {
- self::$png_sig = pack( "C8", 137, 80, 78, 71, 13, 10, 26, 10 );
- self::$CRC_size = 4;
+ self::$pngSig = pack( "C8", 137, 80, 78, 71, 13, 10, 26, 10 );
+ self::$crcSize = 4;
/* based on list at http://owl.phy.queensu.ca/~phil/exiftool/TagNames/PNG.html#TextualData
* and http://www.w3.org/TR/PNG/#11keywords
*/
- self::$text_chunks = array(
+ self::$textChunks = array(
'xml:com.adobe.xmp' => 'xmp',
# Artist is unofficial. Author is the recommended
# keyword in the PNG spec. However some people output
# Artist so support both.
- 'artist' => 'Artist',
- 'model' => 'Model',
- 'make' => 'Make',
- 'author' => 'Artist',
- 'comment' => 'PNGFileComment',
+ 'artist' => 'Artist',
+ 'model' => 'Model',
+ 'make' => 'Make',
+ 'author' => 'Artist',
+ 'comment' => 'PNGFileComment',
'description' => 'ImageDescription',
- 'title' => 'ObjectName',
- 'copyright' => 'Copyright',
+ 'title' => 'ObjectName',
+ 'copyright' => 'Copyright',
# Source as in original device used to make image
# not as in who gave you the image
- 'source' => 'Model',
- 'software' => 'Software',
- 'disclaimer' => 'Disclaimer',
- 'warning' => 'ContentWarning',
- 'url' => 'Identifier', # Not sure if this is best mapping. Maybe WebStatement.
- 'label' => 'Label',
+ 'source' => 'Model',
+ 'software' => 'Software',
+ 'disclaimer' => 'Disclaimer',
+ 'warning' => 'ContentWarning',
+ 'url' => 'Identifier', # Not sure if this is best mapping. Maybe WebStatement.
+ 'label' => 'Label',
'creation time' => 'DateTimeDigitized',
/* Other potentially useful things - Document */
);
@@ -90,7 +95,7 @@ class PNGMetadataExtractor {
// Check for the PNG header
$buf = fread( $fh, 8 );
- if ( $buf != self::$png_sig ) {
+ if ( $buf != self::$pngSig ) {
throw new Exception( __METHOD__ . ": Not a valid PNG file; header: $buf" );
}
@@ -181,9 +186,9 @@ class PNGMetadataExtractor {
// Theoretically should be case-sensitive, but in practise...
$items[1] = strtolower( $items[1] );
- if ( !isset( self::$text_chunks[$items[1]] ) ) {
+ if ( !isset( self::$textChunks[$items[1]] ) ) {
// Only extract textual chunks on our list.
- fseek( $fh, self::$CRC_size, SEEK_CUR );
+ fseek( $fh, self::$crcSize, SEEK_CUR );
continue;
}
@@ -203,26 +208,23 @@ class PNGMetadataExtractor {
if ( $items[5] === false ) {
// decompression failed
wfDebug( __METHOD__ . ' Error decompressing iTxt chunk - ' . $items[1] . "\n" );
- fseek( $fh, self::$CRC_size, SEEK_CUR );
+ fseek( $fh, self::$crcSize, SEEK_CUR );
continue;
}
-
} else {
wfDebug( __METHOD__ . ' Skipping compressed png iTXt chunk due to lack of zlib,'
. " or potentially invalid compression method\n" );
- fseek( $fh, self::$CRC_size, SEEK_CUR );
+ fseek( $fh, self::$crcSize, SEEK_CUR );
continue;
}
}
- $finalKeyword = self::$text_chunks[$items[1]];
+ $finalKeyword = self::$textChunks[$items[1]];
$text[$finalKeyword][$items[3]] = $items[5];
$text[$finalKeyword]['_type'] = 'lang';
-
} else {
// Error reading iTXt chunk
throw new Exception( __METHOD__ . ": Read error on iTXt chunk" );
}
-
} elseif ( $chunk_type == 'tEXt' ) {
$buf = self::read( $fh, $chunk_size );
@@ -238,9 +240,9 @@ class PNGMetadataExtractor {
// Theoretically should be case-sensitive, but in practise...
$keyword = strtolower( $keyword );
- if ( !isset( self::$text_chunks[ $keyword ] ) ) {
+ if ( !isset( self::$textChunks[$keyword] ) ) {
// Don't recognize chunk, so skip.
- fseek( $fh, self::$CRC_size, SEEK_CUR );
+ fseek( $fh, self::$crcSize, SEEK_CUR );
continue;
}
wfSuppressWarnings();
@@ -251,10 +253,9 @@ class PNGMetadataExtractor {
throw new Exception( __METHOD__ . ": Read error (error with iconv)" );
}
- $finalKeyword = self::$text_chunks[$keyword];
+ $finalKeyword = self::$textChunks[$keyword];
$text[$finalKeyword]['x-default'] = $content;
$text[$finalKeyword]['_type'] = 'lang';
-
} elseif ( $chunk_type == 'zTXt' ) {
if ( function_exists( 'gzuncompress' ) ) {
$buf = self::read( $fh, $chunk_size );
@@ -271,16 +272,16 @@ class PNGMetadataExtractor {
// Theoretically should be case-sensitive, but in practise...
$keyword = strtolower( $keyword );
- if ( !isset( self::$text_chunks[ $keyword ] ) ) {
+ if ( !isset( self::$textChunks[$keyword] ) ) {
// Don't recognize chunk, so skip.
- fseek( $fh, self::$CRC_size, SEEK_CUR );
+ fseek( $fh, self::$crcSize, SEEK_CUR );
continue;
}
$compression = substr( $postKeyword, 0, 1 );
$content = substr( $postKeyword, 1 );
if ( $compression !== "\x00" ) {
wfDebug( __METHOD__ . " Unrecognized compression method in zTXt ($keyword). Skipping.\n" );
- fseek( $fh, self::$CRC_size, SEEK_CUR );
+ fseek( $fh, self::$crcSize, SEEK_CUR );
continue;
}
@@ -291,7 +292,7 @@ class PNGMetadataExtractor {
if ( $content === false ) {
// decompression failed
wfDebug( __METHOD__ . ' Error decompressing zTXt chunk - ' . $keyword . "\n" );
- fseek( $fh, self::$CRC_size, SEEK_CUR );
+ fseek( $fh, self::$crcSize, SEEK_CUR );
continue;
}
@@ -303,10 +304,9 @@ class PNGMetadataExtractor {
throw new Exception( __METHOD__ . ": Read error (error with iconv)" );
}
- $finalKeyword = self::$text_chunks[$keyword];
+ $finalKeyword = self::$textChunks[$keyword];
$text[$finalKeyword]['x-default'] = $content;
$text[$finalKeyword]['_type'] = 'lang';
-
} else {
wfDebug( __METHOD__ . " Cannot decompress zTXt chunk due to lack of zlib. Skipping.\n" );
fseek( $fh, $chunk_size, SEEK_CUR );
@@ -332,7 +332,6 @@ class PNGMetadataExtractor {
if ( $exifTime ) {
$text['DateTime'] = $exifTime;
}
-
} elseif ( $chunk_type == 'pHYs' ) {
// how big pixels are (dots per meter).
if ( $chunk_size !== 9 ) {
@@ -359,13 +358,12 @@ class PNGMetadataExtractor {
// 3 = dots per cm (from Exif).
}
}
-
} elseif ( $chunk_type == "IEND" ) {
break;
} else {
fseek( $fh, $chunk_size, SEEK_CUR );
}
- fseek( $fh, self::$CRC_size, SEEK_CUR );
+ fseek( $fh, self::$crcSize, SEEK_CUR );
}
fclose( $fh );
@@ -399,6 +397,7 @@ class PNGMetadataExtractor {
}
}
}
+
return array(
'frameCount' => $frameCount,
'loopCount' => $loopCount,
@@ -407,21 +406,22 @@ class PNGMetadataExtractor {
'bitDepth' => $bitDepth,
'colorType' => $colorType,
);
-
}
+
/**
* Read a chunk, checking to make sure its not too big.
*
- * @param $fh resource The file handle
- * @param $size Integer size in bytes.
- * @throws Exception if too big.
- * @return String The chunk.
+ * @param resource $fh The file handle
+ * @param int $size Size in bytes.
+ * @throws Exception If too big
+ * @return string The chunk.
*/
private static function read( $fh, $size ) {
if ( $size > self::MAX_CHUNK_SIZE ) {
throw new Exception( __METHOD__ . ': Chunk size of ' . $size .
' too big. Max size is: ' . self::MAX_CHUNK_SIZE );
}
+
return fread( $fh, $size );
}
}