<?php /* -*- Mode: php; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */

global $UTIL_DIR;

include_once($UTIL_DIR . "/convert.php");

class StatEntry {
  public $time;
  public $remoteaddr;
  public $page;
  public $agent;
  public $referer;
  public $uri;
}

class SiteStats {

  public $statsdir;
  public $stats = array();

  private $referers = array();
  private $pages = array();
  private $visitors = array();
  

  // Admin config
  public $admin_title = "Site Stats";
  public $admin_submodules = array("Overview" => "overview");

  public function admin_overview($action, $vars)
  {
    switch($action) {
    default:
      $this->readSingle(time());
      break;
    }
  }

  public function admin($sub, $action, $vars)
  {
    switch($sub) {
    case "overview":
      $this->admin_overview($action, $vars);

      $hits = 0;
      foreach($this->visitors as $k => $v) {
        $hits += $v;
      }

      echo "<p>".$hits." hits.</p>\n";

      echo "<p><strong>Referers:</strong></p>\n";
      echo "<ul>\n";
      foreach($this->referers as $k => $v) {
        echo "  <li>(".$v.") <a href=\"" . $k . "\">".$k."</a></li>\n";
      }
      echo "</ul>\n";

      $hits = 0;
      foreach($this->pages as $k => $v) {
        $hits += $v;
      }

      echo "<p><strong>Pages:</strong></p>\n";
      echo "<p>".$hits." hits.</p>\n";
      echo "<ul>\n";
      foreach($this->pages as $k => $v) {
        echo "  <li>(".$v.") <a href=\"?page=" . $k . "\">".$k."</a></li>\n";
      }
      echo "</ul>\n";

      echo "<p><strong>Visitors:</strong></p>\n"; 
      echo "<p>".sizeof($this->visitors)." unique visitors.</p>\n";
      echo "<ul>\n";
      foreach($this->visitors as $k => $v) {
        echo "  <li>(".$v.") ".$k."</li>\n";
      }
      echo "</ul>\n";

      break;
    }
  }

  private $top;
  private $entries = array();
  private $str;
  function cdata($parser, $cdata)
  {
    $this->str .= $cdata;
  }

  public function startElement($parser, $name, $attribs)
  {

    if($name == "E") {
      $this->top = array_push($this->entries, new StatEntry()) - 1;
      return;
    }

    $this->str = "";
  }
  
  public function endElement($parser, $name)
  {
    if($name == "T") $this->entries[$this->top]->time = $this->str;
    if($name == "RA") $this->entries[$this->top]->remoteaddr = $this->str;
    if($name == "P") $this->entries[$this->top]->page = $this->str;
    if($name == "A") $this->entries[$this->top]->agent = $this->str;
    if($name == "R") $this->entries[$this->top]->referer = $this->str;
    if($name == "U") $this->entries[$this->top]->uri = $this->str;
  }

  private function read($file)
  {
    $xml = file_get_contents($file);
    $xml = preg_replace('/&/', '@', $xml);
    
    $xmlhead = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<stats>\n";
    $xmlfoot = "</stats>\n";

    $parser = xml_parser_create();
    xml_set_object($parser, $this);
    xml_set_element_handler($parser, "startElement", "endElement");
    xml_set_character_data_handler($parser, "cdata");

    if (!xml_parse($parser, $xmlhead, FALSE)) {
      die(sprintf("XML error: %s at line %d",
                  xml_error_string(xml_get_error_code($parser)),
                  xml_get_current_line_number($parser)));
    }
    if (!xml_parse($parser, $xml, FALSE)) {
      die(sprintf("XML error: %s at line %d",
                  xml_error_string(xml_get_error_code($parser)),
                  xml_get_current_line_number($parser)));
    }
    if (!xml_parse($parser, $xmlfoot, TRUE)) {
      die(sprintf("XML error: %s at line %d",
                  xml_error_string(xml_get_error_code($parser)),
                  xml_get_current_line_number($parser)));
    }

    xml_parser_free($parser);

    foreach($this->entries as $entry) {

      $skip = false;
      if($entry->remoteaddr == "87.63.201.210") $skip = true;

      if(stripos($entry->agent, "bot") != FALSE) $skip = true;

      if($skip == true) continue;

      $this->visitors[$entry->remoteaddr]++;

      $url = $entry->referer;
      $url = preg_replace('/@/', '&', $url);

      // Don't show 'banned' urls.
      if(strpos($url, "executionroom.com") != FALSE ||
         strpos($url, "google") != FALSE ||
         strpos($url, "bing") != FALSE ||
         strpos($url, "viagra") != FALSE ||
         strpos($url, "inthesetimes.com") != FALSE ||
         strpos($url, "prescription") != FALSE ||
         $url == "") continue;

      if(strpos($url, "youtube.com") != FALSE) {
        $u = parse_url($url);
        parse_str($u['query']);
        if($v != "") {
          //print_r($u['query']);
          $youtubeurl = "http://www.youtube.com/watch?v=".$v;
          $this->referers[$youtubeurl]++;
          continue;
        }
      }

      // If url exists already without www remove www from this url.
      if(substr($url, 7, 3) == "www") {
        $surl = "http://" . substr($url, 11);
        if($this->referers[$surl]) $url = $surl;
      }
      $this->referers[$url]++;
      
      if($entry->page != "") $this->pages[$entry->page]++;
    }

    arsort($this->referers);
    arsort($this->pages);
    arsort($this->visitors);

  }

