Fix for compatibility with short_open_tag = Off
[lhc/web/wiklou.git] / includes / GlobalFunctions.php
index 0239a43..c9cbe1b 100644 (file)
@@ -1,4 +1,4 @@
-<?
+<?php
 # Global functions used everywhere
 
 $wgNumberOfArticles = -1; # Unset
@@ -64,8 +64,10 @@ function wfLocalUrl( $a, $q = "" )
                }       
        } else if ( "" == $q ) {
                $a = str_replace( "$1", $a, $wgArticlePath );
-       } else {
+       } else if ($wgScript != '' ) {
                $a = "{$wgScript}?title={$a}&{$q}";     
+       } else { //XXX ugly hack for toplevel wikis
+               $a = "/{$a}&{$q}";      
        }
        return $a;
 }
@@ -99,6 +101,47 @@ function wfImageUrl( $img )
        return wfUrlencode( $url );
 }
 
+function wfImagePath( $img )
+{
+       global $wgUploadDirectory;
+
+       $nt = Title::newFromText( $img );
+       if( !$nt ) return "";
+
+       $name = $nt->getDBkey();
+       $hash = md5( $name );
+
+       $path = "{$wgUploadDirectory}/" . $hash{0} . "/" .
+         substr( $hash, 0, 2 ) . "/{$name}";
+       return $path;
+}
+
+function wfThumbUrl( $img )
+{
+       global $wgUploadPath;
+
+       $nt = Title::newFromText( $img );
+       if( !$nt ) return "";
+
+       $name = $nt->getDBkey();
+       $hash = md5( $name );
+
+       $url = "{$wgUploadPath}/thumb/" . $hash{0} . "/" .
+         substr( $hash, 0, 2 ) . "/{$name}";
+       return wfUrlencode( $url );
+}
+
+
+function wfImageThumbUrl( $name, $subdir="thumb" )
+{
+       global $wgUploadPath;
+
+       $hash = md5( $name );
+       $url = "{$wgUploadPath}/{$subdir}/" . $hash{0} . "/" .
+         substr( $hash, 0, 2 ) . "/{$name}";
+       return wfUrlencode($url);
+}
+
 function wfImageArchiveUrl( $name )
 {
        global $wgUploadPath;
@@ -106,7 +149,7 @@ function wfImageArchiveUrl( $name )
        $hash = md5( substr( $name, 15) );
        $url = "{$wgUploadPath}/archive/" . $hash{0} . "/" .
          substr( $hash, 0, 2 ) . "/{$name}";
-       return $url;
+       return wfUrlencode($url);
 }
 
 function wfUrlencode ( $s )
@@ -165,6 +208,7 @@ function logProfilingData()
        $elapsed = $now - $start;
        if ( "" != $wgDebugLogFile ) {
                $prof = wfGetProfilingOutput( $start, $elapsed );
+               $forward = "";
                if( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) )
                        $forward = " forwarded for " . $_SERVER['HTTP_X_FORWARDED_FOR'];
                if( !empty( $_SERVER['HTTP_CLIENT_IP'] ) )
