<?php
// ct.php by alexander <http://www.astoever.no>
// a simple flatfile click-tracking script.
//
// Modified and named "c" on April 14, 2007 by Christian J. Robinson.
//
// As of January 2011:
// If the client sends a "X-Do-Not-Track: 1" / "DNT: 1" the click is still
// recorded, but the IP and timestamp are *NOT* logged; the logging output
// will report those events as "[anonymous]".
//
// Usage:
//
//  http://<site>/c?url=<url>
//    (i.e.: http://example.com/c?url=example)
//  http://<site>/c?findurls=<regexp>
//    (i.e.: http://example.com/c?findurls=^example)
//  http://<site>/c?adm=<password>
//  http://<site>/c?adm=<password>&url=<url>

/* The file pointed to by $config['URLfile'] below has the format of:

# comment
example = http://www.example.com/example.html

 * Note that the "example" part can not contain spaces.
 */

/* You can put the following in your .htaccess file to make Apache see this
 * script as PHP:

RewriteEngine on
RewriteRule ^c$ - [T=application/x-httpd-php]

 * And if you want to make sure the private directory isn't readable by the
 * outside world:

RewriteRule ^private/ - [F]

 * Note that you may need to change these lines to reflect your actual
 * configuration (the location of the script and files).
 */


// configuration

// Set your password, url database, and tracking database file:
$config['Password'] = 'xxx';  # Remember to change this!
$config['URLfile']  = 'private/click.urls';  # Make sure this file readable
$config['Database'] = 'private/click.data';  # Make sure this file is writable by httpd


// Configure the user agents, referers, hostnames, and IP addresses to ignore:
// (These are Perl regular expressions, case insensitive.)
$config['Ignore']['Agents']   = '\bgooglebot\b|\bmsnbot\b|Yahoo! Slurp|\bIRLbot\b|\bGigabot\b|\bAsk Jeeves\b|\bAttributor\.comBot\b|\bia_archiver\b';
$config['Ignore']['Referers'] = '\bgoogle\.com\b|\byahoo\.com\b';
$config['Ignore']['Hosts']    = '\bgooglebot\b|\bsearch\.live\b|\bcrawl\.yahoo\b|crawler\d+\.ask\.com|xcrawl\d\+\.alexa\.com';
$config['Ignore']['IPs']      = '';
// Note that these ignore patterns /do not/ stop the redirect functionality of
// this script, they only prevent logging of a "click".


// script begins

error_reporting(E_ALL E_NOTICE);

if(
is_readable('php/errors.php'))
  include 
"php/errors.php";

if(!
function_exists('error404'))
{
  function 
error404()
  {
    
$url func_get_args();
    
$url $url[0];

    
header("HTTP/1.1 404 Not Found");
    
header("Status: 404 Not Found");

    die(
"URL not found: $url");
  }
}

if(isset(
$_GET['source']))
  
print_source();

if(isset(
$_GET['busygif']))
  
print_busygif();

// make sure the script has been configured
if($config['Password'] === 'xxx')
  die(
"This script has not been configured! Aborting.");

// make sure the URL database exists
if(!is_readable($config['URLfile']))
  die(
"There is no file called <em>$config[URLfile]</em> in this directory,".
   
" or it isn't readable.<br />No redirects have been defined.");

// this forces you to make the blank db-file yourself
if(!is_readable($config['Database']) || !is_writable($config['Database']))
  die(
"There is no file called <em>$config[Database]</em> in this directory, ".
   
"or it isn't readable or writable.<br />".
   
"Please make a blank text-file called <em>$config[Database]</em> ".
   
"and remember to set correct permissions with 'chmod'.");

if(empty(
$_GET['url']) && empty($_GET['adm']) && empty($_GET['findurls']))
  
#die("Nothing to do.");
  
error404();

$urls read_urls($config['URLfile']);

if(!empty(
$_GET['findurls'])) findurls($_GET['findurls'], $urls);
if(!empty(
$_GET['adm'])) $ctAdm $_GET['adm'];
if(!empty(
$_GET['url']))
  
