Example #1
0
 public static function createTorrent($torrent, $hash)
 {
     global $saveUploadedTorrents;
     $torrent = new Torrent($torrent);
     if ($torrent->errors()) {
         return self::STE_DELETED;
     }
     if ($torrent->hash_info() == $hash) {
         return self::STE_UPTODATE;
     }
     $req = new rXMLRPCRequest(array(new rXMLRPCCommand("d.get_directory_base", $hash), new rXMLRPCCommand("d.get_custom1", $hash), new rXMLRPCCommand("d.get_throttle_name", $hash), new rXMLRPCCommand("d.get_connection_seed", $hash), new rXMLRPCCommand("d.is_open", $hash), new rXMLRPCCommand("d.is_active", $hash), new rXMLRPCCommand("d.get_state", $hash), new rXMLRPCCommand("d.stop", $hash), new rXMLRPCCommand("d.close", $hash)));
     if ($req->success()) {
         $addition = array(getCmd("d.set_connection_seed=") . $req->val[3], getCmd("d.set_custom") . "=chk-state," . self::STE_UPDATED, getCmd("d.set_custom") . "=chk-time," . time(), getCmd("d.set_custom") . "=chk-stime," . time());
         $isStart = $req->val[4] != 0 && $req->val[5] != 0 && $req->val[6] != 0;
         if (!empty($req->val[2])) {
             $addition[] = getCmd("d.set_throttle_name=") . $req->val[2];
         }
         if (preg_match('/rat_(\\d+)/', $req->val[3], $ratio)) {
             $addition[] = getCmd("view.set_visible=") . "rat_" . $ratio;
         }
         $label = rawurldecode($req->val[1]);
         if (rTorrent::sendTorrent($torrent, $isStart, false, $req->val[0], $label, $saveUploadedTorrents, false, true, $addition)) {
             $req = new rXMLRPCRequest(new rXMLRPCCommand("d.erase", $hash));
             if ($req->success()) {
                 return null;
             }
         }
     }
     return self::STE_ERROR;
 }
Example #2
0
        if (isset($request['comment'])) {
            $comment = trim($request['comment']);
            if (strlen($comment)) {
                $torrent->comment($comment);
            }
        }
        if ($request['private']) {
            $torrent->is_private(true);
        }
        $fname = rTask::formatPath($taskNo) . '/result.torrent';
        $torrent->save($fname);
        if ($request['start_seeding']) {
            $fname = getUniqueUploadedFilename($torrent->info['name'] . '.torrent');
            $path_edit = trim($request['path_edit']);
            if (is_dir($path_edit)) {
                $path_edit = addslash($path_edit);
            }
            if (rTorrentSettings::get()->correctDirectory($path_edit)) {
                $path_edit = dirname($path_edit);
                if ($resumed = rTorrent::fastResume($torrent, $path_edit)) {
                    $torrent = $resumed;
                }
                $torrent->save($fname);
                rTorrent::sendTorrent($torrent, true, true, $path_edit, null, true, isLocalMode());
                @chmod($fname, $profileMask & 0666);
            }
        }
        exit(0);
    }
    exit(1);
}
Example #3
0
        // ( If we want to add same torrent again )
        if ($is_ok && (!is_writeable($torrent_file) || !touch($torrent_file))) {
            Debug("no access to " . $torrent_file);
            $is_ok = false;
        }
        if ($is_ok && !rtMkDir($dest_path, 0777)) {
            Debug("can't create " . $dest_path);
            $is_ok = false;
        }
        if ($is_ok) {
            //			$hash = rtAddTorrent(
            //				$torrent_file,			// path to .torrent file
            //				$auto_start,			// start it or not
            //				$dest_path,			// directory for torrent's data
            //				null,				// label is emply
            //				$autodebug_enabled
            //			);
            $hash = rTorrent::sendTorrent($torrent_file, $auto_start, true, $dest_path, null, false, false);
            if ($hash === false) {
                Debug("rtAddTorrent() fail");
                $is_ok = false;
            } else {
                Debug("torrent added    : " . $hash);
            }
        }
        if (!$is_ok) {
            rename($torrent_file, $torrent_file . ".fail");
        }
    }
}
Debug("--- end ---");
Example #4
0
                     $torrent->clear_comment();
                     $comment = trim($comment);
                     if (strlen($comment)) {
                         $torrent->comment($comment);
                     }
                 }
                 if (isset($torrent->{'rtorrent'})) {
                     unset($torrent->{'rtorrent'});
                 }
                 if (count($req->val) > 9) {
                     $throttle = getCmd("d.set_throttle_name=") . $req->val[9];
                 }
                 $eReq = new rXMLRPCRequest(new rXMLRPCCommand("d.erase", $hash));
                 if ($eReq->run() && !$eReq->fault) {
                     $label = rawurldecode($req->val[5]);
                     if (!rTorrent::sendTorrent($torrent, $isStart, false, $req->val[6], $label, false, $req->val[8] == 1, false, array(getCmd("d.set_custom3") . "=1", getCmd("d.set_connection_seed=") . $req->val[7], $throttle))) {
                         $errors[] = array('desc' => "theUILang.errorAddTorrent", 'prm' => $fname);
                     }
                 } else {
                     $errors[] = array('desc' => "theUILang.badLinkTorTorrent", 'prm' => '');
                 }
             } else {
                 $errors[] = array('desc' => "theUILang.errorReadTorrent", 'prm' => $fname);
             }
         } else {
             $errors[] = array('desc' => "theUILang.cantFindTorrent", 'prm' => '');
         }
     } else {
         $errors[] = array('desc' => "theUILang.badLinkTorTorrent", 'prm' => '');
     }
 }
