X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FGlobalFunctions.php;h=57bd13281ce713f82efe779879dbd10ea19c075c;hb=40745cfef875263d13f29cea01b501655d218f16;hp=bc5e2a92773a812b51aad50c36c593ec77da3ec1;hpb=7fe3ed71f325d19ff509f2f5a005ea7127412104;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index bc5e2a9277..57bd13281c 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -8,7 +8,7 @@ /** * Some globals and requires needed */ - + /** * Total number of articles * @global integer $wgNumberOfArticles @@ -67,18 +67,29 @@ if( !function_exists('is_a') ) { # UTF-8 substr function based on a PHP manual comment if ( !function_exists( 'mb_substr' ) ) { - function mb_substr( $str, $start ) { + function mb_substr( $str, $start ) { preg_match_all( '/./us', $str, $ar ); if( func_num_args() >= 3 ) { - $end = func_get_arg( 2 ); - return join( '', array_slice( $ar[0], $start, $end ) ); - } else { - return join( '', array_slice( $ar[0], $start ) ); + $end = func_get_arg( 2 ); + return join( '', array_slice( $ar[0], $start, $end ) ); + } else { + return join( '', array_slice( $ar[0], $start ) ); } } } +if( !function_exists( 'floatval' ) ) { + /** + * First defined in PHP 4.2.0 + * @param mixed $var; + * @return float + */ + function floatval( $var ) { + return (float)$var; + } +} + /** * Where as we got a random seed * @var bool $wgTotalViews @@ -164,6 +175,25 @@ function wfDebug( $text, $logonly = false ) { } } +/** + * Send a line to a supplementary debug log file, if configured, or main debug log if not. + * $wgDebugLogGroups[$logGroup] should be set to a filename to send to a separate log. + * + * @param string $logGroup + * @param string $text + * @param bool $public Whether to log the event in the public log if no private + * log file is specified, (default true) + */ +function wfDebugLog( $logGroup, $text, $public = true ) { + global $wgDebugLogGroups, $wgDBname; + if( $text{strlen( $text ) - 1} != "\n" ) $text .= "\n"; + if( isset( $wgDebugLogGroups[$logGroup] ) ) { + @error_log( "$wgDBname: $text", 3, $wgDebugLogGroups[$logGroup] ); + } else if ( $public === true ) { + wfDebug( $text, true ); + } +} + /** * Log for database errors * @param string $text Database error message. @@ -171,7 +201,8 @@ function wfDebug( $text, $logonly = false ) { function wfLogDBError( $text ) { global $wgDBerrorLog; if ( $wgDBerrorLog ) { - $text = date('D M j G:i:s T Y') . "\t".$text; + $host = trim(`hostname`); + $text = date('D M j G:i:s T Y') . "\t$host\t".$text; error_log( $text, 3, $wgDBerrorLog ); } } @@ -224,10 +255,10 @@ function wfReadOnly() { if ( '' == $wgReadOnlyFile ) { return false; } - + // Set $wgReadOnly and unset $wgReadOnlyFile, for faster access next time if ( is_file( $wgReadOnlyFile ) ) { - $wgReadOnly = true; + $wgReadOnly = file_get_contents( $wgReadOnlyFile ); } else { $wgReadOnly = false; } @@ -237,9 +268,18 @@ function wfReadOnly() { /** - * Get a message from anywhere, for the current user language + * Get a message from anywhere, for the current user language. + * + * Use wfMsgForContent() instead if the message should NOT + * change depending on the user preferences. + * + * Note that the message may contain HTML, and is therefore + * not safe for insertion anywhere. Some functions such as + * addWikiText will do the escaping for you. Use wfMsgHtml() + * if you need an escaped message. * - * @param string + * @param string lookup key for the message, usually + * defined in languages/Language.php */ function wfMsg( $key ) { $args = func_get_args(); @@ -247,8 +287,36 @@ function wfMsg( $key ) { return wfMsgReal( $key, $args, true ); } +/** + * Same as above except doesn't transform the message + */ +function wfMsgNoTrans( $key ) { + $args = func_get_args(); + array_shift( $args ); + return wfMsgReal( $key, $args, true, false ); +} + /** * Get a message from anywhere, for the current global language + * set with $wgLanguageCode. + * + * Use this if the message should NOT change dependent on the + * language set in the user's preferences. This is the case for + * most text written into logs, as well as link targets (such as + * the name of the copyright policy page). Link titles, on the + * other hand, should be shown in the UI language. + * + * Note that MediaWiki allows users to change the user interface + * language in their preferences, but a single installation + * typically only contains content in one language. + * + * Be wary of this distinction: If you use wfMsg() where you should + * use wfMsgForContent(), a user of the software may have to + * customize over 70 messages in order to, e.g., fix a link in every + * possible language. + * + * @param string lookup key for the message, usually + * defined in languages/Language.php */ function wfMsgForContent( $key ) { global $wgForceUIMsgAsContentMsg; @@ -261,6 +329,20 @@ function wfMsgForContent( $key ) { return wfMsgReal( $key, $args, true, $forcontent ); } +/** + * Same as above except doesn't transform the message + */ +function wfMsgForContentNoTrans( $key ) { + global $wgForceUIMsgAsContentMsg; + $args = func_get_args(); + array_shift( $args ); + $forcontent = true; + if( is_array( $wgForceUIMsgAsContentMsg ) && + in_array( $key, $wgForceUIMsgAsContentMsg ) ) + $forcontent = false; + return wfMsgReal( $key, $args, true, $forcontent, false ); +} + /** * Get a message from the language file, for the UI elements */ @@ -288,11 +370,11 @@ function wfMsgNoDBForContent( $key ) { /** * Really get a message */ -function wfMsgReal( $key, $args, $useDB, $forContent=false ) { +function wfMsgReal( $key, $args, $useDB, $forContent=false, $transform = true ) { $fname = 'wfMsgReal'; wfProfileIn( $fname ); - - $message = wfMsgGetKey( $key, $useDB, $forContent ); + + $message = wfMsgGetKey( $key, $useDB, $forContent, $transform ); $message = wfMsgReplaceArgs( $message, $args ); wfProfileOut( $fname ); return $message; @@ -306,12 +388,17 @@ function wfMsgReal( $key, $args, $useDB, $forContent=false ) { * @return string * @access private */ -function wfMsgGetKey( $key, $useDB, $forContent = false ) { +function wfMsgGetKey( $key, $useDB, $forContent = false, $transform = true ) { global $wgParser, $wgMsgParserOptions; global $wgContLang, $wgLanguageCode; global $wgMessageCache, $wgLang; + + if ( is_object( $wgMessageCache ) ) + $transstat = $wgMessageCache->getTransform(); if( is_object( $wgMessageCache ) ) { + if ( ! $transform ) + $wgMessageCache->disableTransform(); $message = $wgMessageCache->get( $key, $useDB, $forContent ); } else { if( $forContent ) { @@ -321,19 +408,23 @@ function wfMsgGetKey( $key, $useDB, $forContent = false ) { } wfSuppressWarnings(); - + if( is_object( $lang ) ) { $message = $lang->getMessage( $key ); } else { - $message = ''; + $message = false; } wfRestoreWarnings(); - if(!$message) + if($message === false) $message = Language::getMessage($key); - if(strstr($message, '{{' ) !== false) { + if ( $transform && strstr( $message, '{{' ) !== false ) { $message = $wgParser->transformMsg($message, $wgMsgParserOptions); } } + + if ( is_object( $wgMessageCache ) && ! $transform ) + $wgMessageCache->setTransform( $transstat ); + return $message; } @@ -346,16 +437,21 @@ function wfMsgGetKey( $key, $useDB, $forContent = false ) { * @access private */ function wfMsgReplaceArgs( $message, $args ) { - static $replacementKeys = array( '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9' ); - # Fix windows line-endings # Some messages are split with explode("\n", $msg) $message = str_replace( "\r", '', $message ); - # Replace arguments - if( count( $args ) ) { - $message = str_replace( $replacementKeys, $args, $message ); + // Replace arguments + if ( count( $args ) ) + if ( is_array( $args[0] ) ) + foreach ( $args[0] as $key => $val ) + $message = str_replace( '$' . $key, $val, $message ); + else { + foreach( $args as $n => $param ) + $replacementKeys['$' . ($n + 1)] = $param; + $message = strtr( $message, $replacementKeys ); } + return $message; } @@ -373,9 +469,25 @@ function wfMsgReplaceArgs( $message, $args ) { function wfMsgHtml( $key ) { $args = func_get_args(); array_shift( $args ); - return wfMsgReplaceArgs( - htmlspecialchars( wfMsgGetKey( $key, $args, true ) ), - $args ); + return wfMsgReplaceArgs( htmlspecialchars( wfMsgGetKey( $key, true ) ), $args ); +} + +/** + * Return an HTML version of message + * Parameter replacements, if any, are done *after* parsing the wiki-text message, + * so parameters may contain HTML (eg links or form controls). Be sure + * to pre-escape them if you really do want plaintext, or just wrap + * the whole thing in htmlspecialchars(). + * + * @param string $key + * @param string ... parameters + * @return string + */ +function wfMsgWikiHtml( $key ) { + global $wgOut; + $args = func_get_args(); + array_shift( $args ); + return wfMsgReplaceArgs( $wgOut->parse( wfMsgGetKey( $key, true ), /* can't be set to false */ true ), $args ); } /** @@ -393,8 +505,8 @@ function wfAbruptExit( $error = false ){ if( function_exists( 'debug_backtrace' ) ){ // PHP >= 4.3 $bt = debug_backtrace(); for($i = 0; $i < count($bt) ; $i++){ - $file = $bt[$i]['file']; - $line = $bt[$i]['line']; + $file = isset($bt[$i]['file']) ? $bt[$i]['file'] : "unknown"; + $line = isset($bt[$i]['line']) ? $bt[$i]['line'] : "unknown"; wfDebug("WARNING: Abrupt exit in $file at line $line\n"); } } else { @@ -430,17 +542,49 @@ function wfDebugDieBacktrace( $msg = '' ) { } else { $msg .= "\n

Backtrace:

\n$backtrace"; } - } - echo $msg; - die( -1 ); + } + echo $msg; + echo wfReportTime()."\n"; + die( -1 ); } + /** + * Returns a HTML comment with the elapsed time since request. + * This method has no side effects. + * @return string + */ + function wfReportTime() { + global $wgRequestTime; + + $now = wfTime(); + list( $usec, $sec ) = explode( ' ', $wgRequestTime ); + $start = (float)$sec + (float)$usec; + $elapsed = $now - $start; + + # Use real server name if available, so we know which machine + # in a server farm generated the current page. + if ( function_exists( 'posix_uname' ) ) { + $uname = @posix_uname(); + } else { + $uname = false; + } + if( is_array( $uname ) && isset( $uname['nodename'] ) ) { + $hostname = $uname['nodename']; + } else { + # This may be a virtual server. + $hostname = $_SERVER['SERVER_NAME']; + } + $com = sprintf( "", + $hostname, $elapsed ); + return $com; + } + function wfBacktrace() { global $wgCommandLineMode; if ( !function_exists( 'debug_backtrace' ) ) { return false; } - + if ( $wgCommandLineMode ) { $msg = ''; } else { @@ -510,16 +654,16 @@ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) { $fmtLimit = $wgLang->formatNum( $limit ); $prev = wfMsg( 'prevn', $fmtLimit ); $next = wfMsg( 'nextn', $fmtLimit ); - + if( is_object( $link ) ) { $title =& $link; } else { - $title =& Title::newFromText( $link ); + $title = Title::newFromText( $link ); if( is_null( $title ) ) { return false; } } - + $sk = $wgUser->getSkin(); if ( 0 != $offset ) { $po = $offset - $limit; @@ -602,7 +746,7 @@ function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) { * @param string $text Text to be escaped */ function wfEscapeWikiText( $text ) { - $text = str_replace( + $text = str_replace( array( '[', '|', '\'', 'ISBN ' , '://' , "\n=", '{{' ), array( '[', '|', ''', 'ISBN ', '://' , "\n=", '{{' ), htmlspecialchars($text) ); @@ -646,7 +790,7 @@ function wfEscapeJsString( $string ) { '\'' => '\\\'', "\n" => "\\n", "\r" => "\\r", - + # To avoid closing the element or CDATA section "<" => "\\x3c", ">" => "\\x3e", @@ -732,7 +876,7 @@ function wfPurgeSquidServers ($urlArr) { /** * Windows-compatible version of escapeshellarg() - * Windows doesn't recognise single-quotes in the shell, but the escapeshellarg() + * Windows doesn't recognise single-quotes in the shell, but the escapeshellarg() * function puts single quotes in regardless of OS */ function wfEscapeShellArg( ) { @@ -745,7 +889,7 @@ function wfEscapeShellArg( ) { } else { $first = false; } - + if ( wfIsWindows() ) { $retVal .= '"' . str_replace( '"','\"', $arg ) . '"'; } else { @@ -765,6 +909,7 @@ function wfMerge( $old, $mine, $yours, &$result ){ # This check may also protect against code injection in # case of broken installations. if(! file_exists( $wgDiff3 ) ){ + wfDebug( "diff3 not found\n" ); return false; } @@ -779,7 +924,7 @@ function wfMerge( $old, $mine, $yours, &$result ){ fwrite( $yourtextFile, $yours ); fclose( $yourtextFile ); # Check for a conflict - $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a --overlap-only ' . + $cmd = $wgDiff3 . ' -a --overlap-only ' . wfEscapeShellArg( $mytextName ) . ' ' . wfEscapeShellArg( $oldtextName ) . ' ' . wfEscapeShellArg( $yourtextName ); @@ -793,7 +938,7 @@ function wfMerge( $old, $mine, $yours, &$result ){ pclose( $handle ); # Merge differences - $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' . + $cmd = $wgDiff3 . ' -a -e --merge ' . wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName ); $handle = popen( $cmd, 'r' ); $result = ''; @@ -806,6 +951,11 @@ function wfMerge( $old, $mine, $yours, &$result ){ } while ( true ); pclose( $handle ); unlink( $mytextName ); unlink( $oldtextName ); unlink( $yourtextName ); + + if ( $result === '' && $old !== '' && $conflict == false ) { + wfDebug( "Unexpected null result from diff3. Command: $cmd\n" ); + $conflict = true; + } return ! $conflict; } @@ -834,8 +984,8 @@ function wfHttpError( $code, $label, $desc ) { header( 'Content-type: text/html' ); print "" . - htmlspecialchars( $label ) . - "

" . + htmlspecialchars( $label ) . + "

" . htmlspecialchars( $label ) . "

" . htmlspecialchars( $desc ) . @@ -949,7 +1099,7 @@ function wfNegotiateType( $cprefs, $sprefs ) { * Array lookup * Returns an array where the values in the first array are replaced by the * values in the second array with the corresponding keys - * + * * @return array */ function wfArrayLookup( $a, $b ) { @@ -974,7 +1124,7 @@ function wfSuppressWarnings( $end = false ) { if ( $end ) { if ( $suppressCount ) { - $suppressCount --; + --$suppressCount; if ( !$suppressCount ) { error_reporting( $originalLevel ); } @@ -983,7 +1133,7 @@ function wfSuppressWarnings( $end = false ) { if ( !$suppressCount ) { $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE ) ); } - $suppressCount++; + ++$suppressCount; } } @@ -996,7 +1146,7 @@ function wfRestoreWarnings() { # Autodetect, convert and provide timestamps of various types -/** +/** * Unix time - the number of seconds since 1970-01-01 00:00:00 UTC */ define('TS_UNIX', 0); @@ -1016,6 +1166,13 @@ define('TS_DB', 2); */ define('TS_RFC2822', 3); +/** + * ISO 8601 format with no timezone: 1986-02-09T20:00:00Z + * + * This is used by Special:Export + */ +define('TS_ISO_8601', 4); + /** * An Exif timestamp (YYYY:MM:DD HH:MM:SS) * @@ -1023,8 +1180,12 @@ define('TS_RFC2822', 3); * DateTime tag and page 36 for the DateTimeOriginal and * DateTimeDigitized tags. */ -define('TS_EXIF', 4); +define('TS_EXIF', 5); +/** + * Oracle format time. + */ +define('TS_ORACLE', 6); /** * @param mixed $outputtype A timestamp in one of the supported formats, the @@ -1033,8 +1194,9 @@ define('TS_EXIF', 4); * @return string Time in the format specified in $outputtype */ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { - if ($ts==0) { - $uts=time(); + $uts = 0; + if ($ts==0) { + $uts=time(); } elseif (preg_match("/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/",$ts,$da)) { # TS_DB $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6], @@ -1050,13 +1212,21 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { } elseif (preg_match("/^(\d{1,13})$/",$ts,$datearray)) { # TS_UNIX $uts=$ts; + } elseif (preg_match('/^(\d{1,2})-(...)-(\d\d(\d\d)?) (\d\d)\.(\d\d)\.(\d\d)/', $ts, $da)) { + # TS_ORACLE + $uts = strtotime(preg_replace('/(\d\d)\.(\d\d)\.(\d\d)(\.(\d+))?/', "$1:$2:$3", + str_replace("+00:00", "UTC", $ts))); + } elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/', $ts, $da)) { + # TS_ISO_8601 + $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6], + (int)$da[2],(int)$da[3],(int)$da[1]); } else { # Bogus value; fall back to the epoch... wfDebug("wfTimestamp() fed bogus time value: $outputtype; $ts\n"); $uts = 0; } - + switch($outputtype) { case TS_UNIX: return $uts; @@ -1064,11 +1234,15 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { return gmdate( 'YmdHis', $uts ); case TS_DB: return gmdate( 'Y-m-d H:i:s', $uts ); + case TS_ISO_8601: + return gmdate( 'Y-m-d\TH:i:s\Z', $uts ); // This shouldn't ever be used, but is included for completeness case TS_EXIF: return gmdate( 'Y:m:d H:i:s', $uts ); case TS_RFC2822: return gmdate( 'D, d M Y H:i:s', $uts ) . ' GMT'; + case TS_ORACLE: + return gmdate( 'd-M-y h.i.s A', $uts) . ' +00:00'; default: wfDebugDieBacktrace( 'wfTimestamp() called with illegal output type.'); } @@ -1094,13 +1268,13 @@ function wfTimestampOrNull( $outputtype = TS_UNIX, $ts = null ) { * * @return bool True if it's windows, False otherwise. */ -function wfIsWindows() { - if (substr(php_uname(), 0, 7) == 'Windows') { - return true; - } else { - return false; - } -} +function wfIsWindows() { + if (substr(php_uname(), 0, 7) == 'Windows') { + return true; + } else { + return false; + } +} /** * Swap two variables @@ -1142,7 +1316,7 @@ function wfGetSiteNotice() { * * @param string $element * @param array $attribs Name=>value pairs. Values will be escaped. - * @param bool $contents NULL to make an open tag only; '' for a contentless closed tag (default) + * @param string $contents NULL to make an open tag only; '' for a contentless closed tag (default) * @return string */ function wfElement( $element, $attribs = null, $contents = '') { @@ -1173,7 +1347,7 @@ function wfElement( $element, $attribs = null, $contents = '') { * * @param string $element * @param array $attribs Name=>value pairs. Values will be escaped. - * @param bool $contents NULL to make an open tag only; '' for a contentless closed tag (default) + * @param string $contents NULL to make an open tag only; '' for a contentless closed tag (default) * @return string */ function wfElementClean( $element, $attribs = array(), $contents = '') { @@ -1186,9 +1360,53 @@ function wfElementClean( $element, $attribs = array(), $contents = '') { return wfElement( $element, $attribs, $contents ); } +// Shortcuts +function wfOpenElement( $element ) { return "<$element>"; } +function wfCloseElement( $element ) { return ""; } + +/** + * Create a namespace selector + * + * @param mixed $selected The namespace which should be selected, default '' + * @param string $allnamespaces Value of a special item denoting all namespaces. Null to not include (default) + * @return Html string containing the namespace selector + */ +function &HTMLnamespaceselector($selected = '', $allnamespaces = null) { + 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"; + return $s; +} + /** Global singleton instance of MimeMagic. This is initialized on demand, * please always use the wfGetMimeMagic() function to get the instance. -* +* * @private */ $wgMimeMagic= NULL; @@ -1201,7 +1419,7 @@ $wgMimeMagic= NULL; */ function &wfGetMimeMagic() { global $wgMimeMagic; - + if (!is_null($wgMimeMagic)) { return $wgMimeMagic; } @@ -1210,9 +1428,9 @@ function &wfGetMimeMagic() { #include on demand require_once("MimeMagic.php"); } - + $wgMimeMagic= new MimeMagic(); - + return $wgMimeMagic; } @@ -1244,7 +1462,7 @@ function wfTempDir() { function wfMkdirParents( $fullDir, $mode ) { $parts = explode( '/', $fullDir ); $path = ''; - $success = false; + foreach ( $parts as $dir ) { $path .= $dir . '/'; if ( !is_dir( $path ) ) { @@ -1267,4 +1485,153 @@ function wfIncrStats( $key ) { } } +/** + * @param mixed $nr The number to format + * @param int $acc The number of digits after the decimal point, default 2 + * @param bool $round Whether or not to round the value, default true + * @return float + */ +function wfPercent( $nr, $acc = 2, $round = true ) { + $ret = sprintf( "%.${acc}f", $nr ); + return $round ? round( $ret, $acc ) . '%' : "$ret%"; +} + +/** + * Encrypt a username/password. + * + * @param string $userid ID of the user + * @param string $password Password of the user + * @return string Hashed password + */ +function wfEncryptPassword( $userid, $password ) { + global $wgPasswordSalt; + $p = md5( $password); + + if($wgPasswordSalt) + return md5( "{$userid}-{$p}" ); + else + return $p; +} + +/** + * Appends to second array if $value differs from that in $default + */ +function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) { + if ( is_null( $changed ) ) { + wfDebugDieBacktrace('GlobalFunctions::wfAppendToArrayIfNotDefault got null'); + } + if ( $default[$key] !== $value ) { + $changed[$key] = $value; + } +} + +/** + * Since wfMsg() and co suck, they don't return false if the message key they + * looked up didn't exist but a XHTML string, this function checks for the + * nonexistance of messages by looking at wfMsg() output + * + * @param $msg The message key looked up + * @param $wfMsgOut The output of wfMsg*() + * @return bool + */ +function wfEmptyMsg( $msg, $wfMsgOut ) { + return $wfMsgOut === "<$msg>"; +} + +/** + * Find out whether or not a mixed variable exists in a string + * + * @param mixed needle + * @param string haystack + * @return bool + */ +function in_string( $needle, $str ) { + return strpos( $str, $needle ) !== false; +} + +/** + * Returns a regular expression of url protocols + * + * @return string + */ +function wfUrlProtocols() { + global $wgUrlProtocols; + + $x = array(); + foreach ($wgUrlProtocols as $protocol) + $x[] = preg_quote( $protocol, '/' ); + + return implode( '|', $x ); +} + +/** + * Check if a string is well-formed XML. + * Must include the surrounding tag. + * + * @param string $text + * @return bool + * + * @todo Error position reporting return + */ +function wfIsWellFormedXml( $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 bit and doctype, so it can be a fragment + * and can use HTML named entities. + * + * @param string $text + * @return bool + */ +function wfIsWellFormedXmlFragment( $text ) { + $html = + '' . + '' . + $text . + ''; + return wfIsWellFormedXml( $html ); +} + +/** + * shell_exec() with time and memory limits mirrored from the PHP configuration, + * if supported. + */ +function wfShellExec( $cmd ) +{ + global $IP; + + if ( php_uname( 's' ) == 'Linux' ) { + $time = ini_get( 'max_execution_time' ); + $mem = ini_get( 'memory_limit' ); + if( preg_match( '/^([0-9]+)[Mm]$/', trim( $mem ), $m ) ) { + $mem = intval( $m[1] * (1024*1024) ); + } + if ( $time > 0 && $mem > 0 ) { + $script = "$IP/bin/ulimit.sh"; + if ( is_executable( $script ) ) { + $memKB = intval( $mem / 1024 ); + $cmd = escapeshellarg( $script ) . " $time $memKB $cmd"; + } + } + } + return shell_exec( $cmd ); +} + ?>