diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2013-01-18 16:46:04 +0100 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2013-01-18 16:46:04 +0100 |
commit | 63601400e476c6cf43d985f3e7b9864681695ed4 (patch) | |
tree | f7846203a952e38aaf66989d0a4702779f549962 /includes/media | |
parent | 8ff01378c9e0207f9169b81966a51def645b6a51 (diff) |
Update to MediaWiki 1.20.2
this update includes:
* adjusted Arch Linux skin
* updated FluxBBAuthPlugin
* patch for https://bugzilla.wikimedia.org/show_bug.cgi?id=44024
Diffstat (limited to 'includes/media')
26 files changed, 1012 insertions, 407 deletions
diff --git a/includes/media/BMP.php b/includes/media/BMP.php index 6886e950..a515c635 100644 --- a/includes/media/BMP.php +++ b/includes/media/BMP.php @@ -1,6 +1,21 @@ <?php /** - * Handler for Microsoft's bitmap format + * Handler for Microsoft's bitmap format. + * + * 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 diff --git a/includes/media/Bitmap.php b/includes/media/Bitmap.php index 619485cc..99ac854b 100644 --- a/includes/media/Bitmap.php +++ b/includes/media/Bitmap.php @@ -1,6 +1,21 @@ <?php /** - * Generic handler for bitmap images + * Generic handler for bitmap 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 @@ -152,8 +167,11 @@ class BitmapHandler extends ImageHandler { if ( $flags & self::TRANSFORM_LATER ) { wfDebug( __METHOD__ . ": Transforming later per flags.\n" ); - return new ThumbnailImage( $image, $dstUrl, $scalerParams['clientWidth'], - $scalerParams['clientHeight'], false ); + $params = array( + 'width' => $scalerParams['clientWidth'], + 'height' => $scalerParams['clientHeight'] + ); + return new ThumbnailImage( $image, $dstUrl, false, $params ); } # Try to make a target path for the thumbnail @@ -205,8 +223,11 @@ class BitmapHandler extends ImageHandler { } elseif ( $mto ) { return $mto; } else { - return new ThumbnailImage( $image, $dstUrl, $scalerParams['clientWidth'], - $scalerParams['clientHeight'], $dstPath ); + $params = array( + 'width' => $scalerParams['clientWidth'], + 'height' => $scalerParams['clientHeight'] + ); + return new ThumbnailImage( $image, $dstUrl, $dstPath, $params ); } } @@ -243,14 +264,17 @@ class BitmapHandler extends ImageHandler { * client side * * @param $image File File associated with this thumbnail - * @param $params array Array with scaler params + * @param $scalerParams array Array with scaler params * @return ThumbnailImage * - * @fixme no rotation support + * @todo fixme: no rotation support */ - protected function getClientScalingThumbnailImage( $image, $params ) { - return new ThumbnailImage( $image, $image->getURL(), - $params['clientWidth'], $params['clientHeight'], null ); + protected function getClientScalingThumbnailImage( $image, $scalerParams ) { + $params = array( + 'width' => $scalerParams['clientWidth'], + 'height' => $scalerParams['clientHeight'] + ); + return new ThumbnailImage( $image, $image->getURL(), null, $params ); } /** @@ -259,7 +283,7 @@ class BitmapHandler extends ImageHandler { * @param $image File File associated with this thumbnail * @param $params array Array with scaler params * - * @return MediaTransformError Error object if error occured, false (=no error) otherwise + * @return MediaTransformError Error object if error occurred, false (=no error) otherwise */ protected function transformImageMagick( $image, $params ) { # use ImageMagick @@ -358,7 +382,7 @@ class BitmapHandler extends ImageHandler { * @param $image File File associated with this thumbnail * @param $params array Array with scaler params * - * @return MediaTransformError Error object if error occured, false (=no error) otherwise + * @return MediaTransformError Error object if error occurred, false (=no error) otherwise */ protected function transformImageMagickExt( $image, $params ) { global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea; @@ -435,7 +459,7 @@ class BitmapHandler extends ImageHandler { * @param $image File File associated with this thumbnail * @param $params array Array with scaler params * - * @return MediaTransformError Error object if error occured, false (=no error) otherwise + * @return MediaTransformError Error object if error occurred, false (=no error) otherwise */ protected function transformCustom( $image, $params ) { # Use a custom convert command @@ -462,7 +486,7 @@ class BitmapHandler extends ImageHandler { } /** - * Log an error that occured in an external process + * Log an error that occurred in an external process * * @param $retval int * @param $err int @@ -491,7 +515,7 @@ class BitmapHandler extends ImageHandler { * @param $image File File associated with this thumbnail * @param $params array Array with scaler params * - * @return MediaTransformError Error object if error occured, false (=no error) otherwise + * @return MediaTransformError Error object if error occurred, false (=no error) otherwise */ protected function transformGd( $image, $params ) { # Use PHP's builtin GD library functions. @@ -509,7 +533,7 @@ class BitmapHandler extends ImageHandler { if ( !isset( $typemap[$params['mimeType']] ) ) { $err = 'Image type not supported'; wfDebug( "$err\n" ); - $errMsg = wfMsg( 'thumbnail_image-type' ); + $errMsg = wfMessage( 'thumbnail_image-type' )->text(); return $this->getMediaTransformError( $params, $errMsg ); } list( $loader, $colorStyle, $saveType ) = $typemap[$params['mimeType']]; @@ -517,14 +541,14 @@ class BitmapHandler extends ImageHandler { if ( !function_exists( $loader ) ) { $err = "Incomplete GD library configuration: missing function $loader"; wfDebug( "$err\n" ); - $errMsg = wfMsg( 'thumbnail_gd-library', $loader ); + $errMsg = wfMessage( 'thumbnail_gd-library', $loader )->text(); return $this->getMediaTransformError( $params, $errMsg ); } if ( !file_exists( $params['srcPath'] ) ) { $err = "File seems to be missing: {$params['srcPath']}"; wfDebug( "$err\n" ); - $errMsg = wfMsg( 'thumbnail_image-missing', $params['srcPath'] ); + $errMsg = wfMessage( 'thumbnail_image-missing', $params['srcPath'] )->text(); return $this->getMediaTransformError( $params, $errMsg ); } @@ -572,6 +596,7 @@ class BitmapHandler extends ImageHandler { /** * Escape a string for ImageMagick's property input (e.g. -set -comment) * See InterpretImageProperties() in magick/property.c + * @return mixed|string */ function escapeMagickProperty( $s ) { // Double the backslashes @@ -599,6 +624,7 @@ class BitmapHandler extends ImageHandler { * * @param $path string The file path * @param $scene string The scene specification, or false if there is none + * @return string */ function escapeMagickInput( $path, $scene = false ) { # Die on initial metacharacters (caller should prepend path) @@ -616,6 +642,7 @@ class BitmapHandler extends ImageHandler { /** * Escape a string for ImageMagick's output filename. See * InterpretImageFilename() in magick/image.c. + * @return string */ function escapeMagickOutput( $path, $scene = false ) { $path = str_replace( '%', '%%', $path ); @@ -628,6 +655,7 @@ class BitmapHandler extends ImageHandler { * * @param $path string The file path * @param $scene string The scene specification, or false if there is none + * @return string */ protected function escapeMagickPath( $path, $scene = false ) { # Die on format specifiers (other than drive letters). The regex is diff --git a/includes/media/BitmapMetadataHandler.php b/includes/media/BitmapMetadataHandler.php index 746dddda..0a195547 100644 --- a/includes/media/BitmapMetadataHandler.php +++ b/includes/media/BitmapMetadataHandler.php @@ -1,13 +1,36 @@ <?php /** -Class to deal with reconciling and extracting metadata from bitmap images. -This is meant to comply with http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf + * Extraction of metadata from different bitmap image types. + * + * 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 + */ -This sort of acts as an intermediary between MediaHandler::getMetadata -and the various metadata extractors. - -@todo other image formats. -*/ +/** + * Class to deal with reconciling and extracting metadata from bitmap images. + * This is meant to comply with http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf + * + * This sort of acts as an intermediary between MediaHandler::getMetadata + * and the various metadata extractors. + * + * @todo other image formats. + * @ingroup Media + */ class BitmapMetadataHandler { private $metadata = array(); @@ -122,7 +145,7 @@ class BitmapMetadataHandler { /** Main entry point for jpeg's. * * @param $filename string filename (with full path) - * @return metadata result array. + * @return array metadata result array. * @throws MWException on invalid file. */ static function Jpeg ( $filename ) { @@ -193,7 +216,7 @@ class BitmapMetadataHandler { * They don't really have native metadata, so just merges together * XMP and image comment. * - * @param $filename full path to file + * @param $filename string full path to file * @return Array metadata array */ static public function GIF ( $filename ) { diff --git a/includes/media/Bitmap_ClientOnly.php b/includes/media/Bitmap_ClientOnly.php index 3c5d9738..63af2552 100644 --- a/includes/media/Bitmap_ClientOnly.php +++ b/includes/media/Bitmap_ClientOnly.php @@ -1,6 +1,21 @@ <?php /** - * Handler for bitmap images that will be resized by clients + * Handler for bitmap images that will be resized by clients. + * + * 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 @@ -37,7 +52,6 @@ class BitmapHandler_ClientOnly extends BitmapHandler { if ( !$this->normaliseParams( $image, $params ) ) { return new TransformParameterError( $params ); } - return new ThumbnailImage( $image, $image->getURL(), $params['width'], - $params['height'], $image->getLocalRefPath() ); + return new ThumbnailImage( $image, $image->getURL(), $image->getLocalRefPath(), $params ); } } diff --git a/includes/media/DjVu.php b/includes/media/DjVu.php index dedbee0d..84672e05 100644 --- a/includes/media/DjVu.php +++ b/includes/media/DjVu.php @@ -1,6 +1,21 @@ <?php /** - * Handler for DjVu images + * Handler for DjVu 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 @@ -123,7 +138,7 @@ class DjVuHandler extends ImageHandler { $width = isset( $params['width'] ) ? $params['width'] : 0; $height = isset( $params['height'] ) ? $params['height'] : 0; return new MediaTransformError( 'thumbnail_error', $width, $height, - wfMsg( 'djvu_no_xml' ) ); + wfMessage( 'djvu_no_xml' )->text() ); } if ( !$this->normaliseParams( $image, $params ) ) { @@ -131,20 +146,35 @@ class DjVuHandler extends ImageHandler { } $width = $params['width']; $height = $params['height']; - $srcPath = $image->getLocalRefPath(); $page = $params['page']; if ( $page > $this->pageCount( $image ) ) { - return new MediaTransformError( 'thumbnail_error', $width, $height, wfMsg( 'djvu_page_error' ) ); + return new MediaTransformError( + 'thumbnail_error', + $width, + $height, + wfMessage( 'djvu_page_error' )->text() + ); } if ( $flags & self::TRANSFORM_LATER ) { - return new ThumbnailImage( $image, $dstUrl, $width, $height, $dstPath, $page ); + $params = array( + 'width' => $width, + 'height' => $height, + 'page' => $page + ); + return new ThumbnailImage( $image, $dstUrl, $dstPath, $params ); } if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) { - return new MediaTransformError( 'thumbnail_error', $width, $height, wfMsg( 'thumbnail_dest_directory' ) ); + return new MediaTransformError( + 'thumbnail_error', + $width, + $height, + wfMessage( 'thumbnail_dest_directory' )->text() + ); } + $srcPath = $image->getLocalRefPath(); # Use a subshell (brackets) to aggregate stderr from both pipeline commands # before redirecting it to the overall stdout. This works in both Linux and Windows XP. $cmd = '(' . wfEscapeShellArg( $wgDjvuRenderer ) . " -format=ppm -page={$page}" . @@ -167,7 +197,12 @@ class DjVuHandler extends ImageHandler { wfHostname(), $retval, trim($err), $cmd ) ); return new MediaTransformError( 'thumbnail_error', $width, $height, $err ); } else { - return new ThumbnailImage( $image, $dstUrl, $width, $height, $dstPath, $page ); + $params = array( + 'width' => $width, + 'height' => $height, + 'page' => $page + ); + return new ThumbnailImage( $image, $dstUrl, $dstPath, $params ); } } @@ -191,6 +226,7 @@ class DjVuHandler extends ImageHandler { * Cache a document tree for the DjVu XML metadata * @param $image File * @param $gettext Boolean: DOCUMENT (Default: false) + * @return bool */ function getMetaTree( $image , $gettext = false ) { if ( isset( $image->dejaMetaTree ) ) { diff --git a/includes/media/DjVuImage.php b/includes/media/DjVuImage.php index 80b7408c..6aef562b 100644 --- a/includes/media/DjVuImage.php +++ b/includes/media/DjVuImage.php @@ -1,6 +1,6 @@ <?php /** - * DjVu image handler + * DjVu image handler. * * Copyright © 2006 Brion Vibber <brion@pobox.com> * http://www.mediawiki.org/ @@ -21,6 +21,7 @@ * http://www.gnu.org/copyleft/gpl.html * * @file + * @ingroup Media */ /** @@ -284,6 +285,7 @@ EOR; /** * Hack to temporarily work around djvutoxml bug + * @return bool|string */ function convertDumpToXML( $dump ) { if ( strval( $dump ) == '' ) { diff --git a/includes/media/Exif.php b/includes/media/Exif.php index a4acdfe0..784a6018 100644 --- a/includes/media/Exif.php +++ b/includes/media/Exif.php @@ -1,5 +1,7 @@ <?php /** + * Extraction and validation of image metadata. + * * 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 @@ -368,6 +370,12 @@ class Exif { $this->exifGPStoNumber( 'GPSDestLongitude' ); if ( isset( $this->mFilteredExifData['GPSAltitude'] ) && isset( $this->mFilteredExifData['GPSAltitudeRef'] ) ) { + + // We know altitude data is a <num>/<denom> from the validation functions ran earlier. + // But multiplying such a string by -1 doesn't work well, so convert. + list( $num, $denom ) = explode( '/', $this->mFilteredExifData['GPSAltitude'] ); + $this->mFilteredExifData['GPSAltitude'] = $num / $denom; + if ( $this->mFilteredExifData['GPSAltitudeRef'] === "\1" ) { $this->mFilteredExifData['GPSAltitude'] *= - 1; } @@ -549,6 +557,7 @@ class Exif { */ /** * Get $this->mRawExifData + * @return array */ function getData() { return $this->mRawExifData; diff --git a/includes/media/ExifBitmap.php b/includes/media/ExifBitmap.php index 7b9867f7..34a1f511 100644 --- a/includes/media/ExifBitmap.php +++ b/includes/media/ExifBitmap.php @@ -1,5 +1,22 @@ <?php /** + * Handler for bitmap images with exif metadata. + * + * 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 */ @@ -182,7 +199,8 @@ class ExifBitmapHandler extends BitmapHandler { * * @param string $data * @return int 0, 90, 180 or 270 - * @fixme orientation can include flipping as well; see if this is an issue! + * @todo FIXME orientation can include flipping as well; see if this is an + * issue! */ protected function getRotationForExif( $data ) { if ( !$data ) { diff --git a/includes/media/FormatMetadata.php b/includes/media/FormatMetadata.php index 91cb6914..843c1fa2 100644 --- a/includes/media/FormatMetadata.php +++ b/includes/media/FormatMetadata.php @@ -1,5 +1,7 @@ <?php /** + * Formating of image metadata values into human readable form. + * * 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 @@ -98,14 +100,20 @@ class FormatMetadata { ) { continue; } - $tags[$tag] = intval( $h[0] / $h[1] ) + $tags[$tag] = str_pad( intval( $h[0] / $h[1] ), 2, '0', STR_PAD_LEFT ) . ':' . str_pad( intval( $m[0] / $m[1] ), 2, '0', STR_PAD_LEFT ) . ':' . str_pad( intval( $s[0] / $s[1] ), 2, '0', STR_PAD_LEFT ); - $time = wfTimestamp( TS_MW, '1971:01:01 ' . $tags[$tag] ); - // the 1971:01:01 is just a placeholder, and not shown to user. - if ( $time && intval( $time ) > 0 ) { - $tags[$tag] = $wgLang->time( $time ); + try { + $time = wfTimestamp( TS_MW, '1971:01:01 ' . $tags[$tag] ); + // the 1971:01:01 is just a placeholder, and not shown to user. + if ( $time && intval( $time ) > 0 ) { + $tags[$tag] = $wgLang->time( $time ); + } + } catch ( TimestampException $e ) { + // This shouldn't happen, but we've seen bad formats + // such as 4-digit seconds in the wild. + // leave $tags[$tag] as-is } continue; } @@ -231,7 +239,7 @@ class FormatMetadata { case 'dc-date': case 'DateTimeMetadata': if ( $val == '0000:00:00 00:00:00' || $val == ' : : : : ' ) { - $val = wfMsg( 'exif-unknowndate' ); + $val = wfMessage( 'exif-unknowndate' )->text(); } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d):(?:\d\d)$/D', $val ) ) { // Full date. $time = wfTimestamp( TS_MW, $val ); @@ -307,7 +315,7 @@ class FormatMetadata { 'redeye' => ( $val & bindec( '01000000' ) ) >> 6, // 'reserved' => ($val & bindec( '10000000' )) >> 7, ); - + $flashMsgs = array(); # We do not need to handle unknown values since all are used. foreach ( $flashDecode as $subTag => $subValue ) { # We do not need any message for zeroed values. @@ -589,7 +597,7 @@ class FormatMetadata { case 'Software': if ( is_array( $val ) ) { //if its a software, version array. - $val = wfMsg( 'exif-software-version-value', $val[0], $val[1] ); + $val = wfMessage( 'exif-software-version-value', $val[0], $val[1] )->text(); } else { $val = self::msg( $tag, '', $val ); } @@ -597,8 +605,8 @@ class FormatMetadata { case 'ExposureTime': // Show the pretty fraction as well as decimal version - $val = wfMsg( 'exif-exposuretime-format', - self::formatFraction( $val ), self::formatNum( $val ) ); + $val = wfMessage( 'exif-exposuretime-format', + self::formatFraction( $val ), self::formatNum( $val ) )->text(); break; case 'ISOSpeedRatings': // If its = 65535 that means its at the @@ -611,13 +619,13 @@ class FormatMetadata { } break; case 'FNumber': - $val = wfMsg( 'exif-fnumber-format', - self::formatNum( $val ) ); + $val = wfMessage( 'exif-fnumber-format', + self::formatNum( $val ) )->text(); break; case 'FocalLength': case 'FocalLengthIn35mmFilm': - $val = wfMsg( 'exif-focallength-format', - self::formatNum( $val ) ); + $val = wfMessage( 'exif-focallength-format', + self::formatNum( $val ) )->text(); break; case 'MaxApertureValue': @@ -631,14 +639,14 @@ class FormatMetadata { if ( is_numeric( $val ) ) { $fNumber = pow( 2, $val / 2 ); if ( $fNumber !== false ) { - $val = wfMsg( 'exif-maxaperturevalue-value', + $val = wfMessage( 'exif-maxaperturevalue-value', self::formatNum( $val ), self::formatNum( $fNumber, 2 ) - ); + )->text(); } } break; - + case 'iimCategory': switch( strtolower( $val ) ) { // See pg 29 of IPTC photo @@ -694,7 +702,7 @@ class FormatMetadata { case 'PixelYDimension': case 'ImageWidth': case 'ImageLength': - $val = self::formatNum( $val ) . ' ' . wfMsg( 'unit-pixel' ); + $val = self::formatNum( $val ) . ' ' . wfMessage( 'unit-pixel' )->text(); break; // Do not transform fields with pure text. @@ -800,7 +808,7 @@ class FormatMetadata { break; case 'LanguageCode': - $lang = $wgLang->getLanguageName( strtolower( $val ) ); + $lang = Language::fetchLanguageName( strtolower( $val ), $wgLang->getCode() ); if ($lang) { $val = htmlspecialchars( $lang ); } else { @@ -825,14 +833,14 @@ class FormatMetadata { * This turns an array of (for example) authors into a bulleted list. * * This is public on the basis it might be useful outside of this class. - * + * * @param $vals Array array of values * @param $type String Type of array (either lang, ul, ol). * lang = language assoc array with keys being the lang code * ul = unordered list, ol = ordered list * type can also come from the '_type' member of $vals. * @param $noHtml Boolean If to avoid returning anything resembling - * html. (Ugly hack for backwards compatibility with old mediawiki). + * html. (Ugly hack for backwards compatibility with old mediawiki). * @return String single value (in wiki-syntax). */ public static function flattenArray( $vals, $type = 'ul', $noHtml = false ) { @@ -874,7 +882,7 @@ class FormatMetadata { // If default is set, save it for later, // as we don't know if it's equal to // one of the lang codes. (In xmp - // you specify the language for a + // you specify the language for a // default property by having both // a default prop, and one in the language // that are identical) @@ -937,11 +945,11 @@ class FormatMetadata { * @param $lang String lang code of item or false * @param $default Boolean if it is default value. * @param $noHtml Boolean If to avoid html (for back-compat) - * @return language item (Note: despite how this looks, - * this is treated as wikitext not html). + * @throws MWException + * @return string language item (Note: despite how this looks, + * this is treated as wikitext not html). */ private static function langItem( $value, $lang, $default = false, $noHtml = false ) { - global $wgContLang; if ( $lang === false && $default === false) { throw new MWException('$lang and $default cannot both ' . 'be false.'); @@ -956,21 +964,21 @@ class FormatMetadata { if ( $lang === false ) { if ( $noHtml ) { - return wfMsg( 'metadata-langitem-default', - $wrappedValue ) . "\n\n"; + return wfMessage( 'metadata-langitem-default', + $wrappedValue )->text() . "\n\n"; } /* else */ return '<li class="mw-metadata-lang-default">' - . wfMsg( 'metadata-langitem-default', - $wrappedValue ) + . wfMessage( 'metadata-langitem-default', + $wrappedValue )->text() . "</li>\n"; } $lowLang = strtolower( $lang ); - $langName = $wgContLang->getLanguageName( $lowLang ); + $langName = Language::fetchLanguageName( $lowLang ); if ( $langName === '' ) { //try just the base language name. (aka en-US -> en ). list( $langPrefix ) = explode( '-', $lowLang, 2 ); - $langName = $wgContLang->getLanguageName( $langPrefix ); + $langName = Language::fetchLanguageName( $langPrefix ); if ( $langName === '' ) { // give up. $langName = $lang; @@ -979,8 +987,8 @@ class FormatMetadata { // else we have a language specified if ( $noHtml ) { - return '*' . wfMsg( 'metadata-langitem', - $wrappedValue, $langName, $lang ); + return '*' . wfMessage( 'metadata-langitem', + $wrappedValue, $langName, $lang )->text(); } /* else: */ $item = '<li class="mw-metadata-lang-code-' @@ -989,8 +997,8 @@ class FormatMetadata { $item .= ' mw-metadata-lang-default'; } $item .= '" lang="' . $lang . '">'; - $item .= wfMsg( 'metadata-langitem', - $wrappedValue, $langName, $lang ); + $item .= wfMessage( 'metadata-langitem', + $wrappedValue, $langName, $lang )->text(); $item .= "</li>\n"; return $item; } @@ -1004,24 +1012,22 @@ class FormatMetadata { * @param $val String: the value of the tag * @param $arg String: an argument to pass ($1) * @param $arg2 String: a 2nd argument to pass ($2) - * @return string A wfMsg of "exif-$tag-$val" in lower case + * @return string A wfMessage of "exif-$tag-$val" in lower case */ static function msg( $tag, $val, $arg = null, $arg2 = null ) { global $wgContLang; if ($val === '') $val = 'value'; - return wfMsg( $wgContLang->lc( "exif-$tag-$val" ), $arg, $arg2 ); + return wfMessage( $wgContLang->lc( "exif-$tag-$val" ), $arg, $arg2 )->text(); } /** * Format a number, convert numbers from fractions into floating point * numbers, joins arrays of numbers with commas. * - * @private - * * @param $num Mixed: the value to format - * @param $round digits to round to or false. + * @param $round float|int|bool digits to round to or false. * @return mixed A floating point number or whatever we were fed */ static function formatNum( $num, $round = false ) { @@ -1102,8 +1108,9 @@ class FormatMetadata { return $a; } - /** Fetch the human readable version of a news code. - * A news code is an 8 digit code. The first two + /** + * Fetch the human readable version of a news code. + * A news code is an 8 digit code. The first two * digits are a general classification, so we just * translate that. * @@ -1111,7 +1118,7 @@ class FormatMetadata { * a string, not an int. * * @param $val String: The 8 digit news code. - * @return The human readable form + * @return string The human readable form */ static private function convertNewsCode( $val ) { if ( !preg_match( '/^\d{8}$/D', $val ) ) { @@ -1183,7 +1190,7 @@ class FormatMetadata { * Format a coordinate value, convert numbers from floating point * into degree minute second representation. * - * @param $coord Array: degrees, minutes and seconds + * @param $coord int degrees, minutes and seconds * @param $type String: latitude or longitude (for if its a NWS or E) * @return mixed A floating point number or whatever we were fed */ @@ -1193,17 +1200,14 @@ class FormatMetadata { $nCoord = -$coord; if ( $type === 'latitude' ) { $ref = 'S'; - } - elseif ( $type === 'longitude' ) { + } elseif ( $type === 'longitude' ) { $ref = 'W'; } - } - else { + } else { $nCoord = $coord; if ( $type === 'latitude' ) { $ref = 'N'; - } - elseif ( $type === 'longitude' ) { + } elseif ( $type === 'longitude' ) { $ref = 'E'; } } @@ -1216,7 +1220,7 @@ class FormatMetadata { $min = self::formatNum( $min ); $sec = self::formatNum( $sec ); - return wfMsg( 'exif-coordinate-format', $deg, $min, $sec, $ref, $coord ); + return wfMessage( 'exif-coordinate-format', $deg, $min, $sec, $ref, $coord )->text(); } /** @@ -1274,7 +1278,7 @@ class FormatMetadata { // Todo: This can potentially be multi-line. // Need to check how that works in XMP. $street = '<span class="extended-address">' - . htmlspecialchars( + . htmlspecialchars( $vals['CiAdrExtadr'] ) . '</span>'; } @@ -1321,7 +1325,7 @@ class FormatMetadata { } if ( isset( $vals['CiAdrPcode'] ) ) { $postal = '<span class="postal-code">' - . htmlspecialchars( + . htmlspecialchars( $vals['CiAdrPcode'] ) . '</span>'; } @@ -1337,9 +1341,9 @@ class FormatMetadata { . htmlspecialchars( $vals['CiUrlWork'] ) . '</span>'; } - return wfMsg( 'exif-contact-value', $email, $url, + return wfMessage( 'exif-contact-value', $email, $url, $street, $city, $region, $postal, $country, - $tel ); + $tel )->text(); } } } @@ -1352,12 +1356,19 @@ class FormatMetadata { **/ class FormatExif { var $meta; - function FormatExif ( $meta ) { + + /** + * @param $meta array + */ + function FormatExif( $meta ) { wfDeprecated(__METHOD__); $this->meta = $meta; } - function getFormattedData ( ) { + /** + * @return array + */ + function getFormattedData() { return FormatMetadata::getFormattedData( $this->meta ); } } diff --git a/includes/media/GIF.php b/includes/media/GIF.php index 32618e94..84b9b8ca 100644 --- a/includes/media/GIF.php +++ b/includes/media/GIF.php @@ -2,6 +2,21 @@ /** * Handler for GIF 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 */ @@ -78,6 +93,17 @@ class GIFHandler extends BitmapHandler { return false; } + /** + * We cannot animate thumbnails that are bigger than a particular size + * @param File $file + * @return bool + */ + function canAnimateThumbnail( $file ) { + global $wgMaxAnimatedGifArea; + $answer = $this->getImageArea( $file ) <= $wgMaxAnimatedGifArea; + return $answer; + } + function getMetadataType( $image ) { return 'parsed-gif'; } @@ -127,11 +153,11 @@ class GIFHandler extends BitmapHandler { $info[] = $original; if ( $metadata['looped'] ) { - $info[] = wfMsgExt( 'file-info-gif-looped', 'parseinline' ); + $info[] = wfMessage( 'file-info-gif-looped' )->parse(); } if ( $metadata['frameCount'] > 1 ) { - $info[] = wfMsgExt( 'file-info-gif-frames', 'parseinline', $metadata['frameCount'] ); + $info[] = wfMessage( 'file-info-gif-frames' )->numParams( $metadata['frameCount'] )->parse(); } if ( $metadata['duration'] ) { diff --git a/includes/media/GIFMetadataExtractor.php b/includes/media/GIFMetadataExtractor.php index 5dbeb8f8..5fc5c1a7 100644 --- a/includes/media/GIFMetadataExtractor.php +++ b/includes/media/GIFMetadataExtractor.php @@ -7,6 +7,21 @@ * Deliberately not using MWExceptions to avoid external dependencies, encouraging * redistribution. * + * 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 */ @@ -286,7 +301,7 @@ class GIFMetadataExtractor { * sub-blocks in the returned value. Normally this is false, * except XMP is weird and does a hack where you need to keep * these length bytes. - * @return The data. + * @return string The data. */ static function readBlock( $fh, $includeLengths = false ) { $data = ''; diff --git a/includes/media/IPTC.php b/includes/media/IPTC.php index 1d19791c..8fd3552f 100644 --- a/includes/media/IPTC.php +++ b/includes/media/IPTC.php @@ -1,8 +1,31 @@ <?php /** -*Class for some IPTC functions. + * Class for some IPTC functions. + * + * 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 some IPTC functions. + * + * @ingroup Media + */ class IPTC { /** @@ -395,10 +418,10 @@ class IPTC { /** * Helper function to convert charset for iptc values. - * @param $data Mixed String or Array: The iptc string + * @param $data string|array The iptc string * @param $charset String: The charset * - * @return string + * @return string|array */ private static function convIPTC ( $data, $charset ) { if ( is_array( $data ) ) { diff --git a/includes/media/ImageHandler.php b/includes/media/ImageHandler.php new file mode 100644 index 00000000..61759074 --- /dev/null +++ b/includes/media/ImageHandler.php @@ -0,0 +1,249 @@ +<?php +/** + * Media-handling base classes and generic functionality. + * + * 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 + */ + +/** + * Media handler abstract base class for images + * + * @ingroup Media + */ +abstract class ImageHandler extends MediaHandler { + + /** + * @param $file File + * @return bool + */ + function canRender( $file ) { + return ( $file->getWidth() && $file->getHeight() ); + } + + function getParamMap() { + return array( 'img_width' => 'width' ); + } + + function validateParam( $name, $value ) { + if ( in_array( $name, array( 'width', 'height' ) ) ) { + if ( $value <= 0 ) { + return false; + } else { + return true; + } + } else { + return false; + } + } + + function makeParamString( $params ) { + if ( isset( $params['physicalWidth'] ) ) { + $width = $params['physicalWidth']; + } elseif ( isset( $params['width'] ) ) { + $width = $params['width']; + } else { + throw new MWException( 'No width specified to '.__METHOD__ ); + } + # Removed for ProofreadPage + #$width = intval( $width ); + return "{$width}px"; + } + + function parseParamString( $str ) { + $m = false; + if ( preg_match( '/^(\d+)px$/', $str, $m ) ) { + return array( 'width' => $m[1] ); + } else { + return false; + } + } + + function getScriptParams( $params ) { + return array( 'width' => $params['width'] ); + } + + /** + * @param $image File + * @param $params + * @return bool + */ + function normaliseParams( $image, &$params ) { + $mimeType = $image->getMimeType(); + + if ( !isset( $params['width'] ) ) { + return false; + } + + if ( !isset( $params['page'] ) ) { + $params['page'] = 1; + } else { + if ( $params['page'] > $image->pageCount() ) { + $params['page'] = $image->pageCount(); + } + + if ( $params['page'] < 1 ) { + $params['page'] = 1; + } + } + + $srcWidth = $image->getWidth( $params['page'] ); + $srcHeight = $image->getHeight( $params['page'] ); + + if ( isset( $params['height'] ) && $params['height'] != -1 ) { + # Height & width were both set + if ( $params['width'] * $srcHeight > $params['height'] * $srcWidth ) { + # Height is the relative smaller dimension, so scale width accordingly + $params['width'] = self::fitBoxWidth( $srcWidth, $srcHeight, $params['height'] ); + + if ( $params['width'] == 0 ) { + # Very small image, so we need to rely on client side scaling :( + $params['width'] = 1; + } + + $params['physicalWidth'] = $params['width']; + } else { + # Height was crap, unset it so that it will be calculated later + unset( $params['height'] ); + } + } + + if ( !isset( $params['physicalWidth'] ) ) { + # Passed all validations, so set the physicalWidth + $params['physicalWidth'] = $params['width']; + } + + # Because thumbs are only referred to by width, the height always needs + # to be scaled by the width to keep the thumbnail sizes consistent, + # even if it was set inside the if block above + $params['physicalHeight'] = File::scaleHeight( $srcWidth, $srcHeight, + $params['physicalWidth'] ); + + # Set the height if it was not validated in the if block higher up + if ( !isset( $params['height'] ) || $params['height'] == -1 ) { + $params['height'] = $params['physicalHeight']; + } + + + if ( !$this->validateThumbParams( $params['physicalWidth'], + $params['physicalHeight'], $srcWidth, $srcHeight, $mimeType ) ) { + return false; + } + return true; + } + + /** + * Validate thumbnail parameters and fill in the correct height + * + * @param $width Integer: specified width (input/output) + * @param $height Integer: height (output only) + * @param $srcWidth Integer: width of the source image + * @param $srcHeight Integer: height of the source image + * @param $mimeType + * @return bool False to indicate that an error should be returned to the user. + */ + function validateThumbParams( &$width, &$height, $srcWidth, $srcHeight, $mimeType ) { + $width = intval( $width ); + + # Sanity check $width + if( $width <= 0) { + wfDebug( __METHOD__.": Invalid destination width: $width\n" ); + return false; + } + if ( $srcWidth <= 0 ) { + wfDebug( __METHOD__.": Invalid source width: $srcWidth\n" ); + return false; + } + + $height = File::scaleHeight( $srcWidth, $srcHeight, $width ); + if ( $height == 0 ) { + # Force height to be at least 1 pixel + $height = 1; + } + return true; + } + + /** + * @param $image File + * @param $script + * @param $params + * @return bool|ThumbnailImage + */ + function getScriptedTransform( $image, $script, $params ) { + if ( !$this->normaliseParams( $image, $params ) ) { + return false; + } + $url = $script . '&' . wfArrayToCGI( $this->getScriptParams( $params ) ); + + if( $image->mustRender() || $params['width'] < $image->getWidth() ) { + return new ThumbnailImage( $image, $url, false, $params ); + } + } + + function getImageSize( $image, $path ) { + wfSuppressWarnings(); + $gis = getimagesize( $path ); + wfRestoreWarnings(); + return $gis; + } + + /** + * @param $file File + * @return string + */ + function getShortDesc( $file ) { + global $wgLang; + $nbytes = htmlspecialchars( $wgLang->formatSize( $file->getSize() ) ); + $widthheight = wfMessage( 'widthheight' )->numParams( $file->getWidth(), $file->getHeight() )->escaped(); + + return "$widthheight ($nbytes)"; + } + + /** + * @param $file File + * @return string + */ + function getLongDesc( $file ) { + global $wgLang; + $pages = $file->pageCount(); + $size = htmlspecialchars( $wgLang->formatSize( $file->getSize() ) ); + if ( $pages === false || $pages <= 1 ) { + $msg = wfMessage( 'file-info-size' )->numParams( $file->getWidth(), + $file->getHeight() )->params( $size, + $file->getMimeType() )->parse(); + } else { + $msg = wfMessage( 'file-info-size-pages' )->numParams( $file->getWidth(), + $file->getHeight() )->params( $size, + $file->getMimeType() )->numParams( $pages )->parse(); + } + return $msg; + } + + /** + * @param $file File + * @return string + */ + function getDimensionsString( $file ) { + $pages = $file->pageCount(); + if ( $pages > 1 ) { + return wfMessage( 'widthheightpage' )->numParams( $file->getWidth(), $file->getHeight(), $pages )->text(); + } else { + return wfMessage( 'widthheight' )->numParams( $file->getWidth(), $file->getHeight() )->text(); + } + } +} diff --git a/includes/media/Jpeg.php b/includes/media/Jpeg.php index 7033409b..a15b6524 100644 --- a/includes/media/Jpeg.php +++ b/includes/media/Jpeg.php @@ -1,5 +1,22 @@ <?php /** + * Handler for JPEG 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 */ diff --git a/includes/media/JpegMetadataExtractor.php b/includes/media/JpegMetadataExtractor.php index 224b4a2b..8d7e43b9 100644 --- a/includes/media/JpegMetadataExtractor.php +++ b/includes/media/JpegMetadataExtractor.php @@ -1,10 +1,34 @@ <?php /** -* Class for reading jpegs and extracting metadata. -* see also BitmapMetadataHandler. -* -* Based somewhat on GIFMetadataExtrator. -*/ + * Extraction of JPEG image metadata. + * + * 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 jpegs and extracting metadata. + * see also BitmapMetadataHandler. + * + * Based somewhat on GIFMetadataExtrator. + * + * @ingroup Media + */ class JpegMetadataExtractor { const MAX_JPEG_SEGMENTS = 200; @@ -143,13 +167,17 @@ class JpegMetadataExtractor { /** * Helper function for jpegSegmentSplitter * @param &$fh FileHandle for jpeg file - * @return data content of segment. + * @return string data content of segment. */ private static function jpegExtractMarker( &$fh ) { $size = wfUnpack( "nint", fread( $fh, 2 ), 2 ); - if ( $size['int'] <= 2 ) throw new MWException( "invalid marker size in jpeg" ); + if ( $size['int'] <= 2 ) { + throw new MWException( "invalid marker size in jpeg" ); + } $segment = fread( $fh, $size['int'] - 2 ); - if ( strlen( $segment ) !== $size['int'] - 2 ) throw new MWException( "Segment shorter than expected" ); + if ( strlen( $segment ) !== $size['int'] - 2 ) { + throw new MWException( "Segment shorter than expected" ); + } return $segment; } diff --git a/includes/media/Generic.php b/includes/media/MediaHandler.php index 271d3a8d..965099fd 100644 --- a/includes/media/Generic.php +++ b/includes/media/MediaHandler.php @@ -1,6 +1,21 @@ <?php /** - * Media-handling base classes and generic functionality + * Media-handling base classes and generic functionality. + * + * 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 @@ -160,6 +175,7 @@ abstract class MediaHandler { * MediaHandler::METADATA_GOOD for if the metadata is a-ok, * MediaHanlder::METADATA_COMPATIBLE if metadata is old but backwards * compatible (which may or may not trigger a metadata reload). + * @return bool */ function isMetadataValid( $image, $metadata ) { return self::METADATA_GOOD; @@ -173,6 +189,7 @@ abstract class MediaHandler { * Used when the repository has a thumbnailScriptUrl option configured. * * Return false to fall back to the regular getTransform(). + * @return bool */ function getScriptedTransform( $image, $script, $params ) { return false; @@ -186,6 +203,7 @@ abstract class MediaHandler { * @param $dstPath String: filesystem destination path * @param $dstUrl String: Destination URL to use in output HTML * @param $params Array: Arbitrary set of parameters validated by $this->validateParam() + * @return MediaTransformOutput */ final function getTransform( $image, $dstPath, $dstUrl, $params ) { return $this->doTransform( $image, $dstPath, $dstUrl, $params, self::TRANSFORM_LATER ); @@ -227,27 +245,46 @@ abstract class MediaHandler { /** * True if the handled types can be transformed + * @return bool */ function canRender( $file ) { return true; } /** * True if handled types cannot be displayed directly in a browser * but can be rendered + * @return bool */ function mustRender( $file ) { return false; } /** * True if the type has multi-page capabilities + * @return bool */ function isMultiPage( $file ) { return false; } /** * Page count for a multi-page document, false if unsupported or unknown + * @return bool */ function pageCount( $file ) { return false; } /** * The material is vectorized and thus scaling is lossless + * @return bool */ function isVectorized( $file ) { return false; } /** + * The material is an image, and is animated. + * In particular, video material need not return true. + * @note Before 1.20, this was a method of ImageHandler only + * @return bool + */ + function isAnimatedImage( $file ) { return false; } + /** + * If the material is animated, we can animate the thumbnail + * @since 1.20 + * @return bool If material is not animated, handler may return any value. + */ + function canAnimateThumbnail( $file ) { return true; } + /** * False if the handler is disabled for all files + * @return bool */ function isEnabled() { return true; } @@ -258,6 +295,8 @@ abstract class MediaHandler { * Returns false if unknown or if the document is not multi-page. * * @param $image File + * @param $page Unused, left for backcompatibility? + * @return array */ function getPageDimensions( $image, $page ) { $gis = $this->getImageSize( $image, $image->getLocalRefPath() ); @@ -270,6 +309,7 @@ abstract class MediaHandler { /** * Generic getter for text layer. * Currently overloaded by PDF and DjVu handlers + * @return bool */ function getPageText( $image, $page ) { return false; @@ -300,6 +340,7 @@ abstract class MediaHandler { * all the formatting according to some standard. That makes it possible * to do things like visual indication of grouped and chained streams * in ogg container files. + * @return bool */ function formatMetadata( $image ) { return false; @@ -344,7 +385,7 @@ abstract class MediaHandler { */ function visibleMetadataFields() { $fields = array(); - $lines = explode( "\n", wfMsgForContent( 'metadata-fields' ) ); + $lines = explode( "\n", wfMessage( 'metadata-fields' )->inContentLanguage()->text() ); foreach( $lines as $line ) { $matches = array(); if( preg_match( '/^\\*\s*(.*?)\s*$/', $line, $matches ) ) { @@ -471,7 +512,7 @@ abstract class MediaHandler { * match the handler class, a Status object should be returned containing * relevant errors. * - * @param $fileName The local path to the file. + * @param $fileName string The local path to the file. * @return Status object */ function verifyUpload( $fileName ) { @@ -482,9 +523,9 @@ abstract class MediaHandler { * Check for zero-sized thumbnails. These can be generated when * no disk space is available or some other error occurs * - * @param $dstPath The location of the suspect file - * @param $retval Return value of some shell process, file will be deleted if this is non-zero - * @return true if removed, false otherwise + * @param $dstPath string The location of the suspect file + * @param $retval int Return value of some shell process, file will be deleted if this is non-zero + * @return bool True if removed, false otherwise */ function removeBadFile( $dstPath, $retval = 0 ) { if( file_exists( $dstPath ) ) { @@ -509,7 +550,7 @@ abstract class MediaHandler { /** * Remove files from the purge list - * + * * @param array $files * @param array $options */ @@ -517,235 +558,3 @@ abstract class MediaHandler { // Do nothing } } - -/** - * Media handler abstract base class for images - * - * @ingroup Media - */ -abstract class ImageHandler extends MediaHandler { - - /** - * @param $file File - * @return bool - */ - function canRender( $file ) { - return ( $file->getWidth() && $file->getHeight() ); - } - - function getParamMap() { - return array( 'img_width' => 'width' ); - } - - function validateParam( $name, $value ) { - if ( in_array( $name, array( 'width', 'height' ) ) ) { - if ( $value <= 0 ) { - return false; - } else { - return true; - } - } else { - return false; - } - } - - function makeParamString( $params ) { - if ( isset( $params['physicalWidth'] ) ) { - $width = $params['physicalWidth']; - } elseif ( isset( $params['width'] ) ) { - $width = $params['width']; - } else { - throw new MWException( 'No width specified to '.__METHOD__ ); - } - # Removed for ProofreadPage - #$width = intval( $width ); - return "{$width}px"; - } - - function parseParamString( $str ) { - $m = false; - if ( preg_match( '/^(\d+)px$/', $str, $m ) ) { - return array( 'width' => $m[1] ); - } else { - return false; - } - } - - function getScriptParams( $params ) { - return array( 'width' => $params['width'] ); - } - - /** - * @param $image File - * @param $params - * @return bool - */ - function normaliseParams( $image, &$params ) { - $mimeType = $image->getMimeType(); - - if ( !isset( $params['width'] ) ) { - return false; - } - - if ( !isset( $params['page'] ) ) { - $params['page'] = 1; - } else { - if ( $params['page'] > $image->pageCount() ) { - $params['page'] = $image->pageCount(); - } - - if ( $params['page'] < 1 ) { - $params['page'] = 1; - } - } - - $srcWidth = $image->getWidth( $params['page'] ); - $srcHeight = $image->getHeight( $params['page'] ); - - if ( isset( $params['height'] ) && $params['height'] != -1 ) { - # Height & width were both set - if ( $params['width'] * $srcHeight > $params['height'] * $srcWidth ) { - # Height is the relative smaller dimension, so scale width accordingly - $params['width'] = self::fitBoxWidth( $srcWidth, $srcHeight, $params['height'] ); - - if ( $params['width'] == 0 ) { - # Very small image, so we need to rely on client side scaling :( - $params['width'] = 1; - } - - $params['physicalWidth'] = $params['width']; - } else { - # Height was crap, unset it so that it will be calculated later - unset( $params['height'] ); - } - } - - if ( !isset( $params['physicalWidth'] ) ) { - # Passed all validations, so set the physicalWidth - $params['physicalWidth'] = $params['width']; - } - - # Because thumbs are only referred to by width, the height always needs - # to be scaled by the width to keep the thumbnail sizes consistent, - # even if it was set inside the if block above - $params['physicalHeight'] = File::scaleHeight( $srcWidth, $srcHeight, - $params['physicalWidth'] ); - - # Set the height if it was not validated in the if block higher up - if ( !isset( $params['height'] ) || $params['height'] == -1 ) { - $params['height'] = $params['physicalHeight']; - } - - - if ( !$this->validateThumbParams( $params['physicalWidth'], - $params['physicalHeight'], $srcWidth, $srcHeight, $mimeType ) ) { - return false; - } - return true; - } - - /** - * Validate thumbnail parameters and fill in the correct height - * - * @param $width Integer: specified width (input/output) - * @param $height Integer: height (output only) - * @param $srcWidth Integer: width of the source image - * @param $srcHeight Integer: height of the source image - * @param $mimeType Unused - * @return false to indicate that an error should be returned to the user. - */ - function validateThumbParams( &$width, &$height, $srcWidth, $srcHeight, $mimeType ) { - $width = intval( $width ); - - # Sanity check $width - if( $width <= 0) { - wfDebug( __METHOD__.": Invalid destination width: $width\n" ); - return false; - } - if ( $srcWidth <= 0 ) { - wfDebug( __METHOD__.": Invalid source width: $srcWidth\n" ); - return false; - } - - $height = File::scaleHeight( $srcWidth, $srcHeight, $width ); - if ( $height == 0 ) { - # Force height to be at least 1 pixel - $height = 1; - } - return true; - } - - /** - * @param $image File - * @param $script - * @param $params - * @return bool|ThumbnailImage - */ - function getScriptedTransform( $image, $script, $params ) { - if ( !$this->normaliseParams( $image, $params ) ) { - return false; - } - $url = $script . '&' . wfArrayToCGI( $this->getScriptParams( $params ) ); - $page = isset( $params['page'] ) ? $params['page'] : false; - - if( $image->mustRender() || $params['width'] < $image->getWidth() ) { - return new ThumbnailImage( $image, $url, $params['width'], $params['height'], $page ); - } - } - - function getImageSize( $image, $path ) { - wfSuppressWarnings(); - $gis = getimagesize( $path ); - wfRestoreWarnings(); - return $gis; - } - - function isAnimatedImage( $image ) { - return false; - } - - /** - * @param $file File - * @return string - */ - function getShortDesc( $file ) { - global $wgLang; - $nbytes = htmlspecialchars( $wgLang->formatSize( $file->getSize() ) ); - $widthheight = wfMessage( 'widthheight' )->numParams( $file->getWidth(), $file->getHeight() )->escaped(); - - return "$widthheight ($nbytes)"; - } - - /** - * @param $file File - * @return string - */ - function getLongDesc( $file ) { - global $wgLang; - $pages = $file->pageCount(); - $size = htmlspecialchars( $wgLang->formatSize( $file->getSize() ) ); - if ( $pages === false || $pages <= 1 ) { - $msg = wfMessage( 'file-info-size' )->numParams( $file->getWidth(), - $file->getHeight() )->params( $size, - $file->getMimeType() )->parse(); - } else { - $msg = wfMessage( 'file-info-size-pages' )->numParams( $file->getWidth(), - $file->getHeight() )->params( $size, - $file->getMimeType() )->numParams( $pages )->parse(); - } - return $msg; - } - - /** - * @param $file File - * @return string - */ - function getDimensionsString( $file ) { - $pages = $file->pageCount(); - if ( $pages > 1 ) { - return wfMessage( 'widthheightpage' )->numParams( $file->getWidth(), $file->getHeight(), $pages )->text(); - } else { - return wfMessage( 'widthheight' )->numParams( $file->getWidth(), $file->getHeight() )->text(); - } - } -} diff --git a/includes/media/MediaTransformOutput.php b/includes/media/MediaTransformOutput.php index fcfb2f45..773824cb 100644 --- a/includes/media/MediaTransformOutput.php +++ b/includes/media/MediaTransformOutput.php @@ -2,6 +2,21 @@ /** * Base class for the output of file transformation methods. * + * 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 */ @@ -21,28 +36,37 @@ abstract class MediaTransformOutput { protected $storagePath = false; /** - * Get the width of the output box + * @return integer Width of the output box */ public function getWidth() { return $this->width; } /** - * Get the height of the output box + * @return integer Height of the output box */ public function getHeight() { return $this->height; } /** - * @return string The thumbnail URL + * Get the final extension of the thumbnail. + * Returns false for scripted transformations. + * @return string|false + */ + public function getExtension() { + return $this->path ? FileBackend::extensionFromPath( $this->path ) : false; + } + + /** + * @return string|false The thumbnail URL */ public function getUrl() { return $this->url; } /** - * @return string|false The permanent thumbnail storage path + * @return string|bool The permanent thumbnail storage path */ public function getStoragePath() { return $this->storagePath; @@ -69,7 +93,7 @@ abstract class MediaTransformOutput { * custom-url-link Custom URL to link to * custom-title-link Custom Title object to link to * valign vertical-align property, if the output is an inline element - * img-class Class applied to the <img> tag, if there is such a tag + * img-class Class applied to the "<img>" tag, if there is such a tag * * For images, desc-link and file-link are implemented as a click-through. For * sounds and videos, they may be displayed in other ways. @@ -80,6 +104,7 @@ abstract class MediaTransformOutput { /** * This will be overridden to return true in error classes + * @return bool */ public function isError() { return false; @@ -90,7 +115,7 @@ abstract class MediaTransformOutput { * This will return false if there was an error, the * thumbnail is to be handled client-side only, or if * transformation was deferred via TRANSFORM_LATER. - * + * * @return Bool */ public function hasFile() { @@ -113,7 +138,7 @@ abstract class MediaTransformOutput { * Get the path of a file system copy of the thumbnail. * Callers should never write to this path. * - * @return string|false Returns false if there isn't one + * @return string|bool Returns false if there isn't one */ public function getLocalCopyPath() { if ( $this->isError() ) { @@ -132,7 +157,14 @@ abstract class MediaTransformOutput { * @return Bool success */ public function streamFile( $headers = array() ) { - return $this->path && StreamFile::stream( $this->getLocalCopyPath(), $headers ); + if ( !$this->path ) { + return false; + } elseif ( FileBackend::isStoragePath( $this->path ) ) { + $be = $this->file->getRepo()->getBackend(); + return $be->streamFile( array( 'src' => $this->path, 'headers' => $headers ) )->isOK(); + } else { // FS-file + return StreamFile::stream( $this->getLocalCopyPath(), $headers ); + } } /** @@ -182,25 +214,46 @@ class ThumbnailImage extends MediaTransformOutput { * Get a thumbnail object from a file and parameters. * If $path is set to null, the output file is treated as a source copy. * If $path is set to false, no output file will be created. - * + * $parameters should include, as a minimum, (file) 'width' and 'height'. + * It may also include a 'page' parameter for multipage files. + * * @param $file File object * @param $url String: URL path to the thumb - * @param $width Integer: file's width - * @param $height Integer: file's height - * @param $path String|false|null: filesystem path to the thumb - * @param $page Integer: page number, for multipage files + * @param $path String|bool|null: filesystem path to the thumb + * @param $parameters Array: Associative array of parameters * @private */ - function __construct( $file, $url, $width, $height, $path = false, $page = false ) { + function __construct( $file, $url, $path = false, $parameters = array() ) { + # Previous parameters: + # $file, $url, $width, $height, $path = false, $page = false + + if( is_array( $parameters ) ){ + $defaults = array( + 'page' => false + ); + $actualParams = $parameters + $defaults; + } else { + # Using old format, should convert. Later a warning could be added here. + $numArgs = func_num_args(); + $actualParams = array( + 'width' => $path, + 'height' => $parameters, + 'page' => ( $numArgs > 5 ) ? func_get_arg( 5 ) : false + ); + $path = ( $numArgs > 4 ) ? func_get_arg( 4 ) : false; + } + $this->file = $file; $this->url = $url; + $this->path = $path; + # These should be integers when they get here. # If not, there's a bug somewhere. But let's at # least produce valid HTML code regardless. - $this->width = round( $width ); - $this->height = round( $height ); - $this->path = $path; - $this->page = $page; + $this->width = round( $actualParams['width'] ); + $this->height = round( $actualParams['height'] ); + + $this->page = $actualParams['page']; } /** @@ -221,6 +274,9 @@ class ThumbnailImage extends MediaTransformOutput { * custom-url-link Custom URL to link to * custom-title-link Custom Title object to link to * custom target-link Value of the target attribute, for custom-target-link + * parser-extlink-* Attributes added by parser for external links: + * parser-extlink-rel: add rel="nofollow" + * parser-extlink-target: link target, but overridden by custom-target-link * * For images, desc-link and file-link are implemented as a click-through. For * sounds and videos, they may be displayed in other ways. @@ -243,6 +299,11 @@ class ThumbnailImage extends MediaTransformOutput { } if ( !empty( $options['custom-target-link'] ) ) { $linkAttribs['target'] = $options['custom-target-link']; + } elseif ( !empty( $options['parser-extlink-target'] ) ) { + $linkAttribs['target'] = $options['parser-extlink-target']; + } + if ( !empty( $options['parser-extlink-rel'] ) ) { + $linkAttribs['rel'] = $options['parser-extlink-rel']; } } elseif ( !empty( $options['custom-title-link'] ) ) { $title = $options['custom-title-link']; @@ -326,6 +387,6 @@ class TransformParameterError extends MediaTransformError { parent::__construct( 'thumbnail_error', max( isset( $params['width'] ) ? $params['width'] : 0, 120 ), max( isset( $params['height'] ) ? $params['height'] : 0, 120 ), - wfMsg( 'thumbnail_invalid_params' ) ); + wfMessage( 'thumbnail_invalid_params' )->text() ); } } diff --git a/includes/media/PNG.php b/includes/media/PNG.php index 8fe9ecb4..1b329e57 100644 --- a/includes/media/PNG.php +++ b/includes/media/PNG.php @@ -2,6 +2,21 @@ /** * Handler for PNG 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 */ @@ -65,6 +80,14 @@ class PNGHandler extends BitmapHandler { } return false; } + /** + * We do not support making APNG thumbnails, so always false + * @param $image File + * @return bool false + */ + function canAnimateThumbnail( $image ) { + return false; + } function getMetadataType( $image ) { return 'parsed-png'; @@ -113,13 +136,13 @@ class PNGHandler extends BitmapHandler { $info[] = $original; if ( $metadata['loopCount'] == 0 ) { - $info[] = wfMsgExt( 'file-info-png-looped', 'parseinline' ); + $info[] = wfMessage( 'file-info-png-looped' )->parse(); } elseif ( $metadata['loopCount'] > 1 ) { - $info[] = wfMsgExt( 'file-info-png-repeat', 'parseinline', $metadata['loopCount'] ); + $info[] = wfMessage( 'file-info-png-repeat' )->numParams( $metadata['loopCount'] )->parse(); } if ( $metadata['frameCount'] > 0 ) { - $info[] = wfMsgExt( 'file-info-png-frames', 'parseinline', $metadata['frameCount'] ); + $info[] = wfMessage( 'file-info-png-frames' )->numParams( $metadata['frameCount'] )->parse(); } if ( $metadata['duration'] ) { diff --git a/includes/media/PNGMetadataExtractor.php b/includes/media/PNGMetadataExtractor.php index d3c44d4f..9dcde406 100644 --- a/includes/media/PNGMetadataExtractor.php +++ b/includes/media/PNGMetadataExtractor.php @@ -1,10 +1,26 @@ <?php /** * PNG frame counter and metadata extractor. + * * Slightly derived from GIFMetadataExtractor.php * Deliberately not using MWExceptions to avoid external dependencies, encouraging * redistribution. * + * 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 */ diff --git a/includes/media/SVG.php b/includes/media/SVG.php index aac838e1..55fa5547 100644 --- a/includes/media/SVG.php +++ b/includes/media/SVG.php @@ -2,6 +2,21 @@ /** * Handler for SVG 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 */ @@ -49,6 +64,13 @@ class SvgHandler extends ImageHandler { } /** + * We do not support making animated svg thumbnails + */ + function canAnimateThumb( $file ) { + return false; + } + + /** * @param $image File * @param $params * @return bool @@ -93,20 +115,20 @@ class SvgHandler extends ImageHandler { $clientHeight = $params['height']; $physicalWidth = $params['physicalWidth']; $physicalHeight = $params['physicalHeight']; - $srcPath = $image->getLocalRefPath(); if ( $flags & self::TRANSFORM_LATER ) { - return new ThumbnailImage( $image, $dstUrl, $clientWidth, $clientHeight, $dstPath ); + return new ThumbnailImage( $image, $dstUrl, $dstPath, $params ); } if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) { return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight, - wfMsg( 'thumbnail_dest_directory' ) ); + wfMessage( 'thumbnail_dest_directory' )->text() ); } + $srcPath = $image->getLocalRefPath(); $status = $this->rasterize( $srcPath, $dstPath, $physicalWidth, $physicalHeight ); if( $status === true ) { - return new ThumbnailImage( $image, $dstUrl, $clientWidth, $clientHeight, $dstPath ); + return new ThumbnailImage( $image, $dstUrl, $dstPath, $params ); } else { return $status; // MediaTransformError } @@ -119,7 +141,7 @@ class SvgHandler extends ImageHandler { * @param string $dstPath * @param string $width * @param string $height - * @return true|MediaTransformError + * @return bool|MediaTransformError */ public function rasterize( $srcPath, $dstPath, $width, $height ) { global $wgSVGConverters, $wgSVGConverter, $wgSVGConverterPath; @@ -199,15 +221,30 @@ class SvgHandler extends ImageHandler { } /** + * Subtitle for the image. Different from the base + * class so it can be denoted that SVG's have + * a "nominal" resolution, and not a fixed one, + * as well as so animation can be denoted. + * * @param $file File * @return string */ function getLongDesc( $file ) { global $wgLang; - return wfMsgExt( 'svg-long-desc', 'parseinline', - $wgLang->formatNum( $file->getWidth() ), - $wgLang->formatNum( $file->getHeight() ), - $wgLang->formatSize( $file->getSize() ) ); + $size = $wgLang->formatSize( $file->getSize() ); + + if ( $this->isAnimatedImage( $file ) ) { + $msg = wfMessage( 'svg-long-desc-animated' ); + } else { + $msg = wfMessage( 'svg-long-desc' ); + } + + $msg->numParams( + $file->getWidth(), + $file->getHeight() + ); + $msg->Params( $size ); + return $msg->parse(); } function getMetadata( $file, $filename ) { @@ -238,11 +275,19 @@ class SvgHandler extends ImageHandler { } function isMetadataValid( $image, $metadata ) { - return $this->unpackMetadata( $metadata ) !== false; + $meta = $this->unpackMetadata( $metadata ); + if ( $meta === false ) { + return self::METADATA_BAD; + } + if ( !isset( $meta['originalWidth'] ) ) { + // Old but compatible + return self::METADATA_COMPATIBLE; + } + return self::METADATA_GOOD; } function visibleMetadataFields() { - $fields = array( 'title', 'description', 'animated' ); + $fields = array( 'objectname', 'imagedescription' ); return $fields; } @@ -263,8 +308,6 @@ class SvgHandler extends ImageHandler { if ( !$metadata ) { return false; } - unset( $metadata['version'] ); - unset( $metadata['metadata'] ); /* non-formatted XML */ /* TODO: add a formatter $format = new FormatSVG( $metadata ); @@ -275,9 +318,10 @@ class SvgHandler extends ImageHandler { $visibleFields = $this->visibleMetadataFields(); // Rename fields to be compatible with exif, so that - // the labels for these fields work. - $conversion = array( 'width' => 'imagewidth', - 'height' => 'imagelength', + // the labels for these fields work and reuse existing messages. + $conversion = array( + 'originalwidth' => 'imagewidth', + 'originalheight' => 'imagelength', 'description' => 'imagedescription', 'title' => 'objectname', ); @@ -285,6 +329,9 @@ class SvgHandler extends ImageHandler { $tag = strtolower( $name ); if ( isset( $conversion[$tag] ) ) { $tag = $conversion[$tag]; + } else { + // Do not output other metadata not in list + continue; } self::addMeta( $result, in_array( $tag, $visibleFields ) ? 'visible' : 'collapsed', diff --git a/includes/media/SVGMetadataExtractor.php b/includes/media/SVGMetadataExtractor.php index db9f05fd..851fe428 100644 --- a/includes/media/SVGMetadataExtractor.php +++ b/includes/media/SVGMetadataExtractor.php @@ -1,6 +1,6 @@ <?php /** - * SVGMetadataExtractor.php + * Extraction of SVG image metadata. * * 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 @@ -19,12 +19,15 @@ * * @file * @ingroup Media - * @author Derk-Jan Hartman <hartman _at_ videolan d0t org> + * @author "Derk-Jan Hartman <hartman _at_ videolan d0t org>" * @author Brion Vibber * @copyright Copyright © 2010-2010 Brion Vibber, Derk-Jan Hartman * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License */ +/** + * @ingroup Media + */ class SVGMetadataExtractor { static function getMetadata( $filename ) { $svg = new SVGReader( $filename ); @@ -32,6 +35,9 @@ class SVGMetadataExtractor { } } +/** + * @ingroup Media + */ class SVGReader { const DEFAULT_WIDTH = 512; const DEFAULT_HEIGHT = 512; @@ -77,6 +83,12 @@ class SVGReader { $this->metadata['width'] = self::DEFAULT_WIDTH; $this->metadata['height'] = self::DEFAULT_HEIGHT; + // The size in the units specified by the SVG file + // (for the metadata box) + // Per the SVG spec, if unspecified, default to '100%' + $this->metadata['originalWidth'] = '100%'; + $this->metadata['originalHeight'] = '100%'; + // Because we cut off the end of the svg making an invalid one. Complicated // try catch thing to make sure warnings get restored. Seems like there should // be a better way. @@ -84,6 +96,8 @@ class SVGReader { try { $this->read(); } catch( Exception $e ) { + // Note, if this happens, the width/height will be taken to be 0x0. + // Should we consider it the default 512x512 instead? wfRestoreWarnings(); throw $e; } @@ -99,6 +113,7 @@ class SVGReader { /** * Read the SVG + * @return bool */ public function read() { $keepReading = $this->reader->read(); @@ -132,6 +147,11 @@ class SVGReader { $this->readField( $tag, 'description' ); } elseif ( $isSVG && $tag == 'metadata' && $type == XmlReader::ELEMENT ) { $this->readXml( $tag, 'metadata' ); + } elseif ( $isSVG && $tag == 'script' ) { + // We normally do not allow scripted svgs. + // However its possible to configure MW to let them + // in, and such files should be considered animated. + $this->metadata['animated'] = true; } elseif ( $tag !== '#text' ) { $this->debug( "Unhandled top-level XML tag $tag" ); @@ -212,6 +232,11 @@ class SVGReader { break; } elseif ( $this->reader->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::ELEMENT ) { switch( $this->reader->localName ) { + case 'script': + // Normally we disallow files with + // <script>, but its possible + // to configure MW to disable + // such checks. case 'animate': case 'set': case 'animateMotion': @@ -248,7 +273,7 @@ class SVGReader { /** * Parse the attributes of an SVG element * - * The parser has to be in the start element of <svg> + * The parser has to be in the start element of "<svg>" */ private function handleSVGAttribs( ) { $defaultWidth = self::DEFAULT_WIDTH; @@ -271,9 +296,11 @@ class SVGReader { } if( $this->reader->getAttribute('width') ) { $width = $this->scaleSVGUnit( $this->reader->getAttribute('width'), $defaultWidth ); + $this->metadata['originalWidth'] = $this->reader->getAttribute( 'width' ); } if( $this->reader->getAttribute('height') ) { $height = $this->scaleSVGUnit( $this->reader->getAttribute('height'), $defaultHeight ); + $this->metadata['originalHeight'] = $this->reader->getAttribute( 'height' ); } if( !isset( $width ) && !isset( $height ) ) { diff --git a/includes/media/Tiff.php b/includes/media/Tiff.php index 0f317e1a..d95c9074 100644 --- a/includes/media/Tiff.php +++ b/includes/media/Tiff.php @@ -2,6 +2,21 @@ /** * Handler for Tiff 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 */ diff --git a/includes/media/XCF.php b/includes/media/XCF.php index 806db73c..555fa1fb 100644 --- a/includes/media/XCF.php +++ b/includes/media/XCF.php @@ -7,6 +7,21 @@ * Specification in Gnome repository: * http://svn.gnome.org/viewvc/gimp/trunk/devel-docs/xcf.txt?view=markup * + * 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 */ @@ -58,7 +73,7 @@ class XCFHandler extends BitmapHandler { * @author Hashar * * @param $filename String Full path to a XCF file - * @return false|metadata array just like PHP getimagesize() + * @return bool|array metadata array just like PHP getimagesize() */ static function getXCFMetaData( $filename ) { # Decode master structure diff --git a/includes/media/XMP.php b/includes/media/XMP.php index 0dbf5632..36660b3d 100644 --- a/includes/media/XMP.php +++ b/includes/media/XMP.php @@ -1,5 +1,27 @@ <?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. * @@ -191,10 +213,16 @@ class XMPReader { unset( $data['xmp-special'] ); // Convert GPSAltitude to negative if below sea level. - if ( isset( $data['xmp-exif']['GPSAltitudeRef'] ) ) { - if ( $data['xmp-exif']['GPSAltitudeRef'] == '1' - && isset( $data['xmp-exif']['GPSAltitude'] ) - ) { + if ( isset( $data['xmp-exif']['GPSAltitudeRef'] ) + && isset( $data['xmp-exif']['GPSAltitude'] ) + ) { + + // Must convert to a real before multiplying by -1 + // XMPValidate guarantees there will always be a '/' in this value. + list( $nom, $denom ) = explode( '/', $data['xmp-exif']['GPSAltitude'] ); + $data['xmp-exif']['GPSAltitude'] = $nom / $denom; + + if ( $data['xmp-exif']['GPSAltitudeRef'] == '1' ) { $data['xmp-exif']['GPSAltitude'] *= -1; } unset( $data['xmp-exif']['GPSAltitudeRef'] ); @@ -439,13 +467,15 @@ class XMPReader { * generally means we've finished processing a nested structure. * resets some internal variables to indicate that. * - * Note this means we hit the </closing element> not the </rdf:Seq>. + * Note this means we hit the closing element not the "</rdf:Seq>". * - * For example, when processing: + * @par For example, when processing: + * @code{,xml} * <exif:ISOSpeedRatings> <rdf:Seq> <rdf:li>64</rdf:li> * </rdf:Seq> </exif:ISOSpeedRatings> + * @endcode * - * This method is called when we hit the </exif:ISOSpeedRatings> tag. + * This method is called when we hit the "</exif:ISOSpeedRatings>" tag. * * @param $elm String namespace . space . tag name. */ @@ -501,15 +531,17 @@ class XMPReader { * Hit a closing element in MODE_LI (either rdf:Seq, or rdf:Bag ) * Add information about what type of element this is. * - * Note we still have to hit the outer </property> + * Note we still have to hit the outer "</property>" * - * For example, when processing: + * @par For example, when processing: + * @code{,xml} * <exif:ISOSpeedRatings> <rdf:Seq> <rdf:li>64</rdf:li> * </rdf:Seq> </exif:ISOSpeedRatings> + * @endcode * - * This method is called when we hit the </rdf:Seq>. + * This method is called when we hit the "</rdf:Seq>". * (For comparison, we call endElementModeSimple when we - * hit the </rdf:li>) + * hit the "</rdf:li>") * * @param $elm String namespace . ' ' . element name */ @@ -988,7 +1020,7 @@ class XMPReader { * Also does some initial set up for the wrapper element * * @param $parser XMLParser - * @param $elm String namespace <space> element + * @param $elm String namespace "<space>" element * @param $attribs Array attribute name => value */ function startElement( $parser, $elm, $attribs ) { @@ -1071,11 +1103,13 @@ class XMPReader { * Process attributes. * Simple values can be stored as either a tag or attribute * - * Often the initial <rdf:Description> tag just has all the simple + * Often the initial "<rdf:Description>" tag just has all the simple * properties as attributes. * - * Example: + * @par Example: + * @code * <rdf:Description rdf:about="" xmlns:exif="http://ns.adobe.com/exif/1.0/" exif:DigitalZoomRatio="0/10"> + * @endcode * * @param $attribs Array attribute=>value array. */ diff --git a/includes/media/XMPInfo.php b/includes/media/XMPInfo.php index 156d9b50..83b8a102 100644 --- a/includes/media/XMPInfo.php +++ b/includes/media/XMPInfo.php @@ -1,5 +1,27 @@ <?php /** + * Definitions for XMPReader class. + * + * 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 + */ + +/** * This class is just a container for a big array * used by XMPReader to determine which XMP items to * extract. diff --git a/includes/media/XMPValidate.php b/includes/media/XMPValidate.php index 600d99de..5ce3c00b 100644 --- a/includes/media/XMPValidate.php +++ b/includes/media/XMPValidate.php @@ -1,5 +1,27 @@ <?php /** + * Methods for validating XMP properties. + * + * 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 + */ + +/** * This contains some static methods for * validating XMP properties. See XMPInfo and XMPReader classes. * |