/**
  * prepares start of a bittorrent-client.
  * prepares vars and other generic stuff
  * @param $torrent name of the torrent
  * @param $interactive (1|0) : is this a interactive startup with dialog ?
  */
 function prepareStartTorrentClient($torrent, $interactive)
 {
     if ($this->status < 1) {
         $this->status = -1;
         $this->messages .= "Error. ClientHandler in wrong state on prepare-request.";
         return;
     }
     $this->skip_hash_check = "";
     if ($interactive == 1) {
         // interactive, get vars from request vars
         $this->rate = getRequestVar('rate');
         if (empty($this->rate)) {
             if ($this->rate != "0") {
                 $this->rate = $this->cfg["max_upload_rate"];
             }
         }
         $this->drate = getRequestVar('drate');
         if (empty($this->drate)) {
             if ($this->drate != "0") {
                 $this->drate = $this->cfg["max_download_rate"];
             }
         }
         $this->superseeder = getRequestVar('superseeder');
         if (empty($this->superseeder)) {
             $this->superseeder = "0";
         }
         // should be 0 in most cases
         $this->runtime = getRequestVar('runtime');
         if (empty($this->runtime)) {
             $this->runtime = $this->cfg["torrent_dies_when_done"];
         }
         $this->maxuploads = getRequestVar('maxuploads');
         if (empty($this->maxuploads)) {
             if ($this->maxuploads != "0") {
                 $this->maxuploads = $this->cfg["max_uploads"];
             }
         }
         $this->minport = getRequestVar('minport');
         if (empty($this->minport)) {
             $this->minport = $this->cfg["minport"];
         }
         $this->maxport = getRequestVar('maxport');
         if (empty($this->maxport)) {
             $this->maxport = $this->cfg["maxport"];
         }
         $this->maxcons = getRequestVar('maxcons');
         if (empty($this->maxcons)) {
             $this->maxcons = $this->cfg["maxcons"];
         }
         $this->rerequest = getRequestVar("rerequest");
         if (empty($this->rerequest)) {
             $this->rerequest = $this->cfg["rerequest_interval"];
         }
         $this->sharekill = getRequestVar('sharekill');
         if ($this->runtime == "True") {
             $this->sharekill = "-1";
         }
         if (empty($this->sharekill)) {
             if ($this->sharekill != "0") {
                 $this->sharekill = $this->cfg["sharekill"];
             }
         }
         $this->savepath = getRequestVar('savepath');
         $this->skip_hash_check = getRequestVar('skiphashcheck');
     } else {
         // non-interactive, load settings from db and set vars
         $this->rerequest = $this->cfg["rerequest_interval"];
         $this->skip_hash_check = $this->cfg["skiphashcheck"];
         $this->superseeder = 0;
         // load settings
         $settingsAry = loadTorrentSettings(urldecode($torrent));
         $this->rate = $settingsAry["max_upload_rate"];
         $this->drate = $settingsAry["max_download_rate"];
         $this->runtime = $settingsAry["torrent_dies_when_done"];
         $this->maxuploads = $settingsAry["max_uploads"];
         $this->minport = $settingsAry["minport"];
         $this->maxport = $settingsAry["maxport"];
         $this->maxcons = $settingsAry["maxcons"];
         $this->sharekill = $settingsAry["sharekill"];
         $this->savepath = $settingsAry["savepath"];
         // fallback-values if fresh-torrent is started non-interactive or
         // something else strange happened
         if ($this->rate == '') {
             $this->rate = $this->cfg["max_upload_rate"];
         }
         if ($this->drate == '') {
             $this->drate = $this->cfg["max_download_rate"];
         }
         if ($this->runtime == '') {
             $this->runtime = $this->cfg["torrent_dies_when_done"];
         }
         if ($this->maxuploads == '') {
             $this->maxuploads = $this->cfg["max_uploads"];
         }
         if ($this->minport == '') {
             $this->minport = $this->cfg["minport"];
         }
         if ($this->maxport == '') {
             $this->maxport = $this->cfg["maxport"];
         }
         if ($this->maxcons == '') {
             $this->maxcons = $this->cfg["maxcons"];
         }
         if ($this->sharekill == '') {
             $this->sharekill = $this->cfg["sharekill"];
         }
     }
     // queue
     if ($this->cfg["AllowQueing"]) {
         if (IsAdmin()) {
             $this->queue = getRequestVar('queue');
             if ($this->queue == 'on') {
                 $this->queue = "1";
             } else {
                 $this->queue = "0";
             }
         } else {
             $this->queue = "1";
         }
     } else {
         $this->queue = "0";
     }
     //
     $this->torrent = urldecode($torrent);
     $this->alias = getAliasName($this->torrent);
     $this->owner = getOwner($this->torrent);
     if (empty($this->savepath)) {
         $this->savepath = $this->cfg['path'] . $this->owner . "/";
     }
     // ensure path has trailing slash
     $this->savepath = checkDirPathString($this->savepath);
     // The following lines of code were suggested by Jody Steele jmlsteele@stfu.ca
     // This is to help manage user downloads by their user names
     // if the user's path doesnt exist, create it
     if (!is_dir($this->cfg["path"] . "/" . $this->owner)) {
         if (is_writable($this->cfg["path"])) {
             mkdir($this->cfg["path"] . "/" . $this->owner, 0777);
         } else {
             AuditAction($this->cfg["constants"]["error"], "Error -- " . $this->cfg["path"] . " is not writable.");
             if (IsAdmin()) {
                 $this->status = -1;
                 header("location: admin.php?op=configSettings");
                 return;
             } else {
                 $this->status = -1;
                 $this->messages .= "Error. TorrentFlux settings are not correct (path is not writable) -- please contact an admin.";
             }
         }
     }
     // create AliasFile object and write out the stat file
     include_once "AliasFile.php";
     $this->af = AliasFile::getAliasFileInstance($this->cfg["torrent_file_path"] . $this->alias . ".stat", $this->owner, $this->cfg, $this->handlerName);
     //XFER: before a torrent start/restart save upload/download xfer to SQL
     $torrentTotals = getTorrentTotalsCurrent($this->torrent);
     saveXfer($this->owner, $torrentTotals["downtotal"] + 0, $torrentTotals["uptotal"] + 0);
     // update totals for this torrent
     updateTorrentTotals($this->torrent);
     // set param for sharekill
     if ($this->sharekill <= 0) {
         // nice, we seed forever
         $this->sharekill_param = 0;
     } else {
         // recalc sharekill
         $totalAry = getTorrentTotals(urldecode($torrent));
         $upTotal = $totalAry["uptotal"] + 0;
         $torrentSize = $this->af->size + 0;
         $upWanted = $this->sharekill / 100 * $torrentSize;
         if ($upTotal >= $upWanted) {
             // we already have seeded at least
             // wanted percentage. continue to seed
             // forever is suitable in this case ~~
             $this->sharekill_param = 0;
         } else {
             // not done seeding wanted percentage
             $this->sharekill_param = (int) ($this->sharekill - $upTotal / $torrentSize * 100);
             // the type-cast may have floored the value. (tornado lacks
             // precision because only (really?) accepting percentage-values)
             // better to seed more than less so we add a percent in case ;)
             if ($upWanted % $upTotal != 0) {
                 $this->sharekill_param += 1;
             }
             // sanity-check.
             if ($this->sharekill_param <= -1) {
                 $this->sharekill_param = 0;
             }
         }
     }
     if ($this->cfg["AllowQueing"]) {
         if ($this->queue == "1") {
             $this->af->QueueTorrentFile();
             // this only writes out the stat file (does not start torrent)
         } else {
             if ($this->setClientPort() === false) {
                 return;
             }
             $this->af->StartTorrentFile();
             // this only writes out the stat file (does not start torrent)
         }
     } else {
         if ($this->setClientPort() === false) {
             return;
         }
         $this->af->StartTorrentFile();
         // this only writes out the stat file (does not start torrent)
     }
     $this->status = 2;
 }
