Location: PHPKode > projects > BtiTracker > Btit_148/announce.php
<?php




// Schedules an update to the summary table. It gets so much traffic
// that we do all our changes at once.
// When called, the column $column for the current info_hash is incremented
// by $value, or set to exactly $value if $abs is true.
function summaryAdd($column, $value, $abs = false)
{
    if (isset($GLOBALS["summaryupdate"][$column]))
    {
        if (!$abs)
            $GLOBALS["summaryupdate"][$column][0] += $value;
        else
            show_error("Tracker bug calling summaryAdd");
    }
    else
    {
        $GLOBALS["summaryupdate"][$column][0] = $value;
        $GLOBALS["summaryupdate"][$column][1] = $abs;
    }
}

ignore_user_abort(1);

$GLOBALS["peer_id"] = "";
$summaryupdate = array();

$BASEPATH=dirname(__FILE__);
require("$BASEPATH/include/config.php");
require("$BASEPATH/include/common.php");

error_reporting(0);

// connect to db
if ($GLOBALS["persist"])
    $conres=mysql_pconnect($dbhost, $dbuser, $dbpass) or show_error("Tracker errore - mysql_connect: " . mysql_error());
else
    $conres=mysql_connect($dbhost, $dbuser, $dbpass) or show_error("Tracker errore - mysql_connect: " . mysql_error());

    mysql_select_db($database) or show_error("Tracker errore - $database - ".mysql_error());

// connection is done ok

if (isset ($_GET["pid"]))
    $pid = $_GET["pid"];
else
    $pid = "";



if (strpos($pid, "?"))
{
  $tmp = substr($pid , strpos($pid , "?"));
  $pid  = substr($pid , 0,strpos($pid , "?"));
  $tmpname = substr($tmp, 1, strpos($tmp, "=")-1);
  $tmpvalue = substr($tmp, strpos($tmp, "=")+1);
  $_GET[$tmpname] = $tmpvalue;
}

// Many thanks to KktoMx for figuring out this head-ache causer,
// and to bideomex for showing me how to do it PROPERLY... :)
if (get_magic_quotes_gpc())
{
    $info_hash = bin2hex(stripslashes($_GET["info_hash"]));
    $peer_id = bin2hex(stripslashes($_GET["peer_id"]));
}
else
{
    $info_hash = bin2hex($_GET["info_hash"]);
    $peer_id = bin2hex($_GET["peer_id"]);
}

$iscompact=(isset($_GET["compact"])?$_GET["compact"]=='1':false);

// controll if client can handle gzip
if ($GZIP_ENABLED)
    {
    if (stristr($_SERVER["HTTP_ACCEPT_ENCODING"],"gzip") && extension_loaded('zlib') && ini_get("zlib.output_compression") == 0)
        {
        if (ini_get('output_handler')!='ob_gzhandler' && !$iscompact)
            {
            // only for non compact
            ob_start("ob_gzhandler");
            }
        else
            {
            ob_start();
            }
    }
    else
        {
        ob_start();
        }
}
// end gzip controll

header("Content-type: text/plain");
header("Pragma: no-cache");

// Error: no web browsers allowed
$agent = mysql_escape_string($_SERVER["HTTP_USER_AGENT"]);
// Deny access made with a browser...

if (ereg("^Mozilla\\/", $agent) || ereg("^Opera\\/", $agent) || ereg("^Links ", $agent) || ereg("^Lynx\\/", $agent))
{
    header("HTTP/1.0 500 Bad Request");
    die("This a a bittorrent application and can't be loaded into a browser");
}

// check if al needed information is sent by the client
if (!isset($_GET["port"]) || !isset($_GET["downloaded"]) || !isset($_GET["uploaded"]) || !isset($_GET["left"]))
    show_error("Invalid information received from BitTorrent client");

$port = $_GET["port"];
$ip = mysql_escape_string(str_replace("::ffff:", "", $_SERVER["REMOTE_ADDR"]));

// IP Banned ?? -> thank you to stunnabbz for post bug on sf.net
$nip = ip2long($ip);
$res = mysql_query("SELECT * FROM bannedip WHERE $nip >= first AND $nip <= last") or error_log(__FILE__." - ".__LINE__);
if (mysql_num_rows($res) > 0)
 {
   show_error("You are not authorized to use this tracker (".$SITENAME.") -- Your IP address (".$ip.") is BANNED.");
   die();
}
// end banned IP

