1
wishcraft
TBDev 1.03 - RC - Torrent Tracker for XOOPS

Resized Image
TBDev 1.03 RC
Community Release by Chronolabs Co-Op

A TBDev tracker is a server that assists in the communication between peers using the BitTorrent protocol. It is also, in the absence of extensions to the original protocol, the only major critical point, as clients are required to communicate with the tracker to initiate downloads. Clients that have already begun downloading also communicate with the tracker periodically to negotiate with newer peers and provide statistics; however, after the initial reception of peer data, peer communication can continue without a tracker.

This is a Private tracker; a private tracker is this TBDev tracker that restricts use, by requiring users to register with the site. The method for controlling registration used amongst many private trackers is an invitation system, in which active and contributing members are given the ability to grant a new user permission to register at the site. Invitations, typically sent via email or an invite code system, are normally granted to active users who have uploaded a pre-determined amount or meet specific upload-to-download ratio requirements.

Trading invites for different sites is highly frowned upon in the private Torrent community as it allows anti-piracy groups to infiltrate private trackers more easily. Most private trackers monitor how much users upload or download, and in most situations, enforce a minimum upload-to-download ratio.

Some of the allure of private tracker versus a public one are: higher speeds, a tighter community, and safer downloads. Private trackers implement a strict set of rules, so generally files containing malware are extremely uncommon. Many private trackers keep in close contact with each other, so bad users (who trade invites or attempt to fake their ratio) can be quickly blacklisted. Almost all private trackers implement a passkey system, where each user is given a personalized announce URL so if there is unauthorized distribution, it can be pinpointed to the user responsible. Some private trackers have a higher level of security than others — many sites only allow their users to refer to their site as an abbreviation, and never as the site's full name or URL. Other trackers restrict invites to outstanding members, and many trackers, to increase security, have eliminated the invite system altogether. An example of a private tracker is Oink's Pink Palace, which was forcibly shut down in late 2007 by law enforcement officials.

The downside is that in a closed community it can be hard for all members to maintain the required ratio. Competitions may be offered, with prizes of improved ratios. Some trackers will exchange ratio credit for donations. Some trackers will also use "free leech" systems to improve the users ratio. When downloading a free leech torrent only the upload gets logged in, the download is ignored. Usually large torrents are offered as free leech. Seeding to a ratio of at least 1 is still recommended even for free leech torrents.

See: http://www.tbdev.net/ for more information

Features Include
  • Torrent Upload
  • Bitbucket Upload
  • Categories
  • Closed Scrape
  • Closed Announce Tracker
  • Classic TB Dev with templates
  • XOOPS User compatibility


Bugs Fixed
  • No Known Bug - please report them


Download: xoops2.5_tbdev_1.03.zip - 1.4Mbs
Sourceforge: xoops2.5_tbdev_1.03.zip - 1.4Mbs
Demo: http://xoops.demo.chronolabs.coop
Resized Image
http://www.ohloh.net/accounts/226400

Follow, Like & Read:-

twitter.com/RegaltyFamily
github.com/Chronolabs-Cooperative
facebook.com/DrAntonyRoberts

2
wishcraft
TBDev 1.04 - Stable - Torrent Tracker for XOOPS

This has been moved from RC to stable please download 1.04 of TBDev for XOOPS.

Quick Demo and Run Through TBDev 1.04 based on TBDev 2009.





The next changes will move it back to RC we will be modifying the code extensively so it uses the persitence class modeler rather than SQL Injections directly in the code.

New Features Include
  • Super Torrent Mode


Features Include
  • Torrent Upload
  • Bitbucket Upload
  • Categories
  • Closed Scrape
  • Closed Announce Tracker
  • Classic TB Dev with templates
  • XOOPS User compatibility


Bugs Fixed
  • Main header not loading on some files


Download: xoops2.5_tbdev_1.04.zip - 1.4Mbs
Sourceforge: xoops2.5_tbdev_1.04.zip - 1.4Mbs
Demo: http://xoops.demo.chronolabs.coop
Resized Image
http://www.ohloh.net/accounts/226400

Follow, Like & Read:-

twitter.com/RegaltyFamily
github.com/Chronolabs-Cooperative
facebook.com/DrAntonyRoberts

3
wishcraft
Re: TBDev 1.05 - Refactorisation - Torrent Tracker for XOOPS

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] = $_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 $port;
$downloaded $downloaded;
$uploaded $uploaded;
$left $left;

$rsize 50;
foreach(array(
"num want""numwant""num_want") as $k)
{
    if (isset(
$_GET[$k]))
    {
        
$rsize $_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) != )
    
err("Unknown passkey. Please redownload the torrent from {$GLOBALS['TBDEV']['baseurl']}.");
 
$users $users_handler->getObjects($criteriafalse);

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_INTnullfalse);
        
$this->initVar('info_hash'XOBJ_DTYPE_TXTBOXnullfalse40);
        
$this->initVar('name'XOBJ_DTYPE_TXTBOXnullfalse255);
        
$this->initVar('filename'XOBJ_DTYPE_TXTBOXnullfalse255);
        
$this->initVar('save_as'XOBJ_DTYPE_TXTBOXnullfalse255);
        
$this->initVar('search_text'XOBJ_DTYPE_OTHERnullfalse);
        
$this->initVar('descr'XOBJ_DTYPE_OTHERnullfalse);
        
$this->initVar('ori_descr'XOBJ_DTYPE_OTHERnullfalse);
        
$this->initVar('category'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('size'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('added'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('type'XOBJ_DTYPE_ENUMnullfalsefalsefalse, array('single','multi'));
        
$this->initVar('numfiles'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('comments'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('views'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('hits'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('times_completed'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('leechers'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('seeders'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('last_action'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('visible'XOBJ_DTYPE_ENUMnullfalsefalsefalse, array('yes''no'));
        
$this->initVar('banned'XOBJ_DTYPE_ENUMnullfalsefalsefalse, array('yes''no'));
        
$this->initVar('owner'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('numratings'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('ratingsum'XOBJ_DTYPE_INTnullfalse);
        
$this->initVar('nfo'XOBJ_DTYPE_OTHERnullfalse);
        
$this->initVar('client_created_by'XOBJ_DTYPE_TXTBOXnullfalse50);
    }

    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$x9FORCE_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;
    }
        
}
?>
Resized Image
http://www.ohloh.net/accounts/226400

Follow, Like & Read:-

twitter.com/RegaltyFamily
github.com/Chronolabs-Cooperative
facebook.com/DrAntonyRoberts

4
DCrussader
Re: TBDev 1.05 - Refactorisation - Torrent Tracker for XOOPS

Very nice integration
Uses old Legacy administration tabs...
Small error on first run .../modules/tb/my.php, when hit save with default settings, got this:
MySQL Error

SQL error
Table 'addonsbg_xoops.categories' doesn't exist SQL error code: 1146 Date: Wednesday 04th of April 2012 08:10:17 PM



XOOPS 2.5.5 RC
TBDev 1.04

Since you can make such nice integration, why u not make one for SMF or phpBB, this NewBB is old and useless (14.5 MB module). There are several better forums then NewBB (it was good forum till version 2.02), and no thanks but and XForum is the same....
May The Source Be With You!

Login

Who's Online

282 user(s) are online (174 user(s) are browsing Support Forums)


Members: 0


Guests: 282


more...

Donat-O-Meter

Stats
Goal: $100.00
Due Date: Nov 30
Gross Amount: $0.00
Net Balance: $0.00
Left to go: $100.00
Make donations with PayPal!

Latest GitHub Commits