存档

文章标签 ‘种子’

网上整理的torrent种子文件php批量解析类

2021年5月14日 评论已被关闭

在网上综合了一些torrent种子文件解析类,用php来批量解析,然后得到部分解析结果,自己整理了一个类,可以自行拿去,下面是类文件:torrent.class.php

<?php
class xBEncoder{
	const READY=0;
	const READ_STR=1;
	const READ_DICT=2;
	const READ_LIST=3;
	const READ_INT=4;
	const READ_KEY=5;
	public $y;
	protected $z,$m,$n;
	protected $stat;
	protected $stack;
	protected function push($newY,$newStat){
		array_push($this->stack,array($this->y,$this->z,$this->m,$this->n,$this->stat));
		list($this->y,$this->z,$this->m,$this->n,$this->stat)=array($newY,0,0,0,$newStat);
	}
	protected function pop(){
		$t=array_pop($this->stack);
		if($t){
		if($t[4]==self::READ_DICT){
			$t[0]->{$t[1]}=$this->y;
			$t[1]=0;
		}
		elseif($t[4]==self::READ_LIST){$t[0][]=$this->y;}
			list($this->y,$this->z,$this->m,$this->n,$this->stat)=$t;
		}
	}
	public function object_array($array){ 
		if(is_object($array)){ 
			$array=(array)$array; 
		}
		if(is_array($array)){ 
			foreach($array as $key=>$value){ 
			$array[$key]=$this->object_array($value); 
			} 
		} 
		return $array; 
	}
	public function init(){
		$this->stat=self::READY;
		$this->stack=array();
		$this->z=$this->m=$this->n=0;
	}
	public function decode($s,$l){
		$this->y=0;
		for($i=0;$i<$l;++$i){
			switch($this->stat){
				case self::READY:
					if($s[$i]=='d'){
						$this->y=new xBDict();
						$this->stat=self::READ_DICT;
					}
					elseif($s[$i]=='l'){
						$this->y=array();
						$this->stat=self::READ_LIST;
					}
				break;
				case self::READ_INT:
					if($s[$i]=='e'){
						$this->y->val=substr($s,$this->m,$i-$this->m);
						$this->pop();
					}
				break;
				case self::READ_STR:
					if(xBInt::isNum($s[$i])){continue;}
					if($s[$i]=':'){
						$this->z=substr($s,$this->m,$i-$this->m);
						$this->y=substr($s,$i+1,$this->z+0);
						$i+=$this->z;
						$this->pop();
					}
				break;
				case self::READ_KEY:
					if(xBInt::isNum($s[$i])){continue;}
					if($s[$i]=':'){
						$this->n=substr($s,$this->m,$i-$this->m);
						$this->z=substr($s,$i+1,$this->n+0);
						$i+=$this->n;
						$this->stat=self::READ_DICT;
					}
				break;
				case self::READ_DICT:
					if($s[$i]=='e'){
						$this->pop();
						break;
					}
					elseif(!$this->z){
						$this->m=$i;
						$this->stat=self::READ_KEY;
						break;
					}
				case self::READ_LIST:
					switch($s[$i]){
						case 'e':
							$this->pop();
						break;
						case 'd':
							$this->push(new xBDict(),self::READ_DICT);
						break;
						case 'i':
							$this->push(new xBInt(),self::READ_INT);
							$this->m=$i+1;
						break;
						case 'l':
							$this->push(array(),self::READ_LIST);
						break;
						default:
							if(xBInt::isNum($s[$i])){
								$this->push('',self::READ_STR);
								$this->m=$i;
							}
						break;
					}
				break;
			}
		}
		$rtn=empty($this->stack);
		$this->init();
		return $rtn;
	}
	public function encode(){
		return $this->_encDo($this->y);
	}
	protected function _encStr($str){
		return strlen($str).':'.$str;
	}
	protected function _encDo($o){
		if(is_string($o)){return $this->_encStr($o);}
		if($o instanceof xBInt){return 'i'.$o->val.'e';}
		if($o instanceof xBDict){
			$r='d';
			foreach($o as $k=>$c){$r.=$this->_encStr($k).$this->_encDo($c);}
			return $r.'e';
		}
		if(is_array($o)){
			$r='l';
			foreach($o as $c){$r.=$this->_encDo($c);}
			return $r.'e';
		}
	}
}
class xBDict{}
class xBInt{
	public $val;
	public function __construct($val=0){
		$this->val=$val;
	}
	public static function isNum($chr){
		$chr=ord($chr);
		if($chr<=57 && $chr>=48){return true;}
		return false;
	}
}
class BDecode{
	function numberdecode($wholefile,$offset){
		$negative=false;
		if($wholefile[$offset]=='-'){
			$negative=true;
			$offset++;
		}
		if($wholefile[$offset]=='0'){
			$offset++;
			if($negative){return array(false);}
			if($wholefile[$offset]==':' || $wholefile[$offset]=='e'){return array(0,++$offset);}
			return array(false);
		}
		$ret[0]=0;
		for(;;){
			if($wholefile[$offset]>='0' && $wholefile[$offset]<='9'){
				$ret[0] *= 10;
				settype($ret[0],'double');
				$ret[0]+=ord($wholefile[$offset])-ord('0');
				$offset++;
			}
			else if($wholefile[$offset]=='e' || $wholefile[$offset]==':'){
				$ret[1]=$offset+1;
				if($negative){
					if($ret[0]==0){return array(false);}
					$ret[0]=-$ret[0];
				}
				return $ret;
			}
			else {return array(false);}
		}
	}
	function decodeEntry($wholefile,$offset=0){
		if($wholefile[$offset]=='d'){return $this->decodeDict($wholefile,$offset);}
		if($wholefile[$offset]=='l'){return $this->decodelist($wholefile,$offset);}
		if($wholefile[$offset]=='i'){return $this->numberdecode($wholefile, ++$offset);}
		$info=$this->numberdecode($wholefile,$offset);
		if($info[0]===false){return array(false);}
		$ret[0]=substr($wholefile,$info[1],$info[0]);
		$ret[1]=$info[1]+strlen($ret[0]);
		return $ret;
	}
	function decodeList($wholefile,$offset){
		if($wholefile[$offset]!='l'){return array(false);}
		$offset++;
		$ret=array();
		for($i=0;;$i++){
			if($wholefile[$offset]=='e'){break;}
			$value=$this->decodeEntry($wholefile,$offset);
			if($value[0]===false){return array(false);}
			$ret[$i]=$value[0];
			$offset=$value[1];
		}
		return array(0=>$ret,1=>++$offset);
	}
	function decodeDict($wholefile,$offset=0){
		if($wholefile[$offset]=='l'){return $this->decodeList($wholefile,$offset);}
		if($wholefile[$offset]!='d'){return false;}
		$ret=array();
		$offset++;
		for(;;){	
			if($wholefile[$offset]=='e'){
				$offset++;
				break;
			}
			$left=$this->decodeEntry($wholefile,$offset);
			if(!$left[0]){return false;}
			$offset=$left[1];
			if($wholefile[$offset]=='d'){
				$value=$this->decodedict($wholefile,$offset);
				if(!$value[0]){return false;}
				$ret[addslashes($left[0])]=$value[0];
				$offset=$value[1];
				continue;
			}
			if($wholefile[$offset]=='l'){
				$value=$this->decodeList($wholefile,$offset);
				if(!$value[0] && is_bool($value[0])){return false;}
				$ret[addslashes($left[0])]=$value[0];
				$offset=$value[1];
				continue;
			}
			$value=$this->decodeEntry($wholefile,$offset);
			if($value[0]===false){return false;}
			$ret[addslashes($left[0])]=$value[0];
			$offset=$value[1];
		}
		return array(0=>(empty($ret)?true:$ret),1=>$offset);
	}
}
class BEncode{
	function makeSorted($array){
		if(empty($array)){return $array;}
		$i=0;
		foreach($array as $key=>$dummy){
			$keys[$i++]=stripslashes($key);
		}
		sort($keys);
		for($i=0; isset($keys[$i]); $i++){
			$return[addslashes($keys[$i])]=$array[addslashes($keys[$i])];
		}
		return $return;
	}
	function encodeEntry($entry,&$fd,$unstrip=false){
		if(is_bool($entry)){
			$fd.='de';
			return;
		}
		if(is_int($entry) || is_float($entry)){
			$fd .='i'.$entry.'e';
			return;
		}
		if($unstrip){$myentry=stripslashes($entry);}
		else{$myentry=$entry;}
		$length=strlen($myentry);
		$fd.=$length.':'.$myentry;
	}
	function encodeList($array,&$fd){
		$fd.='l';
		if(empty($array)){
			$fd.='e';
			return;
		}
		for($i=0;isset($array[$i]);$i++){
			$this->decideEncode($array[$i],$fd);
		}
		$fd .= 'e';
	}
	function decideEncode($unknown,&$fd){
		if(is_array($unknown)){
			if (isset($unknown[0]) || empty($unknown)){
				return $this->encodeList($unknown,$fd);
			}
			else{
				return $this->encodeDict($unknown,$fd);
			}
		}
		$this->encodeEntry($unknown,$fd);
	}
	function encodeDict($array,&$fd){
		$fd.='d';
		if(is_bool($array)){
			$fd.='e';
			return;
		}
		$newarray=$this->makeSorted($array);
		foreach($newarray as $left=>$right){
			$this->encodeEntry($left,$fd,true);
			$this->decideEncode($right,$fd);
		}
		$fd.='e';
	}
}
class torrentDo{
	private $BDecode;
	private $BEncode;
	private $xBEncoder;
	function __construct(){
		$this->BDecode=new BDecode();
		$this->BEncode=new BEncode();
		$this->xBEncoder=new xBEncoder();
		$this->xBEncoder->init();
    }
	function decideEncode($array){
		$string='';
		$this->BEncode->decideEncode($array,$string);
		return $string;
	}
	function read($file){
		$content=file_get_contents($file);//获取内容
	
		$infoAll=$this->BDecode->decodeEntry($content);
		$torrentInfo=$infoAll[0]['info'];
		$magnet='magnet:?xt=urn:btih:'.strtoupper(sha1($this->decideEncode($torrentInfo)));//磁链接地址

		$this->xBEncoder->decode($content,strlen($content));
		$info=$this->xBEncoder->object_array($this->xBEncoder->y)['info'];

		$name=$info['name'];
		$titleSameFileExt='';

		//统计所有文件
		$eachFileArr=[];
		$byteAll=0;
		foreach($info['files'] as $eachFile){
			$nowNameAndExt=$eachFile['path'][0];
			$nowExt=str_replace('.','',strrchr($nowNameAndExt,'.'));
			$nowName=str_replace('.'.$nowExt,'',$nowNameAndExt);//名称
			$nowByte=intval($eachFile['length']['val']);//字节
			$eachFileArr[]=[
				'name'=>$nowName,
				'ext'=>$nowExt,//拓展名
				'byte'=>$nowByte
			];
			$byteAll+=$nowByte;
			if($name==$nowName){
				$titleSameFileExt=$nowExt;	
			}
		}
		return [
			'title'=>$name,
			'titleSameFileExt'=>$titleSameFileExt,//因为种子文件里面可能多个文件,所以标出和title一致的文件拓展名
			'fileTime'=>filemtime($file),//种子文件最后修改时间,本地.torrent修改时间
			'magnet'=>$magnet,//磁链接
			'fileAll'=>$eachFileArr,//返回种子解析之后所有的文件,包含单个name,ext,byte
			'byteAll'=>$byteAll,//返回种子解析之后所有的文件byte合
			'creationDate'=>isset($infoAll[0]['create date'])?$infoAll[0]['create date']:0,//返回种子文件的创建时间,如有
			'comment'=>isset($infoAll[0]['comment'])?$infoAll[0]['comment']:'',//返回种子文件的备注,如有
			'createdBy'=>isset($infoAll[0]['created by'])?$infoAll[0]['created by']:'',//返回种子文件的创建工具,如有
			'infoAll'=>$infoAll//返回种子文件所有信息,可自行处理
		];
	}
}