$downloaded = floatval($_GET["downloaded"]);
$uploaded = floatval($_GET["uploaded"]);
$left = $_GET["left"];
$pid = AddSlashes($pid);

// if private announce turned on and PID empty string or not send by client
if (($pid=="" || !$pid) && $PRIVATE_ANNOUNCE)
   show_error("Please redownload the torrent. PID system is active and pid was not found in the torrent");


// PID turned on
if ($PRIVATE_ANNOUNCE) {
  $respid = mysql_query("SELECT users.*, level, can_download, WT FROM users INNER JOIN users_level on users.id_level=users_level.id WHERE pid='".$pid."' LIMIT 1");
  if (!$respid || mysql_num_rows($respid)!=1)
     show_error("Invalid PID (private announce): $pid. Please redownload torrent from $BASEURL.");
  else
      {
      $rowpid=mysql_fetch_array($respid);
      if ($rowpid["can_download"]!="yes" && $PRIVATE_ANNOUNCE)
         show_error("Sorry your level ($rowpid[level]) is not allowed to download from $BASEURL.");
      //waittime
      elseif ($rowpid["WT"]>0) {
        $wait=0;
        if (intval($rowpid['downloaded'])>0) $ratio=number_format($rowpid['uploaded']/$rowpid['downloaded'],2);
        else $ratio=0.0;
        $res2 =mysql_query("SELECT UNIX_TIMESTAMP(data) as data, uploader FROM namemap WHERE info_hash='".$info_hash."'");
        $added=mysql_fetch_array($res2);
        $vz = $added["data"];
        $timer = floor((time() - $vz) / 3600);
        if($ratio<1.0 && $rowpid['id']!=$added["uploader"]){
            $wait=$rowpid["WT"];
        }
        $wait -=$timer;
        if ($wait<=0)$wait=0;
        elseif($wait!=0 && $left!=0){show_error($rowpid["username"]." your Waiting Time = ".$wait." h");}
      }
      //end
  }
} else {
// PID turned off
   $respid = mysql_query("SELECT users.*, level, can_download, WT FROM users INNER JOIN users_level on users.id_level=users_level.id WHERE users.cip='$ip' LIMIT 1");
  if (!$respid || mysql_num_rows($respid)!=1)
     // maybe it's guest with new query I must found at least guest user
    $respid = mysql_query("SELECT users.*, level, can_download, WT FROM users INNER JOIN users_level on users.id_level=users_level.id WHERE users.id_level=1 LIMIT 1");
    if (!$respid || mysql_num_rows($respid)!=1)
      {
        // do nothing but tracker is misconfigured!!!
        // guest user not found...
      }
    else
      {
      $rowpid=mysql_fetch_array($respid);
      if ($rowpid["can_download"]!="yes")
         show_error("Sorry your level ($rowpid[level]) is not allowed to download from $BASEURL.");
      //waittime
      elseif ($rowpid["WT"]>0) {
        $wait=0;
        if (intval($rowpid['downloaded'])>0) $ratio=number_format($rowpid['uploaded']/$rowpid['downloaded'],2);
        else $ratio=0.0;
        $res2 =mysql_query("SELECT UNIX_TIMESTAMP(data) as data, uploader FROM namemap WHERE info_hash='".$info_hash."'");
        $added=mysql_fetch_array($res2);
        $vz = $added["data"];
        $timer = floor((time() - $vz) / 3600);
        if($ratio<1.0 && $rowpid['id']!=$added["uploader"]){
            $wait=$rowpid["WT"];
        }
        $wait -=$timer;
        if ($wait<=0)
            $wait=0;
        elseif($wait!=0 && $left!=0)
            {show_error($rowpid["username"]." your Waiting Time = ".$wait." h");}
      }
      //end
    }
}


if (isset($_GET["event"]))
    $event = $_GET["event"];
else
    $event = "";

if (!isset($GLOBALS["ip_override"]))
    $GLOBALS["ip_override"] = true;

if (isset($_GET["numwant"]))
    if ($_GET["numwant"] < $GLOBALS["maxpeers"] && $_GET["numwant"] >= 0)
        $GLOBALS["maxpeers"]=$_GET["numwant"];

if (isset($_GET["trackerid"]))
{
    if (is_numeric($_GET["trackerid"]))
        $GLOBALS["trackerid"] = mysql_escape_string($_GET["trackerid"]);
}
if (!is_numeric($port) || !is_numeric($downloaded) || !is_numeric($uploaded) || !is_numeric($left))
    show_error("Invalid numerical field(s) from client");


