Advertisement
Guest User

bencode

a guest
Sep 28th, 2011
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 7.12 KB | None | 0 0
  1. <?php
  2. /*
  3. TorrentEditor.com API - Simple API to modify torrents
  4. Copyright (C) 2009  Tyler Alvord
  5.  
  6. Web: http://torrenteditor.com
  7. IRC: #torrenteditor.com on efnet.org  
  8.  
  9. This program is free software: you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation, either version 3 of the License, or
  12. (at your option) any later version.
  13.  
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21. */
  22.  
  23. class BEncode
  24. {
  25.     public static function &decode( &$raw, &$offset=0 )
  26.     {  
  27.         if ( $offset >= strlen( $raw ) )
  28.         {
  29.             return new BEncode_Error( "Decoder exceeded max length." ) ;
  30.         }
  31.        
  32.         $char = $raw[$offset];
  33.         switch ( $char )
  34.         {
  35.             case 'i':
  36.                 $int = new BEncode_Int();
  37.                 $int->decode( $raw, $offset );
  38.                 return $int;
  39.                
  40.             case 'd':
  41.                 $dict = new BEncode_Dictionary();
  42.  
  43.                 if ( $check = $dict->decode( $raw, $offset ) )
  44.                 {
  45.                     return $check;
  46.                 }
  47.                 return $dict;
  48.                
  49.             case 'l':
  50.                 $list = new BEncode_List();
  51.                 $list->decode( $raw, $offset );
  52.                 return $list;
  53.                
  54.             case 'e':
  55.                 return new BEncode_End();
  56.                
  57.             case '0':
  58.             case is_numeric( $char ):
  59.                 $str = new BEncode_String();
  60.                 $str->decode( $raw, $offset );
  61.                 return $str;
  62.  
  63.             default:
  64.                 return new BEncode_Error( "Decoder encountered unknown char '$char' at offset $offset." );
  65.         }
  66.     }
  67. }
  68.  
  69. class BEncode_End
  70. {
  71.     public function get_type()
  72.     {
  73.         return 'end';
  74.     }
  75. }
  76.  
  77. class BEncode_Error
  78. {
  79.     private $error;
  80.    
  81.     public function BEncode_Error( $error )
  82.     {
  83.         $this->error = $error;
  84.     }
  85.    
  86.     public function get_plain()
  87.     {
  88.         return $this->error;
  89.     }
  90.    
  91.     public function get_type()
  92.     {
  93.         return 'error';
  94.     }
  95. }
  96.  
  97. class BEncode_Int
  98. {
  99.     private $value;
  100.    
  101.     public function BEncode_Int( $value = null )
  102.     {
  103.         $this->value = $value;
  104.     }
  105.  
  106.     public function decode( &$raw, &$offset )
  107.     {
  108.             $end = strpos( $raw, 'e', $offset );
  109.             $this->value = substr( $raw, ++$offset, $end - $offset );
  110.             $offset += ( $end - $offset );
  111.     }
  112.  
  113.     public function get_plain()
  114.     {
  115.         return $this->value;
  116.     }
  117.  
  118.     public function get_type()
  119.     {
  120.         return 'int';
  121.     }
  122.    
  123.     public function encode()
  124.     {
  125.         return "i{$this->value}e";
  126.     }
  127.    
  128.     public function set( $value )
  129.     {
  130.         $this->value = $value;
  131.     }
  132. }
  133.  
  134. class BEncode_Dictionary
  135. {
  136.     public $value = array();
  137.    
  138.     public function decode( &$raw, &$offset )
  139.     {
  140.             $dictionary = array();
  141.  
  142.             while ( true )
  143.             {
  144.                 $name = BEncode::decode( $raw, ++$offset );
  145.  
  146.                 if ( $name->get_type() == 'end' )
  147.                 {
  148.                     break;
  149.                 }
  150.                 else if ( $name->get_type() == 'error' )
  151.                 {
  152.                     return $name;
  153.                 }
  154.                 else if ( $name->get_type() != 'string' )
  155.                 {
  156.                     return new BEncode_Error( "Key name in dictionary was not a string." );
  157.                 }
  158.  
  159.                 $value = BEncode::decode( $raw, ++$offset );
  160.  
  161.                 if ( $value->get_type() == 'error' )
  162.                 {
  163.                     return $value;
  164.                 }
  165.  
  166.                 $dictionary[$name->get_plain()] = $value;
  167.             }
  168.  
  169.             $this->value = $dictionary;
  170.     }
  171.    
  172.     public function get_value( $key )
  173.     {
  174.         if ( isset( $this->value[$key] ) )
  175.         {
  176.             return $this->value[$key];
  177.         }
  178.         else
  179.         {
  180.             return null;
  181.         }
  182.     }
  183.    
  184.     public function encode()
  185.     {
  186.         $this->sort();
  187.  
  188.         $encoded = 'd';
  189.         while ( list( $key, $value ) = each( $this->value ) )
  190.         {
  191.             $bstr = new BEncode_String();
  192.             $bstr->set( $key );
  193.             $encoded .= $bstr->encode();
  194.             $encoded .= $value->encode();
  195.         }
  196.         $encoded .= 'e';
  197.         return $encoded;
  198.     }
  199.  
  200.     public function get_type()
  201.     {
  202.         return 'dictionary';
  203.     }
  204.    
  205.     public function remove( $key )
  206.     {
  207.         unset( $this->value[$key] );
  208.     }
  209.    
  210.     public function set( $key, $value )
  211.     {
  212.         $this->value[$key] = $value;
  213.     }
  214.    
  215.     private function sort()
  216.     {
  217.         ksort( $this->value );
  218.     }
  219.    
  220.     public function count()
  221.     {
  222.         return count( $this->value );
  223.     }
  224. }
  225.  
  226. class BEncode_List
  227. {
  228.     private $value = array();
  229.    
  230.     public function add( $bval )
  231.     {
  232.         array_push( $this->value, $bval );
  233.     }
  234.  
  235.     public function decode( &$raw, &$offset )
  236.     {
  237.             $list = array();
  238.  
  239.             while ( true )
  240.             {
  241.                 $value = BEncode::decode( $raw, ++$offset );
  242.  
  243.                 if ( $value->get_type() == 'end' )
  244.                 {
  245.                     break;
  246.                 }
  247.                 else if ( $value->get_type() == 'error' )
  248.                 {
  249.                     return $value;
  250.                 }
  251.                 array_push( $list, $value );
  252.             }
  253.  
  254.             $this->value = $list;
  255.     }
  256.    
  257.     public function encode()
  258.     {
  259.         $encoded = 'l';
  260.        
  261.         for ( $i = 0; $i < count( $this->value ); ++$i )
  262.         {
  263.             $encoded .= $this->value[$i]->encode();
  264.         }
  265.         $encoded .= 'e';
  266.         return $encoded;
  267.     }
  268.    
  269.     public function get_plain()
  270.     {
  271.         return $this->value;
  272.     }
  273.  
  274.     public function get_type()
  275.     {
  276.         return 'list';
  277.     }
  278. }
  279.  
  280. class BEncode_String
  281. {
  282.     private $value;
  283.    
  284.     public function BEncode_String( $value = null )
  285.     {
  286.         $this->value = $value;
  287.     }
  288.    
  289.     public function decode( &$raw, &$offset )
  290.     {
  291.             $end = strpos( $raw, ':', $offset );
  292.             $len = substr( $raw, $offset, $end - $offset );
  293.             $offset += ($len + ($end - $offset));
  294.             $end++;
  295.             $this->value = substr( $raw, $end, $len );
  296.     }
  297.    
  298.     public function get_plain()
  299.     {
  300.         return $this->value;
  301.     }
  302.    
  303.     public function get_type()
  304.     {
  305.         return 'string';
  306.     }
  307.    
  308.     public function encode()
  309.     {
  310.         $len = strlen( $this->value );
  311.         return  "$len:{$this->value}";
  312.     }
  313.    
  314.     public function set( $value )
  315.     {
  316.         $this->value = $value;
  317.     }
  318. }
  319.  
  320. ?>
  321.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement