PageRenderTime 57ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/announce.php

https://bitbucket.org/nexea/x00n
PHP | 319 lines | 242 code | 60 blank | 17 comment | 84 complexity | ddeee82654ba9e7dbadf7fd098b0f39f MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. ob_start("ob_gzhandler");
  3. require_once("Settings.php");
  4. require_once("lib/Library.php");
  5. require_once("lib/Benc.php");
  6. // check if we are using standard php tracker(low traffic) or
  7. // xbtt backend(high traffic) if using xbbt we will make a
  8. // redirect to xbtt announce using informations given in config
  9. // + pid if private
  10. if ($XBTT_USE)
  11. {
  12. function implode_with_keys($glue, $array) {
  13. $output = array();
  14. foreach( $array as $key => $item )
  15. $output[] = $key . "=" . $item;
  16. return implode($glue, $output);
  17. }
  18. if (isset ($_GET["pid"])) {
  19. $pid = $_GET["pid"];
  20. $pid = substr($pid , 0,strpos($pid , "?"));
  21. unset($_GET["pid"]);
  22. } else
  23. $pid = "";
  24. $query_string=implode_with_keys("&", $_GET);
  25. if ($pid!="") // private announce
  26. {
  27. header("Location: $XBTT_URL/$pid/announce?" . $query_string);
  28. }
  29. else // public
  30. {
  31. header("Location: $XBTT_URL/announce?" . $query_string);
  32. }
  33. exit;
  34. }
  35. function err($msg)
  36. {
  37. benc_resp(array("failure reason" => array(type => "string", value => $msg)));
  38. exit();
  39. }
  40. function benc_resp($d)
  41. {
  42. benc_resp_raw(benc(array(type => "dictionary", value => $d)));
  43. }
  44. function benc_resp_raw($x)
  45. {
  46. header("Content-Type: text/plain");
  47. header("Pragma: no-cache");
  48. print($x);
  49. }
  50. foreach (array("passkey","info_hash","peer_id","event","ip", "localip") as $x)
  51. {
  52. if(isset($_GET["$x"]))
  53. $GLOBALS[$x] = "" . $_GET[$x];
  54. }
  55. foreach (array("port","downloaded","uploaded","left") as $x)
  56. {
  57. $GLOBALS[$x] = 0 + $_GET[$x];
  58. }
  59. if (strpos($passkey, "?")) {
  60. $tmp = substr($passkey, strpos($passkey, "?"));
  61. $passkey = substr($passkey, 0, strpos($passkey, "?"));
  62. $tmpname = substr($tmp, 1, strpos($tmp, "=")-1);
  63. $tmpvalue = substr($tmp, strpos($tmp, "=")+1);
  64. $GLOBALS[$tmpname] = $tmpvalue;
  65. }
  66. foreach (array("passkey","info_hash","peer_id","port","downloaded","uploaded","left") as $x)
  67. if (!isset($x)) err("Missing key: $x");
  68. foreach (array("info_hash","peer_id") as $x)
  69. if (strlen($GLOBALS[$x]) != 20) err("Invalid $x (" . strlen($GLOBALS[$x]) . " - " . urlencode($GLOBALS[$x]) . ")");
  70. if (strlen($passkey) != 32) err("Invalid passkey (" . strlen($passkey) . " - $passkey)");
  71. //if (empty($ip) || !preg_match('/^(d{1,3}.){3}d{1,3}$/s', $ip))
  72. $ip = getip();
  73. $rsize = 50;
  74. foreach(array("num want", "numwant", "num_want") as $k)
  75. {
  76. if (isset($_GET[$k]))
  77. {
  78. $rsize = 0 + $_GET[$k];
  79. break;
  80. }
  81. }
  82. if (!$port || $port > 0xffff)
  83. err("invalid port");
  84. if (!isset($event))
  85. $event = "";
  86. $seeder = ($left == 0) ? "yes" : "no";
  87. dbconn(false);
  88. $valid = @mysql_fetch_row(@mysql_query("SELECT COUNT(*) FROM users WHERE passkey=" . sqlesc($passkey)));
  89. if ($valid[0] != 1) err("Invalid passkey! Re-download the .torrent from $domain");
  90. $res = mysql_query("SELECT id, banned, seeders + leechers AS numpeers, UNIX_TIMESTAMP(added) AS ts FROM torrents WHERE " . hash_where("info_hash", $info_hash)) or err('nog een query');
  91. $torrent = mysql_fetch_assoc($res);
  92. if (!$torrent)
  93. err("torrent not registered with this tracker");
  94. $torrentid = $torrent["id"];
  95. $fields = "seeder, peer_id, ip, port, uploaded, downloaded, userid";
  96. $numpeers = $torrent["numpeers"];
  97. $limit = "";
  98. if ($numpeers > $rsize)
  99. $limit = "ORDER BY RAND() LIMIT $rsize";
  100. $res = mysql_query("SELECT $fields FROM peers WHERE torrent = $torrentid AND connectable = 'yes' $limit") or err('nog iets');
  101. $resp = "d" . benc_str("interval") . "i" . $announce_interval . "e" . benc_str("peers") . "l";
  102. unset($self);
  103. while ($row = mysql_fetch_assoc($res))
  104. {
  105. $row["peer_id"] = hash_pad($row["peer_id"]);
  106. if ($row["peer_id"] === $peer_id)
  107. {
  108. $userid = $row["userid"];
  109. $self = $row;
  110. continue;
  111. }
  112. $resp .= "d" .
  113. benc_str("ip") . benc_str($row["ip"]) .
  114. benc_str("peer id") . benc_str($row["peer_id"]) .
  115. benc_str("port") . "i" . $row["port"] . "e" .
  116. "e";
  117. }
  118. $resp .= "ee";
  119. $selfwhere = "torrent = $torrentid AND " . hash_where("peer_id", $peer_id);
  120. if (!isset($self))
  121. {
  122. $sql = "SELECT $fields FROM peers WHERE $selfwhere";
  123. $res = mysql_query($sql) or err('fout');
  124. $row = mysql_fetch_assoc($res);
  125. if ($row)
  126. {
  127. $userid = $row["userid"];
  128. $self = $row;
  129. }
  130. }
  131. //// Up/down stats ////////////////////////////////////////////////////////////
  132. if (!isset($self))
  133. {
  134. $valid = @mysql_fetch_row(@mysql_query("SELECT COUNT(*) FROM peers WHERE torrent=$torrentid AND passkey=" . sqlesc($passkey))) or err('mistake');
  135. if ($valid[0] >= 1 && $seeder == 'no') err("Connection limit exceeded! You may only leech from one location at a time.");
  136. if ($valid[0] >= 3 && $seeder == 'yes') err("Connection limit exceeded!");
  137. $rz = mysql_query("SELECT id, uploaded, downloaded, class FROM users WHERE passkey=".sqlesc($passkey)." AND enabled = 'yes' ORDER BY last_access DESC LIMIT 1") or err("Tracker error 2");
  138. if ($privatetracker && mysql_num_rows($rz) == 0)
  139. err("Unknown passkey. Please redownload the torrent from $domain.");
  140. $az = mysql_fetch_assoc($rz);
  141. $userid = $az["id"];
  142. // if ($left > 0 && $az["class"] < UC_VIP)
  143. if ($az["class"] < UC_VIP)
  144. {
  145. $gigs = $az["uploaded"] / (1024*1024*1024);
  146. $elapsed = floor((gmtime() - $torrent["ts"]) / 3600);
  147. $ratio = (($az["downloaded"] > 0) ? ($az["uploaded"] / $az["downloaded"]) : 1);
  148. if ($ratio < 0.5 || $gigs < 5)
  149. $wait = 48;
  150. elseif ($ratio < 0.65 || $gigs < 6.5)
  151. $wait = 24;
  152. elseif ($ratio < 0.8 || $gigs < 8)
  153. $wait = 12;
  154. elseif ($ratio < 0.95 || $gigs < 9.5)
  155. $wait = 6;
  156. else
  157. $wait = 0;
  158. /*if ($elapsed < $wait)
  159. err($elapsed ." - ".$wait."Not authorized (" . ($wait - $elapsed) . "h) - READ THE FAQ!");
  160. */
  161. }
  162. }
  163. else
  164. {
  165. $upthis = max(0, $uploaded - $self["uploaded"]);
  166. $downthis = max(0, $downloaded - $self["downloaded"]);
  167. if ($upthis > 0 || $downthis > 0)
  168. mysql_query("UPDATE users SET uploaded = uploaded + $upthis, downloaded = downloaded + $downthis WHERE id=$userid") or err("Tracker error 3");
  169. }
  170. ///////////////////////////////////////////////////////////////////////////////
  171. function portblacklisted($port)
  172. {
  173. // direct connect
  174. if ($port >= 411 && $port <= 413) return true;
  175. // bittorrent
  176. if ($port >= 6881 && $port <= 6889) return true;
  177. // kazaa
  178. if ($port == 1214) return true;
  179. // gnutella
  180. if ($port >= 6346 && $port <= 6347) return true;
  181. // emule
  182. if ($port == 4662) return true;
  183. // winmx
  184. if ($port == 6699) return true;
  185. if ($port == 2706) return true;
  186. return false;
  187. }
  188. $updateset = array();
  189. if ($event == "stopped")
  190. {
  191. if (isset($self))
  192. {
  193. mysql_query("DELETE FROM peers WHERE $selfwhere");
  194. if (mysql_affected_rows())
  195. {
  196. if ($self["seeder"] == "yes")
  197. $updateset[] = "seeders = seeders - 1";
  198. else
  199. $updateset[] = "leechers = leechers - 1";
  200. }
  201. }
  202. }
  203. else
  204. {
  205. if ($event == "completed")
  206. $updateset[] = "times_completed = times_completed + 1";
  207. if (isset($self))
  208. {
  209. mysql_query("UPDATE peers SET uploaded = $uploaded, downloaded = $downloaded, to_go = $left, last_action = NOW(), seeder = '$seeder'"
  210. . ($seeder == "yes" && $self["seeder"] != $seeder ? ", finishedat = " . time() : "") . " WHERE $selfwhere");
  211. if (mysql_affected_rows() && $self["seeder"] != $seeder)
  212. {
  213. if ($seeder == "yes")
  214. {
  215. $updateset[] = "seeders = seeders + 1";
  216. $updateset[] = "leechers = leechers - 1";
  217. }
  218. else
  219. {
  220. $updateset[] = "seeders = seeders - 1";
  221. $updateset[] = "leechers = leechers + 1";
  222. }
  223. }
  224. }
  225. else
  226. {
  227. if (portblacklisted($port))
  228. err("Port $port is blacklisted.");
  229. else
  230. {
  231. $sockres = @fsockopen($ip, $port, $errno, $errstr, 5);
  232. if (!$sockres)
  233. $connectable = "no";
  234. else
  235. {
  236. $connectable = "yes";
  237. @fclose($sockres);
  238. }
  239. }
  240. $ret = mysql_query("INSERT INTO peers (connectable, torrent, peer_id, ip, port, uploaded, downloaded, to_go, started, last_action, seeder, userid, agent, uploadoffset, downloadoffset, passkey) VALUES ('$connectable', $torrentid, " . sqlesc($peer_id) . ", " . sqlesc($ip) . ", $port, $uploaded, $downloaded, $left, NOW(), NOW(), '$seeder', $userid, " . sqlesc($agent) . ", $uploaded, $downloaded, " . sqlesc($passkey) . ")") or err('tracker error');
  241. if ($ret)
  242. {
  243. if ($seeder == "yes")
  244. $updateset[] = "seeders = seeders + 1";
  245. else
  246. $updateset[] = "leechers = leechers + 1";
  247. }
  248. }
  249. }
  250. if ($seeder == "yes")
  251. {
  252. if ($torrent["banned"] != "yes")
  253. $updateset[] = "visible = 'yes'";
  254. $updateset[] = "last_action = NOW()";
  255. }
  256. if (count($updateset))
  257. mysql_query("UPDATE torrents SET " . join(",", $updateset) . " WHERE id = $torrentid");
  258. benc_resp_raw($resp);
  259. ?>