/////////////////////////////////////////////////////
// Checks

// Upgrade holdover: check for unset directives
if (!isset($GLOBALS["countbytes"]))
    $GLOBALS["countbytes"] = true;
if (!isset($GLOBALS["peercaching"]))
    $GLOBALS["peercaching"] = false;



/* Returns true if the user is firewalled, NAT'd, or whatever.
 * The original tracker had its --nat_check parameter, so
 * here is my version.
 *
 * This code has proven itself to be sufficiently correct,
 * but will consume system resources when a lot of httpd processes
 * are lingering around trying to connect to remote hosts.
 * Consider disabling it under higher loads.
 */
function isFireWalled($hash, $peerid, $ip, $port)
{

    // NAT checking off?
    if (!$GLOBALS["NAT"])
        return false;

    $protocol_name = 'BitTorrent protocol';
    $theError = "";
    // Hoping 10 seconds will be enough
    $fd = fsockopen($ip, $port, $errno, $theError, 10);
    if (!$fd)
        return true;

    stream_set_timeout($fd, 5, 0);
    fwrite($fd, chr(strlen($protocol_name)).$protocol_name.hex2bin("0000000000000000").
        hex2bin($hash));

    $data = fread($fd, strlen($protocol_name)+1+20+20+8); // ideally...

    fclose($fd);
    $offset = 0;

    // First byte: strlen($protocol_name), then the protocol string itself
    if (ord($data[$offset]) != strlen($protocol_name))
        return true;

    $offset++;
    if (substr($data, $offset, strlen($protocol_name)) != $protocol_name)
        return true;

    $offset += strlen($protocol_name);
    // 8 bytes reserved, ignore
    $offset += 8;

    // Download ID (hash)
    if (substr($data, $offset, 20) != hex2bin($hash))
        return true;

    $offset+=20;

    // Peer ID
    if (substr($data, $offset, 20) != hex2bin($peerid))
        return true;

    return false;
}


// Returns info on one peer
function getPeerInfo($user, $hash)
{
    // If "trackerid" is set, let's try that
    if (isset($GLOBALS["trackerid"]))
    {
        $query = "SELECT peer_id,bytes,ip,port,status,lastupdate,sequence FROM peers WHERE sequence=${GLOBALS["trackerid"]} AND infohash=\"$hash\"";
        $results = mysql_query($query) or show_error("Tracker error: invalid torrent");
        $data = mysql_fetch_assoc($results);
        if (!$data || $data["peer_id"] != $user)
        {
            // Damn, but don't crash just yet.
            $query = "SELECT peer_id,bytes,ip,port,status,lastupdate,sequence from peers where peer_id=\"$user\" AND infohash=\"$hash\"";
            $results = mysql_query($query) or showError("Tracker error: invalid torrent");
            $data = mysql_fetch_assoc($results);
            $GLOBALS["trackerid"] = $data["sequence"];
        }
    }
    else
    {
        $query = "SELECT peer_id,bytes,ip,port,status,lastupdate,sequence from peers where peer_id=\"$user\" AND infohash=\"$hash\"";
        $results = mysql_query($query) or showError("Tracker error: invalid torrent");
        $data = mysql_fetch_assoc($results);
        $GLOBALS["trackerid"] = $data["sequence"];
    }

    if (!($data))
        return false;

    return $data;
}

/////////////////////////////////////////////////////
// Any section of code might need to make a new peer, so this is a function here.
// I don't want to put it into funcsv2, even though it should, just for consistency's sake.

