PageRenderTime 253ms CodeModel.GetById 100ms app.highlight 66ms RepoModel.GetById 75ms 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
  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
 28  * You should have received a copy of the GNU General Public License
 29  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 30		*
 31	 */
 32
 33require_once('xmlrpc.php');
 34
 35class Rtorrent
 36{
 37
 38	private $server;
 39	private $params;
 40
 41	function __construct($params)
 42	{
 43
 44		$this->params = $params;
 45
 46		$this->server = new xmlrpc_client(
 47			$params['rtorrent_scgi_folder'],
 48			$params['server_ip'],
 49			$params['server_port'],
 50			(isset($params['https']) && $params['https']=false)?'https':'http11'
 51		);
 52
 53
 54		if(isset($params['username']) && isset($params['password']) )
 55		{
 56			$this->server->setCredentials(
 57				$params['username'],
 58				$params['password'],
 59				$params['set_auth_digest']?CURLAUTH_ANY:CURLAUTH_BASIC
 60			);
 61		}
 62
 63	}
 64
 65	private function SendAndRecieve($message)
 66	{
 67
 68		$this->server->return_type = 'phpvals';
 69		$this->server->no_multicall = true;
 70
 71		//Fixes the HTTP/1.1 417 Expect: error.
 72		$curlopts = array(CURLOPT_HTTPHEADER => array('Expect:'));
 73
 74		//If the user has "trust_cert" set to true, then set curl to do so
 75		if(isset($this->params['trust_cert']) && $this->params['trust_cert'] === true)
 76		{
 77			$this->client->setSSLVerifyPeer(FALSE);
 78		}
 79
 80		$this->server->SetCurlOptions($curlopts);
 81		$response = $this->server->send($message);
 82
 83		if(isset($_GET['debugResponse'])) { print_r($response); }
 84
 85		if($response->faultCode() )
 86		{
 87
 88			return $response->faultString();
 89
 90		}
 91		else
 92		{
 93
 94			return $response->value();
 95
 96		}
 97
 98	}
 99
100	public function Retrieve($id='')
101	{
102
103		$message = new xmlrpcmsg('d.multicall', array(
104			new xmlrpcval('name'), //Make an array for all loaded torrents
105			new xmlrpcval('d.get_hash='), //The torrent hash
106			new xmlrpcval('d.get_name='), //Torrent's name
107			new xmlrpcval('d.get_state='), //0 = stopped, 1 = started
108			new xmlrpcval('d.get_size_bytes='), //The size in bytes
109			new xmlrpcval('d.get_bytes_done='), //How many bytes completed
110			new xmlrpcval('d.get_up_total='), //How much in total has been uploaded
111			new xmlrpcval('d.get_down_rate='), //Download rate in bytes
112			new xmlrpcval('d.get_up_rate='), //Upload rate in bytes
113			new xmlrpcval('d.get_peers_connected='), //Amount of connected peers
114			new xmlrpcval('d.get_peers_not_connected='), //Amount of unconnected peers
115			new xmlrpcval('d.get_peers_accounted='), //Number of leechers
116			new xmlrpcval('d.get_complete='), //Is the torrent completely downloaded?
117			new xmlrpcval('d.is_hash_checking='), //Is it rehashing?
118			new xmlrpcval('d.get_creation_date='), //Date torrent added
119			new xmlrpcval('d.get_base_path='), //Where the torrent exists
120			new xmlrpcval('d.get_free_diskspace='), //Free disk space where torrent is
121			new xmlrpcval('d.is_private='), //Is torrent private?
122			new xmlrpcval('d.get_message='), //Comment
123			new xmlrpcval('d.get_priority='), //Priority (number)
124			new xmlrpcval('d.is_hash_checked='), //Has it been hash checked before?
125			new xmlrpcval('d.get_skip_total='), //How many wasted bytes?
126			new xmlrpcval('d.get_custom5='), //We use this for the torrents "new name"
127			new xmlrpcval('d.get_custom4='), //We use this for the torrents "label"
128			//http://libtorrent.rakshasa.no/ticket/1538 < Describes a solution for
129			//rtorrent builds that don't use I8, we multiply chunk_size by size_chunks
130			new xmlrpcval('d.get_chunk_size='), //Get the size of a single chunk in bytes
131			new xmlrpcval('d.get_size_chunks='), //Get how many chunks are in the torrent
132			new xmlrpcval('d.get_completed_chunks=') //Get how many chunks have downloaded.
133		) );
134
135		$torrents = $this->SendAndRecieve($message);
136
137		if(!is_array($torrents) )
138		{
139
140			return json_encode(array('error'=>$torrents));
141
142		}
143
144		foreach($torrents as $torrent)
145		{
146
147				$df = @disk_free_space(dirname($torrent[14]));
148				$dt = @disk_total_space(dirname($torrent[14]));
149
150				$return_array[$torrent[0]] = array(
151
152					'name' => htmlentities($torrent[1]),
153					'is_downloading' => $torrent[2],
154					//Old versions of rtorrent use i4 which buffer overflows > 4gb
155					'size' => $torrent[3]<0?$torrent[23]* $torrent[24]:$torrent[3],
156					'downloaded' => $torrent[4]<0?$torrent[23]* $torrent[25]:$torrent[4],
157					'uploaded' => $torrent[5]<0?2147483648:$torrent[5],
158					'down_rate' => $torrent[6],
159					'up_rate' => $torrent[7],
160					'peers_connected' => $torrent[8]-($torrent[8]-$torrent[10]),
161					'peers_total' => $torrent[9]+$torrent[8],
162					'seeders_connected' => $torrent[8]-$torrent[10],
163					'is_completed' => $torrent[11],
164					'is_hashing' => $torrent[12],
165					'date_added' => $torrent[13],
166					'base_path' => $torrent[14],
167					//Remember the bug above? We're going to mangle this a bit...
168					'free_diskspace' => $df?$df:$torrent[15],
169					'total_diskspace' => $dt?$dt:0,
170					'private' => $torrent[16],
171					'tracker_status' => $torrent[17],
172					'priority' => $torrent[18],
173					'has_been_hashed' => $torrent[19],
174					'wasted_bytes' => $torrent[20],
175					'new_name' => $torrent[21],
176					'label' => $torrent[22],
177
178				);
179
180		}
181
182		return $return_array;
183
184	}
185
186	public function LoadURL($url, $start)
187	{
188		$command = $start=='true'?'load_start_verbose':'load_verbose';
189
190		$message = new xmlrpcmsg($command, array(new xmlrpcval($url) ) );
191
192		$response = $this->SendAndRecieve($message);
193
194		$this->server->setDebug(2);
195
196		$return = array();
197
198		$return['openurl']=$response==0?true:false;
199
200		return $return;
201
202	}
203
204	public function Remove($id)
205	{
206
207		$message = new xmlrpcmsg('d.erase', array(new xmlrpcval($id) ) );
208
209		$response = $this->SendAndRecieve($message);
210
211		$return = array();
212
213		$return['remove']=$response==0?true:alse;
214
215		return $return;
216
217	}
218
219	public function Pause($id)
220	{
221
222		$message = new xmlrpcmsg('d.stop', array(new xmlrpcval($id)));
223
224		$this->SendAndRecieve($message);
225
226		$message = new xmlrpcmsg('d.close', array(new xmlrpcval($id)));
227
228		$response = $this->SendAndRecieve($message);
229
230		$return = array();
231
232		$return['pause']=$response==0?true:false;
233
234		return $return;
235
236	}
237
238	public function PauseAll()
239	{
240
241		$message = new xmlrpcmsg('d.multicall', array(
242			new xmlrpcval('started'), //Get all ongoing torrents
243			new xmlrpcval('d.stop='), //Stop all ongoing torrents
244		));
245
246		$this->SendAndRecieve($message);
247
248		$message = new xmlrpcmsg('d.multicall', array(
249			new xmlrpcval('stopped'), //Get all ongoing torrents
250			new xmlrpcval('d.close='), //Stop all ongoing torrents
251		));
252
253		$response = $this->SendAndRecieve($message);
254
255		$return = array();
256
257		$return['pause']=$response==0?true:false;
258
259		return $return;
260
261	}
262
263	public function Resume($id)
264	{
265
266		$message = new xmlrpcmsg('d.open', array(new xmlrpcval($id)));
267
268		$this->SendAndRecieve($message);
269
270		$message = new xmlrpcmsg('d.start', array(new xmlrpcval($id)));
271
272		$response = $this->SendAndRecieve($message);
273
274		$return = array();
275
276		$return['resume']=$response==0?true:false;
277
278		return $return;
279
280	}
281
282	public function ResumeAll()
283	{
284
285		$message = new xmlrpcmsg('d.multicall', array(
286			new xmlrpcval('closed'), //Get all ongoing torrents
287			new xmlrpcval('d.open='), //Stop all ongoing torrents
288		));
289
290		$this->SendAndRecieve($message);
291
292		$message = new xmlrpcmsg('d.multicall', array(
293			new xmlrpcval('stopped'), //Get all ongoing torrents
294			new xmlrpcval('d.start='), //Stop all ongoing torrents
295		));
296
297		$response = $this->SendAndRecieve($message);
298
299		$return = array();
300
301		$return['pause']=$response==0?true:false;
302
303		return $return;
304
305	}
306
307	public function SetTorrentPriority($id, $priority)
308	{
309		$message = new xmlrpcmsg('d.set_priority',array(
310			new xmlrpcval($id), //Torrent ID
311			new xmlrpcval($priority, 'int'), //Priority
312		));
313
314		$response = $this->SendAndRecieve($message);
315
316		$return = array();
317
318		$return['setpriority']=$response==0?true:false;
319
320		return $return;
321
322	}
323
324	public function SetFilePriority($id, $file_id, $priority)
325	{
326		//We have a range of priorities
327		if(strpos($file_id,':'))
328		{
329			$priorities_ar = array();
330			$file_id= explode(':', $file_id);
331			for($i=$file_id[0]; $i<=$file_id[1]; ++$i)
332			{
333				$priorities_ar[]= new xmlrpcval(array(
334						'methodName'=>new xmlrpcval('f.set_priority'),
335						'params'=>new xmlrpcval(array(
336								new xmlrpcval($id),
337								new xmlrpcval($i, 'int'),
338								new xmlrpcval($priority, 'int'),
339							), 'array')
340					),'struct');
341
342			}
343		}
344		elseif(strpos($file_id,','))
345		{
346			$priorities_ar = array();
347			$file_id= explode(',', $file_id);
348			$count = count($file_id);
349			for($i=0; $i<=$count; ++$i)
350			{
351				$priorities_ar[]= new xmlrpcval(array(
352						'methodName'=>new xmlrpcval('f.set_priority'),
353						'params'=>new xmlrpcval(array(
354								new xmlrpcval($id),
355								new xmlrpcval($file_id[$i], 'int'),
356								new xmlrpcval($priority, 'int'),
357							), 'array')
358					),'struct');
359
360			}
361		}
362		else
363		{
364			$priorities_ar = array(new xmlrpcval(array(
365						'methodName'=>new xmlrpcval('f.set_priority'),
366						'params'=>new xmlrpcval(array(
367								new xmlrpcval($id),
368								new xmlrpcval($file_id, 'int'),
369								new xmlrpcval($priority, 'int'),
370							), 'array')
371					),'struct'));
372		}
373
374		$priorities_ar[] = new xmlrpcval(array(
375					'methodName'=>new xmlrpcval('d.update_priorities'),
376					'params'=>new xmlrpcval(array(
377							new xmlrpcval($id)
378					), 'array'),
379				), 'struct');
380
381		$message = new xmlrpcmsg('system.multicall',array(
382			new xmlrpcval($priorities_ar, 'array')));
383
384
385		$response = $this->SendAndRecieve($message);
386
387		$return = array();
388
389		$return['setpriority']=true;
390
391		foreach($response as $response_array)
392		{
393			foreach($response_array as $res)
394			{
395				if($res!=0)
396				{
397					$return['setpriority']=false;
398					return $return;
399				}
400			}
401		}
402
403		return $return;
404
405	}
406
407	public function SetRate($type, $rate)
408	{
409
410		if($type!= 'upload' && $type!= 'download')
411		{
412			return json_encode(array('error'=>'Unrecognised command'));
413		}
414		else
415		{
416			$message = new xmlrpcmsg('set_'.$type.'_rate', array(new xmlrpcval($rate.'k')));
417
418			$response = $this->SendAndRecieve($message);
419
420			$return = array();
421
422			$return['setrate']=$response==0?true:false;
423
424			return $return;
425
426		}
427
428	}
429
430	public function GetRate($id)
431	{
432
433		if($id!= 'upload' && $id!= 'download')
434		{
435			return json_encode(array('error'=>'Unrecognised command'));
436		}
437		else
438		{
439			$message = new xmlrpcmsg('get_'.$id.'_rate');
440		}
441
442			return array('getRate'=>$this->SendAndRecieve($message)/1024);
443
444	}
445
446	public function GetTrackers($id)
447	{
448
449		$message = new xmlrpcmsg('t.multicall', array(
450			new xmlrpcval($id), //Torrent ID
451			new xmlrpcval(''),
452			new xmlrpcval('t.get_url='), //Tracker's URL
453			new xmlrpcval('t.get_scrape_incomplete='), //The peers scraped from the tracker
454			new xmlrpcval('t.get_scrape_complete='), //The seeders scraped from the tracker
455			new xmlrpcval('t.is_enabled='), //0 = disabled , 1 = enabled
456			new xmlrpcval('t.get_group='), //0 = disabled , 1 = enabled
457			new xmlrpcval('t.is_open='), //0 = closed , 1 = open
458		) );
459
460		$trackers = $this->SendAndRecieve($message);
461
462		if(!is_array($trackers) )
463		{
464
465			return json_encode(array('error'=>$trackers));
466
467		}
468
469		$return_array = array();
470
471		foreach($trackers as $tracker)
472		{
473
474				$return_array[$tracker[0]] = array(
475
476					'peers' => $tracker[1],
477					'seeders' => $tracker[2],
478					'enabled' => $tracker[3]==1?true:false,
479					'id' => $tracker[4],
480					'open' => $tracker[5]==1?true:false,
481
482				);
483
484		}
485
486		if(array_key_exists('dht://', $return_array))
487		{
488			$message = new xmlrpcmsg('dht_statistics', array(new xmlrpcval($id)));
489			$dht = $this->SendAndRecieve($message);
490			$return_array['dht://']['peers']=$dht['peers'];
491			$return_array['dht://']['nodes']=$dht['nodes'];
492			unset($return_array['dht://']['seeders']);
493		}
494
495		return $return_array;
496
497	}
498
499	public function SetTracker($id, $tracker, $state)
500	{
501		$state=$state==1?1:0;
502
503		$message = new xmlrpcmsg('t.set_enabled', array(
504			new xmlrpcval($id), //Torrent ID
505			new xmlrpcval($tracker, 'int'), //The tracker ID
506			new xmlrpcval($state, 'int') //Disabled or Enabled.
507		) );
508
509		$response = $this->SendAndRecieve($message);
510
511		$return = array();
512
513		$return['settracker']=$reponse[0]==0?true:false;
514
515		return $return;
516	}
517
518	public function GetPeers($id)
519	{
520
521		$message = new xmlrpcmsg('p.multicall', array(
522			new xmlrpcval($id), //Torrent ID
523			new xmlrpcval(''),
524			new xmlrpcval('p.get_address='), //The peer IP
525			new xmlrpcval('p.get_client_version='), //Peers rtorrent Program
526			new xmlrpcval('p.get_completed_percent='), //Peers % complete
527			new xmlrpcval('p.get_down_rate='), //How fast this peer is seeding to us
528			new xmlrpcval('p.get_down_total='), //How much they've seeded to us
529			new xmlrpcval('p.get_up_rate='), //How fast we're seeding to this peer
530			new xmlrpcval('p.get_up_total='), //How much we've seeded to them
531			new xmlrpcval('p.is_encrypted='), //0 = not encrypted , 1 = encrypted
532			new xmlrpcval('p.is_obfuscated='), //0 = not obf., 1 = obf.
533			new xmlrpcval('p.is_snubbed='), //0 = not snubbed, 1 = snubbed
534		) );
535
536		$peers = $this->SendAndRecieve($message);
537
538		if(!is_array($peers) )
539		{
540
541			return json_encode(array('error'=>$peers));
542
543		}
544
545		$return_array = array();
546
547		foreach($peers as $peer)
548		{
549
550				$return_array[$peer[0]] = array(
551
552					'client' => $peer[1],
553					'completed_percent' => $peer[2],
554					'down_rate' => $peer[3],
555					'down_total' => $peer[4],
556					'up_rate' => $peer[5],
557					'up_total' => $peer[6],
558					'is_e' => $peer[7],
559					'is_o' => $peer[8],
560					'is_s' => $peer[9],
561
562				);
563
564		}
565
566		return $return_array;
567
568	}
569
570	public function GetFiles($id)
571	{
572
573		$message = new xmlrpcmsg('f.multicall', array(
574			new xmlrpcval($id), //Torrent ID
575			new xmlrpcval(''),
576			new xmlrpcval('f.get_path='), //The file path
577			new xmlrpcval('f.get_priority='), //The file priority
578			new xmlrpcval('f.get_size_bytes='), //The file size in bytes
579			new xmlrpcval('f.get_completed_chunks='), //Chunks done of the file
580			new xmlrpcval('f.get_size_chunks='), //The file size in chunks
581			new xmlrpcval('f.get_size_chunks='), //The file size in chunks
582		) );
583
584		$files = $this->SendAndRecieve($message);
585
586		if(!is_array($files) )
587		{
588
589			return json_encode(array('error'=>$files));
590
591		}
592
593		$return_array = array();
594
595		foreach($files as $file)
596		{
597
598				$return_array[] = array(
599
600					'path' => $file[0],
601					'priority' => $file[1],
602					'size_bytes' => $file[2]<0?2147483648:$file[2],
603					'chunks_complete' => $file[3],
604					'chunks' => $file[4]
605
606				);
607
608		}
609
610		return $return_array;
611
612	}
613
614	public function SetName($id, $name)
615	{
616		$message = new xmlrpcmsg('d.set_custom5',
617			array(new xmlrpcval($id), new xmlrpcval($name) ) );
618
619		$reponse = $this->SendAndRecieve($message);
620
621		$return = array();
622
623		$return['rename']=$reponse[0]==0?true:false;
624
625		return $return;
626	}
627
628	public function SetLabel($id, $label)
629	{
630
631		$message = new xmlrpcmsg('d.set_custom4',
632			array(new xmlrpcmsg($id), new xmlrpcmsg($label) ) );
633
634		$reponse = $this->SendAndRecieve($message);
635
636		$return = array();
637
638		$return['setLabel']=$reponse[0]==0?true:false;
639
640		return $return;
641
642	}
643
644	public function GetListOfCommands()
645	{
646
647		$message = new xmlrpcmsg('system.listMethods');
648		return $this->SendAndRecieve($message);
649
650	}
651
652	public function Debug()
653	{
654
655		$message = new xmlrpcmsg('system.listMethods');
656		$this->server->setDebug(2);
657		print_r($this);
658		return $this->SendAndRecieve($message);
659
660	}
661
662}