Thread: Passkey System
View Single Post
Old 13-07-08, 15:45
joeroberts's Avatar
joeroberts joeroberts is offline
BT.Manager Owner
Join Date: Jan 2008
United States
Posts: 2,035
Default Passkey by Skorpios, Original passkey split from main topic
The files that must be modified are:

First of all, create the field 'passkey' in the 'users' and 'peers' tables.

Now we need to set each users passkey and add it to the downloaded torrent. Both of these are done in download.php by replacing the lines:
header("Content-Type: application/x-bittorrent");

require_once "include/benc.php";

if (strlen($CURUSER['passkey']) != 32) {

$CURUSER['passkey'] = md5($CURUSER['username'].get_date_time().$CURUSER['passhash']);

mysql_query("UPDATE users SET passkey='$CURUSER[passkey]' WHERE id=$CURUSER[id]");


$dict = bdec_file($fn, (1024*1024));

$dict['value']['announce']['value'] = "$BASEURL/announce.php?passkey=$CURUSER[passkey]";

$dict['value']['announce']['string'] = strlen($dict['value']['announce']['value']).":".$dict['value']['announce']['value'];

$dict['value']['announce']['strlen'] = strlen($dict['value']['announce']['string']);

header('Content-Disposition: attachment; filename="'.$torrent['filename'].'"');

header("Content-Type: application/x-bittorrent");

This creates a passkey if the user doesn't already have one assigned. (It's also worth noting that the announce url is replaced, opening up the possibilty to allow any announce url in uploaded torrents.)

To allow users to reset their passkey if they suspect it has been leaked, we modify my.php and takeprofedit.php. In my.php, wherever you want the passkey reset box to appear, add the line:
tr("Reset passkey","<input type=checkbox name=resetpasskey value=1 />
<font class=small>Any active torrents must be downloaded again to continue leeching/seeding.</font>", 1);
In takeprofedit, we add the corresponding line somewhere before the SQL query:
if ($_POST['resetpasskey']) $updateset[] = "passkey=''";
To allow moderators to be able to reset a user's passkey, add to userdetails.php, in the moderator's editing section (around line 305):
print("<tr><td class=rowhead>Passkey</td><td colspan=2 align=left><input name=resetkey value=1 type=checkbox> Reset passkey</td></tr>n");
The corresponding line for this one goes in modtask.php, again somewhere before the SQL query. It's exactly the same as the one for takeprofedit:
if ($_POST['resetpasskey']) $updateset[] = "passkey=''";
We now have a unique passkey for each user, added dynamically to the torrent's announce url in each download. The passkey can be reset by either the user or a moderator. All that's left to do is to modify announce.php to handle it. This is the part that needs much more work, so feel free to experiment and post any enhancements. This code will allow the client to connect, but you will need to decide what restrictions to impose and how to enforce them.

Replace the section that starts and ends:
$req = "info_hash:peer_id:!ip:port:uploaded:downloaded:left:!event";

foreach (explode(":", $req) as $x)




$downloaded = 0 + $downloaded;

$uploaded = 0 + $uploaded;

$left = 0 + $left;
with the following:
foreach (array("passkey","info_hash","peer_id","ip","event") as $x)

$GLOBALS[$x] = "" . $_GET[$x];

foreach (array("port","downloaded","uploaded","left") as $x)

$GLOBALS[$x] = 0 + $_GET[$x];

if (strpos($passkey, "?")) {

  $tmp = substr($passkey, strpos($passkey, "?"));

$passkey = substr($passkey, 0, strpos($passkey, "?"));

$tmpname = substr($tmp, 1, strpos($tmp, "=")-1);

$tmpvalue = substr($tmp, strpos($tmp, "=")+1);

$GLOBALS[$tmpname] = $tmpvalue;


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]) . ")");

if (strlen($passkey) != 32) err("Invalid passkey (" . strlen($passkey) . " - $passkey)");

//if (empty($ip) || !preg_match('/^(d{1,3}.){3}d{1,3}$/s', $ip))

