Merge "(bug 18195) Allow changing preferences via API"
[lhc/web/wiklou.git] / includes / media / XMP.php
index dc56e80..adb85df 100644 (file)
@@ -1,4 +1,26 @@
 <?php
+/**
+ * Reader for XMP data containing properties relevant to images.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Media
+ */
+
 /**
 * Class for reading xmp data containing properties relevant to
 * images, and spitting out an array that FormatExif accepts.
@@ -40,7 +62,7 @@ class XMPReader {
 
        protected $items;
 
-       /*
+       /**
        * These are various mode constants.
        * they are used to figure out what to do
        * with an element when its encountered.
@@ -106,8 +128,6 @@ class XMPReader {
                        array( $this, 'endElement' ) );
 
                xml_set_character_data_handler( $this->xmlParser, array( $this, 'char' ) );
-
-
        }
 
        /** Destroy the xml parser
@@ -147,7 +167,7 @@ class XMPReader {
                        // only apply to the dc:Creator prop, not the
                        // exif:Artist prop.
 
-                       $data['xmp-general']['Artist'][0] = 
+                       $data['xmp-general']['Artist'][0] =
                                $data['xmp-special']['AuthorsPosition'] . ', '
                                . $data['xmp-general']['Artist'][0];
                }
@@ -212,9 +232,9 @@ class XMPReader {
        * Also catches any errors during processing, writes them to
        * debug log, blanks result array and returns false.
        *
-       * @param String: $content XMP data
-       * @param Boolean: $allOfIt If this is all the data (true) or if its split up (false). Default true
-       * @param Boolean: $reset - does xml parser need to be reset. Default false
+       * @param $content String: XMP data
+       * @param $allOfIt Boolean: If this is all the data (true) or if its split up (false). Default true
+       * @param $reset Boolean: does xml parser need to be reset. Default false
        * @return Boolean success.
        */
        public function parse( $content, $allOfIt = true, $reset = false ) {
@@ -228,7 +248,7 @@ class XMPReader {
                        if ( !$this->charset ) {
                                $bom = array();
                                if ( preg_match( '/\xEF\xBB\xBF|\xFE\xFF|\x00\x00\xFE\xFF|\xFF\xFE\x00\x00|\xFF\xFE/',
-                                        $content, $bom ) 
+                                        $content, $bom )
                                ) {
                                        switch ( $bom[0] ) {
                                                case "\xFE\xFF":
@@ -260,7 +280,9 @@ class XMPReader {
                        }
                        if ( $this->charset !== 'UTF-8' ) {
                                //don't convert if already utf-8
+                               wfSuppressWarnings();
                                $content = iconv( $this->charset, 'UTF-8//IGNORE', $content );
+                               wfRestoreWarnings();
                        }
 
                        $ok = xml_parse( $this->xmlParser, $content, $allOfIt );
@@ -290,14 +312,13 @@ class XMPReader {
         * @return Boolean If it succeeded.
         */
        public function parseExtended( $content ) {
-               // FIXME: This is untested. Hard to find example files
+               // @todo FIXME: This is untested. Hard to find example files
                // or programs that make such files..
                $guid = substr( $content, 0, 32 );
                if ( !isset( $this->results['xmp-special']['HasExtendedXMP'] )
-                       || $this->results['xmp-special']['HasExtendedXMP'] !== $guid )
-               {
+                       || $this->results['xmp-special']['HasExtendedXMP'] !== $guid ) {
                        wfDebugLog('XMP', __METHOD__ . " Ignoring XMPExtended block due to wrong guid (guid= '$guid' )");
-                       return;
+                       return false;
                }
                $len  = unpack( 'Nlength/Noffset', substr( $content, 32, 8 ) );
 
@@ -385,6 +406,7 @@ class XMPReader {
                }
 
        }
+
        /** When we hit a closing element in MODE_IGNORE
        * Check to see if this is the element we started to ignore,
        * in which case we get out of MODE_IGNORE
@@ -400,13 +422,14 @@ class XMPReader {
                return;
 
        }
+
        /**
        * Hit a closing element when in MODE_SIMPLE.
        * This generally means that we finished processing a
        * property value, and now have to save the result to the
        * results array
        *
-       * For example, when processing: 
+       * For example, when processing:
        * <exif:DigitalZoomRatio>0/10</exif:DigitalZoomRatio>
        * this deals with when we hit </exif:DigitalZoomRatio>.
        *
@@ -432,6 +455,7 @@ class XMPReader {
                array_shift( $this->mode );
 
        }
+
        /**
        * Hit a closing element in MODE_STRUCT, MODE_SEQ, MODE_BAG
        * generally means we've finished processing a nested structure.
@@ -539,6 +563,7 @@ class XMPReader {
                        throw new MWException( __METHOD__ . " expected </rdf:seq> or </rdf:bag> but instead got $elm." );
                }
        }
+
        /**
        * End element while in MODE_QDESC
        * mostly when ending an element when we have a simple value
@@ -562,12 +587,13 @@ class XMPReader {
 
 
        }
+
        /**
        * Handler for hitting a closing element.
        *
        * generally just calls a helper function depending on what
        * mode we're in.
-       * 
+       *
        * Ignores the outer wrapping elements that are optional in
        * xmp and have no meaning.
        *
@@ -644,7 +670,6 @@ class XMPReader {
                }
        }
 
-
        /**
        * Hit an opening element while in MODE_IGNORE
        *
@@ -662,6 +687,7 @@ class XMPReader {
                        array_unshift( $this->mode, self::MODE_IGNORE );
                }
        }
+
        /**
        *  Start element in MODE_BAG (unordered array)
        * this should always be <rdf:Bag>
@@ -677,6 +703,7 @@ class XMPReader {
                }
 
        }
+
        /**
        * Start element in MODE_SEQ (ordered array)
        * this should always be <rdf:Seq>
@@ -687,7 +714,7 @@ class XMPReader {
        private function startElementModeSeq( $elm ) {
                if ( $elm === self::NS_RDF . ' Seq' ) {
                        array_unshift( $this->mode, self::MODE_LI );
-               } else if ( $elm === self::NS_RDF . ' Bag' ) {
+               } elseif ( $elm === self::NS_RDF . ' Bag' ) {
                        # bug 27105
                        wfDebugLog( 'XMP', __METHOD__ . ' Expected an rdf:Seq, but got an rdf:Bag. Pretending'
                                . ' it is a Seq, since some buggy software is known to screw this up.' );
@@ -697,6 +724,7 @@ class XMPReader {
                }
 
        }
+
        /**
        * Start element in MODE_LANG (language alternative)
        * this should always be <rdf:Alt>
@@ -719,6 +747,7 @@ class XMPReader {
                }
 
        }
+
        /**
        * Handle an opening element when in MODE_SIMPLE
        *
@@ -759,6 +788,7 @@ class XMPReader {
                }
 
        }
+
        /**
        * Start an element when in MODE_QDESC.
        * This generally happens when a simple element has an inner
@@ -782,6 +812,7 @@ class XMPReader {
                        array_unshift( $this->curItem, $elm );
                }
        }
+
        /**
        * Starting an element when in MODE_INITIAL
        * This usually happens when we hit an element inside
@@ -834,6 +865,7 @@ class XMPReader {
                // process attributes
                $this->doAttribs( $attribs );
        }
+
        /**
        * Hit an opening element when in a Struct (MODE_STRUCT)
        * This is generally for fields of a compound property.
@@ -844,9 +876,9 @@ class XMPReader {
        *  <exif:Mode>1</exif:Mode></rdf:Description></exif:Flash>
        *
        * or:
-       * 
+       *
        * <exif:Flash rdf:parseType='Resource'> <exif:Fired>True</exif:Fired>
-       *  <exif:Mode>1</exif:Mode></exif:Flash> 
+       *  <exif:Mode>1</exif:Mode></exif:Flash>
        *
        * @param $ns String namespace
        * @param $tag String tag name (no ns)
@@ -885,6 +917,7 @@ class XMPReader {
                        array_unshift( $this->curItem, $this->curItem[0] );
                }
        }
+
        /**
        * opening element in MODE_LI
        * process elements of arrays.
@@ -895,7 +928,7 @@ class XMPReader {
        * This method is called when we hit the <rdf:li> element.
        *
        * @param $elm String: namespace . ' ' . tagname
-       * @param $attribs Array: Attributes. (needed for BAGSTRUCTS) 
+       * @param $attribs Array: Attributes. (needed for BAGSTRUCTS)
        * @throws MWException if gets a tag other than <rdf:li>
        */
        private function startElementModeLi( $elm, $attribs ) {
@@ -935,6 +968,7 @@ class XMPReader {
                }
 
        }
+
        /**
        * Opening element in MODE_LI_LANG.
        * process elements of language alternatives
@@ -982,7 +1016,7 @@ class XMPReader {
        function startElement( $parser, $elm, $attribs ) {
 
                if ( $elm === self::NS_RDF . ' RDF'
-                       || $elm === 'adobe:ns:meta/ xmpmeta' 
+                       || $elm === 'adobe:ns:meta/ xmpmeta'
                        || $elm === 'adobe:ns:meta/ xapmeta')
                {
                        /* ignore. */
@@ -1053,10 +1087,8 @@ class XMPReader {
                                throw new MWException( 'StartElement in unknown mode: ' . $this->mode[0] );
                                break;
                }
-
-
-
        }
+
        /**
        * Process attributes.
        * Simple values can be stored as either a tag or attribute
@@ -1070,7 +1102,7 @@ class XMPReader {
        * @param $attribs Array attribute=>value array.
        */
        private function doAttribs( $attribs ) {
-               
+
                // first check for rdf:parseType attribute, as that can change
                // how the attributes are interperted.
 
@@ -1109,6 +1141,7 @@ class XMPReader {
                        }
                }
        }
+
        /**
        * Given an extracted value, save it to results array
        *
@@ -1160,6 +1193,4 @@ class XMPReader {
                        $this->results['xmp-' . $info['map_group']][$finalName] = $val;
                }
        }
-
-
 }