Browse code

Import from the old rivettracker git repository at sourceforge (amisaph/amisapphire branch)

Clarissa Walker (ami-sapphire) authored on 2014/01/24 14:02:23
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,381 @@
1
+<?php
2
+
3
+header("Content-type: text/plain");
4
+header("Pragma: no-cache");
5
+
6
+ignore_user_abort(1);
7
+
8
+$GLOBALS["peer_id"] = "";
9
+$summaryupdate = array();
10
+
11
+require_once("config.php");
12
+require_once("funcsv2.php");
13
+
14
+
15
+// Prep database
16
+if ($GLOBALS["persist"])
17
+	$db = @mysql_pconnect($dbhost, $dbuser, $dbpass) or showError("Tracker error: can't connect to database. Contact the webmaster.");
18
+else
19
+	$db = @mysql_connect($dbhost, $dbuser, $dbpass) or showError("Tracker error: can't connect to database. Contact the webmaster.");
20
+@mysql_select_db($database) or showError("Tracker error: can't open database. Contact the webmaster");
21
+
22
+
23
+if (isset ($_SERVER["PATH_INFO"]) )
24
+{
25
+	// Scrape interface
26
+
27
+// Error: no web browsers allowed
28
+	if (!isset($_GET["info_hash"]))
29
+	{
30
+		header("HTTP/1.0 400 Bad Request");
31
+		die("This file is for BitTorrent clients.\n");
32
+	}
33
+
34
+// Deny access made with a browser...
35
+$agent = mysql_real_escape_string($_SERVER["HTTP_USER_AGENT"]);
36
+
37
+if (preg_match("/^Mozilla|^Opera|^Links|^Lynx/i", $agent))
38
+{
39
+    header("HTTP/1.0 400 Bad Request");
40
+    die("This file is for BitTorrent clients.\n");
41
+}
42
+
43
+	if (substr($_SERVER["PATH_INFO"],-7) == '/scrape')
44
+	{
45
+		if ($scrape == true)
46
+		{
47
+			$usehash = false;
48
+			if (isset($_GET["info_hash"]))
49
+			{
50
+				if (get_magic_quotes_gpc())
51
+					$info_hash = stripslashes(trim(strip_tags($_GET["info_hash"])));
52
+				else
53
+					$info_hash = trim(strip_tags($_GET["info_hash"]));
54
+				if (strlen($info_hash) == 20)
55
+					$info_hash = filterChar(bin2hex($info_hash));
56
+				else if (strlen($info_hash) == 40)
57
+					filterInt(verifyHash($info_hash)) or showError("Invalid info hash value.");
58
+				else
59
+					showError("Invalid info hash value.");
60
+				$usehash = true;
61
+			}
62
+			if ($usehash)
63
+				$query = mysql_query("SELECT info_hash, filename FROM ".$prefix."namemap WHERE info_hash='$info_hash'");
64
+			else
65
+				$query = mysql_query("SELECT info_hash, filename FROM ".$prefix."namemap");
66
+			$namemap = array();
67
+			while ($row = mysql_fetch_row($query))
68
+				$namemap[$row[0]] = $row[1];
69
+	
70
+			if ($usehash)
71
+				$query = mysql_query("SELECT info_hash, seeds, leechers, finished FROM ".$prefix."summary WHERE info_hash='$info_hash'") or showError("Database error. Cannot complete request.");
72
+			else
73
+				$query = mysql_query("SELECT info_hash, seeds, leechers, finished FROM ".$prefix."summary ORDER BY info_hash") or showError("Database error. Cannot complete request.");
74
+
75
+			echo "d5:filesd";
76
+
77
+			while ($row = mysql_fetch_row($query))
78
+			{
79
+				$hash = hex2bin($row[0]);
80
+				echo "20:".$hash."d";
81
+				echo "8:completei".$row[1]."e";
82
+				echo "10:downloadedi".$row[3]."e";
83
+				echo "10:incompletei".$row[2]."e";
84
+				if (isset($namemap[$row[0]]))
85
+					echo "4:name".strlen($namemap[$row[0]]).":".$namemap[$row[0]];
86
+				echo "e";
87
+			}
88
+
89
+			echo "ee";
90
+			exit();
91
+		}
92
+		else
93
+			//client tried scraping but scraping has been disabled by the tracker
94
+			showError("Scraping has been disabled by this tracker.");
95
+	}
96
+}
97
+
98
+
99
+///////////////////////////////////////////////////////////////////
100
+// Handling of parameters from the URL and other setup
101
+
102
+
103
+// Error: no web browsers allowed
104
+if (!isset($_GET["info_hash"]) || !isset($_GET["peer_id"]))
105
+{
106
+	header("HTTP/1.0 400 Bad Request");
107
+	die("This file is for BitTorrent clients.\n");
108
+}
109
+$agent = mysql_real_escape_string($_SERVER["HTTP_USER_AGENT"]);
110
+// Deny access made with a browser...
111
+
112
+if (preg_match("/^Mozilla|^Opera|^Links|^Lynx/i", $agent))
113
+{
114
+    header("HTTP/1.0 400 Bad Request");
115
+    die("This file is for BitTorrent clients.\n");
116
+}
117
+
118
+
119
+$info_hash = bin2hex(clean($_GET["info_hash"]));
120
+$peer_id = filterChar(bin2hex($_GET["peer_id"]));
121
+
122
+
123
+if (!isset($_GET["port"]) || !isset($_GET["downloaded"]) || !isset($_GET["uploaded"]) || !isset($_GET["left"])) {
124
+	showError("Invalid information received from BitTorrent client");
125
+}
126
+
127
+$port = filterInt($_GET["port"]);
128
+$ip = filterFloat(str_replace("::ffff:", "", $_SERVER["REMOTE_ADDR"]));
129
+$downloaded = filterFloat($_GET["downloaded"]);
130
+$uploaded = filterFloat($_GET["uploaded"]);
131
+$left = filterFloat($_GET["left"]);
132
+
133
+
134
+if (isset($_GET["event"]))
135
+	$event = filterData($_GET["event"]);
136
+else
137
+	$event = "";
138
+
139
+if (!isset($GLOBALS["ip_override"]))
140
+	$GLOBALS["ip_override"] = true;
141
+
142
+if (isset($_GET["numwant"]))
143
+	if ($_GET["numwant"] < $GLOBALS["maxpeers"] && $_GET["numwant"] >= 0)
144
+		$GLOBALS["maxpeers"] = filterFloat($_GET["numwant"]);
145
+
146
+if (isset($_GET["trackerid"]))
147
+{	
148
+	if (is_numeric($_GET["trackerid"]))
149
+		$GLOBALS["trackerid"] = filterInt($_GET["trackerid"]);
150
+}
151
+if (!is_numeric($port) || !is_numeric($downloaded) || !is_numeric($uploaded) || !is_numeric($left))
152
+	showError("Invalid numerical field(s) from client");
153
+
154
+
155
+
156
+/////////////////////////////////////////////////////
157
+// Any section of code might need to make a new peer, so this is a function here.
158
+// I don't want to put it into funcsv2, even though it should, just for consistency's sake.
159
+
160
+function start($info_hash, $ip, $port, $peer_id, $left)
161
+{
162
+	require("config.php"); //need prefix value...
163
+	if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
164
+	{
165
+      foreach(explode(",",$_SERVER["HTTP_X_FORWARDED_FOR"]) as $address)
166
+      {
167
+		$addr = ip2long(trim($address));
168
+		if ($addr != -1)
169
+		{
170
+			if ($addr >= -1062731776 && $addr <= -1062666241)
171
+			{
172
+				// 192.168.x.x
173
+			}
174
+			else if ($addr >= -1442971648 && $addr <= -1442906113)
175
+			{
176
+				// 169.254.x.x
177
+			}
178
+			else if ($addr >= 167772160 && $addr <= 184549375)
179
+			{
180
+				// 10.x.x.x
181
+			}
182
+			else if ($addr >= 2130706432 && $addr <= 2147483647)
183
+			{
184
+				// 127.0.0.1
185
+			}
186
+			else if ($addr >= -1408237568 && $addr <= -1407188993)
187
+			{
188
+				// 172.[16-31].x.x
189
+			}
190
+			else
191
+			{
192
+				// Finally, we can accept it as a "real" ip address.
193
+				$ip = mysql_real_escape_string(trim($address));
194
+				break;
195
+			}
196
+		}
197
+	  }
198
+	}
199
+
200
+	if (isset($_GET["ip"]) && $GLOBALS["ip_override"])
201
+	{
202
+		// compact check: valid IP address:
203
+		if (ip2long($_GET["ip"]) == -1)
204
+			showError("Invalid IP address. Must be standard dotted decimal (hostnames not allowed)");
205
+		$ip = filterFloat($_GET["ip"]);
206
+	}
207
+
208
+	if ($left == 0)
209
+		$status = "seeder";
210
+	else
211
+		$status = "leecher";
212
+	if (@isFireWalled($info_hash, $peer_id, $ip, $port))
213
+		$nat = "'Y'";
214
+	else
215
+		$nat = "'N'";
216
+	
217
+	$results = @mysql_query("INSERT INTO ".$prefix."x$info_hash SET peer_id='$peer_id', port='$port', ip='$ip', lastupdate=UNIX_TIMESTAMP(), bytes='$left', status='$status', natuser=$nat");
218
+
219
+	// Special case: duplicated peer_id. 
220
+	if (!$results)
221
+	{
222
+		$error = mysql_error();
223
+		if (stristr($error, "key"))
224
+		{
225
+			// Duplicate peer_id! Check IP address
226
+			$peer = getPeerInfo($peer_id, $info_hash);
227
+			if ($ip == $peer["ip"])
228
+			{
229
+				// Same IP address. Tolerate this error.
230
+				return "WHERE natuser='N'";
231
+			}
232
+			//showError("Duplicated peer_id or changed IP address. Please restart BitTorrent.");
233
+			// Different IP address. Assume they were disconnected, and alter the IP address.
234
+			quickQuery("UPDATE ".$prefix."x$info_hash SET ip='$ip' WHERE peer_id='$peer_id'");
235
+			return "WHERE natuser='N'";
236
+		}
237
+		error_log("RivetTracker: start: ".$error);
238
+		showError("Tracker/database error. The details are in the error log.");
239
+	}
240
+	$GLOBALS["trackerid"] = mysql_insert_id();
241
+
242
+	$compact = mysql_real_escape_string(pack('Nn', ip2long($ip), $port));
243
+	$peerid = mysql_real_escape_string('2:ip' . strlen($ip) . ':' . $ip . '7:peer id20:' . hex2bin($peer_id) . "4:porti{$port}e");
244
+	$no_peerid = mysql_real_escape_string('2:ip' . strlen($ip) . ':' . $ip . "4:porti{$port}e");
245
+	@mysql_query("INSERT INTO ".$prefix."y$info_hash SET sequence='{$GLOBALS["trackerid"]}', compact='$compact', with_peerid='$peerid', without_peerid='$no_peerid'");
246
+
247
+	if ($left == 0)
248
+	{
249
+		summaryAdd("seeds", 1);
250
+		return "WHERE status='leecher' AND natuser='N'";
251
+	}
252
+	else
253
+	{
254
+		summaryAdd("leechers", 1);
255
+		return "WHERE natuser='N'";
256
+	}
257
+}
258
+
259
+// End of function start
260
+
261
+
262
+
263
+////////////////////////////////////////////////////////////////////////////////////////
264
+// Actual work. Depends on value of $event. (Missing event is mapped to '' above)
265
+
266
+if ($event == '')
267
+{
268
+	verifyTorrent($info_hash) or evilReject($ip, $peer_id,$port);
269
+	$peer_exists = getPeerInfo($peer_id, $info_hash);
270
+	$where = "WHERE natuser='N'";
271
+
272
+	if (!is_array($peer_exists))
273
+		$where = start($info_hash, $ip, $port, $peer_id, $left);
274
+
275
+	if ($peer_exists["bytes"] != 0 && $left == 0)
276
+	{
277
+
278
+		quickQuery("UPDATE ".$prefix."x$info_hash SET bytes=0, status='seeder' WHERE sequence='${GLOBALS["trackerid"]}'");
279
+		if (mysql_affected_rows() == 1)
280
+		{
281
+			summaryAdd("leechers", -1);
282
+			summaryAdd("seeds", 1);
283
+			summaryAdd("finished", 1);
284
+		}
285
+	}
286
+	collectBytes($peer_exists, $info_hash, $left);
287
+	sendRandomPeers($info_hash);
288
+}
289
+else if ($event == "started")
290
+{
291
+	verifyTorrent($info_hash) or evilReject($ip, $peer_id,$port);
292
+
293
+	$start = start($info_hash, $ip, $port, $peer_id, $left);
294
+	
295
+	// Don't send the tracker id for newly started clients. Send it next time. Make sure
296
+	// they get a good random list of peers to begin with.
297
+	sendRandomPeers($info_hash);
298
+}
299
+else if ($event == "stopped")
300
+{
301
+	verifyTorrent($info_hash) or evilReject($ip, $peer_id,$port);
302
+	killPeer($peer_id, $info_hash, $left);	
303
+
304
+	// I don't know why, but the real tracker returns peers on event=stopped
305
+	// but I'll just send an empty list. On the other hand, 
306
+	// TheSHADOW asked for this.
307
+	if (isset($_GET["tracker"]))
308
+		$peers = getRandomPeers($info_hash);
309
+	else
310
+		$peers = array("size" => 0);
311
+
312
+	sendPeerList($peers);
313
+}
314
+else if ($event == "completed") // now the same as an empty string
315
+{
316
+	verifyTorrent($info_hash) or evilReject($ip, $peer_id,$port);
317
+	$peer_exists = getPeerInfo($peer_id, $info_hash);
318
+
319
+	if (!is_array($peer_exists))
320
+		start($info_hash, $ip, $port, $peer_id, $left);
321
+	else
322
+	{
323
+		quickQuery("UPDATE ".$prefix."x$info_hash SET bytes=0, status='seeder' WHERE sequence='${GLOBALS["trackerid"]}'");
324
+
325
+		// Race check
326
+		if (mysql_affected_rows() == 1)
327
+		{
328
+			summaryAdd("leechers", -1);
329
+			summaryAdd("seeds", 1);
330
+			summaryAdd("finished", 1);
331
+		}
332
+	}
333
+	collectBytes($peer_exists, $info_hash, $left);
334
+	$peers=getRandomPeers($info_hash);
335
+
336
+	sendPeerList($peers);
337
+
338
+}
339
+else
340
+	showError("Invalid event= from client.");
341
+
342
+
343
+if ($GLOBALS["countbytes"])
344
+{
345
+	// Once every minute or so, we run the speed update checker.
346
+	// This is still not very accurate... :/
347
+	//@ symbol suppresses errors
348
+	$query = @mysql_query("SELECT UNIX_TIMESTAMP() - lastSpeedCycle FROM ".$prefix."summary WHERE info_hash='$info_hash'");
349
+	$results = mysql_fetch_row($query);
350
+	if ($results[0] >= 60 || $event == "completed")
351
+	{
352
+		if (Lock("SPEED:$info_hash"))
353
+		{
354
+			@runSpeed($info_hash, $results[0]);
355
+			Unlock("SPEED:$info_hash");
356
+		}
357
+	}
358
+}
359
+
360
+
361
+
362
+/* 
363
+ * Under heavy loads, this will lighten the load slightly... very slightly...
364
+ */
365
+//if (mt_rand(1,10) == 4)
366
+  trashCollector($info_hash, $report_interval);
367
+
368
+
369
+
370
+// Finally, it's time to do stuff to the summary table.
371
+if (!empty($summaryupdate))
372
+{
373
+	$stuff = "";
374
+	foreach ($summaryupdate as $column => $value)
375
+	{
376
+		$stuff .= ', '.$column. ($value[1] ? "=" : "=$column+") . $value[0];
377
+	}
378
+	mysql_query("UPDATE ".$prefix."summary SET ".substr($stuff, 1)." WHERE info_hash='$info_hash'");
379
+}
380
+
381
+?>
0 382
\ No newline at end of file