$ctUrl preg_replace(
    array(
"/'/"'/"/''/,/'),
    array(
'%27''%22''%2C'),
    
stripslashes($_GET['url'])
  );
$ctLink $urls[$ctUrl];

if(!empty(
$ctUrl) && empty($ctLink))
  
#die("Unknown URL");
  
error404($ctUrl);

if(!empty(
$ctUrl) && !isset($ctAdm) &&
    (
      !
$config['Ignore']['IPs'] ||
      !
preg_match("\x01".$config['Ignore']['IPs']."\x01i",
        
$_SERVER['REMOTE_ADDR'])
    ) && (
      !
$config['Ignore']['Hosts'] ||
      !
preg_match("\x01".$config['Ignore']['Hosts']."\x01i",
        
my_gethostbyaddr($_SERVER['REMOTE_ADDR']))
    ) && (
      !
$config['Ignore']['Referers'] ||
      !
preg_match("\x01".$config['Ignore']['Referers']."\x01i",
        
$_SERVER['HTTP_REFERER'])
    ) && (
      !
$config['Ignore']['Agents'] ||
      !
preg_match("\x01".$config['Ignore']['Agents']."\x01i",
        
$_SERVER['HTTP_USER_AGENT'])
    )
  )
{
  
$DoNotTrackHeader "HTTP_" strtoupper(str_replace("-""_""X-Do-Not-Track"));

  
#echo '<pre>' . join("\n", array_keys($_SERVER));
  
if(
    ((
array_key_exists($DoNotTrackHeader$_SERVER)) and ($_SERVER[$DoNotTrackHeader] == 1))
    or
    ((
array_key_exists('HTTP_DNT'$_SERVER)) and ($_SERVER['HTTP_DNT'] == 1))
  )
  {
    
#echo "\n\n\nnotrack"; exit;
    
write_db($config['Database'], $ctUrl'-');
  } else {
    
#echo "\n\n\ntrack"; exit;
    
write_db($config['Database'], $ctUrl$_SERVER['REMOTE_ADDR']);
  }
}

if(isset(
$ctAdm))
  if(
$ctAdm === $config['Password'])
    
// show click counts
    
count_clicks($config['Database'], $urls$ctUrl$ctLink);
  else
    die(
"Invalid password.");
else
  
// redirect the browser to the actual URL
  #print '<meta http-equiv="refresh" content="0;url='.$ctLink.'" >';
  
header("Location: $ctLink");

