-<?php\r
-\r
-/**\r
- * Returns the image directory of an image\r
- * The result is an absolute path.\r
- *\r
- * This function is called from thumb.php before Setup.php is included\r
- *\r
- * @param $fname String: file name of the image file.\r
- * @public\r
- */\r
-function wfImageDir( $fname ) {\r
- global $wgUploadDirectory, $wgHashedUploadDirectory;\r
-\r
- if (!$wgHashedUploadDirectory) { return $wgUploadDirectory; }\r
-\r
- $hash = md5( $fname );\r
- $dest = $wgUploadDirectory . '/' . $hash{0} . '/' . substr( $hash, 0, 2 );\r
-\r
- return $dest;\r
-}\r
-\r
-/**\r
- * Returns the image directory of an image's thubnail\r
- * The result is an absolute path.\r
- *\r
- * This function is called from thumb.php before Setup.php is included\r
- *\r
- * @param $fname String: file name of the original image file\r
- * @param $shared Boolean: (optional) use the shared upload directory (default: 'false').\r
- * @public\r
- */\r
-function wfImageThumbDir( $fname, $shared = false ) {\r
- $base = wfImageArchiveDir( $fname, 'thumb', $shared );\r
- if ( Image::isHashed( $shared ) ) {\r
- $dir = "$base/$fname";\r
- } else {\r
- $dir = $base;\r
- }\r
-\r
- return $dir;\r
-}\r
-\r
-/**\r
- * Old thumbnail directory, kept for conversion\r
- */\r
-function wfDeprecatedThumbDir( $thumbName , $subdir='thumb', $shared=false) {\r
- return wfImageArchiveDir( $thumbName, $subdir, $shared );\r
-}\r
-\r
-/**\r
- * Returns the image directory of an image's old version\r
- * The result is an absolute path.\r
- *\r
- * This function is called from thumb.php before Setup.php is included\r
- *\r
- * @param $fname String: file name of the thumbnail file, including file size prefix.\r
- * @param $subdir String: subdirectory of the image upload directory that should be used for storing the old version. Default is 'archive'.\r
- * @param $shared Boolean use the shared upload directory (only relevant for other functions which call this one). Default is 'false'.\r
- * @public\r
- */\r
-function wfImageArchiveDir( $fname , $subdir='archive', $shared=false ) {\r
- global $wgUploadDirectory, $wgHashedUploadDirectory;\r
- global $wgSharedUploadDirectory, $wgHashedSharedUploadDirectory;\r
- $dir = $shared ? $wgSharedUploadDirectory : $wgUploadDirectory;\r
- $hashdir = $shared ? $wgHashedSharedUploadDirectory : $wgHashedUploadDirectory;\r
- if (!$hashdir) { return $dir.'/'.$subdir; }\r
- $hash = md5( $fname );\r
-\r
- return $dir.'/'.$subdir.'/'.$hash[0].'/'.substr( $hash, 0, 2 );\r
-}\r
-\r
-\r
-/*\r
- * Return the hash path component of an image path (URL or filesystem),\r
- * e.g. "/3/3c/", or just "/" if hashing is not used.\r
- *\r
- * @param $dbkey The filesystem / database name of the file\r
- * @param $fromSharedDirectory Use the shared file repository? It may\r
- * use different hash settings from the local one.\r
- */\r
-function wfGetHashPath ( $dbkey, $fromSharedDirectory = false ) {\r
- if( Image::isHashed( $fromSharedDirectory ) ) {\r
- $hash = md5($dbkey);\r
- return '/' . $hash{0} . '/' . substr( $hash, 0, 2 ) . '/';\r
- } else {\r
- return '/';\r
- }\r
-}\r
-\r
-/**\r
- * Returns the image URL of an image's old version\r
- *\r
- * @param $name String: file name of the image file\r
- * @param $subdir String: (optional) subdirectory of the image upload directory that is used by the old version. Default is 'archive'\r
- * @public\r
- */\r
-function wfImageArchiveUrl( $name, $subdir='archive' ) {\r
- global $wgUploadPath, $wgHashedUploadDirectory;\r
-\r
- if ($wgHashedUploadDirectory) {\r
- $hash = md5( substr( $name, 15) );\r
- $url = $wgUploadPath.'/'.$subdir.'/' . $hash{0} . '/' .\r
- substr( $hash, 0, 2 ) . '/'.$name;\r
- } else {\r
- $url = $wgUploadPath.'/'.$subdir.'/'.$name;\r
- }\r
- return wfUrlencode($url);\r
-}\r
-\r
-/**\r
- * Return a rounded pixel equivalent for a labeled CSS/SVG length.\r
- * http://www.w3.org/TR/SVG11/coords.html#UnitIdentifiers\r
- *\r
- * @param $length String: CSS/SVG length.\r
- * @return Integer: length in pixels\r
- */\r
-function wfScaleSVGUnit( $length ) {\r
- static $unitLength = array(\r
- 'px' => 1.0,\r
- 'pt' => 1.25,\r
- 'pc' => 15.0,\r
- 'mm' => 3.543307,\r
- 'cm' => 35.43307,\r
- 'in' => 90.0,\r
- '' => 1.0, // "User units" pixels by default\r
- '%' => 2.0, // Fake it!\r
- );\r
- if( preg_match( '/^(\d+(?:\.\d+)?)(em|ex|px|pt|pc|cm|mm|in|%|)$/', $length, $matches ) ) {\r
- $length = floatval( $matches[1] );\r
- $unit = $matches[2];\r
- return round( $length * $unitLength[$unit] );\r
- } else {\r
- // Assume pixels\r
- return round( floatval( $length ) );\r
- }\r
-}\r
-\r
-/**\r
- * Compatible with PHP getimagesize()\r
- * @todo support gzipped SVGZ\r
- * @todo check XML more carefully\r
- * @todo sensible defaults\r
- *\r
- * @param $filename String: full name of the file (passed to php fopen()).\r
- * @return array\r
- */\r
-function wfGetSVGsize( $filename ) {\r
- $width = 256;\r
- $height = 256;\r
-\r
- // Read a chunk of the file\r
- $f = fopen( $filename, "rt" );\r
- if( !$f ) return false;\r
- $chunk = fread( $f, 4096 );\r
- fclose( $f );\r
-\r
- // Uber-crappy hack! Run through a real XML parser.\r
- if( !preg_match( '/<svg\s*([^>]*)\s*>/s', $chunk, $matches ) ) {\r
- return false;\r
- }\r
- $tag = $matches[1];\r
- if( preg_match( '/\bwidth\s*=\s*("[^"]+"|\'[^\']+\')/s', $tag, $matches ) ) {\r
- $width = wfScaleSVGUnit( trim( substr( $matches[1], 1, -1 ) ) );\r
- }\r
- if( preg_match( '/\bheight\s*=\s*("[^"]+"|\'[^\']+\')/s', $tag, $matches ) ) {\r
- $height = wfScaleSVGUnit( trim( substr( $matches[1], 1, -1 ) ) );\r
- }\r
-\r
- return array( $width, $height, 'SVG',\r
- "width=\"$width\" height=\"$height\"" );\r
-}\r
-\r
-/**\r
- * Determine if an image exists on the 'bad image list'.\r
- *\r
- * @param $name String: the image name to check\r
- * @return bool\r
- */\r
-function wfIsBadImage( $name ) {\r
- static $titleList = false;\r
- wfProfileIn( __METHOD__ );\r
- $bad = false;\r
- if( wfRunHooks( 'BadImage', array( $name, &$bad ) ) ) {\r
- if( !$titleList ) {\r
- # Build the list now\r
- $titleList = array();\r
- $lines = explode( "\n", wfMsgForContent( 'bad_image_list' ) );\r
- foreach( $lines as $line ) {\r
- if( preg_match( '/^\*\s*\[\[:?(.*?)\]\]/i', $line, $matches ) ) {\r
- $title = Title::newFromText( $matches[1] );\r
- if( is_object( $title ) && $title->getNamespace() == NS_IMAGE )\r
- $titleList[ $title->getDBkey() ] = true;\r
- }\r
- }\r
- }\r
- wfProfileOut( __METHOD__ );\r
- return array_key_exists( $name, $titleList );\r
- } else {\r
- wfProfileOut( __METHOD__ );\r
- return $bad;\r
- }\r
-}\r
-\r
-/**\r
- * Calculate the largest thumbnail width for a given original file size\r
- * such that the thumbnail's height is at most $maxHeight.\r
- * @param $boxWidth Integer Width of the thumbnail box.\r
- * @param $boxHeight Integer Height of the thumbnail box.\r
- * @param $maxHeight Integer Maximum height expected for the thumbnail.\r
- * @return Integer.\r
- */\r
-function wfFitBoxWidth( $boxWidth, $boxHeight, $maxHeight ) {\r
- $idealWidth = $boxWidth * $maxHeight / $boxHeight;\r
- $roundedUp = ceil( $idealWidth );\r
- if( round( $roundedUp * $boxHeight / $boxWidth ) > $maxHeight )\r
- return floor( $idealWidth );\r
- else\r
- return $roundedUp;\r
-}\r
-\r
-\r
-?>\r
+<?php
+
+/**
+ * Returns the image directory of an image
+ * The result is an absolute path.
+ *
+ * This function is called from thumb.php before Setup.php is included
+ *
+ * @param $fname String: file name of the image file.
+ * @public
+ */
+function wfImageDir( $fname ) {
+ global $wgUploadDirectory, $wgHashedUploadDirectory;
+
+ if (!$wgHashedUploadDirectory) { return $wgUploadDirectory; }
+
+ $hash = md5( $fname );
+ $dest = $wgUploadDirectory . '/' . $hash{0} . '/' . substr( $hash, 0, 2 );
+
+ return $dest;
+}
+
+/**
+ * Returns the image directory of an image's thubnail
+ * The result is an absolute path.
+ *
+ * This function is called from thumb.php before Setup.php is included
+ *
+ * @param $fname String: file name of the original image file
+ * @param $shared Boolean: (optional) use the shared upload directory (default: 'false').
+ * @public
+ */
+function wfImageThumbDir( $fname, $shared = false ) {
+ $base = wfImageArchiveDir( $fname, 'thumb', $shared );
+ if ( Image::isHashed( $shared ) ) {
+ $dir = "$base/$fname";
+ } else {
+ $dir = $base;
+ }
+
+ return $dir;
+}
+
+/**
+ * Old thumbnail directory, kept for conversion
+ */
+function wfDeprecatedThumbDir( $thumbName , $subdir='thumb', $shared=false) {
+ return wfImageArchiveDir( $thumbName, $subdir, $shared );
+}
+
+/**
+ * Returns the image directory of an image's old version
+ * The result is an absolute path.
+ *
+ * This function is called from thumb.php before Setup.php is included
+ *
+ * @param $fname String: file name of the thumbnail file, including file size prefix.
+ * @param $subdir String: subdirectory of the image upload directory that should be used for storing the old version. Default is 'archive'.
+ * @param $shared Boolean use the shared upload directory (only relevant for other functions which call this one). Default is 'false'.
+ * @public
+ */
+function wfImageArchiveDir( $fname , $subdir='archive', $shared=false ) {
+ global $wgUploadDirectory, $wgHashedUploadDirectory;
+ global $wgSharedUploadDirectory, $wgHashedSharedUploadDirectory;
+ $dir = $shared ? $wgSharedUploadDirectory : $wgUploadDirectory;
+ $hashdir = $shared ? $wgHashedSharedUploadDirectory : $wgHashedUploadDirectory;
+ if (!$hashdir) { return $dir.'/'.$subdir; }
+ $hash = md5( $fname );
+
+ return $dir.'/'.$subdir.'/'.$hash[0].'/'.substr( $hash, 0, 2 );
+}
+
+
+/*
+ * Return the hash path component of an image path (URL or filesystem),
+ * e.g. "/3/3c/", or just "/" if hashing is not used.
+ *
+ * @param $dbkey The filesystem / database name of the file
+ * @param $fromSharedDirectory Use the shared file repository? It may
+ * use different hash settings from the local one.
+ */
+function wfGetHashPath ( $dbkey, $fromSharedDirectory = false ) {
+ if( Image::isHashed( $fromSharedDirectory ) ) {
+ $hash = md5($dbkey);
+ return '/' . $hash{0} . '/' . substr( $hash, 0, 2 ) . '/';
+ } else {
+ return '/';
+ }
+}
+
+/**
+ * Returns the image URL of an image's old version
+ *
+ * @param $name String: file name of the image file
+ * @param $subdir String: (optional) subdirectory of the image upload directory that is used by the old version. Default is 'archive'
+ * @public
+ */
+function wfImageArchiveUrl( $name, $subdir='archive' ) {
+ global $wgUploadPath, $wgHashedUploadDirectory;
+
+ if ($wgHashedUploadDirectory) {
+ $hash = md5( substr( $name, 15) );
+ $url = $wgUploadPath.'/'.$subdir.'/' . $hash{0} . '/' .
+ substr( $hash, 0, 2 ) . '/'.$name;
+ } else {
+ $url = $wgUploadPath.'/'.$subdir.'/'.$name;
+ }
+ return wfUrlencode($url);
+}
+
+/**
+ * Return a rounded pixel equivalent for a labeled CSS/SVG length.
+ * http://www.w3.org/TR/SVG11/coords.html#UnitIdentifiers
+ *
+ * @param $length String: CSS/SVG length.
+ * @return Integer: length in pixels
+ */
+function wfScaleSVGUnit( $length ) {
+ static $unitLength = array(
+ 'px' => 1.0,
+ 'pt' => 1.25,
+ 'pc' => 15.0,
+ 'mm' => 3.543307,
+ 'cm' => 35.43307,
+ 'in' => 90.0,
+ '' => 1.0, // "User units" pixels by default
+ '%' => 2.0, // Fake it!
+ );
+ if( preg_match( '/^(\d+(?:\.\d+)?)(em|ex|px|pt|pc|cm|mm|in|%|)$/', $length, $matches ) ) {
+ $length = floatval( $matches[1] );
+ $unit = $matches[2];
+ return round( $length * $unitLength[$unit] );
+ } else {
+ // Assume pixels
+ return round( floatval( $length ) );
+ }
+}
+
+/**
+ * Compatible with PHP getimagesize()
+ * @todo support gzipped SVGZ
+ * @todo check XML more carefully
+ * @todo sensible defaults
+ *
+ * @param $filename String: full name of the file (passed to php fopen()).
+ * @return array
+ */
+function wfGetSVGsize( $filename ) {
+ $width = 256;
+ $height = 256;
+
+ // Read a chunk of the file
+ $f = fopen( $filename, "rt" );
+ if( !$f ) return false;
+ $chunk = fread( $f, 4096 );
+ fclose( $f );
+
+ // Uber-crappy hack! Run through a real XML parser.
+ if( !preg_match( '/<svg\s*([^>]*)\s*>/s', $chunk, $matches ) ) {
+ return false;
+ }
+ $tag = $matches[1];
+ if( preg_match( '/\bwidth\s*=\s*("[^"]+"|\'[^\']+\')/s', $tag, $matches ) ) {
+ $width = wfScaleSVGUnit( trim( substr( $matches[1], 1, -1 ) ) );
+ }
+ if( preg_match( '/\bheight\s*=\s*("[^"]+"|\'[^\']+\')/s', $tag, $matches ) ) {
+ $height = wfScaleSVGUnit( trim( substr( $matches[1], 1, -1 ) ) );
+ }
+
+ return array( $width, $height, 'SVG',
+ "width=\"$width\" height=\"$height\"" );
+}
+
+/**
+ * Determine if an image exists on the 'bad image list'.
+ *
+ * @param $name String: the image name to check
+ * @return bool
+ */
+function wfIsBadImage( $name ) {
+ static $titleList = false;
+ wfProfileIn( __METHOD__ );
+ $bad = false;
+ if( wfRunHooks( 'BadImage', array( $name, &$bad ) ) ) {
+ if( !$titleList ) {
+ # Build the list now
+ $titleList = array();
+ $lines = explode( "\n", wfMsgForContent( 'bad_image_list' ) );
+ foreach( $lines as $line ) {
+ if( preg_match( '/^\*\s*\[\[:?(.*?)\]\]/i', $line, $matches ) ) {
+ $title = Title::newFromText( $matches[1] );
+ if( is_object( $title ) && $title->getNamespace() == NS_IMAGE )
+ $titleList[ $title->getDBkey() ] = true;
+ }
+ }
+ }
+ wfProfileOut( __METHOD__ );
+ return array_key_exists( $name, $titleList );
+ } else {
+ wfProfileOut( __METHOD__ );
+ return $bad;
+ }
+}
+
+/**
+ * Calculate the largest thumbnail width for a given original file size
+ * such that the thumbnail's height is at most $maxHeight.
+ * @param $boxWidth Integer Width of the thumbnail box.
+ * @param $boxHeight Integer Height of the thumbnail box.
+ * @param $maxHeight Integer Maximum height expected for the thumbnail.
+ * @return Integer.
+ */
+function wfFitBoxWidth( $boxWidth, $boxHeight, $maxHeight ) {
+ $idealWidth = $boxWidth * $maxHeight / $boxHeight;
+ $roundedUp = ceil( $idealWidth );
+ if( round( $roundedUp * $boxHeight / $boxWidth ) > $maxHeight )
+ return floor( $idealWidth );
+ else
+ return $roundedUp;
+}
+
+
+?>
-<?php\r
-\r
-/**\r
- * Module of static functions for generating XML\r
- */\r
-\r
-class Xml {\r
- /**\r
- * Format an XML element with given attributes and, optionally, text content.\r
- * Element and attribute names are assumed to be ready for literal inclusion.\r
- * Strings are assumed to not contain XML-illegal characters; special\r
- * characters (<, >, &) are escaped but illegals are not touched.\r
- *\r
- * @param $element String:\r
- * @param $attribs Array: Name=>value pairs. Values will be escaped.\r
- * @param $contents String: NULL to make an open tag only; '' for a contentless closed tag (default)\r
- * @return string\r
- */\r
- public static function element( $element, $attribs = null, $contents = '') {\r
- $out = '<' . $element;\r
- if( !is_null( $attribs ) ) {\r
- foreach( $attribs as $name => $val ) {\r
- $out .= ' ' . $name . '="' . Sanitizer::encodeAttribute( $val ) . '"';\r
- }\r
- }\r
- if( is_null( $contents ) ) {\r
- $out .= '>';\r
- } else {\r
- if( $contents === '' ) {\r
- $out .= ' />';\r
- } else {\r
- $out .= '>' . htmlspecialchars( $contents ) . "</$element>";\r
- }\r
- }\r
- return $out;\r
- }\r
-\r
- /**\r
- * Format an XML element as with self::element(), but run text through the\r
- * UtfNormal::cleanUp() validator first to ensure that no invalid UTF-8\r
- * is passed.\r
- *\r
- * @param $element String:\r
- * @param $attribs Array: Name=>value pairs. Values will be escaped.\r
- * @param $contents String: NULL to make an open tag only; '' for a contentless closed tag (default)\r
- * @return string\r
- */\r
- public static function elementClean( $element, $attribs = array(), $contents = '') {\r
- if( $attribs ) {\r
- $attribs = array_map( array( 'UtfNormal', 'cleanUp' ), $attribs );\r
- }\r
- if( $contents ) {\r
- $contents = UtfNormal::cleanUp( $contents );\r
- }\r
- return self::element( $element, $attribs, $contents );\r
- }\r
-\r
- // Shortcuts\r
- public static function openElement( $element, $attribs = null ) { return self::element( $element, $attribs, null ); }\r
- public static function closeElement( $element ) { return "</$element>"; }\r
-\r
- /**\r
- * Create a namespace selector\r
- *\r
- * @param $selected Mixed: the namespace which should be selected, default ''\r
- * @param $allnamespaces String: value of a special item denoting all namespaces. Null to not include (default)\r
- * @param $includehidden Bool: include hidden namespaces?\r
- * @return String: Html string containing the namespace selector\r
- */\r
- public static function &namespaceSelector($selected = '', $allnamespaces = null, $includehidden=false) {\r
- global $wgContLang;\r
- if( $selected !== '' ) {\r
- if( is_null( $selected ) ) {\r
- // No namespace selected; let exact match work without hitting Main\r
- $selected = '';\r
- } else {\r
- // Let input be numeric strings without breaking the empty match.\r
- $selected = intval( $selected );\r
- }\r
- }\r
- $s = "\n<select id='namespace' name='namespace' class='namespaceselector'>\n";\r
- $arr = $wgContLang->getFormattedNamespaces();\r
- if( !is_null($allnamespaces) ) {\r
- $arr = array($allnamespaces => wfMsg('namespacesall')) + $arr;\r
- }\r
- foreach ($arr as $index => $name) {\r
- if ($index < NS_MAIN) continue;\r
-\r
- $name = $index !== 0 ? $name : wfMsg('blanknamespace');\r
-\r
- if ($index === $selected) {\r
- $s .= "\t" . self::element("option",\r
- array("value" => $index, "selected" => "selected"),\r
- $name) . "\n";\r
- } else {\r
- $s .= "\t" . self::element("option", array("value" => $index), $name) . "\n";\r
- }\r
- }\r
- $s .= "</select>\n";\r
- return $s;\r
- }\r
-\r
- public static function span( $text, $class, $attribs=array() ) {\r
- return self::element( 'span', array( 'class' => $class ) + $attribs, $text );\r
- }\r
-\r
- /**\r
- * Convenience function to build an HTML text input field\r
- * @return string HTML\r
- */\r
- public static function input( $name, $size=false, $value=false, $attribs=array() ) {\r
- return self::element( 'input', array(\r
- 'name' => $name,\r
- 'size' => $size,\r
- 'value' => $value ) + $attribs );\r
- }\r
-\r
- /**\r
- * Internal function for use in checkboxes and radio buttons and such.\r
- * @return array\r
- */\r
- public static function attrib( $name, $present = true ) {\r
- return $present ? array( $name => $name ) : array();\r
- }\r
-\r
- /**\r
- * Convenience function to build an HTML checkbox\r
- * @return string HTML\r
- */\r
- public static function check( $name, $checked=false, $attribs=array() ) {\r
- return self::element( 'input', array(\r
- 'name' => $name,\r
- 'type' => 'checkbox',\r
- 'value' => 1 ) + self::attrib( 'checked', $checked ) + $attribs );\r
- }\r
-\r
- /**\r
- * Convenience function to build an HTML radio button\r
- * @return string HTML\r
- */\r
- public static function radio( $name, $value, $checked=false, $attribs=array() ) {\r
- return self::element( 'input', array(\r
- 'name' => $name,\r
- 'type' => 'radio',\r
- 'value' => $value ) + self::attrib( 'checked', $checked ) + $attribs );\r
- }\r
-\r
- /**\r
- * Convenience function to build an HTML form label\r
- * @return string HTML\r
- */\r
- public static function label( $label, $id ) {\r
- return self::element( 'label', array( 'for' => $id ), $label );\r
- }\r
-\r
- /**\r
- * Convenience function to build an HTML text input field with a label\r
- * @return string HTML\r
- */\r
- public static function inputLabel( $label, $name, $id, $size=false, $value=false, $attribs=array() ) {\r
- return Xml::label( $label, $id ) .\r
- ' ' .\r
- self::input( $name, $size, $value, array( 'id' => $id ) + $attribs );\r
- }\r
-\r
- /**\r
- * Convenience function to build an HTML checkbox with a label\r
- * @return string HTML\r
- */\r
- public static function checkLabel( $label, $name, $id, $checked=false, $attribs=array() ) {\r
- return self::check( $name, $checked, array( 'id' => $id ) + $attribs ) .\r
- ' ' .\r
- self::label( $label, $id );\r
- }\r
-\r
- /**\r
- * Convenience function to build an HTML radio button with a label\r
- * @return string HTML\r
- */\r
- public static function radioLabel( $label, $name, $value, $id, $checked=false, $attribs=array() ) {\r
- return self::radio( $name, $value, $checked, array( 'id' => $id ) + $attribs ) .\r
- ' ' .\r
- self::label( $label, $id );\r
- }\r
-\r
- /**\r
- * Convenience function to build an HTML submit button\r
- * @param $value String: label text for the button\r
- * @param $attribs Array: optional custom attributes\r
- * @return string HTML\r
- */\r
- public static function submitButton( $value, $attribs=array() ) {\r
- return self::element( 'input', array( 'type' => 'submit', 'value' => $value ) + $attribs );\r
- }\r
-\r
- /**\r
- * Convenience function to build an HTML hidden form field.\r
- * @todo Document $name parameter.\r
- * @param $name FIXME\r
- * @param $value String: label text for the button\r
- * @param $attribs Array: optional custom attributes\r
- * @return string HTML\r
- */\r
- public static function hidden( $name, $value, $attribs=array() ) {\r
- return self::element( 'input', array(\r
- 'name' => $name,\r
- 'type' => 'hidden',\r
- 'value' => $value ) + $attribs );\r
- }\r
-\r
- /**\r
- * Returns an escaped string suitable for inclusion in a string literal\r
- * for JavaScript source code.\r
- * Illegal control characters are assumed not to be present.\r
- *\r
- * @param string $string\r
- * @return string\r
- */\r
- public static function escapeJsString( $string ) {\r
- // See ECMA 262 section 7.8.4 for string literal format\r
- $pairs = array(\r
- "\\" => "\\\\",\r
- "\"" => "\\\"",\r
- '\'' => '\\\'',\r
- "\n" => "\\n",\r
- "\r" => "\\r",\r
-\r
- # To avoid closing the element or CDATA section\r
- "<" => "\\x3c",\r
- ">" => "\\x3e",\r
-\r
- # To avoid any complaints about bad entity refs \r
- "&" => "\\x26",\r
- );\r
- return strtr( $string, $pairs );\r
- }\r
-\r
- /**\r
- * Check if a string is well-formed XML.\r
- * Must include the surrounding tag.\r
- *\r
- * @param $text String: string to test.\r
- * @return bool\r
- *\r
- * @todo Error position reporting return\r
- */\r
- public static function isWellFormed( $text ) {\r
- $parser = xml_parser_create( "UTF-8" );\r
-\r
- # case folding violates XML standard, turn it off\r
- xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );\r
-\r
- if( !xml_parse( $parser, $text, true ) ) {\r
- $err = xml_error_string( xml_get_error_code( $parser ) );\r
- $position = xml_get_current_byte_index( $parser );\r
- //$fragment = $this->extractFragment( $html, $position );\r
- //$this->mXmlError = "$err at byte $position:\n$fragment";\r
- xml_parser_free( $parser );\r
- return false;\r
- }\r
- xml_parser_free( $parser );\r
- return true;\r
- }\r
-\r
- /**\r
- * Check if a string is a well-formed XML fragment.\r
- * Wraps fragment in an \<html\> bit and doctype, so it can be a fragment\r
- * and can use HTML named entities.\r
- *\r
- * @param $text String:\r
- * @return bool\r
- */\r
- public static function isWellFormedXmlFragment( $text ) {\r
- $html =\r
- Sanitizer::hackDocType() .\r
- '<html>' .\r
- $text .\r
- '</html>';\r
- return Xml::isWellFormed( $html );\r
- }\r
-}\r
-?>\r
+<?php
+
+/**
+ * Module of static functions for generating XML
+ */
+
+class Xml {
+ /**
+ * Format an XML element with given attributes and, optionally, text content.
+ * Element and attribute names are assumed to be ready for literal inclusion.
+ * Strings are assumed to not contain XML-illegal characters; special
+ * characters (<, >, &) are escaped but illegals are not touched.
+ *
+ * @param $element String:
+ * @param $attribs Array: Name=>value pairs. Values will be escaped.
+ * @param $contents String: NULL to make an open tag only; '' for a contentless closed tag (default)
+ * @return string
+ */
+ public static function element( $element, $attribs = null, $contents = '') {
+ $out = '<' . $element;
+ if( !is_null( $attribs ) ) {
+ foreach( $attribs as $name => $val ) {
+ $out .= ' ' . $name . '="' . Sanitizer::encodeAttribute( $val ) . '"';
+ }
+ }
+ if( is_null( $contents ) ) {
+ $out .= '>';
+ } else {
+ if( $contents === '' ) {
+ $out .= ' />';
+ } else {
+ $out .= '>' . htmlspecialchars( $contents ) . "</$element>";
+ }
+ }
+ return $out;
+ }
+
+ /**
+ * Format an XML element as with self::element(), but run text through the
+ * UtfNormal::cleanUp() validator first to ensure that no invalid UTF-8
+ * is passed.
+ *
+ * @param $element String:
+ * @param $attribs Array: Name=>value pairs. Values will be escaped.
+ * @param $contents String: NULL to make an open tag only; '' for a contentless closed tag (default)
+ * @return string
+ */
+ public static function elementClean( $element, $attribs = array(), $contents = '') {
+ if( $attribs ) {
+ $attribs = array_map( array( 'UtfNormal', 'cleanUp' ), $attribs );
+ }
+ if( $contents ) {
+ $contents = UtfNormal::cleanUp( $contents );
+ }
+ return self::element( $element, $attribs, $contents );
+ }
+
+ // Shortcuts
+ public static function openElement( $element, $attribs = null ) { return self::element( $element, $attribs, null ); }
+ public static function closeElement( $element ) { return "</$element>"; }
+
+ /**
+ * Create a namespace selector
+ *
+ * @param $selected Mixed: the namespace which should be selected, default ''
+ * @param $allnamespaces String: value of a special item denoting all namespaces. Null to not include (default)
+ * @param $includehidden Bool: include hidden namespaces?
+ * @return String: Html string containing the namespace selector
+ */
+ public static function &namespaceSelector($selected = '', $allnamespaces = null, $includehidden=false) {
+ global $wgContLang;
+ if( $selected !== '' ) {
+ if( is_null( $selected ) ) {
+ // No namespace selected; let exact match work without hitting Main
+ $selected = '';
+ } else {
+ // Let input be numeric strings without breaking the empty match.
+ $selected = intval( $selected );
+ }
+ }
+ $s = "\n<select id='namespace' name='namespace' class='namespaceselector'>\n";
+ $arr = $wgContLang->getFormattedNamespaces();
+ if( !is_null($allnamespaces) ) {
+ $arr = array($allnamespaces => wfMsg('namespacesall')) + $arr;
+ }
+ foreach ($arr as $index => $name) {
+ if ($index < NS_MAIN) continue;
+
+ $name = $index !== 0 ? $name : wfMsg('blanknamespace');
+
+ if ($index === $selected) {
+ $s .= "\t" . self::element("option",
+ array("value" => $index, "selected" => "selected"),
+ $name) . "\n";
+ } else {
+ $s .= "\t" . self::element("option", array("value" => $index), $name) . "\n";
+ }
+ }
+ $s .= "</select>\n";
+ return $s;
+ }
+
+ public static function span( $text, $class, $attribs=array() ) {
+ return self::element( 'span', array( 'class' => $class ) + $attribs, $text );
+ }
+
+ /**
+ * Convenience function to build an HTML text input field
+ * @return string HTML
+ */
+ public static function input( $name, $size=false, $value=false, $attribs=array() ) {
+ return self::element( 'input', array(
+ 'name' => $name,
+ 'size' => $size,
+ 'value' => $value ) + $attribs );
+ }
+
+ /**
+ * Internal function for use in checkboxes and radio buttons and such.
+ * @return array
+ */
+ public static function attrib( $name, $present = true ) {
+ return $present ? array( $name => $name ) : array();
+ }
+
+ /**
+ * Convenience function to build an HTML checkbox
+ * @return string HTML
+ */
+ public static function check( $name, $checked=false, $attribs=array() ) {
+ return self::element( 'input', array(
+ 'name' => $name,
+ 'type' => 'checkbox',
+ 'value' => 1 ) + self::attrib( 'checked', $checked ) + $attribs );
+ }
+
+ /**
+ * Convenience function to build an HTML radio button
+ * @return string HTML
+ */
+ public static function radio( $name, $value, $checked=false, $attribs=array() ) {
+ return self::element( 'input', array(
+ 'name' => $name,
+ 'type' => 'radio',
+ 'value' => $value ) + self::attrib( 'checked', $checked ) + $attribs );
+ }
+
+ /**
+ * Convenience function to build an HTML form label
+ * @return string HTML
+ */
+ public static function label( $label, $id ) {
+ return self::element( 'label', array( 'for' => $id ), $label );
+ }
+
+ /**
+ * Convenience function to build an HTML text input field with a label
+ * @return string HTML
+ */
+ public static function inputLabel( $label, $name, $id, $size=false, $value=false, $attribs=array() ) {
+ return Xml::label( $label, $id ) .
+ ' ' .
+ self::input( $name, $size, $value, array( 'id' => $id ) + $attribs );
+ }
+
+ /**
+ * Convenience function to build an HTML checkbox with a label
+ * @return string HTML
+ */
+ public static function checkLabel( $label, $name, $id, $checked=false, $attribs=array() ) {
+ return self::check( $name, $checked, array( 'id' => $id ) + $attribs ) .
+ ' ' .
+ self::label( $label, $id );
+ }
+
+ /**
+ * Convenience function to build an HTML radio button with a label
+ * @return string HTML
+ */
+ public static function radioLabel( $label, $name, $value, $id, $checked=false, $attribs=array() ) {
+ return self::radio( $name, $value, $checked, array( 'id' => $id ) + $attribs ) .
+ ' ' .
+ self::label( $label, $id );
+ }
+
+ /**
+ * Convenience function to build an HTML submit button
+ * @param $value String: label text for the button
+ * @param $attribs Array: optional custom attributes
+ * @return string HTML
+ */
+ public static function submitButton( $value, $attribs=array() ) {
+ return self::element( 'input', array( 'type' => 'submit', 'value' => $value ) + $attribs );
+ }
+
+ /**
+ * Convenience function to build an HTML hidden form field.
+ * @todo Document $name parameter.
+ * @param $name FIXME
+ * @param $value String: label text for the button
+ * @param $attribs Array: optional custom attributes
+ * @return string HTML
+ */
+ public static function hidden( $name, $value, $attribs=array() ) {
+ return self::element( 'input', array(
+ 'name' => $name,
+ 'type' => 'hidden',
+ 'value' => $value ) + $attribs );
+ }
+
+ /**
+ * Returns an escaped string suitable for inclusion in a string literal
+ * for JavaScript source code.
+ * Illegal control characters are assumed not to be present.
+ *
+ * @param string $string
+ * @return string
+ */
+ public static function escapeJsString( $string ) {
+ // See ECMA 262 section 7.8.4 for string literal format
+ $pairs = array(
+ "\\" => "\\\\",
+ "\"" => "\\\"",
+ '\'' => '\\\'',
+ "\n" => "\\n",
+ "\r" => "\\r",
+
+ # To avoid closing the element or CDATA section
+ "<" => "\\x3c",
+ ">" => "\\x3e",
+
+ # To avoid any complaints about bad entity refs
+ "&" => "\\x26",
+ );
+ return strtr( $string, $pairs );
+ }
+
+ /**
+ * Check if a string is well-formed XML.
+ * Must include the surrounding tag.
+ *
+ * @param $text String: string to test.
+ * @return bool
+ *
+ * @todo Error position reporting return
+ */
+ public static function isWellFormed( $text ) {
+ $parser = xml_parser_create( "UTF-8" );
+
+ # case folding violates XML standard, turn it off
+ xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
+
+ if( !xml_parse( $parser, $text, true ) ) {
+ $err = xml_error_string( xml_get_error_code( $parser ) );
+ $position = xml_get_current_byte_index( $parser );
+ //$fragment = $this->extractFragment( $html, $position );
+ //$this->mXmlError = "$err at byte $position:\n$fragment";
+ xml_parser_free( $parser );
+ return false;
+ }
+ xml_parser_free( $parser );
+ return true;
+ }
+
+ /**
+ * Check if a string is a well-formed XML fragment.
+ * Wraps fragment in an \<html\> bit and doctype, so it can be a fragment
+ * and can use HTML named entities.
+ *
+ * @param $text String:
+ * @return bool
+ */
+ public static function isWellFormedXmlFragment( $text ) {
+ $html =
+ Sanitizer::hackDocType() .
+ '<html>' .
+ $text .
+ '</html>';
+ return Xml::isWellFormed( $html );
+ }
+}
+?>