PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/rtorrent.php

http://avalanche-rt.googlecode.com/
PHP | 662 lines | 441 code | 184 blank | 37 comment | 20 complexity | ea91f0eb8f2cbbc10c12fa26e91d46cc MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /*
  3. * Rtorrent.php PHP Library 0.9
  4. *
  5. * Avalanche 0.9 Beta
  6. *
  7. * This code is licensed under the GPL3, or "GNU GENERAL PUBLIC LICENSE Version 3"
  8. * For more details, see http://opensource.org/licenses/gpl-3.0.html
  9. *
  10. * For more information, see http://code.google.com/p/avalanche-rt
  11. *
  12. * Date: Tue, 09th Mar 2010.
  13. *
  14. * @author Keith Cirkel ('keithamus') <avalanche@keithcirkel.co.uk>
  15. * @license http://opensource.org/licenses/gpl-3.0.html
  16. * @copyright Copyright Š 2010, Keith Cirkel
  17. *
  18. * This program is free software: you can redistribute it and/or modify
  19. * it under the terms of the GNU General Public License as published by
  20. * the Free Software Foundation, either version 3 of the License, or
  21. * (at your option) any later version.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. * GNU General Public License for more details.
  27. * You should have received a copy of the GNU General Public License
  28. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  29. *
  30. */
  31. require_once('xmlrpc.php');
  32. class Rtorrent
  33. {
  34. private $server;
  35. private $params;
  36. function __construct($params)
  37. {
  38. $this->params = $params;
  39. $this->server = new xmlrpc_client(
  40. $params['rtorrent_scgi_folder'],
  41. $params['server_ip'],
  42. $params['server_port'],
  43. (isset($params['https']) && $params['https']=false)?'https':'http11'
  44. );
  45. if(isset($params['username']) && isset($params['password']) )
  46. {
  47. $this->server->setCredentials(
  48. $params['username'],
  49. $params['password'],
  50. $params['set_auth_digest']?CURLAUTH_ANY:CURLAUTH_BASIC
  51. );
  52. }
  53. }
  54. private function SendAndRecieve($message)
  55. {
  56. $this->server->return_type = 'phpvals';
  57. $this->server->no_multicall = true;
  58. //Fixes the HTTP/1.1 417 Expect: error.
  59. $curlopts = array(CURLOPT_HTTPHEADER => array('Expect:'));
  60. //If the user has "trust_cert" set to true, then set curl to do so
  61. if(isset($this->params['trust_cert']) && $this->params['trust_cert'] === true)
  62. {
  63. $this->client->setSSLVerifyPeer(FALSE);
  64. }
  65. $this->server->SetCurlOptions($curlopts);
  66. $response = $this->server->send($message);
  67. if(isset($_GET['debugResponse'])) { print_r($response); }
  68. if($response->faultCode() )
  69. {
  70. return $response->faultString();
  71. }
  72. else
  73. {
  74. return $response->value();
  75. }
  76. }
  77. public function Retrieve($id='')
  78. {
  79. $message = new xmlrpcmsg('d.multicall', array(
  80. new xmlrpcval('name'), //Make an array for all loaded torrents
  81. new xmlrpcval('d.get_hash='), //The torrent hash
  82. new xmlrpcval('d.get_name='), //Torrent's name
  83. new xmlrpcval('d.get_state='), //0 = stopped, 1 = started
  84. new xmlrpcval('d.get_size_bytes='), //The size in bytes
  85. new xmlrpcval('d.get_bytes_done='), //How many bytes completed
  86. new xmlrpcval('d.get_up_total='), //How much in total has been uploaded
  87. new xmlrpcval('d.get_down_rate='), //Download rate in bytes
  88. new xmlrpcval('d.get_up_rate='), //Upload rate in bytes
  89. new xmlrpcval('d.get_peers_connected='), //Amount of connected peers
  90. new xmlrpcval('d.get_peers_not_connected='), //Amount of unconnected peers
  91. new xmlrpcval('d.get_peers_accounted='), //Number of leechers
  92. new xmlrpcval('d.get_complete='), //Is the torrent completely downloaded?
  93. new xmlrpcval('d.is_hash_checking='), //Is it rehashing?
  94. new xmlrpcval('d.get_creation_date='), //Date torrent added
  95. new xmlrpcval('d.get_base_path='), //Where the torrent exists
  96. new xmlrpcval('d.get_free_diskspace='), //Free disk space where torrent is
  97. new xmlrpcval('d.is_private='), //Is torrent private?
  98. new xmlrpcval('d.get_message='), //Comment
  99. new xmlrpcval('d.get_priority='), //Priority (number)
  100. new xmlrpcval('d.is_hash_checked='), //Has it been hash checked before?
  101. new xmlrpcval('d.get_skip_total='), //How many wasted bytes?
  102. new xmlrpcval('d.get_custom5='), //We use this for the torrents "new name"
  103. new xmlrpcval('d.get_custom4='), //We use this for the torrents "label"
  104. //http://libtorrent.rakshasa.no/ticket/1538 < Describes a solution for
  105. //rtorrent builds that don't use I8, we multiply chunk_size by size_chunks
  106. new xmlrpcval('d.get_chunk_size='), //Get the size of a single chunk in bytes
  107. new xmlrpcval('d.get_size_chunks='), //Get how many chunks are in the torrent
  108. new xmlrpcval('d.get_completed_chunks=') //Get how many chunks have downloaded.
  109. ) );
  110. $torrents = $this->SendAndRecieve($message);
  111. if(!is_array($torrents) )
  112. {
  113. return json_encode(array('error'=>$torrents));
  114. }
  115. foreach($torrents as $torrent)
  116. {
  117. $df = @disk_free_space(dirname($torrent[14]));
  118. $dt = @disk_total_space(dirname($torrent[14]));
  119. $return_array[$torrent[0]] = array(
  120. 'name' => htmlentities($torrent[1]),
  121. 'is_downloading' => $torrent[2],
  122. //Old versions of rtorrent use i4 which buffer overflows > 4gb
  123. 'size' => $torrent[3]<0?$torrent[23]* $torrent[24]:$torrent[3],
  124. 'downloaded' => $torrent[4]<0?$torrent[23]* $torrent[25]:$torrent[4],
  125. 'uploaded' => $torrent[5]<0?2147483648:$torrent[5],
  126. 'down_rate' => $torrent[6],
  127. 'up_rate' => $torrent[7],
  128. 'peers_connected' => $torrent[8]-($torrent[8]-$torrent[10]),
  129. 'peers_total' => $torrent[9]+$torrent[8],
  130. 'seeders_connected' => $torrent[8]-$torrent[10],
  131. 'is_completed' => $torrent[11],
  132. 'is_hashing' => $torrent[12],
  133. 'date_added' => $torrent[13],
  134. 'base_path' => $torrent[14],
  135. //Remember the bug above? We're going to mangle this a bit...
  136. 'free_diskspace' => $df?$df:$torrent[15],
  137. 'total_diskspace' => $dt?$dt:0,
  138. 'private' => $torrent[16],
  139. 'tracker_status' => $torrent[17],
  140. 'priority' => $torrent[18],
  141. 'has_been_hashed' => $torrent[19],
  142. 'wasted_bytes' => $torrent[20],
  143. 'new_name' => $torrent[21],
  144. 'label' => $torrent[22],
  145. );
  146. }
  147. return $return_array;
  148. }
  149. public function LoadURL($url, $start)
  150. {
  151. $command = $start=='true'?'load_start_verbose':'load_verbose';
  152. $message = new xmlrpcmsg($command, array(new xmlrpcval($url) ) );
  153. $response = $this->SendAndRecieve($message);
  154. $this->server->setDebug(2);
  155. $return = array();
  156. $return['openurl']=$response==0?true:false;
  157. return $return;
  158. }
  159. public function Remove($id)
  160. {
  161. $message = new xmlrpcmsg('d.erase', array(new xmlrpcval($id) ) );
  162. $response = $this->SendAndRecieve($message);
  163. $return = array();
  164. $return['remove']=$response==0?true:alse;
  165. return $return;
  166. }
  167. public function Pause($id)
  168. {
  169. $message = new xmlrpcmsg('d.stop', array(new xmlrpcval($id)));
  170. $this->SendAndRecieve($message);
  171. $message = new xmlrpcmsg('d.close', array(new xmlrpcval($id)));
  172. $response = $this->SendAndRecieve($message);
  173. $return = array();
  174. $return['pause']=$response==0?true:false;
  175. return $return;
  176. }
  177. public function PauseAll()
  178. {
  179. $message = new xmlrpcmsg('d.multicall', array(
  180. new xmlrpcval('started'), //Get all ongoing torrents
  181. new xmlrpcval('d.stop='), //Stop all ongoing torrents
  182. ));
  183. $this->SendAndRecieve($message);
  184. $message = new xmlrpcmsg('d.multicall', array(
  185. new xmlrpcval('stopped'), //Get all ongoing torrents
  186. new xmlrpcval('d.close='), //Stop all ongoing torrents
  187. ));
  188. $response = $this->SendAndRecieve($message);
  189. $return = array();
  190. $return['pause']=$response==0?true:false;
  191. return $return;
  192. }
  193. public function Resume($id)
  194. {
  195. $message = new xmlrpcmsg('d.open', array(new xmlrpcval($id)));
  196. $this->SendAndRecieve($message);
  197. $message = new xmlrpcmsg('d.start', array(new xmlrpcval($id)));
  198. $response = $this->SendAndRecieve($message);
  199. $return = array();
  200. $return['resume']=$response==0?true:false;
  201. return $return;
  202. }
  203. public function ResumeAll()
  204. {
  205. $message = new xmlrpcmsg('d.multicall', array(
  206. new xmlrpcval('closed'), //Get all ongoing torrents
  207. new xmlrpcval('d.open='), //Stop all ongoing torrents
  208. ));
  209. $this->SendAndRecieve($message);
  210. $message = new xmlrpcmsg('d.multicall', array(
  211. new xmlrpcval('stopped'), //Get all ongoing torrents
  212. new xmlrpcval('d.start='), //Stop all ongoing torrents
  213. ));
  214. $response = $this->SendAndRecieve($message);
  215. $return = array();
  216. $return['pause']=$response==0?true:false;
  217. return $return;
  218. }
  219. public function SetTorrentPriority($id, $priority)
  220. {
  221. $message = new xmlrpcmsg('d.set_priority',array(
  222. new xmlrpcval($id), //Torrent ID
  223. new xmlrpcval($priority, 'int'), //Priority
  224. ));
  225. $response = $this->SendAndRecieve($message);
  226. $return = array();
  227. $return['setpriority']=$response==0?true:false;
  228. return $return;
  229. }
  230. public function SetFilePriority($id, $file_id, $priority)
  231. {
  232. //We have a range of priorities
  233. if(strpos($file_id,':'))
  234. {
  235. $priorities_ar = array();
  236. $file_id= explode(':', $file_id);
  237. for($i=$file_id[0]; $i<=$file_id[1]; ++$i)
  238. {
  239. $priorities_ar[]= new xmlrpcval(array(
  240. 'methodName'=>new xmlrpcval('f.set_priority'),
  241. 'params'=>new xmlrpcval(array(
  242. new xmlrpcval($id),
  243. new xmlrpcval($i, 'int'),
  244. new xmlrpcval($priority, 'int'),
  245. ), 'array')
  246. ),'struct');
  247. }
  248. }
  249. elseif(strpos($file_id,','))
  250. {
  251. $priorities_ar = array();
  252. $file_id= explode(',', $file_id);
  253. $count = count($file_id);
  254. for($i=0; $i<=$count; ++$i)
  255. {
  256. $priorities_ar[]= new xmlrpcval(array(
  257. 'methodName'=>new xmlrpcval('f.set_priority'),
  258. 'params'=>new xmlrpcval(array(
  259. new xmlrpcval($id),
  260. new xmlrpcval($file_id[$i], 'int'),
  261. new xmlrpcval($priority, 'int'),
  262. ), 'array')
  263. ),'struct');
  264. }
  265. }
  266. else
  267. {
  268. $priorities_ar = array(new xmlrpcval(array(
  269. 'methodName'=>new xmlrpcval('f.set_priority'),
  270. 'params'=>new xmlrpcval(array(
  271. new xmlrpcval($id),
  272. new xmlrpcval($file_id, 'int'),
  273. new xmlrpcval($priority, 'int'),
  274. ), 'array')
  275. ),'struct'));
  276. }
  277. $priorities_ar[] = new xmlrpcval(array(
  278. 'methodName'=>new xmlrpcval('d.update_priorities'),
  279. 'params'=>new xmlrpcval(array(
  280. new xmlrpcval($id)
  281. ), 'array'),
  282. ), 'struct');
  283. $message = new xmlrpcmsg('system.multicall',array(
  284. new xmlrpcval($priorities_ar, 'array')));
  285. $response = $this->SendAndRecieve($message);
  286. $return = array();
  287. $return['setpriority']=true;
  288. foreach($response as $response_array)
  289. {
  290. foreach($response_array as $res)
  291. {
  292. if($res!=0)
  293. {
  294. $return['setpriority']=false;
  295. return $return;
  296. }
  297. }
  298. }
  299. return $return;
  300. }
  301. public function SetRate($type, $rate)
  302. {
  303. if($type!= 'upload' && $type!= 'download')
  304. {
  305. return json_encode(array('error'=>'Unrecognised command'));
  306. }
  307. else
  308. {
  309. $message = new xmlrpcmsg('set_'.$type.'_rate', array(new xmlrpcval($rate.'k')));
  310. $response = $this->SendAndRecieve($message);
  311. $return = array();
  312. $return['setrate']=$response==0?true:false;
  313. return $return;
  314. }
  315. }
  316. public function GetRate($id)
  317. {
  318. if($id!= 'upload' && $id!= 'download')
  319. {
  320. return json_encode(array('error'=>'Unrecognised command'));
  321. }
  322. else
  323. {
  324. $message = new xmlrpcmsg('get_'.$id.'_rate');
  325. }
  326. return array('getRate'=>$this->SendAndRecieve($message)/1024);
  327. }
  328. public function GetTrackers($id)
  329. {
  330. $message = new xmlrpcmsg('t.multicall', array(
  331. new xmlrpcval($id), //Torrent ID
  332. new xmlrpcval(''),
  333. new xmlrpcval('t.get_url='), //Tracker's URL
  334. new xmlrpcval('t.get_scrape_incomplete='), //The peers scraped from the tracker
  335. new xmlrpcval('t.get_scrape_complete='), //The seeders scraped from the tracker
  336. new xmlrpcval('t.is_enabled='), //0 = disabled , 1 = enabled
  337. new xmlrpcval('t.get_group='), //0 = disabled , 1 = enabled
  338. new xmlrpcval('t.is_open='), //0 = closed , 1 = open
  339. ) );
  340. $trackers = $this->SendAndRecieve($message);
  341. if(!is_array($trackers) )
  342. {
  343. return json_encode(array('error'=>$trackers));
  344. }
  345. $return_array = array();
  346. foreach($trackers as $tracker)
  347. {
  348. $return_array[$tracker[0]] = array(
  349. 'peers' => $tracker[1],
  350. 'seeders' => $tracker[2],
  351. 'enabled' => $tracker[3]==1?true:false,
  352. 'id' => $tracker[4],
  353. 'open' => $tracker[5]==1?true:false,
  354. );
  355. }
  356. if(array_key_exists('dht://', $return_array))
  357. {
  358. $message = new xmlrpcmsg('dht_statistics', array(new xmlrpcval($id)));
  359. $dht = $this->SendAndRecieve($message);
  360. $return_array['dht://']['peers']=$dht['peers'];
  361. $return_array['dht://']['nodes']=$dht['nodes'];
  362. unset($return_array['dht://']['seeders']);
  363. }
  364. return $return_array;
  365. }
  366. public function SetTracker($id, $tracker, $state)
  367. {
  368. $state=$state==1?1:0;
  369. $message = new xmlrpcmsg('t.set_enabled', array(
  370. new xmlrpcval($id), //Torrent ID
  371. new xmlrpcval($tracker, 'int'), //The tracker ID
  372. new xmlrpcval($state, 'int') //Disabled or Enabled.
  373. ) );
  374. $response = $this->SendAndRecieve($message);
  375. $return = array();
  376. $return['settracker']=$reponse[0]==0?true:false;
  377. return $return;
  378. }
  379. public function GetPeers($id)
  380. {
  381. $message = new xmlrpcmsg('p.multicall', array(
  382. new xmlrpcval($id), //Torrent ID
  383. new xmlrpcval(''),
  384. new xmlrpcval('p.get_address='), //The peer IP
  385. new xmlrpcval('p.get_client_version='), //Peers rtorrent Program
  386. new xmlrpcval('p.get_completed_percent='), //Peers % complete
  387. new xmlrpcval('p.get_down_rate='), //How fast this peer is seeding to us
  388. new xmlrpcval('p.get_down_total='), //How much they've seeded to us
  389. new xmlrpcval('p.get_up_rate='), //How fast we're seeding to this peer
  390. new xmlrpcval('p.get_up_total='), //How much we've seeded to them
  391. new xmlrpcval('p.is_encrypted='), //0 = not encrypted , 1 = encrypted
  392. new xmlrpcval('p.is_obfuscated='), //0 = not obf., 1 = obf.
  393. new xmlrpcval('p.is_snubbed='), //0 = not snubbed, 1 = snubbed
  394. ) );
  395. $peers = $this->SendAndRecieve($message);
  396. if(!is_array($peers) )
  397. {
  398. return json_encode(array('error'=>$peers));
  399. }
  400. $return_array = array();
  401. foreach($peers as $peer)
  402. {
  403. $return_array[$peer[0]] = array(
  404. 'client' => $peer[1],
  405. 'completed_percent' => $peer[2],
  406. 'down_rate' => $peer[3],
  407. 'down_total' => $peer[4],
  408. 'up_rate' => $peer[5],
  409. 'up_total' => $peer[6],
  410. 'is_e' => $peer[7],
  411. 'is_o' => $peer[8],
  412. 'is_s' => $peer[9],
  413. );
  414. }
  415. return $return_array;
  416. }
  417. public function GetFiles($id)
  418. {
  419. $message = new xmlrpcmsg('f.multicall', array(
  420. new xmlrpcval($id), //Torrent ID
  421. new xmlrpcval(''),
  422. new xmlrpcval('f.get_path='), //The file path
  423. new xmlrpcval('f.get_priority='), //The file priority
  424. new xmlrpcval('f.get_size_bytes='), //The file size in bytes
  425. new xmlrpcval('f.get_completed_chunks='), //Chunks done of the file
  426. new xmlrpcval('f.get_size_chunks='), //The file size in chunks
  427. new xmlrpcval('f.get_size_chunks='), //The file size in chunks
  428. ) );
  429. $files = $this->SendAndRecieve($message);
  430. if(!is_array($files) )
  431. {
  432. return json_encode(array('error'=>$files));
  433. }
  434. $return_array = array();
  435. foreach($files as $file)
  436. {
  437. $return_array[] = array(
  438. 'path' => $file[0],
  439. 'priority' => $file[1],
  440. 'size_bytes' => $file[2]<0?2147483648:$file[2],
  441. 'chunks_complete' => $file[3],
  442. 'chunks' => $file[4]
  443. );
  444. }
  445. return $return_array;
  446. }
  447. public function SetName($id, $name)
  448. {
  449. $message = new xmlrpcmsg('d.set_custom5',
  450. array(new xmlrpcval($id), new xmlrpcval($name) ) );
  451. $reponse = $this->SendAndRecieve($message);
  452. $return = array();
  453. $return['rename']=$reponse[0]==0?true:false;
  454. return $return;
  455. }
  456. public function SetLabel($id, $label)
  457. {
  458. $message = new xmlrpcmsg('d.set_custom4',
  459. array(new xmlrpcmsg($id), new xmlrpcmsg($label) ) );
  460. $reponse = $this->SendAndRecieve($message);
  461. $return = array();
  462. $return['setLabel']=$reponse[0]==0?true:false;
  463. return $return;
  464. }
  465. public function GetListOfCommands()
  466. {
  467. $message = new xmlrpcmsg('system.listMethods');
  468. return $this->SendAndRecieve($message);
  469. }
  470. public function Debug()
  471. {
  472. $message = new xmlrpcmsg('system.listMethods');
  473. $this->server->setDebug(2);
  474. print_r($this);
  475. return $this->SendAndRecieve($message);
  476. }
  477. }