version 0.1.2 from tar.gz

This commit is contained in:
Johannes Dewender 2013-01-25 09:41:38 +01:00
parent e7cd059d49
commit 8091d18767
17 changed files with 159 additions and 221 deletions

7
Changelog.txt Normal file → Executable file
View File

@ -2,13 +2,6 @@ PeerTracker Changelog
-------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------
v0.1.3 | 01.20.2010
--------------------------------------------------------------------------------------
* CHANGED
* ALL
* fixed failure to assign returned data from stripslashes
v0.1.2 | 11.18.2009 v0.1.2 | 11.18.2009
-------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------
* CHANGED * CHANGED

0
Install.txt Normal file → Executable file
View File

0
License.txt Normal file → Executable file
View File

2
Readme.txt Normal file → Executable file
View File

@ -1,4 +1,4 @@
PeerTracker - Simple, Efficient and Fast BitTorent Tracker PeerTracker - Simple, Efficient and Fast BitTorent Tracker | Version 0.1.1
-------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------

0
Upgrading.txt Normal file → Executable file
View File

0
Usage.txt Normal file → Executable file
View File

0
help.php Normal file → Executable file
View File

0
mysql/.htaccess Normal file → Executable file
View File

42
mysql/announce.php Normal file → Executable file
View File

@ -2,21 +2,21 @@
// License Information ///////////////////////////////////////////////////////////////////////////// // License Information /////////////////////////////////////////////////////////////////////////////
/* /*
* PeerTracker - OpenSource BitTorrent Tracker * PeerTracker - OpenSource BitTorrent Tracker
* Revision - $Id: announce.php 161 2010-01-20 17:49:50Z trigunflame $ * Revision - $Id: announce.php 124 2009-10-28 19:54:09Z trigunflame $
* Copyright (C) 2009 PeerTracker Team * Copyright (C) 2009 PeerTracker Team
* *
* PeerTracker is free software: you can redistribute it and/or modify * PeerTracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* PeerTracker is distributed in the hope that it will be useful, * PeerTracker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerTracker. If not, see <http://www.gnu.org/licenses/>. * along with PeerTracker. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -36,13 +36,6 @@ require './tracker.mysql.php';
// Verify Request ////////////////////////////////////////////////////////////////////////////////// // Verify Request //////////////////////////////////////////////////////////////////////////////////
// strip auto-escaped data
if (get_magic_quotes_gpc())
{
$_GET['info_hash'] = stripslashes($_GET['info_hash']);
$_GET['peer_id'] = stripslashes($_GET['peer_id']);
}
// 20-bytes - info_hash // 20-bytes - info_hash
// sha-1 hash of torrent metainfo // sha-1 hash of torrent metainfo
if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20) exit; if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20) exit;
@ -53,11 +46,12 @@ if (!isset($_GET['peer_id']) || strlen($_GET['peer_id']) != 20) exit;
// integer - port // integer - port
// port the client is accepting connections from // port the client is accepting connections from
if (!(isset($_GET['port']) && is_numeric($_GET['port']))) tracker_error('client listening port is invalid'); if (!(isset($_GET['port']) && is_numeric($_GET['port']))) tracker_error('client listening port is invalid');
// integer - left // integer - left
// number of bytes left for the peer to download // number of bytes left for the peer to download
if (isset($_GET['left']) && is_numeric($_GET['left'])) $_SERVER['tracker']['seeding'] = ($_GET['left'] > 0 ? 0 : 1); else tracker_error('client data left field is invalid'); if (isset($_GET['left']) && is_numeric($_GET['left'])) $_SERVER['tracker']['seeding'] = ($_GET['left'] > 0 ? 0 : 1);
else tracker_error('client data left field is invalid');
// integer boolean - compact - optional // integer boolean - compact - optional
// send a compact peer response // send a compact peer response
@ -89,23 +83,23 @@ else $_GET['numwant'] += 0;
// Handle Request ////////////////////////////////////////////////////////////////////////////////// // Handle Request //////////////////////////////////////////////////////////////////////////////////
// open database // strip info_hash & peer_id
peertracker::open(); if (get_magic_quotes_gpc())
{
stripslashes($_GET['info_hash']);
stripslashes($_GET['peer_id']);
}
// make info_hash & peer_id SQL friendly // make info_hash & peer_id SQL friendly
$_GET['info_hash'] = peertracker::$api->escape_sql($_GET['info_hash']); $_GET['info_hash'] = addslashes($_GET['info_hash']);
$_GET['peer_id'] = peertracker::$api->escape_sql($_GET['peer_id']); $_GET['peer_id'] = addslashes($_GET['peer_id']);
// announce peers
// announce
peertracker::open();
peertracker::peers(); peertracker::peers();
// track client
peertracker::event(); peertracker::event();
// garbage collection
peertracker::clean(); peertracker::clean();
// close database
peertracker::close(); peertracker::close();
?> ?>

30
mysql/scrape.php Normal file → Executable file
View File

@ -2,21 +2,21 @@
// License Information ///////////////////////////////////////////////////////////////////////////// // License Information /////////////////////////////////////////////////////////////////////////////
/* /*
* PeerTracker - OpenSource BitTorrent Tracker * PeerTracker - OpenSource BitTorrent Tracker
* Revision - $Id: scrape.php 161 2010-01-20 17:49:50Z trigunflame $ * Revision - $Id: scrape.php 125 2009-10-29 01:02:21Z trigunflame $
* Copyright (C) 2009 PeerTracker Team * Copyright (C) 2009 PeerTracker Team
* *
* PeerTracker is free software: you can redistribute it and/or modify * PeerTracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* PeerTracker is distributed in the hope that it will be useful, * PeerTracker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerTracker. If not, see <http://www.gnu.org/licenses/>. * along with PeerTracker. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -37,24 +37,15 @@ require './tracker.mysql.php';
// Verify Request ////////////////////////////////////////////////////////////////////////////////// // Verify Request //////////////////////////////////////////////////////////////////////////////////
// tracker statistics // tracker statistics
if (isset($_GET['stats'])) if (isset($_GET['stats']))
{ {
// open database
peertracker::open();
// display stats // display stats
peertracker::open();
peertracker::stats(); peertracker::stats();
// close database
peertracker::close(); peertracker::close();
// exit immediately
exit; exit;
} }
// strip auto-escaped data
if (get_magic_quotes_gpc()) $_GET['info_hash'] = stripslashes($_GET['info_hash']);
// 20-bytes - info_hash // 20-bytes - info_hash
// sha-1 hash of torrent being tracked // sha-1 hash of torrent being tracked
if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20) if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20)
@ -67,13 +58,12 @@ if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20)
// Handle Request ////////////////////////////////////////////////////////////////////////////////// // Handle Request //////////////////////////////////////////////////////////////////////////////////
// open database // strip info_hash & peer_id
if (get_magic_quotes_gpc()) stripslashes($_GET['info_hash']);
// scrape
peertracker::open(); peertracker::open();
// perform scrape
peertracker::scrape(); peertracker::scrape();
// close database
peertracker::close(); peertracker::close();
?> ?>

121
mysql/tracker.mysql.php Normal file → Executable file
View File

@ -4,7 +4,7 @@
/* /*
* PeerTracker - OpenSource BitTorrent Tracker * PeerTracker - OpenSource BitTorrent Tracker
* Revision - $Id: tracker.mysql.php 148 2009-11-16 23:18:28Z trigunflame $ * Revision - $Id: tracker.mysql.php 154 2009-11-18 07:39:10Z trigunflame $
* Copyright (C) 2009 PeerTracker Team * Copyright (C) 2009 PeerTracker Team
* *
* PeerTracker is free software: you can redistribute it and/or modify * PeerTracker is free software: you can redistribute it and/or modify
@ -49,6 +49,13 @@ $_SERVER['tracker'] = array(
// advanced database options // advanced database options
'db_prefix' => 'pt_', /* name prefixes for the PeerTracker tables */ 'db_prefix' => 'pt_', /* name prefixes for the PeerTracker tables */
'db_persist' => false, /* use persistent connections if available. */ 'db_persist' => false, /* use persistent connections if available. */
// note: most likely there is no need to set this unless your mysql database happens
// to be located on another server and/or you have a lot of incoming connections/s.
// in other words, don't change it unless you know for sure that it is absolutely
// necessary to do so. your http server and mysql server must be tuned correctly,
// otherwise you will not get the performance benefits that you seek from using
// persistent connections.
); );
// Tracker Operations ////////////////////////////////////////////////////////////////////////////// // Tracker Operations //////////////////////////////////////////////////////////////////////////////
@ -56,7 +63,8 @@ $_SERVER['tracker'] = array(
// fatal error, stop execution // fatal error, stop execution
function tracker_error($error) function tracker_error($error)
{ {
exit('d14:failure reason' . strlen($error) . ":{$error}e"); echo 'd14:failure reason' . strlen($error) . ":{$error}e";
exit;
} }
// MySQL Database API ////////////////////////////////////////////////////////////////////////////// // MySQL Database API //////////////////////////////////////////////////////////////////////////////
@ -102,19 +110,14 @@ class peertracker_mysql
{ {
mysql_close($this->db); mysql_close($this->db);
} }
// make sql safe
public function escape_sql($sql)
{
return mysql_real_escape_string($sql, $this->db);
}
// query database // query database
public function query($sql) public function query($sql)
{ {
// note: not checking for error
return mysql_query($sql, $this->db); return mysql_query($sql, $this->db);
} }
// return one row // return one row
public function fetch_once($sql) public function fetch_once($sql)
{ {
@ -134,8 +137,6 @@ class peertracker_mysql
{ {
// fetch peers // fetch peers
$query = mysql_query($sql, $this->db) OR tracker_error('failed to select compact peers'); $query = mysql_query($sql, $this->db) OR tracker_error('failed to select compact peers');
// build response
while($peer = mysql_fetch_row($query)) $peers .= $peer[0]; while($peer = mysql_fetch_row($query)) $peers .= $peer[0];
// cleanup // cleanup
@ -147,8 +148,6 @@ class peertracker_mysql
{ {
// fetch peers // fetch peers
$query = mysql_query($sql, $this->db) OR tracker_error('failed to select peers'); $query = mysql_query($sql, $this->db) OR tracker_error('failed to select peers');
// dotted decimal string ip, 20-byte peer_id, integer port
while($peer = mysql_fetch_row($query)) $response .= 'd2:ip' . strlen($peer[1]) . ":{$peer[1]}" . "7:peer id20:{$peer[0]}4:porti{$peer[2]}ee"; while($peer = mysql_fetch_row($query)) $response .= 'd2:ip' . strlen($peer[1]) . ":{$peer[1]}" . "7:peer id20:{$peer[0]}4:porti{$peer[2]}ee";
// cleanup // cleanup
@ -160,8 +159,6 @@ class peertracker_mysql
{ {
// fetch peers // fetch peers
$query = mysql_query($sql, $this->db) OR tracker_error('failed to select peers'); $query = mysql_query($sql, $this->db) OR tracker_error('failed to select peers');
// dotted decimal string ip, integer port
while($peer = mysql_fetch_row($query)) $response .= 'd2:ip' . strlen($peer[0]) . ":{$peer[0]}4:porti{$peer[1]}ee"; while($peer = mysql_fetch_row($query)) $response .= 'd2:ip' . strlen($peer[0]) . ":{$peer[0]}4:porti{$peer[1]}ee";
// cleanup // cleanup
@ -171,10 +168,8 @@ class peertracker_mysql
// full scrape of all torrents // full scrape of all torrents
public function full_scrape($sql, &$response) public function full_scrape($sql, &$response)
{ {
// fetch scrape // fetch statistics
$query = mysql_query($sql) OR tracker_error('unable to perform a full scrape'); $query = mysql_query($sql) OR tracker_error('unable to perform a full scrape');
// 20-byte info_hash, integer complete, integer downloaded, integer incomplete
while ($scrape = mysql_fetch_row($query)) $response .= "20:{$scrape[0]}d8:completei{$scrape[1]}e10:downloadedi0e10:incompletei{$scrape[2]}ee"; while ($scrape = mysql_fetch_row($query)) $response .= "20:{$scrape[0]}d8:completei{$scrape[1]}e10:downloadedi0e10:incompletei{$scrape[2]}ee";
// cleanup // cleanup
@ -220,15 +215,10 @@ class peertracker_mysqli
$this->db->close(); $this->db->close();
} }
// make sql safe
public function escape_sql($sql)
{
return $this->db->real_escape_string($sql);
}
// query database // query database
public function query($sql) public function query($sql)
{ {
// note: not checking for error
return $this->db->query($sql); return $this->db->query($sql);
} }
@ -251,8 +241,6 @@ class peertracker_mysqli
{ {
// fetch peers // fetch peers
$query = $this->db->query($sql) OR tracker_error('failed to select compact peers'); $query = $this->db->query($sql) OR tracker_error('failed to select compact peers');
// build response
while($peer = $query->fetch_row()) $peers .= $peer[0]; while($peer = $query->fetch_row()) $peers .= $peer[0];
// cleanup // cleanup
@ -264,8 +252,6 @@ class peertracker_mysqli
{ {
// fetch peers // fetch peers
$query = $this->db->query($sql) OR tracker_error('failed to select peers'); $query = $this->db->query($sql) OR tracker_error('failed to select peers');
// dotted decimal string ip, 20-byte peer_id, integer port
while($peer = $query->fetch_row()) $response .= 'd2:ip' . strlen($peer[1]) . ":{$peer[1]}" . "7:peer id20:{$peer[0]}4:porti{$peer[2]}ee"; while($peer = $query->fetch_row()) $response .= 'd2:ip' . strlen($peer[1]) . ":{$peer[1]}" . "7:peer id20:{$peer[0]}4:porti{$peer[2]}ee";
// cleanup // cleanup
@ -277,8 +263,6 @@ class peertracker_mysqli
{ {
// fetch peers // fetch peers
$query = $this->db->query($sql) OR tracker_error('failed to select peers'); $query = $this->db->query($sql) OR tracker_error('failed to select peers');
// dotted decimal string ip, integer port
while($peer = $query->fetch_row()) $response .= 'd2:ip' . strlen($peer[0]) . ":{$peer[0]}4:porti{$peer[1]}ee"; while($peer = $query->fetch_row()) $response .= 'd2:ip' . strlen($peer[0]) . ":{$peer[0]}4:porti{$peer[1]}ee";
// cleanup // cleanup
@ -288,10 +272,8 @@ class peertracker_mysqli
// full scrape of all torrents // full scrape of all torrents
public function full_scrape($sql, &$response) public function full_scrape($sql, &$response)
{ {
// fetch scrape // scrape
$query = $this->db->query($sql) OR tracker_error('unable to perform a full scrape'); $query = $this->db->query($sql) OR tracker_error('unable to perform a full scrape');
// 20-byte info_hash, integer complete, integer downloaded, integer incomplete
while ($scrape = $query->fetch_row()) $response .= "20:{$scrape[0]}d8:completei{$scrape[1]}e10:downloadedi0e10:incompletei{$scrape[2]}ee"; while ($scrape = $query->fetch_row()) $response .= "20:{$scrape[0]}d8:completei{$scrape[1]}e10:downloadedi0e10:incompletei{$scrape[2]}ee";
// cleanup // cleanup
@ -352,11 +334,8 @@ class peertracker
// unix timestamp // unix timestamp
$time = time(); $time = time();
// fetch last cleanup time // attempt to locate the last time we ran cleanup
$last = self::$api->fetch_once( $last = self::$api->fetch_once("SELECT value FROM `{$_SERVER['tracker']['db_prefix']}tasks` WHERE name='prune'");
// select last cleanup from tasks
"SELECT value FROM `{$_SERVER['tracker']['db_prefix']}tasks` WHERE name='prune'"
);
// first clean cycle? // first clean cycle?
if (($last[0] + 0) == 0) if (($last[0] + 0) == 0)
@ -403,11 +382,12 @@ class peertracker
// 20-byte info_hash, 20-byte peer_id // 20-byte info_hash, 20-byte peer_id
"VALUES ('{$_GET['info_hash']}', '{$_GET['peer_id']}', '" . "VALUES ('{$_GET['info_hash']}', '{$_GET['peer_id']}', '" .
// 6-byte compacted peer info // 6-byte compacted peer info
self::$api->escape_sql(pack('Nn', ip2long($_GET['ip']), $_GET['port'])) . "', " . addslashes(pack('Nn', ip2long($_GET['ip']), $_GET['port'])) . "', " .
// dotted decimal string ip, integer port, integer state and unix timestamp updated // dotted decimal string ip, integer port
"'{$_GET['ip']}', {$_GET['port']}, {$_SERVER['tracker']['seeding']}, " . time() . '); ' "'{$_GET['ip']}', {$_GET['port']}, " .
// integer state and unix timestamp updated
$_SERVER['tracker']['seeding'] . ', ' . time() . ')'
) OR tracker_error('failed to add new peer data'); ) OR tracker_error('failed to add new peer data');
exit;
} }
// full peer update // full peer update
@ -418,13 +398,13 @@ class peertracker
// update the peers table // update the peers table
"UPDATE `{$_SERVER['tracker']['db_prefix']}peers` " . "UPDATE `{$_SERVER['tracker']['db_prefix']}peers` " .
// set the 6-byte compacted peer info // set the 6-byte compacted peer info
"SET compact='" . self::$api->escape_sql(pack('Nn', ip2long($_GET['ip']), $_GET['port'])) . "SET compact='" . addslashes(pack('Nn', ip2long($_GET['ip']), $_GET['port'])) .
// dotted decimal string ip, integer port // dotted decimal string ip, integer port
"', ip='{$_GET['ip']}', port={$_GET['port']}, " . "', ip='{$_GET['ip']}', port={$_GET['port']}, " .
// integer state and unix timestamp updated // integer state and unix timestamp updated
"state={$_SERVER['tracker']['seeding']}, updated=" . time() . 'state=' . $_SERVER['tracker']['seeding'] . ', updated=' . time() . ' ' .
// that matches the given info_hash and peer_id // that matches the given info_hash and peer_id
" WHERE info_hash='{$_GET['info_hash']}' AND peer_id='{$_GET['peer_id']}'" "WHERE info_hash='{$_GET['info_hash']}' AND peer_id='{$_GET['peer_id']}'"
) OR tracker_error('failed to update peer data'); ) OR tracker_error('failed to update peer data');
} }
@ -433,10 +413,12 @@ class peertracker
{ {
// update peer // update peer
self::$api->query( self::$api->query(
// update the peers table
"UPDATE `{$_SERVER['tracker']['db_prefix']}peers` " .
// set updated to the current unix timestamp // set updated to the current unix timestamp
"UPDATE `{$_SERVER['tracker']['db_prefix']}peers` SET updated=" . time() . 'SET updated=' . time() . ' ' .
// that matches the given info_hash and peer_id // that matches the given info_hash and peer_id
" WHERE info_hash='{$_GET['info_hash']}' AND peer_id='{$_GET['peer_id']}'" "WHERE info_hash='{$_GET['info_hash']}' AND peer_id='{$_GET['peer_id']}'"
) OR tracker_error('failed to update peers last access'); ) OR tracker_error('failed to update peers last access');
} }
@ -458,9 +440,9 @@ class peertracker
// execute peer select // execute peer select
$pState = self::$api->fetch_once( $pState = self::$api->fetch_once(
// select a peer from the peers table // select a peer from the peers table
"SELECT ip, port, state FROM `{$_SERVER['tracker']['db_prefix']}peers` " . "SELECT ip, port, state FROM `{$_SERVER['tracker']['db_prefix']}peers` WHERE " .
// that matches the given info_hash and peer_id // that matches the given info_hash and peer_id
"WHERE info_hash='{$_GET['info_hash']}' AND peer_id='{$_GET['peer_id']}'" "info_hash='{$_GET['info_hash']}' AND peer_id='{$_GET['peer_id']}'"
); );
// process tracker event // process tracker event
@ -504,6 +486,9 @@ class peertracker
"SELECT COUNT(*) FROM `{$_SERVER['tracker']['db_prefix']}peers` WHERE info_hash='{$_GET['info_hash']}'" "SELECT COUNT(*) FROM `{$_SERVER['tracker']['db_prefix']}peers` WHERE info_hash='{$_GET['info_hash']}'"
) OR tracker_error('failed to select peer count'); ) OR tracker_error('failed to select peer count');
// announce response
$response = 'd8:intervali' . $_SERVER['tracker']['announce_interval'] . 'e12:min intervali' . $_SERVER['tracker']['min_interval'] . 'e5:peers';
// select // select
$sql = 'SELECT ' . $sql = 'SELECT ' .
// 6-byte compacted peer info // 6-byte compacted peer info
@ -525,22 +510,15 @@ class peertracker
mt_rand(0, ($total[0]-$_GET['numwant'])) mt_rand(0, ($total[0]-$_GET['numwant']))
) )
); );
// begin response
$response = 'd8:intervali' . $_SERVER['tracker']['announce_interval'] .
'e12:min intervali' . $_SERVER['tracker']['min_interval'] .
'e5:peers';
// compact announce // compact announce
if ($_GET['compact']) if ($_GET['compact'])
{ {
// peers list // fetch peers
$peers = ''; $peers = '';
// build response
self::$api->peers_compact($sql, $peers); self::$api->peers_compact($sql, $peers);
// 6-byte compacted peer info // encoded string of peers in compact form
$response .= strlen($peers) . ':' . $peers; $response .= strlen($peers) . ':' . $peers;
} }
// dictionary announce // dictionary announce
@ -558,7 +536,7 @@ class peertracker
$response .= 'e'; $response .= 'e';
} }
// send response // respond asap
echo $response . 'e'; echo $response . 'e';
// cleanup // cleanup
@ -581,30 +559,29 @@ class peertracker
// from peers // from peers
"FROM `{$_SERVER['tracker']['db_prefix']}peers` " . "FROM `{$_SERVER['tracker']['db_prefix']}peers` " .
// that match info_hash // that match info_hash
"WHERE info_hash='" . self::$api->escape_sql($_GET['info_hash']) . "'" "WHERE info_hash='" . addslashes($_GET['info_hash']) . "'"
) OR tracker_error('unable to scrape the requested torrent'); );
// 20-byte info_hash, integer complete, integer downloaded, integer incomplete // build response
$response .= "20:{$_GET['info_hash']}d8:completei" . ($scrape[0]+0) . $response .= "20:{$_GET['info_hash']}d8:completei" . ($scrape[0]+0) . 'e10:downloadedi0e10:incompletei' . ($scrape[1]+0) . 'ee';
'e10:downloadedi0e10:incompletei' . ($scrape[1]+0) . 'ee';
} }
// full scrape // full scrape
else else
{ {
// scrape // select
$sql = 'SELECT ' . $sql = 'SELECT ' .
// info_hash, total seeders and leechers // total seeders and leechers
'info_hash, SUM(state=1), SUM(state=0) ' . 'info_hash, SUM(state=1), SUM(state=0) ' .
// from peers // from peers
"FROM `{$_SERVER['tracker']['db_prefix']}peers` " . "FROM `{$_SERVER['tracker']['db_prefix']}peers` " .
// grouped by info_hash // grouped by info_hash
'GROUP BY info_hash'; 'GROUP BY info_hash';
// build response // scrape
self::$api->full_scrape($sql, $response); self::$api->full_scrape($sql, $response);
} }
// send response // respond asap
echo $response . 'ee'; echo $response . 'ee';
} }
@ -628,7 +605,7 @@ class peertracker
case 'xml': case 'xml':
header('Content-Type: text/xml'); header('Content-Type: text/xml');
echo '<?xml version="1.0" encoding="ISO-8859-1"?>' . echo '<?xml version="1.0" encoding="ISO-8859-1"?>' .
'<tracker version="$Id: tracker.mysql.php 148 2009-11-16 23:18:28Z trigunflame $">' . '<tracker version="$Id: tracker.mysql.php 154 2009-11-18 07:39:10Z trigunflame $">' .
'<peers>' . number_format($stats[0] + $stats[1]) . '</peers>' . '<peers>' . number_format($stats[0] + $stats[1]) . '</peers>' .
'<seeders>' . number_format($stats[0]) . '</seeders>' . '<seeders>' . number_format($stats[0]) . '</seeders>' .
'<leechers>' . number_format($stats[1]) . '</leechers>' . '<leechers>' . number_format($stats[1]) . '</leechers>' .
@ -638,7 +615,7 @@ class peertracker
// json // json
case 'json': case 'json':
header('Content-Type: text/javascript'); header('Content-Type: text/javascript');
echo '{"tracker":{"version":"$Id: tracker.mysql.php 148 2009-11-16 23:18:28Z trigunflame $",' . echo '{"tracker":{"version":"$Id: tracker.mysql.php 154 2009-11-18 07:39:10Z trigunflame $",' .
'"peers": "' . number_format($stats[0] + $stats[1]) . '",' . '"peers": "' . number_format($stats[0] + $stats[1]) . '",' .
'"seeders":"' . number_format($stats[0]) . '",' . '"seeders":"' . number_format($stats[0]) . '",' .
'"leechers":"' . number_format($stats[1]) . '",' . '"leechers":"' . number_format($stats[1]) . '",' .
@ -648,7 +625,7 @@ class peertracker
// standard // standard
default: default:
echo '<!doctype html><html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8">' . echo '<!doctype html><html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8">' .
'<title>PeerTracker: $Id: tracker.mysql.php 148 2009-11-16 23:18:28Z trigunflame $</title>' . '<title>PeerTracker: $Id: tracker.mysql.php 154 2009-11-18 07:39:10Z trigunflame $</title>' .
'<body><pre>' . number_format($stats[0] + $stats[1]) . '<body><pre>' . number_format($stats[0] + $stats[1]) .
' peers (' . number_format($stats[0]) . ' seeders + ' . number_format($stats[1]) . ' peers (' . number_format($stats[0]) . ' seeders + ' . number_format($stats[1]) .
' leechers) in ' . number_format($stats[2]) . ' torrents</pre></body></html>'; ' leechers) in ' . number_format($stats[2]) . ' torrents</pre></body></html>';