Example #5
0
                        } else {
                            $needToProcessed = false;
                        }
                    }
                    $lst = $torrent->announce_list();
                    if ($lst && count($trks->todelete)) {
                        $needToProcessed = deleteTrackers($lst, $trks->todelete);
                        if ($needToProcessed) {
                            $torrent->announce_list($lst);
                        }
                    }
                    if ($needToProcessed) {
                        if (isset($torrent->{'rtorrent'})) {
                            unset($torrent->{'rtorrent'});
                        }
                        $eReq = new rXMLRPCRequest(new rXMLRPCCommand("d.erase", $hash));
                        if ($eReq->success()) {
                            $label = rawurldecode($req->val[3]);
                            rTorrent::sendTorrent($torrent, $isStart, false, $req->val[4], $label, false, false, false, array(getCmd("d.set_custom3") . "=1"));
                            $processed = true;
                        }
                    }
                }
            }
        }
        if (!$processed && $isStart) {
            $req = new rXMLRPCRequest(new rXMLRPCCommand("d.start", $hash));
            $req->run();
        }
    }
}
Example #6
0
function rtSetDataDir($hash, $dest_path, $add_path, $move_files, $fast_resume, $dbg = false)
{
    if ($dbg) {
        rtDbg(__FUNCTION__, "hash        : " . $hash);
    }
    if ($dbg) {
        rtDbg(__FUNCTION__, "dest_path   : " . $dest_path);
    }
    if ($dbg) {
        rtDbg(__FUNCTION__, "add path    : " . ($add_path ? "1" : "0"));
    }
    if ($dbg) {
        rtDbg(__FUNCTION__, "move files  : " . ($move_files ? "1" : "0"));
    }
    if ($dbg) {
        rtDbg(__FUNCTION__, "fast resume : " . ($fast_resume ? "1" : "0"));
    }
    $is_open = false;
    $is_active = false;
    $is_multy_file = false;
    $base_name = '';
    $base_path = '';
    $base_file = '';
    $is_ok = true;
    if ($dest_path == '') {
        $is_ok = false;
    } else {
        $dest_path = rtAddTailSlash($dest_path);
    }
    // Check if torrent is open or active
    if ($is_ok) {
        $req = rtExec(array("d.is_open", "d.is_active"), $hash, $dbg);
        if (!$req) {
            $is_ok = false;
        } else {
            $is_open = $req->val[0] != 0;
            $is_active = $req->val[1] != 0;
            if ($dbg) {
                rtDbg(__FUNCTION__, "is_open=" . $req->val[0] . ", is_active=" . $req->val[1]);
            }
        }
    }
    // Open closed torrent to get d.get_base_path, d.get_base_filename
    if ($is_ok && $move_files) {
        if (!$is_open && !rtExec("d.open", $hash, $dbg)) {
            $is_ok = false;
        }
    }
    // Ask info from rTorrent
    if ($is_ok && $move_files) {
        $req = rtExec(array("d.get_name", "d.get_base_path", "d.get_base_filename", "d.is_multi_file", "d.get_complete"), $hash, $dbg);
        if (!$req) {
            $is_ok = false;
        } else {
            $base_name = trim($req->val[0]);
            $base_path = trim($req->val[1]);
            $base_file = trim($req->val[2]);
            $is_multy_file = $req->val[3] != 0;
            if ($req->val[4] == 0) {
                // if torrent is not completed -> "fast start" is impossible
                $fast_resume = false;
            }
            if ($dbg) {
                rtDbg(__FUNCTION__, "d.get_name          : " . $base_name);
            }
            if ($dbg) {
                rtDbg(__FUNCTION__, "d.get_base_path     : " . $base_path);
            }
            if ($dbg) {
                rtDbg(__FUNCTION__, "d.get_base_filename : " . $base_file);
            }
            if ($dbg) {
                rtDbg(__FUNCTION__, "d.is_multy_file     : " . $req->val[3]);
            }
            if ($dbg) {
                rtDbg(__FUNCTION__, "d.get_complete      : " . $req->val[4]);
            }
        }
    }
    // Check if paths are valid
    if ($is_ok && $move_files) {
        if ($base_path == '' || $base_file == '') {
            if ($dbg) {
                rtDbg(__FUNCTION__, "base paths are empty");
            }
            $is_ok = false;
        } else {
            // Make $base_path a really BASE path for downloading data
            // (not including single file or subdir for multiple files).
            // Add trailing slash, if none.
            $base_path = rtRemoveTailSlash($base_path);
            $base_path = rtRemoveLastToken($base_path, '/');
            // filename or dirname
            $base_path = rtAddTailSlash($base_path);
        }
    }
    // Get list of torrent data files
    $torrent_files = array();
    if ($is_ok && $move_files) {
        $req = rtExec("f.multicall", array($hash, "", "f.get_path="), $dbg);
        if (!$req) {
            $is_ok = false;
        } else {
            $torrent_files = $req->val;
            if ($dbg) {
                rtDbg(__FUNCTION__, "files in torrent    : " . count($torrent_files));
            }
        }
    }
    // 1. Stop torrent if active (if not, then rTorrent can crash)
    // 2. Close torrent anyway
    if ($is_ok) {
        $cmds = array();
        if ($is_active) {
            $cmds[] = "d.stop";
        }
        if ($is_open || $move_files) {
            $cmds[] = "d.close";
        }
        if (count($cmds) > 0 && !rtExec($cmds, $hash, $dbg)) {
            $is_ok = false;
        }
    }
    // Move torrent data files to new location
    if ($is_ok && $move_files) {
        $full_base_path = $base_path;
        $full_dest_path = $dest_path;
        // Don't use "count( $torrent_files ) > 1" check (there can be one file in a subdir)
        if ($is_multy_file) {
            // torrent is a directory
            $full_base_path .= rtAddTailSlash($base_file);
            $full_dest_path .= $add_path ? rtAddTailSlash($base_name) : "";
        } else {
            // torrent is a single file
        }
        if ($dbg) {
            rtDbg(__FUNCTION__, "from " . $full_base_path);
        }
        if ($dbg) {
            rtDbg(__FUNCTION__, "to   " . $full_dest_path);
        }
        if ($full_base_path != $full_dest_path && is_dir($full_base_path)) {
            if (!rtOpFiles($torrent_files, $full_base_path, $full_dest_path, "Move", $dbg)) {
                $is_ok = false;
            } else {
                // Recursively remove source dirs without files
                if ($dbg) {
                    rtDbg(__FUNCTION__, "clean " . $full_base_path);
                }
                if ($is_multy_file) {
                    rtRemoveDirectory($full_base_path, false);
                    if ($dbg && is_dir($full_base_path)) {
                        rtDbg(__FUNCTION__, "some files were not deleted");
                    }
                }
            }
        }
    }
    if ($is_ok) {
        // fast resume is requested
        if ($fast_resume) {
            if ($dbg) {
                rtDbg(__FUNCTION__, "trying fast resume");
            }
            // collect variables
            $session = rTorrentSettings::get()->session;
            $tied_to_file = null;
            $label = null;
            $addition = null;
            $req = rtExec(array("get_session", "d.get_tied_to_file", "d.get_custom1", "d.get_connection_seed", "d.get_throttle_name"), $hash, $dbg);
            if (!$req) {
                $fast_resume = false;
            } else {
                $session = $req->val[0];
                $tied_to_file = $req->val[1];
                $label = rawurldecode($req->val[2]);
                $addition = array();
                if (!empty($req->val[3])) {
                    $addition[] = getCmd("d.set_connection_seed=") . $req->val[3];
                }
                if (!empty($req->val[4])) {
                    $addition[] = getCmd("d.set_throttle_name=") . $req->val[4];
                }
                // build path to .torrent file
                $fname = rtAddTailSlash($session) . $hash . ".torrent";
                if (empty($session) || !is_readable($fname)) {
                    if (!strlen($tied_to_file) || !is_readable($tied_to_file)) {
                        if ($dbg) {
                            rtDbg(__FUNCTION__, "empty session or inaccessible .torrent file");
                        }
                        $fname = null;
                        $fast_resume = false;
                    } else {
                        $fname = $tied_to_file;
                    }
                }
            }
            // create torrent, remove old and add new one
            if ($fast_resume) {
                $torrent = new Torrent($fname);
                if ($torrent->errors()) {
                    if ($dbg) {
                        rtDbg(__FUNCTION__, "fail to create Torrent object");
                    }
                    $fast_resume = false;
                } else {
                    $is_ok = $add_path ? rtExec("d.set_directory", array($hash, $dest_path), $dbg) : rtExec("d.set_directory_base", array($hash, $dest_path), $dbg);
                    // for erasedata plugin
                    if ($is_ok) {
                        if (!rtExec("d.erase", $hash, $dbg)) {
                            if ($dbg) {
                                rtDbg(__FUNCTION__, "fail to erase old torrent");
                            }
                            $fast_resume = false;
                        } else {
                            if (!rTorrent::sendTorrent($torrent, true, $add_path, $dest_path, $label, true, true, false, $addition)) {
                                if ($dbg) {
                                    rtDbg(__FUNCTION__, "fail to add new torrent");
                                }
                                $fast_resume = false;
                                $is_ok = false;
                            }
                        }
                    }
                }
            }
            if ($dbg) {
                rtDbg(__FUNCTION__, "fast resume " . ($fast_resume ? "done" : "fail"));
            }
        }
        // fast resume is fail or not requested at all
        if ($is_ok && !$fast_resume) {
            // Setup new directory for torrent (we need to stop it first)
            $is_ok = $add_path ? rtExec("d.set_directory", array($hash, $dest_path), $dbg) : rtExec("d.set_directory_base", array($hash, $dest_path), $dbg);
            if ($is_ok) {
                // Start torrent if need
                if ($is_active) {
                    $is_ok = rtExec(array("d.open", "d.start"), $hash, $dbg);
                } elseif ($is_open) {
                    $is_ok = rtExec("d.open", $hash, $dbg);
                } else {
                    $is_ok = rtExec(array("d.open", "d.close"), $hash, $dbg);
                }
            }
        }
    }
    if ($dbg) {
        rtDbg(__FUNCTION__, "finished");
    }
    return $is_ok;
}
Example #7
0
 public function getTorrents($engs, $urls, $isStart, $isAddPath, $directory, $label, $fast)
 {
     $ret = array();
     $history = self::loadHistory();
     for ($i = 0; $i < count($urls); $i++) {
         $url = $urls[$i];
         $success = false;
         if (strpos($url, "magnet:") === 0) {
             if ($success = rTorrent::sendMagnet($url, $isStart, $isAddPath, $directory, $label)) {
                 $history->add($url, $success);
             }
         } else {
             $object = $this->getObject($engs[$i]);
             $torrent = $object->getTorrent($url, $object);
             if ($torrent !== false) {
                 global $saveUploadedTorrents;
                 if (($success = rTorrent::sendTorrent($torrent, $isStart, $isAddPath, $directory, $label, $saveUploadedTorrents, $fast)) === false) {
                     @unlink($torrent);
                 } else {
                     $history->add($url, $success);
                 }
             }
         }
         $ret[] = $success;
     }
     self::saveHistory($history);
     return $ret;
 }