该类调取示例:

<?php
$torrentDo=new torrentDo();
$torrentInfo=$torrentDo->read('种子文件本地路径');
echo '<pre>';
var_dump($torrentInfo);
?>

分类: php学习 标签: , , , ,

php如何解析bt种子文件并获取种子内的文件列表和大小等信息,还可以转换为磁力链接。

2015年12月11日 没有评论

php如何解析bt种子文件并获取种子内的文件列表和大小等信息,还可以转换为磁力链接。

当然还可以将制定的磁力链接转换为种子文件并下载。

代码文件:lightbenc.php,index.php

lightbenc.php是类文件,index.php是操作文件。具体代码如下:

<?php
require ‘lightbenc.php’;
$Lightbenc=new Lightbenc();
$btfile=$Lightbenc->bdecode_getinfo(‘种子.torrent’);
//获取种子文件信息
echo “<strong>种子文件名</strong>:”.$btfile[‘info’][‘name’].'<br />’;
echo “<strong>种子文件数</strong>:”.$btfile[‘info’][‘filecount’].'<br />’;
echo “<strong>种子大小</strong>:”.$btfile[‘info’][‘size’].'<br />’;
echo “<strong>磁力链接</strong>:”.’magnet:?xt=urn:btih:’.$btfile[‘info_hash’].'<br />’;
echo “<strong>下载种子</strong>:”.’http://bt.box.n0808.com/’.substr($btfile[‘info_hash’],0,2).’/’.substr($btfile[‘info_hash’],38).’/’.$btfile[‘info_hash’].’.torrent’.'<br />’;
echo “<strong>备用下载</strong>:”.’http://torcache.net/torrent/’.$btfile[‘info_hash’].’.torrent’.'<br />’;
echo “<strong>备用下载</strong>:”.’http://btcache.sobt.org/’.$btfile[‘info_hash’].’.torrent’.'<br />’;
echo “<strong>备用下载</strong>:”.’https://zoink.it/torrent/’.$btfile[‘info_hash’].’.torrent’.'<br />’;
echo ‘<br /><strong>文件信息</strong>:<br />’;
foreach($btfile[‘info’][‘files’] as $f){
echo ‘—文件总大小:’.$f[‘length’].’ byte<br />’;
echo ‘—文件列表:<br />’;
foreach($f[‘path’] as $path){
echo ‘——‘.$path.'<br />’;
}
echo ‘<br />’;
}
?>

 

