This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Handler for SVG images. |
||
4 | * |
||
5 | * This program is free software; you can redistribute it and/or modify |
||
6 | * it under the terms of the GNU General Public License as published by |
||
7 | * the Free Software Foundation; either version 2 of the License, or |
||
8 | * (at your option) any later version. |
||
9 | * |
||
10 | * This program is distributed in the hope that it will be useful, |
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
13 | * GNU General Public License for more details. |
||
14 | * |
||
15 | * You should have received a copy of the GNU General Public License along |
||
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||
18 | * http://www.gnu.org/copyleft/gpl.html |
||
19 | * |
||
20 | * @file |
||
21 | * @ingroup Media |
||
22 | */ |
||
23 | use Wikimedia\ScopedCallback; |
||
0 ignored issues
–
show
|
|||
24 | |||
25 | /** |
||
26 | * Handler for SVG images. |
||
27 | * |
||
28 | * @ingroup Media |
||
29 | */ |
||
30 | class SvgHandler extends ImageHandler { |
||
31 | const SVG_METADATA_VERSION = 2; |
||
32 | |||
33 | /** @var array A list of metadata tags that can be converted |
||
34 | * to the commonly used exif tags. This allows messages |
||
35 | * to be reused, and consistent tag names for {{#formatmetadata:..}} |
||
36 | */ |
||
37 | private static $metaConversion = [ |
||
38 | 'originalwidth' => 'ImageWidth', |
||
39 | 'originalheight' => 'ImageLength', |
||
40 | 'description' => 'ImageDescription', |
||
41 | 'title' => 'ObjectName', |
||
42 | ]; |
||
43 | |||
44 | function isEnabled() { |
||
45 | global $wgSVGConverters, $wgSVGConverter; |
||
46 | if ( !isset( $wgSVGConverters[$wgSVGConverter] ) ) { |
||
47 | wfDebug( "\$wgSVGConverter is invalid, disabling SVG rendering.\n" ); |
||
48 | |||
49 | return false; |
||
50 | } else { |
||
51 | return true; |
||
52 | } |
||
53 | } |
||
54 | |||
55 | public function mustRender( $file ) { |
||
56 | return true; |
||
57 | } |
||
58 | |||
59 | function isVectorized( $file ) { |
||
60 | return true; |
||
61 | } |
||
62 | |||
63 | /** |
||
64 | * @param File $file |
||
65 | * @return bool |
||
66 | */ |
||
67 | function isAnimatedImage( $file ) { |
||
68 | # @todo Detect animated SVGs |
||
69 | $metadata = $file->getMetadata(); |
||
70 | if ( $metadata ) { |
||
71 | $metadata = $this->unpackMetadata( $metadata ); |
||
72 | if ( isset( $metadata['animated'] ) ) { |
||
73 | return $metadata['animated']; |
||
74 | } |
||
75 | } |
||
76 | |||
77 | return false; |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * Which languages (systemLanguage attribute) is supported. |
||
82 | * |
||
83 | * @note This list is not guaranteed to be exhaustive. |
||
84 | * To avoid OOM errors, we only look at first bit of a file. |
||
85 | * Thus all languages on this list are present in the file, |
||
86 | * but its possible for the file to have a language not on |
||
87 | * this list. |
||
88 | * |
||
89 | * @param File $file |
||
90 | * @return array Array of language codes, or empty if no language switching supported. |
||
91 | */ |
||
92 | public function getAvailableLanguages( File $file ) { |
||
93 | $metadata = $file->getMetadata(); |
||
94 | $langList = []; |
||
95 | if ( $metadata ) { |
||
96 | $metadata = $this->unpackMetadata( $metadata ); |
||
97 | if ( isset( $metadata['translations'] ) ) { |
||
98 | foreach ( $metadata['translations'] as $lang => $langType ) { |
||
99 | if ( $langType === SVGReader::LANG_FULL_MATCH ) { |
||
100 | $langList[] = $lang; |
||
101 | } |
||
102 | } |
||
103 | } |
||
104 | } |
||
105 | return $langList; |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * What language to render file in if none selected. |
||
110 | * |
||
111 | * @param File $file |
||
112 | * @return string Language code. |
||
113 | */ |
||
114 | public function getDefaultRenderLanguage( File $file ) { |
||
115 | return 'en'; |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * We do not support making animated svg thumbnails |
||
120 | * @param File $file |
||
121 | * @return bool |
||
122 | */ |
||
123 | function canAnimateThumbnail( $file ) { |
||
124 | return false; |
||
125 | } |
||
126 | |||
127 | /** |
||
128 | * @param File $image |
||
129 | * @param array $params |
||
130 | * @return bool |
||
131 | */ |
||
132 | function normaliseParams( $image, &$params ) { |
||
133 | global $wgSVGMaxSize; |
||
134 | if ( !parent::normaliseParams( $image, $params ) ) { |
||
135 | return false; |
||
136 | } |
||
137 | # Don't make an image bigger than wgMaxSVGSize on the smaller side |
||
138 | if ( $params['physicalWidth'] <= $params['physicalHeight'] ) { |
||
139 | View Code Duplication | if ( $params['physicalWidth'] > $wgSVGMaxSize ) { |
|
140 | $srcWidth = $image->getWidth( $params['page'] ); |
||
141 | $srcHeight = $image->getHeight( $params['page'] ); |
||
142 | $params['physicalWidth'] = $wgSVGMaxSize; |
||
143 | $params['physicalHeight'] = File::scaleHeight( $srcWidth, $srcHeight, $wgSVGMaxSize ); |
||
0 ignored issues
–
show
It seems like
$srcWidth defined by $image->getWidth($params['page']) on line 140 can also be of type boolean ; however, File::scaleHeight() does only seem to accept integer , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() It seems like
$srcHeight defined by $image->getHeight($params['page']) on line 141 can also be of type boolean ; however, File::scaleHeight() does only seem to accept integer , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
144 | } |
||
145 | View Code Duplication | } else { |
|
146 | if ( $params['physicalHeight'] > $wgSVGMaxSize ) { |
||
147 | $srcWidth = $image->getWidth( $params['page'] ); |
||
148 | $srcHeight = $image->getHeight( $params['page'] ); |
||
149 | $params['physicalWidth'] = File::scaleHeight( $srcHeight, $srcWidth, $wgSVGMaxSize ); |
||
0 ignored issues
–
show
It seems like
$srcHeight defined by $image->getHeight($params['page']) on line 148 can also be of type boolean ; however, File::scaleHeight() does only seem to accept integer , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() It seems like
$srcWidth defined by $image->getWidth($params['page']) on line 147 can also be of type boolean ; however, File::scaleHeight() does only seem to accept integer , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
150 | $params['physicalHeight'] = $wgSVGMaxSize; |
||
151 | } |
||
152 | } |
||
153 | |||
154 | return true; |
||
155 | } |
||
156 | |||
157 | /** |
||
158 | * @param File $image |
||
159 | * @param string $dstPath |
||
160 | * @param string $dstUrl |
||
161 | * @param array $params |
||
162 | * @param int $flags |
||
163 | * @return bool|MediaTransformError|ThumbnailImage|TransformParameterError |
||
164 | */ |
||
165 | function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { |
||
166 | if ( !$this->normaliseParams( $image, $params ) ) { |
||
167 | return new TransformParameterError( $params ); |
||
168 | } |
||
169 | $clientWidth = $params['width']; |
||
170 | $clientHeight = $params['height']; |
||
171 | $physicalWidth = $params['physicalWidth']; |
||
172 | $physicalHeight = $params['physicalHeight']; |
||
173 | $lang = isset( $params['lang'] ) ? $params['lang'] : $this->getDefaultRenderLanguage( $image ); |
||
174 | |||
175 | if ( $flags & self::TRANSFORM_LATER ) { |
||
176 | return new ThumbnailImage( $image, $dstUrl, $dstPath, $params ); |
||
177 | } |
||
178 | |||
179 | $metadata = $this->unpackMetadata( $image->getMetadata() ); |
||
180 | if ( isset( $metadata['error'] ) ) { // sanity check |
||
181 | $err = wfMessage( 'svg-long-error', $metadata['error']['message'] )->text(); |
||
182 | |||
183 | return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight, $err ); |
||
184 | } |
||
185 | |||
186 | View Code Duplication | if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) { |
|
187 | return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight, |
||
188 | wfMessage( 'thumbnail_dest_directory' )->text() ); |
||
189 | } |
||
190 | |||
191 | $srcPath = $image->getLocalRefPath(); |
||
192 | View Code Duplication | if ( $srcPath === false ) { // Failed to get local copy |
|
193 | wfDebugLog( 'thumbnail', |
||
194 | sprintf( 'Thumbnail failed on %s: could not get local copy of "%s"', |
||
195 | wfHostname(), $image->getName() ) ); |
||
196 | |||
197 | return new MediaTransformError( 'thumbnail_error', |
||
198 | $params['width'], $params['height'], |
||
199 | wfMessage( 'filemissing' )->text() |
||
200 | ); |
||
201 | } |
||
202 | |||
203 | // Make a temp dir with a symlink to the local copy in it. |
||
204 | // This plays well with rsvg-convert policy for external entities. |
||
205 | // https://git.gnome.org/browse/librsvg/commit/?id=f01aded72c38f0e18bc7ff67dee800e380251c8e |
||
206 | $tmpDir = wfTempDir() . '/svg_' . wfRandomString( 24 ); |
||
207 | $lnPath = "$tmpDir/" . basename( $srcPath ); |
||
208 | $ok = mkdir( $tmpDir, 0771 ) && symlink( $srcPath, $lnPath ); |
||
209 | /** @noinspection PhpUnusedLocalVariableInspection */ |
||
210 | $cleaner = new ScopedCallback( function () use ( $tmpDir, $lnPath ) { |
||
0 ignored issues
–
show
$cleaner is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
211 | MediaWiki\suppressWarnings(); |
||
212 | unlink( $lnPath ); |
||
213 | rmdir( $tmpDir ); |
||
214 | MediaWiki\restoreWarnings(); |
||
215 | } ); |
||
216 | View Code Duplication | if ( !$ok ) { |
|
217 | wfDebugLog( 'thumbnail', |
||
218 | sprintf( 'Thumbnail failed on %s: could not link %s to %s', |
||
219 | wfHostname(), $lnPath, $srcPath ) ); |
||
220 | return new MediaTransformError( 'thumbnail_error', |
||
221 | $params['width'], $params['height'], |
||
222 | wfMessage( 'thumbnail-temp-create' )->text() |
||
223 | ); |
||
224 | } |
||
225 | |||
226 | $status = $this->rasterize( $lnPath, $dstPath, $physicalWidth, $physicalHeight, $lang ); |
||
227 | if ( $status === true ) { |
||
228 | return new ThumbnailImage( $image, $dstUrl, $dstPath, $params ); |
||
229 | } else { |
||
230 | return $status; // MediaTransformError |
||
231 | } |
||
232 | } |
||
233 | |||
234 | /** |
||
235 | * Transform an SVG file to PNG |
||
236 | * This function can be called outside of thumbnail contexts |
||
237 | * @param string $srcPath |
||
238 | * @param string $dstPath |
||
239 | * @param string $width |
||
240 | * @param string $height |
||
241 | * @param bool|string $lang Language code of the language to render the SVG in |
||
242 | * @throws MWException |
||
243 | * @return bool|MediaTransformError |
||
244 | */ |
||
245 | public function rasterize( $srcPath, $dstPath, $width, $height, $lang = false ) { |
||
246 | global $wgSVGConverters, $wgSVGConverter, $wgSVGConverterPath; |
||
247 | $err = false; |
||
248 | $retval = ''; |
||
249 | if ( isset( $wgSVGConverters[$wgSVGConverter] ) ) { |
||
250 | if ( is_array( $wgSVGConverters[$wgSVGConverter] ) ) { |
||
251 | // This is a PHP callable |
||
252 | $func = $wgSVGConverters[$wgSVGConverter][0]; |
||
253 | $args = array_merge( [ $srcPath, $dstPath, $width, $height, $lang ], |
||
254 | array_slice( $wgSVGConverters[$wgSVGConverter], 1 ) ); |
||
255 | if ( !is_callable( $func ) ) { |
||
256 | throw new MWException( "$func is not callable" ); |
||
257 | } |
||
258 | $err = call_user_func_array( $func, $args ); |
||
259 | $retval = (bool)$err; |
||
260 | } else { |
||
261 | // External command |
||
262 | $cmd = str_replace( |
||
263 | [ '$path/', '$width', '$height', '$input', '$output' ], |
||
264 | [ $wgSVGConverterPath ? wfEscapeShellArg( "$wgSVGConverterPath/" ) : "", |
||
265 | intval( $width ), |
||
266 | intval( $height ), |
||
267 | wfEscapeShellArg( $srcPath ), |
||
268 | wfEscapeShellArg( $dstPath ) ], |
||
269 | $wgSVGConverters[$wgSVGConverter] |
||
270 | ); |
||
271 | |||
272 | $env = []; |
||
273 | if ( $lang !== false ) { |
||
274 | $env['LANG'] = $lang; |
||
275 | } |
||
276 | |||
277 | wfDebug( __METHOD__ . ": $cmd\n" ); |
||
278 | $err = wfShellExecWithStderr( $cmd, $retval, $env ); |
||
279 | } |
||
280 | } |
||
281 | $removed = $this->removeBadFile( $dstPath, $retval ); |
||
282 | if ( $retval != 0 || $removed ) { |
||
283 | $this->logErrorForExternalProcess( $retval, $err, $cmd ); |
||
0 ignored issues
–
show
The variable
$cmd does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
284 | return new MediaTransformError( 'thumbnail_error', $width, $height, $err ); |
||
285 | } |
||
286 | |||
287 | return true; |
||
288 | } |
||
289 | |||
290 | public static function rasterizeImagickExt( $srcPath, $dstPath, $width, $height ) { |
||
291 | $im = new Imagick( $srcPath ); |
||
292 | $im->setImageFormat( 'png' ); |
||
293 | $im->setBackgroundColor( 'transparent' ); |
||
294 | $im->setImageDepth( 8 ); |
||
295 | |||
296 | if ( !$im->thumbnailImage( intval( $width ), intval( $height ), /* fit */ false ) ) { |
||
297 | return 'Could not resize image'; |
||
298 | } |
||
299 | if ( !$im->writeImage( $dstPath ) ) { |
||
300 | return "Could not write to $dstPath"; |
||
301 | } |
||
302 | } |
||
303 | |||
304 | /** |
||
305 | * @param File|FSFile $file |
||
306 | * @param string $path Unused |
||
307 | * @param bool|array $metadata |
||
308 | * @return array |
||
309 | */ |
||
310 | function getImageSize( $file, $path, $metadata = false ) { |
||
311 | if ( $metadata === false && $file instanceof File ) { |
||
312 | $metadata = $file->getMetadata(); |
||
313 | } |
||
314 | $metadata = $this->unpackMetadata( $metadata ); |
||
315 | |||
316 | if ( isset( $metadata['width'] ) && isset( $metadata['height'] ) ) { |
||
317 | return [ $metadata['width'], $metadata['height'], 'SVG', |
||
318 | "width=\"{$metadata['width']}\" height=\"{$metadata['height']}\"" ]; |
||
319 | } else { // error |
||
320 | return [ 0, 0, 'SVG', "width=\"0\" height=\"0\"" ]; |
||
321 | } |
||
322 | } |
||
323 | |||
324 | function getThumbType( $ext, $mime, $params = null ) { |
||
325 | return [ 'png', 'image/png' ]; |
||
326 | } |
||
327 | |||
328 | /** |
||
329 | * Subtitle for the image. Different from the base |
||
330 | * class so it can be denoted that SVG's have |
||
331 | * a "nominal" resolution, and not a fixed one, |
||
332 | * as well as so animation can be denoted. |
||
333 | * |
||
334 | * @param File $file |
||
335 | * @return string |
||
336 | */ |
||
337 | function getLongDesc( $file ) { |
||
338 | global $wgLang; |
||
339 | |||
340 | $metadata = $this->unpackMetadata( $file->getMetadata() ); |
||
341 | if ( isset( $metadata['error'] ) ) { |
||
342 | return wfMessage( 'svg-long-error', $metadata['error']['message'] )->text(); |
||
343 | } |
||
344 | |||
345 | $size = $wgLang->formatSize( $file->getSize() ); |
||
346 | |||
347 | if ( $this->isAnimatedImage( $file ) ) { |
||
348 | $msg = wfMessage( 'svg-long-desc-animated' ); |
||
349 | } else { |
||
350 | $msg = wfMessage( 'svg-long-desc' ); |
||
351 | } |
||
352 | |||
353 | $msg->numParams( $file->getWidth(), $file->getHeight() )->params( $size ); |
||
354 | |||
355 | return $msg->parse(); |
||
356 | } |
||
357 | |||
358 | /** |
||
359 | * @param File|FSFile $file |
||
360 | * @param string $filename |
||
361 | * @return string Serialised metadata |
||
362 | */ |
||
363 | function getMetadata( $file, $filename ) { |
||
364 | $metadata = [ 'version' => self::SVG_METADATA_VERSION ]; |
||
365 | try { |
||
366 | $metadata += SVGMetadataExtractor::getMetadata( $filename ); |
||
367 | } catch ( Exception $e ) { // @todo SVG specific exceptions |
||
368 | // File not found, broken, etc. |
||
369 | $metadata['error'] = [ |
||
370 | 'message' => $e->getMessage(), |
||
371 | 'code' => $e->getCode() |
||
372 | ]; |
||
373 | wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" ); |
||
374 | } |
||
375 | |||
376 | return serialize( $metadata ); |
||
377 | } |
||
378 | |||
379 | View Code Duplication | function unpackMetadata( $metadata ) { |
|
380 | MediaWiki\suppressWarnings(); |
||
381 | $unser = unserialize( $metadata ); |
||
382 | MediaWiki\restoreWarnings(); |
||
383 | if ( isset( $unser['version'] ) && $unser['version'] == self::SVG_METADATA_VERSION ) { |
||
384 | return $unser; |
||
385 | } else { |
||
386 | return false; |
||
387 | } |
||
388 | } |
||
389 | |||
390 | function getMetadataType( $image ) { |
||
391 | return 'parsed-svg'; |
||
392 | } |
||
393 | |||
394 | function isMetadataValid( $image, $metadata ) { |
||
395 | $meta = $this->unpackMetadata( $metadata ); |
||
396 | if ( $meta === false ) { |
||
397 | return self::METADATA_BAD; |
||
398 | } |
||
399 | if ( !isset( $meta['originalWidth'] ) ) { |
||
400 | // Old but compatible |
||
401 | return self::METADATA_COMPATIBLE; |
||
402 | } |
||
403 | |||
404 | return self::METADATA_GOOD; |
||
405 | } |
||
406 | |||
407 | protected function visibleMetadataFields() { |
||
408 | $fields = [ 'objectname', 'imagedescription' ]; |
||
409 | |||
410 | return $fields; |
||
411 | } |
||
412 | |||
413 | /** |
||
414 | * @param File $file |
||
415 | * @param bool|IContextSource $context Context to use (optional) |
||
416 | * @return array|bool |
||
417 | */ |
||
418 | function formatMetadata( $file, $context = false ) { |
||
419 | $result = [ |
||
420 | 'visible' => [], |
||
421 | 'collapsed' => [] |
||
422 | ]; |
||
423 | $metadata = $file->getMetadata(); |
||
424 | if ( !$metadata ) { |
||
425 | return false; |
||
426 | } |
||
427 | $metadata = $this->unpackMetadata( $metadata ); |
||
428 | if ( !$metadata || isset( $metadata['error'] ) ) { |
||
429 | return false; |
||
430 | } |
||
431 | |||
432 | /* @todo Add a formatter |
||
433 | $format = new FormatSVG( $metadata ); |
||
434 | $formatted = $format->getFormattedData(); |
||
435 | */ |
||
436 | |||
437 | // Sort fields into visible and collapsed |
||
438 | $visibleFields = $this->visibleMetadataFields(); |
||
439 | |||
440 | $showMeta = false; |
||
441 | foreach ( $metadata as $name => $value ) { |
||
442 | $tag = strtolower( $name ); |
||
443 | if ( isset( self::$metaConversion[$tag] ) ) { |
||
444 | $tag = strtolower( self::$metaConversion[$tag] ); |
||
445 | } else { |
||
446 | // Do not output other metadata not in list |
||
447 | continue; |
||
448 | } |
||
449 | $showMeta = true; |
||
450 | self::addMeta( $result, |
||
451 | in_array( $tag, $visibleFields ) ? 'visible' : 'collapsed', |
||
452 | 'exif', |
||
453 | $tag, |
||
454 | $value |
||
455 | ); |
||
456 | } |
||
457 | |||
458 | return $showMeta ? $result : false; |
||
459 | } |
||
460 | |||
461 | /** |
||
462 | * @param string $name Parameter name |
||
463 | * @param mixed $value Parameter value |
||
464 | * @return bool Validity |
||
465 | */ |
||
466 | public function validateParam( $name, $value ) { |
||
467 | if ( in_array( $name, [ 'width', 'height' ] ) ) { |
||
468 | // Reject negative heights, widths |
||
469 | return ( $value > 0 ); |
||
470 | } elseif ( $name == 'lang' ) { |
||
471 | // Validate $code |
||
472 | if ( $value === '' || !Language::isValidBuiltInCode( $value ) ) { |
||
473 | wfDebug( "Invalid user language code\n" ); |
||
474 | |||
475 | return false; |
||
476 | } |
||
477 | |||
478 | return true; |
||
479 | } |
||
480 | |||
481 | // Only lang, width and height are acceptable keys |
||
482 | return false; |
||
483 | } |
||
484 | |||
485 | /** |
||
486 | * @param array $params Name=>value pairs of parameters |
||
487 | * @return string Filename to use |
||
488 | */ |
||
489 | public function makeParamString( $params ) { |
||
490 | $lang = ''; |
||
491 | if ( isset( $params['lang'] ) && $params['lang'] !== 'en' ) { |
||
492 | $params['lang'] = strtolower( $params['lang'] ); |
||
493 | $lang = "lang{$params['lang']}-"; |
||
494 | } |
||
495 | if ( !isset( $params['width'] ) ) { |
||
496 | return false; |
||
497 | } |
||
498 | |||
499 | return "$lang{$params['width']}px"; |
||
500 | } |
||
501 | |||
502 | public function parseParamString( $str ) { |
||
503 | $m = false; |
||
504 | if ( preg_match( '/^lang([a-z]+(?:-[a-z]+)*)-(\d+)px$/', $str, $m ) ) { |
||
505 | return [ 'width' => array_pop( $m ), 'lang' => $m[1] ]; |
||
506 | } elseif ( preg_match( '/^(\d+)px$/', $str, $m ) ) { |
||
507 | return [ 'width' => $m[1], 'lang' => 'en' ]; |
||
508 | } else { |
||
509 | return false; |
||
510 | } |
||
511 | } |
||
512 | |||
513 | public function getParamMap() { |
||
514 | return [ 'img_lang' => 'lang', 'img_width' => 'width' ]; |
||
515 | } |
||
516 | |||
517 | /** |
||
518 | * @param array $params |
||
519 | * @return array |
||
520 | */ |
||
521 | function getScriptParams( $params ) { |
||
522 | $scriptParams = [ 'width' => $params['width'] ]; |
||
523 | if ( isset( $params['lang'] ) ) { |
||
524 | $scriptParams['lang'] = $params['lang']; |
||
525 | } |
||
526 | |||
527 | return $scriptParams; |
||
528 | } |
||
529 | |||
530 | public function getCommonMetaArray( File $file ) { |
||
531 | $metadata = $file->getMetadata(); |
||
532 | if ( !$metadata ) { |
||
533 | return []; |
||
534 | } |
||
535 | $metadata = $this->unpackMetadata( $metadata ); |
||
536 | if ( !$metadata || isset( $metadata['error'] ) ) { |
||
537 | return []; |
||
538 | } |
||
539 | $stdMetadata = []; |
||
540 | foreach ( $metadata as $name => $value ) { |
||
541 | $tag = strtolower( $name ); |
||
542 | if ( $tag === 'originalwidth' || $tag === 'originalheight' ) { |
||
543 | // Skip these. In the exif metadata stuff, it is assumed these |
||
544 | // are measured in px, which is not the case here. |
||
545 | continue; |
||
546 | } |
||
547 | if ( isset( self::$metaConversion[$tag] ) ) { |
||
548 | $tag = self::$metaConversion[$tag]; |
||
549 | $stdMetadata[$tag] = $value; |
||
550 | } |
||
551 | } |
||
552 | |||
553 | return $stdMetadata; |
||
554 | } |
||
555 | } |
||
556 |
Let’s assume that you have a directory layout like this:
and let’s assume the following content of
Bar.php
:If both files
OtherDir/Foo.php
andSomeDir/Foo.php
are loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as
OtherDir/Foo.php
does not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php
, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: