<?php
/**
- * @addtogroup Media
- *
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
+ * Exif metadata reader
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
+ * @ingroup Media
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
* @see http://exif.org/Exif2-2.PDF The Exif 2.2 specification
+ * @file
*/
/**
* @todo document (e.g. one-sentence class-overview description)
- * @addtogroup Media
+ * @ingroup Media
*/
class Exif {
+
+ const BYTE = 1; //!< An 8-bit (1-byte) unsigned integer.
+ const ASCII = 2; //!< An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.
+ const SHORT = 3; //!< A 16-bit (2-byte) unsigned integer.
+ const LONG = 4; //!< A 32-bit (4-byte) unsigned integer.
+ const RATIONAL = 5; //!< Two LONGs. The first LONG is the numerator and the second LONG expresses the denominator
+ const UNDEFINED = 7; //!< An 8-bit byte that can take any value depending on the field definition
+ const SLONG = 9; //!< A 32-bit (4-byte) signed integer (2's complement notation),
+ const SRATIONAL = 10; //!< Two SLONGs. The first SLONG is the numerator and the second SLONG is the denominator.
+
//@{
/* @var array
* @private
*/
- /**#@+
- * Exif tag type definition
- */
- const BYTE = 1; # An 8-bit (1-byte) unsigned integer.
- const ASCII = 2; # An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.
- const SHORT = 3; # A 16-bit (2-byte) unsigned integer.
- const LONG = 4; # A 32-bit (4-byte) unsigned integer.
- const RATIONAL = 5; # Two LONGs. The first LONG is the numerator and the second LONG expresses the denominator
- const UNDEFINED = 7; # An 8-bit byte that can take any value depending on the field definition
- const SLONG = 9; # A 32-bit (4-byte) signed integer (2's complement notation),
- const SRATIONAL = 10; # Two SLONGs. The first SLONG is the numerator and the second SLONG is the denominator.
-
/**
* Exif tags grouped by category, the tagname itself is the key and the type
* is the value, in the case of more than one possible value type they are
- * seperated by commas.
+ * separated by commas.
*/
var $mExifTags;
$this->makeFlatExifTags();
$this->debugFile( $this->basename, __FUNCTION__, true );
- wfSuppressWarnings();
- $data = exif_read_data( $this->file );
- wfRestoreWarnings();
+ if( function_exists( 'exif_read_data' ) ) {
+ wfSuppressWarnings();
+ $data = exif_read_data( $this->file );
+ wfRestoreWarnings();
+ } else {
+ throw new MWException( "Internal error: exif_read_data not present. \$wgShowEXIF may be incorrectly set or not checked by an extension." );
+ }
/**
* exif_read_data() will return false on invalid input, such as
* when somebody uploads a file called something.jpeg
if ( is_array( $in ) ) {
return false;
}
-
+
if ( preg_match( "/[^\x0a\x20-\x7e]/", $in ) ) {
$this->debug( $in, __FUNCTION__, 'found a character not in our whitelist' );
return false;
*
* @private
*
- * @param $in Mixed:
- * @param $fname String:
+ * @param $in Mixed:
+ * @param $fname String:
* @param $action Mixed: , default NULL.
*/
- function debug( $in, $fname, $action = NULL ) {
+ function debug( $in, $fname, $action = null ) {
if ( !$this->log ) {
return;
}
/**
* @todo document (e.g. one-sentence class-overview description)
- * @addtogroup Media
+ * @ingroup Media
*/
class FormatExif {
/**
* @param $exif Array: the Exif data to format ( as returned by
* Exif::getFilteredData() )
*/
- function FormatExif( $exif ) {
+ function __construct( $exif ) {
$this->mExif = $exif;
}
}
break;
- // TODO: Flash
+ case 'Flash':
+ $flashDecode = array(
+ 'fired' => $val & bindec( '00000001' ),
+ 'return' => ($val & bindec( '00000110' )) >> 1,
+ 'mode' => ($val & bindec( '00011000' )) >> 3,
+ 'function' => ($val & bindec( '00100000' )) >> 5,
+ 'redeye' => ($val & bindec( '01000000' )) >> 6,
+// 'reserved' => ($val & bindec( '10000000' )) >> 7,
+ );
+
+ # We do not need to handle unknown values since all are used.
+ foreach( $flashDecode as $subTag => $subValue ) {
+ # We do not need any message for zeroed values.
+ if( $subTag != 'fired' && $subValue == 0) {
+ continue;
+ }
+ $fullTag = $tag . '-' . $subTag ;
+ $flashMsgs[] = $this->msg( $fullTag, $subValue );
+ }
+ $tags[$tag] = $wgLang->commaList( $flashMsgs );
+ break;
+
case 'FocalPlaneResolutionUnit':
switch( $val ) {
case 2:
$this->formatNum( $val ) );
break;
+ // Do not transform fields with pure text.
+ // For some languages the formatNum() conversion results to wrong output like
+ // foo,bar@example,com or foo٫bar@example٫com
+ case 'ImageDescription':
+ case 'Artist':
+ case 'Copyright':
+ $tags[$tag] = htmlspecialchars( $val );
+ break;
default:
$tags[$tag] = $this->formatNum( $val );
break;
* @return mixed A floating point number or whatever we were fed
*/
function formatNum( $num ) {
+ global $wgLang;
+
$m = array();
if ( preg_match( '/^(\d+)\/(\d+)$/', $num, $m ) )
- return $m[2] != 0 ? $m[1] / $m[2] : $num;
+ return $wgLang->formatNum( $m[2] != 0 ? $m[1] / $m[2] : $num );
else
- return $num;
+ return $wgLang->formatNum( $num );
}
/**
$gcd = $this->gcd( $numerator, $denominator );
if( $gcd != 0 ) {
// 0 shouldn't happen! ;)
- return $numerator / $gcd . '/' . $denominator / $gcd;
+ return $this->formatNum( $numerator / $gcd ) . '/' . $this->formatNum( $denominator / $gcd );
}
}
return $this->formatNum( $num );
return $a;
}
}
-
-/**
- * MW 1.6 compatibility
- */
-define( 'MW_EXIF_BYTE', Exif::BYTE );
-define( 'MW_EXIF_ASCII', Exif::ASCII );
-define( 'MW_EXIF_SHORT', Exif::SHORT );
-define( 'MW_EXIF_LONG', Exif::LONG );
-define( 'MW_EXIF_RATIONAL', Exif::RATIONAL );
-define( 'MW_EXIF_UNDEFINED', Exif::UNDEFINED );
-define( 'MW_EXIF_SLONG', Exif::SLONG );
-define( 'MW_EXIF_SRATIONAL', Exif::SRATIONAL );
-
-