Tuesday, February 26, 2013

simple class for calling a url using either curl or fopen


<?php
class EmailManager {
    var $_server;
    var $_account;

    const client_login_url = 'https://www.google.com/accounts/ClientLogin';

    function __construct($params = array())
    {
        if(!isset($params["server"])) {
            throw new Exception("Server name required.");
        }
        if(!isset($params["account"])) {
            throw new Exception("Account name required.");
        }
        $this->_account = $params["account"];
        $this->_server = $params["server"];
    }

    protected function authenticateUser($email, $password)
    {
        $postVariables = array(
            'accountType' => 'GOOGLE',
            'Email' => $email,
            'Passwd' => $password,
            'service' => 'analytics'
        );
        $response = $this->httpRequest(EmailManager::client_login_url, null, $postVariables);
    }

    protected function httpRequest($url, $get_variables=null, $post_variables=null, $headers=null)
    {
        $interface = null;
        if(function_exists('curl_exec')) {
            $interface = 'curl';
        } else {
            $interface = 'fopen';
        }
        if($interface == 'curl') {
            return $this->curlRequest($url, $get_variables, $post_variables, $headers);
        } else if($interface == 'fopen') {
            return $this->fOpenRequest($url, $get_variables, $post_variables, $headers);
        }
    }

    private function curlRequest($url, $get_variables=null, $post_variables=null, $headers=null)
    {
        $ch = curl_init();

        if(is_array($get_variables))
        {
            $get_variables = '?' . str_replace('&amp;','&',urldecode(http_build_query($get_variables)));
        }
        else
        {
            $get_variables = null;
        }

        curl_setopt($ch, CURLOPT_URL, $url . $get_variables);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //CURL doesn't like google's cert

        if(is_array($post_variables))
        {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $post_variables);
        }

        if(is_array($headers))
        {
            curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
        }

        $response = curl_exec($ch);
        $code = curl_getinfo($ch,CURLINFO_HTTP_CODE);

        curl_close($ch);

        return array('body'=>$response,'code'=>$code);
    }

    private function fOpenRequest($url, $get_variables=null, $post_variables=null, $headers=null)
    {
        $http_options = array('method'=>'GET','timeout'=>3);

        if(is_array($headers))
        {
            $headers = implode("\r\n",$headers) . "\r\n";
        }
        else
        {
            $headers = '';
        }

        if(is_array($get_variables))
        {
            $get_variables = '?' . str_replace('&amp;','&',urldecode(http_build_query($get_variables)));
        }
        else
        {
            $get_variables = null;
        }

        if(is_array($post_variables))
        {
            $post_variables = str_replace('&amp;','&',urldecode(http_build_query($post_variables)));
            $http_options['method'] = 'POST';
            $headers = "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($post_variables) . "\r\n" . $headers;
            $http_options['header'] = $headers;
            $http_options['content'] = $post_variables;
        }
        else
        {
            $post_variables = '';
            $http_options['header'] = $headers;
        }

        $context = stream_context_create(array('http'=>$http_options));
        $response = @file_get_contents($url . $get_variables, null, $context);

        return array('body'=>$response!==false?$response:'Request failed, fopen provides no further information','code'=>$response!==false?'200':'400');
    }
}
?>

Monday, February 25, 2013

restarting and reloading name server zone files

Restart zone files:
service named restart

Reload changed zone files:
rndc reload
 tail -f ./var/log/messages

Sunday, February 24, 2013

validating fqdn url email hostname using java regular expression

Using java Pattern class to validate the FQDN, URL, E-Mail address hostname


import java.io.*;
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 
 

public class Validator 
{
    private static final Pattern emailPattern = Pattern.compile("^[\\w\\-]([\\.\\w])+[\\w]+@([\\w\\-]+\\.)+[A-Z]{2,4}$", Pattern.CASE_INSENSITIVE);


    private static final Pattern fqdnPattern = Pattern.compile("(?=^.{1,254}$)(^(?:(?!\\d+\\.|-)[a-zA-Z0-9_\\-]{1,63}(?<!-)\\.?)+(?:[a-zA-Z]{2,})$)", Pattern.CASE_INSENSITIVE);

