Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /* константы ошибок */
- define('TORRENTMETA_ERROR_NO_INPUT_FILE',1); // ошибка отсутствия файла для чтения
- /**
- * TorrentMeta
- *
- * Класс для обработки .torrent-файлов
- *
- * @example
- * $torrentFile = new TorrentMeta('./mytorrent.torrent');
- * if ( $torrentFile->getErrorCode()==0 ){
- * echo $torrentFile->getHash(true);
- * }
- */
- class TorrentMeta{
- protected
- // Путь к обрабатываемому файлу. Если обрабатывается строка, остается пустым
- $file = '',
- // Код ошибки
- $errorCode = 0,
- // Мета-данные
- $meta = array(),
- // Хэш торрента
- $hash = '';
- /**
- * Конструктор.
- *
- * @param string $metaFrom - строка для обработки или путь к файлу
- * @param bool $useString - TRUE, если обрабатывается строка, FALSE если обрабатывается файл
- *
- * @return TorrentMeta
- */
- public function __construct($metaFrom='',$useString=false){
- if ( $useString ){
- $this->meta = TorrentMeta::parseByteString($metaFrom);
- }elseif($metaFrom){
- $this->file = $metaFrom;
- if ( $metaFrom ){
- $this->parseMetaFile($metaFrom);
- }
- }
- }
- /**
- * Возвращает код ошибки
- *
- * @return int - код ошибки
- */
- public function getErrorCode(){
- return $this->errorCode;
- }
- /**
- * Возвращает мета-данные файла или строки
- *
- * @return array - мета-данные
- */
- public function getMetaInfo(){
- return $this->meta;
- }
- /**
- * Возвращает хэш торрента
- *
- * @param bool $returnHexVal - Если TRUE, возвращает хэш в виде hex-строки. Если FALSE - в виде двоичной строки
- * @return string
- */
- public function getHash($returnHexVal=false){
- return $returnHexVal ? bin2hex($this->meta['info_hash']) : $this->meta['info_hash'];
- }
- /**
- * Обрабатывает файл и устанавливает свойство meta объекта согласно структуре данных
- *
- * @param string $file - путь к файлу
- * @return bool - TRUE, если обработка удалась, FALSE иначе.
- */
- protected function parseMetaFile($file){
- if ( file_exists($file) ){
- $this->meta = TorrentMeta::parseByteString(file_get_contents($file));
- if( !empty($this->meta) ){
- $this->meta['pieces_array'] = $this->parsePiecesHashes();
- $this->meta['total_size'] = 0;
- if ( isset($this->meta['info']['files']) ){
- for( $i=0;$i<count($this->meta['info']['files']);$i++ )
- $this->meta['total_size'] += $this->meta['info']['files'][$i]['length'];
- }else
- $this->meta['total_size'] = $this->meta['info']['length'];
- }
- }else
- $this->Error(TORRENTMETA_ERROR_NO_INPUT_FILE);
- return false;
- }
- /**
- * Обрабатывает строку частей торрента-файла и разбивает её на хэши частей
- *
- * @return array|bool - Массив хэшей, если разбивка удалась, FALSE иначе
- */
- protected function parsePiecesHashes(){
- if ( !empty($this->meta['info']['pieces']) ){
- $pieces = array();
- $pieces_str = bin2hex($this->meta['info']['pieces']);
- $len = strlen($pieces_str);
- for( $offset=0;$offset<$len;$offset+=40 ){
- $pieces[] = substr($pieces_str,$offset,40);
- }
- return $pieces;
- }
- return false;
- }
- /**
- * Обрабатывает byte-строку с целью получения структурированных данных
- *
- * @static
- * @param string $string - строка для обработки
- * @return array - массив данных
- */
- public static function parseByteString($string){
- $data = array();
- TorrentMeta::parseByteStringRecursive($string,0,$data);
- return $data;
- }
- /**
- * Рекурсивно обрабатывает byte-строку
- *
- * @static
- * @param string $string - строка для обработки
- * @param int $offset - отступ от начала строки
- * @param array $data - массив данных
- * @return int - длина обработаной части строки
- */
- protected static function parseByteStringRecursive($string,$offset,&$data){
- $modifier = substr($string,$offset,1);
- $len = strlen($string);
- if ( (string)intval($modifier)===$modifier ){
- $pos = strpos($string,':',$offset);
- $length = intval(substr($string,$offset,$pos-$offset));
- $data = substr($string,$pos+1,$length);
- $offset = $pos+1+$length;
- }else{
- $offset++;
- switch ($modifier){
- case 'd':
- $data = array();
- do{
- $key = '';
- $offset = TorrentMeta::parseByteStringRecursive($string,$offset,$key);
- if ( $offset>=$len )
- break;
- $value = '';
- $offset_new = TorrentMeta::parseByteStringRecursive($string,$offset,$value);
- if ( $key=='info' ){
- $toHash = substr($string,$offset,$offset_new-$offset);
- $data['info_hash'] = sha1($toHash,true);
- }
- $offset = $offset_new;
- $data[$key] = $value;
- }while( substr($string,$offset,1)!='e' && $offset<$len );
- $offset++;
- break;
- case 'l':
- $data = array();
- do{
- $value = '';
- $offset = TorrentMeta::parseByteStringRecursive($string,$offset,$value);
- $data[] = $value;
- }while( substr($string,$offset,1)!='e' && $offset<$len );
- return $offset+1;
- break;
- case 'i':
- $pos = strpos($string,'e',$offset);
- $data = intval(substr($string,$offset,$pos-$offset));
- return $pos+1;
- break;
- }
- }
- return $offset;
- }
- /**
- * Устанавливает ошибку
- *
- * @param int $errorCode - код ошибки
- */
- protected function Error($errorCode){
- $this->errorCode = $errorCode;
- }
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement