| ... | ... |
@@ -363,6 +363,13 @@ function sendRandomPeers($info_hash) |
| 363 | 363 |
echo str_pad($row[0], 6, chr(32)); |
| 364 | 364 |
} |
| 365 | 365 |
else |
| 366 |
+ if ($column == "compact") |
|
| 367 |
+ {
|
|
| 368 |
+ echo (mysql_num_rows($result) * 18) . ":"; |
|
| 369 |
+ while ($row = mysql_fetch_row($result)) |
|
| 370 |
+ echo str_pad($row[0], 18, chr(32)); |
|
| 371 |
+ } |
|
| 372 |
+ else |
|
| 366 | 373 |
{
|
| 367 | 374 |
echo "l"; |
| 368 | 375 |
while ($row = mysql_fetch_row($result)) |
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,678 @@ |
| 1 |
+<?php |
|
| 2 |
+ |
|
| 3 |
+ |
|
| 4 |
+////////////////////////////////////////////////////////////////// |
|
| 5 |
+// Worker functions |
|
| 6 |
+ |
|
| 7 |
+if (function_exists("bcadd"))
|
|
| 8 |
+{
|
|
| 9 |
+ function sqlAdd($left, $right) |
|
| 10 |
+ {
|
|
| 11 |
+ return bcadd($left, $right,0); |
|
| 12 |
+ } |
|
| 13 |
+ function sqlSubtract($left, $right) |
|
| 14 |
+ {
|
|
| 15 |
+ return bcsub($left, $right,0); |
|
| 16 |
+ } |
|
| 17 |
+ function sqlMultiply($left, $right) |
|
| 18 |
+ {
|
|
| 19 |
+ return bcmul($left, $right,0); |
|
| 20 |
+ } |
|
| 21 |
+ function sqlDivide($left, $right) |
|
| 22 |
+ {
|
|
| 23 |
+ return bcdiv($left, $right,0); |
|
| 24 |
+ } |
|
| 25 |
+} |
|
| 26 |
+else // BC vs SQL math |
|
| 27 |
+{
|
|
| 28 |
+ |
|
| 29 |
+// Uses the mysql database connection to perform string math. :) |
|
| 30 |
+// Used by byte counting functions |
|
| 31 |
+// No error handling as we assume nothing can go wrong. :| |
|
| 32 |
+function sqlAdd($left, $right) |
|
| 33 |
+{
|
|
| 34 |
+ $query = 'SELECT '.$left.'+'.$right; |
|
| 35 |
+ $results = mysql_query($query) or showError("Database error.");
|
|
| 36 |
+ return mysql_result($results,0,0); |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+// Ditto |
|
| 40 |
+function sqlSubtract($left, $right) |
|
| 41 |
+{
|
|
| 42 |
+ $query = 'SELECT '.$left.'-'.$right; |
|
| 43 |
+ $results = mysql_query($query) or showError("Database error");
|
|
| 44 |
+ return mysql_result($results,0,0); |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+function sqlDivide($left, $right) |
|
| 48 |
+{
|
|
| 49 |
+ $query = 'SELECT '.$left.'/'.$right; |
|
| 50 |
+ $results = mysql_query($query) or showError("Database error");
|
|
| 51 |
+ return mysql_result($results,0,0); |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+function sqlMultiply($left, $right) |
|
| 55 |
+{
|
|
| 56 |
+ $query = 'SELECT '.$left.'*'.$right; |
|
| 57 |
+ $results = mysql_query($query) or showError("Database error");
|
|
| 58 |
+ return mysql_result($results,0,0); |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+ |
|
| 62 |
+} // End of BC vs SQL |
|
| 63 |
+ |
|
| 64 |
+// Runs a query with no regard for the result |
|
| 65 |
+function quickQuery($query) |
|
| 66 |
+{
|
|
| 67 |
+ $results = @mysql_query($query); |
|
| 68 |
+ if (!is_bool($results)) |
|
| 69 |
+ mysql_free_result($results); |
|
| 70 |
+ else |
|
| 71 |
+ return $results; |
|
| 72 |
+ return true; |
|
| 73 |
+} |
|
| 74 |
+ |
|
| 75 |
+if(!function_exists('hex2bin'))
|
|
| 76 |
+{
|
|
| 77 |
+ function hex2bin ($input, $assume_safe=true) |
|
| 78 |
+ {
|
|
| 79 |
+ if ($assume_safe !== true && ! ((strlen($input) % 2) === 0 || preg_match ('/^[0-9a-f]+$/i', $input)))
|
|
| 80 |
+ return ""; |
|
| 81 |
+ return pack('H*', $input );
|
|
| 82 |
+ } |
|
| 83 |
+} |
|
| 84 |
+ |
|
| 85 |
+// Reports an error to the client in $message. |
|
| 86 |
+// Any other output will confuse the client, so please don't do that. |
|
| 87 |
+function showError($message, $log=false) |
|
| 88 |
+{
|
|
| 89 |
+ if ($log) |
|
| 90 |
+ error_log("RivetTracker: Sent error ($message)");
|
|
| 91 |
+ echo "d14:failure reason".strlen($message).":$message"."e"; |
|
| 92 |
+ exit(0); |
|
| 93 |
+} |
|
| 94 |
+ |
|
| 95 |
+ |
|
| 96 |
+function errorMessage() |
|
| 97 |
+{
|
|
| 98 |
+ echo "<center><img src='images/important.png' border='0' class='icon' alt='Critical Message' title='Critical Message' /></center>\n<p class='error'>"; |
|
| 99 |
+} |
|
| 100 |
+ |
|
| 101 |
+ |
|
| 102 |
+ |
|
| 103 |
+// Used by newtorrents.php |
|
| 104 |
+// Returns true/false, depending on if there were errors. |
|
| 105 |
+function makeTorrent($hash, $tolerate = false) |
|
| 106 |
+{
|
|
| 107 |
+ require("config.php"); //necessary to get the prefix value, require_once() doesn't seem to work :/
|
|
| 108 |
+ if (strlen($hash) != 40) |
|
| 109 |
+ showError("makeTorrent: Received an invalid hash");
|
|
| 110 |
+ $result = true; |
|
| 111 |
+ $query = "CREATE TABLE ".$prefix."x$hash (peer_id char(40) NOT NULL default '', bytes bigint NOT NULL default 0, ip char(50) NOT NULL default 'error.x', port smallint UNSIGNED NOT NULL default '0', status enum('leecher','seeder') NOT NULL, lastupdate int unsigned NOT NULL default 0, sequence int unsigned AUTO_INCREMENT NOT NULL, natuser enum('N', 'Y') not null default 'N', primary key(sequence), unique(peer_id)) DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci ENGINE = innodb";
|
|
| 112 |
+ if (!@mysql_query($query)) |
|
| 113 |
+ $result = false; |
|
| 114 |
+ if (!$result && !$tolerate) |
|
| 115 |
+ return false; |
|
| 116 |
+ //peercaching is ALWAYS on |
|
| 117 |
+ $query = "CREATE TABLE ".$prefix."y$hash (sequence int unsigned NOT NULL default 0, with_peerid char(101) NOT NULL default '', without_peerid char(40) NOT NULL default '', compact char(6) NOT NULL DEFAULT '', unique k (sequence)) DELAY_KEY_WRITE=1 CHECKSUM=0 DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci ENGINE = innodb"; |
|
| 118 |
+ mysql_query($query); |
|
| 119 |
+ |
|
| 120 |
+ $query = "INSERT INTO ".$prefix."summary set info_hash='".$hash."', lastSpeedCycle=UNIX_TIMESTAMP()"; |
|
| 121 |
+ if (!@mysql_query($query)) |
|
| 122 |
+ $result = false; |
|
| 123 |
+ return $result; |
|
| 124 |
+} |
|
| 125 |
+ |
|
| 126 |
+// Returns true if the torrent exists. |
|
| 127 |
+// Currently checks by locating the row in "summary" |
|
| 128 |
+function verifyTorrent($hash) |
|
| 129 |
+{
|
|
| 130 |
+ require("config.php"); //need prefix value...
|
|
| 131 |
+ $query = "SELECT COUNT(*) FROM ".$prefix."summary where info_hash='$hash'"; |
|
| 132 |
+ $results = mysql_query($query); |
|
| 133 |
+ |
|
| 134 |
+ $res = mysql_result($results,0,0); |
|
| 135 |
+ |
|
| 136 |
+ if ($res == 1) |
|
| 137 |
+ return true; |
|
| 138 |
+ |
|
| 139 |
+ return false; |
|
| 140 |
+} |
|
| 141 |
+ |
|
| 142 |
+function verifyHash($input) |
|
| 143 |
+{
|
|
| 144 |
+ if (strlen($input) === 40 && preg_match('/^[0-9a-f]+$/', $input))
|
|
| 145 |
+ return true; |
|
| 146 |
+ else |
|
| 147 |
+ return false; |
|
| 148 |
+} |
|
| 149 |
+ |
|
| 150 |
+ |
|
| 151 |
+ |
|
| 152 |
+ |
|
| 153 |
+// Returns info on one peer |
|
| 154 |
+function getPeerInfo($user, $hash) |
|
| 155 |
+{
|
|
| 156 |
+ require("config.php");
|
|
| 157 |
+ // If "trackerid" is set, let's try that |
|
| 158 |
+ if (isset($GLOBALS["trackerid"])) |
|
| 159 |
+ {
|
|
| 160 |
+ $query = "SELECT peer_id,bytes,ip,port,status,lastupdate,sequence FROM ".$prefix."x$hash WHERE sequence=${GLOBALS["trackerid"]}";
|
|
| 161 |
+ $results = mysql_query($query) or showError("Tracker error: invalid torrent");
|
|
| 162 |
+ $data = mysql_fetch_assoc($results); |
|
| 163 |
+ if (!$data || $data["peer_id"] != $user) |
|
| 164 |
+ {
|
|
| 165 |
+ // Damn, but don't crash just yet. |
|
| 166 |
+ $query = "SELECT peer_id,bytes,ip,port,status,lastupdate,sequence FROM ".$prefix."x$hash WHERE peer_id='$user'"; |
|
| 167 |
+ $results = mysql_query($query) or showError("Tracker error: invalid torrent");
|
|
| 168 |
+ $data = mysql_fetch_assoc($results); |
|
| 169 |
+ $GLOBALS["trackerid"] = $data["sequence"]; |
|
| 170 |
+ } |
|
| 171 |
+ } |
|
| 172 |
+ else |
|
| 173 |
+ {
|
|
| 174 |
+ $query = "SELECT peer_id,bytes,ip,port,status,lastupdate,sequence FROM ".$prefix."x$hash WHERE peer_id='$user'"; |
|
| 175 |
+ $results = mysql_query($query) or showError("Tracker error: invalid torrent");
|
|
| 176 |
+ $data = mysql_fetch_assoc($results); |
|
| 177 |
+ $GLOBALS["trackerid"] = $data["sequence"]; |
|
| 178 |
+ |
|
| 179 |
+ } |
|
| 180 |
+ |
|
| 181 |
+ if (!($data)) |
|
| 182 |
+ return false; |
|
| 183 |
+ |
|
| 184 |
+ return $data; |
|
| 185 |
+} |
|
| 186 |
+ |
|
| 187 |
+// Slight redesign of loadPeers |
|
| 188 |
+function getRandomPeers($hash, $where="") |
|
| 189 |
+{
|
|
| 190 |
+ require("config.php");
|
|
| 191 |
+ |
|
| 192 |
+ // Don't want to send a bad "num peers" for new seeds |
|
| 193 |
+ if ($GLOBALS["NAT"]) |
|
| 194 |
+ $results = mysql_query("SELECT COUNT(*) FROM ".$prefix."x$hash WHERE natuser = 'N'");
|
|
| 195 |
+ else |
|
| 196 |
+ $results = mysql_query("SELECT COUNT(*) FROM ".$prefix."x$hash");
|
|
| 197 |
+ |
|
| 198 |
+ $peercount = mysql_result($results, 0,0); |
|
| 199 |
+ |
|
| 200 |
+ // ORDER BY RAND() is expensive. Don't do it when the load gets too high |
|
| 201 |
+ if ($peercount < 500) |
|
| 202 |
+ $query = "SELECT ".((isset($_GET["no_peer_id"]) && $_GET["no_peer_id"] == 1) ? "" : "peer_id,")."ip, port, status FROM ".$prefix."x$hash ".$where." ORDER BY RAND() LIMIT ${GLOBALS['maxpeers']}";
|
|
| 203 |
+ else |
|
| 204 |
+ $query = "SELECT ".((isset($_GET["no_peer_id"]) && $_GET["no_peer_id"] == 1) ? "" : "peer_id,")."ip, port, status FROM ".$prefix."x$hash LIMIT ".@mt_rand(0, $peercount - $GLOBALS["maxpeers"]).", ${GLOBALS['maxpeers']}";
|
|
| 205 |
+ |
|
| 206 |
+ $results = mysql_query($query); |
|
| 207 |
+ if (!$results) |
|
| 208 |
+ return false; |
|
| 209 |
+ |
|
| 210 |
+ $peerno = 0; |
|
| 211 |
+ while ($return[] = mysql_fetch_assoc($results)) |
|
| 212 |
+ $peerno++; |
|
| 213 |
+ |
|
| 214 |
+ array_pop ($return); |
|
| 215 |
+ mysql_free_result($results); |
|
| 216 |
+ $return['size'] = $peerno; |
|
| 217 |
+ |
|
| 218 |
+ return $return; |
|
| 219 |
+} |
|
| 220 |
+ |
|
| 221 |
+// Deletes a peer from the system and performs all cleaning up |
|
| 222 |
+// |
|
| 223 |
+// $assumepeer contains the result of getPeerInfo, or false |
|
| 224 |
+// if we should grab it ourselves. |
|
| 225 |
+function killPeer($userid, $hash, $left, $assumepeer = false) |
|
| 226 |
+{
|
|
| 227 |
+ require("config.php");
|
|
| 228 |
+ if (!$assumepeer) |
|
| 229 |
+ {
|
|
| 230 |
+ $peer = getPeerInfo($userid, $hash); |
|
| 231 |
+ if (!$peer) |
|
| 232 |
+ return; |
|
| 233 |
+ if ($left != $peer["bytes"]) |
|
| 234 |
+ $bytes = sqlSubtract($peer["bytes"], $left); |
|
| 235 |
+ else |
|
| 236 |
+ $bytes = 0; |
|
| 237 |
+ } |
|
| 238 |
+ else |
|
| 239 |
+ {
|
|
| 240 |
+ $bytes = 0; |
|
| 241 |
+ $peer = $assumepeer; |
|
| 242 |
+ } |
|
| 243 |
+ |
|
| 244 |
+ quickQuery("DELETE FROM ".$prefix."x$hash WHERE peer_id='$userid'");
|
|
| 245 |
+ if (mysql_affected_rows() == 1) |
|
| 246 |
+ {
|
|
| 247 |
+ //peercaching ALWAYS on |
|
| 248 |
+ quickQuery("DELETE FROM ".$prefix."y$hash WHERE sequence=" . $peer["sequence"]);
|
|
| 249 |
+ if ($peer["status"] == "leecher") |
|
| 250 |
+ summaryAdd("leechers", -1);
|
|
| 251 |
+ else |
|
| 252 |
+ summaryAdd("seeds", -1);
|
|
| 253 |
+ if ($GLOBALS["countbytes"] && ((float)$bytes) > 0) |
|
| 254 |
+ summaryAdd("dlbytes",$bytes);
|
|
| 255 |
+ if ($peer["bytes"] != 0 && $left == 0) |
|
| 256 |
+ summaryAdd("finished", 1);
|
|
| 257 |
+ } |
|
| 258 |
+} |
|
| 259 |
+ |
|
| 260 |
+// Transfers bytes from "left" to "dlbytes" when a peer reports in. |
|
| 261 |
+function collectBytes($peer, $hash, $left) |
|
| 262 |
+{
|
|
| 263 |
+ require("config.php");
|
|
| 264 |
+ $peerid=$peer["peer_id"]; |
|
| 265 |
+ |
|
| 266 |
+ if (!$GLOBALS["countbytes"]) |
|
| 267 |
+ {
|
|
| 268 |
+ quickQuery("UPDATE ".$prefix."x$hash SET lastupdate=UNIX_TIMESTAMP() where " . (isset($GLOBALS["trackerid"]) ? "sequence='${GLOBALS["trackerid"]}'" : "peer_id='$peerid'"));
|
|
| 269 |
+ return; |
|
| 270 |
+ } |
|
| 271 |
+ $diff = sqlSubtract($peer["bytes"], $left); |
|
| 272 |
+ quickQuery("UPDATE ".$prefix."x$hash set " . (($diff != 0) ? "bytes='$left'," : ""). " lastupdate=UNIX_TIMESTAMP() where " . (isset($GLOBALS["trackerid"]) ? "sequence='${GLOBALS["trackerid"]}'" : "peer_id='$peerid'"));
|
|
| 273 |
+ |
|
| 274 |
+ |
|
| 275 |
+ // Anti-negative clause |
|
| 276 |
+ if (((float)$diff) > 0) |
|
| 277 |
+ summaryAdd("dlbytes", $diff);
|
|
| 278 |
+} |
|
| 279 |
+ |
|
| 280 |
+// Transmits the actual data to the peer. No other output is permitted if |
|
| 281 |
+// this function is called, as that would break BEncoding. |
|
| 282 |
+// I don't use the bencode library, so watch out! If you add data, |
|
| 283 |
+// rules such as dictionary sorting are enforced by the remote side. |
|
| 284 |
+function sendPeerList($peers) |
|
| 285 |
+{
|
|
| 286 |
+ echo "d"; |
|
| 287 |
+ echo "8:intervali".$GLOBALS["report_interval"]."e"; |
|
| 288 |
+ if (isset($GLOBALS["min_interval"])) |
|
| 289 |
+ echo "12:min intervali".$GLOBALS["min_interval"]."e"; |
|
| 290 |
+ echo "5:peers"; |
|
| 291 |
+ $size=$peers["size"]; |
|
| 292 |
+ if (isset($_GET["compact"]) && $_GET["compact"] == '1') |
|
| 293 |
+ {
|
|
| 294 |
+ $p = ''; |
|
| 295 |
+ for ($i=0; $i < $size; $i++) |
|
| 296 |
+ $p .= pack("Nn", ip2long($peers[$i]['ip']), $peers[$i]['port']);
|
|
| 297 |
+ echo strlen($p).':'.$p; |
|
| 298 |
+ } |
|
| 299 |
+ else // no_peer_id or no feature supported |
|
| 300 |
+ {
|
|
| 301 |
+ echo 'l'; |
|
| 302 |
+ for ($i=0; $i < $size; $i++) |
|
| 303 |
+ {
|
|
| 304 |
+ echo "d2:ip".strlen($peers[$i]["ip"]).":".$peers[$i]["ip"]; |
|
| 305 |
+ if (isset($peers[$i]["peer_id"])) |
|
| 306 |
+ echo "7:peer id20:".hex2bin($peers[$i]["peer_id"]); |
|
| 307 |
+ echo "4:porti".$peers[$i]["port"]."ee"; |
|
| 308 |
+ } |
|
| 309 |
+ echo "e"; |
|
| 310 |
+ } |
|
| 311 |
+ if (isset($GLOBALS["trackerid"])) |
|
| 312 |
+ {
|
|
| 313 |
+ // Now it gets annoying. trackerid is a string |
|
| 314 |
+ echo "10:tracker id".strlen($GLOBALS["trackerid"]).":".$GLOBALS["trackerid"]; |
|
| 315 |
+ } |
|
| 316 |
+ |
|
| 317 |
+ echo "e"; |
|
| 318 |
+} |
|
| 319 |
+ |
|
| 320 |
+ |
|
| 321 |
+// Faster pass-through version of getRandompeers => sendPeerList |
|
| 322 |
+// It's the only way to use cache tables. In fact, it only uses it. |
|
| 323 |
+function sendRandomPeers($info_hash) |
|
| 324 |
+{
|
|
| 325 |
+ require("config.php");
|
|
| 326 |
+ $result = mysql_query("SELECT COUNT(*) FROM ".$prefix."y$info_hash");
|
|
| 327 |
+ $count = mysql_result($result, 0, 0); |
|
| 328 |
+ |
|
| 329 |
+ if (isset($_GET["compact"]) && $_GET["compact"] == '1') |
|
| 330 |
+ $column = "compact"; |
|
| 331 |
+ else if (isset($_GET["no_peer_id"]) && $_GET["no_peer_id"] == '1') |
|
| 332 |
+ $column = "without_peerid"; |
|
| 333 |
+ else |
|
| 334 |
+ $column = "with_peerid"; |
|
| 335 |
+ |
|
| 336 |
+ if ($count < $GLOBALS["maxpeers"]) |
|
| 337 |
+ $query = "SELECT $column FROM ".$prefix."y$info_hash"; |
|
| 338 |
+ else if ($count > 500) |
|
| 339 |
+ {
|
|
| 340 |
+ do |
|
| 341 |
+ {
|
|
| 342 |
+ $rand1 = mt_rand(0, $count-$GLOBALS["maxpeers"]); |
|
| 343 |
+ $rand2 = mt_rand(0, $count-$GLOBALS["maxpeers"]); |
|
| 344 |
+ } while (abs($rand1 - $rand2) < $GLOBALS["maxpeers"]/2); |
|
| 345 |
+ $query = "(SELECT $column FROM ".$prefix."y$info_hash LIMIT $rand1, ".($GLOBALS["maxpeers"]/2). ") UNION (SELECT $column FROM ".$prefix."y$info_hash LIMIT $rand2, ".($GLOBALS["maxpeers"]/2). ")"; |
|
| 346 |
+ } |
|
| 347 |
+ else |
|
| 348 |
+ $query = "SELECT $column FROM ".$prefix."y$info_hash ORDER BY RAND() LIMIT ".$GLOBALS["maxpeers"]; |
|
| 349 |
+ |
|
| 350 |
+ |
|
| 351 |
+ |
|
| 352 |
+ echo "d"; |
|
| 353 |
+ echo "8:intervali".$GLOBALS["report_interval"]."e"; |
|
| 354 |
+ if (isset($GLOBALS["min_interval"])) |
|
| 355 |
+ echo "12:min intervali".$GLOBALS["min_interval"]."e"; |
|
| 356 |
+ echo "5:peers"; |
|
| 357 |
+ |
|
| 358 |
+ $result = mysql_query($query); |
|
| 359 |
+ if ($column == "compact") |
|
| 360 |
+ {
|
|
| 361 |
+ echo (mysql_num_rows($result) * 6) . ":"; |
|
| 362 |
+ while ($row = mysql_fetch_row($result)) |
|
| 363 |
+ echo str_pad($row[0], 6, chr(32)); |
|
| 364 |
+ } |
|
| 365 |
+ else |
|
| 366 |
+ {
|
|
| 367 |
+ echo "l"; |
|
| 368 |
+ while ($row = mysql_fetch_row($result)) |
|
| 369 |
+ echo "d".$row[0]."e"; |
|
| 370 |
+ echo "e"; |
|
| 371 |
+ } |
|
| 372 |
+ if (isset($GLOBALS["trackerid"])) |
|
| 373 |
+ echo "10:tracker id".strlen($GLOBALS["trackerid"]).":".$GLOBALS["trackerid"]; |
|
| 374 |
+ echo "e"; |
|
| 375 |
+} |
|
| 376 |
+ |
|
| 377 |
+ |
|
| 378 |
+// Returns a $peers array of all peers that have timed out (2* report interval seems fair |
|
| 379 |
+// for any reasonable report interval (900 or larger)) |
|
| 380 |
+function loadLostPeers($hash, $timeout) |
|
| 381 |
+{
|
|
| 382 |
+ require("config.php"); //necessary for getting prefix value
|
|
| 383 |
+ $results = mysql_query("SELECT peer_id,bytes,ip,port,status,lastupdate,sequence from ".$prefix."x$hash where lastupdate < (UNIX_TIMESTAMP() - 2 * $timeout)");
|
|
| 384 |
+ $peerno = 0; |
|
| 385 |
+ if (!$results) |
|
| 386 |
+ return false; |
|
| 387 |
+ |
|
| 388 |
+ while ($return[] = mysql_fetch_assoc($results)) |
|
| 389 |
+ $peerno++; |
|
| 390 |
+ array_pop($return); |
|
| 391 |
+ $return["size"] = $peerno; |
|
| 392 |
+ mysql_free_result($results); |
|
| 393 |
+ return $return; |
|
| 394 |
+} |
|
| 395 |
+ |
|
| 396 |
+function trashCollector($hash, $timeout) |
|
| 397 |
+{
|
|
| 398 |
+ require("config.php"); //need to grab prefix value...
|
|
| 399 |
+ if (isset($GLOBALS["trackerid"])) |
|
| 400 |
+ unset($GLOBALS["trackerid"]); |
|
| 401 |
+ |
|
| 402 |
+ if (!Lock($hash)) |
|
| 403 |
+ return; |
|
| 404 |
+ |
|
| 405 |
+ $results = mysql_query("SELECT lastcycle FROM ".$prefix."summary WHERE info_hash='$hash'");
|
|
| 406 |
+ $lastcheck = (mysql_fetch_row($results)); |
|
| 407 |
+ |
|
| 408 |
+ // Check once every re-announce cycle |
|
| 409 |
+ if (($lastcheck[0] + $timeout) < time()) |
|
| 410 |
+ {
|
|
| 411 |
+ $peers = loadLostPeers($hash, $timeout); |
|
| 412 |
+ for ($i=0; $i < $peers["size"]; $i++) |
|
| 413 |
+ killPeer($peers[$i]["peer_id"], $hash, $peers[$i]["bytes"]); |
|
| 414 |
+ summaryAdd("lastcycle", "UNIX_TIMESTAMP()", true);
|
|
| 415 |
+ } |
|
| 416 |
+ Unlock($hash); |
|
| 417 |
+} |
|
| 418 |
+ |
|
| 419 |
+// Attempts to aquire a lock by name. |
|
| 420 |
+// Returns true on success, false on failure |
|
| 421 |
+function Lock($hash, $time = 0) |
|
| 422 |
+{
|
|
| 423 |
+ $results = mysql_query("SELECT GET_LOCK('$hash', $time)");
|
|
| 424 |
+ $string = mysql_fetch_row($results); |
|
| 425 |
+ if (strcmp($string[0], "1") == 0) |
|
| 426 |
+ return true; |
|
| 427 |
+ return false; |
|
| 428 |
+ |
|
| 429 |
+} |
|
| 430 |
+ |
|
| 431 |
+// Releases a lock. Ignores errors. |
|
| 432 |
+function Unlock($hash) |
|
| 433 |
+{
|
|
| 434 |
+ quickQuery("SELECT RELEASE_LOCK('$hash')");
|
|
| 435 |
+} |
|
| 436 |
+ |
|
| 437 |
+// Returns true if the lock is available |
|
| 438 |
+function isFreeLock($lock) |
|
| 439 |
+{
|
|
| 440 |
+ if (Lock($lock, 0)) |
|
| 441 |
+ {
|
|
| 442 |
+ Unlock($lock); |
|
| 443 |
+ return true; |
|
| 444 |
+ } |
|
| 445 |
+ return false; |
|
| 446 |
+} |
|
| 447 |
+ |
|
| 448 |
+ |
|
| 449 |
+/* Returns true if the user is firewalled, NAT'd, or whatever. |
|
| 450 |
+ * The original tracker had its --nat_check parameter, so |
|
| 451 |
+ * here is my version. |
|
| 452 |
+ * |
|
| 453 |
+ * This code has proven itself to be sufficiently correct, |
|
| 454 |
+ * but will consume system resources when a lot of httpd processes |
|
| 455 |
+ * are lingering around trying to connect to remote hosts. |
|
| 456 |
+ * Consider disabling it under higher loads. |
|
| 457 |
+ */ |
|
| 458 |
+function isFireWalled($hash, $peerid, $ip, $port) |
|
| 459 |
+{
|
|
| 460 |
+ |
|
| 461 |
+ // NAT checking off? |
|
| 462 |
+ if (!$GLOBALS["NAT"]) |
|
| 463 |
+ return false; |
|
| 464 |
+ |
|
| 465 |
+ $protocol_name = 'BitTorrent protocol'; |
|
| 466 |
+ $theError = ""; |
|
| 467 |
+ // Hoping 10 seconds will be enough |
|
| 468 |
+ $fd = fsockopen($ip, $port, $errno, $theError, 10); |
|
| 469 |
+ if (!$fd) |
|
| 470 |
+ return true; |
|
| 471 |
+ |
|
| 472 |
+ stream_set_timeout($fd, 5, 0); |
|
| 473 |
+ fwrite($fd, chr(strlen($protocol_name)).$protocol_name.hex2bin("0000000000000000").
|
|
| 474 |
+ hex2bin($hash)); |
|
| 475 |
+ |
|
| 476 |
+ $data = fread($fd, strlen($protocol_name)+1+20+20+8); // ideally... |
|
| 477 |
+ |
|
| 478 |
+ fclose($fd); |
|
| 479 |
+ $offset = 0; |
|
| 480 |
+ |
|
| 481 |
+ // First byte: strlen($protocol_name), then the protocol string itself |
|
| 482 |
+ if (ord($data[$offset]) != strlen($protocol_name)) |
|
| 483 |
+ return true; |
|
| 484 |
+ |
|
| 485 |
+ $offset++; |
|
| 486 |
+ if (substr($data, $offset, strlen($protocol_name)) != $protocol_name) |
|
| 487 |
+ return true; |
|
| 488 |
+ |
|
| 489 |
+ $offset += strlen($protocol_name); |
|
| 490 |
+ // 8 bytes reserved, ignore |
|
| 491 |
+ $offset += 8; |
|
| 492 |
+ |
|
| 493 |
+ // Download ID (hash) |
|
| 494 |
+ if (substr($data, $offset, 20) != hex2bin($hash)) |
|
| 495 |
+ return true; |
|
| 496 |
+ |
|
| 497 |
+ $offset+=20; |
|
| 498 |
+ |
|
| 499 |
+ // Peer ID |
|
| 500 |
+ if (substr($data, $offset, 20) != hex2bin($peerid)) |
|
| 501 |
+ return true; |
|
| 502 |
+ |
|
| 503 |
+ |
|
| 504 |
+ return false; |
|
| 505 |
+} |
|
| 506 |
+ |
|
| 507 |
+ |
|
| 508 |
+// It's cruel, but if people abuse my tracker, I just might do it. |
|
| 509 |
+// It pretends to accept the torrent, and reports that you are the |
|
| 510 |
+// only person connected. |
|
| 511 |
+function evilReject($ip, $peer_id, $port) |
|
| 512 |
+{
|
|
| 513 |
+ |
|
| 514 |
+ // For those of you who are feeling evil, comment out this line. |
|
| 515 |
+ showError("Torrent is not authorized for use on this tracker.");
|
|
| 516 |
+ |
|
| 517 |
+ $peers[0]["peer_id"] = $peer_id; |
|
| 518 |
+ $peers[0]["ip"] = $ip; |
|
| 519 |
+ $peers[0]["port"] = $port; |
|
| 520 |
+ $peers["size"] = 1; |
|
| 521 |
+ $GLOBALS["report_interval"] = 86400; |
|
| 522 |
+ $GLOBALS["min_interval"] = 86000; |
|
| 523 |
+ sendPeerList($peers); |
|
| 524 |
+ exit(0); |
|
| 525 |
+} |
|
| 526 |
+ |
|
| 527 |
+ |
|
| 528 |
+function runSpeed($info_hash, $delta) |
|
| 529 |
+{
|
|
| 530 |
+ require("config.php");
|
|
| 531 |
+ //stick in our latest data before we calc it out |
|
| 532 |
+ quickQuery("INSERT IGNORE INTO ".$prefix."timestamps (info_hash, bytes, delta, sequence) SELECT '$info_hash' AS info_hash, dlbytes, UNIX_TIMESTAMP() - lastSpeedCycle, NULL FROM ".$prefix."summary WHERE info_hash='$info_hash'");
|
|
| 533 |
+ |
|
| 534 |
+ // mysql blows sometimes so we have to read the data into php before updating it |
|
| 535 |
+ $results = mysql_query('SELECT (MAX(bytes)-MIN(bytes))/SUM(delta), COUNT(*), MIN(sequence) FROM '.$prefix.'timestamps WHERE info_hash="'.$info_hash.'"' );
|
|
| 536 |
+ $data = mysql_fetch_row($results); |
|
| 537 |
+ |
|
| 538 |
+ $results2 = mysql_query('SELECT '.$prefix.'summary.leechers FROM '.$prefix.'summary WHERE info_hash="'.$info_hash.'"');
|
|
| 539 |
+ $data2 = mysql_fetch_row($results2); |
|
| 540 |
+ if ($data2[0] == 0) //if no leechers, speed is zero |
|
| 541 |
+ $data[0] = 0; |
|
| 542 |
+ |
|
| 543 |
+ $results3 = mysql_query("SELECT MIN(d1.bytes), MAX(d1.bytes) FROM (SELECT bytes FROM ".$prefix."timestamps WHERE info_hash='".$info_hash."' ORDER BY sequence DESC LIMIT 5) AS d1");
|
|
| 544 |
+ $data3 = mysql_fetch_row($results3); |
|
| 545 |
+ //if the last 5 updates from clients show the same bytes, it's probably stalled, set speed to zero |
|
| 546 |
+ if ($data3[0] == $data3[1]) |
|
| 547 |
+ $data[0] = 0; |
|
| 548 |
+ |
|
| 549 |
+ summaryAdd("speed", $data[0], true);
|
|
| 550 |
+ summaryAdd("lastSpeedCycle", "UNIX_TIMESTAMP()", true);
|
|
| 551 |
+ |
|
| 552 |
+ // if we have more than 20 drop the rest |
|
| 553 |
+ //if ($data[1] == 21) |
|
| 554 |
+ //quickQuery("DELETE FROM timestamps WHERE info_hash='$info_hash' AND sequence=${data[2]}");
|
|
| 555 |
+ if ($data[1] > 21) |
|
| 556 |
+ // This query requires MySQL 4.0.x, but should rarely be used. |
|
| 557 |
+ quickQuery ('DELETE FROM '.$prefix.'timestamps WHERE info_hash="'.$info_hash.'" ORDER BY sequence LIMIT '.($data['1'] - 20));
|
|
| 558 |
+} |
|
| 559 |
+ |
|
| 560 |
+// Schedules an update to the summary table. It gets so much traffic |
|
| 561 |
+// that we do all our changes at once. |
|
| 562 |
+// When called, the column $column for the current info_hash is incremented |
|
| 563 |
+// by $value, or set to exactly $value if $abs is true. |
|
| 564 |
+function summaryAdd($column, $value, $abs = false) |
|
| 565 |
+{
|
|
| 566 |
+ if (isset($GLOBALS["summaryupdate"][$column])) |
|
| 567 |
+ {
|
|
| 568 |
+ if (!$abs) |
|
| 569 |
+ $GLOBALS["summaryupdate"][$column][0] += $value; |
|
| 570 |
+ else |
|
| 571 |
+ showError("Tracker bug calling summaryAdd");
|
|
| 572 |
+ } |
|
| 573 |
+ else |
|
| 574 |
+ {
|
|
| 575 |
+ $GLOBALS["summaryupdate"][$column][0] = $value; |
|
| 576 |
+ $GLOBALS["summaryupdate"][$column][1] = $abs; |
|
| 577 |
+ } |
|
| 578 |
+} |
|
| 579 |
+ |
|
| 580 |
+ |
|
| 581 |
+//converts byte size to string format for display |
|
| 582 |
+function bytesToString($total_size) |
|
| 583 |
+{
|
|
| 584 |
+ if ($total_size < 1024) //dealing with bytes |
|
| 585 |
+ return $total_size . " bytes"; |
|
| 586 |
+ elseif ($total_size < 1048576) //dealing with kilobytes |
|
| 587 |
+ return round($total_size/1024, 2) . " KB"; |
|
| 588 |
+ elseif ($total_size < 1073741824) //dealing with megabytes |
|
| 589 |
+ return round($total_size/1048576, 2) . " MB"; |
|
| 590 |
+ elseif ($total_size >= 1073741824) //dealing with gigabytes |
|
| 591 |
+ return round($total_size/1073741824, 2) . " GB"; |
|
| 592 |
+} |
|
| 593 |
+ |
|
| 594 |
+ |
|
| 595 |
+// Even if you're missing PHP 4.3.0, the MHASH extension might be of use. |
|
| 596 |
+// Someone was kind enought to email this code snippit in. |
|
| 597 |
+if (function_exists('mhash') && (!function_exists('sha1')) &&
|
|
| 598 |
+defined('MHASH_SHA1'))
|
|
| 599 |
+{
|
|
| 600 |
+ function sha1($str) |
|
| 601 |
+ {
|
|
| 602 |
+ return bin2hex(mhash(MHASH_SHA1,$str)); |
|
| 603 |
+ } |
|
| 604 |
+} |
|
| 605 |
+ |
|
| 606 |
+//If magic quotes are on, returns the cleaned (no single quotes) output string |
|
| 607 |
+function clean($input) |
|
| 608 |
+{
|
|
| 609 |
+ if (get_magic_quotes_gpc()) |
|
| 610 |
+ return stripslashes($input); |
|
| 611 |
+ return $input; |
|
| 612 |
+} |
|
| 613 |
+ |
|
| 614 |
+//If magic quotes are off, returns the added (single quotes) output string |
|
| 615 |
+function addquotes($input) |
|
| 616 |
+{
|
|
| 617 |
+ if (!get_magic_quotes_gpc()) |
|
| 618 |
+ return addslashes($input); |
|
| 619 |
+ return $input; |
|
| 620 |
+} |
|
| 621 |
+ |
|
| 622 |
+//generic filter function for cleaning data |
|
| 623 |
+function filterData($data) |
|
| 624 |
+{
|
|
| 625 |
+ $data = trim(htmlentities(strip_tags($data))); |
|
| 626 |
+ |
|
| 627 |
+ if (get_magic_quotes_gpc()) {
|
|
| 628 |
+ return stripslashes($data); |
|
| 629 |
+ } |
|
| 630 |
+ |
|
| 631 |
+ $data = mysql_real_escape_string($data); |
|
| 632 |
+ |
|
| 633 |
+ return $data; |
|
| 634 |
+} |
|
| 635 |
+ |
|
| 636 |
+//generic filter function for character cleaning data |
|
| 637 |
+function filterChar($data) |
|
| 638 |
+{
|
|
| 639 |
+ $data = filter_var($data, FILTER_SANITIZE_FULL_SPECIAL_CHARS); |
|
| 640 |
+ |
|
| 641 |
+ if (get_magic_quotes_gpc()) {
|
|
| 642 |
+ return stripslashes($data); |
|
| 643 |
+ } |
|
| 644 |
+ |
|
| 645 |
+ $data = mysql_real_escape_string($data); |
|
| 646 |
+ |
|
| 647 |
+ return $data; |
|
| 648 |
+} |
|
| 649 |
+ |
|
| 650 |
+//generic filter function for validating integer and hex data |
|
| 651 |
+function filterInt($data) |
|
| 652 |
+{
|
|
| 653 |
+ $data = filter_var($data, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX); |
|
| 654 |
+ |
|
| 655 |
+ if (get_magic_quotes_gpc()) {
|
|
| 656 |
+ return stripslashes($data); |
|
| 657 |
+ } |
|
| 658 |
+ |
|
| 659 |
+ $data = mysql_real_escape_string($data); |
|
| 660 |
+ |
|
| 661 |
+ return $data; |
|
| 662 |
+} |
|
| 663 |
+ |
|
| 664 |
+//generic filter function for number cleaning data |
|
| 665 |
+function filterFloat($data) |
|
| 666 |
+{
|
|
| 667 |
+ $data = filter_var($data, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); |
|
| 668 |
+ |
|
| 669 |
+ if (get_magic_quotes_gpc()) {
|
|
| 670 |
+ return stripslashes($data); |
|
| 671 |
+ } |
|
| 672 |
+ |
|
| 673 |
+ $data = mysql_real_escape_string($data); |
|
| 674 |
+ |
|
| 675 |
+ return $data; |
|
| 676 |
+} |
|
| 677 |
+ |
|
| 678 |
+?> |
|
| 0 | 679 |
\ No newline at end of file |