PHP Code:
<?
//
// H-Tracker v0.2
// http://h-tracker.org
// Based on TorrentTrader (http://www.torrenttrader.org)
//
//
error_reporting(E_ALL ^ E_NOTICE);
require_once("backend/mysql.php");
require_once("backend/config.php");
@mysql_connect($mysql_host, $mysql_user, $mysql_pass) or err('dbconn: mysql_connect: ' . mysql_error());
@mysql_select_db($mysql_db) or die('dbconn: mysql_select_db: ' + mysql_error());
$MEMBERSONLY = $site_config["MEMBERSONLY"];
$MEMBERSONLY_WAIT = $site_config["MEMBERSONLY_WAIT"];
//START FUNCTIONS
function ip2compact ($ip, $port) {
return pack("N", ip2long($ip)).pack("n", $port);
}
function unesc($x) {
if (get_magic_quotes_gpc())
return stripslashes($x);
return $x;
}
function hex2bin($hexdata) {
$bindata = "";
for ($i=0;$i<strlen($hexdata);$i+=2) {
$bindata.=chr(hexdec(substr($hexdata,$i,2)));
}
return $bindata;
}
function is_valid_id($id)
{
return is_numeric($id) && ($id > 0) && (floor($id) == $id);
}
function validip($ip)
{
if (!empty($ip) && ip2long($ip)!=-1)
{
$reserved_ips = array (
array('0.0.0.0','2.255.255.255'),
array('10.0.0.0','10.255.255.255'),
array('127.0.0.0','127.255.255.255'),
array('169.254.0.0','169.254.255.255'),
array('172.16.0.0','172.31.255.255'),
array('192.0.2.0','192.0.2.255'),
array('192.168.0.0','192.168.255.255'),
array('255.255.255.0','255.255.255.255')
);
foreach ($reserved_ips as $r)
{
$min = ip2long($r[0]);
$max = ip2long($r[1]);
if ((ip2long($ip) >= $min) && (ip2long($ip) <= $max)) return false;
}
return true;
}
else return false;
}
function getip() {
if (isset($_SERVER)) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && validip($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif (isset($_SERVER['HTTP_CLIENT_IP']) && validip($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
} else {
if (getenv('HTTP_X_FORWARDED_FOR') && validip(getenv('HTTP_X_FORWARDED_FOR'))) {
$ip = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('HTTP_CLIENT_IP') && validip(getenv('HTTP_CLIENT_IP'))) {
$ip = getenv('HTTP_CLIENT_IP');
} else {
$ip = getenv('REMOTE_ADDR');
}
}
return $ip;
}
function checkconnect($ip,$port)
{
$sockres = @fsockopen($ip, $port, $errno, $errstr, 5);
if (!$sockres)
$connectable = "no";
else
{
$connectable = "yes";
@fclose($sockres);
}
return $connectable;
}
function hash_pad($hash) {
return str_pad($hash, 20);
}
function hash_where($name, $hash) {
$shhash = preg_replace('/ *$/s', "", $hash);
return "($name = " . sqlesc($hash) . " OR $name = " . sqlesc($shhash) . ")";
}
function sqlesc($x) {
return "'".mysql_real_escape_string($x)."'";
}
function err($msg)
{
benc_resp(array("failure reason" => array(type => "string", value => $msg)));
exit();
}
function benc($obj) {
if (!is_array($obj) || !isset($obj["type"]) || !isset($obj["value"]))
return;
$c = $obj["value"];
switch ($obj["type"]) {
case "string":
return benc_str($c);
case "integer":
return benc_int($c);
case "list":
return benc_list($c);
case "dictionary":
return benc_dict($c);
default:
return;
}
}
function benc_str($s) {
return strlen($s) . ":$s";
}
function benc_int($i) {
return "i" . $i . "e";
}
function benc_list($a) {
$s = "l";
foreach ($a as $e) {
$s .= benc($e);
}
$s .= "e";
return $s;
}
function benc_dict($d) {
$s = "d";
$keys = array_keys($d);
sort($keys);
foreach ($keys as $k) {
$v = $d[$k];
$s .= benc_str($k);
$s .= benc($v);
}
$s .= "e";
return $s;
}
function benc_resp($d)
{
benc_resp_raw(benc(array(type => "dictionary", value => $d)));
}
function benc_resp_raw($x) {
header("Content-Type: text/plain");
header("Pragma: no-cache");
if ($_SERVER["HTTP_ACCEPT_ENCODING"] == "gzip") {
header("Content-Encoding: gzip");
echo gzencode($x, 9, FORCE_GZIP);
} else
print($x);
}
function gmtime()
{
return strtotime(get_date_time());
}
function get_date_time($timestamp = 0)
{
if ($timestamp)
return date("Y-m-d H:i:s", $timestamp);
else
return gmdate("Y-m-d H:i:s");
}
function portblacklisted($port)
{
// direct connect
if ($port >= 411 && $port <= 413) return true;
// kazaa
if ($port == 1214) return true;
// gnutella
if ($port >= 6346 && $port <= 6347) return true;
// emule
if ($port == 4662) return true;
// winmx
if ($port == 6699) return true;
return false;
}
//////////////////////// NOW WE DO THE ANNOUNCE CODE ////////////////////////
// BLOCK ACCESS WITH WEB BROWSERS
$agent = $_SERVER["HTTP_USER_AGENT"];
//if (ereg("^Mozilla\\/", $agent) || ereg("^Opera\\/", $agent) || ereg("^Links ", $agent) || ereg("^Lynx\\/", //$agent))
// err("torrent not registered with this tracker");
//GET DETAILS OF PEERS ANNOUNCE
foreach (array("passkey","info_hash","peer_id","ip","event") as $x) {
if (get_magic_quotes_gpc())
$GLOBALS[$x] = stripslashes($_GET[$x]);
else
$GLOBALS[$x] = $_GET[$x];
}
foreach (array("port","downloaded","uploaded","left") as $x)
$GLOBALS[$x] = 0 + $_GET[$x];
if (strpos($passkey, "?")) {
$tmp = substr($passkey, strpos($passkey, "?"));
$passkey = substr($passkey, 0, strpos($passkey, "?"));
$tmpname = substr($tmp, 1, strpos($tmp, "=")-1);
$tmpvalue = substr($tmp, strpos($tmp, "=")+1);
$GLOBALS[$tmpname] = $tmpvalue;
}
foreach (array("passkey","info_hash","peer_id","port","downloaded","uploaded","left") as $x)
if (!isset($x))
err("Missing key: $x");
$no_peer_id = (int) $_GET["no_peer_id"];
$compact = (int) $_GET["compact"];
if (strlen($GLOBALS['info_hash']) == 20)
$GLOBALS['info_hash'] = bin2hex($GLOBALS['info_hash']);
else if (strlen($GLOBALS['info_hash']) != 40)
err("Invalid info hash value.");
$GLOBALS['info_hash'] = strtolower($GLOBALS['info_hash']);
if ($MEMBERSONLY){
if (strlen($passkey) != 32)
err("Invalid passkey (" . strlen($passkey) . " - $passkey)");
}
$ip = getip();
foreach(array("num want", "numwant", "num_want") as $k)
{
if (isset($_GET[$k]))
{
$rsize = 0 + $_GET[$k];
break;
}
}
//PORT CHECK
if (!$port || $port > 0xffff)
err("invalid port");
//TRACKER EVENT CHECK
if (!isset($event))
$event = "";
$seeder = ($left == 0) ? "yes" : "no";
//Agent Ban
$agentarray = array_map("trim", explode(",", $site_config["BANNED_AGENTS"]));
$useragent = substr($peer_id, 0, 8);
foreach($agentarray as $bannedclient)
if(strpos($useragent, $bannedclient) !== false)
err("Client is banned");
//End Agent Bans
if (portblacklisted($port))
err("Port $port is blacklisted.");
$userfields = "id, class, uploaded, downloaded, ip, passkey, parked"; //user details to get
$peerfields = "seeder, UNIX_TIMESTAMP(last_action) AS ez, peer_id, ip, port, uploaded, downloaded, userid, passkey"; //peers details to get
$torrentfields = "id, name, info_hash, category, banned, freeleech, vip, seeders + leechers AS numpeers, UNIX_TIMESTAMP(added) AS ts, seeders, leechers, times_completed"; //torrent details to get
$userid = 0;
if ($MEMBERSONLY){
//check passkey is valid, and get users details
$res = mysql_query("SELECT $userfields FROM users WHERE passkey=".sqlesc($passkey)." AND enabled = 'yes' ORDER BY last_access DESC LIMIT 1") or err("Cannot Get User Details");
if ($user["parked"] == "yes")
err("Error, your account is parked! Please read the FAQ!");
$user = mysql_fetch_array($res);
if (!$user)
err("Cannot locate a user with that passkey!");
$userid = $user["id"]; //etc
}
//check torrent is valid and get torrent fields
$res = mysql_query("SELECT $torrentfields FROM torrents WHERE ".hash_where("info_hash", $info_hash)) or err("Cannot Get Torrent Details");
$torrent = mysql_fetch_array($res);
if (!$torrent)
err("Torrent not found on this tracker - hash = " . $info_hash);
if ($torrent["banned"]=='yes')
err("Torrent has been banned - hash = " . $info_hash);
$torrentid = $torrent["id"];
if ($torrent["vip"] == "y" && $user["class"] < 3)
err("This torrent is for VIPs only. Please visit $site_config[SITEURL] to upgrade.");
//Now get data from peers table
$peerlimit = 50;
$numpeers = $torrent["numpeers"];
if ($numpeers > $peerlimit){
$limit = "ORDER BY RAND() LIMIT $peerlimit";
}else{
$limit = "";
}
$res = mysql_query("SELECT $peerfields FROM peers WHERE torrent = $torrentid $limit") or err("Error Selecting Peers");
//DO SOME BENC STUFF TO THE PEERS CONNECTION
$resp = "d8:completei$torrent[seeders]e10:downloadedi$torrent[times_completed]e10:incompletei$torrent[leechers]e";
$resp .= benc_str("interval") . "i" . $site_config['announce_interval'] . "e" . benc_str("min interval") . "i300e" . benc_str("peers");
unset($self);
while ($row = mysql_fetch_assoc($res))
{
$row["peer_id"] = hash_pad($row["peer_id"]);
if ($row["peer_id"] === $peer_id)
{
$self = $row;
continue;
}
if (!$compact || $no_peer_id) {
$peers .= "d" .
benc_str("ip") . benc_str($row["ip"]);
if (!$no_peer_id)
$peers .= benc_str("peer id") . benc_str($row["peer_id"]);
$peers .= benc_str("port") . "i" . $row["port"] . "ee";
}else
$peers .= benc_str(ip2compact($row["ip"], $row["port"]));
}
if (!$compact || $no_peer_id)
$resp .= "l{$peers}e";
else
$resp .= benc_str($peers);
$resp .= "ee";
$selfwhere = "torrent = $torrentid AND " . hash_where("peer_id", $peer_id);
// FILL $SELF WITH DETAILS FROM PEERS TABLE (CONNECTING PEERS DETAILS)
if (!isset($self)){
//check passkey isnt leaked
if ($MEMBERSONLY) {
$valid = @mysql_fetch_row(@mysql_query("SELECT COUNT(*) FROM peers WHERE torrent=$torrentid AND passkey=" . sqlesc($passkey)));
if ($valid[0] >= 1 && $seeder == 'no')
err("Connection limit exceeded! You may only leech from one location at a time.");
if ($valid[0] >= 3 && $seeder == 'yes')
err("Connection limit exceeded!");
}
$res = mysql_query("SELECT $peerfields FROM peers WHERE $selfwhere");
$row = mysql_fetch_assoc($res);
if ($row){
$self = $row;
if(($connectable=checkconnect($row['ip'],$row['port']))=='yes')
mysql_query("UPDATE peers SET connectable='yes' WHERE $selfwhere");
}
}
// END $SELF FILL
if (!isset($self)){ //IF PEER IS NOT IN PEERS TABLE DO THE WAIT TIME CHECK
if ($MEMBERSONLY_WAIT && $MEMBERSONLY){
//wait time check
if($left > 0 && in_array($user["class"], explode(",",$site_config["WAIT_CLASS"]))){ //check only leechers and lowest user class
$gigs = $user["uploaded"] / (1024*1024*1024);
$elapsed = floor((gmtime() - $torrent["ts"]) / 3600);
$ratio = (($user["downloaded"] > 0) ? ($user["uploaded"] / $user["downloaded"]) : 1);
if ($ratio == 0 && $gigs == 0) $wait = $site_config["WAITA"];
elseif ($ratio < $site_config["RATIOA"] || $gigs < $site_config["GIGSA"]) $wait = $site_config["WAITA"];
elseif ($ratio < $site_config["RATIOB"] || $gigs < $site_config["GIGSB"]) $wait = $site_config["WAITB"];
elseif ($ratio < $site_config["RATIOC"] || $gigs < $site_config["GIGSC"]) $wait = $site_config["WAITC"];
elseif ($ratio < $site_config["RATIOD"] || $gigs < $site_config["GIGSD"]) $wait = $site_config["WAITD"];
else $wait = 0;
if ($elapsed < $wait)
err("Wait Time (" . ($wait - $elapsed) . " hours) - Visit ".$site_config["SITEURL"]." for more info");
}
}
$connectable=checkconnect($ip,$port);
}else{
// Deny access made with a browser...
if (ereg("^Mozilla\\/", $agent) || ereg("^Opera\\/", $agent) || ereg("^Links ", $agent) || ereg("^Lynx\\/", $agent))
die("Not for browser, use upload.php or browse.php");
// Cheat hunter
if (isset($_SERVER['HTTP_COOKIE']) || isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) || isset($_SERVER['HTTP_ACCEPT_CHARSET'])) {
$body = <<<EOD
Hello
Found cheater on {$_SERVER["REMOTE_ADDR"]}
Header of request
REMOTE_ADDR: {$_SERVER["REMOTE_ADDR"]}
HTTP_USER_AGENT: {$_SERVER[""]}
HTTP_ACCEPT: {$_SERVER["HTTP_ACCEPT"]}
HTTP_ACCEPT_ENCODING: {$_SERVER["HTTP_ACCEPT_ENCODING"]}
HTTP_ACCEPT_LANGUAGE: {$_SERVER["HTTP_ACCEPT_LANGUAGE"]}
HTTP_ACCEPT_CHARSET: {$_SERVER["HTTP_ACCEPT_CHARSET"]}
HTTP_COOKIE: {$_SERVER["HTTP_COOKIE"]}
REQUEST_METHOD: {$_SERVER["REQUEST_METHOD"]}
QUERY_STRING: {$_SERVER["QUERY_STRING"]}
HTTP_CONNECTION: {$_SERVER["HTTP_CONNECTION"]}
HTTP_REFERER: {$_SERVER["HTTP_REFERER"]}
REMOTE_PORT: {$_SERVER["REMOTE_PORT"]}
REQUEST_URI: {$_SERVER["REQUEST_URI"]}
---
Do not reply - autogenerated
WBR, $SITENAME
EOD;
mail($site_config['SITEEMAIL'], "CheatHunter: Cheater on ".$site_config['SITENAME']." from ".$_SERVER['REMOTE_ADDR']."", $body, "From: ".$site_config['SITENAME']." <".$site_config['SITEEMAIL'].">");
die("Rescue the Earth - kill itself");
}
$upthis = max(0, $uploaded - $self["uploaded"]);
$downthis = max(0, $downloaded - $self["downloaded"]);
if (($upthis > 0 || $downthis > 0) && is_valid_id($userid)){ // (LIVE STATS!)
if ($torrent["freeleech"] == 1){
mysql_query("UPDATE users SET uploaded = uploaded + $upthis WHERE id=$userid") or err("Tracker error: Unable to update stats");
}else{
mysql_query("UPDATE users SET uploaded = uploaded + $upthis, downloaded = downloaded + $downthis WHERE id=$userid") or err("Tracker error: Unable to update stats");
}
}
}//END WAIT AND STATS UPDATE
$updateset = array();
////////////////// NOW WE DO THE TRACKER EVENT UPDATES ///////////////////
if ($event == "stopped") { // UPDATE "STOPPED" EVENT
mysql_query("DELETE FROM peers WHERE $selfwhere");
if (mysql_affected_rows()){
if ($self["seeder"] == "yes")
$updateset[] = "seeders = seeders - 1";
else
$updateset[] = "leechers = leechers - 1";
}
}
if ($event == "completed") { // UPDATE "COMPLETED" EVENT
$updateset[] = "times_completed = times_completed + 1";
if ($MEMBERSONLY)
mysql_query("INSERT INTO completed (userid, torrentid, date) VALUES ($userid, $torrentid, '".get_date_time()."')");
}//END COMPLETED
if (isset($self)){// NO EVENT? THEN WE MUST BE A NEW PEER OR ARE NOW SEEDING A COMPLETED TORRENT
mysql_query("UPDATE peers SET ip = " . sqlesc($ip) . ", passkey = " . sqlesc($passkey) . ", port = $port, uploaded = $uploaded, downloaded = $downloaded, to_go = $left, last_action = '".get_date_time()."', client = " . sqlesc($agent) . ", seeder = '$seeder' WHERE $selfwhere");
if (mysql_affected_rows() && $self["seeder"] != $seeder){
if ($seeder == "yes"){
$updateset[] = "seeders = seeders + 1";
$updateset[] = "leechers = leechers - 1";
} else {
$updateset[] = "seeders = seeders - 1";
$updateset[] = "leechers = leechers + 1";
}
}
} else {
$ret = mysql_query("INSERT INTO peers (connectable, torrent, peer_id, ip, passkey, port, uploaded, downloaded, to_go, started, last_action, seeder, userid, client) VALUES ('$connectable', $torrentid, " . sqlesc($peer_id) . ", " . sqlesc($ip) . ", " . sqlesc($passkey) . ", $port, $uploaded, $downloaded, $left, '".get_date_time()."', '".get_date_time()."', '$seeder', '$userid', " . sqlesc($agent) . ")");
if ($ret){
if ($seeder == "yes")
$updateset[] = "seeders = seeders + 1";
else
$updateset[] = "leechers = leechers + 1";
}
}
////////////////// END TRACKER EVENT UPDATES ///////////////////
// SEEDED, LETS MAKE IT VISIBLE THEN
if ($seeder == "yes") {
if ($torrent["banned"] != "yes") // DONT MAKE BANNED ONES VISIBLE
$updateset[] = "visible = 'yes'";
$updateset[] = "last_action = '".get_date_time()."'";
}
// NOW WE UPDATE THE TORRENT AS PER ABOVE
if (count($updateset))
mysql_query("UPDATE torrents SET " . join(",", $updateset) . " WHERE id=$torrentid") or err("Tracker error: Unable to update torrent");
// NOW BENC THE DATA AND SEND TO CLIENT???
benc_resp_raw($resp);
mysql_close();
?>