function start($info_hash, $ip, $port, $peer_id, $left, $downloaded=0, $uploaded=0, $upid="")
{
  global $BASEURL;

    if (isset($_GET["ip"]) && $GLOBALS["ip_override"])
    {
        // compact check: valid IP address:
        if ($_GET["ip"]!=long2ip(ip2long($_GET["ip"])))
            showError("Invalid IP address. Must be standard dotted decimal (hostnames not allowed)");

        $ip = mysql_escape_string($_GET["ip"]);
    }
    else $ip = getip();

    $ip = mysql_escape_string($ip);
    $agent = mysql_escape_string($_SERVER["HTTP_USER_AGENT"]);
    $remotedns = gethostbyaddr($ip);

    if (isset($_GET["ip"])) $nuIP = $_GET["ip"];
      else $nuIP = "";
    if ($remotedns == $nuIP)
      $remotedns = "AA";
    else
        {
        $remotedns = strtoupper($remotedns);
        preg_match('/^(.+)\.([A-Z]{2,3})$/', $remotedns, $tldm);
    if (!empty($tldm[2]))
          $remotedns = mysql_escape_string($tldm[2]);
    else
      $remotedns = "AA";
      }

    if ($left == 0)
        $status = "seeder";
    else
        $status = "leecher";

    if (@isFireWalled($info_hash, $peer_id, $ip, $port))
        $nat = "Y";
    else
        $nat = "N";



    $compact = mysql_escape_string(pack('Nn', ip2long($ip), $port));
    $peerid = mysql_escape_string('2:ip' . strlen($ip) . ':' . $ip . '7:peer id20:' . hex2bin($peer_id) . "4:porti{$port}e");
    $no_peerid = mysql_escape_string('2:ip' . strlen($ip) . ':' . $ip . "4:porti{$port}e");


    $results = @mysql_query("INSERT INTO peers SET infohash=\"$info_hash\", peer_id=\"$peer_id\", port=\"$port\", ip=\"$ip\", lastupdate=UNIX_TIMESTAMP(), bytes=\"$left\", status=\"$status\", natuser=\"$nat\", client=\"$agent\", dns=\"$remotedns\", downloaded=$downloaded, uploaded=$uploaded, pid=\"$upid\"");


    // Special case: duplicated peer_id.
    if (!$results)
    {
        if (mysql_errno()==1062)
        {
            // Duplicate peer_id! Check IP address
            $peer = getPeerInfo($peer_id, $info_hash);
            if ($ip == $peer["ip"])
            {
                // Same IP address. Tolerate this error.
                return "WHERE natuser='N'";
            }
            // Different IP address. Assume they were disconnected, and alter the IP address.
            quickQuery("UPDATE peers SET ip=\"$ip\", compact=\"$compact\", with_peerid=\"$peerid\", without_peerid=\"$no_peerid\" WHERE peer_id=\"$peer_id\"  AND infohash=\"$info_hash\"");
            return "WHERE natuser='N'";
        }
        error_log("BtiTracker: start: ".mysql_error());
        show_error("Tracker/database error. The details are in the error log.");
    }
    $GLOBALS["trackerid"] = mysql_insert_id();

    @mysql_query("UPDATE peers SET sequence=\"${GLOBALS["trackerid"]}\", compact=\"$compact\", with_peerid=\"$peerid\", without_peerid=\"$no_peerid\" WHERE peer_id=\"$peer_id\" AND infohash=\"$info_hash\"");

    if ($left == 0)
    {
        summaryAdd("seeds", 1);
        return "WHERE status=\"leecher\" AND natuser='N'";
    }
    else
    {
        summaryAdd("leechers", 1);
        return "WHERE natuser='N'";
    }
}

/// End of function start

// default for max peers with same pid/ip
if (!isset($GLOBALS["maxseeds"])) $GLOBALS["maxseeds"]=2;
if (!isset($GLOBALS["maxleech"])) $GLOBALS["maxleech"]=2;

//
// Returns true if the torrent exists.
// Currently checks by locating the row in "summary"
// Always returns true if $dynamic_torrents=="1" unless an error occured
function verifyTorrent($hash)
{
    // only for internal tracked torrent!
    $query = "SELECT COUNT(*) FROM summary INNER JOIN namemap ON namemap.info_hash=summary.info_hash WHERE namemap.external='no' AND summary.info_hash=\"$hash\"";
    $results = mysql_query($query);

    $res = mysql_result($results,0,0);

    if ($res == 1)
        return true;

    if ($GLOBALS["dynamic_torrents"])
        return makeTorrent($hash);

    return false;
}


// Slight redesign of loadPeers
function getRandomPeers($hash, $where="")
{
    // Don't want to send a bad "num peers" for new seeds

    $where="WHERE infohash=\"$hash\"";

    if ($GLOBALS["NAT"])
        $results = mysql_query("SELECT COUNT(*) FROM peers WHERE natuser = 'N' AND infohash=\"$hash\"");
    else
        $results = mysql_query("SELECT COUNT(*) FROM peers WHERE infohash=\"$hash\"");

    $peercount = mysql_result($results, 0,0);

    // ORDER BY RAND() is expensive. Don't do it when the load gets too high
    if ($peercount < 500)
        $query = "SELECT ".((isset($_GET["no_peer_id"]) && $_GET["no_peer_id"] == 1) ? "" : "peer_id,")."ip, port, status FROM peers ".$where." ORDER BY RAND() LIMIT ${GLOBALS['maxpeers']}";
    else
        $query = "SELECT ".((isset($_GET["no_peer_id"]) && $_GET["no_peer_id"] == 1) ? "" : "peer_id,")."ip, port, status FROM peers ".$where." LIMIT "hide@address.com(0, $peercount - $GLOBALS["maxpeers"]).", ${GLOBALS['maxpeers']}";

    $results = mysql_query($query);
    if (!$results)
        return false;

    $peerno = 0;
    while ($return[] = mysql_fetch_assoc($results))
        $peerno++;

    array_pop ($return);
    mysql_free_result($results);
    $return['size'] = $peerno;

    return $return;
}

