If the unknown element is empty, there won't be a matching END_ELEMENT. There's nothi...
[lhc/web/wiklou.git] / includes / media / SVGMetadataExtractor.php
index 66dc125..967d671 100644 (file)
@@ -48,7 +48,7 @@ class SVGReader {
         */
        function __construct( $source ) {
                $this->reader = new XMLReader();
-               $this->reader->open( $source );
+               $this->reader->open( $source, null, LIBXML_NOERROR | LIBXML_NOWARNING );
 
                $this->metadata['width'] = self::DEFAULT_WIDTH;
                $this->metadata['height'] = self::DEFAULT_HEIGHT;
@@ -67,18 +67,21 @@ class SVGReader {
         * Read the SVG
         */
        public function read() {
-               $this->reader->read();
+               $keepReading = $this->reader->read();
 
-               if ( $this->reader->name != 'svg' ) {
+               /* Skip until first element */
+               while( $keepReading && $this->reader->nodeType != XmlReader::ELEMENT ) {
+                       $keepReading = $this->reader->read();
+               }
+
+               if ( !$this->qualifiedNameEquals( $this->reader->name, 'svg', 'svg' ) ) {
                        throw new MWException( "Expected <svg> tag, got ".
                                $this->reader->name );
                }
                $this->debug( "<svg> tag is correct." );
-
-               $this->debug( "Starting primary dump processing loop." );
                $this->handleSVGAttribs();
-               $exitDepth =  $this->reader->depth;
 
+               $exitDepth =  $this->reader->depth;
                $keepReading = $this->reader->read();
                $skip = false;
                while ( $keepReading ) {
@@ -87,13 +90,13 @@ class SVGReader {
 
                        $this->debug( "$tag" );
 
-                       if ( $tag == 'svg' && $type == XmlReader::END_ELEMENT && $this->reader->depth <= $exitDepth ) {
+                       if ( $this->qualifiedNameEquals( $tag, 'svg', 'svg' ) && $type == XmlReader::END_ELEMENT && $this->reader->depth <= $exitDepth ) {
                                break;
-                       } elseif ( $tag == 'title' ) {
+                       } elseif ( $this->qualifiedNameEquals( $tag, 'svg', 'title' ) ) {
                                $this->readField( $tag, 'title' );
-                       } elseif ( $tag == 'desc' ) {
+                       } elseif ( $this->qualifiedNameEquals( $tag, 'svg', 'desc' )  ) {
                                $this->readField( $tag, 'description' );
-                       } elseif ( $tag == 'metadata' && $type == XmlReader::ELEMENT ) {
+                       } elseif ( $this->qualifiedNameEquals( $tag, 'svg', 'metadata' ) && $type == XmlReader::ELEMENT ) {
                                $this->readXml( $tag, 'metadata' );
                        } elseif ( $tag !== '#text' ) {
                                $this->debug( "Unhandled top-level XML tag $tag" );
@@ -110,6 +113,8 @@ class SVGReader {
                        }
                }
 
+               $this->reader->close();
+
                return true;
        }
 
@@ -127,7 +132,6 @@ class SVGReader {
                $keepReading = $this->reader->read();
                while( $keepReading ) {
                        if( $this->reader->name == $name && $this->reader->nodeType == XmlReader::END_ELEMENT ) {
-                               $keepReading = false;
                                break;
                        } elseif( $this->reader->nodeType == XmlReader::TEXT ){
                                $this->metadata[$metafield] = $this->reader->value;
@@ -157,24 +161,31 @@ class SVGReader {
         * @param String $name of the element that we are reading from
         */
        private function animateFilter( $name ) {
-               $this->debug ( "animate filter" );
+               $this->debug ( "animate filter for tag $name" );
                if( $this->reader->nodeType != XmlReader::ELEMENT ) {
                        return;
                }
+               if ( $this->reader->isEmptyElement ) {
+                       return;
+               }
                $exitDepth =  $this->reader->depth;
                $keepReading = $this->reader->read();
                while( $keepReading ) {
                        if( $this->reader->name == $name && $this->reader->depth <= $exitDepth
                                && $this->reader->nodeType == XmlReader::END_ELEMENT ) {
-                               $keepReading = false;
                                break;
-                       } elseif( $this->reader->nodeType == XmlReader::ELEMENT ){
+                       } elseif ( $this->reader->nodeType == XmlReader::ELEMENT ) {
                                switch( $this->reader->name ) {
                                        case 'animate':
+                                       case 'svg:animate':
                                        case 'set':
+                                       case 'svg:set':
                                        case 'animateMotion':
+                                       case 'svg:animateMotion':
                                        case 'animateColor':
+                                       case 'svg:animateColor':
                                        case 'animateTransform':
+                                       case 'svg:animateTransform':
                                                $this->debug( "HOUSTON WE HAVE ANIMATION" );
                                                $this->metadata['animated'] = true;
                                                break;
@@ -283,4 +294,22 @@ class SVGReader {
                        return floatval( $length );
                }
        }
+
+       /**
+        * XML namespace check
+        *
+        * Check if a read node name matches the expected nodeName
+        * @param $qualifiedName as read by XMLReader
+        * @param $prefix the namespace prefix that you expect for this element, defaults to svg namespace
+        * @param $localName the localName part of the element that you want to match
+        *
+        * @return boolean
+        */
+       private function qualifiedNameEquals( $qualifiedName, $prefix="svg", $localName ) {
+               if( ($qualifiedName == $localName && $prefix == "svg" ) ||
+                    $qualifiedName == ($prefix . ":" . $localName) ) {
+                       return true;
+               }
+               return false;
+       }
 }