下方为lightbenc.php的代码:

<?php
class Lightbenc{
public static function bdecode($s,&$pos=0){
if($pos>=strlen($s)){return null;}
switch($s[$pos]){
case ‘d’:
$pos++;
$retval=array();
while($s[$pos]!=’e’){
$key=Lightbenc::bdecode($s,$pos);
$val=Lightbenc::bdecode($s,$pos);
if($key===null || $val===null){break;}
$retval[$key]=$val;
}
$retval[“isDct”]=true;
$pos++;
return $retval;
case ‘l’:
$pos++;
$retval=array();
while($s[$pos]!=’e’){
$val=Lightbenc::bdecode($s,$pos);
if($val===null){break;}
$retval[]=$val;
}
$pos++;
return $retval;
case ‘i’:
$pos++;
$digits=strpos($s,’e’,$pos)-$pos;
$val=(int)substr($s,$pos,$digits);
$pos+=$digits+1;
return $val;
default:
$digits=strpos($s,’:’,$pos)-$pos;
if($digits<0 || $digits >20){return null;}
$len=(int)substr($s,$pos,$digits);
$pos+=$digits+1;
$str=substr($s,$pos,$len);
$pos+=$len;
return(string)$str;
}
return null;
}
public static function bencode(&$d){
if(is_array($d)){
$ret=”l”;
if(isset($d[“isDct”]) && $d[“isDct”]){
$isDict=1;
$ret=”d”;
ksort($d,SORT_STRING);
}
foreach($d as $key=>$value){
if(isset($isDict) && $isDict){
if($key==”isDct” and is_bool($value)) continue;
$ret.=strlen($key).”:”.$key;
}
if(is_string($value)){$ret.=strlen($value).”:”.$value;}
elseif(is_int($value)){$ret.=”i${value}e”;}
else {$ret.=Lightbenc::bencode($value);}
}
return $ret.”e”;
} elseif(is_string($d)) return strlen($d).”:”.$d;
elseif(is_int($d)) return “i${d}e”;
else return null;
}
public static function bdecode_file($filename){
$f=file_get_contents($filename,FILE_BINARY);
return Lightbenc::bdecode($f);
}
public static function bdecode_getinfo($filename){
$t=Lightbenc::bdecode(file_get_contents($filename,FILE_BINARY));
$t[‘info_hash’]=sha1(Lightbenc::bencode($t[‘info’]));
if(is_array($t[‘info’][‘files’])){ //multifile
$t[‘info’][‘size’]=0;
$t[‘info’][‘filecount’]=0;
foreach($t[‘info’][‘files’] as $file){
$t[‘info’][‘filecount’]++;
$t[‘info’][‘size’]+=$file[‘length’];
}
}else{
$t[‘info’][‘size’]=$t[‘info’][‘length’];
$t[‘info’][“filecount”]=1;
$t[‘info’][‘files’][0][‘path’]=$t[‘info’][‘name’];
$t[‘info’][‘files’][0][‘length’]=$t[‘info’][‘length’];
}
return $t;
}
}
?>

css.php