Archived

This topic is now archived and is closed to further replies.

Miyanokouji

PHP API for the WebUI

Recommended Posts

I have written a PHP API for the WebUI

Here's the source

Follow the instructions in the comments

Any questions/etc post here.

You _will_ need the cURL and JSON extensions (JSON included in PHP 5.2+ as standard)

If you download torrents greater than 4GB in size and wish to see that size correctly you will need PHP 5.2.4 or greater.

Updates

  • Added setProperty and getProperties, gave list of properties that can be used.
  • Added more defines for ease of use and also added is_online to check it's online
  • Eeek! Didn't test the code properly after update2. is_online no longer outputs "invalid request" to the browser.
  • Added the recheckTorrent function, modde the start, pause, stop, forcestart, and recheck functions to be able to receive arrays of hashes. A load of comments. Probably some other minor changes.
  • Fixed a bug found by nowotny. Thanks nowotny!
  • Added removedata functionality as coded by nowotny, also added the ability to add torrents from a URL (just use addTorrent("someurl"))
  • Very very minor bug fix - fixed is_online so that it _only_ returns true or false.
  • Another minor bug fix - forcestartTorrent and recheckTorrent no longer output the result. (Credit once again goes to nowotny)
  • Yet another addition by Nowotny! The getLabel function has now been added.
  • Bugfix. Due to new information the UTORRENT_TYPE_* definitions have changed.
  • Very belated bugfix. Fixed addTorrent to use substr, not substring and to url-encode the file if a URL is passed. Thanks to m69bv3 and protomank. This will probably be the last time I update this, not because I consider it finished (due to not considering WebUI finshed, but because I have far too much going on in my life (GCSEs, etc) and too many coding projects.) If you wish to take on this PHP API as your own project, please keep your modifications in the same style as mine, or rewrite my parts into your style too, and most importantly, mention me somewhere :P
  • [2008-04-08] [ultima] Fixed addTorrent's add-url call (was mistakenly calling get-url instead of add-url). Fixed setPriority. Use substr (not the non-existent substring).
  • [2008-04-08] [ultima] I've a greatly simplified version of the API here, though it's raw and untested (no dogfood testing from me this time). Guinea pigs are welcome!

<?php
define("UTORRENT_TORRENT_HASH",0);
define("UTORRENT_TORRENT_STATUS",1);
define("UTORRENT_TORRENT_NAME",2);
define("UTORRENT_TORRENT_SIZE",3);
define("UTORRENT_TORRENT_PROGRESS",4);
define("UTORRENT_TORRENT_DOWNLOADED",5);
define("UTORRENT_TORRENT_UPLOADED",6);
define("UTORRENT_TORRENT_RATIO",7);
define("UTORRENT_TORRENT_UPSPEED",8);
define("UTORRENT_TORRENT_DOWNSPEED",9);
define("UTORRENT_TORRENT_ETA",10);
define("UTORRENT_TORRENT_LABEL",11);
define("UTORRENT_TORRENT_PEERS_CONNECTED",12);
define("UTORRENT_TORRENT_PEERS_SWARM",13);
define("UTORRENT_TORRENT_SEEDS_CONNECTED",14);
define("UTORRENT_TORRENT_SEEDS_SWARM",15);
define("UTORRENT_TORRENT_AVAILABILITY",16);
define("UTORRENT_TORRENT_QUEUE_POSITION",17);
define("UTORRENT_TORRENT_REMAINING",18);
define("UTORRENT_FILEPRIORITY_HIGH",3);
define("UTORRENT_FILEPRIORITY_NORMAL",2);
define("UTORRENT_FILEPRIORITY_LOW",1);
define("UTORRENT_FILEPRIORITY_SKIP",0);
define("UTORRENT_TYPE_INTEGER",0);
define("UTORRENT_TYPE_BOOLEAN",1);
define("UTORRENT_TYPE_STRING",2);
define("UTORRENT_STATUS_STARTED",1);
define("UTORRENT_STATUS_CHECKED",2);
define("UTORRENT_STATUS_START_AFTER_CHECK",4);



