<?php
/************************************************************
* *
* CECID - CEnsorship CIrcumvention Device *
* *
* 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 2 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, write *
* to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307 USA *
* *
* To contact the author, email hide@address.com *
* *
************************************************************/
define("fphit", 1);
define("userhit", 2);
define("clienthit", 3);
define("data", 4);
require('template/tempconf.php'); // Load some default configuration variables temporarily until we can load the file.
// Parse config file
$configarr = parse_config_file('cecidconfigdb');
if ($configarr != '') extract($configarr);
// For security, this should be set to E_ERROR, however we want users to be able to report verbose
// debugging info.
if ($debug==2) {
error_reporting (E_ALL);
} else {
error_reporting (E_ERROR);
}
if (($configured != 1) || (!file_exists('cecidconfigdb'))) {
err("The script has not yet been configured. Click <a href=\"config.php\">here</a>.");
exit();
}
$verchk="http://cecid.sf.net/verchk.php?ver=$version";
//Killed this: seems pointless as most servers dont support it anyway, and having multiple scripts
//consuming heaps of resources filtering words (or stuck in an infinate loop) for two mins is bad...
//set_time_limit (120);
$server = "http://".$_SERVER['SERVER_NAME'].$_SERVER['SCRIPT_NAME'];
$me = $server;
$ipcount = 10; //Number of ips to send to users
// Stats
$stats=param('stats');
if ($stats > 0) {
include('template/stats.php');
exit();
}
// Banned word addition
$newword=param('newword');
if ($newword)
{
if (!$addword)
{
err ("Banned word addition has been disabled.");
exit;
}
if ($_POST)
{
$newword = $_POST['word']."\n";
$BWpointer = fopen ($bwordpath, "a");
fwrite ($BWpointer, $newword);
$state = 1;
include 'template/newbw.php';
}
else
{
$state = 2;
include 'template/newbw.php';
}
exit;
}
// Client support
require($cecidclient);
if (($_POST) || (param('linkfollow')))
{
if (param('linkfollow'))
{
$url=rawurldecode(str_rot13(param('linkfollow')));
}
else
{
$url=$_POST['url']; //Unsafe var - corrected below
}
$rm = ($_POST['rm']);
$bw = false;
// Init $bw - banned word filtering bool
if (($_POST['bw']) || (param('bw')))
$bw=true; //Set bw, if necessary
debug ("Banned Word Filtering: ".$bw."<br>");
// Need to make sure that the user isnt doing anything naughty...
if (substr($url, 0, 1) == '/')
err ('Access Denied.');
// 0.71pre - Put a default protocol in, just incase a net fruit decides NOT
// to leave the 'http://' bit in the box
if (!strstr($url, ':'))
$url="http://" . $url;
// Now we need to htmlentitise the url, just in case the user has
// done something like: http://<iframe src= ect.
$url = htmlspecialchars($url);
//If URL is an image, then pipe it through the script, if allowed
if (list( , , $type, ) = getimagesize($url)) {
header("Content-type: " . image_type_to_mime_type($type));
debug ("<br>Image detected<br>");
if ($imagesup == 0) {
echo ('Image support is disabled on this script.');
exit();
}
debug ("Opening URL...");
$fp = fopen($url, "rb");
if ($fp) {
debug ("successful<br>");
while(!feof($fp)) {
$img = $img.fread($fp, 1024);
}
} else {
err('The url you entered could not be accessed.');
}
echo $img;
recordstat(data, strlen($img));
exit();
}
debug("<br>Image not detected<br>");
// Get url
$urlhtml = implode ('', file ($url));
recordstat(data, strlen($urlhtml));
// Fix infinite loop bug
$urlhtml = trim($urlhtml);
debug ("New Banned Word Core v0.1<br>");
if ($bw)
{
debug ("Loading banned words<br>");
$bannedwords = file($bwordpath);
// Generate the censored words
debug ("Generating safe words<br>");
foreach ($bannedwords as $num => $item)
{
$item = rtrim($item);
$key = $item;
if ($rm) {
$replacewords[$key]="-----";
continue;
}
$bwordlen = intval((strlen($item))/2);
$firststr = substr($item, 0, $bwordlen);
$secondstr = substr($item, 0-$bwordlen);
$replacewords[$key]=$firststr. "." . $secondstr;
}
$pos = 0;
$inscript = false;
debug("Banned word filtering has begun<br>");
do
{
$charatpos = substr ($urlhtml, $pos, 1);
// Skip whitespace after a tag
if($charatpos == " " || $charatpos == "\n" || $charatpos=="\r" || $charatpos == "\t") {
$pos++;
continue;
}
if ($charatpos != '<')
{
$to = strpos ($urlhtml, '<', $pos);
/*if (!$inscript)
{*/
debug("Filtering Phrase \"" . htmlentities(substr($urlhtml, $pos, ($to-$pos))) ."\"<br>");
$urlhtml = filter($urlhtml, $pos, $to, $bannedwords, $replacewords);
/*}*/
$pos=strpos($urlhtml, "<", $pos);
}
else
{
$to = strpos($urlhtml, '>', $pos);
$closing=false;
if (substr($urlhtml, $pos, 1)=='/')
{
$closing=true;
$pos++;
}
$tag = substr ($urlhtml, $pos+1, ($to-$pos)-1);
debug ("Tag skipped: <$tag> <br>");
$tag = strtolower (substr ($tag, 0, 3));
if($tag=="scr" || $tag=="sty") // Script / style tag
{
if ($closing)
$inscript = false;
else
$inscript = true;
}
$pos = $to+1;
}
//debug('$pos='.$pos.'<br>');
if($pos >= strlen($urlhtml))
break;
}
while(1);
}
debug("Last 10 chars: " . htmlentities(substr($urlhtml, -10)) . '<br>');
// Find all links, and parse them - take their urls,
// append the domain if need be, hash 'em and
// pass it back to the script (done by fixnhash)
// This will make hyperlinks (not ftp) into references back
// to cecid with the 'followlink' param to the encoded URL
if ($imagesup) {
//Fix hyperlinks, images and other embedded content.
$urlhtml = preg_replace ("/(src|href|HREF|SRC)=(\"|\'|)([^\s\">]+)(\"|>|\040|\')/e", "'$1='.quote('$2').fixnhash('$3').quote('$4')", $urlhtml, 1000);
// Fix forms
$urlhtml = preg_replace ("/(action|ACTION)=(\"|\'|)([^\s\">]+)(\"|>|\040|\')/e", "'$1='.quote('$2').fixa('$3').quote('$4')", $urlhtml, 1000);
} else {
//Fix hyperlinks
$urlhtml = preg_replace ("/(href|HREF)=(\"|\'|)([^\s\">]+)(\"|>|\040|\')/e", "'$1='.quote('$2').fixnhash('$3').quote('$4')", $urlhtml, 1000);
// Fix images, forms (ie. all embedded content)
$urlhtml = preg_replace ("/(src|action|SRC|ACTION)=(\"|\'|)([^\s\">]+)(\"|>|\040|\')/e", "'$1='.quote('$2').fixa('$3').quote('$4')", $urlhtml, 1000);
}
//[A-Za-z0-9_\?\.\&\/\:\=] this was replaced with '\W[^\"] - buggy? [^\"]
//Probs now known to be caused by \W, replaced with ([^\s\">]+)
//$urlhtml = preg_replace ("\"?", "\"$url?", $urlhtml); //This will replace local cgi links like <a href="?images=test.gif"> - see above
if ($urlhtml=="") {
err ("<b>$url</b><br>Error: The page you supplied could not be loaded - this could be because the site is down, you mistyped the url, or this server is under heavy load. Please try again."); //Send HTML to user
exit();
}
echo $urlhtml;
echo "<p><b>This page has been anonymised by <a href=\"http://cecid.sourceforge.net\">CECID</a>. </b>"; if ($bw) echo "Weighted phrases have been edited out."; echo "<br>\n";
echo "WARNING: If the above phrase does not appear on the bottom of a website, your connection is NOT being anonymised. A form (ie. on a search engine) can stop anonymisation.</p>\n";
include('template/basicindex.php');
debug ($url);
} else { //Display welcome page
$time_start = getmicrotime();
require('template/index.php'); ?>
<table width="75%" cellspacing=0><tr><td class=dblue><p align=justify>
CECID v<?=$version?> running on <?=$_SERVER['SERVER_SOFTWARE']?><br><br>
Script network data:<br>
<?
update_scripts(); //Update script network listings.
$time_end = getmicrotime();
?><br>
Page generated in <?=(round(($time_end-$time_start), 3))?> seconds.</p></td></tr></table></p><br>
<?
}
//Gets parameters send to a script (ie index.php?action=view )
function param($name)
{
if( isset($_GET[$name]) && strlen(trim($_GET[$name]))>0)
return addslashes(trim($_GET[$name]));
return NULL;
}
function fixnhash($url)
{
global $myname;
global $bw;
if ((substr ($url, 0, 7) != 'http://')||(substr ($url, 0, 8) != 'https://'))
{
// url not specific - we need to rectify
$url = fixurl($url);
}
// Ensure that backslash hasnt been left onto url
if (substr($url, -1)=="\\")
$url=substr($url, 0, -1);
// We now have a nice, specific url - let's hash it.
$url = rawurlencode(str_rot13($url));
// Now let's make the hashed url the argument of a call back to CECID
if ($bw)
{
$url = "$myname?bw=true&linkfollow=$url";
}
else
{
$url = "$myname?linkfollow=$url";
}
// Return the processed URL
return $url;
}
// Make a url specific
function fixurl ($url)
{
if ($_POST['url'])
{
//Get the page we're on
$currpage = $_POST['url'];
}
else
{
$currpage = rawurldecode(str_rot13(param('linkfollow')));
}
if (substr($currpage, -1) != "/")
$currpage = $currpage."/"; //Append '/' onto end of currpage if necessary
// now we need to find out what style the url we've been given is in:
// ie 'index.htm', './index.htm', '?index=true' ect.
if ((substr ($url, 0, 4) == 'href')||(substr ($url, 0, 3) == 'src')||(substr ($url, 0, 6) == 'action')) {
// Search and replace has returned the entire string... *sigh
list ($null,$realurl,$null) = explode ("\"", $url, 3);
debug ("Fixurl was called: a href/src/action - $url - changed to $realurl - recursing...<br>");
// Call this function: try again
return fixurl($realurl);
}
else if ((substr ($url, 0, 7) == 'http://')||(substr ($url, 0, 8) == 'https://')) {
// URL already OK
debug ("Fixurl was called: URL already OK: $url <br>");
return $url;
}
else if (substr ($url, 0, 1) == '?')
{
// Must be a reference to the page we're on, simply prepend $currpage
debug ("Fixurl was called: -reference to currpage- ".$currpage.$url."<br>");
return $currpage.$url;
}
else if ((substr ($url, 0, 1) == '/'))
{
// Has 1 directory command...need to adjust path accordingly
$currurlarr = parse_url ($currpage);
$host = $currurlarr['host'];
$path = $currurlarr['path'];
$urlarr = pathinfo ($url);
$path2 = $urlarr['dirname'];
$filename = $urlarr['basename'];
$dircount = 0;
$path2=substr ($path2, 1);
if (substr ($path, -1) == '/')
$path = substr ($path, 0, -1);
while (substr ($path, -1) != '/')
{
$path = substr ($path, 0, -1);
if($path=='')
break;
}
// make sure there is no / at the front, and 1 / at the end
if (substr($host, -1) != '/')
$host = $host.'/';
if (substr($path, -1) != '/')
$path = $path.'/';
if (substr($path2, -1) != '/')
$path2 = $path2.'/';
if (substr($path, 0, 1) == '/')
$path = substr($path, 1);
if (substr($path2, 0, 1) == '/')
$path2 = substr($path2, 1);
// Having resolved the directory commands, we should now
// be able to just stick the strings together:
debug ("Fixurl was called: -had directory command: http://".$host.$path.$path2.$filename."<br>");
return "http://".$host.$path.$path2.$filename;
}
else if ((substr ($url, 0, 3) == '../'))
{
//Has at least 1 directory command...need to adjust path accordingly
$currurlarr = parse_url ($currpage);
$host = $currurlarr['host'];
$path = $currurlarr['path'];
$urlarr = pathinfo ($url);
$path2 = $urlarr['dirname'];
$filename = $urlarr['basename'];
$dircount = 0;
while (substr ($path2, 0, 3) == '../')
{
// Trim url of ../'s, count no of ../'s
$dircount++;
$path2=substr ($path2, 3);
}
for ($i=1; $i<=$dircount; $i++)
{
// Remove one layer of path for each ../
$path = substr ($path, -1);
while (substr ($path, -1) != '/') {
$path = substr ($path, -1);
}
}
// Make sure there is no / at the front, and 1 / at the end
if (substr($host, -1) != '/')
$host = $host.'/';
if (substr($path, -1) != '/')
$path = $path.'/';
if (substr($path2, -1) != '/')
$path2 = $path2.'/';
if (substr($path, 0, 1) == '/')
$path = substr($path, 1);
if (substr($path2, 0, 1) == '/')
$path2 = substr($path2, 1);
// Having resolved the directory commands, we should now be
// able to just stick the strings together:
debug ("Fixurl was called: -had directory commands: http://".$host.$path.$path2.$filename."<br>");
return "http://".$host.$path.$path2.$filename;
}
else
{
// Should be of the style 'index.php' or '/index.php', prepend path and host
$currurlarr = parse_url ($currpage);
$host = $currurlarr['host'];
$path = $currurlarr['path'];
// Make sure there is no / at the front, and 1 / at the end
if (substr($host, -1) != '/')
$host = $host.'/';
if (substr($path, -1) != '/')
$path = $path.'/';
if (substr($path, 0, 1) == '/')
$path = substr($path, 1);
if (substr($url, 0, 1)=='/')
$url=substr($url, 1);
debug ("Fixurl was called: -simply prepending path and host: http://".$host.$path.$url."<br>"); return "http://".$host.$path.$url;
}
}
function fixa($url)
{
$url = fixurl($url);
// Ensure that backslash hasnt been left onto url
if (substr($url, -1)=="\\")
$url=substr($url, 0, -1);
return $url;
}
function debug($message)
{
// Outputs status messages if $debug=true
global $debug;
if ($debug != 0) echo $message;
}
function quote($dblquote)
{
switch($dblquote)
{
case '>':
return '>';
case '\"':
return '';
case ' ':
return ' ';
default:
return '';
}
}
function err ($string)
{
global $version;
$msg=$string;
$state=3;
include 'template/newbw.php';
}
// Filter function - changes the bad words for good ones
//
function filter ($text, $start, $end, $bannedwords, $replacewords)
{
$startbit = substr($text, 0, $start);
$midbit = substr($text, $start, $end - $start);
$endbit = substr($text, $end);
$midbitarr = explode(' ', $midbit);
foreach ($midbitarr as $num => $midword) {
$midword = rtrim($midword);
$midword = strtolower($midword); // If this was originally uppercase, it'll be output as lowercase. We need someway of detecting whether a string is uppercase and using strtoupper after filtering if so.
if (isset($replacewords[$midword])) {
$midbitarr[$num] = $replacewords[$midword];
}
}
$midbit = implode(' ', $midbitarr);
$retval = $startbit . $midbit . $endbit;
return $retval;
}
function recordstat($stattype, $amount) { // Note amount is only used for data, is ignored otherwise
global $statsdbasepath;
$statsarr = getstatsarr();
list($fphits, $userhits, $clienthits, $firstaccess, $lastaccess, $fptoday, $usertoday, $clienttoday, $statday, $data) = $statsarr;
// stat types: fphit, userhit, clienthit, data
$today=date('z');
if ($firstaccess == 0) {
$firstaccess = time();
}
if ($today != $statday) { //If it isnt $statday any more, reset the daily hits
$statday = $today;
$usertoday=0; $clienttoday=0; $fptoday=0;
}
if ($stattype == fphit) {
$fphits++;
$fptoday++;
$lastaccess=time();
} elseif ($stattype == userhit) {
$userhits++;
$usertoday++;
$lastaccess=time();
} elseif ($stattype == clienthit) {
$clienthits++;
$clienttoday++;
$lastaccess=time();
} elseif ($stattype == data) {
$data=$data+$amount;
$lastaccess=time();
} else {
debug("WARNING: Unknown stattype $stattype.");
}
$tempstatsarr = array($fphits, $userhits, $clienthits, $firstaccess, $lastaccess, $fptoday, $usertoday, $clienttoday, $statday, $data);
$i=0;
foreach($statsarr as $num => $line) {
$newstatsarr[$num] = $tempstatsarr[$i];
$i++;
}
storestatsarr($newstatsarr);
}
function getstatsarr() {
global $statsdbasepath;
if (filesize($statsdbasepath) == 0) {
storestatsarr(array(0,0,0,0,0,0,0,0,0,0));
}
$statsfilearr = file($statsdbasepath);
foreach($statsfilearr as $num => $line) {
if (($line == '') || (substr($line, 0, 1) == ';')) continue; // Skip comments and empty lines
$statsarr[$num] = rtrim($line);
}
return($statsarr);
}
function storestatsarr($statsarr) {
global $statsdbasepath;
$statsfilearr = file($statsdbasepath);
foreach($statsarr as $num => $line) {
$statsfilearr[$num] = $line."\n";
}
$fp = fopen($statsdbasepath, 'w');
foreach($statsfilearr as $line) {
fwrite($fp, $line);
}
fclose($fp);
}
function parse_config_file($filename) {
if (!file_exists($filename)) return;
$temparr = file($filename);
$a=0;
foreach($temparr as $key => $value) {
if (trim($value) == '') continue;
$filearr[$a] = trim($value);
$a++;
}
$configarr['myname']=$filearr[0];
$configarr['cecidclient']=$filearr[1];
$configarr['bwordpath']=$filearr[2];
$configarr['templatepath']=$filearr[3];
$configarr['addrdbasepath']=$filearr[4];
$configarr['accessdbasepath']=$filearr[5];
$configarr['scriptdbasepath']=$filearr[6];
$configarr['statsdbasepath']=$filearr[7];
$configarr['imagesup']=$filearr[8];
$configarr['debug']=$filearr[9];
$configarr['version']=$filearr[10];
$configarr['addword']=$filearr[11];
$configarr['configured']=$filearr[12];
$configarr['respondtoping']=$filearr[13];
$configarr['user']=$filearr[14];
$configarr['pass']=$filearr[15];
return($configarr);
}
function getmicrotime(){
list($usec, $sec) = explode(" ",microtime());
$time = ((float)$usec + (float)$sec);
return($time);
}
?>