Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2017
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 7.23 KB | None | 0 0
  1. <?php
  2. /* константы ошибок */
  3. define('TORRENTMETA_ERROR_NO_INPUT_FILE',1); // ошибка отсутствия файла для чтения
  4. /**
  5. * TorrentMeta
  6. *
  7. * Класс для обработки .torrent-файлов
  8. *
  9. * @example
  10. *   $torrentFile = new TorrentMeta('./mytorrent.torrent');
  11. *   if ( $torrentFile->getErrorCode()==0 ){
  12. *       echo $torrentFile->getHash(true);
  13. *   }
  14. */
  15. class TorrentMeta{
  16.    
  17.     protected
  18.         // Путь к обрабатываемому файлу. Если обрабатывается строка, остается пустым
  19.         $file = '',
  20.         // Код ошибки
  21.         $errorCode = 0,
  22.         // Мета-данные
  23.         $meta = array(),
  24.         // Хэш торрента
  25.         $hash = '';
  26.  
  27.     /**
  28.      * Конструктор.
  29.      *
  30.      * @param string $metaFrom - строка для обработки или путь к файлу
  31.      * @param bool $useString - TRUE, если обрабатывается строка, FALSE если обрабатывается файл
  32.      *
  33.      * @return TorrentMeta
  34.      */
  35.     public function __construct($metaFrom='',$useString=false){
  36.             if ( $useString ){
  37.                     $this->meta = TorrentMeta::parseByteString($metaFrom);
  38.             }elseif($metaFrom){
  39.                     $this->file = $metaFrom;
  40.                     if ( $metaFrom ){
  41.                             $this->parseMetaFile($metaFrom);
  42.                     }
  43.             }
  44.     }
  45.     /**
  46.      * Возвращает код ошибки
  47.      *
  48.      * @return int - код ошибки
  49.      */
  50.     public function getErrorCode(){
  51.             return $this->errorCode;
  52.     }
  53.     /**
  54.      * Возвращает мета-данные файла или строки
  55.      *
  56.      * @return array - мета-данные
  57.      */
  58.     public function getMetaInfo(){
  59.             return $this->meta;
  60.     }
  61.     /**
  62.      * Возвращает хэш торрента
  63.      *
  64.      * @param bool $returnHexVal - Если TRUE, возвращает хэш в виде hex-строки. Если FALSE - в виде двоичной строки
  65.      * @return string
  66.      */
  67.     public function getHash($returnHexVal=false){
  68.         return $returnHexVal ? bin2hex($this->meta['info_hash']) : $this->meta['info_hash'];
  69.     }
  70.     /**
  71.      * Обрабатывает файл и устанавливает свойство meta объекта согласно структуре данных
  72.      *
  73.      * @param string $file - путь к файлу
  74.      * @return bool - TRUE, если обработка удалась, FALSE иначе.
  75.      */
  76.     protected function parseMetaFile($file){
  77.         if ( file_exists($file) ){
  78.             $this->meta = TorrentMeta::parseByteString(file_get_contents($file));
  79.             if( !empty($this->meta) ){
  80.                     $this->meta['pieces_array'] = $this->parsePiecesHashes();
  81.             $this->meta['total_size'] = 0;
  82.             if ( isset($this->meta['info']['files']) ){
  83.                 for( $i=0;$i<count($this->meta['info']['files']);$i++ )
  84.                     $this->meta['total_size'] += $this->meta['info']['files'][$i]['length'];
  85.             }else
  86.                 $this->meta['total_size'] = $this->meta['info']['length'];
  87.             }
  88.         }else
  89.             $this->Error(TORRENTMETA_ERROR_NO_INPUT_FILE);
  90.         return false;
  91.     }
  92.     /**
  93.      * Обрабатывает строку частей торрента-файла и разбивает её на хэши частей
  94.      *
  95.      * @return array|bool - Массив хэшей, если разбивка удалась, FALSE иначе
  96.      */
  97.     protected function parsePiecesHashes(){
  98.         if ( !empty($this->meta['info']['pieces']) ){
  99.             $pieces = array();
  100.             $pieces_str = bin2hex($this->meta['info']['pieces']);
  101.             $len = strlen($pieces_str);
  102.             for( $offset=0;$offset<$len;$offset+=40 ){
  103.                 $pieces[] = substr($pieces_str,$offset,40);
  104.             }
  105.             return $pieces;
  106.         }
  107.         return false;
  108.     }
  109.     /**
  110.      * Обрабатывает byte-строку с целью получения структурированных данных
  111.      *
  112.      * @static
  113.      * @param string $string - строка для обработки
  114.      * @return array - массив данных
  115.      */
  116.     public static function parseByteString($string){
  117.         $data = array();
  118.         TorrentMeta::parseByteStringRecursive($string,0,$data);
  119.         return $data;
  120.     }
  121.     /**
  122.      * Рекурсивно обрабатывает byte-строку
  123.      *
  124.      * @static
  125.      * @param string $string - строка для обработки
  126.      * @param int $offset - отступ от начала строки
  127.      * @param array $data - массив данных
  128.      * @return int - длина обработаной части строки
  129.      */
  130.     protected static function parseByteStringRecursive($string,$offset,&$data){
  131.         $modifier = substr($string,$offset,1);
  132.         $len = strlen($string);
  133.         if ( (string)intval($modifier)===$modifier ){
  134.             $pos = strpos($string,':',$offset);
  135.             $length = intval(substr($string,$offset,$pos-$offset));
  136.             $data = substr($string,$pos+1,$length);
  137.             $offset = $pos+1+$length;
  138.         }else{
  139.             $offset++;
  140.             switch ($modifier){
  141.                 case 'd':
  142.                     $data = array();
  143.                     do{
  144.                         $key = '';
  145.                         $offset = TorrentMeta::parseByteStringRecursive($string,$offset,$key);
  146.                         if ( $offset>=$len )
  147.                                 break;
  148.                         $value = '';
  149.                         $offset_new = TorrentMeta::parseByteStringRecursive($string,$offset,$value);
  150.                         if ( $key=='info' ){
  151.                             $toHash = substr($string,$offset,$offset_new-$offset);
  152.                             $data['info_hash'] = sha1($toHash,true);
  153.                         }
  154.                         $offset = $offset_new;
  155.                         $data[$key] = $value;
  156.                     }while( substr($string,$offset,1)!='e' && $offset<$len );
  157.                     $offset++;
  158.                 break;
  159.                 case 'l':
  160.                     $data = array();
  161.                     do{
  162.                         $value = '';
  163.                         $offset = TorrentMeta::parseByteStringRecursive($string,$offset,$value);
  164.                         $data[] = $value;
  165.                     }while( substr($string,$offset,1)!='e' && $offset<$len );
  166.                     return $offset+1;
  167.                 break;
  168.                 case 'i':
  169.                     $pos = strpos($string,'e',$offset);
  170.                     $data = intval(substr($string,$offset,$pos-$offset));
  171.                     return $pos+1;
  172.                 break;
  173.             }
  174.         }
  175.         return $offset;
  176.     }
  177.     /**
  178.      * Устанавливает ошибку
  179.      *
  180.      * @param int $errorCode  - код ошибки
  181.      */
  182.     protected function Error($errorCode){
  183.             $this->errorCode = $errorCode;
  184.     }
  185.    
  186. }
  187. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement