* Adding wfSuppressWarnings() before the Exif validation, some of the type
[lhc/web/wiklou.git] / includes / Image.php
index 0db9aea..5817272 100644 (file)
@@ -3,9 +3,16 @@
  * @package MediaWiki
  */
 
-if ( $wgShowEXIF ) {
-       require_once ( 'exifReader.inc' ) ;
-       }
+# NOTE FOR WINDOWS USERS:
+# To enable EXIF functions, add the folloing lines to the
+# "Windows extensions" section of php.ini:
+#
+# extension=extensions/php_mbstring.dll
+# extension=extensions/php_exif.dll
+
+if ($wgShowEXIF)
+       require_once('Exif.php');
+
 
 /**
  * Class to represent an image
@@ -33,6 +40,7 @@ class Image
                $type,          #  |
                $attr,          # /
                $size,          # Size in bytes (loadFromXxx)
+               $exif,                  # EXIF data
                $dataLoaded;    # Whether or not all this has been loaded from the database (loadFromXxx)
 
 
@@ -59,6 +67,7 @@ class Image
        function Image( $title ) {
                $this->title =& $title;
                $this->name = $title->getDBkey();
+               $this->exif = serialize ( array() ) ;
 
                $n = strrpos( $this->name, '.' );
                $this->extension = strtolower( $n ? substr( $this->name, $n + 1 ) : '' );
@@ -109,6 +118,7 @@ class Image
                                                $this->height = $commonsCachedValues['height'];
                                                $this->bits = $commonsCachedValues['bits'];
                                                $this->type = $commonsCachedValues['type'];
+                                               $this->exif = $commonsCachedValues['exif'];
                                                $this->size = $commonsCachedValues['size'];
                                                $this->fromSharedDirectory = true;
                                                $this->dataLoaded = true;
@@ -124,6 +134,7 @@ class Image
                                $this->height = $cachedValues['height'];
                                $this->bits = $cachedValues['bits'];
                                $this->type = $cachedValues['type'];
+                               $this->exif = $cachedValues['exif'];
                                $this->size = $cachedValues['size'];
                                $this->fromSharedDirectory = false;
                                $this->dataLoaded = true;
@@ -154,6 +165,7 @@ class Image
                                                                  'height' => $this->height,
                                                                  'bits' => $this->bits,
                                                                  'type' => $this->type,
+                                                                 'exif' => $this->exif,
                                                                  'size' => $this->size);
 
                        $wgMemc->set( $keys[0], $cachedValues );
@@ -209,10 +221,12 @@ class Image
                        $this->height = 0;
                        $this->bits = 0;
                        $this->type = 0;
+                       $this->exif = serialize ( array() ) ;
                } else {
                        $this->width = $gis[0];
                        $this->height = $gis[1];
                        $this->type = $gis[2];
+                       $this->exif = serialize ( $this->retrieveExifData() ) ;
                        if ( isset( $gis['bits'] ) )  {
                                $this->bits = $gis['bits'];
                        } else {
@@ -233,7 +247,7 @@ class Image
                
                $dbr =& wfGetDB( DB_SLAVE );
                $row = $dbr->selectRow( 'image', 
-                       array( 'img_size', 'img_width', 'img_height', 'img_bits', 'img_type' ),
+                       array( 'img_size', 'img_width', 'img_height', 'img_bits', 'img_type' , 'img_metadata' ),
                        array( 'img_name' => $this->name ), $fname );
                if ( $row ) {
                        $this->fromSharedDirectory = false;
@@ -275,6 +289,7 @@ class Image
                        $this->type = 0;
                        $this->fileExists = false;
                        $this->fromSharedDirectory = false;
+                       $this->exif = serialize ( array() ) ;
                }
 
                # Unconditionally set loaded=true, we don't want the accessors constantly rechecking
@@ -290,6 +305,8 @@ class Image
                $this->height = $row->img_height;
                $this->bits = $row->img_bits;
                $this->type = $row->img_type;
+               $this->exif = $row->img_metadata;
+               if ( $this->exif == "" ) $this->exif = serialize ( array() ) ;
                $this->dataLoaded = true;
        }
 
@@ -330,12 +347,13 @@ class Image
                        // This avoids breaking replication in MySQL
                        $dbw->selectDB( $wgSharedUploadDBname );
                }
-               $dbw->update( '`image`', 
+               $dbw->update( 'image', 
                        array( 
                                'img_width' => $this->width,
                                'img_height' => $this->height,
                                'img_bits' => $this->bits,
                                'img_type' => $this->type,
+                               'img_metadata' => $this->exif,
                        ), array( 'img_name' => $this->name ), $fname
                );
                if ( $this->fromSharedDirectory ) {
@@ -632,7 +650,7 @@ class Image
         * @return ThumbnailImage
         * @access private
         */
-       function /* private */ renderThumb( $width, $useScript = true ) {
+       function renderThumb( $width, $useScript = true ) {
                global $wgUseSquid, $wgInternalServer;
                global $wgThumbnailScriptPath, $wgSharedThumbnailScriptPath;
                
@@ -703,7 +721,7 @@ class Image
         *
         * @access private
         */
-       function /*private*/ reallyRenderThumb( $thumbPath, $width, $height ) {
+       function reallyRenderThumb( $thumbPath, $width, $height ) {
                global $wgSVGConverters, $wgSVGConverter,
                        $wgUseImageMagick, $wgImageMagickConvertCommand;
                
@@ -1008,6 +1026,7 @@ class Image
                                'img_description' => $desc,
                                'img_user' => $wgUser->getID(),
                                'img_user_text' => $wgUser->getName(),
+                               'img_metadata' => $this->exif,
                        ), $fname, 'IGNORE' 
                );
                $descTitle = $this->getTitle();
@@ -1052,6 +1071,7 @@ class Image
                                        'img_user' => $wgUser->getID(),
                                        'img_user_text' => $wgUser->getName(),
                                        'img_description' => $desc,
+                                       'img_metadata' => $this->exif,
                                ), array( /* WHERE */
                                        'img_name' => $this->name
                                ), $fname
@@ -1114,23 +1134,55 @@ class Image
        
        function retrieveExifData () {
                global $wgShowEXIF ;
-               if ( ! $wgShowEXIF ) return array () ;
-
-               $file = $this->getImagePath () ;
-               $per = new phpExifReader ( $file ) ;
-               $per->processFile () ;
-               $a = $per->getImageInfo() ;
-               unset ( $a["FileName"] ) ;
-               unset ( $a["Thumbnail"] ) ;
-               return $a ;
+               if ( ! $wgShowEXIF ) return array ();
+               if ( $this->type !== '2' ) return array ();
+
+               $exif = exif_read_data( $this->imagePath );
+
+               $obj = new Exif;
+               // Some of the type checks in validate will spew warnings on invalid data
+               wfSuppressWarnings();
+               foreach($exif as $k => $v) {
+                       if ( !in_array($k, $obj->mValidExif) || !$obj->validate($k, $v) )
+                               unset($exif[$k]);
                }
+               wfRestoreWarnings();
+               
+               return $exif;
+       }
                
        function getExifData () {
-               return $this->retrieveExifData () ;
-               }
-       
-       function storeExifData () {
+               global $wgRequest;
+               
+               $ret = unserialize ( $this->exif );
+
+               if ( count( $ret) == 0 || $wgRequest->getVal( 'action' ) == 'purge' ) { # No EXIF data was stored for this image
+                       $this->updateExifData() ;
+                       $ret = unserialize ( $this->exif ) ;
                }
+               
+               return $ret ;
+       }
+
+       function updateExifData () {
+               global $wgShowEXIF ;
+               if ( ! $wgShowEXIF ) return ;
+               if ( false === $this->getImagePath() ) return ; # Not a local image
+               
+               $fname = "Image:updateExifData" ;
+               
+               # Get EXIF data from image
+               $exif = $this->retrieveExifData () ;
+               $this->exif = serialize ( $exif ) ;
+               
+               # Update EXIF data in database
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->update( 'image', 
+                       array( 'img_metadata' => $this->exif ),
+                       array( 'img_name' => $this->name ),
+                       $fname
+               );
+       }
 
 } //class
 
@@ -1345,21 +1397,27 @@ function wfGetSVGsize( $filename ) {
 }
 
 /**
- * Is an image on the bad image list?
+ * Determine if an image exists on the 'bad image list'
+ *
+ * @param string $name The image to check
+ * @return bool
  */
 function wfIsBadImage( $name ) {
-       global $wgLang;
-
-       $lines = explode("\n", wfMsgForContent( 'bad_image_list' ));
-       foreach ( $lines as $line ) {
-               if ( preg_match( '/^\*\s*\[\[:(' . $wgLang->getNsText( NS_IMAGE ) . ':.*(?=]]))\]\]/', $line, $m ) ) {
-                       $t = Title::newFromText( $m[1] );
-                       if ( $t->getDBkey() == $name ) {
-                               return true;
+       global $wgContLang;
+       static $titleList = false;
+       if ( $titleList === false ) {
+               $titleList = array();
+
+               $lines = explode("\n", wfMsgForContent( 'bad_image_list' ));
+               foreach ( $lines as $line ) {
+                       if ( preg_match( '/^\*\s*\[{2}:(' . $wgContLang->getNsText( NS_IMAGE ) . ':.*?)\]{2}/', $line, $m ) ) {
+                               $t = Title::newFromText( $m[1] );
+                               $titleList[$t->getDBkey()] = 1;
                        }
                }
        }
-       return false;
+
+       return array_key_exists( $name, $titleList );
 }