// Transmits the actual data to the peer. No other output is permitted if
// this function is called, as that would break BEncoding.
// I don't use the bencode library, so watch out! If you add data,
// rules such as dictionary sorting are enforced by the remote side.
function sendPeerList($peers)
{
    echo "d";
    echo "8:intervali".$GLOBALS["report_interval"]."e";
    if (isset($GLOBALS["min_interval"]))
        echo "12:min intervali".$GLOBALS["min_interval"]."e";
    echo "5:peers";
    $size=$peers["size"];
    if (isset($_GET["compact"]) && $_GET["compact"] == '1')
    {
        $p = '';
        for ($i=0; $i < $size; $i++)
            $p .= str_pad(pack("Nn", ip2long($peers[$i]['ip']), $peers[$i]['port']), 6);
        echo strlen($p).':'.$p;
    }
    else // no_peer_id or no feature supported
    {
        echo 'l';
        for ($i=0; $i < $size; $i++)
        {
            echo "d2:ip".strlen($peers[$i]["ip"]).":".$peers[$i]["ip"];
            if (isset($peers[$i]["peer_id"]))
                echo "7:peer id20:".hex2bin($peers[$i]["peer_id"]);
            echo "4:porti".$peers[$i]["port"]."ee";
        }
        echo "e";
    }
    if (isset($GLOBALS["trackerid"]))
    {
        // Now it gets annoying. trackerid is a string
        echo "10:tracker id".strlen($GLOBALS["trackerid"]).":".$GLOBALS["trackerid"];
    }
    echo "e";
}

// Faster pass-through version of getRandompeers => sendPeerList
// It's the only way to use cache tables. In fact, it only uses it.
function sendRandomPeers($info_hash)
{

    if (isset($_GET["compact"]) && $_GET["compact"] == '1')
        $column = "compact";
    else if (isset($_GET["no_peer_id"]) && $_GET["no_peer_id"] == '1')
        $column = "without_peerid";
    else
        $column = "with_peerid";

    $query = "SELECT $column FROM peers WHERE infohash=\"$info_hash\" ORDER BY RAND() LIMIT ".$GLOBALS["maxpeers"];

    echo "d";
    echo "8:intervali".$GLOBALS["report_interval"]."e";
    if (isset($GLOBALS["min_interval"]))
        echo "12:min intervali".$GLOBALS["min_interval"]."e";
    echo "5:peers";

    $result = mysql_query($query);
    if ($column == "compact")
    {
        echo (mysql_num_rows($result) * 6) . ":";
        while ($row = mysql_fetch_row($result))
            echo str_pad($row[0], 6); //echo $row[0];
    }
    else
    {
        echo "l";
        while ($row = mysql_fetch_row($result))
            echo "d".$row[0]."e";
        echo "e";
    }
    if (isset($GLOBALS["trackerid"]))
        echo "10:tracker id".strlen($GLOBALS["trackerid"]).":".$GLOBALS["trackerid"];
    echo "e";

    mysql_free_result($result);
}


// Deletes a peer from the system and performs all cleaning up
//
//  $assumepeer contains the result of getPeerInfo, or false
//  if we should grab it ourselves.
function killPeer($userid, $hash, $left, $assumepeer = false)
{
    if (!$assumepeer)
    {
        $peer = getPeerInfo($userid, $hash);
        if (!$peer)
            return;
        if ($left != $peer["bytes"])
            $bytes = bcsub($peer["bytes"], $left);
        else
            $bytes = 0;
    }
    else
    {
        $bytes = 0;
        $peer = $assumepeer;
    }

    quickQuery("DELETE FROM peers WHERE peer_id=\"$userid\" AND infohash=\"$hash\"");
    if (mysql_affected_rows() == 1)
    {
        if ($peer["status"] == "leecher")
            summaryAdd("leechers", -1);
        else
            summaryAdd("seeds", -1);
        if ($GLOBALS["countbytes"] && ((float)$bytes) > 0)
            summaryAdd("dlbytes",$bytes);
        if ($peer["bytes"] != 0 && $left == 0)
            summaryAdd("finished", 1);

        summaryAdd("lastcycle", "UNIX_TIMESTAMP()", true);
    }
}