@@ -213,85 +257,24 @@ function wfMsgNoDB( $key ) {
 
 # Really get a message
 function wfMsgReal( $key, $args, $useDB ) {
-       global $wgLang, $wgReplacementKeys, $wgMemc, $wgDBname;
-       global $wgUseDatabaseMessages, $wgUseMemCached, $wgOut;
-       global $wgAllMessagesEn, $wgLanguageCode;
+       global $wgReplacementKeys, $wgMessageCache, $wgLang;
 
        $fname = "wfMsg";
        wfProfileIn( $fname );
-       
-       static $messageCache = false;
-       $memcKey = "$wgDBname:messages";
-       $fname = "wfMsg";
-       $message = false;
-
-       # newFromText is too slow!
-       $title = ucfirst( $key );
-       if ( $messageCache ) {
-               $message = $messageCache[$title];
-       } elseif ( !$wgUseDatabaseMessages || !$useDB ) {
+       if ( $wgMessageCache ) {
+               $message = $wgMessageCache->get( $key, $useDB );
+       } elseif ( $wgLang ) {
                $message = $wgLang->getMessage( $key );
+       } else {
+               wfDebug( "No language object when getting $key\n" );
+               $message = "&lt;$key&gt;";
        }
 
-       if ( !$message && $wgUseMemCached ) {
-               # Try memcached
-               if ( !$messageCache ) {
-                       $messageCache = $wgMemc->get( $memcKey );
-               }
-               
-               # If there's nothing in memcached, load all the messages from the database
-               # This should only happen on server reset -- ordinary changes should update
-               # memcached in editUpdates()
-               if ( !$messageCache ) {
-                       # Other threads don't need to load the messages if another thread is doing it.
-                       $wgMemc->set( $memcKey, "loading", time() + 60 );
-                       $messageCache = wfLoadAllMessages();
-                       # Save in memcached
-                       $wgMemc->set( $memcKey, $messageCache, time() + 3600 );
-                       
-                       
-               }
-               if ( is_array( $messageCache ) && array_key_exists( $title, $messageCache ) ) {
-                       $message = $messageCache[$title];
-               } elseif ( $messageCache == "loading" ) {
-                       $messageCache = false;
-               }
-       }
-
-       # If there was no MemCached, load each message from the DB individually
-       if ( !$message ) {
-               if ( $useDB ) {
-                       $sql = "SELECT cur_text FROM cur WHERE cur_namespace=" . NS_MEDIAWIKI . 
-                               " AND cur_title='$title'";
-                       $res = wfQuery( $sql, DB_READ, $fname );
-
-                       if ( wfNumRows( $res ) ) {
-                               $obj = wfFetchObject( $res );
-                               $message = $obj->cur_text;
-                               wfFreeResult( $res );
-                       }
-               }
-       }
-
-       # Try the array in $wgLang
-       if ( !$message ) {
-               $message = $wgLang->getMessage( $key );
-       } 
-
-       # Try the English array
-       if ( !$message && $wgLanguageCode != "en" ) {
-               $message = Language::getMessage( $key );
-       }
-       
        # Replace arguments
        if( count( $args ) ) {
                $message = str_replace( $wgReplacementKeys, $args, $message );
        }
        wfProfileOut( $fname );
-       if ( !$message ) {
-               # Failed, message does not exist
-               return "&lt;$key&gt;";
-       }
        return $message;
 }
 
@@ -364,7 +347,7 @@ function wfSpecialPage()
        $sysopSP = $wgLang->getSysopSpecialPages();
        $devSP = $wgLang->getDeveloperSpecialPages();
 
-       $wgOut->setArticleFlag( false );
+       $wgOut->setArticleRelated( false );
        $wgOut->setRobotpolicy( "noindex,follow" );
 
        $par = NULL;
@@ -403,22 +386,23 @@ function wfGo( $s )
        $se->goResult();
 }
 
-/* private */ $wgAbruptExitCalled = false;
-
 # Just like exit() but makes a note of it.
 function wfAbruptExit(){
-       // Safety to avoid infinite recursion in case of (unlikely) bugs somewhere
-       global $wgAbruptExitCalled;
-       if ( $wgAbruptExitCalled ){
+       static $called = false;
+       if ( $called ){
                exit();
        }
-       $wgAbruptExitCalled = true;
-
-       $bt = debug_backtrace();
-       for($i = 0; $i < count($bt) ; $i++){
-               $file = $bt[$i]["file"];
-               $line = $bt[$i]["line"];
-               wfDebug("WARNING: Abrupt exit in $file at line $line\n");
+       $called = true;
+
+       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"];
+                       wfDebug("WARNING: Abrupt exit in $file at line $line\n");
+               }
+       } else { 
+               wfDebug("WARNING: Abrupt exit\n");
        }
        exit();
 }
@@ -488,13 +472,18 @@ function wfImageDir( $fname )
        return $dest;
 }
 
