<?php class BEncode { /** * @var string */ /** * @var int */ /** * Decode * * @param $haystack string * @return mixed */ { self::$haystack = $haystack; self::$offset = 0; $result = self::parse(); self::$haystack = null; return $result; } /** * * @return array */ { self::$offset++; { $key = self::parseString(); $result[ $key ] = self::parse(); } self::$offset += 1; return $result; } /** * * @return array */ { self::$offset++; { $result[] = self::parse(); } self::$offset += 1; return $result; } /** * * @return int */ { self::$offset += 1; if( !is_numeric($value) ) throw new Exception('Parsed data is not integer ''.$value.'' at offset:'.self::$offset, 3); self::$offset += $l + 1; return $value; } /** * * @return string */ { $string = ''; self::$offset += $l+1; self::$offset += $length; return $string; } /** * * @return mixed */ { $result = null; switch( self::$haystack[self::$offset] ) { case 'd': $result = self::parseDictionarie(); break; case 'l': $result = self::parseList(); break; case 'i': $result = self::parseIntiger(); break; default: $result = self::parseString(); else throw new Exception('Unknown type. ''.self::$haystack[self::$offset].'' at offset:'.self::$offset, 1); } return $result; } { if( self::$haystack[self::$offset] == 'e' ) return true; return false; } /* ENCODE */ /** * Encode * @param $mixed mixed * @return string */ { $result = ''; { else { $type = 'l'; // find what type of array we have // if there's one(or more) none numeric key we have dictionarie foreach($mixed as $key => $e) { { $type = 'd'; break; } } } $result .= $type; foreach($mixed as $key => $e) { if( $type == 'l' ) $result .= self::encode($e); else { } } $result .= 'e'; } else { $result .= 'i'.(int)$mixed.'e'; else { } } return $result; } } ?>
Clasa Torrent
<?php require 'BEncode.php'; /** * hex2bin * * from php.net * * @param $h string * @return string */ function hex2bin($h) { $r=''; return $r; } class Tracker { /** * Tracker url * @var string */ protected $url; public function __construct($url) { $this->url = $url; } /** * Get data from tracker * * @param $hash_info string * @return mixed false if failed */ public function ask( $hash_info ) { $url = $this->url .'&peer_id='. self::getPeerId() .'&port=0&uploaded=0&downloaded=0&left=100'; try { $result = BEncode::decode($result); } catch(Exception $e) { return false; } return $result; } /** * Validate the url * @param $url string * @return bool */ { } /** * PeerID * @var string */ { if( self::$sId === null ) { } return self::$sId; } } class Torrent { /** * Torrent data * @var array */ protected $data; /** * Hash (sha1) * @var string */ protected $hash; /** * @var int */ protected $peers = -1; /** * @var int */ protected $seeds = -1; /** * Constructor * @param $data string */ public function __construct($data) { $this->data = BEncode::decode($data); $this->hash = sha1( BEncode::encode($this->data['info']) ); } /** * * @return string */ public function getName() { return @$this->data['info']['name']; } /** * * @return array */ public function getFiles() { return @$this->data['info']['files']; } public function getHash() { return $this->hash; } public function getSeeds() { return $this->seeds; } public function getPeers() { return $this->peers; } /** * Update tracker info * @return bool */ public function updateTracker() { if( @Tracker::validUrl($this->data['announce']) ) $trackers[] = $this->data['announce']; { foreach( $this->data['announce-list'] as $ar ) { } } foreach( $trackers as $url ) { if( @!Tracker::validUrl($url) ) continue; $t = new Tracker($url); $result = $t->ask( $this->getHash() ); return true; } return false; } /** * Create from torrent file * * @param $filename string * @return Torrent */ { return new Torrent($content); } } ?>
Klasa pobiera dane o torrencie(ilość seedów peerów) z trackera, niestety nie każdy tracker wysyła 'complete' & 'incomplete'
przykład:
<?php $torrent = Torrent::fromFile('jakis.torrent'); $torrent->updateTracker(); ?>