0
sqlite3/.htaccess Normal file → Executable file
View File

37
sqlite3/announce.php Normal file → Executable file
View File

@ -2,21 +2,21 @@
// License Information ///////////////////////////////////////////////////////////////////////////// // License Information /////////////////////////////////////////////////////////////////////////////
/* /*
* PeerTracker - OpenSource BitTorrent Tracker * PeerTracker - OpenSource BitTorrent Tracker
* Revision - $Id: announce.php 161 2010-01-20 17:49:50Z trigunflame $ * Revision - $Id: announce.php 124 2009-10-28 19:54:09Z trigunflame $
* Copyright (C) 2009 PeerTracker Team * Copyright (C) 2009 PeerTracker Team
* *
* PeerTracker is free software: you can redistribute it and/or modify * PeerTracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* PeerTracker is distributed in the hope that it will be useful, * PeerTracker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerTracker. If not, see <http://www.gnu.org/licenses/>. * along with PeerTracker. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -36,13 +36,6 @@ require './tracker.sqlite3.php';
// Verify Request ////////////////////////////////////////////////////////////////////////////////// // Verify Request //////////////////////////////////////////////////////////////////////////////////
// strip auto-escaped data
if (get_magic_quotes_gpc())
{
$_GET['info_hash'] = stripslashes($_GET['info_hash']);
$_GET['peer_id'] = stripslashes($_GET['peer_id']);
}
// 20-bytes - info_hash // 20-bytes - info_hash
// sha-1 hash of torrent metainfo // sha-1 hash of torrent metainfo
if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20) exit; if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20) exit;
@ -53,11 +46,12 @@ if (!isset($_GET['peer_id']) || strlen($_GET['peer_id']) != 20) exit;
// integer - port // integer - port
// port the client is accepting connections from // port the client is accepting connections from
if (!(isset($_GET['port']) && is_numeric($_GET['port']))) tracker_error('client listening port is invalid'); if (!(isset($_GET['port']) && is_numeric($_GET['port']))) tracker_error('client listening port is invalid');
// integer - left // integer - left
// number of bytes left for the peer to download // number of bytes left for the peer to download
if (isset($_GET['left']) && is_numeric($_GET['left'])) $_SERVER['tracker']['seeding'] = ($_GET['left'] > 0 ? 0 : 1); else tracker_error('client data left field is invalid'); if (isset($_GET['left']) && is_numeric($_GET['left'])) $_SERVER['tracker']['seeding'] = ($_GET['left'] > 0 ? 0 : 1);
else tracker_error('client data left field is invalid');
// integer boolean - compact - optional // integer boolean - compact - optional
// send a compact peer response // send a compact peer response
@ -89,19 +83,18 @@ else $_GET['numwant'] += 0;
// Handle Request ////////////////////////////////////////////////////////////////////////////////// // Handle Request //////////////////////////////////////////////////////////////////////////////////
// open database // strip info_hash & peer_id
if (get_magic_quotes_gpc())
{
stripslashes($_GET['info_hash']);
stripslashes($_GET['peer_id']);
}
// announce
peertracker::open(); peertracker::open();
// announce peers
peertracker::peers(); peertracker::peers();
// track client
peertracker::event(); peertracker::event();
// garbage collection
peertracker::clean(); peertracker::clean();
// close database
peertracker::close(); peertracker::close();
?> ?>

0
sqlite3/db/.htaccess Normal file → Executable file
View File

0
sqlite3/db/index.html Normal file → Executable file
View File

30
sqlite3/scrape.php Normal file → Executable file
View File

@ -2,21 +2,21 @@
// License Information ///////////////////////////////////////////////////////////////////////////// // License Information /////////////////////////////////////////////////////////////////////////////
/* /*
* PeerTracker - OpenSource BitTorrent Tracker * PeerTracker - OpenSource BitTorrent Tracker
* Revision - $Id: scrape.php 161 2010-01-20 17:49:50Z trigunflame $ * Revision - $Id: scrape.php 125 2009-10-29 01:02:21Z trigunflame $
* Copyright (C) 2009 PeerTracker Team * Copyright (C) 2009 PeerTracker Team
* *
* PeerTracker is free software: you can redistribute it and/or modify * PeerTracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* PeerTracker is distributed in the hope that it will be useful, * PeerTracker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerTracker. If not, see <http://www.gnu.org/licenses/>. * along with PeerTracker. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -37,24 +37,15 @@ require './tracker.sqlite3.php';
// Verify Request ////////////////////////////////////////////////////////////////////////////////// // Verify Request //////////////////////////////////////////////////////////////////////////////////
// tracker statistics // tracker statistics
if (isset($_GET['stats'])) if (isset($_GET['stats']))
{ {
// open database
peertracker::open();
// display stats // display stats
peertracker::open();
peertracker::stats(); peertracker::stats();
// close database
peertracker::close(); peertracker::close();
// exit immediately
exit; exit;
} }
// strip auto-escaped data
if (get_magic_quotes_gpc()) $_GET['info_hash'] = stripslashes($_GET['info_hash']);
// 20-bytes - info_hash // 20-bytes - info_hash
// sha-1 hash of torrent being tracked // sha-1 hash of torrent being tracked
if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20) if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20)
@ -67,13 +58,12 @@ if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20)
// Handle Request ////////////////////////////////////////////////////////////////////////////////// // Handle Request //////////////////////////////////////////////////////////////////////////////////
// open database // strip info_hash & peer_id
if (get_magic_quotes_gpc()) stripslashes($_GET['info_hash']);
// scrape
peertracker::open(); peertracker::open();
// perform scrape
peertracker::scrape(); peertracker::scrape();
// close database
peertracker::close(); peertracker::close();
?> ?>

111
sqlite3/tracker.sqlite3.php Normal file → Executable file
View File

@ -4,7 +4,7 @@
/* /*
* PeerTracker - OpenSource BitTorrent Tracker * PeerTracker - OpenSource BitTorrent Tracker
* Revision - $Id: tracker.sqlite3.php 148 2009-11-16 23:18:28Z trigunflame $ * Revision - $Id: tracker.sqlite3.php 135 2009-10-31 23:25:07Z trigunflame $
* Copyright (C) 2009 PeerTracker Team * Copyright (C) 2009 PeerTracker Team
* *
* PeerTracker is free software: you can redistribute it and/or modify * PeerTracker is free software: you can redistribute it and/or modify
@ -49,12 +49,13 @@ $_SERVER['tracker'] = array(
// fatal error, stop execution // fatal error, stop execution
function tracker_error($error) function tracker_error($error)
{ {
exit('d14:failure reason' . strlen($error) . ":{$error}e"); echo 'd14:failure reason' . strlen($error) . ":{$error}e";
exit;
} }
// SQLite3 Tracker Database //////////////////////////////////////////////////////////////////////// // SQLite3 Tracker Database ////////////////////////////////////////////////////////////////////////
// peertracker core // PeerTracker Core
class peertracker class peertracker
{ {
// database connection // database connection
@ -87,8 +88,8 @@ class peertracker
// create peers table // create peers table
'CREATE TABLE IF NOT EXISTS peers ' . 'CREATE TABLE IF NOT EXISTS peers ' .
'(info_hash BLOB, peer_id BLOB, compact BLOB, ip TEXT, ' . '(info_hash BLOB, peer_id BLOB, compact BLOB, ip TEXT, ' .
'port INTEGER DEFAULT 0, state INTEGER DEFAULT 0, ' . 'port INTEGER DEFAULT 0, updated INTEGER DEFAULT 0, ' .
'updated INTEGER DEFAULT 0); ' . 'state INTEGER DEFAULT 0); ' .
// create tasks table // create tasks table
'CREATE TABLE IF NOT EXISTS tasks' . 'CREATE TABLE IF NOT EXISTS tasks' .
'(name TEXT, value INTEGER DEFAULT 0); ' . '(name TEXT, value INTEGER DEFAULT 0); ' .
@ -127,11 +128,8 @@ class peertracker
// unix timestamp // unix timestamp
$time = time(); $time = time();
// fetch last cleanup time // attempt to locate the last time we ran cleanup
if (($last = self::$db->querySingle( if (($last = self::$db->querySingle("SELECT value FROM tasks WHERE name='prune';") + 0) == 0)
// select last cleanup from tasks
"SELECT value FROM tasks WHERE name='prune';"
) + 0) == 0)
{ {
self::$db->exec( self::$db->exec(
// begin query transaction // begin query transaction
@ -171,11 +169,15 @@ class peertracker
// build peer query // build peer query
$peer = self::$db->prepare( $peer = self::$db->prepare(
// insert into the peers table // insert into the peers table
'INSERT OR IGNORE INTO peers (info_hash, peer_id, compact, ip, port, state, updated) ' . 'INSERT OR IGNORE INTO peers ' .
// table columns
'(info_hash, peer_id, compact, ip, port, updated, state) ' .
// 20-byte info_hash, 20-byte peer_id, 6-byte compacted peer info // 20-byte info_hash, 20-byte peer_id, 6-byte compacted peer info
'VALUES (:info_hash, :peer_id, :compact, ' . 'VALUES (:info_hash, :peer_id, :compact, ' .
// dotted decimal string ip, integer port, integer state and unix timestamp updated // dotted decimal string ip, integer port
"'{$_GET['ip']}', {$_GET['port']}, {$_SERVER['tracker']['seeding']}, " . time() . '); ' "'{$_GET['ip']}', {$_GET['port']}, " .
// unix timestamp updated and integer state
time() . ', ' . $_SERVER['tracker']['seeding'] . '); '
); );
// assign binary data // assign binary data
@ -192,12 +194,14 @@ class peertracker
{ {
// build peer query // build peer query
$peer = self::$db->prepare( $peer = self::$db->prepare(
// update the 6-byte compacted peer info, dotted decimal string ip, integer port // update the peers table
"UPDATE peers SET compact=:compact, ip='{$_GET['ip']}', port={$_GET['port']}, " . 'UPDATE peers ' .
// integer state and unix timestamp updated // set the 6-byte compacted peer info, dotted decimal string ip, integer port
"state={$_SERVER['tracker']['seeding']}, updated=" . time() . "SET compact=:compact, ip='{$_GET['ip']}', port={$_GET['port']}, " .
// unix timestamp updated and integer state
'updated=' . time() . ', state=' . $_SERVER['tracker']['seeding'] . ' ' .
// that matches the given info_hash and peer_id // that matches the given info_hash and peer_id
" WHERE info_hash=:info_hash AND peer_id=:peer_id;" "WHERE info_hash=:info_hash AND peer_id=:peer_id;"
); );
// assign binary data // assign binary data
@ -214,10 +218,12 @@ class peertracker
{ {
// build peer query // build peer query
$peer = self::$db->prepare( $peer = self::$db->prepare(
// update the peers table
'UPDATE peers ' .
// set updated to the current unix timestamp // set updated to the current unix timestamp
'UPDATE peers SET updated=' . time() . 'SET updated=' . time() . ' ' .
// that matches the given info_hash and peer_id // that matches the given info_hash and peer_id
' WHERE info_hash=:info_hash AND peer_id=:peer_id;' 'WHERE info_hash=:info_hash AND peer_id=:peer_id;'
); );
// assign binary data // assign binary data
@ -258,8 +264,8 @@ class peertracker
$peer->bindValue(':info_hash', $_GET['info_hash'], SQLITE3_BLOB); $peer->bindValue(':info_hash', $_GET['info_hash'], SQLITE3_BLOB);
$peer->bindValue(':peer_id', $_GET['peer_id'], SQLITE3_BLOB); $peer->bindValue(':peer_id', $_GET['peer_id'], SQLITE3_BLOB);
// execute peer select & cleanup // execute peer select & cleanup
$success = $peer->execute() OR tracker_error('failed to select peer data'); if (!$success = $peer->execute()) tracker_error('failed to select peer data');
$pState = $success->fetchArray(SQLITE3_NUM); $pState = $success->fetchArray(SQLITE3_NUM);
$success->finalize(); $success->finalize();
$peer->close(); $peer->close();
@ -309,11 +315,14 @@ class peertracker
$peer->bindValue(':info_hash', $_GET['info_hash'], SQLITE3_BLOB); $peer->bindValue(':info_hash', $_GET['info_hash'], SQLITE3_BLOB);
// execute peer row count & cleanup // execute peer row count & cleanup
$success = $peer->execute() OR tracker_error('failed to select peer count'); if (!$success = $peer->execute()) tracker_error('failed to select peer count');
$total = $success->fetchArray(SQLITE3_NUM); $total = $success->fetchArray(SQLITE3_NUM);
$success->finalize(); $success->finalize();
$peer->close(); $peer->close();
// announce response
$response = 'd8:intervali' . $_SERVER['tracker']['announce_interval'] . 'e12:min intervali' . $_SERVER['tracker']['min_interval'] . 'e5:peers';
// prepare query // prepare query
$peer = self::$db->prepare( $peer = self::$db->prepare(
// select // select
@ -339,27 +348,20 @@ class peertracker
) )
); );
// begin response
$response = 'd8:intervali' . $_SERVER['tracker']['announce_interval'] .
'e12:min intervali' . $_SERVER['tracker']['min_interval'] .
'e5:peers';
// assign binary data // assign binary data
$peer->bindValue(':info_hash', $_GET['info_hash'], SQLITE3_BLOB); $peer->bindValue(':info_hash', $_GET['info_hash'], SQLITE3_BLOB);
// execute peer selection // execute peer selection
$success = $peer->execute() OR tracker_error('failed to select peers'); if (!$success = $peer->execute()) tracker_error('failed to select peers');
// compact announce // compact announce
if ($_GET['compact']) if ($_GET['compact'])
{ {
// peers list // fetch peers
$peers = ''; $peers = '';
// build response
while ($p = $success->fetchArray(SQLITE3_NUM)) $peers .= $p[0]; while ($p = $success->fetchArray(SQLITE3_NUM)) $peers .= $p[0];
// 6-byte compacted peer info // encoded string of peers in compact form
$response .= strlen($peers) . ':' . $peers; $response .= strlen($peers) . ':' . $peers;
} }
// dictionary announce // dictionary announce
@ -371,13 +373,13 @@ class peertracker
// include peer_id // include peer_id
if (!$_GET['no_peer_id']) if (!$_GET['no_peer_id'])
{ {
// dotted decimal string ip, 20-byte peer_id, integer port // fetch peers
while ($p = $success->fetchArray(SQLITE3_NUM)) $response .= 'd2:ip' . strlen($p[1]) . ":{$p[1]}" . "7:peer id20:{$p[0]}4:porti{$p[2]}ee"; while ($p = $success->fetchArray(SQLITE3_NUM)) $response .= 'd2:ip' . strlen($p[1]) . ":{$p[1]}" . "7:peer id20:{$p[0]}4:porti{$p[2]}ee";
} }
// omit peer_id // omit peer_id
else else
{ {
// dotted decimal string ip, integer port // fetch peers
while ($p = $success->fetchArray(SQLITE3_NUM)) $response .= 'd2:ip' . strlen($p[0]) . ":{$p[0]}4:porti{$p[1]}ee"; while ($p = $success->fetchArray(SQLITE3_NUM)) $response .= 'd2:ip' . strlen($p[0]) . ":{$p[0]}4:porti{$p[1]}ee";
} }
@ -385,7 +387,7 @@ class peertracker
$response .= 'e'; $response .= 'e';
} }
// send response // respond asap
echo $response . 'e'; echo $response . 'e';
// cleanup // cleanup
@ -397,7 +399,7 @@ class peertracker
// scrape info_hash // scrape info_hash
public function scrape() public function scrape()
{ {
// begin response // scrape response
$response = 'd5:filesd'; $response = 'd5:filesd';
// scrape info_hash // scrape info_hash
@ -414,13 +416,12 @@ class peertracker
// assign binary data // assign binary data
$query->bindValue(':info_hash', $_GET['info_hash'], SQLITE3_BLOB); $query->bindValue(':info_hash', $_GET['info_hash'], SQLITE3_BLOB);
// execute peer selection
if (!$success = $query->execute()) tracker_error('unable to scrape the requested torrent');
// scrape // scrape
$success = $query->execute() OR tracker_error('unable to scrape the requested torrent');
$scrape = $success->fetchArray(SQLITE3_NUM); $scrape = $success->fetchArray(SQLITE3_NUM);
$response .= "20:{$_GET['info_hash']}d8:completei" . ($scrape[0]+0) . 'e10:downloadedi0e10:incompletei' . ($scrape[1]+0) . 'ee';
// 20-byte info_hash, integer complete, integer downloaded, integer incomplete
$response .= "20:{$_GET['info_hash']}d8:completei" . ($scrape[0]+0) .
'e10:downloadedi0e10:incompletei' . ($scrape[1]+0) . 'ee';
// cleanup // cleanup
$success->finalize(); $success->finalize();
@ -431,20 +432,18 @@ class peertracker
{ {
// scrape // scrape
$query = self::$db->query( $query = self::$db->query(
// select info_hash, total seeders and leechers // total seeders and leechers
'SELECT info_hash, SUM(state=1), SUM(state=0) ' . 'SELECT info_hash, SUM(state=1), SUM(state=0) ' .
// from peers grouped by info_hash // for each info_hash being tracked
'FROM peers GROUP BY info_hash;' 'FROM peers GROUP BY info_hash;'
) OR tracker_error('unable to perform a full scrape'); ) OR tracker_error('unable to perform a full scrape');
// 20-byte info_hash, integer complete, integer downloaded, integer incomplete
while ($scrape = $query->fetchArray(SQLITE3_NUM)) $response .= "20:{$scrape[0]}d8:completei{$scrape[1]}e10:downloadedi0e10:incompletei{$scrape[2]}ee"; while ($scrape = $query->fetchArray(SQLITE3_NUM)) $response .= "20:{$scrape[0]}d8:completei{$scrape[1]}e10:downloadedi0e10:incompletei{$scrape[2]}ee";
// cleanup // cleanup
$query->finalize(); $query->finalize();
} }
// send response // respond asap
echo $response . 'ee'; echo $response . 'ee';
} }
@ -455,8 +454,10 @@ class peertracker
$query = self::$db->query( $query = self::$db->query(
// select seeders and leechers // select seeders and leechers
'SELECT SUM(state=1), SUM(state=0), ' . 'SELECT SUM(state=1), SUM(state=0), ' .
// unique torrents from peers // unique torrents
'COUNT(DISTINCT info_hash) FROM peers;' 'COUNT(DISTINCT info_hash) ' .
// from peers
'FROM peers;'
) OR tracker_error('failed to retrieve tracker statistics'); ) OR tracker_error('failed to retrieve tracker statistics');
$stats = $query->fetchArray(SQLITE3_NUM); $stats = $query->fetchArray(SQLITE3_NUM);
@ -467,7 +468,7 @@ class peertracker
case 'xml': case 'xml':
header('Content-Type: text/xml'); header('Content-Type: text/xml');
echo '<?xml version="1.0" encoding="ISO-8859-1"?>' . echo '<?xml version="1.0" encoding="ISO-8859-1"?>' .
'<tracker version="$Id: tracker.sqlite3.php 148 2009-11-16 23:18:28Z trigunflame $">' . '<tracker version="$Id: tracker.sqlite3.php 135 2009-10-31 23:25:07Z trigunflame $">' .
'<peers>' . number_format($stats[0] + $stats[1]) . '</peers>' . '<peers>' . number_format($stats[0] + $stats[1]) . '</peers>' .
'<seeders>' . number_format($stats[0]) . '</seeders>' . '<seeders>' . number_format($stats[0]) . '</seeders>' .
'<leechers>' . number_format($stats[1]) . '</leechers>' . '<leechers>' . number_format($stats[1]) . '</leechers>' .
@ -477,7 +478,7 @@ class peertracker
// json // json
case 'json': case 'json':
header('Content-Type: text/javascript'); header('Content-Type: text/javascript');
echo '{"tracker":{"version":"$Id: tracker.sqlite3.php 148 2009-11-16 23:18:28Z trigunflame $",' . echo '{"tracker":{"version":"$Id: tracker.sqlite3.php 135 2009-10-31 23:25:07Z trigunflame $",' .
'"peers": "' . number_format($stats[0] + $stats[1]) . '",' . '"peers": "' . number_format($stats[0] + $stats[1]) . '",' .
'"seeders":"' . number_format($stats[0]) . '",' . '"seeders":"' . number_format($stats[0]) . '",' .
'"leechers":"' . number_format($stats[1]) . '",' . '"leechers":"' . number_format($stats[1]) . '",' .
@ -487,7 +488,7 @@ class peertracker
// standard // standard
default: default:
echo '<!doctype html><html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8">' . echo '<!doctype html><html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8">' .
'<title>PeerTracker: $Id: tracker.sqlite3.php 148 2009-11-16 23:18:28Z trigunflame $</title>' . '<title>PeerTracker: $Id: tracker.sqlite3.php 135 2009-10-31 23:25:07Z trigunflame $</title>' .
'<body><pre>' . number_format($stats[0] + $stats[1]) . '<body><pre>' . number_format($stats[0] + $stats[1]) .
' peers (' . number_format($stats[0]) . ' seeders + ' . number_format($stats[1]) . ' peers (' . number_format($stats[0]) . ' seeders + ' . number_format($stats[1]) .
' leechers) in ' . number_format($stats[2]) . ' torrents</pre></body></html>'; ' leechers) in ' . number_format($stats[2]) . ' torrents</pre></body></html>';