-function wfImageArchiveDir( $fname )
+function wfImageThumbDir( $fname , $subdir="thumb")
+{
+       return wfImageArchiveDir( $fname, $subdir );
+}
+
+function wfImageArchiveDir( $fname , $subdir="archive")
 {
        global $wgUploadDirectory;
 
        $hash = md5( $fname );
        $oldumask = umask(0);
-       $archive = "{$wgUploadDirectory}/archive";
+       $archive = "{$wgUploadDirectory}/{$subdir}";
        if ( ! is_dir( $archive ) ) { mkdir( $archive, 0777 ); }
        $archive .= "/" . $hash{0};
        if ( ! is_dir( $archive ) ) { mkdir( $archive, 0777 ); }
@@ -611,7 +600,7 @@ function wfShowingResultsNum( $offset, $limit, $num )
        return wfMsg( "showingresultsnum", $limit, $offset+1, $num );
 }
 
-function wfViewPrevNext( $offset, $limit, $link, $query = "" )
+function wfViewPrevNext( $offset, $limit, $link, $query = "", $atend = false )
 {
        global $wgUser;
        $prev = wfMsg( "prevn", $limit );
@@ -630,7 +619,11 @@ function wfViewPrevNext( $offset, $limit, $link, $query = "" )
        $q = "limit={$limit}&offset={$no}";
        if ( "" != $query ) { $q .= "&{$query}"; }
 
-       $nlink = "<a href=\"" . wfLocalUrlE( $link, $q ) . "\">{$next}</a>";
+       if ( $atend ) {
+               $nlink = $next;
+       } else {
+               $nlink = "<a href=\"" . wfLocalUrlE( $link, $q ) . "\">{$next}</a>";
+       }
        $nums = wfNumLink( $offset, 20, $link , $query ) . " | " .
          wfNumLink( $offset, 50, $link, $query ) . " | " .
          wfNumLink( $offset, 100, $link, $query ) . " | " .
@@ -696,26 +689,12 @@ function wfCheckLimits( $deflimit = 50, $optionname = "rclimit" ) {
 function wfEscapeWikiText( $text )
 {
        $text = str_replace( 
-               array( '[',     "'",     'ISBN '    , '://'     , "\n=" ),
-               array( '&#91;', '&#39;', 'ISBN&#32;', '&#58;//' , "\n&#61;" ),
+               array( '[',     '|',      "'",     'ISBN '    , '://'     , "\n=" ),
+               array( '&#91;', '&#124;', '&#39;', 'ISBN&#32;', '&#58;//' , "\n&#61;" ),
                htmlspecialchars($text) );
        return $text;
 }
 
-# Loads the entire MediaWiki namespace, returns the array
-function wfLoadAllMessages()
-{
-       $sql = "SELECT cur_title,cur_text FROM cur WHERE cur_namespace=" . NS_MEDIAWIKI;
-       $res = wfQuery( $sql, DB_READ, $fname );
-       
-       $messages = array();
-       for ( $row = wfFetchObject( $res ); $row; $row = wfFetchObject( $res ) ) {
-               $messages[$row->cur_title] = $row->cur_text;
-       }
-       wfFreeResult( $res );
-       return $messages;
-}
-
 function wfQuotedPrintable( $string, $charset = "" ) 
 {
        # Probably incomplete; see RFC 2045
@@ -735,5 +714,125 @@ function wfQuotedPrintable( $string, $charset = "" )
        return $out;
 }
 
+# Changes the first character to an HTML entity
+function wfHtmlEscapeFirst( $text ) {
+       $ord = ord($text);
+       $newText = substr($text, 1);
+       return "&#$ord;$newText";
+}
+
+function wfSetVar( &$dest, $source )
+{
+       $temp = $dest;
+       $dest = $source;
+       return $temp;
+}
+
+function &wfSetRef( &$dest, $source )
+{
+       $temp =& $dest;
+       $dest =& $source;
+       return $temp;
+}
+
+# This function takes two arrays as input, and returns a CGI-style string, e.g.
+# "days=7&limit=100". Options in the first array override options in the second.
+# Options set to "" will not be output.
+function wfArrayToCGI( $array1, $array2 = NULL ) 
+{
+       if ( !is_null( $array2 ) ) {
+               $array1 = $array1 + $array2;
+       }
 
+       $cgi = "";
+       foreach ( $array1 as $key => $value ) {
+               if ( "" !== $value ) {
+                       if ( "" != $cgi ) {
+                               $cgi .= "&";
+                       }
+                       $cgi .= "{$key}={$value}";
+               }
+       }
+       return $cgi;
+}
+
+/* Purges a list of Squids defined in $wgSquidServers.
+$urlArr should contain the full URLs to purge as values 
+(example: $urlArr[] = 'http://my.host/something')
+XXX report broken Squids per mail or log */
+
+function wfPurgeSquidServers ($urlArr) {
+    global  $wgSquidServers;
+    $maxsocketspersquid = 8; //  socket cap per Squid
+    $urlspersocket = 400; // 400 seems to be a good tradeoff, opening a socket takes a while
+    $sockspersq =  ceil(count($urlArr) / $urlspersocket );
+    if ($sockspersq == 1) {
+       /* the most common case */
+        $urlspersocket = count($urlArr);
+    } else if ($sockspersq > $maxsocketspersquid ) {
+       $urlspersocket = ceil(count($urlArr) / $maxsocketspersquid);
+       $sockspersq = $maxsocketspersquid;
+    }
+    $totalsockets = count($wgSquidServers) * $sockspersq;
+    $sockets = Array();
+    
+    /* this sets up the sockets and tests the first socket for each server. */
+    for ($ss=0;$ss < count($wgSquidServers);$ss++) {
+        $failed = false;
+        $so = 0;
+        while ($so < $sockspersq && !$failed) {
+            if ($so == 0) {
+               /* first socket for this server, do the tests */
+                $socket = @fsockopen($wgSquidServers[$ss], 80, $error, $errstr, 3);
+                if (!$socket) {
+                    $failed = true;
+                    $totalsockets -= $sockspersq;
+                } else {
+                    @fputs($socket,"PURGE " . $urlArr[0] . " HTTP/1.0\r\n".
+                    "Connection: Keep-Alive\r\n\r\n");
+                   $res = @fread($socket,512);
+                   /* Squid only returns http headers with 200 or 404 status, 
+                   if there's more returned something's wrong */
+                   if (strlen($res) > 250) {
+                        fclose($socket);
+                        $failed = true;
+                        $totalsockets -= $sockspersq;
+                    } else {
+                        @stream_set_blocking($socket,false);
+                        $sockets[] = $socket;
+                    }
+                } 
+            } else {
+               /* open the remaining sockets for this server */
+                $sockets[] = @fsockopen($wgSquidServers[$ss], 80, $error, $errstr, 2);
+                @stream_set_blocking($sockets[$s],false);
+            }
+            $so++;
+        }
+    }
+    
+    if ($urlspersocket > 1) {
+        /* now do the heavy lifting. The fread() relies on Squid returning only the headers */
+        for ($r=0;$r < $urlspersocket;$r++) {
+            for ($s=0;$s < $totalsockets;$s++) {
+               if($r != 0) {
+                   $res = '';
+                   $esc = 0;
+                   while (strlen($res) < 100 && $esc < 20  ) {
+                       $res .= @fread($sockets[$s],512);
+                       $esc++;
+                   }
+               }
+                $urindex = $r + $urlspersocket * ($s - $sockspersq * floor($s / $sockspersq));
+                @fputs($sockets[$s],"PURGE " . $urlArr[$urindex] . " HTTP/1.0\r\n".
+                "Connection: Keep-Alive\r\n\r\n");
+            }
+        }
+    }
+
+    foreach ($sockets as $socket) {
+        @fclose($sockets);
+    }
+    return;
+}
 ?>