PageRenderTime 279ms CodeModel.GetById 80ms app.highlight 145ms RepoModel.GetById 36ms app.codeStats 1ms

/wp-content/plugins/wassup/lib/main.php

https://bitbucket.org/openfarmtech/weblog-content
PHP | 1339 lines | 1038 code | 116 blank | 185 comment | 223 complexity | 63386f157a0e14f1dedb76120f68e179 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2if (!class_exists('pagination')) { 	//in case another app uses this class...
   3class pagination{
   4/*
   5Script Name: *Digg Style Paginator Class
   6Script URI: http://www.mis-algoritmos.com/2007/05/27/digg-style-pagination-class/
   7Description: Class in PHP that allows to use a pagination like a digg or sabrosus style.
   8Script Version: 0.3.2
   9Author: Victor De la Rocha
  10Author URI: http://www.mis-algoritmos.com
  11*/
  12	/*Default values*/
  13        var $total_pages;
  14        var $limit;
  15        var $target;
  16        var $page;
  17        var $adjacents;
  18        var $showCounter;
  19        var $className;
  20        var $parameterName;
  21        var $urlF ;
  22
  23        /*Buttons next and previous*/
  24        var $nextT;
  25        var $nextI;
  26        var $prevT;
  27        var $prevI;
  28
  29        /*****/
  30        var $calculate;
  31	
  32	#Total items
  33	function items($value){$this->total_pages = intval($value);}
  34	
  35	#how many items to show per page
  36	function limit($value){$this->limit = intval($value);}
  37	
  38	#Page to sent the page value
  39	function target($value){$this->target = $value;}
  40	
  41	#Current page
  42	function currentPage($value){$this->page = intval($value);}
  43	
  44	#How many adjacent pages should be shown on each side of the current page?
  45	function adjacents($value){$this->adjacents = intval($value);}
  46	
  47	#show counter?
  48	function showCounter($value=""){$this->showCounter=($value===true)?true:false;}
  49
  50	#to change the class name of the pagination div
  51	function changeClass($value=""){$this->className=$value;}
  52
  53	function nextLabel($value){$this->nextT = $value;}
  54	function nextIcon($value){$this->nextI = $value;}
  55	function prevLabel($value){$this->prevT = $value;}
  56	function prevIcon($value){$this->prevI = $value;}
  57
  58	#to change the class name of the pagination div
  59	function parameterName($value=""){$this->parameterName=$value;}
  60
  61	#to change urlFriendly
  62	function urlFriendly($value="%"){
  63			if(eregi('^ *$',$value)){
  64					$this->urlF=false;
  65					return false;
  66				}
  67			$this->urlF=$value;
  68		}
  69	
  70	var $pagination;
  71
  72	function pagination(){
  73                /*Set Default values*/
  74                $this->total_pages = null;
  75                $this->limit = null;
  76                $this->target = "";
  77                $this->page = 1;
  78                $this->adjacents = 2;
  79                $this->showCounter = false;
  80                $this->className = "pagination";
  81                $this->parameterName = "pages";
  82                $this->urlF = false;//urlFriendly
  83
  84                /*Buttons next and previous*/
  85                $this->nextT = __("Next","wassup");
  86                $this->nextI = "&#187;"; //&#9658;
  87                $this->prevT = __("Previous","wassup");
  88                $this->prevI = "&#171;"; //&#9668;
  89
  90                $this->calculate = false;
  91	}
  92	function show(){
  93			if(!$this->calculate)
  94				if($this->calculate())
  95					echo "<div class=\"$this->className\">$this->pagination</div>";
  96		}
  97	function get_pagenum_link($id){
  98			if(strpos($this->target,'?')===false)
  99					if($this->urlF)
 100							return str_replace($this->urlF,$id,$this->target);
 101						else
 102							return "$this->target?$this->parameterName=$id";
 103				else
 104					return "$this->target&$this->parameterName=$id";
 105		}
 106	
 107	function calculate(){
 108			$this->pagination = "";
 109			$this->calculate == true;
 110			$error = false;
 111			if($this->urlF and $this->urlF != '%' and strpos($this->target,$this->urlF)===false){
 112					//Es necesario especificar el comodin para sustituir
 113					echo 'Especificaste un wildcard para sustituir, pero no existe en el target<br />';
 114                                        $error = true;
 115                                }elseif($this->urlF and $this->urlF == '%' and strpos($this->target,$this->urlF)===false){
 116                                        echo 'Es necesario especificar en el target el comodin';
 117                                        $error = true;
 118                                }
 119                        if($this->total_pages == null){
 120                                        echo __("It is necessary to specify the","wassup")." <strong>".__("number of pages","wassup")."</strong> (\$class->items(1000))<br />";
 121                                        $error = true;
 122                                }
 123                        if($this->limit == null){
 124                                        echo __("It is necessary to specify the","wassup")." <strong>".__("limit of items","wassup")."</strong> ".__("to show per page","wassup")." (\$class->limit(10))<br />";
 125                                        $error = true;
 126				}
 127			if($error)return false;
 128			
 129			$n = trim($this->nextT.' '.$this->nextI);
 130			$p = trim($this->prevI.' '.$this->prevT);
 131			
 132			/* Setup vars for query. */
 133			if($this->page) 
 134				$start = ($this->page - 1) * $this->limit;             //first item to display on this page
 135			else
 136				$start = 0;                                //if no page var is given, set start to 0
 137		
 138			/* Setup page vars for display. */
 139			if ($this->page == 0) $this->page = 1;                    //if no page var is given, default to 1.
 140			$prev = $this->page - 1;                            //previous page is page - 1
 141			$next = $this->page + 1;                            //next page is page + 1
 142			$lastpage = ceil($this->total_pages/$this->limit);        //lastpage is = total pages / items per page, rounded up.
 143			$lpm1 = $lastpage - 1;                        //last page minus 1
 144			
 145			/* 
 146				Now we apply our rules and draw the pagination object. 
 147				We're actually saving the code to a variable in case we want to draw it more than once.
 148			*/
 149			
 150			if($lastpage > 1){
 151					//anterior button
 152					if($this->page > 1)
 153							$this->pagination .= "<a href=\"".$this->get_pagenum_link($prev)."\">$p</a>";
 154						else
 155							$this->pagination .= "<span class=\"disabled\">$p</span>";
 156					//pages	
 157					if ($lastpage < 7 + ($this->adjacents * 2)){//not enough pages to bother breaking it up
 158							for ($counter = 1; $counter <= $lastpage; $counter++){
 159									if ($counter == $this->page)
 160											$this->pagination .= "<span class=\"current\">$counter</span>";
 161										else
 162											$this->pagination .= "<a href=\"".$this->get_pagenum_link($counter)."\">$counter</a>";
 163								}
 164						}
 165					elseif($lastpage > 5 + ($this->adjacents * 2)){//enough pages to hide some
 166							//close to beginning; only hide later pages
 167							if($this->page < 1 + ($this->adjacents * 2)){
 168									for ($counter = 1; $counter < 4 + ($this->adjacents * 2); $counter++){
 169											if ($counter == $this->page)
 170													$this->pagination .= "<span class=\"current\">$counter</span>";
 171												else
 172													$this->pagination .= "<a href=\"".$this->get_pagenum_link($counter)."\">$counter</a>";
 173										}
 174									$this->pagination .= "...";
 175									$this->pagination .= "<a href=\"".$this->get_pagenum_link($lpm1)."\">$lpm1</a>";
 176									$this->pagination .= "<a href=\"".$this->get_pagenum_link($lastpage)."\">$lastpage</a>";
 177								}
 178							//in middle; hide some front and some back
 179							elseif($lastpage - ($this->adjacents * 2) > $this->page && $this->page > ($this->adjacents * 2)){
 180									$this->pagination .= "<a href=\"".$this->get_pagenum_link(1)."\">1</a>";
 181									$this->pagination .= "<a href=\"".$this->get_pagenum_link(2)."\">2</a>";
 182									$this->pagination .= "...";
 183									for ($counter = $this->page - $this->adjacents; $counter <= $this->page + $this->adjacents; $counter++)
 184										if ($counter == $this->page)
 185												$this->pagination .= "<span class=\"current\">$counter</span>";
 186											else
 187												$this->pagination .= "<a href=\"".$this->get_pagenum_link($counter)."\">$counter</a>";
 188									$this->pagination .= "...";
 189									$this->pagination .= "<a href=\"".$this->get_pagenum_link($lpm1)."\">$lpm1</a>";
 190									$this->pagination .= "<a href=\"".$this->get_pagenum_link($lastpage)."\">$lastpage</a>";
 191								}
 192							//close to end; only hide early pages
 193							else{
 194									$this->pagination .= "<a href=\"".$this->get_pagenum_link(1)."\">1</a>";
 195									$this->pagination .= "<a href=\"".$this->get_pagenum_link(2)."\">2</a>";
 196									$this->pagination .= "...";
 197									for ($counter = $lastpage - (2 + ($this->adjacents * 2)); $counter <= $lastpage; $counter++)
 198										if ($counter == $this->page)
 199												$this->pagination .= "<span class=\"current\">$counter</span>";
 200											else
 201												$this->pagination .= "<a href=\"".$this->get_pagenum_link($counter)."\">$counter</a>";
 202								}
 203						}
 204					//siguiente button
 205					if ($this->page < $counter - 1)
 206							$this->pagination .= "<a href=\"".$this->get_pagenum_link($next)."\">$n</a>";
 207						else
 208							$this->pagination .= "<span class=\"disabled\">$n</span>";
 209						if($this->showCounter)$this->pagination .= "<div class=\"pagination_data\">($this->total_pages ".__("Pages","wassup").")</div>";
 210				}
 211
 212			return true;
 213		}
 214	} //end class pagination
 215} //end if !class_exists('pagination')
 216
 217if (!class_exists('Detector')) { 	//in case another app uses this class...
 218//
 219// Detector class (c) Mohammad Hafiz bin Ismail 2006
 220// detect location by ipaddress
 221// detect browser type and operating system
 222//
 223// November 27, 2006
 224//
 225// by : Mohammad Hafiz bin Ismail (info@mypapit.net)
 226// 
 227// You are allowed to use this work under the terms of 
 228// Creative Commons Attribution-Share Alike 3.0 License
 229// 
 230// Reference : http://creativecommons.org/licenses/by-sa/3.0/
 231// 
 232
 233class Detector {
 234
 235	var $town;
 236	var $state;
 237	var $country;
 238	var $Ctimeformatode;
 239	var $longitude;
 240	var $latitude;
 241	var $ipaddress;
 242	var $txt;
 243
 244	var $browser;
 245	var $browser_version;
 246	var $os_version;
 247	var $os;
 248	var $useragent;
 249
 250	function Detector($ip="", $ua="")
 251	{	
 252		$apiserver="http://showip.fakap.net/txt/";
 253		if ($ip != "") {	
 254		if (preg_match('/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/',$ip,$matches))
 255		  {
 256		    $this->ipaddress=$ip;
 257		  }
 258
 259		else { $this->ipaddress = "0.0.0.0"; }
 260
 261		//uncomment this below if CURL doesnt work		
 262
 263		$this->txt=file_get_contents($apiserver . "$ip");
 264
 265		$wtf=$this->txt;
 266		$this->processTxt($wtf);
 267		}
 268
 269		$this->useragent=$ua;
 270		$this->check_os($ua);
 271		$this->check_browser($ua);
 272	}
 273
 274	function processTxt($wtf)
 275
 276	{
 277//	  	$tok = strtok($txt, ',');
 278	  	$this->town = strtok($wtf,',');
 279	  	$this->state = strtok(',');
 280	  	$this->country=strtok(',');
 281	  	$this->ccode = strtok(',');
 282	  	$this->latitude=strtok(',');
 283	  	$this->longitude=strtok(',');
 284	}
 285
 286	function check_os($useragent) {
 287
 288			$os = "N/A"; $version = "";
 289
 290			if (preg_match("/Windows NT 5.1/",$useragent,$match)) {
 291				$os = "WinXP"; $version = "";
 292			} elseif (preg_match("/Windows NT 5.2/",$useragent,$match)) {
 293				$os = "Win2003"; $version = "";
 294			} elseif (preg_match("/Windows NT 6.0/",$useragent,$match)) {
 295				$os = "WinVista"; $version = "";
 296			} elseif (preg_match("/(?:Windows NT 5.0|Windows 2000)/",$useragent,$match)) {
 297				$os = "Win2000"; $version = "";
 298			} elseif (preg_match("/Windows ME/",$useragent,$match)) {
 299				$os = "WinME"; $version = "";
 300			} elseif (preg_match("/(?:WinNT|Windows\s?NT)\s?([0-9\.]+)?/",$useragent,$match)) {
 301				$os = "WinNT"; $version = $match[1];
 302			} elseif (preg_match("/Mac OS X/",$useragent,$match)) {
 303				$os = "MacOSX"; $version = "";
 304			} elseif (preg_match("/(Mac_PowerPC|Macintosh)/",$useragent,$match)) {
 305				$os = "MacPPC"; $version = "";
 306			} elseif (preg_match("/(?:Windows95|Windows 95|Win95|Win 95)/",$useragent,$match)) {
 307				$os = "Win95"; $version = "";
 308			} elseif (preg_match("/(?:Windows98|Windows 98|Win98|Win 98|Win 9x)/",$useragent,$match)) {
 309				$os = "Win98"; $version = "";
 310			} elseif (preg_match("/(?:WindowsCE|Windows CE|WinCE|Win CE)/",$useragent,$match)) {
 311				$os = "WinCE"; $version = "";
 312			} elseif (preg_match("/PalmOS/",$useragent,$match)) {
 313				$os = "PalmOS";
 314			} elseif (preg_match("/\(PDA(?:.*)\)(.*)Zaurus/",$useragent,$match)) {
 315				$os = "Sharp Zaurus";
 316			} elseif (preg_match("/Linux\s*((?:i[0-9]{3})?\s*(?:[0-9]\.[0-9]{1,2}\.[0-9]{1,2})?\s*(?:i[0-9]{3})?)?/",$useragent,$match)) {
 317				$os = "Linux"; $version = $match[1];
 318			} elseif (preg_match("/NetBSD\s*((?:i[0-9]{3})?\s*(?:[0-9]\.[0-9]{1,2}\.[0-9]{1,2})?\s*(?:i[0-9]{3})?)?/",$useragent,$match)) {
 319				$os = "NetBSD"; $version = $match[1];
 320			} elseif (preg_match("/OpenBSD\s*([0-9\.]+)?/",$useragent,$match)) {
 321				$os = "OpenBSD"; $version = $match[1];
 322			} elseif (preg_match("/CYGWIN\s*((?:i[0-9]{3})?\s*(?:[0-9]\.[0-9]{1,2}\.[0-9]{1,2})?\s*(?:i[0-9]{3})?)?/",$useragent,$match)) {
 323				$os = "CYGWIN"; $version = $match[1];
 324			} elseif (preg_match("/SunOS\s*([0-9\.]+)?/",$useragent,$match)) {
 325				$os = "SunOS"; $version = $match[1];
 326			} elseif (preg_match("/IRIX\s*([0-9\.]+)?/",$useragent,$match)) {
 327				$os = "SGI IRIX"; $version = $match[1];
 328			} elseif (preg_match("/FreeBSD\s*((?:i[0-9]{3})?\s*(?:[0-9]\.[0-9]{1,2})?\s*(?:i[0-9]{3})?)?/",$useragent,$match)) {
 329				$os = "FreeBSD"; $version = $match[1];
 330			} elseif (preg_match("/SymbianOS\/([0-9.]+)/i",$useragent,$match)) {
 331				$os = "SymbianOS"; $version = $match[1];
 332			} elseif (preg_match("/Symbian\/([0-9.]+)/i",$useragent,$match)) {
 333				$os = "Symbian"; $version = $match[1];
 334			} elseif (preg_match("/PLAYSTATION 3/",$useragent,$match)) {
 335				$os = "Playstation"; $version = 3;
 336			}
 337
 338			$this->os = $os;
 339			$this->os_version = $version;
 340		}
 341
 342		function check_browser($useragent) {
 343
 344			$browser = "";
 345
 346			if (preg_match("/^Mozilla(?:.*)compatible;\sMSIE\s(?:.*)Opera\s([0-9\.]+)/",$useragent,$match)) {
 347				$browser = "Opera";
 348			} elseif (preg_match("/^Opera\/([0-9\.]+)/",$useragent,$match)) {
 349				$browser = "Opera";
 350			} elseif (preg_match("/^Mozilla(?:.*)compatible;\siCab\s([0-9\.]+)/",$useragent,$match)) {
 351				$browser = "iCab";
 352			} elseif (preg_match("/^iCab\/([0-9\.]+)/",$useragent,$match)) {
 353				$browser = "iCab";
 354			} elseif (preg_match("/^Mozilla(?:.*)compatible;\sMSIE\s([0-9\.]+)/",$useragent,$match)) {
 355				$browser = "IE";
 356			} elseif (preg_match("/^(?:.*)compatible;\sMSIE\s([0-9\.]+)/",$useragent,$match)) {
 357				$browser = "IE";
 358			} elseif (preg_match("/^Mozilla(?:.*)(?:.*)Chrome/",$useragent,$match)) {
 359				$browser = "Google Chrome";
 360			} elseif (preg_match("/^Mozilla(?:.*)(?:.*)Safari\/([0-9\.]+)/",$useragent,$match)) {
 361				$browser = "Safari";
 362			} elseif (preg_match("/^Mozilla(?:.*)\(Macintosh(?:.*)OmniWeb\/v([0-9\.]+)/",$useragent,$match)) {
 363				$browser = "Omniweb";
 364			} elseif (preg_match("/^Mozilla(?:.*)\(compatible; Google Desktop/",$useragent,$match)) {
 365				$browser = "Google Desktop";
 366			} elseif (preg_match("/^Mozilla(?:.*)\(compatible;\sOmniWeb\/([0-9\.v-]+)/",$useragent,$match)) {
 367				$browser = "Omniweb";
 368			} elseif (preg_match("/^Mozilla(?:.*)Gecko(?:.*?)(?:Camino|Chimera)\/([0-9\.]+)/",$useragent,$match)) {
 369				$browser = "Camino";
 370			} elseif (preg_match("/^Mozilla(?:.*)Gecko(?:.*?)Netscape\/([0-9\.]+)/",$useragent,$match)) {
 371				$browser = "Netscape";
 372			} elseif (preg_match("/^Mozilla(?:.*)Gecko(?:.*?)(?:Fire(?:fox|bird)|Phoenix)\/([0-9\.]+)/",$useragent,$match)) {
 373				$browser = "Firefox";
 374			} elseif (preg_match("/^Mozilla(?:.*)Gecko(?:.*?)Minefield\/([0-9\.]+)/",$useragent,$match)) {
 375				$browser = "Minefield";
 376			} elseif (preg_match("/^Mozilla(?:.*)Gecko(?:.*?)Epiphany\/([0-9\.]+)/",$useragent,$match)) {
 377				$browser = "Epiphany";
 378			} elseif (preg_match("/^Mozilla(?:.*)Galeon\/([0-9\.]+)\s(?:.*)Gecko/",$useragent,$match)) {
 379				$browser = "Galeon";
 380			} elseif (preg_match("/^Mozilla(?:.*)Gecko(?:.*?)K-Meleon\/([0-9\.]+)/",$useragent,$match)) {
 381				$browser = "K-Meleon";
 382			} elseif (preg_match("/^Mozilla(?:.*)rv:([0-9\.]+)\)\sGecko/",$useragent,$match)) {
 383				$browser = "Mozilla";
 384			} elseif (preg_match("/^Mozilla(?:.*)compatible;\sKonqueror\/([0-9\.]+);/",$useragent,$match)) {
 385				$browser = "Konqueror";
 386			} elseif (preg_match("/^Mozilla\/(?:[34]\.[0-9]+)(?:.*)AvantGo\s([0-9\.]+)/",$useragent,$match)) {
 387				$browser = "AvantGo";
 388			} elseif (preg_match("/^Mozilla(?:.*)NetFront\/([34]\.[0-9]+)/",$useragent,$match)) {
 389				$browser = "NetFront";
 390			} elseif (preg_match("/^Mozilla\/([34]\.[0-9]+)/",$useragent,$match)) {
 391				$browser = "Netscape";
 392			} elseif (preg_match("/^Liferea\/([0-9\.]+)/",$useragent,$match)) {
 393				$browser = "Liferea";
 394			} elseif (preg_match("/^curl\/([0-9\.]+)/",$useragent,$match)) {
 395				$browser = "curl";
 396			} elseif (preg_match("/^links\/([0-9\.]+)/i",$useragent,$match)) {
 397				$browser = "Links";
 398			} elseif (preg_match("/^links\s?\(([0-9\.]+)/i",$useragent,$match)) {
 399				$browser = "Links";
 400			} elseif (preg_match("/^lynx\/([0-9a-z\.]+)/i",$useragent,$match)) {
 401				$browser = "Lynx";
 402			} elseif (preg_match("/^Wget\/([0-9\.]+)/i",$useragent,$match)) {
 403				$browser = "Wget";
 404			} elseif (preg_match("/^Xiino\/([0-9\.]+)/i",$useragent,$match)) {
 405				$browser = "Xiino";
 406			} elseif (preg_match("/^W3C_Validator\/([0-9\.]+)/i",$useragent,$match)) {
 407				$browser = "W3C Validator";
 408			} elseif (preg_match("/^Jigsaw(?:.*) W3C_CSS_Validator_(?:[A-Z]+)\/([0-9\.]+)/i",$useragent,$match)) {
 409				$browser = "W3C CSS Validator";
 410			} elseif (preg_match("/^Dillo\/([0-9\.]+)/i",$useragent,$match)) {
 411				$browser = "Dillo";
 412			} elseif (preg_match("/^amaya\/([0-9\.]+)/i",$useragent,$match)) {
 413				$browser = "Amaya";
 414			} elseif (preg_match("/^DocZilla\/([0-9\.]+)/i",$useragent,$match)) {
 415				$browser = "DocZilla";
 416			} elseif (preg_match("/^fetch\slibfetch\/([0-9\.]+)/i",$useragent,$match)) {
 417				$browser = "FreeBSD libfetch";
 418			} elseif (preg_match("/^Nokia([0-9a-zA-Z\-.]+)\/([0-9\.]+)/i",$useragent,$match)) {
 419				$browser="Nokia";
 420			} elseif (preg_match("/^SonyEricsson([0-9a-zA-Z\-.]+)\/([a-zA-Z0-9\.]+)/i",$useragent,$match)) {
 421				$browser="SonyEricsson";
 422			}
 423
 424			//$version = $match[1];
 425			//restrict version to major and minor version #'s
 426			preg_match("/^\d+(\.\d+)?/",$match[1],$majorvers);
 427			$version = $majorvers[0];
 428
 429			$this->browser = $browser;
 430			$this->browser_version = $version;
 431	}
 432} //end class Detector
 433} //end if !class_exists('Detector')
 434
 435function wassup_get_time() {
 436	$timeright = gmdate("U");
 437	$offset = (get_option("gmt_offset")*60*60);
 438	$timeright = ($timeright + $offset) ;
 439	return $timeright;
 440}
 441
 442/*
 443# PHP Calendar (version 2.3), written by Keith Devens
 444# http://keithdevens.com/software/php_calendar
 445#  see example at http://keithdevens.com/weblog
 446# License: http://keithdevens.com/software/license
 447*/
 448//
 449// Currently not used in WassUp it's a next implementation idea
 450//
 451function generate_calendar($year, $month, $days = array(), $day_name_length = 3, $month_href = NULL, $first_day = 0, $pn = array()){
 452	$first_of_month = gmmktime(0,0,0,$month,1,$year);
 453	#remember that mktime will automatically correct if invalid dates are entered
 454	# for instance, mktime(0,0,0,12,32,1997) will be the date for Jan 1, 1998
 455	# this provides a built in "rounding" feature to generate_calendar()
 456
 457	$day_names = array(); #generate all the day names according to the current locale
 458	for($n=0,$t=(3+$first_day)*86400; $n<7; $n++,$t+=86400) #January 4, 1970 was a Sunday
 459		$day_names[$n] = ucfirst(gmstrftime('%A',$t)); #%A means full textual day name
 460
 461	list($month, $year, $month_name, $weekday) = explode(',',gmstrftime('%m,%Y,%B,%w',$first_of_month));
 462	$weekday = ($weekday + 7 - $first_day) % 7; #adjust for $first_day
 463	$title   = htmlentities(ucfirst($month_name)).'&nbsp;'.$year;  #note that some locales don't capitalize month and day names
 464
 465	#Begin calendar. Uses a real <caption>. See http://diveintomark.org/archives/2002/07/03
 466	@list($p, $pl) = each($pn); @list($n, $nl) = each($pn); #previous and next links, if applicable
 467	if($p) $p = '<span class="calendar-prev">'.($pl ? '<a href="'.htmlspecialchars($pl).'">'.$p.'</a>' : $p).'</span>&nbsp;';
 468	if($n) $n = '&nbsp;<span class="calendar-next">'.($nl ? '<a href="'.htmlspecialchars($nl).'">'.$n.'</a>' : $n).'</span>';
 469	$calendar = '<table class="calendar">'."\n".
 470		'<caption class="calendar-month">'.$p.($month_href ? '<a href="'.htmlspecialchars($month_href).'">'.$title.'</a>' : $title).$n."</caption>\n<tr>";
 471
 472	if($day_name_length){ #if the day names should be shown ($day_name_length > 0)
 473		#if day_name_length is >3, the full name of the day will be printed
 474		foreach($day_names as $d)
 475			$calendar .= '<th abbr="'.htmlentities($d).'">'.htmlentities($day_name_length < 4 ? substr($d,0,$day_name_length) : $d).'</th>';
 476		$calendar .= "</tr>\n<tr>";
 477	}
 478
 479	if($weekday > 0) $calendar .= '<td colspan="'.$weekday.'">&nbsp;</td>'; #initial 'empty' days
 480	for($day=1,$days_in_month=gmdate('t',$first_of_month); $day<=$days_in_month; $day++,$weekday++){
 481		if($weekday == 7){
 482			$weekday   = 0; #start a new week
 483			$calendar .= "</tr>\n<tr>";
 484		}
 485		if(isset($days[$day]) and is_array($days[$day])){
 486			@list($link, $classes, $content) = $days[$day];
 487			if(is_null($content))  $content  = $day;
 488			$calendar .= '<td'.($classes ? ' class="'.htmlspecialchars($classes).'">' : '>').
 489				($link ? '<a href="'.htmlspecialchars($link).'">'.$content.'</a>' : $content).'</td>';
 490		}
 491		else $calendar .= "<td>$day</td>";
 492	}
 493	if($weekday != 7) $calendar .= '<td colspan="'.(7-$weekday).'">&nbsp;</td>'; #remaining "empty" days
 494
 495	return $calendar."</tr>\n</table>\n";
 496}
 497
 498//Truncate $input string to a length of $max
 499function stringShortener($input, $max=0, $separator="(...)", $exceedFromEnd=0){
 500	if(!$input || !is_string($input)){return false;};
 501	
 502	//Replace all %-hex chars with literals and trim the input string 
 503	//  of whitespaces ...because it's shorter and more legible. 
 504	//  -Helene D. 11/18/07
 505	$instring = trim(stripslashes(rawurldecode(html_entity_decode($input)))," +\t");	//insecure
 506
 507	$inputlen=strlen($instring);
 508	$max=(is_numeric($max))?(integer)$max:$inputlen;
 509	//if($max>=$inputlen){return $input;};	//caused security loophole ...only $outstring should be returned
 510	if ($max < $inputlen) {
 511		$separator=($separator)?$separator:"(...)";
 512		$modulus=(($max%2));
 513		$halfMax=floor($max/2);
 514		$begin="";
 515		if(!$modulus){$begin=substr($instring, 0, $halfMax);}
 516		else{$begin=(!$exceedFromEnd)? substr($instring, 0, $halfMax+1) : substr($instring, 0, $halfMax);}
 517		$end="";
 518		if(!$modulus){$end=substr($instring,$inputlen-$halfMax);}
 519		else{$end=($exceedFromEnd)? substr($instring,$inputlen-$halfMax-1) :substr($instring,$inputlen-$halfMax);}
 520		$extracted=substr($instring, strpos($instring,$begin)+strlen($begin), $inputlen-$max );
 521		$outstring = $begin.$separator.$end;
 522		if (strlen($outstring) >= $inputlen) {  //Because "Fir(...)fox" is longer than "Firefox"
 523			$outstring = $instring;
 524		}
 525		//# use WordPress 2.x function attribute_escape and 1.2.x 
 526		//  function wp_specialchars to make malicious code 
 527		//  harmless when echoed to the screen
 528		$outstring=attribute_escape(wp_specialchars($outstring,ENT_QUOTES));
 529	} else {
 530		$outstring = attribute_escape(wp_specialchars($instring,ENT_QUOTES));
 531	}
 532	return $outstring;
 533} //end function stringShortener
 534
 535//# Return a value of true if url argument is a root url and false when
 536//#  url constains a subdirectory path or query parameters...
 537//#  - Helene D. 2007
 538function url_rootcheck($urltocheck) {
 539	$isroot = false;
 540	//url must begin with 'http://'
 541	if (strncasecmp($urltocheck,'http://',7) == 0) {
 542		$isroot = true;
 543		$urlparts=parse_url($urltocheck);
 544		if (!empty($urlparts['path']) && $urlparts['path'] != "/") {
 545			$isroot=false;
 546		} elseif (!empty($urlparts['query'])) {
 547			$isroot=false;
 548		}
 549	}
 550	return $isroot;
 551}
 552
 553//#from a page/post url input, output a url with "$blogurl" prepended for 
 554//#  blogs that have wordpress installed in a separate folder
 555//#  -Helene D. 1/22/08
 556function wAddSiteurl($inputurl) {
 557	$wpurl = rtrim(get_bloginfo('wpurl'),"/");
 558	$blogurl = rtrim(get_bloginfo('home'),"/");
 559	if (strcasecmp($blogurl, $wpurl) == 0) {
 560		$outputurl=$inputurl;
 561	} elseif (stristr($inputurl,$blogurl) === FALSE && url_rootcheck($blogurl))  {
 562		$outputurl=$blogurl."/".ltrim($inputurl,"/");
 563	} else {
 564		$outputurl=$inputurl;
 565	}
 566	$outputurl = rawurldecode(html_entity_decode($outputurl)); //dangerous
 567	$outputurl = wCleanURL($outputurl);	//safe
 568	return $outputurl;
 569}
 570
 571//sanitize url of potentially dangerous code before display
 572function wCleanURL($url="") { 
 573	if (empty($url)) { 
 574		return;
 575	}
 576	//$urlstring = stripslashes($url);
 577	if (function_exists('esc_url')) {	//#WP 2.8+
 578		$cleaned_url = esc_url(stripslashes($url));
 579	} else {
 580		$cleaned_url = clean_url(stripslashes($url));
 581	}
 582	if (empty($cleaned_url)) {	//oops, clean_url chomp
 583		$cleaned_url = attribute_escape(stripslashes($url));
 584	}
 585	return $cleaned_url;
 586} //end function
 587
 588//Output wassup records in Digg spy style...
 589function spyview ($from_date="",$to_date="",$rows="999",$spytype="",$spy_datasource="") {
 590	global $wpdb, $wp_version, $debug_mode;
 591
 592	$whereis="";
 593	if ($spytype == 'spider') {
 594		$whereis = " AND spider!=''";
 595	} elseif ($spytype == 'nospider') {
 596		$whereis = " AND spider=''";
 597	} elseif ($spytype == 'spam') {
 598		$whereis = " AND spam>0";
 599	} elseif ($spytype == 'nospam') {
 600		$whereis = " AND spam=0";
 601	} elseif ($spytype == 'nospamspider') {
 602		$whereis = " AND spam=0 AND spider=''";
 603	} elseif ($spytype == 'searchengine') {
 604		$whereis = " AND searchengine!='' AND search!=''";
 605	} elseif ($spytype == 'referrer') {
 606		$whereis = " AND referrer!='' AND referrer NOT LIKE '%$wpurl%' AND searchengine='' AND search=''";
 607	} elseif ($spytype == 'comauthor') {
 608		$whereis = " AND comment_author!=''";
 609	} elseif ($spytype == 'loggedin') {
 610		$whereis = " AND username!=''";
 611	}
 612	//check for arguments...
 613	if(empty($to_date)) $to_date = wassup_get_time();
 614	if (empty($from_date)) $from_date = ($to_date - 5);
 615	if (empty($spy_datasource)) {
 616		//temp table is default data source unless not exists
 617		$spy_datasource = $wpdb->prefix . "wassup_tmp";
 618		if ($wpdb->get_var("SHOW TABLES LIKE '$spy_datasource'") != $spy_datasource) { 
 619			$spy_datasource = $wpdb->prefix . "wassup";
 620		}
 621	}
 622
 623	if (function_exists('get_option')) {
 624		$wassup_settings = get_option('wassup_settings');
 625	}
 626	if (!empty($wassup_settings['wassup_screen_res'])) {
 627		$screen_res_size = (int) $wassup_settings['wassup_screen_res'];
 628	} else { 
 629		$screen_res_size = 670;
 630	}
 631	$max_char_len = ($screen_res_size)/10;
 632	//set smaller screen_res_size to make room for sidebar in WP2.7+
 633	if (version_compare($wp_version, '2.7', '>=')) { 
 634		$screen_res_size = $screen_res_size-160;
 635		$max_char_len = $max_char_len-16;
 636	}
 637	$wpurl = get_bloginfo('wpurl');
 638	$blogurl = get_bloginfo('home');
 639	$unclass = "sum-box";
 640
 641	$qryC = $wpdb->get_results("SELECT id, wassup_id, `timestamp`, ip, hostname, searchengine, urlrequested, agent, referrer, spider, username, comment_author FROM $spy_datasource WHERE `timestamp` BETWEEN $from_date AND $to_date $whereis ORDER BY `timestamp` DESC");
 642	if (!empty($qryC)) {
 643		//restrict # of rows to display when needed...
 644		$row_count = 0;
 645	//display the rows...
 646	foreach ($qryC as $cv) {
 647		$unclass = "sum-box";
 648		if ( $row_count < (int)$rows ) {
 649		   $timestamp = $cv->timestamp;
 650		   $ip = @explode(",", $cv->ip);
 651		   if ($cv->referrer != '') {
 652		   	if ($cv->searchengine != "" || stristr($cv->referrer,$wpurl)!=$cv->referrer) { 
 653		   	if ($cv->searchengine == "") {
 654				$referrer = '<a href="'.wCleanURL($cv->referrer).'" target=_"BLANK"><span style="font-weight: bold;">'.stringShortener("{$cv->referrer}", round($max_char_len*.8,0)).'</span></a>';
 655		   	} else {
 656				 $referrer = '<a href="'.wCleanURL($cv->referrer).'" target=_"BLANK">'.stringShortener("{$cv->referrer}", round($max_char_len*.9,0)).'</a>';
 657		   	}
 658		   	} else { 
 659		   		$referrer = __('From your blog','wassup');
 660		   	}
 661		   } else {
 662		   	$referrer = __('Direct hit','wassup');
 663		   } 
 664		   // User is logged in or is a comment's author
 665		   if ($cv->username != "") {
 666		   	$unclass .= "-log";
 667		   	$map_icon = "marker_loggedin.png";
 668		   } elseif ($cv->comment_author != "") {
 669		   	$unclass .= "-aut";
 670			$map_icon = "marker_author.png";
 671		   } elseif ($cv->spider != "") {
 672		   	$unclass .= "-spider";
 673		   	$map_icon = "marker_bot.png";
 674		   } else {
 675		   	$map_icon = "marker_user.png";
 676		   }
 677
 678		// Start getting GEOIP info
 679		   $location="";
 680		   $lat = 0;
 681		   $lon = 0;
 682		   if (function_exists('curl_init')) {
 683			//TODO: save geo data in 'wassup_tmp_geoloc' table
 684			//      so multi-page visits from save ip don't do
 685			//      redundant curl lookups
 686		   	$geo_url = "http://api.hostip.info/get_html.php?ip=".$ip[0]."&position=true";
 687		   	$ci = curl_init();
 688
 689		   	curl_setopt($ci, CURLOPT_URL, $geo_url);
 690		   	curl_setopt($ci, CURLOPT_HEADER,0);
 691		   	curl_setopt($ci, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
 692		   	@curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 0);
 693		   	curl_setopt($ci, CURLOPT_RETURNTRANSFER, 1);
 694
 695		   	$data = curl_exec($ci);
 696		   	curl_close($ci);
 697
 698	 	   	$data = explode("\n",$data);
 699		   	$loc_country = "";
 700			$loc_city = "";
 701			if (stristr("unknown", $data[0]) === FALSE) {
 702		   		$loc_country = preg_replace('/country: /i', "", $data[0]);
 703		   	}
 704		   	if (!empty($data[1]) && stristr("unknown", $data[1]) === FALSE) {
 705		   		$loc_city = preg_replace('/city: /i', '', $data[1]);
 706		   	}
 707			$geoloc = trim($loc_country." ".$loc_city);
 708			if ($debug_mode) {
 709				echo "<!--\n Curl data: \n"; //debug
 710				echo var_dump($data);	//debug
 711				echo "\n geoloc=$geoloc \n";	//debug
 712				echo "-->\n"; //debug
 713			}
 714
 715		   	if ($wassup_settings['wassup_geoip_map'] == 1) {
 716		   		$gkey = $wassup_settings['wassup_googlemaps_key'];
 717		   	if ($geoloc != "") {
 718		   		$geocode = geocodeWassUp($geoloc, $gkey);
 719		   		if($geocode[0] != 200) {
 720		   			$lat = explode(":", $data[2]);
 721		   			$lat = $lat[1];
 722		      			$lon = explode(":", $data[3]);
 723		   			$lon = $lon[1];
 724		   		} else { 
 725		   			$lat = $geocode[2];
 726		   			$lon = $geocode[3];
 727		   		}
 728		   	}
 729		   	}
 730		   	$location = $data[0];
 731		   	if (!empty($data[1])) { 
 732				$location .= " - ".$data[1];
 733			}
 734		   	echo "<!-- heartbeat -->\n";
 735		   } //end if curl_init
 736
 737	// Print the JS code to add marker on the map
 738	if ($wassup_settings['wassup_geoip_map'] == 1) {
 739		if ($lat!=0 && $lon!=0) {
 740		$item_id = $cv->id;
 741		$img_dir = WASSUPURL.'/img';
 742                echo "
 743                <script type=\"text/javascript\">
 744                var icon$item_id = new GIcon();
 745                icon$item_id.image = '".$img_dir."/".$map_icon."';
 746                icon$item_id.shadow = '$img_dir/shadow.png';
 747                icon$item_id.iconSize = new GSize(20.0, 34.0);
 748                icon$item_id.shadowSize = new GSize(38.0, 34.0);
 749                icon$item_id.iconAnchor = new GPoint(10.0, 17.0);
 750                icon$item_id.infoWindowAnchor = new GPoint(10.0, 17.0);
 751                var point = new GLatLng($lat,$lon);
 752                var marker$item_id = new GMarker(point, icon$item_id);
 753                map.addOverlay(marker$item_id);
 754                GEvent.addListener(marker$item_id, 'click', function() {
 755                marker$item_id.openInfoWindowHtml('<div style=\"white-space:nowrap\"><div class=\"bubble\">Ip: ".
 756			$ip[0]
 757			."<br />Hour: ".
 758			gmdate('H:i:s', $timestamp)
 759			."<br />Request: <a href=".
 760			wAddSiteurl($cv->urlrequested)
 761			." target=\"_BLANK\">".
 762			stringShortener($cv->urlrequested, round($max_char_len*.9,0))
 763			."</a><br />".
 764			"</div></div>');
 765                });
 766                map.panTo(new GLatLng($lat,$lon),3);
 767                </script>";
 768                } //end if $lat!=0
 769	} // end if wassup_geoip_map
 770?>
 771		<div class="sum-spy">
 772		<span class="<?php print $unclass; ?>">
 773		   	<?php print $ip[0]; ?></span>
 774		<div class="sum-det-spy"><span class="det1">
 775		<?php
 776			print '<a href="'.wAddSiteurl("{$cv->urlrequested}").'" target="_BLANK">';
 777			print stringShortener("{$cv->urlrequested}", round($max_char_len*.9,0)); ?>
 778		</a></span><br />
 779		<span class="det2"><strong><?php print gmdate("H:i:s", $timestamp); ?> - </strong>
 780		<?php 
 781		print $referrer;
 782		if (!empty($location)) {
 783			print "<br />".$location; 
 784		} ?>
 785		</span>
 786		</div>
 787		</div>
 788<?php
 789		} //end if row_count
 790		$row_count=$row_count+1;
 791		} //end foreach
 792	} else {
 793		//display "no activity" periodically so we know spy is running...
 794		if ((int)$to_date%59 == 0 ) {
 795			echo '<div class="sum-spy"><span class="det3">'.gmdate("H:i:s",$to_date).' - '.__("No visitor activity","wassup").' &nbsp; &nbsp; :-( &nbsp; </span></div>';
 796		}
 797	} //end if !empty($qryC)
 798} //end function spyview
 799
 800// Geocoding location with Google Maps
 801function geocodeWassUp($location, $key) {
 802	//Three parts to the querystring: q is address, output is the format (
 803	$address = urlencode($location);
 804	$url = "http://maps.google.com/maps/geo?q=".$address."&output=csv&key=".$key;
 805
 806	$ch = curl_init();
 807
 808	curl_setopt($ch, CURLOPT_URL, $url);
 809	curl_setopt($ch, CURLOPT_HEADER,0);
 810	curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
 811	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
 812	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 813
 814	$data = curl_exec($ch);
 815	curl_close($ch);
 816
 817	$data = explode(",",$data);
 818	if ($data[0] == 200) {
 819		return $data;
 820
 821	} else {
 822		$error = $data[0];
 823		return $error;
 824	}
 825}
 826
 827/* wGetStats- Return an associative array containing the top statistics 
 828 *  numbers of "stat_type" from wassup table. Associative array fields are 
 829 *  'top_count', 'top_item', and optionally, 'top_link', when data is url.
 830 *  Results are sorted in descending count order and known spam is 
 831 *  automatically excluded when spam check is enabled in 'Wassup Options'.
 832 * Input parameters are 'stat_type'=[name of any column in wassup table],
 833 * and 2 optional parameters: 
 834 *  stat_limit=N-- limits results to the top N values. Default=10.
 835 *  stat_condition='mysql where clause'-- usually a date range clause on 
 836 *  `timestamp`.  Defaults to 24 hours.
 837 * Used by action.php TopTen and wassup_widget to retrieve statistics data.
 838 * - Helene D. 2009-03-04
 839 */
 840function wGetStats($stat_type, $stat_limit=10, $stat_condition="") {
 841	global $wpdb, $debug_mode;
 842
 843	$wassup_settings = get_option('wassup_settings');
 844	$top_ten = unserialize(html_entity_decode($wassup_settings['wassup_top10']));
 845	$wpurl =  get_bloginfo('wpurl');
 846	$blogurl =  get_bloginfo('home');
 847	$table_name = (!empty($wassup_settings['wassup_table']))? $wassup_settings['wassup_table'] : $wpdb->prefix . "wassup";
 848	$table_tmp_name = $table_name . "_tmp";
 849
 850	if (empty($stat_limit) || !(is_numeric($stat_limit))) {
 851		$stat_limit=10;
 852	}
 853	if (empty($stat_condition)) {
 854		$to_date = wassup_get_time();
 855		$from_date = ((int)$to_date - 24*(60*60)); //24 hours
 856		$stat_condition = " `timestamp` >= $from_date ";
 857	}
 858	//exclude spam if it is being recorded
 859	if ($wassup_settings['wassup_spamcheck'] == 1) {
 860		$spam_condition = " AND spam=0";
 861	} else {
 862		$spam_condition = "";
 863	}
 864	$stat_condition .= $spam_condition; 
 865
 866	//get the stats data
 867	//top search phrases...
 868	if ($stat_type == "searches") {
 869		$stat_results = $wpdb->get_results("SELECT count(search) AS top_count, search AS top_item, referrer AS top_link FROM $table_name WHERE $stat_condition AND search!='' AND spider='' GROUP BY search ORDER BY top_count DESC LIMIT $stat_limit");
 870
 871	//top external referrers...
 872	} elseif ($stat_type == "referrers") {
 873		//exclude internal referrals
 874		$url = parse_url($blogurl);
 875		$sitedomain = $url['host'];
 876		$exclude_list = $sitedomain;
 877		if ($wpurl != $blogurl) {
 878			$url = parse_url($wpurl);
 879			$wpdomain = $url['host'];
 880			$exclude_list .= ",".$wpdomain;
 881		}
 882		//exclude external referrers
 883		if (!empty($top_ten['topreferrer_exclude'])) {
 884			$exclude_list .= ",".$top_ten['topreferrer_exclude'];
 885		}
 886		//create mysql conditional statement to exclude referrers
 887		$exclude_referrers = "";
 888		$exclude_array = array_unique(explode(",", $exclude_list));
 889		foreach ($exclude_array as $exclude_domain) {
 890			$exclude_domain = trim($exclude_domain);
 891			if ($exclude_domain != "" ) {
 892				$exclude_referrers .= " AND referrer NOT LIKE 'http://".$exclude_domain."%' AND referrer NOT LIKE 'http://www.".$exclude_domain."%'";
 893			}
 894		}
 895		$stat_results = $wpdb->get_results("SELECT count(*) AS top_count, LOWER(referrer) AS top_item, referrer AS top_link FROM $table_name WHERE $stat_condition AND referrer!='' AND search='' AND spider='' $exclude_referrers GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
 896
 897	//top url requests...
 898	} elseif ($stat_type == "urlrequested") {
 899		$stat_results = $wpdb->get_results("SELECT count(*) AS top_count, LOWER(REPLACE(urlrequested, '/', '')) AS top_group, LOWER(urlrequested) AS top_item, urlrequested AS top_link FROM $table_name WHERE $stat_condition GROUP BY top_group ORDER BY top_count DESC LIMIT $stat_limit");
 900
 901	//top browser...
 902	} elseif ($stat_type == "browser") {
 903		$stat_results = $wpdb->get_results("SELECT count(*) AS top_count, SUBSTRING_INDEX(SUBSTRING_INDEX(browser, ' 0.', 1), '.', 1) AS top_item FROM $table_name WHERE $stat_condition AND `browser`!='' AND `browser` NOT LIKE 'N/A%' AND `spider`='' GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
 904
 905	//top os...
 906	} elseif ($stat_type == "os") {
 907		$stat_results = $wpdb->get_results("SELECT count(os) as top_count, `os` AS top_item FROM $table_name WHERE $stat_condition AND `os`!='' AND `os` NOT LIKE 'N/A%' AND spider='' GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
 908
 909	//top language/locale..
 910	} elseif ($stat_type == "language" || $stat_type == "locale") {
 911		$stat_results = $wpdb->get_results("SELECT count(LOWER(language)) as top_count, LOWER(language) as top_item FROM $table_name WHERE $stat_condition AND language!='' AND spider='' GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
 912
 913	} else {
 914		//TODO: check that wp_wassup.$stat_type column exist and is char
 915		if (!empty($stat_type)) {
 916			$stat_results = $wpdb->get_results("SELECT count($stat_type) AS top_count, `$stat_type` AS top_item FROM $table_name WHERE $stat_condition AND `$stat_type`!='' AND `$stat_type` NOT LIKE 'N/A%' GROUP BY `$stat_type` ORDER BY top_count DESC LIMIT $stat_limit");
 917		}
 918	}
 919
 920	if (!empty($stat_results[0]->top_count)) {
 921		return $stat_results;
 922	} else { 
 923		return array();
 924	}
 925} //end function wGetStats
 926
 927function backup_wassup($savefile="") {	//untested
 928	global $wpdb, $wassup_options;
 929	//# save to server file, $savefile - alternate method to export wassup table.
 930	//#   Useful when browser keeps timing out during export. -Helene D. 2009-03-16
 931	if (!empty($savefile)) {
 932		$savedir = dirname($savefile);
 933	} else {
 934		$savefile="wassup_backup.php";
 935		$savedir = "";
 936	}
 937	//use web root or home directory for backup, if full path not specified
 938	if ($savedir == "" || preg_match('#^/#',$savefile)==0) { 
 939		if (!empty($_ENV['DOCUMENT_ROOT'])) {
 940			$savedir = $_ENV['DOCUMENT_ROOT'];
 941			$savefile = rtrim($_ENV['DOCUMENT_ROOT'],'/').'/'.$savefile;
 942		} elseif (!empty($_ENV['HOME'])) {
 943			$savedir = $_ENV['HOME'];
 944			$savefile = rtrim($_ENV['HOME'],'/').'/'.$savefile;
 945		}
 946	}
 947	if (!$wassup_options->isWritableFolder($savedir)) {
 948		//unable to save to file
 949		$wassup_options->wassup_alert_message = "ERROR: Unable to Save file to $savedir";
 950		$wassup_option->saveOptions();
 951		return false;
 952	} else {
 953		$records = $wpdb->get_results("SELECT * FROM $table_name");
 954		$wassup_rec = array_map('stripslashes',$records);
 955		$fb = @fopen($savefile,'w');
 956		if (!$fb) { 
 957			$wassup_options->wassup_alert_message = "ERROR: Unable to backup to file, $savefile";
 958			$wassup_option->saveOptions();
 959			return false;
 960		} else { 
 961			$bytes=0;
 962			foreach ($records as $record) {
 963				$wassup_data=sprintf("INSERT INTO `wp_wassup` (`wassup_id`, `timestamp`, `ip`, `hostname`, `urlrequested`, `agent`, `referrer`, `search`, `searchpage`, `os`, `browser`, `language`, `screen_res`, `searchengine`, `spider`, `feed`, `username`, `comment_author`, `spam`) VALUES '%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s'\n", mysql_real_escape_string($record->wassup_id),
 964			mysql_real_escape_string($record->timestamp),
 965			mysql_real_escape_string($record->ip),
 966			mysql_real_escape_string($record->hostname),
 967			mysql_real_escape_string($record->urlrequested),
 968			mysql_real_escape_string($record->agent),
 969			mysql_real_escape_string($record->referrer),
 970			mysql_real_escape_string($record->search),
 971			mysql_real_escape_string($record->searchpage),
 972			mysql_real_escape_string($record->os),
 973			mysql_real_escape_string($record->browser),
 974			mysql_real_escape_string($record->language),
 975			mysql_real_escape_string($record->screen_res),
 976			mysql_real_escape_string($record->searchengine),
 977			mysql_real_escape_string($record->spider),
 978			mysql_real_escape_string($record->feed),
 979			mysql_real_escape_string($record->username),
 980			mysql_real_escape_string($record->comment_author),
 981			mysql_real_escape_string($record->spam));
 982
 983				$bytes += fwrite($fb, $wassup_data);
 984			} //end foreach
 985			fclose($fb);
 986			$wassup_options->wassup_alert_message = "$bytes Wassup data bytes saved file to $savefile";
 987			$wassup_option->saveOptions();
 988			return $bytes;
 989		} //end else fb
 990	} //end else wassup_options
 991} //end function
 992
 993// How many digits have an integer
 994function digit_count($n, $base=10) {
 995
 996  if($n == 0) return 1;
 997
 998  if($base == 10) {
 999    # using the built-in log10(x)
1000    # might be more accurate than log(x)/log(10).
1001    return 1 + floor(log10(abs($n)));
1002  }else{
1003    # here  logB(x) = log(x)/log(B) will have to do.
1004   return 1 + floor(log(abs($n))/ log($base));
1005  }
1006}
1007
1008//Round the integer to the next near 10
1009function roundup($value) {
1010	$dg = digit_count($value);
1011	if ($dg <= 2) {
1012		$dg = 1;
1013	} else {
1014		$dg = ($dg-2);
1015	}
1016	return (ceil(intval($value)/pow(10, $dg))*pow(10, $dg)+pow(10, $dg));
1017}
1018
1019function chart_data($Wvisits, $pages=null, $atime=null, $type, $charttype=null, $axes=null, $chart_type=null) {
1020	global $debug_mode;
1021	$chartAPIdata = false;
1022// Port of JavaScript from http://code.google.com/apis/chart/
1023// http://james.cridland.net/code
1024   // First, find the maximum value from the values given
1025   if ($axes == 1) {
1026	$maxValue = roundup(max(array_merge($Wvisits, $pages)));
1027	//$maxValue = roundup(max($Wvisits));
1028	$halfValue = ($maxValue/2); 
1029	$maxPage = $maxValue;
1030   } else {
1031	$maxValue = roundup(max($Wvisits));
1032	$halfValue = ($maxValue/2);
1033	$maxPage = roundup(max($pages));
1034	$halfPage = ($maxPage/2);
1035   }
1036
1037   // A list of encoding characters to help later, as per Google's example
1038   $simpleEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1039
1040   $chartData = "s:";
1041
1042	// Chart type has two datasets
1043	if ($charttype == "main") {
1044		$label_time = "";
1045		for ($i = 0; $i < count($Wvisits); $i++) {
1046			$currentValue = $Wvisits[$i];
1047			$currentTime = $atime[$i];
1048			if ($chart_type == "dashboard") {
1049				$label_time="|";
1050			} else {
1051				$label_time.=str_replace(' ', '+', $currentTime)."|";
1052			}
1053     
1054			if ($currentValue > -1) {
1055				$chartData.=substr($simpleEncoding,61*($currentValue/$maxValue),1);
1056			} else {
1057				$chartData.='_';
1058			}
1059		} 
1060		// Add pageviews line to the chart
1061		if (count($pages) != 0) {
1062			$chartData.=",";
1063			for ($i = 0; $i < count($pages); $i++) {
1064				$currentPage = $pages[$i];
1065				$currentTime = $atime[$i];
1066     
1067				if ($currentPage > -1) {
1068					$chartData.=substr($simpleEncoding,61*($currentPage/$maxPage),1);
1069				} else {
1070					$chartData.='_';
1071				}
1072			}
1073		}
1074		// Return the chart data - and let the Y axis to show the maximum value
1075   		if ($axes == 1) {
1076			$chartAPIdata=$chartData."&chxt=x,y&chxl=0:|".$label_time."1:|0|".$halfValue."|".$maxValue."&chxs=0,6b6b6b,9";
1077		} else {
1078			$chartAPIdata=$chartData."&chxt=x,y,r&chxl=0:|".$label_time."1:|0|".$halfValue."|".$maxValue."|2:|0|".$halfPage."|".$maxPage."&chxs=0,6b6b6b,9";
1079		}
1080	
1081	// Chart type has one one dataset
1082	// It's unused now
1083	} else {
1084		for ($i = 0; $i < count($Wvisits); $i++) {
1085			$currentValue = $Wvisits[$i];
1086			$currentTime = $atime[$i];
1087			$label_time.=str_replace(' ', '+', $currentTime)."|";
1088
1089			if ($currentValue > -1) {
1090				$chartData.=substr($simpleEncoding,61*($currentValue/$maxValue),1);
1091			} else {
1092				$chartData.='_';
1093			}
1094		}
1095		$chartAPIdata=$chartData."&chxt=x,y&chxl=0:|".$label_time."|1:|0|".$halfValue."|".$maxValue."&chxs=0,6b6b6b,9";
1096	}
1097	return $chartAPIdata;
1098
1099} //end function
1100
1101// Used to show main visitors details query, to count items and to extract data for main chart
1102class MainItems {
1103	// declare variables
1104        var $tableName;
1105        var $from_date;
1106        var $to_date;
1107        var $searchString;
1108        var $whereis;
1109        var $ItemsType;
1110        var $Limit;
1111        var $Last;
1112	var $WpUrl;
1113
1114	/* Constructor */
1115	function mainitems($table_name,$date_from,$date_to,$whereis=null,$limit=null) {
1116		global $wpdb;
1117		$this->tableName = $table_name;
1118		$this->from_date = $date_from;
1119		$this->to_date = $date_to;
1120		$this->whereis = $whereis;
1121		$this->limit = $limit;
1122	}
1123	/* Methods */
1124	// Function to show main query and count items
1125        function calc_tot($Type, $Search="", $specific_where_clause=null, $distinct_type=null) {
1126		global $wpdb, $wassup_options, $debug_mode;
1127
1128                $this->ItemsType = $Type;
1129		$this->searchString = $Search;
1130		$ss = "";
1131		if (!empty($Search) || !empty($specific_where_clause)) {
1132			$ss = $this->buildSearch($Search,$specific_where_clause);
1133		}
1134
1135		// Switch by every (global) items type (visits, pageviews, spams, etc...)
1136                switch ($Type) {
1137                        // This is the MAIN query to show the chronology
1138		case "main":
1139			//## Extend mysql wait timeout to 2.5 minutes and extend
1140			//#  php script timeout to 3 minutes to prevent script
1141			//#  hangs with large tables on slow server.
1142			if (!ini_get('safe_mode')) @set_time_limit(3*60);
1143			$results = $wpdb->query("SET wait_timeout = 160");
1144
1145			//TODO: use a subquery for MySQL 5+
1146			//main query
1147			//  - retrieve one row per wassup_id with timestamp = max(timestamp) (ie. latest record)
1148			// "sql_buffer_result" select option helps in cases where it takes a long time to retrieve results.  -Helene D. 2/29/09
1149			$qry = sprintf("SELECT SQL_BUFFER_RESULT *, max(`timestamp`) as max_timestamp, count(wassup_id) as page_hits FROM %s WHERE `timestamp` >= %s %s %s GROUP BY wassup_id ORDER BY max_timestamp DESC %s",
1150				$this->tableName,
1151				$this->from_date, 
1152				$ss,
1153				$this->whereis,
1154				$this->Limit);
1155			$results = $wpdb->get_results($qry);
1156			//return $results;
1157			break;
1158		case "count":
1159			// These are the queries to count the items hits/pages/spam
1160			$qry = sprintf("SELECT COUNT(%s `wassup_id`) AS itemstot FROM %s WHERE `timestamp` >= %s %s %s",
1161					$distinct_type,
1162					$this->tableName,
1163					$this->from_date,
1164					$ss,
1165					$this->whereis);
1166			$results = $wpdb->get_var($qry);
1167			//$itemstot = $wpdb->get_var($qry);
1168			//return $itemstot;
1169			break;
1170		} //end switch
1171		if (!empty($results)) {
1172			return $results;
1173		} else {
1174			return false;
1175		}
1176	} //end function calc_tot
1177
1178	// $Ctype = chart's type by time
1179	// $Res = resolution
1180	// $Search = string to add to where clause
1181        function TheChart($Ctype, $Res, $chart_height, $Search="", $axes_type, $chart_bg, $chart_type=null) {
1182		global $wpdb, $debug_mode;
1183
1184		$mysqlversion=substr(mysql_get_server_info(),0,3);
1185		$this->searchString = $Search;
1186		$this->Last = $Ctype;
1187
1188		//# MySql 'FROM_UNIXTIME' converts a UTC timestamp to a
1189		//#  local datetime based on the server host timezone(TZ).
1190		//#  Wassup's 'timestamp' is neither UTC nor server host
1191		//#  time. It is Wordpress time and must be converted to
1192		//#  UTC minus the TZ difference between the server host
1193		//#  and Wordpress time offset to get an accurate output 
1194		//#  from 'FROM_UNIXTIME'
1195		$WPoffset = (int)(get_option("gmt_offset")*60*60);
1196		$UTCoffset = $WPoffset + ((int)date('Z') - $WPoffset);
1197		//
1198		//#for US/Euro date display: USA Timezone=USA date format.
1199		//TODO: Use date format in Wordpress to determine x-axis format
1200		if (in_array(date('T'), array("ADT","AST","AKDT","AKST","CDT","CST","EDT","EST","HADT","HAST","MDT","MST","PDT","PST"))) { 
1201			$USAdate = true;
1202		} else {
1203			$USAdate = false;
1204		}
1205		// Options by chart type
1206		switch ($Ctype) {
1207		case .4:
1208			$label = __("Last 6 Hours", "wassup");
1209			$strto = "6 hours";
1210			$Ctimeformat = "%H";
1211			$x_axes_label = "%H:00";
1212			break;
1213		case 7:
1214			$label = __("Last 7 Days", "wassup");
1215			$strto = "7 days";
1216			$Ctimeformat = "%d";
1217			if ($USAdate) { $x_axes_label = "%a %b %d"; }
1218			else { $x_axes_label = "%a %d %b"; }
1219			break;
1220		case 30:
1221			$label = __("Last Month", "wassup");
1222			$strto = "30 days";
1223			$Ctimeformat = "%d";
1224			if ($USAdate) { $x_axes_label = " %b %d"; }
1225			else { $x_axes_label = "%d %b"; }
1226			break;
1227		case 90:
1228			$label = __("Last 3 Months", "wassup");
1229			$strto = "3 months";
1230			$Ctimeformat = "%u";
1231			$x_axes_label = "%b, wk-%u";
1232			break;
1233		case 180:
1234			$label = __("Last 6 Months", "wassup");
1235			$strto = "6 months";
1236			$Ctimeformat = "%m";
1237			$x_axes_label = " %b %Y";
1238			break;
1239		case 365:
1240			$label = __("Last Year", "wassup");
1241			$strto = "12 months";
1242			$Ctimeformat = "%m";
1243			$x_axes_label = "%b %Y";
1244			break;
1245		case 0:
1246			$label = __("All Time", "wassup");
1247			$strto = "";
1248			$Ctimeformat = "%m";
1249			$x_axes_label = "%b %Y";
1250			break;
1251		case 1:
1252		default:
1253			$label = __("Last 24 Hours", "wassup");
1254			$strto = "24 hours";
1255			$Ctimeformat = "%H";
1256			$x_axes_label = "%H:00";
1257		}
1258
1259		// Add Search variable to WHERE clause
1260		$ss = $this->buildSearch($Search);
1261
1262                $hour_todate = $this->to_date;
1263		if ($strto != "") {
1264                	$hour_fromdate = strtotime("-".$strto, $hour_todate);
1265		} else {
1266                	$hour_fromdate = 0;
1267		}
1268		//if ($hour_fromdate == "") $hour_fromdate = strtotime("-24 hours", $hour_todate);
1269
1270		$qry = sprintf("SELECT COUNT(DISTINCT `wassup_id`) as items, COUNT(`wassup_id`) as pages, DATE_FORMAT(FROM_UNIXTIME(CAST((`timestamp` - %s) AS UNSIGNED)), '%s') as thedate FROM %s WHERE `timestamp` > %s %s %s GROUP BY DATE_FORMAT(FROM_UNIXTIME(CAST((`timestamp` - %s) AS UNSIGNED)), '%s') ORDER BY `timestamp`",
1271			$UTCoffset,
1272			$x_axes_label,
1273			$this->tableName,
1274			$hour_fromdate, 
1275			$this->whereis,
1276			$ss, 
1277			$UTCoffset,
1278			$Ctimeformat);
1279                $aitems = $wpdb->get_results($qry,ARRAY_A);
1280		// Extract arrays for Visits, Pages and X_Axis_Label
1281		if (count($aitems) > 0) {
1282			foreach ($aitems as $bhits) {
1283      

Large files files are truncated, but you can click here to view the full file