     private static final Pattern hostPattern = Pattern.compile("^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\\-]*[A-Za-z0-9])$", Pattern.CASE_INSENSITIVE);

    private static final Pattern urlPattern = Pattern.compile("[^(http\\:\\/\\/[a-zA-Z0-9_\\-]+(?:\\.[a-zA-Z0-9_\\-]+)*\\.[a-zA-Z]{2,4}(?:\\/[a-zA-Z0-9_]+)*(?:\\/[a-zA-Z0-9_]+\\.[a-zA-Z]{2,4}(?:\\?[a-zA-Z0-9_]+\\=[a-zA-Z0-9_]+)?)?(?:\\&[a-zA-Z0-9_]+\\=[a-zA-Z0-9_]+)*)$]", Pattern.CASE_INSENSITIVE);


    public static boolean isInteger(String intVal)
    {
        try {
            int i = new Integer(intVal);
            return true;
        } catch (Exception e) {
        }
        return false;
    }

    public static boolean isBoolean(String boolVal)
    {
        try {
            boolean b = new Boolean(boolVal);
            return true;
        } catch (Exception e) {
        }
        return false;
    }

    public static boolean isFloat(String floatVal)
    {
        try {
            float f = new Float(floatVal);
            return true;
        } catch (Exception e) {
        }
        return false;
    }

    public static boolean isLong(String logVal)
    {
        try {
            long l = new Long(logVal);
            return true;
        } catch(Exception e) {
        }
        return false;
    }

    public static boolean isFQDN(String fqdnVal)
    {
        try {
                   Matcher matcher = fqdnPattern.matcher(fqdnVal); 
                return matcher.matches(); 
        } catch (Exception e){
        }
        return false;


    }

    public static boolean isURL(String url)
    {
        try {
                   Matcher matcher = urlPattern.matcher(url); 
                return matcher.matches(); 
        } catch (Exception e){
        }
        return false;

    }

    public static boolean isEmailAddr(String emailAddr)
    {
        try {
                   Matcher matcher = emailPattern.matcher(emailAddr); 
                return matcher.matches(); 
        } catch (Exception e){
        }
        return false;
    }

    public static boolean isHost (String hostname)
    {
        try {
                   Matcher matcher = hostPattern.matcher(hostname); 
                return matcher.matches(); 
        } catch (Exception e){
        }
        return false;
    }

