11878f16fSAndreas Gohr<?php 21878f16fSAndreas Gohr/** 31878f16fSAndreas Gohr * statistics plugin 41878f16fSAndreas Gohr * 51878f16fSAndreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 61878f16fSAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 71878f16fSAndreas Gohr */ 81878f16fSAndreas Gohr 91878f16fSAndreas Gohr// must be run within Dokuwiki 101878f16fSAndreas Gohrif(!defined('DOKU_INC')) die(); 111878f16fSAndreas Gohr 121878f16fSAndreas Gohrif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 131878f16fSAndreas Gohrrequire_once(DOKU_PLUGIN.'admin.php'); 141878f16fSAndreas Gohr 151878f16fSAndreas Gohr/** 161878f16fSAndreas Gohr * All DokuWiki plugins to extend the admin function 171878f16fSAndreas Gohr * need to inherit from this class 181878f16fSAndreas Gohr */ 191878f16fSAndreas Gohrclass admin_plugin_statistics extends DokuWiki_Admin_Plugin { 201878f16fSAndreas Gohr var $dblink = null; 211878f16fSAndreas Gohr 221878f16fSAndreas Gohr /** 231878f16fSAndreas Gohr * return some info 241878f16fSAndreas Gohr */ 251878f16fSAndreas Gohr function getInfo(){ 261878f16fSAndreas Gohr return confToHash(dirname(__FILE__).'/info.txt'); 271878f16fSAndreas Gohr } 281878f16fSAndreas Gohr 291878f16fSAndreas Gohr /** 301878f16fSAndreas Gohr * Access for managers allowed 311878f16fSAndreas Gohr */ 321878f16fSAndreas Gohr function forAdminOnly(){ 331878f16fSAndreas Gohr return false; 341878f16fSAndreas Gohr } 351878f16fSAndreas Gohr 361878f16fSAndreas Gohr /** 371878f16fSAndreas Gohr * return sort order for position in admin menu 381878f16fSAndreas Gohr */ 391878f16fSAndreas Gohr function getMenuSort() { 40*14d99ec0SAndreas Gohr return 150; 411878f16fSAndreas Gohr } 421878f16fSAndreas Gohr 431878f16fSAndreas Gohr /** 441878f16fSAndreas Gohr * handle user request 451878f16fSAndreas Gohr */ 461878f16fSAndreas Gohr function handle() { 471878f16fSAndreas Gohr } 481878f16fSAndreas Gohr 491878f16fSAndreas Gohr /** 5094171ff3SAndreas Gohr * fixme build statistics here 511878f16fSAndreas Gohr */ 521878f16fSAndreas Gohr function html() { 53*14d99ec0SAndreas Gohr // fixme build a navigation menu in a TOC here 54*14d99ec0SAndreas Gohr 55*14d99ec0SAndreas Gohr switch($_REQUEST['opt']){ 56*14d99ec0SAndreas Gohr 57*14d99ec0SAndreas Gohr default: 58*14d99ec0SAndreas Gohr echo $this->locale_xhtml('intro'); 59*14d99ec0SAndreas Gohr echo $this->html_dashboard(); 60*14d99ec0SAndreas Gohr } 61*14d99ec0SAndreas Gohr } 62*14d99ec0SAndreas Gohr 63*14d99ec0SAndreas Gohr function html_timeselect(){ 64*14d99ec0SAndreas Gohr echo '<form>'; 65*14d99ec0SAndreas Gohr 66*14d99ec0SAndreas Gohr echo '</form>'; 67*14d99ec0SAndreas Gohr } 68*14d99ec0SAndreas Gohr 69*14d99ec0SAndreas Gohr 70*14d99ec0SAndreas Gohr function html_dashboard(){ 71*14d99ec0SAndreas Gohr 72*14d99ec0SAndreas Gohr $sql = "SELECT page, COUNT(*) as cnt 73*14d99ec0SAndreas Gohr FROM ".$this->getConf('db_prefix')."access 74*14d99ec0SAndreas Gohr WHERE DATE(dt) = CURDATE() 75*14d99ec0SAndreas Gohr GROUP BY page 76*14d99ec0SAndreas Gohr ORDER BY cnt DESC, page 77*14d99ec0SAndreas Gohr LIMIT 20"; 78*14d99ec0SAndreas Gohr $result = $this->runSQL($sql); 79*14d99ec0SAndreas Gohr $this->html_resulttable($result,array('Page','Count')); 80*14d99ec0SAndreas Gohr } 81*14d99ec0SAndreas Gohr 82*14d99ec0SAndreas Gohr /** 83*14d99ec0SAndreas Gohr * Display a result in a HTML table 84*14d99ec0SAndreas Gohr */ 85*14d99ec0SAndreas Gohr function html_resulttable($result,$header){ 86*14d99ec0SAndreas Gohr echo '<table>'; 87*14d99ec0SAndreas Gohr echo '<tr>'; 88*14d99ec0SAndreas Gohr foreach($header as $h){ 89*14d99ec0SAndreas Gohr echo '<th>'.hsc($h).'</th>'; 90*14d99ec0SAndreas Gohr } 91*14d99ec0SAndreas Gohr echo '</tr>'; 92*14d99ec0SAndreas Gohr 93*14d99ec0SAndreas Gohr foreach($result as $row){ 94*14d99ec0SAndreas Gohr echo '<tr>'; 95*14d99ec0SAndreas Gohr foreach($row as $k => $v){ 96*14d99ec0SAndreas Gohr echo '<td class="stats_'.$k.'">'; 97*14d99ec0SAndreas Gohr if($k == 'page'){ 98*14d99ec0SAndreas Gohr echo '<a href="'.wl($v).'" class="wikilink1">'; 99*14d99ec0SAndreas Gohr echo hsc($v); 100*14d99ec0SAndreas Gohr echo '</a>'; 101*14d99ec0SAndreas Gohr }elseif($k == 'url'){ 102*14d99ec0SAndreas Gohr echo '<a href="'.$v.'" class="urlextern">'; 103*14d99ec0SAndreas Gohr echo hsc($v); 104*14d99ec0SAndreas Gohr echo '</a>'; 105*14d99ec0SAndreas Gohr }elseif($k == 'html'){ 106*14d99ec0SAndreas Gohr echo $v; 107*14d99ec0SAndreas Gohr }else{ 108*14d99ec0SAndreas Gohr echo hsc($v); 109*14d99ec0SAndreas Gohr } 110*14d99ec0SAndreas Gohr echo '</td>'; 111*14d99ec0SAndreas Gohr } 112*14d99ec0SAndreas Gohr echo '</tr>'; 113*14d99ec0SAndreas Gohr } 114*14d99ec0SAndreas Gohr echo '</table>'; 1151878f16fSAndreas Gohr } 1161878f16fSAndreas Gohr 1171878f16fSAndreas Gohr 1181878f16fSAndreas Gohr /** 119*14d99ec0SAndreas Gohr * Return a link to the DB, opening the connection if needed 1201878f16fSAndreas Gohr */ 121*14d99ec0SAndreas Gohr function dbLink(){ 1221878f16fSAndreas Gohr // connect to DB if needed 1231878f16fSAndreas Gohr if(!$this->dblink){ 1241878f16fSAndreas Gohr $this->dblink = mysql_connect($this->getConf('db_server'), 1251878f16fSAndreas Gohr $this->getConf('db_user'), 1261878f16fSAndreas Gohr $this->getConf('db_password')); 1271878f16fSAndreas Gohr if(!$this->dblink){ 1281878f16fSAndreas Gohr msg('DB Error: connection failed',-1); 1291878f16fSAndreas Gohr return null; 1301878f16fSAndreas Gohr } 1311878f16fSAndreas Gohr // set utf-8 1321878f16fSAndreas Gohr if(!mysql_db_query($this->getConf('db_database'),'set names utf8',$this->dblink)){ 1331878f16fSAndreas Gohr msg('DB Error: could not set UTF-8 ('.mysql_error($this->dblink).')',-1); 1341878f16fSAndreas Gohr return null; 1351878f16fSAndreas Gohr } 1361878f16fSAndreas Gohr } 137*14d99ec0SAndreas Gohr return $this->dblink; 138*14d99ec0SAndreas Gohr } 1391878f16fSAndreas Gohr 140*14d99ec0SAndreas Gohr /** 141*14d99ec0SAndreas Gohr * Simple function to run a DB query 142*14d99ec0SAndreas Gohr */ 143*14d99ec0SAndreas Gohr function runSQL($sql_string) { 144*14d99ec0SAndreas Gohr $link = $this->dbLink(); 145*14d99ec0SAndreas Gohr 146*14d99ec0SAndreas Gohr $result = mysql_db_query($this->conf['db_database'],$sql_string,$link); 14794171ff3SAndreas Gohr if(!$result){ 148*14d99ec0SAndreas Gohr msg('DB Error: '.mysql_error($link),-1); 1491878f16fSAndreas Gohr return null; 1501878f16fSAndreas Gohr } 1511878f16fSAndreas Gohr 1521878f16fSAndreas Gohr $resultarray = array(); 1531878f16fSAndreas Gohr 1541878f16fSAndreas Gohr //mysql_db_query returns 1 on a insert statement -> no need to ask for results 1551878f16fSAndreas Gohr if ($result != 1) { 1561878f16fSAndreas Gohr for($i=0; $i< mysql_num_rows($result); $i++) { 1571878f16fSAndreas Gohr $temparray = mysql_fetch_assoc($result); 1581878f16fSAndreas Gohr $resultarray[]=$temparray; 1591878f16fSAndreas Gohr } 1601878f16fSAndreas Gohr mysql_free_result($result); 1611878f16fSAndreas Gohr } 1621878f16fSAndreas Gohr 163*14d99ec0SAndreas Gohr if (mysql_insert_id($link)) { 164*14d99ec0SAndreas Gohr $resultarray = mysql_insert_id($link); //give back ID on insert 1651878f16fSAndreas Gohr } 1661878f16fSAndreas Gohr 1671878f16fSAndreas Gohr return $resultarray; 1681878f16fSAndreas Gohr } 1691878f16fSAndreas Gohr 1701878f16fSAndreas Gohr /** 171*14d99ec0SAndreas Gohr * Returns a short name for a User Agent and sets type, version and os info 1721878f16fSAndreas Gohr */ 173*14d99ec0SAndreas Gohr function ua_info($ua,&$type,&$ver,&$os){ 174*14d99ec0SAndreas Gohr $ua = strtr($ua,' +','__'); 175*14d99ec0SAndreas Gohr $ua = strtolower($ua); 176*14d99ec0SAndreas Gohr 177*14d99ec0SAndreas Gohr // common browsers 178*14d99ec0SAndreas Gohr $regvermsie = '/msie([+_ ]|)([\d\.]*)/i'; 179*14d99ec0SAndreas Gohr $regvernetscape = '/netscape.?\/([\d\.]*)/i'; 180*14d99ec0SAndreas Gohr $regverfirefox = '/firefox\/([\d\.]*)/i'; 181*14d99ec0SAndreas Gohr $regversvn = '/svn\/([\d\.]*)/i'; 182*14d99ec0SAndreas Gohr $regvermozilla = '/mozilla(\/|)([\d\.]*)/i'; 183*14d99ec0SAndreas Gohr $regnotie = '/webtv|omniweb|opera/i'; 184*14d99ec0SAndreas Gohr $regnotnetscape = '/gecko|compatible|opera|galeon|safari/i'; 185*14d99ec0SAndreas Gohr 186*14d99ec0SAndreas Gohr $name = ''; 187*14d99ec0SAndreas Gohr # IE ? 188*14d99ec0SAndreas Gohr if(preg_match($regvermsie,$ua,$m) && !preg_match($regnotie,$ua)){ 189*14d99ec0SAndreas Gohr $type = 'browser'; 190*14d99ec0SAndreas Gohr $ver = $m[2]; 191*14d99ec0SAndreas Gohr $name = 'msie'; 192*14d99ec0SAndreas Gohr } 193*14d99ec0SAndreas Gohr # Firefox ? 194*14d99ec0SAndreas Gohr elseif (preg_match($regverfirefox,$ua,$m)){ 195*14d99ec0SAndreas Gohr $type = 'browser'; 196*14d99ec0SAndreas Gohr $ver = $m[1]; 197*14d99ec0SAndreas Gohr $name = 'firefox'; 198*14d99ec0SAndreas Gohr } 199*14d99ec0SAndreas Gohr # Subversion ? 200*14d99ec0SAndreas Gohr elseif (preg_match($regversvn,$ua,$m)){ 201*14d99ec0SAndreas Gohr $type = 'rcs'; 202*14d99ec0SAndreas Gohr $ver = $m[1]; 203*14d99ec0SAndreas Gohr $name = 'svn'; 204*14d99ec0SAndreas Gohr } 205*14d99ec0SAndreas Gohr # Netscape 6.x, 7.x ... ? 206*14d99ec0SAndreas Gohr elseif (preg_match($regvernetscape,$ua,$m)){ 207*14d99ec0SAndreas Gohr $type = 'browser'; 208*14d99ec0SAndreas Gohr $ver = $m[1]; 209*14d99ec0SAndreas Gohr $name = 'netscape'; 210*14d99ec0SAndreas Gohr } 211*14d99ec0SAndreas Gohr # Netscape 3.x, 4.x ... ? 212*14d99ec0SAndreas Gohr elseif(preg_match($regvermozilla,$ua,$m) && !preg_match($regnotnetscape,$ua)){ 213*14d99ec0SAndreas Gohr $type = 'browser'; 214*14d99ec0SAndreas Gohr $ver = $m[2]; 215*14d99ec0SAndreas Gohr $name = 'netscape'; 216*14d99ec0SAndreas Gohr }else{ 217*14d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/browsers.php'); 218*14d99ec0SAndreas Gohr foreach($BrowsersSearchIDOrder as $regex){ 219*14d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 220*14d99ec0SAndreas Gohr // it's a browser! 221*14d99ec0SAndreas Gohr $type = 'browser'; 222*14d99ec0SAndreas Gohr $name = strtolower($regex); 223*14d99ec0SAndreas Gohr break; 224*14d99ec0SAndreas Gohr } 225*14d99ec0SAndreas Gohr } 226*14d99ec0SAndreas Gohr } 227*14d99ec0SAndreas Gohr 228*14d99ec0SAndreas Gohr // check OS for browsers 229*14d99ec0SAndreas Gohr if($type == 'browser'){ 230*14d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/operating_systems.php'); 231*14d99ec0SAndreas Gohr foreach($OSSearchIDOrder as $regex){ 232*14d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 233*14d99ec0SAndreas Gohr $os = $OSHashID[$regex]; 234*14d99ec0SAndreas Gohr break; 235*14d99ec0SAndreas Gohr } 236*14d99ec0SAndreas Gohr } 237*14d99ec0SAndreas Gohr 238*14d99ec0SAndreas Gohr } 239*14d99ec0SAndreas Gohr 240*14d99ec0SAndreas Gohr // are we done now? 241*14d99ec0SAndreas Gohr if($name) return $name; 242*14d99ec0SAndreas Gohr 243*14d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/robots.php'); 244*14d99ec0SAndreas Gohr foreach($RobotsSearchIDOrder as $regex){ 245*14d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 246*14d99ec0SAndreas Gohr // it's a robot! 247*14d99ec0SAndreas Gohr $type = 'robot'; 248*14d99ec0SAndreas Gohr return strtolower($regex); 249*14d99ec0SAndreas Gohr } 250*14d99ec0SAndreas Gohr } 251*14d99ec0SAndreas Gohr 252*14d99ec0SAndreas Gohr // dunno 2531878f16fSAndreas Gohr return ''; 2541878f16fSAndreas Gohr } 2551878f16fSAndreas Gohr 2561878f16fSAndreas Gohr /** 257*14d99ec0SAndreas Gohr * 258*14d99ec0SAndreas Gohr * @fixme: put search engine queries in seperate table here 259*14d99ec0SAndreas Gohr */ 260*14d99ec0SAndreas Gohr function log_search($referer,&$type){ 261*14d99ec0SAndreas Gohr $referer = strtr($referer,' +','__'); 262*14d99ec0SAndreas Gohr $referer = strtolower($referer); 263*14d99ec0SAndreas Gohr 264*14d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/search_engines.php'); 265*14d99ec0SAndreas Gohr 266*14d99ec0SAndreas Gohr foreach($SearchEnginesSearchIDOrder as $regex){ 267*14d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$referer)){ 268*14d99ec0SAndreas Gohr if(!$NotSearchEnginesKeys[$regex] || 269*14d99ec0SAndreas Gohr !preg_match('/'.$NotSearchEnginesKeys[$regex].'/',$referer)){ 270*14d99ec0SAndreas Gohr // it's a search engine! 271*14d99ec0SAndreas Gohr $type = 'search'; 272*14d99ec0SAndreas Gohr break; 273*14d99ec0SAndreas Gohr } 274*14d99ec0SAndreas Gohr } 275*14d99ec0SAndreas Gohr } 276*14d99ec0SAndreas Gohr if($type != 'search') return; // we're done here 277*14d99ec0SAndreas Gohr 278*14d99ec0SAndreas Gohr #fixme now do the keyword magic! 279*14d99ec0SAndreas Gohr } 280*14d99ec0SAndreas Gohr 281*14d99ec0SAndreas Gohr /** 282*14d99ec0SAndreas Gohr * Resolve IP to country/city 283*14d99ec0SAndreas Gohr */ 284*14d99ec0SAndreas Gohr function log_ip($ip){ 285*14d99ec0SAndreas Gohr // check if IP already known and up-to-date 286*14d99ec0SAndreas Gohr $sql = "SELECT ip 287*14d99ec0SAndreas Gohr FROM ".$this->getConf('db_prefix')."iplocation 288*14d99ec0SAndreas Gohr WHERE ip ='".addslashes($ip)."' 289*14d99ec0SAndreas Gohr AND lastupd > DATE_SUB(CURDATE(),INTERVAL 30 DAY)"; 290*14d99ec0SAndreas Gohr $result = $this->runSQL($sql); 291*14d99ec0SAndreas Gohr if($result[0]['ip']) return; 292*14d99ec0SAndreas Gohr 293*14d99ec0SAndreas Gohr $http = new DokuHTTPClient(); 294*14d99ec0SAndreas Gohr $http->timeout = 10; 295*14d99ec0SAndreas Gohr $data = $http->get('http://api.hostip.info/get_html.php?ip='.$ip); 296*14d99ec0SAndreas Gohr 297*14d99ec0SAndreas Gohr if(preg_match('/^Country: (.*?) \((.*?)\)\nCity: (.*?)$/s',$data,$match)){ 298*14d99ec0SAndreas Gohr $country = addslashes(trim($match[1])); 299*14d99ec0SAndreas Gohr $code = addslashes(strtolower(trim($match[2]))); 300*14d99ec0SAndreas Gohr $city = addslashes(trim($match[3])); 301*14d99ec0SAndreas Gohr $host = addslashes(gethostbyaddr($ip)); 302*14d99ec0SAndreas Gohr $ip = addslashes($ip); 303*14d99ec0SAndreas Gohr 304*14d99ec0SAndreas Gohr $sql = "REPLACE INTO ".$this->getConf('db_prefix')."iplocation 305*14d99ec0SAndreas Gohr SET ip = '$ip', 306*14d99ec0SAndreas Gohr country = '$country', 307*14d99ec0SAndreas Gohr code = '$code', 308*14d99ec0SAndreas Gohr city = '$city', 309*14d99ec0SAndreas Gohr host = '$host'"; 310*14d99ec0SAndreas Gohr $this->runSQL($sql); 311*14d99ec0SAndreas Gohr } 312*14d99ec0SAndreas Gohr } 313*14d99ec0SAndreas Gohr 314*14d99ec0SAndreas Gohr /** 3151878f16fSAndreas Gohr * log a page access 3161878f16fSAndreas Gohr * 3171878f16fSAndreas Gohr * called from log.php 3181878f16fSAndreas Gohr */ 3191878f16fSAndreas Gohr function log_access(){ 32094171ff3SAndreas Gohr if(!$_REQUEST['p']) return; 32194171ff3SAndreas Gohr 322*14d99ec0SAndreas Gohr # FIXME check referer against blacklist and drop logging for bad boys 323*14d99ec0SAndreas Gohr 324*14d99ec0SAndreas Gohr // handle referer 325*14d99ec0SAndreas Gohr $referer = trim($_REQUEST['r']); 326*14d99ec0SAndreas Gohr if($referer){ 327*14d99ec0SAndreas Gohr $ref = addslashes($referer); 328*14d99ec0SAndreas Gohr $ref_md5 = ($ref) ? md5($referer) : ''; 329*14d99ec0SAndreas Gohr if(strpos($referer,DOKU_URL) === 0){ 330*14d99ec0SAndreas Gohr $ref_type = 'internal'; 331*14d99ec0SAndreas Gohr }else{ 332*14d99ec0SAndreas Gohr $ref_type = 'external'; 333*14d99ec0SAndreas Gohr $this->log_search($referer,$ref_type); 334*14d99ec0SAndreas Gohr } 335*14d99ec0SAndreas Gohr }else{ 336*14d99ec0SAndreas Gohr $ref = ''; 337*14d99ec0SAndreas Gohr $ref_md5 = ''; 338*14d99ec0SAndreas Gohr $ref_type = ''; 339*14d99ec0SAndreas Gohr } 340*14d99ec0SAndreas Gohr 341*14d99ec0SAndreas Gohr // handle user agent 342*14d99ec0SAndreas Gohr $agent = trim($_SERVER['HTTP_USER_AGENT']); 343*14d99ec0SAndreas Gohr 344*14d99ec0SAndreas Gohr $ua = addslashes($agent); 345*14d99ec0SAndreas Gohr $ua_type = ''; 346*14d99ec0SAndreas Gohr $ua_ver = ''; 347*14d99ec0SAndreas Gohr $os = ''; 348*14d99ec0SAndreas Gohr $ua_info = addslashes($this->ua_info($agent,$ua_type,$ua_ver,$os)); 349*14d99ec0SAndreas Gohr 3501878f16fSAndreas Gohr $page = addslashes($_REQUEST['p']); 3511878f16fSAndreas Gohr $ip = addslashes($_SERVER['REMOTE_ADDR']); 3521878f16fSAndreas Gohr $sx = (int) $_REQUEST['sx']; 3531878f16fSAndreas Gohr $sy = (int) $_REQUEST['sy']; 3541878f16fSAndreas Gohr $vx = (int) $_REQUEST['vx']; 3551878f16fSAndreas Gohr $vy = (int) $_REQUEST['vy']; 3561878f16fSAndreas Gohr $user = addslashes($_SERVER['REMOTE_USER']); 3571878f16fSAndreas Gohr $session = addslashes(session_id()); 3581878f16fSAndreas Gohr 35994171ff3SAndreas Gohr $sql = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."access 3601878f16fSAndreas Gohr SET page = '$page', 3611878f16fSAndreas Gohr ip = '$ip', 3621878f16fSAndreas Gohr ua = '$ua', 3631878f16fSAndreas Gohr ua_info = '$ua_info', 364*14d99ec0SAndreas Gohr ua_type = '$ua_type', 365*14d99ec0SAndreas Gohr ua_ver = '$ua_ver', 366*14d99ec0SAndreas Gohr os = '$os', 3671878f16fSAndreas Gohr ref = '$ref', 36894171ff3SAndreas Gohr ref_md5 = '$ref_md5', 369*14d99ec0SAndreas Gohr ref_type = '$ref_type', 3701878f16fSAndreas Gohr screen_x = '$sx', 3711878f16fSAndreas Gohr screen_y = '$sy', 3721878f16fSAndreas Gohr view_x = '$vx', 3731878f16fSAndreas Gohr view_y = '$vy', 3741878f16fSAndreas Gohr user = '$user', 3751878f16fSAndreas Gohr session = '$session'"; 3761878f16fSAndreas Gohr $ok = $this->runSQL($sql); 3771878f16fSAndreas Gohr if(is_null($ok)){ 3781878f16fSAndreas Gohr global $MSG; 3791878f16fSAndreas Gohr print_r($MSG); 3801878f16fSAndreas Gohr } 381*14d99ec0SAndreas Gohr 382*14d99ec0SAndreas Gohr // resolve the IP 383*14d99ec0SAndreas Gohr $this->log_ip($_SERVER['REMOTE_ADDR']); 3841878f16fSAndreas Gohr } 3851878f16fSAndreas Gohr 3861878f16fSAndreas Gohr /** 3871878f16fSAndreas Gohr * Just send a 1x1 pixel blank gif to the browser 3881878f16fSAndreas Gohr * 3891878f16fSAndreas Gohr * @called from log.php 3901878f16fSAndreas Gohr * 3911878f16fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 3921878f16fSAndreas Gohr * @author Harry Fuecks <fuecks@gmail.com> 3931878f16fSAndreas Gohr */ 3941878f16fSAndreas Gohr function sendGIF(){ 3951878f16fSAndreas Gohr $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'); 3961878f16fSAndreas Gohr header('Content-Type: image/gif'); 3971878f16fSAndreas Gohr header('Content-Length: '.strlen($img)); 3981878f16fSAndreas Gohr header('Connection: Close'); 3991878f16fSAndreas Gohr print $img; 4001878f16fSAndreas Gohr flush(); 4011878f16fSAndreas Gohr // Browser should drop connection after this 4021878f16fSAndreas Gohr // Thinks it's got the whole image 4031878f16fSAndreas Gohr } 4041878f16fSAndreas Gohr 4051878f16fSAndreas Gohr} 406