$ip = getip();
Such major changes were necessary here, because many clients do not comply with the defined standards and will send a malformed GET request url. This detects a malformed request and retrieves the correct data from it.

Next we need to verify the passkey is actually valid. After the lines:

insert the lines:
$valid = @mysql_fetch_row(@mysql_query("SELECT COUNT(*) FROM users WHERE passkey=" . sqlesc($passkey)));

if ($valid[0] != 1) err("Invalid passkey! Re-download the .torrent from $BASEURL");
To use the passkey to determine which username to record stats for, replace:
//// Up/down stats ////////////////////////////////////////////////////////////

if (!isset($self))


$rz = mysql_query("SELECT id, uploaded, downloaded, class FROM users WHERE ip='$ip' AND enabled = 'yes' ORDER BY last_access DESC LIMIT 1") or err("Tracker error 2");

if ($MEMBERSONLY && mysql_num_rows($rz) == 0)

err("Unrecognized host ($ip). Please go to $BASEURL to sign-up or login.");
//// Up/down stats ////////////////////////////////////////////////////////////

if (!isset($self))


$valid = @mysql_fetch_row(@mysql_query("SELECT COUNT(*) FROM peers WHERE torrent=$torrentid AND passkey=" . sqlesc($passkey)));

if ($valid[0] >= 1 && $seeder == 'no') err("Connection limit exceeded! You may only leech from one location at a time.");

if ($valid[0] >= 3 && $seeder == 'yes') err("Connection limit exceeded!");

$rz = mysql_query("SELECT id, uploaded, downloaded, class FROM users WHERE passkey=".sqlesc($passkey)." AND enabled = 'yes' ORDER BY last_access DESC LIMIT 1") or err("Tracker error 2");

if ($MEMBERSONLY && mysql_num_rows($rz) == 0)

err("Unknown passkey. Please redownload the torrent from $BASEURL.");
Now, with any luck, I've documented all the necessary changes and this should work without any problems.

The last change in the code already has some restrictions coded in. It will allow the torrent to be leeched from only one location at a time, as long as it is not currently being seeded elsewhere. This should prevent a torrent from being leeched by multiple users from the same account, for instance, if a passkey was leaked. On the other hand, some users like to seed from home and from work at the same time, in an attempt to improve their ratio. This code restricts users to seeding from a maximum of three locations simultaneously. For these checks to work, one final change is required, which is to insert the passkey into the peers table when the user connects. To do this, replace the line:
 $ret = mysql_query("INSERT INTO peers (connectable, torrent, peer_id, ip, port, uploaded, downloaded, to_go, started, last_action, seeder, userid, agent, uploadoffset, downloadoffset) VALUES ('$connectable', $torrentid, " . sqlesc($peer_id) . ", " . sqlesc($ip) . ", $port, $uploaded, $downloaded, $left, NOW(), NOW(), '$seeder', $userid, " . sqlesc($agent) . ", $uploaded, $downloaded)");
$ret = mysql_query("INSERT INTO peers (connectable, torrent, peer_id, ip, port, uploaded, downloaded, to_go, started, last_action, seeder, userid, agent, uploadoffset, downloadoffset, passkey) VALUES ('$connectable', $torrentid, " . sqlesc($peer_id) . ", " . sqlesc($ip) . ", $port, $uploaded, $downloaded, $left, NOW(), NOW(), '$seeder', $userid, " . sqlesc($agent) . ", $uploaded, $downloaded, " . sqlesc($passkey) . ")");
Do not ask me to help you work on your site that is not phpMyBitTorrent
Do not ask me to make a mod for any other source
Do not Ask me to setup your site.
I will no longer help you setup your site, there is a setup script if you have trouble with it post in the forum here or in BT.Managerô forum
My Current Demo is here
Reply With Quote
The Following 3 Users Say Thank You to joeroberts For This Useful Post:
adrian21 (23-04-09), sammygo (24-07-09), Tibys08 (29-05-11)