EOL fixes.
authorRotem Liss <rotem@users.mediawiki.org>
Thu, 31 Aug 2006 11:20:43 +0000 (11:20 +0000)
committerRotem Liss <rotem@users.mediawiki.org>
Thu, 31 Aug 2006 11:20:43 +0000 (11:20 +0000)
includes/ImageFunctions.php
includes/Xml.php

index a66b4d7..38887bb 100644 (file)
-<?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;
+}
+
+
+?>
index 3026242..dc91fa5 100644 (file)
-<?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
-                       '&nbsp;' .\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
-                       '&nbsp;' .\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
-                       '&nbsp;' .\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 ) .
+                       '&nbsp;' .
+                       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 ) .
+                       '&nbsp;' .
+                       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 ) .
+                       '&nbsp;' .
+                       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 );
+       }
+}
+?>