PHP模块,用于读取种子文件
时间:2020-03-06 15:04:43 来源:igfitidea点击:
是否有一个PHP模块可用于以编程方式读取种子文件以查找有关种子的信息(例如,Seeders)?
解决方案
Google在sourceforge上提供了此PHP客户端,在PHP类上提供了该torrent类。应该是我们所需要的。
种子文件基本上是用BEncode编码的嵌套字典。 BEncode是一种简单的编码,并且有一些BDecode PHP类,例如此类。
种子文件的结构在BEP0003中进行了描述。
请注意,种子文件不包含我们提到的"播种者"字段。播种机列表是动态的,由跟踪服务器进行管理。有了torrent的hash_info
和tracker_url
(两者都可以从torrent文件中获得),我们可以将scrape-request发送到跟踪器,它将在'complete'字段中返回播种机的数量,请参阅Tracker Scrape Convention。
我曾经在一个小型网站上使用过这些功能。想想我是用一个名为OpenTracker的php bittorrent跟踪器找到它们的,但是找不到该网站...
不过,我们不会在torrent文件中找到播种机。种子文件仅包含有关文件,哈希码和长度等的信息。还有一些我相信的跟踪器信息。我们必须从跟踪器中获得多少个播种机等等。我们可以在BitTorrent.org上阅读有关该协议的信息。我认为通信是经过编码的,因此我们也可以使用这些功能。这意味着我们只需要弄清楚要发送的内容就可以得到想要的东西。
注意:我没有编写这三个函数。就像我说的,我是在一个开源洪流跟踪器的源代码中找到它们的。这些函数没有注释,但是在我们知道种子文件的结果之后,函数名称和print_r一起就足以理解该如何使用它们。我在底部添加了一些示例代码以展示如何使用它们。他们工作了。
function bdecode($str) { $pos = 0; return bdecode_r($str, $pos); } function bdecode_r($str, &$pos) { $strlen = strlen($str); if (($pos < 0) || ($pos >= $strlen)) { return null; } else if ($str{$pos} == 'i') { $pos++; $numlen = strspn($str, '-0123456789', $pos); $spos = $pos; $pos += $numlen; if (($pos >= $strlen) || ($str{$pos} != 'e')) { return null; } else { $pos++; return intval(substr($str, $spos, $numlen)); } } else if ($str{$pos} == 'd') { $pos++; $ret = array(); while ($pos < $strlen) { if ($str{$pos} == 'e') { $pos++; return $ret; } else { $key = bdecode_r($str, $pos); if ($key == null) { return null; } else { $val = bdecode_r($str, $pos); if ($val == null) { return null; } else if (!is_array($key)) { $ret[$key] = $val; } } } } return null; } else if ($str{$pos} == 'l') { $pos++; $ret = array(); while ($pos < $strlen) { if ($str{$pos} == 'e') { $pos++; return $ret; } else { $val = bdecode_r($str, $pos); if ($val == null) { return null; } else { $ret[] = $val; } } } return null; } else { $numlen = strspn($str, '0123456789', $pos); $spos = $pos; $pos += $numlen; if (($pos >= $strlen) || ($str{$pos} != ':')) { return null; } else { $vallen = intval(substr($str, $spos, $numlen)); $pos++; $val = substr($str, $pos, $vallen); if (strlen($val) != $vallen) { return null; } else { $pos += $vallen; return $val; } } } } function bencode($var) { if (is_int($var)) { return 'i' . $var . 'e'; } else if (is_array($var)) { if (count($var) == 0) { return 'de'; } else { $assoc = false; foreach ($var as $key => $val) { if (!is_int($key)) { $assoc = true; break; } } if ($assoc) { ksort($var, SORT_REGULAR); $ret = 'd'; foreach ($var as $key => $val) { $ret .= bencode($key) . bencode($val); } return $ret . 'e'; } else { $ret = 'l'; foreach ($var as $val) { $ret .= bencode($val); } return $ret . 'e'; } } } else { return strlen($var) . ':' . $var; } }
一些示例用法:
# Read a file $content = file_get_contents("file.torrent"); $content_d = bdecode($content); # Check if bdecode succeeded if(empty($content_d)) exit('Something is wrong with the torrent. BDecode failed.'); # Calculate info_hash $info_hash = sha1(bencode($content_d['info']), true); # Calculate length $length = 0; function add_length($value, $key) { global $length; if($key == 'length') $length += $value; } array_walk_recursive($content_d, 'add_length');