class uTorrent {
//set host to be the IP or hostname of your uTorrent machine
//set user and pass to be the user and pass you use for the webui
public $host = "";
public $user = "";
public $pass = "";
public function is_online() {
$ch = curl_init();
//uses start because at present (WebUI 0.31, uTorrent 1.7.2) this simply returns {"":""} and doesn't modify anything.
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=");
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
$ret = curl_exec($ch);
if($ret !== false) {
$ret = true;
}

return $ret;
}
//returns an array of all torrent information
public function getTorrents() {
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?list=1");
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
$ret = curl_exec($ch);
//echo curl_getinfo($ch,CURLINFO_HTTP_CODE);
$obj = json_decode($ret,true);
$torrents = $obj['torrents'];
curl_close($ch);
return $torrents;
}
//returns an array of all labels.
public function getLabels(){
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?list=1");
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
$ret = curl_exec($ch);
$obj = json_decode($ret,true);
$labels = $obj['label'];
curl_close($ch);
return $labels;
}


//if you set $estring then when the function is done and returns false, estring will be a string telling you what error happened.
//$filename could probably be a temporary filenames ($_FILES['somefile']['tmp_name']) but I haven't checked
//$filename can be a URL
public function addTorrent($filename,&$estring = false) {

if(substr($filename,0,7) == "http://") {
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=add-url&s=".urlencode($filename));
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
} else if(file_exists($filename)) {
$form_fields = array();
//$form_fields['add_button'] = "Add File \n";
$form_fields['torrent_file'] = "@".realpath($filename);
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=add-file");
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
//curl_setopt($ch,CURLOPT_HEADER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_setopt($ch,CURLOPT_POSTFIELDS,$form_fields);
curl_setopt($ch,CURLOPT_VERBOSE,true);
$ret = curl_exec($ch);
//echo $ret;
//echo curl_error($ch);

curl_close($ch);
$obj = json_decode($ret,true);
if(isset($obj['error'])) {
if($estring !== false) {
$estring = $obj['error'];
}
return false;
} else {
return true;
}
} else {
$estring = "File doesn't exist!";
return false;
}
}
public function removeTorrent($hash,$data=false) {
$hashes = "";
if(is_array($hash)) {
foreach($hash as $value) {
$hashes.="&hash=".$value;
}
} else {
$hashes = "&hash=".$hash;
}
if($data) {
$action='removedata';
} else {
$action='remove';
}

$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=".$action.$hashes);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}
public function startTorrent($hash) {
$hashes = "";
if(is_array($hash)) {
foreach($hash as $value) {
$hashes.="&hash=".$value;
}
} else {
$hashes = "&hash=".$hash;
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=start".$hashes);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}
public function pauseTorrent($hash) {
$hashes = "";
if(is_array($hash)) {
foreach($hash as $value) {
$hashes.="&hash=".$value;
}
} else {
$hashes = "&hash=".$hash;
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=pause".$hashes);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}
public function stopTorrent($hash) {
$hashes = "";
if(is_array($hash)) {
foreach($hash as $value) {
$hashes.="&hash=".$value;
}
} else {
$hashes = "&hash=".$hash;
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=stop".$hashes);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}
public function forcestartTorrent($hash) {
$hashes = "";
if(is_array($hash)) {
foreach($hash as $value) {
$hashes.="&hash=".$value;
}
} else {
$hashes = "&hash=".$hash;
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=forcestart".$hashes);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}
public function recheckTorrent($hash) {
$hashes = "";
if(is_array($hash)) {
foreach($hash as $value) {
$hashes.="&hash=".$value;
}
} else {
$hashes = "&hash=".$hash;
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=recheck".$hashes);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}
//This could get the files of multiple torrents, but unfortunately json_decode overwrites the files array each time, instead of
// doing something nice like having files[i] where i is the number of how many hashes you used.
//If someone writes a better JSON decoding function which does that I'd be happy to use that instead.
public function getFiles($hash) {
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=getfiles&hash=".$hash);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
$ret = curl_exec($ch);
$obj = json_decode($ret,true);
return $obj;
}

//This could be get the properties of multiple torrents, but unfortunately json_decode overwrites the props array each time, instead of
// doing something nice like having props[i] where i is the number of how many hashes you used.
//If someone writes a better JSON decoding function which does that I'd be happy to use that instead.
public function getProperties($hash) {
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=getprops&hash=".$hash);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
$ret = curl_exec($ch);
$obj = json_decode($ret,true);
return $obj;
}

/*
* properties (in format * propertyname type and explanation)
* trackers string (what trackers to use seperated by \r\n\r\n)
* ulrate int (maximum upload rate of torrent)
* dlrate int (maximum download rate of torrent)
* superseed bool (whether or not to superseed)
* dht bool (whether or not to use DHT)
* pex bool (whether or not to use peer exchange)
* seed_override bool (whether or not global seeding settings are overridden)
* seed_ratio int (what ratio to seed to before stopping)
* seed_time int (what time to seed to before stopping (seconds))
* ulslots int (number of upload slots)
*/
//this might work using multiple hashes but for now I haven't set to be able to
//it equally might work with multiple properties and values, again I haven't tried so haven't coded it to do so
public function setProperty($hash,$property,$value) {
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=setprops&hash=".$hash."&s=".$property."&v=".$value);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}
//$file is a number between 0 and the number of files in the torrent minus one. ( I think. might be 1-based)
//Files are in the order that getFiles returns them in
//Priority is one of the UTORRENT_FILEPRIORITYs I defined earlier
//If $files is an array it will set the priority on each
public function setPriority($hash,$files,$priority) {
$filenums = "";
if(is_array($files)) {
foreach($files as $value) {
$filenums.="&f=".$value;
}
} else {
$filenums = "&f=".$file;
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=setprio&hash=$hash&p=".$priority.$filenums);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}

public function getSettings() {
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=getsettings");
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
$ret = curl_exec($ch);
$obj = json_decode($ret,true);
return $obj;
}
public function setSetting($setting,$value) {
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=setsetting&s=".$setting."&v=".$value);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}

}


?>

USAGE

You can either set your host, user, and pass in the class, by changing it like so

-snip-
class uTorrent {
-snip
public $host = "someip:someport";
public $user = "somename";
public $pass = "somepass";

OR, you can do it after you make the uTorrent object, like so

$torrent = new uTorrent;
$torrent->host = "someip:someport";
$torrent->user = "someuser";
$torrent->pass="somepass";

Here are some examples of usage (in these examples we'll assume you set the host, user and pass in the class (as per the first example)

//print out current torrents (just the names in a newline-seperated list)
$utorrent = new uTorrent();
$torrents = $utorrent->getTorrents();
foreach($torrents as $torrent) {
echo $torrent[UTORRENT_TORRENT_NAME]."\n";
}

//Forces a recheck of every torrent
//way number one (slower)
$utorrent = new uTorrent();
foreach($utorrent->getTorrents() as $torrent) {
$utorrent->recheck($torrent);

}

//Forces a recheck of every torrent
//Way number two (faster)
$utorrent = new uTorrent();
$torrents = array();
//collects an array containing every hash
foreach($utorrent->getTorrents() as $torrent) {
$torrents[] = $torrent[UTORRENT_TORRENT_HASH];
}
//rechecks every torrent
$utorrent->recheck($torrents);

Share this post


Link to post
Share on other sites

I need to implement such thing to my site (it is in the local network): Users open special page where they can add a new torrent download and watch the download progress. (Guest account allows only to see the download progress, not to add new downloads) Admin account allows to delete downloads and to change settings - ordinary users aren't allowed to do it. I guess that these API will help me to do it.

I'm not familar with php classes and objects. So I go in this way:

I think that these API are used on a web server, not in the zip archive of webui. Is this right?

So I've created webui directory in my web root directory. There are two files webui_api.php and webui.php.

webui_api.php contains the code from the first post. webui.php contains:

require_once("webui_api.php");
$torrent = new uTorrent;
$torrents = $torrent->getTorrents();
echo "result: ".$torrents;

if ($torrent->addTorrent("c:\28.nedel.spustya.2007.DivX.DVDRip.kinozal.tv.avi.torrent"))
{print"<br> OK";}
else
{print "Bad";}

So, echo "result: ".$torrents; prints result:<

and adding file shows OK. But no file is added.

Please, explain (examples appreciated) how to use these API.

Share this post


Link to post
Share on other sites

Um. I'm not all that familiar with coding in PHP, but from a cursory glance over the code... Aren't you supposed to be setting $torrent's $host, $user, and $pass variables before actually using its methods...?

Also, IINM, getTorrents() returns an array... is it legal to concatenate strings with arrays in PHP?

Share this post


Link to post
Share on other sites

$torrent's $host, $user, and $pass variables are set in webui_api.php so there is no mistake.

$torrent = new uTorrent;
$torrents = $torrent->getTorrents();
print_r(array_count_values($torrents));

print_r - tells that it is not array.

Can anyone show an example of listing downloads on the web page, similar to guest account?

Share this post


Link to post
Share on other sites

Sorry for the slow response - been away on holiday all week with no internet!

TheDestroyer, I think your problem lies within this line:

if ($torrent->addTorrent("c:\28.nedel.spustya.2007.DivX.DVDRip.kinozal.tv.avi.torrent"))

You should be using c:\\ I think (\28 would probably produce the ASCII character for 28 (or 2) (or nothing) (or something else entirely) (As you can tell I don't really know much about escape characters, except that backslashes need escaping)

Also, I'm not entirely sure how cURL handles uploading files that don't exist (addTorrent was sort of an afterthought)

And I added some usage examples and updated it again to add recheck($hash) and stuff :D

Share this post


Link to post
Share on other sites

Thanx for reply. But I still have got problems listing torrents...

Your example :

//print out current torrents (just the names in a newline-seperated list)

gives an error:

Warning: Invalid argument supplied for foreach() ...

How to fix it?

Share this post


Link to post
Share on other sites

Destroyer: You failed to read this, before the examples.

(in these examples we'll assume you set the host, user and pass in the class (as per the first example)

If they are set correctly there is no problem. (just tested the script myself)

For example, in my case I have used the second method of setting them that I gave (I.E. Not in the class) (this is with the user and pass changed to non-real values)

$utorrent = new uTorrent();
$utorrent->host = "192.168.1.65:20405";
$utorrent->user = "M";
$utorrent->pass = "likefromJamesBond";
$torrents = $utorrent->getTorrents();
foreach($torrents as $torrent) {
echo $torrent[UTORRENT_TORRENT_NAME]."\n";
}

I'll see if I have time some time to add in some error handling in the class though this is really a very minor priority as I have a lot of projects all on the go at once and school is starting again soon for me

Share this post


Link to post
Share on other sites

Thank you very much! My mistake was - IP without a port of webui.

Waiting for more examples of userfull application of these API.

There is a problem in getting size of uploads that are more then 4 GB. Result is negative. We can add 4 Gb to the result and get correct filesize, but if filesize is for example 10 Gb then we don't know how many times to add 4 Gb to the result of

$torrent[uTORRENT_TORRENT_SIZE]

Please, help me to get correct filesize.

Share this post


Link to post
Share on other sites

I don't think that issue's going to be at all easily fixable.

My instant suspicion goes to the PHP JSON module, as PHP internally uses only long integers (64-bit) to store data, although the JSON module might not, and the actual WebUI works for files over 4GB, so it's not a problem with the WebUI or my script.

Eventually, some time in the future, I might see if I can go over the JSON module's source code and see if I'm right.

Share this post


Link to post
Share on other sites

You need to update your PHP installation to the latest version... I updated today from 5.2.1 to 5.2.4 and it's fixed...

Miyanokouji: I think there is a bug in the setPriority function...

Below is the corected code:

public function setPriority($hash,$files,$priority) {
$filenums = "";
if(is_array($files)) {
foreach($files as $value) {
$filenums.="&f=".$value;
}
} else {
$filenums = "&f=".$files;
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=setprio&hash=$hash&p=".$priority.$filenums);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}

Share this post


Link to post
Share on other sites

Thanks for the info and bugfix nowotny, I've now updated the webui and am intending to do another update soon to add url torrent-adding function. What use it'll be is up to the end user <.<

Share this post


Link to post
Share on other sites

I enhanced the removeTorrent function to the ability of removing the downloaded data too... It's backwards compatible so nothing will break...

Here's the code:

//if you set $data to TRUE it'll delete already downloaded data too. Otherwise just the torret file is deleted
public function removeTorrent($hash,$data=FALSE) {
$hashes = "";
if(is_array($hash)) {
foreach($hash as $value) {
$hashes.="&hash=".$value;
}
} else {
$hashes = "&hash=".$hash;
}

if($data) {
$action='removedata';
} else {
$action='remove';
}

$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=".$action.$hashes);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
}

Share this post


Link to post
Share on other sites

How to use the addTorrent function ?

require_once("webui_api.php");
$torrent = new uTorrent;
if ($torrent->addTorrent("c:\\111.torrent"))
{print"<br> OK";}
else
{print "Bad";}

But no file is added.

Share this post


Link to post
Share on other sites

Miyanokouji: the forcestartTorrent and recheckTorrent functions are missing curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); setting... it makes them output the response which I don't think we want... ;)

Share this post


Link to post
Share on other sites

Here is a getLabels function for retrieving labels:

public function getLabels(){
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?list=1");
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
$ret = curl_exec($ch);
$obj = json_decode($ret,true);
$labels = $obj['label'];
curl_close($ch);
return $labels;
}

Share this post


Link to post
Share on other sites

I really liked the API you've written, but I lacked CURL on my server, so I decided to write a slightly altered version using fsockopen. Sorry, it works a little bit differently for some things (configuration etc), but most of it should be the same (function names and output).

What I would really like to have is a json_decode alternative that can run on PHP4 or PHP5 prior to 5.2.4 that can handle longs (so we can show sizes larger than 2GB).

Here's the code:

<?php
define("UTORRENT_TORRENT_HASH", 0);
define("UTORRENT_TORRENT_STATUS", 1);
define("UTORRENT_TORRENT_NAME", 2);
define("UTORRENT_TORRENT_SIZE", 3);
define("UTORRENT_TORRENT_PROGRESS", 4);
define("UTORRENT_TORRENT_DOWNLOADED", 5);
define("UTORRENT_TORRENT_UPLOADED", 6);
define("UTORRENT_TORRENT_RATIO", 7);
define("UTORRENT_TORRENT_UPSPEED", 8);
define("UTORRENT_TORRENT_DOWNSPEED", 9);
define("UTORRENT_TORRENT_ETA", 10);
define("UTORRENT_TORRENT_LABEL", 11);
define("UTORRENT_TORRENT_PEERS_CONNECTED", 12);
define("UTORRENT_TORRENT_PEERS_SWARM", 13);
define("UTORRENT_TORRENT_SEEDS_CONNECTED", 14);
define("UTORRENT_TORRENT_SEEDS_SWARM", 15);
define("UTORRENT_TORRENT_AVAILABILITY", 16);
define("UTORRENT_TORRENT_QUEUE_POSITION", 17);
define("UTORRENT_TORRENT_REMAINING", 18);
define("UTORRENT_FILEPRIORITY_HIGH", 3);
define("UTORRENT_FILEPRIORITY_NORMAL", 2);
define("UTORRENT_FILEPRIORITY_LOW", 1);
define("UTORRENT_FILEPRIORITY_SKIP", 0);
define("UTORRENT_TYPE_INTEGER", 0);
define("UTORRENT_TYPE_BOOLEAN", 1);
define("UTORRENT_TYPE_STRING", 2);
define("UTORRENT_STATUS_STARTED", 1);
define("UTORRENT_STATUS_CHECKED", 2);
define("UTORRENT_STATUS_START_AFTER_CHECK", 4);

class uTorrent {
public $sHost;
public $iPort;
public $sUser;
public $sPassword;
public $iTimeout;
private $oSocket;

public function __construct($sHost = '127.0.0.1', $iPort = 32459, $sUser = 'admin', $sPassword = 'utorrent', $iTimeout = 10) {
$this->sHost = $sHost;
$this->iPort = $iPort;
$this->sUser = $sUser;
$this->sPassword = $sPassword;
$this->iTimeout = $iTimeout;
}

private function doRequest($sURL) {
$this->oSocket = @fsockopen($this->sHost, $this->iPort, $iError, $sError, $this->iTimeout);
if($this->oSocket) {
// Connected
fputs($this->oSocket, 'GET ' . $sURL . '&cid=' . rand(100000000, 259199361) . ' HTTP/1.0' . "\r\n");
fputs($this->oSocket, 'Authorization: Basic ' . base64_encode($this->sUser . ':' . $this->sPassword) . "\r\n\r\n");

// Retrieve content-length header
$sHeader = '';
for(; !strpos($sHeader, "\r\n\r\n"); $sHeader .= fread($this->oSocket, 1));
$aHeaders = explode("\n", $sHeader);
$iContentLength = (int) substr($aHeaders[2], 16);
if($iContentLength) {
$sRead = fread($this->oSocket, $iContentLength);
fclose($this->oSocket);
return $sRead;
} else {
// Could not read content length header
fclose($this->oSocket);
return 'Could not read content-length';
}
} else {
// Couldn't connect to socket
return 'Could not connect';
}
}

public function is_online() {
// Uses start because at present (WebUI 0.31, uTorrent 1.7.2) this simply returns {"":""} and doesn't modify anything
if($this->doRequest('/gui/?action=')) {
return true;
} else {
return false;
}
}

// Returns an array of all torrent information
public function getTorrents() {
$aResponse = json_decode($this->doRequest('/gui/?list=1'), true);
return $aResponse['torrents'];
}

// Returns an array of all labels.
public function getLabels() {
$aResponse = json_decode($this->doRequest('/gui/?list=1'), true);
return $aResponse['label'];
}

private function uploadFile($sFilename, $sHost, $iPort, $sPage, $sPostFieldName, $bGetResponse = false, $bGetHTTPHeaders = false) {
// Read the file
$sFileContents = file_get_contents($sFilename);

// Generate a boundary
$sBoundary = '---------------------------' . substr(sha1(rand(0, 65000) * pi()), 0, 10);

// Set up POST data
$sData = '--' . $sBoundary . "\n" .
'Content-Disposition: form-data; name="' . $sPostFieldName . '"; filename="' . basename($sFilename) . '"' . "\n".
'Content-Type: application/octet-stream' . "\n\n" . $sFileContents . '--' . $sBoundary .
'--' . "\r\n\r\n";

// Set up POST request
$sRequest = 'POST ' . $sPage . ' HTTP/1.0' . "\n" .
'Content-Type: multipart/form-data; boundary=' . $sBoundary . "\n" .
'Content-Length: ' . strlen($sData) . "\r\n\r\n";

// Open socket
$this->oSocket = fsockopen($sHost, $iPort);

if($this->oSocket) {
// Write the request and data to the socket
fputs($this->oSocket, $sRequest . $sData);
if($bGetResponse) {
$sResult = '';
while(!feof($this->oSocket)) {
$sResult .= fread($this->oSocket, 1024);
}
fclose($this->oSocket);

// If the user does not want the HTTP headers, strip them
if(!$bGetHTTPHeaders) {
$sResult = substr($sResult, (strpos($sResult, "\r\n\r\n")+4));
}

return $sResult;
} else {
fclose($this->oSocket);
return true;
}
} else {
// Could not open socket!
return false;
}
}

// If you set $mErrorString then when the function is done and returns false, estring will be a string telling you what error happened.
// $sFilename could probably be a temporary filenames ($_FILES['somefile']['tmp_name']) but I haven't checked
// $sFilename can be a URL
public function addTorrent($sFilename, &$mErrorString = false) {
if(substring($sFilename, 0, 7) == 'http://') {
$this->doRequest('/gui/?action=get-url&s=' . $sFilename);
} else if(file_exists($sFilename)) {
$aResponse = json_decode($this->uploadFile($sFilename, $this->sHost, $this->iPort, '/gui/?action=add-file', 'torrent_file', true), true);
if(isset($aResponse['error'])) {
if($mErrorString !== false) {
$mErrorString = $aResponse['error'];
}
return false;
} else {
return true;
}
} else {
$mErrorString = 'File does not exist!';
return false;
}
}

private function processHashArgument($mHash) {
$sHashes = "";
if(is_array($mHash)) {
foreach($mHash as $sHash) {
$sHashes .= "&hash=" . $sHash;
}
} else {
$sHashes = "&hash=" . $mHash;
}

return $sHashes;
}

public function removeTorrent($mHash, $bRemoveData = false) {
if($bRemoveData) {
$sAction = 'removedata';
} else {
$sAction = 'remove';
}

$this->doRequest('/gui/?action=' . $sAction . $this->processHashArgument($mHash));
}

public function startTorrent($mHash) {
$this->doRequest('/gui/?action=start' . $this->processHashArgument($mHash));
}

public function pauseTorrent($mHash) {
$this->doRequest('/gui/?action=pause' . $this->processHashArgument($mHash));
}
public function stopTorrent($mHash) {
$this->doRequest('/gui/?action=stop' . $this->processHashArgument($mHash));
}
public function forcestartTorrent($mHash) {
$this->doRequest('/gui/?action=forcestart' . $this->processHashArgument($mHash));
}

public function recheckTorrent($mHash) {
$this->doRequest('/gui/?action=recheck' . $this->processHashArgument($mHash));
}

// This could get the files of multiple torrents, but unfortunately json_decode overwrites the files array each time,
// instead of doing something nice like having files[i] where i is the number of how many hashes you used.
// If someone writes a better JSON decoding function which does that I'd be happy to use that instead.
public function getFiles($sHash) {
return json_decode($this->doRequest('/gui/?action=getfiles&hash=' . $sHash), true);
}

// This could be get the properties of multiple torrents, but unfortunately json_decode overwrites the props array each time,
// instead of doing something nice like having props[i] where i is the number of how many hashes you used.
// If someone writes a better JSON decoding function which does that I'd be happy to use that instead.
public function getProperties($sHash) {
return json_decode($this->doRequest('/gui/?action=getprops&hash=' . $sHash), true);
}

// properties (in format * propertyname type and explanation)
// trackers string (what trackers to use seperated by \r\n\r\n)
// ulrate int (maximum upload rate of torrent)
// dlrate int (maximum download rate of torrent)
// superseed bool (whether or not to superseed)
// dht bool (whether or not to use DHT)
// pex bool (whether or not to use peer exchange)
// seed_override bool (whether or not global seeding settings are overridden)
// seed_ratio int (what ratio to seed to before stopping)
// seed_time int (what time to seed to before stopping (seconds))
// ulslots int (number of upload slots)

// This might work using multiple hashes but for now I haven't set to be able to it equally might
// work with multiple properties and values, again I haven't tried so haven't coded it to do so
public function setProperty($sHash, $sProperty, $sValue) {
$this->doRequest('/gui/?action=setprops&hash=' . $sHash . "&s=" . $sProperty . "&v=" . $sValue);
}

// $file is a number between 0 and the number of files in the torrent minus one. ( I think. might be 1-based)
// Files are in the order that getFiles returns them in
// Priority is one of the UTORRENT_FILEPRIORITYs I defined earlier
// If $mFiles is an array it will set the priority on each
public function setPriority($sHash, $mFiles, $iPriority) {
$sFilenumbers = "";
if(is_array($mFiles)) {
foreach($mFiles as $iValue) {
$sFilenumbers .= "&f=" . $iValue;
}
} else {
$sFilenumbers = "&f=" . $mFiles;
}

$this->doRequest('/gui/?action=setprio&hash=' . $sHash . '&p=' . $iPriority . '&f=' . $sFilenumbers);
}

public function getSettings() {
return json_decode($this->doRequest('/gui/?action=getsettings'), true);
}
public function setSetting($sSetting, $sValue) {
$this->doRequest('/gui/?action=setsetting&s=' . $sSetting . "&v=" . $sValue);
}
}

Here's how I would use it to pause all the torrents:

$uTorrent = new uTorrent('127.0.0.1', 57777, 'rexxars', 'password', 10);
if($uTorrent->is_online())
{
foreach($uTorrent->getTorrents() as $aTorrent)
{
$uTorrent->pauseTorrent($aTorrent[UTORRENT_TORRENT_HASH]);
}
}

Hope it can be to help for somebody :-)

Share this post


Link to post
Share on other sites

Hi,

Here some change on addtorrent() on adding torrent with url

Thank's for this API!

   //if you set $estring then when the function is done and returns false, estring will be a string telling you what error happened.
//$filename could probably be a temporary filenames ($_FILES['somefile']['tmp_name']) but I haven't checked
//$filename can be a URL
public function addTorrent($filename,&$estring = false) {
if(substr($filename,0,7) == "http://") {
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=add-url&s=".$filename);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_exec($ch);
} else if(file_exists($filename)) {
$form_fields = array();
//$form_fields['add_button'] = "Add File \n";
$form_fields['torrent_file'] = "@".realpath($filename);
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"http://".$this->host."/gui/?action=add-file");
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
//curl_setopt($ch,CURLOPT_HEADER,true);
curl_setopt($ch,CURLOPT_USERPWD,$this->user.":".$this->pass);
curl_setopt($ch,CURLOPT_POSTFIELDS,$form_fields);
curl_setopt($ch,CURLOPT_VERBOSE,true);
$ret = curl_exec($ch);
//echo $ret;
//echo curl_error($ch);

curl_close($ch);
$obj = json_decode($ret,true);
if(isset($obj['error'])) {
if($estring !== false) {
$estring = $obj['error'];
}
return false;
} else {
return true;
}
} else {
$estring = "File doesn't exist!";
return false;
}
}

Share this post


Link to post
Share on other sites