    public static void main(String args[])
    {
        try {
            String action = args[0];
            String input = args[1];
            boolean result = false;
            if (action.equals("email")) {
                result = isEmailAddr(input);   
            } else if (action.equals("host")) {
                result = isHost(input);
            } else if(action.equals("url")) {
                result = isURL(input);
            } else if(action.equals("fqdn")) {
                result = isFQDN(input);
            }
            System.out.println("RESULT : " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

shell script echo new line to file


var1="Hello"
var2="World!"
logwrite="$var1\n$var2"
echo -e "$logwrite"  >> /Users/username/Desktop/user.txt
Explanation:
The \n escape sequence indicates a line feed. Passing the -e argument to echo enables interpretation of escape sequences.
It may even be simplified further:
var1="Hello"
var2="World!"
echo -e "$var1\n$var2"  >> /Users/username/Desktop/user.txt
or even:
echo -e "Hello\nWorld! "  >> /Users/username/Desktop/user.txt

How to tell if a string is not defined in a bash shell script

#!/bin/bash

if [ -z $1 ]; then
        echo 'Enter something please.';
        exit 1;
fi;

How To Manually Create Zone Files For Domain Names In Linux Server


http://www.wallpaperama.com/forums/how-to-manually-create-zone-files-for-domain-names-in-linux-server-t1698.html

How To Manually Create Zone Files For Domain Names In Linux Server

today i am going to teach how you can add a domain name to your web server using BIND. these is my case:
  • i have a fedora core linux web server with apache and bind9
  • my bind is chroot jailed, if you have a directory called "chroot" in /var/named then you are also chroot jail
  • i have a domain name poitint to my server.
  • i have access to root
  • i have access to linux shell (via ssh)
these are my properties (example)
  1. My domain name: wallpaperama.com
  2. My nameserver for wallpaperama.com is: ns1.wallpaperama.com
  3. My email address is myemail@example.com
  4. My linux server ip address is: 70.238.57.57
  5. My linux server hostname is: ns1.wallpaperama.com


STEP 1. login to your shell as root

STEP 2. send this command to create our first file called : wallpaperama.com.hosts
nano /var/named/chroot/var/named/wallpaperama.com.hosts
this will open a blank file called wallpaperama.com.hosts with our text editor called nano. you can use vi if you want to, if you want to use vi, then replace the command with: vi /var/named/chroot/var/named/wallpaperama.com.hosts

STEP 3. Now that you have wallpaperama.com.hosts file, add the following information:
$ttl 38400
wallpaperama.com.    IN      SOA     localhost.localdomain. myemail@example.com. (
                        1184045571
                        10800
                        3600
                        604800
                        38400 )
wallpaperama.com.    IN      NS      localhost.localdomain.
www.wallpaperama.com.        IN      A       70.238.57.57

now if you look at the information, all you have to do is replaced the following with your own information:
wallpaperama.com (replace any wallpaperama.com with whatever your DOMAIN NAME is)
myemail@example.com (replace myemail@example.com with whatever your EMAIL name is)
70.238.57.57 (replace 70.238.57.57 with whatever your IP ADDRESS name is)
1184045571 (this has to be a unique number you haven't used before. some people use the curretn time and date, for example 200707011535 with is the year = 2007, month = 07, day = 01, hour = 15, minute = 35)
NOTE: its important to you keep the same format as it is on the example above. Make sure you use the same format exactly as it appears above. what i mean by the format is to make sure the { } ; are in the same line as my example, otherwise, when you restart your DNS server, it will fail. i tell you cuz it failed on me once.


STEP 4. Now you need to edit the named.conf file, send this command:
nano /var/named/chroot/etc/named.conf
it should look something like this:
options {
        directory "/etc";
        pid-file "/var/run/named/named.pid";
        };

zone "." {
        type hint;
        file "/etc/db.cache";
        };

zone "anydomain.com" {
        type master;
        file "/var/named/anydomain.com.hosts";
        };

STEP 5. now you need to edit named.conf to add your domain name. so in my example, i will be adding wallpaperama.com and now, this is how named.conf should look like:
options {
        directory "/etc";
        pid-file "/var/run/named/named.pid";
        };

zone "." {
        type hint;
        file "/etc/db.cache";
        };

zone "anydomain.com" {
        type master;
        file "/var/named/anydomain.com.hosts";

zone "wallpaperama.com" {
        type master;
        file "/var/named/wallpaperama.com.hosts";
        };
As you can see all i did was added wallpaperama.com at the bottom of the file:
type master; (this is a master zone )
file "/var/named/wallpaperama.com.hosts"; (this is the location of the file where we created the wallpaperama.com.hosts on STEP 4.
NOTE: make sure you use the same format exactly as it appears above. what i mean by the format is to make sure the { } ; are in the same line as my example, otherwise, when you restart your DNS server, it will fail. i tell you cuz it failed on me once.

STEP 6. Now that you have all the correct files, you will need to restart your DNS server for the changes to take affect. so restart your DNS server with the following command:
/etc/init.d/named restart


Now open your website on your browser and you should see your webserver.

this is what i got:


Ok, the next step would be to point to a directory specially for my domain instead of getting the default apache page right.

so this is how you do it: click on this link on how to add virtual domain names in apache server

Thursday, February 21, 2013

gapi.class.php gapi class for google analytics data

<?php
/**
 * GAPI - Google Analytics PHP Interface
 * 
 * http://code.google.com/p/gapi-google-analytics-php-interface/
 * 
 * @copyright Stig Manning 2009
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * @author Stig Manning <stig@sdm.co.nz>
 * @version 1.3
 * 
 */

class gapi
{
  const http_interface = 'auto'; //'auto': autodetect, 'curl' or 'fopen'
  
  const client_login_url = 'https://www.google.com/accounts/ClientLogin';
  const account_data_url = 'https://www.google.com/analytics/feeds/accounts/default';
  const report_data_url = 'https://www.google.com/analytics/feeds/data';
  const interface_name = 'GAPI-1.3';
  const dev_mode = false;
  
  private $auth_token = null;
  private $account_entries = array();
  private $account_root_parameters = array();
  private $report_aggregate_metrics = array();
  private $report_root_parameters = array();
  private $results = array();
  
  /**
   * Constructor function for all new gapi instances
   * 
   * Set up authenticate with Google and get auth_token
   *
   * @param String $email
   * @param String $password
   * @param String $token
   * @return gapi
   */
  public function __construct($email, $password, $token=null)
  {
    if($token !== null)
    {
      $this->auth_token = $token;
    }
    else 
    {
      $this->authenticateUser($email,$password);
    }
  }
  
  /**
   * Return the auth token, used for storing the auth token in the user session
   *
   * @return String
   */
  public function getAuthToken()
  {
    return $this->auth_token;
  }
  
  /**
   * Request account data from Google Analytics
   *
   * @param Int $start_index OPTIONAL: Start index of results
   * @param Int $max_results OPTIONAL: Max results returned
   */
  public function requestAccountData($start_index=1, $max_results=20)
  {
    $response = $this->httpRequest(gapi::account_data_url, array('start-index'=>$start_index,'max-results'=>$max_results), null, $this->generateAuthHeader());
    
    if(substr($response['code'],0,1) == '2')
    {
      return $this->accountObjectMapper($response['body']);
    }
    else 
    {
      throw new Exception('GAPI: Failed to request account data. Error: "' . strip_tags($response['body']) . '"');
    }
  }
  
  /**
   * Request report data from Google Analytics
   *
   * $report_id is the Google report ID for the selected account
   * 
   * $parameters should be in key => value format
   * 
   * @param String $report_id
   * @param Array $dimensions Google Analytics dimensions e.g. array('browser')
   * @param Array $metrics Google Analytics metrics e.g. array('pageviews')
   * @param Array $sort_metric OPTIONAL: Dimension or dimensions to sort by e.g.('-visits')
   * @param String $filter OPTIONAL: Filter logic for filtering results
   * @param String $start_date OPTIONAL: Start of reporting period
   * @param String $end_date OPTIONAL: End of reporting period
   * @param Int $start_index OPTIONAL: Start index of results
   * @param Int $max_results OPTIONAL: Max results returned
   */
  public function requestReportData($report_id, $dimensions, $metrics, $sort_metric=null, $filter=null, $start_date=null, $end_date=null, $start_index=1, $max_results=30)
  {
    $parameters = array('ids'=>'ga:' . $report_id);
    
    if(is_array($dimensions))
    {
      $dimensions_string = '';
      foreach($dimensions as $dimesion)
      {
        $dimensions_string .= ',ga:' . $dimesion;
      }
      $parameters['dimensions'] = substr($dimensions_string,1);
    }
    else 
    {
      $parameters['dimensions'] = 'ga:'.$dimensions;
    }

    if(is_array($metrics))
    {
      $metrics_string = '';
      foreach($metrics as $metric)
      {
        $metrics_string .= ',ga:' . $metric;
      }
      $parameters['metrics'] = substr($metrics_string,1);
    }
    else 
    {
      $parameters['metrics'] = 'ga:'.$metrics;
    }
    
    if($sort_metric==null&&isset($parameters['metrics']))
    {
      $parameters['sort'] = $parameters['metrics'];
    }
    elseif(is_array($sort_metric))
    {
      $sort_metric_string = '';
      
      foreach($sort_metric as $sort_metric_value)
      {
        //Reverse sort - Thanks Nick Sullivan
        if (substr($sort_metric_value, 0, 1) == "-")
        {
          $sort_metric_string .= ',-ga:' . substr($sort_metric_value, 1); // Descending
        }
        else
        {
          $sort_metric_string .= ',ga:' . $sort_metric_value; // Ascending
        }
      }
      
      $parameters['sort'] = substr($sort_metric_string, 1);
    }
    else 
    {
      if (substr($sort_metric, 0, 1) == "-")
      {
        $parameters['sort'] = '-ga:' . substr($sort_metric, 1);
      }
      else 
      {
        $parameters['sort'] = 'ga:' . $sort_metric;
      }
    }
    
    if($filter!=null)
    {
      $filter = $this->processFilter($filter);
      if($filter!==false)
      {
        $parameters['filters'] = $filter;
      }
    }
    
    if($start_date==null)
    {
      $start_date=date('Y-m-d',strtotime('1 month ago'));
    }
    
    $parameters['start-date'] = $start_date;
    
    if($end_date==null)
    {
      $end_date=date('Y-m-d');
    }
    
    $parameters['end-date'] = $end_date;
    
    
    $parameters['start-index'] = $start_index;
    $parameters['max-results'] = $max_results;
    
    $parameters['prettyprint'] = gapi::dev_mode ? 'true' : 'false';
    
    $response = $this->httpRequest(gapi::report_data_url, $parameters, null, $this->generateAuthHeader());
    
    //HTTP 2xx
    if(substr($response['code'],0,1) == '2')
    {
      return $this->reportObjectMapper($response['body']);
    }
    else 
    {
      throw new Exception('GAPI: Failed to request report data. Error: "' . strip_tags($response['body']) . '"');
    }
  }

  /**
   * Process filter string, clean parameters and convert to Google Analytics
   * compatible format
   * 
   * @param String $filter
   * @return String Compatible filter string
   */
  protected function processFilter($filter)
  {
    $valid_operators = '(!~|=~|==|!=|>|<|>=|<=|=@|!@)';
    
    $filter = preg_replace('/\s\s+/',' ',trim($filter)); //Clean duplicate whitespace
    $filter = str_replace(array(',',';'),array('\,','\;'),$filter); //Escape Google Analytics reserved characters
    $filter = preg_replace('/(&&\s*|\|\|\s*|^)([a-z]+)(\s*' . $valid_operators . ')/i','$1ga:$2$3',$filter); //Prefix ga: to metrics and dimensions
    $filter = preg_replace('/[\'\"]/i','',$filter); //Clear invalid quote characters
    $filter = preg_replace(array('/\s*&&\s*/','/\s*\|\|\s*/','/\s*' . $valid_operators . '\s*/'),array(';',',','$1'),$filter); //Clean up operators
    
    if(strlen($filter)>0)
    {
      return urlencode($filter);
    }
    else 
    {
      return false;
    }
  }
  
  /**
   * Report Account Mapper to convert the XML to array of useful PHP objects
   *
   * @param String $xml_string
   * @return Array of gapiAccountEntry objects
   */
  protected function accountObjectMapper($xml_string)
  {
    $xml = simplexml_load_string($xml_string);
    
    $this->results = null;
    
    $results = array();
    $account_root_parameters = array();
    
    //Load root parameters
    
    $account_root_parameters['updated'] = strval($xml->updated);
    $account_root_parameters['generator'] = strval($xml->generator);
    $account_root_parameters['generatorVersion'] = strval($xml->generator->attributes());
    
    $open_search_results = $xml->children('http://a9.com/-/spec/opensearchrss/1.0/');
    
    foreach($open_search_results as $key => $open_search_result)
    {
      $report_root_parameters[$key] = intval($open_search_result);
    }
    
    $account_root_parameters['startDate'] = strval($google_results->startDate);
    $account_root_parameters['endDate'] = strval($google_results->endDate);
    
    //Load result entries
    
    foreach($xml->entry as $entry)
    {
      $properties = array();
      foreach($entry->children('http://schemas.google.com/analytics/2009')->property as $property)
      {
        $properties[str_replace('ga:','',$property->attributes()->name)] = strval($property->attributes()->value);
      }
      
      $properties['title'] = strval($entry->title);
      $properties['updated'] = strval($entry->updated);
      
      $results[] = new gapiAccountEntry($properties);
    }
    
    $this->account_root_parameters = $account_root_parameters;
    $this->results = $results;
    
    return $results;
  }
  
  
  /**
   * Report Object Mapper to convert the XML to array of useful PHP objects
   *
   * @param String $xml_string
   * @return Array of gapiReportEntry objects
   */
  protected function reportObjectMapper($xml_string)
  {
    $xml = simplexml_load_string($xml_string);
    
    $this->results = null;
    $results = array();
    
    $report_root_parameters = array();
    $report_aggregate_metrics = array();
    
    //Load root parameters
    
    $report_root_parameters['updated'] = strval($xml->updated);
    $report_root_parameters['generator'] = strval($xml->generator);
    $report_root_parameters['generatorVersion'] = strval($xml->generator->attributes());
    
    $open_search_results = $xml->children('http://a9.com/-/spec/opensearchrss/1.0/');
    
    foreach($open_search_results as $key => $open_search_result)
    {
      $report_root_parameters[$key] = intval($open_search_result);
    }
    
    $google_results = $xml->children('http://schemas.google.com/analytics/2009');

    foreach($google_results->dataSource->property as $property_attributes)
    {
      $report_root_parameters[str_replace('ga:','',$property_attributes->attributes()->name)] = strval($property_attributes->attributes()->value);
    }
    
    $report_root_parameters['startDate'] = strval($google_results->startDate);
    $report_root_parameters['endDate'] = strval($google_results->endDate);
    
    //Load result aggregate metrics
    
    foreach($google_results->aggregates->metric as $aggregate_metric)
    {
      $metric_value = strval($aggregate_metric->attributes()->value);
      
      //Check for float, or value with scientific notation
      if(preg_match('/^(\d+\.\d+)|(\d+E\d+)|(\d+.\d+E\d+)$/',$metric_value))
      {
        $report_aggregate_metrics[str_replace('ga:','',$aggregate_metric->attributes()->name)] = floatval($metric_value);
      }
      else
      {
        $report_aggregate_metrics[str_replace('ga:','',$aggregate_metric->attributes()->name)] = intval($metric_value);
      }
    }
    
    //Load result entries
    
    foreach($xml->entry as $entry)
    {
      $metrics = array();
      foreach($entry->children('http://schemas.google.com/analytics/2009')->metric as $metric)
      {
        $metric_value = strval($metric->attributes()->value);
        
        //Check for float, or value with scientific notation
        if(preg_match('/^(\d+\.\d+)|(\d+E\d+)|(\d+.\d+E\d+)$/',$metric_value))
        {
          $metrics[str_replace('ga:','',$metric->attributes()->name)] = floatval($metric_value);
        }
        else
        {
          $metrics[str_replace('ga:','',$metric->attributes()->name)] = intval($metric_value);
        }
      }
      
      $dimensions = array();
      foreach($entry->children('http://schemas.google.com/analytics/2009')->dimension as $dimension)
      {
        $dimensions[str_replace('ga:','',$dimension->attributes()->name)] = strval($dimension->attributes()->value);
      }
      
      $results[] = new gapiReportEntry($metrics,$dimensions);
    }
    
    $this->report_root_parameters = $report_root_parameters;
    $this->report_aggregate_metrics = $report_aggregate_metrics;
    $this->results = $results;
    
    return $results;
  }
  
  /**
   * Authenticate Google Account with Google
   *
   * @param String $email
   * @param String $password
   */
  protected function authenticateUser($email, $password)
  {
    $post_variables = array(
      'accountType' => 'GOOGLE',
      'Email' => $email,
      'Passwd' => $password,
      'source' => gapi::interface_name,
      'service' => 'analytics'
    );
    
    $response = $this->httpRequest(gapi::client_login_url,null,$post_variables);
    
    //Convert newline delimited variables into url format then import to array
    parse_str(str_replace(array("\n","\r\n"),'&',$response['body']),$auth_token);
    
    if(substr($response['code'],0,1) != '2' || !is_array($auth_token) || empty($auth_token['Auth']))
    {
      throw new Exception('GAPI: Failed to authenticate user. Error: "' . strip_tags($response['body']) . '"');
    }
    
    $this->auth_token = $auth_token['Auth'];
  }
  
  /**
   * Generate authentication token header for all requests
   *
   * @return Array
   */
  protected function generateAuthHeader()
  {
    return array('Authorization: GoogleLogin auth=' . $this->auth_token);
  }
  
  /**
   * Perform http request
   * 
   *
   * @param Array $get_variables
   * @param Array $post_variables
   * @param Array $headers
   */
  protected function httpRequest($url, $get_variables=null, $post_variables=null, $headers=null)
  {
    $interface = gapi::http_interface;
    
    if(gapi::http_interface =='auto')
    {
      if(function_exists('curl_exec'))
      {
        $interface = 'curl';
      }
      else 
      {
        $interface = 'fopen';
      }
    }
    
    if($interface == 'curl')
    {
      return $this->curlRequest($url, $get_variables, $post_variables, $headers);
    }
    elseif($interface == 'fopen') 
    {
      return $this->fopenRequest($url, $get_variables, $post_variables, $headers);
    }
    else 
    {
      throw new Exception('Invalid http interface defined. No such interface "' . gapi::http_interface . '"');
    }
  }
  
  /**
   * HTTP request using PHP CURL functions
   * Requires curl library installed and configured for PHP
   * 
   * @param Array $get_variables
   * @param Array $post_variables
   * @param Array $headers
   */
  private function curlRequest($url, $get_variables=null, $post_variables=null, $headers=null)
  {
    $ch = curl_init();
    
    if(is_array($get_variables))
    {
      $get_variables = '?' . str_replace('&amp;','&',urldecode(http_build_query($get_variables)));
    }
    else 
    {
      $get_variables = null;
    }
    
    curl_setopt($ch, CURLOPT_URL, $url . $get_variables);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //CURL doesn't like google's cert
    
    if(is_array($post_variables))
    {
      curl_setopt($ch, CURLOPT_POST, true);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $post_variables);
    }
    
    if(is_array($headers))
    {
      curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
    }
    
    $response = curl_exec($ch);
    $code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
    
    curl_close($ch);
    
    return array('body'=>$response,'code'=>$code);
  }
  
  /**
   * HTTP request using native PHP fopen function
   * Requires PHP openSSL
   *
   * @param Array $get_variables
   * @param Array $post_variables
   * @param Array $headers
   */
  private function fopenRequest($url, $get_variables=null, $post_variables=null, $headers=null)
  {
    $http_options = array('method'=>'GET','timeout'=>3);
    
    if(is_array($headers))
    {
      $headers = implode("\r\n",$headers) . "\r\n";
    }
    else 
    {
      $headers = '';
    }
    
    if(is_array($get_variables))
    {
      $get_variables = '?' . str_replace('&amp;','&',urldecode(http_build_query($get_variables)));
    }
    else 
    {
      $get_variables = null;
    }
    
    if(is_array($post_variables))
    {
      $post_variables = str_replace('&amp;','&',urldecode(http_build_query($post_variables)));
      $http_options['method'] = 'POST';
      $headers = "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($post_variables) . "\r\n" . $headers;
      $http_options['header'] = $headers;
      $http_options['content'] = $post_variables;
    }
    else 
    {
      $post_variables = '';
      $http_options['header'] = $headers;
    }
    
    $context = stream_context_create(array('http'=>$http_options));
    $response = @file_get_contents($url . $get_variables, null, $context);  
    
    return array('body'=>$response!==false?$response:'Request failed, fopen provides no further information','code'=>$response!==false?'200':'400');
  }
  
  /**
   * Case insensitive array_key_exists function, also returns
   * matching key.
   *
   * @param String $key
   * @param Array $search
   * @return String Matching array key
   */
  public static function array_key_exists_nc($key, $search)
  {
    if (array_key_exists($key, $search))
    {
      return $key;
    }
    if (!(is_string($key) && is_array($search)))
    {
      return false;
    }
    $key = strtolower($key);
    foreach ($search as $k => $v)
    {
      if (strtolower($k) == $key)
      {
        return $k;
      }
    }
    return false;
  }
  
  /**
   * Get Results
   *
   * @return Array
   */
  public function getResults()
  {
    if(is_array($this->results))
    {
      return $this->results;
    }
    else 
    {
      return;
    }
  }
  
  
  /**
   * Get an array of the metrics and the matchning
   * aggregate values for the current result
   *
   * @return Array
   */
  public function getMetrics()
  {
    return $this->report_aggregate_metrics;
  }
  
  /**
   * Call method to find a matching root parameter or 
   * aggregate metric to return
   *
   * @param $name String name of function called
   * @return String
   * @throws Exception if not a valid parameter or aggregate 
   * metric, or not a 'get' function
   */
  public function __call($name,$parameters)
  {
    if(!preg_match('/^get/',$name))
    {
      throw new Exception('No such function "' . $name . '"');
    }
    
    $name = preg_replace('/^get/','',$name);
    
    $parameter_key = gapi::array_key_exists_nc($name,$this->report_root_parameters);
    
    if($parameter_key)
    {
      return $this->report_root_parameters[$parameter_key];
    }
    
    $aggregate_metric_key = gapi::array_key_exists_nc($name,$this->report_aggregate_metrics);
    
    if($aggregate_metric_key)
    {
      return $this->report_aggregate_metrics[$aggregate_metric_key];
    }

    throw new Exception('No valid root parameter or aggregate metric called "' . $name . '"');
  }
}

/**
 * Class gapiAccountEntry
 * 
 * Storage for individual gapi account entries
 *
 */
class gapiAccountEntry
{
  private $properties = array();
  
  public function __construct($properties)
  {
    $this->properties = $properties;
  }
  
  /**
   * toString function to return the name of the account
   *
   * @return String
   */
  public function __toString()
  {
    if(isset($this->properties['title']))
    {
      return $this->properties['title'];
    }
    else 
    {
      return;
    }
  }
  
  /**
   * Get an associative array of the properties
   * and the matching values for the current result
   *
   * @return Array
   */
  public function getProperties()
  {
    return $this->properties;
  }
  
  /**
   * Call method to find a matching parameter to return
   *
   * @param $name String name of function called
   * @return String
   * @throws Exception if not a valid parameter, or not a 'get' function
   */
  public function __call($name,$parameters)
  {
    if(!preg_match('/^get/',$name))
    {
      throw new Exception('No such function "' . $name . '"');
    }
    
    $name = preg_replace('/^get/','',$name);
    
    $property_key = gapi::array_key_exists_nc($name,$this->properties);
    
    if($property_key)
    {
      return $this->properties[$property_key];
    }
    
    throw new Exception('No valid property called "' . $name . '"');
  }
}

/**
 * Class gapiReportEntry
 * 
 * Storage for individual gapi report entries
 *
 */
class gapiReportEntry
{
  private $metrics = array();
  private $dimensions = array();
  
  public function __construct($metrics,$dimesions)
  {
    $this->metrics = $metrics;
    $this->dimensions = $dimesions;
  }
  
  /**
   * toString function to return the name of the result
   * this is a concatented string of the dimesions chosen
   * 
   * For example:
   * 'Firefox 3.0.10' from browser and browserVersion
   *
   * @return String
   */
  public function __toString()
  {
    if(is_array($this->dimensions))
    {
      return implode(' ',$this->dimensions);
    }
    else 
    {
      return '';
    }
  }
  
  /**
   * Get an associative array of the dimesions
   * and the matching values for the current result
   *
   * @return Array
   */
  public function getDimesions()
  {
    return $this->dimensions;
  }
  
  /**
   * Get an array of the metrics and the matchning
   * values for the current result
   *
   * @return Array
   */
  public function getMetrics()
  {
    return $this->metrics;
  }
  
  /**
   * Call method to find a matching metric or dimension to return
   *
   * @param $name String name of function called
   * @return String
   * @throws Exception if not a valid metric or dimensions, or not a 'get' function
   */
  public function __call($name,$parameters)
  {
    if(!preg_match('/^get/',$name))
    {
      throw new Exception('No such function "' . $name . '"');
    }
    
    $name = preg_replace('/^get/','',$name);
    
    $metric_key = gapi::array_key_exists_nc($name,$this->metrics);
    
    if($metric_key)
    {
      return $this->metrics[$metric_key];
    }
    
    $dimension_key = gapi::array_key_exists_nc($name,$this->dimensions);
    
    if($dimension_key)
    {
      return $this->dimensions[$dimension_key];
    }

    throw new Exception('No valid metric or dimesion called "' . $name . '"');
  }
}