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 71 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+#Options -Indexes +FollowSymLinks
2
+#RewriteEngine On
3
+RewriteRule ^announce$ announce.php [NC,L]
4
+RewriteRule ^scrape$ scrape.php [NC,L]
0 5
new file mode 100644
... ...
@@ -0,0 +1,217 @@
1
+<?php
2
+/*
3
+
4
+	Programming info
5
+
6
+All functions output a small array, which we'll call $return for now.
7
+
8
+$return[0] is the data expected of the function
9
+$return[1] is the offset over the whole bencoded data of the next
10
+           piece of data.
11
+
12
+numberdecode returns [0] as the integer read, and [1]-1 points to the
13
+symbol that was interprented as the end of the interger (either "e" or
14
+":"). 
15
+numberdecode is used for integer decodes both for i11e and 11:hello there
16
+so it is tolerant of the ending symbol.
17
+
18
+decodelist returns $return[0] as an integer indexed array like you would use in C
19
+for all the entries. $return[1]-1 is the "e" that ends the list, so [1] is the next
20
+useful byte.
21
+
22
+decodeDict returns $return[0] as an array of text-indexed entries. For example,
23
+$return[0]["announce"] = "http://www.whatever.com:6969/announce";
24
+$return[1]-1 again points to the "e" that ends the dictionary.
25
+
26
+decodeEntry returns [0] as an integer in the case $offset points to
27
+i12345e or a string if $offset points to 11:hello there style strings.
28
+It also calls decodeDict or decodeList if it encounters a d or an l.
29
+
30
+
31
+Known bugs:
32
+- The program doesn't pay attention to the string it's working on.
33
+  A zero-sized or truncated data block will cause string offset errors
34
+  before they get rejected by the decoder. This is worked around by
35
+  suppressing errors.
36
+
37
+*/
38
+
39
+// Protect our namespace using a class
40
+class BDecode
41
+{
42
+
43
+function numberdecode($wholefile, $start)
44
+{
45
+	$ret[0] = 0;
46
+	$offset = $start;
47
+
48
+	// Funky handling of negative numbers and zero
49
+	$negative = false;
50
+	if ($wholefile[$offset] == '-')
51
+	{
52
+		$negative = true;
53
+		$offset++;
54
+	}
55
+	if ($wholefile[$offset] == '0')
56
+	{
57
+		$offset++;
58
+		if ($negative)
59
+			return array(false);
60
+		if ($wholefile[$offset] == ':' || $wholefile[$offset] == 'e')
61
+		{
62
+			$offset++;
63
+			$ret[0] = 0;
64
+			$ret[1] = $offset;
65
+			return $ret;
66
+		}
67
+		return array(false);
68
+	}
69
+	while (true)
70
+	{
71
+
72
+		if ($wholefile[$offset] >= '0' && $wholefile[$offset] <= '9')
73
+		{
74
+			
75
+			$ret[0] *= 10;
76
+			$ret[0] += ord($wholefile[$offset]) - ord("0");
77
+			$offset++;
78
+		}
79
+		// Tolerate : or e because this is a multiuse function
80
+		else if ($wholefile[$offset] == 'e' || $wholefile[$offset] == ':')
81
+		{
82
+			$ret[1] = $offset+1;
83
+			if ($negative)
84
+			{
85
+				if ($ret[0] == 0)
86
+					return array(false);
87
+				$ret[0] = - $ret[0];
88
+			}
89
+			return $ret;
90
+		}
91
+		else
92
+			return array(false);
93
+	}
94
+
95
+}
96
+
97
+function decodeEntry($wholefile, $offset=0)
98
+{
99
+	if ($wholefile[$offset] == 'd')
100
+		return $this->decodeDict($wholefile, $offset);
101
+	if ($wholefile[$offset] == 'l')
102
+		return $this->decodelist($wholefile, $offset);
103
+	if ($wholefile[$offset] == "i")
104
+	{
105
+		$offset++;
106
+		return $this->numberdecode($wholefile, $offset);
107
+	}
108
+	// String value: decode number, then grab substring
109
+	$info = $this->numberdecode($wholefile, $offset);
110
+	if ($info[0] === false)
111
+		return array(false);
112
+	$ret[0] = substr($wholefile, $info[1], $info[0]);
113
+	$ret[1] = $info[1]+strlen($ret[0]);
114
+	return $ret;
115
+}
116
+
117
+function decodeList($wholefile, $start)
118
+{
119
+	$offset = $start+1;
120
+	$i = 0;
121
+	if ($wholefile[$start] != 'l')
122
+		return array(false);
123
+	$ret = array();
124
+	while (true)
125
+	{
126
+		if ($wholefile[$offset] == 'e')
127
+			break;
128
+		$value = $this->decodeEntry($wholefile, $offset);
129
+		if ($value[0] === false)
130
+			return array(false);
131
+		$ret[$i] = $value[0];
132
+		$offset = $value[1];
133
+		$i ++;
134
+	}
135
+
136
+	// The empy list is an empty array. Seems fine.
137
+	$final[0] = $ret;
138
+	$final[1] = $offset+1;
139
+	return $final;
140
+
141
+
142
+
143
+}
144
+
145
+// Tries to construct an array
146
+function decodeDict($wholefile, $start=0)
147
+{
148
+	$offset = $start;
149
+	if ($wholefile[$offset] == 'l')
150
+		return $this->decodeList($wholefile, $start);
151
+	if ($wholefile[$offset] != 'd')
152
+		return false;
153
+	$ret = array();
154
+	$offset++;
155
+	while (true)
156
+	{	
157
+		if ($wholefile[$offset] == 'e')
158
+		{
159
+			$offset++;
160
+			break;
161
+		}
162
+		$left = $this->decodeEntry($wholefile, $offset);
163
+		if (!$left[0])
164
+			return false;
165
+		$offset = $left[1];
166
+		if ($wholefile[$offset] == 'd')
167
+		{
168
+			// Recurse
169
+			$value = $this->decodedict($wholefile, $offset);
170
+			if (!$value[0])
171
+				return false;
172
+			$ret[addslashes($left[0])] = $value[0];
173
+			$offset= $value[1];
174
+			continue;
175
+		}
176
+		else if ($wholefile[$offset] == 'l')
177
+		{
178
+			$value = $this->decodeList($wholefile, $offset);
179
+			if (!$value[0] && is_bool($value[0]))
180
+				return false;
181
+			$ret[addslashes($left[0])] = $value[0];
182
+			$offset = $value[1];
183
+		}
184
+		else
185
+		{
186
+ 			$value = $this->decodeEntry($wholefile, $offset);
187
+			if ($value[0] === false)
188
+				return false;
189
+			$ret[addslashes($left[0])] = $value[0];
190
+			$offset = $value[1];
191
+		}
192
+	}
193
+	if (empty($ret))
194
+		$final[0] = true;
195
+	else
196
+		$final[0] = $ret;
197
+	$final[1] = $offset;
198
+   	return $final;
199
+
200
+
201
+}
202
+
203
+
204
+} // End of class declaration.
205
+
206
+
207
+
208
+// Use this function. eg:  BDecode("d8:announce44:http://www. ... e");
209
+function BDecode($wholefile)
210
+{
211
+	$decoder = new BDecode;
212
+	$return = $decoder->decodeEntry($wholefile);
213
+	return $return[0];
214
+}
215
+
216
+
217
+?>
0 218
\ No newline at end of file
1 219
new file mode 100644
... ...
@@ -0,0 +1,122 @@
1
+<?php
2
+
3
+// Woohoo! Who needs mhash or PHP 4.3?
4
+// Don't require it. Still recommended, but not mandatory.
5
+if (!function_exists("sha1"))
6
+	@include_once("sha1lib.php");
7
+
8
+
9
+// We'll protect the namespace of our code
10
+// using a class
11
+class BEncode
12
+{
13
+
14
+// Dictionary keys must be sorted. foreach tends to iterate over the order
15
+// the array was made, so we make a new one in sorted order. :)
16
+/*
17
+function makeSorted($array)
18
+{
19
+	$i = 0;
20
+
21
+	// Shouldn't happen!
22
+	if (empty($array))
23
+		return $array;
24
+
25
+	foreach($array as $key => $value)
26
+		$keys[$i++] = stripslashes($key);
27
+	sort($keys);
28
+	for ($i=0 ; isset($keys[$i]); $i++)
29
+		$return[addslashes($keys[$i])] = $array[addslashes($keys[$i])];
30
+	return $return;
31
+}
32
+*/
33
+// Encodes strings, integers and empty dictionaries.
34
+// $unstrip is set to true when decoding dictionary keys
35
+function encodeEntry($entry, &$fd, $unstrip = false)
36
+{
37
+	if (is_bool($entry))
38
+	{
39
+		$fd .= "de";
40
+		return;
41
+	}
42
+	if (is_int($entry) || is_float($entry))
43
+	{
44
+		$fd .= "i".$entry."e";
45
+		return;
46
+	}
47
+	if ($unstrip)
48
+		$myentry = stripslashes($entry);
49
+	else
50
+		$myentry = $entry;
51
+	$length = strlen($myentry);
52
+	$fd .= $length.":".$myentry;
53
+	return;
54
+}
55
+
56
+// Encodes lists
57
+function encodeList($array, &$fd)
58
+{
59
+	$fd .= "l";
60
+
61
+	// The empty list is defined as array();
62
+	if (empty($array))
63
+	{
64
+		$fd .= "e";
65
+		return;
66
+	}
67
+	for ($i = 0; isset($array[$i]); $i++)
68
+		$this->decideEncode($array[$i], $fd);
69
+	$fd .= "e";
70
+}
71
+
72
+// Passes lists and dictionaries accordingly, and has encodeEntry handle
73
+// the strings and integers.
74
+function decideEncode($unknown, &$fd)
75
+{
76
+	if (is_array($unknown))
77
+	{
78
+		if (isset($unknown[0]) || empty($unknown))
79
+			return $this->encodeList($unknown, $fd);
80
+		else
81
+			return $this->encodeDict($unknown, $fd);
82
+	}
83
+	$this->encodeEntry($unknown, $fd);
84
+}
85
+
86
+// Encodes dictionaries
87
+function encodeDict($array, &$fd)
88
+{
89
+	$fd .= "d";
90
+	if (is_bool($array))
91
+	{
92
+		$fd .= "e";
93
+		return;
94
+	}
95
+	// NEED TO SORT!
96
+	//$newarray = $this->makeSorted($array);
97
+	ksort($array, SORT_STRING);
98
+
99
+	foreach($array as $left => $right)
100
+	{
101
+		$this->encodeEntry($left, $fd, true);
102
+		$this->decideEncode($right, $fd);
103
+	}
104
+	$fd .= "e";
105
+	return;
106
+}
107
+
108
+
109
+
110
+} // End of class declaration.
111
+
112
+// Use this function in your own code.
113
+function BEncode($array)
114
+{
115
+	$string = "";
116
+	$encoder = new BEncode;
117
+	$encoder->decideEncode($array, $string);
118
+	return $string;
119
+}
120
+
121
+
122
+?>
0 123
\ No newline at end of file
1 124
new file mode 100644
... ...
@@ -0,0 +1,44 @@
1
+<?php
2
+require ("config.php");
3
+require ("funcsv2.php");
4
+//Check session
5
+session_start();
6
+
7
+if (!$_SESSION['admin_logged_in'])
8
+{
9
+	//check fails
10
+	header("Location: authenticate.php?status=session");
11
+	exit();
12
+}
13
+?>
14
+
15
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
16
+<html><head><title>Torrent Information</title>
17
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
18
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
19
+</head><body>
20
+<?php
21
+require_once("torrent_functions.php");
22
+?>
23
+<table width="50%" border=0><tr><td>
24
+This script parses a torrent file and displays detailed information about it.
25
+</td></tr>
26
+</table><br>
27
+<form enctype="multipart/form-data" method="POST" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
28
+Torrent file: <input type="file" name="torrent" size="40"><br>
29
+<br>
30
+OR
31
+<br><br>
32
+Torrent URL: <input type=text name="url" size="50"><br><br>
33
+Output type: <select name="output">
34
+<option value="-1">Auto-detect
35
+<option value="0">Classic (raw)
36
+<option value="1">.torrent file
37
+<option value="2">/scrape
38
+<option value="3">/announce
39
+</select><br><br>
40
+<input type="submit" value="Decode">
41
+</form>
42
+
43
+<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Return to Admin Page</a>
44
+</body></html>
0 45
new file mode 100644
... ...
@@ -0,0 +1,60 @@
1
+<?php
2
+
3
+require ("config.php");
4
+require ("funcsv2.php");
5
+//Check session
6
+session_start();
7
+
8
+if (!$_SESSION['admin_logged_in'])
9
+{
10
+	//check fails
11
+	header("Location: authenticate.php?status=session");
12
+	exit();
13
+}
14
+?>
15
+
16
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
17
+
18
+<html>
19
+<head>
20
+	<title>Admin Page</title>
21
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
22
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
23
+</head>
24
+<body>
25
+<h1>Admin Page</h1>
26
+
27
+<a href="newtorrents.php"><img src="images/add.png" border="0" class="icon" alt="Add Torrent" title="Add Torrent" /></a><a href="newtorrents.php">Add Torrent to Tracker Database</a><br>
28
+<a href="batch_upload.php"><img src="images/batch_upload.png" border="0" class="icon" alt="Batch Upload Torrents" title="Batch Upload Torrents" /></a><a href="batch_upload.php">Batch Upload Torrents</a><br>
29
+<a href="edit_database.php"><img src="images/database.png" border="0" class="icon" alt="Edit Torrent in Database" title="Edit Torrent in Database" /></a><a href="edit_database.php">Edit Torrent Already in Database</a><br>
30
+<a href="DumpTorrentCGI.php"><img src="images/torrent.png" border="0" class="icon" alt="Show Information on Torrent" title="Show Information on Torrent" /></a><a href="DumpTorrentCGI.php">Show Information on Torrent File</a><br>
31
+<a href="index.php"><img src="images/stats.png" border="0" class="icon" alt="Tracker Statistics" title="Tracker Statistics" /></a><a href="index.php">Show Current Tracker Statistics</a><br>
32
+<a href="sanity.php"><img src="images/check.png" border="0" class="icon" alt="Check for Expired Peers" title="Check for Expired Peers" /></a><a href="sanity.php">Check Tracker for Expired Peers</a><br>
33
+<a href="statistics.php"><img src="images/userstats.png" border="0" class="icon" alt="User Statistics" title="User Statistics" /></a><a href="statistics.php">Detailed User Statistics from Tracker</a><br>
34
+<a href="deleter.php"><img src="images/delete.png" border="0" class="icon" alt="Delete Torrent" title="Delete Torrent" /></a><a href="deleter.php">Delete Torrent from Tracker Database</a><br>
35
+<a href="editconfig.php"><img src="images/edit.png" border="0" class="icon" alt="Edit Config File" title="Edit Config File" /></a><a href="editconfig.php">Edit Configuration Settings</a><br>
36
+<a href="uploadstats.php"><img src="images/download.png" border="0" class="icon" alt="Upload Statistics" title="Upload Statistics" /></a><a href="uploadstats.php">Upload Statistics</a><br>
37
+<a href="css.php"><img src="images/color.png" border="0" class="icon" alt="Change CSS File" title="Change CSS File" /></a><a href="css.php">Change CSS File</a><br>
38
+<a href="./docs/help.html"><img src="images/help.png" border="0" class="icon" alt="Help" title="Help" /></a><a href="./docs/help.html">Help</a><br>
39
+<a href="authenticate.php?status=logout"><img src="images/logout.png" border="0" class="icon" alt="Logout" title="Logout" /></a><a href="authenticate.php?status=logout">Logout</a><br>
40
+
41
+<?php
42
+//Check for install.php file, security risk if still available
43
+if (file_exists("install.php"))
44
+{
45
+	echo errorMessage() . "Your install.php file has NOT been deleted.  This is a security risk, please delete it immediately.</p>\n";
46
+}
47
+
48
+if (!is_writeable("./torrents/"))
49
+{
50
+	echo errorMessage() . "The 'torrents' folder does not have write access, check the permissions.</p>\n";
51
+}
52
+
53
+if (!is_writeable("./rss/"))
54
+{
55
+	echo errorMessage() . "The 'rss' folder does not have write access, check the permissions.</p>\n";
56
+}
57
+
58
+?>
59
+</body>
60
+</html>
0 61
\ No newline at end of file
1 62
new file mode 100644
... ...
@@ -0,0 +1,10 @@
1
+<?php
2
+
3
+/// Use this file as an alternative to tracker.php/announce
4
+/// for TorrentSpy and other /scrape support.
5
+
6
+$_SERVER["PATH_INFO"] = "/announce";
7
+require("tracker.php");
8
+exit;
9
+
10
+?>
0 11
\ No newline at end of file
1 12
new file mode 100644
... ...
@@ -0,0 +1,65 @@
1
+<?php
2
+//Main Login Page
3
+
4
+//Destroy any previous session data
5
+//This way it requires a login
6
+session_start();
7
+session_destroy();
8
+
9
+//get status
10
+$status = $_GET['status'];
11
+
12
+?>
13
+
14
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
15
+<html>
16
+<head>
17
+	<title>Login</title>
18
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
19
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
20
+</head>
21
+<body>
22
+<center>
23
+<h1>Login</h1>
24
+<img src="images/lock.png" border="0" alt="Please Login" title="Please Login" />
25
+<h3>Please login with your username and password.</h3>
26
+<form action="login.php" method="POST">
27
+<table border="0">
28
+<tr><td class="right">
29
+Username:</td>
30
+<td class="left">
31
+<input type="text" size="20" name="f_user">
32
+</td></tr>
33
+<tr><td class="right">
34
+Password:</td>
35
+<td class="left">
36
+<input type="password" size="20" name="f_pass">
37
+</td></tr>
38
+<tr><td></td><td class="left">
39
+<input type="submit" name="LogIn" value="Log In">
40
+</td></tr>
41
+</table>
42
+<?php
43
+//Display legal stuff if file exists
44
+if (file_exists("legalterms.txt"))
45
+	echo "<br><input type=\"checkbox\" name=\"legalterms\"> I agree to the <a href=\"legalterms.txt\">use policy and terms of service.</a>";
46
+else //display hidden value, needed so that login.php can check the value
47
+	echo "<input type=\"hidden\" name=\"legalterms\" value=\"on\">";
48
+
49
+if ($status == "error")
50
+echo "<p class=\"error\">Error, username or password is incorrect.<br>Entries are cAsESEnsITiVE, do you have your capslock key on?...</p>";
51
+if ($status == "session")
52
+echo "<p class=\"error\">Your session has timed out, please re-login.</p>";
53
+if ($status == "logout")
54
+echo "<p class=\"success\">You have successfully logged out.</p>";
55
+if ($status == "indexlogin")
56
+echo "<p class=\"error\">Error, this tracker requires a username and password in order to view the main page.</p>";
57
+if ($status == "legalterms")
58
+echo "<p class=\"error\">You need to agree to the use policy and terms of service in order to log in.</p>";
59
+?>
60
+</form>
61
+<br>
62
+<a href="index.php"><img src="images/stats.png" border="0" class="icon" alt="Tracker Statistics" title="Tracker Statistics" /></a><a href="index.php">Tracker Statistics</a><br>
63
+</center>
64
+</body>
65
+</html>
0 66
new file mode 100644
... ...
@@ -0,0 +1,214 @@
1
+<?php
2
+
3
+require ("config.php");
4
+require ("funcsv2.php"); //required for errorMessage() function
5
+//Check session
6
+session_start();
7
+
8
+if (!$_SESSION['admin_logged_in'])
9
+{
10
+	//check fails
11
+	header("Location: authenticate.php?status=session");
12
+	exit();
13
+}
14
+?>
15
+
16
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
17
+
18
+<html>
19
+<head>
20
+	<title>Batch Upload Torrents</title>
21
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
22
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
23
+</head>
24
+<body>
25
+<center>
26
+<h1>Batch Upload Torrents</h1>
27
+</center>
28
+<br>
29
+
30
+<?php
31
+
32
+if (isset($_FILES["zipfile"]) && $_FILES["zipfile"]["error"] != 4 && isset($_FILES["zipfile"]["tmp_name"])) //4 corresponds to the error no file uploaded
33
+{
34
+	?>
35
+	<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Return to Admin Page</a>
36
+	<br><br>
37
+	<?php
38
+	$zip = zip_open($_FILES["zipfile"]["tmp_name"]);
39
+	
40
+	if ($zip == true)
41
+	{
42
+		$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Couldn't connect to the database, contact the administrator</p>");
43
+		mysql_select_db($database) or die(errorMessage() . "Can't open the database.</p>");
44
+	
45
+	   while ($zip_entry = zip_read($zip))
46
+	   {
47
+	   	echo "Name: " . zip_entry_name($zip_entry) . "<br>\n";
48
+	      if (substr(zip_entry_name($zip_entry), -8) == ".torrent")
49
+			{
50
+				$error_status = true;
51
+				if (zip_entry_open($zip, $zip_entry, "r"))
52
+			   {
53
+			   	//read in file from zip
54
+			  		$buffer = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
55
+			      //go through each torrent file and add it if possible
56
+					require_once ("BDecode.php");
57
+					require_once ("BEncode.php");
58
+					
59
+					$tracker_url = $website_url . substr($_SERVER['REQUEST_URI'], 0, -16) . $announceurl;
60
+					
61
+					$array = BDecode($buffer);
62
+					if (!$array)
63
+					{
64
+						echo errorMessage() . "Error: The parser was unable to load this torrent.</p>\n";
65
+						$error_status = false;
66
+					}
67
+					if (isset($array["announce-list"])) {
68
+						//multiple trackers are listed
69
+						$found_tracker = false;
70
+						for ($i = 0; $i < count($array["announce-list"]); $i++) {
71
+							if (strtolower($array["announce-list"][$i][0]) == $tracker_url) {
72
+								$found_tracker = true;
73
+								break;
74
+							}
75
+						}
76
+						if ($found_tracker == false)
77
+						{
78
+							echo errorMessage() . "Error: Multiple trackers were found but none of them match the
79
+								announce URL:<br>$tracker_url<br>Please re-create and re-upload the torrent.</p>\n";
80
+							$error_status = false;
81
+							exit;
82
+						}
83
+					} else {
84
+						//a single tracker is listed
85
+						if (strtolower($array["announce"]) != $tracker_url) {
86
+							echo errorMessage() . "Error: The tracker announce URL does not match this:<br>$tracker_url<br>Please re-create and re-upload the torrent.</p>\n";
87
+							$error_status = false;
88
+							exit;
89
+						}
90
+					}
91
+					if (function_exists("sha1"))
92
+						$hash = @sha1(BEncode($array["info"]));
93
+					else
94
+					{
95
+						echo errorMessage() . "Error: It looks like you do not have a hash function available, this will not work.</p>\n";
96
+						$error_status = false;
97
+					}
98
+				
99
+					//figure out total size of all files in torrent, needed for insertion into database
100
+					$info = $array["info"];
101
+					$total_size = 0;
102
+					if (isset($info["files"]))
103
+					{
104
+						foreach ($info["files"] as $file)
105
+						{
106
+							$total_size = $total_size + $file["length"];
107
+						}
108
+					}
109
+					else
110
+					{
111
+						$total_size = $info["length"];
112
+					}
113
+					
114
+					//Validate torrent file, make sure everything is correct
115
+					$filename = $array["info"]["name"];
116
+					$filename = mysql_real_escape_string($filename);
117
+					$filename = stripslashes($filename);
118
+					$filename = clean($filename);
119
+				
120
+					if ((strlen($hash) != 40) || !verifyHash($hash))
121
+					{
122
+						echo errorMessage() . "Error: Info hash must be exactly 40 hex bytes.</p>\n";
123
+						$error_status = false;
124
+					}
125
+					
126
+				
127
+					if ($error_status == true)
128
+					{
129
+						$query = "INSERT INTO " . $prefix . "namemap (info_hash, title, filename, url, size, pubDate) VALUES (\"$hash\", \"$filename\", \"$filename\", \"$url\", \"$total_size\", \"" . date("$dateformat") . "\")";
130
+						$status = makeTorrent($hash, true);
131
+						quickQuery($query);
132
+						if ($status == true)
133
+						{
134
+							//create torrent file in folder, at this point we assume it's valid
135
+							if (!$handle = fopen("torrents/" . $filename . ".torrent", 'w'))
136
+							{
137
+	         				echo errorMessage() . "Error: Can't write to file.</p>\n";
138
+	        					break;
139
+	    					}
140
+							//populate file with contents
141
+					   	if (fwrite($handle, $buffer) === FALSE)
142
+					   	{
143
+					       	echo errorMessage() . "Error: Can't write to file.</p>\n";
144
+					      	break;
145
+					   	}
146
+					   	fclose($handle);
147
+							//make torrent file readable by all
148
+							chmod("torrents/" . $filename . ".torrent", 0644);
149
+							echo "<p class=\"success\">Torrent was added successfully.</p>\n";
150
+						}
151
+						else
152
+						{
153
+							echo errorMessage() . "There were some errors. Check if this torrent has been added previously.</p>\n";
154
+						}
155
+					}
156
+			
157
+			      zip_entry_close($zip_entry);
158
+			    }
159
+			} 
160
+			else
161
+				echo errorMessage() . "Unable to add torrent, it doesn't end in .torrent</p>\n";
162
+			
163
+		echo "<br>";
164
+	   }
165
+	   zip_close($zip);
166
+	}
167
+
168
+	//finished reading zip file
169
+	
170
+	//run RSS generator because we have new torrents in database
171
+	require_once("rss_generator.php");
172
+
173
+
174
+}
175
+else
176
+{
177
+	//display upload box
178
+	?>
179
+	<?php require("config.php"); $tracker_url = $website_url . substr($_SERVER['REQUEST_URI'], 0, -16) . $announceurl; ?>
180
+	<p>This page lets you upload a zip file containing multiple torrents and add them into the database.  The
181
+	zip file cannot have any folders in it.  This requires that you are running PHP with compiled zip support.
182
+	If you are unsure, check with your system administrator or phpinfo().  Any torrents that already exist in
183
+	the database will be skipped.  If you want to use HTTP seeding you'll need to add this feature to the torrent
184
+	files before you zip and upload the file.  If you are uploading a very large zip file this may take some time...
185
+	<br>
186
+	<br>
187
+	Notes:
188
+	<br>
189
+	[1] Even if the custom title option is enabled, the torrents will have the same title as the filename.  If you
190
+	have the custom title option enabled, you may change the titles to your preference after the batch upload has
191
+	finished.<br>[2] The torrents you are batch uploading should include the following Tracker URL:
192
+	<b><?php echo $tracker_url ?></b></p>
193
+	
194
+	<?php
195
+	if (function_exists("zip_open"))
196
+	{
197
+		?>
198
+		<form enctype="multipart/form-data" action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>" method="post">
199
+		<b>Zip File:</b><input type="file" name="zipfile" size="50"/>
200
+		<input type="submit" value="Upload ZIP File"/>
201
+		</form>
202
+		<?php
203
+	}
204
+	else
205
+		echo errorMessage() . "Error: It looks like you don't have ZIP support compiled into PHP.</p>\n";
206
+}
207
+
208
+?>
209
+
210
+<br>
211
+<br>
212
+<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Return to Admin Page</a>
213
+</body>
214
+</html>
0 215
new file mode 100644
... ...
@@ -0,0 +1,269 @@
1
+<?php
2
+
3
+require ("config.php");
4
+require ("funcsv2.php"); //required for errorMessage() function
5
+//Check session
6
+session_start();
7
+
8
+if (!$_SESSION['admin_logged_in'])
9
+{
10
+	//check fails
11
+	header("Location: authenticate.php?status=session");
12
+	exit();
13
+}
14
+
15
+// Prep database, needed for cleaning function
16
+if ($GLOBALS["persist"])
17
+	$db = @mysql_pconnect($dbhost, $dbuser, $dbpass) or showError("Can't connect to database. Contact the webmaster.");
18
+else
19
+	$db = @mysql_connect($dbhost, $dbuser, $dbpass) or showError("Can't connect to database. Contact the webmaster.");
20
+@mysql_select_db($database) or showError("Can't open database. Contact the webmaster");
21
+
22
+?>
23
+
24
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
25
+
26
+<html>
27
+<head>
28
+	<title>Change CSS File</title>
29
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
30
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
31
+	<style type="text/css">
32
+		td.cell{
33
+			width: 2%;
34
+			}
35
+	</style>
36
+	<script type="text/javascript">
37
+	function changeColor(color)
38
+	{
39
+		document.getElementById("color_box").value = color;
40
+		document.getElementById("thecolor").style.backgroundColor = color;
41
+	}
42
+	</script>
43
+</head>
44
+<body>
45
+<center>
46
+<h1>Change CSS File</h1>
47
+</center>
48
+<br>
49
+
50
+<?php
51
+
52
+if (isset($_POST["set_css"]))
53
+{
54
+	//delete style.css file
55
+	if (copy("./css/" . filterData($_POST["set_css"]), "./css/style.css"))
56
+		echo "<p class=\"success\">style.css file has been replaced with " . filterData($_POST["set_css"]) . "</p>";
57
+	else
58
+	{
59
+		echo errorMessage() . "Error: Unable to copy over style.css, are the permissions correct?</p>";
60
+		exit();
61
+	}
62
+}
63
+elseif (isset($_POST["delete_css"]))
64
+{
65
+	//delete css file
66
+	if (unlink("./css/" . filterData($_POST["delete_css"])))
67
+		echo "<p class=\"success\">" . filterData($_POST["delete_css"]) . " has been deleted</p>";
68
+	else
69
+	{
70
+		echo errorMessage() . "Error: Unable to delete " . filterData($_POST["delete_css"]) . ", are you sure the permissions are correct?</p>";
71
+		exit();
72
+	}
73
+}
74
+elseif (isset($_POST["create_css"]))
75
+{
76
+	//create new css file by copying over style.css into new file
77
+	if (substr($_POST["create_css"], -4) == ".css")
78
+	{
79
+		if (!file_exists("./css/" . filterData($_POST["create_css"])))
80
+		{
81
+			if (copy("./css/style.css", "./css/" . filterData($_POST["create_css"])))
82
+				echo "<p class=\"success\">" . filterData($_POST["create_css"]) . ", was created successfuly</p>";
83
+			else
84
+			{
85
+				echo errorMessage() . "Error: Unable to create " . filterData($_POST["create_css"]) . ", are you sure the permissions are correct?</p>";
86
+				exit();			
87
+			}
88
+		}
89
+		else
90
+		{
91
+			echo errorMessage() . "Error: " . filterData($_POST["create_css"]) . " already exists, please choose a different name</p>";
92
+			exit();
93
+		}
94
+	}
95
+	else
96
+	{
97
+		echo errorMessage() . "Error: Your file doesn't end with .css</p>";
98
+		exit();
99
+	}
100
+}
101
+
102
+if (isset($_POST["create_css"]) || isset($_POST["edit_css"]))
103
+{
104
+	//display color picker
105
+	?>
106
+	<h2>Color Picker:</h2>
107
+	<table style="cursor: pointer;" border="0">
108
+	<?php
109
+	function rgbhex($red, $green, $blue)
110
+	{
111
+		return sprintf('#%02X%02X%02X', $red, $green, $blue);
112
+	}
113
+	
114
+	//create table of 216 web safe colors
115
+	for ($red = 0; $red < 256; $red = $red + 51)
116
+	{
117
+		echo "<tr>";
118
+		for ($green = 0; $green < 256; $green = $green + 51)
119
+		{
120
+			for ($blue = 0; $blue < 256; $blue = $blue + 51)
121
+			{
122
+				$hexcolor = rgbhex($red, $green, $blue);
123
+				echo "<td bgcolor='" . $hexcolor . "' title='" . $hexcolor . "' class='cell' onClick=\"changeColor('" . $hexcolor . "')\">&nbsp;</td>\n";
124
+			}
125
+		}
126
+		echo "</tr>";
127
+	}
128
+	
129
+	?>
130
+	</table>
131
+	<br>
132
+	<b>Color:</b>
133
+	<table border="0"><tr>
134
+	<td id="thecolor" align="left" bgcolor="#000000"><input type="text" id="color_box" value="#000000"/>
135
+	</td></tr>
136
+	</table>
137
+	<br>
138
+	<?php
139
+	
140
+	if (isset($_POST["create_css"]))
141
+		$filename = filterData($_POST["create_css"]);
142
+	if (isset($_POST["edit_css"]))
143
+		$filename = filterData($_POST["edit_css"]);
144
+	//display text box with css in it
145
+	?>
146
+	<h2>Editing File: <?php echo $filename;?></h2>
147
+	<form action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>" method="post">
148
+	<input type="hidden" name="hidden_filename" value="<?php echo $filename;?>"/>
149
+	<input type="hidden" name="current_css_file" value="<?php echo $_POST['current_css_file'];?>"/>
150
+	<textarea name="file_contents" cols="120" rows="20"><?php
151
+	//open css file
152
+	readfile("./css/" . $filename);
153
+	?></textarea>
154
+	<br><br>
155
+	<input type="submit" value="Save File"/>
156
+	</form>
157
+	<?php
158
+	
159
+}
160
+
161
+if (isset($_POST["file_contents"]))
162
+{
163
+	//save previously edited text into file
164
+	if (is_writable("./css/" . filterData($_POST["hidden_filename"])))
165
+	{
166
+		//open file
167
+		$stream = fopen("./css/" . filterData($_POST["hidden_filename"]), "w");
168
+		fwrite($stream, filterData($_POST["file_contents"]));
169
+		fclose($stream);
170
+		echo "<p class=\"success\">" . filterData($_POST["hidden_filename"]) . ", was saved successfuly</p>";
171
+	}
172
+	else
173
+	{
174
+		echo errorMessage() . "Error: The file cannot be saved, check the permissions</p>";
175
+		exit();
176
+	}
177
+	//if editing the current css file, replace that too
178
+	if ($_POST["current_css_file"] == $_POST["hidden_filename"])
179
+	{
180
+		if (copy("./css/" . filterData($_POST["hidden_filename"]), "./css/style.css"))
181
+			echo "<p class=\"success\">style.css file has been replaced with " . filterData($_POST["hidden_filename"]) . "</p>";
182
+		else
183
+		{
184
+			echo errorMessage() . "Error: Unable to copy over style.css, are the permissions correct?</p>";
185
+			exit();
186
+		}
187
+	}
188
+}
189
+
190
+if (!isset($_POST["create_css"]) && !isset($_POST["edit_css"]) && !isset($_POST["delete_css"]) && 
191
+!isset($_POST["set_css"]) && !isset($_POST["file_contents"]))
192
+{
193
+	//save all files in css directory to array
194
+	$current_css_file = "";
195
+	$css_style_md5 = md5_file("./css/style.css");
196
+	$number_files = 0;
197
+	if ($dh = opendir("./css/"))
198
+	{
199
+		while (($file = readdir($dh)) !== false)
200
+		{
201
+			if (filetype("./css/" . $file) == "file" && $file != "index.php" && $file != "style.css" && substr($file, -4) == ".css")
202
+			{
203
+				if (md5_file("./css/" . $file) == $css_style_md5)
204
+					$current_css_file = $file;
205
+				$files_array[$number_files] = $file;
206
+				$number_files++;
207
+			}
208
+		}
209
+		closedir($dh);
210
+	}
211
+	echo "<b>Currently Used CSS File: " . $current_css_file . "</b><br><br>";
212
+	?>
213
+	
214
+	<form action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>" method="post">
215
+	<b>Set CSS File:</b><select name="set_css">
216
+	<?php
217
+	for ($i = 0; $i < $number_files; $i++)
218
+	{
219
+		if ($files_array[$i] != $current_css_file) //no point setting it to itself...
220
+			echo "<option value=\"" . $files_array[$i] . "\">" . $files_array[$i] . "</option>\n\t";
221
+	}
222
+	?>
223
+	</select>
224
+	<input type="submit" value="Set CSS File"/>
225
+	</form>
226
+	<br><br>
227
+	
228
+	<form action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>" method="post"> 
229
+	<b>Delete CSS File:</b><select name="delete_css">
230
+	<?php
231
+	for ($i = 0; $i < $number_files; $i++)
232
+	{
233
+		if ($files_array[$i] != $current_css_file) //can't delete the file if it's already being used...
234
+			echo "<option value=\"" . $files_array[$i] . "\">" . $files_array[$i] . "</option>\n\t";
235
+	}
236
+	?>
237
+	</select>
238
+	<input type="submit" value="Delete CSS File"/>
239
+	</form>
240
+	<br><br>
241
+	
242
+	<form action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>" method="post">
243
+	<input type="hidden" name="current_css_file" value="<?php echo $current_css_file;?>"/>
244
+	<b>Edit Existing CSS File:</b><select name="edit_css">
245
+	<?php
246
+	for ($i = 0; $i < $number_files; $i++)
247
+	{
248
+		echo "<option value=\"" . $files_array[$i] . "\">" . $files_array[$i] . "</option>\n\t";
249
+	}
250
+	?>
251
+	</select>
252
+	<input type="submit" value="Edit CSS File"/>
253
+	</form>
254
+	<br><br>
255
+	
256
+	<form action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>" method="post"> 
257
+	<b>Create New CSS File (e.g. mycssfile.css):</b>
258
+	<input type="text" size="40" name="create_css"/>
259
+	<input type="submit" value="Create New CSS File"/>
260
+	</form>
261
+	<?php
262
+}
263
+?>
264
+
265
+<br>
266
+<br>
267
+<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Return to Admin Page</a>
268
+</body>
269
+</html>
0 270
new file mode 100644
... ...
@@ -0,0 +1,101 @@
1
+th { /* Table Header */
2
+	background-color: #3366CC;
3
+	padding: 4px;
4
+	border-bottom: 2px solid #000000;
5
+}
6
+th.subheader { /* Sub-Table Header */
7
+	background-color: #306EFF
8
+	border-bottom: 2px solid #660000;
9
+}
10
+tr.selected {
11
+        background-color: #FFCC00;
12
+        color: #FFFFFF;
13
+}
14
+tr.row0 {
15
+	background-color: #C9C2CC;
16
+	color: #000000;
17
+}
18
+tr.row0 a:link {color: #000066}
19
+tr.row0 a:visited {color: #000066}
20
+tr.row0 a:active  {color: #000066}
21
+tr.row0 a:hover   {color: #000066}
22
+tr.row1 {
23
+	background-color: #CCCCFF;
24
+	color: #000000;
25
+}
26
+tr.row1 a:link {color: #000066}
27
+tr.row1 a:visited {color: #000066}
28
+tr.row1 a:active  {color: #000066}
29
+tr.row1 a:hover   {color: #000066}
30
+td.percent {
31
+	background-color: #33CC33;
32
+}
33
+td.percentleft {
34
+	background-color: #CCCCCC;
35
+}
36
+img.icon { 
37
+	vertical-align: middle;
38
+	padding: 4px;
39
+}
40
+body {
41
+	font: 12pt sans-serif;
42
+	background-color: #000060;
43
+	color: #FFFFFF;
44
+}
45
+h1 { /* Tracker Header/Title */
46
+	font: 24px verdana, sans-serif;
47
+	text-align: center;
48
+}
49
+h2 { /* Smaller Page Headers */
50
+	font: 18px verdana, sans-serif;
51
+}
52
+a {
53
+	color: #FF33FF;
54
+	text-decoration: none;
55
+	background-color: transparent;
56
+}
57
+a:hover {
58
+	text-decoration: underline;
59
+}
60
+a:link    {color: #CCCCFF}
61
+a:visited {color: #CCCCFF}
62
+a:active  {color: #CCCCFF}
63
+a:hover   {color: #CCCCFF}
64
+table.percentages {
65
+	width: 200px;
66
+}
67
+table.torrentlist td {
68
+	padding: 4px;
69
+}
70
+table.nopadding td {
71
+	padding: 0px;
72
+}
73
+.details {
74
+	font: 12px verdana, sans-serif;
75
+	height: 0px;
76
+}
77
+p.error {
78
+	color: yellow;
79
+	text-align: center;
80
+	font-weight: bold;
81
+}
82
+p.success {
83
+	color: green;
84
+	text-align: center;
85
+	font-weight: bold;
86
+}	
87
+table {
88
+	width: 100%;
89
+}
90
+.center {	
91
+	text-align: center; 
92
+}
93
+.left {
94
+	text-align: left;
95
+}
96
+.right {
97
+	text-align: right;
98
+}
99
+span.notice {
100
+	color: #FF0000;
101
+}
0 102
\ No newline at end of file
1 103
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+<?php
2
+
3
+header("Location: ../index.php");
4
+
5
+?>
0 6
\ No newline at end of file
1 7
new file mode 100644
... ...
@@ -0,0 +1,95 @@
1
+th { /* Table Header */
2
+	background-color: #CCCC99;
3
+	padding: 4px;
4
+	border-bottom: 2px solid #664D33;
5
+}
6
+th.subheader { /* Sub-Table Header */
7
+	background-color: #99FF99;
8
+	border-bottom: 2px solid #336633;
9
+}
10
+tr.selected {
11
+        background-color: #FFCC00;
12
+        color: #000000;
13
+}
14
+tr.row0 {
15
+	background-color: #A7BCD3;
16
+}
17
+tr.row0 a:link {color: #000770}
18
+tr.row0 a:visited {color: #000770}
19
+tr.row0 a:active  {color: #000770}
20
+tr.row0 a:hover   {color: #000770}
21
+tr.row1 {
22
+	background-color: #8AA9C6;
23
+}
24
+tr.row1 a:link {color: #000770}
25
+tr.row1 a:visited {color: #000770}
26
+tr.row1 a:active  {color: #000770}
27
+tr.row1 a:hover   {color: #000770}
28
+td.percent {
29
+	background-color: #33CC33;
30
+}
31
+td.percentleft {
32
+	background-color: #CCCCCC;
33
+}
34
+img.icon { 
35
+	vertical-align: middle;
36
+	padding: 4px;
37
+}
38
+body {
39
+	font: 12pt sans-serif;
40
+	background-color: #99B2CC;
41
+	color: #000000;
42
+}
43
+h1 { /* Tracker Header/Title */
44
+	font: 24px verdana, sans-serif;
45
+	text-align: center;
46
+}
47
+h2 { /* Smaller Page Headers */
48
+	font: 18px verdana, sans-serif;
49
+}
50
+a {
51
+	color: #000770;
52
+	text-decoration: none;
53
+	background-color: transparent;
54
+}
55
+a:hover {
56
+	text-decoration: underline;
57
+}
58
+table.percentages {
59
+	width: 200px;
60
+}
61
+table.torrentlist td {
62
+	padding: 4px;
63
+}
64
+table.nopadding td {
65
+	padding: 0px;
66
+}
67
+.details {
68
+	font: 12px verdana, sans-serif;
69
+	height: 0px;
70
+}
71
+p.error {
72
+	color: red;
73
+	text-align: center;
74
+	font-weight: bold;
75
+}
76
+p.success {
77
+	color: green;
78
+	text-align: center;
79
+	font-weight: bold;
80
+}	
81
+table {
82
+	width: 100%;
83
+}
84
+.center {	
85
+	text-align: center; 
86
+}
87
+.left {
88
+	text-align: left;
89
+}
90
+.right {
91
+	text-align: right;
92
+}
93
+span.notice {
94
+	color: #FF0000;
95
+}
0 96
\ No newline at end of file
1 97
new file mode 100644
... ...
@@ -0,0 +1,95 @@
1
+th { /* Table Header */
2
+	background-color: #CCCC99;
3
+	padding: 4px;
4
+	border-bottom: 2px solid #664D33;
5
+}
6
+th.subheader { /* Sub-Table Header */
7
+	background-color: #99FF99;
8
+	border-bottom: 2px solid #336633;
9
+}
10
+tr.selected {
11
+        background-color: #FFCC00;
12
+        color: #000000;
13
+}
14
+tr.row0 {
15
+	background-color: #A7BCD3;
16
+}
17
+tr.row0 a:link {color: #000770}
18
+tr.row0 a:visited {color: #000770}
19
+tr.row0 a:active  {color: #000770}
20
+tr.row0 a:hover   {color: #000770}
21
+tr.row1 {
22
+	background-color: #8AA9C6;
23
+}
24
+tr.row1 a:link {color: #000770}
25
+tr.row1 a:visited {color: #000770}
26
+tr.row1 a:active  {color: #000770}
27
+tr.row1 a:hover   {color: #000770}
28
+td.percent {
29
+	background-color: #33CC33;
30
+}
31
+td.percentleft {
32
+	background-color: #CCCCCC;
33
+}
34
+img.icon { 
35
+	vertical-align: middle;
36
+	padding: 4px;
37
+}
38
+body {
39
+	font: 12pt sans-serif;
40
+	background-color: #99B2CC;
41
+	color: #000000;
42
+}
43
+h1 { /* Tracker Header/Title */
44
+	font: 24px verdana, sans-serif;
45
+	text-align: center;
46
+}
47
+h2 { /* Smaller Page Headers */
48
+	font: 18px verdana, sans-serif;
49
+}
50
+a {
51
+	color: #000770;
52
+	text-decoration: none;
53
+	background-color: transparent;
54
+}
55
+a:hover {
56
+	text-decoration: underline;
57
+}
58
+table.percentages {
59
+	width: 200px;
60
+}
61
+table.torrentlist td {
62
+	padding: 4px;
63
+}
64
+table.nopadding td {
65
+	padding: 0px;
66
+}
67
+.details {
68
+	font: 12px verdana, sans-serif;
69
+	height: 0px;
70
+}
71
+p.error {
72
+	color: red;
73
+	text-align: center;
74
+	font-weight: bold;
75
+}
76
+p.success {
77
+	color: green;
78
+	text-align: center;
79
+	font-weight: bold;
80
+}	
81
+table {
82
+	width: 100%;
83
+}
84
+.center {	
85
+	text-align: center; 
86
+}
87
+.left {
88
+	text-align: left;
89
+}
90
+.right {
91
+	text-align: right;
92
+}
93
+span.notice {
94
+	color: #FF0000;
95
+}
0 96
\ No newline at end of file
1 97
new file mode 100644
... ...
@@ -0,0 +1,132 @@
1
+<?php
2
+require ("config.php");
3
+//Check session
4
+session_start();
5
+
6
+if (!$_SESSION['admin_logged_in'])
7
+{
8
+	//check fails
9
+	header("Location: authenticate.php?status=session");
10
+	exit();
11
+}
12
+?>
13
+
14
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
15
+<html>
16
+<head>
17
+	<title>Delete Torrent(s) From Database</title>
18
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
19
+	<link rel="stylesheet" type="text/css" href="./css/style.css" />
20
+	<script language="javascript">
21
+	function selectRow(checkBox)
22
+	{
23
+		if (checkBox.value % 2 == 1) //odd
24
+			var Style = "row1";
25
+		else //even
26
+			var Style = "row0";
27
+		if (checkBox.checked == true)
28
+			var Style = "selected";
29
+		var el = checkBox.parentNode;
30
+		while(el.tagName.toLowerCase() != "tr")
31
+		{
32
+			el = el.parentNode;
33
+    		}
34
+    		el.className = Style;
35
+	}
36
+	</script>
37
+</head>
38
+<body>
39
+<form action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>"  method="POST">
40
+<?php
41
+require_once("funcsv2.php");
42
+
43
+// check database user
44
+if (isset($dbuser) && isset($dbpass))
45
+{
46
+	$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Cannot connect to database. Check your username and password in the config file.</p>");
47
+	mysql_select_db($database) or die(errorMessage() . "Error selecting database.</p>");
48
+
49
+	foreach ($_POST as $left => $right)
50
+	{
51
+		if (strlen($left) == 41)
52
+		{
53
+			if (!is_numeric($right) || !verifyHash(substr($left, 1)))
54
+				continue;
55
+			$hash = substr($left, 1);
56
+			//delete torrent file
57
+			$query = "SELECT filename FROM ".$prefix."namemap WHERE info_hash =\"$hash\"";
58
+			$delete_file = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
59
+			$delete = mysql_fetch_row($delete_file);
60
+			unlink("torrents/" . $delete[0] . ".torrent");
61
+			//continue deleting information in database
62
+			@mysql_query("DELETE FROM " . $prefix . "summary WHERE info_hash=\"$hash\"");
63
+			@mysql_query("DELETE FROM " . $prefix . "namemap WHERE info_hash=\"$hash\""); 
64
+			@mysql_query("DELETE FROM " . $prefix . "timestamps WHERE info_hash=\"$hash\"");
65
+			@mysql_query("DELETE FROM " . $prefix . "webseedfiles WHERE info_hash=\"$hash\"");
66
+			@mysql_query("DROP TABLE " . $prefix . "y$hash");
67
+			@mysql_query("DROP TABLE " . $prefix . "x$hash");
68
+			//optimize tables, good after major changes have been made to database
69
+			@mysql_query("OPTIMIZE TABLE " . $prefix . "summary");
70
+			@mysql_query("OPTIMIZE TABLE " . $prefix . "namemap");
71
+			@mysql_query("OPTIMIZE TABLE " . $prefix . "timestamps");
72
+			//run RSS generator
73
+			require_once("rss_generator.php");
74
+		}
75
+	}
76
+}
77
+else
78
+{
79
+	$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
80
+	mysql_select_db($database) or die(errorMessage() . "Tracker error: can't open database $database - " . mysql_error() . "</p>");
81
+	$GLOBALS["maydelete"] = false;
82
+}
83
+
84
+?>
85
+<h1>Delete Torrent(s) From Database</h1>
86
+<table class="torrentlist" cellspacing="1">
87
+<tr>
88
+	<th>Name/Info Hash</th>
89
+	<th>File Size</th>
90
+	<th>Seeders</th>
91
+	<th>Leechers</th>
92
+	<th>Completed D/Ls</th>
93
+	<th>Bytes Transfered</th>
94
+	<th>Delete?</th>
95
+</tr>
96
+<?php
97
+
98
+if ($GLOBALS["customtitle"] != "true")
99
+$results = mysql_query("SELECT ".$prefix."summary.info_hash, ".$prefix."namemap.size, ".$prefix."summary.seeds, ".$prefix."summary.leechers, format(".$prefix."summary.finished,0), format(".$prefix."summary.dlbytes/1073741824,3), ".$prefix."namemap.filename FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash ORDER BY ".$prefix."namemap.filename") or die(errorMessage() . "" . mysql_error() . "</p>");
100
+else $results = mysql_query("SELECT ".$prefix."summary.info_hash, ".$prefix."namemap.size, ".$prefix."summary.seeds, ".$prefix."summary.leechers, format(".$prefix."summary.finished,0), format(".$prefix."summary.dlbytes/1073741824,3), ".$prefix."namemap.title FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash ORDER BY ".$prefix."namemap.title") or die(errorMessage() . "" . mysql_error() . "</p>");
101
+
102
+
103
+$i = 0;
104
+
105
+while ($data = mysql_fetch_row($results)) {
106
+	$writeout = "row" . $i % 2;
107
+	$hash = $data[0];
108
+	if (is_null($data[6]))
109
+		$data[6] = $data[0];
110
+	if (strlen($data[6]) == 0)
111
+		$data[6] = $data[0];
112
+		
113
+	echo "<tr class=\"$writeout\">\n";
114
+	echo "\t<td>".$data[6]."</td>\n";
115
+	echo "\t<td>".bytesToString($data[1])."</td>\n";
116
+	for ($j=2; $j < 5; $j++)
117
+		echo "\t<td class=\"center\">$data[$j]</td>\n";
118
+	echo "\t<td class=\"center\">$data[5] GB</td>\n";
119
+	
120
+	echo "\t<td class=\"center\"><input type=\"checkbox\" name=\"x$hash\" value=\"$i\" onclick=\"selectRow(this);\"/></td>\n";
121
+	echo "</tr>\n";
122
+	$i++;
123
+}
124
+
125
+?>
126
+</table>
127
+<p class="error">Warning: there is no confirmation for deleting files. Clicking this button is final.</p>
128
+<p class="center"><input type="submit" value="Delete" /></p>
129
+</form>
130
+<a href="index.php"><img src="images/stats.png" border="0" class="icon" alt="Tracker Statistics" title="Tracker Statistics" /></a><a href="index.php">Return to Statistics Page</a><br>
131
+<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Return to Admin Page</a>
132
+</body></html>
0 133
new file mode 100644
... ...
@@ -0,0 +1,77 @@
1
+<?php
2
+
3
+require_once ("config.php");
4
+
5
+//Check session only if hiddentracker is TRUE
6
+if ($hiddentracker == true)
7
+{
8
+	session_start();
9
+	
10
+	if (!$_SESSION['admin_logged_in'] && !$_SESSION['upload_logged_in'])
11
+	{
12
+		//check fails
13
+		header("Location: authenticate.php?status=error");
14
+		exit();
15
+	}
16
+}
17
+else
18
+{
19
+	//don't run
20
+	exit();
21
+}
22
+
23
+
24
+//if hash isn't of length 40, don't even bother connecting to database
25
+if (strlen($_GET['hash']) != 40)
26
+{
27
+	header("index.php"); 	
28
+  	exit();
29
+}
30
+
31
+require_once ("funcsv2.php"); //required for errorMessage()
32
+
33
+//connect to database and turn hash value into a filename
34
+if ($GLOBALS["persist"])
35
+	$db = mysql_pconnect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
36
+else
37
+	$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
38
+mysql_select_db($database) or die(errorMessage() . "Tracker error: can't open database $database - " . mysql_error() . "</p>");
39
+$query = "SELECT filename FROM ".$prefix."namemap WHERE info_hash = '" . $_GET['hash'] . "'";
40
+$results = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
41
+$row = mysql_fetch_row($results);
42
+
43
+if ($row[0] == null)
44
+{
45
+	//hash doesn't exist in database, error out
46
+	header("Location: index.php");
47
+  	exit();
48
+}
49
+else
50
+	$filename = $row[0];
51
+
52
+if (!file_exists("./torrents/" . $filename . ".torrent"))
53
+{
54
+  	header("Location: index.php");
55
+  	exit();
56
+}
57
+
58
+//you have be referred from the main website URL then you can download
59
+if (strpos($_SERVER['HTTP_REFERER'], $website_url . "/") === 0 && strpos($_SERVER['HTTP_REFERER'], "http") === 0)
60
+{
61
+  	$stat = stat("./torrents/" . $filename . ".torrent");
62
+  	header("Content-Type: application/x-bittorrent");
63
+  	header("Content-Length: " . $stat[7]);
64
+  	header("Last-Modified: " . gmdate("D, d M Y H:i:s", $stat[9]) . " GMT");
65
+  	header("Content-Disposition: attachment; filename=\"" . $filename . ".torrent\"");
66
+  	readfile("./torrents/" . $filename . ".torrent");
67
+  	exit();
68
+}
69
+else
70
+{
71
+	header("Location: index.php");
72
+	exit();
73
+}
74
+
75
+header('Pragma: no-cache');
76
+header('Cache-Control: no-cache, no-store, must-revalidate');
77
+?>
0 78
\ No newline at end of file
1 79
new file mode 100644
... ...
@@ -0,0 +1,83 @@
1
+API Interfaces
2
+
3
+
4
+BDecode($string)
5
+---------------
6
+
7
+Takes input as a single string. This string should be the whole
8
+.torrent file or whatever encoded stream you want to decode.
9
+
10
+Returns the array of the original encoded data. For example, to
11
+get the URL of the tracker used by a .torrent, use
12
+
13
+	$fd = fopen("myfile.torrent", "rb");
14
+	$stream = fread($fd, filesize("myfile.torrent"));
15
+	fclose($fd);
16
+	
17
+	$array = BDecode($stream);
18
+	
19
+	echo "Url: ".$array["announce"]."\n";
20
+
21
+
22
+
23
+
24
+BEncode($array)
25
+---------------
26
+
27
+Pretty much the opposite of the decoder. It takes an array and
28
+outputs the encoded data as one large string. Assuming there
29
+are no bugs in the code, BEncode(BDecode($stream) should give
30
+the exact same string back.
31
+
32
+
33
+
34
+
35
+
36
+$array
37
+------
38
+
39
+My first impression of the whole BEncode system is that Python
40
+makes a distinction between lists and dictionaries. I'm sure that's
41
+a good thing for the Python programmers but we have a different
42
+problem.
43
+
44
+PHP doesn't really make a difference between lists and
45
+dictionaries. They're all arrays. As such, the difference
46
+between a dictionary and an array is simple: lists are numerically
47
+indexed only. If (isset($array[0])) is true, you may assume the
48
+array is a "list" and treat it as such. Iterate until !isset($array[$i]);
49
+
50
+In the event of a list that has zero entries ("le"), it will be represented
51
+as array() (is_array() && empty()). Dictionaries ("de") will be represented
52
+as the boolean type true, not an array.
53
+
54
+This should hold as long as Bram doesn't do something cruel in the
55
+near future. :)
56
+
57
+
58
+Notes
59
+-----
60
+
61
+The return value will always be an array if the response is one of the
62
+normal responses of BitTorrent, which are always dictionaries. But it will
63
+also accept non-dictionaries as input.
64
+
65
+For exmaple, BDecode("i15e") === (int) 15
66
+
67
+Finally, the decoder is a little more tolerant of bencoding errors than
68
+the Python becode library. Things like sorted dictionaries when decoding
69
+are not enforced.
70
+
71
+
72
+
73
+Dictionaries
74
+------------
75
+One last thing about dictionaries. If you were to do something like this:
76
+
77
+foreach ($array as $left => $right) { .. }
78
+ or similarly
79
+$array[$left] = $right;
80
+
81
+Then beware: $left has had addslashes applied to it. This is to work
82
+around a small quirk in PHP. Null bytes ("\0") would cause the value
83
+of $left to be truncated at the null byte.
0 84
\ No newline at end of file
1 85
new file mode 100644
... ...
@@ -0,0 +1,340 @@
1
+		    GNU GENERAL PUBLIC LICENSE
2
+		       Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+			    Preamble
10
+
11
+  The licenses for most software are designed to take away your
12
+freedom to share and change it.  By contrast, the GNU General Public
13
+License is intended to guarantee your freedom to share and change free
14
+software--to make sure the software is free for all its users.  This
15
+General Public License applies to most of the Free Software
16
+Foundation's software and to any other program whose authors commit to
17
+using it.  (Some other Free Software Foundation software is covered by
18
+the GNU Library General Public License instead.)  You can apply it to
19
+your programs, too.
20
+
21
+  When we speak of free software, we are referring to freedom, not
22
+price.  Our General Public Licenses are designed to make sure that you
23
+have the freedom to distribute copies of free software (and charge for
24
+this service if you wish), that you receive source code or can get it
25
+if you want it, that you can change the software or use pieces of it
26
+in new free programs; and that you know you can do these things.
27
+
28
+  To protect your rights, we need to make restrictions that forbid
29
+anyone to deny you these rights or to ask you to surrender the rights.
30
+These restrictions translate to certain responsibilities for you if you
31
+distribute copies of the software, or if you modify it.
32
+
33
+  For example, if you distribute copies of such a program, whether
34
+gratis or for a fee, you must give the recipients all the rights that
35
+you have.  You must make sure that they, too, receive or can get the
36
+source code.  And you must show them these terms so they know their
37
+rights.
38
+
39
+  We protect your rights with two steps: (1) copyright the software, and
40
+(2) offer you this license which gives you legal permission to copy,
41
+distribute and/or modify the software.
42
+
43
+  Also, for each author's protection and ours, we want to make certain
44
+that everyone understands that there is no warranty for this free
45
+software.  If the software is modified by someone else and passed on, we
46
+want its recipients to know that what they have is not the original, so
47
+that any problems introduced by others will not reflect on the original
48
+authors' reputations.
49
+
50
+  Finally, any free program is threatened constantly by software
51
+patents.  We wish to avoid the danger that redistributors of a free
52
+program will individually obtain patent licenses, in effect making the
53
+program proprietary.  To prevent this, we have made it clear that any
54
+patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+  The precise terms and conditions for copying, distribution and
57
+modification follow.
58
+
59
+		    GNU GENERAL PUBLIC LICENSE
60
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+  0. This License applies to any program or other work which contains
63
+a notice placed by the copyright holder saying it may be distributed
64
+under the terms of this General Public License.  The "Program", below,
65
+refers to any such program or work, and a "work based on the Program"
66
+means either the Program or any derivative work under copyright law:
67
+that is to say, a work containing the Program or a portion of it,
68
+either verbatim or with modifications and/or translated into another
69
+language.  (Hereinafter, translation is included without limitation in
70
+the term "modification".)  Each licensee is addressed as "you".
71
+
72
+Activities other than copying, distribution and modification are not
73
+covered by this License; they are outside its scope.  The act of
74
+running the Program is not restricted, and the output from the Program
75
+is covered only if its contents constitute a work based on the
76
+Program (independent of having been made by running the Program).
77
+Whether that is true depends on what the Program does.
78
+
79
+  1. You may copy and distribute verbatim copies of the Program's
80
+source code as you receive it, in any medium, provided that you
81
+conspicuously and appropriately publish on each copy an appropriate
82
+copyright notice and disclaimer of warranty; keep intact all the
83
+notices that refer to this License and to the absence of any warranty;
84
+and give any other recipients of the Program a copy of this License
85
+along with the Program.
86
+
87
+You may charge a fee for the physical act of transferring a copy, and
88
+you may at your option offer warranty protection in exchange for a fee.
89
+
90
+  2. You may modify your copy or copies of the Program or any portion
91
+of it, thus forming a work based on the Program, and copy and
92
+distribute such modifications or work under the terms of Section 1
93
+above, provided that you also meet all of these conditions:
94
+
95
+    a) You must cause the modified files to carry prominent notices
96
+    stating that you changed the files and the date of any change.
97
+
98
+    b) You must cause any work that you distribute or publish, that in
99
+    whole or in part contains or is derived from the Program or any
100
+    part thereof, to be licensed as a whole at no charge to all third
101
+    parties under the terms of this License.
102
+
103
+    c) If the modified program normally reads commands interactively
104
+    when run, you must cause it, when started running for such
105
+    interactive use in the most ordinary way, to print or display an
106
+    announcement including an appropriate copyright notice and a
107
+    notice that there is no warranty (or else, saying that you provide
108
+    a warranty) and that users may redistribute the program under
109
+    these conditions, and telling the user how to view a copy of this
110
+    License.  (Exception: if the Program itself is interactive but
111
+    does not normally print such an announcement, your work based on
112
+    the Program is not required to print an announcement.)
113
+
114
+These requirements apply to the modified work as a whole.  If
115
+identifiable sections of that work are not derived from the Program,
116
+and can be reasonably considered independent and separate works in
117
+themselves, then this License, and its terms, do not apply to those
118
+sections when you distribute them as separate works.  But when you
119
+distribute the same sections as part of a whole which is a work based
120
+on the Program, the distribution of the whole must be on the terms of
121
+this License, whose permissions for other licensees extend to the
122
+entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+Thus, it is not the intent of this section to claim rights or contest
125
+your rights to work written entirely by you; rather, the intent is to
126
+exercise the right to control the distribution of derivative or
127
+collective works based on the Program.
128
+
129
+In addition, mere aggregation of another work not based on the Program
130
+with the Program (or with a work based on the Program) on a volume of
131
+a storage or distribution medium does not bring the other work under
132
+the scope of this License.
133
+
134
+  3. You may copy and distribute the Program (or a work based on it,
135
+under Section 2) in object code or executable form under the terms of
136
+Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+    a) Accompany it with the complete corresponding machine-readable
139
+    source code, which must be distributed under the terms of Sections
140
+    1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+    b) Accompany it with a written offer, valid for at least three
143
+    years, to give any third party, for a charge no more than your
144
+    cost of physically performing source distribution, a complete
145
+    machine-readable copy of the corresponding source code, to be
146
+    distributed under the terms of Sections 1 and 2 above on a medium
147
+    customarily used for software interchange; or,
148
+
149
+    c) Accompany it with the information you received as to the offer
150
+    to distribute corresponding source code.  (This alternative is
151
+    allowed only for noncommercial distribution and only if you
152
+    received the program in object code or executable form with such
153
+    an offer, in accord with Subsection b above.)
154
+
155
+The source code for a work means the preferred form of the work for
156
+making modifications to it.  For an executable work, complete source
157
+code means all the source code for all modules it contains, plus any
158
+associated interface definition files, plus the scripts used to
159
+control compilation and installation of the executable.  However, as a
160
+special exception, the source code distributed need not include
161
+anything that is normally distributed (in either source or binary
162
+form) with the major components (compiler, kernel, and so on) of the
163
+operating system on which the executable runs, unless that component
164
+itself accompanies the executable.
165
+
166
+If distribution of executable or object code is made by offering
167
+access to copy from a designated place, then offering equivalent
168
+access to copy the source code from the same place counts as
169
+distribution of the source code, even though third parties are not
170
+compelled to copy the source along with the object code.
171
+
172
+  4. You may not copy, modify, sublicense, or distribute the Program
173
+except as expressly provided under this License.  Any attempt
174
+otherwise to copy, modify, sublicense or distribute the Program is
175
+void, and will automatically terminate your rights under this License.
176
+However, parties who have received copies, or rights, from you under
177
+this License will not have their licenses terminated so long as such
178
+parties remain in full compliance.
179
+
180
+  5. You are not required to accept this License, since you have not
181
+signed it.  However, nothing else grants you permission to modify or
182
+distribute the Program or its derivative works.  These actions are
183
+prohibited by law if you do not accept this License.  Therefore, by
184
+modifying or distributing the Program (or any work based on the
185
+Program), you indicate your acceptance of this License to do so, and
186
+all its terms and conditions for copying, distributing or modifying
187
+the Program or works based on it.
188
+
189
+  6. Each time you redistribute the Program (or any work based on the
190
+Program), the recipient automatically receives a license from the
191
+original licensor to copy, distribute or modify the Program subject to
192
+these terms and conditions.  You may not impose any further
193
+restrictions on the recipients' exercise of the rights granted herein.
194
+You are not responsible for enforcing compliance by third parties to
195
+this License.
196
+
197
+  7. If, as a consequence of a court judgment or allegation of patent
198
+infringement or for any other reason (not limited to patent issues),
199
+conditions are imposed on you (whether by court order, agreement or
200
+otherwise) that contradict the conditions of this License, they do not
201
+excuse you from the conditions of this License.  If you cannot
202
+distribute so as to satisfy simultaneously your obligations under this
203
+License and any other pertinent obligations, then as a consequence you
204
+may not distribute the Program at all.  For example, if a patent
205
+license would not permit royalty-free redistribution of the Program by
206
+all those who receive copies directly or indirectly through you, then
207
+the only way you could satisfy both it and this License would be to
208
+refrain entirely from distribution of the Program.
209
+
210
+If any portion of this section is held invalid or unenforceable under
211
+any particular circumstance, the balance of the section is intended to
212
+apply and the section as a whole is intended to apply in other
213
+circumstances.
214
+
215
+It is not the purpose of this section to induce you to infringe any
216
+patents or other property right claims or to contest validity of any
217
+such claims; this section has the sole purpose of protecting the
218
+integrity of the free software distribution system, which is
219
+implemented by public license practices.  Many people have made
220
+generous contributions to the wide range of software distributed
221
+through that system in reliance on consistent application of that
222
+system; it is up to the author/donor to decide if he or she is willing
223
+to distribute software through any other system and a licensee cannot
224
+impose that choice.
225
+
226
+This section is intended to make thoroughly clear what is believed to
227
+be a consequence of the rest of this License.
228
+
229
+  8. If the distribution and/or use of the Program is restricted in
230
+certain countries either by patents or by copyrighted interfaces, the
231
+original copyright holder who places the Program under this License
232
+may add an explicit geographical distribution limitation excluding
233
+those countries, so that distribution is permitted only in or among
234
+countries not thus excluded.  In such case, this License incorporates
235
+the limitation as if written in the body of this License.
236
+
237
+  9. The Free Software Foundation may publish revised and/or new versions
238
+of the General Public License from time to time.  Such new versions will
239
+be similar in spirit to the present version, but may differ in detail to
240
+address new problems or concerns.
241
+
242
+Each version is given a distinguishing version number.  If the Program
243
+specifies a version number of this License which applies to it and "any
244
+later version", you have the option of following the terms and conditions
245
+either of that version or of any later version published by the Free
246
+Software Foundation.  If the Program does not specify a version number of
247
+this License, you may choose any version ever published by the Free Software
248
+Foundation.
249
+
250
+  10. If you wish to incorporate parts of the Program into other free
251
+programs whose distribution conditions are different, write to the author
252
+to ask for permission.  For software which is copyrighted by the Free
253
+Software Foundation, write to the Free Software Foundation; we sometimes
254
+make exceptions for this.  Our decision will be guided by the two goals
255
+of preserving the free status of all derivatives of our free software and
256
+of promoting the sharing and reuse of software generally.
257
+
258
+			    NO WARRANTY
259
+
260
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
262
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
266
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
267
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+REPAIR OR CORRECTION.
269
+
270
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+POSSIBILITY OF SUCH DAMAGES.
279
+
280
+		     END OF TERMS AND CONDITIONS
281
+
282
+	    How to Apply These Terms to Your New Programs
283
+
284
+  If you develop a new program, and you want it to be of the greatest
285
+possible use to the public, the best way to achieve this is to make it
286
+free software which everyone can redistribute and change under these terms.
287
+
288
+  To do so, attach the following notices to the program.  It is safest
289
+to attach them to the start of each source file to most effectively
290
+convey the exclusion of warranty; and each file should have at least
291
+the "copyright" line and a pointer to where the full notice is found.
292
+
293
+    <one line to give the program's name and a brief idea of what it does.>
294
+    Copyright (C) <year>  <name of author>
295
+
296
+    This program is free software; you can redistribute it and/or modify
297
+    it under the terms of the GNU General Public License as published by
298
+    the Free Software Foundation; either version 2 of the License, or
299
+    (at your option) any later version.
300
+
301
+    This program is distributed in the hope that it will be useful,
302
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
304
+    GNU General Public License for more details.
305
+
306
+    You should have received a copy of the GNU General Public License
307
+    along with this program; if not, write to the Free Software
308
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
309
+
310
+
311
+Also add information on how to contact you by electronic and paper mail.
312
+
313
+If the program is interactive, make it output a short notice like this
314
+when it starts in an interactive mode:
315
+
316
+    Gnomovision version 69, Copyright (C) year name of author
317
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318
+    This is free software, and you are welcome to redistribute it
319
+    under certain conditions; type `show c' for details.
320
+
321
+The hypothetical commands `show w' and `show c' should show the appropriate
322
+parts of the General Public License.  Of course, the commands you use may
323
+be called something other than `show w' and `show c'; they could even be
324
+mouse-clicks or menu items--whatever suits your program.
325
+
326
+You should also get your employer (if you work as a programmer) or your
327
+school, if any, to sign a "copyright disclaimer" for the program, if
328
+necessary.  Here is a sample; alter the names:
329
+
330
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
332
+
333
+  <signature of Ty Coon>, 1 April 1989
334
+  Ty Coon, President of Vice
335
+
336
+This General Public License does not permit incorporating your program into
337
+proprietary programs.  If your program is a subroutine library, you may
338
+consider it more useful to permit linking proprietary applications with the
339
+library.  If this is what you want to do, use the GNU Library General
340
+Public License instead of this License.
0 341
new file mode 100644
... ...
@@ -0,0 +1,159 @@
1
+RivetTracker is a modified version of PHPBTTracker Version 1.5rc3, written by "DeHackEd".
2
+
3
+Changes:
4
+
5
+---Version 1.03---
6
+
7
+-Prevented XSS attack on index.php page with htmlspecialchars (Thanks to report on forums)
8
+-Show message about folder permissions for 'torrents' and 'rss' when logged into admin.php main menu page
9
+-Changed install.php text at the end explaining folder permissions
10
+-Fixed rss_generator.php bug where torrents were not being ordered according to date (newest should be first)
11
+
12
+---Version 1.02---
13
+
14
+-Fixed dltorrent.php bug where if the tracker was set to hidden, user was unable to download the torrent because of OR instead of AND in conditional check (Thanks to bug report on forums)
15
+
16
+---Version 1.01---
17
+
18
+-Fixed index.php page where authenticate.php link didn't have PHP file extension (Thanks to bug report from Johannes)
19
+-Fixed MySQL formatting finished downloads with thousands and PHP not being able to recognize this correctly (Thanks to bug report on forums)
20
+
21
+---Version 1.0---
22
+
23
+-Changed database engine from default MyISAM to InnoDB, hopefully this will prevent table crashes
24
+-Changed CSS files
25
+-Changed session authentication to more secure method, does not store username or MD5 anymore
26
+-Passwords are now no longer stored in cleartext in the config.php file, they are computed as md5(username.password)
27
+
28
+---Version 0.9991---
29
+
30
+-Added information on upgrading in help file
31
+-Fixed install bug
32
+
33
+---Version 0.999---
34
+
35
+-Fixed bug where RSS feed was being displayed in header when it was disabled
36
+-Fixed rounding error in statistics.php where user was being shown as 100% done when they are only almost done (99.6%)
37
+-Changed display of bytes transferred on index.php page to correct units, before it defaulted to GB
38
+-Added check for stalled download in runSpeed() function
39
+-Fixed error where speed was set to 0 if seeders == 0, not always the case, can still be downloading even if there are no seeders (partial d/l)
40
+-took out repair statement in sanity.php and sanity_no_output.php
41
+-Added CSS page where you can change/swap/create CSS files and examine colors with the color picker
42
+-Added batch upload of torrents via ZIP file
43
+-Added help link to index.php
44
+-Used htmlspecialchars on inputs in order to prevent code injection
45
+-Added javascript row select in delete page
46
+-Fixed delete bug, URL bug
47
+-Added MySQL table prefix option
48
+-Sanitized some inputs (still more?), this way if someone gets your admin password they won't be able to execute malicious code
49
+
50
+---Version 0.995---
51
+
52
+-Fixed bug in namemap table where MySQL size variable INT type was being used, changed it to BIGINT
53
+-Fixed bug where single quotes were not being checked in torrent file, filenames, title, RSS description, and RSS title
54
+-Changed funcsv2.php and added in the clean() and addquotes() functions
55
+-Added REPAIR MySQL command to sanity.php and sanity_no_output.php (to fix table crashes, sometimes it happens, dunno why)
56
+-Fixed bug where null entry for filename search caused error
57
+-Added scrape option in config.php file, changed tracker to check for this before doling out scrape information to client
58
+-Changed location of announce URL to announce.php in order to enable support for scraping
59
+-Added display of files inside torrent via [+] button on index.php page
60
+-Added ability to disable RSS feed
61
+-Peercaching is now on by default, slightly more diskspace needed for this but it's worth it because of the lessened strain on database
62
+-Added ability to have a hiddentracker, this is not a private tracker, but hidden enough so that it requires a login, .htaccess or something
63
+similar will be needed to secure the "torrents" folder, also all BT clients can connect to the tracker still, there is no username authentication there
64
+-Added dltorrent.php that is used when in hiddentracker mode, no direct linking to .torrent file on main page
65
+-Removed updatePeer(), the function was emtpy so not a big deal...
66
+-Added ability to have legal terms and a policy agreement before logging in, if you want this create a file called legalterms.txt with the info in it
67
+-Changed edit database script so that you click on a file to edit it instead of displaying too much information on one screen
68
+-Various minor display improvements
69
+-Checked IE and Firefox for display issues
70
+-Updated documentation with some minor additions
71
+
72
+---Version 0.99---
73
+
74
+-Changed fonts in CSS file so they were easier to read/view in IE
75
+-Limit results on index.php page, can now switch between pages
76
+-Limit results on statistics.php page, can now switch between pages
77
+-Fixed bug install.php and editconfig.php where RSS information was not required, now it is
78
+-Torrent URL checked in newtorrents.php file, error message if it doesn't start with http://
79
+-Tracker announce URL checked in newtorrents.php file, if it doesn't match the tracker, user is asked to re-create torrent and re-upload
80
+-Added display of private torrent variable in DumpTorrentCGI.php
81
+-Fixed bug where uploaded torrent was being used even if there was an error
82
+-Displays torrent information after successful torrent added to database
83
+-Split functions used by DumpTorrentCGI.php into torrent_functions.php, now it can be used by any file to display torrent info
84
+-Changed index.php page to point to admin.php not authenticate.php login page
85
+-Fixed bug where in install or editing the config file, maxpeers could be set to negative number or zero
86
+-Added size to list of items displayed when removing a torrent
87
+-Fixed bug where in install or editing the config file, max reannounce interval and min reannounce interval could be negative or zero
88
+-Made speed estimate slightly more accurate, if no leechers, sets speed to zero
89
+-Added an aggregate total at the top of the index.php page
90
+-Added search functionality to statistics.php page using REGEXP in MySQL
91
+-Added sanity_no_output.php, a stripped down version of sanity.php that gets run by the index.php page every once in awhile
92
+-Added uploadstats.php in admin section that shows upload rates for HTTP seeding and regular bittorrent
93
+-Added support for GetRight HTTP seeding and Bittornado HTTP seeding
94
+-Changed doctype on all pages to <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
95
+-Added help.html file in docs folder that consolidates all information into one file, help.pdf is the PDF equivalent
96
+
97
+---Version 0.9---
98
+
99
+-Added alt and title properties for all image files
100
+-added automatic creation of valid RSS 2.0 file (listed on main page, right side)
101
+-added pubDate (for RSS feed) to table namemap in MySQL
102
+-added index.php redirect file in rss folder
103
+-modified install.php and editconfig.php for additional RSS variables, timezone, and more
104
+-check at beginning of index.php if there is no config.php file, error out and display message
105
+-check at beginning of install.php, if there is a config.php file, this is an indication of an already
106
+ existing installation and thus the user should be warned and unable to continue
107
+-various minor display improvements
108
+-added RSS variables, timezone, and others to config.php file
109
+-changed 'info' in MySQL namemap table to 'size' and make it store total size of all file(s) in torrent in bytes
110
+This is related to an error where the filesize was reported as higher than actual when the file(s) in the torrent were very small
111
+-display total file(s) size in DumpTorrentCGI.php
112
+-added bytesToString() function in funcsv2.php
113
+-make sure install.php and editconfig.php check for blank entries for required variables so config.php isn't populated with null values
114
+-added check for install.php file in admin.php, if so, display strong warning message
115
+-added critical message icon to most class="error" areas
116
+-added page in admin section where user can edit torrents and values already in database
117
+-added errorMessage() in funcsv2.php that shows error message and icon, most errors that are displayed with die() now use this function
118
+-made installer easier to read and walkthrough
119
+-converted all uppercase HTML to lowercase
120
+-run optimize MySQL command after deleter.php runs
121
+-removed dynamic_torrents variable that allowed torrents to be added without authentication
122
+-fixed division by zero error in statistics.php
123
+
124
+---Version 0.8---
125
+
126
+-Adding a torrent file saves the file in the "torrents" folder and is displayed on the main statistics page.
127
+-Restructured files into more folders
128
+-Added icons from the Tango Project:
129
+http://tango.freedesktop.org/
130
+(creative commons license)
131
+http://creativecommons.org/licenses/by-sa/2.5/
132
+-Show tracker URL in newtorrents.php
133
+-Delete torrent from database will also delete the saved torrent file
134
+-Added index.php redirect file in images, docs, and torrents folders
135
+-Fixed DumpTorrentCGI.php MAX_FILE_SIZE error
136
+-Consolidated authentication to one script
137
+-Password protect newtorrents.php page to prevent people uploading items who don't actually have an account
138
+
139
+---Version 0.1---
140
+
141
+-minor formatting issues, addition of links to admin page and create torrent in index.php
142
+-each statistics column is totalled and displayed in the last row
143
+-admin page added with links to relevent scripts, each script except add torrent requires session authentication
144
+-added admin username and password in config.php
145
+-fixed index.php $GLOBALS bug for <title>
146
+-added title variable in config.php
147
+-upload user in config.php is able to add torrents but not access admin resources, this requires the separate admin user
148
+-admin user is able to access any page
149
+-if the number of leechers is zero, then the speed is zero
150
+-if the number of leechers is zero and the number of seeders is zero, then the speed is zero
151
+-mystats.php renamed to index.php
152
+-changed speed units to KB, MB, and GB
153
+-fixed installer.php writing to config.php to account for additional variables
154
+-added statistics.php script, admin resource that shows detailed information on each user the tracker has saved
155
+-removed "short description" in add torrent, now it just defaults to the size all the time
156
+-heavily modified install.php file to allow for a more robust and easier installation
157
+-allow config.php file to be saved to server or downloaded in install.php
158
+-added page in admin section where user can change config.php values right from webpage
159
+
0 160
new file mode 100644
... ...
@@ -0,0 +1,216 @@
1
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2
+<html>
3
+<head>
4
+<title>RivetTracker Help</title>
5
+</head>
6
+<body>
7
+<center>
8
+<h3>RivetTracker Help</h3>
9
+</center>
10
+<hr>
11
+<table border="0">
12
+<tr bgcolor="#CCCCCC">
13
+<td>
14
+<ul>
15
+<li><a href="#about">About</a></li>
16
+<li><a href="#bittorrent">What is BitTorrent?</a></li>
17
+<li><a href="#tracker">What is a Tracker?</a></li>
18
+<li><a href="#requirements">Requirements</a></li>
19
+<li><a href="#installation">RivetTracker Installation</a></li>
20
+<li><a href="#upgrading">Upgrading</a></li>
21
+<li><a href="#httpseeding">HTTP Seeding</a></li>
22
+<li><a href="#help">Support/Help</a></li>
23
+<li><a href="#contribute">Contribute</a></li>
24
+<li><a href="#thanksto">Thanks To</a></li>
25
+</ul>
26
+</td>
27
+</tr>
28
+</table>
29
+
30
+<a name="about"></a>
31
+<h3>About</h3>
32
+
33
+<p>RivetTracker is a modified version of <a href="http://dehacked.2y.net/BT/">PHPBTTracker Version 1.5rc3</a>,
34
+written by "DeHackEd".  This program provides the same functionality as most other BitTorrent trackers and uses MySQL as the database backend.
35
+It provides an RSS feed, optional support for HTTP seeding, detailed connection statistics, and much more.</p>
36
+<p>PHPBTTracker was released under the <a href="http://www.fsf.org/licensing/licenses/info/GPLv2.html">GPLv2 license</a>
37
+as is this program.</p>
38
+<p>Some of the images used were provided by the <a href="http://tango.freedesktop.org/">Tango Desktop Project</a>.
39
+These images are licensed under the
40
+<a href="http://creativecommons.org/licenses/by-sa/2.5/">Creative Commons Attribution-ShareAlike 2.5 License</a>.</p>
41
+
42
+<a name="bittorrent"></a>
43
+<h3>What is BitTorrent?</h3>
44
+
45
+<p>BitTorrent is a Peer to Peer (P2P) communication protocol for sharing files.  A client downloads a small
46
+.torrent file from a website that contains the necessary information to put the whole file or files together.
47
+This torrent file contains a link to a tracker or trackers that provide information on who else is downloading or
48
+seeding the file.  The term seeder refers to someone who has downloaded the entire file and is uploading parts of
49
+it to others called leechers.  Leechers are people who have started the download and are downloading the file but
50
+have not finished yet.  The beauty of BitTorrent is that it allows people to share files (especially large ones) easily
51
+without incuring huge hosting costs because of bandwidth limitations.  Since all seeders and leechers are constantly uploading
52
+whatever data they have available, this speeds up the overall distribution of the file.  You can start using BitTorrent
53
+right now by downloading and installing a <a href="http://en.wikipedia.org/wiki/BitTorrent_client">BitTorrent client</a>.
54
+<p>If you are new to BitTorrent and have not used it before please be careful when initially using it.  Sadly, BitTorrent
55
+has become used heavily for distributing pirated movies, music, and games.  That being said, many Linux distributions use
56
+BitTorrent legally to efficiently release their distribution on a global scale.  Many websites use BitTorrent
57
+for purposes which may be illegal in the country that you live in.  Just be careful and watch what you are downloading!</p>
58
+<p>For more information on the specifics of the BitTorrent protocol you can visit the following websites:
59
+<ul>
60
+<li><a href="http://wiki.theory.org/Main_Page">http://wiki.theory.org/Main_Page</a></li>
61
+<li><a href="http://en.wikipedia.org/wiki/BitTorrent">http://en.wikipedia.org/wiki/BitTorrent</a></li>
62
+</ul>
63
+
64
+<a name="tracker"></a>
65
+<h3>What is a Tracker?</h3>
66
+
67
+<p>A <a href="http://en.wikipedia.org/wiki/BitTorrent_tracker">BitTorrent tracker</a> is a piece of software that BitTorrent
68
+clients communicate with in order to receive information about other people downloading the file.  You can think of a tracker
69
+as a mediator between clients.  It doesn't actually transmit the file it just provides information about other people that have it.</p>
70
+<p>RivetTracker is special because it is built using PHP and MySQL.  This means you can easily create a website to share files
71
+and have a tracker that people around the world are able to connect to.  The web-interface makes it easy to navigate and administer.</p>
72
+
73
+<a name="requirements"></a>
74
+<h3>Requirements</h3>
75
+
76
+
77
+<ul>
78
+<li>A webserver, <a href="http://www.apache.org">Apache</a> is a great one.</li>
79
+<li>A recent version of <a href="http://www.php.net">PHP.</a></li>
80
+<li>The <a href="http://www.mysql.org">MySQL Database.</a></li>
81
+</ul>
82
+
83
+<p>RivetTracker has been tested under <a href="http://www.ubuntu.com">Ubuntu Linux</a>,
84
+support under Windows is unknown at this time.</p>
85
+
86
+<a name="installation"></a>
87
+<h3>RivetTracker Installation</h3>
88
+
89
+<p>Installation is very easy, just copy the folder and all the files to your webserver.
90
+Next, run install.php to create the MySQL database and setup the configuration.</p>
91
+<a href="./imgs/1.gif"><img src="./imgs/1.gif" border="0" alt="Installation" /></a>
92
+<p>In this case, I want to create a new database and user that only has access rights to that database.
93
+For security reasons, it is recommended that you go with the second option.</p>
94
+<a href="./imgs/2.gif"><img src="./imgs/2.gif" border="0" alt="Database Setup"/></a>
95
+<p>In this step I provided the installer with a user that can create other users.  You will also be required to specify
96
+the hostname of the MySQL server, user that will be created, and the database name.  As you can see in the image
97
+I have provided all the necessary information.  Click install and the script will go through the process of connecting
98
+to the MySQL server and running the appropriate setup commands.</p>
99
+<a href="./imgs/3.gif"><img src="./imgs/3.gif" border="0" alt="Configuration File"/></a>
100
+<p>This section lets you setup the configuration file that stores all your settings about the tracker.  Make sure you
101
+read the directions carefully about each item.  It's fairly self-explanatory, just take your time.  When you are
102
+ready click on the create config file button to continue.</p>
103
+<p>An important note about the hidden tracker feature is that it requires a login by either the admin or upload
104
+account in order to even view the main torrents page and download them.  However, the /torrents folder is NOT
105
+protected in any way.  You will have to go in and create a .htaccess file or something else to protect that folder.
106
+Also, having the hidden tracker on does not mean this is a private tracker.  People will still be able to connect to
107
+your torrents and use the tracker system if they can get a copy of the torrent.  Also, it may be possible if you
108
+also have scrape support enabled that a client could connect and get information about what files are on your tracker
109
+through the scrape.  Unfortunately, I do not know all the details of how scrape works.  If you need a very secure
110
+tracker, I would suggest checking out the other programs that are available.</p>
111
+<p>At this point, your installation is finished.</p>
112
+<p><font color="red"><big>***MAKE SURE YOU DELETE install.php AFTER YOU ARE FINISHED INSTALLING!***</big></font></p>
113
+<p>Also, make sure that the "torrents" and "rss" folders are writeable by your webserver.</p>
114
+<p>Click on the link to go to your main statistics page.</p>
115
+<a href="./imgs/4.gif"><img src="./imgs/4.gif" border="0" alt="Main Page"/></a>
116
+<p>There are no torrents yet because you have not added them to the database.</p>
117
+<p>At this point you can start adding torrents to the database by logging in as either the upload user
118
+or as the administrator.  When you get to the add torrent page you should see something like this:</p>
119
+<a href="./imgs/5.gif"><img src="./imgs/5.gif" border="0" alt="Add Torrent"/></a>
120
+<p>Simply provide a .torrent file that you have created and specify whether you want one, both, or neither of the
121
+web seeding features.  Most information can be automatically gathered from the torrent file but if you wish, you can
122
+provide a specific filename and URL for the database to use.</p>
123
+<p>Click add and you have just added your first torrent to the database.  If you go back to the statistics page
124
+you should see it listed as well as a link to download the torrent file.</p>
125
+<p>If you want <a href="http://www.azureuswiki.com/index.php/Scrape">scrape</a> functionality, 
126
+check the appropriate box in the configuration settings.  It is generally safe to leave this enabled, however,
127
+there is the possiblity that BitTorrent clients could use this abusively and request this information too much.
128
+For trackers that serve large numbers of torrents with many users, this will also increase bandwidth usage.
129
+Scraping is used in order to figure out if a request for additional peers is warranted.  This request for peers
130
+eats up a lot of bandwidth and it is usually better to try to gauge this by asking the tracker via a scrape.</p>
131
+<p>The speed information is a rough estimate and only gets updated when a client
132
+connects to the tracker.</p>
133
+<p>You can now utilize a short announce URL for your tracker.  If you enable this feature, you will need the provided
134
+htaccess file and URL rewriting capabilities enabled and set properly on your server.  More info to set it up will be
135
+located <a href="./htaccess-readme.txt">here.</a></p>
136
+<p>If you don't like the color scheme you can change it by editing the provided CSS file.
137
+Go into the admin page and click on "Change CSS File".  From there you will be able to create new
138
+CSS files or edit existing ones.</p>
139
+<p>The RSS feed that is available is great for people who publish files on a regular basis, for example audio or
140
+video podcasts.</p>
141
+<p>If you want to have legal information like a use policy, create a file called "legalterms.txt" in the main directory
142
+where the index.php file is.  Inside the legalterms text file, put your information.  Now, when people go to login
143
+they will have to agree to the terms before it will let them on.</p>
144
+
145
+<a name="upgrading"></a>
146
+<h3>Upgrading</h3>
147
+
148
+<p>If you are upgrading from a previous installation of RivetTracker there is an easy way to save your
149
+torrents.  Because there might be changes to the database or changes to the configuration file, it is
150
+much easier just to delete the existing database and installation and start from scratch.  Before you do this
151
+however, go into your current 'torrents' folder and ZIP them all up into one file.  Next, delete your current
152
+database and do a complete reinstall of RivetTracker.  After this, go into the admin page and use the batch
153
+upload system to upload the ZIP file you created.  This will load each torrent file in the ZIP one by one.
154
+It makes it much easier to upload large quantities of torrent files into the database.</p>
155
+
156
+<a name="httpseeding"></a>
157
+<h3>HTTP Seeding</h3>
158
+
159
+<p>There are two standards for providing <a href="http://wiki.theory.org/BitTorrentSpecification#WebSeeding">web seeding</a>
160
+in BitTorrent.  Web seeding allows an HTTP or FTP server to act as a seeder and provide files to the client.  Most of the major
161
+BitTorrent clients support one standard or the other, or both.</p>
162
+<p>The first standard was created by BitTornado and you can find the detailed specification
163
+<a href="http://bittornado.com/docs/webseed-spec.txt">here</a>.  It requires that the .torrent file be created with
164
+an additional list that holds the location or locations of a URL script that provides an interface to the BitTorrent client.
165
+The benefit of this is that the script is able to limit bandwidth usage and the number of connections to the server requesting the file.
166
+It also prevents hotlinking directly to the file and abuse.  The downside is that only some BitTorrent client support this
167
+standard.</p>
168
+<p>The other standard for web seeding is detailed by the GetRight creator <a href="http://getright.com/seedtorrent.html">here</a>.
169
+This solution also requires that .torrent files include an additional list of direct links to the file or a link to a
170
+directory where the heirarchy can be re-created.  The benefit of this standard is that it does not require any additional
171
+script be setup or communication with the server that the BitTornado standard does.  The downside is that this standard is
172
+open to abuse from clients potentially hotlinking directly to the file.</p>
173
+<p>RivetTracker includes support for both standards as well as the scripts required by BitTornado.  When you go to add
174
+a torrent to the database, there is an option to add web seeding support.  Simply fill in the required information and when
175
+the torrent is uploaded this information is added into the .torrent file.  This makes migration of old torrent files a snap.</p>
176
+
177
+<a name="help"></a>
178
+<h3>Support/Help</h3>
179
+
180
+<p>If this document was unable to answer your question or you're stuck on something please visit the RivetCode
181
+<a href="http://forums.rivetcode.com">forums</a> or <a href="http://www.rivetcode.com/contact/">contact me</a>.
182
+
183
+<a name="contribute"></a>
184
+<h3>Contribute</h3>
185
+
186
+<p>Want to contribute to future RivetTracker development and releases?  There are a couple ways
187
+in which you can help.  First of all, try to find bugs and submit <a href="http://www.rivetcode.com/contact/">bug reports</a>.
188
+You can also submit suggestions for future versions <a href="http://www.rivetcode.com/contact/">here</a>.
189
+If you know PHP and are willing to dive into the code, adding features and improving on the project would also be immensely
190
+helpful.  There is a <a href="http://sourceforge.net/projects/rivettracker/">Sourceforge project</a> page that has the bug tracker,
191
+git repository, and download links.  Public git access is available via:
192
+<pre>git clone git://rivettracker.git.sourceforge.net/gitroot/rivettracker/rivettracker</pre><p>
193
+
194
+
195
+<p>Finally, if you want to consider donating a few dollars for further development of this software and future projects that
196
+would be fantastic.  Every little bit helps, thanks!</p>
197
+<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
198
+<input type="hidden" name="cmd" value="_s-xclick">
199
+<input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but04.gif" border="0" name="submit" alt="Make a donation and help support further RivetCode software!" title="Make a donation and help support further RivetCode software!">
200
+<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
201
+<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHmAYJKoZIhvcNAQcEoIIHiTCCB4UCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYCrOE3S7LR5OwDimRfELsv9ZG7z14706zRg+x8jBQLiltSecWAKIKf+v2MKwsjwpD2wFvtyclEWIADoAuNXJZsxI0Myt+vz49udx+pamfVtSBGjRwQoRbfEr5aw2IzbtKSGcSWB4x3vVd9M/sq1MqTbcUDFbkwdidLcwzCBuPgjFzELMAkGBSsOAwIaBQAwggEUBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECJEgkx1sSxmOgIHw+yFB2f0GyCQgCSywBGzq2fypvBo9keMNl9O/i43T+dK4rfLLuoKN+mpD6wpi6jwNNiowGb38XwzqiCy6+PrwiNtLKkUSKSMF+sWxT763cbFGehPNA99i4YkEojQ5by/5hpiPxb9N+G3ud//ygOYw7K6F19oiornqjkqZSAr6i8ADpHoJyWN37xO3O1j/j5xViRL8TFOQFQdEEn4SyA0fDUg/DWDsGye8jtAsrtxOXYyKzkUAC5kmcDux6ecMuS4flH1030H5tkkjpz/oJhV63prg5oehTEwmZy81j2ubtH+RIJZ9WL7SO//OCM77fYMgoIIDhzCCA4MwggLsoAMCAQICAQAwDQYJKoZIhvcNAQEFBQAwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMB4XDTA0MDIxMzEwMTMxNVoXDTM1MDIxMzEwMTMxNVowgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBR07d/ETMS1ycjtkpkvjXZe9k+6CieLuLsPumsJ7QC1odNz3sJiCbs2wC0nLE0uLGaEtXynIgRqIddYCHx88pb5HTXv4SZeuv0Rqq4+axW9PLAAATU8w04qqjaSXgbGLP3NmohqM6bV9kZZwZLR/klDaQGo1u9uDb9lr4Yn+rBQIDAQABo4HuMIHrMB0GA1UdDgQWBBSWn3y7xm8XvVk/UtcKG+wQ1mSUazCBuwYDVR0jBIGzMIGwgBSWn3y7xm8XvVk/UtcKG+wQ1mSUa6GBlKSBkTCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb22CAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCBXzpWmoBa5e9fo6ujionW1hUhPkOBakTr3YCDjbYfvJEiv/2P+IobhOGJr85+XHhN0v4gUkEDI8r2/rNk1m0GA8HKddvTjyGw/XqXa+LSTlDYkqI8OwR8GEYj4efEtcRpRYBxV8KxAW93YDWzFGvruKnnLbDAF6VR5w/cCMn5hzGCAZowggGWAgEBMIGUMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbQIBADAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDcwODI5MDMyNjExWjAjBgkqhkiG9w0BCQQxFgQUFcAEoXVkNQqmb7Dx3Htz7+AccEcwDQYJKoZIhvcNAQEBBQAEgYAsc18izZga46hGipu+C9xiR89ucTahC2T1vL8XJa1dqKxg0ii0c75dWJ29/baxATr3VNiQ7KES6d55M4q9cGFzm1lvJjDybVhIjahiED0PygiOqM/B/reCPb79y0DZ07AJaDf0RESyX+SsplTVq3bWFw5VtMryECZkZe8BkF6q4Q==-----END PKCS7-----">
202
+</form>
203
+
204
+<a name="thanksto"></a>
205
+<h3>Thanks To</h3>
206
+
207
+<ul>
208
+<li>DeHackEd, author of PHPBTTracker</li>
209
+<li>Bram Cohen, author of BitTorrent</li>
210
+<li>Everyone on #bittorrent who answered my questions</li>
211
+<li>The Tango Desktop Project for the excellent icons</li>
212
+<li>All the testers who reported bugs and gave suggestions</li>
213
+</ul>
214
+
215
+</body>
216
+</html>
0 217
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+This is for Apache users to utilize the given .htaccess file in RivetTracker.
2
+
3
+[1] Make sure you have the mod_rewrite module enabled.
4
+[2] For /local/path/to/rivettracker, change this to your absolute local path
5
+    to your RivetTracker install.
6
+    [a] Unix servers: /local/path/to/rivettracker
7
+    [b] Windows servers: <drive letter>:\local\path\to\rivettracker
8
+
9
+
10
+For Apache 2.0.x and 2.2.x installs, put this in your httpd.conf file:
11
+
12
+<Directory "/local/path/to/rivettracker">
13
+Options -Indexes +FollowSymLinks
14
+RewriteEngine On
15
+AllowOverride All
16
+Order allow,deny
17
+Allow from all
18
+</Directory>
19
+
20
+
21
+For Apache 2.4.x installs, put this in your httpd.conf file:
22
+
23
+<Directory "/local/path/to/rivettracker">
24
+Options -Indexes +FollowSymLinks
25
+RewriteEngine On
26
+AllowOverride All
27
+Require all granted
28
+</Directory>
29
+
30
+
31
+You could also change AllowOverride None to AllowOverride All in the main
32
+httpd.conf and uncomment the first two lines in the htaccess file, but that
33
+also searches for .htaccess in all other subdirectories as well.
34
+
35
+
36
+For nginx users, it turns out to be a bit different. Read this:
37
+http://wiki.nginx.org/HttpRewriteModule
0 38
\ No newline at end of file
1 39
new file mode 100644
2 40
Binary files /dev/null and b/docs/imgs/1.gif differ
3 41
new file mode 100644
4 42
Binary files /dev/null and b/docs/imgs/2.gif differ
5 43
new file mode 100644
6 44
Binary files /dev/null and b/docs/imgs/3.gif differ
7 45
new file mode 100644
8 46
Binary files /dev/null and b/docs/imgs/4.gif differ
9 47
new file mode 100644
10 48
Binary files /dev/null and b/docs/imgs/5.gif differ
11 49
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+<?php
2
+
3
+header("Location: ../index.php");
4
+
5
+?>
0 6
\ No newline at end of file
1 7
new file mode 100644
... ...
@@ -0,0 +1,252 @@
1
+Welcome to my BitTorrent Tracker written in PHP.
2
+
3
+Highlights:
4
++ Provides the same functionality as the offical tracker
5
++ Runs using MySQL as a database backend
6
++ Built-in statistics collection with sample summary script
7
++ Customiztion is pretty easy to implement
8
+
9
+Pitfalls
10
+- PHP has some limitations, so this tracker is not optimal.
11
+
12
+This is my first PHP project, and I'm rather happy with the
13
+result.
14
+
15
+UPGRADING
16
+---------
17
+
18
+If you are upgrading from a previous version, then you may be in trouble.
19
+The database structure was slightly modified to accomidate a change in the
20
+latest MySQL. The word "hash" became a keyword, and cannot be used as a
21
+column name. Furthermore, the addition of the "speed" code requires
22
+table additions and a new table entirely.
23
+
24
+The script upgrade.php is provided to carry out these modifications. You do
25
+not need to run it if you are installing from scratch, and if only needs
26
+to be done once regardless. Also, running it will not cause any problems
27
+even if you have the latest version of the database.
28
+
29
+
30
+** New in version 1.5: Peer caching. If you want to use this feature,
31
+you must execute the makecache.php script to generate the tables from
32
+your current database.
33
+
34
+
35
+INSTALLATION
36
+------------
37
+
38
+Requirements:
39
+- Working PHP environment (ideally Apache with PHP built-in or
40
+  working via module)
41
+- Working MySQL server
42
+
43
+
44
+Upload tracker.php, funcsv2.php, newtorrents.php, BDecode.php, BEncode.php
45
+ and install.php to the web site which will be hosting the tracker. Uploading 
46
+index.php is recommended if you want a home page for the tracker. Feel free
47
+to re-theme it.
48
+
49
+Access the install.php script from your web browser. It will
50
+guide you through the creation of the SQL database. All you need
51
+is the database's username and password. You may want to let your
52
+webmaster run through this phase.
53
+
54
+If install.php has write access to the installation directory, it will
55
+write its own config.php file with the database configuration and some
56
+default settings. If install.php cannot do this, you must modify
57
+config-sample.php yourself and upload it to the same directory as
58
+tracker.php and rename it to config.php.
59
+
60
+*************************
61
+************************* Set up config.php !!!
62
+
63
+There are two variables named $upload_username and $upload_password.
64
+These are the values that will be used by the newtorrents.php script
65
+to authorize submission of new torrents. You must set these, or your
66
+tracker will not accept new files, making it rather useless.
67
+
68
+
69
+
70
+OTHER FILES
71
+-----------
72
+
73
+The tracker package also includes some other scripts. Here is a list and a
74
+description of what they do.
75
+
76
+- DumpTorrentCGI.php
77
+ Originally intended as a demo of the BEncode library, but it became popular
78
+ pretty quickly. This script allows users to upload a .torrent file to the
79
+ server (or specify a URL to download) and the script will decode it and
80
+ display the file's contents to the user in a (hopefully) friendly manner.
81
+ It also supports other bencoded data, such as /announce and /scrape data,
82
+ although it is not reliable enough to do /scrape due to a strange quirk
83
+ in PHP.
84
+- BEncode.php
85
+ Used by DumpTorrentCGI.php and newtorrents.php to make bencoded data
86
+ streams. The primary reason for doing this is calculating info_hash values.
87
+- BDecode.php
88
+ The decoding compliment to BEncode.php
89
+- sanity.php
90
+ When run, this script will do some simple consistency checks on the
91
+ tracker's summary page and will forcibly expire peers who have not reported
92
+ in within double the configured re-announce interval. If it doesn't seem to
93
+ work, try running it as sanity.php?nolock=on
94
+- sha1lib.php
95
+ An SHA1 implementation entirely in PHP. It's not perfect and it's slow, but
96
+ in a pinch, it works fine. Ignored if PHP version is at least 4.3.0 or if
97
+ the mhash extension is installed.
98
+
99
+
100
+The rest is documentation and other text documents.
101
+
102
+FILE RENAMING AND MOVING
103
+------------------------
104
+All PHP files will function properly if renamed, except
105
+funcsv2.php and config.php. Renaming these files require
106
+modifying most other .php files.
107
+
108
+
109
+USAGE
110
+-----
111
+Create your torrent files as usual. Specify the url to 
112
+tracker.php (or its new name if you renamed it) as the announce
113
+URL.
114
+
115
+***********************************
116
+If you want /scrape functionality, target announce.php
117
+instead of tracker.php.
118
+***********************************
119
+
120
+Call up the newtorrents.php URL. Specify all the data you want to
121
+show up on the statistics page. You must specify at least the
122
+username, password, and either upload the .torrent or copy the
123
+info_hash into the indicated field.
124
+
125
+The checkbox, when checked (defaults to yes) will cause the script
126
+to fill in the file's name and a short description. The description is
127
+the file's size (roughly calculated) and the comment field if present
128
+in the torrent file.
129
+
130
+*New: a PHP implemention of the SHA1 algorithm is included. All users
131
+can upload directly to the newtorrents.php script now. Note however
132
+that is may produce wrong hashes and generally run slowly.
133
+
134
+
135
+DELETING TORRENTS
136
+-----------------
137
+The script deleter.php allows you to delete torrents from the database.
138
+The username and password are NOT the same as newtorrnets.php uses.
139
+Use the login and password that the SQL database itself uses. Of course,
140
+there's nothing preventing you from making these identical.
141
+
142
+Be warned: there is no confirmation of deletion and a torrent
143
+need not be abandoned to be erased. Changes take effect immediately.
144
+
145
+
146
+
147
+TORRENTSPY COMPATABILITY (and other /scrape functions)
148
+------------------------
149
+Starting with version 1.5, since an official statement has
150
+been made on /scrape conventions, announce.php and scrape.php
151
+are provided. announce.php simply executes tracker.php,
152
+while scrape.php causes tracker.php to output scrape data.
153
+
154
+The old style of using http://www.site.com/tracker.php/announce
155
+is still included (in fact, this is how scrape.php works) but
156
+is now discouraged since this convention caused more problems
157
+than it ever really should have.
158
+
159
+Any program not capable of figuring out the scrape.php script
160
+name from announce.php is broken and needs to be fixed.
161
+
162
+
163
+
164
+STATISTIC COLLECTING (or, "Database Structure")
165
+--------------------
166
+
167
+I tried to make the database information as easy to understand
168
+as possible. "SELECT * FROM summary" should provide you with
169
+all the programming information you need, but here is a brief
170
+rundown of what the fields mean.
171
+
172
+Summary:
173
+	*info_hash - The 40 character hex representation of
174
+	 the file. It is unique to every torrent.
175
+
176
+	*dlbytes - The approximate sum of all the bytes downloaded
177
+	 by everyone.
178
+
179
+	*seeds - The number of connected users who have the
180
+	 whole file and are uploading.
181
+
182
+	*leechers - The number of connected users who are still
183
+	 downloading the file.
184
+
185
+	*finished - The number of users who have fully downloaded
186
+	 the file. Use this as a measure of how many people
187
+	 have the file.
188
+
189
+	*lastcycle - Used by the trash collector to decide if
190
+	 it should try to purge users who have timed out.
191
+
192
+	*lastSpeedCycle - Used by the speec calculator to decide
193
+	 if the speed should be updated.
194
+
195
+	*speed - in bytes per second. Consider it to be extremely
196
+	rough.
197
+
198
+Namemap:
199
+  Note that all fields (except hash) are optional and may be "" (but not NULL,
200
+  those are annoying). A torrent need not have an entry here at all.
201
+  This is used only by the index.php script.
202
+	*info_hash - The file's unique 40 character hash.
203
+
204
+	*filename - The file that this torrent represents
205
+
206
+	*url - A link to where the .torrent file may be grabbed.
207
+
208
+	*info - A short text description added after the previous
209
+	 information is shown. Default is the file size.
210
+
211
+timestamps:
212
+  Used by the speed calculator to contain the sliding window average
213
+  download rate. This is of little interest to external users, so 
214
+  I'll skip it.
215
+
216
+x<hexadecimal string>:
217
+  Each torrent's user list is stored in a table whose name is the
218
+  info_hash of the torrent prefixed by an x.  
219
+  
220
+	*peer_id - A 40 character hash that is unique to each client
221
+
222
+	*bytes - The number of bytes this peer still needs to download
223
+	 to have the complete file. Seeders have this set to 0.
224
+
225
+	*ip - The client's IP address
226
+
227
+	*port - The port the client is listening on (usually 6881)
228
+
229
+	*status - Either "seeder" or "leecher" (see above). It's a bit
230
+	 redundent right now since "bytes==0" is the same as a seeder	 
231
+
232
+	*lastupdate - Unix time of when the client last reported in.
233
+	 Clients whose time is 2 * report_interval will be deleted.
234
+
235
+y<hexadecimal string>:
236
+  The couterpart to the "x" table, only with the peer caching data.
237
+  I won't describe it here.
238
+
239
+
240
+CREDITS
241
+-------
242
+
243
+People besides me who deserve credit.
244
+
245
+Bram Cohen - Author of BT, and really patient guy.
246
+KktoMx     - Figured out the "stripslashes" problem.
247
+bideomex   - Found the dumb thing I did with stripslashes.
248
+Gottaname  - First real load test.
249
+"daan" (?) - SHA1 in PHP code. See http://www.php.net/manual/en/function.sha1.php
250
+             user comments.
251
+Bak4San    - Provider of torrents with ten thousand peers. On a weekly
252
+             basis.
0 253
new file mode 100644
... ...
@@ -0,0 +1,107 @@
1
+                   HTTP-BASED SEEDING SPECIFICATION
2
+                   ================================
3
+
4
+This specification is for John Hoffman's and DeHackEd's proposed
5
+extension to the BitTorrent metadata format, and for an alternate
6
+protocol for retrieving torrent data from a web server.  This
7
+extension is not official as of this writing.
8
+
9
+
10
+METADATA EXTENSION:
11
+
12
+* "httpseeds"
13
+
14
+In the main area of the metadata file and not part of the "info"
15
+section, will be a new key, "httpseeds".  This key will refer to a
16
+list of URLs, and will contain a list of web addresses where torrent
17
+data can be retrieved.  This key may be safely ignored if the client
18
+is not capable of using it.
19
+
20
+* examples.
21
+
22
+d['httpseeds'] = [ 'http://www.whatever.com/seed.php' ]
23
+  This specifies the client can retrieve data by accessing the given
24
+  URL with the parameters supplied in the protocol specification
25
+  below.
26
+
27
+d['httpseeds'] = [ 'http://www.site1.com/source1.php',
28
+                   'http://www.site2.com/source2.php'  ]
29
+  More than one URL may be specified; if so, the client will attempt
30
+  to access both URLs to download seed data.
31
+
32
+
33
+PROTOCOL:
34
+
35
+The client calls the URL given, in the following format:
36
+<url>?info_hash=[hash]&piece=[piece]{&ranges=[start]-[end]{,[start]-[end]}...}
37
+
38
+Examples:
39
+http://www.whatever.com/seed.php?info_hash=%9C%D9i%8A%F5Uu%1A%91%86%AE%06lW%EA%21W%235%E0&piece=3
40
+http://www.whatever.com/seed.php?info_hash=%9C%D9i%8A%F5Uu%1A%91%86%AE%06lW%EA%21W%235%E0&piece=8&ranges=49152-131071,180224-262143
41
+
42
+The URL would be for a script which has access to the files
43
+contained in the torrent, and to the metadata (.torrent) file
44
+itself, so that it may calculate what byte ranges to pull from
45
+what files.  One such script has been written by DeHackEd, and
46
+is available at http://bt.degreez.net .
47
+
48
+The script should return, if everything is okay, either a status
49
+of 200 (OK) and a block of data (either the entire piece if no
50
+ranges were given, or the ranges of data requested for that piece
51
+appended together), in binary format, or 503 (Service Temporarily
52
+Unavailable), with the body of the return being an ASCII integer
53
+value specifying how long the client should wait before retrying.
54
+The client should consider any other return code as an error.
55
+In the case of an error, the client should retry, but should
56
+retry less often if the failure to contact the seed continues.
57
+
58
+
59
+* server-side implementation notes.
60
+
61
+The purpose of the http seed script is to limit access to the
62
+data being downloaded so that the web server isn't overwhelmed
63
+by clients asking for the data.  If it weren't for this limiting,
64
+there would be no way to prevent someone from coding a client
65
+to try to download continuously or multiply, resulting in a
66
+heavy load on the server.  Limiting the download rate also
67
+allows an http seed script to be run on a web account where
68
+the total amount of data downloaded is restricted or may result
69
+in extra service charges.
70
+
71
+The script must provide three major functions:
72
+
73
+1. Limit its average upload to a reasonable level. 
74
+
75
+2. Intelligently tell peers how long they should wait before
76
+   retrying.
77
+
78
+3. translate from an info-hash and piece number to a byte range
79
+   within a file or set of files, and return those bytes.
80
+
81
+Another highly desirable function is to check whether peers are
82
+retrying too often, and to automatically ban those peers.
83
+
84
+Other desirable features include a way of monitoring the tracker
85
+the torrent is using and to stop uploading data if sufficient
86
+P2P seeds exist, and a way to feed back to the tracker to show
87
+a seed is present.
88
+
89
+
90
+
91
+* client-side implementation notes.
92
+
93
+The prototype code base has a default retry time of 30 seconds;
94
+after 3 retries with errors, the time is lengthened with each
95
+cycle.
96
+
97
+The prototype code will not display any errors with contacting
98
+http seeds (unless the URL given in the .torrent is incorrect)
99
+until it has received data from that seed.  (The prototype code
100
+also won't display any errors for any http reply that was
101
+actually received.)
102
+
103
+Current behavior is:  Request the rarest piece you're missing
104
+in entirety that you can locate.  If you have no pieces that
105
+aren't partially downloaded, skip one retry cycle, then start
106
+requesting partials.  If you receive a 503 response, set the
107
+retry time equal to the integer value received in the response.
0 108
\ No newline at end of file
1 109
new file mode 100644
... ...
@@ -0,0 +1,126 @@
1
+<?php
2
+require ("config.php");
3
+require_once ("funcsv2.php");
4
+//Check session
5
+session_start();
6
+
7
+if (!$_SESSION['admin_logged_in'])
8
+{
9
+	//check fails
10
+	header("Location: authenticate.php?status=session");
11
+	exit();
12
+}
13
+?>
14
+
15
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
16
+
17
+<html>
18
+<head>
19
+	<title>Edit Torrent in Database</title>
20
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
21
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
22
+</head>
23
+<body>
24
+<h1>Edit Torrent in Database</h1>
25
+<h2>This page allows you to edit torrents that are already in the database.  If you need to change other things about
26
+the torrent please <a href="deleter.php">delete it</a> and add it again.</h2>
27
+	
28
+<?php
29
+
30
+//connect to database
31
+if ($GLOBALS["persist"])
32
+	$db = mysql_pconnect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
33
+else
34
+	$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
35
+mysql_select_db($database) or die(errorMessage() . "Error selecting database.</p>");
36
+
37
+//get filename from URL string
38
+if (isset($_GET['filename'])) {
39
+	$filename = htmlentities($_GET['filename']);
40
+}
41
+
42
+//if not edit database or filename set, display all torrents as links
43
+if (!isset($_POST["editdatabase"]) && !isset($filename))
44
+{
45
+	?>
46
+	<p><strong>Click on a file to edit it:</strong></p>
47
+	<table border="0">
48
+	<?php
49
+	if ($GLOBALS["customtitle"] == "true")
50
+	$query = "SELECT title, filename FROM ".$prefix."namemap ORDER BY title ASC";	
51
+	else $query = "SELECT filename FROM ".$prefix."namemap ORDER BY filename ASC";
52
+	$rows = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
53
+	
54
+	while ($data = mysql_fetch_row($rows))
55
+	{
56
+		if ($GLOBALS["customtitle"] == "true")
57
+		echo "<tr><td><a href=\"" . htmlentities($_SERVER['PHP_SELF']) . "?filename=" . rawurlencode($data[1]) . "\">" . $data[0] . "</a></td></tr>\n";
58
+		else echo "<tr><td><a href=\"" . htmlentities($_SERVER['PHP_SELF']) . "?filename=" . rawurlencode($data[0]) . "\">" . $data[0] . "</a></td></tr>\n";
59
+	}
60
+	?>
61
+	</table>
62
+	<?php
63
+}
64
+
65
+if (isset($filename) && !isset($_POST["editdatabase"]))
66
+{
67
+	$query = "SELECT info_hash,title,filename,url,pubDate FROM ".$prefix."namemap WHERE filename = '" . mysql_real_escape_string($filename) . "'";
68
+	$rows = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
69
+	
70
+	$data = mysql_fetch_row($rows); //should be only one entry...
71
+	?>
72
+	<form action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>" method="POST">
73
+	<input type="hidden" name="editdatabase" value="1">
74
+	<input type="hidden" name="<?php echo $data[0];?>" value="<?php echo $data[0];?>">
75
+	<input type="hidden" name="<?php echo $data[0] . "_old_filename";?>" value="<?php echo $data[2];?>">
76
+	<table border="0">
77
+	<tr><td><b>Info Hash: </b></td><td><?php echo $data[0];?></td></tr>
78
+	<tr><td><b>Title:</b></td><td><input type="text" name="<?php echo $data[0] . "_title";?>" size="60" value="<?php echo $data[1];?>"></td></tr>
79
+	<tr><td><b>Filename:</b></td><td><input type="text" name="<?php echo $data[0] . "_filename";?>" size="60" value="<?php echo $data[2];?>"></td></tr>
80
+	<tr><td><b>URL:</b></td><td><input type="text" name="<?php echo $data[0] . "_url";?>" size="60" value="<?php echo $data[3];?>"></td></tr>
81
+	<tr><td><b>Publication Date:</b></td><td><input type="text" name="<?php echo $data[0] . "_pubDate";?>" size="60" value="<?php echo $data[4];?>"></td></tr>
82
+	<tr><td><hr></td><td><hr></td></tr>		
83
+	
84
+	</table>
85
+	<br>
86
+	<input type="submit" value="Edit Entry">
87
+	</form>
88
+	
89
+	<?php
90
+}
91
+
92
+//write data to database
93
+if (isset($_POST["editdatabase"]))
94
+{
95
+	$temp_counter = (count($_POST)-1)/5;
96
+	array_shift($_POST);
97
+	
98
+	for ($i = 0; $i < $temp_counter; $i++)
99
+	{
100
+		$temp_hash = htmlspecialchars(array_shift($_POST));
101
+		$old_filename = htmlspecialchars(array_shift($_POST));
102
+		$temp_title = htmlspecialchars(array_shift($_POST));
103
+		$temp_filename = array_shift($_POST);
104
+		$temp_filename = Ltrim($temp_filename);
105
+		$temp_filename = htmlspecialchars(rtrim($temp_filename));
106
+		$temp_url = htmlspecialchars(array_shift($_POST));
107
+		$temp_pubDate = htmlspecialchars(array_shift($_POST));
108
+		$query = "UPDATE ".$prefix."namemap SET title=\"$temp_title\", filename=\"$temp_filename\", url=\"$temp_url\", pubDate=\"$temp_pubDate\" WHERE info_hash=\"$temp_hash\"";
109
+		mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
110
+		//if filename changes, rename .torrent
111
+		if ($old_filename != $temp_filename)
112
+			rename("torrents/" . $old_filename . ".torrent", "torrents/" . $temp_filename . ".torrent");
113
+	}
114
+	
115
+	//run RSS generator
116
+	require_once("rss_generator.php");
117
+	
118
+	echo "<br><p class=\"success\">The database was edited successfully!</p>\n";
119
+}
120
+
121
+?>
122
+<br>
123
+<br>
124
+<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Return to Admin Page</a>
125
+</body>
126
+</html>
0 127
new file mode 100644
... ...
@@ -0,0 +1,548 @@
1
+<?php
2
+require ("config.php");
3
+require_once ("funcsv2.php");
4
+//Check session
5
+session_start();
6
+
7
+if (!$_SESSION['admin_logged_in'])
8
+{
9
+	//check fails
10
+	header("Location: authenticate.php?status=session");
11
+	exit();
12
+}
13
+?>
14
+
15
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
16
+<html><head><title>Edit Config File</title>
17
+	<meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
18
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
19
+</head><body>
20
+
21
+<?php
22
+//open up config file and display for editing
23
+if (!isset($_POST["saveconfig"]))
24
+{
25
+	?>
26
+	<h1>Edit Config File</h1>
27
+	<form action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>" method="POST">
28
+	<input type="hidden" name="saveconfig" value="1">
29
+	<h2>This page allows you to configure the "config.php" settings.  This file stores all the necessary
30
+	settings for your tracker.  Please do NOT edit the "config.php" file directly, 
31
+	use this admin page for any changes.</h2>
32
+	<h2><span class="notice">*</span> - required value</h2>
33
+	<table border="1" cellpadding="3">
34
+	<?php
35
+	//open up config file
36
+	$fr = fopen("config.php", "r") or die(errorMessage() . "Error: couldn't read config.php!</p>");
37
+	$temp = fgets($fr);
38
+	$temp = fgets($fr);
39
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
40
+	?>
41
+	<tr><td>Make tracker hidden: This will require a login by either the admin or upload user in order to
42
+	see the torrents available on the main statistics page.  This does not mean it's a private tracker.  If you
43
+	need a private tracker, there are many other trackers out there.  Also, you will need to secure the "torrents"
44
+	folder with an .htaccess file for Apache or some other method.  The tracker will still accept all valid
45
+	connections by clients.  There is no user checking in that regard.</td>
46
+	<td><input type="checkbox" value="<?php if($temp == "true") echo "on"; else echo "off"?>" name="hiddentracker"<?php if ($temp == "true") echo " checked";?>></td></tr>
47
+	<?php
48
+	$temp = fgets($fr);
49
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
50
+	?>
51
+	<tr><td>Enable or disable scraping by clients.  Generally it is safe to leave this on unless
52
+	you have a large number of torrents or users which can lead to increased bandwidth usage.  Also, scraping
53
+	can possibily be used maliciously by abusive clients.</td>
54
+	<td><input type="checkbox" value="<?php if($temp == "true") echo "on"; else echo "off"?>" name="scrape"<?php if ($temp == "true") echo " checked";?>></td></tr>
55
+	<?php
56
+	$temp = fgets($fr);
57
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
58
+	?>
59
+	<tr><td>Displays custom titles on the main torrent statistics page instead of the filename. This is because the uploader script will auto-rename your uploaded filename to exactly what you specified initally or by automatically using the data from the uploaded torrent. Check this if you want the titles to be different from the filename.</td>
60
+	<td><input type="checkbox" value="<?php if($temp == "true") echo "on"; else echo "off"?>" name="customtitle"<?php if ($temp == "true") echo " checked";?>></td></tr>
61
+	<?php
62
+	$temp = fgets($fr);
63
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
64
+	?>
65
+	<tr><td>Short Announce URL: You can turn on the short announce feature, making the URL end in /announce for your tracker. You should not utilize both tracker URL forms in one torrent at the same time, or you will get inconsistent results. Note: You will need the provided htaccess file, have URL rewrite capabilities, and have it properly set up to use this feature. Otherwise, leave it disabled.</td>
66
+	<td><select name="announceurl" id="announceurl">
67
+	<option title="disabled" value="announce.php"<?php if($temp == "announce.php") echo " selected=\"selected\"";?>>disabled</option>
68
+	<option title="enabled" value="announce"<?php if($temp == "announce") echo " selected=\"selected\"";?>>enabled</option>
69
+	</select>
70
+	</td>
71
+	</tr>
72
+	<?php
73
+	$temp = fgets($fr);
74
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
75
+	?>
76
+	<tr><td><span class="notice">*</span> Lists the number of torrents on each page on your torrent tracker list. Default is 10.</td>
77
+	<td><input type="text" name="indexpagelimitspecify" size="40" value="<?php echo $temp;?>"></td></tr>
78
+	<?php
79
+	$temp = fgets($fr);
80
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
81
+	?>
82
+	<tr><td><span class="notice">*</span> Lists the number of torrents on each page on the detailed statistics page. Default is 5.</td>
83
+	<td><input type="text" name="statspagelimitspecify" size="40" value="<?php echo $temp;?>"></td></tr>
84
+	<?php
85
+	$temp = fgets($fr);
86
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
87
+	?>
88
+	<tr><td><span class="notice">*</span> Maximum reannounce interval (in seconds) 1800 == 30 minutes</td>
89
+	<td><input type="text" name="report_interval" size="40" value="<?php echo $temp;?>"></td></tr>
90
+	<?php
91
+	$temp = fgets($fr);
92
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
93
+	?>
94
+	<tr><td><span class="notice">*</span> Minimum reannounce interval (also in seconds) 300 == 5 minutes</td>
95
+	<td><input type="text" name="min_interval" size="40" value="<?php echo $temp;?>"></td></tr>
96
+	<?php
97
+	$temp = fgets($fr);
98
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
99
+	?>
100
+	<tr><td><span class="notice">*</span> Number of peers to send in one request.  Some logic will break if you set this to more than 300,
101
+	so please don't do that. 100 is the most you should set anyway.</td>
102
+	<td><input type="text" name="maxpeers" size="40" value="<?php echo $temp;?>"></td></tr>
103
+	<?php
104
+	$temp = fgets($fr);
105
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
106
+	?>	
107
+	<tr><td>If set, NAT checking will be performed.
108
+	This may cause trouble with some providers, so it's
109
+	off by default.</td>
110
+	<td><input type="checkbox" value="<?php if($temp == "true") echo "on"; else echo "off"?>" name="NAT"<?php if ($temp == "true") echo " checked";?>></td></tr>
111
+	<?php
112
+	$temp = fgets($fr);
113
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
114
+	?>
115
+	<tr><td>Persistent MySQL connections:
116
+	Check with your webmaster to see if you're allowed to use these.
117
+	Highly recommended, especially for higher loads, but generally
118
+	not allowed unless it's a dedicated machine.</td>
119
+	<td><input type="checkbox" value="<?php if($temp == "true") echo "on"; else echo "off"?>" name="persist"<?php if ($temp == "true") echo " checked";?>></td></tr>
120
+	<?php
121
+	$temp = fgets($fr);
122
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
123
+	?>
124
+	<tr><td>Allow users to override ip address.
125
+	Enable this if you know people have a legit reason to use
126
+	this function. Leave disabled otherwise.</td>
127
+	<td><input type="checkbox" value="<?php if($temp == "true") echo "on"; else echo "off"?>" name="ip_override"<?php if ($temp == "true") echo " checked";?>></td></tr>
128
+	<?php
129
+	$temp = fgets($fr);
130
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
131
+	?>
132
+	<tr><td>For heavily loaded trackers, uncheck this. It will stop count the number
133
+	of downloaded bytes and the speed of the torrent, but will significantly reduce
134
+	the load.</td>
135
+	<td><input type="checkbox" value="<?php if($temp == "true") echo "on"; else echo "off"?>" name="countbytes"<?php if ($temp == "true") echo " checked";?>></td></tr>
136
+	<?php
137
+	$temp = fgets($fr);
138
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
139
+	?>
140
+	<tr><td><span class="notice">*</span> Username for individual who can add torrents to tracker database.
141
+	This user is only able to create, and not delete torrents to the tracker.
142
+	For full privileges, see the admin user.</td>
143
+	<td><input type="text" name="upload_username" size="40" value="<?php echo $temp;?>"></td></tr>
144
+	<?php
145
+	$temp = fgets($fr);
146
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
147
+	?>
148
+	<tr><td><span class="notice">*</span> Password for individual who can add torrents to tracker database.
149
+	Again, this user is only able to create, and not delete torrents to the tracker.
150
+	For full privileges, see the admin user.<br><br>
151
+	<input type="hidden" name="old_upload_password" value="<?php echo $temp;?>">
152
+	<b>Current MD5 hashed username+password: <?php echo $temp;?></b></td>
153
+	<td><input type="password" name="upload_password" size="40" value=""></td></tr>
154
+	<?php
155
+	$temp = fgets($fr);
156
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
157
+	?>
158
+	<tr><td><span class="notice">*</span> Admin username. The admin is able to go to the admin page and show detailed 
159
+	information about the tracker as well as access a few other important tools.
160
+	The admin is also able to upload torrents to the database
161
+	just like the previous account.</td>
162
+	<td><input type="text" name="admin_username" size="40" value="<?php echo $temp;?>"></td></tr>
163
+	<?php
164
+	$temp = fgets($fr);
165
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
166
+	?>
167
+	<tr><td><span class="notice">*</span> Password for admin.  Again, The admin is able to go to the admin page and show detailed 
168
+	information about the tracker as well as access a few other important tools.
169
+	The admin is also able to upload torrents to the database.<br><br>
170
+	<input type="hidden" name="old_admin_password" value="<?php echo $temp;?>">
171
+	<b>Current MD5 hashed username+password: <?php echo $temp;?></b></td>
172
+	<td><input type="password" name="admin_password" size="40" value=""></td></tr>
173
+	<?php
174
+	$temp = fgets($fr);
175
+	$temp = clean(substr($temp, strpos($temp, "=")+3, -3));
176
+	?>
177
+	<tr><td>Title on index.php statistics page, if not set, defaults to "Tracker Statistics"</td>
178
+	<td><input type="text" name="title" size="40" value="<?php echo $temp;?>"></td></tr>
179
+	<?php
180
+	$temp = fgets($fr);
181
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
182
+	?>
183
+	<tr><td><span class="notice">*</span> Database Hostname: This is the MySQL database hostname, if it is the local machine, it should
184
+	be set to localhost.</td>
185
+	<td><input type="text" name="dbhost" size="40" value="<?php echo $temp;?>"></td></tr>
186
+	<?php
187
+	$temp = fgets($fr);
188
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
189
+	?>
190
+	<tr><td><span class="notice">*</span> Database Username: This is the user who has access to the database table.  If you are unsure,
191
+	check with your system administrator.</td>
192
+	<td><input type="text" name="dbuser" size="40" value="<?php echo $temp;?>"></td></tr>
193
+	<?php
194
+	$temp = fgets($fr);
195
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
196
+	?>
197
+	<tr><td><span class="notice">*</span> Database Password: This is the password for the user who has access to the database table.
198
+	If you are unsure, check with your system administrator.</td>
199
+	<td><input type="text" name="dbpass" size="40" value="<?php echo $temp;?>"></td></tr>
200
+	<?php
201
+	$temp = fgets($fr);
202
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
203
+	?>
204
+	<tr><td><span class="notice">*</span> Database name: This is the name of the database.  If you are unsure, check with
205
+	your system administrator.</td>
206
+	<td><input type="text" name="database" size="40" value="<?php echo $temp;?>"></td></tr>
207
+	<?php
208
+	$temp = fgets($fr);
209
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
210
+	?>
211
+	<tr><td>Enable RSS feed:
212
+	If you do not want the RSS feed to be created for privacy reasons or do not need it disable this checkbox.</td>
213
+	<td><input type="checkbox" value="<?php if($temp == "true") echo "on"; else echo "off"?>" name="enablerss"<?php if ($temp == "true") echo " checked";?>></td></tr>
214
+	<?php
215
+	$temp = fgets($fr);
216
+	$temp = clean(substr($temp, strpos($temp, "=")+3, -3));
217
+	?>
218
+	<tr><td>RSS Title: In the rss.xml file, this is the main <pre>&lt;title&gt;</pre> tag.</td>
219
+	<td><input type="text" name="rss_title" size="40" value="<?php echo $temp;?>"></td></tr>
220
+	<?php
221
+	$temp = fgets($fr);
222
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
223
+	?>
224
+	<tr><td>RSS link to main website: In the rss.xml file, this is the main <pre>&lt;link&gt;</pre> tag.</td>
225
+	<td><input type="text" name="rss_link" size="40" value="<?php echo $temp;?>"></td></tr>
226
+	<?php
227
+	$temp = fgets($fr);
228
+	$temp = clean(substr($temp, strpos($temp, "=")+3, -3));
229
+	?>
230
+	<tr><td>RSS description: In the rss.xml file, this is the main <pre>&lt;description&gt;</pre> tag.</td>
231
+	<td><input type="text" name="rss_description" size="60" value="<?php echo $temp;?>"></td></tr>
232
+	<?php
233
+	$temp = fgets($fr);
234
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
235
+	?>
236
+	<tr><td><span class="notice">*</span> Main website url that the tracker runs on, example: http://www.mywebsite.com</td>
237
+	<td><input type="text" name="website_url" size="40" value="<?php echo $temp;?>"></td></tr>
238
+	<?php
239
+	$temp = fgets($fr);
240
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
241
+	?>
242
+	<tr><td><span class="notice">*</span> For HTTP seeding, this is the maximum total upload rate per second in kilobytes, for example 100 would be 100 KB/s</td>
243
+	<td><input type="text" name="max_upload_rate" size="40" value="<?php echo $temp;?>"></td></tr>
244
+	<?php
245
+	$temp = fgets($fr);
246
+	$temp = substr($temp, strpos($temp, "=")+2, -2);
247
+	?>
248
+	<tr><td><span class="notice">*</span> For HTTP seeding, this is the maximum number of uploads to run at a time</td>
249
+	<td><input type="text" name="max_uploads" size="40" value="<?php echo $temp;?>"></td></tr>
250
+	<?php
251
+	$temp = fgets($fr);
252
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
253
+	?>
254
+	<tr><td><span class="notice">*</span> Date format of the torrent publication date. It shows on statistics.php. If you change this setting, you will have to change it for every other existing torrent!</td>
255
+	<td>
256
+	<select name="dateformat" id="dateformat">
257
+	<option title="Mon, 4 Jan, 1999 01:15:40 PM" value="D, j M, Y h:i:s A"<?php if($temp == "D, j M, Y h:i:s A") echo " selected=\"selected\"";?>>Mon, 4 Jan, 1999 01:15:40 PM</option>
258
+	<option title="Monday, 4 Jan, 1999 01:15:40 PM" value="l, j M, Y h:i:s A"<?php if($temp == "l, j M, Y h:i:s A") echo " selected=\"selected\"";?>>Monday, 4 Jan, 1999 01:15:40 PM</option>
259
+	<option title="Mon, 4 January, 1999 01:15:40 PM" value="D, j F, Y h:i:s A"<?php if($temp == "D, j F, Y h:i:s A") echo " selected=\"selected\"";?>>Mon, 4 January, 1999 01:15:40 PM</option>
260
+	<option title="Monday, 4 January, 1999 01:15:40 PM" value="l, j M, Y h:i:s A"<?php if($temp == "l, j F, Y h:i:s A") echo " selected=\"selected\"";?>>Monday, 4 January, 1999 01:15:40 PM</option>
261
+	<option title="Mon, 4 Jan, 1999 13:15:40" value="D, j M, Y H:i:s"<?php if($temp == "D, j M, Y H:i:s") echo " selected=\"selected\"";?>>Mon, 4 Jan, 1999 13:15:40</option>
262
+	<option title="Monday, 4 Jan, 1999 13:15:40" value="l, j M, Y H:i:s"<?php if($temp == "l, j M, Y H:i:s") echo " selected=\"selected\"";?>>Monday, 4 Jan, 1999 13:15:40</option>
263
+	<option title="Mon, 4 January, 1999 13:15:40" value="D, j F, Y H:i:s"<?php if($temp == "D, j F, Y H:i:s") echo " selected=\"selected\"";?>>Mon, January 4, 1999 13:15:40</option>
264
+	<option title="Monday, 4 January, 1999 13:15:40" value="l, j F, Y H:i:s"<?php if($temp == "l, j F, Y H:i:s") echo " selected=\"selected\"";?>>Monday, 4 January, 1999 13:15:40</option>
265
+	<option title="Mon, Jan 4, 1999 01:15:40 PM" value="D, M j, Y h:i:s A"<?php if($temp == "D, M j, Y h:i:s A") echo " selected=\"selected\"";?>>Mon, Jan 4, 1999 01:15:40 PM</option>
266
+	<option title="Monday, Jan 4, 1999 01:15:40 PM" value="l, M j, Y h:i:s A"<?php if($temp == "l, M j, Y h:i:s A") echo " selected=\"selected\"";?>>Monday, Jan 4, 1999 01:15:40 PM</option>
267
+	<option title="Mon, January 4, 1999 01:15:40 PM" value="D, F j, Y h:i:s A"<?php if($temp == "D, F j, Y h:i:s A") echo " selected=\"selected\"";?>>Mon, January 4, 1999 01:15:40 PM</option>
268
+	<option title="Monday, January 4, 1999 01:15:40 PM" value="l, F j, Y h:i:s A"<?php if($temp == "l, F j, Y h:i:s A") echo " selected=\"selected\"";?>>Monday, January 4, 1999 01:15:40 PM</option>
269
+	<option title="Mon, Jan 4, 1999 13:15:40" value="D, M j, Y H:i:s"<?php if($temp == "D, M j, Y H:i:s") echo " selected=\"selected\"";?>>Mon, Jan 4, 1999 13:15:40</option>
270
+	<option title="Monday, Jan 4, 1999 13:15:40" value="l, M j, Y H:i:s"<?php if($temp == "l, M j, Y H:i:s") echo " selected=\"selected\"";?>>Monday, Jan 4, 1999 13:15:40</option>
271
+	<option title="Mon, January 4, 1999 13:15:40" value="D, F j, Y H:i:s"<?php if($temp == "D, F j, Y H:i:s") echo " selected=\"selected\"";?>>Mon, January 4, 1999 13:15:40</option>
272
+	<option title="Monday, January 4, 1999 13:15:40" value="l, F j, Y H:i:s"<?php if($temp == "l, F j, Y H:i:s") echo " selected=\"selected\"";?>>Monday, January 4, 1999 13:15:40</option>
273
+	</select>
274
+	</td>
275
+	</tr>
276
+	<?php
277
+	$temp = fgets($fr);
278
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
279
+	?>
280
+	<tr><td><span class="notice">*</span> Timezone that the server runs on</td>
281
+	<td>
282
+	<select name="timezone" id="timezone">
283
+	<option title="[UTC - 12] Baker Island Time" value="-1200"<?php if($temp == "-1200") echo " selected=\"selected\"";?>>[UTC - 12] Baker Island Time</option>
284
+	<option title="[UTC - 11] Niue Time, Samoa Standard Time" value="-1100"<?php if($temp == "-1100") echo " selected=\"selected\"";?>>[UTC - 11] Niue Time, Samoa Standard Time</option>
285
+	<option title="[UTC - 10] Hawaii-Aleutian Standard Time, Cook Island Time" value="-1000"<?php if($temp == "-1000") echo " selected=\"selected\"";?>>[UTC - 10] Hawaii-Aleutian Standard Time, Cook Isl...</option>
286
+	<option title="[UTC - 9:30] Marquesas Islands Time" value="-0930"<?php if($temp == "-0930") echo " selected=\"selected\"";?>>[UTC - 9:30] Marquesas Islands Time</option>
287
+	<option title="[UTC - 9] Alaska Standard Time, Gambier Island Time" value="-0900"<?php if($temp == "-0900") echo " selected=\"selected\"";?>>[UTC - 9] Alaska Standard Time, Gambier Island Tim...</option>
288
+	<option title="[UTC - 8] Pacific Standard Time" value="-0800"<?php if($temp == "-0800") echo " selected=\"selected\"";?>>[UTC - 8] Pacific Standard Time</option>
289
+	<option title="[UTC - 7] Mountain Standard Time" value="-0700"<?php if($temp == "-0700") echo " selected=\"selected\"";?>>[UTC - 7] Mountain Standard Time</option>
290
+	<option title="[UTC - 6] Central Standard Time" value="-0600"<?php if($temp == "-0600") echo " selected=\"selected\"";?>>[UTC - 6] Central Standard Time</option>
291
+	<option title="[UTC - 5] Eastern Standard Time" value="-0500"<?php if($temp == "-0500") echo " selected=\"selected\"";?>>[UTC - 5] Eastern Standard Time</option>
292
+	<option title="[UTC - 4] Atlantic Standard Time" value="-0400"<?php if($temp == "-0400") echo " selected=\"selected\"";?>>[UTC - 4] Atlantic Standard Time</option>
293
+	<option title="[UTC - 3:30] Newfoundland Standard Time" value="-0330"<?php if($temp == "-0330") echo " selected=\"selected\"";?>>[UTC - 3:30] Newfoundland Standard Time</option>
294
+	<option title="[UTC - 3] Amazon Standard Time, Central Greenland Time" value="-0300"<?php if($temp == "-0300") echo " selected=\"selected\"";?>>[UTC - 3] Amazon Standard Time, Central Greenland ...</option>
295
+	<option title="[UTC - 2] Fernando de Noronha Time, South Georgia &amp; the South Sandwich Islands Time" value="-0200"<?php if($temp == "-0200") echo " selected=\"selected\"";?>>[UTC - 2] Fernando de Noronha Time, South Georgia ...</option>
296
+	<option title="[UTC - 1] Azores Standard Time, Cape Verde Time, Eastern Greenland Time" value="-0100"<?php if($temp == "-0100") echo " selected=\"selected\"";?>>[UTC - 1] Azores Standard Time, Cape Verde Time, E...</option>
297
+	<option title="[UTC] Western European Time, Greenwich Mean Time" value="+0000"<?php if($temp == "+0000") echo " selected=\"selected\"";?>>[UTC] Western European Time, Greenwich Mean Time</option>
298
+	<option title="[UTC + 1] Central European Time, West African Time" value="+0100"<?php if($temp == "+0100") echo " selected=\"selected\"";?>>[UTC + 1] Central European Time, West African Time</option>
299
+	<option title="[UTC + 2] Eastern European Time, Central African Time" value="+0200"<?php if($temp == "+0200") echo " selected=\"selected\"";?>>[UTC + 2] Eastern European Time, Central African T...</option>
300
+	<option title="[UTC + 3] Moscow Standard Time, Eastern African Time" value="+0300"<?php if($temp == "+0300") echo " selected=\"selected\"";?>>[UTC + 3] Moscow Standard Time, Eastern African Ti...</option>
301
+	<option title="[UTC + 3:30] Iran Standard Time" value="+0330"<?php if($temp == "+0330") echo " selected=\"selected\"";?>>[UTC + 3:30] Iran Standard Time</option>
302
+	<option title="[UTC + 4] Gulf Standard Time, Samara Standard Time" value="+0400"<?php if($temp == "+0400") echo " selected=\"selected\"";?>>[UTC + 4] Gulf Standard Time, Samara Standard Time</option>
303
+	<option title="[UTC + 4:30] Afghanistan Time" value="+0430"<?php if($temp == "+0430") echo " selected=\"selected\"";?>>[UTC + 4:30] Afghanistan Time</option>
304
+	<option title="[UTC + 5] Pakistan Standard Time, Yekaterinburg Standard Time" value="+0500"<?php if($temp == "+0500") echo " selected=\"selected\"";?>>[UTC + 5] Pakistan Standard Time, Yekaterinburg St...</option>
305
+	<option title="[UTC + 5:30] Indian Standard Time, Sri Lanka Time" value="+0530"<?php if($temp == "+0530") echo " selected=\"selected\"";?>>[UTC + 5:30] Indian Standard Time, Sri Lanka Time</option>
306
+	<option title="[UTC + 6] Bangladesh Time, Bhutan Time, Novosibirsk Standard Time" value="+0600"<?php if($temp == "+0600") echo " selected=\"selected\"";?>>[UTC + 6] Bangladesh Time, Bhutan Time, Novosibirs...</option>
307
+	<option title="[UTC + 6:30] Cocos Islands Time, Myanmar Time" value="+0630"<?php if($temp == "+0630") echo " selected=\"selected\"";?>>[UTC + 6:30] Cocos Islands Time, Myanmar Time</option>
308
+	<option title="[UTC + 7] Indochina Time, Krasnoyarsk Standard Time" value="+0700"<?php if($temp == "+0700") echo " selected=\"selected\"";?>>[UTC + 7] Indochina Time, Krasnoyarsk Standard Tim...</option>
309
+	<option title="[UTC + 8] Chinese Standard Time, Australian Western Standard Time, Irkutsk Standard Time" value="+0800"<?php if($temp == "+0800") echo " selected=\"selected\"";?>>[UTC + 8] Chinese Standard Time, Australian Wester...</option>
310
+	<option title="[UTC + 9] Japan Standard Time, Korea Standard Time, Chita Standard Time" value="+0900"<?php if($temp == "+0900") echo " selected=\"selected\"";?>>[UTC + 9] Japan Standard Time, Korea Standard Time...</option>
311
+	<option title="[UTC + 9:30] Australian Central Standard Time" value="+0930"<?php if($temp == "+0930") echo " selected=\"selected\"";?>>[UTC + 9:30] Australian Central Standard Time</option>
312
+	<option title="[UTC + 10] Australian Eastern Standard Time, Vladivostok Standard Time" value="+1000"<?php if($temp == "+1000") echo " selected=\"selected\"";?>>[UTC + 10] Australian Eastern Standard Time, Vladi...</option>
313
+	<option title="[UTC + 10:30] Lord Howe Standard Time" value="+1030"<?php if($temp == "+1030") echo " selected=\"selected\"";?>>[UTC + 10:30] Lord Howe Standard Time</option>
314
+	<option title="[UTC + 11] Solomon Island Time, Magadan Standard Time" value="+1100"<?php if($temp == "+1100") echo " selected=\"selected\"";?>>[UTC + 11] Solomon Island Time, Magadan Standard T...</option>
315
+	<option title="[UTC + 11:30] Norfolk Island Time" value="+1130"<?php if($temp == "+1130") echo " selected=\"selected\"";?>>[UTC + 11:30] Norfolk Island Time</option>
316
+	<option title="[UTC + 12] New Zealand Time, Fiji Time, Kamchatka Standard Time" value="+1200"<?php if($temp == "+1200") echo " selected=\"selected\"";?>>[UTC + 12] New Zealand Time, Fiji Time, Kamchatka ...</option>
317
+	<option title="[UTC + 13] Tonga Time, Phoenix Islands Time" value="+1300"<?php if($temp == "+1300") echo " selected=\"selected\"";?>>[UTC + 13] Tonga Time, Phoenix Islands Time</option>
318
+	<option title="[UTC + 14] Line Island Time" value="+1400"<?php if($temp == "+1400") echo " selected=\"selected\"";?>>[UTC + 14] Line Island Time</option>
319
+	</select>
320
+	</td>
321
+	</tr>
322
+	<?php
323
+	
324
+	//get MySQL table prefix, store in hidden form field
325
+	$temp = fgets($fr);
326
+	$temp = substr($temp, strpos($temp, "=")+3, -3);
327
+	?>
328
+	<input type="hidden" name="prefix" value="<?php echo $temp;?>" />	
329
+
330
+	<?php
331
+	fclose($fr);
332
+
333
+	?>		
334
+	</table>
335
+	<input type="submit" value="Save Config">
336
+	</form>
337
+	
338
+	<?php
339
+}
340
+
341
+
342
+if (isset($_POST["saveconfig"]))
343
+{
344
+	//check required entries for values, if blank: error out
345
+	if ($_POST["announceurl"] == "")
346
+	{
347
+		echo errorMessage() . "Error: The announce URL is blank.</p>";
348
+		exit();
349
+	}
350
+	if (!is_numeric($_POST["indexpagelimitspecify"]) || $_POST["indexpagelimitspecify"] == "" || $_POST["indexpagelimitspecify"] <= 0)
351
+	{
352
+		echo errorMessage() . "Error: The index page limit is not an integer, a negative number, or is blank.</p>";
353
+		exit();
354
+	}	
355
+	if (!is_numeric($_POST["statspagelimitspecify"]) || $_POST["statspagelimitspecify"] == "" || $_POST["statspagelimitspecify"] <= 0)
356
+	{
357
+		echo errorMessage() . "Error: The statistics page limit is not an integer, a negative number, or is blank.</p>";
358
+		exit();
359
+	}
360
+	if (!is_numeric($_POST["report_interval"]) || $_POST["report_interval"] == "" || $_POST["report_interval"] <= 0)
361
+	{
362
+		echo errorMessage() . "Error: The maximum reannounce interval is not an integer, a negative number, or is blank.</p>";
363
+		exit();
364
+	}
365
+	if (!is_numeric($_POST["min_interval"]) || $_POST["min_interval"] == "" || $_POST["min_interval"] <= 0)
366
+	{
367
+		echo errorMessage() . "Error: The minimum reannounce interval is not an integer, a negative number, or is blank.</p>";
368
+		exit();
369
+	}
370
+	if (!is_numeric($_POST["maxpeers"]) || $_POST["maxpeers"] == "" || $_POST["maxpeers"] > 300 || $_POST["maxpeers"] <= 0)
371
+	{
372
+		echo errorMessage() . "Error: The number of peers to send in one request is not an integer, over 300, a negative number, zero, or blank.</p>";
373
+		exit();
374
+	}
375
+	if ($_POST["upload_username"] == "")
376
+	{
377
+		echo errorMessage() . "Error: The upload username is blank.</p>";
378
+		exit();
379
+	}
380
+	if ($_POST["admin_username"] == "")
381
+	{
382
+		echo errorMessage() . "Error: The admin username is blank.</p>";
383
+		exit();
384
+	}
385
+	if ($_POST["dbhost"] == "")
386
+	{
387
+		echo errorMessage() . "Error: The database hostname is blank.</p>";
388
+		exit();
389
+	}
390
+	if ($_POST["dbuser"] == "")
391
+	{
392
+		echo errorMessage() . "Error: The database username is blank.</p>";
393
+		exit();
394
+	}
395
+	if ($_POST["dbpass"] == "")
396
+	{
397
+		echo errorMessage() . "Error: The database password is blank.</p>";
398
+		exit();
399
+	}
400
+	if ($_POST["database"] == "")
401
+	{
402
+		echo errorMessage() . "Error: The database name is blank.</p>";
403
+		exit();
404
+	}
405
+	if ($_POST["rss_link"] != "" && Substr($_POST["rss_link"], 0, 7) != "http://")
406
+	{
407
+		echo errorMessage() . "Error: The RSS website URL does not start with http://</p>";
408
+		exit();
409
+	}
410
+	if ($_POST["website_url"] == "" || Substr($_POST["website_url"], 0, 7) != "http://")
411
+	{
412
+		echo errorMessage() . "Error: The website URL does not start with http:// or is blank.</p>";
413
+		exit();
414
+	}
415
+	if (!is_numeric($_POST["max_upload_rate"]) || $_POST["max_upload_rate"] == "" || $_POST["max_upload_rate"] <= 0)
416
+	{
417
+		echo errorMessage() . "Error: The maximum upload rate is not an integer, a negative number, or is blank.</p>";
418
+		exit();
419
+	}
420
+	if (!is_numeric($_POST["max_uploads"]) || $_POST["max_uploads"] == "" || $_POST["max_uploads"] <= 0)
421
+	{
422
+		echo errorMessage() . "Error: The maximum uploads is not an integer, a negative number, or is blank.</p>";
423
+		exit();
424
+	}
425
+	if ($_POST["dateformat"] == "")
426
+	{
427
+		echo errorMessage() . "Error: The date format is blank.</p>";
428
+		exit();
429
+	}
430
+	if ($_POST["timezone"] == "")
431
+	{
432
+		echo errorMessage() . "Error: The timezone is blank.</p>";
433
+		exit();
434
+	}
435
+	if ($_POST["upload_username"] == $_POST["admin_username"])
436
+	{
437
+		echo errorMessage() . "Error: The admin username cannot be the same as the upload username.</p>";
438
+		exit();
439
+	}
440
+	
441
+	//calculate new MD5 password if needed
442
+	if ($_POST["upload_password"] != "")
443
+	{
444
+		$_POST["upload_password"] = md5($_POST["upload_username"].$_POST["upload_password"]);
445
+	}
446
+	else
447
+		$_POST["upload_password"] = $_POST["old_upload_password"];
448
+	if ($_POST["admin_password"] != "")
449
+	{
450
+		$_POST["admin_password"] = md5($_POST["admin_username"].$_POST["admin_password"]);
451
+	}
452
+	else
453
+		$_POST["admin_password"] = $_POST["old_admin_password"];
454
+		
455
+	//check if config.php has write access
456
+	if (is_writable("config.php"))
457
+	{
458
+		//go through checkboxes and change "on" to "true"
459
+		if (isset($_POST["hiddentracker"]))
460
+			$hiddentracker = "true";
461
+		else
462
+			$hiddentracker = "false";
463
+		if (isset($_POST["enablerss"]))
464
+			$enablerss = "true";
465
+		else
466
+			$enablerss = "false";
467
+		if (isset($_POST["scrape"]))
468
+			$scrape = "true";
469
+		else
470
+			$scrape = "false";
471
+		if (isset($_POST["customtitle"]))
472
+			$customtitle = "true";
473
+		else
474
+			$customtitle = "false";
475
+		if (isset($_POST["NAT"]))
476
+			$NAT = "true";
477
+		else
478
+			$NAT = "false";
479
+		if (isset($_POST["persist"]))
480
+			$persist = "true";
481
+		else
482
+			$persist = "false";
483
+		if (isset($_POST["ip_override"]))
484
+			$ip_override = "true";
485
+		else
486
+			$ip_override = "false";
487
+		if (isset($_POST["countbytes"]))
488
+			$countbytes = "true";
489
+		else
490
+			$countbytes = "false";
491
+
492
+		//write config.php file
493
+		$fd = fopen("config.php", "w") or die(errorMessage() . "Warning: write to config.php!</p>");
494
+		fwrite($fd, 
495
+		"<?php //Please do NOT edit this file, use the admin page for changes.\n" .
496
+		"\$GLOBALS['hiddentracker'] = " . $hiddentracker . ";\n" .
497
+		"\$GLOBALS['scrape'] = " . $scrape . ";\n" .
498
+		"\$GLOBALS['customtitle'] = " . $customtitle . ";\n" .
499
+		"\$announceurl = '" . htmlspecialchars($_POST["announceurl"]) . "';\n" .
500
+		"\$GLOBALS['indexpagelimitspecify'] = " . htmlspecialchars($_POST["indexpagelimitspecify"]) . ";\n" .
501
+		"\$GLOBALS['statspagelimitspecify'] = " . htmlspecialchars($_POST["statspagelimitspecify"]) . ";\n" .
502
+		"\$GLOBALS['report_interval'] = " . htmlspecialchars($_POST["report_interval"]) . ";\n" .
503
+		"\$GLOBALS['min_interval'] = " . htmlspecialchars($_POST["min_interval"]) . ";\n" .
504
+		"\$GLOBALS['maxpeers'] = " . htmlspecialchars($_POST["maxpeers"]) . ";\n" .
505
+		"\$GLOBALS['NAT'] = " . $NAT . ";\n" .
506
+		"\$GLOBALS['persist'] = " . $persist . ";\n" .
507
+		"\$GLOBALS['ip_override'] = " . $ip_override . ";\n" .
508
+		"\$GLOBALS['countbytes'] = " . $countbytes . ";\n" .
509
+		"\$upload_username = '" . htmlspecialchars($_POST["upload_username"]) . "';\n" .
510
+		"\$upload_password = '" . htmlspecialchars($_POST["upload_password"]) . "';\n" .
511
+		"\$admin_username = '" . htmlspecialchars($_POST["admin_username"]) . "';\n" .
512
+		"\$admin_password = '" . htmlspecialchars($_POST["admin_password"]) . "';\n" .
513
+		"\$GLOBALS['title'] = '" . htmlspecialchars(addquotes($_POST["title"])) . "';\n" .
514
+		"\$dbhost = '" . htmlspecialchars($_POST["dbhost"]) . "';\n" .
515
+		"\$dbuser = '" . htmlspecialchars($_POST["dbuser"]) . "';\n" .
516
+		"\$dbpass = '" . htmlspecialchars($_POST["dbpass"]) . "';\n" .
517
+		"\$database = '" . htmlspecialchars($_POST["database"]) . "';\n" .
518
+		"\$enablerss = " . $enablerss . ";\n" .
519
+		"\$rss_title = '" . htmlspecialchars(addquotes($_POST["rss_title"])) . "';\n" .
520
+		"\$rss_link = '" . htmlspecialchars($_POST["rss_link"]) . "';\n" .
521
+		"\$rss_description = '" . htmlspecialchars(addquotes($_POST["rss_description"])) . "';\n" .
522
+		"\$website_url = '" . htmlspecialchars($_POST["website_url"]) . "';\n" .
523
+		"\$GLOBALS['max_upload_rate'] = " . htmlspecialchars($_POST['max_upload_rate']) . ";\n" .
524
+		"\$GLOBALS['max_uploads'] = " . htmlspecialchars($_POST['max_uploads']) . ";\n" .
525
+		"\$dateformat = '" . htmlspecialchars($_POST["dateformat"]) . "';\n" .
526
+		"\$timezone = '" . htmlspecialchars($_POST["timezone"]) . "';\n" .
527
+		"\$prefix = '" . htmlspecialchars($_POST["prefix"]) . "';\n" .
528
+		"?>"
529
+		);
530
+
531
+		fclose($fd);
532
+		echo "<br><p class=\"success\">config.php file was edited successfully!</p>\n";
533
+		
534
+		//run RSS generator
535
+		require_once("rss_generator.php");
536
+	}
537
+	else
538
+	{
539
+		echo errorMessage() . "config.php was not able to be written.  Please check the permissions and try again.</p>\n";
540
+	}
541
+}
542
+
543
+?>
544
+<br>
545
+<br>
546
+<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Return to Admin Page</a>
547
+</body>
548
+</html>
0 549
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
1 680
new file mode 100644
2 681
Binary files /dev/null and b/images/add.png differ
3 682
new file mode 100644
4 683
Binary files /dev/null and b/images/admin.png differ
5 684
new file mode 100644
6 685
Binary files /dev/null and b/images/batch_upload.png differ
7 686
new file mode 100644
8 687
Binary files /dev/null and b/images/check.png differ
9 688
new file mode 100644
10 689
Binary files /dev/null and b/images/color.png differ
11 690
new file mode 100644
12 691
Binary files /dev/null and b/images/database.png differ
13 692
new file mode 100644
14 693
Binary files /dev/null and b/images/delete.png differ
15 694
new file mode 100644
16 695
Binary files /dev/null and b/images/download.png differ
17 696
new file mode 100644
18 697
Binary files /dev/null and b/images/edit.png differ
19 698
new file mode 100644
20 699
Binary files /dev/null and b/images/help.png differ
21 700
new file mode 100644
22 701
Binary files /dev/null and b/images/important.png differ
23 702
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+<?php
2
+
3
+header("Location: ../index.php");
4
+
5
+?>
0 6
\ No newline at end of file
1 7
new file mode 100644
2 8
Binary files /dev/null and b/images/install.png differ
3 9
new file mode 100644
4 10
Binary files /dev/null and b/images/lock.png differ
5 11
new file mode 100644
6 12
Binary files /dev/null and b/images/logout.png differ
7 13
new file mode 100644
8 14
Binary files /dev/null and b/images/magnet-icon.gif differ
9 15
new file mode 100644
10 16
Binary files /dev/null and b/images/no.png differ
11 17
new file mode 100644
12 18
Binary files /dev/null and b/images/rss-logo.png differ
13 19
new file mode 100644
14 20
Binary files /dev/null and b/images/stats.png differ
15 21
new file mode 100644
16 22
Binary files /dev/null and b/images/torrent.png differ
17 23
new file mode 100644
18 24
Binary files /dev/null and b/images/userstats.png differ
19 25
new file mode 100644
20 26
Binary files /dev/null and b/images/yes.png differ
21 27
new file mode 100644
... ...
@@ -0,0 +1,424 @@
1
+<?php
2
+//if config.php file not available, error out
3
+if (!file_exists("config.php"))
4
+{
5
+	echo "<font color=red><strong>Error: config.php file is not available.  Did you forget to upload it?" .
6
+	" If you haven't run the installer yet, please do so <a href=\"install.php\">here.</a></strong></font>";
7
+	exit();
8
+}
9
+
10
+require_once ("config.php");
11
+require_once ("funcsv2.php");
12
+
13
+//Check session only if hiddentracker is TRUE
14
+if ($hiddentracker == true)
15
+{
16
+	session_start();
17
+	
18
+	if (!$_SESSION['admin_logged_in'] && !$_SESSION['upload_logged_in'])
19
+	{
20
+		//check fails
21
+		header("Location: authenticate.php?status=indexlogin");
22
+		exit();
23
+	}
24
+}
25
+?>
26
+
27
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
28
+
29
+<?php
30
+//variables for column totals
31
+$total_disk_usage = 0;
32
+$total_seeders = 0;
33
+$total_leechers = 0;
34
+$total_downloads = 0;
35
+$total_bytes_transferred = 0;
36
+$total_speed = 0;
37
+
38
+$scriptname = $_SERVER["PHP_SELF"] . "?";
39
+if (!isset($GLOBALS["countbytes"]))
40
+	$GLOBALS["countbytes"] = true;
41
+?>
42
+<html>
43
+<head>
44
+	<title><?php if ($GLOBALS["title"] != "") echo $GLOBALS["title"]; else echo "Tracker Statistics";?></title>
45
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
46
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
47
+	<?php
48
+	if ($enablerss == true)
49
+		echo "<link rel=\"alternate\" title=\"" . $rss_title . "\" href=\"rss/rss.xml\" type=\"application/rss+xml\">";
50
+	?>
51
+</head>
52
+<body>
53
+<?php
54
+//display total stats as header on page
55
+if ($GLOBALS["persist"])
56
+	$db = mysql_pconnect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
57
+else
58
+	$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
59
+mysql_select_db($database) or die(errorMessage() . "Tracker error: can't open database $database - " . mysql_error() . "</p>");
60
+
61
+$query = "SELECT SUM(".$prefix."namemap.size), SUM(".$prefix."summary.seeds), SUM(".$prefix."summary.leechers), SUM(".$prefix."summary.finished), SUM(".$prefix."summary.dlbytes), SUM(".$prefix."summary.speed) FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash";
62
+$results = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
63
+$data = mysql_fetch_row($results);
64
+?>
65
+
66
+<center>
67
+<table>
68
+<tr>
69
+<th class="subheader">Total Space Used</th>
70
+<th class="subheader">Seeders</th>
71
+<th class="subheader">Leechers</th>
72
+<th class="subheader">Completed D/Ls</th>
73
+<th class="subheader">Bytes Transferred</th>
74
+<th class="subheader">Speed (rough estimate)</th>
75
+</tr>
76
+<tr>
77
+<?php
78
+if ($data[0] != null) //if there are no torrents in database, don't show anything
79
+{
80
+	echo "<td align=\"center\">" . bytesToString($data[0]) . "</td>\n";
81
+	echo "<td align=\"center\">" . $data[1] . "</td>\n";
82
+	echo "<td align=\"center\">" . $data[2] . "</td>\n";
83
+	echo "<td align=\"center\">" . $data[3] . "</td>\n";
84
+	echo "<td align=\"center\">" . bytesToString($data[4]) . "</td>\n";
85
+	if ($GLOBALS["countbytes"]) //stop count bytes OFF, OK to do speed calculation
86
+	{
87
+		if ($data[5] > 2097152)
88
+			echo "<td align=\"center\">" . round($data[5] / 1048576, 2) . " MB/sec</td>\n";
89
+		else
90
+			echo "<td align=\"center\">" . round($data[5] / 1024, 2) . " KB/sec</td>\n";
91
+	}
92
+	else
93
+		echo "<td align=\"center\">No Info Available</td>\n";
94
+}
95
+?>
96
+</tr>
97
+</table>
98
+</center>
99
+<br>
100
+
101
+<h1><?php if ($GLOBALS["title"] != "") echo $GLOBALS["title"]; else echo "Tracker Statistics";?></h1>
102
+<table width="100%">
103
+<tr>
104
+<td width="25%">
105
+<?php
106
+//Display logout option if logged in
107
+if ($hiddentracker == true)
108
+{
109
+	echo "Hello, <i>" . $_SESSION["username"] . "</i><br>";
110
+	echo "<a href=\"authenticate.php?status=logout\"><img src=\"images/logout.png\" border=\"0\" class=\"icon\" alt=\"Logout\" title=\"Logout\" /></a><a href=\"authenticate.php?status=logout\">Logout</a>";
111
+}
112
+?>
113
+</td>
114
+<td align="center">
115
+<a href="newtorrents.php"><img src="images/add.png" border="0" class="icon" alt="Add Torrent" title="Add Torrent" /></a><a href="newtorrents.php">Add Torrent to Tracker Database</a>
116
+<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Admin Page</a>
117
+</td>
118
+<td align="right" width="25%">
119
+
120
+<?php
121
+if (file_exists("rss/rss.xml"))
122
+{
123
+	echo "<a href='rss/rss.xml'><img src='images/rss-logo.png' border='0' class='icon' alt='RSS 2.0 Feed' title='RSS 2.0 Feed' /></a><a href='rss/rss.xml'>RSS 2.0 Feed</a>";
124
+}
125
+?>
126
+</td>
127
+</tr>
128
+</table>
129
+
130
+
131
+<table>
132
+<tr>
133
+	<?php
134
+	//Cleanup page number to prevent XSS
135
+	if (isset($_GET["page_number"])) {
136
+		$_GET["page_number"] = htmlspecialchars($_GET["page_number"]);
137
+	} else {
138
+		$_GET["page_number"] = "";
139
+	}
140
+	$scriptname = htmlspecialchars($scriptname);
141
+	
142
+	if (!isset($_GET["activeonly"]))
143
+		$scriptname = $scriptname . "activeonly=	yes&amp;";
144
+	if (isset($_GET["seededonly"]) && !isset($_GET["activeonly"]))
145
+	{
146
+		$scriptname = $scriptname . "seededonly=yes&";
147
+		$_GET["page_number"] = 1;
148
+	}
149
+	if (isset($_GET["page_number"]))
150
+		$scriptname = $scriptname . "page_number=" . $_GET["page_number"] . "&amp;";
151
+		
152
+	if (isset($_GET["activeonly"]))
153
+		echo "<td><a href=\"$scriptname\">Show all torrents</a></td>\n";
154
+	else
155
+		echo "<td><a href=\"$scriptname\">Show only active torrents</a></td>\n";
156
+		
157
+	$scriptname = $_SERVER["PHP_SELF"] . "?";
158
+	$scriptname = htmlspecialchars($scriptname);
159
+	
160
+	if (!isset($_GET["seededonly"]))
161
+		$scriptname = $scriptname . "seededonly=yes&amp;";
162
+	if (isset($_GET["activeonly"]) && !isset($_GET["seededonly"]))
163
+	{
164
+		$scriptname = $scriptname . "activeonly=yes&";
165
+		$_GET["page_number"] = 1;
166
+	}
167
+	if (isset($_GET["page_number"]))
168
+		$scriptname = $scriptname . "page_number=" . $_GET["page_number"] . "&amp;";
169
+		
170
+	if (isset($_GET["seededonly"]))
171
+		echo "<td align=\"right\"><a href=\"$scriptname\">Show all torrents</a></td>\n";
172
+	else
173
+		echo "<td align=\"right\"><a href=\"$scriptname\">Show only seeded torrents</a></td>\n";
174
+		
175
+	$scriptname = $_SERVER["PHP_SELF"] . "?";
176
+	$scriptname = htmlspecialchars($scriptname);
177
+	
178
+	?>
179
+</tr>
180
+</table>
181
+
182
+<?php
183
+if ($GLOBALS["persist"])
184
+	$db = mysql_pconnect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
185
+else
186
+	$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
187
+mysql_select_db($database) or die(errorMessage() . "Tracker error: can't open database $database - " . mysql_error() . "</p>");
188
+
189
+if (isset($_GET["seededonly"]))
190
+	$where = " WHERE seeds > 0";
191
+else if (isset($_GET["activeonly"]))
192
+	$where = " WHERE leechers+seeds > 0";
193
+else
194
+	$where = " ";
195
+
196
+$query = "SELECT COUNT(*) FROM ".$prefix."summary $where";
197
+$results = mysql_query($query);
198
+$res = mysql_result($results,0,0);
199
+
200
+if (isset($_GET["activeonly"]))
201
+	$scriptname = $scriptname . "activeonly=yes&";
202
+if (isset($_GET["seededonly"]))
203
+	$scriptname = $scriptname . "seededonly=yes&";
204
+
205
+echo "<p align='center'>Page: \n";
206
+$count = 0;
207
+$page = 1;
208
+while($count < $res)
209
+{
210
+	if (isset($_GET["page_number"]) && $page == $_GET["page_number"])
211
+		echo "<b><a href=\"$scriptname" . "page_number=$page\">($page)</a></b>-\n";
212
+	else if (!isset($_GET["page_number"]) && $page == 1)
213
+		echo "<b><a href=\"$scriptname" . "page_number=$page\">($page)</a></b>-\n";
214
+	else
215
+		echo "<a href=\"$scriptname" . "page_number=$page\">$page</a>-\n";
216
+	$page++;
217
+	$count = $count + ($GLOBALS['indexpagelimitspecify']);
218
+}
219
+echo "</p>\n";
220
+?>
221
+
222
+<table>
223
+<tr>
224
+	<td>
225
+	<table class="torrentlist">
226
+
227
+	<!-- Column Headers -->
228
+	<tr>
229
+		<th>Name/Info Hash</th>
230
+		<th>Seeders</th>
231
+		<th>Leechers</th>
232
+		<th>Completed D/Ls</th>
233
+		<?php
234
+		// Bytes mode off? Ignore the columns
235
+		if ($GLOBALS["countbytes"])
236
+			echo '<th>Bytes Transferred</th><th>Speed (rough estimate)</th>';
237
+		?>
238
+	</tr>
239
+	
240
+<?php
241
+if ($GLOBALS["customtitle"] != "true")
242
+{
243
+	if (!isset($_GET["page_number"]))
244
+	$query = "SELECT ".$prefix."summary.info_hash, ".$prefix."summary.seeds, ".$prefix."summary.leechers, ".$prefix."summary.finished, ".$prefix."summary.dlbytes, ".$prefix."namemap.filename, ".$prefix."namemap.url, ".$prefix."namemap.size, ".$prefix."summary.speed FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash $where ORDER BY ".$prefix."namemap.filename LIMIT 0,${GLOBALS['indexpagelimitspecify']}";
245
+	else
246
+	{
247
+		if ($_GET["page_number"] <= 0) //account for possible negative number entry by user
248
+			$_GET["page_number"] = 1;
249
+		
250
+		$page_limit = ($_GET["page_number"] - 1) * ($GLOBALS['indexpagelimitspecify']);
251
+		$query = "SELECT ".$prefix."summary.info_hash, ".$prefix."summary.seeds, ".$prefix."summary.leechers, ".$prefix."summary.finished, ".$prefix."summary.dlbytes, ".$prefix."namemap.filename, ".$prefix."namemap.url, ".$prefix."namemap.size, ".$prefix."summary.speed FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash $where ORDER BY ".$prefix."namemap.filename LIMIT $page_limit,${GLOBALS['indexpagelimitspecify']}";
252
+	}
253
+}
254
+
255
+if ($GLOBALS["customtitle"] == "true")
256
+{
257
+	if (!isset($_GET["page_number"]))
258
+	$query = "SELECT ".$prefix."summary.info_hash, ".$prefix."summary.seeds, ".$prefix."summary.leechers, ".$prefix."summary.finished, ".$prefix."summary.dlbytes, ".$prefix."namemap.title, ".$prefix."namemap.url, ".$prefix."namemap.size, ".$prefix."summary.speed, ".$prefix."namemap.filename FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash $where ORDER BY ".$prefix."namemap.title LIMIT 0,${GLOBALS['indexpagelimitspecify']}";
259
+	else
260
+	{
261
+		if ($_GET["page_number"] <= 0) //account for possible negative number entry by user
262
+			$_GET["page_number"] = 1;
263
+		
264
+		$page_limit = ($_GET["page_number"] - 1) * ($GLOBALS["indexpagelimitspecify"]);
265
+		$query = "SELECT ".$prefix."summary.info_hash, ".$prefix."summary.seeds, ".$prefix."summary.leechers, ".$prefix."summary.finished, ".$prefix."summary.dlbytes, ".$prefix."namemap.title, ".$prefix."namemap.url, ".$prefix."namemap.size, ".$prefix."summary.speed, ".$prefix."namemap.filename  FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash $where ORDER BY ".$prefix."namemap.title LIMIT $page_limit,${GLOBALS['indexpagelimitspecify']}";
266
+	}
267
+}
268
+
269
+$results = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
270
+$i = 0;
271
+
272
+while ($data = mysql_fetch_row($results)) {
273
+	// NULLs are such a pain at times. isset($nullvar) == false
274
+	if (is_null($data[5]))
275
+		$data[5] = $data[0];
276
+	if (is_null($data[6]))
277
+	$data[6] = "";
278
+	if (is_null($data[7]))
279
+		$data[7] = "";
280
+	if (strlen($data[5]) == 0)
281
+		$data[5] = $data[0];
282
+	$myhash = $data[0];
283
+	$writeout = "row" . $i % 2;
284
+	echo "<tr class=\"$writeout\">\n";
285
+	echo "\t<td>";
286
+	echo "\t<table class=\"nopadding\" border=\"0\"><tr><td valign=\"top\" align=\"left\" width=\"10%\">\n";
287
+	echo "\t<form method='post' action='torrent_functions.php'>\n";
288
+	echo "\t<input type='hidden' name='hash' value='" . $data[0] . "'/>\n";
289
+	echo "\t<input type='submit' value=' + '/></form>\n";
290
+	echo "\t</td><td valign=\"top\" align=\"left\">\n";
291
+	if (strlen($data[6]) > 0)
292
+		echo "<a href=\"${data[6]}\">${data[5]}</a> - ";
293
+	else
294
+		echo $data[5] . " - ";
295
+
296
+if ($GLOBALS["customtitle"] == "true")
297
+{
298
+	if ($hiddentracker == true) //obscure direct link to torrent, use dltorrent.php script
299
+		echo "<a href=\"dltorrent.php?hash=" . $myhash . "\">  (Download Torrent)</a>";
300
+	else //just display ordinary direct link
301
+		echo "<a href=\"torrents/" . rawurlencode($data[9]) . ".torrent\">  (Download Torrent)</a>";
302
+}
303
+
304
+if ($GLOBALS["customtitle"] != "true")
305
+{
306
+	if ($hiddentracker == true) //obscure direct link to torrent, use dltorrent.php script
307
+		echo "<a href=\"dltorrent.php?hash=" . $myhash . "\">  (Download Torrent)</a>";
308
+	else //just display ordinary direct link
309
+		echo "<a href=\"torrents/" . rawurlencode($data[5]) . ".torrent\">  (Download Torrent)</a>";
310
+}
311
+
312
+	//Magnet link
313
+	echo "&nbsp;<a href='";
314
+		//https://en.wikipedia.org/wiki/Magnet_URI_scheme
315
+		//Base-32 encoded SHA1 hash sum
316
+		echo "magnet:?xt=urn:btih:".$data[0];
317
+		//Size in bytes
318
+		echo "&xl=".$data[7];
319
+		//name
320
+		if ($GLOBALS["customtitle"] == "true")
321
+		echo "&dn=".rawurlencode($data[9]);
322
+		else echo "&dn=".rawurlencode($data[5]);
323
+		//tracker url
324
+		echo "&tr=".$website_url . substr($_SERVER['PHP_SELF'], 0, -9) . $announceurl;
325
+	echo "'>(Magnet";
326
+	echo "<img src='images/magnet-icon.gif' border='0' class='icon' alt='Magnet Link' title='Magnet Link' />";
327
+	echo ")</a>";
328
+
329
+	echo "</td></tr>";
330
+
331
+
332
+	if (strlen($data[7]) > 0) //show file size
333
+	{
334
+		echo "<tr><td>&nbsp;</td><td>" . bytesToString($data[7]) . "</td>";
335
+		$total_disk_usage = $total_disk_usage + $data[7]; //total up file sizes
336
+	}
337
+	echo "</tr></table></td>\n";
338
+	for ($j=1; $j < 4; $j++) //show seeders, leechers, and completed downloads
339
+	{
340
+		echo "\t<td class=\"center\">$data[$j]</td>\n";
341
+		if ($j == 1) //add to total seeders
342
+			$total_seeders = $total_seeders + $data[1];
343
+		if ($j == 2) //add to total leechers
344
+			$total_leechers = $total_leechers + $data[2];
345
+		if ($j == 3) //add to completed downloads
346
+			$total_downloads = $total_downloads + $data[3];
347
+	}
348
+
349
+	if ($GLOBALS["countbytes"])
350
+	{
351
+		echo "\t<td class=\"center\">" . bytestoString($data[4]) . "</td>\n";
352
+		$total_bytes_transferred = $total_bytes_transferred + $data[4]; //add to total GB transferred
353
+
354
+		// The SPEED column calculations.
355
+		if ($data[8] <= 0)
356
+		{
357
+			$speed = "0";
358
+			$total_speed = $total_speed - $data[8]; //for total speed column
359
+		}
360
+		else if ($data[8] > 2097152)
361
+			$speed = round($data[8] / 1048576, 2) . " MB/sec";
362
+		else
363
+			$speed = round($data[8] / 1024, 2) . " KB/sec";
364
+		echo "\t<td class=\"center\">$speed</td>\n";
365
+		$total_speed = $total_speed + $data[8]; //add to total speed, in bytes
366
+	}
367
+	echo "</tr>\n";
368
+	$i++;
369
+}
370
+
371
+if ($i == 0)
372
+	echo "<tr class=\"row0\"><td style=\"text-align: center;\" colspan=\"6\">No torrents</td></tr>";
373
+
374
+//show totals in last row
375
+echo "<tr>";
376
+echo "<th>Space Used: " . bytesToString($total_disk_usage) . "</th>";
377
+echo "<th>" . $total_seeders . "</th>";
378
+echo "<th>" . $total_leechers . "</th>";
379
+echo "<th>" . $total_downloads . "</th>";
380
+if ($GLOBALS["countbytes"]) //stop count bytes variable
381
+{
382
+	echo "<th>" . bytestoString($total_bytes_transferred) . "</th>";
383
+	if ($total_speed > 2097152)
384
+		echo "<th>" . round($total_speed / 1048576, 2) . " MB/sec</th>";
385
+	else
386
+		echo "<th>" . round($total_speed / 1024, 2) . " KB/sec</th>";
387
+}
388
+
389
+?>
390
+	</tr></table></td></tr>
391
+<table>
392
+	<tr class="details">
393
+		<td align="left"><a href="http://www.rivetcode.com">RivetTracker</a>
394
+		<?php
395
+		require("version.php");
396
+		print($version);
397
+		?>
398
+		</td>
399
+		<td align="right">
400
+		<?php
401
+		if (file_exists("legalterms.txt"))
402
+			echo "<td align=\"right\"><a href=\"legalterms.txt\">Use Policy and Terms of Service</a>";
403
+		?>
404
+		</td>
405
+	</tr>
406
+</table>
407
+<a href="./docs/help.html"><img src="images/help.png" border="0" class="icon" alt="Help" title="Help" /></a><a href="./docs/help.html">Help</a>
408
+<h3>Notes</h3>
409
+<?php
410
+if ($GLOBALS["NAT"])
411
+	echo "<ul><li>This tracker does NAT checking when users connect. If you receive a probe to port 6881, it's probably this tracker.</li></ul>\n";
412
+else
413
+	echo "<ul><li>NAT checking has been disabled on this tracker.</li></ul>\n";
414
+
415
+echo "<ul><li>Even if there are no seeders, the download may still work because of HTTP seeding.</li></ul>\n";
416
+	
417
+if (rand(1, 10) == 1)
418
+{
419
+	//10% of the time, run sanity_no_output.php to prune database and keep users fresh
420
+	include("sanity_no_output.php");
421
+}
422
+
423
+?>
424
+</body></html>
0 425
new file mode 100644
... ...
@@ -0,0 +1,753 @@
1
+<?php
2
+require_once ("funcsv2.php");
3
+
4
+//check if config.php file already exists, if so, this could be an already existing installation
5
+if (file_exists("config.php"))
6
+{
7
+	echo "<font color=red><strong>The config.php file already exists.  This is an indication of an already existing installation" .
8
+	" of RivetTracker.  If you are sure you are installing for the first time, please try recopying the files/folders." .
9
+	" This is also a security feature to prevent malicious attempts to run the installer if you forgot to delete it." .
10
+	" This installer will now abort.</strong></font>";
11
+	exit();
12
+}
13
+
14
+if (isset($_POST["download"]))
15
+{
16
+	//download config.php using header()
17
+	header('content-type: application/octet-stream');
18
+	header("Content-Disposition: attachment; filename=\"config.php\"");
19
+
20
+	print "<?php //Please do NOT edit this file, use the admin page for changes.\n";
21
+	print "\$GLOBALS['hiddentracker'] = " . htmlspecialchars($_POST["hiddentracker"]) . ";\n";
22
+	print "\$GLOBALS['scrape'] = " . htmlspecialchars($_POST["scrape"]) . ";\n";
23
+	print "\$GLOBALS['customtitle'] = " . htmlspecialchars($_POST["customtitle"]) . ";\n";
24
+	print "\$announceurl = '" . htmlspecialchars($_POST["announceurl"]) . "';\n";
25
+	print "\$GLOBALS['indexpagelimitspecify'] = " . htmlspecialchars($_POST["indexpagelimitspecify"]) . ";\n";
26
+	print "\$GLOBALS['statspagelimitspecify'] = " . htmlspecialchars($_POST["statspagelimitspecify"]) . ";\n";
27
+	print "\$GLOBALS['report_interval'] = " . htmlspecialchars($_POST["report_interval"]) . ";\n";
28
+	print "\$GLOBALS['min_interval'] = " . htmlspecialchars($_POST["min_interval"]) . ";\n";
29
+	print "\$GLOBALS['maxpeers'] = " . htmlspecialchars($_POST["maxpeers"]) . ";\n";
30
+	print "\$GLOBALS['NAT'] = " . htmlspecialchars($_POST["NAT"]) . ";\n";
31
+	print "\$GLOBALS['persist'] = " . htmlspecialchars($_POST["persist"]) . ";\n";
32
+	print "\$GLOBALS['ip_override'] = " . htmlspecialchars($_POST["ip_override"]) . ";\n";
33
+	print "\$GLOBALS['countbytes'] = " . htmlspecialchars($_POST["countbytes"]) . ";\n";
34
+	print "\$upload_username = '" . htmlspecialchars($_POST["upload_username"]) . "';\n";
35
+	print "\$upload_password = '" . htmlspecialchars($_POST["upload_password"]) . "';\n";
36
+	print "\$admin_username = '" . htmlspecialchars($_POST["admin_username"]) . "';\n";
37
+	print "\$admin_password = '" . htmlspecialchars($_POST["admin_password"]) . "';\n";
38
+	print "\$GLOBALS['title'] = '" . htmlspecialchars(addquotes($_POST["title"])) . "';\n";
39
+	print "\$dbhost = '" . htmlspecialchars($_POST["dbhost"]) . "';\n";
40
+	print "\$dbuser = '" . htmlspecialchars($_POST["dbuser"]) . "';\n";
41
+	print "\$dbpass = '" . htmlspecialchars($_POST["dbpass"]) . "';\n";
42
+	print "\$database = '" . htmlspecialchars($_POST["database"]) . "';\n";
43
+	print "\$enablerss = " . htmlspecialchars($_POST['enablerss']) . ";\n";
44
+	print "\$rss_title = '" . htmlspecialchars(addquotes($_POST["rss_title"])) . "';\n";
45
+	print "\$rss_link = '" . htmlspecialchars($_POST["rss_link"]) . "';\n";
46
+	print "\$rss_description = '" . htmlspecialchars($_POST["rss_description"]) . "';\n";
47
+	print "\$website_url = '" . htmlspecialchars($_POST['website_url']) . "';\n";
48
+	print "\$GLOBALS['max_upload_rate'] = " . htmlspecialchars($_POST['max_upload_rate']) . ";\n";
49
+	print "\$GLOBALS['max_uploads'] = " . htmlspecialchars($_POST['max_uploads']) . ";\n";
50
+	print "\$dateformat = '" . htmlspecialchars($_POST['dateformat']) . "';\n";
51
+	print "\$timezone = '" . htmlspecialchars($_POST['timezone']) . "';\n";
52
+	print "\$prefix = '" . htmlspecialchars($_POST['prefix']) . "';\n";
53
+	print "?>";
54
+exit;
55
+}
56
+
57
+?>
58
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
59
+
60
+<html>
61
+<head>
62
+	<title>RivetTracker Installer</title>
63
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
64
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
65
+</head>
66
+<body>
67
+<p align="right"><a href="./docs/help.html"><img src="images/help.png" border="0" class="icon" alt="Help" title="Help" /></a><a href="./docs/help.html">Help</a></p>
68
+
69
+<?php
70
+
71
+	if (!isset($_POST["started"]))
72
+	{
73
+		?>
74
+		<center>
75
+		<h1>RivetTracker Installer</h1>
76
+		<img src="images/install.png" border="0" class="icon" alt="RivetTracker Installation" title="RivetTracker Installation" />
77
+		<br>
78
+		<br>
79
+		<br>
80
+		<h2>Check for PHP and MySQL</h2>
81
+		</center>
82
+		<form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>">
83
+		<input type="hidden" name="started" value="1">
84
+<?php
85
+
86
+echo <<<HTML
87
+<style>table {width: 650px; margin: auto;} th {background: transparent; border: none; align: center;} td.a {width: 225px; text-align: center;} td.c {width: 50px; height: 42px; margin: auto;}</style>
88
+HTML;
89
+
90
+// PHP Version
91
+$_GET['php_version'] = PHP_VERSION;
92
+	
93
+// Check 5.3
94
+if (version_compare(PHP_VERSION, '5.3.0', '>='))
95
+	{
96
+echo <<<HTML
97
+<font face="Verdana" size="3"><br><table><tr><th>PHP Version:</th></tr><tr><td class="a">{$_GET['php_version']}</td><td class="b">Your server supports PHP 5.3+.</td><td class="c"><img src="./images/yes.png" class="icon" alt="Supported" /></td></tr></table></font>
98
+HTML;
99
+	}
100
+	// Check 5.0
101
+	else if (version_compare(PHP_VERSION, '5.0.0', '>='))
102
+	{
103
+echo <<<HTML
104
+<font face="Verdana" size="3"><br><table><tr><th>PHP Version:</th></tr><tr><td class="a">{$_GET['php_version']}</td><td class="b">Your server supports PHP 5.0+. Update to PHP 5.3 or higher when possible. </td><td class="c"><img src="./images/yes.png" class="icon" alt="Supported" /></td></tr></font>
105
+HTML;
106
+	}
107
+	// Does not support PHP 5
108
+	else if (version_compare(PHP_VERSION, '4.4.9', '<='))
109
+	{
110
+echo <<<HTML
111
+<font face="Verdana" size="3"><br><table><tr><th>PHP Version:</th></tr><tr><td class="a">{$_GET['php_version']}</td><td class="b">Your server does not support PHP 5. You may have issues running this tracker.</td><td class="c">&nbsp;<img src="./images/no.png" alt="Not Supported" </tr></table></font>
112
+HTML;
113
+	}
114
+
115
+echo <<<HTML
116
+<br>
117
+HTML;
118
+
119
+//MySQL check
120
+if (class_exists('mysqli') OR function_exists('mysql_connect'))
121
+{
122
+echo <<<HTML
123
+<font face="Verdana" size="3"><table><tr><th>MySQL Support:</th></tr><tr><td class="a">Yes</td><td class="b">Your server supports MySQL.</td><td class="c"><img src="./images/yes.png" class="icon" alt="Supported" /></td></tr></table></font>
124
+HTML;
125
+	}
126
+	// No MySQL
127
+	else
128
+	{
129
+echo <<<HTML
130
+<font face="Verdana" size="3"><table><tr><th>MySQL Support:</tr></th><tr><td class="a">No</td><td class="b">Your server does not support MySQL.</td><td class="c">&nbsp;<img src="./images/no.png" alt="Not Supported" /></td></tr></table></font>
131
+HTML;
132
+	}
133
+
134
+echo ("<br><br>");
135
+		if (version_compare(PHP_VERSION, '5.0.0', '>=') && class_exists('mysqli') || version_compare(PHP_VERSION, '5.0.0', '>=') && function_exists('mysql_connect')) echo "<center><font face=\"Verdana\">Fully supported. You may continue.</font></center>";
136
+		else if (version_compare(PHP_VERSION, '5.0.0', '>=') && !class_exists('mysqli') || version_compare(PHP_VERSION, '5.0.0', '>=') && !function_exists('mysql_connect')) die ("<center><font face=\"Verdana\">Fully supported, but cannot connect to database. You may not continue.</font></center>");
137
+
138
+		if (version_compare(PHP_VERSION, '4.4.9', '<=') && class_exists('mysqli') || version_compare(PHP_VERSION, '4.4.9', '<=') && function_exists('mysql_connect')) echo "<center><font face=\"Verdana\">Not fully supported, but you may try.</font></center>";
139
+		else if (version_compare(PHP_VERSION, '4.4.9', '<=') && !class_exists('mysqli') || version_compare(PHP_VERSION, '4.4.9', '<=') && !function_exists('mysql_connect')) die("<center><font face=\"Verdana\">Not fully supported, also cannot connect to database. You may not continue.</font></center>");
140
+		?>
141
+		<br>
142
+		<br>
143
+		<center>
144
+		<input type="submit" name="checkpassed" value="Continue">
145
+		</form>
146
+		</center>
147
+		<br>
148
+		</body></html><?php exit;
149
+	}
150
+	if (isset($_POST["checkpassed"]))
151
+	{
152
+		?>
153
+		<center>
154
+		<h1>RivetTracker Installer</h1>
155
+		<img src="images/install.png" border="0" class="icon" alt="RivetTracker Installation" title="RivetTracker Installation" />
156
+		</center>
157
+		<br>
158
+		<br>
159
+		<form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>">
160
+		<input type="hidden" name="started" value="1">
161
+		<h2>The MySQL database needs to be prepared for the tracker. This script will help
162
+		you do that.</h2>
163
+		<h2>You have two choices:</h2>
164
+		<br>
165
+		<ul>
166
+		<li><h2>If you have a username, password, and database for the tracker already
167
+		created:</h2></li>
168
+		</ul>
169
+		<input type="submit" name="preexisting" value="Click Here">
170
+		<br>
171
+		<br>
172
+		<ul>
173
+		<li><h2>If you need to create the account and database, and you have the username and password
174
+		of a user who can create user accounts and databases:</h2></li>
175
+		</ul>
176
+		<input type="submit" name="makeaccount" value="Click Here">
177
+		</form>
178
+		<br>
179
+		</body></html><?php exit;
180
+	}
181
+	if (isset($_POST["preexisting"]))
182
+	{
183
+		?>
184
+		<form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>">
185
+		<input type="hidden" name="maketables" value="1">
186
+		<input type="hidden" name="started" value="1">
187
+		<h1>RivetTracker Installation</h1>
188
+		<center>
189
+		<img src="images/install.png" border="0" class="icon" alt="RivetTracker Installation" title="RivetTracker Installation" />
190
+		</center>
191
+		<br><br>
192
+		<table border=0 cellpadding=5>
193
+		<tr><td align="right">Database hostname:<br>(in MySQL format, example: localhost)</td><td align="left"><input type="text" name="host" value="localhost" size="40"></td></tr>
194
+		<tr><td align="right">Tracker's database username:</td><td align="left"><input type="text" name="username" size="40"></td></tr>
195
+		<tr><td align="right">Tracker's database password:</td><td align="left"><input type="password" name="password" size="40"></td></tr>
196
+		<tr><td align="right">Database name:</td><td align="left"><input type="text" name="database" size="40"></td></tr>
197
+		<tr><td align="right">Table Prefix:<br> (If you want to use an existing<br> database this will add the tables
198
+		in<br> with the specified prefix. If you<br> are unsure, leave this blank.)<br>e.g.: rt_</td><td align="left"><input type="text" name="prefix" size="40"></td></tr>
199
+		</table>
200
+		<br><br>
201
+		<center>
202
+		<input type="submit" value="Install">
203
+		</center>
204
+		<br>
205
+		</form></body></html><?php exit;
206
+
207
+	}
208
+	if (isset($_POST["makeaccount"]))
209
+	{
210
+		?>
211
+		<form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>">
212
+		<input type="hidden" name="domakeaccount" value="1">
213
+		<input type="hidden" name="started" value="1">
214
+		<h1>Tracker Installation</h1>
215
+		<center>
216
+		<img src="images/install.png" border="0" class="icon" alt="RivetTracker Installation" title="RivetTracker Installation" />
217
+		</center>
218
+		<br><br>
219
+		<table border=0 cellpadding=5>
220
+		<tr><td align="right">Username of database admin:</td><td align="left"><input type="text" name="adminname" size="40"></td></tr>
221
+		<tr><td align="right">Password of database admin:</td><td align="left"><input type="password" name="adminpass" size="40"></td></tr>
222
+		<tr><td align="right">Database hostname:<br>(in MySQL format, example: localhost)</td><td align="left"><input type="text" name="host" size="40" value="localhost"></td></tr>
223
+		<tr><td align="right">Create user for MySQL:<br>(make sure this user does not already exist)</td><td align="left"><input type="text" name="username" size="40"></td></tr>
224
+		<tr><td align="right">Password:</td><td align="left"><input type="password" name="password" size="40"></td></tr>
225
+		<tr><td align="right">Create database (name):</td><td align="left"><input type="text" name="database" size="40"></td></tr>
226
+		</table>
227
+		<br><br>
228
+		<center>		
229
+		<input type="submit" value="Install">
230
+		</center>
231
+		</form></body></html>
232
+		<?php exit;
233
+	}
234
+
235
+	if (isset($_POST["prefix"])) {
236
+		$prefix = $_POST["prefix"];
237
+	} else {
238
+		$prefix = "";
239
+	}
240
+
241
+	$makenamemap= 'CREATE TABLE ' . $prefix . 'namemap (info_hash char(40) NOT NULL default "", title varchar(250) NOT NULL default "", filename varchar(250) NOT NULL default "", url varchar(250) NOT NULL default "", size bigint(20) unsigned NOT NULL, pubDate varchar(50) NOT NULL default "", PRIMARY KEY(info_hash)) DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci ENGINE = innodb';
242
+	$makesummary = 'CREATE TABLE ' . $prefix . 'summary (info_hash char(40) NOT NULL default "", dlbytes bigint unsigned NOT NULL default 0, seeds int unsigned NOT NULL default 0, leechers int unsigned NOT NULL default 0, finished int unsigned NOT NULL default 0, lastcycle int unsigned NOT NULL default "0", lastSpeedCycle int unsigned NOT NULL DEFAULT "0", speed bigint unsigned NOT NULL default 0, piecelength int(11) NOT NULL default -1, numpieces int(11) NOT NULL default 0, PRIMARY KEY (info_hash)) DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci ENGINE = innodb';
243
+	$maketimestamps = 'CREATE TABLE ' . $prefix . 'timestamps (info_hash char(40) not null, sequence int unsigned not null auto_increment, bytes bigint unsigned not null, delta smallint unsigned not null, primary key(sequence), key sorting (info_hash)) DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci ENGINE = innodb';
244
+	$makespeedlimit = 'CREATE TABLE ' . $prefix . 'speedlimit (uploaded bigint(25) NOT NULL default 0, total_uploaded bigint(30) NOT NULL default 0, started bigint(25) NOT NULL default 0) DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci ENGINE = innodb';
245
+	$makewebseedfiles = 'CREATE TABLE ' . $prefix . 'webseedfiles (info_hash char(40) default NULL, filename char(250) NOT NULL default "", startpiece int(11) NOT NULL default 0, endpiece int(11) NOT NULL default 0, startpieceoffset int(11) NOT NULL default 0, fileorder int(11) NOT NULL default 0, UNIQUE KEY fileseq (info_hash,fileorder)) DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci ENGINE = innodb';
246
+	if (isset($_POST["maketables"]))
247
+	{
248
+		$username = $_POST["username"] or die(errorMessage() . "No username was given, please try again.</p>");
249
+		$password = $_POST["password"] or die(errorMessage() . "No username password was given, this is a huge security risk, please try again.</p>");
250
+		$database = $_POST["database"] or die(errorMessage() . "No database specified, please try again.</p>");
251
+		$hostname = $_POST["host"] or die(errorMessage() . "No database hostname specified, please try again.</p>");
252
+
253
+		$db = mysql_connect($hostname, $username, $password) or die(errorMessage() . "Can't connect to database: " . mysql_error() . "</p>"); 
254
+		mysql_select_db($database) or die(errorMessage() . "Can't select database: " . mysql_error() . "</p>");
255
+		mysql_query($makesummary) or die(errorMessage() . "Can't make the summary table: " . mysql_error() . "</p>");
256
+		mysql_query($makenamemap) or die(errorMessage() . "Can't make the namemap table: " . mysql_error() . "</p>");
257
+		mysql_query($maketimestamps) or die(errorMessage() . "Can't make the timestamps table: " . mysql_error() . "</p>");
258
+		mysql_query($makespeedlimit) or die(errorMessage() . "Can't make the speedlimit table: " . mysql_error() . "</p>");
259
+		mysql_query($makewebseedfiles) or die(errorMessage() . "Can't make the webseedfiles table: " . mysql_error() . "</p>");
260
+		mysql_query("INSERT INTO ".$prefix."speedlimit values (0,0,0)") or die(errorMessage() . "Can't insert zeros into speedlimit table: " . mysql_error() . "</p>");
261
+		echo "<p class=\"success\">Database was created successfully!</p><br><br>";
262
+	}
263
+
264
+	if (isset($_POST["domakeaccount"]))
265
+	{
266
+		$username = $_POST["username"] or die(errorMessage() . "No username was given, please try again.</p>");
267
+		$password = $_POST["password"] or die(errorMessage() . "No username password was given, this is a huge security risk, please try again.</p>");
268
+		$database = $_POST["database"] or die(errorMessage() . "No database specified, please try again.</p>");
269
+		$hostname = $_POST["host"] or die(errorMessage() . "No database hostname specified, please try again.</p>");
270
+
271
+		$dbadmin = $_POST["adminname"] or die(errorMessage() . "No admin username was given, please try again.</p>");
272
+		$dbpass = $_POST["adminpass"]; // No admin password, OK but huge security risk...
273
+		
274
+		// Escaping strings will be ignored for now.
275
+		$db = mysql_connect($hostname, $dbadmin, $dbpass) or die(errorMessage() . "Error connecting: " . mysql_error() . "</p>");
276
+		mysql_select_db("mysql") or die(errorMessage() . "Can't select db \"mysql\":" . mysql_error() . "</p>");
277
+
278
+		mysql_query("INSERT INTO user SET user=\"$username\", password=PASSWORD(\"$password\"), host=\"\"") or die(errorMessage() . "Can't make user: " . mysql_error() . "</p>");
279
+		mysql_query("INSERT INTO db SET Host=\"%\", db=\"$database\", user=\"$username\", select_priv='Y', Insert_priv='Y', Update_priv='Y', Delete_priv='Y', Create_priv='Y', Drop_priv='Y', Alter_priv='Y', index_priv='Y'") or die(errorMessage() . "Cannot insert into \"Db\": " . mysql_error() . "</p>");
280
+		mysql_query("CREATE DATABASE $database") or die(errorMessage() . "Can't make database: " . mysql_error() . "</p>");
281
+		
282
+		mysql_query("FLUSH PRIVILEGES") or die(errorMessage() . "Can't flush privileges: " . mysql_error() . "</p>");
283
+	
284
+		mysql_select_db($database) or die(errorMessage() . "Can't select database \"$database\":" . mysql_error() . "</p>");
285
+	
286
+		mysql_query($makesummary) or die(errorMessage() . "Can't make the summary table: " . mysql_error() . "</p>");
287
+		mysql_query($makenamemap) or die(errorMessage() . "Can't make the namemap table: " . mysql_error() . "</p>");
288
+		mysql_query($maketimestamps) or die(errorMessage() . "Can't make the timestamps table: " . mysql_error() . "</p>");
289
+		mysql_query($makespeedlimit) or die(errorMessage() . "Can't make the speedlimit table: " . mysql_error() . "</p>");
290
+		mysql_query($makewebseedfiles) or die(errorMessage() . "Can't make the webseedfiles table: " . mysql_error() . "</p>");
291
+		mysql_query("INSERT INTO ".$prefix."speedlimit values (0,0,0)") or die(errorMessage() . "Can't insert zeros into speedlimit table: " . mysql_error() . "</p>");
292
+		echo "<p class=\"success\">Database was created successfully!</p><br><br>";
293
+
294
+	}
295
+
296
+	if (isset($_POST["domakeaccount"]) || isset($_POST["maketables"]))
297
+	{
298
+		//have user set values for config.php
299
+		?>
300
+		<form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>">
301
+		<input type="hidden" name="config" value="1">
302
+		<input type="hidden" name="started" value="1">
303
+		<?php
304
+		echo "<input type=\"hidden\" name=\"dbhost\" value=\"" . $hostname . "\">\n";
305
+		echo "<input type=\"hidden\" name=\"dbuser\" value=\"" . $username . "\">\n";
306
+		echo "<input type=\"hidden\" name=\"dbpass\" value=\"" . $password . "\">\n";
307
+		echo "<input type=\"hidden\" name=\"database\" value=\"" . $database . "\">\n";
308
+		echo "<input type=\"hidden\" name=\"prefix\" value=\"" . $prefix . "\">\n";
309
+		?>
310
+		<h1>Create Configuration File</h1>
311
+		<br><br>
312
+		<h2>This last step allows you to configure the "config.php" file.  This file stores all the necessary
313
+		settings for your tracker.  You can edit these settings at a later time in the admin page if you need
314
+		to change them.  Please do NOT edit the "config.php" file directly, use the admin page for any changes.
315
+		It's usually pretty safe to leave most of the settings to the default unless you know what you're doing.</h2>
316
+		<h2><span class="notice">*</span> - required value</h2>
317
+		<table border=1 cellpadding=3>
318
+		
319
+		<tr><td>Make tracker hidden: This will require a login by either the admin or upload user in order to
320
+		see the torrents available on the main statistics page.  This does not mean it's a private tracker.  If you
321
+		need a private tracker, there are many other trackers out there.  Also, you will need to secure the "torrents"
322
+		folder with an .htaccess file for Apache or some other method.  The tracker will still accept all valid
323
+		connections by clients.  There is no user checking in that regard.</td>
324
+		<td><input type="checkbox" name="hiddentracker"></td></tr>
325
+		
326
+		<tr><td>Enable or disable scraping by clients.  Generally it is safe to leave this on unless
327
+		you have a large number of torrents or users which can lead to increased bandwidth usage.  Also, scraping
328
+		can possibily be used maliciously by abusive clients.</td>
329
+		<td><input type="checkbox" name="scrape" checked></td></tr>
330
+
331
+		<tr><td>Displays custom titles on the main torrent statistics page instead of the filename.  This is
332
+		because the uploader script will auto-rename your uploaded filename to exactly what you specified initally
333
+		or by automatically using the data from the uploaded torrent.  Check this if you want the titles to be
334
+		different from the filename.</td>
335
+		<td><input type="checkbox" name="customtitle"></td></tr>
336
+
337
+		<tr><td>Short Announce URL: You can enable the short announce feature, making the URL end in /announce for
338
+		your tracker.  You should not utilize both tracker URL forms in one torrent at the same time, or you will get
339
+		inconsistent results.  Note: You will need the provided htaccess file, have URL rewrite capabilities, and have
340
+		it properly set up to use this feature.  Otherwise, leave it disabled.</td>
341
+		<td><select name="announceurl" id="announceurl">
342
+		<option title="disabled" value="announce.php"<?php if($temp == "announce.php") echo " selected=\"selected\"";?>>disabled</option>
343
+		<option title="enabled" value="announce"<?php if($temp == "announce") echo " selected=\"selected\"";?>>enabled</option>
344
+		</select>
345
+		</td>
346
+		</tr>
347
+
348
+		<tr><td><span class="notice">* </span>Lists the number of torrents on each page on your torrent tracker list.  Default is 10.</td>
349
+		<td><input type="text" name="indexpagelimitspecify" size="40" value="10"></td></tr>
350
+
351
+		<tr><td><span class="notice">* </span>Lists the number of torrents on each page on the detailed statistics page.  Default is 5.</td>
352
+		<td><input type="text" name="statspagelimitspecify" size="40" value="5"></td></tr>
353
+
354
+		<tr><td><span class="notice">* </span>Maximum reannounce interval (in seconds) 1800 == 30 minutes</td>
355
+		<td><input type="text" name="report_interval" size="40" value="1800"></td></tr>
356
+
357
+		<tr><td><span class="notice">* </span>Minimum reannounce interval (also in seconds) 300 == 5 minutes</td>
358
+		<td><input type="text" name="min_interval" size="40" value="300"></td></tr>
359
+
360
+		<tr><td><span class="notice">* </span>Number of peers to send in one request.  Some logic will break if you set this to more than 300,
361
+		so please don't do that. 100 is the most you should set anyway.</td>
362
+		<td><input type="text" name="maxpeers" size="40" value="50"></td></tr>
363
+
364
+		<tr><td>If set, NAT checking will be performed.
365
+		This may cause trouble with some providers, so it's
366
+		off by default.</td>
367
+		<td><input type="checkbox" name="NAT"></td></tr>
368
+
369
+		<tr><td>Persistent MySQL connections:
370
+		Check with your webmaster to see if you're allowed to use these.
371
+		Highly recommended, especially for higher loads, but generally
372
+		not allowed unless it's a dedicated machine.</td>
373
+		<td><input type="checkbox" name="persist"></td></tr>
374
+
375
+		<tr><td>Allow users to override ip address.
376
+		Enable this if you know people have a legit reason to use
377
+		this function. Leave disabled otherwise.</td>
378
+		<td><input type="checkbox" name="ip_override"></td></tr>
379
+
380
+		<tr><td>For heavily loaded trackers, uncheck this. It will stop count the number
381
+		of downloaded bytes and the speed of the torrent, but will significantly reduce
382
+		the load.</td>
383
+		<td><input type="checkbox" name="countbytes" checked></td></tr>
384
+
385
+		<tr><td><span class="notice">* </span>Username for individual who can add torrents to tracker database.
386
+		This user is only able to create, and not delete torrents to the tracker.
387
+		For full privileges, see the admin user.</td>
388
+		<td><input type="text" name="upload_username" size="40"></td></tr>
389
+
390
+		<tr><td><span class="notice">* </span>Password for individual who can add torrents to tracker database.
391
+		Again, this user is only able to create, and not delete torrents to the tracker.
392
+		For full privileges, see the admin user.</td>
393
+		<td><input type="password" name="upload_password" size="40"></td></tr>
394
+
395
+		<tr><td><span class="notice">* </span>Admin username. The admin is able to go to the admin page and show detailed 
396
+		information about the tracker as well as access a few other important tools.
397
+		The admin is also able to upload torrents to the database
398
+		just like the previous account.</td>
399
+		<td><input type="text" name="admin_username" size="40"></td></tr>
400
+
401
+		<tr><td><span class="notice">* </span>Password for admin.  Again, The admin is able to go to the admin page and show detailed 
402
+		information about the tracker as well as access a few other important tools.
403
+		The admin is also able to upload torrents to the database.</td>
404
+		<td><input type="password" name="admin_password" size="40"></td></tr>
405
+
406
+		<tr><td>Title on index.php statistics page, if not set, defaults to "Tracker Statistics"</td>
407
+		<td><input type="text" name="title" size="40"></td></tr>
408
+		
409
+		<tr><td>Enable RSS feed: If you do not want the RSS feed to be created for 
410
+		privacy reasons or do not need it disable this checkbox.</td>
411
+		<td><input type="checkbox" name="enablerss" checked></td></tr>
412
+		
413
+		<tr><td>RSS Title: In the rss.xml file, this is the main <pre>&lt;title&gt;</pre> tag.</td>
414
+		<td><input type="text" name="rss_title" size="40"></td></tr>
415
+		
416
+		<tr><td>RSS link to main website: In the rss.xml file, this is the main <pre>&lt;link&gt;</pre> tag.</td>
417
+		<td><input type="text" name="rss_link" size="40"></td></tr>
418
+		
419
+		<tr><td>RSS description: In the rss.xml file, this is the main <pre>&lt;description&gt;</pre> tag.</td>
420
+		<td><input type="text" name="rss_description" size="60"></td></tr>
421
+		
422
+		<tr><td><span class="notice">* </span>Main website url that the tracker runs on, example: http://www.mywebsite.com</td>
423
+		<td><input type="text" name="website_url" size="40"></td></tr>
424
+		
425
+		<tr><td><span class="notice">* </span>For HTTP seeding, this is the maximum total upload rate per second in kilobytes, for example 100 would be 100 KB/s</td>
426
+		<td><input type="text" name="max_upload_rate" size="40" value="100"></td></tr>
427
+		
428
+		<tr><td><span class="notice">* </span>For HTTP seeding, this is the maximum number of uploads to run at a time</td>
429
+		<td><input type="text" name="max_uploads" size="40" value="5"></td></tr>
430
+		
431
+		<tr><td><span class="notice">* </span>Date format of the torrent publication date. It shows on statistics.php. If you change this setting, you will have to change it for every other existing torrent!</td>
432
+		<td>
433
+		<select name="dateformat" id="dateformat">
434
+		<option title="Mon, 4 Jan, 1999 01:15:40 PM" value="D, j M, Y h:i:s A" selected="selected">Mon, 4 Jan, 1999 01:15:40 PM</option>
435
+		<option title="Monday, 4 Jan, 1999 01:15:40 PM" value="l, j M, Y h:i:s A">Monday, 4 Jan, 1999 01:15:40 PM</option>
436
+		<option title="Mon, 4 January, 1999 01:15:40 PM" value="D, j F, Y h:i:s A">Mon, 4 January, 1999 01:15:40 PM</option>
437
+		<option title="Monday, 4 January, 1999 01:15:40 PM" value="l, j F, Y h:i:s A">Monday, 4 January, 1999 01:15:40 PM</option>
438
+		<option title="Mon, 4 Jan, 1999 13:15:40" value="D, j M, Y H:i:s">Mon, 4 Jan, 1999 13:15:40</option>
439
+		<option title="Monday, 4 Jan, 1999 13:15:40" value="l, j M, Y H:i:s">Monday, 4 Jan, 1999 13:15:40</option>
440
+		<option title="Mon, 4 January, 1999 13:15:40" value="D, j F, Y H:i:s">Mon, 4 January, 1999 13:15:40</option>
441
+		<option title="Monday, 4 January, 1999 13:15:40" value="l, j F, Y H:i:s">Monday, 4 January, 1999 13:15:40</option>
442
+		<option title="Mon, Jan 4, 1999 01:15:40 PM" value="D, M j, Y h:i:s A">Mon, Jan 4, 1999 01:15:40 PM</option>
443
+		<option title="Monday, Jan 4, 1999 01:15:40 PM" value="l, M j, Y h:i:s A">Monday, Jan 4, 1999 01:15:40 PM</option>
444
+		<option title="Mon, January 4, 1999 01:15:40 PM" value="D, F j, Y h:i:s A">Mon, January 4, 1999 01:15:40 PM</option>
445
+		<option title="Monday, January 4, 1999 01:15:40 PM" value="l, F j, Y h:i:s A">Monday, January 4, 1999 01:15:40 PM</option>
446
+		<option title="Mon, Jan 4, 1999 13:15:40" value="D, M j, Y H:i:s">Mon, Jan 4, 1999 13:15:40</option>
447
+		<option title="Monday, Jan 4, 1999 13:15:40" value="l, M j, Y H:i:s">Monday, Jan 4, 1999 13:15:40</option>
448
+		<option title="Mon, January 4, 1999 13:15:40" value="D, F j, Y H:i:s">Mon, January 4, 1999 13:15:40</option>
449
+		<option title="Monday, January 4, 1999 13:15:40" value="l, F j, Y H:i:s">Monday, January 4, 1999 13:15:40</option>
450
+		</select>
451
+		</td>
452
+		</tr>
453
+
454
+		<tr><td><span class="notice">* </span>Timezone that the server runs on</td>
455
+		<td>
456
+		<select name="timezone" id="timezone">
457
+		<option title="[UTC - 12] Baker Island Time" value="-1200">[UTC - 12] Baker Island Time</option>
458
+		<option title="[UTC - 11] Niue Time, Samoa Standard Time" value="-1100">[UTC - 11] Niue Time, Samoa Standard Time</option>
459
+		<option title="[UTC - 10] Hawaii-Aleutian Standard Time, Cook Island Time" value="-1000">[UTC - 10] Hawaii-Aleutian Standard Time, Cook Isl...</option>
460
+		<option title="[UTC - 9:30] Marquesas Islands Time" value="-0930">[UTC - 9:30] Marquesas Islands Time</option>
461
+		<option title="[UTC - 9] Alaska Standard Time, Gambier Island Time" value="-0900">[UTC - 9] Alaska Standard Time, Gambier Island Tim...</option>
462
+		<option title="[UTC - 8] Pacific Standard Time" value="-0800">[UTC - 8] Pacific Standard Time</option>
463
+		<option title="[UTC - 7] Mountain Standard Time" value="-0700">[UTC - 7] Mountain Standard Time</option>
464
+		<option title="[UTC - 6] Central Standard Time" value="-0600">[UTC - 6] Central Standard Time</option>
465
+		<option title="[UTC - 5] Eastern Standard Time" value="-0500">[UTC - 5] Eastern Standard Time</option>
466
+		<option title="[UTC - 4] Atlantic Standard Time" value="-0400">[UTC - 4] Atlantic Standard Time</option>
467
+		<option title="[UTC - 3:30] Newfoundland Standard Time" value="-0330">[UTC - 3:30] Newfoundland Standard Time</option>
468
+		<option title="[UTC - 3] Amazon Standard Time, Central Greenland Time" value="-0300">[UTC - 3] Amazon Standard Time, Central Greenland ...</option>
469
+		<option title="[UTC - 2] Fernando de Noronha Time, South Georgia &amp; the South Sandwich Islands Time" value="-0200">[UTC - 2] Fernando de Noronha Time, South Georgia ...</option>
470
+		<option title="[UTC - 1] Azores Standard Time, Cape Verde Time, Eastern Greenland Time" value="-0100">[UTC - 1] Azores Standard Time, Cape Verde Time, E...</option>
471
+		<option title="[UTC] Western European Time, Greenwich Mean Time" value="+0000" selected="selected">[UTC] Western European Time, Greenwich Mean Time</option>
472
+		<option title="[UTC + 1] Central European Time, West African Time" value="+0100">[UTC + 1] Central European Time, West African Time</option>
473
+		<option title="[UTC + 2] Eastern European Time, Central African Time" value="+0200">[UTC + 2] Eastern European Time, Central African T...</option>
474
+		<option title="[UTC + 3] Moscow Standard Time, Eastern African Time" value="+0300">[UTC + 3] Moscow Standard Time, Eastern African Ti...</option>
475
+		<option title="[UTC + 3:30] Iran Standard Time" value="+0330">[UTC + 3:30] Iran Standard Time</option>
476
+		<option title="[UTC + 4] Gulf Standard Time, Samara Standard Time" value="+0400">[UTC + 4] Gulf Standard Time, Samara Standard Time</option>
477
+		<option title="[UTC + 4:30] Afghanistan Time" value="+0430">[UTC + 4:30] Afghanistan Time</option>
478
+		<option title="[UTC + 5] Pakistan Standard Time, Yekaterinburg Standard Time" value="+0500">[UTC + 5] Pakistan Standard Time, Yekaterinburg St...</option>
479
+		<option title="[UTC + 5:30] Indian Standard Time, Sri Lanka Time" value="+0530">[UTC + 5:30] Indian Standard Time, Sri Lanka Time</option>
480
+		<option title="[UTC + 6] Bangladesh Time, Bhutan Time, Novosibirsk Standard Time" value="+0600">[UTC + 6] Bangladesh Time, Bhutan Time, Novosibirs...</option>
481
+		<option title="[UTC + 6:30] Cocos Islands Time, Myanmar Time" value="+0630">[UTC + 6:30] Cocos Islands Time, Myanmar Time</option>
482
+		<option title="[UTC + 7] Indochina Time, Krasnoyarsk Standard Time" value="+0700">[UTC + 7] Indochina Time, Krasnoyarsk Standard Tim...</option>
483
+		<option title="[UTC + 8] Chinese Standard Time, Australian Western Standard Time, Irkutsk Standard Time" value="+0800">[UTC + 8] Chinese Standard Time, Australian Wester...</option>
484
+		<option title="[UTC + 9] Japan Standard Time, Korea Standard Time, Chita Standard Time" value="+0900">[UTC + 9] Japan Standard Time, Korea Standard Time...</option>
485
+		<option title="[UTC + 9:30] Australian Central Standard Time" value="+0930">[UTC + 9:30] Australian Central Standard Time</option>
486
+		<option title="[UTC + 10] Australian Eastern Standard Time, Vladivostok Standard Time" value="+1000">[UTC + 10] Australian Eastern Standard Time, Vladi...</option>
487
+		<option title="[UTC + 10:30] Lord Howe Standard Time" value="+1030">[UTC + 10:30] Lord Howe Standard Time</option>
488
+		<option title="[UTC + 11] Solomon Island Time, Magadan Standard Time" value="+1100">[UTC + 11] Solomon Island Time, Magadan Standard T...</option>
489
+		<option title="[UTC + 11:30] Norfolk Island Time" value="+1130">[UTC + 11:30] Norfolk Island Time</option>
490
+		<option title="[UTC + 12] New Zealand Time, Fiji Time, Kamchatka Standard Time" value="+1200">[UTC + 12] New Zealand Time, Fiji Time, Kamchatka ...</option>
491
+		<option title="[UTC + 13] Tonga Time, Phoenix Islands Time" value="+1300">[UTC + 13] Tonga Time, Phoenix Islands Time</option>
492
+		<option title="[UTC + 14] Line Island Time" value="+1400">[UTC + 14] Line Island Time</option>
493
+		</select>
494
+		</td>
495
+		</tr>
496
+		
497
+		</table>
498
+		<br>
499
+		<center>
500
+		<input type="submit" value="Create Config File">
501
+		</center>
502
+		<br><br><br>
503
+		</form>
504
+		</body>
505
+		</html>
506
+		<?php
507
+	}
508
+
509
+	if (isset($_POST["config"]))
510
+	{
511
+		//check required entries for values, if blank: error out
512
+		if ($_POST["announceurl"] == "")
513
+		{
514
+			echo errorMessage() . "Error: The announce URL is blank.</p>";
515
+			exit();
516
+		}
517
+		if (!is_numeric($_POST["indexpagelimitspecify"]) || $_POST["indexpagelimitspecify"] == "" || $_POST["indexpagelimitspecify"] <= 0)
518
+		{
519
+			echo errorMessage() . "Error: The index page limit is not an integer, a negative number, or is blank.</p>";
520
+			exit();
521
+		}	
522
+		if (!is_numeric($_POST["statspagelimitspecify"]) || $_POST["statspagelimitspecify"] == "" || $_POST["statspagelimitspecify"] <= 0)
523
+		{
524
+			echo errorMessage() . "Error: The statistics page limit is not an integer, a negative number, or is blank.</p>";
525
+			exit();
526
+		}
527
+		if (!is_numeric($_POST["report_interval"]) || $_POST["report_interval"] == "" || $_POST["report_interval"] <= 0)
528
+		{
529
+			echo errorMessage() . "Error: The maximum reannounce interval is not an integer, a negative number, or is blank.</p>";
530
+			exit();
531
+		}
532
+		if (!is_numeric($_POST["min_interval"]) || $_POST["min_interval"] == "" || $_POST["min_interval"] <= 0)
533
+		{
534
+			echo errorMessage() . "Error: The minimum reannounce interval is not an integer, a negative number, or is blank.</p>";
535
+			exit();
536
+		}
537
+		if (!is_numeric($_POST["maxpeers"]) || $_POST["maxpeers"] == "" || $_POST["maxpeers"] > 300 || $_POST["maxpeers"] <= 0)
538
+		{
539
+			echo errorMessage() . "Error: The number of peers to send in one request is not an integer, over 300, a negative number, zero, or blank.</p>";
540
+			exit();
541
+		}
542
+		if ($_POST["upload_username"] == "")
543
+		{
544
+			echo errorMessage() . "Error: The upload username is blank.</p>";
545
+			exit();
546
+		}
547
+		if ($_POST["upload_password"] == "")
548
+		{
549
+			echo errorMessage() . "Error: The upload user password is blank. This is considered a security risk.</p>";
550
+			exit();
551
+		}
552
+		if ($_POST["admin_username"] == "")
553
+		{
554
+			echo errorMessage() . "Error: The admin username is blank.</p>";
555
+			exit();
556
+		}
557
+		if ($_POST["admin_password"] == "")
558
+		{
559
+			echo errorMessage() . "Error: The admin user password is blank. This is considered a LARGE security risk.</p>";
560
+			exit();
561
+		}
562
+		if ($_POST["dbhost"] == "")
563
+		{
564
+			echo errorMessage() . "Error: The database hostname is blank.</p>";
565
+			exit();
566
+		}
567
+		if ($_POST["dbuser"] == "")
568
+		{
569
+			echo errorMessage() . "Error: The database username is blank.</p>";
570
+			exit();
571
+		}
572
+		if ($_POST["dbpass"] == "")
573
+		{
574
+			echo errorMessage() . "Error: The database password is blank.</p>";
575
+			exit();
576
+		}
577
+		if ($_POST["database"] == "")
578
+		{
579
+			echo errorMessage() . "Error: The database name is blank.</p>";
580
+			exit();
581
+		}
582
+		if ($_POST["rss_link"] != "" && Substr($_POST["rss_link"], 0, 7) != "http://")
583
+		{
584
+			echo errorMessage() . "Error: The RSS website URL does not start with http://</p>";
585
+			exit();
586
+		}
587
+		if ($_POST["website_url"] == "" || Substr($_POST["website_url"], 0, 7) != "http://")
588
+		{
589
+			echo errorMessage() . "Error: The website URL does not start with http:// or is blank.</p>";
590
+			exit();
591
+		}
592
+		if (!is_numeric($_POST["max_upload_rate"]) || $_POST["max_upload_rate"] == "" || $_POST["max_upload_rate"] <= 0)
593
+		{
594
+			echo errorMessage() . "Error: The maximum upload rate is not an integer, a negative number, or is blank.</p>";
595
+			exit();
596
+		}
597
+		if (!is_numeric($_POST["max_uploads"]) || $_POST["max_uploads"] == "" || $_POST["max_uploads"] <= 0)
598
+		{
599
+			echo errorMessage() . "Error: The maximum uploads is not an integer, a negative number, or is blank.</p>";
600
+			exit();
601
+		}
602
+		if ($_POST["dateformat"] == "")
603
+		{
604
+			echo errorMessage() . "Error: The date format is blank.</p>";
605
+			exit();
606
+		}
607
+		if ($_POST["timezone"] == "")
608
+		{
609
+			echo errorMessage() . "Error: The timezone is blank.</p>";
610
+			exit();
611
+		}
612
+		if ($_POST["upload_username"] == $_POST["admin_username"])
613
+		{
614
+			echo errorMessage() . "Error: The admin username cannot be the same as the upload username.</p>";
615
+			exit();
616
+		}
617
+	
618
+		//create config.php based on user input
619
+		//first try creating it on the server
620
+		if (is_writable("./"))
621
+		{
622
+			//go through checkboxes and change "on" to "true"
623
+			if ($_POST["hiddentracker"] == "on")
624
+				$hiddentracker = "true";
625
+			else
626
+				$hiddentracker = "false";
627
+			if ($_POST["enablerss"] == "on")
628
+				$enablerss = "true";
629
+			else
630
+				$enablerss = "false";
631
+			if ($_POST["scrape"] == "on")
632
+				$scrape = "true";
633
+			else
634
+				$scrape = "false";
635
+			if ($_POST["customtitle"] == "on")
636
+				$customtitle = "true";
637
+			else
638
+				$customtitle = "false";
639
+			if ($_POST["NAT"] == "on")
640
+				$NAT = "true";
641
+			else
642
+				$NAT = "false";
643
+			if ($_POST["persist"] == "on")
644
+				$persist = "true";
645
+			else
646
+				$persist = "false";
647
+			if ($_POST["ip_override"] == "on")
648
+				$ip_override = "true";
649
+			else
650
+				$ip_override = "false";
651
+			if ($_POST["countbytes"] == "on")
652
+				$countbytes = "true";
653
+			else
654
+				$countbytes = "false";
655
+
656
+			//write config.php file
657
+			$fd = fopen("config.php", "w") or die(errorMessage() . "Error: couldn't make config.php!</p>");
658
+			fwrite($fd, 
659
+			"<?php //Please do NOT edit this file, use the admin page for changes.\n" .
660
+			"\$GLOBALS['hiddentracker'] = " . $hiddentracker . ";\n" .
661
+			"\$GLOBALS['scrape'] = " . $scrape . ";\n" .
662
+			"\$GLOBALS['customtitle'] = " . $customtitle . ";\n" .
663
+			"\$announceurl = " . htmlspecialchars($_POST["announceurl"]) . ";\n" .
664
+			"\$GLOBALS['indexpagelimitspecify'] = " . htmlspecialchars($_POST["indexpagelimitspecify"]) . ";\n" .
665
+			"\$GLOBALS['statspagelimitspecify'] = " . htmlspecialchars($_POST["statspagelimitspecify"]) . ";\n" .
666
+			"\$GLOBALS['report_interval'] = " . htmlspecialchars($_POST["report_interval"]) . ";\n" .
667
+			"\$GLOBALS['min_interval'] = " . htmlspecialchars($_POST["min_interval"]) . ";\n" .
668
+			"\$GLOBALS['maxpeers'] = " . htmlspecialchars($_POST["maxpeers"]) . ";\n" .
669
+			"\$GLOBALS['NAT'] = " . $NAT . ";\n" .
670
+			"\$GLOBALS['persist'] = " . $persist . ";\n" .
671
+			"\$GLOBALS['ip_override'] = " . $ip_override . ";\n" .
672
+			"\$GLOBALS['countbytes'] = " . $countbytes . ";\n" .
673
+			"\$upload_username = '" . htmlspecialchars($_POST["upload_username"]) . "';\n" .
674
+			"\$upload_password = '" . md5($_POST["upload_username"].$_POST["upload_password"]) . "';\n" .
675
+			"\$admin_username = '" . htmlspecialchars($_POST["admin_username"]) . "';\n" .
676
+			"\$admin_password = '" . md5($_POST["admin_username"].$_POST["admin_password"]) . "';\n" .
677
+			"\$GLOBALS['title'] = '" . htmlspecialchars(addquotes($_POST["title"])) . "';\n" .
678
+			"\$dbhost = '" . htmlspecialchars($_POST["dbhost"]) . "';\n" .
679
+			"\$dbuser = '" . htmlspecialchars($_POST["dbuser"]) . "';\n" .
680
+			"\$dbpass = '" . htmlspecialchars($_POST["dbpass"]) . "';\n" .
681
+			"\$database = '" . htmlspecialchars($_POST["database"]) . "';\n" .
682
+			"\$enablerss = " . $enablerss . ";\n" .
683
+			"\$rss_title = '" . htmlspecialchars(addquotes($_POST["rss_title"])) . "';\n" .
684
+			"\$rss_link = '" . htmlspecialchars($_POST["rss_link"]) . "';\n" .
685
+			"\$rss_description = '" . htmlspecialchars(addquotes($_POST["rss_description"])) . "';\n" .
686
+			"\$website_url = '" . htmlspecialchars($_POST["website_url"]) . "';\n" .
687
+			"\$GLOBALS['max_upload_rate'] = " . htmlspecialchars($_POST['max_upload_rate']) . ";\n" .
688
+			"\$GLOBALS['max_uploads'] = " . htmlspecialchars($_POST['max_uploads']) . ";\n" .
689
+			"\$dateformat = '" . htmlspecialchars($_POST["dateformat"]) . "';\n" .
690
+			"\$timezone = '" . htmlspecialchars($_POST["timezone"]) . "';\n" .
691
+			"\$prefix = '" . htmlspecialchars($_POST["prefix"]) . "';\n" .
692
+			"?>"
693
+			);
694
+
695
+			fclose($fd);
696
+			echo "<br><p class=\"success\">config.php file was created successfully!</p>";
697
+		}
698
+
699
+		//if unable to create on server, user downloads config.php file for future upload
700
+		if (!is_writable("./"))
701
+		{
702
+			?>
703
+			<h2>"config.php" was unable to be created on the server, 
704
+			you will have to download the file and upload it manually.</h2>
705
+			<br>
706
+			<form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>">
707
+			<input type="hidden" name="download" value="1">
708
+			<input type="hidden" name="hiddentracker" value="<?php if (isset($_POST['hiddentracker']) AND $_POST['hiddentracker'] == 'on') echo 'true'; else echo 'false';?>">
709
+			<input type="hidden" name="scrape" value="<?php if (isset($_POST['scrape']) AND $_POST['scrape'] == 'on') echo 'true'; else echo 'false';?>">
710
+			<input type="hidden" name="customtitle" value="<?php if (isset($_POST['customtitle']) AND $_POST['customtitle'] == 'on') echo 'true'; else echo 'false';?>">
711
+			<input type="hidden" name="announceurl" value="<?php echo $_POST['announceurl'];?>">
712
+			<input type="hidden" name="indexpagelimitspecify" value="<?php echo $_POST['indexpagelimitspecify'];?>">
713
+			<input type="hidden" name="statspagelimitspecify" value="<?php echo $_POST['statspagelimitspecify'];?>">
714
+			<input type="hidden" name="report_interval" value="<?php echo $_POST['report_interval'];?>">
715
+			<input type="hidden" name="min_interval" value="<?php echo $_POST['min_interval'];?>">
716
+			<input type="hidden" name="maxpeers" value="<?php echo $_POST['maxpeers'];?>">
717
+			<input type="hidden" name="NAT" value="<?php if (isset($_POST['NAT']) AND $_POST['NAT'] == 'on') echo 'true'; else echo 'false';?>">
718
+			<input type="hidden" name="persist" value="<?php if (isset($_POST['persist']) AND $_POST['persist'] == 'on') echo 'true'; else echo 'false';?>">
719
+			<input type="hidden" name="ip_override" value="<?php if (isset($_POST['ip_override']) AND $_POST['ip_override'] == 'on') echo 'true'; else echo 'false';?>">
720
+			<input type="hidden" name="countbytes" value="<?php if (isset($_POST['countbytes']) AND $_POST['countbytes'] == 'on') echo 'true'; else echo 'false';?>">
721
+			<input type="hidden" name="upload_username" value="<?php echo $_POST['upload_username'];?>">
722
+			<input type="hidden" name="upload_password" value="<?php echo md5($_POST["upload_username"].$_POST["upload_password"]);?>">
723
+			<input type="hidden" name="admin_username" value="<?php echo $_POST['admin_username'];?>">
724
+			<input type="hidden" name="admin_password" value="<?php echo md5($_POST["admin_username"].$_POST["admin_password"]);?>">
725
+			<input type="hidden" name="title" value="<?php echo $_POST['title'];?>">
726
+			<input type="hidden" name="dbhost" value="<?php echo $_POST['dbhost'];?>">
727
+			<input type="hidden" name="dbuser" value="<?php echo $_POST['dbuser'];?>">
728
+			<input type="hidden" name="dbpass" value="<?php echo $_POST['dbpass'];?>">
729
+			<input type="hidden" name="database" value="<?php echo $_POST['database'];?>">
730
+			<input type="hidden" name="enablerss" value="<?php if (isset($_POST['enablerss']) AND $_POST['enablerss'] == 'on') echo 'true'; else echo 'false';?>">
731
+			<input type="hidden" name="rss_title" value="<?php echo $_POST['rss_title'];?>">
732
+			<input type="hidden" name="rss_link" value="<?php echo $_POST['rss_link'];?>">
733
+			<input type="hidden" name="rss_description" value="<?php echo $_POST['rss_description'];?>">
734
+			<input type="hidden" name="website_url" value="<?php echo $_POST['website_url'];?>">
735
+			<input type="hidden" name="max_upload_rate" value="<?php echo $_POST['max_upload_rate'];?>">
736
+			<input type="hidden" name="max_uploads" value="<?php echo $_POST['max_uploads'];?>">
737
+			<input type="hidden" name="dateformat" value="<?php echo $_POST['dateformat'];?>">
738
+			<input type="hidden" name="timezone" value="<?php echo $_POST['timezone'];?>">
739
+			<input type="hidden" name="prefix" value="<?php echo $_POST['prefix'];?>">
740
+			<input type="submit" value="Download config.php File">
741
+			</form>
742
+			<br>
743
+			<?php
744
+		}
745
+
746
+		//display message to delete install.php file
747
+		echo "<p class=\"error\">Make sure you go and delete this installer script when you are done! (install.php)</p><br><br>\n";
748
+		echo "<p class=\"error\">Also, check the permissions and make sure the 'torrents' and 'rss' folders are able to be written to by the server.</p><br><br>\n";
749
+		echo "<br><center><a href=\"index.php\">Main Statistics Page</a></center>\n";		
750
+		echo "</body></html>\n";
751
+	}
752
+
753
+?>
0 754
new file mode 100644
... ...
@@ -0,0 +1,35 @@
1
+<?php
2
+//Login Script
3
+//Validates Username and Password
4
+require_once ("config.php");
5
+
6
+if ($_POST['legalterms'] != "on")
7
+{
8
+	//did not agree to legal terms, go back
9
+	header("Location: authenticate.php?status=legalterms");
10
+	exit();
11
+}
12
+
13
+if (md5($_POST['f_user'].$_POST['f_pass']) == $admin_password && $_POST['f_user'] == $admin_username)
14
+{
15
+	//successful admin login
16
+	session_start();
17
+	$_SESSION['admin_logged_in'] = true;
18
+	header("Location: admin.php");
19
+	exit();
20
+}
21
+
22
+if (md5($_POST['f_user'].$_POST['f_pass']) == $upload_password && $_POST['f_user'] == $upload_username)
23
+{
24
+	//successful upload login
25
+	session_start();
26
+	$_SESSION['upload_logged_in'] = true;
27
+	header("Location: index.php");
28
+	exit();
29
+}
30
+
31
+//Username or password was incorrect at this point!
32
+header("Location: authenticate.php?status=error");
33
+exit();
34
+
35
+?>
0 36
new file mode 100644
... ...
@@ -0,0 +1,311 @@
1
+<?php
2
+require_once("config.php");
3
+require_once("funcsv2.php");
4
+//Check session
5
+session_start();
6
+
7
+if (!$_SESSION['admin_logged_in'] && !$_SESSION['upload_logged_in'])
8
+{
9
+	//check fails
10
+	header("Location: authenticate.php?status=error");
11
+	exit();
12
+}
13
+?>
14
+
15
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
16
+<html>
17
+<head>
18
+	<title>Add Torrent to Tracker</title>
19
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
20
+	<link rel="stylesheet" type="text/css" href="./css/style.css" />
21
+</head>
22
+<body>
23
+
24
+<?php
25
+$tracker_url = $website_url . substr($_SERVER['PHP_SELF'], 0, -15) . $announceurl;
26
+
27
+if (isset($_FILES["torrent"]))
28
+	addTorrent();
29
+
30
+
31
+endOutput();
32
+
33
+	
34
+function addTorrent()
35
+{
36
+	require ("config.php");
37
+	$tracker_url = $website_url . substr($_SERVER['PHP_SELF'], 0, -15) . $announceurl;
38
+	
39
+	$hash = strtolower($_POST["hash"]);
40
+
41
+	$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Couldn't connect to the database, contact the administrator</p>");
42
+	mysql_select_db($database) or die(errorMessage() . "Can't open the database.</p>");
43
+	
44
+	require_once ("funcsv2.php");
45
+	require_once ("BDecode.php");
46
+	require_once ("BEncode.php");
47
+	
48
+	if ($_FILES["torrent"]["error"] != 4)	
49
+	{
50
+		$fd = fopen($_FILES["torrent"]["tmp_name"], "rb") or die(errorMessage() . "File upload error 1</p>\n");
51
+		is_uploaded_file($_FILES["torrent"]["tmp_name"]) or die(errorMessage() . "File upload error 2</p>\n");
52
+		$alltorrent = fread($fd, filesize($_FILES["torrent"]["tmp_name"]));
53
+
54
+		$array = BDecode($alltorrent);
55
+		if (!$array)
56
+		{
57
+			echo errorMessage() . "Error: The parser was unable to load your torrent.  Please re-create and re-upload the torrent.</p>\n";
58
+			endOutput();
59
+			exit;
60
+		}		
61
+
62
+		if (isset($array["announce-list"])) {
63
+			//multiple trackers are listed
64
+			$found_tracker = false;
65
+			for ($i = 0; $i < count($array["announce-list"]); $i++) {
66
+				if (strtolower($array["announce-list"][$i][0]) == $tracker_url) {
67
+					$found_tracker = true;
68
+					break;
69
+				}
70
+			}
71
+			if ($found_tracker == false)
72
+			{
73
+				echo errorMessage() . "Error: Multiple trackers were found but none of them match the
74
+					announce URL:<br>$tracker_url<br>Please re-create and re-upload the torrent.</p>\n";
75
+				endOutput();
76
+				exit;
77
+			}
78
+		} else {
79
+			//a single tracker is listed
80
+			if (strtolower($array["announce"]) != $tracker_url) {
81
+				echo errorMessage() . "Error: The tracker announce URL does not match this:<br>$tracker_url<br>Please re-create and re-upload the torrent.</p>\n";
82
+				endOutput();
83
+				exit;
84
+			}
85
+		}
86
+		
87
+		if (isset($_POST["httpseed"]) && $_POST["httpseed"] == "enabled" && $_POST["relative_path"] == "")
88
+		{
89
+			echo errorMessage() . "Error: HTTP seeding was checked however no relative path was given.</p>\n";
90
+			endOutput();
91
+			exit;
92
+		}
93
+		if (isset($_POST["httpseed"]) && $_POST["httpseed"] == "enabled" && $_POST["relative_path"] != "")
94
+		{
95
+			if (Substr($_POST["relative_path"], -1) == "/")
96
+			{
97
+				if (!is_dir($_POST["relative_path"]))
98
+				{
99
+					echo errorMessage() . "Error: HTTP seeding relative path ends in / but is not a valid directory.</p>\n";
100
+					endOutput();
101
+					exit;
102
+				}
103
+			}
104
+			else
105
+			{
106
+				if (!is_file($_POST["relative_path"]))
107
+				{
108
+					echo errorMessage() . "Error: HTTP seeding relative path is not a valid file.</p>\n";
109
+					endOutput();
110
+					exit;
111
+				}
112
+			}
113
+		}
114
+		if (isset($_POST["getrightseed"]) && $_POST["getrightseed"] == "enabled" && $_POST["httpftplocation"] == "")
115
+		{
116
+			echo errorMessage() . "Error: GetRight HTTP seeding was checked however no URL was given.</p>\n";
117
+			endOutput();
118
+			exit;
119
+		}
120
+		if (isset($_POST["getrightseed"]) && $_POST["getrightseed"] == "enabled" &&
121
+			(Substr($_POST["httpftplocation"], 0, 7) != "http://" && Substr($_POST["httpftplocation"], 0, 6) != "ftp://")
122
+		)
123
+		{
124
+			echo errorMessage() . "Error: GetRight HTTP seeding URL must start with http:// or ftp://</p>\n";
125
+			endOutput();
126
+			exit;
127
+		}
128
+		$hash = @sha1(BEncode($array["info"]));
129
+		fclose($fd);
130
+		
131
+		$target_path = "torrents/";
132
+		$target_path = $target_path . basename( clean($_FILES['torrent']['name'])); 
133
+		$move_torrent = move_uploaded_file($_FILES["torrent"]["tmp_name"], $target_path);
134
+		if ($move_torrent == false)
135
+		{
136
+			echo errorMessage() . "Unable to move " . $_FILES["torrent"]["tmp_name"] . " to torrents/</p>\n";
137
+		}	
138
+	}
139
+	
140
+
141
+	if (isset($_POST["title"]))
142
+		$title = clean($_POST["title"]);
143
+	else
144
+		$title = "";
145
+		
146
+	if (isset($_POST["filename"]))
147
+		$filename = clean($_POST["filename"]);
148
+	else
149
+		$filename = "";
150
+	
151
+	if (isset($_POST["url"]))
152
+		$url = clean($_POST["url"]);
153
+	else
154
+		$url = "";
155
+
156
+	if (isset($_POST["autoset"]))
157
+	if (strcmp($_POST["autoset"], "enabled") == 0)
158
+	{
159
+		if (strlen($filename) == 0 && isset($array["info"]["name"]))
160
+			$filename = $array["info"]["name"];
161
+	}
162
+	
163
+
164
+	//figure out total size of all files in torrent
165
+	$info = $array["info"];
166
+	$total_size = 0;
167
+	if (isset($info["files"]))
168
+	{
169
+		foreach ($info["files"] as $file)
170
+		{
171
+			$total_size = $total_size + $file["length"];
172
+		}
173
+	}
174
+	else
175
+	{
176
+		$total_size = $info["length"];
177
+	}
178
+	
179
+	//Validate torrent file, make sure everything is correct
180
+	
181
+	$filename = mysql_real_escape_string($filename);
182
+	$filename = stripslashes($filename);
183
+	$filename = htmlspecialchars(clean($filename));
184
+	$url = htmlspecialchars(mysql_real_escape_string($url));
185
+
186
+	if ((strlen($hash) != 40) || !verifyHash($hash))
187
+	{
188
+		echo errorMessage() . "Error: Info hash must be exactly 40 hex bytes.</p>\n";
189
+		endOutput();
190
+	}
191
+
192
+	if (Substr($url, 0, 7) != "http://" && $url != "")
193
+	{
194
+		echo errorMessage() . "Error: The Torrent URL does not start with http:// Make sure you entered a correct URL.</p>\n";
195
+		endOutput();
196
+	}
197
+
198
+	if ($GLOBALS["customtitle"] == "true")
199
+	$query = "INSERT INTO ".$prefix."namemap (info_hash, title, filename, url, size, pubDate) VALUES (\"$hash\", \"$title\", \"$filename\", \"$url\", \"$total_size\", \"" . date("$dateformat") . "\")";
200
+	else $query = "INSERT INTO ".$prefix."namemap (info_hash, title, filename, url, size, pubDate) VALUES (\"$hash\", \"$filename\", \"$filename\", \"$url\", \"$total_size\", \"" . date("$dateformat") . "\")";
201
+	$status = makeTorrent($hash, true);
202
+	quickQuery($query);
203
+	if ($status)
204
+	{
205
+		echo "<p class=\"success\">Torrent was added successfully.</p>\n";
206
+		echo "<a href=\"newtorrents.php\"><img src=\"images/add.png\" border=\"0\" class=\"icon\" alt=\"Add Torrent\" title=\"Add Torrent\" /></a><a href=\"newtorrents.php\">Add Another Torrent</a><br>\n";
207
+		//rename torrent file to match filename
208
+		rename("torrents/" . clean($_FILES['torrent']['name']), "torrents/" . $filename . ".torrent");
209
+		//make torrent file readable by all
210
+		chmod("torrents/" . $filename . ".torrent", 0644);
211
+	
212
+		//run RSS generator
213
+		require_once("rss_generator.php");
214
+		//Display information from DumpTorrentCGI.php
215
+		require_once("torrent_functions.php");
216
+	}
217
+	else
218
+	{
219
+		echo errorMessage() . "There were some errors. Check if this torrent has been added previously.</p>\n";
220
+		//delete torrent file if it doesn't exist in database
221
+		$query = "SELECT COUNT(*) FROM ".$prefix."summary WHERE info_hash = '$hash'";
222
+		$results = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
223
+		$data = mysql_fetch_row($results);
224
+		if ($data[0] == 0)
225
+		{
226
+			if (file_exists("torrents/" . $_FILES['torrent']['name']))
227
+				unlink("torrents/" . $_FILES['torrent']['name']);
228
+		}
229
+		//make torrent file readable by all
230
+		chmod("torrents/" . $filename . ".torrent", 0644);
231
+		endOutput();
232
+	}
233
+}
234
+
235
+function endOutput() 
236
+{
237
+	require ("config.php");
238
+	$tracker_url = $website_url . substr($_SERVER['PHP_SELF'], 0, -15) . $announceurl;
239
+	?>
240
+	<p align="right"><a href="./docs/help.html"><img src="images/help.png" border="0" class="icon" alt="Help" title="Help" /></a><a href="./docs/help.html">Help</a></p>
241
+	<div class="center">
242
+	<h1>Add Torrent to Tracker Database</h1>
243
+	<h3>Tracker URL: <?php echo $tracker_url;?></h3>
244
+	<form enctype="multipart/form-data" method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
245
+	<table>
246
+	<tr>
247
+		<?php
248
+		if ($GLOBALS["customtitle"] == "true")
249
+		echo "<td class=\"right\">Title:</td>
250
+		<td class=\"left\"><input type=\"title\" name=\"title\" size=\"50\"/></td>";
251
+		else ($GLOBALS["customtitle"] != "true");
252
+		?>
253
+	</tr>
254
+	<tr>
255
+		<td class="right">Torrent file:</td>
256
+		<td class="left"><?php
257
+		if (function_exists("sha1"))
258
+			echo "<input type=\"file\" name=\"torrent\" size=\"50\"/>";
259
+		else
260
+			echo '<i>File uploading not available - no SHA1 function.</i>';
261
+		?></td>
262
+	</tr>
263
+	<tr><td colspan="2"><hr></td></tr>
264
+	<tr>	
265
+	<td class="center" colspan="2"><input type="checkbox" name="httpseed" value="enabled">Use BitTornado HTTP seeding specification (optional)</td>
266
+	</tr>
267
+	<tr>
268
+	<td class="right">Relative location of file or directory:<br>e.g. ../../files/file.zip</td>
269
+	<td class="left"><input type="text" name="relative_path" size="70"/></td>
270
+	</tr>
271
+	<tr><td colspan="2"><hr></td></tr>
272
+	<tr>
273
+	<td class="center" colspan="2"><input type="checkbox" name="getrightseed" value="enabled">Use GetRight HTTP seeding specification (optional)</td>
274
+	</tr>
275
+	<tr>
276
+	<td class="right">FTP/HTTP URL of file or directory:<br>e.g. http://yourwebsite.com/file.zip</td>
277
+	<td class="left"><input type="text" name="httpftplocation" size="70"/></td>
278
+	</tr>
279
+	<tr><td colspan="2"><hr></td></tr>
280
+	<?php if (function_exists("sha1")) 
281
+		echo "<tr><td class=\"center\" colspan=\"2\"><input type=\"checkbox\" name=\"autoset\" value=\"enabled\" checked=\"checked\" /> Fill in fields below automatically using data from the torrent file.</td></tr>\n";
282
+	?>
283
+	<tr>
284
+		<td class="right">Info Hash:</td>
285
+		<td class="left"><input type="text" name="hash" size="40"/></td>
286
+	</tr>
287
+	<tr>
288
+		<td class="right">File name (optional): </td>
289
+		<td class="left"><input type="text" name="filename" size="60" maxlength="200"/></td>
290
+	</tr>
291
+	<tr>
292
+		<td class="right">Torrent's URL (optional): </td>
293
+		<td class="left"><input type="text" name="url" size="60" maxlength="200"/></td>
294
+	</tr>
295
+	<tr><td colspan="2"><hr></td></tr>
296
+	<tr>
297
+		<td class="center" colspan="2"><input type="submit" value="Add Torrent to Database"/> - <input type="reset" value="Clear Settings"/></td>
298
+	</tr>
299
+	</table>
300
+	<br>
301
+	<input type="hidden" name="username" value="<?php echo $_POST['username']; ?>"/>
302
+	<input type="hidden" name="password" value="<?php echo $_POST['password']; ?>"/>
303
+	</form>
304
+	<a href="index.php"><img src="images/stats.png" border="0" class="icon" alt="Tracker Statistics" title="Tracker Statistics" /></a><a href="index.php">Return to Statistics Page</a><br>
305
+	</div>
306
+	</body></html>
307
+	<?php 	
308
+	// Still in function endOutput()
309
+	exit;
310
+}
311
+?>
0 312
\ No newline at end of file
1 313
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+<?php
2
+
3
+header("Location: ../index.php");
4
+
5
+?>
0 6
\ No newline at end of file
1 7
new file mode 100644
... ...
@@ -0,0 +1,68 @@
1
+<?php
2
+//re-read config.php file after it has been written
3
+include ("config.php");
4
+require_once ("funcsv2.php");
5
+
6
+//This script runs whenever:
7
+//1) a torrent is added to the database
8
+//2) a torrent is deleted from the database
9
+//3) the config.php file is edited
10
+//This is to ensure that the correct rss.xml file is available and generated
11
+
12
+//connect to database
13
+$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Cannot connect to database. Check your username and password in the config file.</p>");
14
+mysql_select_db($database) or die(errorMessage() . "Error selecting database.</p>");
15
+$query = "SELECT filename,url,size,pubDate FROM ".$prefix."namemap ORDER BY pubDate DESC";
16
+$results = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
17
+
18
+//if there are no entries in database or RSS feed is disabled in config.php file, delete rss.xml file
19
+if (mysql_num_rows($results) == 0 || $enablerss == false)
20
+{
21
+	if (file_exists("rss/rss.xml")) //make sure file exists before trying to delete
22
+		unlink("rss/rss.xml") or die ("Can't delete rss.xml file using unlink().  Are you running the server under Windows?");
23
+}
24
+else //otherwise, generate new rss.xml file
25
+{
26
+	$fd = fopen("rss/rss.xml", "w") or die(errorMessage() . "Error: Unable to write to rss.xml file!</p>");
27
+	$start_text = 
28
+	"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
29
+	"<rss version=\"2.0\">\n" .
30
+	"<channel>\n" .
31
+	"<title>" . clean($rss_title) . "</title>\n" .
32
+	"<link>" . $rss_link . "</link>\n" .
33
+	"<description>" . clean($rss_description) . "</description>\n" .
34
+	"<lastBuildDate>" . date('D, j M Y h:i:s') . " " . $timezone . "</lastBuildDate>\n";
35
+	
36
+	$middle_text = "";
37
+	while ($row = mysql_fetch_row($results))
38
+	{
39
+		//figure out full torrent URL
40
+		$url = $website_url . $_SERVER['REQUEST_URI'];
41
+		$url = str_replace("newtorrents.php", "", $url);
42
+		$url = str_replace("editconfig.php", "", $url);
43
+		$url = str_replace("deleter.php", "", $url);
44
+		$url = $url . "torrents/" . $row[0] . ".torrent";
45
+		$url = str_replace(" ", "%20", $url);
46
+		
47
+		//figure out file(s) size
48
+		$file_size = bytesToString($row[2]);
49
+		
50
+		//go through each entry in database
51
+		$middle_text = $middle_text . "<item>\n" .
52
+		"<title>" . $row[0] . " (" . $file_size . ")</title>\n" .
53
+		"<description>" . $row[0] . " (" . $file_size . ") " . $row[1] . "</description>\n" .
54
+		"<pubDate>" . $row[3] . " " . $timezone . "</pubDate>\n" .
55
+		"<guid>" . $url . "</guid>\n" .
56
+		"<link>" . $url . "</link>\n" .
57
+		"<enclosure url=\"" . $url . "\" length=\"" . filesize("torrents/" . $row[0] . ".torrent") . "\" type=\"application/x-bittorrent\" />\n" .
58
+		"</item>\n";
59
+	}
60
+	
61
+	$end_text = "</channel>\n</rss>";
62
+	
63
+	fwrite($fd, $start_text . $middle_text . $end_text);
64
+	fclose($fd);
65
+	
66
+}
67
+
68
+?>
0 69
\ No newline at end of file
1 70
new file mode 100644
... ...
@@ -0,0 +1,218 @@
1
+<?php
2
+require ("config.php");
3
+require_once("funcsv2.php");
4
+//Check session
5
+session_start();
6
+
7
+if (!$_SESSION['admin_logged_in'])
8
+{
9
+	//check fails
10
+	header("Location: authenticate.php?status=session");
11
+	exit();
12
+}
13
+?>
14
+
15
+
16
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
17
+<html>
18
+<head>
19
+	<title>Check Tracker for Expired Peers</title>
20
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
21
+	<link rel="stylesheet" type="text/css" href="./css/style.css" />
22
+</head>
23
+<body>
24
+<h1>Check Tracker for Expired Peers</h1>
25
+<?php
26
+
27
+
28
+error_reporting(E_ALL);
29
+//header("Content-Type: text/plain");
30
+
31
+//require_once("config.php");
32
+//require_once("funcsv2.php");
33
+
34
+$summaryupdate = array();
35
+
36
+// Non-persistant: we lock tables!
37
+$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - ".mysql_error() . "</p>");
38
+mysql_select_db($database) or die(errorMessage() . "Tracker error: can't open database $database - ".mysql_error() . "</p>");
39
+
40
+if (isset($_GET["nolock"]))
41
+	$locking = false;
42
+else
43
+	$locking = true;
44
+
45
+// Assumes success
46
+if ($locking)
47
+	quickQuery("LOCK TABLES ".$prefix."summary WRITE, ".$prefix."namemap READ");
48
+
49
+?>
50
+<table class="torrentlist" cellspacing="1">
51
+<!-- Column Headers -->
52
+<tr>
53
+	<th>Name/Info Hash</th>
54
+	<th>Seeders</th>
55
+	<th>Leechers</th>
56
+	<th>Bytes Transfered</th>
57
+	<th>Stale Clients</th>
58
+	<th>Peer Cache</th>
59
+</tr>
60
+<?php
61
+
62
+$results = mysql_query("SELECT ".$prefix."summary.info_hash, seeds, leechers, dlbytes, ".$prefix."namemap.filename FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash");
63
+
64
+$i = 0;
65
+
66
+while ($row = mysql_fetch_row($results))
67
+{
68
+	$writeout = "row" . $i % 2;
69
+	list($hash, $seeders, $leechers, $bytes, $filename) = $row;
70
+	if ($locking)
71
+	{
72
+		//peercaching ALWAYS on
73
+		quickQuery("LOCK TABLES ".$prefix."x$hash WRITE, ".$prefix."y$hash WRITE, ".$prefix."summary WRITE");
74
+	}
75
+	$results2 = mysql_query("SELECT status, COUNT(status) from ".$prefix."x$hash GROUP BY status");
76
+	echo "<tr class=\"$writeout\"><td>";
77
+	if (!is_null($filename))
78
+		echo $filename;
79
+	else
80
+		echo $hash;
81
+	echo "</td>";
82
+	if (!$results2)
83
+	{
84
+		echo "<td colspan=\"4\">Unable to process: ".mysql_error()."</td></tr>";
85
+		continue;
86
+	}
87
+
88
+	$counts = array();
89
+	while ($row = mysql_fetch_row($results2))
90
+		$counts[$row[0]] = $row[1];	
91
+	if (!isset($counts["leecher"]))
92
+		$counts["leecher"] = 0;
93
+	if (!isset($counts["seeder"]))
94
+		$counts["seeder"] = 0;
95
+
96
+	if ($counts["seeder"] != $seeders)
97
+	{
98
+		quickQuery("UPDATE ".$prefix."summary SET seeds=".$counts["seeder"]." WHERE info_hash=\"$hash\"");
99
+		echo "<td class=\"center\">$seeders -> ".$counts["seeder"]."</td>";
100
+	}
101
+	else
102
+		echo "<td class=\"center\">$seeders</td>";
103
+		
104
+	if ($counts["leecher"] != $leechers)
105
+	{
106
+		quickQuery("UPDATE ".$prefix."summary SET leechers=".$counts["leecher"]." WHERE info_hash=\"$hash\"");
107
+		echo "<td class=\"center\">$leechers -> ".$counts["leecher"]."</td>";
108
+	}
109
+	else
110
+		echo "<td class=\"center\">$leechers</td>";
111
+		
112
+	if ($counts["leecher"] == 0)
113
+	{
114
+		//If there are no leechers, set the speed to zero
115
+		quickQuery("UPDATE ".$prefix."summary set speed=0 WHERE info_hash=\"$hash\"");
116
+	}
117
+
118
+	if ($bytes < 0)
119
+	{
120
+		quickQuery("UPDATE ".$prefix."summary SET dlbytes=0 WHERE info_hash=\"$hash\"");
121
+		echo "<td class=\"center\">$bytes -> Zero</td>";
122
+	}
123
+	else
124
+		echo "<td class=\"center\">". round($bytes/1048576/1024,3) ." GB</td>";
125
+
126
+	myTrashCollector($hash, $report_interval, time(), $writeout);
127
+	echo "<td class=\"center\">";
128
+	
129
+	$result = mysql_query("SELECT ".$prefix."x$hash.sequence FROM ".$prefix."x$hash LEFT JOIN ".$prefix."y$hash ON ".$prefix."x$hash.sequence = ".$prefix."y$hash.sequence WHERE ".$prefix."y$hash.sequence IS NULL") or die(errorMessage() . "" . mysql_error() . "</p>");
130
+	if (mysql_num_rows($result) > 0)
131
+	{
132
+		echo "Added ", mysql_num_rows($result);
133
+		$row = array();
134
+		
135
+		while ($data = mysql_fetch_row($result))
136
+				$row[] = "sequence=\"${data[0]}\"";
137
+		$where = implode(" OR ", $row);
138
+		$query = mysql_query("SELECT * FROM ".$prefix."x$hash WHERE $where");
139
+		
140
+		while ($row = mysql_fetch_assoc($query))
141
+		{
142
+			$compact = mysql_real_escape_string(pack('Nn', ip2long($row["ip"]), $row["port"]));
143
+			$peerid = mysql_real_escape_string('2:ip' . strlen($row["ip"]) . ':' . $row["ip"] . '7:peer id20:' . hex2bin($row["peer_id"]) . "4:porti{$row["port"]}e");
144
+			$no_peerid = mysql_real_escape_string('2:ip' . strlen($row["ip"]) . ':' . $row["ip"] . "4:porti{$row["port"]}e");
145
+			mysql_query("INSERT INTO ".$prefix."y$hash SET sequence='{$row["sequence"]}', compact='$compact', with_peerid='$peerid', without_peerid='$no_peerid'");
146
+		}
147
+	}	
148
+	else
149
+		echo "Added none";
150
+
151
+	$result = mysql_query("SELECT ".$prefix."y$hash.sequence FROM ".$prefix."y$hash LEFT JOIN ".$prefix."x$hash ON ".$prefix."y$hash.sequence = ".$prefix."x$hash.sequence WHERE ".$prefix."x$hash.sequence IS NULL");
152
+	if (mysql_num_rows($result) > 0)
153
+	{
154
+		echo ", Deleted ",mysql_num_rows($result);
155
+
156
+		$row = array();
157
+		
158
+		while ($data = mysql_fetch_row($result))
159
+			$row[] = "sequence=\"${data[0]}\"";
160
+		$where = implode(" OR ", $row);
161
+		$query = mysql_query("DELETE FROM ".$prefix."y$hash WHERE $where");
162
+	}
163
+	else
164
+		echo ", Deleted none";
165
+
166
+	echo "</td>";
167
+	
168
+	echo "</tr>\n";
169
+	$i ++;
170
+
171
+
172
+	if ($locking)
173
+		quickQuery("UNLOCK TABLES");
174
+		
175
+	//Repair tables, is this necessary?  Sometimes the tables crash...
176
+	//Can't repair table if locked?
177
+	//quickQuery("REPAIR Table x$hash");
178
+	//quickQuery("REPAIR Table y$hash");
179
+
180
+	// Finally, it's time to do stuff to the summary table.
181
+	if (!empty($summaryupdate))
182
+	{
183
+		$stuff = "";
184
+		foreach ($summaryupdate as $column => $value)
185
+		{
186
+			$stuff .= ', '.$column. ($value[1] ? "=" : "=$column+") . $value[0];
187
+		}
188
+		mysql_query("UPDATE ".$prefix."summary SET ".substr($stuff, 1)." WHERE info_hash=\"$hash\"");
189
+		$summaryupdate = array();
190
+	}
191
+
192
+
193
+}
194
+
195
+function myTrashCollector($hash, $timeout, $now, $writeout)
196
+{
197
+//	error_log("Trash collector working on $hash");
198
+ 	require("config.php");
199
+ 	$peers = loadLostPeers($hash, $timeout);
200
+ 	for ($i=0; $i < $peers["size"]; $i++)
201
+	        killPeer($peers[$i]["peer_id"], $hash, $peers[$i]["bytes"], $peers[$i]);
202
+	if ($i != 0)
203
+		echo "<td class=\"center\">Removed $i</td>";
204
+	else
205
+		echo "<td class=\"center\">Removed 0</td>";
206
+ 	quickQuery("UPDATE ".$prefix."summary SET lastcycle='$now' WHERE info_hash='$hash'");
207
+}
208
+
209
+
210
+
211
+
212
+?>
213
+</table>
214
+<p><a href="sanity.php?nolock=on">Not working? Try running this.</a></p>
215
+<a href="index.php"><img src="images/stats.png" border="0" class="icon" alt="Tracker Statistics" title="Tracker Statistics" /></a><a href="index.php">Return to Statistics Page</a><br>
216
+<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Return to Admin Page</a>
217
+</body>
218
+</html>
0 219
new file mode 100644
... ...
@@ -0,0 +1,126 @@
1
+<?php
2
+require_once("config.php");
3
+require_once("funcsv2.php");
4
+
5
+$summaryupdate = array();
6
+
7
+// Non-persistant: we lock tables!
8
+$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - ".mysql_error() . "</p>");
9
+mysql_select_db($database) or die(errorMessage() . "Tracker error: can't open database $database - ".mysql_error() . "</p>");
10
+
11
+
12
+quickQuery("LOCK TABLES ".$prefix."summary WRITE, ".$prefix."namemap READ");
13
+
14
+$results = mysql_query("SELECT ".$prefix."summary.info_hash, seeds, leechers, dlbytes, ".$prefix."namemap.filename FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash");
15
+
16
+$i = 0;
17
+
18
+while ($row = mysql_fetch_row($results))
19
+{
20
+	$writeout = "row" . $i % 2;
21
+	list($hash, $seeders, $leechers, $bytes, $filename) = $row;
22
+	if (isset($locking) && $locking)
23
+	{
24
+		//peercaching ALWAYS on
25
+		quickQuery("LOCK TABLES ".$prefix."x$hash WRITE, ".$prefix."y$hash WRITE, ".$prefix."summary WRITE");
26
+	}
27
+	$results2 = mysql_query("SELECT status, COUNT(status) FROM ".$prefix."x$hash GROUP BY status");
28
+
29
+	if (!$results2)
30
+	{
31
+		//unable to process
32
+		continue;
33
+	}
34
+
35
+	$counts = array();
36
+	while ($row = mysql_fetch_row($results2))
37
+		$counts[$row[0]] = $row[1];	
38
+	if (!isset($counts["leecher"]))
39
+		$counts["leecher"] = 0;
40
+	if (!isset($counts["seeder"]))
41
+		$counts["seeder"] = 0;
42
+
43
+	if ($counts["leecher"] != $leechers)
44
+		quickQuery("UPDATE ".$prefix."summary SET leechers=".$counts["leecher"]." WHERE info_hash=\"$hash\"");
45
+
46
+	if ($counts["seeder"] != $seeders)
47
+		quickQuery("UPDATE ".$prefix."summary SET seeds=".$counts["seeder"]." WHERE info_hash=\"$hash\"");
48
+		
49
+	if ($counts["leecher"] == 0)
50
+	{
51
+		//If there are no leechers, set the speed to zero
52
+		quickQuery("UPDATE ".$prefix."summary set speed=0 WHERE info_hash='$hash'");
53
+	}
54
+	
55
+
56
+	if ($bytes < 0)
57
+		quickQuery("UPDATE ".$prefix."summary SET dlbytes=0 WHERE info_hash='$hash'");
58
+
59
+	myTrashCollector($hash, $report_interval, time(), $writeout);
60
+
61
+	$result = mysql_query("SELECT ".$prefix."x$hash.sequence FROM ".$prefix."x$hash LEFT JOIN ".$prefix."y$hash ON ".$prefix."x$hash.sequence = ".$prefix."y$hash.sequence WHERE ".$prefix."y$hash.sequence IS NULL") or die(errorMessage() . "" . mysql_error() . "</p>");
62
+	if (mysql_num_rows($result) > 0)
63
+	{
64
+		$row = array();
65
+		
66
+		while ($data = mysql_fetch_row($result))
67
+				$row[] = "sequence=\"${data[0]}\"";
68
+		$where = implode(" OR ", $row);
69
+		$query = mysql_query("SELECT * FROM ".$prefix."x$hash WHERE $where");
70
+		
71
+		while ($row = mysql_fetch_assoc($query))
72
+		{
73
+			$compact = mysql_real_escape_string(pack('Nn', ip2long($row["ip"]), $row["port"]));
74
+			$peerid = mysql_real_escape_string('2:ip' . strlen($row["ip"]) . ':' . $row["ip"] . '7:peer id20:' . hex2bin($row["peer_id"]) . "4:porti{$row["port"]}e");
75
+			$no_peerid = mysql_real_escape_string('2:ip' . strlen($row["ip"]) . ':' . $row["ip"] . "4:porti{$row["port"]}e");
76
+			mysql_query("INSERT INTO ".$prefix."y$hash SET sequence='{$row["sequence"]}', compact='$compact', with_peerid='$peerid', without_peerid='$no_peerid'");
77
+		}
78
+	}	
79
+
80
+	$result = mysql_query("SELECT ".$prefix."y$hash.sequence FROM ".$prefix."y$hash LEFT JOIN ".$prefix."x$hash ON ".$prefix."y$hash.sequence = ".$prefix."x$hash.sequence WHERE ".$prefix."x$hash.sequence IS NULL");
81
+	if (mysql_num_rows($result) > 0)
82
+	{
83
+		$row = array();
84
+		
85
+		while ($data = mysql_fetch_row($result))
86
+			$row[] = "sequence=\"${data[0]}\"";
87
+		$where = implode(" OR ", $row);
88
+		$query = mysql_query("DELETE FROM ".$prefix."y$hash WHERE $where");
89
+	}
90
+
91
+
92
+	$i ++;
93
+
94
+	quickQuery("UNLOCK TABLES");
95
+	
96
+	//Repair tables, is this necessary?  Sometimes the tables crash...
97
+	//Can't repair table if locked?
98
+	//quickQuery("REPAIR Table x$hash");
99
+	//quickQuery("REPAIR Table y$hash");
100
+
101
+	// Finally, it's time to do stuff to the summary table.
102
+	if (!empty($summaryupdate))
103
+	{
104
+		$stuff = "";
105
+		foreach ($summaryupdate as $column => $value)
106
+		{
107
+			$stuff .= ', '.$column. ($value[1] ? "=" : "=$column+") . $value[0];
108
+		}
109
+		mysql_query("UPDATE ".$prefix."summary SET ".substr($stuff, 1)." WHERE info_hash=\"$hash\"");
110
+		$summaryupdate = array();
111
+	}
112
+		
113
+}
114
+
115
+
116
+function myTrashCollector($hash, $timeout, $now, $writeout)
117
+{
118
+	require("config.php");
119
+	$peers = loadLostPeers($hash, $timeout);
120
+	for ($i=0; $i < $peers["size"]; $i++) {
121
+	        killPeer($peers[$i]["peer_id"], $hash, $peers[$i]["bytes"], $peers[$i]);
122
+	}
123
+ 	quickQuery("UPDATE ".$prefix."summary SET lastcycle='$now' WHERE info_hash='$hash'");
124
+}
125
+
126
+?>
0 127
\ No newline at end of file
1 128
new file mode 100644
... ...
@@ -0,0 +1,12 @@
1
+<?php
2
+//takes information from installer.php and creates config.php file
3
+//allows user to save config.php
4
+
5
+header('content-type: application/octet-stream');
6
+header("Content-Disposition: attachment; filename=\"config.php\"");
7
+
8
+print "<?php $config = " . var_export($config, true)  . ";"
9
+
10
+
11
+
12
+?>
0 13
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+<?php
2
+
3
+$_SERVER["PATH_INFO"] = "/scrape";
4
+require("tracker.php");
5
+exit;
6
+
7
+?>
0 8
\ No newline at end of file
1 9
new file mode 100644
... ...
@@ -0,0 +1,179 @@
1
+<?php
2
+//Used for HTTP seeding
3
+//Requires information in torrent file for client to use
4
+
5
+header("Content-Type: text/plain");
6
+
7
+//error_log("One");
8
+if (!isset($_GET["info_hash"]) || !isset($_GET["piece"]))
9
+	reject("400 Bad Request");
10
+
11
+if (get_magic_quotes_gpc())
12
+	$info_hash=stripslashes($_GET["info_hash"]);
13
+else
14
+	$info_hash=$_GET["info_hash"];
15
+
16
+$piece = $_GET["piece"];
17
+//error_log("Two");
18
+
19
+if (!is_numeric($piece) || strlen($info_hash) != 20)
20
+	reject("400 Bad Request");
21
+
22
+$info_hash = bin2hex($info_hash);
23
+
24
+//error_log("Info hash=$info_hash, piece numnber=$piece");
25
+
26
+require_once("config.php");
27
+
28
+//change from KB to bytes
29
+$max_upload_rate = $GLOBALS["max_upload_rate"] * 1024;
30
+
31
+function Lock($hash, $time = 0)
32
+{
33
+	$results = mysql_query("SELECT GET_LOCK('$hash', $time)");
34
+   $string = mysql_fetch_row($results);
35
+   if (strcmp($string[0], "1") == 0)
36
+   {
37
+   	//error_log("Got lock $hash");
38
+   	return true;
39
+	}
40
+	//error_log("Failed to lock $hash");
41
+   return false;
42
+}
43
+
44
+function Unlock($hash)
45
+{
46
+        mysql_query("SELECT RELEASE_LOCK('$hash')");
47
+}
48
+
49
+function reject($error = "503 Service Temporarily Unavailable", $message="")
50
+{
51
+	header("HTTP/1.0 $error");
52
+	echo $message;
53
+	die;
54
+}
55
+
56
+mysql_connect($dbhost, $dbuser, $dbpass) or die;
57
+mysql_select_db($database) or die;
58
+
59
+if (!Lock("WebSeedLock", 2))
60
+	reject();
61
+
62
+$result = mysql_query("SELECT (UNIX_TIMESTAMP() - started) FROM ".$prefix."speedlimit");
63
+$row = mysql_fetch_row($result);
64
+
65
+// If nothing has happened for a little while, do NOT
66
+// let that average enable massive bursts.
67
+if ($row[0] > 180)
68
+	mysql_query("UPDATE ".$prefix."speedlimit SET started=UNIX_TIMESTAMP()-1, total_uploaded=total_uploaded+uploaded, uploaded=0");
69
+
70
+$result = mysql_query("SELECT uploaded / (UNIX_TIMESTAMP() - started) FROM ".$prefix."speedlimit");
71
+$row = mysql_fetch_row($result);
72
+
73
+if ((float)($row[0]) > $max_upload_rate)
74
+{
75
+	$result = mysql_query("SELECT (uploaded/". $max_upload_rate . "+started) - UNIX_TIMESTAMP() FROM ".$prefix."speedlimit");
76
+	$row = mysql_fetch_row($result);
77
+	reject("503 Service Temporarily Unavailable", (int)$row[0] + mt_rand(1,30));
78
+}
79
+
80
+$result = mysql_query("SELECT seeds FROM ".$prefix."summary WHERE info_hash=$info_hash");
81
+if ($result)
82
+{
83
+	//error_log("Doing PHPBT check");
84
+	$row = mysql_fetch_assoc($result);
85
+	if ($row["seeds"] > 5) //if there are seeds available, don't use HTTP seeding
86
+		reject();
87
+}
88
+if (mysql_num_rows($result) == 0) //hash isn't even in database!
89
+{
90
+	//reject em!
91
+	reject();
92
+}
93
+
94
+Unlock("WebSeedLock");
95
+
96
+// Max uploads check
97
+for ($lockno=0; $lockno < $GLOBALS["max_uploads"]; $lockno++)
98
+	if (Lock("WebSeed--$lockno", 0))
99
+		break;
100
+//error_log("Lockno=$lockno");
101
+if ($lockno == $GLOBALS["max_uploads"])
102
+	reject();
103
+
104
+
105
+// Get to work!
106
+$result = mysql_query("SELECT ".$prefix."summary.piecelength, ".$prefix."summary.numpieces FROM ".$prefix."summary WHERE info_hash=\"$info_hash\"");
107
+if (!$result)
108
+	reject("500 Internal Server Error");
109
+
110
+$config = mysql_fetch_assoc($result);
111
+if (!$config)
112
+	reject("403 Forbidden");
113
+
114
+$result = mysql_query("SELECT * FROM ".$prefix."webseedfiles WHERE info_hash=\"$info_hash\" ORDER BY fileorder");
115
+
116
+if ($config["numpieces"] < $piece || $piece < 0)
117
+	reject("400 Bad Request");
118
+
119
+
120
+// Data to return, and accounting.
121
+$xmit = "";
122
+$xmitbytes = 0;
123
+
124
+while ($row = mysql_fetch_assoc($result))
125
+{
126
+	if (!($piece >= $row["startpiece"] && $piece <= $row["endpiece"]))
127
+		continue;
128
+
129
+	$offset = ($row["startpiece"] == $piece) ? 0 : (($piece - $row["startpiece"])*$config["piecelength"] - $row["startpieceoffset"]);
130
+	$fd = fopen($row["filename"], "rb") or reject("500 Internal Server Error");
131
+	if (fseek($fd, $offset) != 0)
132
+		reject("500 Internal Server Error");
133
+	$data = fread($fd, $config["piecelength"]-$xmitbytes);
134
+	if ($data === false)
135
+		reject("500 Internal Server Error");
136
+	$xmit .= $data;
137
+	$xmitbytes += strlen($data);
138
+	if ($xmitbytes == $config["piecelength"])
139
+		break;
140
+	fclose($fd);
141
+}
142
+
143
+
144
+// Header is most likely already: 200 Ok
145
+
146
+//error_log("Send length: $xmitbytes == ".strlen($xmit));
147
+
148
+if (isset($_GET["ranges"]))
149
+{
150
+	$myxmit = "";
151
+	$ranges = explode(",", $_GET["ranges"]);
152
+	foreach ($ranges as $blocks)
153
+	{
154
+		$startstop = explode("-", $blocks);
155
+		if (!is_numeric($startstop[0]) || !is_numeric($startstop[1]))
156
+			reject("400 Bad Request");
157
+		if (isset($startstop[2]))
158
+			reject("400 Bad Request");
159
+		$start = $startstop[0];
160
+		$stop = $startstop[1];
161
+		if ($start > $stop)
162
+			reject("400 Bad Request");
163
+		$myxmit .= substr($xmit, $start, $stop-$start+1);
164
+	}
165
+	header("Content-Length: ".strlen($myxmit));
166
+	mysql_query("UPDATE ".$prefix."speedlimit SET uploaded=uploaded+".strlen($myxmit));
167
+	echo $myxmit;
168
+}
169
+else
170
+{
171
+	mysql_query("UPDATE ".$prefix."speedlimit SET uploaded=uploaded+$xmitbytes");
172
+	header("Content-Length: $xmitbytes");
173
+	echo $xmit;
174
+}
175
+
176
+Unlock("WebSeed--$lockno");
177
+exit;
178
+
179
+?>
0 180
new file mode 100644
... ...
@@ -0,0 +1,249 @@
1
+<?php
2
+/*
3
+ * A PHP implementation of the Secure Hash Algorithm, SHA-1, as defined
4
+ * in FIPS PUB 180-1
5
+ * Adjusted from the Javascript implementation by Joror (daan@parse.nl).
6
+ *
7
+ * Javascript Version 2.1 Copyright Paul Johnston 2000 - 2002.
8
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
9
+ * Distributed under the BSD License
10
+ * See http://pajhome.org.uk/crypt/md5 for details.
11
+ */
12
+
13
+class Sha1Lib
14
+{
15
+	/*
16
+	 * Configurable variables. You may need to tweak these to be compatible with
17
+	 * the server-side, but the defaults work in most cases.
18
+	 */
19
+	var $hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
20
+	var $b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
21
+	var $chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
22
+	
23
+	/*
24
+	 * These are the functions you'll usually want to call
25
+	 * They take string arguments and return either hex or base-64 encoded strings
26
+	 */
27
+	function hex_sha1($s){return $this->binb2hex($this->core_sha1($this->str2binb($s),strlen($s) * $this->chrsz));}
28
+	function b64_sha1($s){return $this->binb2b64($this->core_sha1($this->str2binb($s),strlen($s) * $this->chrsz));}
29
+	function str_sha1($s){return $this->binb2str($this->core_sha1($this->str2binb($s),strlen($s) * $this->chrsz));}
30
+	function hex_hmac_sha1($key, $data){ return $this->binb2hex($this->core_hmac_sha1($key, $data));}
31
+	function b64_hmac_sha1($key, $data){ return $this->binb2b64($this->core_hmac_sha1($key, $data));}
32
+	function str_hmac_sha1($key, $data){ return $this->binb2str($this->core_hmac_sha1($key, $data));}
33
+	
34
+	/*
35
+	 * Perform a simple self-test to see if the VM is working
36
+	 */
37
+	function sha1_vm_test()
38
+	{
39
+		return $this->hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
40
+	}
41
+	
42
+	/*
43
+	 * Calculate the SHA-1 of an array of big-endian words, and a bit $length
44
+	 */
45
+	function core_sha1($x, $len)
46
+	{
47
+		/* append padding */
48
+		$x[$len >> 5] |= 0x80 << (24 - $len % 32);
49
+		$x[(($len + 64 >> 9) << 4) + 15] = $len;
50
+	
51
+		$w = Array();
52
+		$a =  1732584193;
53
+		$b = -271733879;
54
+		$c = -1732584194;
55
+		$d =  271733878;
56
+		$e = -1009589776;
57
+	
58
+		for($i = 0; $i < sizeof($x); $i += 16)
59
+		{
60
+			$olda = $a;
61
+			$oldb = $b;
62
+			$oldc = $c;
63
+			$oldd = $d;
64
+			$olde = $e;
65
+	
66
+			for($j = 0; $j < 80; $j++)
67
+			{
68
+				if ($j < 16) 
69
+					$w[$j] = $x[$i + $j];
70
+				else 
71
+					$w[$j] = $this->rol($w[$j-3] ^ $w[$j-8] ^ $w[$j-14] ^ $w[$j-16], 1);
72
+					
73
+				$t = $this->safe_add(	$this->safe_add($this->rol($a, 5), $this->sha1_ft($j, $b, $c, $d)), 
74
+										$this->safe_add($this->safe_add($e, $w[$j]), $this->sha1_kt($j)));
75
+				$e = $d;
76
+				$d = $c;
77
+				$c = $this->rol($b, 30);
78
+				$b = $a;
79
+				$a = $t;
80
+			}
81
+
82
+			$a = $this->safe_add($a, $olda);
83
+			$b = $this->safe_add($b, $oldb);
84
+			$c = $this->safe_add($c, $oldc);
85
+			$d = $this->safe_add($d, $oldd);
86
+			$e = $this->safe_add($e, $olde);
87
+		}
88
+		
89
+		return Array($a, $b, $c, $d, $e);
90
+	}
91
+	
92
+	/*
93
+	 * Joror: PHP does not have the java(script) >>> operator, so this is a 
94
+	 * replacement function. Credits to Terium.
95
+	 */
96
+	function zerofill_rightshift($a, $b) 
97
+	{ 
98
+		$z = hexdec(80000000); 
99
+		if ($z & $a) 
100
+		{ 
101
+			$a >>= 1; 
102
+			$a &= (~ $z); 
103
+			$a |= 0x40000000; 
104
+			$a >>= ($b-1); 
105
+		} 
106
+		else 
107
+		{ 
108
+			$a >>= $b; 
109
+		} 
110
+		return $a; 
111
+	}
112
+	
113
+	/*
114
+	 * Perform the appropriate triplet combination function for the current
115
+	 * iteration
116
+	 */
117
+	function sha1_ft($t, $b, $c, $d)
118
+	{
119
+		if($t < 20) return ($b & $c) | ((~$b) & $d);
120
+		if($t < 40) return $b ^ $c ^ $d;
121
+		if($t < 60) return ($b & $c) | ($b & $d) | ($c & $d);
122
+		return $b ^ $c ^ $d;
123
+	}
124
+	
125
+	/*
126
+	 * Determine the appropriate additive constant for the current iteration
127
+	 * Silly php does not understand the inline-if operator well when nested,
128
+	 * so that's why it's ()ed now.
129
+	 */
130
+	function sha1_kt($t)
131
+	{
132
+		return ($t < 20) ?  1518500249 : (($t < 40) ?  1859775393 :
133
+				(($t < 60) ? -1894007588 : -899497514));
134
+	}  
135
+	
136
+	/*
137
+	 * Calculate the HMAC-SHA1 of a key and some data
138
+	 */
139
+	function core_hmac_sha1($key, $data)
140
+	{
141
+		$bkey = $this->str2binb($key);
142
+		if(sizeof($bkey) > 16) $bkey = $this->core_sha1($bkey, sizeof($key) * $this->chrsz);
143
+	
144
+		$ipad = Array();
145
+		$opad = Array();
146
+		
147
+		for($i = 0; $i < 16; $i++) 
148
+		{
149
+			$ipad[$i] = $bkey[$i] ^ 0x36363636;
150
+			$opad[$i] = $bkey[$i] ^ 0x5C5C5C5C;
151
+		}
152
+	
153
+		$hash = $this->core_sha1(array_merge($ipad,$this->str2binb($data)), 512 + sizeof($data) * $this->chrsz);
154
+		return $this->core_sha1(array_merge($opad,$hash), 512 + 160);
155
+	}
156
+	
157
+	/*
158
+	 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
159
+	 * to work around bugs in some JS interpreters.
160
+	 */
161
+	function safe_add($x, $y)
162
+	{
163
+		$lsw = ($x & 0xFFFF) + ($y & 0xFFFF);
164
+		$msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16);
165
+		return ($msw << 16) | ($lsw & 0xFFFF);
166
+	}
167
+	
168
+	/*
169
+	 * Bitwise rotate a 32-bit number to the left.
170
+	 */
171
+	function rol($num, $cnt)
172
+	{
173
+		return ($num << $cnt) | $this->zerofill_rightshift($num, (32 - $cnt));
174
+	}
175
+	
176
+	/*
177
+	 * Convert an 8-bit or 16-bit string to an array of big-endian words
178
+	 * In 8-bit function, characters >255 have their hi-byte silently ignored.
179
+	 */
180
+	function str2binb($str)
181
+	{
182
+		$bin = Array();
183
+		$mask = (1 << $this->chrsz) - 1;
184
+		for($i = 0; $i < strlen($str) * $this->chrsz; $i += $this->chrsz)
185
+			$bin[$i >> 5] |= (ord($str{$i / $this->chrsz}) & $mask) << (24 - $i%32);
186
+		
187
+		return $bin;
188
+	}
189
+	
190
+	/*
191
+	 * Convert an array of big-endian words to a string
192
+	 */
193
+	function binb2str($bin)
194
+	{
195
+		$str = "";
196
+		$mask = (1 << $this->chrsz) - 1;
197
+		for($i = 0; $i < sizeof($bin) * 32; $i += $this->chrsz)
198
+			$str .= chr($this->zerofill_rightshift($bin[$i>>5], 24 - $i%32) & $mask);
199
+		return $str;
200
+	}
201
+	
202
+	/*
203
+	 * Convert an array of big-endian words to a hex string.
204
+	 */
205
+	function binb2hex($binarray)
206
+	{
207
+		$hex_tab = $this->hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
208
+		$str = "";
209
+		for($i = 0; $i < sizeof($binarray) * 4; $i++)
210
+		{
211
+			$str .= $hex_tab{($binarray[$i>>2] >> ((3 - $i%4)*8+4)) & 0xF} .
212
+					$hex_tab{($binarray[$i>>2] >> ((3 - $i%4)*8  )) & 0xF};
213
+		}
214
+		
215
+		return $str;
216
+	}
217
+	
218
+	/*
219
+	 * Convert an array of big-endian words to a base-64 string
220
+	 */
221
+	function binb2b64($binarray)
222
+	{
223
+		$tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
224
+		$str = "";
225
+		for($i = 0; i < sizeof($binarray) * 4; $i += 3)
226
+		{
227
+			$triplet = 	((($binarray[$i   >> 2] >> 8 * (3 -  $i   %4)) & 0xFF) << 16)
228
+						| ((($binarray[$i+1 >> 2] >> 8 * (3 - ($i+1)%4)) & 0xFF) << 8 )
229
+						|  (($binarray[$i+2 >> 2] >> 8 * (3 - ($i+2)%4)) & 0xFF);
230
+			for($j = 0; $j < 4; $j++)
231
+			{
232
+				if($i * 8 + $j * 6 > sizeof($binarray) * 32) $str .= $this->b64pad;
233
+				else $str .= $tab{($triplet >> 6*(3-j)) & 0x3F};
234
+			}
235
+		}
236
+		return $str;
237
+	}
238
+}
239
+
240
+if ( !function_exists('sha1') )
241
+{
242
+	function sha1( $string, $raw_output = false )
243
+	{
244
+		$library = new Sha1Lib();
245
+		
246
+		return $raw_output ? $library->str_sha1($string) : $library->hex_sha1($string);
247
+	}
248
+}
249
+?>
0 250
\ No newline at end of file
1 251
new file mode 100644
... ...
@@ -0,0 +1,182 @@
1
+<?php
2
+require ("config.php");
3
+require_once ("funcsv2.php");
4
+//Check session
5
+session_start();
6
+
7
+if (!$_SESSION['admin_logged_in'])
8
+{
9
+	//check fails
10
+	header("Location: authenticate.php?status=session");
11
+	exit();
12
+}
13
+?>
14
+
15
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
16
+
17
+<html>
18
+<head>
19
+	<title>Tracker User Statistics</title>
20
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
21
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
22
+</head>
23
+<body>
24
+<h1>Tracker User Statistics</h1>
25
+
26
+<form action="<?php echo htmlentities($_SERVER['PHP_SELF']);?>" method="POST">
27
+Filename Search:<input type="text" name="filename_search" size="40"<?php if (isset($_POST["filename_search"]))echo " value=\"" . filterData($_POST["filename_search"]) . "\"";?>>
28
+<input type="submit" value="Search">
29
+</form>
30
+<br>
31
+
32
+<?php
33
+require_once ("config.php");
34
+require_once ("funcsv2.php");
35
+
36
+//connect to database and grab each torrent in database
37
+if ($GLOBALS["persist"])
38
+	$db = mysql_pconnect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
39
+else
40
+	$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
41
+mysql_select_db($database) or die(errorMessage() . "Tracker error: can't open database $database - " . mysql_error() . "</p>");
42
+
43
+//Display search information
44
+if (isset($_POST["filename_search"]) && $_POST["filename_search"] != "")
45
+{
46
+	echo "<h2 align=\"center\">Search Results:</h2>";
47
+	$query = "SELECT * FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash WHERE ".$prefix."namemap.filename REGEXP \"$_POST[filename_search]\" ORDER BY ".$prefix."namemap.filename";
48
+}
49
+else //display everything
50
+{
51
+	$scriptname = htmlentities($_SERVER['PHP_SELF']) . "?";
52
+	
53
+	if (!isset($_GET["activeonly"])) 
54
+		echo "<a href=\"$scriptname" . "activeonly=yes\">Show only torrents with seeders/leechers</a>\n";
55
+	else
56
+	{
57
+		echo "<a href=\"$scriptname\">Show all torrents</a>\n";
58
+		$scriptname = $scriptname . "activeonly=yes&";	
59
+	}
60
+
61
+	if (isset($_GET["activeonly"]))
62
+		$where = " WHERE leechers+seeds > 0";
63
+	else
64
+		$where = " ";
65
+	
66
+	$query = "SELECT COUNT(*) FROM ".$prefix."summary $where";
67
+	$results = mysql_query($query);
68
+	$res = mysql_result($results,0,0);
69
+	
70
+	echo "<p align='center'>Page: \n";
71
+	$count = 0;
72
+	$page = 1;
73
+	while($count < $res)
74
+	{
75
+		if (isset($_GET["page_number"]) && $page == $_GET["page_number"])
76
+			echo "<b><a href=\"$scriptname" . "page_number=$page\">($page)</a></b>-\n";
77
+		else if (!isset($_GET["page_number"]) && $page == 1)
78
+			echo "<b><a href=\"$scriptname" . "page_number=$page\">($page)</a></b>-\n";
79
+		else
80
+			echo "<a href=\"$scriptname" . "page_number=$page\">$page</a>-\n";
81
+		$page++;
82
+		$count = $count + ($GLOBALS["statspagelimitspecify"]);
83
+	}
84
+	echo "</p>\n";
85
+	
86
+	if (!isset($_GET["page_number"]))
87
+		$query = "SELECT * FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash $where ORDER BY ".$prefix."namemap.filename LIMIT 0,${GLOBALS['statspagelimitspecify']}";
88
+	else
89
+	{
90
+		$page_limit = ($_GET["page_number"] - 1) * ($GLOBALS["statspagelimitspecify"]);
91
+		$query = "SELECT * FROM ".$prefix."summary LEFT JOIN ".$prefix."namemap ON ".$prefix."summary.info_hash = ".$prefix."namemap.info_hash $where ORDER BY ".$prefix."namemap.filename LIMIT $page_limit,${GLOBALS['statspagelimitspecify']}";
92
+	}
93
+}
94
+
95
+$results = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
96
+
97
+while ($data = mysql_fetch_row($results))
98
+{
99
+	$xhash = "x" . $data[0];
100
+	$query2 = "SELECT * FROM ".$prefix."$xhash";
101
+	$results2 = mysql_query($query2) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
102
+
103
+	if (mysql_num_rows($results2) == 0 && isset($_GET["activeonly"]))
104
+		break;
105
+	else
106
+	{
107
+		echo "<hr><table>\n";
108
+		echo "<tr><th>Info Hash</th><th>Filename</th><th>URL</th><th>File Size</th><th>Publication Date</th></tr>\n";
109
+		echo "<tr><td>" . $data[0] . "</td><td>" . $data[12] . "</td><td>\n";
110
+		if (Substr($data[13], 0, 7) == "http://")
111
+			echo "<a href=\"" . $data[13] . "\">" . $data[13] . "</a>\n";
112
+		else
113
+			echo $data[13];
114
+		echo "</td><td>" . bytesToString($data[14]) . "</td>\n";
115
+		echo "<td>" . $data[15] . "</td></tr>\n";
116
+		echo "</table>\n";
117
+	}
118
+
119
+	echo "<table>\n";
120
+	echo "<tr><th class=\"subheader\">IP Address</th><th class=\"subheader\">Data Left to Download</th><th class=\"subheader\" width=200>Percent Finished</th><th class=\"subheader\">Port</th><th class=\"subheader\">Last Update</th><th class=\"subheader\">NAT User</th></tr>\n";
121
+	while ($data2 = mysql_fetch_row($results2))
122
+	{
123
+		//grab information on each user
124
+		echo "<tr><td>" . $data2[2] . "</td>\n";
125
+		echo "<td>" . bytesToString($data2[1]) . "</td>\n";
126
+
127
+		//calculate percent done for user
128
+		$percent_done = 1.00;
129
+		if ($data2[1] != 0) //only run calculation if they are still downloading
130
+		{
131
+			$size_in_bytes = $data[14];
132
+			if ($size_in_bytes == 0) //thou shalt not divide by zero
133
+				$percent_done = 0;
134
+			else
135
+				$percent_done = round(($size_in_bytes - $data2[1]) / $size_in_bytes, 3);
136
+		}
137
+
138
+		?>
139
+		<td>
140
+		<table class="percentages" cellspacing="0">
141
+		<tr>
142
+		<td align="right" class="percent" width="<?php echo round($percent_done * 200, 0); ?>" height="15">
143
+		<?php if ($percent_done > .5) echo $percent_done * 100 . "%"; ?>
144
+		</td>
145
+		<td align="left" class="percentleft" width="<?php echo 200 - round($percent_done * 200, 0); ?>" height="15">
146
+		<?php if ($percent_done <= .5) echo $percent_done * 100 . "%"; ?>		
147
+		</td>
148
+		</tr>
149
+		</table>
150
+		</td>
151
+		<?php
152
+		echo "<td>" . $data2[3] . "</td>\n"; //port
153
+		echo "<td>" . date('g:ia m-d-Y', $data2[5]) . "</td>\n"; //last time check-in
154
+		echo "<td>" . $data2[7] . "</td>\n"; //NAT user
155
+		echo "</tr>\n";
156
+	}
157
+	echo "</table><br>\n";
158
+}
159
+echo "<hr>";
160
+if (!isset($_POST["filename_search"]))
161
+{
162
+	echo "<p align='center'>Page: \n";
163
+	$count = 0;
164
+	$page = 1;
165
+	while($count < $res)
166
+	{
167
+	if (isset($_GET["page_number"]) && $page == $_GET["page_number"])
168
+		echo "<b><a href=\"$scriptname" . "page_number=$page\">($page)</a></b>-\n";
169
+	else if (!isset($_GET["page_number"]) && $page == 1)
170
+		echo "<b><a href=\"$scriptname" . "page_number=$page\">($page)</a></b>-\n";
171
+	else
172
+		echo "<a href=\"$scriptname" . "page_number=$page\">$page</a>-\n";
173
+	$page++;
174
+	$count = $count + ($GLOBALS["statspagelimitspecify"]);
175
+	}
176
+	echo "</p>\n";
177
+}
178
+?>
179
+
180
+<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Return to Admin Page</a>
181
+</body>
182
+</html>
0 183
new file mode 100644
... ...
@@ -0,0 +1,484 @@
1
+<?php
2
+
3
+require_once("BDecode.php");
4
+require_once("BEncode.php");
5
+
6
+function classicoutput($array, $infohash)
7
+{
8
+
9
+	if (isset($array["info"]["pieces"]))
10
+		$array["info"]["pieces"] = "<i>Checksum data (" . strlen ($array["info"]["pieces"]) / 20 . " pieces)</i>";
11
+
12
+	echo "Info hash: <TT>$infohash</TT><br>";
13
+	echo "<pre>";
14
+	print_r(cleaner($array));
15
+	echo "</pre>";
16
+}
17
+
18
+function announceoutput($array)
19
+{
20
+	if (!isset($array["peers"][0]))
21
+	{
22
+		echo "Not a tracker announce block. Falling back on classic.<br><br>";
23
+		classicoutput($array, "(Not checked)");
24
+		exit;
25
+	}
26
+	echo "<h2>Client configuration options</h2>";
27
+	echo "<table border=0 cellpadding=2 cellspacing=2>";
28
+	foreach ($array as $left => $right)
29
+	{
30
+		if ($left == "peers")
31
+			continue;
32
+		if (is_array($right))
33
+			$myright = "<I>Error</I>";
34
+		else
35
+			$myright = $right;
36
+		echo "<tr><td align=right>".$left."</td><td>=</td><td>".$myright."</td></tr>\n";
37
+	}
38
+	echo "</table><br><h2>Peers</h2><pre>";
39
+	foreach ($array["peers"] as $data)
40
+	{
41
+		if (!is_array($data)) // special case: [0] == true  means empty list
42
+		{
43
+			echo "(Empty results)\n";
44
+			break;
45
+		}
46
+		echo 		bin2hex($data["peer id"])." at ".$data["ip"].":".$data["port"]."\n";
47
+	}
48
+	echo "</pre>";
49
+}
50
+
51
+function escapeURL($url)
52
+{
53
+	$ret = "";
54
+	$i=0;
55
+	while (strlen($url) > $i)
56
+	{
57
+		$ret .= "%".$url[$i].$url[$i + 1];
58
+		$i+=2;
59
+	}
60
+	return $ret;
61
+}
62
+
63
+
64
+function stringcleaner($str)
65
+{
66
+	/* WARNING:
67
+	
68
+	It appears PHP doesn't handle null bytes in the key portion
69
+	of string-indexed arrays. $array["abcd\0e"] = $something
70
+	will find itself with only 4 letters in the key. This may
71
+	cause some confusion when using /scrape, for example.
72
+	
73
+	*/
74
+
75
+	$len = strlen($str);
76
+	for ($i=0; $i < $len; $i ++)
77
+	{
78
+		if (ord($str[$i]) < 32 || ord($str[$i]) > 128)
79
+			return "<B>".bin2hex($str)."</B>";
80
+	}
81
+	return $str;
82
+}
83
+
84
+function cleaner($array)
85
+{
86
+	if (!is_array($array))
87
+		return $array;
88
+	$newarray = array();
89
+	foreach($array as $left => $right)
90
+	{
91
+		if (is_string($left))
92
+			$newleft = stringcleaner(stripslashes($left));
93
+		else
94
+			$newleft = $left;
95
+
96
+		if (is_string($right))
97
+			$newright = stringcleaner($right);
98
+		else if (is_array($right))
99
+			$newright = cleaner($right);
100
+		else
101
+			$newright = $right;
102
+
103
+		$newarray[$newleft] = $newright;
104
+	}
105
+	return $newarray;
106
+}
107
+
108
+
109
+if (isset($_POST["output"]))
110
+{
111
+	if (!is_numeric($_POST["output"]))
112
+		$output = -1;
113
+	else
114
+		$output = $_POST["output"];
115
+	if ($output > 3 || $output < -1)
116
+		$output = -1;
117
+
118
+
119
+}
120
+else if (isset($_GET["style"]))
121
+	$output = $_GET["style"];
122
+else
123
+	$output = -1;
124
+
125
+//used by index.php to show information on torrent
126
+if (isset($_POST["hash"]))
127
+{
128
+	if (!isset($status)) //not coming from newtorrents page
129
+	{
130
+	?>
131
+	<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
132
+	<html>
133
+	<head>
134
+		<title>Torrent Information</title>
135
+		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
136
+		<link rel="stylesheet" type="text/css" href="./css/style.css" />
137
+	</head>
138
+	<body>
139
+	<?php
140
+	}
141
+	//lookup file
142
+	require_once("config.php");
143
+	require_once("funcsv2.php");
144
+	//connect to DB
145
+	if ($GLOBALS["persist"])
146
+		$db = mysql_pconnect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
147
+	else
148
+		$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
149
+	mysql_select_db($database) or die(errorMessage() . "Tracker error: can't open database $database - " . mysql_error() . "</p>");
150
+	$query = "SELECT filename FROM ".$prefix."namemap WHERE info_hash = '" . $_POST["hash"] . "'";
151
+	$results = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
152
+	$data = mysql_fetch_row($results);
153
+	//find filename and set it
154
+	$_FILES["torrent"]["tmp_name"] = "torrents/" . $data[0] . ".torrent";
155
+	if (!isset($status))
156
+		echo "<h1>" . $data[0] . "</h1>"; 
157
+	echo "<a href=\"index.php\"><img src=\"images/stats.png\" border=\"0\" class=\"icon\" alt=\"Tracker Statistics\" title=\"Tracker Statistics\" /></a><a href=\"index.php\">Return to Statistics Page</a><br>\n";
158
+}
159
+
160
+//main displaying and processing
161
+if (isset($_FILES["torrent"]) || isset($_POST["url"]) || isset($_GET["url"]))
162
+{
163
+	if (strlen($_FILES["torrent"]["tmp_name"]) > 0 && file_exists($_FILES["torrent"]["tmp_name"])) //for DumpTorrentCGI.php, and index.php
164
+	{
165
+		$fd = fopen($_FILES["torrent"]["tmp_name"], "rb") or die(errorMessage() . "File upload error 1</p>");
166
+		if (!isset($_POST["hash"]))
167
+			is_uploaded_file($_FILES["torrent"]["tmp_name"]) or die(errorMessage() . "File upload error 2</p>");
168
+		$alltorrent = fread($fd, filesize($_FILES["torrent"]["tmp_name"]));
169
+		fclose($fd);
170
+	}
171
+	else if (file_exists("torrents/" . $filename . ".torrent")) //for newtorrents.php
172
+	{
173
+		$fd = fopen("torrents/" . $filename . ".torrent", "rb") or die(errorMessage() . "File upload error 1</p>");
174
+		$alltorrent = fread($fd, filesize("torrents/" . $filename . ".torrent"));
175
+		fclose($fd);
176
+	}
177
+	else if (isset($_POST["url"]))
178
+	{
179
+		(strlen($_POST["url"]) > 0) or die(errorMessage() . "Logic error in script.</p>");
180
+		if (strtolower(substr($_POST["url"], 0, 7)) != "http://")
181
+			die(errorMessage() . "Error: you must specify \"http://\" as part of the URL.</p>");
182
+		$fd = fopen($_POST["url"], "rb") or die(errorMessage() . "File download error.</p>");
183
+		$alltorrent = "";
184
+		while (!feof($fd))
185
+		{
186
+			$alltorrent .= fread($fd, 4096);
187
+			if (strlen($alltorrent) > 50000)
188
+				die(errorMessage() . "File too large to download.</p>");
189
+		}
190
+		fclose($fd);
191
+	}
192
+	else if (isset($_GET["url"]))
193
+	{
194
+ 	 	(strlen($_GET["url"]) > 0) or die(errorMessage() . "Logic error in script.</p>");
195
+ 	 	if (strtolower(substr($_GET["url"], 0, 7)) != "http://")
196
+ 	 	        die(errorMessage() . "Error: you must specify \"http://\" as part of the URL</p>");
197
+ 	 	$fd = fopen($_GET["url"], "rb") or die(errorMessage() . "File download error.</p>");
198
+ 	 	$alltorrent = "";
199
+ 	 	while (!feof($fd))
200
+ 	 	{
201
+ 	 	 	$alltorrent .= fread($fd, 4096);
202
+ 	 	 	if (strlen($alltorrent) > 50000)
203
+ 	 	 	        die(errorMessage() . "File too large to download.</p>");
204
+ 	 	}
205
+ 	 	fclose($fd);
206
+
207
+	}
208
+	$array = BDecode($alltorrent);
209
+	if (!isset($array))
210
+	{
211
+		echo errorMessage() . "There was an error handling your uploaded torrent. It may be corrupted. Are you sure it's of type .torrent?</p>";
212
+		exit;
213
+	}
214
+
215
+	if ($array == false)
216
+	{
217
+      echo errorMessage() . "There was an error handling your uploaded torrent. It may be corrupted. Are you sure it's of type .torrent?</p>";             
218
+		exit;
219
+	}
220
+
221
+	// Making torrents look nice: If $array["info"] exists, it is used to calculate
222
+	// an Info_hash value.
223
+
224
+	$infohash = "<I>Not applicable</I>";	
225
+	if (isset($array["info"]))
226
+		if (is_array($array["info"]))
227
+		{
228
+			if (function_exists("sha1"))
229
+				$infohash = @sha1(BEncode($array["info"]));
230
+			else
231
+				$infohash = "(No SHA1 available to calculate info_hash)</TT><br>";
232
+			
233
+			// If the "pieces" section exists, it is replaced by some nice text.
234
+			// The alternative is pages of garbage.
235
+		}
236
+
237
+	// Auto-detect file type
238
+	if ($output == -1)
239
+	{
240
+		if (isset($array["announce"]) && isset($array["info"]))
241
+			$output = 1;
242
+		else if (isset($array["files"]))
243
+			$output = 2;
244
+		else if (isset($array["peers"]))
245
+			$output = 3;
246
+		else
247
+			$output = 0;
248
+	}
249
+
250
+	// Output information.
251
+	if ($output == 0)
252
+	{
253
+		classicoutput($array, $infohash);
254
+	}
255
+
256
+	if ($output == 1)
257
+	{
258
+		if (!isset($array["info"]))
259
+		{
260
+		 	echo "Error: not a torrent file. Falling back on classic.<br><br>";
261
+
262
+		 	classicoutput($array, "<I>Not applicable</I>");
263
+		 	exit;	                
264
+		}
265
+
266
+		echo "<br><h2>Non-file data:</h2>\n";
267
+		echo "<table border=0 cellpadding=2 cellspacing=2><tr>";
268
+		echo "<td align=right>Info hash</td><td>=</td><td><TT>$infohash</TT></td></tr>\n";
269
+		echo "<tr><td align=right>Announce URL(s)</td><td>=</td><td>";
270
+		if (isset($array["announce-list"])) {
271
+			for ($i = 0; $i < count($array["announce-list"]); $i++) {
272
+				echo $array["announce-list"][$i][0] . "<br>";
273
+			}
274
+		} else {
275
+			//single tracker
276
+			echo $array["announce"];
277
+		}
278
+		echo "</td></tr>\n";
279
+
280
+		if (isset($array["creation date"]))
281
+		{
282
+			echo "<tr><td align=right>Creation date</td><td>=</td><td>";
283
+			if (is_numeric($array["creation date"]))
284
+				echo date("F j, Y", $array["creation date"]);
285
+			else
286
+				echo $array["creation date"];
287
+			echo "</td></tr>";
288
+		}
289
+		if ($array["info"]["private"] == 1)
290
+			echo "<tr><td align=right>Private (No DHT Allowed)</td><td>=</td><td>yes</td></tr>\n";
291
+		else
292
+			echo "<tr><td align=right>Private (No DHT Allowed)</td><td>=</td><td>no</td></tr>\n";
293
+
294
+		foreach ($array as $left => $right)
295
+		{
296
+			if ($left == "announce" || $left == "info" || $left == "creation date" || $left == "announce-list")
297
+				continue; // skip
298
+			if ($left == "url-list" || $left == "httpseeds")
299
+			{
300
+				echo "<tr><td align=right>$left</td><td>=</td><td>";
301
+				print_r(cleaner($array[$left]));
302
+				echo "</td></tr>\n";
303
+				continue;
304
+			}
305
+			echo "<tr><td align=right>$left</td><td>=</td><td>".$array[$left]."</td></tr>\n";
306
+		}
307
+		
308
+		echo "</table><br><br><h2>File data:</h2><pre>";
309
+		$info = $array["info"];
310
+		
311
+		$total_size = 0;
312
+		if (isset($info["files"]))
313
+		{
314
+			echo "Directory: ".$info["name"]."\nFiles:\n";
315
+			foreach ($info["files"] as $file)
316
+			{
317
+				if (isset($file["path"][1]))
318
+				{
319
+					echo "    " . $file["path"][0];
320
+					for ($i=1; isset($file["path"][$i]); $i++)
321
+						echo "/".$file["path"][$i];
322
+				}
323
+				else
324
+					echo "    " . $file["path"][0];
325
+				echo "  (".$file["length"]." bytes)\n";
326
+				$total_size = $total_size + $file["length"];
327
+			}
328
+			echo "\n";
329
+		}
330
+		else
331
+		{
332
+			echo "File: ".$info["name"]. " (".$info["length"]." bytes)\n\n";
333
+			$total_size = $info["length"];
334
+		}
335
+		
336
+		echo "Piece length: ".$info["piece length"]."\nNumber of pieces: ". strlen ($array["info"]["pieces"])/20 . "\n\n";
337
+		if ($total_size < 1024) //dealing with bytes
338
+			echo "Total Size: " . $total_size . " bytes</pre>\n";
339
+		elseif ($total_size < 1048576) //dealing with kilobytes
340
+			echo "Total Size: " . round($total_size/1024, 2) . " kilobytes</pre>\n";
341
+		elseif ($total_size < 1073741824) //dealing with megabytes
342
+			echo "Total Size: " . round($total_size/1048576, 2) . " megabytes</pre>\n";
343
+		elseif ($total_size >= 1073741824) //dealing with gigabytes
344
+			echo "Total Size: " . round($total_size/1073741824, 2) . " gigabytes</pre>\n";
345
+	}
346
+
347
+	if ($output == 2)
348
+	{
349
+		if (!isset($array["files"]))
350
+		{
351
+			echo "Error: not /scrape data. Falling back on classic.<br><br>";
352
+			classicoutput($array, $infohash);
353
+			exit;		
354
+		}
355
+		$files = $array["files"];
356
+		
357
+		// Copy and paste from python tracker output, with some 
358
+		// formatting changes
359
+		echo '<table cellpadding=2 cellspacing=2 border=1 summary="files"><tr><th>info hash</th><th align="right">complete</th><th align="right">downloading</th><th>finished downloads</th><th>file name</th></tr>';
360
+		
361
+				
362
+		foreach ($files as $hash => $data)
363
+		{
364
+			echo "<tr><td><TT>".bin2hex(stripslashes($hash))."</TT>";
365
+			echo "</td><td>".$data["complete"]."</td><td>".$data["incomplete"]."</td><td>";
366
+			if (isset($data["downloaded"]))
367
+				echo $data["downloaded"];
368
+			else
369
+				echo "-";
370
+			echo "</td><td>";
371
+			if (isset($data["name"]))
372
+				echo $data["name"];
373
+			else
374
+				echo "(unavailable)";
375
+			echo "</td></tr>";
376
+		}
377
+		echo "</table>";
378
+	}
379
+
380
+	// http://tracker.com:6969/announce
381
+	if ($output == 3)
382
+	{
383
+		announceoutput($array);
384
+	}
385
+
386
+	if (isset($filename) && file_exists("torrents/" . $filename . ".torrent")) //for newtorrents.php
387
+	{
388
+		echo "<a href=\"newtorrents.php\"><img src=\"images/add.png\" border=\"0\" class=\"icon\" alt=\"Add Torrent\" title=\"Add Torrent\" /></a><a href=\"newtorrents.php\">Add Another Torrent</a><br>\n";
389
+		//add in Bittornado HTTP seeding spec
390
+		if (isset($_POST["httpseed"]) && $_POST["httpseed"] == "enabled")
391
+		{
392
+			//add information into database
393
+			$info = $array["info"] or die("Invalid torrent file.");
394
+			
395
+			$fsbase = $_POST["relative_path"];
396
+			
397
+			if (isset($info["files"])) // Multi-file
398
+			{
399
+				if (substr($fsbase, -1) != '/')
400
+					$fsbase .= '/';
401
+				$pieceno = 0;
402
+				$fileno = 0;
403
+				$piecelen = 0;
404
+				
405
+				// Iterate for each file.
406
+				while (isset($info["files"][$fileno]))
407
+				{
408
+					if ($piecelen == $info["piece length"])
409
+					{
410
+						$pieceno++;
411
+						$piecelen = 0;
412
+					}
413
+					$startoffset = $piecelen;
414
+					$startpiece = $pieceno;
415
+					$filesize = $info["files"][$fileno]["length"];
416
+					while (true)
417
+					{
418
+						$sub = min($info["piece length"]-$piecelen, $filesize);
419
+						$piecelen += $sub;
420
+						$filesize -= $sub;
421
+						
422
+						if ($filesize == 0)
423
+							break;
424
+						if ($piecelen == $info["piece length"])
425
+						{
426
+							$pieceno++;
427
+							$piecelen = 0;
428
+						}
429
+						if ($piecelen > $info["piece length"])
430
+							die("Logic error in script. Please report to the author.");
431
+					}
432
+					$filename = $fsbase;
433
+					if (isset($info["files"][$fileno]["path"][1]))
434
+					{
435
+						$filename .= $file["path"][0];
436
+						for ($i=1; isset($info["files"][$fileno]["path"][$i]); $i++)
437
+							$filename .= "/".$info["files"][$fileno]["path"][$i];
438
+					}
439
+					else
440
+						$filename .= $info["files"][$fileno]["path"][0];
441
+					$filename = mysql_real_escape_string($filename);			
442
+					mysql_query("INSERT INTO ".$prefix."webseedfiles (info_hash,filename,startpiece,endpiece,startpieceoffset,fileorder) values (\"$hash\", \"$filename\", $startpiece, $pieceno, $startoffset, $fileno)");
443
+					$fileno++;
444
+				}
445
+			} // end of multi-file section
446
+			else //single file
447
+				mysql_query("INSERT INTO ".$prefix."webseedfiles (info_hash,filename,startpiece,endpiece,startpieceoffset,fileorder) values (\"$hash\", \"".mysql_real_escape_string($fsbase)."\", 0, ". (strlen($array["info"]["pieces"])/20 - 1).", 0, 0)");
448
+		}
449
+		
450
+		if ((isset($_POST["getrightseed"]) && $_POST["getrightseed"] == "enabled") || (isset($_POST["httpseed"]) && $_POST["httpseed"] == "enabled")) //only do one write
451
+		{
452
+			//edit torrent file
453
+			$read_httpseed = fopen("torrents/" . $filename . ".torrent", "rb");
454
+			$binary_data = fread($read_httpseed, filesize("torrents/" . $filename . ".torrent"));
455
+			$data_array = BDecode($binary_data);
456
+			
457
+			if ($_POST["httpseed"] == "enabled")
458
+				$data_array["httpseeds"][0] = $website_url . substr($_SERVER['REQUEST_URI'], 0, -15) . "seed.php";
459
+			if ($_POST["getrightseed"] == "enabled")
460
+				$data_array["url-list"][0] = $_POST["httpftplocation"];
461
+				
462
+			$to_write = BEncode($data_array);
463
+			fclose($read_httpseed);
464
+			//write torrent file
465
+			$write_httpseed = fopen("torrents/" . $filename . ".torrent", "wb");
466
+			fwrite($write_httpseed, $to_write);
467
+			fclose($write_httpseed);
468
+		}
469
+		
470
+		//add in piecelength and number of pieces
471
+		$query = "UPDATE ".$prefix."summary SET piecelength=\"" . $info["piece length"] . "\", numpieces=\"" . strlen ($array["info"]["pieces"])/20 . "\" WHERE info_hash=\"" . $hash . "\"";
472
+		quickQuery($query);
473
+	}
474
+	
475
+	if (!isset($_POST["hash"])) //don't display admin link if coming from index.php
476
+		echo "<a href='admin.php'><img src='images/admin.png' border='0' class='icon' alt='Admin Page' title='Admin Page' /></a><a href='admin.php'>Return to Admin Page</a><br>";
477
+	?>
478
+	<a href="index.php"><img src="images/stats.png" border="0" class="icon" alt="Tracker Statistics" title="Tracker Statistics" /></a><a href="index.php">Return to Statistics Page</a><br>
479
+	</body></html>
480
+	<?php
481
+	exit();
482
+}
483
+
484
+?>
0 485
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+<?php
2
+
3
+header("Location: ../index.php");
4
+
5
+?>
0 6
\ No newline at end of file
1 7
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
1 383
new file mode 100644
... ...
@@ -0,0 +1,94 @@
1
+<?php
2
+
3
+require ("config.php");
4
+require ("funcsv2.php");
5
+//Check session
6
+session_start();
7
+
8
+if (!$_SESSION['admin_logged_in'])
9
+{
10
+	//check fails
11
+	header("Location: authenticate.php?status=session");
12
+	exit();
13
+}
14
+?>
15
+
16
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
17
+
18
+<html>
19
+<head>
20
+	<title>Upload Statistics</title>
21
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
22
+	<link rel="stylesheet" href="./css/style.css" type="text/css" />
23
+</head>
24
+<body>
25
+<h1>Upload Statistics</h1>
26
+<h2>This may be wildly inaccurate because when torrents are deleted, the bittorrent traffic is removed yet the HTTP traffic stays the same.</h2>
27
+<?php
28
+if ($GLOBALS["persist"])
29
+	$db = mysql_pconnect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
30
+else
31
+	$db = mysql_connect($dbhost, $dbuser, $dbpass) or die(errorMessage() . "Tracker error: can't connect to database - " . mysql_error() . "</p>");
32
+mysql_select_db($database) or die(errorMessage() . "Tracker error: can't open database $database - " . mysql_error() . "</p>");
33
+
34
+$query = "SELECT SUM(".$prefix."summary.dlbytes) FROM ".$prefix."summary";
35
+$results = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
36
+$data = mysql_fetch_row($results);
37
+if ($data[0] == null)
38
+	$btuploaded = 0;
39
+else
40
+	$btuploaded = $data[0];
41
+	
42
+$query = "SELECT total_uploaded FROM ".$prefix."speedlimit";
43
+$results = mysql_query($query) or die(errorMessage() . "Can't do SQL query - " . mysql_error() . "</p>");
44
+$data = mysql_fetch_row($results);
45
+$httpuploaded = $data[0];
46
+?>
47
+<br>
48
+<center>
49
+<table>
50
+<tr><th>HTTP Seeding Uploaded<span class="notice">*</span></th>
51
+<th>Bittorrent P2P Seeding Uploaded</th></tr>
52
+<tr>
53
+<td align="center">
54
+<?php
55
+echo bytesToString($httpuploaded);
56
+?>
57
+</td>
58
+<td align="center">
59
+<?php
60
+echo bytesToString($btuploaded);
61
+?>
62
+</td>
63
+</tr>
64
+<tr>
65
+<td align="center">
66
+<?php
67
+if ($httpuploaded + $btuploaded != 0)
68
+	echo round(($httpuploaded / ($httpuploaded + $btuploaded))*100, 2) . "%";
69
+else
70
+	echo "0%";
71
+?>
72
+</td>
73
+<td align="center">
74
+<?php
75
+if ($httpuploaded + $btuploaded != 0)
76
+	echo round(($btuploaded / ($httpuploaded + $btuploaded))*100, 2) . "%";
77
+else
78
+	echo "0%";
79
+?>
80
+</td>
81
+</tr>
82
+</table>
83
+</center>
84
+<p align="center">
85
+<?php
86
+echo "Total Uploaded: " . bytesToString($httpuploaded + $btuploaded);
87
+?>
88
+</p>
89
+<br>
90
+<span class="notice">* - This does not include the GetRight HTTP seeding format which links directly to files.</span>
91
+<br><br>
92
+<a href="admin.php"><img src="images/admin.png" border="0" class="icon" alt="Admin Page" title="Admin Page" /></a><a href="admin.php">Return to Admin Page</a>
93
+</body>
94
+</html>
0 95
\ No newline at end of file
1 96
new file mode 100644
... ...
@@ -0,0 +1,3 @@
1
+<?php
2
+echo "Version: 1.04";
3
+?>
0 4
\ No newline at end of file