<? /* * Todo: - admin menu to remove referer from table; * * History (admun): * 0.90 initial version * 0.91 Added the possibility to call pop,10 to show the most populair pages * Minor bugfixes for htmlspecialchars * Added substr to trim the line. Internet Explorer makes long lines instead of braking them * 0.92 Added timeoffset functionality to refWhen ... * 0.93 Added three display options (needs reinstallation!) * Bugfixes and another calling option; lastall * Added "-" on each refer * 0.94 use sql_table, add supportFeature * 0.95 add rel="nofollow" * 0.96 trim the line to other display mode * 0.97 add NP_BlackList support aka fight the referer spam! * add code for plugin uninstall table remove (comment out by default) * 0.98 update to NP_BlackList 0.97+ support * * Start of Referer2 by pdreker: 04.03.2004 * History: 0.10 initial version based on referer 0.93 by -=Xiffy=- * Main Differences: * - uses textarea for list options, because this is a lot more readable and has no length * restrictions. List are not comma separated any more, but newline separated (i.e. one * entry per line) * - minor grammar and speling fixes. Clarified how the options have to be entered. * - uses sql_table() instead of hardcoded table name. * - IP banning supports CIDR notation (e.g. 192.168.1.0/24 to block all IPs in 192.168.1.0-255) * - different defaults for <br /> insertion and display of referer time (exactly the other way * around). * - added on option to automagically clean the referer DB table. This means, after you save the * options the domain bans will be applied to the database. This comes in handy, if a new * d*ckhead came along sprinkling p0rn links on your site: just add the domain to the ban * list, and if the option is checked the entries will be removed from the DB, so they don't * show up any more. WARNING: it is rather easy to shoot yourself in the foot, if you enter a * too wide ban (e.g. entering "x" as a ban will remove all referers with "x" in their domain * name... NO FURTHER QUESTIONS ASKED! * 0.11 small maintenance release * - changed the "lastall" target to look like all others (no table anymore). The old target * was moved to "lastalltable" * 0.12 bugfix release (a.k.a. getting quick release) * - fixed a warning with empty blocklist or search engine list. * - fixed a typo in search engine handling which prevented search engines from being * recognized properly * 0.13 bugfix release (a.k.a. "Dont kill the referrer table") * - fixed a stupid oversight, which might delete all referrers from the DB table * if you had an empty entry there (yielded DELETE FROM .... WHERE ... LIKE "%%", which matches * every entry...) */ // to make this plugin works on Nucleus versions <=2.0 as well if (!function_exists('sql_table')) { function sql_table($name) { return 'nucleus_' . $name; } } class NP_Referer2 extends NucleusPlugin { function cidrCheck($ip_address, $cidr_address) { $first = substr($cidr_address, 0, strpos($cidr_address, "/")); $netmask = substr(strstr($cidr_address, "/"), 1); $first_bin = str_pad(decbin(ip2long($first)), 32, "0", STR_PAD_LEFT); $ip_bin = str_pad(decbin(ip2long($ip_address)), 32, "0", STR_PAD_LEFT); $netmask_bin = str_pad(str_repeat("1", (integer)$netmask), 32, "0", STR_PAD_RIGHT); // check: if (ip & mask) == first -> match // "compute" the "&" for($i = 0; $i<32; $i++) { if ($netmask_bin[$i] == "1") { $check_bin .= $ip_bin[$i]; } else { $check_bin .= "0"; } } $result = (strcmp($check_bin, $first_bin) == 0); return $result; } function supportsFeature($feature) { switch($feature) { case 'SqlTablePrefix': return 1; default: return 0; } } function getEventList() { return array('PostPluginOptionsUpdate'); } function event_PostPluginOptionsUpdate($data) { if ($data['context'] != 'global') return; if ($data['plugid'] != $this->GetID()) return; // if we get here we have just saved our own options $cleanDB = $this->getOption('cleanDB'); if($cleanDB == 'yes') { $query = "DELETE FROM " . sql_table('plug_referer2') . " WHERE "; $filterlist = explode("\n",$this->getOption(blockDomain)); $gotone = false; foreach($filterlist as $block) { $block = rtrim($block); if($block != "") { $query .= "ref_from LIKE '%$block%' OR "; $gotone = true; } } // remove last "OR " $query = substr($query, 0, -4); // echo $query; // chicken ;-) if($gotone) mysql_query($query); // only do query if we really found something to clean // clear the option again if($this->getOption('autoResetCleanDB') == 'yes') { $this->setOption('cleanDB', 'no'); } } } function doSkinVar($skintype, $what='last', $amount=10) { global $manager; global $blog; global $CONF; global $HTTP_REFERER; global $HTTP_HOST; $table_name = sql_table("plug_referer2"); $logtime = time(); $refer = $_SERVER['HTTP_REFERER']; //ED$ $HTTP_REFERER; $parsed = parse_url($refer); $refParts = explode("/", $refer); if ($_SERVER['QUERY_STRING']) { $pageRef = $_SERVER['PHP_SELF']."_".$_SERVER['QUERY_STRING']; } else { $pageRef = $_SERVER['PHP_SELF']; } // see if we need to block this referer if ($parsed[scheme] != "http") { $refer = ""; } // not local please ... // ED$ if ($parsed[host] == $HTTP_HOST ) { $refer = ""; } if ($parsed[host] == $_SERVER['HTTP_HOST'] ) { $refer = ""; } $filterip = explode("\n",$this->getOption(blockIp)); $filterlist = explode("\n",$this->getOption(blockDomain)); $searchengines = explode("\n",$this->getOption(searchengines)); $addbreaks = $this->getOption(addBR); $maxlength = $this->getOption(maxlength); $showtime = $this->getOption(showDateTime); // ignore filtered domains foreach($filterip as $block) { if(strstr($block, "/")) { // CIDR notation $block = rtrim($block); if($this->cidrCheck($_SERVER['REMOTE_ADDR'], $block)) { $refer = ""; } } else { // Single IP Address $block = rtrim($block); if ($block != "" && strstr($_SERVER['REMOTE_ADDR'], $block)) { $refer = ""; } } } foreach($filterlist as $block) { $block = rtrim($block); if ($block != "" && strstr($parsed[host],$block)) { $refer = ""; } } // search engine ?? foreach($searchengines as $engine ) { $engine = rtrim($engine); if ($engine != "" && strstr($parsed[host],$engine)) { $extra = $parsed[query]; // searchwords used .... } } // check for spam attempts, you never know ! if ($refer != "" and $manager->pluginInstalled('NP_Blacklist') and $blacklist =& $manager->getPlugin('NP_Blacklist')) { if (floatval($blacklist->getVersion()) >= 0.96) { $spamcheck = array ('type' => 'Referer', 'data' => $refer, 'return' => false); $manager->notify('SpamCheck', array ('spamcheck' => & $spamcheck)); } else { if (floatval($blacklist->getVersion()) == 0.95) { $blacklist->blacklist('NP_Referer',$refer); } } } // if we didn't block this, let's put it in the db .... // and if this is the first time we were called then ... if ($refer && !$this->count == 1) { if (! $extra) { // find the page title ... $fp = @fopen ($refer, "r"); if ($fp){ $ref_str = fread($fp, 4096); if (eregi("<title>(.*)</title>", $ref_str, $out)) { $extra = htmlspecialchars ($out[1],ENT_QUOTES); } } if (! $extra) {$extra = $parsed[host]." ".$parsed[path];} } // let's put it in the db now ... $query = "INSERT into $table_name (ref_to, ref_from, ref_extra)" . " VALUES ('".$pageRef."','".$refer."','".$extra."')"; mysql_query($query); } $this->count = 1; // we've been here now. // and put something on the page .... // build the appropiate query for $what if ($what == "lastall") { $query = "SELECT ref_from AS refFrom" . ", ref_extra AS refShow" . ", ref_to AS refTo" . ", UNIX_TIMESTAMP(ref_when) AS refWhen" . " FROM $table_name " . " ORDER BY ref_when DESC" . " LIMIT ".$amount; $refs = mysql_query($query); if ($refs) { while ($ref = mysql_fetch_object($refs)) { $ref->refShow = $this->searchString($ref->refFrom, $ref->refShow); $temp = parse_url($ref->refFrom); $host = $temp['host']; $titletag = $host." : ".$ref->refShow; if ($what == "item" ){ echo "- <a title=\"".$titletag."\" href=\"".htmlspecialchars($ref->refFrom)."\" rel=\"nofollow\">"; if ($showtime == yes) { echo strftime("%e/%m/%g - %R",$ref->refWhen + ($blog->getTimeOffset() * 3600))." "; } echo stripslashes($ref->refShow)."</a>"; } else { echo "- <a title=\"".$titletag."\" href=\"".htmlspecialchars($ref->refFrom)."\" rel=\"nofollow\">"; if ($showtime == yes) { echo strftime("%R",$ref->refWhen + ($blog->getTimeOffset() * 3600))." "; } if (strlen($ref->refShow) > $maxlength ) echo substr(stripslashes($ref->refShow),0,$maxlength) . "..."; else echo substr(stripslashes($ref->refShow),0,$maxlength); echo "</a>"; } if ($addbreaks == yes) {echo "<br />";} } } } if ($what == "lastalltable") { $query = "SELECT ref_from AS refFrom" . ", ref_extra AS refShow" . ", ref_to AS refTo" . ", UNIX_TIMESTAMP(ref_when) AS refWhen" . " FROM $table_name " . " ORDER BY ref_when DESC" . " LIMIT ".$amount; $refs = mysql_query($query); if ($refs) { //echo "<table>"; while ($ref = mysql_fetch_object($refs)) { $ref->refTo = str_replace("_","?",$ref->refTo); $ref->refShow = $this->searchString($ref->refFrom, $ref->refShow); $temp = parse_url($ref->refFrom); $host = $temp['host']; $titletag = $host." : ".$ref->refShow; //echo "<tr><td width=\"50%\">"; echo "- <a title=\"".$titletag."\" href=\"".htmlspecialchars($ref->refFrom)."\" rel=\"nofollow\">".strftime("%e/%m/%g - %R",$ref->refWhen + (0 * 3600))." ".stripslashes($ref->refShow)."</a>"; //echo "</td><td width=\"50%\">"; $linktxt = substr($ref->refTo,strpos($ref->refTo,"?") + 1); if( strpos($linktxt,"temid") > 0 ) { $citemid = substr($linktxt,strpos($linktxt,"itemid=") + 7); if ( strpos($citemid,"&") > 0) { $citemid = substr($citemid,0, strpos($citemid,"&")); } $titleq = "SELECT ititle FROM ".sql_table('item')." WHERE inumber = ". $citemid; $result = mysql_query($titleq); $row = mysql_fetch_object($result); if (! $row->ititle == "") { $linktxt = $row->ititle; } else { $linktxt = $citemid . "-" .$linktxt; } } echo "<a href=\"".htmlspecialchars($ref->refTo)."\" rel=\"nofollow\"> -> ".$linktxt."</a>"; echo "</td></tr>"; } echo "</table>"; } } if ($what == "last" || $what == "item") { $query = "SELECT ref_from AS refFrom" . ", ref_extra AS refShow" . ", UNIX_TIMESTAMP(ref_when) AS refWhen" . " FROM $table_name " . " WHERE " . " ref_to = '".$pageRef."'" . " ORDER BY ref_when DESC" . " LIMIT ".$amount; $refs = mysql_query($query); if ($refs) { while ($ref = mysql_fetch_object($refs)) { $ref->refShow = $this->searchString($ref->refFrom, $ref->refShow); $temp = parse_url($ref->refFrom); $host = $temp['host']; $titletag = $host." : ".$ref->refShow; if ($what == "item" ){ echo "- <a title=\"".$titletag."\" href=\"".htmlspecialchars($ref->refFrom)."\" rel=\"nofollow\">"; if ($showtime == yes) { echo strftime("%e/%m/%g - %R",$ref->refWhen + ($blog->getTimeOffset() * 3600))." "; } echo stripslashes($ref->refShow)."</a>"; } else { echo "- <a title=\"".$titletag."\" href=\"".htmlspecialchars($ref->refFrom)."\" rel=\"nofollow\">"; if ($showtime == yes) { echo strftime("%R",$ref->refWhen + ($blog->getTimeOffset() * 3600))." "; } echo substr(stripslashes($ref->refShow),0,$maxlength)."</a>"; } if ($addbreaks == yes) {echo "<br />";} } } } if ($what == "pop") { // which pages get hits from outside? $query = "SELECT ref_to AS refTo" . ", ref_extra AS refShow" . ", COUNT(ref_to) AS refCount" . " FROM $table_name " . " GROUP BY ref_to " . " ORDER BY refCount DESC" . " LIMIT 0," .$amount; // skip the first that'll be the normal index .... $refs = mysql_query($query); if ($refs) { while ($ref = mysql_fetch_object($refs)) { $ref->refTo = str_replace("_","?",$ref->refTo); $titletag = $ref->refCount ." hits for: " .$ref->refTo; $linktxt = $ref->refCount." ".substr($ref->refTo,strpos($ref->refTo,"?") + 1); if( strpos($linktxt,"itemid") > 0 ) { $citemid = substr($linktxt,strpos($linktxt,"itemid=") + 7); if ( strpos($citemid,"&") > 0) { $citemid = substr($citemid,0, strpos($citemid,"&")); } $titleq = "SELECT ititle FROM ".sql_table('item')." WHERE inumber = ". $citemid; $result = mysql_query($titleq); $row = mysql_fetch_object($result); if (! $row->ititle == "") { $linktxt = $ref->refCount." ".$row->ititle; } } echo "- <a title=\"".$titletag."\" href=\"".htmlspecialchars($ref->refTo)."\" rel=\"nofollow\">".$linktxt."</a>"; if ($addbreaks == yes) {echo "<br />";} } } } if ($what == "top" || $what == "topall" ) { // get the top $query = "SELECT ref_from AS refFrom" . ", ref_extra AS refShow" . ", UNIX_TIMESTAMP(ref_when) AS refWhen" . ", COUNT(ref_from) AS refCount" . " FROM $table_name " . " GROUP BY ref_from " . " ORDER BY refCount DESC" . " LIMIT " .$amount; $refs = mysql_query($query); if ($refs) { while ($ref = mysql_fetch_object($refs)) { $ref->refShow = $this->searchString($ref->refFrom, $ref->refShow); $temp = parse_url($ref->refFrom); $host = $temp['host']; $titletag = $host." : ".$ref->refShow; echo "- <a title=\"".$titletag."\" href=\"".htmlspecialchars($ref->refFrom)."\" rel=\"nofollow\">".$ref->refCount." "; if ($what == "top") { echo substr(stripslashes($ref->refShow),0,$maxlength); } else { if (strlen($ref->refShow) > $maxlength ) echo substr(stripslashes($ref->refShow),0,$maxlength) . "..."; else echo substr(stripslashes($ref->refShow),0,$maxlength); //echo substr(stripslashes($ref->refShow),0,$maxlength). "...; //ED$ echo stripslashes($ref->refShow); } echo "</a>"; if ($addbreaks == yes) {echo "<br />";} } } } } function searchString($from, $query) { if (strstr($from,"google") || strstr($from,"ilse") || strstr($from,"altavista") || strstr($from,"search.msn")) { parse_str($query,$res); $q = $res['q']; if (strstr($from,"google")) { $query = "[g] "; } else if (strstr($from,"ilse")) { $query = "[i] "; if ($q == "") { $q = $res['search_for']; } } else if (strstr($from,"altavista")) { $query = "[a] "; } else if (strstr($from,"search.msn")) { $query = "[m] "; } $query .= htmlspecialchars($q); } if (strstr($from,"search.yahoo")) { parse_str($query,$res); $q = $res['p']; $query = "[y] " . htmlspecialchars($q); } return $query; } // name of plugin function getName() { return 'Referer2'; } // author of plugin function getAuthor() { return 'pdreker, based on code by -=Xiffy=- inspired by: Mat Bennett, mod by admun (Edmond Hui)'; } function getURL() { return 'http://www.dreker.org/'; } function getVersion(){ return '0.98'; } function getDescription() { return 'Keeps track of the referring pages. Call with <%Referer2(last,10)%> to show the last 10 referers. <%Referer2(top,10)%> to see the top referer'; } function install(){ // create required table // NOT FINISHED WITH DEFAULTS !! $this->createOption('addBR','Add linebreaks <br /> to the links', 'yesno','no'); $this->createOption('showDateTime', 'Show when the referring occured', 'yesno', 'yes'); $this->createOption('autoResetCleanDB', 'Automatically reset "Clean referer table" option to "no"', 'yesno', 'yes'); $this->createOption('maxlength','How many character to show at most', 'text', '30'); $this->createOption('blockDomain','List of domains to ignore. Any domain containing this string is ' . 'ignored. One Entry per line','textarea', "spankit\nbobbakazoo\nsearch4pornography\narizonasba\nchocoborancher\nchaiti"); $this->createOption('blockIp','List of IP addresses to ignore. Any referral from on of these IPs is ' . 'ignored. You can use CIDR notation here (e.g. 192.168.1.0/24) ' . 'One Entry per line.','textarea', "66.28.25.3\n64.75.32.137\n217.198.193.71\n18.85.23.46"); $this->createOption('searchengines','List of search engine names. Any referral matching one of these ' . 'strings gets a special treatment (Lookup of search parameters). One Entry per Line. ' . 'The special treatment has to be coded into the plugin itself.','textarea', "google\nsearch.yahoo\nilse\nfasttrack\nsearch.msn\nzoek\naltavista"); $this->createOption('cleanDB', 'Clean the referer table after saving options?', 'yesno', 'no'); $table_name = sql_table("plug_referer2"); mysql_query ("CREATE TABLE $table_name ( `ref_to` VARCHAR(60) NOT NULL, `ref_when` TIMESTAMP NOT NULL, `ref_from` VARCHAR(160) NOT NULL, `ref_extra` VARCHAR(80), KEY `from` (`ref_from`), KEY `when` (`ref_when`), KEY `to` (`ref_to`))"); } function uninstall(){ // uncomment below to delete created tables on uninstall //$table_name = sql_table("plug_referer2"); //mysql_query ("DROP TABLE $table_name"); } function getTableList() { return array(sql_table("plug_referer2")); } } ?>