/**
 * deletes a torrent
 *
 * @param $torrent name of the torrent
 * @param $alias_file alias-file of the torrent
 * @return boolean of success
 */
function deleteTorrent($torrent, $alias_file)
{
    $delfile = $torrent;
    global $cfg;
    //$alias_file = getRequestVar('alias_file');
    $torrentowner = getOwner($delfile);
    if ($cfg["user"] == $torrentowner || IsAdmin()) {
        include_once "AliasFile.php";
        // we have more meta-files than .torrent. handle this.
        if (substr(strtolower($torrent), -8) == ".torrent") {
            // this is a torrent-client
            $btclient = getTorrentClient($delfile);
            $af = AliasFile::getAliasFileInstance($cfg['torrent_file_path'] . $alias_file, $torrentowner, $cfg, $btclient);
            // update totals for this torrent
            updateTorrentTotals($delfile);
            // remove torrent-settings from db
            deleteTorrentSettings($delfile);
            // client-proprietary leftovers
            include_once "ClientHandler.php";
            $clientHandler = ClientHandler::getClientHandlerInstance($cfg, $btclient);
            $clientHandler->deleteTorrentCache($torrent);
        } else {
            if (substr(strtolower($torrent), -4) == ".url") {
                // this is wget. use tornado statfile
                $alias_file = str_replace(".url", "", $alias_file);
                $af = AliasFile::getAliasFileInstance($cfg['torrent_file_path'] . $alias_file, $cfg['user'], $cfg, 'tornado');
            } else {
                // this is "something else". use tornado statfile as default
                $af = AliasFile::getAliasFileInstance($cfg['torrent_file_path'] . $alias_file, $cfg['user'], $cfg, 'tornado');
            }
        }
        if ($cfg['enable_xfer'] != 0) {
            //XFER: before torrent deletion save upload/download xfer data to SQL
            $torrentTotals = getTorrentTotalsCurrent($delfile);
            saveXfer($torrentowner, $torrentTotals["downtotal"] + 0, $torrentTotals["uptotal"] + 0);
        }
        // torrent+stat
        @unlink($cfg["torrent_file_path"] . $delfile);
        @unlink($cfg["torrent_file_path"] . $alias_file);
        // try to remove the QInfo if in case it was queued.
        @unlink($cfg["torrent_file_path"] . "queue/" . $alias_file . ".Qinfo");
        // try to remove the pid file
        @unlink($cfg["torrent_file_path"] . $alias_file . ".pid");
        @unlink($cfg["torrent_file_path"] . getAliasName($delfile) . ".prio");
        AuditAction($cfg["constants"]["delete_torrent"], $delfile);
        return true;
    } else {
        AuditAction($cfg["constants"]["error"], $cfg["user"] . " attempted to delete " . $delfile);
        return false;
    }
}
 /**
  * prepares start of a bittorrent-client.
  * prepares vars and other generic stuff
  * @param $torrent name of the torrent
  * @param $interactive (1|0) : is this a interactive startup with dialog ?
  */
 function prepareStartTorrentClient($torrent, $interactive)
 {
     if ($this->state < 1) {
         $this->state = -1;
         $this->messages .= "Error. ClientHandler in wrong state on prepare-request.";
         return;
     }
     $this->skip_hash_check = "";
     if ($interactive == 1) {
         // interactive, get vars from request vars
         $this->rate = getRequestVar('rate');
         if (empty($this->rate)) {
             if ($this->rate != "0") {
                 $this->rate = $this->cfg["max_upload_rate"];
             }
         }
         $this->drate = getRequestVar('drate');
         if (empty($this->drate)) {
             if ($this->drate != "0") {
                 $this->drate = $this->cfg["max_download_rate"];
             }
         }
         $this->superseeder = getRequestVar('superseeder');
         if (empty($this->superseeder)) {
             $this->superseeder = "0";
         }
         // should be 0 in most cases
         $this->runtime = getRequestVar('runtime');
         if (empty($this->runtime)) {
             $this->runtime = $this->cfg["torrent_dies_when_done"];
         }
         $this->maxuploads = getRequestVar('maxuploads');
         if (empty($this->maxuploads)) {
             if ($this->maxuploads != "0") {
                 $this->maxuploads = $this->cfg["max_uploads"];
             }
         }
         $this->minport = getRequestVar('minport');
         if (empty($this->minport)) {
             $this->minport = $this->cfg["minport"];
         }
         $this->maxport = getRequestVar('maxport');
         if (empty($this->maxport)) {
             $this->maxport = $this->cfg["maxport"];
         }
         $this->maxcons = getRequestVar('maxcons');
         if (empty($this->maxcons)) {
             $this->maxcons = $this->cfg["maxcons"];
         }
         $this->rerequest = getRequestVar("rerequest");
         if (empty($this->rerequest)) {
             $this->rerequest = $this->cfg["rerequest_interval"];
         }
         $this->sharekill = getRequestVar('sharekill');
         if ($this->runtime == "True") {
             $this->sharekill = "-1";
         }
         if (empty($this->sharekill)) {
             if ($this->sharekill != "0") {
                 $this->sharekill = $this->cfg["sharekill"];
             }
         }
         $this->savepath = getRequestVar('savepath');
         $this->skip_hash_check = getRequestVar('skiphashcheck');
     } else {
         // non-interactive, load settings from db and set vars
         $this->rerequest = $this->cfg["rerequest_interval"];
         $this->skip_hash_check = $this->cfg["skiphashcheck"];
         $this->superseeder = 0;
         // load settings
         $settingsAry = loadTorrentSettings(urldecode($torrent));
         $this->rate = $settingsAry["max_upload_rate"];
         $this->drate = $settingsAry["max_download_rate"];
         $this->runtime = $settingsAry["torrent_dies_when_done"];
         $this->maxuploads = $settingsAry["max_uploads"];
         $this->minport = $settingsAry["minport"];
         $this->maxport = $settingsAry["maxport"];
         $this->maxcons = $settingsAry["maxcons"];
         $this->sharekill = $settingsAry["sharekill"];
         $this->savepath = $settingsAry["savepath"];
         // fallback-values if fresh-torrent is started non-interactive or
         // something else strange happened
         if ($this->rate == '') {
             $this->rate = $this->cfg["max_upload_rate"];
         }
         if ($this->drate == '') {
             $this->drate = $this->cfg["max_download_rate"];
         }
         if ($this->runtime == '') {
             $this->runtime = $this->cfg["torrent_dies_when_done"];
         }
         if ($this->maxuploads == '') {
             $this->maxuploads = $this->cfg["max_uploads"];
         }
         if ($this->minport == '') {
             $this->minport = $this->cfg["minport"];
         }
         if ($this->maxport == '') {
             $this->maxport = $this->cfg["maxport"];
         }
         if ($this->maxcons == '') {
             $this->maxcons = $this->cfg["maxcons"];
         }
         if ($this->sharekill == '') {
             $this->sharekill = $this->cfg["sharekill"];
         }
     }
     // queue
     if ($this->cfg["AllowQueing"]) {
         if (IsAdmin()) {
             $this->queue = getRequestVar('queue');
             if ($this->queue == 'on') {
                 $this->queue = "1";
             } else {
                 $this->queue = "0";
             }
         } else {
             $this->queue = "1";
         }
     } else {
         $this->queue = "0";
     }
     //
     $this->torrent = urldecode($torrent);
     $this->alias = getAliasName($this->torrent);
     $this->owner = getOwner($this->torrent);
     if (empty($this->savepath)) {
         $this->savepath = $this->cfg['path'] . $this->owner . "/";
     }
     // ensure path has trailing slash
     $this->savepath = checkDirPathString($this->savepath);
     // check target-directory, create if not present
     if (!checkDirectory($this->savepath, 0777)) {
         AuditAction($this->cfg["constants"]["error"], "Error checking " . $this->savepath . ".");
         $this->state = -1;
         $this->messages .= "Error. TorrentFlux settings are not correct (path-setting).";
         global $argv;
         if (isset($argv)) {
             die($this->messages);
         } else {
             if (IsAdmin()) {
                 @header("location: admin.php?op=configSettings");
                 exit;
             } else {
                 $this->messages .= " please contact an admin.";
                 showErrorPage($this->messages);
             }
         }
     }
     // create AliasFile object and write out the stat file
     include_once "AliasFile.php";
     $this->af = AliasFile::getAliasFileInstance($this->cfg["torrent_file_path"] . $this->alias . ".stat", $this->owner, $this->cfg, $this->handlerName);
     // set param for sharekill
     $this->sharekill = intval($this->sharekill);
     if ($this->sharekill == 0) {
         // nice, we seed forever
         $this->sharekill_param = 0;
     } elseif ($this->sharekill > 0) {
         // recalc sharekill
         // sanity-check. catch "data-size = 0".
         $transferSize = intval($this->af->size);
         if ($transferSize > 0) {
             $totalAry = getTorrentTotals($this->torrent);
             $upTotal = $totalAry["uptotal"] + 0;
             $downTotal = $totalAry["downtotal"] + 0;
             $upWanted = $this->sharekill / 100 * $transferSize;
             $sharePercentage = $upTotal / $transferSize * 100;
             if ($upTotal >= $upWanted && $downTotal >= $transferSize) {
                 // we already have seeded at least wanted percentage.
                 // skip start of client
                 // set state
                 $this->state = 1;
                 // message
                 $this->messages = "skipping start of transfer " . $this->torrent . " due to share-ratio (has: " . @number_format($sharePercentage, 2) . " ; set:" . $this->sharekill . ")";
                 // DEBUG : log the messages
                 AuditAction($this->cfg["constants"]["debug"], $this->messages);
                 // return
                 return;
             } else {
                 // not done seeding wanted percentage
                 $this->sharekill_param = intval(ceil($this->sharekill - $sharePercentage));
                 // sanity-check.
                 if ($this->sharekill_param < 1) {
                     $this->sharekill_param = 1;
                 }
             }
         } else {
             $this->messages = "data-size is 0 when recalcing share-kill for " . $this->torrent . ". setting sharekill absolute to " . $this->sharekill;
             AuditAction($this->cfg["constants"]["error"], $this->messages);
             $this->sharekill_param = $this->sharekill;
         }
     } else {
         $this->sharekill_param = $this->sharekill;
     }
     // set port if start (not queue)
     if (!($this->cfg["AllowQueing"] && $this->queue == "1")) {
         if ($this->setClientPort() === false) {
             return;
         }
     }
     //XFER: before a torrent start/restart save upload/download xfer to SQL
     $torrentTotals = getTorrentTotalsCurrent($this->torrent);
     saveXfer($this->owner, $torrentTotals["downtotal"] + 0, $torrentTotals["uptotal"] + 0);
     // update totals for this torrent
     updateTorrentTotals($this->torrent);
     // write stat-file
     if ($this->cfg["AllowQueing"] && $this->queue == "1") {
         $this->af->QueueTorrentFile();
     } else {
         $this->af->StartTorrentFile();
     }
     // set state
     $this->state = 2;
 }