This is an example of semi refactorised code i am working on for TBDev 1.05 Release, this could be a month off.. Anyway I have for example done most of my first file at the top of the code.
This is announce.php
/*
+------------------------------------------------
| TBDev.net BitTorrent Tracker PHP for XOOPS
| =============================================
| by CoLdFuSiOn
| (c) 2003 - 2009 TBDev.Net
| http://www.tbdev.net
| =============================================
| svn: http://sourceforge.net/projects/tbdevnet/
| Licence Info: GPL
+------------------------------------------------
| 2011-09-01
| 0.01
| Wishcraft
| http://chronolabs.coop/
+------------------------------------------------
*/
error_reporting(0);
require_once '../../mainfile.php';
$GLOBALS['xoopsLogger']->activated = false;
require_once 'include/config.php';
$users_handler = xoops_getmodulehandler('users', 'td');
$torrents_handler = xoops_getmodulehandler('torrents', 'td');
$peers_handler = xoops_getmodulehandler('peers', 'td');
define ('UC_VIP', 2);
// DO NOT EDIT BELOW UNLESS YOU KNOW WHAT YOU'RE DOING!!
$agent = $_SERVER["HTTP_USER_AGENT"];
// Deny access made with a browser...
if (
ereg("^Mozilla\/", $agent) ||
ereg("^Opera\/", $agent) ||
ereg("^Links ", $agent) ||
ereg("^Lynx\/", $agent) ||
isset($_SERVER['HTTP_COOKIE']) ||
isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ||
isset($_SERVER['HTTP_ACCEPT_CHARSET'])
)
err("torrent not registered with this tracker CODE 1");
/////////////////////// FUNCTION DEFS ///////////////////////////////////
function err($msg)
{
$torrents_handler->benc_resp(array('failure reason' => array('type' => 'string', 'value' => $msg)));
exit();
}
function hash_where($name, $hash) {
$shhash = preg_replace('/ *$/s', "", $hash);
return "($name = " . sqlesc($hash) . " OR $name = " . sqlesc($shhash) . ")";
}
function portblacklisted($port)
{
// direct connect
if ($port >= 411 && $port <= 413) return true;
// bittorrent
if ($port >= 6881 && $port <= 6889) return true;
// kazaa
if ($port == 1214) return true;
// gnutella
if ($port >= 6346 && $port <= 6347) return true;
// emule
if ($port == 4662) return true;
// winmx
if ($port == 6699) return true;
return false;
}
/////////////////////// FUNCTION DEFS END ///////////////////////////////
$parts = array();
$pattern = '[0-9a-fA-F]{32}';
if( !isset($_GET['passkey']) OR !ereg($pattern, $_GET['passkey'], $parts) )
err("Invalid Passkey");
else
$GLOBALS['passkey'] = $parts[0];
foreach (array("info_hash","peer_id","event","ip","localip") as $x) {
if(isset($_GET["$x"]))
$GLOBALS[$x] = "" . $_GET[$x];
}
foreach (array("port","downloaded","uploaded","left") as $x) {
$GLOBALS[$x] = 0 + $_GET[$x];
}
foreach (array("passkey","info_hash","peer_id","port","downloaded","uploaded","left") as $x)
if (!isset($x)) err("Missing key: $x");
foreach (array("info_hash","peer_id") as $x)
if (strlen($GLOBALS[$x]) != 20)
err("Invalid $x (" . strlen($GLOBALS[$x]) . " - " . urlencode($GLOBALS[$x]) . ")");
unset($x);
$info_hash = bin2hex($info_hash);
$ip = $_SERVER['REMOTE_ADDR'];
$port = 0 + $port;
$downloaded = 0 + $downloaded;
$uploaded = 0 + $uploaded;
$left = 0 + $left;
$rsize = 50;
foreach(array("num want", "numwant", "num_want") as $k)
{
if (isset($_GET[$k]))
{
$rsize = 0 + $_GET[$k];
break;
}
}
if (!$port || $port > 0xffff)
err("invalid port");
if (!isset($event))
$event = "";
$seeder = ($left == 0) ? "yes" : "no";
$criteria = new CriteriaCompo(new Criteria('passkey', $passkey));
if ( $users_handler->getCount($criteria) != 1 )
err("Unknown passkey. Please redownload the torrent from {$GLOBALS['TBDEV']['baseurl']}.");
$users = $users_handler->getObjects($criteria, false);
if( $users[0]->getVar('enabled') == 'no' )
err('Permission denied, you're not enabled');
$criteria = new CriteriaCompo(new Criteria('info_hash', $info_hash));
//$res = $GLOBALS['xoopsDB']->queryF("SELECT id, banned, seeders + leechers AS numpeers, added AS ts FROM ".$GLOBALS['xoopsDB']->prefix("tb_torrents")." WHERE info_hash = " .sqlesc($info_hash));//" . hash_where("info_hash", $info_hash));
$torrents = $torrents_handler->getObjects($criteria, false);
if (!is_object($torrents[0]))
err("torrent not registered with this tracker CODE 2");
$torrentid = $torrents[0]->getVar("id");
$fields = "seeder, peer_id, ip, port, uploaded, downloaded, userid";
$numpeers = $torrents[0]->getVar("seeders")+$torrents[0]->getVar("leechers");
$criteria = new CriteriaCompo(new Criteria('torrent', $torrentid));
$criteria->add(new Criteria('connectable', 'yes'));
if ($numpeers > $rsize) {
$criteria->setSort('RAND()');
$criteria->setOrder('DESC');
$criteria->settLimit($rsize);
}
$peers = $peers_handler->getObjects($criteria, false);
if($_GET['compact'] != 1){
$resp = "d" . $torrents_handler->benc_str("interval") . "i" . $GLOBALS['TBDEV']['announce_interval'] . "e" . $torrents_handler->benc_str("peers") . "l";
} else {
$resp = "d" . $torrents_handler->benc_str("interval") . "i" . $GLOBALS['TBDEV']['announce_interval'] ."e" . $torrents_handler->benc_str("min interval") . "i" . 300 ."e5:"."peers" ;
}
$peer = array();
$peer_num = 0;
foreach ($peers as $key => $peerobj) {
if($_GET['compact'] != 1) {
if (str_pad($peerobj->getVar("peer_id"), 20) === $peer_id) {
$self = $peerobj;
continue;
}
$resp .= "d" . $torrents_handler->benc_str("ip") . $torrents_handler->benc_str($peerobj->getVar("ip"));
if (!$_GET['no_peer_id']) {
$resp .= $torrents_handler->benc_str("peer id") . $torrents_handler->benc_str($peerobj->getVar("peer_id"));
}
$resp .= $torrents_handler->benc_str("port") . "i" . $peerobj->getVar("port") . "e" . "e";
} else {
$peer_ip = explode('.', $peerobj->getVar("ip"));
$peer_ip = pack("C*", $peer_ip[0], $peer_ip[1], $peer_ip[2], $peer_ip[3]);
$peer_port = pack("n*", (int)$peerobj->getVar("port"));
$time = intval((time() % 7680) / 60);
if($_GET['left'] == 0) {
$time += 128;
}
$time = pack("C", $time);
$peer[] = $time . $peer_ip . $peer_port;
$peer_num++;
}
}
if ($_GET['compact']!=1)
$resp .= "ee";
else {
$o = "";
for($i=0;$i<$peer_num;$i++)
{
$o .= substr($peer[$i], 1, 6);
}
$resp .= strlen($o) . ':' . $o . 'e';
}
$criteria = new CriteriaCompo(new Criteria('torrent', $torrentid));
$criteria->add(new Criteria('peer_id', $peer_id));
//////////////////////////// END NEW COMPACT MODE////////////////////////////////
if (!isset($self)) {
$peers = $peers_handler->getObjects($criteria, false);
if (is_object($peers[0])) {
$userid = $peers[0]->getVar("userid");
$self = $peers[0];
}
}
//// Up/down stats ////////////////////////////////////////////////////////////
if (!isset($self)) {
$criteria = new CriteriaCompo(new Criteria('torrent', $torrentid));
$criteria->add(new Criteria('passkey', $passkey));
if ($peers_handler->getCount($criteria) >= 1 && $seeder == 'no')
err("Connection limit exceeded! You may only leech from one location at a time.");
if ($peers_handler->getCount($criteria) >= 3 && $seeder == 'yes')
err("Connection limit exceeded!");
if ($left > 0 && $users[0]->getVar('class') < UC_VIP && $GLOBALS['TBDEV']['user_ratios'])
{
$gigs = $users[0]->getVar('uploaded') / (1024*1024*1024);
$elapsed = floor((time() - $torrents[0]->getVar("ts")) / 3600);
$ratio = (($users[0]->getVar('downloaded') > 0) ? ($users[0]->getVar('uploaded') / $users[0]->getVar('downloaded')) : 1);
if ($ratio < 0.5 || $gigs < 5) $wait = 48;
elseif ($ratio < 0.65 || $gigs < 6.5) $wait = 24;
elseif ($ratio < 0.8 || $gigs < 8) $wait = 12;
elseif ($ratio < 0.95 || $gigs < 9.5) $wait = 6;
else $wait = 0;
if ($elapsed < $wait)
err("Not authorized (" . ($wait - $elapsed) . "h) - READ THE FAQ!");
}
} else {
$upthis = max(0, $uploaded - $self->getVar("uploaded"));
$downthis = max(0, $downloaded - $self->getVar("downloaded"));
if ($upthis > 0 || $downthis > 0) {
$users[0]->setVar('uploaded', $users[0]->getVar('uploaded')+$upthis);
$users[0]->setVar('downloaded', $users[0]->getVar('downloaded')+$downthis);
$users_handler->insert($users[0], true);
}
}
///////////////////////////////////////////////////////////////////////////////
$updateset = array();
if ($event == "stopped")
{
if (isset($self))
{
$criteria = new CriteriaCompo(new Criteria('torrent', $torrentid));
$criteria->add(new Criteria('peer_id', $peer_id));
if ($peers_handler->deleteAll($criteria))
{
if ($self["seeder"] == "yes")
$torrents[0]->setVar('seeders', $torrents[0]->getVar('seeders')-1);
else
$torrents[0]->setVar('leechers', $torrents[0]->getVar('leechers')-1);
}
}
} else {
if ($event == "completed")
$torrents[0]->setVar('times_completed', $torrents[0]->getVar('times_completed')+1);
if (isset($self))
{
$self->setVar('uploaded', $uploaded);
$self->setVar('downloaded', $downloaded);
$self->setVar('to_go', $left);
$self->setVar('last_action', time());
$self->setVar('seeder', $seeder);
if ($seeder == "yes" && $self->getVar("seeder") != $seeder )
$self->setVar('finishedat', time());
if ($peers_handler->insert($self, true) && $self->getVar("seeder") != $seeder) {
if ($seeder == "yes") {
$torrents[0]->setVar('seeders', $torrents[0]->getVar('seeders')+1);
$torrents[0]->setVar('leechers', $torrents[0]->getVar('leechers')-1);
} else {
$torrents[0]->setVar('seeders', $torrents[0]->getVar('seeders')-1);
$torrents[0]->setVar('leechers', $torrents[0]->getVar('leechers')+1);
}
}
} else {
if ($event != "started")
err("Peer not found. ".$passkey." Restart the torrent.");
if (portblacklisted($port)) {
err("Port $port is blacklisted.");
} elseif ( $GLOBALS['TBDEV']['connectable_check'] ) {
$sockres = @fsockopen($ip, $port, $errno, $errstr, 5);
if (!$sockres)
$connectable = "no";
else
{
$connectable = "yes";
@fclose($sockres);
}
} else {
$connectable = 'yes';
}
$newpeer = $peers_handler->create();
$newpeer->setVar('connectable', $connectable);
$newpeer->setVar('torrent', $torrentid);
$newpeer->setVar('peer_id', $peer_id);
$newpeer->setVar('ip', $ip);
$newpeer->setVar('port', $port);
$newpeer->setVar('uploaded', $uploaded);
$newpeer->setVar('downloaded', $downloaded);
$newpeer->setVar('to_go', $left);
$newpeer->setVar('started', time());
$newpeer->setVar('last_action', time());
$newpeer->setVar('seeder', $seeder);
$newpeer->setVar('userid', $user[0]->getVar('id'));
$newpeer->setVar('agent', $agent);
$newpeer->setVar('passkey', $passkey);
if ($peers_handler->insert($newpeer, true))
{
if ($seeder == "yes")
$torrents[0]->setVar('seeders', $torrents[0]->getVar('seeders')+1);
else
$torrents[0]->setVar('leechers', $torrents[0]->getVar('leechers')+1);
}
}
}
if ($seeder == "yes")
{
if ($torrents[0]->getVar("banned") != "yes")
$torrents[0]->setVar('visible', 'yes');
$torrents[0]->setVar('last_action', time());
}
$torrents_handler->insert($torrents[0], true);
$torrents_handler->benc_resp_raw($resp);
?>
it links to class/torrents.php which are all built for the database structure.
// class/torrents.php so far - code edited 11:56 PM 1/09/2011 AEST.
defined('XOOPS_ROOT_PATH') or die("XOOPS root path not defined");
class TbTorrents extends XoopsObject
{
function __construct()
{
$this->initVar('id', XOBJ_DTYPE_INT, null, false);
$this->initVar('info_hash', XOBJ_DTYPE_TXTBOX, null, false, 40);
$this->initVar('name', XOBJ_DTYPE_TXTBOX, null, false, 255);
$this->initVar('filename', XOBJ_DTYPE_TXTBOX, null, false, 255);
$this->initVar('save_as', XOBJ_DTYPE_TXTBOX, null, false, 255);
$this->initVar('search_text', XOBJ_DTYPE_OTHER, null, false);
$this->initVar('descr', XOBJ_DTYPE_OTHER, null, false);
$this->initVar('ori_descr', XOBJ_DTYPE_OTHER, null, false);
$this->initVar('category', XOBJ_DTYPE_INT, null, false);
$this->initVar('size', XOBJ_DTYPE_INT, null, false);
$this->initVar('added', XOBJ_DTYPE_INT, null, false);
$this->initVar('type', XOBJ_DTYPE_ENUM, null, false, false, false, array('single','multi'));
$this->initVar('numfiles', XOBJ_DTYPE_INT, null, false);
$this->initVar('comments', XOBJ_DTYPE_INT, null, false);
$this->initVar('views', XOBJ_DTYPE_INT, null, false);
$this->initVar('hits', XOBJ_DTYPE_INT, null, false);
$this->initVar('times_completed', XOBJ_DTYPE_INT, null, false);
$this->initVar('leechers', XOBJ_DTYPE_INT, null, false);
$this->initVar('seeders', XOBJ_DTYPE_INT, null, false);
$this->initVar('last_action', XOBJ_DTYPE_INT, null, false);
$this->initVar('visible', XOBJ_DTYPE_ENUM, null, false, false, false, array('yes', 'no'));
$this->initVar('banned', XOBJ_DTYPE_ENUM, null, false, false, false, array('yes', 'no'));
$this->initVar('owner', XOBJ_DTYPE_INT, null, false);
$this->initVar('numratings', XOBJ_DTYPE_INT, null, false);
$this->initVar('ratingsum', XOBJ_DTYPE_INT, null, false);
$this->initVar('nfo', XOBJ_DTYPE_OTHER, null, false);
$this->initVar('client_created_by', XOBJ_DTYPE_TXTBOX, null, false, 50);
}
function TbTorrents()
{
$this->__construct();
}
}
class TbTorrentsHandler extends XoopsPersistableObjectHandler
{
function TbTorrentsHandler(&$db)
{
$this->__construct($db);
}
function __construct(&$db)
{
parent::__construct($db, "tb_torrents", 'TbTorrents', "id");
}
function benc_resp($d)
{
$this->benc_resp_raw($this->benc(array('type' => 'dictionary', 'value' => $d)));
}
function benc_resp_raw($x)
{
header( "Content-Type: text/plain" );
header( "Pragma: no-cache" );
if ( $_SERVER['HTTP_ACCEPT_ENCODING'] == 'gzip' )
{
header( "Content-Encoding: gzip" );
echo gzencode( $x, 9, FORCE_GZIP );
}
else
echo $x ;
}
function benc($obj) {
if (!is_array($obj) || !isset($obj["type"]) || !isset($obj["value"]))
return;
$c = $obj["value"];
switch ($obj["type"]) {
case "string":
return $this->benc_str($c);
case "integer":
return $this->benc_int($c);
case "list":
return $this->benc_list($c);
case "dictionary":
return $this->benc_dict($c);
default:
return;
}
}
function benc_str($s) {
return strlen($s) . ":$s";
}
function benc_int($i) {
return "i" . $i . "e";
}
function benc_list($a) {
$s = "l";
foreach ($a as $e) {
$s .= $this->benc($e);
}
$s .= "e";
return $s;
}
function benc_dict($d) {
$s = "d";
$keys = array_keys($d);
sort($keys);
foreach ($keys as $k) {
$v = $d[$k];
$s .= $this->benc_str($k);
$s .= $this->benc($v);
}
$s .= "e";
return $s;
}
}
?>