Example #8
0
 public function getTorrents($rss, $url, $isStart, $isAddPath, $directory, $label, $throttle, $ratio, $needFlush = true)
 {
     $thash = 'Failed';
     $ret = $rss->getTorrent($url);
     if ($ret !== false) {
         $addition = array();
         if (!empty($throttle)) {
             $addition[] = getCmd("d.set_throttle_name=") . $throttle;
         }
         if (!empty($ratio)) {
             $addition[] = getCmd("view.set_visible=") . $ratio;
         }
         global $saveUploadedTorrents;
         $thash = $ret === 'magnet' ? rTorrent::sendMagnet($url, $isStart, $isAddPath, $directory, $label, $addition) : rTorrent::sendTorrent($ret, $isStart, $isAddPath, $directory, $label, $saveUploadedTorrents, false, true, $addition);
         if ($thash === false) {
             $thash = 'Failed';
             @unlink($ret);
             $ret = false;
         }
     }
     if ($ret === false) {
         $this->rssList->addError("theUILang.rssCantLoadTorrent", $url);
     }
     $this->history->add($url, $thash, $rss->getItemTimestamp($url));
     if ($needFlush) {
         $this->saveHistory();
     }
 }
            $name = $cli->get_filename();
            if ($name === false) {
                $name = md5($url) . ".torrent";
            }
            $uploaded_file = getUploadsPath() . "/" . $name;
            $f = @fopen($uploaded_file, "w");
            if ($f !== false) {
                @fwrite($f, $cli->results, strlen($cli->results));
                fclose($f);
                $success = true;
            }
        }
    }
}
if ($success) {
    @chmod($uploaded_file, 0666);
    $uploaded_file = realpath($uploaded_file);
    $label = null;
    if (isset($_REQUEST['label'])) {
        $label = trim($_REQUEST['label']);
    }
    $dir_edit = null;
    if (isset($_REQUEST['dir_edit'])) {
        $dir_edit = trim($_REQUEST['dir_edit']);
    }
    if (rTorrent::sendTorrent($uploaded_file, !isset($_REQUEST['torrents_start_stopped']), !isset($_REQUEST['not_add_path']), $dir_edit, $label, $saveUploadedTorrents, isset($_REQUEST['fast_resume'])) === false) {
        unlink($uploaded_file);
        $success = false;
    }
}
header("Location: " . $_SERVER['PHP_SELF'] . '?result=' . intval($success));
Example #10
0
 public static function run($hash, $state = null, $time = null, $successful_time = null)
 {
     global $saveUploadedTorrents;
     if (is_null($state)) {
         self::getState($hash, $state, $time, $successful_time);
     }
     if ($state == self::STE_INPROGRESS && time() - $time > self::MAX_LOCK_TIME) {
         $state = 0;
     }
     if ($state != self::STE_INPROGRESS) {
         $state = self::STE_INPROGRESS;
         if (!self::setState($hash, $state)) {
             return false;
         }
         $fname = rTorrentSettings::get()->session . $hash . ".torrent";
         if (is_readable($fname)) {
             $torrent = new Torrent($fname);
             if (!$torrent->errors()) {
                 if (preg_match('`^http://(?P<tracker>rutracker)\\.org/forum/viewtopic\\.php\\?t=(?P<id>\\d+)$`', $torrent->comment(), $matches) || preg_match('`^http://(?P<tracker>kinozal)\\.tv/details\\.php\\?id=(?P<id>\\d+)$`', $torrent->comment(), $matches)) {
                     if ($matches["tracker"] == "rutracker") {
                         $client = self::makeClient($torrent->comment());
                         if ($client->status == 200 && preg_match("`ajax.form_token\\s*=\\s*'(?P<form_token>[^']+)';.*topic_id\\s*:\\s*(?P<topic_id>\\d+),\\s*t_hash\\s*:\\s*'(?P<t_hash>[^']+)'`s", $client->results, $matches1)) {
                             $client->setcookies();
                             $client->fetch("http://rutracker.org/forum/ajax.php", "POST", "application/x-www-form-urlencoded; charset=UTF-8", "action=get_info_hash" . "&topic_id=" . $matches1["topic_id"] . "&t_hash=" . $matches1["t_hash"] . "&form_token=" . $matches1["form_token"]);
                             if ($client->status == 200) {
                                 $ret = json_decode($client->results, true);
                                 if ($ret && array_key_exists("ih_hex", $ret) && strtoupper($ret["ih_hex"]) == $hash) {
                                     self::setState($hash, self::STE_UPTODATE);
                                     return true;
                                 }
                             }
                         }
                         $client->setcookies();
                         $client->fetchComplex("http://dl.rutracker.org/forum/dl.php?t=" . $matches["id"]);
                     } else {
                         if ($matches["tracker"] == "kinozal") {
                             $client = self::makeClient("http://kinozal.tv/get_srv_details.php?action=2&id=" . $matches["id"]);
                             if ($client->status == 200 && preg_match('`<li>.*(?P<hash>[0-9A-Fa-f]{40})</li>`', $client->results, $matches1)) {
                                 if (strtoupper($matches1["hash"]) == $hash) {
                                     self::setState($hash, self::STE_UPTODATE);
                                     return true;
                                 }
                             }
                             $client->setcookies();
                             $client->fetchComplex("http://dl.kinozal.tv/download.php?id=" . $matches["id"]);
                         } else {
                             self::setState($hash, self::STE_NOT_NEED);
                             return true;
                         }
                     }
                     if ($client->status == 200) {
                         $torrent = new Torrent($client->results);
                         if (!$torrent->errors()) {
                             if ($torrent->hash_info() != $hash) {
                                 $req = new rXMLRPCRequest(array(new rXMLRPCCommand("d.get_directory_base", $hash), new rXMLRPCCommand("d.get_custom1", $hash), new rXMLRPCCommand("d.get_throttle_name", $hash), new rXMLRPCCommand("d.get_connection_seed", $hash), new rXMLRPCCommand("d.is_open", $hash), new rXMLRPCCommand("d.is_active", $hash), new rXMLRPCCommand("d.get_state", $hash), new rXMLRPCCommand("d.stop", $hash), new rXMLRPCCommand("d.close", $hash)));
                                 if ($req->success()) {
                                     $addition = array(getCmd("d.set_connection_seed=") . $req->val[3], getCmd("d.set_custom") . "=chk-state," . self::STE_UPDATED, getCmd("d.set_custom") . "=chk-time," . time(), getCmd("d.set_custom") . "=chk-stime," . time());
                                     $isStart = $req->val[4] != 0 && $req->val[5] != 0 && $req->val[6] != 0;
                                     if (!empty($req->val[2])) {
                                         $addition[] = getCmd("d.set_throttle_name=") . $req->val[2];
                                     }
                                     if (preg_match('/rat_(\\d+)/', $req->val[3], $ratio)) {
                                         $addition[] = getCmd("view.set_visible=") . "rat_" . $ratio;
                                     }
                                     $label = rawurldecode($req->val[1]);
                                     if (rTorrent::sendTorrent($torrent, $isStart, false, $req->val[0], $label, $saveUploadedTorrents, false, true, $addition)) {
                                         $req = new rXMLRPCRequest(new rXMLRPCCommand("d.erase", $hash));
                                         if ($req->success()) {
                                             $state = null;
                                         }
                                     }
                                 }
                             } else {
                                 $state = self::STE_UPTODATE;
                             }
                         } else {
                             $state = self::STE_DELETED;
                         }
                     } else {
                         $state = $client->status < 0 ? self::STE_CANT_REACH_TRACKER : self::STE_DELETED;
                     }
                 } else {
                     $state = self::STE_NOT_NEED;
                 }
             }
         }
         if ($state == self::STE_INPROGRESS) {
             $state == self::STE_ERROR;
         }
         if (!is_null($state)) {
             self::setState($hash, $state);
         }
     }
     return $state != self::STE_CANT_REACH_TRACKER;
 }
Example #11
0
<?php

require __DIR__ . '/vendor/autoload.php';
// Example usage, list all torrents that are seeding, then check if the ratio is above 1.00, and if so, delete them.
$x = new rTorrent("http://*****:*****@localhost/RPC2");
foreach ($x->getDownloads('seeding') as $torrent) {
    if ($torrent->getRatio() > 1000) {
        $torrent->erase();
    }
}
Example #12
0
<?php

require_once '../../php/rtorrent.php';
if (isset($_REQUEST['result'])) {
    cachedEcho('noty(theUILang.cantFindTorrent,"error");', "text/html");
}
if (isset($_REQUEST['hash'])) {
    $torrent = rTorrent::getSource($_REQUEST['hash']);
    if ($torrent) {
        $torrent->send();
    }
}
header("HTTP/1.0 302 Moved Temporarily");
header("Location: " . $_SERVER['PHP_SELF'] . '?result=0');