Bakhritdinov

functions.benc.php

Jan 6th, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2.  
  3. /**
  4.  * Converts String to Hex
  5.  * @param string $string String to be converted
  6.  * @return string Converted string
  7.  */
  8. function hex($string){
  9.     $hex='';
  10.     for ($i=0; $i < strlen($string); $i++){
  11.         $hex .= dechex(ord($string[$i]));
  12.     }
  13.     return $hex;
  14. }
  15.  
  16. /**
  17.  * Makes magnet link e.g. instead of downloading .torrent
  18.  * @param string $info_hash SHA1 infohash
  19.  * @param string $filename Name to display
  20.  * @param string|array $trackers Announce url or array of announce-urls of trackers
  21.  * @return string
  22.  */
  23. function make_magnet($info_hash,$filename,$trackers){
  24.     if (is_array($trackers)) $trackers = implode('&tr=',array_map('urlencode',$trackers)); else $trackers = urlencode($trackers);
  25.     return 'magnet:?xt=urn:btih:'.$info_hash.'&dn='.urlencode($filename).'&tr='.$trackers;
  26.  
  27. }
  28.  
  29.  
  30.  
  31. /**
  32.  * Makes magnet link to a DChub
  33.  * @param string $tiger_hash TIGER infohash
  34.  * @param string $filename Name to display
  35.  * @param int $filesize Filesize in bytes
  36.  * @param string|array $trackers Announce url or array of announce-urls of trackers
  37.  * @return string
  38.  */
  39. function make_dc_magnet($tiger_hash,$filename,$filesize,$hubs){
  40.     if (is_array($hubs)) $hubs = implode('&xs=',array_map('urlencode',$hubs)); else $hubs = urlencode($hubs);
  41.     return 'magnet:?xt=urn:tree:tiger:'.$tiger_hash.'&xl='.$filesize.'&dn='.urlencode($filename).'&xs='.$hubs;
  42.  
  43. }
  44.  
  45.  
  46. /**
  47.  * Gets available retrackers (DChubs, and other stuff) by user's ip
  48.  * @param boolean $all Get All Retrackers, ignoring subnet mask default false
  49.  * @param string $table Table used to get stuff
  50.  * @return array Array of retrackers or empty array if no retrackers present
  51.  */
  52. function get_retrackers($all = false, $table = 'retrackers') {
  53.     // global $IPCHECK;
  54.     global $db;
  55.     $ip = getip();
  56.     $row = $db->query("SELECT announce_url, mask FROM $table ORDER BY sort ASC");
  57.     while ($res = $db->get_row() ) { $rtarray[] = $res; if ($all) $return[] = $res['announce_url']; }
  58.  
  59.     if (!$rtarray) return array();
  60.  
  61.     if ($all) return $return;
  62.  
  63.     foreach ($rtarray as $retracker) {
  64.        
  65.         if (!empty($retracker['mask'])) {
  66.             $RTCHECK = new IPAddressSubnetSniffer(array($retracker['mask']));
  67.  
  68.             if ($RTCHECK->ip_is_allowed($ip)) $retrackers[] = $retracker['announce_url'];
  69.         }
  70.         else $retrackers[] = $retracker['announce_url'];
  71.         // $retrackers[] = $retracker['announce_url'];
  72.     }
  73.  
  74.     if ($retrackers) return $retrackers; else return array();
  75. }
  76.  
  77. /**
  78.  * Gets dictionary value
  79.  * @param array $d torrent dictionary
  80.  * @param string $k dictionary key
  81.  * @param string $t value type
  82.  * @return void|multiple Return value
  83.  * @see bdec_dict()
  84.  */
  85. function dict_get($d, $k, $t) {
  86.     if ($d["type"] != "dictionary")
  87.     err("not a dictionary");
  88.     $dd = $d["value"];
  89.     if (!isset($dd[$k]))
  90.     return;
  91.     $v = $dd[$k];
  92.     if ($v["type"] != $t)
  93.     err("invalid dictionary entry type");
  94.     return $v["value"];
  95. }
  96.  
  97. /**
  98.  * Check that dicitionary is valid
  99.  * @param array $d Dictionary
  100.  * @param string $s Undocumented
  101.  * @return Ambigous <multitype:, unknown> Undocumented
  102.  */
  103. function dict_check($d, $s) {
  104.     if ($d["type"] != "dictionary")
  105.     err("not a dictionary");
  106.     $a = explode(":", $s);
  107.     $dd = $d["value"];
  108.     $ret = array();
  109.     foreach ($a as $k) {
  110.         unset($t);
  111.         if (preg_match('/^(.*)\((.*)\)$/', $k, $m)) {
  112.             $k = $m[1];
  113.             $t = $m[2];
  114.         }
  115.         if (!isset($dd[$k]))
  116.         err("dictionary is missing key(s)");
  117.         if (isset($t)) {
  118.             if ($dd[$k]["type"] != $t)
  119.             err("invalid entry in dictionary");
  120.             $ret[] = $dd[$k]["value"];
  121.         }
  122.         else
  123.         $ret[] = $dd[$k];
  124.     }
  125.     return $ret;
  126. }
  127.  
  128. /**
  129.  * Binary encodes an value
  130.  * @param mixed $obj Value to be encoded
  131.  * @return string Encoded value
  132.  * @see benc_str()
  133.  * @see benc_int()
  134.  * @see benc_list()
  135.  * @see benc_dict()
  136.  */
  137. function benc($obj) {
  138.     if (!is_array($obj) || !isset($obj["type"]) || !isset($obj["value"]))
  139.     return;
  140.     $c = $obj["value"];
  141.     switch ($obj["type"]) {
  142.         case "string":
  143.             return benc_str($c);
  144.         case "integer":
  145.             return benc_int($c);
  146.         case "list":
  147.             return benc_list($c);
  148.         case "dictionary":
  149.             return benc_dict($c);
  150.         default:
  151.             return;
  152.     }
  153. }
  154. /**
  155.  * Binary encodes a string
  156.  * @param string $s String to be encoded
  157.  * @return string Encoded string
  158.  */
  159. function benc_str($s) {
  160.     return strlen($s) . ":$s";
  161. }
  162. /**
  163.  * Binary encodes an integer
  164.  * @param int $i Integer to be encoded
  165.  * @return string Encoded Integer
  166.  */
  167. function benc_int($i) {
  168.     return "i" . $i . "e";
  169. }
  170. /**
  171.  * Binary encodes a list
  172.  * @param array $a List to be encoded
  173.  * @return string Encoded list
  174.  */
  175. function benc_list($a) {
  176.     $s = "l";
  177.     foreach ($a as $e) {
  178.         $s .= benc($e);
  179.     }
  180.     $s .= "e";
  181.     return $s;
  182. }
  183.  
  184. /**
  185.  * Binary encodes a dictionary
  186.  * @param array $d Dictionary to be encoded
  187.  * @return string Encoded dictionary
  188.  * @see benc() benc_str()
  189.  */
  190. function benc_dict($d) {
  191.     $s = "d";
  192.     $keys = array_keys($d);
  193.     sort($keys);
  194.     foreach ($keys as $k) {
  195.         $v = $d[$k];
  196.         $s .= benc_str($k);
  197.         $s .= benc($v);
  198.     }
  199.     $s .= "e";
  200.     return $s;
  201. }
  202. /**
  203.  * Binary decodes a torrent file
  204.  * @param string $f File path to be decoded
  205.  * @return array Decoded file
  206.  * @see bdec()
  207.  */
  208. function bdec_file($f, $ms) {
  209.     $fp = fopen($f, "rb");
  210.  
  211.     if (!$fp)
  212.         return;
  213.     $e = fread($fp, $ms);
  214.     fclose($fp);
  215.     return bdec($e);
  216. }
  217. /**
  218.  * Binary decodes a Value
  219.  * @param string $s Value to be decoded
  220.  * @return array Decoded value
  221.  */
  222. function bdec($s) {
  223.     if (preg_match('/^(\d+):/', $s, $m)) {
  224.         $l = $m[1];
  225.         $pl = strlen($l) + 1;
  226.         $v = substr($s, $pl, $l);
  227.         $ss = substr($s, 0, $pl + $l);
  228.         if (strlen($v) != $l) return;
  229.         return array('type' => "string", 'value' => $v, 'strlen' => strlen($ss), 'string' => $ss);
  230.     }
  231.     if (preg_match('/^i(\d+)e/', $s, $m)) {
  232.         $v = $m[1];
  233.         $ss = "i" . $v . "e";
  234.         if ($v === "-0")
  235.         return;
  236.         if ($v[0] == "0" && strlen($v) != 1)
  237.         return;
  238.         return array('type' => "integer", 'value' => $v, 'strlen' => strlen($ss), 'string' => $ss);
  239.     }
  240.     switch ($s[0]) {
  241.         case "l":
  242.             return bdec_list($s);
  243.         case "d":
  244.             return bdec_dict($s);
  245.         default:
  246.             return;
  247.     }
  248. }
  249. /**
  250.  * Binary decodes a list
  251.  * @param string $s List to be decoded
  252.  * @return array Decoded list
  253.  */
  254. function bdec_list($s) {
  255.     if ($s[0] != "l")
  256.     return;
  257.     $sl = strlen($s);
  258.     $i = 1;
  259.     $v = array();
  260.     $ss = "l";
  261.     for (;;) {
  262.         if ($i >= $sl)
  263.         return;
  264.         if ($s[$i] == "e")
  265.         break;
  266.         $ret = bdec(substr($s, $i));
  267.         if (!isset($ret) || !is_array($ret))
  268.         return;
  269.         $v[] = $ret;
  270.         $i += $ret["strlen"];
  271.         $ss .= $ret["string"];
  272.     }
  273.     $ss .= "e";
  274.     return array('type' => "list", 'value' => $v, 'strlen' => strlen($ss), 'string' => $ss);
  275. }
  276. /**
  277.  * Binary decodes a dictionary
  278.  * @param string $s Dictionary to be decoded
  279.  * @return array Decoded dictionary
  280.  */
  281. function bdec_dict($s) {
  282.     if ($s[0] != "d")
  283.     return;
  284.     $sl = strlen($s);
  285.     $i = 1;
  286.     $v = array();
  287.     $ss = "d";
  288.     for (;;) {
  289.         if ($i >= $sl)
  290.         return;
  291.         if ($s[$i] == "e")
  292.         break;
  293.         $ret = bdec(substr($s, $i));
  294.         if (!isset($ret) || !is_array($ret) || $ret["type"] != "string")
  295.         return;
  296.         $k = $ret["value"];
  297.         $i += $ret["strlen"];
  298.         $ss .= $ret["string"];
  299.         if ($i >= $sl)
  300.         return;
  301.         $ret = bdec(substr($s, $i));
  302.         if (!isset($ret) || !is_array($ret))
  303.         return;
  304.         $v[$k] = $ret;
  305.         $i += $ret["strlen"];
  306.         $ss .= $ret["string"];
  307.     }
  308.     $ss .= "e";
  309.     return array('type' => "dictionary", 'value' => $v, 'strlen' => strlen($ss), 'string' => $ss);
  310. }
  311.  
  312. /**
  313.  * Gets announce urls from DECODED torrent dicrionary
  314.  * @param array $dict Decoded torrent dictionary
  315.  * @return array|boolean Array of urls on success, false on fail
  316.  */
  317. function get_announce_urls($dict){
  318.     if ($dict['value']['announce'] && !$dict['value']['announce-list']) {$anarray[0] = $dict['value']['announce']['value']; return $anarray; }
  319.  
  320.     if ($dict['value']['announce-list']) {
  321.  
  322.         if (!$dict['value']['announce-list']['value']) return false;
  323.         $retrackers = get_retrackers(true);
  324.         foreach ($dict['value']['announce-list']['value'] as $urls) {
  325.             if (!in_array($urls['value'][0]['value'],$retrackers))
  326.             $anarray[] = $urls['value'][0]['value'];
  327.         }
  328.  
  329.         return $anarray;
  330.  
  331.     }
  332. }
  333.  
  334. /**
  335.  * Puts announce urls into DECODED dictionary. DICT is global.
  336.  * @param array $dict Decoded dictionary to be processed
  337.  * @param array $anarray Array of announce urls. First element good to be a local announce-url
  338.  * @return void Uses global $dict
  339.  */
  340. function put_announce_urls($dict,$anarray){
  341.     global $dict;
  342.     $liststring = '';
  343.     unset($dict['value']['announce']);
  344.     unset($dict['value']['announce-list']);
  345.     $dict['value']['announce'] = bdec(benc_str($anarray[0]));
  346.  
  347.  
  348.     if (is_array($anarray))
  349.     foreach ($anarray as $announce) {
  350.         $announces[] = array('type' => 'list', 'value' => array(bdec(benc_str($announce))), 'strlen' => strlen("l".$announce."e"), 'string' => "l".$announce."e");
  351.         $liststring .= "l".$announce."e";
  352.     }
  353.     $dict['value']['announce-list']['type'] = 'list';
  354.     $dict['value']['announce-list']['value'] = $announces;
  355.  
  356.  
  357.     $dict['value']['announce-list']['string'] = "l".$liststring."e";
  358.     $dict['value']['announce-list']['strlen'] = strlen($dict['value']['announce-list']['string']);
  359.  
  360. }
  361.  
  362. /**
  363.  * Gets port from adress
  364.  * @param string $urlInfo URL to be parsed
  365.  * @return int Port
  366.  */
  367. function getUrlPort($urlInfo) {
  368.     if( isset($urlInfo['port']) ) {
  369.         $port = $urlInfo['port'];
  370.     } else { // no port specified; get default port
  371.         if (isset($urlInfo['scheme'])) {
  372.             switch($urlInfo['scheme']) {
  373.                 case 'http':
  374.                     $port = 80; // default for http
  375.                     break;
  376.                 case 'https':
  377.                     $port = 443; // default for https
  378.                     break;
  379.                 default:
  380.                     $port = 0; // error; unsupported scheme
  381.                     break;
  382.             }
  383.         } else {
  384.             $port = 80; // error; unknown scheme, using default 80 port
  385.         }
  386.     }
  387.     return $port;
  388. }
  389.  
  390. /**
  391.  * Checks that tracker returns failed event.
  392.  * @param string $result Bencoded result to be parsed
  393.  * @return string String to be used in remote tracker statistics
  394.  */
  395. function check_fail($result) {
  396.     if ($result['value']['failure reason']['value']) return 'failed:'.$result['value']['failure reason']['value'].'_'; else return 'ok_';
  397. }
  398.  
  399. /**
  400.  * Gets amout of remote tracker peers. May be recursivity.
  401.  * @param string $url Announce url of request
  402.  * @param string $info_hash Info-hash of torrent to be parsed
  403.  * @param string $method Method of gathering amount of peers. May be scrape or announce. Default 'scrape'. If scrape fails, recursivety swithes to announce and executes again.
  404.  * @return array Result array ('tracker','seeders','leechers','state');
  405.  */
  406. function get_remote_peers($url, $info_hash, $method = 'scrape') {
  407.     global $CRON;
  408.     if ($method == "announce") {
  409.         $get_params = array(
  410.                 "info_hash" => pack("H*", $info_hash),
  411.                 "peer_id" => "-UT1820-5dmPcUOYGnrx",
  412.                 "port" => rand(10000, 65535),
  413.                 "uploaded" => 0,
  414.                 "no_peer_id" => 1,
  415.                 "downloaded" => 0,
  416.                 "compact" => 1,
  417.                 "left" => 1,
  418.                 "numwant" => 9999
  419.         );
  420.     } else {
  421.         $urlorig=$url;
  422.         $url = str_replace('announce', 'scrape', $url);
  423.         $get_params = array(
  424.                 "info_hash" => pack("H*", $info_hash)
  425.         );
  426.     }
  427.  
  428.  
  429.     $urlInfo = @parse_url($url);
  430.     $http_host = $urlInfo['host'];
  431.     $http_port = getUrlPort($urlInfo);
  432.  
  433.     if ($http_port === 0)
  434.     return array('tracker' => $http_host, 'state' => 'failed:no_port_detected_'.$method);
  435.     else
  436.     $http_port = ':' . $http_port;
  437.  
  438.     $http_path = $urlInfo['path'];
  439.     $get_request_params = explode('&', $urlInfo['query']);
  440.  
  441.     foreach (array_filter($get_request_params) as $array_value) {
  442.         list($key, $value) = explode('=', $array_value);
  443.         $new_get_request_params[$key] = $value;
  444.     }
  445.  
  446.     if (!$new_get_request_params) $new_get_request_params=array();
  447.     // Params gathering complete
  448.  
  449.     // Creating params
  450.     $http_params = @http_build_query(@array_merge($new_get_request_params, $get_params));
  451.  
  452.     $opts = array('http' =>
  453.     array(
  454.         'method' => 'GET',
  455.         'header' => 'User-Agent: uTorrent/1820',
  456.         'timeout' => $CRON['multi_timeout']
  457.     //'Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2',
  458.     )
  459.     );
  460.  
  461.     $context = @stream_context_create($opts);
  462.     $result = @file_get_contents('http://'.$http_host.$http_port.$http_path.($http_params ? '?'.$http_params : ''), false, $context);
  463.     // $result = true;
  464.     if (!$result)
  465.     {
  466.         if ($method=='scrape')
  467.         return get_remote_peers($urlorig, $info_hash, "announce"); else
  468.         return array('tracker' => $http_host, 'state' => 'failed:no_benc_result_or_timeout_'.$method);
  469.  
  470.     }
  471.  
  472.  
  473.     //var_dump($method);
  474.     $resulttemp=$result;
  475.     $result = @bdec($result);
  476.  
  477.     if (!is_array($result)) return array('tracker' => $http_host, 'state' => 'failed:unable_to_bdec:'.$resulttemp.'_'.$method);
  478.     unset($resulttemp);
  479.     //    print('<pre>'); var_dump($result);
  480.     if ($method == 'scrape') {
  481.  
  482.         if ($result['value']['files']['value']) {
  483.             $peersarray = @array_shift($result['value']['files']['value']);
  484.             return array('tracker' => $http_host, 'seeders' => $peersarray['value']['complete']['value'], 'leechers' => $peersarray['value']['incomplete']['value'], 'state' => check_fail($result).$method);
  485.         } else return get_remote_peers($urlorig, $info_hash, "announce");
  486.     }
  487.  
  488.     if($method == 'announce') {
  489.         return array('tracker' => $http_host, 'seeders' => (is_array($result['value']['peers']['value'])?count($result['value']['peers']['value']):(strlen($result['value']['peers']['value'])/6)), 'leechers' => 0, 'state'=> check_fail($result).$method);
  490.     }
  491.  
  492. }
  493.  
  494. ?>
Advertisement
Add Comment
Please, Sign In to add comment