function 
count_clicks($db$urls$url$link)
{
  
$ctArray read_db($db);

  
header("Content-Type: text/html; charset=UTF-8");

  if(
$_GET['raw'])
  {
    
print_url_click_list_raw($ctArray$url$link);
    return;
  }

  print <<<EOF
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Click Counts</title>
<style type="text/css">
<!--
body {
    background:   #FFFFFF;
    color:        #000000;
    margin-top:   20px;
    margin-left:  20px;
    margin-right: 20px;
}
a:link {
    text-decoration: underline;
    color:           #0000EE;
}
a:visited {
    text-decoration: underline;
    color:           #990066;
}
a:hover {
    text-decoration: none;
    color:           #FF0000;
}
a:active, a:focus {
    text-decoration: none;
    color:           #FF9999;
}
ul       {list-style-type: circle;}
ul ul    {list-style-type: disc;  }
ul ul ul {list-style-type: square;}
del      {color: #aa0000;         }
.sserif  {font-family: sans-serif;}
.small   {font-size: smaller;     }
.warning {
  background:     yellow;
  border:         solid 1px black;
  padding-top:    1ex;
  padding-bottom: 1ex;
}
-->
</style>
</head>
<body>
<h1 align="center">Click Counts</h1>\n
EOF;

  if(
preg_match('/\bMSIE\b/'$_SERVER['HTTP_USER_AGENT']))
    print <<<EOF
<div class="warning">
<center>
<font size="+2" color="#dd0000">WARNING!</font>
<br>
Internet Explorer is notoriously <font color="#ff0000">incompatible</font>
and <font color="#ff0000">insecure</font>.  You should be viewing this page
with <a href="http://www.mozilla.org/firefox/">Firefox</a>,
<a href="http://www.opera.com/">Opera</a>, or something else.
</center>
</div>\n
EOF;

  if(!empty(
$_GET['url']))
    
print_url_click_list($ctArray$url$link);
  else
    
print_click_list($ctArray$urls);

  print <<<EOF
<p align="right">
<a href="http://christianrobinson.name/c?source" title="Download the source code.">c</a>
&copy;left <a href="http://christianrobinson.name/">Christian J. Robinson</a> based on
<a href="http://www.astoever.no/code/ct.phps" title="Download the original source code.">ct.php</a>
by <a href="http://www.astoever.no" title="Alexander Støver Inc.">alexander</a>
</p>
</body>
</html>\n
EOF;
}

function 
print_url_click_list_raw($list$url$link)
{
  print 
'<ul>'."\n";
  foreach (
$list[$url]['addresses'] as $key => $value)
  {
    
asort($valueSORT_NUMERIC);
    
$ip my_gethostbyaddr($key);
    if (
$ip === '-')
    {
      print 
'<li>[anonymous] '.plural(count($value), 'click').'<ul>'."\n";
    } else {
      print 
'<li><a href="http://ws.arin.net/cgi-bin/whois.pl?queryinput='.
        
$key.'" title="'.htmlentities($key).'" class="sserif">'.$ip.'</a> '.
        
'(<a href="http://www.geobytes.com/IpLocator.htm?GetLocation&ipaddress='.
        
$key.'" class="sserif small">GeoIP</a>) '.
        
plural(count($value), 'click').':<ul>'."\n";

      foreach (
$value as $tmp)
        print 
"<li>".date('r'$tmp)."\n";
    }

    print 
'</ul>'."\n";
  }
  print 
'</ul>'."\n";
}

function 
print_url_click_list($list$url$link)
{
  global 
$config;

  if(
$list[$url])
  {
    print 
'<p><a href="'.$link.'" title="'.htmlentities($link).'">'.$url.'</a> '.
      
plural($list[$url]['count'], 'click').":</p>\n";
    print 
'<ul>'."\n";
    foreach (
$list[$url]['addresses'] as $key => $value)
    {
      
asort($valueSORT_NUMERIC);
      
$ip my_gethostbyaddr($key);
      if (
$ip === '-')
      {
        print 
'<li>[anonymous] '.plural(count($value), 'click')."\n".
          
'<div style="-moz-column-count: 2;"><ul>'."\n";
      } else {
        print 
'<li><a href="http://ws.arin.net/cgi-bin/whois.pl?queryinput='.
          
$key.'" title="'.htmlentities($key).'" class="sserif">'.my_gethostbyaddr($key).
          
'</a> (<a href="http://www.geobytes.com/IpLocator.htm?GetLocation&ipaddress='.
          
$key.'" class="sserif small">GeoIP</a>) '.
          
plural(count($value), 'click').":\n".
          
'<div style="-moz-column-count: 2;"><ul>'."\n";

        foreach (
$value as $tmp)
          print 
"<li>".date('r'$tmp)."\n";
      }

      print 
"</ul></div>\n";
    }
    print 
'</ul>'."\n";
  }

  print 
'<hr width="60%"><p align="center"><a href="'.$_SERVER['SCRIPT_NAME'].
    
'?adm='.$config['Password'].'">return to list</a></p>'."\n";
}

function 
print_click_list($list$urls)
{
  global 
$config;

  print <<<EOF
<script type="text/javascript">
<!--

// Instead of using the Firefox-only trick of embedding an image in an
// <img src>, let the PHP script return it and force it to be loaded by
// the browser on load:
temp        = new Image(); temp.src = "
$_SERVER[SCRIPT_NAME]?busygif";
var BusyGif = '<img src="
$_SERVER[SCRIPT_NAME]?busygif" border="0">';

/*
var BusyGif = '<img src="data:image/gif;base64,'+
'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'+
'fySDhGYQdDWGQyUhADs=" border="0">';
*/

var ClickData = new Array();
var xmlhttp   = new Array();
var toggles   = new Array();

function toggleVisibility(item)
{
  var element = document.getElementById(item);
  var toggle  = document.getElementById(item+'toggle');

  if (! (ClickData && ClickData[item]))
  {
    toggle.innerHTML = BusyGif;
    getClickData(item);
    return;
  }

  if (element.style.display == 'none')
  {
    show(item);
  } else {
    collapse(item);
  }

  showCollapseAll();
}

function show(item)
{
  var element = document.getElementById(item);
  var toggle  = document.getElementById(item+'toggle');

  element.style.display = 'block';
  toggle.innerHTML = '&ndash;';
}

function collapse(item)
{
  var element = document.getElementById(item);
  var toggle  = document.getElementById(item+'toggle');

  element.style.display = 'none';
  toggle.innerHTML = '+';
}

function collapseAll()
{
  var element = '';

  for (i = 0; i < toggles.length; i++)
  {
    element = document.getElementById(toggles[i]);
    if (element.style.display == 'block')
    {
      collapse(toggles[i]);
    }
  }

  showCollapseAll();
}

function showCollapseAll()
{
  var show    = false;
  var element = document.getElementById('call');
  var temp    = '';

  for (i=0; i<toggles.length; i++)
  {
    temp = document.getElementById(toggles[i]);
    if (temp.style.display == 'block')
    {
      show = true;
    }
  }

  if (show)
  {
    element.style.display = 'block';
  } else {
    element.style.display = 'none';
  }
}

function getClickData(item)
{
  xmlhttp[item] = MyHttpRequest();
  xmlhttp[item].open('GET', '
$_SERVER[SCRIPT_NAME]?adm=$config[Password]&url='+item+'&raw=1',true);
  xmlhttp[item].onreadystatechange=function() {
    if (xmlhttp[item].readyState==4)
    {
      var temp = xmlhttp[item].responseText;
      var element = document.getElementById(item);
      delete xmlhttp[item]['onreadystatechange'];
      delete xmlhttp[item];
      element.innerHTML = temp;
      ClickData[item] = 1;
      toggleVisibility(item);
    }
  }
  xmlhttp[item].send(null);
}

function MyHttpRequest(request)
{
  var request=false;
  /*@cc_on @*/
  /*@if (@_jscript_version >= 5)
  // JScript gives us Conditional compilation, we can cope with old IE versions
  // and security blocked creation of the objects.
   try {
    request = new ActiveXObject("Msxml2.XMLHTTP");
   } catch (e) {
    try {
     request = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (E) {
     request = false;
    }
   }
  @end @*/
  if (!request && typeof XMLHttpRequest!='undefined') {
    try {
      request = new XMLHttpRequest();
    } catch (e) {
      request = false;
    }
  }
  if (!request && window.createRequest) {
    try {
      request = window.createRequest();
    } catch (e) {
      request = false;
    }
  }

  return request;
}

// -->
</script>\n
EOF;

  foreach (
$list as $key => $value)
    
$urlCount[$key] = $value['count'];

  if(
$_GET['s'] === 'n')
    
asort($urlCountSORT_NUMERIC);
  else
    
ksort($urlCountSORT_STRING);

  if(
$_GET['d'] === 'd')
    
$urlCount array_reverse($urlCount);

  print 
'<div style="-moz-column-count: 2;"><ul>'."\n";
  foreach (
$urlCount as $key => $value)
  {
    if(empty(
$key)) continue;

    if(
$urls[$key])
    {
      print 
'<span style="display: table;"><li><a href="'.$urls[$key].
        
'" title="'.htmlentities($urls[$key]).'">'.$key.'</a> '.plural($value'click')."\n";

      print 
'<script type="text/javascript">'."\n".
        
"<!--\n".
        
'toggles.push("'.$key.'");'."\n".
        
'document.write(" (<a href=\"javascript:toggleVisibility(\''.$key.
        
'\');\" id=\"'.$key.
        
'toggle\" style=\"text-decoration: none; color: red;\" '.
        
'onMouseOver=\"window.status=\'Click to expand stats for &quot;'.$key.
        
'&quot;\';return true\" onMouseOut=\"window.status=\'\';return true\"'.
        
' alt=\"Click to expand stats for &quot;'.$key.'&quot;\" '.
        
'title=\"Click to expand stats for &quot;'.$key.'&quot;\">+</a>)'.
        
'<div style=\"display: none;\" id=\"'.$key.'\"></div>");'."\n".
        
"// -->\n</script>\n";

      print 
'<noscript>(<a href="'.$_SERVER['SCRIPT_NAME'].'?adm='.$config['Password'].
        
'&amp;url='.urlencode(urldecode($key)).'" alt="Click to view stats for &quot;'.$key.
        
'&quot;" title="Click to view stats for &quot;'.$key.
        
'&quot;">stats</a>)</noscript>'."\n</li></span>\n";
    } else {
      print 
'<span style="display: table;"><li><del>'.$key.'</del> '.
        
plural($value'click').'</li></span>'."\n";
    }
  }
  print 
"</ul></div>\n";

  print 
'<script type="text/javascript">'."\n".
    
'document.write("<center><a href=\"javascript:collapseAll();\" '.
    
'style=\"text-decoration: none; color: red; display: none;\" '.
    
'id=\"call\">- collapse all -</a></center>");'."\n</script>\n";

  print 
'<hr width="60%">'."\n";

  if(
$_GET['s'] === 'n')
    print 
'<p align="center"><a href="'.
      
$_SERVER['SCRIPT_NAME'].'?adm='.$config['Password'].'&amp;s=a'.
      (
$_GET['d'] ? '&amp;d='.$_GET['d'] : '').
      
'">Sort alphabetically</a>';
  else
    print 
'<p align="center"><a href="'.
      
$_SERVER['SCRIPT_NAME'].'?adm='.$config['Password'].'&amp;s=n'.
      (
$_GET['d'] ? '&amp;d='.$_GET['d'] : '').
      
'">Sort by click count</a>';

  print 
' &middot; ';

  if(
$_GET['d'] === 'd')
    print 
'<a href="'.$_SERVER['SCRIPT_NAME'].
      
'?adm='.$config['Password'].($_GET['s'] ? '&amp;s='.$_GET['s'] : '').'&amp;d=a'.
      
'">Sort in ascending order</a>';
  else
    print 
'<a href="'.$_SERVER['SCRIPT_NAME'].
      
'?adm='.$config['Password'].($_GET['s'] ? '&amp;s='.$_GET['s'] : '').
      
'&amp;d=d'.'">Sort in descending order</a>';

  print 
"</p>\n";
}

function 
findurls($pattern$urls)
{
  
$pattern_escaped addcslashes($pattern'/');
  
$pattern_html    htmlspecialchars($pattern);
  foreach (
$urls as $key => $value)
    if (
preg_match('/'.$pattern_escaped.'/i'$key))
      
$matches[$key]=$value;

  
ksort($matchesSORT_STRING); reset($matches);

  
header("Content-Type: text/html; charset=UTF-8");

  print <<<EOF
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html>
<head>
<title>URLs matching: 
$pattern_html</title>
<meta name="robots" content="noindex, nofollow, noarchive">
<style type="text/css">
<!--
body {
    background:   #FFFFFF;
    color:        #000000;
    margin-top:   20px;
    margin-left:  20px;
    margin-right: 20px;
}
a:link {
    text-decoration: underline;
    color:           #0000EE;
}
a:visited {
    text-decoration: underline;
    color:           #990066;
}
a:hover {
    text-decoration: none;
    color:           #FF0000;
}
a:active, a:focus {
    text-decoration: none;
    color:           #FF9999;
}
ul {list-style-type: circle;}
-->
</style>
</head>
<body>
<h1 align="center">URLs matching: 
$pattern_html</h1>\n
EOF;

  if(
$matches)
  {
    if (
count($matches) > 10)
    {
      print 
"<center><small>(Only the first 10 matches are listed...)</small></center>\n";
      
$matches array_slice($matches010);
    }

    print 
"<div style=\"-moz-column-count: 2;\"><ul>\n";
    foreach (
$matches as $key => $value)
      print 
"<li><a href=\"$_SERVER[SCRIPT_NAME]?url=$key\" ".
        
"title=\"".htmlentities($value)."\">$key</a></li>\n";
    print 
"</ul></div>\n";
  } else
    print 
"<center><b>No matches found</b></center>\n";

  print <<<EOF
<hr width="60%">
<p align="right">
<a href="http://christianrobinson.name/c?source" title="Download the source code.">c</a>
&copy;left <a href="http://christianrobinson.name/">Christian J. Robinson</a> based on
<a href="http://www.astoever.no/code/ct.phps" title="Download the original source code.">ct.php</a>
by <a href="http://www.astoever.no" title="Alexander Støver Inc.">alexander</a>
</p>
</body>
</html>\n
EOF;

  exit;
}

function 
read_urls($file)
{
  
$handle fopen($file'r');
  while(
$line fgets($handle1024))
  {
    if(
preg_match('/^\s*#/'$line))
      continue;

    if(
preg_match("/^\s*([^\s]+?)\s*=\s*(.+)/"$line$m))
      
$urls[preg_replace(array("/'/"'/"/''/,/'), array('%27''%22''%2C'), $m[1])] = $m[2];
  }
  
fclose($handle);

  return 
$urls;
}

function 
read_db($db)
{
  
$handle fopen($db'r');
  while(
$line fgets($handle512))
  {
    
$line rtrim($line);
    if(empty(
$line)) continue;
    list(
$urltmp$time$addr) = split(' '$line);
    ++
$arr[$urltmp]['count'];
    
$arr[$urltmp]['addresses'][$addr][] = $time;
  }
  
fclose($handle);

  return 
$arr;
}

function 
write_db($db$url$ip)
{
  
$now = ($ip === '-' '-' time());

  
$handle fopen($db'a');
  
fwrite($handle$url.' '.$now.' '.$ip."\n");
  
fclose($handle);
}

function 
my_gethostbyaddr($ip)
{
  static 
$ipcache = array();

  if(
$ip === '-')
    return 
$ip;

  if(!isset(
$ipcache[$ip]))
    
$ipcache[$ip] = gethostbyaddr($ip);

  return 
$ipcache[$ip];
}

function 
plural($i$s)
{
  return 
$i.($i == $s${s}s");
}

function 
print_source()
{
  global 
$config;

  
$file join(''file(getcwd() . $_SERVER['SCRIPT_NAME']));
  
$file preg_replace(
    
'/(\$config\[(["\'])Password\2\]\s*=\s*(["\']))'.quotemeta($config['Password']).'(\3;)/',
    
'\1xxx\4',
    
$file1
  
);

  
header("Content-Type: text/html; charset=UTF-8");
  print 
'<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"'."\n".
    
' "http://www.w3.org/TR/html4/loose.dtd">'."\n";
  print 
"<HTML>\n<HEAD>\n".
    
"<TITLE>Source of $_SERVER[SCRIPT_NAME]</TITLE>\n".
    
"</HEAD>\n<BODY BGCOLOR=\"white\">\n";
  
highlight_string($file);
  print 
"\n</BODY>\n</HTML>\n";
  exit;
}

function 
print_busygif()
{
  
header("Content-Type: image/gif");
  print 
base64_decode(
'R0lGODlhEAAQAMQAAP///+7u7t3d3bu7u6qqqpmZmYiIiHd3d2ZmZlVVVURERDMzMyIiIhEREQAR'.
'AAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05F'.
'VFNDQVBFMi4wAwEAAAAh+QQFBwAQACwAAAAAEAAQAAAFdyAkQgGJJOWoQgIjBM8jkKsoPEzgyMGs'.
'CjPDw7ADpkQBxRDmSCRetpRA6Rj4kFBkgLC4IlUGhbNQIwXOYYWCXDufzYPDMaoKGBoKb886OjAK'.
'dgZAAgQkfCwzAgsDBAUCgl8jAQkHEAVkAoA1AgczlyIDczUDA2UhACH5BAUHABAALAAAAAAPABAA'.
'AAVjICSO0IGIATkqIiMKDaGKC8Q49jPMYsE0hQdrlABCGgvT45FKiRKQhWA0mPKGPAgBcTjsspBC'.
'AoH4gl+FmXNEUEBVAYHToJAVZK/XWoQQDAgBZioHaX8igigFKYYQVlkCjiMhACH5BAUHABAALAAA'.
'AAAQAA8AAAVgICSOUGGQqIiIChMESyo6CdQGdRqUENESI8FAdFgAFwqDISYwPB4CVSMnEhSej+Fo'.
'gNhtHyfRQFmIol5owmEta/fcKITB6y4choMBmk7yGgSAEAJ8JAVDgQFmKUCCZnwhACH5BAUHABAA'.
'LAAAAAAQABAAAAViICSOYkGe4hFAiSImAwotB+si6Co2QxvjAYHIgBAqDoWCK2Bq6A40iA4yYMgg'.
'NZKwGFgVCAQZotFwwJIF4QnxaC9IsZNgLtAJDKbraJCGzPVSIgEDXVNXA0JdgH6ChoCKKCEAIfkE'.
'BQcAEAAsAAAAABAADgAABUkgJI7QcZComIjPw6bs2kINLB5uW9Bo0gyQx8LkKgVHiccKVdyRlqjF'.
'SAApOKOtR810StVeU9RAmLqOxi0qRG3LptikAVQEh4UAACH5BAUHABAALAAAAAAQABAAAAVxICSO'.
'0DCQKBQQonGIh5AGB2sYkMHIqYAIN0EDRxoQZIaC6bAoMRSiwMAwCIwCggRkwRMJWKSAomBVCc5l'.
'UiGRUBjO6FSBwWggwijBooDCdiFfIlBRAlYBZQ0PWRANaSkED1oQYHgjDA8nM3kPfCmejiEAIfkE'.
'BQcAEAAsAAAAABAAEAAABWAgJI6QIJCoOIhFwabsSbiFAotGMEMKgZoB3cBUQIgURpFgmEI0EqjA'.
'CYXwiYJBGAGBgGIDWsVicbiNEgSsGbKCIMCwA4IBCRgXt8bDACkvYQF6U1OADg8mDlaACQtwJCEA'.
'IfkEBQcAEAAsAAABABAADwAABV4gJEKCOAwiMa4Q2qIDwq4wiriBmItCCREHUsIwCgh2q8MiyEKO'.
'DK7ZbHCoqqSjWGKI1d2kRp+RAWGyHg+DQUEmKliGx4HBKECIMwG61AgssAQPKA19EAxRKz4QCVIh'.
'ACH5BAUHABAALAAAAAAQABAAAAVjICSOUBCQqHhCgiAOKyqcLVvEZOC2geGiK5NpQBAZCilgAYFM'.
'ogo/J0lgqEpHgoO2+GIMUL6p4vFojhQNg8rxWLgYBQJCASkwEKLC17hYFJtRIwwBfRAJDk4Obwsi'.
'dEkrWkkhACH5BAUHABAALAAAAQAQAA8AAAVcICSOUGAGAqmKpjis6vmuqSrUxQyPhDEEtpUOgmgY'.
'ETCCcrB4OBWwQsGHEhQatVFhB/mNAojFVsQgBhgKpSHRTRxEhGwhoRg0CCXYAkKHHPZCZRAKUERZ'.
'MAYGMCEAIfkEBQcAEAAsAAABABAADwAABV0gJI4kFJToGAilwKLCST6PUcrB8A70844CXenwILRk'.
'IoYyBRk4BQlHo3FIOQmvAEGBMpYSop/IgPBCFpCqIuEsIESHgkgoJxwQAjSzwb1DClwwgQhgAVVM'.
'IgVyKCEAIfkECQcAEAAsAAAAABAAEAAABWQgJI5kSQ6NYK7Dw6xr8hCw+ELC85hCIAq3Am0U6JUK'.
'jkHJNzIsFAqDqShQHRhY6bKqgvgGCZOSFDhAUiWCYQwJSxGHKqGAE/5EqIHBjOgyRQELCBB7EAQH'.
'fySDhGYQdDWGQyUhADs='
  
);
  exit;
}

# vim: set ft=php nu sw=2 ts=2 et: ?>