// Transfers bytes from "left" to "dlbytes" when a peer reports in.
function collectBytes($peer, $hash, $left, $downloaded=0, $uploaded=0, $pid="")
{
    $peerid=$peer["peer_id"];

    if (!$GLOBALS["countbytes"])
    {
        quickQuery("UPDATE peers SET lastupdate=UNIX_TIMESTAMP(), downloaded=$downloaded, uploaded=$uploaded, pid=\"$pid\" where infohash=\"$hash\" AND " . (isset($GLOBALS["trackerid"]) ? "sequence=\"${GLOBALS["trackerid"]}\"" : "peer_id=\"$peerid\""));
        return;
    }
    $diff = bcsub($peer["bytes"], $left);
    quickQuery("UPDATE peers set " . (($diff != 0) ? "bytes=\"$left\"," : ""). " lastupdate=UNIX_TIMESTAMP(), downloaded=$downloaded, uploaded=$uploaded, pid=\"$pid\" where infohash=\"$hash\" AND " . (isset($GLOBALS["trackerid"]) ? "sequence=\"${GLOBALS["trackerid"]}\"" : "peer_id=\"$peerid\""));

    // Anti-negative clause
    if (((float)$diff) > 0)
        summaryAdd("dlbytes", $diff);
}

function runSpeed($info_hash, $delta)
{
        //stick in our latest data before we calc it out
        quickQuery("INSERT IGNORE INTO timestamps (info_hash, bytes, delta, sequence) SELECT '$info_hash' AS info_hash, dlbytes, UNIX_TIMESTAMP() - lastSpeedCycle, NULL FROM summary WHERE info_hash=\"$info_hash\"");

        // mysql blows sometimes so we have to read the data into php before updating it
        $results = mysql_query('SELECT (MAX(bytes)-MIN(bytes))/SUM(delta), COUNT(*), MIN(sequence) FROM timestamps WHERE info_hash="'.$info_hash.'"' );
        $data = mysql_fetch_row($results);

        summaryAdd("speed", $data[0], true);
        summaryAdd("lastSpeedCycle", "UNIX_TIMESTAMP()", true);

        // if we have more than 20 drop the rest
        if ($data[1] == 21)
            quickQuery("DELETE FROM timestamps WHERE info_hash=\"$info_hash\" AND sequence=${data[2]}");
        else if ($data[1] > 21)
        // This query requires MySQL 4.0.x, but should rarely be used.
        quickQuery ('DELETE FROM timestamps WHERE info_hash="'.$info_hash.'" ORDER BY sequence LIMIT '.($data['1'] - 20));
}

//




// select how many users with same
$results = mysql_query("SELECT status, count(status) FROM peers WHERE ".($PRIVATE_ANNOUNCE?"pid=\"$pid\"":"ip=\"$ip\"")." AND infohash=\"$info_hash\" AND peer_id<>\"$peer_id\" GROUP BY status") or show_error("Tracker error: invalid torrent");
$status = array();

while ($resstat = mysql_fetch_row($results))
  $status[$resstat[0]]=$resstat[1];

if (!isset($status["leecher"]))
    $status["leecher"]=0;
if (!isset($status["seeder"]))
    $status["seeder"]=0;

if ($status["seeder"]>=$GLOBALS["maxseeds"] || $status["leecher"]>=$GLOBALS["maxleech"])
   show_error("Sorry max peers reached! Redownload torrent from $BASEURL");
// end select

