Index: trunk/phase3/includes/media/Generic.php |
— | — | @@ -83,7 +83,8 @@ |
84 | 84 | /** |
85 | 85 | * Get handler-specific metadata which will be saved in the img_metadata field. |
86 | 86 | * |
87 | | - * @param $image File: the image object, or false if there isn't one |
| 87 | + * @param $image File: the image object, or false if there isn't one. |
| 88 | + * Warning, File::getPropsFromPath might pass an (object)array() instead (!) |
88 | 89 | * @param $path String: the filename |
89 | 90 | * @return String |
90 | 91 | */ |
Index: trunk/phase3/includes/media/SVGMetadataExtractor.php |
— | — | @@ -47,13 +47,40 @@ |
48 | 48 | * @param $source String: URI from which to read |
49 | 49 | */ |
50 | 50 | function __construct( $source ) { |
| 51 | + global $wgSVGMetadataCutoff; |
51 | 52 | $this->reader = new XMLReader(); |
52 | | - $this->reader->open( $source, null, LIBXML_NOERROR | LIBXML_NOWARNING ); |
53 | 53 | |
| 54 | + // Don't use $file->getSize() since file object passed to SVGHandler::getMetadata is bogus. |
| 55 | + $size = filesize( $source ); |
| 56 | + if ( $size === false ) { |
| 57 | + throw new MWException( "Error getting filesize of SVG." ); |
| 58 | + } |
| 59 | + |
| 60 | + if ( $size > $wgSVGMetadataCutoff ) { |
| 61 | + $this->debug( "SVG is $size bytes, which is bigger than $wgSVGMetadataCutoff. Truncating." ); |
| 62 | + $contents = file_get_contents( $source, false, null, -1, $wgSVGMetadataCutoff ); |
| 63 | + if ($contents === false) { |
| 64 | + throw new MWException( 'Error reading SVG file.' ); |
| 65 | + } |
| 66 | + $this->reader->XML( $contents, null, LIBXML_NOERROR | LIBXML_NOWARNING ); |
| 67 | + } else { |
| 68 | + $this->reader->open( $source, null, LIBXML_NOERROR | LIBXML_NOWARNING ); |
| 69 | + } |
| 70 | + |
54 | 71 | $this->metadata['width'] = self::DEFAULT_WIDTH; |
55 | 72 | $this->metadata['height'] = self::DEFAULT_HEIGHT; |
56 | 73 | |
57 | | - $this->read(); |
| 74 | + // Because we cut off the end of the svg making an invalid one. Complicated |
| 75 | + // try catch thing to make sure warnings get restored. Seems like there should |
| 76 | + // be a better way. |
| 77 | + wfSuppressWarnings(); |
| 78 | + try { |
| 79 | + $this->read(); |
| 80 | + } catch( Exception $e ) { |
| 81 | + wfRestoreWarnings(); |
| 82 | + throw $e; |
| 83 | + } |
| 84 | + wfRestoreWarnings(); |
58 | 85 | } |
59 | 86 | |
60 | 87 | /* |
— | — | @@ -83,7 +110,6 @@ |
84 | 111 | |
85 | 112 | $exitDepth = $this->reader->depth; |
86 | 113 | $keepReading = $this->reader->read(); |
87 | | - $skip = false; |
88 | 114 | while ( $keepReading ) { |
89 | 115 | $tag = $this->reader->name; |
90 | 116 | $type = $this->reader->nodeType; |
— | — | @@ -100,17 +126,15 @@ |
101 | 127 | $this->readXml( $tag, 'metadata' ); |
102 | 128 | } elseif ( $tag !== '#text' ) { |
103 | 129 | $this->debug( "Unhandled top-level XML tag $tag" ); |
104 | | - $this->animateFilter( $tag ); |
105 | | - //$skip = true; |
| 130 | + |
| 131 | + if ( !isset( $this->metadata['animated'] ) ) { |
| 132 | + // Recurse into children of current tag, looking for animation. |
| 133 | + $this->animateFilter( $tag ); |
| 134 | + } |
106 | 135 | } |
107 | 136 | |
108 | | - if ($skip) { |
109 | | - $keepReading = $this->reader->next(); |
110 | | - $skip = false; |
111 | | - $this->debug( "Skip" ); |
112 | | - } else { |
113 | | - $keepReading = $this->reader->read(); |
114 | | - } |
| 137 | + // Goto next element, which is sibling of current (Skip children). |
| 138 | + $keepReading = $this->reader->next(); |
115 | 139 | } |
116 | 140 | |
117 | 141 | $this->reader->close(); |
— | — | @@ -134,7 +158,7 @@ |
135 | 159 | if( $this->reader->name == $name && $this->reader->nodeType == XmlReader::END_ELEMENT ) { |
136 | 160 | break; |
137 | 161 | } elseif( $this->reader->nodeType == XmlReader::TEXT ){ |
138 | | - $this->metadata[$metafield] = $this->reader->value; |
| 162 | + $this->metadata[$metafield] = trim( $this->reader->value ); |
139 | 163 | } |
140 | 164 | $keepReading = $this->reader->read(); |
141 | 165 | } |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -675,6 +675,9 @@ |
676 | 676 | $wgSVGConverterPath = ''; |
677 | 677 | /** Don't scale a SVG larger than this */ |
678 | 678 | $wgSVGMaxSize = 2048; |
| 679 | +/** Don't read SVG metadata beyond this point. |
| 680 | + * Default is 1024*256 bytes */ |
| 681 | +$wgSVGMetadataCutoff = 262144; |
679 | 682 | |
680 | 683 | /** |
681 | 684 | * MediaWiki will reject HTMLesque tags in uploaded files due to idiotic browsers which can't |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -49,6 +49,8 @@ |
50 | 50 | * The transliteration for passwords in case they were migrated from an old Latin-1 |
51 | 51 | install (previous to MediaWiki 1.5) is now only done for wikis with |
52 | 52 | $wgLegacyEncoding set. |
| 53 | +* (bug 27508) Add $wgSVGMetadataCutoff to limit the maximum amount of an svg we |
| 54 | + look at when finding metadata to prevent excessive resource usage. |
53 | 55 | |
54 | 56 | === New features in 1.18 === |
55 | 57 | * Added a special page, disabled by default, that allows users with the |