SHOW:
|
|
- or go back to the newest paste.
1 | <?php | |
2 | - | //Подключаем главный системный файл |
2 | + | |
3 | - | require 'functions.benc.php'; |
3 | + | /** |
4 | * Converts String to Hex | |
5 | - | $dict = bdec_file('test.torrent', (1024 * 1024) ); |
5 | + | * @param string $string String to be converted |
6 | * @return string Converted string | |
7 | - | $v = $dict['value']['info']['value']['name']['value']; |
7 | + | */ |
8 | function hex($string){ | |
9 | - | print_r($dict); |
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 | ?> |