// UPDATE users ratio down/up for every event on every announce
// only with the difference between stored down/up and sended by client
if ($LIVESTATS)
  {
     $resstat=mysql_query("SELECT uploaded, downloaded FROM peers WHERE peer_id=\"$peer_id\" AND infohash=\"$info_hash\"");
     if ($resstat && mysql_num_rows($resstat)>0)
         {
         $livestat=mysql_fetch_array($resstat);
         // only if uploaded/downloaded are >= stored data in peer list
         if ($uploaded>=$livestat["uploaded"])
               $newup=($uploaded-$livestat["uploaded"]);
         else
               $newup=$uploaded;

         if ($downloaded>=$livestat["downloaded"])
               $newdown=($downloaded-$livestat["downloaded"]);
         else
               $newdown=$downloaded;
         quickquery("UPDATE users SET downloaded=IFNULL(downloaded,0)+$newdown, uploaded=IFNULL(uploaded,0)+$newup WHERE ".($PRIVATE_ANNOUNCE?"pid='$pid'":"cip='$ip'")."");
         }
       mysql_free_result($resstat);

       // begin history - also this is registred live or not
       if ($LOG_HISTORY)
         {
          $resu=mysql_query("SELECT id FROM users WHERE ".($PRIVATE_ANNOUNCE?"pid='$pid'":"cip='$ip'") ." ORDER BY lastconnect DESC LIMIT 1");
          // if found at least one user should be 1
          if ($resu && mysql_num_rows($resu)==1)
            {
              $curuid=mysql_fetch_array($resu);
              quickQuery("UPDATE history set uploaded=IFNULL(uploaded,0)+$newup, downloaded=IFNULL(downloaded,0)+$newdown WHERE uid=".$curuid["id"]." AND infohash='$info_hash'");
            }
          mysql_free_result($resu);
       }
       // end history    }
}



switch ($event)
{
    // client sent start
    case "started":
       verifyTorrent($info_hash) or show_error("Torrent is not authorized for use on this tracker.");

       $start = start($info_hash, $ip, $port, $peer_id, $left, $downloaded, $uploaded, $pid);

       if ($GLOBALS["peercaching"])
           sendRandomPeers($info_hash);
       else
       {
           $peers = getRandomPeers($info_hash, "");
           sendPeerList($peers);
       }

       // begin history
       if ($LOG_HISTORY)
         {
          $resu=mysql_query("SELECT id FROM users WHERE ".($PRIVATE_ANNOUNCE?"pid='$pid'":"cip='$ip'") ." ORDER BY lastconnect DESC LIMIT 1");
          // if found at least one user should be 1
          if ($resu && mysql_num_rows($resu)==1)
            {
              $curuid=mysql_fetch_array($resu);
              quickQuery("UPDATE history set active='yes',agent='".getagent($agent,$peer_id)."' WHERE uid=".$curuid["id"]." AND infohash='$info_hash'");
              // record is not present, create it (only if not seeder: original seeder don't exist in history table, other already exists)
              if (mysql_affected_rows()==0 && $left>0)
                 quickQuery("INSERT INTO history (uid,infohash,active,agent) VALUES (".$curuid["id"].",'$info_hash','yes','".getagent($agent,$peer_id)."')");
            }
          mysql_free_result($resu);
       }
       // end history
    break;

    // client sent stop
    case "stopped":

       verifyTorrent($info_hash) or show_error("Torrent is not authorized for use on this tracker.");
       killPeer($peer_id, $info_hash, $left);

       // I don't know why, but the real tracker returns peers on event=stopped
       // but I'll just send an empty list. On the other hand,
       // TheSHADOW asked for this.
       if (isset($_GET["tracker"]))
           $peers = getRandomPeers($info_hash);
       else
           $peers = array("size" => 0);

       sendPeerList($peers);

       // update user uploaded/downloaded
       if (!$LIVESTATS)
            @mysql_query("UPDATE users SET uploaded=IFNULL(uploaded,0)+$uploaded, downloaded=IFNULL(downloaded,0)+$downloaded WHERE ".($PRIVATE_ANNOUNCE?"pid='$pid'":"cip='$ip'")." AND id>1 LIMIT 1");

       // begin history - if LIVESTAT, only the active/agent part
       if ($LOG_HISTORY)
         {
          $resu=mysql_query("SELECT id FROM users WHERE ".($PRIVATE_ANNOUNCE?"pid='$pid'":"cip='$ip'") ." ORDER BY lastconnect DESC LIMIT 1");
          // if found at least one user should be 1
          if ($resu && mysql_num_rows($resu)==1)
            {
              $curuid=mysql_fetch_array($resu);
              quickQuery("UPDATE history set active='no',".($LIVESTATS?"":" uploaded=IFNULL(uploaded,0)+$uploaded, downloaded=IFNULL(downloaded,0)+$downloaded,")." agent='".getagent($agent,$peer_id)."' WHERE uid=".$curuid["id"]." AND infohash='$info_hash'");
            }
          mysql_free_result($resu);
       }
       // end history    }
    break;

    // client sent complete
    case "completed":
        verifyTorrent($info_hash) or show_error("Torrent is not authorized for use on this tracker.");
        $peer_exists = getPeerInfo($peer_id, $info_hash);

        if (!is_array($peer_exists))
            start($info_hash, $ip, $port, $peer_id, $left, $downloaded, $uploaded, $pid);
        else
        {
            quickQuery("UPDATE peers SET bytes=0, status=\"seeder\" WHERE sequence=\"${GLOBALS["trackerid"]}\" AND infohash=\"$info_hash\"");

            // Race check
            if (mysql_affected_rows() == 1)
            {
                summaryAdd("leechers", -1);
                summaryAdd("seeds", 1);
                summaryAdd("finished", 1);
                summaryAdd("lastcycle", "UNIX_TIMESTAMP()", true);
            }
        }
        collectBytes($peer_exists, $info_hash, $left, $downloaded, $uploaded, $pid);

        $peers=getRandomPeers($info_hash);

        sendPeerList($peers);

        // begin history
        if ($LOG_HISTORY)
          {
           $resu=mysql_query("SELECT id FROM users WHERE ".($PRIVATE_ANNOUNCE?"pid='$pid'":"cip='$ip'") ." ORDER BY lastconnect DESC LIMIT 1");
           // if found at least one user should be 1
           if ($resu && mysql_num_rows($resu)==1)
             {
               $curuid=mysql_fetch_array($resu);
               // if user has already completed this torrent, mysql will give error because of unique index (uid+infohash)
               // upload/download will be updated on stop event...
               // record should already exist (created on stated event)
               quickQuery("UPDATE history SET date=UNIX_TIMESTAMP(),active='yes',agent='".getagent($agent,$peer_id)."' WHERE uid=".$curuid["id"]." AND infohash='$info_hash'");
               // record is not present, create it
               if (mysql_affected_rows()==0)
                  quickQuery("INSERT INTO history (uid,infohash,date,active,agent) VALUES (".$curuid["id"].",'$info_hash',UNIX_TIMESTAMP(),'yes','".getagent($agent,$peer_id)."')");

             }
           mysql_free_result($resu);
        }
        // end history
    break;

    // client sent no event
    case "":
        verifyTorrent($info_hash) or show_error("Torrent is not authorized for use on this tracker.");
        $peer_exists = getPeerInfo($peer_id, $info_hash);
        $where = "WHERE natuser='N'";

        if (!is_array($peer_exists))
            $where = start($info_hash, $ip, $port, $peer_id, $left, $downloaded, $uploaded, $pid);

        if ($peer_exists["bytes"] != 0 && $left == 0)
        {
            quickQuery("UPDATE peers SET bytes=0, status=\"seeder\" WHERE sequence=\"${GLOBALS["trackerid"]}\" AND infohash=\"$info_hash\"");
            if (mysql_affected_rows() == 1)
            {
                summaryAdd("leechers", -1);
                summaryAdd("seeds", 1);
                summaryAdd("finished", 1);
                summaryAdd("lastcycle", "UNIX_TIMESTAMP()", true);
            }
        }
        collectBytes($peer_exists, $info_hash, $left, $downloaded, $uploaded, $pid);

    if ($GLOBALS["peercaching"])
        sendRandomPeers($info_hash);
    else
    {
        $peers = getRandomPeers($info_hash, "");
        sendPeerList($peers);
    }

    break;

    // not valid event
    default:
        show_error("Invalid event= from client.");

}


if ($GLOBALS["countbytes"])
{
    // Once every minute or so, we run the speed update checker.
    $query = @mysql_query("SELECT UNIX_TIMESTAMP() - lastSpeedCycle FROM summary WHERE info_hash=\"$info_hash\"");
    $results = mysql_fetch_row($query);
    if ($results[0] >= 60)
       @runSpeed($info_hash, $results[0]);
}


// Finally, it's time to do stuff to the summary table.
if (!empty($summaryupdate))
{
    $stuff = "";
    foreach ($summaryupdate as $column => $value)
    {
        $stuff .= ', '.$column. ($value[1] ? "=" : "=$column+") . $value[0];
    }
    mysql_query("UPDATE summary SET ".substr($stuff, 1)." WHERE info_hash=\"$info_hash\"");
}

// generaly not needed, but
// just in case server don't close connection
mysql_close();

?>
Return current item: BtiTracker