Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

GlobalFunctions.php

Go to the documentation of this file.
00001 <?php 00002 # Global functions used everywhere 00003 00004 $wgNumberOfArticles = -1; # Unset 00005 $wgTotalViews = -1; 00006 $wgTotalEdits = -1; 00007 00008 require_once( 'DatabaseFunctions.php' ); 00009 require_once( 'UpdateClasses.php' ); 00010 require_once( 'LogPage.php' ); 00011 00012 /* 00013 * Compatibility functions 00014 */ 00015 00016 # PHP <4.3.x is not actively supported; 4.1.x and 4.2.x might or might not work. 00017 # <4.1.x will not work, as we use a number of features introduced in 4.1.0 00018 # such as the new autoglobals. 00019 00020 if( !function_exists('iconv') ) { 00021 # iconv support is not in the default configuration and so may not be present. 00022 # Assume will only ever use utf-8 and iso-8859-1. 00023 # This will *not* work in all circumstances. 00024 function iconv( $from, $to, $string ) { 00025 if(strcasecmp( $from, $to ) == 0) return $string; 00026 if(strcasecmp( $from, 'utf-8' ) == 0) return utf8_decode( $string ); 00027 if(strcasecmp( $to, 'utf-8' ) == 0) return utf8_encode( $string ); 00028 return $string; 00029 } 00030 } 00031 00032 if( !function_exists('file_get_contents') ) { 00033 # Exists in PHP 4.3.0+ 00034 function file_get_contents( $filename ) { 00035 return implode( '', file( $filename ) ); 00036 } 00037 } 00038 00039 if( !function_exists('is_a') ) { 00040 # Exists in PHP 4.2.0+ 00041 function is_a( $object, $class_name ) { 00042 return 00043 (strcasecmp( get_class( $object, $class_name ) == 0) || 00044 is_subclass_of( $object, $class_name ) ); 00045 } 00046 } 00047 00048 # html_entity_decode exists in PHP 4.3.0+ but is FATALLY BROKEN even then, 00049 # with no UTF-8 support. 00050 function do_html_entity_decode( $string, $quote_style=ENT_COMPAT, $charset='ISO-8859-1' ) { 00051 static $trans; 00052 if( !isset( $trans ) ) { 00053 $trans = array_flip( get_html_translation_table( HTML_ENTITIES, $quote_style ) ); 00054 # Assumes $charset will always be the same through a run, and only understands 00055 # utf-8 or default. Note - mixing latin1 named entities and unicode numbered 00056 # ones will result in a bad link. 00057 if( strcasecmp( 'utf-8', $charset ) == 0 ) { 00058 $trans = array_map( 'utf8_encode', $trans ); 00059 } 00060 } 00061 return strtr( $string, $trans ); 00062 } 00063 00064 $wgRandomSeeded = false; 00065 00066 function wfSeedRandom() 00067 { 00068 global $wgRandomSeeded; 00069 00070 if ( ! $wgRandomSeeded ) { 00071 $seed = hexdec(substr(md5(microtime()),-8)) & 0x7fffffff; 00072 mt_srand( $seed ); 00073 $wgRandomSeeded = true; 00074 } 00075 } 00076 00077 # Generates a URL from a URL-encoded title and a query string 00078 # Title::getLocalURL() is preferred in most cases 00079 # 00080 function wfLocalUrl( $a, $q = '' ) 00081 { 00082 global $wgServer, $wgScript, $wgArticlePath; 00083 00084 $a = str_replace( ' ', '_', $a ); 00085 00086 if ( '' == $a ) { 00087 if( '' == $q ) { 00088 $a = $wgScript; 00089 } else { 00090 $a = "{$wgScript}?{$q}"; 00091 } 00092 } else if ( '' == $q ) { 00093 $a = str_replace( "$1", $a, $wgArticlePath ); 00094 } else if ($wgScript != '' ) { 00095 $a = "{$wgScript}?title={$a}&{$q}"; 00096 } else { //XXX hackish solution for toplevel wikis 00097 $a = "/{$a}?{$q}"; 00098 } 00099 return $a; 00100 } 00101 00102 function wfLocalUrlE( $a, $q = '' ) 00103 { 00104 return wfEscapeHTML( wfLocalUrl( $a, $q ) ); 00105 # die( "Call to obsolete function wfLocalUrlE()" ); 00106 } 00107 00108 function wfFullUrl( $a, $q = '' ) { 00109 wfDebugDieBacktrace( 'Call to obsolete function wfFullUrl(); use Title::getFullURL' ); 00110 } 00111 00112 function wfFullUrlE( $a, $q = '' ) { 00113 wfDebugDieBacktrace( 'Call to obsolete function wfFullUrlE(); use Title::getFullUrlE' ); 00114 00115 } 00116 00117 // orphan function wfThumbUrl( $img ) 00118 //{ 00119 // global $wgUploadPath; 00120 // 00121 // $nt = Title::newFromText( $img ); 00122 // if( !$nt ) return ""; 00123 // 00124 // $name = $nt->getDBkey(); 00125 // $hash = md5( $name ); 00126 // 00127 // $url = "{$wgUploadPath}/thumb/" . $hash{0} . "/" . 00128 // substr( $hash, 0, 2 ) . "/{$name}"; 00129 // return wfUrlencode( $url ); 00130 //} 00131 00132 00133 function wfImageArchiveUrl( $name ) 00134 { 00135 global $wgUploadPath; 00136 00137 $hash = md5( substr( $name, 15) ); 00138 $url = "{$wgUploadPath}/archive/" . $hash{0} . "/" . 00139 substr( $hash, 0, 2 ) . "/{$name}"; 00140 return wfUrlencode($url); 00141 } 00142 00143 function wfUrlencode ( $s ) 00144 { 00145 $s = urlencode( $s ); 00146 $s = preg_replace( '/%3[Aa]/', ':', $s ); 00147 $s = preg_replace( '/%2[Ff]/', '/', $s ); 00148 00149 return $s; 00150 } 00151 00152 function wfUtf8Sequence($codepoint) { 00153 if($codepoint < 0x80) return chr($codepoint); 00154 if($codepoint < 0x800) return chr($codepoint >> 6 & 0x3f | 0xc0) . 00155 chr($codepoint & 0x3f | 0x80); 00156 if($codepoint < 0x10000) return chr($codepoint >> 12 & 0x0f | 0xe0) . 00157 chr($codepoint >> 6 & 0x3f | 0x80) . 00158 chr($codepoint & 0x3f | 0x80); 00159 if($codepoint < 0x100000) return chr($codepoint >> 18 & 0x07 | 0xf0) . # Double-check this 00160 chr($codepoint >> 12 & 0x3f | 0x80) . 00161 chr($codepoint >> 6 & 0x3f | 0x80) . 00162 chr($codepoint & 0x3f | 0x80); 00163 # Doesn't yet handle outside the BMP 00164 return "&#$codepoint;"; 00165 } 00166 00167 # Converts numeric character entities to UTF-8 00168 function wfMungeToUtf8($string) { 00169 global $wgInputEncoding; # This is debatable 00170 #$string = iconv($wgInputEncoding, "UTF-8", $string); 00171 $string = preg_replace ( '/&#([0-9]+);/e', 'wfUtf8Sequence($1)', $string ); 00172 $string = preg_replace ( '/&#x([0-9a-f]+);/ie', 'wfUtf8Sequence(0x$1)', $string ); 00173 # Should also do named entities here 00174 return $string; 00175 } 00176 00177 # Converts a single UTF-8 character into the corresponding HTML character entity 00178 function wfUtf8Entity( $matches ) { 00179 $char = $matches[0]; 00180 # Find the length 00181 $z = ord( $char{0} ); 00182 if ( $z & 0x80 ) { 00183 $length = 0; 00184 while ( $z & 0x80 ) { 00185 $length++; 00186 $z <<= 1; 00187 } 00188 } else { 00189 $length = 1; 00190 } 00191 00192 if ( $length != strlen( $char ) ) { 00193 return ''; 00194 } 00195 if ( $length == 1 ) { 00196 return $char; 00197 } 00198 00199 # Mask off the length-determining bits and shift back to the original location 00200 $z &= 0xff; 00201 $z >>= $length; 00202 00203 # Add in the free bits from subsequent bytes 00204 for ( $i=1; $i<$length; $i++ ) { 00205 $z <<= 6; 00206 $z |= ord( $char{$i} ) & 0x3f; 00207 } 00208 00209 # Make entity 00210 return "&#$z;"; 00211 } 00212 00213 # Converts all multi-byte characters in a UTF-8 string into the appropriate character entity 00214 function wfUtf8ToHTML($string) { 00215 return preg_replace_callback( '/[\\xc0-\\xfd][\\x80-\\xbf]*/', 'wfUtf8Entity', $string ); 00216 } 00217 00218 function wfDebug( $text, $logonly = false ) 00219 { 00220 global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly; 00221 00222 if ( isset( $wgOut ) && $wgDebugComments && !$logonly ) { 00223 $wgOut->debug( $text ); 00224 } 00225 if ( "" != $wgDebugLogFile && !$wgProfileOnly ) { 00226 error_log( $text, 3, $wgDebugLogFile ); 00227 } 00228 } 00229 00230 function logProfilingData() 00231 { 00232 global $wgRequestTime, $wgDebugLogFile; 00233 global $wgProfiling, $wgProfileStack, $wgProfileLimit, $wgUser; 00234 $now = wfTime(); 00235 00236 list( $usec, $sec ) = explode( " ", $wgRequestTime ); 00237 $start = (float)$sec + (float)$usec; 00238 $elapsed = $now - $start; 00239 if ( $wgProfiling ) { 00240 $prof = wfGetProfilingOutput( $start, $elapsed ); 00241 $forward = ''; 00242 if( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) 00243 $forward = ' forwarded for ' . $_SERVER['HTTP_X_FORWARDED_FOR']; 00244 if( !empty( $_SERVER['HTTP_CLIENT_IP'] ) ) 00245 $forward .= ' client IP ' . $_SERVER['HTTP_CLIENT_IP']; 00246 if( !empty( $_SERVER['HTTP_FROM'] ) ) 00247 $forward .= ' from ' . $_SERVER['HTTP_FROM']; 00248 if( $forward ) 00249 $forward = "\t(proxied via {$_SERVER['REMOTE_ADDR']}{$forward})"; 00250 if($wgUser->getId() == 0) 00251 $forward .= ' anon'; 00252 $log = sprintf( "%s\t%04.3f\t%s\n", 00253 gmdate( 'YmdHis' ), $elapsed, 00254 urldecode( $_SERVER['REQUEST_URI'] . $forward ) ); 00255 if ( '' != $wgDebugLogFile ) { 00256 error_log( $log . $prof, 3, $wgDebugLogFile ); 00257 } 00258 } 00259 } 00260 00261 00262 function wfReadOnly() 00263 { 00264 global $wgReadOnlyFile; 00265 00266 if ( "" == $wgReadOnlyFile ) { return false; } 00267 return is_file( $wgReadOnlyFile ); 00268 } 00269 00270 $wgReplacementKeys = array( "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9" ); 00271 00272 # Get a message from anywhere 00273 function wfMsg( $key ) { 00274 $args = func_get_args(); 00275 if ( count( $args ) ) { 00276 array_shift( $args ); 00277 } 00278 return wfMsgReal( $key, $args, true ); 00279 } 00280 00281 # Get a message from the language file 00282 function wfMsgNoDB( $key ) { 00283 $args = func_get_args(); 00284 if ( count( $args ) ) { 00285 array_shift( $args ); 00286 } 00287 return wfMsgReal( $key, $args, false ); 00288 } 00289 00290 # Really get a message 00291 function wfMsgReal( $key, $args, $useDB ) { 00292 global $wgReplacementKeys, $wgMessageCache, $wgLang; 00293 00294 $fname = 'wfMsg'; 00295 wfProfileIn( $fname ); 00296 if ( $wgMessageCache ) { 00297 $message = $wgMessageCache->get( $key, $useDB ); 00298 } elseif ( $wgLang ) { 00299 $message = $wgLang->getMessage( $key ); 00300 } else { 00301 wfDebug( "No language object when getting $key\n" ); 00302 $message = "&lt;$key&gt;"; 00303 } 00304 00305 # Replace arguments 00306 if( count( $args ) ) { 00307 $message = str_replace( $wgReplacementKeys, $args, $message ); 00308 } 00309 wfProfileOut( $fname ); 00310 return $message; 00311 } 00312 00313 function wfCleanFormFields( $fields ) 00314 { 00315 wfDebugDieBacktrace( 'Call to obsolete wfCleanFormFields(). Use wgRequest instead...' ); 00316 } 00317 00318 function wfMungeQuotes( $in ) 00319 { 00320 $out = str_replace( '%', '%25', $in ); 00321 $out = str_replace( "'", '%27', $out ); 00322 $out = str_replace( '"', '%22', $out ); 00323 return $out; 00324 } 00325 00326 function wfDemungeQuotes( $in ) 00327 { 00328 $out = str_replace( '%22', '"', $in ); 00329 $out = str_replace( '%27', "'", $out ); 00330 $out = str_replace( '%25', '%', $out ); 00331 return $out; 00332 } 00333 00334 function wfCleanQueryVar( $var ) 00335 { 00336 wfDebugDieBacktrace( 'Call to obsolete function wfCleanQueryVar(); use wgRequest instead' ); 00337 } 00338 00339 function wfSearch( $s ) 00340 { 00341 $se = new SearchEngine( $s ); 00342 $se->showResults(); 00343 } 00344 00345 function wfGo( $s ) 00346 { # pick the nearest match 00347 $se = new SearchEngine( $s ); 00348 $se->goResult(); 00349 } 00350 00351 # Just like exit() but makes a note of it. 00352 function wfAbruptExit(){ 00353 static $called = false; 00354 if ( $called ){ 00355 exit(); 00356 } 00357 $called = true; 00358 00359 if( function_exists( 'debug_backtrace' ) ){ // PHP >= 4.3 00360 $bt = debug_backtrace(); 00361 for($i = 0; $i < count($bt) ; $i++){ 00362 $file = $bt[$i]['file']; 00363 $line = $bt[$i]['line']; 00364 wfDebug("WARNING: Abrupt exit in $file at line $line\n"); 00365 } 00366 } else { 00367 wfDebug('WARNING: Abrupt exit\n'); 00368 } 00369 exit(); 00370 } 00371 00372 function wfDebugDieBacktrace( $msg = '' ) { 00373 if ( function_exists( 'debug_backtrace' ) ) { 00374 $msg .= "\n<p>Backtrace:</p>\n<ul>\n"; 00375 $backtrace = debug_backtrace(); 00376 foreach( $backtrace as $call ) { 00377 $f = explode( DIRECTORY_SEPARATOR, $call['file'] ); 00378 $file = $f[count($f)-1]; 00379 $msg .= '<li>' . $file . " line " . $call['line'] . ', in '; 00380 if( !empty( $call['class'] ) ) $msg .= $call['class'] . '::'; 00381 $msg .= $call['function'] . "()</li>\n"; 00382 } 00383 } 00384 die( $msg ); 00385 } 00386 00387 function wfNumberOfArticles() 00388 { 00389 global $wgNumberOfArticles; 00390 00391 wfLoadSiteStats(); 00392 return $wgNumberOfArticles; 00393 } 00394 00395 /* private */ function wfLoadSiteStats() 00396 { 00397 global $wgNumberOfArticles, $wgTotalViews, $wgTotalEdits; 00398 if ( -1 != $wgNumberOfArticles ) return; 00399 00400 $sql = 'SELECT ss_total_views, ss_total_edits, ss_good_articles ' . 00401 'FROM site_stats WHERE ss_row_id=1'; 00402 $res = wfQuery( $sql, DB_READ, 'wfLoadSiteStats' ); 00403 00404 if ( 0 == wfNumRows( $res ) ) { return; } 00405 else { 00406 $s = wfFetchObject( $res ); 00407 $wgTotalViews = $s->ss_total_views; 00408 $wgTotalEdits = $s->ss_total_edits; 00409 $wgNumberOfArticles = $s->ss_good_articles; 00410 } 00411 } 00412 00413 function wfEscapeHTML( $in ) 00414 { 00415 return str_replace( 00416 array( '&', '"', '>', '<' ), 00417 array( '&amp;', '&quot;', '&gt;', '&lt;' ), 00418 $in ); 00419 } 00420 00421 function wfEscapeHTMLTagsOnly( $in ) { 00422 return str_replace( 00423 array( '"', '>', '<' ), 00424 array( '&quot;', '&gt;', '&lt;' ), 00425 $in ); 00426 } 00427 00428 function wfUnescapeHTML( $in ) 00429 { 00430 $in = str_replace( '&lt;', '<', $in ); 00431 $in = str_replace( '&gt;', '>', $in ); 00432 $in = str_replace( '&quot;', '"', $in ); 00433 $in = str_replace( '&amp;', '&', $in ); 00434 return $in; 00435 } 00436 00437 function wfImageDir( $fname ) 00438 { 00439 global $wgUploadDirectory; 00440 00441 $hash = md5( $fname ); 00442 $oldumask = umask(0); 00443 $dest = $wgUploadDirectory . '/' . $hash{0}; 00444 if ( ! is_dir( $dest ) ) { mkdir( $dest, 0777 ); } 00445 $dest .= '/' . substr( $hash, 0, 2 ); 00446 if ( ! is_dir( $dest ) ) { mkdir( $dest, 0777 ); } 00447 00448 umask( $oldumask ); 00449 return $dest; 00450 } 00451 00452 function wfImageThumbDir( $fname , $subdir='thumb') 00453 { 00454 return wfImageArchiveDir( $fname, $subdir ); 00455 } 00456 00457 function wfImageArchiveDir( $fname , $subdir='archive') 00458 { 00459 global $wgUploadDirectory; 00460 00461 $hash = md5( $fname ); 00462 $oldumask = umask(0); 00463 00464 # Suppress warning messages here; if the file itself can't 00465 # be written we'll worry about it then. 00466 $archive = "{$wgUploadDirectory}/{$subdir}"; 00467 if ( ! is_dir( $archive ) ) { @mkdir( $archive, 0777 ); } 00468 $archive .= '/' . $hash{0}; 00469 if ( ! is_dir( $archive ) ) { @mkdir( $archive, 0777 ); } 00470 $archive .= '/' . substr( $hash, 0, 2 ); 00471 if ( ! is_dir( $archive ) ) { @mkdir( $archive, 0777 ); } 00472 00473 umask( $oldumask ); 00474 return $archive; 00475 } 00476 00477 function wfRecordUpload( $name, $oldver, $size, $desc, $copyStatus = "", $source = "" ) 00478 { 00479 global $wgUser, $wgLang, $wgTitle, $wgOut, $wgDeferredUpdateList; 00480 global $wgUseCopyrightUpload; 00481 00482 $fname = 'wfRecordUpload'; 00483 00484 $sql = 'SELECT img_name,img_size,img_timestamp,img_description,img_user,' . 00485 "img_user_text FROM image WHERE img_name='" . wfStrencode( $name ) . "'"; 00486 $res = wfQuery( $sql, DB_READ, $fname ); 00487 00488 $now = wfTimestampNow(); 00489 $won = wfInvertTimestamp( $now ); 00490 $size = IntVal( $size ); 00491 00492 if ( $wgUseCopyrightUpload ) 00493 { 00494 $textdesc = '== ' . wfMsg ( 'filedesc' ) . " ==\n" . $desc . "\n" . 00495 '== ' . wfMsg ( 'filestatus' ) . " ==\n" . $copyStatus . "\n" . 00496 '== ' . wfMsg ( 'filesource' ) . " ==\n" . $source ; 00497 } 00498 else $textdesc = $desc ; 00499 00500 $now = wfTimestampNow(); 00501 $won = wfInvertTimestamp( $now ); 00502 00503 if ( 0 == wfNumRows( $res ) ) { 00504 $sql = 'INSERT INTO image (img_name,img_size,img_timestamp,' . 00505 "img_description,img_user,img_user_text) VALUES ('" . 00506 wfStrencode( $name ) . "',$size,'{$now}','" . 00507 wfStrencode( $desc ) . "', '" . $wgUser->getID() . 00508 "', '" . wfStrencode( $wgUser->getName() ) . "')"; 00509 wfQuery( $sql, DB_WRITE, $fname ); 00510 00511 $sql = 'SELECT cur_id,cur_text FROM cur WHERE cur_namespace=' . 00512 Namespace::getImage() . " AND cur_title='" . 00513 wfStrencode( $name ) . "'"; 00514 $res = wfQuery( $sql, DB_READ, $fname ); 00515 if ( 0 == wfNumRows( $res ) ) { 00516 $common = 00517 Namespace::getImage() . ",'" . 00518 wfStrencode( $name ) . "','" . 00519 wfStrencode( $desc ) . "','" . $wgUser->getID() . "','" . 00520 wfStrencode( $wgUser->getName() ) . "','" . $now . 00521 "',1"; 00522 $sql = 'INSERT INTO cur (cur_namespace,cur_title,' . 00523 'cur_comment,cur_user,cur_user_text,cur_timestamp,cur_is_new,' . 00524 'cur_text,inverse_timestamp,cur_touched) VALUES (' . 00525 $common . 00526 ",'" . wfStrencode( $textdesc ) . "','{$won}','{$now}')"; 00527 wfQuery( $sql, DB_WRITE, $fname ); 00528 $id = wfInsertId() or 0; # We should throw an error instead 00529 00530 $titleObj = Title::makeTitle( NS_IMAGE, $name ); 00531 RecentChange::notifyNew( $now, $titleObj, 0, $wgUser, $desc ); 00532 00533 $u = new SearchUpdate( $id, $name, $desc ); 00534 $u->doUpdate(); 00535 } 00536 } else { 00537 $s = wfFetchObject( $res ); 00538 00539 $sql = 'INSERT INTO oldimage (oi_name,oi_archive_name,oi_size,' . 00540 "oi_timestamp,oi_description,oi_user,oi_user_text) VALUES ('" . 00541 wfStrencode( $s->img_name ) . "','" . 00542 wfStrencode( $oldver ) . 00543 "',{$s->img_size},'{$s->img_timestamp}','" . 00544 wfStrencode( $s->img_description ) . "','" . 00545 wfStrencode( $s->img_user ) . "','" . 00546 wfStrencode( $s->img_user_text) . "')"; 00547 wfQuery( $sql, DB_WRITE, $fname ); 00548 00549 $sql = "UPDATE image SET img_size={$size}," . 00550 "img_timestamp='" . wfTimestampNow() . "',img_user='" . 00551 $wgUser->getID() . "',img_user_text='" . 00552 wfStrencode( $wgUser->getName() ) . "', img_description='" . 00553 wfStrencode( $desc ) . "' WHERE img_name='" . 00554 wfStrencode( $name ) . "'"; 00555 wfQuery( $sql, DB_WRITE, $fname ); 00556 00557 $sql = "UPDATE cur SET cur_touched='{$now}' WHERE cur_namespace=" . 00558 Namespace::getImage() . " AND cur_title='" . 00559 wfStrencode( $name ) . "'"; 00560 wfQuery( $sql, DB_WRITE, $fname ); 00561 } 00562 00563 $log = new LogPage( wfMsg( 'uploadlogpage' ), wfMsg( 'uploadlogpagetext' ) ); 00564 $da = wfMsg( 'uploadedimage', '[[:' . $wgLang->getNsText( 00565 Namespace::getImage() ) . ":{$name}|{$name}]]" ); 00566 $ta = wfMsg( 'uploadedimage', $name ); 00567 $log->addEntry( $da, $desc, $ta ); 00568 } 00569 00570 00571 /* Some generic result counters, pulled out of SearchEngine */ 00572 00573 function wfShowingResults( $offset, $limit ) 00574 { 00575 global $wgLang; 00576 return wfMsg( 'showingresults', $wgLang->formatNum( $limit ), $wgLang->formatNum( $offset+1 ) ); 00577 } 00578 00579 function wfShowingResultsNum( $offset, $limit, $num ) 00580 { 00581 global $wgLang; 00582 return wfMsg( 'showingresultsnum', $wgLang->formatNum( $limit ), $wgLang->formatNum( $offset+1 ), $wgLang->formatNum( $num ) ); 00583 } 00584 00585 function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) 00586 { 00587 global $wgUser, $wgLang; 00588 $fmtLimit = $wgLang->formatNum( $limit ); 00589 $prev = wfMsg( 'prevn', $fmtLimit ); 00590 $next = wfMsg( 'nextn', $fmtLimit ); 00591 $link = wfUrlencode( $link ); 00592 00593 $sk = $wgUser->getSkin(); 00594 if ( 0 != $offset ) { 00595 $po = $offset - $limit; 00596 if ( $po < 0 ) { $po = 0; } 00597 $q = "limit={$limit}&offset={$po}"; 00598 if ( '' != $query ) { $q .= "&{$query}"; } 00599 $plink = '<a href="' . wfLocalUrlE( $link, $q ) . "\">{$prev}</a>"; 00600 } else { $plink = $prev; } 00601 00602 $no = $offset + $limit; 00603 $q = "limit={$limit}&offset={$no}"; 00604 if ( "" != $query ) { $q .= "&{$query}"; } 00605 00606 if ( $atend ) { 00607 $nlink = $next; 00608 } else { 00609 $nlink = '<a href="' . wfLocalUrlE( $link, $q ) . "\">{$next}</a>"; 00610 } 00611 $nums = wfNumLink( $offset, 20, $link , $query ) . ' | ' . 00612 wfNumLink( $offset, 50, $link, $query ) . ' | ' . 00613 wfNumLink( $offset, 100, $link, $query ) . ' | ' . 00614 wfNumLink( $offset, 250, $link, $query ) . ' | ' . 00615 wfNumLink( $offset, 500, $link, $query ); 00616 00617 return wfMsg( 'viewprevnext', $plink, $nlink, $nums ); 00618 } 00619 00620 function wfNumLink( $offset, $limit, $link, $query = '' ) 00621 { 00622 global $wgUser, $wgLang; 00623 if ( '' == $query ) { $q = ''; } 00624 else { $q = "{$query}&"; } 00625 $q .= "limit={$limit}&offset={$offset}"; 00626 00627 $fmtLimit = $wgLang->formatNum( $limit ); 00628 $s = '<a href="' . wfLocalUrlE( $link, $q ) . "\">{$fmtLimit}</a>"; 00629 return $s; 00630 } 00631 00632 function wfClientAcceptsGzip() { 00633 global $wgUseGzip; 00634 if( $wgUseGzip ) { 00635 # FIXME: we may want to blacklist some broken browsers 00636 if( preg_match( 00637 '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/', 00638 $_SERVER['HTTP_ACCEPT_ENCODING'], 00639 $m ) ) { 00640 if( ( $m[1] == 'q' ) && ( $m[2] == 0 ) ) return false; 00641 wfDebug( " accepts gzip\n" ); 00642 return true; 00643 } 00644 } 00645 return false; 00646 } 00647 00648 # Yay, more global functions! 00649 function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) { 00650 global $wgUser, $wgRequest; 00651 00652 $limit = $wgRequest->getInt( 'limit', 0 ); 00653 if( $limit < 0 ) $limit = 0; 00654 if( ( $limit == 0 ) && ( $optionname != '' ) ) { 00655 $limit = (int)$wgUser->getOption( $optionname ); 00656 } 00657 if( $limit <= 0 ) $limit = $deflimit; 00658 if( $limit > 5000 ) $limit = 5000; # We have *some* limits... 00659 00660 $offset = $wgRequest->getInt( 'offset', 0 ); 00661 if( $offset < 0 ) $offset = 0; 00662 if( $offset > 65000 ) $offset = 65000; # do we need a max? what? 00663 00664 return array( $limit, $offset ); 00665 } 00666 00667 # Escapes the given text so that it may be output using addWikiText() 00668 # without any linking, formatting, etc. making its way through. This 00669 # is achieved by substituting certain characters with HTML entities. 00670 # As required by the callers, <nowiki> is not used. It currently does 00671 # not filter out characters which have special meaning only at the 00672 # start of a line, such as "*". 00673 function wfEscapeWikiText( $text ) 00674 { 00675 $text = str_replace( 00676 array( '[', '|', "'", 'ISBN ' , '://' , "\n=" ), 00677 array( '&#91;', '&#124;', '&#39;', 'ISBN&#32;', '&#58;//' , "\n&#61;" ), 00678 htmlspecialchars($text) ); 00679 return $text; 00680 } 00681 00682 function wfQuotedPrintable( $string, $charset = '' ) 00683 { 00684 # Probably incomplete; see RFC 2045 00685 if( empty( $charset ) ) { 00686 global $wgInputEncoding; 00687 $charset = $wgInputEncoding; 00688 } 00689 $charset = strtoupper( $charset ); 00690 $charset = str_replace( 'ISO-8859', 'ISO8859', $charset ); // ? 00691 00692 $illegal = '\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\xff='; 00693 $replace = $illegal . '\t ?_'; 00694 if( !preg_match( "/[$illegal]/", $string ) ) return $string; 00695 $out = "=?$charset?Q?"; 00696 $out .= preg_replace( "/([$replace])/e", 'sprintf("=%02X",ord("$1"))', $string ); 00697 $out .= '?='; 00698 return $out; 00699 } 00700 00701 function wfTime(){ 00702 $st = explode( ' ', microtime() ); 00703 return (float)$st[0] + (float)$st[1]; 00704 } 00705 00706 # Changes the first character to an HTML entity 00707 function wfHtmlEscapeFirst( $text ) { 00708 $ord = ord($text); 00709 $newText = substr($text, 1); 00710 return "&#$ord;$newText"; 00711 } 00712 00713 # Sets dest to source and returns the original value of dest 00714 function wfSetVar( &$dest, $source ) 00715 { 00716 $temp = $dest; 00717 $dest = $source; 00718 return $temp; 00719 } 00720 00721 # Sets dest to a reference to source and returns the original dest 00722 # Pity that doesn't work in PHP 00723 function &wfSetRef( &$dest, &$source ) 00724 { 00725 die( "You can't rebind a variable in the caller's scope" ); 00726 } 00727 00728 # This function takes two arrays as input, and returns a CGI-style string, e.g. 00729 # "days=7&limit=100". Options in the first array override options in the second. 00730 # Options set to "" will not be output. 00731 function wfArrayToCGI( $array1, $array2 = NULL ) 00732 { 00733 if ( !is_null( $array2 ) ) { 00734 $array1 = $array1 + $array2; 00735 } 00736 00737 $cgi = ''; 00738 foreach ( $array1 as $key => $value ) { 00739 if ( '' !== $value ) { 00740 if ( '' != $cgi ) { 00741 $cgi .= '&'; 00742 } 00743 $cgi .= "{$key}={$value}"; 00744 } 00745 } 00746 return $cgi; 00747 } 00748 00749 # This is obsolete, use SquidUpdate::purge() 00750 function wfPurgeSquidServers ($urlArr) { 00751 SquidUpdate::purge( $urlArr ); 00752 } 00753 00754 # Windows-compatible version of escapeshellarg() 00755 function wfEscapeShellArg( ) 00756 { 00757 $args = func_get_args(); 00758 $first = true; 00759 $retVal = ''; 00760 foreach ( $args as $arg ) { 00761 if ( !$first ) { 00762 $retVal .= ' '; 00763 } else { 00764 $first = false; 00765 } 00766 00767 if ( wfIsWindows() ) { 00768 $retVal .= '"' . str_replace( '"','\"', $arg ) . '"'; 00769 } else { 00770 $retVal .= escapeshellarg( $arg ); 00771 } 00772 } 00773 return $retVal; 00774 } 00775 00776 # wfMerge attempts to merge differences between three texts. 00777 # Returns true for a clean merge and false for failure or a conflict. 00778 00779 function wfMerge( $old, $mine, $yours, &$result ){ 00780 global $wgDiff3; 00781 00782 # This check may also protect against code injection in 00783 # case of broken installations. 00784 if(! file_exists( $wgDiff3 ) ){ 00785 return false; 00786 } 00787 00788 # Make temporary files 00789 $td = '/tmp/'; 00790 $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' ); 00791 $mytextFile = fopen( $mytextName = tempnam( $td, 'merge-mine-' ), 'w' ); 00792 $yourtextFile = fopen( $yourtextName = tempnam( $td, 'merge-your-' ), 'w' ); 00793 00794 fwrite( $oldtextFile, $old ); fclose( $oldtextFile ); 00795 fwrite( $mytextFile, $mine ); fclose( $mytextFile ); 00796 fwrite( $yourtextFile, $yours ); fclose( $yourtextFile ); 00797 00798 # Check for a conflict 00799 $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a --overlap-only ' . 00800 wfEscapeShellArg( $mytextName ) . ' ' . 00801 wfEscapeShellArg( $oldtextName ) . ' ' . 00802 wfEscapeShellArg( $yourtextName ); 00803 $handle = popen( $cmd, 'r' ); 00804 00805 if( fgets( $handle ) ){ 00806 $conflict = true; 00807 } else { 00808 $conflict = false; 00809 } 00810 pclose( $handle ); 00811 00812 # Merge differences 00813 $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' . 00814 wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName ); 00815 $handle = popen( $cmd, 'r' ); 00816 $result = ''; 00817 do { 00818 $data = fread( $handle, 8192 ); 00819 if ( strlen( $data ) == 0 ) { 00820 break; 00821 } 00822 $result .= $data; 00823 } while ( true ); 00824 pclose( $handle ); 00825 unlink( $mytextName ); unlink( $oldtextName ); unlink( $yourtextName ); 00826 return ! $conflict; 00827 } 00828 00829 function wfVarDump( $var ) 00830 { 00831 global $wgOut; 00832 $s = str_replace("\n","<br>\n", var_export( $var, true ) . "\n"); 00833 if ( headers_sent() || !@is_object( $wgOut ) ) { 00834 print $s; 00835 } else { 00836 $wgOut->addHTML( $s ); 00837 } 00838 } 00839 00840 # Provide a simple HTTP error. 00841 function wfHttpError( $code, $label, $desc ) { 00842 global $wgOut; 00843 $wgOut->disable(); 00844 header( "HTTP/1.0 $code $label" ); 00845 header( "Status: $code $label" ); 00846 $wgOut->sendCacheControl(); 00847 00848 # Don't send content if it's a HEAD request. 00849 if( $_SERVER['REQUEST_METHOD'] == 'HEAD' ) { 00850 header( 'Content-type: text/plain' ); 00851 print "$desc\n"; 00852 } 00853 } 00854 00855 # Converts an Accept-* header into an array mapping string values to quality factors 00856 function wfAcceptToPrefs( $accept, $def = '*/*' ) { 00857 # No arg means accept anything (per HTTP spec) 00858 if( !$accept ) { 00859 return array( $def => 1 ); 00860 } 00861 00862 $prefs = array(); 00863 00864 $parts = explode( ',', $accept ); 00865 00866 foreach( $parts as $part ) { 00867 # FIXME: doesn't deal with params like 'text/html; level=1' 00868 @list( $value, $qpart ) = explode( ';', $part ); 00869 if( !isset( $qpart ) ) { 00870 $prefs[$value] = 1; 00871 } elseif( preg_match( '/q\s*=\s*(\d*\.\d+)/', $qpart, $match ) ) { 00872 $prefs[$value] = $match[1]; 00873 } 00874 } 00875 00876 return $prefs; 00877 } 00878 00879 /* private */ function mimeTypeMatch( $type, $avail ) { 00880 if( array_key_exists($type, $avail) ) { 00881 return $type; 00882 } else { 00883 $parts = explode( '/', $type ); 00884 if( array_key_exists( $parts[0] . '/*', $avail ) ) { 00885 return $parts[0] . '/*'; 00886 } elseif( array_key_exists( '*/*', $avail ) ) { 00887 return '*/*'; 00888 } else { 00889 return NULL; 00890 } 00891 } 00892 } 00893 00894 # FIXME: doesn't handle params like 'text/plain; charset=UTF-8' 00895 # XXX: generalize to negotiate other stuff 00896 function wfNegotiateType( $cprefs, $sprefs ) { 00897 $combine = array(); 00898 00899 foreach( array_keys($sprefs) as $type ) { 00900 $parts = explode( '/', $type ); 00901 if( $parts[1] != '*' ) { 00902 $ckey = mimeTypeMatch( $type, $cprefs ); 00903 if( $ckey ) { 00904 $combine[$type] = $sprefs[$type] * $cprefs[$ckey]; 00905 } 00906 } 00907 } 00908 00909 foreach( array_keys( $cprefs ) as $type ) { 00910 $parts = explode( '/', $type ); 00911 if( $parts[1] != '*' && !array_key_exists( $type, $sprefs ) ) { 00912 $skey = mimeTypeMatch( $type, $sprefs ); 00913 if( $skey ) { 00914 $combine[$type] = $sprefs[$skey] * $cprefs[$type]; 00915 } 00916 } 00917 } 00918 00919 $bestq = 0; 00920 $besttype = NULL; 00921 00922 foreach( array_keys( $combine ) as $type ) { 00923 if( $combine[$type] > $bestq ) { 00924 $besttype = $type; 00925 $bestq = $combine[$type]; 00926 } 00927 } 00928 00929 return $besttype; 00930 } 00931 00932 # Array lookup 00933 # Returns an array where the values in the first array are replaced by the 00934 # values in the second array with the corresponding keys 00935 function wfArrayLookup( $a, $b ) 00936 { 00937 return array_flip( array_intersect( array_flip( $a ), array_keys( $b ) ) ); 00938 } 00939 00940 # Since Windows is so different to any of the other popular OSes, it seems appropriate 00941 # to have a simple way to test for its presence 00942 function wfIsWindows() { 00943 if (substr(php_uname(), 0, 7) == 'Windows') { 00944 return true; 00945 } else { 00946 return false; 00947 } 00948 } 00949 00950 ?>

Generated on Tue Jun 29 23:40:03 2004 for Mediawiki by doxygen 1.3.7