  /*
  private function read($file)
  {
    $xml = file_get_contents($file);
    
    $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<stats>\n" . $xml . "\n</stats>\n";

    $dom = new DomDocument;
    $dom->preserveWhiteSpace = TRUE;
    $dom->loadXML($xml);

    $entries = $dom->getElementsByTagName('e');

    foreach($entries as $entry) {
      $skip = false;
      $remoteaddrs = $entry->getElementsByTagName('ra');
      foreach($remoteaddrs as $remoteaddr) {
        $addr = $remoteaddr->textContent;
        if($addr == "87.63.201.210") $skip = true;
      }

      $agents = $entry->getElementsByTagName('a');
      foreach($agents as $agent) {
        $ag = $agent->textContent;
        if(stripos($ag, "bot") != FALSE) $skip = true;
      }

      if($skip == true) continue;

      $this->visitors[$addr]++;

      $refs = $entry->getElementsByTagName('r');
      foreach($refs as $ref) {
        $url = $ref->textContent;
        if(strpos($url, "executionroom.com") != FALSE ||
           strpos($url, "google") != FALSE ||
           strpos($url, "bing") != FALSE ||
           $url == "") {} else {
          if(substr($url, 7, 3) == "www") $url = "http://" . substr($url, 11);
          $this->referers[$url]++;
        }
      }

      $pages = $entry->getElementsByTagName('p');
      foreach($pages as $page) {
        $pg = $page->textContent;
        if($pg != "") $this->pages[$pg]++;
      }
    }

    arsort($this->referers);
    arsort($this->pages);
    arsort($this->visitors);
  }
  */
  public function log($loadtime)
  {
    $now = time();

    $str = "<e>".
      "<t>".xmlenc($now)."</t>". // Time
      "<ra>".xmlenc($_SERVER['REMOTE_ADDR'])."</ra>". // remote ip
      //      "<rh>".xmlenc($_SERVER['REMOTE_HOST'])."</rh>". // remote hostname
      //      "<l>".xmlenc($loadtime)."</l>". // Loadtime
      "<p>".xmlenc($GLOBALS['page'])."</p>". // Page
      //      $_SERVER['REMOTE_PORT'] . // current port
      //      $_SERVER['SCRIPT_FILENAME'] . // script name
      "<a>".xmlenc($_SERVER['HTTP_USER_AGENT'])."</a>". // User agent (browser)
      "<r>".xmlenc($_SERVER['HTTP_REFERER'])."</r>". // referer (link)
      "<u>".xmlenc($_SERVER['REQUEST_URI'])."</u>". // URI
      // GeoIP ??
      "</e>\n";

    $file = $this->getFilename($now);

    if(!file_exists(dirname($file))) mkdir(dirname($file), 0777, true);

    $fp = fopen($file, "a");
    fwrite($fp, $str);
    fclose($fp);
  }

  private function getFilename($timestamp)
  {
    $year = date("Y", $timestamp);
    $month = date("m", $timestamp);
    $file = $this->statsdir . "/" . $year . "/" . $month . ".xml";
    return $file;
  }

  private function readSingle($timestamp)
  {
    $file = $this->getFilename($timestamp);
    if(file_exists($file)) $this->read($file);
  }

  private function readAll()
  {
  }

  public function SiteStats($statsdir, $readall = false)
  {
    $this->statsdir = $statsdir;
    if(file_exists($statsdir) && is_dir($statsdir)) {
      if($readall) {
        $this->readAll();
      } else {
        // $this->readSingle(time());
      }
    }
  }

}

function sitestats_init()
{
  global $DATA_DIR;
  return new SiteStats($DATA_DIR."/sitestats", true);
}

?>