<?php

//PHPCIPHER NO ENCRYPT
// PHPLOCKITOPT NOENCODE
  // Tell Logaholic about this parser type.
  
  // Needs these parameters: Description (text description), ClassName (modify for each parser) and, AutoDiscoverable - true/false - must currently be true.
	$log_parser_types[] = Array("order" => "11", "Description" => "Apache Common/Combined, with leading hostname", "ClassName" => "ApacheCommonLogParserWithHostname", "AutoDiscoverable" => true);

	class ApacheCommonLogParserWithHostname extends GenericLogParser {
		
    var $scanEx;
		var $regEx;
		
		function Initialize($file) {
            $flogline=gzgets($file,5120);
            if (substr($flogline, 0, 1) =="#") {
                $this->lasterrormessage .= "# lines should not present in this format, aborting";
                return false;
            } else {
              $this->scanEx = '%s %s %s %s [%[^]]] "%s %s %[^"]" %d %s "%[^"]" "%[^"]"';
              // $this->regEx = '%^(.*)'. # Domain
              //   '\s'. # Space
              //   '(\S+)\s+\S+\s+(\S+)\s+\[([^]]+)\]\s+'.
              //   '"(?:-|(?:GET|POST|HEAD) ([^ ?]*?\??[^ ]+?)?\s?(?:HTTP/[0-9.]+)?|\\\x.*?)"'.
              //   '\s+([0-9]+)\s+([-0-9]+)\s+"(.*?)"\s+"(.*?)"\s*$%m';
				$this->regEx = '%^(.*)\\s'.   	# Domain
					'(\\S+)\\s+'.        		# IP Address
					'\\S+\\s+'.    				# IdentD user - totally unreliable and unused in all cases - ignore.
					'(\\S+)\\s+'. 				# authenticated user
					'\\[([^]]+)\\]\\s+'. 		# log entry date
												# URL and query.  Lots of optional stuff here.  A blank URL will be just -, so that shows up first with an or
												# If we have a non -, though, we'll have a GET, POST or HEAD, but we don't want to capture that (?:).
												# Then, we have the url - which is terminated by a space or a ? (or an implied ", which is specified later).
												# Optional parameter (?), then an optional protocol specifier (HTTP).												
					'"(?:-|(?:GET |POST | HEAD |\\\)([^ ?]*?\\??[^ ]+?)?\s?(?:HTTP/[0-9.]+)?)'.
					'"\\s+'.					# This *always* ends with a quote and a space, though - just a quote could be an embedded quote, but the quote, then space  
					'([0-9]+)\\s+'. 			# Status
					'([-0-9]+)\\s+'. 			# Bytes.
					'"(.*?)"\\s+'. 				# referrer.  This always ends with quote space.  Could have quotes in the referrer, though, so can't just look for that.
					'"(.*?)"\\s*'. 				# Agent. 
					'$'.     					# This ends things ($) 
					'%m';  						# the "m" modifier means to look at the entire text, not worrying about CR/LF's.  We always pass only a single line.
             return true;
            }
		}
		
		function ParseLine($line) {       
      		// if ($matches= sscanf($line, $this->scanEx)) {
      		if (preg_match($this->regEx, $line, $matches)) {
              $this->clientip = $matches[2];
              $long = ip2long($this->clientip);

              if ($long == -1 || $long === FALSE) {
                if(IsValidFQDN($matches[2])){
                  $this->clientip = $matches[2];
                } else {
                  return false;
                }
              }

              $this->authuser = $matches[3];

              $localtime = LogdateToStamp('d/M/Y:H:i:s O', $matches[4]);
              if (!$localtime) {
                $this->lastlineisdata = false;
                return false;
              } else {
                $this->logdate = $localtime;             
              }

              $this->reqfile = $matches[5];
              $this->status = (int)$matches[6];
              $this->bytes = $matches[7];
              if ($this->bytes == "-") {
                  $this->bytes = 0;
                }
              $this->referrer = $matches[8];
              $this->agent = $matches[9];
              $this->cookie = "";

      			  # Pre check line results
      			  if($this->status == 0){
      					$this->lastlineisdata = false;
      					return false;
      			  }
      				
      			  if($this->logdate == false){
      					$this->lastlineisdata = false;
      					return false;
      			  }
			  
              $this->lastlineisdata = true;
              return true;
        } else {
              $this->lastlineisdata = false;
              $this->lasterrormessage = "Unparseable log line:<br><pre>".$line."\n</pre>";
              // echo $line."\n Matches:" . print_r($matches);
              return false;
            }
		}
	}
	
?>
