mirror of
				https://gitee.com/ledc/IYUUAutoReseed
				synced 2025-10-30 16:29:49 +00:00 
			
		
		
		
	IYUUAutoReseed初始化版本库v0.2.0
This commit is contained in:
		
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | /app/torrent | ||||||
|  | /app/config/config.php | ||||||
|  | /php-7.2.12-nts | ||||||
|  | /*.bat | ||||||
|  | /*.sh | ||||||
							
								
								
									
										58
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | 木兰宽松许可证, 第1版 | ||||||
|  | 2019年8月 http://license.coscl.org.cn/MulanPSL | ||||||
|  |  | ||||||
|  | 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第1版(“本许可证”)的如下条款的约束: | ||||||
|  |  | ||||||
|  | 0.   定义 | ||||||
|  |  | ||||||
|  | “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 | ||||||
|  |  | ||||||
|  | “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 | ||||||
|  |  | ||||||
|  | “法人实体”是指提交贡献的机构及其“关联实体”。 | ||||||
|  |  | ||||||
|  | “关联实体”是指,对“本许可证”下的一方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 | ||||||
|  |  | ||||||
|  | “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 | ||||||
|  |  | ||||||
|  | 1.   授予版权许可 | ||||||
|  |  | ||||||
|  | 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 | ||||||
|  |  | ||||||
|  | 2.   授予专利许可 | ||||||
|  |  | ||||||
|  | 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括仅因您或他人修改“贡献”或其他结合而将必然会侵犯到的专利权利要求。如您或您的“关联实体”直接或间接地(包括通过代理、专利被许可人或受让人),就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 | ||||||
|  |  | ||||||
|  | 3.   无商标许可 | ||||||
|  |  | ||||||
|  | “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 | ||||||
|  |  | ||||||
|  | 4.   分发限制 | ||||||
|  |  | ||||||
|  | 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 | ||||||
|  |  | ||||||
|  | 5.   免责声明与责任限制 | ||||||
|  |  | ||||||
|  | “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 | ||||||
|  |  | ||||||
|  | 条款结束 | ||||||
|  |  | ||||||
|  | 如何将木兰宽松许可证,第1版,应用到您的软件 | ||||||
|  |  | ||||||
|  | 如果您希望将木兰宽松许可证,第1版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: | ||||||
|  |  | ||||||
|  | 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; | ||||||
|  |  | ||||||
|  | 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; | ||||||
|  |  | ||||||
|  | 3, 请将如下声明文本放入每个源文件的头部注释中。 | ||||||
|  |  | ||||||
|  | Copyright (c) [2019] [name of copyright holder] | ||||||
|  | [Software Name] is licensed under the Mulan PSL v1. | ||||||
|  | You can use this software according to the terms and conditions of the Mulan PSL v1. | ||||||
|  | You may obtain a copy of Mulan PSL v1 at: | ||||||
|  |     http://license.coscl.org.cn/MulanPSL | ||||||
|  | THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR | ||||||
|  | PURPOSE. | ||||||
|  | See the Mulan PSL v1 for more details. | ||||||
							
								
								
									
										141
									
								
								app/Class/Bencode.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								app/Class/Bencode.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Created by PhpStorm. | ||||||
|  |  * User: Rhilip | ||||||
|  |  * Date: 2019/4/21 | ||||||
|  |  * Time: 21:12 | ||||||
|  |  */ | ||||||
|  | class Bencode | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * Decodes a BEncoded string to the following values: | ||||||
|  |      * - Dictionary (starts with d, ends with e) | ||||||
|  |      * - List (starts with l, ends with e | ||||||
|  |      * - Integer (starts with i, ends with e | ||||||
|  |      * - String (starts with number denoting number of characters followed by : and then the string) | ||||||
|  |      * | ||||||
|  |      * @see https://wiki.theory.org/index.php/BitTorrentSpecification | ||||||
|  |      * | ||||||
|  |      * @param string $data | ||||||
|  |      * @param int $pos | ||||||
|  |      * @return mixed | ||||||
|  |      */ | ||||||
|  |     public static function decode($data, &$pos = 0) | ||||||
|  |     { | ||||||
|  |         $start_decode = ($pos === 0); | ||||||
|  |         if ($data[$pos] === 'd') { | ||||||
|  |             $pos++; | ||||||
|  |             $return = []; | ||||||
|  |             while ($data[$pos] !== 'e') { | ||||||
|  |                 $key = self::decode($data, $pos); | ||||||
|  |                 $value = self::decode($data, $pos); | ||||||
|  |                 if ($key === null || $value === null) { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 if (!is_string($key)) { | ||||||
|  |                     throw new RuntimeException('Invalid key type, must be string: ' . gettype($key)); | ||||||
|  |                 } | ||||||
|  |                 $return[$key] = $value; | ||||||
|  |             } | ||||||
|  |             ksort($return); | ||||||
|  |             $pos++; | ||||||
|  |         } elseif ($data[$pos] === 'l') { | ||||||
|  |             $pos++; | ||||||
|  |             $return = []; | ||||||
|  |             while ($data[$pos] !== 'e') { | ||||||
|  |                 $value = self::decode($data, $pos); | ||||||
|  |                 $return[] = $value; | ||||||
|  |             } | ||||||
|  |             $pos++; | ||||||
|  |         } elseif ($data[$pos] === 'i') { | ||||||
|  |             $pos++; | ||||||
|  |             $digits = strpos($data, 'e', $pos) - $pos; | ||||||
|  |             $return = substr($data, $pos, $digits); | ||||||
|  |             if ($return === '-0') { | ||||||
|  |                 throw new RuntimeException('Cannot have integer value -0'); | ||||||
|  |             } | ||||||
|  |             $multiplier = 1; | ||||||
|  |             if ($return[0] === '-') { | ||||||
|  |                 $multiplier = -1; | ||||||
|  |                 $return = substr($return, 1); | ||||||
|  |             } | ||||||
|  |             if (!ctype_digit($return)) { | ||||||
|  |                 throw new RuntimeException('Cannot have non-digit values in integer number: ' . $return); | ||||||
|  |             } | ||||||
|  |             $return = $multiplier * ((int)$return); | ||||||
|  |             $pos += $digits + 1; | ||||||
|  |         } else { | ||||||
|  |             $digits = strpos($data, ':', $pos) - $pos; | ||||||
|  |             $len = (int)substr($data, $pos, $digits); | ||||||
|  |             $pos += ($digits + 1); | ||||||
|  |             $return = substr($data, $pos, $len); | ||||||
|  |             $pos += $len; | ||||||
|  |         } | ||||||
|  |         if ($start_decode) { | ||||||
|  |             if ($pos !== strlen($data)) { | ||||||
|  |                 throw new RuntimeException('Could not fully decode bencode string'); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return $return; | ||||||
|  |     } | ||||||
|  |     /** | ||||||
|  |      * @param mixed $data | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     public static function encode($data) | ||||||
|  |     { | ||||||
|  |         if (is_array($data)) { | ||||||
|  |             $return = ''; | ||||||
|  |             $check = -1; | ||||||
|  |             $list = true; | ||||||
|  |             foreach ($data as $key => $value) { | ||||||
|  |                 if ($key !== ++$check) { | ||||||
|  |                     $list = false; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             if ($list) { | ||||||
|  |                 $return .= 'l'; | ||||||
|  |                 foreach ($data as $value) { | ||||||
|  |                     $return .= self::encode($value); | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 $return .= 'd'; | ||||||
|  |                 foreach ($data as $key => $value) { | ||||||
|  |                     $return .= self::encode(strval($key)); | ||||||
|  |                     $return .= self::encode($value); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             $return .= 'e'; | ||||||
|  |         } elseif (is_integer($data)) { | ||||||
|  |             $return = 'i' . $data . 'e'; | ||||||
|  |         } else { | ||||||
|  |             $return = strlen($data) . ':' . $data; | ||||||
|  |         } | ||||||
|  |         return $return; | ||||||
|  |     } | ||||||
|  |     /** | ||||||
|  |      * Given a path to a file, decode the contents of it | ||||||
|  |      * | ||||||
|  |      * @param string $path | ||||||
|  |      * @return mixed | ||||||
|  |      */ | ||||||
|  |     public static function load($path) | ||||||
|  |     { | ||||||
|  |         if (is_file($path)) { | ||||||
|  |             return self::decode(file_get_contents($path)); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |     /** | ||||||
|  |      * Given a path for a file, encode the contents of it | ||||||
|  |      * | ||||||
|  |      * @param string $path | ||||||
|  |      * @param $data | ||||||
|  |      * @return mixed | ||||||
|  |      */ | ||||||
|  |     public static function dump($path, $data) | ||||||
|  |     { | ||||||
|  |         return file_put_contents($path, self::encode($data)); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										313
									
								
								app/Class/Function.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								app/Class/Function.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,313 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * 调试函数 | ||||||
|  |  */ | ||||||
|  | function p($data, $echo=true){ | ||||||
|  | 	$str='******************************'."\n"; | ||||||
|  | 	// 如果是boolean或者null直接显示文字;否则print | ||||||
|  | 	if (is_bool($data)) { | ||||||
|  | 		$show_data=$data ? 'true' : 'false'; | ||||||
|  | 	}elseif (is_null($data)) { | ||||||
|  | 		$show_data='null'; | ||||||
|  | 	}else{ | ||||||
|  | 		$show_data=print_r($data,true); | ||||||
|  | 	} | ||||||
|  | 	$str.=$show_data; | ||||||
|  | 	$str.="\n".'******************************'."\n"; | ||||||
|  | 	if($echo){ | ||||||
|  | 		echo $str; | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | 	return $str; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 微信推送Server酱 | ||||||
|  |  */ | ||||||
|  | function sc($text='', $desp='') | ||||||
|  | { | ||||||
|  | 	global $configALL; | ||||||
|  | 	$token = $configALL['sc.ftqq.com']; | ||||||
|  | 	$desp = ($desp=='')?date("Y-m-d H:i:s") :$desp; | ||||||
|  | 	$postdata = http_build_query(array( | ||||||
|  | 			'text' => $text, | ||||||
|  | 			'desp' => $desp | ||||||
|  | 		)); | ||||||
|  | 	$opts = array('http' =>	array( | ||||||
|  | 			'method'  => 'POST', | ||||||
|  | 			'header'  => 'Content-type: application/x-www-form-urlencoded', | ||||||
|  | 			'content' => $postdata | ||||||
|  | 		)); | ||||||
|  | 	$context  = stream_context_create($opts); | ||||||
|  | 	$result = file_get_contents('http://sc.ftqq.com/'.$token.'.send', false, $context); | ||||||
|  | 	return  $result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 微信推送 爱语飞飞 | ||||||
|  |  */ | ||||||
|  | function ff($text='', $desp='') | ||||||
|  | { | ||||||
|  | 	global $configALL; | ||||||
|  | 	$token = $configALL['iyuu.cn']; | ||||||
|  | 	$desp = ($desp=='')?date("Y-m-d H:i:s") :$desp; | ||||||
|  | 	$postdata = http_build_query(array( | ||||||
|  | 			'text' => $text, | ||||||
|  | 			'desp' => $desp | ||||||
|  | 		)); | ||||||
|  | 	$opts = array('http' =>	array( | ||||||
|  | 			'method'  => 'POST', | ||||||
|  | 			'header'  => 'Content-type: application/x-www-form-urlencoded', | ||||||
|  | 			'content' => $postdata | ||||||
|  | 		)); | ||||||
|  | 	$context  = stream_context_create($opts); | ||||||
|  | 	$result = file_get_contents('http://iyuu.cn/'.$token.'.send', false, $context); | ||||||
|  | 	return  $result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 微信推送 爱语飞飞 | ||||||
|  |  * @param array  $torrent 种子数组 | ||||||
|  | 		Array | ||||||
|  | 		( | ||||||
|  | 			[id] => 118632 | ||||||
|  | 			[h1] => CCTV5+ 2019 ATP Men's Tennis Final 20191115B HDTV 1080i H264-HDSTV | ||||||
|  | 			[title] => 央视体育赛事频道 2019年ATP男子网球年终总决赛 单打小组赛 纳达尔VS西西帕斯 20191115[优惠剩余时间:4时13分] | ||||||
|  | 			[details] => https://xxx.me/details.php?id=118632 | ||||||
|  | 			[download] => https://xxx.me/download.php?id=118632 | ||||||
|  | 			[filename] => 118632.torrent | ||||||
|  | 			[type] => 0 | ||||||
|  | 			[sticky] => 1 | ||||||
|  | 			[time] => Array | ||||||
|  | 				( | ||||||
|  | 					[0] => "2019-11-16 20:41:53">4时13分 | ||||||
|  | 					[1] => "2019-11-16 14:41:53">1时<br />46分 | ||||||
|  | 				) | ||||||
|  | 			[comments] => 0 | ||||||
|  | 			[size] => 5232.64MB | ||||||
|  | 			[seeders] => 69 | ||||||
|  | 			[leechers] => 10 | ||||||
|  | 			[completed] => 93 | ||||||
|  | 			[percentage] => 100% | ||||||
|  | 			[owner] => 匿名 | ||||||
|  | 		) | ||||||
|  |  */ | ||||||
|  | function send($site = '', $torrent = array()) | ||||||
|  | { | ||||||
|  | 	$br = "\r\n"; | ||||||
|  | 	$text = $site. ' 免费:' .$torrent['filename']. ',添加成功'; | ||||||
|  | 	$desp = '主标题:'.$torrent['h1'] . $br; | ||||||
|  |  | ||||||
|  | 	if ( isset($torrent['title']) ) { | ||||||
|  | 		$desp .= '副标题:'.$torrent['title']. $br; | ||||||
|  | 	} | ||||||
|  | 	if ( isset($torrent['size']) ) { | ||||||
|  | 		$desp .= '大小:'.$torrent['size']. $br; | ||||||
|  | 	} | ||||||
|  | 	if ( isset($torrent['seeders']) ) { | ||||||
|  | 		$desp .= '做种数:'.$torrent['seeders']. $br; | ||||||
|  | 	} | ||||||
|  | 	if ( isset($torrent['leechers']) ) { | ||||||
|  | 		$desp .= '下载数:'.$torrent['leechers']. $br; | ||||||
|  | 	} | ||||||
|  | 	if ( isset($torrent['owner']) ) { | ||||||
|  | 		$desp .= '发布者:'.$torrent['owner']. $br; | ||||||
|  | 	} | ||||||
|  | 	return ff($text, $desp); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief 下载种子 | ||||||
|  |  * @param string $url 种子URL | ||||||
|  |  * @param string  $cookies 模拟登陆的cookie | ||||||
|  |  * @return mixed 返回的数据 | ||||||
|  |  */ | ||||||
|  | function download($url, $cookies, $useragent, $method = 'GET') | ||||||
|  | { | ||||||
|  | 	$header = array( | ||||||
|  | 		"Content-Type:application/x-www-form-urlencoded", | ||||||
|  | 		'User-Agent: '.$useragent); | ||||||
|  | 	$ch = curl_init(); | ||||||
|  | 	if($method === 'POST'){ | ||||||
|  | 		curl_setopt($ch, CURLOPT_POST, true ); | ||||||
|  | 	} | ||||||
|  | 	if(stripos($url, 'https://') !== FALSE) { | ||||||
|  | 		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); | ||||||
|  | 		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); | ||||||
|  | 		curl_setopt($ch, CURLOPT_SSLVERSION, 1); | ||||||
|  | 	} | ||||||
|  | 	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | ||||||
|  | 	curl_setopt($ch, CURLOPT_HTTPHEADER,$header); | ||||||
|  | 	curl_setopt($ch, CURLOPT_COOKIE,$cookies); | ||||||
|  | 	curl_setopt($ch, CURLOPT_URL, $url); | ||||||
|  | 	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,60); | ||||||
|  | 	curl_setopt($ch, CURLOPT_TIMEOUT,600); | ||||||
|  | 	$data = curl_exec($ch); | ||||||
|  | 	$status = curl_getinfo($ch); | ||||||
|  | 	curl_close($ch); | ||||||
|  | 	if (isset($status['http_code']) && $status['http_code'] == 200) { | ||||||
|  | 		return $data; | ||||||
|  | 	} | ||||||
|  | 	if (isset($status['http_code']) && $status['http_code'] == 302) { | ||||||
|  | 		return download($status['redirect_url'], $cookies, $useragent); | ||||||
|  | 	} | ||||||
|  | 	return $data; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief 文件大小格式化为MB | ||||||
|  |  * @param string $from 文件大小 | ||||||
|  |  * @return int 单位MB | ||||||
|  |  */ | ||||||
|  | function convertToMB($from){ | ||||||
|  |     $number=substr($from,0,-2); | ||||||
|  |     switch(strtoupper(substr($from,-2))){ | ||||||
|  |         case "KB": | ||||||
|  |             return $number/1024; | ||||||
|  |         case "MB": | ||||||
|  |             return $number; | ||||||
|  |         case "GB": | ||||||
|  |             return $number*pow(1024,1); | ||||||
|  |         case "TB": | ||||||
|  |             return $number*pow(1024,2); | ||||||
|  |         case "PB": | ||||||
|  |             return $number*pow(1024,3); | ||||||
|  |         default: | ||||||
|  |             return $from; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief 种子过滤器 | ||||||
|  |  * @param string $site 站点标识 | ||||||
|  |  * @param array  $torrent 种子数组 | ||||||
|  |  * 	Array | ||||||
|  | 	( | ||||||
|  | 		[id] => 118632 | ||||||
|  | 		[h1] => CCTV5+ 2019 ATP Men's Tennis Final 20191115B HDTV 1080i H264-HDSTV | ||||||
|  | 		[title] => 央视体育赛事频道 2019年ATP男子网球年终总决赛 单打小组赛 纳达尔VS西西帕斯 20191115[优惠剩余时间:4时13分] | ||||||
|  | 		[details] => https://xxx.me/details.php?id=118632 | ||||||
|  | 		[download] => https://xxx.me/download.php?id=118632 | ||||||
|  | 		[filename] => 118632.torrent | ||||||
|  | 		[type] => 0 | ||||||
|  | 		[sticky] => 1 | ||||||
|  | 		[time] => Array | ||||||
|  | 			( | ||||||
|  | 				[0] => "2019-11-16 20:41:53">4时13分 | ||||||
|  | 				[1] => "2019-11-16 14:41:53">1时<br />46分 | ||||||
|  | 			) | ||||||
|  | 		[comments] => 0 | ||||||
|  | 		[size] => 5232.64MB | ||||||
|  | 		[seeders] => 69 | ||||||
|  | 		[leechers] => 10 | ||||||
|  | 		[completed] => 93 | ||||||
|  | 		[percentage] => 100% | ||||||
|  | 		[owner] => 匿名 | ||||||
|  | 	) | ||||||
|  |  * @return bool 或 string 	false不过滤 | ||||||
|  |  */ | ||||||
|  | function filter($site = '', $torrent = array()){ | ||||||
|  | 	global $configALL; | ||||||
|  | 	$config = $configALL[$site]; | ||||||
|  | 	$filter = array(); | ||||||
|  | 	// 读取配置 | ||||||
|  | 	if (isset($configALL['default']['filter']) || isset($config['filter'])) { | ||||||
|  | 		$filter = isset($config['filter']) && $config['filter'] ? $config['filter'] : $configALL['default']['filter']; | ||||||
|  | 	}else { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	$filename = $torrent['filename']; | ||||||
|  |  | ||||||
|  | 	// 兼容性 | ||||||
|  | 	if ( empty($torrent['size']) ) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	// 大小过滤 | ||||||
|  | 	$size = convertToMB($torrent['size']); | ||||||
|  | 	$min = isset($filter['size']['min']) ? convertToMB($filter['size']['min']) : 0; | ||||||
|  | 	$max = isset($filter['size']['max']) ? convertToMB($filter['size']['max']) : 2097152;	//默认 2097152MB = 2TB | ||||||
|  | 	if ($min > $size || $size > $max) { | ||||||
|  | 		return $filename. ' ' .$size. 'MB,被大小过滤'; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// 兼容性 | ||||||
|  | 	if ( empty($torrent['seeders']) ) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	// 种子数过滤 | ||||||
|  | 	$seeders = $torrent['seeders']; | ||||||
|  | 	$min = isset($filter['seeders']['min']) ? $filter['seeders']['min'] : 1;	//默认 1 | ||||||
|  | 	$max = isset($filter['seeders']['max']) ? $filter['seeders']['max'] : 3;	//默认 3 | ||||||
|  | 	if ($min > $seeders || $seeders > $max) { | ||||||
|  | 		return $filename. ' 当前做种' .$seeders. '人,被过滤'; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// 兼容性 | ||||||
|  | 	if ( empty($torrent['leechers']) ) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	// 下载数过滤 | ||||||
|  | 	$leechers = $torrent['leechers']; | ||||||
|  | 	$min = isset($filter['leechers']['min']) ? $filter['leechers']['min'] : 0;		//默认 | ||||||
|  | 	$max = isset($filter['leechers']['max']) ? $filter['leechers']['max'] : 30000;	//默认 | ||||||
|  | 	if ($min > $leechers || $leechers > $max) { | ||||||
|  | 		return $filename. ' 当前下载' .$leechers. '人,被过滤'; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// 兼容性 | ||||||
|  | 	if ( empty($torrent['completed']) ) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	// 完成数过滤 | ||||||
|  | 	$completed = $torrent['completed']; | ||||||
|  | 	$min = isset($filter['completed']['min']) ? $filter['completed']['min'] : 0;		//默认 | ||||||
|  | 	$max = isset($filter['completed']['max']) ? $filter['completed']['max'] : 30000;	//默认 | ||||||
|  | 	if ($min > $completed || $completed > $max) { | ||||||
|  | 		return $filename. ' 已完成数' .$completed. '人,被过滤'; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 奇数 | ||||||
|  |  */ | ||||||
|  | function oddFilter($var) | ||||||
|  | { | ||||||
|  |     // 返回$var最后一个二进制位, | ||||||
|  |     // 为1则保留(奇数的二进制的最后一位肯定是1) | ||||||
|  |     return($var & 1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 偶数 | ||||||
|  |  */ | ||||||
|  | function evenFilter($var) | ||||||
|  | { | ||||||
|  | 	// 返回$var最后一个二进制位, | ||||||
|  |     // 为0则保留(偶数的二进制的最后一位肯定是0) | ||||||
|  | 	return(!($var & 1)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 发布员签名 | ||||||
|  |  * 注意:同时配置iyuu.cn与secret时,优先使用secret。 | ||||||
|  |  */ | ||||||
|  | function sign( $timestamp ){ | ||||||
|  | 	global $configALL; | ||||||
|  | 	// 爱语飞飞 | ||||||
|  | 	$token = isset($configALL['iyuu.cn']) && $configALL['iyuu.cn'] ? $configALL['iyuu.cn'] : ''; | ||||||
|  | 	// 鉴权 | ||||||
|  | 	$token = isset($configALL['secret']) && $configALL['secret'] ? $configALL['secret'] : $token; | ||||||
|  | 	return sha1($timestamp . $token); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief 分离token中的用户uid | ||||||
|  |  * token算法:IYUU + uid + T + sha1(openid+time+盐) | ||||||
|  |  * @param string $token		用户请求token | ||||||
|  |  */ | ||||||
|  | function getUid($token){ | ||||||
|  | 	//验证是否IYUU开头,strpos($token,'T')<15,token总长度小于60(40+10+5) | ||||||
|  | 	return (strlen($token)<60)&&(strpos($token,'IYUU')===0)&&(strpos($token,'T')<15) ? substr($token,4,strpos($token,'T')-4): false; | ||||||
|  | } | ||||||
							
								
								
									
										332
									
								
								app/Class/IFile.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								app/Class/IFile.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,332 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * @brief 文件处理 | ||||||
|  |  * @version 0.6 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @class IFile | ||||||
|  |  * @brief IFile 文件处理类 | ||||||
|  |  */ | ||||||
|  | class IFile | ||||||
|  | { | ||||||
|  | 	private $resource = null; //文件资源句柄 | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 构造函数,打开资源流,并独占锁定 | ||||||
|  | 	 * @param String $fileName 文件路径名 | ||||||
|  | 	 * @param String $mode     操作方式,默认为读操作,可供选择的项为:r,r+,w+,w+,a,a+ | ||||||
|  | 	 * @note $mod,'r'  只读方式打开,将文件指针指向文件头 | ||||||
|  | 	 *             'r+' 读写方式打开,将文件指针指向文件头 | ||||||
|  | 	 * 			   'w'  写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。 | ||||||
|  | 	 * 			   'w+' 读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。 | ||||||
|  | 	 * 			   'a'  写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。 | ||||||
|  | 	 * 			   'a+' 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。 | ||||||
|  | 	 */ | ||||||
|  | 	function __construct($fileName,$mode='r') | ||||||
|  | 	{ | ||||||
|  | 		$dirName  = dirname($fileName); | ||||||
|  | 		$baseName = basename($fileName); | ||||||
|  |  | ||||||
|  | 		//检查并创建文件夹 | ||||||
|  | 		self::mkdir($dirName); | ||||||
|  |  | ||||||
|  | 		$this->resource = fopen($fileName,$mode.'b'); | ||||||
|  | 		if($this->resource) | ||||||
|  | 		{ | ||||||
|  | 			flock($this->resource,LOCK_EX); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 获取文件内容 | ||||||
|  | 	 * @return String 文件内容 | ||||||
|  | 	 */ | ||||||
|  | 	public function read() | ||||||
|  | 	{ | ||||||
|  | 		$content = null; | ||||||
|  | 		while(!feof($this->resource)) | ||||||
|  | 		{ | ||||||
|  | 			$content.= fread($this->resource,1024); | ||||||
|  | 		} | ||||||
|  | 		return $content; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 文件写入操作 | ||||||
|  | 	 * @param  String $content 要写入的文件内容 | ||||||
|  | 	 * @return Int or false    写入的字符数; false:写入失败; | ||||||
|  | 	 */ | ||||||
|  | 	public function write($content) | ||||||
|  | 	{ | ||||||
|  | 		$worldsnum = fwrite($this->resource,$content); | ||||||
|  | 		$this->save(); | ||||||
|  | 		return is_bool($worldsnum) ? false : $worldsnum; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief  清空目录下的所有文件 | ||||||
|  | 	 * @return bool false:失败; true:成功; | ||||||
|  | 	 */ | ||||||
|  | 	public static function clearDir($dir) | ||||||
|  | 	{ | ||||||
|  | 		if($dir[0] != '.' && is_dir($dir) && is_writable($dir)) | ||||||
|  | 		{ | ||||||
|  | 			$dirRes = opendir($dir); | ||||||
|  | 			while( false !== ($fileName = readdir($dirRes)) ) | ||||||
|  | 			{ | ||||||
|  | 				if($fileName[0] !== '.') | ||||||
|  | 				{ | ||||||
|  | 					$fullpath = $dir.'/'.$fileName; | ||||||
|  | 					if(is_file($fullpath)) | ||||||
|  | 					{ | ||||||
|  | 						self::unlink($fullpath); | ||||||
|  | 					} | ||||||
|  | 					else | ||||||
|  | 					{ | ||||||
|  | 						self::clearDir($fullpath); | ||||||
|  | 						rmdir($fullpath); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			closedir($dirRes); | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 获取文件信息 | ||||||
|  | 	 * @param String $fileName 文件路径 | ||||||
|  | 	 * @return array or null   array:文件信息; null:文件不存在; | ||||||
|  | 	 */ | ||||||
|  | 	public static function getInfo($fileName) | ||||||
|  | 	{ | ||||||
|  | 		if(is_file($fileName)) | ||||||
|  | 			return stat($fileName); | ||||||
|  |  | ||||||
|  | 		else | ||||||
|  | 			return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief  创建文件夹 | ||||||
|  | 	 * @param String $path  路径 | ||||||
|  | 	 * @param int    $chmod 文件夹权限 | ||||||
|  | 	 * @note  $chmod 参数不能是字符串(加引号),否则linux会出现权限问题 | ||||||
|  | 	 */ | ||||||
|  | 	public static function mkdir($path,$chmod=0777) | ||||||
|  | 	{ | ||||||
|  | 		return is_dir($path) or (self::mkdir(dirname($path),$chmod) and mkdir($path,$chmod)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 复制文件 | ||||||
|  | 	 * @param String $from 源文件路径 | ||||||
|  | 	 * @param String $to   目标文件路径 | ||||||
|  | 	 * @param String $mod  操作模式,c:复制(默认); x:剪切(删除$from文件) | ||||||
|  | 	 * @return bool  操作结果 true:成功; false:失败; | ||||||
|  | 	 */ | ||||||
|  | 	public static function copy($from,$to,$mode = 'c') | ||||||
|  | 	{ | ||||||
|  | 		$dir = dirname($to); | ||||||
|  |  | ||||||
|  | 		//创建目录 | ||||||
|  | 		self::mkdir($dir); | ||||||
|  |  | ||||||
|  | 		copy($from,$to); | ||||||
|  |  | ||||||
|  | 		if(is_file($to)) | ||||||
|  | 		{ | ||||||
|  | 			if($mode == 'x') | ||||||
|  | 			{ | ||||||
|  | 				self::unlink($from); | ||||||
|  | 			} | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 删除文件 | ||||||
|  | 	 * @param String $fileName 文件路径 | ||||||
|  | 	 * @return bool  操作结果 false:删除失败; | ||||||
|  | 	 */ | ||||||
|  | 	public static function unlink($fileName) | ||||||
|  | 	{ | ||||||
|  | 		if(is_file($fileName) && is_writable($fileName)) | ||||||
|  | 		{ | ||||||
|  | 			return unlink($fileName); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief  删除$dir文件夹 或者 其下所有文件 | ||||||
|  | 	 * @param  String $dir       文件路径 | ||||||
|  | 	 * @param  bool   $recursive 是否强制删除,如果强制删除则递归删除该目录下的全部文件,默认为false | ||||||
|  | 	 * @return bool true:删除成功; false:删除失败; | ||||||
|  | 	 */ | ||||||
|  | 	public static function rmdir($dir,$recursive = false) | ||||||
|  | 	{ | ||||||
|  | 		if(is_dir($dir) && is_writable($dir)) | ||||||
|  | 		{ | ||||||
|  | 			//强制删除 | ||||||
|  | 			if($recursive == true) | ||||||
|  | 			{ | ||||||
|  | 				self::clearDir($dir); | ||||||
|  | 				return self::rmdir($dir,false); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			//非强制删除 | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				if(rmdir($dir)) | ||||||
|  | 				{ | ||||||
|  | 					return true; | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					return false; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 获取文件类型 | ||||||
|  | 	 * @param  String $fileName  文件名 | ||||||
|  | 	 * @return String $filetype  文件类型 | ||||||
|  | 	 * @note 如果文件不存在,返回false,如果文件后缀名不在识别列表之内,返回NULL,对于docx及elsx格式文档识别在会出现识别为ZIP格式的错误,这是office2007的bug目前尚未修复,请谨慎使用 | ||||||
|  | 	 */ | ||||||
|  | 	public static function getFileType($fileName) | ||||||
|  | 	{ | ||||||
|  | 		$filetype = null; | ||||||
|  | 		if(!is_file($fileName)) | ||||||
|  | 		{ | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		$fileRes = fopen($fileName,"rb"); | ||||||
|  | 	    if(!$fileRes) | ||||||
|  | 		{ | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  |         $bin= fread($fileRes, 2); | ||||||
|  |         fclose($fileRes); | ||||||
|  |  | ||||||
|  |         if($bin != null) | ||||||
|  |         { | ||||||
|  |         	$strInfo  = unpack("C2chars", $bin); | ||||||
|  | 	        $typeCode = intval($strInfo['chars1'].$strInfo['chars2']); | ||||||
|  | 			$typelist = self::getTypeList(); | ||||||
|  | 			foreach($typelist as $val) | ||||||
|  | 			{ | ||||||
|  | 				if(strtolower($val[0]) == strtolower($typeCode)) | ||||||
|  | 				{ | ||||||
|  | 					if($val[0] == 8075) | ||||||
|  | 					{ | ||||||
|  | 						return array('zip','docx','xlsx'); | ||||||
|  | 					} | ||||||
|  | 					else | ||||||
|  | 					{ | ||||||
|  | 						return $val[1]; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |         } | ||||||
|  | 		return $filetype; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 获取文件类型映射关系 | ||||||
|  |      * @return array 文件类型映射关系数组 | ||||||
|  |      */ | ||||||
|  |     public static function getTypeList() | ||||||
|  |     { | ||||||
|  |     	return array( | ||||||
|  | 	    	array('255216','jpg'), | ||||||
|  | 			array('13780','png'), | ||||||
|  | 			array('7173','gif'), | ||||||
|  | 			array('6677','bmp'), | ||||||
|  | 			array('6063','xml'), | ||||||
|  | 			array('60104','html'), | ||||||
|  | 			array('208207','xls/doc'), | ||||||
|  | 			array('8075','zip'), | ||||||
|  | 			array('8075','docx'), | ||||||
|  | 			array('8075','xlsx'), | ||||||
|  | 			array("8297","rar"), | ||||||
|  |     	); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 获取文件大小 | ||||||
|  | 	 * @param  String $fileName 文件名 | ||||||
|  | 	 * @return Int    文件大小的字节数,如果文件无效则返回 NULL | ||||||
|  | 	 */ | ||||||
|  | 	public static function getFileSize($fileName) | ||||||
|  | 	{ | ||||||
|  | 		return is_file($fileName) ? filesize($fileName):null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 检测文件夹是否为空 | ||||||
|  | 	 * @param String $dir 路径地址 | ||||||
|  | 	 * @return bool true:$dir为空目录; false:$dir为非空目录; | ||||||
|  | 	 */ | ||||||
|  | 	public static function isEmptyDir($dir) | ||||||
|  | 	{ | ||||||
|  | 		if(is_dir($dir)) | ||||||
|  | 		{ | ||||||
|  | 			$isEmpty = true; | ||||||
|  | 			$dirRes  = opendir($dir); | ||||||
|  | 			while(false !== ($fileName = readdir($dirRes))) | ||||||
|  | 			{ | ||||||
|  | 				if($fileName!='.' && $fileName!='..') | ||||||
|  | 				{ | ||||||
|  | 					$isEmpty = false; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			closedir($dirRes); | ||||||
|  | 			return $isEmpty; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 释放文件锁定 | ||||||
|  | 	 */ | ||||||
|  | 	public function save() | ||||||
|  | 	{ | ||||||
|  | 		flock($this->resource,LOCK_UN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief  获取文件扩展名 | ||||||
|  | 	 * @param  String $fileName  文件名 | ||||||
|  | 	 * @return String 文件后缀名 | ||||||
|  | 	 */ | ||||||
|  | 	public static function getFileSuffix($fileName) | ||||||
|  | 	{ | ||||||
|  | 		$fileInfoArray = pathinfo($fileName); | ||||||
|  | 		return $fileInfoArray['extension']; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 析构函数,释放文件连接句柄 | ||||||
|  | 	 */ | ||||||
|  | 	function __destruct() | ||||||
|  | 	{ | ||||||
|  | 		if(is_resource($this->resource)) | ||||||
|  | 		{ | ||||||
|  | 			fclose($this->resource); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										71
									
								
								app/Class/Oauth.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								app/Class/Oauth.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * IYUU用户注册、认证 | ||||||
|  |  */ | ||||||
|  | use Curl\Curl; | ||||||
|  | class Oauth{ | ||||||
|  |     // 合作的站点 | ||||||
|  |     public static $sites = ['ourbits']; | ||||||
|  |     // 爱语飞飞token | ||||||
|  |     public static $token = ''; | ||||||
|  |     // 合作站点用户id | ||||||
|  |     public static $user_id = 0; | ||||||
|  |     // 合作站点密钥 | ||||||
|  |     public static $passkey = ''; | ||||||
|  |     // 合作站名字 | ||||||
|  |     public static $site = ''; | ||||||
|  |     /** | ||||||
|  |      * 初始化配置 | ||||||
|  |      */ | ||||||
|  |     public static function init(){ | ||||||
|  |         global $configALL; | ||||||
|  |         foreach (self::$sites as $name) { | ||||||
|  |             if (isset($configALL[$name]['passkey']) && $configALL[$name]['passkey'] && isset($configALL[$name]['id']) && $configALL[$name]['id'] ) { | ||||||
|  |                 self::$token = self::getSign(); | ||||||
|  |                 self::$user_id = $configALL[$name]['id']; | ||||||
|  |                 self::$passkey =  sha1( $configALL[$name]['passkey'] );     // 避免泄露用户passkey秘钥 | ||||||
|  |                 self::$site = $name; | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         echo "-----缺少合作站点登录参数:token, user_id, passkey, site \n"; | ||||||
|  |         echo "-----当前正在使用测试接口,功能可能会受到限制! \n\n"; | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |     /** | ||||||
|  |      * 从配置文件内读取爱语飞飞token作为鉴权参数 | ||||||
|  |      */ | ||||||
|  |     public static function getSign(){ | ||||||
|  |         global $configALL; | ||||||
|  |         // 爱语飞飞 | ||||||
|  |         $token = isset($configALL['iyuu.cn']) && $configALL['iyuu.cn'] ? $configALL['iyuu.cn'] : ''; | ||||||
|  |         if (empty($token) || strlen($token)<46) { | ||||||
|  |             echo "缺少辅种接口请求参数:爱语飞飞token \n"; | ||||||
|  |             echo "请访问https://iyuu.cn 用微信扫码申请,并填入配置文件config.php内。\n\n"; | ||||||
|  |             exit(1); | ||||||
|  |         } | ||||||
|  |         return $token; | ||||||
|  |     } | ||||||
|  |     /** | ||||||
|  |      * 用户注册与登录 | ||||||
|  |      * 作用:在服务器端实现微信用户与合作站点用户id的关联 | ||||||
|  |      * 参数:爱语飞飞token + 合作站点用户id + sha1(合作站点密钥passkey) + 合作站点标识 | ||||||
|  |      */ | ||||||
|  |     public static function login($apiUrl = ''){ | ||||||
|  |         $is_oauth = self::init(); | ||||||
|  |         if ( $is_oauth ) { | ||||||
|  |             $curl = new Curl(); | ||||||
|  |             $curl->setOpt(CURLOPT_SSL_VERIFYPEER, false); | ||||||
|  |             $data = [ | ||||||
|  |                 'token'  => self::$token, | ||||||
|  |                 'id'     => self::$user_id, | ||||||
|  |                 'passkey'=> self::$passkey, | ||||||
|  |                 'site'   => self::$site, | ||||||
|  |             ]; | ||||||
|  |             $res = $curl->get($apiUrl, $data); | ||||||
|  |             p($res->response); | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return false;         | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										368
									
								
								app/Class/Rpc.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										368
									
								
								app/Class/Rpc.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,368 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Rpc操作类 | ||||||
|  |  */ | ||||||
|  | class Rpc | ||||||
|  | { | ||||||
|  | 	/** | ||||||
|  |      * 版本号 | ||||||
|  |      * @var string | ||||||
|  |      */ | ||||||
|  |     const VER = '0.0.1'; | ||||||
|  |  | ||||||
|  | 	// 下载种子的请求类型 GET POST | ||||||
|  | 	public static $method = 'GET'; | ||||||
|  | 	// RPC连接池 | ||||||
|  | 	public static $links = array(); | ||||||
|  | 	/** | ||||||
|  |      * cookie | ||||||
|  |      */ | ||||||
|  |     public static $cookies = ''; | ||||||
|  | 	/** | ||||||
|  |      * 浏览器 User-Agent | ||||||
|  |      */ | ||||||
|  |     public static $userAgent = ''; | ||||||
|  | 	/** | ||||||
|  |      * passkey | ||||||
|  |      */ | ||||||
|  |     public static $passkey = ''; | ||||||
|  | 	/** | ||||||
|  |      * 客户端配置 | ||||||
|  |      */ | ||||||
|  |     public static $clients = ''; | ||||||
|  | 	/** | ||||||
|  |      * 监控目录 | ||||||
|  |      */ | ||||||
|  |     public static $watch = ''; | ||||||
|  | 	/** | ||||||
|  |      * 种子存放路径 | ||||||
|  |      */ | ||||||
|  |     public static $torrentDir = ''; | ||||||
|  | 	/** | ||||||
|  |      * 工作模式 | ||||||
|  |      */ | ||||||
|  |     public static $workingMode = ''; | ||||||
|  | 	// 站点标识 | ||||||
|  | 	public static $site = ''; | ||||||
|  | 	/** | ||||||
|  |      * 负载均衡 控制变量 | ||||||
|  |      */ | ||||||
|  |     public static $RPC_Key = 0; | ||||||
|  | 	/** | ||||||
|  |      * 退出状态码 | ||||||
|  |      */ | ||||||
|  | 	public static $ExitCode = 0; | ||||||
|  | 	/** | ||||||
|  |      * 初始化 | ||||||
|  |      */ | ||||||
|  | 	public static function init($site = '', $method = 'GET'){ | ||||||
|  | 		global $configALL; | ||||||
|  |  | ||||||
|  | 		self::$site = $site; | ||||||
|  | 		self::$method = strtoupper($method); | ||||||
|  |  | ||||||
|  | 		$config = $configALL[$site]; | ||||||
|  | 		self::$cookies = $config['cookie']; | ||||||
|  | 		self::$userAgent = isset($config['userAgent']) && $config['userAgent'] ? $config['userAgent'] : $configALL['default']['userAgent']; | ||||||
|  | 		self::$clients = isset($config['clients']) && $config['clients'] ? $config['clients'] : $configALL['default']['clients']; | ||||||
|  | 		self::$workingMode = isset($config['workingMode']) && $config['workingMode'] ? $config['workingMode'] : 0; | ||||||
|  | 		$watch = isset($config['watch']) && $config['watch'] ? $config['watch'] : $configALL['default']['watch']; | ||||||
|  | 		self::$watch = rtrim($watch,'/') . DS; | ||||||
|  | 		self::$torrentDir = TORRENT_PATH . $site . DS; | ||||||
|  | 		// 建立目录 | ||||||
|  | 		IFile::mkdir(self::$torrentDir); | ||||||
|  | 		 | ||||||
|  | 		self::links(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  |      * 连接远端RPC服务器 | ||||||
|  |      * | ||||||
|  |      * @param string | ||||||
|  |      * @return array | ||||||
|  |      */ | ||||||
|  |     public static function links() | ||||||
|  |     { | ||||||
|  |         if(self::$workingMode === 1 && empty(self::$links)){ | ||||||
|  | 			foreach ( self::$clients as $k => $v ){ | ||||||
|  | 				// 跳过未配置的客户端 | ||||||
|  | 				if (empty($v['username']) || empty( $v['password'])) { | ||||||
|  | 					unset(self::$clients[$k]); | ||||||
|  | 					echo "clients_".$k." 用户名或密码未配置,已跳过 \n\n"; | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				try | ||||||
|  | 				{ | ||||||
|  | 					switch($v['type']){ | ||||||
|  | 						case 'transmission': | ||||||
|  | 							self::$links[$k]['rpc'] = new TransmissionRPC($v['host'], $v['username'], $v['password']); | ||||||
|  | 							$result = self::$links[$k]['rpc']->sstats(); | ||||||
|  | 							print $v['type'].':'.$v['host']." Rpc连接成功 [{$result->result}] \n"; | ||||||
|  | 							break; | ||||||
|  | 						case 'qBittorrent': | ||||||
|  | 							self::$links[$k]['rpc'] = new qBittorrent($v['host'], $v['username'], $v['password']); | ||||||
|  | 							$result = self::$links[$k]['rpc']->appVersion(); | ||||||
|  | 							print $v['type'].':'.$v['host']." Rpc连接成功 [{$result}] \n"; | ||||||
|  | 							break; | ||||||
|  | 						case 'uTorrent': | ||||||
|  | 							self::$links[$k]['rpc'] = new uTorrent($v['host'], $v['username'], $v['password']); | ||||||
|  | 							$result = self::$links[$k]['rpc']->getBuild(); | ||||||
|  | 							print $v['type'].':'.$v['host']." Rpc连接 [{$result}] \n"; | ||||||
|  | 							break; | ||||||
|  | 						default: | ||||||
|  | 							echo '[ERROR] '.$v['type']; | ||||||
|  | 							exit(1); | ||||||
|  | 							break; | ||||||
|  | 					} | ||||||
|  | 					self::$links[$k]['type'] = $v['type']; | ||||||
|  | 					self::$links[$k]['downloadDir'] = $v['downloadDir']; | ||||||
|  | 				} catch (Exception $e) { | ||||||
|  | 					echo '[ERROR] ' . $e->getMessage() . PHP_EOL; | ||||||
|  | 					exit(1); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 添加下载任务 | ||||||
|  | 	 * @param string $torrent 种子元数据 | ||||||
|  | 	 * @param string $save_path 保存路径 | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
|  |     public static function add($torrent, $save_path = '', $extra_options = array()) | ||||||
|  |     { | ||||||
|  | 		switch( (int)self::$workingMode ){ | ||||||
|  | 			case 0:		// watch默认工作模式 | ||||||
|  | 				// 复制到watch目录 | ||||||
|  | 				copy($torrent,$save_path); | ||||||
|  | 				if(is_file($save_path)){ | ||||||
|  | 					print "********watch模式,下载任务添加成功 \n\n"; | ||||||
|  | 					return true; | ||||||
|  | 				}else { | ||||||
|  | 					print "-----watch模式,下载任务添加失败!!! \n\n"; | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 			case 1:		//负载均衡模式 | ||||||
|  | 				try | ||||||
|  | 				{ | ||||||
|  | 					$is_url = false; | ||||||
|  | 					if( (strpos($torrent,'http://')===0) || (strpos($torrent,'https://')===0) || (strpos($torrent,'magnet:?xt=urn:btih:')===0) ){ | ||||||
|  | 						$is_url = true; | ||||||
|  | 					} | ||||||
|  | 					// 负载均衡 | ||||||
|  | 					$rpcKey = self::$RPC_Key; | ||||||
|  | 					echo '选中:负载均衡'.$rpcKey."\n"; | ||||||
|  | 					self::rpcSelect();					 | ||||||
|  | 					// 调试 | ||||||
|  | 					#p($result); | ||||||
|  | 					// 下载服务器类型 判断 | ||||||
|  | 					$type = self::$links[$rpcKey]['type']; | ||||||
|  | 					switch($type){ | ||||||
|  | 						case 'transmission': | ||||||
|  | 							if( $is_url ){ | ||||||
|  | 								echo 'add'; | ||||||
|  | 								$result = self::$links[$rpcKey]['rpc']->add( $torrent, self::$links[$rpcKey]['downloadDir'], $extra_options );			// 种子URL添加下载任务 | ||||||
|  | 							}else{ | ||||||
|  | 								echo 'add_metainfo'; | ||||||
|  | 								$result = self::$links[$rpcKey]['rpc']->add_metainfo( $torrent, self::$links[$rpcKey]['downloadDir'], $extra_options );	// 种子文件添加下载任务 | ||||||
|  | 							} | ||||||
|  | 							$id = $name = ''; | ||||||
|  | 							if( isset($result->arguments->torrent_duplicate) ){ | ||||||
|  | 								$id = $result->arguments->torrent_duplicate->id; | ||||||
|  | 								$name = $result->arguments->torrent_duplicate->name; | ||||||
|  | 							}elseif( isset($result->arguments->torrent_added) ){ | ||||||
|  | 								$id = $result->arguments->torrent_added->id; | ||||||
|  | 								$name = $result->arguments->torrent_added->name; | ||||||
|  | 							} | ||||||
|  | 							if(!$id){ | ||||||
|  | 								print "-----RPC添加种子任务,失败 [{$result->result}] \n\n"; | ||||||
|  | 							}else{ | ||||||
|  | 								print "********RPC添加下载任务成功 [{$result->result}] (id=$id) \n\n"; | ||||||
|  | 								// 新添加的任务,开始 | ||||||
|  | 								self::$links[$rpcKey]['rpc']->start( $id ); | ||||||
|  | 								return true; | ||||||
|  | 							} | ||||||
|  | 							break; | ||||||
|  | 						case 'qBittorrent': | ||||||
|  | 							if( $is_url ){ | ||||||
|  | 								echo 'add'; | ||||||
|  | 								$result = self::$links[$rpcKey]['rpc']->add( $torrent, self::$links[$rpcKey]['downloadDir'], $extra_options );			// 种子URL添加下载任务 | ||||||
|  | 							}else{ | ||||||
|  | 								echo 'add_metainfo'; | ||||||
|  | 								$result = self::$links[$rpcKey]['rpc']->add_metainfo( $torrent, self::$links[$rpcKey]['downloadDir'], $extra_options );	// 种子文件添加下载任务 | ||||||
|  | 							} | ||||||
|  | 							if ($result === 'Ok.') { | ||||||
|  | 								print "********RPC添加下载任务成功 [{$result}] \n\n"; | ||||||
|  | 								return true; | ||||||
|  | 							} else { | ||||||
|  | 								print "-----RPC添加种子任务,失败 [{$result}] \n\n"; | ||||||
|  | 							} | ||||||
|  | 							break; | ||||||
|  | 						default: | ||||||
|  | 							echo '[ERROR] '.$type; | ||||||
|  | 							break; | ||||||
|  | 					} | ||||||
|  | 				} catch (Exception $e) { | ||||||
|  | 					die('[ERROR] ' . $e->getMessage() . PHP_EOL); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 			case 2: | ||||||
|  | 				echo "\n\n"; | ||||||
|  | 				# 暂未开放 | ||||||
|  | 				break; | ||||||
|  | 			default: | ||||||
|  | 				echo "\n\n"; | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 负载均衡 选择算法 | ||||||
|  |      * | ||||||
|  |      * @param | ||||||
|  |      * @return | ||||||
|  |      */ | ||||||
|  |     public static function rpcSelect() | ||||||
|  |     { | ||||||
|  | 		$clientsConut = count(self::$clients); | ||||||
|  | 		if( $clientsConut > 1 ){ | ||||||
|  | 			if( $clientsConut > (self::$RPC_Key+1) ){ | ||||||
|  | 				self::$RPC_Key++; | ||||||
|  | 			}else{ | ||||||
|  | 				self::$RPC_Key = 0; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 种子处理函数 | ||||||
|  | 	 * @param array $data 种子数组 | ||||||
|  | 	 * Array | ||||||
|  | 		( | ||||||
|  | 			[id] => 118632 | ||||||
|  | 			[h1] => CCTV5+ 2019 ATP Men's Tennis Final 20191115B HDTV 1080i H264-HDxxx | ||||||
|  | 			[title] => 央视体育赛事频道 2019年ATP男子网球年终总决赛 单打小组赛 纳达尔VS西西帕斯 20191115[优惠剩余时间:4时13分] | ||||||
|  | 			[details] => https://XXX.me/details.php?id=118632 | ||||||
|  | 			[download] => https://XXX.me/download.php?id=118632 | ||||||
|  | 			[filename] => 118632.torrent | ||||||
|  | 			[type] => 0 | ||||||
|  | 			[sticky] => 1 | ||||||
|  | 			[time] => Array | ||||||
|  | 				( | ||||||
|  | 					[0] => "2019-11-16 20:41:53">4时13分 | ||||||
|  | 					[1] => "2019-11-16 14:41:53">1时<br />46分 | ||||||
|  | 				) | ||||||
|  | 			[comments] => 0 | ||||||
|  | 			[size] => 5232.64MB | ||||||
|  | 			[seeders] => 69 | ||||||
|  | 			[leechers] => 10 | ||||||
|  | 			[completed] => 93 | ||||||
|  | 			[percentage] => 100% | ||||||
|  | 			[owner] => 匿名 | ||||||
|  | 		) | ||||||
|  | 	 * @return | ||||||
|  | 	 */ | ||||||
|  | 	public static function call($data = array()) | ||||||
|  | 	{ | ||||||
|  | 		foreach ($data as $key => $value) { | ||||||
|  | 			// 控制台打印 | ||||||
|  | 			echo '主标题:'.$value['h1']."\n"; | ||||||
|  | 			echo '副标题:'.$value['title']."\n"; | ||||||
|  | 			echo '详情页:'.$value['details']."\n"; | ||||||
|  | 			if ( $value['type'] != 0 ) { | ||||||
|  | 				echo "-----非免费,已忽略! \n\n"; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if ( isset($value['hr']) && ($value['hr'] == 1) ) { | ||||||
|  | 				echo "-----HR种子,已忽略! \n\n"; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			// 下载任务的可选参数 | ||||||
|  | 			$extra_options = array(); | ||||||
|  | 			// 保存的文件名 | ||||||
|  | 			$filename = $value['id'] . '.torrent'; | ||||||
|  | 			// 默认watch工作模式,复制到此目录 | ||||||
|  | 			$to = self::$watch . $filename; | ||||||
|  | 			// 种子完整存放路径 | ||||||
|  | 			$torrentFile = self::$torrentDir . $filename; | ||||||
|  | 			if(is_file($torrentFile)){ | ||||||
|  | 				$fileSize = filesize($torrentFile);		//失败会返回false 或 0(0代表上次下载失败) | ||||||
|  | 				if ( !empty($fileSize) ) { | ||||||
|  | 					//种子已经存在 | ||||||
|  | 					echo '-----存在旧种子:'.$filename."\n\n"; | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				// 删除下载错误的文件 | ||||||
|  | 				IFile::unlink($torrentFile); | ||||||
|  | 			} | ||||||
|  | 			 | ||||||
|  | 			// 调用过滤函数 | ||||||
|  | 			$isFilter = filter(self::$site, $value); | ||||||
|  | 			if ( is_string( $isFilter ) ) { | ||||||
|  | 				echo "-----" .$isFilter. "\n\n"; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			//种子不存在 | ||||||
|  | 			echo '正在下载新种子... '.$value['download']." \n"; | ||||||
|  | 			// 创建文件、下载种子以二进制写入 | ||||||
|  | 			$content = ''; | ||||||
|  | 			$content = download($value['download'], self::$cookies, self::$userAgent, self::$method); | ||||||
|  | 			#p($content); | ||||||
|  | 			// 文件句柄 | ||||||
|  | 			$resource = fopen($torrentFile, "wb"); | ||||||
|  | 			// 成功:返回写入字节数,失败返回false | ||||||
|  | 			$worldsnum = fwrite($resource, $content); | ||||||
|  | 			// 关闭 | ||||||
|  | 			fclose($resource); | ||||||
|  | 			// 判断 | ||||||
|  | 			if(is_bool($worldsnum)){ | ||||||
|  | 				print "种子下载失败!!! \n\n"; | ||||||
|  | 				IFile::unlink($torrentFile); | ||||||
|  | 				continue; | ||||||
|  | 			}else{ | ||||||
|  | 				print "成功下载种子" . $filename . ',共计:' . $worldsnum . "字节 \n"; | ||||||
|  | 				sleep(mt_rand(2,10)); | ||||||
|  | 				$ret = false; | ||||||
|  | 				$rpcKey = self::$RPC_Key; | ||||||
|  | 				switch( (int)self::$workingMode ){ | ||||||
|  | 					case 0:		//默认工作模式 | ||||||
|  | 						$ret = self::add($torrentFile, $to); | ||||||
|  | 						break; | ||||||
|  | 					case 1:		//负载均衡模式 | ||||||
|  | 						$type = self::$links[$rpcKey]['type']; | ||||||
|  | 						// 下载服务器类型 | ||||||
|  | 						switch ($type) { | ||||||
|  | 							case 'transmission': | ||||||
|  | 								# code... | ||||||
|  | 								break; | ||||||
|  | 							case 'qBittorrent': | ||||||
|  | 								$extra_options['name'] = 'torrents'; | ||||||
|  | 								$extra_options['filename'] = $filename; | ||||||
|  | 								$extra_options['autoTMM'] = 'false';	//关闭自动种子管理 | ||||||
|  | 								break; | ||||||
|  | 							default: | ||||||
|  | 								# code... | ||||||
|  | 								break; | ||||||
|  | 						} | ||||||
|  | 						// 种子文件添加下载任务 | ||||||
|  | 						$ret = self::add($content, $to, $extra_options); | ||||||
|  | 						break; | ||||||
|  | 					case 2: | ||||||
|  | 						echo "\n\n"; | ||||||
|  | 						# 暂未开放 | ||||||
|  | 						break; | ||||||
|  | 					default: | ||||||
|  | 						echo "\n\n"; | ||||||
|  | 						break; | ||||||
|  | 				} | ||||||
|  | 				global $configALL; | ||||||
|  | 				if( isset($configALL['iyuu.cn']) && ($ret === true) ){ | ||||||
|  | 					send(self::$site, $value); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										708
									
								
								app/Class/TransmissionRPC.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										708
									
								
								app/Class/TransmissionRPC.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,708 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Transmission bittorrent client/daemon RPC communication class | ||||||
|  |  * Copyright (C) 2010 Johan Adriaans <johan.adriaans@gmail.com>, | ||||||
|  |  *                    Bryce Chidester <bryce@cobryce.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software: you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  *  | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * PHP version specific information | ||||||
|  |  * version_compare() (PHP 4 >= 4.1.0, PHP 5) | ||||||
|  |  * ctype_digit() (PHP 4 >= 4.0.4, PHP 5) | ||||||
|  |  * stream_context_create (PHP 4 >= 4.3.0, PHP 5) | ||||||
|  |  * PHP Class support (PHP 5) (PHP 4 might work, untested) | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * A friendly little version check... | ||||||
|  |  */ | ||||||
|  | if ( version_compare( PHP_VERSION, TransmissionRPC::MIN_PHPVER, '<' ) ) | ||||||
|  |   die( "The TransmissionRPC class requires PHP version {TransmissionRPC::TRANSMISSIONRPC_MIN_PHPVER} or above." . PHP_EOL ); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Transmission bittorrent client/daemon RPC communication class | ||||||
|  |  * | ||||||
|  |  * Usage example: | ||||||
|  |  * <code> | ||||||
|  |  *   $rpc = new TransmissionRPC($rpc_url); | ||||||
|  |  *   $result = $rpc->add_file( $url_or_path_to_torrent, $target_folder ); | ||||||
|  |  * </code> | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | class TransmissionRPC | ||||||
|  | { | ||||||
|  |   /** | ||||||
|  |    * User agent used in all http communication | ||||||
|  |    */ | ||||||
|  |   const HTTP_UA = 'TransmissionRPC for PHP/0.3'; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Minimum PHP version required | ||||||
|  |    * 5.2.10 implemented the required http stream ignore_errors option | ||||||
|  |    */ | ||||||
|  |   const MIN_PHPVER = '5.2.10'; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * The URL to the bittorent client you want to communicate with | ||||||
|  |    * the port (default: 9091) can be set in you Transmission preferences | ||||||
|  |    * @var string | ||||||
|  |    */ | ||||||
|  |   public $url = ''; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * If your Transmission RPC requires authentication, supply username here  | ||||||
|  |    * @var string | ||||||
|  |    */ | ||||||
|  |   public $username = ''; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * If your Transmission RPC requires authentication, supply password here  | ||||||
|  |    * @var string | ||||||
|  |    */ | ||||||
|  |   public $password = ''; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Return results as an array, or an object (default) | ||||||
|  |    * @var bool | ||||||
|  |    */ | ||||||
|  |   public $return_as_array = false; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Print debugging information, default is off | ||||||
|  |    * @var bool | ||||||
|  |    */ | ||||||
|  |   public $debug = false; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Transmission RPC version | ||||||
|  |    * @var int | ||||||
|  |    */ | ||||||
|  |   protected $rpc_version = 0; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Transmission uses a session id to prevent CSRF attacks | ||||||
|  |    * @var string  | ||||||
|  |    */ | ||||||
|  |   protected $session_id = ''; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Default values for stream context | ||||||
|  |    * @var array | ||||||
|  |    */ | ||||||
|  |   private $default_context_opts = array( 'http' => array( | ||||||
|  |                                            'user_agent'  => self::HTTP_UA, | ||||||
|  |                                            'timeout' => '60',	// Don't want to be too slow | ||||||
|  |                                            'ignore_errors' => true,	// Leave the error parsing/handling to the code | ||||||
|  |                                          ) | ||||||
|  |                                        ); | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Constants for torrent status | ||||||
|  |    */ | ||||||
|  |   const TR_STATUS_STOPPED       = 0; | ||||||
|  |   const TR_STATUS_CHECK_WAIT    = 1; | ||||||
|  |   const TR_STATUS_CHECK         = 2; | ||||||
|  |   const TR_STATUS_DOWNLOAD_WAIT = 3; | ||||||
|  |   const TR_STATUS_DOWNLOAD      = 4; | ||||||
|  |   const TR_STATUS_SEED_WAIT     = 5; | ||||||
|  |   const TR_STATUS_SEED          = 6; | ||||||
|  |  | ||||||
|  |   const RPC_LT_14_TR_STATUS_CHECK_WAIT = 1; | ||||||
|  |   const RPC_LT_14_TR_STATUS_CHECK      = 2; | ||||||
|  |   const RPC_LT_14_TR_STATUS_DOWNLOAD   = 4; | ||||||
|  |   const RPC_LT_14_TR_STATUS_SEED       = 8; | ||||||
|  |   const RPC_LT_14_TR_STATUS_STOPPED    = 16; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Start one or more torrents | ||||||
|  |    * | ||||||
|  |    * @param int|array ids A list of transmission torrent ids | ||||||
|  |    */ | ||||||
|  |   public function start ( $ids ) | ||||||
|  |   { | ||||||
|  |     if ( !is_array( $ids ) ) $ids = array( $ids );	// Convert $ids to an array if only a single id was passed | ||||||
|  |     $request = array( "ids" => $ids ); | ||||||
|  |     return $this->request( "torrent-start", $request ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Stop one or more torrents | ||||||
|  |    * | ||||||
|  |    * @param int|array ids A list of transmission torrent ids | ||||||
|  |    */ | ||||||
|  |   public function stop ( $ids ) | ||||||
|  |   { | ||||||
|  |     if ( !is_array( $ids ) ) $ids = array( $ids );	// Convert $ids to an array if only a single id was passed | ||||||
|  |     $request = array( "ids" => $ids ); | ||||||
|  |     return $this->request( "torrent-stop", $request ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Reannounce one or more torrents | ||||||
|  |    * | ||||||
|  |    * @param int|array ids A list of transmission torrent ids | ||||||
|  |    */ | ||||||
|  |   public function reannounce ( $ids ) | ||||||
|  |   { | ||||||
|  |     if ( !is_array( $ids ) ) $ids = array( $ids );	// Convert $ids to an array if only a single id was passed | ||||||
|  |     $request = array( "ids" => $ids ); | ||||||
|  |     return $this->request( "torrent-reannounce", $request ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Verify one or more torrents | ||||||
|  |    * | ||||||
|  |    * @param int|array ids A list of transmission torrent ids | ||||||
|  |    */ | ||||||
|  |   public function verify ( $ids ) | ||||||
|  |   { | ||||||
|  |     if ( !is_array( $ids ) ) $ids = array( $ids );	// Convert $ids to an array if only a single id was passed | ||||||
|  |     $request = array( "ids" => $ids ); | ||||||
|  |     return $this->request( "torrent-verify", $request ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Get information on torrents in transmission, if the ids parameter is  | ||||||
|  |    * empty all torrents will be returned. The fields array can be used to return certain | ||||||
|  |    * fields. Default fields are: "id", "name", "status", "doneDate", "haveValid", "totalSize". | ||||||
|  |    * See https://github.com/transmission/transmission/blob/2.9x/extras/rpc-spec.txt for available fields | ||||||
|  |    * | ||||||
|  |    * @param array fields An array of return fields | ||||||
|  |    * @param int|array ids A list of transmission torrent ids | ||||||
|  |    *     | ||||||
|  |     Request:  | ||||||
|  |       { | ||||||
|  |          "arguments": { | ||||||
|  |              "fields": [ "id", "name", "totalSize" ], | ||||||
|  |              "ids": [ 7, 10 ] | ||||||
|  |          }, | ||||||
|  |          "method": "torrent-get", | ||||||
|  |          "tag": 39693 | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     Response: | ||||||
|  |       { | ||||||
|  |          "arguments": { | ||||||
|  |             "torrents": [  | ||||||
|  |                {  | ||||||
|  |                    "id": 10, | ||||||
|  |                    "name": "Fedora x86_64 DVD", | ||||||
|  |                    "totalSize": 34983493932, | ||||||
|  |                }, | ||||||
|  |                { | ||||||
|  |                    "id": 7, | ||||||
|  |                    "name": "Ubuntu x86_64 DVD", | ||||||
|  |                    "totalSize", 9923890123, | ||||||
|  |                }  | ||||||
|  |             ] | ||||||
|  |          }, | ||||||
|  |          "result": "success", | ||||||
|  |          "tag": 39693 | ||||||
|  |       } | ||||||
|  |    */ | ||||||
|  |   public function get ( $ids = array(), $fields = array() ) | ||||||
|  |   { | ||||||
|  |     if ( !is_array( $ids ) ) $ids = array( $ids );	// Convert $ids to an array if only a single id was passed | ||||||
|  |     if ( count( $fields ) == 0 ) $fields = array( "id", "name", "status", "doneDate", "haveValid", "totalSize" );	// Defaults | ||||||
|  |     $request = array( | ||||||
|  |       "fields" => $fields, | ||||||
|  |       "ids" => $ids | ||||||
|  |     ); | ||||||
|  |     return $this->request( "torrent-get", $request ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Set properties on one or more torrents, available fields are: | ||||||
|  |    *   "bandwidthPriority"   | number     this torrent's bandwidth tr_priority_t | ||||||
|  |    *   "downloadLimit"       | number     maximum download speed (in K/s) | ||||||
|  |    *   "downloadLimited"     | boolean    true if "downloadLimit" is honored | ||||||
|  |    *   "files-wanted"        | array      indices of file(s) to download | ||||||
|  |    *   "files-unwanted"      | array      indices of file(s) to not download | ||||||
|  |    *   "honorsSessionLimits" | boolean    true if session upload limits are honored | ||||||
|  |    *   "ids"                 | array      torrent list, as described in 3.1 | ||||||
|  |    *   "location"            | string     new location of the torrent's content | ||||||
|  |    *   "peer-limit"          | number     maximum number of peers | ||||||
|  |    *   "priority-high"       | array      indices of high-priority file(s) | ||||||
|  |    *   "priority-low"        | array      indices of low-priority file(s) | ||||||
|  |    *   "priority-normal"     | array      indices of normal-priority file(s) | ||||||
|  |    *   "seedRatioLimit"      | double     session seeding ratio | ||||||
|  |    *   "seedRatioMode"       | number     which ratio to use.  See tr_ratiolimit | ||||||
|  |    *   "uploadLimit"         | number     maximum upload speed (in K/s) | ||||||
|  |    *   "uploadLimited"       | boolean    true if "uploadLimit" is honored | ||||||
|  |    * See https://github.com/transmission/transmission/blob/2.9x/extras/rpc-spec.txt for more information | ||||||
|  |    * | ||||||
|  |    * @param array arguments An associative array of arguments to set | ||||||
|  |    * @param int|array ids A list of transmission torrent ids | ||||||
|  |    */   | ||||||
|  |   public function set ( $ids = array(), $arguments = array() ) | ||||||
|  |   { | ||||||
|  |     // See https://github.com/transmission/transmission/blob/2.9x/extras/rpc-spec.txt for available fields | ||||||
|  |     if ( !is_array( $ids ) ) $ids = array( $ids );	// Convert $ids to an array if only a single id was passed | ||||||
|  |     if ( !isset( $arguments['ids'] ) ) $arguments['ids'] = $ids;	// Any $ids given in $arguments overrides the method parameter | ||||||
|  |     return $this->request( "torrent-set", $arguments ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Add a new torrent | ||||||
|  |    * | ||||||
|  |    * Available extra options: | ||||||
|  |    *  key                  | value type & description | ||||||
|  |    *  ---------------------+------------------------------------------------- | ||||||
|  |    *  "download-dir"       | string      path to download the torrent to | ||||||
|  |    *  "filename"           | string      filename or URL of the .torrent file | ||||||
|  |    *  "metainfo"           | string      base64-encoded .torrent content | ||||||
|  |    *  "paused"             | boolean     if true, don't start the torrent | ||||||
|  |    *  "peer-limit"         | number      maximum number of peers | ||||||
|  |    *  "bandwidthPriority"  | number      torrent's bandwidth tr_priority_t | ||||||
|  |    *  "files-wanted"       | array       indices of file(s) to download | ||||||
|  |    *  "files-unwanted"     | array       indices of file(s) to not download | ||||||
|  |    *  "priority-high"      | array       indices of high-priority file(s) | ||||||
|  |    *  "priority-low"       | array       indices of low-priority file(s) | ||||||
|  |    *  "priority-normal"    | array       indices of normal-priority file(s) | ||||||
|  |    *   | ||||||
|  |    *   Either "filename" OR "metainfo" MUST be included. | ||||||
|  |    *     All other arguments are optional.    | ||||||
|  |    * | ||||||
|  |    * @param torrent_location The URL or path to the torrent file | ||||||
|  |    * @param save_path Folder to save torrent in | ||||||
|  |    * @param extra options Optional extra torrent options | ||||||
|  |    */ | ||||||
|  |   public function add_file ( $torrent_location, $save_path = '', $extra_options = array() ) | ||||||
|  |   { | ||||||
|  |     if(!empty($save_path)) $extra_options['download-dir'] = $save_path; | ||||||
|  |     $extra_options['filename'] = $torrent_location; | ||||||
|  |      | ||||||
|  |     return $this->request( "torrent-add", $extra_options ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Add a torrent using the raw torrent data | ||||||
|  |    * | ||||||
|  |    * @param torrent_metainfo The raw, unencoded contents (metainfo) of a torrent | ||||||
|  |    * @param save_path Folder to save torrent in | ||||||
|  |    * @param extra options Optional extra torrent options | ||||||
|  |    */ | ||||||
|  |   public function add_metainfo ( $torrent_metainfo, $save_path = '', $extra_options = array() ) | ||||||
|  |   { | ||||||
|  |     $extra_options['download-dir'] = $save_path; | ||||||
|  |     $extra_options['metainfo'] = base64_encode( $torrent_metainfo ); | ||||||
|  |      | ||||||
|  |     return $this->request( "torrent-add", $extra_options ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* Add a new torrent using a file path or a URL (For backwards compatibility) | ||||||
|  |    * @param torrent_location The URL or path to the torrent file | ||||||
|  |    * @param save_path Folder to save torrent in | ||||||
|  |    * @param extra options Optional extra torrent options | ||||||
|  |    */ | ||||||
|  |   public function add ( $torrent_location, $save_path = '', $extra_options = array() ) | ||||||
|  |   { | ||||||
|  |     return $this->add_file( $torrent_location, $save_path, $extra_options ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Remove torrent from transmission | ||||||
|  |    * | ||||||
|  |    * @param bool delete_local_data Also remove local data? | ||||||
|  |    * @param int|array ids A list of transmission torrent ids | ||||||
|  |    */ | ||||||
|  |   public function remove ( $ids, $delete_local_data = false ) | ||||||
|  |   { | ||||||
|  |     if ( !is_array( $ids ) ) $ids = array( $ids );	// Convert $ids to an array if only a single id was passed | ||||||
|  |     $request = array( | ||||||
|  |       "ids" => $ids, | ||||||
|  |       "delete-local-data" => $delete_local_data | ||||||
|  |     ); | ||||||
|  |     return $this->request( "torrent-remove", $request ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Move local storage location | ||||||
|  |    * | ||||||
|  |    * @param int|array ids A list of transmission torrent ids | ||||||
|  |    * @param string target_location The new storage location | ||||||
|  |    * @param string move_existing_data Move existing data or scan new location for available data | ||||||
|  |    */ | ||||||
|  |   public function move ( $ids, $target_location, $move_existing_data = true ) | ||||||
|  |   { | ||||||
|  |     if ( !is_array( $ids ) ) $ids = array( $ids );	// Convert $ids to an array if only a single id was passed | ||||||
|  |     $request = array( | ||||||
|  |       "ids" => $ids, | ||||||
|  |       "location" => $target_location, | ||||||
|  |       "move" => $move_existing_data | ||||||
|  |     ); | ||||||
|  |     return $this->request( "torrent-set-location", $request );   | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   /** | ||||||
|  |    * 3.7.  Renaming a Torrent's Path | ||||||
|  |    *  | ||||||
|  |    * Method name: "torrent-rename-path" | ||||||
|  |    *  | ||||||
|  |    * For more information on the use of this function, see the transmission.h | ||||||
|  |    * documentation of tr_torrentRenamePath(). In particular, note that if this | ||||||
|  |    * call succeeds you'll want to update the torrent's "files" and "name" field | ||||||
|  |    * with torrent-get. | ||||||
|  |    * | ||||||
|  |    * Request arguments: | ||||||
|  |    *  | ||||||
|  |    * string                           | value type & description | ||||||
|  |    * ---------------------------------+------------------------------------------------- | ||||||
|  |    * "ids"                            | array      the torrent torrent list, as described in 3.1 | ||||||
|  |    *                                  |            (must only be 1 torrent) | ||||||
|  |    * "path"                           | string     the path to the file or folder that will be renamed | ||||||
|  |    * "name"                           | string     the file or folder's new name | ||||||
|  |   | ||||||
|  |    * Response arguments: "path", "name", and "id", holding the torrent ID integer | ||||||
|  |    * | ||||||
|  |    * @param int|array ids A 1-element list of transmission torrent ids | ||||||
|  |    * @param string path The path to the file or folder that will be renamed | ||||||
|  |    * @param string name The file or folder's new name | ||||||
|  |    */ | ||||||
|  |   public function rename ( $ids, $path, $name ) | ||||||
|  |   { | ||||||
|  |     if ( !is_array( $ids ) ) $ids = array( $ids );  // Convert $id to an array if only a single id was passed | ||||||
|  |     if ( count( $ids ) !== 1 ) { | ||||||
|  |       throw new TransmissionRPCException( 'A single id is accepted', TransmissionRPCException::E_INVALIDARG ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $request = array( | ||||||
|  |       "ids" => $ids, | ||||||
|  |       "path" => $path, | ||||||
|  |       "name" => $name | ||||||
|  |     ); | ||||||
|  |     return $this->request( "torrent-rename-path", $request );   | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Retrieve session statistics | ||||||
|  |    * | ||||||
|  |    * @returns array of statistics | ||||||
|  |    */ | ||||||
|  |   public function sstats ( ) | ||||||
|  |   { | ||||||
|  |     return $this->request( "session-stats", array() ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Retrieve all session variables | ||||||
|  |    * | ||||||
|  |    * @returns array of session information | ||||||
|  |    */ | ||||||
|  |   public function sget ( ) | ||||||
|  |   { | ||||||
|  |     return $this->request( "session-get", array() ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Set session variable(s) | ||||||
|  |    * | ||||||
|  |    * @param array of session variables to set | ||||||
|  |    */ | ||||||
|  |   public function sset ( $arguments ) | ||||||
|  |   { | ||||||
|  |     return $this->request( "session-set", $arguments ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Return the interpretation of the torrent status | ||||||
|  |    * | ||||||
|  |    * @param int The integer "torrent status" | ||||||
|  |    * @returns string The translated meaning | ||||||
|  |    */   | ||||||
|  |   public function getStatusString ( $intstatus ) | ||||||
|  |   { | ||||||
|  |     if($this->rpc_version < 14){ | ||||||
|  |       if( $intstatus == self::RPC_LT_14_TR_STATUS_CHECK_WAIT ) | ||||||
|  |         return "Waiting to verify local files"; | ||||||
|  |       if( $intstatus == self::RPC_LT_14_TR_STATUS_CHECK ) | ||||||
|  |         return "Verifying local files"; | ||||||
|  |       if( $intstatus == self::RPC_LT_14_TR_STATUS_DOWNLOAD ) | ||||||
|  |         return "Downloading"; | ||||||
|  |       if( $intstatus == self::RPC_LT_14_TR_STATUS_SEED ) | ||||||
|  |         return "Seeding"; | ||||||
|  |       if( $intstatus == self::RPC_LT_14_TR_STATUS_STOPPED ) | ||||||
|  |         return "Stopped"; | ||||||
|  |     }else{ | ||||||
|  |       if( $intstatus == self::TR_STATUS_CHECK_WAIT ) | ||||||
|  |         return "Waiting to verify local files"; | ||||||
|  |       if( $intstatus == self::TR_STATUS_CHECK ) | ||||||
|  |         return "Verifying local files"; | ||||||
|  |       if( $intstatus == self::TR_STATUS_DOWNLOAD ) | ||||||
|  |         return "Downloading"; | ||||||
|  |       if( $intstatus == self::TR_STATUS_SEED ) | ||||||
|  |         return "Seeding"; | ||||||
|  |       if( $intstatus == self::TR_STATUS_STOPPED ) | ||||||
|  |         return "Stopped"; | ||||||
|  |       if( $intstatus == self::TR_STATUS_SEED_WAIT ) | ||||||
|  |         return "Queued for seeding"; | ||||||
|  |       if( $intstatus == self::TR_STATUS_DOWNLOAD_WAIT ) | ||||||
|  |         return "Queued for download"; | ||||||
|  |     } | ||||||
|  |     return "Unknown"; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Here be dragons (Internal methods) | ||||||
|  |    */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Clean up the request array. Removes any empty fields from the request | ||||||
|  |    * | ||||||
|  |    * @param array array The request associative array to clean | ||||||
|  |    * @returns array The cleaned array | ||||||
|  |    */   | ||||||
|  |   protected function cleanRequestData ( $array ) | ||||||
|  |   { | ||||||
|  |     if ( !is_array( $array ) || count( $array ) == 0 ) return null;	// Nothing to clean | ||||||
|  |     setlocale( LC_NUMERIC, 'en_US.utf8' );	// Override the locale - if the system locale is wrong, then 12.34 will encode as 12,34 which is invalid JSON | ||||||
|  |     foreach ( $array as $index => $value ) | ||||||
|  |     { | ||||||
|  |       if( is_object( $value ) ) $array[$index] = $value->toArray();	// Convert objects to arrays so they can be JSON encoded | ||||||
|  |       if( is_array( $value ) ) $array[$index] = $this->cleanRequestData( $value );	// Recursion | ||||||
|  |       if( empty( $value ) && $value !== 0 )	// Remove empty members | ||||||
|  |       { | ||||||
|  |         unset( $array[$index] ); | ||||||
|  |         continue; // Skip the rest of the tests - they may re-add the element. | ||||||
|  |       } | ||||||
|  |       if( is_numeric( $value ) ) $array[$index] = $value+0;	// Force type-casting for proper JSON encoding (+0 is a cheap way to maintain int/float/etc) | ||||||
|  |       if( is_bool( $value ) ) $array[$index] = ( $value ? 1 : 0);	// Store boolean values as 0 or 1 | ||||||
|  |       if( is_string( $value ) ) { | ||||||
|  |         if ( mb_detect_encoding($value,"auto") !== 'UTF-8' ) { | ||||||
|  |           $array[$index] = mb_convert_encoding($value, "UTF-8"); | ||||||
|  |           //utf8_encode( $value );	// Make sure all data is UTF-8 encoded for Transmission | ||||||
|  |         }       | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return $array; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Clean up the result object. Replaces all minus(-) characters in the object properties with underscores | ||||||
|  |    * and converts any object with any all-digit property names to an array. | ||||||
|  |    * | ||||||
|  |    * @param object The request result to clean | ||||||
|  |    * @returns array The cleaned object | ||||||
|  |    */   | ||||||
|  |   protected function cleanResultObject ( $object ) | ||||||
|  |   { | ||||||
|  |     // Prepare and cast object to array | ||||||
|  |     $return_as_array = false; | ||||||
|  |     $array = $object; | ||||||
|  |     if ( !is_array( $array ) ) $array = (array) $array; | ||||||
|  |     foreach ( $array as $index => $value ) | ||||||
|  |     { | ||||||
|  |       if( is_array( $array[$index] ) || is_object( $array[$index] ) ) | ||||||
|  |       { | ||||||
|  |         $array[$index] = $this->cleanResultObject( $array[$index] );	// Recursion | ||||||
|  |       } | ||||||
|  |       if ( strstr( $index, '-' ) ) | ||||||
|  |       { | ||||||
|  |         $valid_index = str_replace( '-', '_', $index ); | ||||||
|  |         $array[$valid_index] = $array[$index];  | ||||||
|  |         unset( $array[$index] ); | ||||||
|  |         $index = $valid_index; | ||||||
|  |       } | ||||||
|  |       // Might be an array, check index for digits, if so, an array should be returned | ||||||
|  |       if ( ctype_digit( (string) $index ) ) { $return_as_array = true; } | ||||||
|  |       if ( empty( $value ) ) unset( $array[$index] ); | ||||||
|  |     } | ||||||
|  |     // Return array cast to object | ||||||
|  |     return $return_as_array ? $array : (object) $array; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   /** | ||||||
|  |    * 执行 rpc 请求 | ||||||
|  |    * | ||||||
|  |    * @param $method 请求类型/方法, 详见 $this->allowMethods | ||||||
|  |    * @param array $arguments 附加参数, 可选 | ||||||
|  |    * @return mixed | ||||||
|  |    */ | ||||||
|  |   protected function request($method, $arguments = array()) | ||||||
|  |   { | ||||||
|  |     // Check the parameters | ||||||
|  |     if ( !is_scalar( $method ) ) | ||||||
|  |       throw new TransmissionRPCException( 'Method name has no scalar value', TransmissionRPCException::E_INVALIDARG ); | ||||||
|  |     if ( !is_array( $arguments ) ) | ||||||
|  |       throw new TransmissionRPCException( 'Arguments must be given as array', TransmissionRPCException::E_INVALIDARG ); | ||||||
|  |      | ||||||
|  |     $arguments = $this->cleanRequestData( $arguments );	// Sanitize input | ||||||
|  |      | ||||||
|  |     // Grab the X-Transmission-Session-Id if we don't have it already | ||||||
|  |     if( !$this->session_id ) | ||||||
|  |       if( !$this->GetSessionID() ) | ||||||
|  |         throw new TransmissionRPCException( 'Unable to acquire X-Transmission-Session-Id', TransmissionRPCException::E_SESSIONID ); | ||||||
|  |  | ||||||
|  |     $data = array( | ||||||
|  |         'method' => $method, | ||||||
|  |         'arguments' => $arguments | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     $header = array( | ||||||
|  |         'Content-Type: application/json', | ||||||
|  |         'Authorization: Basic '.base64_encode(sprintf("%s:%s", $this->username, $this->password)), | ||||||
|  |         'X-Transmission-Session-Id: '.$this->session_id | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     $ch = curl_init(); | ||||||
|  |     curl_setopt($ch, CURLOPT_URL, $this->url); | ||||||
|  |     curl_setopt($ch, CURLOPT_HTTPHEADER, $header); | ||||||
|  |     curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); | ||||||
|  |     curl_setopt($ch, CURLOPT_USERPWD, $this->username.':'.$this->password); | ||||||
|  |     curl_setopt($ch, CURLOPT_HEADER, false); | ||||||
|  |     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | ||||||
|  |     curl_setopt($ch, CURLOPT_POST, true); | ||||||
|  |     curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); | ||||||
|  |     curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); | ||||||
|  |     curl_setopt($ch, CURLOPT_TIMEOUT, 600); | ||||||
|  |     $content = curl_exec($ch); | ||||||
|  |     curl_close($ch); | ||||||
|  |  | ||||||
|  |     if (!$content)  $content = json_encode(array('result' => 'failed')); | ||||||
|  |     return $this->return_as_array ? json_decode( $content, true ) : $this->cleanResultObject( json_decode( $content ) );	// Return the sanitized result | ||||||
|  |   } | ||||||
|  |   /** | ||||||
|  |    * Performs an empty GET on the Transmission RPC to get the X-Transmission-Session-Id | ||||||
|  |    * and store it in $this->session_id | ||||||
|  |    * | ||||||
|  |    * @return string | ||||||
|  |    */ | ||||||
|  |   public function GetSessionID() | ||||||
|  |   { | ||||||
|  |     if( !$this->url ) | ||||||
|  |       throw new TransmissionRPCException( "Class must be initialized before GetSessionID() can be called.", TransmissionRPCException::E_INVALIDARG ); | ||||||
|  |      | ||||||
|  |     // Setup the context | ||||||
|  |     $contextopts = $this->default_context_opts;	// Start with the defaults | ||||||
|  |      | ||||||
|  |     // Make sure it's blank/empty (reset) | ||||||
|  |     $this->session_id = null; | ||||||
|  |      | ||||||
|  |     // Setup authentication (if provided) | ||||||
|  |     if ( $this->username && $this->password ) | ||||||
|  |       $contextopts['http']['header'] = sprintf( "Authorization: Basic %s\r\n", base64_encode( $this->username.':'.$this->password ) ); | ||||||
|  |      | ||||||
|  |     if( $this->debug ) echo "TRANSMISSIONRPC_DEBUG:: GetSessionID():: Stream context created with options:". | ||||||
|  |                             PHP_EOL . print_r( $contextopts, true ); | ||||||
|  |      | ||||||
|  |     $context  = stream_context_create( $contextopts );	// Create the context for this request | ||||||
|  |     if ( ! $fp = @fopen( $this->url, 'r', false, $context ) )	// Open a filepointer to the data, and use fgets to get the result | ||||||
|  |       throw new TransmissionRPCException( 'Unable to connect to '.$this->url, TransmissionRPCException::E_CONNECTION ); | ||||||
|  |      | ||||||
|  |     // Check the response (headers etc) | ||||||
|  |     $stream_meta = stream_get_meta_data( $fp ); | ||||||
|  |     fclose( $fp ); | ||||||
|  |     if( $this->debug ) echo "TRANSMISSIONRPC_DEBUG:: GetSessionID():: Stream meta info: ". | ||||||
|  |                             PHP_EOL . print_r( $stream_meta, true ); | ||||||
|  |     if( $stream_meta['timed_out'] ) | ||||||
|  |       throw new TransmissionRPCException( "Timed out connecting to {$this->url}", TransmissionRPCException::E_CONNECTION ); | ||||||
|  |     if( substr( $stream_meta['wrapper_data'][0], 9, 3 ) == "401" ) | ||||||
|  |       throw new TransmissionRPCException( "Invalid username/password.", TransmissionRPCException::E_AUTHENTICATION ); | ||||||
|  |     elseif( substr( $stream_meta['wrapper_data'][0], 9, 3 ) == "409" )	// This is what we're hoping to find | ||||||
|  |     { | ||||||
|  |       // Loop through the returned headers and extract the X-Transmission-Session-Id | ||||||
|  |       foreach( $stream_meta['wrapper_data'] as $header ) | ||||||
|  |       { | ||||||
|  |         if( strpos( $header, 'X-Transmission-Session-Id: ' ) === 0 ) | ||||||
|  |         { | ||||||
|  |           if( $this->debug ) echo "TRANSMISSIONRPC_DEBUG:: GetSessionID():: Session-Id header: ". | ||||||
|  |                                   PHP_EOL . print_r( $header, true ); | ||||||
|  |           $this->session_id = trim( substr( $header, 27 ) ); | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       if( ! $this->session_id ) {	// Didn't find a session_id | ||||||
|  |         throw new TransmissionRPCException( "Unable to retrieve X-Transmission-Session-Id", TransmissionRPCException::E_SESSIONID ); | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       throw new TransmissionRPCException( "Unexpected response from Transmission RPC: ".$stream_meta['wrapper_data'][0] ); | ||||||
|  |     } | ||||||
|  |     return $this->session_id; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Takes the connection parameters | ||||||
|  |    * | ||||||
|  |    * TODO: Sanitize username, password, and URL | ||||||
|  |    * | ||||||
|  |    * @param string $url | ||||||
|  |    * @param string $username | ||||||
|  |    * @param string $password | ||||||
|  |    */ | ||||||
|  |   public function __construct( $url = 'http://localhost:9091/transmission/rpc', $username = null, $password = null, $return_as_array = false ) | ||||||
|  |   { | ||||||
|  |     // server URL | ||||||
|  |     $this->url = $url; | ||||||
|  |      | ||||||
|  |     // Username & password | ||||||
|  |     $this->username = $username; | ||||||
|  |     $this->password = $password; | ||||||
|  |      | ||||||
|  |     // Get the Transmission RPC_version | ||||||
|  |     $this->rpc_version = self::sget()->arguments->rpc_version; | ||||||
|  |      | ||||||
|  |     // Return As Array | ||||||
|  |     $this->return_as_array = $return_as_array; | ||||||
|  |      | ||||||
|  |     // Reset X-Transmission-Session-Id so we (re)fetch one | ||||||
|  |     $this->session_id = null; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This is the type of exception the TransmissionRPC class will throw | ||||||
|  |  */ | ||||||
|  | class TransmissionRPCException extends Exception | ||||||
|  | { | ||||||
|  |   /** | ||||||
|  |    * Exception: Invalid arguments | ||||||
|  |    */ | ||||||
|  |   const E_INVALIDARG = -1; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Exception: Invalid Session-Id | ||||||
|  |    */ | ||||||
|  |   const E_SESSIONID = -2; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Exception: Error while connecting | ||||||
|  |    */ | ||||||
|  |   const E_CONNECTION = -3; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Exception: Error 401 returned, unauthorized | ||||||
|  |    */ | ||||||
|  |   const E_AUTHENTICATION = -4; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Exception constructor | ||||||
|  |    */ | ||||||
|  |   public function __construct( $message = null, $code = 0, Exception $previous = null ) | ||||||
|  |   { | ||||||
|  |     // PHP version 5.3.0 and above support Exception linking | ||||||
|  |     if ( version_compare( PHP_VERSION, '5.3.0', '>=' ) ) | ||||||
|  |       parent::__construct( $message, $code, $previous ); | ||||||
|  |     else | ||||||
|  |       parent::__construct( $message, $code ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ?> | ||||||
							
								
								
									
										288
									
								
								app/Class/qBittorrent.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								app/Class/qBittorrent.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,288 @@ | |||||||
|  | <?php | ||||||
|  | use Curl\Curl; | ||||||
|  | /** | ||||||
|  |  * https://github.com/qbittorrent/qBittorrent/wiki/Web-API-Documentation | ||||||
|  |  */ | ||||||
|  | class qBittorrent | ||||||
|  | { | ||||||
|  |     private $debug; | ||||||
|  |     private $url; | ||||||
|  |     private $api_version; | ||||||
|  |     private $curl; | ||||||
|  |     protected $delimiter; | ||||||
|  |     private $endpoints = [ | ||||||
|  |         'login' => [ | ||||||
|  |             '1' => '/login', | ||||||
|  |             '2' => '/api/v2/auth/login' | ||||||
|  |         ], | ||||||
|  |         'app_version' => [ | ||||||
|  |             '1' => '/version/qbittorrent', | ||||||
|  |             '2' => '/api/v2/app/version' | ||||||
|  |         ], | ||||||
|  |         'api_version' => [ | ||||||
|  |             '1' => '/version/api', | ||||||
|  |             '2' => '/api/v2/app/webapiVersion' | ||||||
|  |         ], | ||||||
|  |         'build_info' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/app/buildInfo' | ||||||
|  |         ], | ||||||
|  |         'preferences' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/app/preferences' | ||||||
|  |         ], | ||||||
|  |         'setPreferences' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/app/setPreferences' | ||||||
|  |         ], | ||||||
|  | 		'defaultSavePath' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/app/defaultSavePath' | ||||||
|  |         ], | ||||||
|  |         'torrent_list' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/torrents/info' | ||||||
|  |         ], | ||||||
|  |         'torrent_add' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/torrents/add' | ||||||
|  |         ], | ||||||
|  |         'torrent_delete' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/torrents/delete' | ||||||
|  |         ], | ||||||
|  |         'torrent_pause' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/torrents/pause' | ||||||
|  |         ], | ||||||
|  |         'torrent_resume' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/torrents/resume' | ||||||
|  |         ], | ||||||
|  |         'set_torrent_location' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/torrents/setLocation' | ||||||
|  |         ], | ||||||
|  |         'maindata' => [ | ||||||
|  |             '1' => null, | ||||||
|  |             '2' => '/api/v2/sync/maindata' | ||||||
|  |         ] | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|  |     public function __construct($url='', $username='', $password='', $api_version = 2, $debug = false) | ||||||
|  |     { | ||||||
|  |         $this->debug = $debug; | ||||||
|  |         $this->url = rtrim($url,'/'); | ||||||
|  |         $this->username = $username; | ||||||
|  |         $this->password = $password; | ||||||
|  |         $this->api_version = $api_version; | ||||||
|  |         $this->curl = new Curl(); | ||||||
|  |         $this->curl->setOpt(CURLOPT_SSL_VERIFYPEER, false); // 禁止验证证书 | ||||||
|  |         $this->curl->setOpt(CURLOPT_SSL_VERIFYHOST, false); // 不检查证书 | ||||||
|  |         $this->curl->setOpt(CURLOPT_CONNECTTIMEOUT, 60);    // 超时 | ||||||
|  |         $this->curl->setOpt(CURLOPT_TIMEOUT, 600);          // 超时 | ||||||
|  |         // Authenticate and get cookie, else throw exception | ||||||
|  |         if (!$this->authenticate()) { | ||||||
|  |             throw new \Exception("Unable to authenticate with Web Api."); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function appVersion() | ||||||
|  |     { | ||||||
|  |         return $this->getData('app_version'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function apiVersion() | ||||||
|  |     { | ||||||
|  |         return $this->getData('api_version'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function buildInfo() | ||||||
|  |     { | ||||||
|  |         return $this->getData('build_info'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function preferences($data = null) | ||||||
|  |     { | ||||||
|  |         if (!empty($data)) { | ||||||
|  |             return $this->postData('setPreferences', ['json' => json_encode($data)]); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $this->getData('preferences'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function torrentList() | ||||||
|  |     { | ||||||
|  |         return $this->getData('torrent_list'); | ||||||
|  |     } | ||||||
|  |     /** | ||||||
|  |      * @param array $extra_options | ||||||
|  |         array( | ||||||
|  |             'urls'    =>  '', | ||||||
|  |             'savepath'    =>  '', | ||||||
|  |             'cookie'    =>  '', | ||||||
|  |             'category'    =>  '', | ||||||
|  |             'skip_checking'    =>  true, | ||||||
|  |             'paused'    =>  true, | ||||||
|  |             'root_folder'    =>  true, | ||||||
|  |         ) | ||||||
|  |      *  @return array | ||||||
|  |      */ | ||||||
|  |     public function add($torrent_url, $save_path = '', $extra_options = array()) | ||||||
|  |     { | ||||||
|  | 		if(!empty($save_path)) $extra_options['savepath'] = $save_path; | ||||||
|  |         $extra_options['urls'] = $torrent_url; | ||||||
|  |         #$extra_options['skip_checking'] = 'true';    //跳校验 | ||||||
|  |         // 关键 上传文件流 multipart/form-data【严格按照api文档编写】 | ||||||
|  |         $post_data = $this->buildUrls($extra_options); | ||||||
|  |         #p($post_data); | ||||||
|  |         // 设置请求头 | ||||||
|  |         $this->curl->setHeader('Content-Type','multipart/form-data; boundary='.$this->delimiter); | ||||||
|  |         $this->curl->setHeader('Content-Length',strlen($post_data)); | ||||||
|  |         return $this->postData('torrent_add', $post_data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | 	public function add_metainfo($torrent_metainfo, $save_path = '', $extra_options = array()) | ||||||
|  |     { | ||||||
|  | 		if(!empty($save_path)) $extra_options['savepath'] = $save_path; | ||||||
|  |         $extra_options['torrents'] = $torrent_metainfo; | ||||||
|  |         #$extra_options['skip_checking'] = 'true';    //跳校验 | ||||||
|  |         // 关键 上传文件流 multipart/form-data【严格按照api文档编写】 | ||||||
|  |         $post_data = $this->buildData($extra_options); | ||||||
|  |         #p($post_data); | ||||||
|  |         // 设置请求头 | ||||||
|  |         $this->curl->setHeader('Content-Type','multipart/form-data; boundary='.$this->delimiter); | ||||||
|  |         $this->curl->setHeader('Content-Length',strlen($post_data)); | ||||||
|  |         return $this->postData('torrent_add', $post_data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function torrentDelete($hash='', $deleteFiles = false) | ||||||
|  |     { | ||||||
|  |         return $this->postData('torrent_delete', ['hashes' => $hash, 'deleteFiles' => $deleteFiles ? 'true':'false']); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function torrentDeleteAll($deleteFiles = false) | ||||||
|  |     { | ||||||
|  |         $torrents = json_decode($this->torrentList()); | ||||||
|  |         $response = ''; | ||||||
|  |         foreach ($torrents as $torrent) { | ||||||
|  |             $response .= $this->torrentDelete($torrent->hash, $deleteFiles); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $response; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function torrentPause($hash) | ||||||
|  |     { | ||||||
|  |         return $this->postData('torrent_pause', ['hashes' => $hash]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function torrentResume($hash) | ||||||
|  |     { | ||||||
|  |         return $this->postData('torrent_resume', ['hashes' => $hash]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function setTorrentLocation($hash, $location) | ||||||
|  |     { | ||||||
|  |         return $this->postData('set_torrent_location', ['hashes' => $hash, 'location' => $location]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function getData($endpoint) | ||||||
|  |     { | ||||||
|  |         $this->curl->get($this->url . $this->endpoints[$endpoint][$this->api_version]); | ||||||
|  |  | ||||||
|  |         if ($this->debug) { | ||||||
|  |             var_dump($this->curl->request_headers); | ||||||
|  |             var_dump($this->curl->response_headers); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if ($this->curl->error) { | ||||||
|  |             return $this->errorMessage(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $this->curl->response; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function postData($endpoint, $data) | ||||||
|  |     { | ||||||
|  |         $this->curl->post($this->url . $this->endpoints[$endpoint][$this->api_version], $data); | ||||||
|  |  | ||||||
|  |         if ($this->debug) { | ||||||
|  |             var_dump($this->curl->request_headers); | ||||||
|  |             var_dump($this->curl->response_headers); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if ($this->curl->error) { | ||||||
|  |             return $this->errorMessage(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $this->curl->response; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function authenticate() | ||||||
|  |     { | ||||||
|  |         $this->curl->post($this->url . $this->endpoints['login'][$this->api_version], [ | ||||||
|  |             'username' => $this->username, | ||||||
|  |             'password' => $this->password | ||||||
|  |         ]); | ||||||
|  |  | ||||||
|  |         if ($this->debug) { | ||||||
|  |             var_dump($this->curl->request_headers); | ||||||
|  |             var_dump($this->curl->response_headers); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Find authentication cookie and set in curl connection | ||||||
|  |         foreach ($this->curl->response_headers as $header) { | ||||||
|  |             if (preg_match('/SID=(\S[^;]+)/', $header, $matches)) { | ||||||
|  |                 $this->curl->setHeader('Cookie', $matches[0]); | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function errorMessage() | ||||||
|  |     { | ||||||
|  |         return 'Curl Error Code: ' . $this->curl->error_code . ' (' . $this->curl->response . ')'; | ||||||
|  |     } | ||||||
|  |     /** | ||||||
|  |      * 拼接种子urls multipart/form-data | ||||||
|  |      * https://github.com/qbittorrent/qBittorrent/wiki/Web-API-Documentation#add-new-torrent | ||||||
|  |      */ | ||||||
|  |     private function buildUrls($param){ | ||||||
|  |         $this->delimiter = uniqid(); | ||||||
|  |         $eol = "\r\n"; | ||||||
|  |         $data = ''; | ||||||
|  |         // 拼接文件流 | ||||||
|  |         foreach ($param as $name => $content) { | ||||||
|  |             $data .= "--" . $this->delimiter . $eol; | ||||||
|  |             $data .= 'Content-Disposition: form-data; name' . '="' .$name. '"' . "\r\n\r\n"; | ||||||
|  |             $data .= $content . $eol; | ||||||
|  |         } | ||||||
|  |         $data .= "--" . $this->delimiter . "--" . $eol; | ||||||
|  |         return $data; | ||||||
|  |     } | ||||||
|  |     /** | ||||||
|  |      * 拼接种子上传文件流 multipart/form-data | ||||||
|  |      * https://github.com/qbittorrent/qBittorrent/wiki/Web-API-Documentation#add-new-torrent | ||||||
|  |      */ | ||||||
|  |     private function buildData($param){ | ||||||
|  |         $this->delimiter = uniqid(); | ||||||
|  |         $eol = "\r\n"; | ||||||
|  |         $data = ''; | ||||||
|  |         $torrents = $param['torrents']; | ||||||
|  |         unset($param['torrents']); | ||||||
|  |         // 拼接文件流 | ||||||
|  |         $data .= "--" . $this->delimiter . $eol | ||||||
|  |         . 'Content-Disposition: form-data; '; | ||||||
|  |         foreach ($param as $name => $content) { | ||||||
|  |             $data.= $name . '="' . $content.'"; '; | ||||||
|  |         } | ||||||
|  |         $data .= $eol; | ||||||
|  |         $data .= 'Content-Type: application/x-bittorrent'."\r\n\r\n"; | ||||||
|  |         $data .= $torrents . $eol; | ||||||
|  |         $data .= "--" . $this->delimiter . "--" . $eol; | ||||||
|  |         return $data; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										255
									
								
								app/Class/uTorrent.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								app/Class/uTorrent.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,255 @@ | |||||||
|  | <?php | ||||||
|  | define("UTORRENT_TORRENT_HASH", 0); | ||||||
|  | define("UTORRENT_TORRENT_STATUS", 1); | ||||||
|  | define("UTORRENT_TORRENT_NAME", 2); | ||||||
|  | define("UTORRENT_TORRENT_SIZE", 3); | ||||||
|  | define("UTORRENT_TORRENT_PROGRESS", 4); | ||||||
|  | define("UTORRENT_TORRENT_DOWNLOADED", 5); | ||||||
|  | define("UTORRENT_TORRENT_UPLOADED", 6); | ||||||
|  | define("UTORRENT_TORRENT_RATIO", 7); | ||||||
|  | define("UTORRENT_TORRENT_UPSPEED", 8); | ||||||
|  | define("UTORRENT_TORRENT_DOWNSPEED", 9); | ||||||
|  | define("UTORRENT_TORRENT_ETA", 10); | ||||||
|  | define("UTORRENT_TORRENT_LABEL", 11); | ||||||
|  | define("UTORRENT_TORRENT_PEERS_CONNECTED", 12); | ||||||
|  | define("UTORRENT_TORRENT_PEERS_SWARM", 13); | ||||||
|  | define("UTORRENT_TORRENT_SEEDS_CONNECTED", 14); | ||||||
|  | define("UTORRENT_TORRENT_SEEDS_SWARM", 15); | ||||||
|  | define("UTORRENT_TORRENT_AVAILABILITY", 16); | ||||||
|  | define("UTORRENT_TORRENT_QUEUE_POSITION", 17); | ||||||
|  | define("UTORRENT_TORRENT_REMAINING", 18); | ||||||
|  | define("UTORRENT_FILEPRIORITY_HIGH", 3); | ||||||
|  | define("UTORRENT_FILEPRIORITY_NORMAL", 2); | ||||||
|  | define("UTORRENT_FILEPRIORITY_LOW", 1); | ||||||
|  | define("UTORRENT_FILEPRIORITY_SKIP", 0); | ||||||
|  | define("UTORRENT_TYPE_INTEGER", 0); | ||||||
|  | define("UTORRENT_TYPE_BOOLEAN", 1); | ||||||
|  | define("UTORRENT_TYPE_STRING", 2); | ||||||
|  | define("UTORRENT_STATUS_STARTED", 1); | ||||||
|  | define("UTORRENT_STATUS_CHECKED", 2); | ||||||
|  | define("UTORRENT_STATUS_START_AFTER_CHECK", 4); | ||||||
|  |  | ||||||
|  | class uTorrent { | ||||||
|  |     // class static variables | ||||||
|  |     private static $base = "%s/gui/%s"; | ||||||
|  |  | ||||||
|  |     // member variables | ||||||
|  |     public $host; | ||||||
|  |     public $user; | ||||||
|  |     public $pass; | ||||||
|  |  | ||||||
|  |     protected $token; | ||||||
|  |     protected $guid; | ||||||
|  |  | ||||||
|  |     // constructor | ||||||
|  |     function __construct($host = "", $user = "", $pass = "") { | ||||||
|  |         $this->host = rtrim($host,'/'); | ||||||
|  |         $this->user = $user; | ||||||
|  |         $this->pass = $pass; | ||||||
|  |  | ||||||
|  |         if (!$this->getToken()) { | ||||||
|  |             //handle error here, don't know how to best do this yet | ||||||
|  |             die('could not get token'); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // performs request | ||||||
|  |     private function makeRequest($request, $decode = true, $options = array()) { | ||||||
|  |         $request = preg_replace('/^\?/', '?token='.$this->token . '&', $request); | ||||||
|  |  | ||||||
|  |         $ch = curl_init(); | ||||||
|  |         curl_setopt_array($ch, $options); | ||||||
|  |         curl_setopt($ch, CURLOPT_URL, sprintf(self::$base, $this->host, $request)); | ||||||
|  |         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | ||||||
|  |         curl_setopt($ch, CURLOPT_USERPWD, $this->user.":".$this->pass); | ||||||
|  |         curl_setopt($ch, CURLOPT_COOKIE, "GUID=".$this->guid); | ||||||
|  |  | ||||||
|  |         $req = curl_exec($ch); | ||||||
|  |         curl_close($ch); | ||||||
|  |  | ||||||
|  |         return ($decode ? json_decode($req, true) : $req); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // implodes given parameter with glue, whether it is an array or not | ||||||
|  |     private function paramImplode($glue, $param) { | ||||||
|  |         return $glue.implode($glue, is_array($param) ? $param : array($param)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // gets token, returns true on success | ||||||
|  |     private function getToken() { | ||||||
|  |         $url = sprintf(self::$base, $this->host, 'token.html'); | ||||||
|  |         $ch = curl_init(); | ||||||
|  |         curl_setopt($ch, CURLOPT_URL, $url); | ||||||
|  |         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | ||||||
|  |         curl_setopt($ch, CURLOPT_USERPWD, $this->user.":".$this->pass); | ||||||
|  |         curl_setopt($ch, CURLOPT_HEADER, true); | ||||||
|  |         $output = curl_exec($ch); | ||||||
|  |         $info = curl_getinfo($ch); | ||||||
|  |         curl_close($ch); | ||||||
|  |  | ||||||
|  |         $headers = substr($output, 0, $info['header_size']); | ||||||
|  |  | ||||||
|  |         if (preg_match("@Set-Cookie: GUID=([^;]+);@i", $headers, $matches)) { | ||||||
|  |             $this->guid = $matches[1]; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (preg_match('/<div id=\'token\'.+>(.*)<\/div>/', $output, $m)) { | ||||||
|  |             $this->token = $m[1]; | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // returns the uTorrent build number | ||||||
|  |     public function getBuild(){ | ||||||
|  |         $json = $this->makeRequest("?"); | ||||||
|  |         return $json['build']; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // returns an array of files for the specified torrent hash | ||||||
|  |     // TODO: | ||||||
|  |     //  - (when implemented in API) allow multiple hashes to be specified | ||||||
|  |     public function getFiles($hash) { | ||||||
|  |         $json = $this->makeRequest("?action=getfiles&hash=".$hash); | ||||||
|  |         return $json['files']; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // returns an array of all labels | ||||||
|  |     public function getLabels(){ | ||||||
|  |         $json = $this->makeRequest("?list=1"); | ||||||
|  |         return $json['label']; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // returns an array of the properties for the specified torrent hash | ||||||
|  |     // TODO: | ||||||
|  |     //  - (when implemented in API) allow multiple hashes to be specified | ||||||
|  |     public function getProperties($hash) { | ||||||
|  |         $json = $this->makeRequest("?action=getprops&hash=".$hash); | ||||||
|  |         return $json['props']; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // returns an array of all settings | ||||||
|  |     public function getSettings() { | ||||||
|  |         $json = $this->makeRequest("?action=getsettings"); | ||||||
|  |         return $json['settings']; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // returns an array of all torrent jobs and related information | ||||||
|  |     public function getTorrents() { | ||||||
|  |         $json = $this->makeRequest("?list=1"); | ||||||
|  |         return $json['torrents']; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Get all the RSS favourites/filters | ||||||
|  |      * @return model\Filter[] | ||||||
|  |      */ | ||||||
|  |     public function getRSSFilters() { | ||||||
|  |         $json = $this->makeRequest("?list=1"); | ||||||
|  |         $filters = array(); | ||||||
|  |         foreach ($json['rssfilters'] as $filter) { | ||||||
|  |             $filters[] = model\Filter::fromData($filter); | ||||||
|  |         } | ||||||
|  |         return $filters; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Update an RSS filter as retrieved from getRSSFilters | ||||||
|  |      * @param \uTorrent\model\Filter $filter | ||||||
|  |      */ | ||||||
|  |     public function setRSSFilter(model\Filter $filter) { | ||||||
|  |         $request = array_merge(array('action' => 'filter-update'), $filter->toParams()); | ||||||
|  |         return $this->makeRequest('?'.http_build_query($request)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Add a new RSS filter | ||||||
|  |      * Requires a utorrent > 2.2.1 (not sure which version exactly) | ||||||
|  |      * @param \uTorrent\model\Filter $filter | ||||||
|  |      * @return int ID of the new filter | ||||||
|  |      */ | ||||||
|  |     public function addRSSFilter(model\Filter $filter) { | ||||||
|  |         $filter->filterId = -1; | ||||||
|  |         $resp = $this->setRSSFilter($filter); | ||||||
|  |         if (!empty($resp['filter_ident'])) { | ||||||
|  |             return $resp['filter_ident']; | ||||||
|  |         } else { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // returns true if WebUI server is online and enabled, false otherwise | ||||||
|  |     public function is_online() { | ||||||
|  |         return is_array($this->makeRequest("?")); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // sets the properties for the specified torrent hash | ||||||
|  |     // TODO: | ||||||
|  |     //  - allow multiple hashes, properties, and values to be set simultaneously | ||||||
|  |     public function setProperties($hash, $property, $value) { | ||||||
|  |         $this->makeRequest("?action=setprops&hash=".$hash."&s=".$property."&v=".$value, false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // sets the priorities for the specified files in the specified torrent hash | ||||||
|  |     public function setPriority($hash, $files, $priority) { | ||||||
|  |         $this->makeRequest("?action=setprio&hash=".$hash."&p=".$priority.$this->paramImplode("&f=", $files), false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // sets the settings | ||||||
|  |     // TODO: | ||||||
|  |     //  - allow multiple settings and values to be set simultaneously | ||||||
|  |     public function setSetting($setting, $value) { | ||||||
|  |         $this->makeRequest("?action=setsetting&s=".$setting."&v=".$value, false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // add a file to the list | ||||||
|  |     public function torrentAdd($filename, &$estring = false) { | ||||||
|  |         $split = explode(":", $filename, 2); | ||||||
|  |         if (count($split) > 1 && (stristr("|http|https|file|magnet|", "|".$split[0]."|") !== false)) { | ||||||
|  |             $this->makeRequest("?action=add-url&s=".urlencode($filename), false); | ||||||
|  |         } | ||||||
|  |         elseif (file_exists($filename)) { | ||||||
|  |             $json = $this->makeRequest("?action=add-file", true, array(CURLOPT_POSTFIELDS => array("torrent_file" => "@".realpath($filename)))); | ||||||
|  |  | ||||||
|  |             if (isset($json['error'])) { | ||||||
|  |                 if ($estring !== false) $estring = $json['error']; | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             if ($estring !== false) $estring = "File doesn't exist!"; | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // force start the specified torrent hashes | ||||||
|  |     public function torrentForceStart($hash) { | ||||||
|  |         $this->makeRequest("?action=forcestart".$this->paramImplode("&hash=", $hash), false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // pause the specified torrent hashes | ||||||
|  |     public function torrentPause($hash) { | ||||||
|  |         $this->makeRequest("?action=pause".$this->paramImplode("&hash=", $hash), false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // recheck the specified torrent hashes | ||||||
|  |     public function torrentRecheck($hash) { | ||||||
|  |         $this->makeRequest("?action=recheck".$this->paramImplode("&hash=", $hash), false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // start the specified torrent hashes | ||||||
|  |     public function torrentStart($hash) { | ||||||
|  |         $this->makeRequest("?action=start".$this->paramImplode("&hash=", $hash), false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // stop the specified torrent hashes | ||||||
|  |     public function torrentStop($hash) { | ||||||
|  |         $this->makeRequest("?action=stop".$this->paramImplode("&hash=", $hash), false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // remove the specified torrent hashes (and data, if $data is set to true) | ||||||
|  |     public function torrentRemove($hash, $data = false) { | ||||||
|  |         $this->makeRequest("?action=".($data ? "removedata" : "remove").$this->paramImplode("&hash=", $hash), false); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										352
									
								
								app/config/config.sample.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								app/config/config.sample.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,352 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * 技术讨论及后续更新,请加入QQ群!!!!!!! | ||||||
|  | 	群名称:IYUU自动辅种交流 | ||||||
|  | 	QQ群号:859882209 | ||||||
|  |  * 手动配置方法,请查看:https://www.iyuu.cn/archives/324/ | ||||||
|  |  */ | ||||||
|  | return array( | ||||||
|  | 	// 1.爱语飞飞 微信通知配置 | ||||||
|  | 	'iyuu.cn'		=> 'IYUU', | ||||||
|  | 	// 2.server酱 微信通知配置 | ||||||
|  | 	'sc.ftqq.com'   => '', | ||||||
|  | 	// 3.发布员鉴权 | ||||||
|  | 	'secret' 		=> '', | ||||||
|  | 	// 4.全局默认配置 | ||||||
|  |     'default'      => array( | ||||||
|  | 		// 5.【必须配置】浏览器UA,打开http://demo.iyuu.cn 复制过来即可 | ||||||
|  | 		'userAgent'     => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36', | ||||||
|  | 		// 6.【自动辅种必须配置】全局客户端设置(条目不够可以复制,用不到的请删除) | ||||||
|  |         'clients'   => array( | ||||||
|  | 			// 全局客户端设置 开始 | ||||||
|  |             array( | ||||||
|  | 				'type'	=>	'transmission',	// 支持:transmission、qBittorrent | ||||||
|  | 				'host'	=>	'http://127.0.0.1:9091/transmission/rpc', | ||||||
|  | 				'username'	=>	'', | ||||||
|  | 				'password'	=>	'', | ||||||
|  | 				//'move' =>array( | ||||||
|  | 				//	'type' => 2,		// 0保持不变,1减,2加, 3直接替换 | ||||||
|  | 				//	'path' =>array( | ||||||
|  | 				//		'/sda1' => '/volume1', | ||||||
|  | 				//	), | ||||||
|  | 				//), | ||||||
|  | 			), | ||||||
|  | 			// (条目不够可以复制,用不到的请删除) | ||||||
|  | 			array( | ||||||
|  | 				'type'	=>	'qBittorrent',	// 支持:transmission、qBittorrent | ||||||
|  | 				'host'	=>	'http://www.baidu.com:8083', | ||||||
|  | 				'username'	=>	'', | ||||||
|  | 				'password'	=>	'', | ||||||
|  | 			), | ||||||
|  | 			// 全局客户端设置 结束 | ||||||
|  | 		), | ||||||
|  | 		'CONNECTTIMEOUT'=> 60, | ||||||
|  |         'TIMEOUT'       => 600, | ||||||
|  | 	), | ||||||
|  | 	/** | ||||||
|  | 	 * 以下为各站点的独立配置(互不影响、互不冲突) | ||||||
|  | 	 * 自动辅种:需要配置各站的passkey(没有配置passkey的站点会自动跳过) | ||||||
|  | 	 */ | ||||||
|  |     // m-team 序号:1 | ||||||
|  |     'm-team'      => array( | ||||||
|  | 		// 14.m-team的cookie	如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => 'tp=', | ||||||
|  | 		// 15.m-team的passkey	【必须配置】 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 		// 种子Tracker的IP地址选择 可选:ipv4,ipv6 | ||||||
|  | 		'ip_type'		=> 'ipv4', | ||||||
|  |     ), | ||||||
|  |     // keepfrds 序号:2 | ||||||
|  |     'keepfrds'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// ourbits 序号:3 | ||||||
|  | 	'ourbits'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 		'id' => 0,					// 用户ID | ||||||
|  | 		'is_vip'		=> 0,		// 是否具有VIP或特殊权限?0 普通,1 VIP | ||||||
|  |     ), | ||||||
|  |     // HDSky 序号:4 | ||||||
|  |     'hdsky'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  |     ), | ||||||
|  | 	// pter 序号:5 | ||||||
|  | 	'pter'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  |     ), | ||||||
|  | 	// tjupt 序号:6 | ||||||
|  | 	'tjupt'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  |     ), | ||||||
|  | 	// hdhome 序号:7 | ||||||
|  | 	'hdhome'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  |     ), | ||||||
|  | 	// btschool 序号:8 | ||||||
|  | 	'btschool'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// PTHome 序号:9 | ||||||
|  |     'pthome'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  |     ), | ||||||
|  | 	// hddolby 序号:10 | ||||||
|  | 	'hddolby'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  |     ), | ||||||
|  | 	// TorrentCCF 序号:11 | ||||||
|  |     'torrentccf'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  |     ), | ||||||
|  | 	// PTMSG 序号:12 | ||||||
|  |     'ptmsg'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  |     ), | ||||||
|  | 	// MoeCat 序号:13 | ||||||
|  |     'moecat'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 		// 种子Tracker的IP地址选择 可选:ipv4,ipv6 | ||||||
|  | 		'ip_type'		=> 'ipv4', | ||||||
|  |     ), | ||||||
|  |     // totheglory 序号:14 | ||||||
|  |     'ttg'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  |     ), | ||||||
|  | 	// nanyangpt 序号:15 | ||||||
|  |     'nanyangpt'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// springsunday.net 序号:16 | ||||||
|  |     'ssd'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// yingk 序号:17 | ||||||
|  |     'yingk'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// hdcity 序号:18 | ||||||
|  |     'hdcity'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置	cuhash | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// 52pt.site 序号:19 | ||||||
|  |     '52pt'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// brobits.cc 序号:20 | ||||||
|  |     'brobits'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// www.beitai.pt 序号:21 | ||||||
|  |     'beitai'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// pt.eastgame.org 序号:22 | ||||||
|  |     'eastgame'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// pt.soulvoice.club 序号:23 | ||||||
|  |     'soulvoice'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// chdbits 序号:24 | ||||||
|  |     'chdbits'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// leaguehd 序号:25 | ||||||
|  |     'leaguehd'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  |         'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// ptsbao.club 序号:26 | ||||||
|  | 	'ptsbao'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// hdchina 序号:27 | ||||||
|  | 	'hdchina'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// hdarea 序号:28 | ||||||
|  | 	'hdarea'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// hdtime 序号:29 | ||||||
|  | 	'hdtime'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// 1ptba 序号:30 | ||||||
|  | 	'1ptba'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// hd4fans 序号:31 | ||||||
|  | 	'hd4fans'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// hdbug 序号:32 | ||||||
|  | 	'hdbug'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// opencd 序号:33 | ||||||
|  | 	'opencd'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// hdstreet 序号:34 | ||||||
|  | 	'hdstreet'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// joyhd 序号:35 | ||||||
|  | 	'joyhd'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// dmhy 序号:36 | ||||||
|  | 	'dmhy'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// upxin 序号:37 | ||||||
|  | 	'upxin'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// oshen 序号:38 | ||||||
|  | 	'oshen'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// discfan 序号:39 | ||||||
|  | 	'discfan'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// hdzone 序号:40 | ||||||
|  | 	'hdzone'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// cnscg 序号:41 | ||||||
|  | 	'cnscg'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  | 	// nicept 序号:42 | ||||||
|  | 	'nicept'      => array( | ||||||
|  | 		// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 		'cookie'        => '', | ||||||
|  | 		// 如果需要自动辅种,必须配置 | ||||||
|  | 		'passkey'       => '', | ||||||
|  | 	), | ||||||
|  |  | ||||||
|  | 	// 配置文件结束 | ||||||
|  | ); | ||||||
							
								
								
									
										1
									
								
								app/config/version.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								app/config/version.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | <?php return '20191224.1010'; | ||||||
							
								
								
									
										42
									
								
								app/init.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/init.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | <?php | ||||||
|  | //---------------------------------- | ||||||
|  | // 公共入口文件 | ||||||
|  | //---------------------------------- | ||||||
|  | // 定义目录 | ||||||
|  | defined('ROOT_PATH') or define("ROOT_PATH",  dirname(__DIR__)); | ||||||
|  | defined('APP_PATH') or define('APP_PATH', __DIR__); | ||||||
|  | define('DS', DIRECTORY_SEPARATOR); | ||||||
|  | define('TORRENT_PATH', APP_PATH.DS.'torrent'.DS); | ||||||
|  |  | ||||||
|  | // 严格开发模式 | ||||||
|  | error_reporting( E_ALL ); | ||||||
|  | #ini_set('display_errors', 1); | ||||||
|  |  | ||||||
|  | // 永不超时 | ||||||
|  | ini_set('max_execution_time', 0); | ||||||
|  | set_time_limit(0); | ||||||
|  | // 内存限制,如果外面设置的内存比 /etc/php/php-cli.ini 大,就不要设置了 | ||||||
|  | if (intval(ini_get("memory_limit")) < 1024) | ||||||
|  | { | ||||||
|  |     ini_set('memory_limit', '1024M'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if( PHP_SAPI != 'cli' ) | ||||||
|  | { | ||||||
|  |     exit("You must run the CLI environment\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 设置时区 | ||||||
|  | date_default_timezone_set('Asia/Shanghai'); | ||||||
|  |  | ||||||
|  | // 系统配置 | ||||||
|  | if( file_exists( APP_PATH."/config/config.php" ) ) | ||||||
|  | { | ||||||
|  |     // 配置(全局变量) | ||||||
|  |     $configALL = require_once APP_PATH."/config/config.php"; | ||||||
|  | }else{ | ||||||
|  |     // 示例配置 | ||||||
|  |     $configALL = require_once APP_PATH . '/config/config.sample.php'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | require_once ROOT_PATH . '/vendor/autoload.php'; | ||||||
							
								
								
									
										10
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | { | ||||||
|  |     "require": { | ||||||
|  |         "owner888/phpspider": "^2.1", | ||||||
|  |         "curl/curl": "^2.2" | ||||||
|  |     }, | ||||||
|  |     "autoload": { | ||||||
|  |         "classmap":["app/Class"], | ||||||
|  |         "files": ["app/Class/Function.php"] | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										131
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | |||||||
|  | { | ||||||
|  |     "_readme": [ | ||||||
|  |         "This file locks the dependencies of your project to a known state", | ||||||
|  |         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", | ||||||
|  |         "This file is @generated automatically" | ||||||
|  |     ], | ||||||
|  |     "content-hash": "32806a4860870f6306b69cf349584387", | ||||||
|  |     "packages": [ | ||||||
|  |         { | ||||||
|  |             "name": "curl/curl", | ||||||
|  |             "version": "2.2.0", | ||||||
|  |             "source": { | ||||||
|  |                 "type": "git", | ||||||
|  |                 "url": "https://github.com/php-mod/curl.git", | ||||||
|  |                 "reference": "d22086dd2eee5ca02e4c29b9a5bdf3645bfdbbff" | ||||||
|  |             }, | ||||||
|  |             "dist": { | ||||||
|  |                 "type": "zip", | ||||||
|  |                 "url": "https://api.github.com/repos/php-mod/curl/zipball/d22086dd2eee5ca02e4c29b9a5bdf3645bfdbbff", | ||||||
|  |                 "reference": "d22086dd2eee5ca02e4c29b9a5bdf3645bfdbbff", | ||||||
|  |                 "shasum": "", | ||||||
|  |                 "mirrors": [ | ||||||
|  |                     { | ||||||
|  |                         "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", | ||||||
|  |                         "preferred": true | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             "require": { | ||||||
|  |                 "ext-curl": "*", | ||||||
|  |                 "php": "^5.6 | ^7.0" | ||||||
|  |             }, | ||||||
|  |             "require-dev": { | ||||||
|  |                 "phpunit/phpunit": "^5.7", | ||||||
|  |                 "squizlabs/php_codesniffer": "~2.1" | ||||||
|  |             }, | ||||||
|  |             "type": "library", | ||||||
|  |             "autoload": { | ||||||
|  |                 "psr-0": { | ||||||
|  |                     "Curl": "src/" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             "notification-url": "https://packagist.org/downloads/", | ||||||
|  |             "license": [ | ||||||
|  |                 "MIT" | ||||||
|  |             ], | ||||||
|  |             "authors": [ | ||||||
|  |                 { | ||||||
|  |                     "name": "Hassan Amouhzi", | ||||||
|  |                     "email": "hassan@anezi.net", | ||||||
|  |                     "homepage": "http://hassan.amouhzi.com" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "name": "php-curl-class", | ||||||
|  |                     "homepage": "https://github.com/php-curl-class" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "name": "user52", | ||||||
|  |                     "homepage": "https://github.com/user52" | ||||||
|  |                 } | ||||||
|  |             ], | ||||||
|  |             "description": "cURL class for PHP", | ||||||
|  |             "homepage": "https://github.com/php-mod/curl", | ||||||
|  |             "keywords": [ | ||||||
|  |                 "curl", | ||||||
|  |                 "dot" | ||||||
|  |             ], | ||||||
|  |             "time": "2018-12-04T19:47:03+00:00" | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "owner888/phpspider", | ||||||
|  |             "version": "v2.1.6", | ||||||
|  |             "source": { | ||||||
|  |                 "type": "git", | ||||||
|  |                 "url": "https://github.com/owner888/phpspider.git", | ||||||
|  |                 "reference": "e6021148adec201418c16ba26f39bc013ba5b4d9" | ||||||
|  |             }, | ||||||
|  |             "dist": { | ||||||
|  |                 "type": "zip", | ||||||
|  |                 "url": "https://api.github.com/repos/owner888/phpspider/zipball/e6021148adec201418c16ba26f39bc013ba5b4d9", | ||||||
|  |                 "reference": "e6021148adec201418c16ba26f39bc013ba5b4d9", | ||||||
|  |                 "shasum": "", | ||||||
|  |                 "mirrors": [ | ||||||
|  |                     { | ||||||
|  |                         "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", | ||||||
|  |                         "preferred": true | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             "require": { | ||||||
|  |                 "php": ">=5.5.0" | ||||||
|  |             }, | ||||||
|  |             "suggest": { | ||||||
|  |                 "ext-pcntl、ext-redis": "For better performance. " | ||||||
|  |             }, | ||||||
|  |             "type": "library", | ||||||
|  |             "autoload": { | ||||||
|  |                 "psr-4": { | ||||||
|  |                     "phpspider\\": "./" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             "notification-url": "https://packagist.org/downloads/", | ||||||
|  |             "license": [ | ||||||
|  |                 "MIT" | ||||||
|  |             ], | ||||||
|  |             "authors": [ | ||||||
|  |                 { | ||||||
|  |                     "name": "Seatle Yang", | ||||||
|  |                     "email": "seatle@foxmail.com", | ||||||
|  |                     "homepage": "http://www.phpspider.org", | ||||||
|  |                     "role": "Developer" | ||||||
|  |                 } | ||||||
|  |             ], | ||||||
|  |             "description": "The PHPSpider Framework.", | ||||||
|  |             "homepage": "http://www.phpspider.org", | ||||||
|  |             "keywords": [ | ||||||
|  |                 "framework", | ||||||
|  |                 "phpspider" | ||||||
|  |             ], | ||||||
|  |             "time": "2018-08-15T08:04:29+00:00" | ||||||
|  |         } | ||||||
|  |     ], | ||||||
|  |     "packages-dev": [], | ||||||
|  |     "aliases": [], | ||||||
|  |     "minimum-stability": "stable", | ||||||
|  |     "stability-flags": [], | ||||||
|  |     "prefer-stable": false, | ||||||
|  |     "prefer-lowest": false, | ||||||
|  |     "platform": [], | ||||||
|  |     "platform-dev": [] | ||||||
|  | } | ||||||
							
								
								
									
										612
									
								
								iyuu.cn.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										612
									
								
								iyuu.cn.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,612 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * IYUUAutoReseed自动辅种 | ||||||
|  |  */ | ||||||
|  | use Curl\Curl; | ||||||
|  | require_once __DIR__ . '/app/init.php'; | ||||||
|  | iyuuAutoReseed::init(); | ||||||
|  | $hashArray = iyuuAutoReseed::get(); | ||||||
|  | if ( iyuuAutoReseed::$move != null ) { | ||||||
|  | 	echo "种子移动完毕,请重新编辑配置,再尝试辅种! \n\n"; | ||||||
|  | 	exit; | ||||||
|  | } | ||||||
|  | iyuuAutoReseed::call($hashArray); | ||||||
|  | iyuuAutoReseed::wechatMessage(); | ||||||
|  | /** | ||||||
|  |  * IYUUAutoReseed自动辅种类 | ||||||
|  |  */ | ||||||
|  | class iyuuAutoReseed | ||||||
|  | { | ||||||
|  | 	/** | ||||||
|  |      * 版本号 | ||||||
|  |      * @var string | ||||||
|  |      */ | ||||||
|  | 	const VER = '0.1.0'; | ||||||
|  | 	/** | ||||||
|  | 	 * RPC连接池 | ||||||
|  | 	 * @var array | ||||||
|  | 	 */ | ||||||
|  | 	public static $links = array(); | ||||||
|  | 	/** | ||||||
|  |      * 客户端配置 | ||||||
|  | 	 * @var array | ||||||
|  |      */ | ||||||
|  | 	public static $clients = array(); | ||||||
|  | 	/** | ||||||
|  | 	 * 不辅种的站点 'ourbits','hdchina' | ||||||
|  | 	 * @var array | ||||||
|  | 	 */ | ||||||
|  | 	public static $noReseed = []; | ||||||
|  | 	/** | ||||||
|  |      * 缓存路径 | ||||||
|  | 	 * @var string | ||||||
|  |      */ | ||||||
|  | 	public static $cacheDir  = TORRENT_PATH.'cache'.DS; | ||||||
|  | 	public static $cacheHash = TORRENT_PATH.'cachehash'.DS; | ||||||
|  | 	/** | ||||||
|  |      * API接口配置 | ||||||
|  | 	 * @var string | ||||||
|  | 	 * @var array | ||||||
|  |      */ | ||||||
|  | 	public static $apiUrl = 'http://iyuu.cn:2122'; | ||||||
|  | 	public static $endpoints = array( | ||||||
|  | 		'add' => '/api/add', | ||||||
|  | 		'update' => '/api/update', | ||||||
|  | 		'reseed' => '/api/reseed', | ||||||
|  | 		'login'  => '/login', | ||||||
|  | 	); | ||||||
|  | 	/** | ||||||
|  |      * 退出状态码 | ||||||
|  | 	 * @var int | ||||||
|  |      */ | ||||||
|  | 	public static $ExitCode = 0; | ||||||
|  | 	/** | ||||||
|  | 	 * 客户端转移做种 状态码[请把transmission配置为第一个客户端] | ||||||
|  | 	 * @var array | ||||||
|  | 	 */ | ||||||
|  | 	public static $move = null; | ||||||
|  | 	/** | ||||||
|  | 	 * 微信消息体 | ||||||
|  | 	 * @var array | ||||||
|  | 	 */ | ||||||
|  | 	public static $wechatMsg = array( | ||||||
|  | 		'hashCount'			=>	0,		// 提交给服务器的hash总数 | ||||||
|  | 		'sitesCount'		=>	0,		// 可辅种站点总数 | ||||||
|  | 		'reseedCount'		=>	0,		// 返回的总数据 | ||||||
|  | 		'reseedSuccess'		=>	0,		// 成功:辅种成功(会加入缓存,哪怕种子在校验中,下次也会过滤) | ||||||
|  | 		'reseedError'		=>	0,		// 错误:辅种失败(可以重试)		 | ||||||
|  | 		'reseedRepeat'		=>	0,		// 重复:客户端已做种 | ||||||
|  | 		'reseedSkip'		=>	0,		// 跳过:因未设置passkey,而跳过 | ||||||
|  | 		'reseedPass'		=>	0,		// 忽略:因上次成功添加、存在缓存,而跳过 | ||||||
|  | 	); | ||||||
|  | 	/** | ||||||
|  |      * 初始化 | ||||||
|  | 	 * @return void | ||||||
|  |      */ | ||||||
|  | 	public static function init(){ | ||||||
|  | 		global $configALL; | ||||||
|  | 		self::$clients = isset($configALL['default']['clients']) && $configALL['default']['clients'] ? $configALL['default']['clients'] : array(); | ||||||
|  | 		echo "程序正在初始化运行参数... \n"; | ||||||
|  | 		// 递归删除上次历史记录 | ||||||
|  | 		IFile::rmdir(self::$cacheDir, true); | ||||||
|  | 		// 建立目录 | ||||||
|  | 		IFile::mkdir(self::$cacheDir); | ||||||
|  | 		IFile::mkdir(self::$cacheHash); | ||||||
|  | 		// 连接全局客户端 | ||||||
|  | 		self::links(); | ||||||
|  | 		// 合作站点自动注册鉴权 | ||||||
|  | 		Oauth::login(self::$apiUrl . self::$endpoints['login']); | ||||||
|  | 	} | ||||||
|  | 	/** | ||||||
|  |      * 连接远端RPC服务器 | ||||||
|  |      * | ||||||
|  |      * @param string | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public static function links() | ||||||
|  |     { | ||||||
|  |         if(empty(self::$links)){ | ||||||
|  | 			foreach ( self::$clients as $k => $v ){ | ||||||
|  | 				// 跳过未配置的客户端 | ||||||
|  | 				if (empty($v['username']) || empty( $v['password'])) { | ||||||
|  | 					unset(self::$clients[$k]); | ||||||
|  | 					echo "clients_".$k." 用户名或密码未配置,已跳过 \n\n"; | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				try | ||||||
|  | 				{ | ||||||
|  | 					switch($v['type']){ | ||||||
|  | 						case 'transmission': | ||||||
|  | 							self::$links[$k]['rpc'] = new TransmissionRPC($v['host'], $v['username'], $v['password']); | ||||||
|  | 							$result = self::$links[$k]['rpc']->sstats(); | ||||||
|  | 							print $v['type'].':'.$v['host']." Rpc连接 [{$result->result}] \n"; | ||||||
|  | 							break; | ||||||
|  | 						case 'qBittorrent': | ||||||
|  | 							self::$links[$k]['rpc'] = new qBittorrent($v['host'], $v['username'], $v['password']); | ||||||
|  | 							$result = self::$links[$k]['rpc']->appVersion(); | ||||||
|  | 							print $v['type'].':'.$v['host']." Rpc连接 [{$result}] \n"; | ||||||
|  | 							break; | ||||||
|  | 						default: | ||||||
|  | 							echo '[ERROR] '.$v['type']; | ||||||
|  | 							exit(1); | ||||||
|  | 							break; | ||||||
|  | 					} | ||||||
|  | 					self::$links[$k]['type'] = $v['type']; | ||||||
|  | 					// 检查是否转移种子的做种客户端? | ||||||
|  | 					if ( isset($v['move']) && $v['move'] ) { | ||||||
|  | 						self::$move = array($k,$v['type']); | ||||||
|  | 					} | ||||||
|  | 				} catch (Exception $e) { | ||||||
|  | 					echo '[ERROR] ' . $e->getMessage() . PHP_EOL; | ||||||
|  | 					exit(1); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	/** | ||||||
|  |      * 从客户端获取种子的哈希列表 | ||||||
|  | 	 * @var array | ||||||
|  |      */ | ||||||
|  | 	public static function get(){ | ||||||
|  | 		$hashArray = array(); | ||||||
|  | 		foreach ( self::$clients as $k => $v ){ | ||||||
|  | 			$result = array(); | ||||||
|  | 			$res = $info_hash = array(); | ||||||
|  | 			$json = $sha1 = ''; | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				switch($v['type']){ | ||||||
|  | 					case 'transmission': | ||||||
|  | 						$ids = $fields = array(); | ||||||
|  | 						#$fields = array( "id", "status", "name", "hashString", "downloadDir", "torrentFile" ); | ||||||
|  | 						$fields = array( "id", "status", "hashString", "downloadDir"); | ||||||
|  | 						$result = self::$links[$k]['rpc']->get($ids, $fields); | ||||||
|  | 						if ( empty($result->result) || $result->result != 'success' ){ | ||||||
|  | 							// 获取种子列表 失败 | ||||||
|  | 							echo "获取种子列表失败,原因可能是transmission暂时无响应,请稍后重试! \n"; | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
|  | 						if( empty($result->arguments) ){ | ||||||
|  | 							echo "未获取到需要辅种的数据,请多多保种,然后重试! \n"; | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
|  | 						// 对象转数组 | ||||||
|  | 						$res = object_array($result->arguments->torrents); | ||||||
|  | 						// 过滤,只保留正常做种 | ||||||
|  | 						$res = array_filter($res, "filterStatus"); | ||||||
|  | 						// 提取数组:hashString | ||||||
|  | 						$info_hash = array_column($res, 'hashString'); | ||||||
|  | 						// 升序排序 | ||||||
|  | 						sort($info_hash); | ||||||
|  | 						// 微信模板消息 统计 | ||||||
|  | 						self::$wechatMsg['hashCount'] += count($info_hash); | ||||||
|  | 						$json = json_encode($info_hash, JSON_UNESCAPED_UNICODE); | ||||||
|  | 						// 去重 应该从文件读入,防止重复提交 | ||||||
|  | 						$sha1 = sha1( $json ); | ||||||
|  | 						if ( isset($hashArray['sha1']) && (in_array($sha1, $hashArray['sha1']) != false) ) { | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
|  | 						// 组装返回数据 | ||||||
|  | 						$hashArray['hash']['clients_'.$k] = $json; | ||||||
|  | 						$hashArray['sha1'][] = $sha1; | ||||||
|  | 						// 变换数组:hashString为键 | ||||||
|  | 						self::$links[$k]['hash'] = array_column($res, "downloadDir", 'hashString'); | ||||||
|  | 						#p(self::$links[$k]['hash']);exit; | ||||||
|  | 						break; | ||||||
|  | 					case 'qBittorrent': | ||||||
|  | 						$result = self::$links[$k]['rpc']->torrentList(); | ||||||
|  | 						$res = json_decode($result,true); | ||||||
|  | 						if ( empty($res) ) { | ||||||
|  | 							echo "未获取到需要辅种的数据,请多多保种,然后重试! \n"; | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
|  | 						#p($res);exit; | ||||||
|  | 						// 过滤,只保留正常做种 | ||||||
|  | 						$res = array_filter($res, "qbfilterStatus"); | ||||||
|  | 						// 提取数组:hashString | ||||||
|  | 						$info_hash = array_column($res, 'hash'); | ||||||
|  | 						// 升序排序 | ||||||
|  | 						sort($info_hash); | ||||||
|  | 						// 微信模板消息 统计 | ||||||
|  | 						self::$wechatMsg['hashCount'] += count($info_hash); | ||||||
|  | 						$json = json_encode($info_hash, JSON_UNESCAPED_UNICODE); | ||||||
|  | 						// 去重 应该从文件读入,防止重复提交 | ||||||
|  | 						$sha1 = sha1( $json ); | ||||||
|  | 						if ( isset($hashArray['sha1']) && (in_array($sha1, $hashArray['sha1']) != false) ) { | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
|  | 						// 组装返回数据 | ||||||
|  | 						$hashArray['hash']['clients_'.$k] = $json; | ||||||
|  | 						$hashArray['sha1'][] = $sha1; | ||||||
|  | 						// 变换数组:hash为键 | ||||||
|  | 						self::$links[$k]['hash'] = array_column($res, "save_path", 'hash'); | ||||||
|  | 						#p(self::$links[$k]['hash']);exit; | ||||||
|  | 						break; | ||||||
|  | 					default: | ||||||
|  | 						echo '[ERROR] '.$v['type']; | ||||||
|  | 						exit(1); | ||||||
|  | 						break; | ||||||
|  | 				} | ||||||
|  | 				// 是否执行转移种子做种客户端? | ||||||
|  | 				if ( self::$move != null && (empty($v['move'])) ) { | ||||||
|  | 					self::move($res, $v['type']); | ||||||
|  | 				} | ||||||
|  | 			} catch (Exception $e) { | ||||||
|  | 				echo '[ERROR] ' . $e->getMessage() . PHP_EOL; | ||||||
|  | 				exit(1); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return $hashArray; | ||||||
|  | 	} | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 添加下载任务 | ||||||
|  | 	 * @param string $torrent 种子元数据 | ||||||
|  | 	 * @param string $save_path 保存路径 | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
|  |     public static function add($rpcKey, $torrent, $save_path = '', $extra_options = array()) | ||||||
|  |     { | ||||||
|  | 		try | ||||||
|  | 		{ | ||||||
|  | 			$is_url = false; | ||||||
|  | 			if( (strpos($torrent,'http://')===0) || (strpos($torrent,'https://')===0) || (strpos($torrent,'magnet:?xt=urn:btih:')===0) ){ | ||||||
|  | 				$is_url = true; | ||||||
|  | 			} | ||||||
|  | 			// 下载服务器类型 | ||||||
|  | 			$type = self::$links[$rpcKey]['type']; | ||||||
|  | 			// 判断 | ||||||
|  | 			switch( $type ){ | ||||||
|  | 				case 'transmission': | ||||||
|  | 					$extra_options['paused'] = true; | ||||||
|  | 					if( $is_url ){ | ||||||
|  | 						$result = self::$links[$rpcKey]['rpc']->add( $torrent, $save_path, $extra_options );			// 种子URL添加下载任务 | ||||||
|  | 					} else{ | ||||||
|  | 						$result = self::$links[$rpcKey]['rpc']->add_metainfo( $torrent, $save_path, $extra_options );	// 种子元数据添加下载任务 | ||||||
|  | 					} | ||||||
|  | 					if(isset($result->result) && $result->result == 'success'){ | ||||||
|  | 						$id = $name = ''; | ||||||
|  | 						if( isset($result->arguments->torrent_duplicate) ){ | ||||||
|  | 							$id = $result->arguments->torrent_duplicate->id; | ||||||
|  | 							$name = $result->arguments->torrent_duplicate->name; | ||||||
|  | 						}elseif( isset($result->arguments->torrent_added) ){ | ||||||
|  | 							$id = $result->arguments->torrent_added->id; | ||||||
|  | 							$name = $result->arguments->torrent_added->name; | ||||||
|  | 						} | ||||||
|  | 						print "********RPC添加下载任务成功 [{$result->result}] (id=$id) \n"; | ||||||
|  | 						if( $is_url ){ | ||||||
|  | 							print "种子:".$torrent. "\n"; | ||||||
|  | 						} | ||||||
|  | 						print "名字:".$name."\n\n"; | ||||||
|  | 						return true; | ||||||
|  | 					}else{ | ||||||
|  | 						$errmsg = isset($result->result) ? $result->result : '未知错误,请稍后重试!'; | ||||||
|  | 						print "-----RPC添加种子任务,失败 [{$errmsg}] \n"; | ||||||
|  | 						if( $is_url ){ | ||||||
|  | 							print "种子:".$torrent. "\n"; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					break; | ||||||
|  | 				case 'qBittorrent': | ||||||
|  | 					$extra_options['paused'] = 'true'; | ||||||
|  | 					$extra_options['autoTMM'] = 'false';	//关闭自动种子管理 | ||||||
|  | 					if( $is_url ){ | ||||||
|  | 						$result = self::$links[$rpcKey]['rpc']->add( $torrent, $save_path, $extra_options );			// 种子URL添加下载任务 | ||||||
|  | 					} else{ | ||||||
|  | 						$extra_options['name'] = 'torrents'; | ||||||
|  | 						$extra_options['filename'] = rand(1,4294967200).'.torrent'; | ||||||
|  | 						$result = self::$links[$rpcKey]['rpc']->add_metainfo( $torrent, $save_path, $extra_options );	// 种子元数据添加下载任务 | ||||||
|  | 					} | ||||||
|  | 					if ($result === 'Ok.') { | ||||||
|  | 						print "********RPC添加下载任务成功 [{$result}] \n\n"; | ||||||
|  | 						return true; | ||||||
|  | 					} else { | ||||||
|  | 						print "-----RPC添加种子任务,失败 [{$result}] \n\n"; | ||||||
|  | 					} | ||||||
|  | 					break; | ||||||
|  | 				default: | ||||||
|  | 					echo '[ERROR] '.$type; | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
|  | 		} catch (Exception $e) { | ||||||
|  | 			echo '[ERROR] ' . $e->getMessage() . PHP_EOL; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	/** | ||||||
|  | 	 * 正常做种的种子在各下载器的互相转移 | ||||||
|  | 	 */ | ||||||
|  | 	public static function move($torrent=array(), $type = 'qBittorrent'){ | ||||||
|  | 		switch($type){ | ||||||
|  | 			case 'transmission': | ||||||
|  | 				break; | ||||||
|  | 			case 'qBittorrent': | ||||||
|  | 				foreach ($torrent as $k => $v) { | ||||||
|  | 					// 路径转换 | ||||||
|  | 					#$v['save_path'] = '/volume3' . $v['save_path'];	// docker路径转换 | ||||||
|  | 					self::add(self::$move[0], $v['magnet_uri'], $v['save_path'] ); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 			default: | ||||||
|  | 				echo '[ERROR] '.$type; | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	/** | ||||||
|  | 	 * @brief 提交种子hash给远端API,用来获取辅种数据 | ||||||
|  | 	 * @param array $hashArray 种子hash数组 | ||||||
|  | 	 * @return | ||||||
|  | 	 */ | ||||||
|  | 	public static function call($hashArray = array()) | ||||||
|  | 	{ | ||||||
|  | 		global $configALL; | ||||||
|  | 		$resArray = $sites = array(); | ||||||
|  | 		$curl = new Curl(); | ||||||
|  | 		$curl->setOpt(CURLOPT_SSL_VERIFYPEER, false); | ||||||
|  | 		// 签名 | ||||||
|  | 		$hashArray['timestamp'] = time(); | ||||||
|  | 		// 爱语飞飞token | ||||||
|  | 		$hashArray['sign'] = Oauth::getSign(); | ||||||
|  | 		$hashArray['version'] = self::VER; | ||||||
|  | 		// 写日志 | ||||||
|  | 		if (true) { | ||||||
|  | 			// 文件句柄 | ||||||
|  | 			$resource = fopen(self::$cacheDir.'hashString.txt', "wb"); | ||||||
|  | 			// 成功:返回写入字节数,失败返回false | ||||||
|  | 			$worldsnum = fwrite($resource, p($hashArray, false)); | ||||||
|  | 			fclose($resource); | ||||||
|  | 		} | ||||||
|  | 		// 发起请求 | ||||||
|  | 		echo "正在提交辅种信息…… \n"; | ||||||
|  | 		$res = $curl->post(self::$apiUrl . self::$endpoints['reseed'], $hashArray); | ||||||
|  | 		$resArray = json_decode($res->response, true); | ||||||
|  | 		// 写日志 | ||||||
|  | 		if(true){ | ||||||
|  | 			// 文件句柄 | ||||||
|  | 			$resource = fopen(self::$cacheDir.'reseed.txt', "wb"); | ||||||
|  | 			// 成功:返回写入字节数,失败返回false | ||||||
|  | 			$worldsnum = fwrite($resource, p($resArray, false)); | ||||||
|  | 			fclose($resource); | ||||||
|  | 		} | ||||||
|  | 		// 判断返回值 | ||||||
|  | 		if ( isset($resArray['errmsg']) && ($resArray['errmsg'] == 'ok') ) { | ||||||
|  | 			echo "辅种信息提交成功!!! \n\n"; | ||||||
|  | 		}else{ | ||||||
|  | 			$errmsg = isset($resArray['errmsg']) ? $resArray['errmsg'] : '远端服务器无响应,请稍后重试!'; | ||||||
|  | 			echo '-----辅种失败,原因:' .$errmsg. " \n\n"; | ||||||
|  | 			exit(1); | ||||||
|  | 		} | ||||||
|  | 		// 可辅种站点信息列表 | ||||||
|  | 		$sites = $resArray['sites']; | ||||||
|  | 		self::$wechatMsg['sitesCount'] = count($sites); | ||||||
|  | 		#p($sites); | ||||||
|  | 		// 按客户端循环辅种 开始 | ||||||
|  | 		foreach (self::$links as $k => $v) { | ||||||
|  | 			$reseed = $infohash_Dir = array(); | ||||||
|  | 			// info_hash 对应的下载目录 | ||||||
|  | 			$infohash_Dir = self::$links[$k]['hash']; | ||||||
|  | 			if (empty($resArray['clients_'.$k])) { | ||||||
|  | 				echo "clients_".$k."没有查询到可辅种数据 \n\n"; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			#p($infohash_Dir); | ||||||
|  | 			// 当前客户端辅种数据 | ||||||
|  | 			$reseed = $resArray['clients_'.$k];			 | ||||||
|  | 			foreach ($reseed as $info_hash => $vv) { | ||||||
|  | 				// 当前种子哈希对应的目录 | ||||||
|  | 				$downloadDir = $infohash_Dir[$info_hash]; | ||||||
|  | 				foreach ($vv['torrent'] as $id => $value) { | ||||||
|  | 					// 匹配的辅种数据累加 | ||||||
|  | 					self::$wechatMsg['reseedCount']++; | ||||||
|  | 					// 站点id | ||||||
|  | 					$sitesID = $value['sid']; | ||||||
|  | 					$url = $_url = ''; | ||||||
|  | 					$download_page = $details_url = ''; | ||||||
|  | 					// 页面规则 | ||||||
|  | 					$download_page = str_replace('{}', $value['torrent_id'], $sites[$sitesID]['download_page']); | ||||||
|  | 					$_url = 'https://' .$sites[$sitesID]['base_url']. '/' .$download_page; | ||||||
|  | 					if ( empty($configALL[$sites[$sitesID]['site']]['passkey']) ) { | ||||||
|  | 						echo '-------因当前' .$sites[$sitesID]['site']. '站点未设置passkey,已跳过!!' . "\n\n"; | ||||||
|  | 						self::$wechatMsg['reseedSkip']++; | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  | 					// 种子URL组合方式区分 | ||||||
|  | 					switch ($sites[$sitesID]['site']) { | ||||||
|  | 						case 'ttg': | ||||||
|  | 							$url = $_url."/". $configALL[$sites[$sitesID]['site']]['passkey']; | ||||||
|  | 							break; | ||||||
|  | 						case 'm-team': | ||||||
|  | 							$ip_type = ''; | ||||||
|  | 							if (isset($configALL[$sites[$sitesID]['site']]['ip_type'])) { | ||||||
|  | 								$ip_type = $configALL[$sites[$sitesID]['site']]['ip_type'] == 'ipv6' ? '&ipv6=1' : ''; | ||||||
|  | 							} | ||||||
|  | 							$url = $_url."&passkey=". $configALL[$sites[$sitesID]['site']]['passkey'] . $ip_type. "&https=1";						 | ||||||
|  | 							break; | ||||||
|  | 						case 'moecat': | ||||||
|  | 							$ip_type = ''; | ||||||
|  | 							if (isset($configALL[$sites[$sitesID]['site']]['ip_type'])) { | ||||||
|  | 								$ip_type = $configALL[$sites[$sitesID]['site']]['ip_type'] == 'ipv6' ? '&ipv6=1' : ''; | ||||||
|  | 							} | ||||||
|  | 							$url = $_url."&passkey=". $configALL[$sites[$sitesID]['site']]['passkey'] . $ip_type. "&https=1";						 | ||||||
|  | 							break; | ||||||
|  | 						case 'hdchina': | ||||||
|  | 							if ( empty($configALL[$sites[$sitesID]['site']]['cookie']) ) { | ||||||
|  | 								echo '-------因当前' .$sites[$sitesID]['site']. '站点未设置cookie,已跳过!!' . "\n\n"; | ||||||
|  | 								self::$wechatMsg['reseedSkip']++; | ||||||
|  | 								break; | ||||||
|  | 							} | ||||||
|  | 							$cookie = isset($configALL[$sites[$sitesID]['site']]['cookie']) ? $configALL[$sites[$sitesID]['site']]['cookie'] : ''; | ||||||
|  | 							$userAgent = $configALL['default']['userAgent']; | ||||||
|  | 							// 拼接URL | ||||||
|  | 							$details_page = str_replace('{}', $value['torrent_id'], 'details.php?id={}&hit=1'); | ||||||
|  | 							$details_url = 'https://' .$sites[$sitesID]['base_url']. '/' .$details_page; | ||||||
|  | 							$details_html = download($details_url, $cookie, $userAgent); | ||||||
|  | 							print "种子详情页:".$details_url. "\n"; | ||||||
|  | 							// 提取种子下载地址 | ||||||
|  | 							$download_page = str_replace('{}', '', $sites[$sitesID]['download_page']); | ||||||
|  | 							$offset = strpos($details_html, $download_page); | ||||||
|  | 							$urlTemp = substr($details_html, $offset, 50); | ||||||
|  | 							// 种子地址 | ||||||
|  | 							$_url = substr($urlTemp,0,strpos($urlTemp,'">')); | ||||||
|  | 							$_url = 'https://' .$sites[$sitesID]['base_url']. '/' . $_url; | ||||||
|  | 							print "种子下载页:".$_url. "\n"; | ||||||
|  | 							$url = download($_url, $cookie, $userAgent); | ||||||
|  | 							break; | ||||||
|  | 						case 'hdcity': | ||||||
|  | 							if ( empty($configALL[$sites[$sitesID]['site']]['cookie']) ) { | ||||||
|  | 								echo '-------因当前' .$sites[$sitesID]['site']. '站点未设置cookie,已跳过!!' . "\n\n"; | ||||||
|  | 								self::$wechatMsg['reseedSkip']++; | ||||||
|  | 								break; | ||||||
|  | 							} | ||||||
|  | 							$cookie = isset($configALL[$sites[$sitesID]['site']]['cookie']) ? $configALL[$sites[$sitesID]['site']]['cookie'] : ''; | ||||||
|  | 							$userAgent = $configALL['default']['userAgent']; | ||||||
|  | 							print "种子:".$_url. "\n"; | ||||||
|  | 							if ( isset($configALL[$sites[$sitesID]['site']]['cuhash']) ) { | ||||||
|  | 								// 已获取cuhash | ||||||
|  | 								# code... | ||||||
|  | 							}else { | ||||||
|  | 								// 获取cuhash | ||||||
|  | 								$html = download('https://' .$sites[$sitesID]['base_url']. '/pt', $cookie, $userAgent); | ||||||
|  | 								// 提取种子下载地址 | ||||||
|  | 								$offset = strpos($html,'cuhash='); | ||||||
|  | 								$len = strlen('cuhash='); | ||||||
|  | 								$cuhashTemp = substr($html,$offset+$len,40); | ||||||
|  | 								$configALL[$sites[$sitesID]['site']]['cuhash'] = substr($cuhashTemp,0,strpos($cuhashTemp,'"')); | ||||||
|  | 							} | ||||||
|  | 							$url = $_url."&cuhash=". $configALL[$sites[$sitesID]['site']]['cuhash']; | ||||||
|  | 							// 城市下载种子时会302转向 | ||||||
|  | 							$url = download($url, $cookie, $userAgent); | ||||||
|  | 							break; | ||||||
|  | 						default: | ||||||
|  | 							$url = $_url."&passkey=". $configALL[$sites[$sitesID]['site']]['passkey']; | ||||||
|  | 							break; | ||||||
|  | 					} | ||||||
|  | 					/** | ||||||
|  | 					 * 检查站点是否可以辅种 | ||||||
|  | 					 */ | ||||||
|  | 					// 判断是否具有VIP或特殊权限? | ||||||
|  | 					$is_vip = isset($configALL[$sites[$sitesID]['site']]['is_vip']) && $configALL[$sites[$sitesID]['site']]['is_vip'] ? 1 : 0; | ||||||
|  | 					if ( (in_array($sites[$sitesID]['site'], self::$noReseed)==false) || $is_vip ) { | ||||||
|  | 						/** | ||||||
|  | 						 *  可以辅种 | ||||||
|  | 						 */ | ||||||
|  | 						if ( isset($infohash_Dir[$value['info_hash']]) ) { | ||||||
|  | 							// 与客户端现有种子重复 | ||||||
|  | 							echo '-------与客户端现有种子重复:'.$_url."\n\n"; | ||||||
|  | 							self::$wechatMsg['reseedRepeat']++; | ||||||
|  | 							continue; | ||||||
|  | 						}else{ | ||||||
|  | 							// 判断上次是否成功添加? | ||||||
|  | 							if ( is_file(self::$cacheHash . $value['info_hash'].'.txt') ) { | ||||||
|  | 								echo '-------当前种子上次辅种已成功添加,已跳过!'.$_url."\n\n"; | ||||||
|  | 								self::$wechatMsg['reseedPass']++; | ||||||
|  | 								continue; | ||||||
|  | 							} | ||||||
|  | 							// 把拼接的种子URL,推送给下载器 | ||||||
|  | 							$ret = false; | ||||||
|  | 							// 成功返回:true | ||||||
|  | 							$ret = self::add($k, $url, $downloadDir); | ||||||
|  | 							// 添加成功的种子,以infohash为文件名,写入缓存 | ||||||
|  | 							if ($ret) { | ||||||
|  | 								// 成功的种子 | ||||||
|  | 								// 文件句柄 | ||||||
|  | 								$resource = fopen(self::$cacheHash . $value['info_hash'].'.txt', "wb"); | ||||||
|  | 								// 成功:返回写入字节数,失败返回false | ||||||
|  | 								$worldsnum = fwrite($resource, $url); | ||||||
|  | 								fclose($resource); | ||||||
|  | 								self::$wechatMsg['reseedSuccess']++; | ||||||
|  | 								continue; | ||||||
|  | 							}else{ | ||||||
|  | 								// 失败的种子 | ||||||
|  | 								// 站点类型判断 | ||||||
|  | 								switch ($sites[$sitesID]['site']) { | ||||||
|  | 									case 'hdcity': | ||||||
|  | 										echo '当前' .$sites[$sitesID]['site']. '站点是配置cuhash(不是passkey),添加成功说明配置正确!如果添加任务失败,请查阅常见问题!!' . "\n"; | ||||||
|  | 										break; | ||||||
|  | 									default: | ||||||
|  | 										break; | ||||||
|  | 								} | ||||||
|  | 								// 失败累加 | ||||||
|  | 								self::$wechatMsg['reseedError']++; | ||||||
|  | 								continue; | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					}else{ | ||||||
|  | 						/** | ||||||
|  | 						 *  不辅种 | ||||||
|  | 						 */ | ||||||
|  | 						echo '-------已跳过不辅种的站点:'.$_url."\n\n"; | ||||||
|  | 						// 写入日志文件,供用户手动辅种 | ||||||
|  | 						if ( !isset($infohash_Dir[$value['info_hash']]) ) { | ||||||
|  | 							// 站点类型判断 | ||||||
|  | 							switch ($sites[$sitesID]['site']) { | ||||||
|  | 								case 'hdchina': | ||||||
|  | 									$url = $_url; | ||||||
|  | 									break; | ||||||
|  | 								default: | ||||||
|  | 									break; | ||||||
|  | 							} | ||||||
|  | 							// 文件句柄 | ||||||
|  | 							$resource = fopen(self::$cacheDir . $sites[$sitesID]['site'].'.txt', 'a'); | ||||||
|  | 							// 成功:返回写入字节数,失败返回false | ||||||
|  | 							$worldsnum = fwrite($resource, 'clients_'.$k."\n".$downloadDir."\n".$url."\n".$details_url."\n\n"); | ||||||
|  | 							fclose($resource); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		// 按客户端循环辅种 结束 | ||||||
|  | 	} | ||||||
|  | 	/** | ||||||
|  | 	 *  | ||||||
|  | 	 */ | ||||||
|  | 	public static function wechatMessage(){ | ||||||
|  | 		$br = "\r\n"; | ||||||
|  | 		$text = 'IYUU自动辅种-统计报表'; | ||||||
|  | 		$desp = '总做种:'.self::$wechatMsg['hashCount'] . '  [客户端正在做种的hash总数]' .$br; | ||||||
|  | 		$desp .= '返回数据:'.self::$wechatMsg['reseedCount']. '  [服务器返回的可辅种数据]' .$br; | ||||||
|  | 		$desp .= '支持站点:'.self::$wechatMsg['sitesCount']. '  [当前支持自动辅种的站点数量]' .$br;		 | ||||||
|  | 		$desp .= '成功:'.self::$wechatMsg['reseedSuccess']. '  [辅种成功,会把hash加入缓存]' .$br; | ||||||
|  | 		$desp .= '失败:'.self::$wechatMsg['reseedError']. '  [下载器下载种子失败或网络超时引起,可以重试]' .$br; | ||||||
|  | 		$desp .= '重复:'.self::$wechatMsg['reseedRepeat']. '  [客户端已做种]' .$br; | ||||||
|  | 		$desp .= '跳过:'.self::$wechatMsg['reseedSkip']. '  [未设置passkey]' .$br; | ||||||
|  | 		$desp .= '忽略:'.self::$wechatMsg['reseedPass']. '  [成功添加存在缓存]' .$br; | ||||||
|  | 		return ff($text, $desp); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * transmission过滤函数,只保留正常做种 | ||||||
|  |  */ | ||||||
|  | function filterStatus( $v ){ | ||||||
|  | 	return isset($v['status']) && $v['status']===6; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * qBittorrent过滤函数,只保留正常做种 | ||||||
|  |  */ | ||||||
|  | function qbfilterStatus( $v ){ | ||||||
|  | 	if( isset($v['state']) && in_array($v['state'], array('uploading','stalledUP','pausedUP','queuedUP','checkingUP','forcedUP')) ){ | ||||||
|  | 		 | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | //PHP stdClass Object转array | ||||||
|  | function object_array($array) { | ||||||
|  | 	if(is_object($array)) { | ||||||
|  | 		$array = (array)$array; | ||||||
|  | 	} | ||||||
|  | 	if(is_array($array)) { | ||||||
|  | 		foreach($array as $key=>$value) { | ||||||
|  | 			$array[$key] = object_array($value); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return $array; | ||||||
|  | } | ||||||
|  | // 对象转数组 | ||||||
|  | function object2array(&$object) { | ||||||
|  | 	return json_decode( json_encode( $object ), true ); | ||||||
|  | } | ||||||
							
								
								
									
										101
									
								
								readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								readme.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | |||||||
|  | ## 功能 | ||||||
|  | IYUU自动辅种工具,目前能对国内大部分的PT站点自动辅种,支持下载器集群,支持多盘位,支持多下载目录,支持远程连接等。 | ||||||
|  |  | ||||||
|  | ## 原理 | ||||||
|  | IYUU自动辅种工具(英文名:IYUUAutoReseed),是一款PHP语言编写的Private Tracker辅种脚本,通过计划任务或常驻内存,按指定频率调用transmission、qBittorrent下载软件的API接口,提取正在做种的info_hash提交到服务器API接口,根据API接口返回的数据拼接种子连接,提交给下载器,自动辅种各个站点。 | ||||||
|  |  | ||||||
|  | ## 优势 | ||||||
|  |  - 全程自动化,无需人工干预; | ||||||
|  |  - 支持多盘位,多做种目录,多下载器,支持远程连接下载器; | ||||||
|  |  - 辅种精确度高,精度可配置; | ||||||
|  |  - 支持微信通知,消息即时达; | ||||||
|  |  - 自动对合集包,进行拆包辅种(暂未开发) | ||||||
|  |  | ||||||
|  | ## 支持的下载器 | ||||||
|  |  1. transmission | ||||||
|  |  2. qBittorrent | ||||||
|  |  | ||||||
|  | ## 支持自动辅种的站点 | ||||||
|  | 学校、杜比、家园、天空、朋友、馒头、萌猫、我堡、猫站、铂金家、烧包、北洋、TCCF、南洋、TTG、映客、城市、52pt、brobits、备胎、SSD、CHD、ptmsg、leaguehd、聆音、瓷器、hdarea、eastgame(TLF)、1ptba、hdtime、hd4fans、opencd、hdbug、hdstreet、joyhd、u2、upxin(HDU)、oshen、discfan(GZT)、cnscg圣城。 | ||||||
|  |  | ||||||
|  | ## 运行环境 | ||||||
|  | 所有具备PHP运行环境的所有平台!官方下载的记得开启crul、fileinfo、mbstring,这3个扩展。 | ||||||
|  | 例如:Linux、Windows、MacOS | ||||||
|  |  1. Windows下安装php环境:https://www.php.net/downloads | ||||||
|  |      | ||||||
|  |  | ||||||
|  | ## 下载源码 | ||||||
|  |  - github仓库:https://github.com/ledccn/IYUUAutoReseed | ||||||
|  |  - 码云仓库:https://gitee.com/ledc/IYUUAutoReseed | ||||||
|  |  | ||||||
|  | ## 使用方法 | ||||||
|  | 详见Wiki: https://gitee.com/ledc/IYUUAutoReseed/wikis  | ||||||
|  |  | ||||||
|  | ## 需求提交/错误反馈 | ||||||
|  |  - 点击链接加入群聊【IYUU自动辅种交流】:[https://jq.qq.com/?_wv=1027&k=5JOfOlM][1] | ||||||
|  |  - QQ群:859882209 | ||||||
|  |  - issues: https://gitee.com/ledc/IYUUAutoReseed/issues  | ||||||
|  |  | ||||||
|  | ## 捐助开发者 | ||||||
|  | 如果觉得我的付出,节约了您的宝贵时间,请随意打赏一杯咖啡!或者一杯水! | ||||||
|  |  | ||||||
|  | 如果喜欢,请帮忙在[Github](https://github.com/ledccn/IYUUAutoReseed)或[码云](https://gitee.com/ledc/IYUUAutoReseed)给个Star,也可以对IYUUAutoReseed进行[捐赠](https://gitee.com/ledc/IYUUAutoReseed#%E6%8D%90%E5%8A%A9%E5%BC%80%E5%8F%91%E8%80%85)哦 ^_^。 | ||||||
|  |  | ||||||
|  | **您所有的打赏将用于服务器续期,增加服务的延续性。** | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ![微信打赏.png][2] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## 捐赠者列表 | ||||||
|  | 感谢以下捐赠者,排名不分先后! | ||||||
|  |  | ||||||
|  | |名字 | 金额 | 时间| | ||||||
|  | | - | :-: | ---- | | ||||||
|  | | 祭 | ¥6元 | 2019年12月10日18:02 | | ||||||
|  | | 未署名 | ¥88.88元 | 2019年12月16日20:38 | | ||||||
|  | | 当下丶 [阿里云1H2G VPS]2021.9.17 | ¥1300元 | 2019年12月16日16:00 | | ||||||
|  | | xzs | ¥20元 | 2019年12月24日11:29 | | ||||||
|  | | loveB杉 | ¥20元 | 2019年12月24日20:59 | | ||||||
|  | | 风少 | ¥20元 | 2019年12月24日23:30 | | ||||||
|  | | 小夏 | ¥1元 | 2019年12月25日11:38 | | ||||||
|  | | 优つ伤 | ¥50元 | 2019年12月25日19:21 | | ||||||
|  | | Nice | ¥20元 | 2019年12月27日12:54 | | ||||||
|  | | 木腕清(天才) | ¥10元 | 2019年12月28日11:26 | | ||||||
|  | | @希望功能越来越多 | ¥20元 | 2019年12月28日17:29 | | ||||||
|  | | 竹节香附 | ¥20元 | 2019年12月28日18:21 | | ||||||
|  | | 李元芳 | ¥6.66 | 2019年12月30日16:19 | | ||||||
|  | | Ge(附言:client0修正) | ¥20元 | 2019年12月31日12:02 | | ||||||
|  | | 怪叔叔 | ¥20元 | 2019年12月31日15:46 | | ||||||
|  | | Shaopeng | ¥10元 | 2020年1月1日18:57 | | ||||||
|  | | III(感谢大佬的软件) | ¥10元 | 2020年1月1日22:34 | | ||||||
|  | | 子不语 | ¥10元 | 2020年1月3日13:31 | | ||||||
|  | | 寒山先生 | ¥100元 | 2020年1月3日20:35 | | ||||||
|  | | 阿腾 | ¥20元 | 2020年1月3日22:37 | | ||||||
|  | | 手动滑稽 | ¥23.33元 | 2020年1月4日01:38 | | ||||||
|  | | 凭樊 | ¥5元 | 2020年1月4日17:58 | | ||||||
|  | | Mocar | ¥10元 | 2020年1月4日20:03 | | ||||||
|  | | Throne | ¥10元 | 2020年1月4日20:09 | | ||||||
|  | | JeSsiE杰西 | ¥200元 | 2020年1月5日09:48 | | ||||||
|  | | 人生五十载 | ¥30元 | 2020年1月5日12:29 | | ||||||
|  | | C陈奕轰隆隆 | ¥20元 | 2020年1月5日15:55 | | ||||||
|  | | 寒山先生 | ¥100元 | 2020年1月6日12:17 | | ||||||
|  | | 244574970 | ¥20元 | 2020年1月6日16:18 | | ||||||
|  | | Shaopeng | ¥10元 | 2020年1月6日22:01 | | ||||||
|  | | 轲 | ¥387元 | 2020年1月7日20:34 | | ||||||
|  | | 纸鸢 | ¥2元 | 2020年1月9日11:45 | | ||||||
|  | | 寒山先生 | ¥100元 | 2020年1月9日11:51 | | ||||||
|  | | 王浩淼 | ¥50元 | 2020年1月9日11:53 | | ||||||
|  | | 寒山先生 | ¥100元 | 2020年1月11日11:47 | | ||||||
|  |  | ||||||
|  | 补充说明: | ||||||
|  |  | ||||||
|  | 1.  此明细不是为了竞价排名,而是以公开、透明的制度说明所捐赠资源的使用情况和去处;  | ||||||
|  | 2.  所捐赠的资源不属于任何个人,而应作为项目或者开发团队的所需开销;  | ||||||
|  | 3.  如果捐赠了却不希望您的名字出现在这里,可以联系我们进行相应处理; | ||||||
|  | 4.  更新有延时,如未能及时更新,可联系我。 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | [1]: https://jq.qq.com/?_wv=1027&k=5JOfOlM | ||||||
|  | [2]: https://www.iyuu.cn/usr/uploads/2019/12/801558607.png | ||||||
							
								
								
									
										7
									
								
								vendor/autoload.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/autoload.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | // autoload.php @generated by Composer | ||||||
|  |  | ||||||
|  | require_once __DIR__ . '/composer/autoload_real.php'; | ||||||
|  |  | ||||||
|  | return ComposerAutoloaderInit902220bdd481fe56c25750cdf0255dd6::getLoader(); | ||||||
							
								
								
									
										445
									
								
								vendor/composer/ClassLoader.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										445
									
								
								vendor/composer/ClassLoader.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,445 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This file is part of Composer. | ||||||
|  |  * | ||||||
|  |  * (c) Nils Adermann <naderman@naderman.de> | ||||||
|  |  *     Jordi Boggiano <j.boggiano@seld.be> | ||||||
|  |  * | ||||||
|  |  * For the full copyright and license information, please view the LICENSE | ||||||
|  |  * file that was distributed with this source code. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | namespace Composer\Autoload; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. | ||||||
|  |  * | ||||||
|  |  *     $loader = new \Composer\Autoload\ClassLoader(); | ||||||
|  |  * | ||||||
|  |  *     // register classes with namespaces | ||||||
|  |  *     $loader->add('Symfony\Component', __DIR__.'/component'); | ||||||
|  |  *     $loader->add('Symfony',           __DIR__.'/framework'); | ||||||
|  |  * | ||||||
|  |  *     // activate the autoloader | ||||||
|  |  *     $loader->register(); | ||||||
|  |  * | ||||||
|  |  *     // to enable searching the include path (eg. for PEAR packages) | ||||||
|  |  *     $loader->setUseIncludePath(true); | ||||||
|  |  * | ||||||
|  |  * In this example, if you try to use a class in the Symfony\Component | ||||||
|  |  * namespace or one of its children (Symfony\Component\Console for instance), | ||||||
|  |  * the autoloader will first look for the class under the component/ | ||||||
|  |  * directory, and it will then fallback to the framework/ directory if not | ||||||
|  |  * found before giving up. | ||||||
|  |  * | ||||||
|  |  * This class is loosely based on the Symfony UniversalClassLoader. | ||||||
|  |  * | ||||||
|  |  * @author Fabien Potencier <fabien@symfony.com> | ||||||
|  |  * @author Jordi Boggiano <j.boggiano@seld.be> | ||||||
|  |  * @see    http://www.php-fig.org/psr/psr-0/ | ||||||
|  |  * @see    http://www.php-fig.org/psr/psr-4/ | ||||||
|  |  */ | ||||||
|  | class ClassLoader | ||||||
|  | { | ||||||
|  |     // PSR-4 | ||||||
|  |     private $prefixLengthsPsr4 = array(); | ||||||
|  |     private $prefixDirsPsr4 = array(); | ||||||
|  |     private $fallbackDirsPsr4 = array(); | ||||||
|  |  | ||||||
|  |     // PSR-0 | ||||||
|  |     private $prefixesPsr0 = array(); | ||||||
|  |     private $fallbackDirsPsr0 = array(); | ||||||
|  |  | ||||||
|  |     private $useIncludePath = false; | ||||||
|  |     private $classMap = array(); | ||||||
|  |     private $classMapAuthoritative = false; | ||||||
|  |     private $missingClasses = array(); | ||||||
|  |     private $apcuPrefix; | ||||||
|  |  | ||||||
|  |     public function getPrefixes() | ||||||
|  |     { | ||||||
|  |         if (!empty($this->prefixesPsr0)) { | ||||||
|  |             return call_user_func_array('array_merge', $this->prefixesPsr0); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return array(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getPrefixesPsr4() | ||||||
|  |     { | ||||||
|  |         return $this->prefixDirsPsr4; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getFallbackDirs() | ||||||
|  |     { | ||||||
|  |         return $this->fallbackDirsPsr0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getFallbackDirsPsr4() | ||||||
|  |     { | ||||||
|  |         return $this->fallbackDirsPsr4; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getClassMap() | ||||||
|  |     { | ||||||
|  |         return $this->classMap; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @param array $classMap Class to filename map | ||||||
|  |      */ | ||||||
|  |     public function addClassMap(array $classMap) | ||||||
|  |     { | ||||||
|  |         if ($this->classMap) { | ||||||
|  |             $this->classMap = array_merge($this->classMap, $classMap); | ||||||
|  |         } else { | ||||||
|  |             $this->classMap = $classMap; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Registers a set of PSR-0 directories for a given prefix, either | ||||||
|  |      * appending or prepending to the ones previously set for this prefix. | ||||||
|  |      * | ||||||
|  |      * @param string       $prefix  The prefix | ||||||
|  |      * @param array|string $paths   The PSR-0 root directories | ||||||
|  |      * @param bool         $prepend Whether to prepend the directories | ||||||
|  |      */ | ||||||
|  |     public function add($prefix, $paths, $prepend = false) | ||||||
|  |     { | ||||||
|  |         if (!$prefix) { | ||||||
|  |             if ($prepend) { | ||||||
|  |                 $this->fallbackDirsPsr0 = array_merge( | ||||||
|  |                     (array) $paths, | ||||||
|  |                     $this->fallbackDirsPsr0 | ||||||
|  |                 ); | ||||||
|  |             } else { | ||||||
|  |                 $this->fallbackDirsPsr0 = array_merge( | ||||||
|  |                     $this->fallbackDirsPsr0, | ||||||
|  |                     (array) $paths | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $first = $prefix[0]; | ||||||
|  |         if (!isset($this->prefixesPsr0[$first][$prefix])) { | ||||||
|  |             $this->prefixesPsr0[$first][$prefix] = (array) $paths; | ||||||
|  |  | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         if ($prepend) { | ||||||
|  |             $this->prefixesPsr0[$first][$prefix] = array_merge( | ||||||
|  |                 (array) $paths, | ||||||
|  |                 $this->prefixesPsr0[$first][$prefix] | ||||||
|  |             ); | ||||||
|  |         } else { | ||||||
|  |             $this->prefixesPsr0[$first][$prefix] = array_merge( | ||||||
|  |                 $this->prefixesPsr0[$first][$prefix], | ||||||
|  |                 (array) $paths | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Registers a set of PSR-4 directories for a given namespace, either | ||||||
|  |      * appending or prepending to the ones previously set for this namespace. | ||||||
|  |      * | ||||||
|  |      * @param string       $prefix  The prefix/namespace, with trailing '\\' | ||||||
|  |      * @param array|string $paths   The PSR-4 base directories | ||||||
|  |      * @param bool         $prepend Whether to prepend the directories | ||||||
|  |      * | ||||||
|  |      * @throws \InvalidArgumentException | ||||||
|  |      */ | ||||||
|  |     public function addPsr4($prefix, $paths, $prepend = false) | ||||||
|  |     { | ||||||
|  |         if (!$prefix) { | ||||||
|  |             // Register directories for the root namespace. | ||||||
|  |             if ($prepend) { | ||||||
|  |                 $this->fallbackDirsPsr4 = array_merge( | ||||||
|  |                     (array) $paths, | ||||||
|  |                     $this->fallbackDirsPsr4 | ||||||
|  |                 ); | ||||||
|  |             } else { | ||||||
|  |                 $this->fallbackDirsPsr4 = array_merge( | ||||||
|  |                     $this->fallbackDirsPsr4, | ||||||
|  |                     (array) $paths | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  |         } elseif (!isset($this->prefixDirsPsr4[$prefix])) { | ||||||
|  |             // Register directories for a new namespace. | ||||||
|  |             $length = strlen($prefix); | ||||||
|  |             if ('\\' !== $prefix[$length - 1]) { | ||||||
|  |                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); | ||||||
|  |             } | ||||||
|  |             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; | ||||||
|  |             $this->prefixDirsPsr4[$prefix] = (array) $paths; | ||||||
|  |         } elseif ($prepend) { | ||||||
|  |             // Prepend directories for an already registered namespace. | ||||||
|  |             $this->prefixDirsPsr4[$prefix] = array_merge( | ||||||
|  |                 (array) $paths, | ||||||
|  |                 $this->prefixDirsPsr4[$prefix] | ||||||
|  |             ); | ||||||
|  |         } else { | ||||||
|  |             // Append directories for an already registered namespace. | ||||||
|  |             $this->prefixDirsPsr4[$prefix] = array_merge( | ||||||
|  |                 $this->prefixDirsPsr4[$prefix], | ||||||
|  |                 (array) $paths | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Registers a set of PSR-0 directories for a given prefix, | ||||||
|  |      * replacing any others previously set for this prefix. | ||||||
|  |      * | ||||||
|  |      * @param string       $prefix The prefix | ||||||
|  |      * @param array|string $paths  The PSR-0 base directories | ||||||
|  |      */ | ||||||
|  |     public function set($prefix, $paths) | ||||||
|  |     { | ||||||
|  |         if (!$prefix) { | ||||||
|  |             $this->fallbackDirsPsr0 = (array) $paths; | ||||||
|  |         } else { | ||||||
|  |             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Registers a set of PSR-4 directories for a given namespace, | ||||||
|  |      * replacing any others previously set for this namespace. | ||||||
|  |      * | ||||||
|  |      * @param string       $prefix The prefix/namespace, with trailing '\\' | ||||||
|  |      * @param array|string $paths  The PSR-4 base directories | ||||||
|  |      * | ||||||
|  |      * @throws \InvalidArgumentException | ||||||
|  |      */ | ||||||
|  |     public function setPsr4($prefix, $paths) | ||||||
|  |     { | ||||||
|  |         if (!$prefix) { | ||||||
|  |             $this->fallbackDirsPsr4 = (array) $paths; | ||||||
|  |         } else { | ||||||
|  |             $length = strlen($prefix); | ||||||
|  |             if ('\\' !== $prefix[$length - 1]) { | ||||||
|  |                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); | ||||||
|  |             } | ||||||
|  |             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; | ||||||
|  |             $this->prefixDirsPsr4[$prefix] = (array) $paths; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Turns on searching the include path for class files. | ||||||
|  |      * | ||||||
|  |      * @param bool $useIncludePath | ||||||
|  |      */ | ||||||
|  |     public function setUseIncludePath($useIncludePath) | ||||||
|  |     { | ||||||
|  |         $this->useIncludePath = $useIncludePath; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Can be used to check if the autoloader uses the include path to check | ||||||
|  |      * for classes. | ||||||
|  |      * | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function getUseIncludePath() | ||||||
|  |     { | ||||||
|  |         return $this->useIncludePath; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Turns off searching the prefix and fallback directories for classes | ||||||
|  |      * that have not been registered with the class map. | ||||||
|  |      * | ||||||
|  |      * @param bool $classMapAuthoritative | ||||||
|  |      */ | ||||||
|  |     public function setClassMapAuthoritative($classMapAuthoritative) | ||||||
|  |     { | ||||||
|  |         $this->classMapAuthoritative = $classMapAuthoritative; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Should class lookup fail if not found in the current class map? | ||||||
|  |      * | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function isClassMapAuthoritative() | ||||||
|  |     { | ||||||
|  |         return $this->classMapAuthoritative; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * APCu prefix to use to cache found/not-found classes, if the extension is enabled. | ||||||
|  |      * | ||||||
|  |      * @param string|null $apcuPrefix | ||||||
|  |      */ | ||||||
|  |     public function setApcuPrefix($apcuPrefix) | ||||||
|  |     { | ||||||
|  |         $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * The APCu prefix in use, or null if APCu caching is not enabled. | ||||||
|  |      * | ||||||
|  |      * @return string|null | ||||||
|  |      */ | ||||||
|  |     public function getApcuPrefix() | ||||||
|  |     { | ||||||
|  |         return $this->apcuPrefix; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Registers this instance as an autoloader. | ||||||
|  |      * | ||||||
|  |      * @param bool $prepend Whether to prepend the autoloader or not | ||||||
|  |      */ | ||||||
|  |     public function register($prepend = false) | ||||||
|  |     { | ||||||
|  |         spl_autoload_register(array($this, 'loadClass'), true, $prepend); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Unregisters this instance as an autoloader. | ||||||
|  |      */ | ||||||
|  |     public function unregister() | ||||||
|  |     { | ||||||
|  |         spl_autoload_unregister(array($this, 'loadClass')); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Loads the given class or interface. | ||||||
|  |      * | ||||||
|  |      * @param  string    $class The name of the class | ||||||
|  |      * @return bool|null True if loaded, null otherwise | ||||||
|  |      */ | ||||||
|  |     public function loadClass($class) | ||||||
|  |     { | ||||||
|  |         if ($file = $this->findFile($class)) { | ||||||
|  |             includeFile($file); | ||||||
|  |  | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Finds the path to the file where the class is defined. | ||||||
|  |      * | ||||||
|  |      * @param string $class The name of the class | ||||||
|  |      * | ||||||
|  |      * @return string|false The path if found, false otherwise | ||||||
|  |      */ | ||||||
|  |     public function findFile($class) | ||||||
|  |     { | ||||||
|  |         // class map lookup | ||||||
|  |         if (isset($this->classMap[$class])) { | ||||||
|  |             return $this->classMap[$class]; | ||||||
|  |         } | ||||||
|  |         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (null !== $this->apcuPrefix) { | ||||||
|  |             $file = apcu_fetch($this->apcuPrefix.$class, $hit); | ||||||
|  |             if ($hit) { | ||||||
|  |                 return $file; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $file = $this->findFileWithExtension($class, '.php'); | ||||||
|  |  | ||||||
|  |         // Search for Hack files if we are running on HHVM | ||||||
|  |         if (false === $file && defined('HHVM_VERSION')) { | ||||||
|  |             $file = $this->findFileWithExtension($class, '.hh'); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (null !== $this->apcuPrefix) { | ||||||
|  |             apcu_add($this->apcuPrefix.$class, $file); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (false === $file) { | ||||||
|  |             // Remember that this class does not exist. | ||||||
|  |             $this->missingClasses[$class] = true; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $file; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function findFileWithExtension($class, $ext) | ||||||
|  |     { | ||||||
|  |         // PSR-4 lookup | ||||||
|  |         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; | ||||||
|  |  | ||||||
|  |         $first = $class[0]; | ||||||
|  |         if (isset($this->prefixLengthsPsr4[$first])) { | ||||||
|  |             $subPath = $class; | ||||||
|  |             while (false !== $lastPos = strrpos($subPath, '\\')) { | ||||||
|  |                 $subPath = substr($subPath, 0, $lastPos); | ||||||
|  |                 $search = $subPath . '\\'; | ||||||
|  |                 if (isset($this->prefixDirsPsr4[$search])) { | ||||||
|  |                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); | ||||||
|  |                     foreach ($this->prefixDirsPsr4[$search] as $dir) { | ||||||
|  |                         if (file_exists($file = $dir . $pathEnd)) { | ||||||
|  |                             return $file; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // PSR-4 fallback dirs | ||||||
|  |         foreach ($this->fallbackDirsPsr4 as $dir) { | ||||||
|  |             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { | ||||||
|  |                 return $file; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // PSR-0 lookup | ||||||
|  |         if (false !== $pos = strrpos($class, '\\')) { | ||||||
|  |             // namespaced class name | ||||||
|  |             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) | ||||||
|  |                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); | ||||||
|  |         } else { | ||||||
|  |             // PEAR-like class name | ||||||
|  |             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (isset($this->prefixesPsr0[$first])) { | ||||||
|  |             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { | ||||||
|  |                 if (0 === strpos($class, $prefix)) { | ||||||
|  |                     foreach ($dirs as $dir) { | ||||||
|  |                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { | ||||||
|  |                             return $file; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // PSR-0 fallback dirs | ||||||
|  |         foreach ($this->fallbackDirsPsr0 as $dir) { | ||||||
|  |             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { | ||||||
|  |                 return $file; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // PSR-0 include paths. | ||||||
|  |         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { | ||||||
|  |             return $file; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Scope isolated include. | ||||||
|  |  * | ||||||
|  |  * Prevents access to $this/self from included files. | ||||||
|  |  */ | ||||||
|  | function includeFile($file) | ||||||
|  | { | ||||||
|  |     include $file; | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								vendor/composer/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/composer/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  |  | ||||||
|  | Copyright (c) Nils Adermann, Jordi Boggiano | ||||||
|  |  | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||||
|  | in the Software without restriction, including without limitation the rights | ||||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the Software is furnished | ||||||
|  | to do so, subject to the following conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be included in all | ||||||
|  | copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  | THE SOFTWARE. | ||||||
|  |  | ||||||
							
								
								
									
										17
									
								
								vendor/composer/autoload_classmap.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/composer/autoload_classmap.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | // autoload_classmap.php @generated by Composer | ||||||
|  |  | ||||||
|  | $vendorDir = dirname(dirname(__FILE__)); | ||||||
|  | $baseDir = dirname($vendorDir); | ||||||
|  |  | ||||||
|  | return array( | ||||||
|  |     'Bencode' => $baseDir . '/app/Class/Bencode.php', | ||||||
|  |     'IFile' => $baseDir . '/app/Class/IFile.php', | ||||||
|  |     'Oauth' => $baseDir . '/app/Class/Oauth.php', | ||||||
|  |     'Rpc' => $baseDir . '/app/Class/Rpc.php', | ||||||
|  |     'TransmissionRPC' => $baseDir . '/app/Class/TransmissionRPC.php', | ||||||
|  |     'TransmissionRPCException' => $baseDir . '/app/Class/TransmissionRPC.php', | ||||||
|  |     'qBittorrent' => $baseDir . '/app/Class/qBittorrent.php', | ||||||
|  |     'uTorrent' => $baseDir . '/app/Class/uTorrent.php', | ||||||
|  | ); | ||||||
							
								
								
									
										10
									
								
								vendor/composer/autoload_files.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								vendor/composer/autoload_files.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | // autoload_files.php @generated by Composer | ||||||
|  |  | ||||||
|  | $vendorDir = dirname(dirname(__FILE__)); | ||||||
|  | $baseDir = dirname($vendorDir); | ||||||
|  |  | ||||||
|  | return array( | ||||||
|  |     '818e4acb2b433594ec9a26bacb71084d' => $baseDir . '/app/Class/Function.php', | ||||||
|  | ); | ||||||
							
								
								
									
										10
									
								
								vendor/composer/autoload_namespaces.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								vendor/composer/autoload_namespaces.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | // autoload_namespaces.php @generated by Composer | ||||||
|  |  | ||||||
|  | $vendorDir = dirname(dirname(__FILE__)); | ||||||
|  | $baseDir = dirname($vendorDir); | ||||||
|  |  | ||||||
|  | return array( | ||||||
|  |     'Curl' => array($vendorDir . '/curl/curl/src'), | ||||||
|  | ); | ||||||
							
								
								
									
										10
									
								
								vendor/composer/autoload_psr4.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								vendor/composer/autoload_psr4.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | // autoload_psr4.php @generated by Composer | ||||||
|  |  | ||||||
|  | $vendorDir = dirname(dirname(__FILE__)); | ||||||
|  | $baseDir = dirname($vendorDir); | ||||||
|  |  | ||||||
|  | return array( | ||||||
|  |     'phpspider\\' => array($vendorDir . '/owner888/phpspider'), | ||||||
|  | ); | ||||||
							
								
								
									
										70
									
								
								vendor/composer/autoload_real.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								vendor/composer/autoload_real.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | // autoload_real.php @generated by Composer | ||||||
|  |  | ||||||
|  | class ComposerAutoloaderInit902220bdd481fe56c25750cdf0255dd6 | ||||||
|  | { | ||||||
|  |     private static $loader; | ||||||
|  |  | ||||||
|  |     public static function loadClassLoader($class) | ||||||
|  |     { | ||||||
|  |         if ('Composer\Autoload\ClassLoader' === $class) { | ||||||
|  |             require __DIR__ . '/ClassLoader.php'; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function getLoader() | ||||||
|  |     { | ||||||
|  |         if (null !== self::$loader) { | ||||||
|  |             return self::$loader; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         spl_autoload_register(array('ComposerAutoloaderInit902220bdd481fe56c25750cdf0255dd6', 'loadClassLoader'), true, true); | ||||||
|  |         self::$loader = $loader = new \Composer\Autoload\ClassLoader(); | ||||||
|  |         spl_autoload_unregister(array('ComposerAutoloaderInit902220bdd481fe56c25750cdf0255dd6', 'loadClassLoader')); | ||||||
|  |  | ||||||
|  |         $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); | ||||||
|  |         if ($useStaticLoader) { | ||||||
|  |             require_once __DIR__ . '/autoload_static.php'; | ||||||
|  |  | ||||||
|  |             call_user_func(\Composer\Autoload\ComposerStaticInit902220bdd481fe56c25750cdf0255dd6::getInitializer($loader)); | ||||||
|  |         } else { | ||||||
|  |             $map = require __DIR__ . '/autoload_namespaces.php'; | ||||||
|  |             foreach ($map as $namespace => $path) { | ||||||
|  |                 $loader->set($namespace, $path); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             $map = require __DIR__ . '/autoload_psr4.php'; | ||||||
|  |             foreach ($map as $namespace => $path) { | ||||||
|  |                 $loader->setPsr4($namespace, $path); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             $classMap = require __DIR__ . '/autoload_classmap.php'; | ||||||
|  |             if ($classMap) { | ||||||
|  |                 $loader->addClassMap($classMap); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $loader->register(true); | ||||||
|  |  | ||||||
|  |         if ($useStaticLoader) { | ||||||
|  |             $includeFiles = Composer\Autoload\ComposerStaticInit902220bdd481fe56c25750cdf0255dd6::$files; | ||||||
|  |         } else { | ||||||
|  |             $includeFiles = require __DIR__ . '/autoload_files.php'; | ||||||
|  |         } | ||||||
|  |         foreach ($includeFiles as $fileIdentifier => $file) { | ||||||
|  |             composerRequire902220bdd481fe56c25750cdf0255dd6($fileIdentifier, $file); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $loader; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function composerRequire902220bdd481fe56c25750cdf0255dd6($fileIdentifier, $file) | ||||||
|  | { | ||||||
|  |     if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { | ||||||
|  |         require $file; | ||||||
|  |  | ||||||
|  |         $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										58
									
								
								vendor/composer/autoload_static.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								vendor/composer/autoload_static.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | // autoload_static.php @generated by Composer | ||||||
|  |  | ||||||
|  | namespace Composer\Autoload; | ||||||
|  |  | ||||||
|  | class ComposerStaticInit902220bdd481fe56c25750cdf0255dd6 | ||||||
|  | { | ||||||
|  |     public static $files = array ( | ||||||
|  |         '818e4acb2b433594ec9a26bacb71084d' => __DIR__ . '/../..' . '/app/Class/Function.php', | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     public static $prefixLengthsPsr4 = array ( | ||||||
|  |         'p' =>  | ||||||
|  |         array ( | ||||||
|  |             'phpspider\\' => 10, | ||||||
|  |         ), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     public static $prefixDirsPsr4 = array ( | ||||||
|  |         'phpspider\\' =>  | ||||||
|  |         array ( | ||||||
|  |             0 => __DIR__ . '/..' . '/owner888/phpspider', | ||||||
|  |         ), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     public static $prefixesPsr0 = array ( | ||||||
|  |         'C' =>  | ||||||
|  |         array ( | ||||||
|  |             'Curl' =>  | ||||||
|  |             array ( | ||||||
|  |                 0 => __DIR__ . '/..' . '/curl/curl/src', | ||||||
|  |             ), | ||||||
|  |         ), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     public static $classMap = array ( | ||||||
|  |         'Bencode' => __DIR__ . '/../..' . '/app/Class/Bencode.php', | ||||||
|  |         'IFile' => __DIR__ . '/../..' . '/app/Class/IFile.php', | ||||||
|  |         'Oauth' => __DIR__ . '/../..' . '/app/Class/Oauth.php', | ||||||
|  |         'Rpc' => __DIR__ . '/../..' . '/app/Class/Rpc.php', | ||||||
|  |         'TransmissionRPC' => __DIR__ . '/../..' . '/app/Class/TransmissionRPC.php', | ||||||
|  |         'TransmissionRPCException' => __DIR__ . '/../..' . '/app/Class/TransmissionRPC.php', | ||||||
|  |         'qBittorrent' => __DIR__ . '/../..' . '/app/Class/qBittorrent.php', | ||||||
|  |         'uTorrent' => __DIR__ . '/../..' . '/app/Class/uTorrent.php', | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     public static function getInitializer(ClassLoader $loader) | ||||||
|  |     { | ||||||
|  |         return \Closure::bind(function () use ($loader) { | ||||||
|  |             $loader->prefixLengthsPsr4 = ComposerStaticInit902220bdd481fe56c25750cdf0255dd6::$prefixLengthsPsr4; | ||||||
|  |             $loader->prefixDirsPsr4 = ComposerStaticInit902220bdd481fe56c25750cdf0255dd6::$prefixDirsPsr4; | ||||||
|  |             $loader->prefixesPsr0 = ComposerStaticInit902220bdd481fe56c25750cdf0255dd6::$prefixesPsr0; | ||||||
|  |             $loader->classMap = ComposerStaticInit902220bdd481fe56c25750cdf0255dd6::$classMap; | ||||||
|  |  | ||||||
|  |         }, null, ClassLoader::class); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										119
									
								
								vendor/composer/installed.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								vendor/composer/installed.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | |||||||
|  | [ | ||||||
|  |     { | ||||||
|  |         "name": "curl/curl", | ||||||
|  |         "version": "2.2.0", | ||||||
|  |         "version_normalized": "2.2.0.0", | ||||||
|  |         "source": { | ||||||
|  |             "type": "git", | ||||||
|  |             "url": "https://github.com/php-mod/curl.git", | ||||||
|  |             "reference": "d22086dd2eee5ca02e4c29b9a5bdf3645bfdbbff" | ||||||
|  |         }, | ||||||
|  |         "dist": { | ||||||
|  |             "type": "zip", | ||||||
|  |             "url": "https://api.github.com/repos/php-mod/curl/zipball/d22086dd2eee5ca02e4c29b9a5bdf3645bfdbbff", | ||||||
|  |             "reference": "d22086dd2eee5ca02e4c29b9a5bdf3645bfdbbff", | ||||||
|  |             "shasum": "", | ||||||
|  |             "mirrors": [ | ||||||
|  |                 { | ||||||
|  |                     "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", | ||||||
|  |                     "preferred": true | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         "require": { | ||||||
|  |             "ext-curl": "*", | ||||||
|  |             "php": "^5.6 | ^7.0" | ||||||
|  |         }, | ||||||
|  |         "require-dev": { | ||||||
|  |             "phpunit/phpunit": "^5.7", | ||||||
|  |             "squizlabs/php_codesniffer": "~2.1" | ||||||
|  |         }, | ||||||
|  |         "time": "2018-12-04T19:47:03+00:00", | ||||||
|  |         "type": "library", | ||||||
|  |         "installation-source": "dist", | ||||||
|  |         "autoload": { | ||||||
|  |             "psr-0": { | ||||||
|  |                 "Curl": "src/" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "notification-url": "https://packagist.org/downloads/", | ||||||
|  |         "license": [ | ||||||
|  |             "MIT" | ||||||
|  |         ], | ||||||
|  |         "authors": [ | ||||||
|  |             { | ||||||
|  |                 "name": "Hassan Amouhzi", | ||||||
|  |                 "email": "hassan@anezi.net", | ||||||
|  |                 "homepage": "http://hassan.amouhzi.com" | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 "name": "php-curl-class", | ||||||
|  |                 "homepage": "https://github.com/php-curl-class" | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 "name": "user52", | ||||||
|  |                 "homepage": "https://github.com/user52" | ||||||
|  |             } | ||||||
|  |         ], | ||||||
|  |         "description": "cURL class for PHP", | ||||||
|  |         "homepage": "https://github.com/php-mod/curl", | ||||||
|  |         "keywords": [ | ||||||
|  |             "curl", | ||||||
|  |             "dot" | ||||||
|  |         ] | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         "name": "owner888/phpspider", | ||||||
|  |         "version": "v2.1.6", | ||||||
|  |         "version_normalized": "2.1.6.0", | ||||||
|  |         "source": { | ||||||
|  |             "type": "git", | ||||||
|  |             "url": "https://github.com/owner888/phpspider.git", | ||||||
|  |             "reference": "e6021148adec201418c16ba26f39bc013ba5b4d9" | ||||||
|  |         }, | ||||||
|  |         "dist": { | ||||||
|  |             "type": "zip", | ||||||
|  |             "url": "https://api.github.com/repos/owner888/phpspider/zipball/e6021148adec201418c16ba26f39bc013ba5b4d9", | ||||||
|  |             "reference": "e6021148adec201418c16ba26f39bc013ba5b4d9", | ||||||
|  |             "shasum": "", | ||||||
|  |             "mirrors": [ | ||||||
|  |                 { | ||||||
|  |                     "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", | ||||||
|  |                     "preferred": true | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         "require": { | ||||||
|  |             "php": ">=5.5.0" | ||||||
|  |         }, | ||||||
|  |         "suggest": { | ||||||
|  |             "ext-pcntl、ext-redis": "For better performance. " | ||||||
|  |         }, | ||||||
|  |         "time": "2018-08-15T08:04:29+00:00", | ||||||
|  |         "type": "library", | ||||||
|  |         "installation-source": "dist", | ||||||
|  |         "autoload": { | ||||||
|  |             "psr-4": { | ||||||
|  |                 "phpspider\\": "./" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "notification-url": "https://packagist.org/downloads/", | ||||||
|  |         "license": [ | ||||||
|  |             "MIT" | ||||||
|  |         ], | ||||||
|  |         "authors": [ | ||||||
|  |             { | ||||||
|  |                 "name": "Seatle Yang", | ||||||
|  |                 "email": "seatle@foxmail.com", | ||||||
|  |                 "homepage": "http://www.phpspider.org", | ||||||
|  |                 "role": "Developer" | ||||||
|  |             } | ||||||
|  |         ], | ||||||
|  |         "description": "The PHPSpider Framework.", | ||||||
|  |         "homepage": "http://www.phpspider.org", | ||||||
|  |         "keywords": [ | ||||||
|  |             "framework", | ||||||
|  |             "phpspider" | ||||||
|  |         ] | ||||||
|  |     } | ||||||
|  | ] | ||||||
							
								
								
									
										11
									
								
								vendor/curl/curl/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/curl/curl/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | vendor/* | ||||||
|  | *.orig | ||||||
|  | .buildpath | ||||||
|  | .project | ||||||
|  | .settings/* | ||||||
|  | .idea/* | ||||||
|  | composer.lock | ||||||
|  | *~ | ||||||
|  | tests/phpunit_report/* | ||||||
|  | /.settings/ | ||||||
|  | /.php_cs.cache | ||||||
							
								
								
									
										113
									
								
								vendor/curl/curl/.gitlab-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								vendor/curl/curl/.gitlab-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,113 @@ | |||||||
|  | stages: | ||||||
|  |     - build | ||||||
|  |     - test | ||||||
|  |  | ||||||
|  | build-test-server: | ||||||
|  |     image: docker:latest | ||||||
|  |     stage: build | ||||||
|  |     services: | ||||||
|  |         - docker:dind | ||||||
|  |     script: | ||||||
|  |         - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY | ||||||
|  |         - docker build --pull -t "$CI_REGISTRY_IMAGE:server-test" tests/server | ||||||
|  |         - docker push "$CI_REGISTRY_IMAGE:server-test" | ||||||
|  |     only: | ||||||
|  |         changes: | ||||||
|  |             - tests/server | ||||||
|  |  | ||||||
|  | tests-php5.6: | ||||||
|  |     image: alpine:3.7 | ||||||
|  |     stage: test | ||||||
|  |     services: | ||||||
|  |         - name: "$CI_REGISTRY_IMAGE:server-test" | ||||||
|  |           alias: server_test | ||||||
|  |     script: | ||||||
|  |         - apk add --no-cache php5-cli php5-curl php5-gd php5-phar php5-json php5-openssl php5-dom php5-xml php5-zlib | ||||||
|  |         - ln -s /usr/bin/php5 /usr/bin/php | ||||||
|  |         - php --version | ||||||
|  |         - if [ ! -f composer.phar ]; then DOWLOAD_COMPOSER=1 ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "if (hash_file('sha384', 'composer-setup.php') === '93b54496392c062774670ac18b134c3b3a95e5a5e5c8f1a9f115f203b75bf9a129d5daa8ba6a13e2cc8a1da0806388a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php composer-setup.php ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "unlink('composer-setup.php');" ; fi; | ||||||
|  |         - php composer.phar install | ||||||
|  |         - vendor/bin/phpcs --warning-severity=0 --standard=PSR2 src | ||||||
|  |         - vendor/bin/phpunit | ||||||
|  |     cache: | ||||||
|  |         key: php5.6 | ||||||
|  |         paths: | ||||||
|  |             - composer.phar | ||||||
|  |             - vendor | ||||||
|  |  | ||||||
|  | tests-php7.0: | ||||||
|  |     image: alpine:3.5 | ||||||
|  |     stage: test | ||||||
|  |     services: | ||||||
|  |         - name: "$CI_REGISTRY_IMAGE:server-test" | ||||||
|  |           alias: server_test | ||||||
|  |     script: | ||||||
|  |         - apk add --no-cache php7 php7-curl php7-gd php7-phar php7-json php7-openssl php7-dom php7-mbstring | ||||||
|  |         - ln -s /usr/bin/php7 /usr/bin/php | ||||||
|  |         - php --version | ||||||
|  |         - if [ ! -f composer.phar ]; then DOWLOAD_COMPOSER=1 ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "if (hash_file('sha384', 'composer-setup.php') === '93b54496392c062774670ac18b134c3b3a95e5a5e5c8f1a9f115f203b75bf9a129d5daa8ba6a13e2cc8a1da0806388a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php composer-setup.php ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "unlink('composer-setup.php');" ; fi; | ||||||
|  |         - php composer.phar install | ||||||
|  |         - vendor/bin/phpcs --warning-severity=0 --standard=PSR2 src | ||||||
|  |         - nohup php -S localhost:8000 -t tests/server/php-curl-test > phpd.log 2>&1 & | ||||||
|  |         - vendor/bin/phpunit | ||||||
|  |     cache: | ||||||
|  |         key: php7.0 | ||||||
|  |         paths: | ||||||
|  |             - composer.phar | ||||||
|  |             - vendor | ||||||
|  |  | ||||||
|  | tests-php7.1: | ||||||
|  |     image: alpine:3.7 | ||||||
|  |     stage: test | ||||||
|  |     services: | ||||||
|  |         - name: "$CI_REGISTRY_IMAGE:server-test" | ||||||
|  |           alias: server_test | ||||||
|  |     script: | ||||||
|  |         - apk add --no-cache php7-cli php7-curl php7-gd php7-phar php7-json php7-openssl php7-dom php7-simplexml php7-tokenizer php7-mbstring php7-xml | ||||||
|  |         - php --version | ||||||
|  |         - if [ ! -f composer.phar ]; then DOWLOAD_COMPOSER=1 ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "if (hash_file('sha384', 'composer-setup.php') === '93b54496392c062774670ac18b134c3b3a95e5a5e5c8f1a9f115f203b75bf9a129d5daa8ba6a13e2cc8a1da0806388a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php composer-setup.php ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "unlink('composer-setup.php');" ; fi; | ||||||
|  |         - php composer.phar install | ||||||
|  |         - vendor/bin/phpcs --warning-severity=0 --standard=PSR2 src | ||||||
|  |         - nohup php -S localhost:8000 -t tests/server/php-curl-test > phpd.log 2>&1 & | ||||||
|  |         - vendor/bin/phpunit | ||||||
|  |     cache: | ||||||
|  |         key: php7.1 | ||||||
|  |         paths: | ||||||
|  |             - composer.phar | ||||||
|  |             - vendor | ||||||
|  |  | ||||||
|  | tests-php7.2: | ||||||
|  |     image: alpine:3.8 | ||||||
|  |     stage: test | ||||||
|  |     services: | ||||||
|  |         - name: "$CI_REGISTRY_IMAGE:server-test" | ||||||
|  |           alias: server_test | ||||||
|  |     script: | ||||||
|  |         - apk add --no-cache php7-cli php7-curl php7-gd php7-phar php7-json php7-openssl php7-dom php7-simplexml php7-tokenizer php7-mbstring php7-xml | ||||||
|  |         - php --version | ||||||
|  |         - if [ ! -f composer.phar ]; then DOWLOAD_COMPOSER=1 ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "if (hash_file('sha384', 'composer-setup.php') === '93b54496392c062774670ac18b134c3b3a95e5a5e5c8f1a9f115f203b75bf9a129d5daa8ba6a13e2cc8a1da0806388a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php composer-setup.php ; fi; | ||||||
|  |         - if [ -n "$DOWLOAD_COMPOSER" ] ; then php -r "unlink('composer-setup.php');" ; fi; | ||||||
|  |         - php composer.phar install | ||||||
|  |         - vendor/bin/phpcs --warning-severity=0 --standard=PSR2 src | ||||||
|  |         - nohup php -S localhost:8000 -t tests/server/php-curl-test > phpd.log 2>&1 & | ||||||
|  |         - vendor/bin/phpunit | ||||||
|  |     cache: | ||||||
|  |         key: php7.2 | ||||||
|  |         paths: | ||||||
|  |             - composer.phar | ||||||
|  |             - vendor | ||||||
							
								
								
									
										20
									
								
								vendor/curl/curl/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/curl/curl/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | The MIT License (MIT) | ||||||
|  |  | ||||||
|  | Copyright (c) 2013 php-mod | ||||||
|  |  | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||||
|  | this software and associated documentation files (the "Software"), to deal in | ||||||
|  | the Software without restriction, including without limitation the rights to | ||||||
|  | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||||
|  | the Software, and to permit persons to whom the Software is furnished to do so, | ||||||
|  | subject to the following conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be included in all | ||||||
|  | copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||||
|  | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||||
|  | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||||
|  | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||||
|  | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||||
							
								
								
									
										125
									
								
								vendor/curl/curl/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								vendor/curl/curl/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | |||||||
|  | # PHP Curl Class | ||||||
|  |  | ||||||
|  | This library provides an object-oriented wrapper of the PHP cURL extension. | ||||||
|  |  | ||||||
|  | If you have questions or problems with installation or usage [create an Issue](https://github.com/php-mod/curl/issues). | ||||||
|  |  | ||||||
|  | ## Installation | ||||||
|  |  | ||||||
|  | In order to install this library via composer run the following command in the console: | ||||||
|  |  | ||||||
|  | ```sh | ||||||
|  | composer require curl/curl | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | or add the package manually to your composer.json file in the require section: | ||||||
|  |  | ||||||
|  | ```json | ||||||
|  | "curl/curl": "^2.0" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Usage examples | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | $curl = new Curl\Curl(); | ||||||
|  | $curl->get('http://www.example.com/'); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | $curl = new Curl\Curl(); | ||||||
|  | $curl->get('http://www.example.com/search', array( | ||||||
|  |     'q' => 'keyword', | ||||||
|  | )); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | $curl = new Curl\Curl(); | ||||||
|  | $curl->post('http://www.example.com/login/', array( | ||||||
|  |     'username' => 'myusername', | ||||||
|  |     'password' => 'mypassword', | ||||||
|  | )); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | $curl = new Curl\Curl(); | ||||||
|  | $curl->setBasicAuthentication('username', 'password'); | ||||||
|  | $curl->setUserAgent(''); | ||||||
|  | $curl->setReferrer(''); | ||||||
|  | $curl->setHeader('X-Requested-With', 'XMLHttpRequest'); | ||||||
|  | $curl->setCookie('key', 'value'); | ||||||
|  | $curl->get('http://www.example.com/'); | ||||||
|  |  | ||||||
|  | if ($curl->error) { | ||||||
|  |     echo $curl->error_code; | ||||||
|  | } | ||||||
|  | else { | ||||||
|  |     echo $curl->response; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var_dump($curl->request_headers); | ||||||
|  | var_dump($curl->response_headers); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | $curl = new Curl\Curl(); | ||||||
|  | $curl->setOpt(CURLOPT_RETURNTRANSFER, TRUE); | ||||||
|  | $curl->setOpt(CURLOPT_SSL_VERIFYPEER, FALSE); | ||||||
|  | $curl->get('https://encrypted.example.com/'); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | $curl = new Curl\Curl(); | ||||||
|  | $curl->put('http://api.example.com/user/', array( | ||||||
|  |     'first_name' => 'Zach', | ||||||
|  |     'last_name' => 'Borboa', | ||||||
|  | )); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | $curl = new Curl\Curl(); | ||||||
|  | $curl->patch('http://api.example.com/profile/', array( | ||||||
|  |     'image' => '@path/to/file.jpg', | ||||||
|  | )); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | $curl = new Curl\Curl(); | ||||||
|  | $curl->delete('http://api.example.com/user/', array( | ||||||
|  |     'id' => '1234', | ||||||
|  | )); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | $curl->close(); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | // Example access to curl object. | ||||||
|  | curl_set_opt($curl->curl, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1'); | ||||||
|  | curl_close($curl->curl); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | // Example of downloading a file or any other content | ||||||
|  | $curl = new Curl\Curl(); | ||||||
|  | // open the file where the request response should be written | ||||||
|  | $file_handle = fopen($target_file, 'w+'); | ||||||
|  | // pass it to the curl resource | ||||||
|  | $curl->setOpt(CURLOPT_FILE, $file_handle); | ||||||
|  | // do any type of request | ||||||
|  | $curl->get('https://github.com'); | ||||||
|  | // disable writing to file | ||||||
|  | $curl->setOpt(CURLOPT_FILE, null); | ||||||
|  | // close the file for writing | ||||||
|  | fclose($file_handle); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Testing | ||||||
|  |  | ||||||
|  | In order to test the library: | ||||||
|  |  | ||||||
|  | 1. Create a fork | ||||||
|  | 2. Clone the fork to your machine | ||||||
|  | 3. Install the depencies `composer install` | ||||||
|  | 4. Run the unit tests `./vendor/bin/phpunit tests` | ||||||
							
								
								
									
										36
									
								
								vendor/curl/curl/composer.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/curl/curl/composer.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | { | ||||||
|  |   "name": "curl/curl", | ||||||
|  |   "description": "cURL class for PHP", | ||||||
|  |   "keywords": ["dot", "curl"], | ||||||
|  |   "homepage": "https://github.com/php-mod/curl", | ||||||
|  |   "type": "library", | ||||||
|  |   "license": "MIT", | ||||||
|  |   "authors": [ | ||||||
|  |     { | ||||||
|  |       "name": "php-curl-class", | ||||||
|  |       "homepage": "https://github.com/php-curl-class" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "Hassan Amouhzi", | ||||||
|  |       "email": "hassan@anezi.net", | ||||||
|  |       "homepage": "http://hassan.amouhzi.com" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "user52", | ||||||
|  |       "homepage": "https://github.com/user52" | ||||||
|  |     } | ||||||
|  |   ], | ||||||
|  |   "require": { | ||||||
|  |     "php": "^5.6 | ^7.0", | ||||||
|  |     "ext-curl": "*" | ||||||
|  |   }, | ||||||
|  |   "require-dev": { | ||||||
|  |     "phpunit/phpunit": "^5.7", | ||||||
|  |     "squizlabs/php_codesniffer": "~2.1" | ||||||
|  |   }, | ||||||
|  |   "autoload": { | ||||||
|  |     "psr-0": { | ||||||
|  |       "Curl": "src/" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								vendor/curl/curl/phpunit.xml.dist
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/curl/curl/phpunit.xml.dist
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <phpunit backupGlobals="false" | ||||||
|  |          backupStaticAttributes="false" | ||||||
|  |          colors="true" | ||||||
|  |          convertErrorsToExceptions="true" | ||||||
|  |          convertNoticesToExceptions="true" | ||||||
|  |          convertWarningsToExceptions="true" | ||||||
|  |          processIsolation="false" | ||||||
|  |          stopOnFailure="false" | ||||||
|  |          syntaxCheck="true" | ||||||
|  |          verbose="false" | ||||||
|  |          bootstrap="vendor/autoload.php" | ||||||
|  | > | ||||||
|  |     <php> | ||||||
|  |       <ini name="display_errors" value="on"/> | ||||||
|  |     </php> | ||||||
|  |  | ||||||
|  |     <testsuites> | ||||||
|  |         <testsuite name="PHP MP4Box Tests Suite"> | ||||||
|  |             <directory>tests</directory> | ||||||
|  |         </testsuite> | ||||||
|  |     </testsuites> | ||||||
|  |  | ||||||
|  | </phpunit> | ||||||
							
								
								
									
										719
									
								
								vendor/curl/curl/src/Curl/Curl.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										719
									
								
								vendor/curl/curl/src/Curl/Curl.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,719 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace Curl; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * An object-oriented wrapper of the PHP cURL extension. | ||||||
|  |  * | ||||||
|  |  * This library requires to have the php cURL extensions installed: | ||||||
|  |  * https://php.net/manual/curl.setup.php | ||||||
|  |  * | ||||||
|  |  * Example of making a get request with parameters: | ||||||
|  |  * | ||||||
|  |  * ```php | ||||||
|  |  * $curl = new Curl\Curl(); | ||||||
|  |  * $curl->get('http://www.example.com/search', array( | ||||||
|  |  *     'q' => 'keyword', | ||||||
|  |  * )); | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * Example post request with post data: | ||||||
|  |  * | ||||||
|  |  * ```php | ||||||
|  |  * $curl = new Curl\Curl(); | ||||||
|  |  * $curl->post('http://www.example.com/login/', array( | ||||||
|  |  *     'username' => 'myusername', | ||||||
|  |  *     'password' => 'mypassword', | ||||||
|  |  * )); | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * @see https://php.net/manual/curl.setup.php | ||||||
|  |  */ | ||||||
|  | class Curl | ||||||
|  | { | ||||||
|  |     // The HTTP authentication method(s) to use. | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string Type AUTH_BASIC | ||||||
|  |      */ | ||||||
|  |     const AUTH_BASIC = CURLAUTH_BASIC; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string Type AUTH_DIGEST | ||||||
|  |      */ | ||||||
|  |     const AUTH_DIGEST = CURLAUTH_DIGEST; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string Type AUTH_GSSNEGOTIATE | ||||||
|  |      */ | ||||||
|  |     const AUTH_GSSNEGOTIATE = CURLAUTH_GSSNEGOTIATE; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string Type AUTH_NTLM | ||||||
|  |      */ | ||||||
|  |     const AUTH_NTLM = CURLAUTH_NTLM; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string Type AUTH_ANY | ||||||
|  |      */ | ||||||
|  |     const AUTH_ANY = CURLAUTH_ANY; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string Type AUTH_ANYSAFE | ||||||
|  |      */ | ||||||
|  |     const AUTH_ANYSAFE = CURLAUTH_ANYSAFE; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string The user agent name which is set when making a request | ||||||
|  |      */ | ||||||
|  |     const USER_AGENT = 'PHP Curl/1.9 (+https://github.com/php-mod/curl)'; | ||||||
|  |  | ||||||
|  |     private $_cookies = array(); | ||||||
|  |  | ||||||
|  |     private $_headers = array(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var resource Contains the curl resource created by `curl_init()` function | ||||||
|  |      */ | ||||||
|  |     public $curl; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var bool Whether an error occured or not | ||||||
|  |      */ | ||||||
|  |     public $error = false; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var int Contains the error code of the curren request, 0 means no error happend | ||||||
|  |      */ | ||||||
|  |     public $error_code = 0; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string If the curl request failed, the error message is contained | ||||||
|  |      */ | ||||||
|  |     public $error_message = null; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var bool Whether an error occured or not | ||||||
|  |      */ | ||||||
|  |     public $curl_error = false; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var int Contains the error code of the curren request, 0 means no error happend. | ||||||
|  |      * @see https://curl.haxx.se/libcurl/c/libcurl-errors.html | ||||||
|  |      */ | ||||||
|  |     public $curl_error_code = 0; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string If the curl request failed, the error message is contained | ||||||
|  |      */ | ||||||
|  |     public $curl_error_message = null; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var bool Whether an error occured or not | ||||||
|  |      */ | ||||||
|  |     public $http_error = false; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var int Contains the status code of the current processed request. | ||||||
|  |      */ | ||||||
|  |     public $http_status_code = 0; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string If the curl request failed, the error message is contained | ||||||
|  |      */ | ||||||
|  |     public $http_error_message = null; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string|array TBD (ensure type) Contains the request header informations | ||||||
|  |      */ | ||||||
|  |     public $request_headers = null; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string|array TBD (ensure type) Contains the response header informations | ||||||
|  |      */ | ||||||
|  |     public $response_headers = array(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string Contains the response from the curl request | ||||||
|  |      */ | ||||||
|  |     public $response = null; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var bool Whether the current section of response headers is after 'HTTP/1.1 100 Continue' | ||||||
|  |      */ | ||||||
|  |     protected $response_header_continue = false; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Constructor ensures the available curl extension is loaded. | ||||||
|  |      * | ||||||
|  |      * @throws \ErrorException | ||||||
|  |      */ | ||||||
|  |     public function __construct() | ||||||
|  |     { | ||||||
|  |         if (!extension_loaded('curl')) { | ||||||
|  |             throw new \ErrorException('The cURL extensions is not loaded, make sure you have installed the cURL extension: https://php.net/manual/curl.setup.php'); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $this->init(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // private methods | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Initializer for the curl resource. | ||||||
|  |      * | ||||||
|  |      * Is called by the __construct() of the class or when the curl request is reseted. | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     private function init() | ||||||
|  |     { | ||||||
|  |         $this->curl = curl_init(); | ||||||
|  |         $this->setUserAgent(self::USER_AGENT); | ||||||
|  |         $this->setOpt(CURLINFO_HEADER_OUT, true); | ||||||
|  |         $this->setOpt(CURLOPT_HEADER, false); | ||||||
|  |         $this->setOpt(CURLOPT_RETURNTRANSFER, true); | ||||||
|  |         $this->setOpt(CURLOPT_HEADERFUNCTION, array($this, 'addResponseHeaderLine')); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Handle writing the response headers | ||||||
|  |      * | ||||||
|  |      * @param resource $curl The current curl resource | ||||||
|  |      * @param string $header_line A line from the list of response headers | ||||||
|  |      * | ||||||
|  |      * @return int Returns the length of the $header_line | ||||||
|  |      */ | ||||||
|  |     public function addResponseHeaderLine($curl, $header_line) | ||||||
|  |     { | ||||||
|  |         $trimmed_header = trim($header_line, "\r\n"); | ||||||
|  |  | ||||||
|  |         if ($trimmed_header === "") { | ||||||
|  |             $this->response_header_continue = false; | ||||||
|  |         } elseif (strtolower($trimmed_header) === 'http/1.1 100 continue') { | ||||||
|  |             $this->response_header_continue = true; | ||||||
|  |         } elseif (!$this->response_header_continue) { | ||||||
|  |             $this->response_headers[] = $trimmed_header; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         return strlen($header_line); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // protected methods | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Execute the curl request based on the respectiv settings. | ||||||
|  |      * | ||||||
|  |      * @return int Returns the error code for the current curl request | ||||||
|  |      */ | ||||||
|  |     protected function exec() | ||||||
|  |     { | ||||||
|  |         $this->response_headers = array(); | ||||||
|  |         $this->response = curl_exec($this->curl); | ||||||
|  |         $this->curl_error_code = curl_errno($this->curl); | ||||||
|  |         $this->curl_error_message = curl_error($this->curl); | ||||||
|  |         $this->curl_error = !($this->curl_error_code === 0); | ||||||
|  |         $this->http_status_code = curl_getinfo($this->curl, CURLINFO_HTTP_CODE); | ||||||
|  |         $this->http_error = in_array(floor($this->http_status_code / 100), array(4, 5)); | ||||||
|  |         $this->error = $this->curl_error || $this->http_error; | ||||||
|  |         $this->error_code = $this->error ? ($this->curl_error ? $this->curl_error_code : $this->http_status_code) : 0; | ||||||
|  |         $this->request_headers = preg_split('/\r\n/', curl_getinfo($this->curl, CURLINFO_HEADER_OUT), null, PREG_SPLIT_NO_EMPTY); | ||||||
|  |         $this->http_error_message = $this->error ? (isset($this->response_headers['0']) ? $this->response_headers['0'] : '') : ''; | ||||||
|  |         $this->error_message = $this->curl_error ? $this->curl_error_message : $this->http_error_message; | ||||||
|  |  | ||||||
|  |         return $this->error_code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @param array|object|string $data | ||||||
|  |      */ | ||||||
|  |     protected function preparePayload($data) | ||||||
|  |     { | ||||||
|  |         $this->setOpt(CURLOPT_POST, true); | ||||||
|  |  | ||||||
|  |         if (is_array($data) || is_object($data)) { | ||||||
|  |             $skip = false; | ||||||
|  |             foreach ($data as $key => $value) { | ||||||
|  |                 // If a value is an instance of CurlFile skip the http_build_query | ||||||
|  |                 // see issue https://github.com/php-mod/curl/issues/46 | ||||||
|  |                 // suggestion from: https://stackoverflow.com/a/36603038/4611030 | ||||||
|  |                 if ($value instanceof \CurlFile) { | ||||||
|  |                     $skip = true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             if (!$skip) { | ||||||
|  |                 $data = http_build_query($data); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $this->setOpt(CURLOPT_POSTFIELDS, $data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Set auth options for the current request. | ||||||
|  |      * | ||||||
|  |      * Available auth types are: | ||||||
|  |      * | ||||||
|  |      * + self::AUTH_BASIC | ||||||
|  |      * + self::AUTH_DIGEST | ||||||
|  |      * + self::AUTH_GSSNEGOTIATE | ||||||
|  |      * + self::AUTH_NTLM | ||||||
|  |      * + self::AUTH_ANY | ||||||
|  |      * + self::AUTH_ANYSAFE | ||||||
|  |      * | ||||||
|  |      * @param int $httpauth The type of authentication | ||||||
|  |      */ | ||||||
|  |     protected function setHttpAuth($httpauth) | ||||||
|  |     { | ||||||
|  |         $this->setOpt(CURLOPT_HTTPAUTH, $httpauth); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // public methods | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @deprecated calling exec() directly is discouraged | ||||||
|  |      */ | ||||||
|  |     public function _exec() | ||||||
|  |     { | ||||||
|  |         return $this->exec(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // functions | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Make a get request with optional data. | ||||||
|  |      * | ||||||
|  |      * The get request has no body data, the data will be correctly added to the $url with the http_build_query() method. | ||||||
|  |      * | ||||||
|  |      * @param string $url  The url to make the get request for | ||||||
|  |      * @param array  $data Optional arguments who are part of the url | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function get($url, $data = array()) | ||||||
|  |     { | ||||||
|  |         if (count($data) > 0) { | ||||||
|  |             $this->setOpt(CURLOPT_URL, $url.'?'.http_build_query($data)); | ||||||
|  |         } else { | ||||||
|  |             $this->setOpt(CURLOPT_URL, $url); | ||||||
|  |         } | ||||||
|  |         $this->setOpt(CURLOPT_HTTPGET, true); | ||||||
|  |         $this->exec(); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Make a post request with optional post data. | ||||||
|  |      * | ||||||
|  |      * @param string $url  The url to make the post request | ||||||
|  |      * @param array  $data Post data to pass to the url | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function post($url, $data = array()) | ||||||
|  |     { | ||||||
|  |         $this->setOpt(CURLOPT_URL, $url); | ||||||
|  |         $this->preparePayload($data); | ||||||
|  |         $this->exec(); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Make a put request with optional data. | ||||||
|  |      * | ||||||
|  |      * The put request data can be either sent via payload or as get paramters of the string. | ||||||
|  |      * | ||||||
|  |      * @param string $url The url to make the put request | ||||||
|  |      * @param array $data Optional data to pass to the $url | ||||||
|  |      * @param bool $payload Whether the data should be transmitted trough payload or as get parameters of the string | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function put($url, $data = array(), $payload = false) | ||||||
|  |     { | ||||||
|  |         if (! empty($data)) { | ||||||
|  |             if ($payload === false) { | ||||||
|  |                 $url .= '?'.http_build_query($data); | ||||||
|  |             } else { | ||||||
|  |                 $this->preparePayload($data); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $this->setOpt(CURLOPT_URL, $url); | ||||||
|  |         $this->setOpt(CURLOPT_CUSTOMREQUEST, 'PUT'); | ||||||
|  |         $this->exec(); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Make a patch request with optional data. | ||||||
|  |      * | ||||||
|  |      * The patch request data can be either sent via payload or as get paramters of the string. | ||||||
|  |      * | ||||||
|  |      * @param string $url The url to make the patch request | ||||||
|  |      * @param array $data Optional data to pass to the $url | ||||||
|  |      * @param bool $payload Whether the data should be transmitted trough payload or as get parameters of the string | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function patch($url, $data = array(), $payload = false) | ||||||
|  |     { | ||||||
|  |         if (! empty($data)) { | ||||||
|  |             if ($payload === false) { | ||||||
|  |                 $url .= '?'.http_build_query($data); | ||||||
|  |             } else { | ||||||
|  |                 $this->preparePayload($data); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $this->setOpt(CURLOPT_URL, $url); | ||||||
|  |         $this->setOpt(CURLOPT_CUSTOMREQUEST, 'PATCH'); | ||||||
|  |         $this->exec(); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Make a delete request with optional data. | ||||||
|  |      * | ||||||
|  |      * @param string $url The url to make the delete request | ||||||
|  |      * @param array $data Optional data to pass to the $url | ||||||
|  |      * @param bool $payload Whether the data should be transmitted trough payload or as get parameters of the string | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function delete($url, $data = array(), $payload = false) | ||||||
|  |     { | ||||||
|  |         if (! empty($data)) { | ||||||
|  |             if ($payload === false) { | ||||||
|  |                 $url .= '?'.http_build_query($data); | ||||||
|  |             } else { | ||||||
|  |                 $this->preparePayload($data); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $this->setOpt(CURLOPT_URL, $url); | ||||||
|  |         $this->setOpt(CURLOPT_CUSTOMREQUEST, 'DELETE'); | ||||||
|  |         $this->exec(); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // setters | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Pass basic auth data. | ||||||
|  |      * | ||||||
|  |      * If the the rquested url is secured by an httaccess basic auth mechanism you can use this method to provided the auth data. | ||||||
|  |      * | ||||||
|  |      * ```php | ||||||
|  |      * $curl = new Curl(); | ||||||
|  |      * $curl->setBasicAuthentication('john', 'doe'); | ||||||
|  |      * $curl->get('http://example.com/secure.php'); | ||||||
|  |      * ``` | ||||||
|  |      * | ||||||
|  |      * @param string $username The username for the authentification | ||||||
|  |      * @param string $password The password for the given username for the authentification | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function setBasicAuthentication($username, $password) | ||||||
|  |     { | ||||||
|  |         $this->setHttpAuth(self::AUTH_BASIC); | ||||||
|  |         $this->setOpt(CURLOPT_USERPWD, $username.':'.$password); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Provide optional header informations. | ||||||
|  |      * | ||||||
|  |      * In order to pass optional headers by key value pairing: | ||||||
|  |      * | ||||||
|  |      * ```php | ||||||
|  |      * $curl = new Curl(); | ||||||
|  |      * $curl->setHeader('X-Requested-With', 'XMLHttpRequest'); | ||||||
|  |      * $curl->get('http://example.com/request.php'); | ||||||
|  |      * ``` | ||||||
|  |      * | ||||||
|  |      * @param string $key   The header key | ||||||
|  |      * @param string $value The value for the given header key | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function setHeader($key, $value) | ||||||
|  |     { | ||||||
|  |         $this->_headers[$key] = $key.': '.$value; | ||||||
|  |         $this->setOpt(CURLOPT_HTTPHEADER, array_values($this->_headers)); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Provide a User Agent. | ||||||
|  |      * | ||||||
|  |      * In order to provide you cusomtized user agent name you can use this method. | ||||||
|  |      * | ||||||
|  |      * ```php | ||||||
|  |      * $curl = new Curl(); | ||||||
|  |      * $curl->setUserAgent('My John Doe Agent 1.0'); | ||||||
|  |      * $curl->get('http://example.com/request.php'); | ||||||
|  |      * ``` | ||||||
|  |      * | ||||||
|  |      * @param string $useragent The name of the user agent to set for the current request | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function setUserAgent($useragent) | ||||||
|  |     { | ||||||
|  |         $this->setOpt(CURLOPT_USERAGENT, $useragent); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @deprecated Call setReferer() instead | ||||||
|  |      */ | ||||||
|  |     public function setReferrer($referrer) | ||||||
|  |     { | ||||||
|  |         $this->setReferer($referrer); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Set the HTTP referer header. | ||||||
|  |      * | ||||||
|  |      * The $referer informations can help identify the requested client where the requested was made. | ||||||
|  |      * | ||||||
|  |      * @param string $referer An url to pass and will be set as referer header | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function setReferer($referer) | ||||||
|  |     { | ||||||
|  |         $this->setOpt(CURLOPT_REFERER, $referer); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Set contents of HTTP Cookie header. | ||||||
|  |      * | ||||||
|  |      * @param string $key   The name of the cookie | ||||||
|  |      * @param string $value The value for the provided cookie name | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function setCookie($key, $value) | ||||||
|  |     { | ||||||
|  |         $this->_cookies[$key] = $value; | ||||||
|  |         $this->setOpt(CURLOPT_COOKIE, http_build_query($this->_cookies, '', '; ')); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Set customized curl options. | ||||||
|  |      * | ||||||
|  |      * To see a full list of options: http://php.net/curl_setopt | ||||||
|  |      * | ||||||
|  |      * @see http://php.net/curl_setopt | ||||||
|  |      * | ||||||
|  |      * @param int   $option The curl option constante e.g. `CURLOPT_AUTOREFERER`, `CURLOPT_COOKIESESSION` | ||||||
|  |      * @param mixed $value  The value to pass for the given $option | ||||||
|  |      */ | ||||||
|  |     public function setOpt($option, $value) | ||||||
|  |     { | ||||||
|  |         return curl_setopt($this->curl, $option, $value); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |     * Get customized curl options. | ||||||
|  |     * | ||||||
|  |     * To see a full list of options: http://php.net/curl_getinfo | ||||||
|  |     * | ||||||
|  |     * @see http://php.net/curl_getinfo | ||||||
|  |     * | ||||||
|  |     * @param int   $option The curl option constante e.g. `CURLOPT_AUTOREFERER`, `CURLOPT_COOKIESESSION` | ||||||
|  |     * @param mixed $value  The value to check for the given $option | ||||||
|  |     */ | ||||||
|  |     public function getOpt($option) | ||||||
|  |     { | ||||||
|  |         return curl_getinfo($this->curl, $option); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |     * Return the endpoint set for curl | ||||||
|  |     * | ||||||
|  |     * @see http://php.net/curl_getinfo | ||||||
|  |     * | ||||||
|  |     * @return string of endpoint | ||||||
|  |     */ | ||||||
|  |     public function getEndpoint() | ||||||
|  |     { | ||||||
|  |         return $this->getOpt(CURLINFO_EFFECTIVE_URL); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Enable verbositiy. | ||||||
|  |      * | ||||||
|  |      * @todo As to keep naming convention it should be renamed to `setVerbose()` | ||||||
|  |      * | ||||||
|  |      * @param string $on | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function verbose($on = true) | ||||||
|  |     { | ||||||
|  |         $this->setOpt(CURLOPT_VERBOSE, $on); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Reset all curl options. | ||||||
|  |      * | ||||||
|  |      * In order to make multiple requests with the same curl object all settings requires to be reset. | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function reset() | ||||||
|  |     { | ||||||
|  |         $this->close(); | ||||||
|  |         $this->_cookies = array(); | ||||||
|  |         $this->_headers = array(); | ||||||
|  |         $this->error = false; | ||||||
|  |         $this->error_code = 0; | ||||||
|  |         $this->error_message = null; | ||||||
|  |         $this->curl_error = false; | ||||||
|  |         $this->curl_error_code = 0; | ||||||
|  |         $this->curl_error_message = null; | ||||||
|  |         $this->http_error = false; | ||||||
|  |         $this->http_status_code = 0; | ||||||
|  |         $this->http_error_message = null; | ||||||
|  |         $this->request_headers = null; | ||||||
|  |         $this->response_headers = array(); | ||||||
|  |         $this->response = null; | ||||||
|  |         $this->init(); | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Closing the current open curl resource. | ||||||
|  |      * @return self | ||||||
|  |      */ | ||||||
|  |     public function close() | ||||||
|  |     { | ||||||
|  |         if (is_resource($this->curl)) { | ||||||
|  |             curl_close($this->curl); | ||||||
|  |         } | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Close the connection when the Curl object will be destroyed. | ||||||
|  |      */ | ||||||
|  |     public function __destruct() | ||||||
|  |     { | ||||||
|  |         $this->close(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Was an 'info' header returned. | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function isInfo() | ||||||
|  |     { | ||||||
|  |         return $this->http_status_code >= 100 && $this->http_status_code < 200; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Was an 'OK' response returned. | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function isSuccess() | ||||||
|  |     { | ||||||
|  |         return $this->http_status_code >= 200 && $this->http_status_code < 300; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Was a 'redirect' returned. | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function isRedirect() | ||||||
|  |     { | ||||||
|  |         return $this->http_status_code >= 300 && $this->http_status_code < 400; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Was an 'error' returned (client error or server error). | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function isError() | ||||||
|  |     { | ||||||
|  |         return $this->http_status_code >= 400 && $this->http_status_code < 600; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Was a 'client error' returned. | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function isClientError() | ||||||
|  |     { | ||||||
|  |         return $this->http_status_code >= 400 && $this->http_status_code < 500; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Was a 'server error' returned. | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function isServerError() | ||||||
|  |     { | ||||||
|  |         return $this->http_status_code >= 500 && $this->http_status_code < 600; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * Get a specific response header key or all values from the response headers array. | ||||||
|  |      * | ||||||
|  |      * Usage example: | ||||||
|  |      * | ||||||
|  |      * ```php | ||||||
|  |      * $curl = (new Curl())->get('http://example.com'); | ||||||
|  |      * | ||||||
|  |      * echo $curl->getResponseHeaders('Content-Type'); | ||||||
|  |      * ``` | ||||||
|  |      * | ||||||
|  |      * Or in order to dump all keys with the given values use: | ||||||
|  |      * | ||||||
|  |      * ```php | ||||||
|  |      * $curl = (new Curl())->get('http://example.com'); | ||||||
|  |      * | ||||||
|  |      * var_dump($curl->getResponseHeaders()); | ||||||
|  |      * ``` | ||||||
|  |      * | ||||||
|  |      * @param string $headerKey Optional key to get from the array. | ||||||
|  |      * @return bool|string | ||||||
|  |      * @since 1.9 | ||||||
|  |      */ | ||||||
|  |     public function getResponseHeaders($headerKey = null) | ||||||
|  |     { | ||||||
|  |         $headers = array(); | ||||||
|  |         $headerKey = strtolower($headerKey); | ||||||
|  |          | ||||||
|  |         foreach ($this->response_headers as $header) { | ||||||
|  |             $parts = explode(":", $header, 2); | ||||||
|  |              | ||||||
|  |             $key = isset($parts[0]) ? $parts[0] : null; | ||||||
|  |             $value = isset($parts[1]) ? $parts[1] : null; | ||||||
|  |              | ||||||
|  |             $headers[trim(strtolower($key))] = trim($value); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         if ($headerKey) { | ||||||
|  |             return isset($headers[$headerKey]) ? $headers[$headerKey] : false; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         return $headers; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getResponse() | ||||||
|  |     { | ||||||
|  |         return $this->response; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getErrorCode() | ||||||
|  |     { | ||||||
|  |         return $this->curl_error_code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getErrorMessage() | ||||||
|  |     { | ||||||
|  |         return $this->curl_error_message; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getHttpStatus() | ||||||
|  |     { | ||||||
|  |         return $this->http_status_code; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										277
									
								
								vendor/curl/curl/tests/CurlTest.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								vendor/curl/curl/tests/CurlTest.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,277 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace Curl; | ||||||
|  |  | ||||||
|  | class CurlTest extends \PHPUnit_Framework_TestCase | ||||||
|  | { | ||||||
|  |  | ||||||
|  | 	const TEST_URL = 'http://server_test'; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * | ||||||
|  | 	 * @var Curl | ||||||
|  | 	 */ | ||||||
|  | 	protected $curl; | ||||||
|  |  | ||||||
|  | 	function setUp() { | ||||||
|  | 		$this->curl = new Curl(); | ||||||
|  | 		$this->curl->setOpt(CURLOPT_SSL_VERIFYPEER, FALSE); | ||||||
|  | 		$this->curl->setOpt(CURLOPT_SSL_VERIFYHOST, FALSE); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function server($request_method, $data='') { | ||||||
|  | 		$request_method = strtolower($request_method); | ||||||
|  | 		$this->curl->$request_method(self::TEST_URL . '/server.php', $data); | ||||||
|  | 		return $this->curl->response; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testExtensionLoaded() { | ||||||
|  | 			 | ||||||
|  | 		$this->assertTrue(extension_loaded('curl')); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testUserAgent() { | ||||||
|  | 			 | ||||||
|  | 		$this->curl->setUserAgent(Curl::USER_AGENT); | ||||||
|  | 		$this->assertEquals(Curl::USER_AGENT, $this->server('GET', array( | ||||||
|  | 				'test' => 'server', | ||||||
|  | 				'key' => 'HTTP_USER_AGENT', | ||||||
|  | 		))); | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testGet() { | ||||||
|  | 		$this->assertTrue($this->server('GET', array( | ||||||
|  | 				'test' => 'server', | ||||||
|  | 				'key' => 'REQUEST_METHOD', | ||||||
|  | 		)) === 'GET'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testPostRequestMethod() { | ||||||
|  | 		$this->assertTrue($this->server('POST', array( | ||||||
|  | 				'test' => 'server', | ||||||
|  | 				'key' => 'REQUEST_METHOD', | ||||||
|  | 		)) === 'POST'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testPostData() { | ||||||
|  | 		$this->assertTrue($this->server('POST', array( | ||||||
|  | 				'test' => 'post', | ||||||
|  | 				'key' => 'test', | ||||||
|  | 		)) === 'post'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testPostMultidimensionalData() { | ||||||
|  |  | ||||||
|  | 		$data = array( | ||||||
|  | 				'key' => 'file', | ||||||
|  | 				'file' => array( | ||||||
|  | 						'wibble', | ||||||
|  | 						'wubble', | ||||||
|  | 						'wobble', | ||||||
|  | 				), | ||||||
|  | 		); | ||||||
|  |  | ||||||
|  | 		$this->curl->post(self::TEST_URL . '/post_multidimensional.php', $data); | ||||||
|  |  | ||||||
|  | 		$this->assertEquals( | ||||||
|  | 				'key=file&file%5B0%5D=wibble&file%5B1%5D=wubble&file%5B2%5D=wobble', | ||||||
|  | 				$this->curl->response); | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testPostFilePathUpload() | ||||||
|  |     { | ||||||
|  |  | ||||||
|  | 		$file_path = $this->get_png(); | ||||||
|  |  | ||||||
|  | 		$data = array( | ||||||
|  | 				'key' => 'image', | ||||||
|  | 				'image' => '@' . $file_path, | ||||||
|  | 		); | ||||||
|  |  | ||||||
|  |         $this->curl->setOpt(CURLOPT_RETURNTRANSFER, true); | ||||||
|  |  | ||||||
|  | 		$this->curl->post(self::TEST_URL . '/post_file_path_upload.php', $data); | ||||||
|  |  | ||||||
|  | 		$this->assertEquals( | ||||||
|  | 				array( | ||||||
|  | 						'request_method' => 'POST', | ||||||
|  | 						'key' => 'image', | ||||||
|  | 						'mime_content_type' => 'ERROR', // Temp change the image response, but assuming this is not fixing the issue indeed. | ||||||
|  | 						//'mime_content_type' => 'image/png' | ||||||
|  | 				), | ||||||
|  |                 json_decode($this->curl->response, true)); | ||||||
|  |  | ||||||
|  | 		unlink($file_path); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testPutRequestMethod() { | ||||||
|  | 		$this->assertTrue($this->server('PUT', array( | ||||||
|  | 				'test' => 'server', | ||||||
|  | 				'key' => 'REQUEST_METHOD', | ||||||
|  | 		)) === 'PUT'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testPutData() { | ||||||
|  | 		$this->assertTrue($this->server('PUT', array( | ||||||
|  | 				'test' => 'put', | ||||||
|  | 				'key' => 'test', | ||||||
|  | 		)) === 'put'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testPutFileHandle() { | ||||||
|  | 		$png = $this->create_png(); | ||||||
|  | 		$tmp_file = $this->create_tmp_file($png); | ||||||
|  |  | ||||||
|  | 		$this->curl->setOpt(CURLOPT_PUT, TRUE); | ||||||
|  | 		$this->curl->setOpt(CURLOPT_INFILE, $tmp_file); | ||||||
|  | 		$this->curl->setOpt(CURLOPT_INFILESIZE, strlen($png)); | ||||||
|  | 		$this->curl->put(self::TEST_URL . '/server.php', array( | ||||||
|  | 				'test' => 'put_file_handle', | ||||||
|  | 		)); | ||||||
|  |  | ||||||
|  | 		fclose($tmp_file); | ||||||
|  |  | ||||||
|  | 		$this->assertTrue($this->curl->response === 'image/png'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testDelete() { | ||||||
|  | 		$this->assertTrue($this->server('DELETE', array( | ||||||
|  | 				'test' => 'server', | ||||||
|  | 				'key' => 'REQUEST_METHOD', | ||||||
|  | 		)) === 'DELETE'); | ||||||
|  |  | ||||||
|  | 		$this->assertTrue($this->server('DELETE', array( | ||||||
|  | 				'test' => 'delete', | ||||||
|  | 				'key' => 'test', | ||||||
|  | 		)) === 'delete'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testBasicHttpAuth() { | ||||||
|  |  | ||||||
|  | 		$data = array(); | ||||||
|  |  | ||||||
|  | 		$this->curl->get(self::TEST_URL . '/http_basic_auth.php', $data); | ||||||
|  |  | ||||||
|  | 		$this->assertEquals('canceled', $this->curl->response); | ||||||
|  |  | ||||||
|  | 		$username = 'myusername'; | ||||||
|  | 		$password = 'mypassword'; | ||||||
|  |  | ||||||
|  | 		$this->curl->setBasicAuthentication($username, $password); | ||||||
|  |  | ||||||
|  | 		$this->curl->get(self::TEST_URL . '/http_basic_auth.php', $data); | ||||||
|  |  | ||||||
|  | 		$this->assertEquals( | ||||||
|  | 				'{"username":"myusername","password":"mypassword"}', | ||||||
|  | 				$this->curl->response); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testReferrer() { | ||||||
|  | 		$this->curl->setReferer('myreferrer'); | ||||||
|  | 		$this->assertTrue($this->server('GET', array( | ||||||
|  | 				'test' => 'server', | ||||||
|  | 				'key' => 'HTTP_REFERER', | ||||||
|  | 		)) === 'myreferrer'); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public function testDeprecatedReferrer() { | ||||||
|  | 		$this->curl->setReferrer('myreferrer'); | ||||||
|  | 		$this->assertTrue($this->server('GET', array( | ||||||
|  | 				'test' => 'server', | ||||||
|  | 				'key' => 'HTTP_REFERER', | ||||||
|  | 		)) === 'myreferrer'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testCookies() { | ||||||
|  | 		$this->curl->setCookie('mycookie', 'yum'); | ||||||
|  | 		$this->assertTrue($this->server('GET', array( | ||||||
|  | 				'test' => 'cookie', | ||||||
|  | 				'key' => 'mycookie', | ||||||
|  | 		)) === 'yum'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testError() { | ||||||
|  | 		$this->curl->setOpt(CURLOPT_CONNECTTIMEOUT_MS, 2000); | ||||||
|  | 		$this->curl->get('http://1.2.3.4/'); | ||||||
|  | 		$this->assertTrue($this->curl->error === TRUE); | ||||||
|  | 		$this->assertTrue($this->curl->curl_error === TRUE); | ||||||
|  | 		$this->assertTrue($this->curl->curl_error_code === CURLE_OPERATION_TIMEOUTED); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testHeaders() { | ||||||
|  | 		$this->curl->setHeader('Content-Type', 'application/json'); | ||||||
|  | 		$this->curl->setHeader('X-Requested-With', 'XMLHttpRequest'); | ||||||
|  | 		$this->curl->setHeader('Accept', 'application/json'); | ||||||
|  | 		$this->assertTrue($this->server('GET', array( | ||||||
|  | 				'test' => 'server', | ||||||
|  | 				'key' => 'CONTENT_TYPE', | ||||||
|  | 		)) === 'application/json'); | ||||||
|  | 		$this->assertTrue($this->server('GET', array( | ||||||
|  | 				'test' => 'server', | ||||||
|  | 				'key' => 'HTTP_X_REQUESTED_WITH', | ||||||
|  | 		)) === 'XMLHttpRequest'); | ||||||
|  | 		$this->assertTrue($this->server('GET', array( | ||||||
|  | 				'test' => 'server', | ||||||
|  | 				'key' => 'HTTP_ACCEPT', | ||||||
|  | 		)) === 'application/json'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function testHeadersWithContinue() { | ||||||
|  | 		$headers = file(dirname(__FILE__) . '/data/response_headers_with_continue.txt'); | ||||||
|  | 		 | ||||||
|  | 		$this->curl->response_headers = array(); | ||||||
|  | 		foreach($headers as $header_line) { | ||||||
|  | 			$this->curl->addResponseHeaderLine(null, $header_line); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		$expected_headers = array_values(array_filter(array_map(function($l) { return trim($l, "\r\n"); }, array_slice($headers, 1)))); | ||||||
|  |  | ||||||
|  | 		$this->assertEquals($expected_headers, $this->curl->response_headers); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public function testReset() | ||||||
|  | 	{ | ||||||
|  | 		$curl = $this->getMockBuilder(get_class($this->curl))->getMock(); | ||||||
|  | 		$curl->expects($this->once())->method('reset')->with(); | ||||||
|  | 		// lets make small request | ||||||
|  | 		$curl->setOpt(CURLOPT_CONNECTTIMEOUT_MS, 2000); | ||||||
|  | 		$curl->get('http://1.2.3.4/'); | ||||||
|  | 		$curl->reset(); | ||||||
|  | 		$this->assertFalse($curl->error); | ||||||
|  | 		$this->assertSame(0, $curl->error_code); | ||||||
|  | 		$this->assertNull($curl->error_message); | ||||||
|  | 		$this->assertFalse($curl->curl_error); | ||||||
|  | 		$this->assertSame(0, $curl->curl_error_code); | ||||||
|  | 		$this->assertNull($curl->curl_error_message); | ||||||
|  | 		$this->assertFalse($curl->http_error); | ||||||
|  | 		$this->assertSame(0, $curl->http_status_code); | ||||||
|  | 		$this->assertNull($curl->http_error_message); | ||||||
|  | 		$this->assertNull($curl->request_headers); | ||||||
|  | 		$this->assertEmpty($curl->response_headers); | ||||||
|  | 		$this->assertNull($curl->response); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function create_png() { | ||||||
|  | 		// PNG image data, 1 x 1, 1-bit colormap, non-interlaced | ||||||
|  | 		ob_start(); | ||||||
|  | 		imagepng(imagecreatefromstring(base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'))); | ||||||
|  | 		$raw_image = ob_get_contents(); | ||||||
|  | 		ob_end_clean(); | ||||||
|  | 		return $raw_image; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function create_tmp_file($data) { | ||||||
|  | 		$tmp_file = tmpfile(); | ||||||
|  | 		fwrite($tmp_file, $data); | ||||||
|  | 		rewind($tmp_file); | ||||||
|  | 		return $tmp_file; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function get_png() { | ||||||
|  | 		$tmp_filename = tempnam('/tmp', 'php-curl-class.'); | ||||||
|  | 		file_put_contents($tmp_filename, $this->create_png()); | ||||||
|  | 		return $tmp_filename; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								vendor/curl/curl/tests/data/response_headers_with_continue.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/curl/curl/tests/data/response_headers_with_continue.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | HTTP/1.1 100 Continue | ||||||
|  |  | ||||||
|  | HTTP/1.1 200 OK | ||||||
|  | Server: nginx/1.1.19 | ||||||
|  | Date: Fri, 11 Aug 2017 13:22:00 GMT | ||||||
|  | Content-Type: image/jpeg | ||||||
|  | Content-Length: 62574 | ||||||
|  | Connection: close | ||||||
|  | Cache-Control: max-age=7257600 | ||||||
|  | Expires: Fri, 03 Nov 2017 13:22:00 GMT | ||||||
|  | Strict-Transport-Security: max-age=31536000; includeSubDomains | ||||||
|  | X-Frame-Option: DENY | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								vendor/curl/curl/tests/data/test.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/curl/curl/tests/data/test.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.8 KiB | 
							
								
								
									
										9
									
								
								vendor/curl/curl/tests/server/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/curl/curl/tests/server/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | FROM alpine:3.7 | ||||||
|  |  | ||||||
|  | RUN apk add --no-cache php5-cli php5-curl php5-gd php5-phar php5-json php5-openssl php5-dom | ||||||
|  |  | ||||||
|  | COPY php-curl-test php-curl-test | ||||||
|  |  | ||||||
|  | EXPOSE 80 | ||||||
|  |  | ||||||
|  | CMD ["php5", "-S", "0.0.0.0:80", "-t", "php-curl-test"] | ||||||
							
								
								
									
										37
									
								
								vendor/curl/curl/tests/server/php-curl-test/deploy.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/curl/curl/tests/server/php-curl-test/deploy.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | // The commands | ||||||
|  | $commands = array( | ||||||
|  |     'cd ../../.. && git pull', | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | // Run the commands for output | ||||||
|  | $output = ''; | ||||||
|  | foreach($commands AS $command){ | ||||||
|  | // Run it | ||||||
|  |     $tmp = shell_exec($command); | ||||||
|  | // Output | ||||||
|  |     $output .= "<span style=\"color: #6BE234;\">\$</span> <span style=\"color: #729FCF;\">{$command}\n</span>"; | ||||||
|  |     $output .= htmlentities(trim($tmp)) . "\n"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Make it pretty for manual user access (and why not?) | ||||||
|  | ?> | ||||||
|  | <!DOCTYPE HTML> | ||||||
|  | <html lang="en-US"> | ||||||
|  | <head> | ||||||
|  |     <meta charset="UTF-8"> | ||||||
|  |     <title>GIT DEPLOYMENT SCRIPT</title> | ||||||
|  | </head> | ||||||
|  | <body style="background-color: #000000; color: #FFFFFF; font-weight: bold; padding: 0 10px;"> | ||||||
|  | <pre> | ||||||
|  | . ____ . ____________________________ | ||||||
|  | |/ \| | | | ||||||
|  | [| <span style="color: #FF0000;">♥ ♥</span> |] | Git Deployment Script v0.1 | | ||||||
|  | |___==___| / © oodavid 2012 | | ||||||
|  | |____________________________| | ||||||
|  |  | ||||||
|  |     <?php echo $output; ?> | ||||||
|  | </pre> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										14
									
								
								vendor/curl/curl/tests/server/php-curl-test/http_basic_auth.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/curl/curl/tests/server/php-curl-test/http_basic_auth.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | if (!isset($_SERVER['PHP_AUTH_USER'])) { | ||||||
|  | 	header('WWW-Authenticate: Basic realm="My Realm"'); | ||||||
|  | 	header('HTTP/1.0 401 Unauthorized'); | ||||||
|  | 	echo 'canceled'; | ||||||
|  | 	exit; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | header('Content-Type: application/json'); | ||||||
|  | echo json_encode(array( | ||||||
|  | 		'username' => $_SERVER['PHP_AUTH_USER'], | ||||||
|  | 		'password' => $_SERVER['PHP_AUTH_PW'], | ||||||
|  | )); | ||||||
							
								
								
									
										21
									
								
								vendor/curl/curl/tests/server/php-curl-test/post_file_path_upload.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/curl/curl/tests/server/php-curl-test/post_file_path_upload.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $request_method = isset($_SERVER['REQUEST_METHOD']) ? | ||||||
|  | 						$_SERVER['REQUEST_METHOD'] : ''; | ||||||
|  |  | ||||||
|  | $data_values = $request_method === 'POST' ? $_POST : $_GET; | ||||||
|  |  | ||||||
|  | $key = isset($data_values['key']) ? $data_values['key'] : ''; | ||||||
|  |  | ||||||
|  | $response = array(); | ||||||
|  |  | ||||||
|  | $response['request_method'] = $request_method; | ||||||
|  | $response['key'] = $key; | ||||||
|  |  | ||||||
|  | if(isset($_FILES[$key])) { | ||||||
|  | 	$response['mime_content_type'] = mime_content_type($_FILES[$key]['tmp_name']); | ||||||
|  | } else { | ||||||
|  | 	$response['mime_content_type'] = 'ERROR'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | echo json_encode($response); | ||||||
							
								
								
									
										4
									
								
								vendor/curl/curl/tests/server/php-curl-test/post_multidimensional.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								vendor/curl/curl/tests/server/php-curl-test/post_multidimensional.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $http_raw_post_data = file_get_contents('php://input'); | ||||||
|  | echo $http_raw_post_data; | ||||||
							
								
								
									
										31
									
								
								vendor/curl/curl/tests/server/php-curl-test/server.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/curl/curl/tests/server/php-curl-test/server.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | <?php | ||||||
|  | $request_method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : ''; | ||||||
|  | $data_values = $request_method === 'POST' ? $_POST : $_GET; | ||||||
|  | $test = isset($data_values['test']) ? $data_values['test'] : ''; | ||||||
|  | $key = isset($data_values['key']) ? $data_values['key'] : ''; | ||||||
|  |  | ||||||
|  | if ($test === 'put_file_handle') { | ||||||
|  |     $tmp_filename = tempnam('/tmp', 'php-curl-class.'); | ||||||
|  |     file_put_contents($tmp_filename, file_get_contents('php://input')); | ||||||
|  |     echo mime_content_type($tmp_filename); | ||||||
|  |     unlink($tmp_filename); | ||||||
|  |     exit; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | header('Content-Type: text/plain'); | ||||||
|  |  | ||||||
|  | $data_mapping = array( | ||||||
|  |     'cookie' => '_COOKIE', | ||||||
|  |     'delete' => '_GET', | ||||||
|  |     'post' => '_POST', | ||||||
|  |     'put' => '_GET', | ||||||
|  |     'server' => '_SERVER', | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | if(isset($data_mapping[$test])) { | ||||||
|  |     $data = ${$data_mapping[$test]}; | ||||||
|  |     $value = isset($data[$key]) ? $data[$key] : ''; | ||||||
|  | echo $value; | ||||||
|  | } else { | ||||||
|  |     echo "Error."; | ||||||
|  | } | ||||||
							
								
								
									
										52
									
								
								vendor/owner888/phpspider/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/owner888/phpspider/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | # phpspider -- PHP蜘蛛爬虫框架 | ||||||
|  | 《我用爬虫一天时间“偷了”知乎一百万用户,只为证明PHP是世界上最好的语言 》所使用的程序   | ||||||
|  |  | ||||||
|  | phpspider是一个爬虫开发框架。使用本框架,你不用了解爬虫的底层技术实现,爬虫被网站屏蔽、有些网站需要登录或验证码识别才能爬取等问题。简单几行PHP代码,就可以创建自己的爬虫,利用框架封装的多进程Worker类库,代码更简洁,执行效率更高速度更快。 | ||||||
|  |  | ||||||
|  | demo目录下有一些特定网站的爬取规则,只要你安装了PHP环境,代码就可以在命令行下直接跑。 对爬虫感兴趣的开发者可以加QQ群一起讨论:147824717。 | ||||||
|  |  | ||||||
|  | 下面以糗事百科为例, 来看一下我们的爬虫长什么样子: | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  | $configs = array( | ||||||
|  |     'name' => '糗事百科', | ||||||
|  |     'domains' => array( | ||||||
|  |         'qiushibaike.com', | ||||||
|  |         'www.qiushibaike.com' | ||||||
|  |     ), | ||||||
|  |     'scan_urls' => array( | ||||||
|  |         'http://www.qiushibaike.com/' | ||||||
|  |     ), | ||||||
|  |     'content_url_regexes' => array( | ||||||
|  |         "http://www.qiushibaike.com/article/\d+" | ||||||
|  |     ), | ||||||
|  |     'list_url_regexes' => array( | ||||||
|  |         "http://www.qiushibaike.com/8hr/page/\d+\?s=\d+" | ||||||
|  |     ), | ||||||
|  |     'fields' => array( | ||||||
|  |         array( | ||||||
|  |             // 抽取内容页的文章内容 | ||||||
|  |             'name' => "article_content", | ||||||
|  |             'selector' => "//*[@id='single-next-link']", | ||||||
|  |             'required' => true | ||||||
|  |         ), | ||||||
|  |         array( | ||||||
|  |             // 抽取内容页的文章作者 | ||||||
|  |             'name' => "article_author", | ||||||
|  |             'selector' => "//div[contains(@class,'author')]//h2", | ||||||
|  |             'required' => true | ||||||
|  |         ), | ||||||
|  |     ), | ||||||
|  | ); | ||||||
|  | $spider = new phpspider($configs); | ||||||
|  | $spider->start(); | ||||||
|  | ``` | ||||||
|  | 爬虫的整体框架就是这样, 首先定义了一个$configs数组, 里面设置了待爬网站的一些信息, 然后通过调用```$spider = new phpspider($configs);```和```$spider->start();```来配置并启动爬虫. | ||||||
|  |  | ||||||
|  | #### 运行界面如下:       | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 更多详细内容,移步到: | ||||||
|  |  | ||||||
|  | [开发文档](http://doc.phpspider.org) | ||||||
							
								
								
									
										77
									
								
								vendor/owner888/phpspider/autoloader.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								vendor/owner888/phpspider/autoloader.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * This file is part of phpspider. | ||||||
|  |  * | ||||||
|  |  * Licensed under The MIT License | ||||||
|  |  * For full copyright and license information, please see the MIT-LICENSE.txt | ||||||
|  |  * Redistributions of files must retain the above copyright notice. | ||||||
|  |  * | ||||||
|  |  * @author    seatle<seatle@foxmail.com> | ||||||
|  |  * @copyright seatle<seatle@foxmail.com> | ||||||
|  |  * @link      http://www.phpspider.org/ | ||||||
|  |  * @license   http://www.opensource.org/licenses/mit-license.php MIT License | ||||||
|  |  */ | ||||||
|  | namespace phpspider; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * autoloader. | ||||||
|  |  */ | ||||||
|  | class autoloader | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * Autoload root path. | ||||||
|  |      * | ||||||
|  |      * @var string | ||||||
|  |      */ | ||||||
|  |     protected static $_autoload_root_path = ''; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Set autoload root path. | ||||||
|  |      * | ||||||
|  |      * @param string $root_path | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_root_path($root_path) | ||||||
|  |     { | ||||||
|  |         self::$_autoload_root_path = $root_path; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Load files by namespace. | ||||||
|  |      * | ||||||
|  |      * @param string $name | ||||||
|  |      * @return boolean | ||||||
|  |      */ | ||||||
|  |     public static function load_by_namespace($name) | ||||||
|  |     { | ||||||
|  |         $class_path = str_replace('\\', DIRECTORY_SEPARATOR, $name); | ||||||
|  |  | ||||||
|  |         if (strpos($name, 'phpspider\\') === 0)  | ||||||
|  |         { | ||||||
|  |             $class_file = __DIR__ . substr($class_path, strlen('phpspider')) . '.php'; | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             if (self::$_autoload_root_path)  | ||||||
|  |             { | ||||||
|  |                 $class_file = self::$_autoload_root_path . DIRECTORY_SEPARATOR . $class_path . '.php'; | ||||||
|  |             } | ||||||
|  |             if (empty($class_file) || !is_file($class_file))  | ||||||
|  |             { | ||||||
|  |                 $class_file = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . "$class_path.php"; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (is_file($class_file))  | ||||||
|  |         { | ||||||
|  |             require_once($class_file); | ||||||
|  |             if (class_exists($name, false))  | ||||||
|  |             { | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | spl_autoload_register('\phpspider\autoloader::load_by_namespace'); | ||||||
							
								
								
									
										38
									
								
								vendor/owner888/phpspider/composer.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								vendor/owner888/phpspider/composer.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | { | ||||||
|  |     "name": "owner888/phpspider", | ||||||
|  |     "type": "library", | ||||||
|  |     "keywords": [ | ||||||
|  |         "framework",  | ||||||
|  |         "phpspider" | ||||||
|  |     ], | ||||||
|  |     "homepage": "http://www.phpspider.org", | ||||||
|  |     "license": "MIT", | ||||||
|  |     "description": "The PHPSpider Framework.", | ||||||
|  |     "authors": [ | ||||||
|  |         { | ||||||
|  |             "name": "Seatle Yang", | ||||||
|  |             "email": "seatle@foxmail.com", | ||||||
|  |             "homepage": "http://www.phpspider.org", | ||||||
|  |             "role": "Developer" | ||||||
|  |         } | ||||||
|  |     ], | ||||||
|  |     "support": { | ||||||
|  |         "email": "seatle@foxmail.com", | ||||||
|  |         "issues": "https://github.com/owner888/phpspider/issues", | ||||||
|  |         "forum": "http://wenda.phpspider.org/", | ||||||
|  |         "wiki": "http://doc.phpspider.org/", | ||||||
|  |         "source": "https://github.com/owner888/phpspider" | ||||||
|  |     }, | ||||||
|  |     "require": { | ||||||
|  |         "php": ">=5.5.0" | ||||||
|  |     }, | ||||||
|  |     "suggest": { | ||||||
|  |         "ext-pcntl、ext-redis": "For better performance. " | ||||||
|  |     }, | ||||||
|  |     "autoload": { | ||||||
|  |         "psr-4": { | ||||||
|  |             "phpspider\\": "./" | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     "minimum-stability": "dev" | ||||||
|  | } | ||||||
							
								
								
									
										64
									
								
								vendor/owner888/phpspider/core/cache.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								vendor/owner888/phpspider/core/cache.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | <?php | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | PHPSpider [ A PHP Framework For Crawler ] | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Copyright (c) 2006-2014 https://doc.phpspider.org All rights reserved. | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Author: Seatle Yang <seatle@foxmail.com> | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | //---------------------------------- | ||||||
|  | // PHPSpider缓存类文件 | ||||||
|  | //---------------------------------- | ||||||
|  |  | ||||||
|  | class cache | ||||||
|  | { | ||||||
|  |     // 多进程下面不能用单例模式 | ||||||
|  |     //protected static $_instance; | ||||||
|  |     /** | ||||||
|  |      * 获取实例 | ||||||
|  |      *  | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-04-10 22:55 | ||||||
|  |      */ | ||||||
|  |     public static function init() | ||||||
|  |     { | ||||||
|  |         if(extension_loaded('Redis')) | ||||||
|  |         { | ||||||
|  |             $_instance = new Redis(); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             $errmsg = "extension redis is not installed"; | ||||||
|  |             log::add($errmsg, "Error"); | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         // 这里不能用pconnect,会报错:Uncaught exception 'RedisException' with message 'read error on connection' | ||||||
|  |         $_instance->connect($GLOBALS['config']['redis']['host'], $GLOBALS['config']['redis']['port'], $GLOBALS['config']['redis']['timeout']); | ||||||
|  |  | ||||||
|  |         // 验证 | ||||||
|  |         if ($GLOBALS['config']['redis']['pass']) | ||||||
|  |         { | ||||||
|  |             if ( !$_instance->auth($GLOBALS['config']['redis']['pass']) )  | ||||||
|  |             { | ||||||
|  |                 $errmsg = "Redis Server authentication failed!!"; | ||||||
|  |                 log::add($errmsg, "Error"); | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 不序列化的话不能存数组,用php的序列化方式其他语言又不能读取,所以这里自己用json序列化了,性能还比php的序列化好1.4倍 | ||||||
|  |         //$_instance->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE);     // don't serialize data | ||||||
|  |         //$_instance->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);      // use built-in serialize/unserialize | ||||||
|  |         //$_instance->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_IGBINARY); // use igBinary serialize/unserialize | ||||||
|  |  | ||||||
|  |         $_instance->setOption(Redis::OPT_PREFIX, $GLOBALS['config']['redis']['prefix'] . ":"); | ||||||
|  |  | ||||||
|  |         return $_instance; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										55
									
								
								vendor/owner888/phpspider/core/constants.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								vendor/owner888/phpspider/core/constants.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | <?php | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | PHPSpider [ A PHP Framework For Crawler ] | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Copyright (c) 2006-2014 https://doc.phpspider.org All rights reserved. | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Author: Seatle Yang <seatle@foxmail.com> | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | //---------------------------------- | ||||||
|  | // PHPSpider公共入口文件 | ||||||
|  | //---------------------------------- | ||||||
|  |  | ||||||
|  | //namespace phpspider\core; | ||||||
|  |  | ||||||
|  | // Display errors. | ||||||
|  | ini_set('display_errors', 'on'); | ||||||
|  | // Reporting all. | ||||||
|  | error_reporting(E_ALL); | ||||||
|  |  | ||||||
|  | // 永不超时 | ||||||
|  | ini_set('max_execution_time', 0); | ||||||
|  | set_time_limit(0); | ||||||
|  | // 内存限制,如果外面设置的内存比 /etc/php/php-cli.ini 大,就不要设置了 | ||||||
|  | if (intval(ini_get("memory_limit")) < 1024)  | ||||||
|  | { | ||||||
|  |     ini_set('memory_limit', '1024M'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if( PHP_SAPI != 'cli' ) | ||||||
|  | { | ||||||
|  |     exit("You must run the CLI environment\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Date.timezone | ||||||
|  | if (!ini_get('date.timezone'))  | ||||||
|  | { | ||||||
|  |     date_default_timezone_set('Asia/Shanghai'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //核心库目录 | ||||||
|  | define('CORE', dirname(__FILE__)); | ||||||
|  | define('PATH_ROOT', CORE."/../"); | ||||||
|  | define('PATH_DATA', CORE."/../data"); | ||||||
|  | define('PATH_LIBRARY', CORE."/../library"); | ||||||
|  |  | ||||||
|  | //系统配置 | ||||||
|  | //if( file_exists( PATH_ROOT."/config/inc_config.php" ) ) | ||||||
|  | //{ | ||||||
|  |     //require PATH_ROOT."/config/inc_config.php";  | ||||||
|  | //} | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										579
									
								
								vendor/owner888/phpspider/core/db.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										579
									
								
								vendor/owner888/phpspider/core/db.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,579 @@ | |||||||
|  | <?php | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | PHPSpider [ A PHP Framework For Crawler ] | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Copyright (c) 2006-2014 https://doc.phpspider.org All rights reserved. | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Author: Seatle Yang <seatle@foxmail.com> | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | //---------------------------------- | ||||||
|  | // PHPSpider数据库类文件 | ||||||
|  | //---------------------------------- | ||||||
|  |  | ||||||
|  | namespace phpspider\core; | ||||||
|  |  | ||||||
|  | class db | ||||||
|  | { | ||||||
|  |     private static $configs = array(); | ||||||
|  |     private static $rsid; | ||||||
|  |     private static $links = array(); | ||||||
|  |     private static $link_name = 'default'; | ||||||
|  |     private static $autocommiting = false; | ||||||
|  |  | ||||||
|  |     public static function _init() | ||||||
|  |     { | ||||||
|  |         // 获取配置 | ||||||
|  |         $config = self::$link_name == 'default' ? self::_get_default_config() : self::$configs[self::$link_name]; | ||||||
|  |  | ||||||
|  |         // 创建连接 | ||||||
|  |         if (empty(self::$links[self::$link_name]) || empty(self::$links[self::$link_name]['conn'])) | ||||||
|  |         { | ||||||
|  |             // 第一次连接,初始化fail和pid | ||||||
|  |             if (empty(self::$links[self::$link_name]))  | ||||||
|  |             { | ||||||
|  |                 self::$links[self::$link_name]['fail'] = 0; | ||||||
|  |                 self::$links[self::$link_name]['pid'] = function_exists('posix_getpid') ? posix_getpid() : 0;  | ||||||
|  |                 //echo "progress[".self::$links[self::$link_name]['pid']."] create db connect[".self::$link_name."]\n"; | ||||||
|  |             } | ||||||
|  |             self::$links[self::$link_name]['conn'] = mysqli_connect($config['host'], $config['user'], $config['pass'], $config['name'], $config['port']); | ||||||
|  |             if(mysqli_connect_errno()) | ||||||
|  |             { | ||||||
|  |                 self::$links[self::$link_name]['fail']++; | ||||||
|  |                 $errmsg = 'Mysql Connect failed['.self::$links[self::$link_name]['fail'].']: ' . mysqli_connect_error(); | ||||||
|  |                 echo util::colorize(date("H:i:s") . " {$errmsg}\n\n", 'fail'); | ||||||
|  |                 log::add($errmsg, "Error"); | ||||||
|  |                 // 连接失败5次,中断进程 | ||||||
|  |                 if (self::$links[self::$link_name]['fail'] >= 5)  | ||||||
|  |                 { | ||||||
|  |                     exit(250); | ||||||
|  |                 } | ||||||
|  |                 self::_init($config); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 mysqli_query(self::$links[self::$link_name]['conn'], " SET character_set_connection=utf8, character_set_results=utf8, character_set_client=binary, sql_mode='' "); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             $curr_pid = function_exists('posix_getpid') ? posix_getpid() : 0; | ||||||
|  |             // 如果父进程已经生成资源就释放重新生成,因为多进程不能共享连接资源 | ||||||
|  |             if (self::$links[self::$link_name]['pid'] != $curr_pid)  | ||||||
|  |             { | ||||||
|  |                 self::clear_link(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 重新设置连接 | ||||||
|  |      * 传空的话就等于关闭数据库再连接 | ||||||
|  |      * 在多进程环境下如果主进程已经调用过了,子进程一定要调用一次 clear_link,否则会报错: | ||||||
|  |      * Error while reading greeting packet. PID=19615,这是两个进程互抢一个连接句柄引起的 | ||||||
|  |      *  | ||||||
|  |      * @param array $config | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-03-29 00:51 | ||||||
|  |      */ | ||||||
|  |     public static function clear_link() | ||||||
|  |     { | ||||||
|  |         if(self::$links)  | ||||||
|  |         { | ||||||
|  |             foreach(self::$links as $k=>$v) | ||||||
|  |             { | ||||||
|  |                 @mysqli_close($v['conn']); | ||||||
|  |                 unset(self::$links[$k]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         // 注意,只会连接最后一个,不过貌似也够用了啊 | ||||||
|  |         self::_init(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 改变链接为指定配置的链接(如果不同时使用多个数据库,不会涉及这个操作) | ||||||
|  |      * @parem  $link_name 链接标识名 | ||||||
|  |      * @parem  $config 多次使用时, 这个数组只需传递一次 | ||||||
|  |      *         config 格式与 $GLOBALS['config']['db'] 一致 | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_connect($link_name, $config = array()) | ||||||
|  |     { | ||||||
|  |         self::$link_name = $link_name; | ||||||
|  |         if (!empty($config)) | ||||||
|  |         { | ||||||
|  |             self::$configs[self::$link_name] = $config; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             if (empty(self::$configs[self::$link_name])) | ||||||
|  |             { | ||||||
|  |                 throw new Exception("You not set a config array for connect!"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * 还原为默认连接(如果不同时使用多个数据库,不会涉及这个操作) | ||||||
|  |      * @parem $config 指定配置(默认使用inc_config.php的配置) | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_connect_default() | ||||||
|  |     { | ||||||
|  |         $config = self::_get_default_config(); | ||||||
|  |         self::set_connect('default', $config); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * 获取默认配置 | ||||||
|  |      */ | ||||||
|  |     protected static function _get_default_config() | ||||||
|  |     { | ||||||
|  |         if (empty(self::$configs['default'])) | ||||||
|  |         { | ||||||
|  |             if (!is_array($GLOBALS['config']['db'])) | ||||||
|  |             { | ||||||
|  |                 exit('db.php _get_default_config()' . '没有mysql配置'); | ||||||
|  |             } | ||||||
|  |             self::$configs['default'] = $GLOBALS['config']['db']; | ||||||
|  |         } | ||||||
|  |         return self::$configs['default']; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 返回查询游标 | ||||||
|  |      * @return rsid | ||||||
|  |      */ | ||||||
|  |     protected static function _get_rsid($rsid = '') | ||||||
|  |     { | ||||||
|  |         return $rsid == '' ? self::$rsid : $rsid; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function autocommit($mode = false) | ||||||
|  |     { | ||||||
|  |         if ( self::$autocommiting )  | ||||||
|  |         { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         self::$autocommiting = true; | ||||||
|  |  | ||||||
|  |         self::_init(); | ||||||
|  |         return mysqli_autocommit(self::$links[self::$link_name]['conn'], $mode); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function begin_tran() | ||||||
|  |     { | ||||||
|  |         return self::autocommit(false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function commit() | ||||||
|  |     { | ||||||
|  |         mysqli_commit(self::$links[self::$link_name]['conn']); | ||||||
|  |         self::autocommit(true); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     public static function rollback() | ||||||
|  |     { | ||||||
|  |         mysqli_rollback(self::$links[self::$link_name]['conn']); | ||||||
|  |         self::autocommit(true); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function query($sql) | ||||||
|  |     { | ||||||
|  |         $sql = trim($sql); | ||||||
|  |  | ||||||
|  |         // 初始化数据库 | ||||||
|  |         self::_init(); | ||||||
|  |         self::$rsid = @mysqli_query(self::$links[self::$link_name]['conn'], $sql); | ||||||
|  |  | ||||||
|  |         if (self::$rsid === false) | ||||||
|  |         { | ||||||
|  |             // 不要每次都ping,浪费流量浪费性能,执行出错了才重新连接 | ||||||
|  |             $errno = mysqli_errno(self::$links[self::$link_name]['conn']); | ||||||
|  |             if ($errno == 2013 || $errno == 2006)  | ||||||
|  |             { | ||||||
|  |                 $errmsg = mysqli_error(self::$links[self::$link_name]['conn']); | ||||||
|  |                 log::add($errmsg, "Error"); | ||||||
|  |  | ||||||
|  |                 @mysqli_close(self::$links[self::$link_name]['conn']); | ||||||
|  |                 self::$links[self::$link_name]['conn'] = null; | ||||||
|  |                 return self::query($sql); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             $errmsg = "Query SQL: ".$sql; | ||||||
|  |             log::add($errmsg, "Warning"); | ||||||
|  |             $errmsg = "Error SQL: ".mysqli_error(self::$links[self::$link_name]['conn']); | ||||||
|  |             log::add($errmsg, "Warning"); | ||||||
|  |  | ||||||
|  |             $backtrace = debug_backtrace(); | ||||||
|  |             array_shift($backtrace); | ||||||
|  |             $narr = array('class', 'type', 'function', 'file', 'line'); | ||||||
|  |             $err = "debug_backtrace:\n"; | ||||||
|  |             foreach($backtrace as $i => $l) | ||||||
|  |             { | ||||||
|  |                 foreach($narr as $k) | ||||||
|  |                 { | ||||||
|  |                     if( !isset($l[$k]) )  | ||||||
|  |                     { | ||||||
|  |                         $l[$k] = ''; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 $err .= "[$i] in function {$l['class']}{$l['type']}{$l['function']} "; | ||||||
|  |                 if($l['file']) $err .= " in {$l['file']} "; | ||||||
|  |                 if($l['line']) $err .= " on line {$l['line']} "; | ||||||
|  |                 $err .= "\n"; | ||||||
|  |             } | ||||||
|  |             log::add($err); | ||||||
|  |  | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             return self::$rsid; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function fetch($rsid = '') | ||||||
|  |     { | ||||||
|  |         $rsid = self::_get_rsid($rsid); | ||||||
|  |         $row = mysqli_fetch_array($rsid, MYSQLI_ASSOC); | ||||||
|  |         return $row; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function get_one($sql) | ||||||
|  |     { | ||||||
|  |         if (!preg_match("/limit/i", $sql)) | ||||||
|  |         { | ||||||
|  |             $sql = preg_replace("/[,;]$/i", '', trim($sql)) . " limit 1 "; | ||||||
|  |         } | ||||||
|  |         $rsid = self::query($sql); | ||||||
|  |         if ($rsid === false)  | ||||||
|  |         { | ||||||
|  |             return array(); | ||||||
|  |         } | ||||||
|  |         $row = self::fetch($rsid); | ||||||
|  |         self::free($rsid); | ||||||
|  |         return $row; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function get_all($sql) | ||||||
|  |     { | ||||||
|  |         $rsid = self::query($sql); | ||||||
|  |         if ($rsid === false)  | ||||||
|  |         { | ||||||
|  |             return array(); | ||||||
|  |         } | ||||||
|  |         while ( $row = self::fetch($rsid) ) | ||||||
|  |         { | ||||||
|  |             $rows[] = $row; | ||||||
|  |         } | ||||||
|  |         self::free($rsid); | ||||||
|  |         return empty($rows) ? false : $rows; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function free($rsid) | ||||||
|  |     { | ||||||
|  |         return mysqli_free_result($rsid); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function insert_id() | ||||||
|  |     { | ||||||
|  |         return mysqli_insert_id(self::$links[self::$link_name]['conn']); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function affected_rows() | ||||||
|  |     { | ||||||
|  |         return mysqli_affected_rows(self::$links[self::$link_name]['conn']); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function insert($table = '', $data = null, $return_sql = false) | ||||||
|  |     { | ||||||
|  |         $items_sql = $values_sql = ""; | ||||||
|  |         foreach ($data as $k => $v) | ||||||
|  |         { | ||||||
|  |             $v = stripslashes($v); | ||||||
|  |             $v = addslashes($v); | ||||||
|  |             $items_sql .= "`$k`,"; | ||||||
|  |             $values_sql .= "\"$v\","; | ||||||
|  |         } | ||||||
|  |         $sql = "Insert Ignore Into `{$table}` (" . substr($items_sql, 0, -1) . ") Values (" . substr($values_sql, 0, -1) . ")"; | ||||||
|  |         if ($return_sql)  | ||||||
|  |         { | ||||||
|  |             return $sql; | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             if (self::query($sql)) | ||||||
|  |             { | ||||||
|  |                 return mysqli_insert_id(self::$links[self::$link_name]['conn']); | ||||||
|  |             } | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function insert_batch($table = '', $set = NULL, $return_sql = FALSE)  | ||||||
|  |     { | ||||||
|  |         if (empty($table) || empty($set))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         $set = self::strsafe($set); | ||||||
|  |         $fields = self::get_fields($table); | ||||||
|  |  | ||||||
|  |         $keys_sql = $vals_sql = array(); | ||||||
|  |         foreach ($set as $i=>$val)  | ||||||
|  |         { | ||||||
|  |             ksort($val); | ||||||
|  |             $vals = array(); | ||||||
|  |             foreach ($val as $k => $v) | ||||||
|  |             { | ||||||
|  |                 // 过滤掉数据库没有的字段 | ||||||
|  |                 if (!in_array($k, $fields))  | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 // 如果是第一个数组,把key当做插入条件 | ||||||
|  |                 if ($i == 0 && $k == 0)  | ||||||
|  |                 { | ||||||
|  |                     $keys_sql[] = "`$k`"; | ||||||
|  |                 } | ||||||
|  |                 $vals[] = "\"$v\""; | ||||||
|  |             } | ||||||
|  |             $vals_sql[] = implode(",", $vals); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $sql = "Insert Ignore Into `{$table}`(".implode(", ", $keys_sql).") Values (".implode("), (", $vals_sql).")"; | ||||||
|  |  | ||||||
|  |         if ($return_sql) return $sql; | ||||||
|  |          | ||||||
|  |         $rt = self::query($sql); | ||||||
|  |         $insert_id = self::insert_id(); | ||||||
|  |         $return = empty($insert_id) ? $rt : $insert_id; | ||||||
|  |         return $return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function update_batch($table = '', $set = NULL, $index = NULL, $where = NULL, $return_sql = FALSE)  | ||||||
|  |     { | ||||||
|  |         if (empty($table) || is_null($set) || is_null($index))  | ||||||
|  |         { | ||||||
|  |             // 不要用exit,会中断程序 | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         $set = self::strsafe($set); | ||||||
|  |         $fields = self::get_fields($table); | ||||||
|  |  | ||||||
|  |         $ids = array(); | ||||||
|  |         foreach ($set as $val) | ||||||
|  | 		{ | ||||||
|  |             ksort($val); | ||||||
|  |             // 去重,其实不去也可以,因为相同的when只会执行第一个,后面的就直接跳过不执行了 | ||||||
|  |             $key = md5($val[$index]); | ||||||
|  | 			$ids[$key] = $val[$index]; | ||||||
|  |  | ||||||
|  | 			foreach (array_keys($val) as $field) | ||||||
|  | 			{ | ||||||
|  | 				if ($field != $index) | ||||||
|  | 				{ | ||||||
|  | 					$final[$field][$key] =  'When `'.$index.'` = "'.$val[$index].'" Then "'.$val[$field].'"'; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |         //$ids = array_values($ids); | ||||||
|  |  | ||||||
|  |         // 如果不是数组而且不为空,就转数组 | ||||||
|  |         if (!is_array($where) && !empty($where)) | ||||||
|  |         { | ||||||
|  |             $where = array($where); | ||||||
|  |         } | ||||||
|  |         $where[] = $index.' In ("'.implode('","', $ids).'")'; | ||||||
|  |         $where = empty($where) ? "" : " Where ".implode(" And ", $where); | ||||||
|  |  | ||||||
|  | 		$sql = "Update `".$table."` Set "; | ||||||
|  | 		$cases = ''; | ||||||
|  |  | ||||||
|  | 		foreach ($final as $k => $v) | ||||||
|  | 		{ | ||||||
|  |             // 过滤掉数据库没有的字段 | ||||||
|  |             if (!in_array($k, $fields))  | ||||||
|  |             { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 			$cases .= '`'.$k.'` = Case '."\n"; | ||||||
|  | 			foreach ($v as $row) | ||||||
|  | 			{ | ||||||
|  | 				$cases .= $row."\n"; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			$cases .= 'Else `'.$k.'` End, '; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		$sql .= substr($cases, 0, -2); | ||||||
|  |  | ||||||
|  |         // 其实不带 Where In ($index) 的条件也可以的 | ||||||
|  | 		$sql .= $where; | ||||||
|  |  | ||||||
|  |         if ($return_sql) return $sql; | ||||||
|  |          | ||||||
|  |         $rt = self::query($sql); | ||||||
|  |         $insert_id = self::affected_rows(); | ||||||
|  |         $return = empty($affected_rows) ? $rt : $affected_rows; | ||||||
|  |         return $return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function update($table = '', $data = array(), $where = null, $return_sql = false) | ||||||
|  |     { | ||||||
|  |         $sql = "UPDATE `{$table}` SET "; | ||||||
|  |         foreach ($data as $k => $v) | ||||||
|  |         { | ||||||
|  |             $v = stripslashes($v); | ||||||
|  |             $v = addslashes($v); | ||||||
|  |             $sql .= "`{$k}` = \"{$v}\","; | ||||||
|  |         } | ||||||
|  |         if (!is_array($where)) | ||||||
|  |         { | ||||||
|  |             $where = array($where); | ||||||
|  |         } | ||||||
|  |         // 删除空字段,不然array("")会成为WHERE | ||||||
|  |         foreach ($where as $k => $v) | ||||||
|  |         { | ||||||
|  |             if (empty($v)) | ||||||
|  |             { | ||||||
|  |                 unset($where[$k]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         $where = empty($where) ? "" : " Where " . implode(" And ", $where); | ||||||
|  |         $sql = substr($sql, 0, -1) . $where; | ||||||
|  |         if ($return_sql)  | ||||||
|  |         { | ||||||
|  |             return $sql; | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             if (self::query($sql)) | ||||||
|  |             { | ||||||
|  |                 return mysqli_affected_rows(self::$links[self::$link_name]['conn']); | ||||||
|  |             } | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function delete($table = '', $where = null, $return_sql = false) | ||||||
|  |     { | ||||||
|  |         // 小心全部被删除了 | ||||||
|  |         if (empty($where))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         $where = 'Where ' . (!is_array($where) ? $where : implode(' And ', $where)); | ||||||
|  |         $sql = "Delete From `{$table}` {$where}"; | ||||||
|  |         if ($return_sql)  | ||||||
|  |         { | ||||||
|  |             return $sql; | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             if (self::query($sql)) | ||||||
|  |             { | ||||||
|  |                 return mysqli_affected_rows(self::$links[self::$link_name]['conn']); | ||||||
|  |             } | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function ping() | ||||||
|  |     { | ||||||
|  |         if (!mysqli_ping(self::$links[self::$link_name]['conn'])) | ||||||
|  |         { | ||||||
|  |             @mysqli_close(self::$links[self::$link_name]['conn']); | ||||||
|  |             self::$links[self::$link_name]['conn'] = null; | ||||||
|  |             self::_init(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function strsafe($array) | ||||||
|  |     { | ||||||
|  |         $arrays = array(); | ||||||
|  |         if(is_array($array)===true) | ||||||
|  |         { | ||||||
|  |             foreach ($array as $key => $val) | ||||||
|  |             {                 | ||||||
|  |                 if(is_array($val)===true) | ||||||
|  |                 { | ||||||
|  |                     $arrays[$key] = self::strsafe($val); | ||||||
|  |                 } | ||||||
|  |                 else  | ||||||
|  |                 { | ||||||
|  |                     //先去掉转义,避免下面重复转义了 | ||||||
|  |                     $val = stripslashes($val); | ||||||
|  |                     //进行转义 | ||||||
|  |                     $val = addslashes($val); | ||||||
|  |                     //处理addslashes没法处理的 _ % 字符 | ||||||
|  |                     //$val = strtr($val, array('_'=>'\_', '%'=>'\%')); | ||||||
|  |                     $arrays[$key] = $val; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return $arrays; | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             $array = stripslashes($array); | ||||||
|  |             $array = addslashes($array); | ||||||
|  |             //$array = strtr($array, array('_'=>'\_', '%'=>'\%')); | ||||||
|  |             return $array; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 这个是给insert、update、insert_batch、update_batch用的 | ||||||
|  |     public static function get_fields($table) | ||||||
|  |     { | ||||||
|  |         // $sql = "SHOW COLUMNS FROM $table"; //和下面的语句效果一样 | ||||||
|  |         $rows = self::get_all("Desc `{$table}`"); | ||||||
|  |         $fields = array(); | ||||||
|  |         foreach ($rows as $k => $v) | ||||||
|  |         { | ||||||
|  |             // 过滤自增主键 | ||||||
|  |             // if ($v['Key'] != 'PRI') | ||||||
|  |             if ($v['Extra'] != 'auto_increment') | ||||||
|  |             { | ||||||
|  |                 $fields[] = $v['Field']; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return $fields; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function table_exists($table_name) | ||||||
|  |     { | ||||||
|  |         $sql = "SHOW TABLES LIKE '" . $table_name . "'"; | ||||||
|  |         $rsid = self::query($sql); | ||||||
|  |         $table = self::fetch($rsid); | ||||||
|  |         if (empty($table))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										101
									
								
								vendor/owner888/phpspider/core/init.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								vendor/owner888/phpspider/core/init.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | |||||||
|  | <?php | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | PHPSpider [ A PHP Framework For Crawler ] | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Copyright (c) 2006-2014 https://doc.phpspider.org All rights reserved. | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Author: Seatle Yang <seatle@foxmail.com> | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | //---------------------------------- | ||||||
|  | // PHPSpider公共入口文件 | ||||||
|  | //---------------------------------- | ||||||
|  |  | ||||||
|  | // 严格开发模式 | ||||||
|  | error_reporting( E_ALL ); | ||||||
|  | //ini_set('display_errors', 1); | ||||||
|  |  | ||||||
|  | // 永不超时 | ||||||
|  | ini_set('max_execution_time', 0); | ||||||
|  | set_time_limit(0); | ||||||
|  | // 内存限制,如果外面设置的内存比 /etc/php/php-cli.ini 大,就不要设置了 | ||||||
|  | if (intval(ini_get("memory_limit")) < 1024)  | ||||||
|  | { | ||||||
|  |     ini_set('memory_limit', '1024M'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if( PHP_SAPI != 'cli' ) | ||||||
|  | { | ||||||
|  |     exit("You must run the CLI environment\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 设置时区 | ||||||
|  | date_default_timezone_set('Asia/Shanghai'); | ||||||
|  |  | ||||||
|  | // 引入PATH_DATA | ||||||
|  | require_once __DIR__ . '/constants.php'; | ||||||
|  | // 核心库目录 | ||||||
|  | define('CORE', dirname(__FILE__)); | ||||||
|  | define('PATH_ROOT', CORE."/../"); | ||||||
|  | define('PATH_DATA', CORE."/../data"); | ||||||
|  | define('PATH_LIBRARY', CORE."/../library"); | ||||||
|  |  | ||||||
|  | // 系统配置 | ||||||
|  | if( file_exists( PATH_ROOT."/config/inc_config.php" ) ) | ||||||
|  | { | ||||||
|  |     require PATH_ROOT."/config/inc_config.php";  | ||||||
|  | } | ||||||
|  | require CORE.'/log.php'; | ||||||
|  | require CORE.'/requests.php'; | ||||||
|  | require CORE.'/selector.php'; | ||||||
|  | require CORE.'/util.php'; | ||||||
|  | require CORE.'/db.php'; | ||||||
|  | require CORE.'/cache.php'; | ||||||
|  | require CORE."/worker.php";  | ||||||
|  | require CORE."/phpspider.php";  | ||||||
|  |  | ||||||
|  | // 启动的时候生成data目录 | ||||||
|  | util::path_exists(PATH_DATA); | ||||||
|  | util::path_exists(PATH_DATA."/lock"); | ||||||
|  | util::path_exists(PATH_DATA."/log"); | ||||||
|  | util::path_exists(PATH_DATA."/cache"); | ||||||
|  | util::path_exists(PATH_DATA."/status"); | ||||||
|  |  | ||||||
|  | function autoload($classname) { | ||||||
|  |     set_include_path(PATH_ROOT.'/library/'); | ||||||
|  |     spl_autoload($classname); //replaces include/require | ||||||
|  | } | ||||||
|  |  | ||||||
|  | spl_autoload_extensions('.php'); | ||||||
|  | spl_autoload_register('autoload'); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 自动加载类库处理 | ||||||
|  |  * @return void | ||||||
|  |  */ | ||||||
|  | //function __autoload( $classname ) | ||||||
|  | //{ | ||||||
|  |     //$classname = preg_replace("/[^0-9a-z_]/i", '', $classname); | ||||||
|  |     //if( class_exists ( $classname ) ) { | ||||||
|  |         //return true; | ||||||
|  |     //} | ||||||
|  |     //$classfile = $classname.'.php'; | ||||||
|  |     //try | ||||||
|  |     //{ | ||||||
|  |         //if ( file_exists ( PATH_LIBRARY.'/'.$classfile ) ) | ||||||
|  |         //{ | ||||||
|  |             //require PATH_LIBRARY.'/'.$classfile; | ||||||
|  |         //} | ||||||
|  |         //else | ||||||
|  |         //{ | ||||||
|  |             //throw new Exception ( 'Error: Cannot find the '.$classname ); | ||||||
|  |         //} | ||||||
|  |     //} | ||||||
|  |     //catch ( Exception $e ) | ||||||
|  |     //{ | ||||||
|  |         //log::error($e->getMessage().'|'.$classname); | ||||||
|  |         //exit(); | ||||||
|  |     //} | ||||||
|  | //} | ||||||
							
								
								
									
										119
									
								
								vendor/owner888/phpspider/core/log.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								vendor/owner888/phpspider/core/log.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | |||||||
|  | <?php | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | PHPSpider [ A PHP Framework For Crawler ] | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Copyright (c) 2006-2014 https://doc.phpspider.org All rights reserved. | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Author: Seatle Yang <seatle@foxmail.com> | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | //---------------------------------- | ||||||
|  | // PHPSpider日志类文件 | ||||||
|  | //---------------------------------- | ||||||
|  |  | ||||||
|  | namespace phpspider\core; | ||||||
|  | // 引入PATH_DATA | ||||||
|  | require_once __DIR__ . '/constants.php'; | ||||||
|  |  | ||||||
|  | class log | ||||||
|  | { | ||||||
|  |     public static $log_show = false; | ||||||
|  |     public static $log_type = false; | ||||||
|  |     public static $log_file = "data/phpspider.log"; | ||||||
|  |     public static $out_sta = ""; | ||||||
|  |     public static $out_end = ""; | ||||||
|  |  | ||||||
|  |     public static function note($msg) | ||||||
|  |     { | ||||||
|  |         self::$out_sta = self::$out_end = ""; | ||||||
|  |         self::msg($msg, 'note'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function info($msg) | ||||||
|  |     { | ||||||
|  |         self::$out_sta = self::$out_end = ""; | ||||||
|  |         self::msg($msg, 'info'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function warn($msg) | ||||||
|  |     { | ||||||
|  |         self::$out_sta = self::$out_end = ""; | ||||||
|  |         if (!util::is_win())  | ||||||
|  |         { | ||||||
|  |             self::$out_sta = "\033[33m"; | ||||||
|  |             self::$out_end = "\033[0m"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         self::msg($msg, 'warn'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function debug($msg) | ||||||
|  |     { | ||||||
|  |         self::$out_sta = self::$out_end = ""; | ||||||
|  |         if (!util::is_win())  | ||||||
|  |         { | ||||||
|  |             self::$out_sta = "\033[36m"; | ||||||
|  |             self::$out_end = "\033[0m"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         self::msg($msg, 'debug'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function error($msg) | ||||||
|  |     { | ||||||
|  |         self::$out_sta = self::$out_end = ""; | ||||||
|  |         if (!util::is_win())  | ||||||
|  |         { | ||||||
|  |             self::$out_sta = "\033[31m"; | ||||||
|  |             self::$out_end = "\033[0m"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         self::msg($msg, 'error'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function msg($msg, $log_type) | ||||||
|  |     { | ||||||
|  |         if ($log_type != 'note' && self::$log_type && strpos(self::$log_type, $log_type) === false)  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if ($log_type == 'note')  | ||||||
|  |         { | ||||||
|  |             $msg = self::$out_sta. $msg . "\n".self::$out_end; | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             $msg = self::$out_sta.date("Y-m-d H:i:s")." [{$log_type}] " . $msg .self::$out_end. "\n"; | ||||||
|  |         } | ||||||
|  |         if(self::$log_show) | ||||||
|  |         { | ||||||
|  |             echo $msg; | ||||||
|  |         } | ||||||
|  |         file_put_contents(self::$log_file, $msg, FILE_APPEND | LOCK_EX); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 记录日志 XXX | ||||||
|  |      * @param string $msg | ||||||
|  |      * @param string $log_type  Note|Warning|Error | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function add($msg, $log_type = '') | ||||||
|  |     { | ||||||
|  |         if ($log_type != '')  | ||||||
|  |         { | ||||||
|  |             $msg = date("Y-m-d H:i:s")." [{$log_type}] " . $msg . "\n"; | ||||||
|  |         } | ||||||
|  |         if(self::$log_show) | ||||||
|  |         { | ||||||
|  |             echo $msg; | ||||||
|  |         } | ||||||
|  |         //file_put_contents(PATH_DATA."/log/".strtolower($log_type).".log", $msg, FILE_APPEND | LOCK_EX); | ||||||
|  |         file_put_contents(PATH_DATA."/log/error.log", $msg, FILE_APPEND | LOCK_EX); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										2870
									
								
								vendor/owner888/phpspider/core/phpspider.bak20170807.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2870
									
								
								vendor/owner888/phpspider/core/phpspider.bak20170807.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3598
									
								
								vendor/owner888/phpspider/core/phpspider.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3598
									
								
								vendor/owner888/phpspider/core/phpspider.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1388
									
								
								vendor/owner888/phpspider/core/queue.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1388
									
								
								vendor/owner888/phpspider/core/queue.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										998
									
								
								vendor/owner888/phpspider/core/requests.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										998
									
								
								vendor/owner888/phpspider/core/requests.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,998 @@ | |||||||
|  | <?php | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | PHPSpider [ A PHP Framework For Crawler ] | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Copyright (c) 2006-2014 https://doc.phpspider.org All rights reserved. | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Author: Seatle Yang <seatle@foxmail.com> | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | GET请求 | ||||||
|  | // | requests::get('http://www.test.com'); | ||||||
|  | // | SERVER | ||||||
|  | // | $_GET | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | POST请求 | ||||||
|  | // | $data = array('name'=>'request'); | ||||||
|  | // | requests::post('http://www.test.com', $data); | ||||||
|  | // | SERVER | ||||||
|  | // | $_POST | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | POST RESTful请求 | ||||||
|  | // | $data = array('name'=>'request'); | ||||||
|  | // | $data_string = json_encode($data); | ||||||
|  | // | requests::set_header("Content-Type", "application/json"); | ||||||
|  | // | requests::post('http://www.test.com', $data_string); | ||||||
|  | // | SERVER | ||||||
|  | // | file_get_contents('php://input') | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | POST 文件上传 | ||||||
|  | // | $data = array('file1'=>''./data/phpspider.log''); | ||||||
|  | // | requests::post('http://www.test.com', null, $data); | ||||||
|  | // | SERVER | ||||||
|  | // | $_FILES | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | 代理 | ||||||
|  | // | requests::set_proxy(array('223.153.69.150:42354')); | ||||||
|  | // | $html = requests::get('https://www.test.com'); | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | //---------------------------------- | ||||||
|  | // PHPSpider请求类文件 | ||||||
|  | //---------------------------------- | ||||||
|  |  | ||||||
|  | namespace phpspider\core; | ||||||
|  |  | ||||||
|  | if (!function_exists('curl_file_create'))  | ||||||
|  | { | ||||||
|  |     function curl_file_create($filename, $mimetype = '', $postname = '')  | ||||||
|  |     { | ||||||
|  |         return "@$filename;filename=" | ||||||
|  |             . ($postname ?: basename($filename)) | ||||||
|  |             . ($mimetype ? ";type=$mimetype" : ''); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class requests | ||||||
|  | { | ||||||
|  |     const VERSION = '2.0.1'; | ||||||
|  |  | ||||||
|  |     protected static $ch = null; | ||||||
|  |  | ||||||
|  |     /**** Public variables ****/ | ||||||
|  |  | ||||||
|  |     /* user definable vars */ | ||||||
|  |  | ||||||
|  |     public static $timeout         = 15; | ||||||
|  |     public static $encoding        = null; | ||||||
|  |     public static $input_encoding  = null; | ||||||
|  |     public static $output_encoding = null; | ||||||
|  |     public static $cookies         = array(); // array of cookies to pass | ||||||
|  |     // $cookies['username'] = "seatle"; | ||||||
|  |     public static $rawheaders = array();                        // array of raw headers to send | ||||||
|  |     public static $domain_cookies = array();                    // array of cookies for domain to pass | ||||||
|  |     public static $hosts = array();                             // random host binding for make request faster | ||||||
|  |     public static $headers = array();                           // headers returned from server sent here | ||||||
|  |     public static $useragents = array("requests/2.0.0");        // random agent we masquerade as | ||||||
|  |     public static $client_ips = array();                        // random ip we masquerade as | ||||||
|  |     public static $proxies = array();                           // random proxy ip | ||||||
|  |     public static $raw = "";                                    // head + body content returned from server sent here | ||||||
|  |     public static $head = "";                                   // head content | ||||||
|  |     public static $content = "";                                // The body before encoding | ||||||
|  |     public static $text = "";                                   // The body after encoding | ||||||
|  |     public static $info = array();                              // curl info | ||||||
|  |     public static $history = 302;                               // http request status before redirect. ex:30x | ||||||
|  |     public static $status_code = 0;                             // http request status | ||||||
|  |     public static $error = "";                                  // error messages sent here | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * set timeout | ||||||
|  |      * $timeout 为数组时会分别设置connect和read | ||||||
|  |      * | ||||||
|  |      * @param init or array $timeout | ||||||
|  |      * @return | ||||||
|  |      */ | ||||||
|  |     public static function set_timeout($timeout) | ||||||
|  |     { | ||||||
|  |         self::$timeout = $timeout; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置代理 | ||||||
|  |      * 如果代理有多个,请求时会随机使用 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $proxies | ||||||
|  |      * array ( | ||||||
|  |      *    'socks5://user1:pass2@host:port', | ||||||
|  |      *    'socks5://user2:pass2@host:port' | ||||||
|  |      *) | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-09-18 10:17 | ||||||
|  |      */ | ||||||
|  |     public static function set_proxy($proxy) | ||||||
|  |     { | ||||||
|  |         self::$proxies = is_array($proxy) ? $proxy : array($proxy); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 删除代理 | ||||||
|  |      * 因为每个链接信息里面都有代理信息,有的链接需要,有的不需要,所以必须提供一个删除功能 | ||||||
|  |      *  | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2018-07-16 17:59 | ||||||
|  |      */ | ||||||
|  |     public static function del_proxy() | ||||||
|  |     { | ||||||
|  |         self::$proxies = array(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 自定义请求头部 | ||||||
|  |      * 请求头内容可以用 requests::$rawheaders 来获取 | ||||||
|  |      * 比如获取Content-Type:requests::$rawheaders['Content-Type'] | ||||||
|  |      * | ||||||
|  |      * @param string $headers | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_header($key, $value) | ||||||
|  |     { | ||||||
|  |         self::$rawheaders[$key] = $value; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置全局COOKIE | ||||||
|  |      * | ||||||
|  |      * @param string $cookie | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_cookie($key, $value, $domain = '') | ||||||
|  |     { | ||||||
|  |         if (empty($key))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (!empty($domain))  | ||||||
|  |         { | ||||||
|  |             self::$domain_cookies[$domain][$key] = $value; | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             self::$cookies[$key] = $value; | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 批量设置全局cookie | ||||||
|  |      *  | ||||||
|  |      * @param mixed $cookies | ||||||
|  |      * @param string $domain | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2017-08-03 18:06 | ||||||
|  |      */ | ||||||
|  |     public static function set_cookies($cookies, $domain = '') | ||||||
|  |     { | ||||||
|  |         $cookies_arr = explode(';', $cookies); | ||||||
|  |         if (empty($cookies_arr)) | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         foreach ($cookies_arr as $cookie)  | ||||||
|  |         { | ||||||
|  |             $cookie_arr = explode('=', $cookie, 2); | ||||||
|  |             $key        = $cookie_arr[0]; | ||||||
|  |             $value      = empty($cookie_arr[1]) ? '' : $cookie_arr[1]; | ||||||
|  |  | ||||||
|  |             if (!empty($domain))  | ||||||
|  |             { | ||||||
|  |                 self::$domain_cookies[$domain][$key] = $value; | ||||||
|  |             } | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 self::$cookies[$key] = $value; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取单一Cookie | ||||||
|  |      *  | ||||||
|  |      * @param mixed $name    cookie名称 | ||||||
|  |      * @param string $domain 不传则取全局cookie,就是手动set_cookie的cookie | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2017-08-03 18:06 | ||||||
|  |      */ | ||||||
|  |     public static function get_cookie($name, $domain = '') | ||||||
|  |     { | ||||||
|  |         if (!empty($domain) && !isset(self::$domain_cookies[$domain]))  | ||||||
|  |         { | ||||||
|  |             return ''; | ||||||
|  |         } | ||||||
|  |         $cookies = empty($domain) ? self::$cookies : self::$domain_cookies[$domain]; | ||||||
|  |         return isset($cookies[$name]) ? $cookies[$name] : ''; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * 获取Cookie数组 | ||||||
|  |      *  | ||||||
|  |      * @param string $domain 不传则取全局cookie,就是手动set_cookie的cookie | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2017-08-03 18:06 | ||||||
|  |      */ | ||||||
|  |     public static function get_cookies($domain = '') | ||||||
|  |     { | ||||||
|  |         if (!empty($domain) && !isset(self::$domain_cookies[$domain]))  | ||||||
|  |         { | ||||||
|  |             return array(); | ||||||
|  |         } | ||||||
|  |         return empty($domain) ? self::$cookies : self::$domain_cookies[$domain]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 删除Cookie | ||||||
|  |      *  | ||||||
|  |      * @param string $domain  不传则删除全局Cookie | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2017-08-03 18:06 | ||||||
|  |      */ | ||||||
|  |     public static function del_cookie($key, $domain = '') | ||||||
|  |     { | ||||||
|  |         if (empty($key))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (!empty($domain) && !isset(self::$domain_cookies[$domain]))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (!empty($domain))  | ||||||
|  |         { | ||||||
|  |             if (isset(self::$domain_cookies[$domain][$key]))  | ||||||
|  |             { | ||||||
|  |                 unset(self::$domain_cookies[$domain][$key]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             if (isset(self::$cookies[$key]))  | ||||||
|  |             { | ||||||
|  |                 unset(self::$cookies[$key]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 删除Cookie | ||||||
|  |      *  | ||||||
|  |      * @param string $domain  不传则删除全局Cookie | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2017-08-03 18:06 | ||||||
|  |      */ | ||||||
|  |     public static function del_cookies($domain = '') | ||||||
|  |     { | ||||||
|  |         if (!empty($domain) && !isset(self::$domain_cookies[$domain]))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if ( empty($domain) )  | ||||||
|  |         { | ||||||
|  |             self::$cookies = array(); | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             if (isset(self::$domain_cookies[$domain]))  | ||||||
|  |             { | ||||||
|  |                 unset(self::$domain_cookies[$domain]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置随机的user_agent | ||||||
|  |      * | ||||||
|  |      * @param string $useragent | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_useragent($useragent) | ||||||
|  |     { | ||||||
|  |         self::$useragents = is_array($useragent) ? $useragent : array($useragent); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * set referer | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |     public static function set_referer($referer) | ||||||
|  |     { | ||||||
|  |         self::$rawheaders['Referer'] = $referer; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置伪造IP | ||||||
|  |      * 传入数组则为随机IP | ||||||
|  |      * @param string $ip | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_client_ip($ip) | ||||||
|  |     { | ||||||
|  |         self::$client_ips = is_array($ip) ? $ip : array($ip); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 删除伪造IP | ||||||
|  |      *  | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2018-07-16 17:59 | ||||||
|  |      */ | ||||||
|  |     public static function del_client_ip() | ||||||
|  |     { | ||||||
|  |         self::$client_ips = array(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置中文请求 | ||||||
|  |      *  | ||||||
|  |      * @param string $lang | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_accept_language($lang = 'zh-CN') | ||||||
|  |     { | ||||||
|  |         self::$rawheaders['Accept-Language'] = $lang; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置Hosts | ||||||
|  |      * 负载均衡到不同的服务器,如果对方使用CDN,采用这个是最好的了 | ||||||
|  |      * | ||||||
|  |      * @param string $hosts | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_hosts($host, $ips = array()) | ||||||
|  |     { | ||||||
|  |         $ips = is_array($ips) ? $ips : array($ips); | ||||||
|  |         self::$hosts[$host] = $ips; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 分割返回的header和body | ||||||
|  |      * header用来判断编码和获取Cookie | ||||||
|  |      * body用来判断编码,得到编码前和编码后的内容 | ||||||
|  |      *  | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2017-08-03 18:06 | ||||||
|  |      */ | ||||||
|  |     public static function split_header_body() | ||||||
|  |     { | ||||||
|  |         $head = $body = ''; | ||||||
|  |         $head = substr(self::$raw, 0, self::$info['header_size']); | ||||||
|  |         $body = substr(self::$raw, self::$info['header_size']); | ||||||
|  |         // http header | ||||||
|  |         self::$head = $head; | ||||||
|  |         // The body before encoding | ||||||
|  |         self::$content = $body; | ||||||
|  |  | ||||||
|  |         //$http_headers = array(); | ||||||
|  |         //// 解析HTTP数据流 | ||||||
|  |         //if (!empty(self::$raw))  | ||||||
|  |         //{ | ||||||
|  |             //self::get_response_cookies($domain); | ||||||
|  |             //// body里面可能有 \r\n\r\n,但是第一个一定是HTTP Header,去掉后剩下的就是body | ||||||
|  |             //$array = explode("\r\n\r\n", self::$raw); | ||||||
|  |             //foreach ($array as $k=>$v)  | ||||||
|  |             //{ | ||||||
|  |                 //// post 方法会有两个http header:HTTP/1.1 100 Continue、HTTP/1.1 200 OK | ||||||
|  |                 //if (preg_match("#^HTTP/.*? 100 Continue#", $v))  | ||||||
|  |                 //{ | ||||||
|  |                     //unset($array[$k]); | ||||||
|  |                     //continue; | ||||||
|  |                 //} | ||||||
|  |                 //if (preg_match("#^HTTP/.*? \d+ #", $v))  | ||||||
|  |                 //{ | ||||||
|  |                     //$header = $v; | ||||||
|  |                     //unset($array[$k]); | ||||||
|  |                     //$http_headers = self::get_response_headers($v); | ||||||
|  |                 //} | ||||||
|  |             //} | ||||||
|  |             //$body = implode("\r\n\r\n", $array); | ||||||
|  |         //} | ||||||
|  |  | ||||||
|  |         // 设置了输出编码的转码,注意: xpath只支持utf-8,iso-8859-1 不要转,他本身就是utf-8 | ||||||
|  |         $body = self::encoding($body); //自动转码 | ||||||
|  |         // 转码后 | ||||||
|  |         self::$encoding = self::$output_encoding; | ||||||
|  |  | ||||||
|  |         // The body after encoding | ||||||
|  |         self::$text = $body; | ||||||
|  |         return array($head, $body); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得域名相对应的Cookie | ||||||
|  |      *  | ||||||
|  |      * @param mixed $header | ||||||
|  |      * @param mixed $domain | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2017-08-03 18:06 | ||||||
|  |      */ | ||||||
|  |     public static function get_response_cookies($header, $domain) | ||||||
|  |     { | ||||||
|  |         // 解析Cookie并存入 self::$cookies 方便调用 | ||||||
|  |         preg_match_all("/.*?Set\-Cookie: ([^\r\n]*)/i", $header, $matches); | ||||||
|  |         $cookies = empty($matches[1]) ? array() : $matches[1]; | ||||||
|  |  | ||||||
|  |         // 解析到Cookie | ||||||
|  |         if (!empty($cookies))  | ||||||
|  |         { | ||||||
|  |             $cookies = implode(';', $cookies); | ||||||
|  |             $cookies = explode(';', $cookies); | ||||||
|  |             foreach ($cookies as $cookie) | ||||||
|  |             { | ||||||
|  |                 $cookie_arr = explode('=', $cookie, 2); | ||||||
|  |                 // 过滤 httponly、secure | ||||||
|  |                 if (count($cookie_arr) < 2)  | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 $cookie_name = !empty($cookie_arr[0]) ? trim($cookie_arr[0]) : ''; | ||||||
|  |                 if (empty($cookie_name))  | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 // 过滤掉domain路径 | ||||||
|  |                 if (in_array(strtolower($cookie_name), array('path', 'domain', 'expires', 'max-age')))  | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 self::$domain_cookies[$domain][trim($cookie_arr[0])] = trim($cookie_arr[1]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得response header | ||||||
|  |      * 此方法占时没有用到 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $header | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2017-08-03 18:06 | ||||||
|  |      */ | ||||||
|  |     public static function get_response_headers($header) | ||||||
|  |     { | ||||||
|  |         $headers = array(); | ||||||
|  |         $header_lines = explode("\n", $header); | ||||||
|  |         if (!empty($header_lines))  | ||||||
|  |         { | ||||||
|  |             foreach ($header_lines as $line)  | ||||||
|  |             { | ||||||
|  |                 $header_arr = explode(':', $line, 2); | ||||||
|  |                 $key        = empty($header_arr[0]) ? '' : trim($header_arr[0]); | ||||||
|  |                 $val        = empty($header_arr[1]) ? '' : trim($header_arr[1]); | ||||||
|  |                 if (empty($key) || empty($val)) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 $headers[$key] = $val; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         self::$headers = $headers; | ||||||
|  |         return self::$headers; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取编码 | ||||||
|  |      * @param $string | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     public static function get_encoding($string) | ||||||
|  |     { | ||||||
|  |         $encoding = mb_detect_encoding($string, array('UTF-8', 'GBK', 'GB2312', 'LATIN1', 'ASCII', 'BIG5', 'ISO-8859-1')); | ||||||
|  |         return strtolower($encoding); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 移除页面head区域代码 | ||||||
|  |      * @param $html | ||||||
|  |      * @return mixed | ||||||
|  |      */ | ||||||
|  |     private static function _remove_head($html) | ||||||
|  |     { | ||||||
|  |         return preg_replace('/<head.+?>.+<\/head>/is', '<head></head>', $html); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * 简单的判断一下参数是否为一个URL链接 | ||||||
|  |      * @param  string  $str  | ||||||
|  |      * @return boolean       | ||||||
|  |      */ | ||||||
|  |     private static function _is_url($url) | ||||||
|  |     { | ||||||
|  |         //$pattern = '/^http(s)?:\\/\\/.+/'; | ||||||
|  |         $pattern = "/\b(([\w-]+:\/\/?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/)))/"; | ||||||
|  |         if (preg_match($pattern, $url))  | ||||||
|  |         { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 初始化 CURL | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |     public static function init() | ||||||
|  |     { | ||||||
|  |         if (!is_resource ( self::$ch )) | ||||||
|  |         { | ||||||
|  |             self::$ch = curl_init (); | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_RETURNTRANSFER, true ); | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_HEADER, false ); | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_USERAGENT, "phpspider-requests/".self::VERSION ); | ||||||
|  |             // 如果设置了两个时间,就分开设置 | ||||||
|  |             if (is_array(self::$timeout))  | ||||||
|  |             { | ||||||
|  |                 curl_setopt( self::$ch, CURLOPT_CONNECTTIMEOUT, self::$timeout[0] ); | ||||||
|  |                 curl_setopt( self::$ch, CURLOPT_TIMEOUT, self::$timeout[1]); | ||||||
|  |             } | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 curl_setopt(self::$ch, CURLOPT_CONNECTTIMEOUT, ceil(self::$timeout / 2)); | ||||||
|  |                 curl_setopt(self::$ch, CURLOPT_TIMEOUT, self::$timeout); | ||||||
|  |             } | ||||||
|  |             curl_setopt(self::$ch, CURLOPT_MAXREDIRS, 5); //maximum number of redirects allowed | ||||||
|  |             // 在多线程处理场景下使用超时选项时,会忽略signals对应的处理函数,但是无耐的是还有小概率的crash情况发生 | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_NOSIGNAL, true); | ||||||
|  |         } | ||||||
|  |         return self::$ch; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * get 请求 | ||||||
|  |      */ | ||||||
|  |     public static function get($url, $fields = array(), $allow_redirects = true, $cert = NULL) | ||||||
|  |     { | ||||||
|  |         self::init (); | ||||||
|  |         return self::request($url, 'get', $fields, NULL, $allow_redirects, $cert); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * post 请求 | ||||||
|  |      * $fields 有三种类型:1、数组;2、http query;3、json | ||||||
|  |      * 1、array('name'=>'yangzetao')  | ||||||
|  |      * 2、http_build_query(array('name'=>'yangzetao'))  | ||||||
|  |      * 3、json_encode(array('name'=>'yangzetao')) | ||||||
|  |      * 前两种是普通的post,可以用$_POST方式获取 | ||||||
|  |      * 第三种是post stream( json rpc,其实就是webservice ) | ||||||
|  |      * 虽然是post方式,但是只能用流方式 http://input 后者 $HTTP_RAW_POST_DATA 获取  | ||||||
|  |      *  | ||||||
|  |      * @param mixed $url  | ||||||
|  |      * @param array $fields  | ||||||
|  |      * @param mixed $proxies  | ||||||
|  |      * @static | ||||||
|  |      * @access public | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function post($url, $fields = array(), $files = array(), $allow_redirects = true, $cert = NULL) | ||||||
|  |     { | ||||||
|  |         self::init (); | ||||||
|  |         return self::request($url, 'POST', $fields, $files, $allow_redirects, $cert); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function put($url, $fields = array(), $allow_redirects = true, $cert = NULL) | ||||||
|  |     { | ||||||
|  |         self::init (); | ||||||
|  |         return self::request($url, 'PUT', $fields, $allow_redirects, $cert); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function delete($url, $fields = array(), $allow_redirects = true, $cert = NULL) | ||||||
|  |     { | ||||||
|  |         self::init (); | ||||||
|  |         return self::request($url, 'DELETE', $fields, $allow_redirects, $cert); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 响应HTTP头域里的元信息 | ||||||
|  |     // 此方法被用来获取请求实体的元信息而不需要传输实体主体(entity-body) | ||||||
|  |     // 此方法经常被用来测试超文本链接的有效性,可访问性,和最近的改变。. | ||||||
|  |     public static function head($url, $fields = array(), $allow_redirects = true, $cert = NULL) | ||||||
|  |     { | ||||||
|  |         self::init (); | ||||||
|  |         self::request($url, 'HEAD', $fields, $allow_redirects, $cert); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function options($url, $fields = array(), $allow_redirects = true, $cert = NULL) | ||||||
|  |     { | ||||||
|  |         self::init (); | ||||||
|  |         return self::request($url, 'OPTIONS', $fields, $allow_redirects, $cert); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function patch($url, $fields = array(), $allow_redirects = true, $cert = NULL) | ||||||
|  |     { | ||||||
|  |         self::init (); | ||||||
|  |         return self::request($url, 'PATCH', $fields, $allow_redirects, $cert); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * request | ||||||
|  |      *  | ||||||
|  |      * @param mixed $url        请求URL | ||||||
|  |      * @param string $method    请求方法 | ||||||
|  |      * @param array $fields     表单字段 | ||||||
|  |      * @param array $files      上传文件 | ||||||
|  |      * @param mixed $cert       CA证书 | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2017-08-03 18:06 | ||||||
|  |      */ | ||||||
|  |     public static function request($url, $method = 'GET', $fields = array(), $files = array(), $allow_redirects = true, $cert = NULL) | ||||||
|  |     { | ||||||
|  |         $method = strtoupper($method); | ||||||
|  |         if(!self::_is_url($url)) | ||||||
|  |         { | ||||||
|  |             self::$error = "You have requested URL ({$url}) is not a valid HTTP address"; | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 如果是 get 方式,直接拼凑一个 url 出来 | ||||||
|  |         if ($method == 'GET' && !empty($fields))  | ||||||
|  |         { | ||||||
|  |             $url = $url.(strpos($url, '?') === false ? '?' : '&').http_build_query($fields); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $parse_url = parse_url($url); | ||||||
|  |         if (empty($parse_url) || empty($parse_url['host']) || !in_array($parse_url['scheme'], array('http', 'https')))  | ||||||
|  |         { | ||||||
|  |             self::$error = "No connection adapters were found for '{$url}'"; | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         $scheme = $parse_url['scheme']; | ||||||
|  |         $domain = $parse_url['host']; | ||||||
|  |  | ||||||
|  |         // 随机绑定 hosts,做负载均衡 | ||||||
|  |         if (self::$hosts)  | ||||||
|  |         { | ||||||
|  |             if (isset(self::$hosts[$domain])) | ||||||
|  |             { | ||||||
|  |                 $hosts = self::$hosts[$domain]; | ||||||
|  |                 $key = rand(0, count($hosts)-1); | ||||||
|  |                 $ip = $hosts[$key]; | ||||||
|  |                 $url = str_replace($domain, $ip, $url); | ||||||
|  |                 self::$rawheaders['Host'] = $domain; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         curl_setopt( self::$ch, CURLOPT_URL, $url ); | ||||||
|  |  | ||||||
|  |         if ($method != 'GET') | ||||||
|  |         { | ||||||
|  |             // 如果是 post 方式 | ||||||
|  |             if ($method == 'POST') | ||||||
|  |             { | ||||||
|  |                 //curl_setopt( self::$ch, CURLOPT_POST, true ); | ||||||
|  |                 $tmpheaders = array_change_key_case(self::$rawheaders, CASE_LOWER); | ||||||
|  |                 // 有些RESTful服务只接受JSON形态的数据 | ||||||
|  |                 // CURLOPT_POST会把上傳的文件类型设为 multipart/form-data | ||||||
|  |                 // 把CURLOPT_POSTFIELDS的内容按multipart/form-data 的形式编码 | ||||||
|  |                 // CURLOPT_CUSTOMREQUEST可以按指定内容上传 | ||||||
|  |                 if ( isset($tmpheaders['content-type']) && $tmpheaders['content-type'] == 'application/json' )  | ||||||
|  |                 { | ||||||
|  |                     curl_setopt( self::$ch, CURLOPT_CUSTOMREQUEST, $method );  | ||||||
|  |                 } | ||||||
|  |                 else  | ||||||
|  |                 { | ||||||
|  |                     curl_setopt( self::$ch, CURLOPT_POST, true ); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 $file_fields = array(); | ||||||
|  |                 if (!empty($files))  | ||||||
|  |                 { | ||||||
|  |                     foreach ($files as $postname => $file)  | ||||||
|  |                     { | ||||||
|  |                         $filepath = realpath($file); | ||||||
|  |                         // 如果文件不存在 | ||||||
|  |                         if (!file_exists($filepath))  | ||||||
|  |                         { | ||||||
|  |                             continue; | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                         $filename = basename($filepath); | ||||||
|  |                         $type = self::get_mimetype($filepath); | ||||||
|  |                         $file_fields[$postname] = curl_file_create($filepath, $type, $filename); | ||||||
|  |                         // curl -F "name=seatle&file=@/absolute/path/to/image.png" htt://localhost/uploadfile.php | ||||||
|  |                         //$cfile = '@'.realpath($filename).";type=".$type.";filename=".$filename; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 self::$rawheaders['X-HTTP-Method-Override'] = $method; | ||||||
|  |                 curl_setopt( self::$ch, CURLOPT_CUSTOMREQUEST, $method );  | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if ( $method == 'POST' )  | ||||||
|  |             { | ||||||
|  |                 // 不是上传文件的,用http_build_query, 能实现更好的兼容性,更小的请求数据包 | ||||||
|  |                 if ( empty($file_fields) )  | ||||||
|  |                 { | ||||||
|  |                     // post方式 | ||||||
|  |                     if ( is_array($fields) )  | ||||||
|  |                     { | ||||||
|  |                         $fields = http_build_query($fields); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else  | ||||||
|  |                 { | ||||||
|  |                     // 有post数据 | ||||||
|  |                     if ( is_array($fields) && !empty($fields) )  | ||||||
|  |                     { | ||||||
|  |                         // 某些server可能会有问题 | ||||||
|  |                         $fields = array_merge($fields, $file_fields); | ||||||
|  |                     } | ||||||
|  |                     else  | ||||||
|  |                     { | ||||||
|  |                         $fields = $file_fields; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // 不能直接传数组,不知道是什么Bug,会非常慢 | ||||||
|  |                 curl_setopt( self::$ch, CURLOPT_POSTFIELDS, $fields ); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $cookies = self::get_cookies(); | ||||||
|  |         $domain_cookies = self::get_cookies($domain); | ||||||
|  |         $cookies =  array_merge($cookies, $domain_cookies); | ||||||
|  |         // 是否设置了cookie | ||||||
|  |         if (!empty($cookies))  | ||||||
|  |         { | ||||||
|  |             foreach ($cookies as $key=>$value)  | ||||||
|  |             { | ||||||
|  |                 $cookie_arr[] = $key.'='.$value; | ||||||
|  |             } | ||||||
|  |             $cookies = implode('; ', $cookie_arr); | ||||||
|  |             curl_setopt(self::$ch, CURLOPT_COOKIE, $cookies); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (!empty(self::$useragents))  | ||||||
|  |         { | ||||||
|  |             $key = rand(0, count(self::$useragents) - 1); | ||||||
|  |             self::$rawheaders['User-Agent'] = self::$useragents[$key]; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (!empty(self::$client_ips))  | ||||||
|  |         { | ||||||
|  |             $key                                 = rand(0, count(self::$client_ips) - 1); | ||||||
|  |             self::$rawheaders['CLIENT-IP']       = self::$client_ips[$key]; | ||||||
|  |             self::$rawheaders['X-FORWARDED-FOR'] = self::$client_ips[$key]; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (self::$rawheaders) | ||||||
|  |         { | ||||||
|  |             $http_headers = array(); | ||||||
|  |             foreach (self::$rawheaders as $k=>$v)  | ||||||
|  |             { | ||||||
|  |                 $http_headers[] = $k.': '.$v; | ||||||
|  |             } | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_HTTPHEADER, $http_headers ); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         curl_setopt( self::$ch, CURLOPT_ENCODING, 'gzip' ); | ||||||
|  |  | ||||||
|  |         // 关闭验证 | ||||||
|  |         if ($scheme == 'https')  | ||||||
|  |         { | ||||||
|  |             curl_setopt(self::$ch, CURLOPT_SSL_VERIFYPEER, false); | ||||||
|  |             curl_setopt(self::$ch, CURLOPT_SSL_VERIFYHOST, false); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (self::$proxies) | ||||||
|  |         { | ||||||
|  |             $key = rand(0, count(self::$proxies) - 1); | ||||||
|  |             $proxy = self::$proxies[$key]; | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_PROXY, $proxy ); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // header + body,header 里面有 cookie | ||||||
|  |         curl_setopt( self::$ch, CURLOPT_HEADER, true ); | ||||||
|  |         // 请求跳转后的内容 | ||||||
|  |         if ($allow_redirects) | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_FOLLOWLOCATION, true); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         self::$raw = curl_exec ( self::$ch ); | ||||||
|  |         // 真实url | ||||||
|  |         //$location = curl_getinfo( self::$ch, CURLINFO_EFFECTIVE_URL); | ||||||
|  |         self::$info = curl_getinfo( self::$ch ); | ||||||
|  |         //print_r(self::$info); | ||||||
|  |         self::$status_code = self::$info['http_code']; | ||||||
|  |         if (self::$raw === false) | ||||||
|  |         { | ||||||
|  |             self::$error = 'Curl error: ' . curl_error( self::$ch ); | ||||||
|  |             //trigger_error(self::$error, E_USER_WARNING); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 关闭句柄 | ||||||
|  |         curl_close( self::$ch ); | ||||||
|  |  | ||||||
|  |         // 请求成功之后才把URL存起来 | ||||||
|  |         list($header, $text) = self::split_header_body(); | ||||||
|  |         self::$history = self::get_history($header); | ||||||
|  |         self::$headers = self::get_response_headers($header); | ||||||
|  |         self::get_response_cookies($header, $domain); | ||||||
|  |         //$data = substr($data, 10); | ||||||
|  |         //$data = gzinflate($data); | ||||||
|  |         return $text; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function get_history($header) | ||||||
|  |     { | ||||||
|  |         $status_code = 0; | ||||||
|  |         $lines = explode("\n", $header); | ||||||
|  |         foreach ($lines as $line)  | ||||||
|  |         { | ||||||
|  |             $line = trim($line); | ||||||
|  |             if (preg_match("#^HTTP/.*? (\d+) Found#", $line, $out)) | ||||||
|  |             { | ||||||
|  |                 $status_code = empty($out[1]) ? 0 : intval($out[1]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return $status_code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 获取 mimetype | ||||||
|  |     public static function get_mimetype($filepath) | ||||||
|  |     { | ||||||
|  |         $fp  = finfo_open(FILEINFO_MIME); | ||||||
|  |         $mime = finfo_file($fp, $filepath); | ||||||
|  |         finfo_close($fp); | ||||||
|  |         $arr  = explode(';', $mime); | ||||||
|  |         $type = empty($arr[0]) ? '' : $arr[0]; | ||||||
|  |         return $type; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 拼凑文件和表单 | ||||||
|  |      * 占时没有用到 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $post_fields | ||||||
|  |      * @param mixed $file_fields | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2017-08-03 18:06 | ||||||
|  |      */ | ||||||
|  |     public static function get_postfile_form($post_fields, $file_fields) | ||||||
|  |     { | ||||||
|  |         // 构造post数据 | ||||||
|  |         $data = ''; | ||||||
|  |         $delimiter = '-------------' . uniqid(); | ||||||
|  |         // 表单数据 | ||||||
|  |         foreach ($post_fields as $name => $content)  | ||||||
|  |         { | ||||||
|  |             $data .= '--'.$delimiter."\r\n"; | ||||||
|  |             $data .= 'Content-Disposition: form-data; name = "'.$name.'"'; | ||||||
|  |             $data .= "\r\n\r\n"; | ||||||
|  |             $data .= $content; | ||||||
|  |             $data .= "\r\n"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         foreach ($file_fields as $input_name => $file)  | ||||||
|  |         { | ||||||
|  |             $data .= '--'.$delimiter."\r\n"; | ||||||
|  |             $data .= 'Content-Disposition: form-data; name = "'.$input_name.'";'. | ||||||
|  |                 ' filename="'.$file['filename'].'"'."\r\n"; | ||||||
|  |             $data .= "Content-Type: {$file['type']}\r\n"; | ||||||
|  |             $data .= "\r\n"; | ||||||
|  |             $data .= $file['content']; | ||||||
|  |             $data .= "\r\n"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 结束符 | ||||||
|  |         $data .= '--'.$delimiter."--\r\n"; | ||||||
|  |  | ||||||
|  |         //return array( | ||||||
|  |             //CURLOPT_HTTPHEADER => array( | ||||||
|  |                 //'Content-Type:multipart/form-data;boundary=' . $delimiter, | ||||||
|  |                 //'Content-Length:' . strlen($data) | ||||||
|  |             //), | ||||||
|  |             //CURLOPT_POST => true, | ||||||
|  |             //CURLOPT_POSTFIELDS => $data, | ||||||
|  |         //); | ||||||
|  |         return array($delimiter, $data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * html encoding transform | ||||||
|  |      * | ||||||
|  |      * @param string $html | ||||||
|  |      * @param string $in | ||||||
|  |      * @param string $out | ||||||
|  |      * @param string $content | ||||||
|  |      * @param string $mode | ||||||
|  |      *            auto|iconv|mb_convert_encoding | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     public static function encoding($html, $in = null, $out = null, $mode = 'auto') | ||||||
|  |     { | ||||||
|  |         $valid = array( | ||||||
|  |             'auto', | ||||||
|  |             'iconv', | ||||||
|  |             'mb_convert_encoding', | ||||||
|  |         ); | ||||||
|  |         if (isset(self::$output_encoding)) | ||||||
|  |         { | ||||||
|  |             $out = self::$output_encoding; | ||||||
|  |         } | ||||||
|  |         if ( ! isset($out)) | ||||||
|  |         { | ||||||
|  |             $out = 'UTF-8'; | ||||||
|  |         } | ||||||
|  |         if ( ! in_array($mode, $valid)) | ||||||
|  |         { | ||||||
|  |             throw new Exception('invalid mode, mode='.$mode); | ||||||
|  |         } | ||||||
|  |         $if = function_exists('mb_convert_encoding'); | ||||||
|  |         $if = $if && ($mode == 'auto' || $mode == 'mb_convert_encoding'); | ||||||
|  |         if (function_exists('iconv') && ($mode == 'auto' || $mode == 'iconv')) | ||||||
|  |         { | ||||||
|  |             $func = 'iconv'; | ||||||
|  |         } | ||||||
|  |         elseif ($if) | ||||||
|  |         { | ||||||
|  |             $func = 'mb_convert_encoding'; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             throw new Exception('charsetTrans failed, no function'); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $pattern = '/(<meta[^>]*?charset=([\"\']?))([a-z\d_\-]*)(\2[^>]*?>)/is'; | ||||||
|  |         if ( ! isset($in)) | ||||||
|  |         { | ||||||
|  |             $n = preg_match($pattern, $html, $in); | ||||||
|  |             if ($n > 0) | ||||||
|  |             { | ||||||
|  |                 $in = $in[3]; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 $in = null; | ||||||
|  |             } | ||||||
|  |             if (empty($in) and function_exists('mb_detect_encoding')) | ||||||
|  |             { | ||||||
|  |                 $in = mb_detect_encoding($html, array('UTF-8', 'GBK', 'GB2312', 'LATIN1', 'ASCII', 'BIG5', 'ISO-8859-1')); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (isset($in)) | ||||||
|  |         { | ||||||
|  |             if ($in == 'ISO-8859-1') | ||||||
|  |             { | ||||||
|  |                 $in = 'UTF-8'; | ||||||
|  |             } | ||||||
|  |             $old  = error_reporting(error_reporting() & ~E_NOTICE); | ||||||
|  |             $html = call_user_func($func, $in, $out.'//IGNORE', $html); | ||||||
|  |             error_reporting($old); | ||||||
|  |             $html = preg_replace($pattern, "\\1$out\\4", $html, 1); | ||||||
|  |         } | ||||||
|  |         return $html; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										588
									
								
								vendor/owner888/phpspider/core/selector.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										588
									
								
								vendor/owner888/phpspider/core/selector.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,588 @@ | |||||||
|  | <?php | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | PHPSpider [ A PHP Framework For Crawler ] | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Copyright (c) 2006-2014 https://doc.phpspider.org All rights reserved. | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Author: Seatle Yang <seatle@foxmail.com> | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | //---------------------------------- | ||||||
|  | // PHPSpider选择器类文件 | ||||||
|  | //---------------------------------- | ||||||
|  |  | ||||||
|  | namespace phpspider\core; | ||||||
|  |  | ||||||
|  | use phpspider\library\phpquery; | ||||||
|  | use DOMDocument; | ||||||
|  | use DOMXpath; | ||||||
|  | use Exception; | ||||||
|  |  | ||||||
|  | class selector | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * 版本号 | ||||||
|  |      * @var string | ||||||
|  |      */ | ||||||
|  |     const VERSION = '1.0.2'; | ||||||
|  |     public static $dom = null; | ||||||
|  |     public static $dom_auth = ''; | ||||||
|  |     public static $xpath = null; | ||||||
|  |     public static $error = null; | ||||||
|  |  | ||||||
|  |     public static function select($html, $selector, $selector_type = 'xpath') | ||||||
|  |     { | ||||||
|  |         if (empty($html) || empty($selector))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $selector_type = strtolower($selector_type); | ||||||
|  |         if ($selector_type == 'xpath')  | ||||||
|  |         { | ||||||
|  |             return self::_xpath_select($html, $selector); | ||||||
|  |         } | ||||||
|  |         elseif ($selector_type == 'regex')  | ||||||
|  |         { | ||||||
|  |             return self::_regex_select($html, $selector); | ||||||
|  |         } | ||||||
|  |         elseif ($selector_type == 'css')  | ||||||
|  |         { | ||||||
|  |             return self::_css_select($html, $selector); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function remove($html, $selector, $selector_type = 'xpath') | ||||||
|  |     { | ||||||
|  |         if (empty($html) || empty($selector))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $remove_html = ""; | ||||||
|  |         $selector_type = strtolower($selector_type); | ||||||
|  |         if ($selector_type == 'xpath')  | ||||||
|  |         { | ||||||
|  |             $remove_html = self::_xpath_select($html, $selector, true); | ||||||
|  |         } | ||||||
|  |         elseif ($selector_type == 'regex')  | ||||||
|  |         { | ||||||
|  |             $remove_html = self::_regex_select($html, $selector, true); | ||||||
|  |         } | ||||||
|  |         elseif ($selector_type == 'css')  | ||||||
|  |         { | ||||||
|  |             $remove_html =  self::_css_select($html, $selector, true); | ||||||
|  |         } | ||||||
|  |         $html = str_replace($remove_html, "", $html); | ||||||
|  |         return $html; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * xpath选择器 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $html | ||||||
|  |      * @param mixed $selector | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-10-26 12:53 | ||||||
|  |      */ | ||||||
|  |     private static function _xpath_select($html, $selector, $remove = false) | ||||||
|  |     { | ||||||
|  |         if (!is_object(self::$dom)) | ||||||
|  |         { | ||||||
|  |             self::$dom = new DOMDocument(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 如果加载的不是之前的HTML内容,替换一下验证标识 | ||||||
|  |         if (self::$dom_auth != md5($html))  | ||||||
|  |         { | ||||||
|  |             self::$dom_auth = md5($html); | ||||||
|  |             @self::$dom->loadHTML('<?xml encoding="UTF-8">'.$html); | ||||||
|  |             self::$xpath = new DOMXpath(self::$dom); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         //libxml_use_internal_errors(true); | ||||||
|  |         //self::$dom->loadHTML('<?xml encoding="UTF-8">'.$html); | ||||||
|  |         //$errors = libxml_get_errors(); | ||||||
|  |         //if (!empty($errors))  | ||||||
|  |         //{ | ||||||
|  |             //print_r($errors); | ||||||
|  |             //exit; | ||||||
|  |         //} | ||||||
|  |  | ||||||
|  |         $elements = @self::$xpath->query($selector); | ||||||
|  |         if ($elements === false) | ||||||
|  |         { | ||||||
|  |             self::$error = "the selector in the xpath(\"{$selector}\") syntax errors"; | ||||||
|  |             // 不应该返回false,因为isset(false)为true,更不能通过 !$values 去判断,因为!0为true,所以这里只能返回null | ||||||
|  |             //return false; | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $result = array(); | ||||||
|  |         if (!is_null($elements))  | ||||||
|  |         { | ||||||
|  |             foreach ($elements as $element)  | ||||||
|  |             { | ||||||
|  |                 // 如果是删除操作,取一整块代码 | ||||||
|  |                 if ($remove)  | ||||||
|  |                 { | ||||||
|  |                     $content = self::$dom->saveXml($element); | ||||||
|  |                 } | ||||||
|  |                 else  | ||||||
|  |                 { | ||||||
|  |                     $nodeName = $element->nodeName; | ||||||
|  |                     $nodeType = $element->nodeType;     // 1.Element 2.Attribute 3.Text | ||||||
|  |                     //$nodeAttr = $element->getAttribute('src'); | ||||||
|  |                     //$nodes = util::node_to_array(self::$dom, $element); | ||||||
|  |                     //echo $nodes['@src']."\n"; | ||||||
|  |                     // 如果是img标签,直接取src值 | ||||||
|  |                     if ($nodeType == 1 && in_array($nodeName, array('img')))  | ||||||
|  |                     { | ||||||
|  |                         $content = $element->getAttribute('src'); | ||||||
|  |                     } | ||||||
|  |                     // 如果是标签属性,直接取节点值 | ||||||
|  |                     elseif ($nodeType == 2 || $nodeType == 3 || $nodeType == 4)  | ||||||
|  |                     { | ||||||
|  |                         $content = $element->nodeValue; | ||||||
|  |                     } | ||||||
|  |                     else  | ||||||
|  |                     { | ||||||
|  |                         // 保留nodeValue里的html符号,给children二次提取 | ||||||
|  |                         $content = self::$dom->saveXml($element); | ||||||
|  |                         //$content = trim(self::$dom->saveHtml($element)); | ||||||
|  |                         $content = preg_replace(array("#^<{$nodeName}.*>#isU","#</{$nodeName}>$#isU"), array('', ''), $content); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 $result[] = $content; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (empty($result))  | ||||||
|  |         { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         // 如果只有一个元素就直接返回string,否则返回数组 | ||||||
|  |         return count($result) > 1 ? $result : $result[0]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * css选择器 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $html | ||||||
|  |      * @param mixed $selector | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-10-26 12:53 | ||||||
|  |      */ | ||||||
|  |     private static function _css_select($html, $selector, $remove = false) | ||||||
|  |     { | ||||||
|  |         $selector = self::css_to_xpath($selector); | ||||||
|  |         //echo $selector."\n"; | ||||||
|  |         //exit("\n"); | ||||||
|  |         return self::_xpath_select($html, $selector, $remove); | ||||||
|  |         // 如果加载的不是之前的HTML内容,替换一下验证标识 | ||||||
|  |         //if (self::$dom_auth['css'] != md5($html))  | ||||||
|  |         //{ | ||||||
|  |             //self::$dom_auth['css'] = md5($html); | ||||||
|  |             //phpQuery::loadDocumentHTML($html);  | ||||||
|  |         //} | ||||||
|  |         //if ($remove)  | ||||||
|  |         //{ | ||||||
|  |             //return phpQuery::pq($selector)->remove();  | ||||||
|  |         //} | ||||||
|  |         //else  | ||||||
|  |         //{ | ||||||
|  |             //return phpQuery::pq($selector)->html();  | ||||||
|  |         //} | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 正则选择器 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $html | ||||||
|  |      * @param mixed $selector | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-10-26 12:53 | ||||||
|  |      */ | ||||||
|  |     private static function _regex_select($html, $selector, $remove = false) | ||||||
|  |     { | ||||||
|  |         if(@preg_match_all($selector, $html, $out) === false) | ||||||
|  |         { | ||||||
|  |             self::$error = "the selector in the regex(\"{$selector}\") syntax errors"; | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         $count = count($out); | ||||||
|  |         $result = array(); | ||||||
|  |         // 一个都没有匹配到 | ||||||
|  |         if ($count == 0)  | ||||||
|  |         { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         // 只匹配一个,就是只有一个 () | ||||||
|  |         elseif ($count == 2)  | ||||||
|  |         { | ||||||
|  |             // 删除的话取匹配到的所有内容 | ||||||
|  |             if ($remove)  | ||||||
|  |             { | ||||||
|  |                 $result = $out[0]; | ||||||
|  |             } | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 $result = $out[1]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             for ($i = 1; $i < $count; $i++)  | ||||||
|  |             { | ||||||
|  |                 // 如果只有一个元素,就直接返回好了 | ||||||
|  |                 $result[] = count($out[$i]) > 1 ? $out[$i] : $out[$i][0]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (empty($result))  | ||||||
|  |         { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         return count($result) > 1 ? $result : $result[0]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function find_all($html, $selector) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     public static function css_to_xpath($selectors)  | ||||||
|  |     { | ||||||
|  | 		$queries = self::parse_selector($selectors); | ||||||
|  |         $delimiter_before = false; | ||||||
|  |         $xquery = ''; | ||||||
|  |         foreach($queries as $s)  | ||||||
|  |         { | ||||||
|  |             // TAG | ||||||
|  |             $is_tag = preg_match('@^[\w|\||-]+$@', $s) || $s == '*'; | ||||||
|  |             if ($is_tag)  | ||||||
|  |             { | ||||||
|  |                 $xquery .= $s; | ||||||
|  |             }  | ||||||
|  |             // ID | ||||||
|  |             else if ($s[0] == '#')  | ||||||
|  |             { | ||||||
|  |                 if ($delimiter_before) | ||||||
|  |                 { | ||||||
|  |                     $xquery .= '*'; | ||||||
|  |                 } | ||||||
|  |                 // ID用精确查询 | ||||||
|  |                 $xquery .= "[@id='".substr($s, 1)."']"; | ||||||
|  |             } | ||||||
|  |             // CLASSES | ||||||
|  |             else if ($s[0] == '.')  | ||||||
|  |             { | ||||||
|  |                 if ($delimiter_before) | ||||||
|  |                 { | ||||||
|  |                     $xquery .= '*'; | ||||||
|  |                 } | ||||||
|  |                 // CLASS用模糊查询 | ||||||
|  |                 $xquery .= "[contains(@class,'".substr($s, 1)."')]"; | ||||||
|  |             } | ||||||
|  |             // ATTRIBUTES | ||||||
|  |             else if ($s[0] == '[')  | ||||||
|  |             { | ||||||
|  |                 if ($delimiter_before) | ||||||
|  |                 { | ||||||
|  |                     $xquery .= '*'; | ||||||
|  |                 } | ||||||
|  |                 // strip side brackets | ||||||
|  |                 $attr = trim($s, ']['); | ||||||
|  |                 // attr with specifed value | ||||||
|  |                 if (mb_strpos($s, '='))  | ||||||
|  |                 { | ||||||
|  |                     $value = null; | ||||||
|  |                     list($attr, $value) = explode('=', $attr); | ||||||
|  |                     $value = trim($value, "'\""); | ||||||
|  |                     if (self::is_regexp($attr))  | ||||||
|  |                     { | ||||||
|  |                         // cut regexp character | ||||||
|  |                         $attr = substr($attr, 0, -1); | ||||||
|  |                         $xquery .= "[@{$attr}]"; | ||||||
|  |                     }  | ||||||
|  |                     else  | ||||||
|  |                     { | ||||||
|  |                         $xquery .= "[@{$attr}='{$value}']"; | ||||||
|  |                     } | ||||||
|  |                 }  | ||||||
|  |                 // attr without specified value | ||||||
|  |                 else  | ||||||
|  |                 { | ||||||
|  |                     $xquery .= "[@{$attr}]"; | ||||||
|  |                 } | ||||||
|  |             }  | ||||||
|  |             // ~ General Sibling Selector | ||||||
|  |             else if ($s[0] == '~') | ||||||
|  |             { | ||||||
|  |             } | ||||||
|  |             // + Adjacent sibling selectors | ||||||
|  |             else if ($s[0] == '+')  | ||||||
|  |             { | ||||||
|  |             }  | ||||||
|  |             // PSEUDO CLASSES | ||||||
|  |             else if ($s[0] == ':')  | ||||||
|  |             { | ||||||
|  |             } | ||||||
|  |             // DIRECT DESCENDANDS | ||||||
|  |             else if ($s == '>')  | ||||||
|  |             { | ||||||
|  |                 $xquery .= '/'; | ||||||
|  |                 $delimiter_before = 2; | ||||||
|  |             }  | ||||||
|  |             // ALL DESCENDANDS | ||||||
|  |             else if ($s == ' ')  | ||||||
|  |             { | ||||||
|  |                 $xquery .= '//'; | ||||||
|  |                 $delimiter_before = 2; | ||||||
|  |             }  | ||||||
|  |             // ERRORS | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 exit("Unrecognized token '$s'"); | ||||||
|  |             } | ||||||
|  |             $delimiter_before = $delimiter_before === 2; | ||||||
|  |         } | ||||||
|  |         return $xquery; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @access private | ||||||
|  | 	 */ | ||||||
|  |     public static function parse_selector($query)  | ||||||
|  |     { | ||||||
|  |         $query = trim( preg_replace( '@\s+@', ' ', preg_replace('@\s*(>|\\+|~)\s*@', '\\1', $query) ) ); | ||||||
|  |         $queries = array(); | ||||||
|  |         if ( !$query ) | ||||||
|  |         { | ||||||
|  |             return $queries; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $special_chars = array('>',' '); | ||||||
|  |         $special_chars_mapping = array(); | ||||||
|  |         $strlen = mb_strlen($query); | ||||||
|  |         $class_chars = array('.', '-'); | ||||||
|  |         $pseudo_chars = array('-'); | ||||||
|  |         $tag_chars = array('*', '|', '-'); | ||||||
|  |         // split multibyte string | ||||||
|  |         // http://code.google.com/p/phpquery/issues/detail?id=76 | ||||||
|  |         $_query = array(); | ||||||
|  |         for ( $i=0; $i<$strlen; $i++ ) | ||||||
|  |         { | ||||||
|  |             $_query[] = mb_substr($query, $i, 1); | ||||||
|  |         } | ||||||
|  |         $query = $_query; | ||||||
|  |         // it works, but i dont like it... | ||||||
|  |         $i = 0; | ||||||
|  |         while( $i < $strlen )  | ||||||
|  |         { | ||||||
|  |             $c = $query[$i]; | ||||||
|  |             $tmp = ''; | ||||||
|  |             // TAG | ||||||
|  |             if ( self::is_char($c) || in_array($c, $tag_chars) )  | ||||||
|  |             { | ||||||
|  |                 while(isset($query[$i]) && (self::is_char($query[$i]) || in_array($query[$i], $tag_chars)))  | ||||||
|  |                 { | ||||||
|  |                     $tmp .= $query[$i]; | ||||||
|  |                     $i++; | ||||||
|  |                 } | ||||||
|  |                 $queries[] = $tmp; | ||||||
|  |             }  | ||||||
|  |             // IDs | ||||||
|  |             else if ( $c == '#' )  | ||||||
|  |             { | ||||||
|  |                 $i++; | ||||||
|  |                 while( isset($query[$i]) && (self::is_char($query[$i]) || $query[$i] == '-') )  | ||||||
|  |                 { | ||||||
|  |                     $tmp .= $query[$i]; | ||||||
|  |                     $i++; | ||||||
|  |                 } | ||||||
|  |                 $queries[] = '#'.$tmp; | ||||||
|  |             }  | ||||||
|  |             // SPECIAL CHARS | ||||||
|  |             else if ( in_array($c, $special_chars) )  | ||||||
|  |             { | ||||||
|  |                 $queries[] = $c; | ||||||
|  |                 $i++; | ||||||
|  |                 // MAPPED SPECIAL MULTICHARS | ||||||
|  |                 //			} else if ( $c.$query[$i+1] == '//') { | ||||||
|  |                 //				$return[] = ' '; | ||||||
|  |                 //				$i = $i+2; | ||||||
|  |             }  | ||||||
|  |             // MAPPED SPECIAL CHARS | ||||||
|  |             else if ( isset($special_chars_mapping[$c]))  | ||||||
|  |             { | ||||||
|  |                 $queries[] = $special_chars_mapping[$c]; | ||||||
|  |                 $i++; | ||||||
|  |             }  | ||||||
|  |             // COMMA | ||||||
|  |             else if ( $c == ',' )  | ||||||
|  |             { | ||||||
|  |                 $i++; | ||||||
|  |                 while( isset($query[$i]) && $query[$i] == ' ') | ||||||
|  |                 { | ||||||
|  |                     $i++; | ||||||
|  |                 } | ||||||
|  |             }  | ||||||
|  |             // CLASSES | ||||||
|  |             else if ($c == '.')  | ||||||
|  |             { | ||||||
|  |                 while( isset($query[$i]) && (self::is_char($query[$i]) || in_array($query[$i], $class_chars)))  | ||||||
|  |                 { | ||||||
|  |                     $tmp .= $query[$i]; | ||||||
|  |                     $i++; | ||||||
|  |                 } | ||||||
|  |                 $queries[] = $tmp; | ||||||
|  |             }  | ||||||
|  |             // ~ General Sibling Selector | ||||||
|  |             else if ($c == '~') | ||||||
|  |             { | ||||||
|  |                 $space_allowed = true; | ||||||
|  |                 $tmp .= $query[$i++]; | ||||||
|  |                 while( isset($query[$i]) | ||||||
|  |                     && (self::is_char($query[$i]) | ||||||
|  |                     || in_array($query[$i], $class_chars) | ||||||
|  |                     || $query[$i] == '*' | ||||||
|  |                     || ($query[$i] == ' ' && $space_allowed) | ||||||
|  |                 ))  | ||||||
|  |                 { | ||||||
|  |                     if ($query[$i] != ' ') | ||||||
|  |                     { | ||||||
|  |                         $space_allowed = false; | ||||||
|  |                     } | ||||||
|  |                     $tmp .= $query[$i]; | ||||||
|  |                     $i++; | ||||||
|  |                 } | ||||||
|  |                 $queries[] = $tmp; | ||||||
|  |             } | ||||||
|  |             // + Adjacent sibling selectors | ||||||
|  |             else if ($c == '+')  | ||||||
|  |             { | ||||||
|  |                 $space_allowed = true; | ||||||
|  |                 $tmp .= $query[$i++]; | ||||||
|  |                 while( isset($query[$i]) | ||||||
|  |                     && (self::is_char($query[$i]) | ||||||
|  |                     || in_array($query[$i], $class_chars) | ||||||
|  |                     || $query[$i] == '*' | ||||||
|  |                     || ($space_allowed && $query[$i] == ' ') | ||||||
|  |                 ))  | ||||||
|  |                 { | ||||||
|  |                     if ($query[$i] != ' ') | ||||||
|  |                         $space_allowed = false; | ||||||
|  |                     $tmp .= $query[$i]; | ||||||
|  |                     $i++; | ||||||
|  |                 } | ||||||
|  |                 $queries[] = $tmp; | ||||||
|  |             }  | ||||||
|  |             // ATTRS | ||||||
|  |             else if ($c == '[')  | ||||||
|  |             { | ||||||
|  |                 $stack = 1; | ||||||
|  |                 $tmp .= $c; | ||||||
|  |                 while( isset($query[++$i]))  | ||||||
|  |                 { | ||||||
|  |                     $tmp .= $query[$i]; | ||||||
|  |                     if ( $query[$i] == '[')  | ||||||
|  |                     { | ||||||
|  |                         $stack++; | ||||||
|  |                     }  | ||||||
|  |                     else if ( $query[$i] == ']') | ||||||
|  |                     { | ||||||
|  |                         $stack--; | ||||||
|  |                         if (! $stack ) | ||||||
|  |                         { | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 $queries[] = $tmp; | ||||||
|  |                 $i++; | ||||||
|  |             }  | ||||||
|  |             // PSEUDO CLASSES | ||||||
|  |             else if ($c == ':')  | ||||||
|  |             { | ||||||
|  |                 $stack = 1; | ||||||
|  |                 $tmp .= $query[$i++]; | ||||||
|  |                 while( isset($query[$i]) && (self::is_char($query[$i]) || in_array($query[$i], $pseudo_chars)))  | ||||||
|  |                 { | ||||||
|  |                     $tmp .= $query[$i]; | ||||||
|  |                     $i++; | ||||||
|  |                 } | ||||||
|  |                 // with arguments ? | ||||||
|  |                 if ( isset($query[$i]) && $query[$i] == '(')  | ||||||
|  |                 { | ||||||
|  |                     $tmp .= $query[$i]; | ||||||
|  |                     $stack = 1; | ||||||
|  |                     while( isset($query[++$i]))  | ||||||
|  |                     { | ||||||
|  |                         $tmp .= $query[$i]; | ||||||
|  |                         if ( $query[$i] == '(')  | ||||||
|  |                         { | ||||||
|  |                             $stack++; | ||||||
|  |                         }  | ||||||
|  |                         else if ( $query[$i] == ')') | ||||||
|  |                         { | ||||||
|  |                             $stack--; | ||||||
|  |                             if (! $stack ) | ||||||
|  |                             { | ||||||
|  |                                 break; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     $queries[] = $tmp; | ||||||
|  |                     $i++; | ||||||
|  |                 }  | ||||||
|  |                 else  | ||||||
|  |                 { | ||||||
|  |                     $queries[] = $tmp; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 $i++; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (isset($queries[0]))  | ||||||
|  |         { | ||||||
|  |             if (isset($queries[0][0]) && $queries[0][0] == ':') | ||||||
|  |             { | ||||||
|  |                 array_unshift($queries, '*'); | ||||||
|  |             } | ||||||
|  |             if ($queries[0] != '>') | ||||||
|  |             { | ||||||
|  |                 array_unshift($queries, ' '); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $queries; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function is_char($char) | ||||||
|  |     { | ||||||
|  |         return preg_match('@\w@', $char); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 模糊匹配 | ||||||
|  |      * ^ 前缀字符串 | ||||||
|  |      * * 包含字符串 | ||||||
|  |      * $ 后缀字符串 | ||||||
|  | 	 * @access private | ||||||
|  | 	 */ | ||||||
|  |     protected static function is_regexp($pattern)  | ||||||
|  |     { | ||||||
|  | 		return in_array( | ||||||
|  | 			$pattern[ mb_strlen($pattern)-1 ], | ||||||
|  | 			array('^','*','$') | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										936
									
								
								vendor/owner888/phpspider/core/util.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										936
									
								
								vendor/owner888/phpspider/core/util.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,936 @@ | |||||||
|  | <?php | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | PHPSpider [ A PHP Framework For Crawler ] | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Copyright (c) 2006-2014 https://doc.phpspider.org All rights reserved. | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Author: Seatle Yang <seatle@foxmail.com> | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | //---------------------------------- | ||||||
|  | // PHPSpider实用函数集合类文件 | ||||||
|  | //---------------------------------- | ||||||
|  |  | ||||||
|  | namespace phpspider\core; | ||||||
|  | // 引入PATH_DATA | ||||||
|  | require_once __DIR__ . '/constants.php'; | ||||||
|  |  | ||||||
|  | class util | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * 文件锁 | ||||||
|  |      * 如果没有锁,就加一把锁并且执行逻辑,然后删除锁 | ||||||
|  |      * if (!util::lock('statistics_offer')) | ||||||
|  |      * { | ||||||
|  |      *     util::lock('statistics_offer'); | ||||||
|  |      *     ... | ||||||
|  |      *     util::unlock('statistics_offer'); | ||||||
|  |      * } | ||||||
|  |      * 否则输出锁存在 | ||||||
|  |      * else | ||||||
|  |      * { | ||||||
|  |      *     echo "process has been locked\n"; | ||||||
|  |      * } | ||||||
|  |      *  | ||||||
|  |      * @param mixed $lock_name | ||||||
|  |      * @param int $lock_timeout | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-02-18 14:28 | ||||||
|  |      */ | ||||||
|  |     public static function lock($lock_name, $lock_timeout = 600) | ||||||
|  |     { | ||||||
|  |         $lock = util::get_file(PATH_DATA."/lock/{$lock_name}.lock"); | ||||||
|  |         if ($lock)  | ||||||
|  |         { | ||||||
|  |             $time = time() - $lock; | ||||||
|  |             // 还没到10分钟,说明进程还活着 | ||||||
|  |             if ($time < $lock_timeout)  | ||||||
|  |             { | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |             unlink(PATH_DATA."/lock/{$lock_name}.lock"); | ||||||
|  |         } | ||||||
|  |         util::put_file(PATH_DATA."/lock/{$lock_name}.lock", time()); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function unlock($lock_name) | ||||||
|  |     { | ||||||
|  |         unlink(PATH_DATA."/lock/{$lock_name}.lock"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function time2second($time, $is_log = true) | ||||||
|  |     { | ||||||
|  |         if(is_numeric($time))  | ||||||
|  |         { | ||||||
|  |             $value = array( | ||||||
|  |                 "years" => 0, "days" => 0, "hours" => 0, | ||||||
|  |                 "minutes" => 0, "seconds" => 0, | ||||||
|  |             ); | ||||||
|  |             if($time >= 31556926) | ||||||
|  |             { | ||||||
|  |                 $value["years"] = floor($time/31556926); | ||||||
|  |                 $time = ($time%31556926); | ||||||
|  |             } | ||||||
|  |             if($time >= 86400) | ||||||
|  |             { | ||||||
|  |                 $value["days"] = floor($time/86400); | ||||||
|  |                 $time = ($time%86400); | ||||||
|  |             } | ||||||
|  |             if($time >= 3600) | ||||||
|  |             { | ||||||
|  |                 $value["hours"] = floor($time/3600); | ||||||
|  |                 $time = ($time%3600); | ||||||
|  |             } | ||||||
|  |             if($time >= 60) | ||||||
|  |             { | ||||||
|  |                 $value["minutes"] = floor($time/60); | ||||||
|  |                 $time = ($time%60); | ||||||
|  |             } | ||||||
|  |             $value["seconds"] = floor($time); | ||||||
|  |             //return (array) $value; | ||||||
|  |             //$t = $value["years"] ."y ". $value["days"] ."d ". $value["hours"] ."h ". $value["minutes"] ."m ".$value["seconds"]."s"; | ||||||
|  |             if ($is_log)  | ||||||
|  |             { | ||||||
|  |                 $t = $value["days"] ."d ". $value["hours"] ."h ". $value["minutes"] ."m ".$value["seconds"]."s"; | ||||||
|  |             } | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 $t = $value["days"] ." days ". $value["hours"] ." hours ". $value["minutes"] ." minutes"; | ||||||
|  |             } | ||||||
|  |             return $t; | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function get_days($day_sta, $day_end = true, $range = 86400) | ||||||
|  |     { | ||||||
|  |         if ($day_end === true) $day_end = date('Y-m-d'); | ||||||
|  |  | ||||||
|  |         return array_map(function ($time) { | ||||||
|  |             return date('Y-m-d', $time); | ||||||
|  |         }, range(strtotime($day_sta), strtotime($day_end), $range)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取文件行数 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $filepath | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-03-31 21:54 | ||||||
|  |      */ | ||||||
|  |     public static function get_file_line($filepath) | ||||||
|  |     { | ||||||
|  |         $line = 0 ; | ||||||
|  |         $fp = fopen($filepath , 'r'); | ||||||
|  |         if (!$fp)  | ||||||
|  |         { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  |         //获取文件的一行内容,注意:需要php5才支持该函数; | ||||||
|  |         while( stream_get_line($fp,8192,"\n") ){ | ||||||
|  |             $line++; | ||||||
|  |         } | ||||||
|  |         fclose($fp);//关闭文件 | ||||||
|  |         return $line; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得表数 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $table_name     表名 | ||||||
|  |      * @param mixed $item_value     唯一索引 | ||||||
|  |      * @param int $table_num        表数量 | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2015-10-22 23:25 | ||||||
|  |      */ | ||||||
|  |     public static function get_table_num($item_value, $table_num = 100) | ||||||
|  |     { | ||||||
|  |         //sha1:返回一个40字符长度的16进制数字 | ||||||
|  |         $item_value = sha1(strtolower($item_value)); | ||||||
|  |         //base_convert:进制建转换,下面是把16进制转成10进制,方便做除法运算 | ||||||
|  |         //str_pad:把字符串填充为指定的长度,下面是在左边加0,表数量大于100就3位,否则2位 | ||||||
|  |         $step = $table_num > 100 ? 3 : 2; | ||||||
|  |         $item_value = str_pad(base_convert(substr($item_value, -2), 16, 10) % $table_num, $step, "0", STR_PAD_LEFT); | ||||||
|  |         return $item_value; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得表面 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $table_name     表名 | ||||||
|  |      * @param mixed $item_value     唯一索引 | ||||||
|  |      * @param int $table_num        表数量 | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2015-10-22 23:25 | ||||||
|  |      */ | ||||||
|  |     public static function get_table_name($table_name, $item_value, $table_num = 100) | ||||||
|  |     { | ||||||
|  |         //sha1:返回一个40字符长度的16进制数字 | ||||||
|  |         $item_value = sha1(strtolower($item_value)); | ||||||
|  |         //base_convert:进制建转换,下面是把16进制转成10进制,方便做除法运算 | ||||||
|  |         //str_pad:把字符串填充为指定的长度,下面是在左边加0,共3位 | ||||||
|  |         $step = $table_num > 100 ? 3 : 2; | ||||||
|  |         $item_value = str_pad(base_convert(substr($item_value, -2), 16, 10) % $table_num, $step, "0", STR_PAD_LEFT); | ||||||
|  |         return $table_name."_".$item_value; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 获得当前使用内存 | ||||||
|  |     public static function memory_get_usage() | ||||||
|  |     { | ||||||
|  |         $memory = memory_get_usage(); | ||||||
|  |         return self::format_bytes($memory); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     // 获得最高使用内存 | ||||||
|  |     public static function memory_get_peak_usage() | ||||||
|  |     { | ||||||
|  |         $memory = memory_get_peak_usage(); | ||||||
|  |         return self::format_bytes($memory); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     // 转换大小单位 | ||||||
|  |     public static function format_bytes($size) | ||||||
|  |     { | ||||||
|  |         $unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb'); | ||||||
|  |         return @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $unit[$i]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取数组大小 | ||||||
|  |      * | ||||||
|  |      * @param mixed $arr 数组 | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     public static function array_size($arr) | ||||||
|  |     { | ||||||
|  |         ob_start(); | ||||||
|  |         print_r($arr); | ||||||
|  |         $mem = ob_get_contents(); | ||||||
|  |         ob_end_clean(); | ||||||
|  |         $mem = preg_replace("/\n +/", "", $mem); | ||||||
|  |         $mem = strlen($mem); | ||||||
|  |         return self::format_bytes($mem); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * 数字随机数 | ||||||
|  |      *  | ||||||
|  |      * @param int $num | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-09-18 10:17 | ||||||
|  |      */ | ||||||
|  |     public static function rand_num($num = 7) | ||||||
|  |     { | ||||||
|  |         $rand = ""; | ||||||
|  |         for ($i = 0; $i < $num; $i ++) | ||||||
|  |         { | ||||||
|  |             $rand .= mt_rand(0, 9); | ||||||
|  |         } | ||||||
|  |         return $rand; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 字母数字混合随机数 | ||||||
|  |      *  | ||||||
|  |      * @param int $num | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-09-18 10:17 | ||||||
|  |      */ | ||||||
|  |     public static function rand_str($num = 10) | ||||||
|  |     { | ||||||
|  |         $chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; | ||||||
|  |         $string = ""; | ||||||
|  |         for ($i = 0; $i < $num; $i ++) | ||||||
|  |         { | ||||||
|  |             $string .= substr($chars, rand(0, strlen($chars)), 1); | ||||||
|  |         } | ||||||
|  |         return $string; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * 汉字转拼音 | ||||||
|  |      * | ||||||
|  |      * @param mixed $str 汉字 | ||||||
|  |      * @param int $ishead | ||||||
|  |      * @param int $isclose | ||||||
|  |      * @static | ||||||
|  |      * @access public | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     public static function pinyin($str, $ishead = 0, $isclose = 1) | ||||||
|  |     { | ||||||
|  |         // $str = iconv("utf-8", "gbk//ignore", $str); | ||||||
|  |         $str = mb_convert_encoding($str, "gbk", "utf-8"); | ||||||
|  |         global $pinyins; | ||||||
|  |         $restr = ''; | ||||||
|  |         $str = trim($str); | ||||||
|  |         $slen = strlen($str); | ||||||
|  |         if ($slen < 2) | ||||||
|  |         { | ||||||
|  |             return $str; | ||||||
|  |         } | ||||||
|  |         if (count($pinyins) == 0) | ||||||
|  |         { | ||||||
|  |             $fp = fopen(PATH_DATA . '/pinyin.dat', 'r'); | ||||||
|  |             while (!feof($fp)) | ||||||
|  |             { | ||||||
|  |                 $line = trim(fgets($fp)); | ||||||
|  |                 $pinyins[$line[0] . $line[1]] = substr($line, 3, strlen($line) - 3); | ||||||
|  |             } | ||||||
|  |             fclose($fp); | ||||||
|  |         } | ||||||
|  |         for ($i = 0; $i < $slen; $i ++) | ||||||
|  |         { | ||||||
|  |             if (ord($str[$i]) > 0x80) | ||||||
|  |             { | ||||||
|  |                 $c = $str[$i] . $str[$i + 1]; | ||||||
|  |                 $i ++; | ||||||
|  |                 if (isset($pinyins[$c])) | ||||||
|  |                 { | ||||||
|  |                     if ($ishead == 0) | ||||||
|  |                     { | ||||||
|  |                         $restr .= $pinyins[$c]; | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         $restr .= $pinyins[$c][0]; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     // $restr .= "_"; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else if (preg_match("/[a-z0-9]/i", $str[$i])) | ||||||
|  |             { | ||||||
|  |                 $restr .= $str[$i]; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 // $restr .= "_"; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if ($isclose == 0) | ||||||
|  |         { | ||||||
|  |             unset($pinyins); | ||||||
|  |         } | ||||||
|  |         return $restr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 生成字母前缀 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $s0 | ||||||
|  |      * @return char | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-09-18 10:17 | ||||||
|  |      */ | ||||||
|  |     public static function letter_first($s0) | ||||||
|  |     { | ||||||
|  |         $firstchar_ord = ord(strtoupper($s0{0})); | ||||||
|  |         if (($firstchar_ord >= 65 and $firstchar_ord <= 91) or ($firstchar_ord >= 48 and $firstchar_ord <= 57)) return $s0{0}; | ||||||
|  |         // $s = iconv("utf-8", "gbk//ignore", $s0); | ||||||
|  |         $s = mb_convert_encoding($s0, "gbk", "utf-8"); | ||||||
|  |         $asc = ord($s{0}) * 256 + ord($s{1}) - 65536; | ||||||
|  |         if ($asc >= -20319 and $asc <= -20284) return "A"; | ||||||
|  |         if ($asc >= -20283 and $asc <= -19776) return "B"; | ||||||
|  |         if ($asc >= -19775 and $asc <= -19219) return "C"; | ||||||
|  |         if ($asc >= -19218 and $asc <= -18711) return "D"; | ||||||
|  |         if ($asc >= -18710 and $asc <= -18527) return "E"; | ||||||
|  |         if ($asc >= -18526 and $asc <= -18240) return "F"; | ||||||
|  |         if ($asc >= -18239 and $asc <= -17923) return "G"; | ||||||
|  |         if ($asc >= -17922 and $asc <= -17418) return "H"; | ||||||
|  |         if ($asc >= -17417 and $asc <= -16475) return "J"; | ||||||
|  |         if ($asc >= -16474 and $asc <= -16213) return "K"; | ||||||
|  |         if ($asc >= -16212 and $asc <= -15641) return "L"; | ||||||
|  |         if ($asc >= -15640 and $asc <= -15166) return "M"; | ||||||
|  |         if ($asc >= -15165 and $asc <= -14923) return "N"; | ||||||
|  |         if ($asc >= -14922 and $asc <= -14915) return "O"; | ||||||
|  |         if ($asc >= -14914 and $asc <= -14631) return "P"; | ||||||
|  |         if ($asc >= -14630 and $asc <= -14150) return "Q"; | ||||||
|  |         if ($asc >= -14149 and $asc <= -14091) return "R"; | ||||||
|  |         if ($asc >= -14090 and $asc <= -13319) return "S"; | ||||||
|  |         if ($asc >= -13318 and $asc <= -12839) return "T"; | ||||||
|  |         if ($asc >= -12838 and $asc <= -12557) return "W"; | ||||||
|  |         if ($asc >= -12556 and $asc <= -11848) return "X"; | ||||||
|  |         if ($asc >= -11847 and $asc <= -11056) return "Y"; | ||||||
|  |         if ($asc >= -11055 and $asc <= -10247) return "Z"; | ||||||
|  |         return 0; // null | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * 获得某天前的时间戳 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $day | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-09-18 10:17 | ||||||
|  |      */ | ||||||
|  |     public static function getxtime($day) | ||||||
|  |     { | ||||||
|  |         $day = intval($day); | ||||||
|  |         return mktime(23, 59, 59, date("m"), date("d") - $day, date("y")); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 读文件 | ||||||
|  |      */ | ||||||
|  |     public static function get_file($url, $timeout = 10) | ||||||
|  |     { | ||||||
|  |         if (function_exists('curl_init')) | ||||||
|  |         { | ||||||
|  |             $ch = curl_init(); | ||||||
|  |             curl_setopt($ch, CURLOPT_URL, $url); | ||||||
|  |             curl_setopt($ch, CURLOPT_HEADER, 0); | ||||||
|  |             curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); | ||||||
|  |             curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | ||||||
|  |             curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); | ||||||
|  |             $content = curl_exec($ch); | ||||||
|  |             curl_close($ch); | ||||||
|  |             if ($content) return $content; | ||||||
|  |         } | ||||||
|  |         $ctx = stream_context_create(array('http' => array('timeout' => $timeout))); | ||||||
|  |         $content = @file_get_contents($url, 0, $ctx); | ||||||
|  |         if ($content) return $content; | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 写文件,如果文件目录不存在,则递归生成 | ||||||
|  |      */ | ||||||
|  |     public static function put_file($file, $content, $flag = 0) | ||||||
|  |     { | ||||||
|  |         $pathinfo = pathinfo($file); | ||||||
|  |         if (!empty($pathinfo['dirname'])) | ||||||
|  |         { | ||||||
|  |             if (file_exists($pathinfo['dirname']) === false) | ||||||
|  |             { | ||||||
|  |                 if (@mkdir($pathinfo['dirname'], 0777, true) === false) | ||||||
|  |                 { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if ($flag === FILE_APPEND) | ||||||
|  |         { | ||||||
|  |             // 多个php-fpm写一个文件的时候容易丢失,要加锁 | ||||||
|  |             //return @file_put_contents($file, $content, FILE_APPEND|LOCK_EX); | ||||||
|  |             return @file_put_contents($file, $content, FILE_APPEND); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             return @file_put_contents($file, $content, LOCK_EX); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 检查路径是否存在,不存在则递归生成路径 | ||||||
|  |      * | ||||||
|  |      * @param mixed $path 路径 | ||||||
|  |      * @static | ||||||
|  |      * @access public | ||||||
|  |      * @return bool or string | ||||||
|  |      */ | ||||||
|  |     public static function path_exists($path) | ||||||
|  |     { | ||||||
|  |         $pathinfo = pathinfo($path . '/tmp.txt'); | ||||||
|  |         if (!empty($pathinfo['dirname'])) | ||||||
|  |         { | ||||||
|  |             if (file_exists($pathinfo['dirname']) === false) | ||||||
|  |             { | ||||||
|  |                 if (mkdir($pathinfo['dirname'], 0777, true) === false) | ||||||
|  |                 { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return $path; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 递归删除目录 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $dir | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-09-18 10:17 | ||||||
|  |      */ | ||||||
|  |     public static function deldir($dir) | ||||||
|  |     { | ||||||
|  |         //先删除目录下的文件: | ||||||
|  |         $dh = opendir($dir); | ||||||
|  |         while ($file = readdir($dh))  | ||||||
|  |         { | ||||||
|  |             if($file!="." && $file!="..")  | ||||||
|  |             { | ||||||
|  |                 $fullpath = $dir."/".$file; | ||||||
|  |                 if(!is_dir($fullpath))  | ||||||
|  |                 { | ||||||
|  |                     unlink($fullpath); | ||||||
|  |                 }  | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     self::deldir($fullpath); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         closedir($dh); | ||||||
|  |         //删除当前文件夹: | ||||||
|  |         if(rmdir($dir))  | ||||||
|  |         { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 递归修改目录权限 | ||||||
|  |      * | ||||||
|  |      * @param mixed $path 目录 | ||||||
|  |      * @param mixed $filemode 权限 | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public static function chmodr($path, $filemode) | ||||||
|  |     { | ||||||
|  |         if (!is_dir($path)) | ||||||
|  |         { | ||||||
|  |             return @chmod($path, $filemode); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         $dh = opendir($path); | ||||||
|  |         while (($file = readdir($dh)) !== false) | ||||||
|  |         { | ||||||
|  |             if ($file != '.' && $file != '..') | ||||||
|  |             { | ||||||
|  |                 $fullpath = $path . '/' . $file; | ||||||
|  |                 if (is_link($fullpath)) | ||||||
|  |                 { | ||||||
|  |                     return FALSE; | ||||||
|  |                 } | ||||||
|  |                 elseif (!is_dir($fullpath) && !@chmod($fullpath, $filemode)) | ||||||
|  |                 { | ||||||
|  |                     return FALSE; | ||||||
|  |                 } | ||||||
|  |                 elseif (!self::chmodr($fullpath, $filemode)) | ||||||
|  |                 { | ||||||
|  |                     return FALSE; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         closedir($dh); | ||||||
|  |          | ||||||
|  |         if (@chmod($path, $filemode)) | ||||||
|  |         { | ||||||
|  |             return TRUE; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             return FALSE; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 数组格式化为CSV | ||||||
|  |      *  | ||||||
|  |      * @param mixed $data | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-07-29 11:32 | ||||||
|  |      */ | ||||||
|  |     public static function format_csv($data) | ||||||
|  |     { | ||||||
|  |         foreach ($data as $k=>$v)  | ||||||
|  |         { | ||||||
|  |             $v = str_replace(",", "", $v); | ||||||
|  |             $v = str_replace(",", "", $v); | ||||||
|  |             $data[$k] = $v; | ||||||
|  |         } | ||||||
|  |         return implode(",", $data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 判断是否为utf8字符串 | ||||||
|  |      * @parem $str | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public static function is_utf8($str) | ||||||
|  |     { | ||||||
|  |         if ($str === mb_convert_encoding(mb_convert_encoding($str, "UTF-32", "UTF-8"), "UTF-8", "UTF-32")) | ||||||
|  |         { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取文件编码 | ||||||
|  |      * @param $string | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     public static function get_encoding($string) | ||||||
|  |     { | ||||||
|  |         $encoding = mb_detect_encoding($string, array('UTF-8', 'GBK', 'GB2312', 'LATIN1', 'ASCII', 'BIG5')); | ||||||
|  |         return strtolower($encoding); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 转换数组值的编码格式 | ||||||
|  |      * @param  array $arr            | ||||||
|  |      * @param  string $toEncoding    | ||||||
|  |      * @param  string $fromEncoding  | ||||||
|  |      * @return array                 | ||||||
|  |      */ | ||||||
|  |     public static function array_iconv($arr, $from_encoding, $to_encoding) | ||||||
|  |     { | ||||||
|  |         eval('$arr = '.iconv($from_encoding, $to_encoding.'//IGNORE', var_export($arr,TRUE)).';'); | ||||||
|  |         return $arr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 从普通时间返回Linux时间截(strtotime中文处理版) | ||||||
|  |      * @parem string $dtime | ||||||
|  |      * @return int | ||||||
|  |      */ | ||||||
|  |     public static function cn_strtotime($dtime) | ||||||
|  |     { | ||||||
|  |         if (!preg_match("/[^0-9]/", $dtime)) | ||||||
|  |         { | ||||||
|  |             return $dtime; | ||||||
|  |         } | ||||||
|  |         $dtime = trim($dtime); | ||||||
|  |         $dt = Array(1970, 1, 1, 0, 0, 0); | ||||||
|  |         $dtime = preg_replace("/[\r\n\t]|日|秒/", " ", $dtime); | ||||||
|  |         $dtime = str_replace("年", "-", $dtime); | ||||||
|  |         $dtime = str_replace("月", "-", $dtime); | ||||||
|  |         $dtime = str_replace("时", ":", $dtime); | ||||||
|  |         $dtime = str_replace("分", ":", $dtime); | ||||||
|  |         $dtime = trim(preg_replace("/[ ]{1,}/", " ", $dtime)); | ||||||
|  |         $ds = explode(" ", $dtime); | ||||||
|  |         $ymd = explode("-", $ds[0]); | ||||||
|  |         if (!isset($ymd[1])) | ||||||
|  |         { | ||||||
|  |             $ymd = explode(".", $ds[0]); | ||||||
|  |         } | ||||||
|  |         if (isset($ymd[0])) | ||||||
|  |         { | ||||||
|  |             $dt[0] = $ymd[0]; | ||||||
|  |         } | ||||||
|  |         if (isset($ymd[1])) $dt[1] = $ymd[1]; | ||||||
|  |         if (isset($ymd[2])) $dt[2] = $ymd[2]; | ||||||
|  |         if (strlen($dt[0]) == 2) $dt[0] = '20' . $dt[0]; | ||||||
|  |         if (isset($ds[1])) | ||||||
|  |         { | ||||||
|  |             $hms = explode(":", $ds[1]); | ||||||
|  |             if (isset($hms[0])) $dt[3] = $hms[0]; | ||||||
|  |             if (isset($hms[1])) $dt[4] = $hms[1]; | ||||||
|  |             if (isset($hms[2])) $dt[5] = $hms[2]; | ||||||
|  |         } | ||||||
|  |         foreach ($dt as $k => $v) | ||||||
|  |         { | ||||||
|  |             $v = preg_replace("/^0{1,}/", '', trim($v)); | ||||||
|  |             if ($v == '') | ||||||
|  |             { | ||||||
|  |                 $dt[$k] = 0; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         $mt = mktime($dt[3], $dt[4], $dt[5], $dt[1], $dt[2], $dt[0]); | ||||||
|  |         if (!empty($mt)) | ||||||
|  |         { | ||||||
|  |             return $mt; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             return strtotime($dtime); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function cn_substr($string, $length = 80, $etc = '...', $count_words = true) | ||||||
|  |     { | ||||||
|  |         mb_internal_encoding("UTF-8"); | ||||||
|  |         if ($length == 0) return ''; | ||||||
|  |         if (strlen($string) <= $length) return $string; | ||||||
|  |         preg_match_all("/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/", $string, $info); | ||||||
|  |         if ($count_words) | ||||||
|  |         { | ||||||
|  |             $j = 0; | ||||||
|  |             $wordscut = ""; | ||||||
|  |             for ($i = 0; $i < count($info[0]); $i ++) | ||||||
|  |             { | ||||||
|  |                 $wordscut .= $info[0][$i]; | ||||||
|  |                 if (ord($info[0][$i]) >= 128) | ||||||
|  |                 { | ||||||
|  |                     $j = $j + 2; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     $j = $j + 1; | ||||||
|  |                 } | ||||||
|  |                 if ($j >= $length) | ||||||
|  |                 { | ||||||
|  |                     return $wordscut . $etc; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return join('', $info[0]); | ||||||
|  |         } | ||||||
|  |         return join("", array_slice($info[0], 0, $length)) . $etc; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取文件后缀名 | ||||||
|  |      * | ||||||
|  |      * @param mixed $file_name 文件名 | ||||||
|  |      * @static | ||||||
|  |      * | ||||||
|  |      * @access public | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     public static function get_extension($file_name) | ||||||
|  |     { | ||||||
|  |         $ext = explode('.', $file_name); | ||||||
|  |         $ext = array_pop($ext); | ||||||
|  |         return strtolower($ext); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 获取 Url 跳转后的真实地址 | ||||||
|  |     public static function getrealurl($url) | ||||||
|  |     { | ||||||
|  |         if (empty($url)) | ||||||
|  |         { | ||||||
|  |             return $url; | ||||||
|  |         } | ||||||
|  |         $header = get_headers($url, 1); | ||||||
|  |         if (empty($header[0]) || empty($header[1])) | ||||||
|  |         { | ||||||
|  |             return $url; | ||||||
|  |         } | ||||||
|  |         if (strpos($header[0], '301') || strpos($header[0], '302')) | ||||||
|  |         { | ||||||
|  |             if (empty($header['Location'])) | ||||||
|  |             { | ||||||
|  |                 return $url; | ||||||
|  |             } | ||||||
|  |             if (is_array($header['Location'])) | ||||||
|  |             { | ||||||
|  |                 return $header['Location'][count($header['Location']) - 1]; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 return $header['Location']; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             return $url; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     // 解压服务器用 Content-Encoding:gzip 压缩过的数据 | ||||||
|  |     public static function gzdecode($data) | ||||||
|  |     { | ||||||
|  |         $flags = ord(substr($data, 3, 1)); | ||||||
|  |         $headerlen = 10; | ||||||
|  |         $extralen = 0; | ||||||
|  |         $filenamelen = 0; | ||||||
|  |         if ($flags & 4) | ||||||
|  |         { | ||||||
|  |             $extralen = unpack('v', substr($data, 10, 2)); | ||||||
|  |             $extralen = $extralen[1]; | ||||||
|  |             $headerlen += 2 + $extralen; | ||||||
|  |         } | ||||||
|  |         if ($flags & 8)         // Filename | ||||||
|  |         $headerlen = strpos($data, chr(0), $headerlen) + 1; | ||||||
|  |         if ($flags & 16)         // Comment | ||||||
|  |         $headerlen = strpos($data, chr(0), $headerlen) + 1; | ||||||
|  |         if ($flags & 2)         // CRC at end of file | ||||||
|  |         $headerlen += 2; | ||||||
|  |         $unpacked = @gzinflate(substr($data, $headerlen)); | ||||||
|  |         if ($unpacked === FALSE) $unpacked = $data; | ||||||
|  |         return $unpacked; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 数字金额转换为中文 | ||||||
|  |      * @param string|integer|float $num 目标数字 | ||||||
|  |      * @param boolean $sim 使用小写(默认) | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     public static function number2chinese($num, $sim = FALSE) | ||||||
|  |     { | ||||||
|  |         if (!is_numeric($num)) return '含有非数字非小数点字符!'; | ||||||
|  |         $char = $sim ? array('零', '一', '二', '三', '四', '五', '六', '七', '八', '九') : array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'); | ||||||
|  |         $unit = $sim ? array('', '十', '百', '千', '', '万', '亿', '兆') : array('', '拾', '佰', '仟', '', '萬', '億', '兆'); | ||||||
|  |         $retval = ''; | ||||||
|  |          | ||||||
|  |         $num = sprintf("%01.2f", $num); | ||||||
|  |          | ||||||
|  |         list ($num, $dec) = explode('.', $num); | ||||||
|  |          | ||||||
|  |         // 小数部分 | ||||||
|  |         if ($dec['0'] > 0) | ||||||
|  |         { | ||||||
|  |             $retval .= "{$char[$dec['0']]}角"; | ||||||
|  |         } | ||||||
|  |         if ($dec['1'] > 0) | ||||||
|  |         { | ||||||
|  |             $retval .= "{$char[$dec['1']]}分"; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // 整数部分 | ||||||
|  |         if ($num > 0) | ||||||
|  |         { | ||||||
|  |             $retval = "元" . $retval; | ||||||
|  |             $f = 1; | ||||||
|  |             $str = strrev(intval($num)); | ||||||
|  |             for ($i = 0, $c = strlen($str); $i < $c; $i ++) | ||||||
|  |             { | ||||||
|  |                 if ($str[$i] > 0) | ||||||
|  |                 { | ||||||
|  |                     $f = 0; | ||||||
|  |                 } | ||||||
|  |                 if ($f == 1 && $str[$i] == 0) | ||||||
|  |                 { | ||||||
|  |                     $out[$i] = ""; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     $out[$i] = $char[$str[$i]]; | ||||||
|  |                 } | ||||||
|  |                 $out[$i] .= $str[$i] != '0' ? $unit[$i % 4] : ''; | ||||||
|  |                 if ($i > 1 and $str[$i] + $str[$i - 1] == 0) | ||||||
|  |                 { | ||||||
|  |                     $out[$i] = ''; | ||||||
|  |                 } | ||||||
|  |                 if ($i % 4 == 0) | ||||||
|  |                 { | ||||||
|  |                     $out[$i] .= $unit[4 + floor($i / 4)]; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             $retval = join('', array_reverse($out)) . $retval; | ||||||
|  |         } | ||||||
|  |         return $retval; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public static function colorize($str, $status = "info")  | ||||||
|  |     { | ||||||
|  |         $out = ""; | ||||||
|  |         switch ($status)  | ||||||
|  |         { | ||||||
|  |             case 'succ': | ||||||
|  |                 $out = "\033[32m";    // Blue | ||||||
|  |                 break; | ||||||
|  |             case "error": | ||||||
|  |                 $out = "\033[31m";    // Red | ||||||
|  |                 break; | ||||||
|  |             case "warn": | ||||||
|  |                 $out = "\033[33m";    // Yellow | ||||||
|  |                 break; | ||||||
|  |             case "note": | ||||||
|  |                 $out = "\033[34m";    // Green | ||||||
|  |                 break; | ||||||
|  |             case "debug": | ||||||
|  |                 $out = "\033[36m";    // Green | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 $out = "\033[0m";     // info | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |         return $out.$str."\033[0m"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function node_to_array($dom, $node)  | ||||||
|  |     { | ||||||
|  |         if(!is_a( $dom, 'DOMDocument' ) || !is_a( $node, 'DOMNode' ))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $array = array();  | ||||||
|  |         // Discard empty nodes | ||||||
|  |         $localName = trim( $node->localName ); | ||||||
|  |         if( empty($localName))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if( XML_TEXT_NODE == $node->nodeType )  | ||||||
|  |         { | ||||||
|  |             return $node->nodeValue; | ||||||
|  |         } | ||||||
|  |         foreach ($node->attributes as $attr)  | ||||||
|  |         {  | ||||||
|  |             $array['@'.$attr->localName] = $attr->nodeValue; | ||||||
|  |         }  | ||||||
|  |         foreach ($node->childNodes as $childNode)  | ||||||
|  |         {  | ||||||
|  |             if ( (isset($childNode->childNodes->length) && 1 == $childNode->childNodes->length) &&  | ||||||
|  |                  XML_TEXT_NODE == $childNode->firstChild->nodeType ) | ||||||
|  |             {  | ||||||
|  |                 $array[$childNode->localName] = $childNode->nodeValue;  | ||||||
|  |             }   | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 if( false !== ($a = self::node_to_array( $dom, $childNode)))  | ||||||
|  |                 { | ||||||
|  |                     $array[$childNode->localName] = $a; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return $array;  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function is_win() | ||||||
|  |     { | ||||||
|  |         return strtoupper(substr(PHP_OS,0,3))==="WIN"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 和 http_build_query 相反,分解出参数 | ||||||
|  |      *  | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-05-16 17:29 | ||||||
|  |      */ | ||||||
|  |     public static function http_split_query($query, $is_query = false) | ||||||
|  |     { | ||||||
|  |         if (!$is_query)  | ||||||
|  |         { | ||||||
|  |             $parse_arr = parse_url($query); | ||||||
|  |             if (empty($parse_arr['query']))  | ||||||
|  |             { | ||||||
|  |                 return array(); | ||||||
|  |             } | ||||||
|  |             $query = $parse_arr['query']; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $query_arr = explode("&", $query); | ||||||
|  |         $params = array(); | ||||||
|  |         foreach ($query_arr as $val)  | ||||||
|  |         { | ||||||
|  |             $arr = explode("=", $val); | ||||||
|  |             $params[$arr[0]] = $arr[1]; | ||||||
|  |         } | ||||||
|  |         return $params; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										421
									
								
								vendor/owner888/phpspider/core/worker.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								vendor/owner888/phpspider/core/worker.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,421 @@ | |||||||
|  | <?php | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | PHPSpider [ A PHP Framework For Crawler ] | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Copyright (c) 2006-2014 https://doc.phpspider.org All rights reserved. | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  | // | Author: Seatle Yang <seatle@foxmail.com> | ||||||
|  | // +---------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | //---------------------------------- | ||||||
|  | // Worker多进程操作类 | ||||||
|  | //---------------------------------- | ||||||
|  |  | ||||||
|  | class worker | ||||||
|  | { | ||||||
|  |     // worker进程数 | ||||||
|  |     public $count = 0; | ||||||
|  |     // worker id,worker进程从1开始,0被master进程所使用 | ||||||
|  |     public $worker_id = 0; | ||||||
|  |     // worker 进程ID | ||||||
|  |     public $worker_pid = 0; | ||||||
|  |     // 进程用户 | ||||||
|  |     public $user = ''; | ||||||
|  |     // 进程名 | ||||||
|  |     public $title = ''; | ||||||
|  |     // 每个进程是否只运行一次 | ||||||
|  |     public $run_once = true; | ||||||
|  |     // 是否输出日志 | ||||||
|  |     public $log_show = false; | ||||||
|  |     // master进程启动回调 | ||||||
|  |     public $on_start = false; | ||||||
|  |     // master进程停止回调 | ||||||
|  |     public $on_stop = false; | ||||||
|  |     // worker进程启动回调 | ||||||
|  |     public $on_worker_start = false; | ||||||
|  |     // worker进程停止回调 | ||||||
|  |     public $on_worker_stop = false; | ||||||
|  |     // master进程ID | ||||||
|  |     protected static $_master_pid = 0; | ||||||
|  |     // worker进程ID | ||||||
|  |     protected static $_worker_pids = array(); | ||||||
|  |     // master、worker进程启动时间 | ||||||
|  |     public $time_start = 0; | ||||||
|  |     // master、worker进程运行状态 [starting|running|shutdown|reload] | ||||||
|  |     protected static $_status = "starting"; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     public function __construct() | ||||||
|  |     { | ||||||
|  |         self::$_master_pid = posix_getpid(); | ||||||
|  |         // 产生时钟云,添加后父进程才可以收到信号 | ||||||
|  |         declare(ticks = 1); | ||||||
|  |         $this->install_signal(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 安装信号处理函数 | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     protected function install_signal() | ||||||
|  |     { | ||||||
|  |         // stop | ||||||
|  |         pcntl_signal(SIGINT,  array($this, 'signal_handler'), false); | ||||||
|  |         // reload | ||||||
|  |         pcntl_signal(SIGUSR1, array($this, 'signal_handler'), false); | ||||||
|  |         // status | ||||||
|  |         pcntl_signal(SIGUSR2, array($this, 'signal_handler'), false); | ||||||
|  |         // ignore | ||||||
|  |         pcntl_signal(SIGPIPE, SIG_IGN, false); | ||||||
|  |         // install signal handler for dead kids | ||||||
|  |         // pcntl_signal(SIGCHLD, array($this, 'signal_handler')); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 卸载信号处理函数 | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     protected function uninstall_signal() | ||||||
|  |     { | ||||||
|  |         // uninstall stop signal handler | ||||||
|  |         pcntl_signal(SIGINT,  SIG_IGN, false); | ||||||
|  |         // uninstall reload signal handler | ||||||
|  |         pcntl_signal(SIGUSR1, SIG_IGN, false); | ||||||
|  |         // uninstall  status signal handler | ||||||
|  |         pcntl_signal(SIGUSR2, SIG_IGN, false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 信号处理函数,会被其他类调用到,所以要设置为public | ||||||
|  |      * @param int $signal | ||||||
|  |      */ | ||||||
|  |     public function signal_handler($signal) { | ||||||
|  |         switch ($signal) { | ||||||
|  |             // stop 2 | ||||||
|  |             case SIGINT: | ||||||
|  |                 // master进程和worker进程都会调用 | ||||||
|  |                 $this->stop_all(); | ||||||
|  |                 break; | ||||||
|  |             // reload 30 | ||||||
|  |             case SIGUSR1: | ||||||
|  |                 echo "reload\n"; | ||||||
|  |                 break; | ||||||
|  |             // show status 31 | ||||||
|  |             case SIGUSR2:    | ||||||
|  |                 echo "status\n"; | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 运行worker实例 | ||||||
|  |      */ | ||||||
|  |     public function run() | ||||||
|  |     { | ||||||
|  |         $this->time_start = microtime(true);  | ||||||
|  |         $this->worker_id = 0; | ||||||
|  |         $this->worker_pid = posix_getpid(); | ||||||
|  |         $this->set_process_title($this->title); | ||||||
|  |  | ||||||
|  |         // 这里赋值,worker进程也会克隆到 | ||||||
|  |         if ($this->log_show)  | ||||||
|  |         { | ||||||
|  |             log::$log_show = true; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if ($this->on_start)  | ||||||
|  |         { | ||||||
|  |             call_user_func($this->on_start, $this); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // worker进程从1开始,0被master进程所使用 | ||||||
|  |         for ($i = 1; $i <= $this->count; $i++)  | ||||||
|  |         { | ||||||
|  |             $this->fork_one_worker($i); | ||||||
|  |         } | ||||||
|  |         $this->monitor_workers(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建一个子进程 | ||||||
|  |      * @param Worker $worker | ||||||
|  |      * @throws Exception | ||||||
|  |      */ | ||||||
|  |     public function fork_one_worker($worker_id) | ||||||
|  |     { | ||||||
|  |         //$sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP); | ||||||
|  |         $pid = pcntl_fork(); | ||||||
|  |  | ||||||
|  |         // 主进程记录子进程pid | ||||||
|  |         if($pid > 0) | ||||||
|  |         { | ||||||
|  |             self::$_worker_pids[$worker_id] = $pid; | ||||||
|  |         } | ||||||
|  |         // 子进程运行 | ||||||
|  |         elseif(0 === $pid) | ||||||
|  |         { | ||||||
|  |             $this->time_start = microtime(true); | ||||||
|  |             $this->worker_id = $worker_id; | ||||||
|  |             $this->worker_pid = posix_getpid(); | ||||||
|  |             $this->set_process_title($this->title); | ||||||
|  |             $this->set_process_user($this->user); | ||||||
|  |             // 清空master进程克隆过来的worker进程ID | ||||||
|  |             self::$_worker_pids = array(); | ||||||
|  |             //$this->uninstall_signal(); | ||||||
|  |  | ||||||
|  |             // 设置worker进程的运行状态为运行中 | ||||||
|  |             self::$_status = "running"; | ||||||
|  |  | ||||||
|  |             // 注册进程退出回调,用来检查是否有错误(子进程里面注册) | ||||||
|  |             register_shutdown_function(array($this, 'check_errors')); | ||||||
|  |  | ||||||
|  |             // 如果设置了worker进程启动回调函数 | ||||||
|  |             if ($this->on_worker_start)  | ||||||
|  |             { | ||||||
|  |                 call_user_func($this->on_worker_start, $this); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // 停止当前worker实例 | ||||||
|  |             $this->stop(); | ||||||
|  |             // 这里用0表示正常退出 | ||||||
|  |             exit(0); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             log::add("fork one worker fail", "Error"); | ||||||
|  |             exit; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 尝试设置运行当前进程的用户 | ||||||
|  |      * | ||||||
|  |      * @param $user_name | ||||||
|  |      */ | ||||||
|  |     protected static function set_process_user($user_name) | ||||||
|  |     { | ||||||
|  |         // 用户名为空 或者 当前用户不是root用户 | ||||||
|  |         if(empty($user_name) || posix_getuid() !== 0) | ||||||
|  |         { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         $user_info = posix_getpwnam($user_name); | ||||||
|  |         if($user_info['uid'] != posix_getuid() || $user_info['gid'] != posix_getgid()) | ||||||
|  |         { | ||||||
|  |             if(!posix_setgid($user_info['gid']) || !posix_setuid($user_info['uid'])) | ||||||
|  |             { | ||||||
|  |                 log::add('Can not run woker as '.$user_name." , You shuld be root", "Error"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置当前进程的名称,在ps aux命令中有用 | ||||||
|  |      * 注意 需要php>=5.5或者安装了protitle扩展 | ||||||
|  |      * @param string $title | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     protected function set_process_title($title) | ||||||
|  |     { | ||||||
|  |         if (!empty($title))  | ||||||
|  |         { | ||||||
|  |             // 需要扩展 | ||||||
|  |             if(extension_loaded('proctitle') && function_exists('setproctitle')) | ||||||
|  |             { | ||||||
|  |                 @setproctitle($title); | ||||||
|  |             } | ||||||
|  |             // >=php 5.5 | ||||||
|  |             elseif (function_exists('cli_set_process_title')) | ||||||
|  |             { | ||||||
|  |                 cli_set_process_title($title); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 监控所有子进程的退出事件及退出码 | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function monitor_workers() | ||||||
|  |     { | ||||||
|  |         // 设置master进程的运行状态为运行中 | ||||||
|  |         self::$_status = "running"; | ||||||
|  |         while(1) | ||||||
|  |         { | ||||||
|  |             // pcntl_signal_dispatch 子进程无法接受到信号 | ||||||
|  |             // 如果有信号到来,尝试触发信号处理函数 | ||||||
|  |             //pcntl_signal_dispatch(); | ||||||
|  |             // 挂起进程,直到有子进程退出或者被信号打断 | ||||||
|  |             $status = 0; | ||||||
|  |             $pid = pcntl_wait($status, WUNTRACED); | ||||||
|  |             // 如果有信号到来,尝试触发信号处理函数 | ||||||
|  |             //pcntl_signal_dispatch(); | ||||||
|  |  | ||||||
|  |             // 子进程退出信号 | ||||||
|  |             if($pid > 0) | ||||||
|  |             { | ||||||
|  |                 //echo "worker[".$pid."] stop\n"; | ||||||
|  |                 //$this->stop(); | ||||||
|  |  | ||||||
|  |                 // 如果不是正常退出,是被kill等杀掉的 | ||||||
|  |                 if($status !== 0) | ||||||
|  |                 { | ||||||
|  |                     log::add("worker {$pid} exit with status $status", "Warning"); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // key 和 value 互换 | ||||||
|  |                 $worker_pids = array_flip(self::$_worker_pids); | ||||||
|  |                 // 通过 pid 得到 worker_id | ||||||
|  |                 $worker_id = $worker_pids[$pid]; | ||||||
|  |                 // 这里不unset掉,是为了进程重启 | ||||||
|  |                 self::$_worker_pids[$worker_id] = 0; | ||||||
|  |                 //unset(self::$_worker_pids[$pid]); | ||||||
|  |  | ||||||
|  |                 // 再生成一个worker | ||||||
|  |                 if (!$this->run_once)  | ||||||
|  |                 { | ||||||
|  |                     $this->fork_one_worker($worker_id); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // 如果所有子进程都退出了,触发主进程退出函数 | ||||||
|  |                 $all_worker_stop = true; | ||||||
|  |                 foreach (self::$_worker_pids as $_worker_pid)  | ||||||
|  |                 { | ||||||
|  |                     // 只要有一个worker进程还存在进程ID,就不算退出 | ||||||
|  |                     if ($_worker_pid != 0)  | ||||||
|  |                     { | ||||||
|  |                         $all_worker_stop = false; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 if ($all_worker_stop)  | ||||||
|  |                 { | ||||||
|  |                     if ($this->on_stop)  | ||||||
|  |                     { | ||||||
|  |                         call_user_func($this->on_stop, $this); | ||||||
|  |                     } | ||||||
|  |                     exit(0); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             // 其他信号 | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 // worker进程接受到master进行信号退出的,会到这里来 | ||||||
|  |                 if ($this->on_stop)  | ||||||
|  |                 { | ||||||
|  |                     call_user_func($this->on_stop, $this); | ||||||
|  |                 } | ||||||
|  |                 exit(0); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 执行关闭流程(所有进程) | ||||||
|  |      * 事件触发,非正常程序执行完毕 | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function stop_all() | ||||||
|  |     { | ||||||
|  |         // 设置master、worker进程的运行状态为关闭状态 | ||||||
|  |         self::$_status = "shutdown"; | ||||||
|  |         // master进程 | ||||||
|  |         if(self::$_master_pid === posix_getpid()) | ||||||
|  |         { | ||||||
|  |             // 循环给worker进程发送关闭信号 | ||||||
|  |             foreach (self::$_worker_pids as $worker_pid)  | ||||||
|  |             { | ||||||
|  |                 posix_kill($worker_pid, SIGINT); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         // worker进程 | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             // 接收到master进程发送的关闭信号之后退出,这里应该考虑业务的完整性,不能强行exit | ||||||
|  |             $this->stop(); | ||||||
|  |             exit(0); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 停止当前worker实例 | ||||||
|  |      * 正常运行结束和接受信号退出,都会调用这个方法 | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function stop() | ||||||
|  |     { | ||||||
|  |         if ($this->on_worker_stop)  | ||||||
|  |         { | ||||||
|  |             call_user_func($this->on_worker_stop, $this); | ||||||
|  |         } | ||||||
|  |         // 设置worker进程的运行状态为关闭 | ||||||
|  |         self::$_status = "shutdown"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 检查错误,PHP exit之前会执行 | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function check_errors() | ||||||
|  |     { | ||||||
|  |         // 如果当前worker进程不是正常退出 | ||||||
|  |         if(self::$_status != "shutdown") | ||||||
|  |         { | ||||||
|  |             $error_msg = "WORKER EXIT UNEXPECTED "; | ||||||
|  |             $errors = error_get_last(); | ||||||
|  |             if($errors && ($errors['type'] === E_ERROR || | ||||||
|  |                 $errors['type'] === E_PARSE || | ||||||
|  |                 $errors['type'] === E_CORE_ERROR || | ||||||
|  |                 $errors['type'] === E_COMPILE_ERROR ||  | ||||||
|  |                 $errors['type'] === E_RECOVERABLE_ERROR )) | ||||||
|  |             { | ||||||
|  |                 $error_msg .= $this->get_error_type($errors['type']) . " {$errors['message']} in {$errors['file']} on line {$errors['line']}"; | ||||||
|  |             } | ||||||
|  |             log::add($error_msg, 'Error'); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取错误类型对应的意义 | ||||||
|  |      * @param integer $type | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     protected function get_error_type($type) | ||||||
|  |     { | ||||||
|  |         switch($type) | ||||||
|  |         { | ||||||
|  |         case E_ERROR: // 1 // | ||||||
|  |             return 'E_ERROR'; | ||||||
|  |         case E_WARNING: // 2 // | ||||||
|  |             return 'E_WARNING'; | ||||||
|  |         case E_PARSE: // 4 // | ||||||
|  |             return 'E_PARSE'; | ||||||
|  |         case E_NOTICE: // 8 // | ||||||
|  |             return 'E_NOTICE'; | ||||||
|  |         case E_CORE_ERROR: // 16 // | ||||||
|  |             return 'E_CORE_ERROR'; | ||||||
|  |         case E_CORE_WARNING: // 32 // | ||||||
|  |             return 'E_CORE_WARNING'; | ||||||
|  |         case E_COMPILE_ERROR: // 64 // | ||||||
|  |             return 'E_COMPILE_ERROR'; | ||||||
|  |         case E_COMPILE_WARNING: // 128 // | ||||||
|  |             return 'E_COMPILE_WARNING'; | ||||||
|  |         case E_USER_ERROR: // 256 // | ||||||
|  |             return 'E_USER_ERROR'; | ||||||
|  |         case E_USER_WARNING: // 512 // | ||||||
|  |             return 'E_USER_WARNING'; | ||||||
|  |         case E_USER_NOTICE: // 1024 // | ||||||
|  |             return 'E_USER_NOTICE'; | ||||||
|  |         case E_STRICT: // 2048 // | ||||||
|  |             return 'E_STRICT'; | ||||||
|  |         case E_RECOVERABLE_ERROR: // 4096 // | ||||||
|  |             return 'E_RECOVERABLE_ERROR'; | ||||||
|  |         case E_DEPRECATED: // 8192 // | ||||||
|  |             return 'E_DEPRECATED'; | ||||||
|  |         case E_USER_DEPRECATED: // 16384 // | ||||||
|  |             return 'E_USER_DEPRECATED'; | ||||||
|  |         } | ||||||
|  |         return ""; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								vendor/owner888/phpspider/gitadd.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/owner888/phpspider/gitadd.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | if [ ! -d "$1" ] && [ ! -f "$1" ]; then  | ||||||
|  |     echo "file $1 not exists" | ||||||
|  |     exit | ||||||
|  | fi | ||||||
|  | filename=$1 | ||||||
|  |  | ||||||
|  | comment="add file" | ||||||
|  | if [[ $2 != "" ]]; then | ||||||
|  |     comment=$2 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | echo "start update..." | ||||||
|  | git pull | ||||||
|  | echo "start add new file..." | ||||||
|  | git add $filename | ||||||
|  | echo "start commit..." | ||||||
|  | git commit -m "$comment" $filename | ||||||
|  | git push -u origin master | ||||||
|  | echo "git commit complete..." | ||||||
							
								
								
									
										129
									
								
								vendor/owner888/phpspider/hacked-emails/banners.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								vendor/owner888/phpspider/hacked-emails/banners.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | |||||||
|  |  | ||||||
|  |                _-o#&&*''''?d:>b\_ | ||||||
|  |           _o/"`''  '',, dMF9MMMMMHo_ | ||||||
|  |        .o&#'        `"MbHMMMMMMMMMMMHo. | ||||||
|  |      .o"" '         vodM*$&&HMMMMMMMMMM?. | ||||||
|  |     ,'              $M&ood,~'`(&##MMMMMMH\ | ||||||
|  |    /               ,MMMMMMM#b?#bobMMMMHMMML | ||||||
|  |   &              ?MMMMMMMMMMMMMMMMM7MMM$R*Hk | ||||||
|  |  ?$.            :MMMMMMMMMMMMMMMMMMM/HMMM|`*L | ||||||
|  | |               |MMMMMMMMMMMMMMMMMMMMbMH'   T, | ||||||
|  | $H#:            `*MMMMMMMMMMMMMMMMMMMMb#]'  `? | ||||||
|  | ]MMH#             ""*""""*#MMMMMMMMMMMMM'    - | ||||||
|  | MMMMMb_                   |MMMMMMMMMMMP'     : | ||||||
|  | HMMMMMMMHo                 `MMMMMMMMMT       . | ||||||
|  | ?MMMMMMMMP                  9MMMMMMMM]       - | ||||||
|  | -?MMMMMMM                  |MMMMMMMMM?,d-    '  {Name} | ||||||
|  |  :|MMMMMM-                 `MMMMMMMT .M|.   :     {Description} | ||||||
|  |   .9MMM[                    &MMMMM*' `'    .          {Loaded} | ||||||
|  |    :9MMk                    `MMM#"        - | ||||||
|  |      &M]                     `          .- | ||||||
|  |       `&.                             . | ||||||
|  |         `~,   .                     ./ | ||||||
|  |             . _                  .- | ||||||
|  |               '`--._,dd###pp=""' | ||||||
|  |  | ||||||
|  | $$$$$AnyShIt$$$$$$ | ||||||
|  |  | ||||||
|  |               _v->#H#P? "':o<>\_ | ||||||
|  |           .,dP` `''  "'-o.+H6&MMMHo_ | ||||||
|  |         oHMH9'         `?&bHMHMMMMMMHo. | ||||||
|  |       oMP"' '           ooMP*#&HMMMMMMM?. | ||||||
|  |     ,M*          -     `*MSdob//`^&##MMMH\ | ||||||
|  |    d*'                .,MMMMMMH#o>#ooMMMMMb | ||||||
|  |   HM-                :HMMMMMMMMMMMMMMM&HM[R\ | ||||||
|  |  d"Z\.               9MMMMMMMMMMMMMMMMM[HMM|: | ||||||
|  | -H    -              MMMMMMMMMMMMMMMMMMMbMP' : | ||||||
|  | :??Mb#               `9MMMMMMMMMMMMMMMMMMH#! . | ||||||
|  | : MMMMH#,              "*""""`#HMMMMMMMMMMH  - | ||||||
|  | ||MMMMMM6\.                    [MMMMMMMMMH'  : | ||||||
|  | :|MMMMMMMMMMHo                 `9MMMMMMMM'   . | ||||||
|  | . HMMMMMMMMMMP'                 !MMMMMMMM    ` | ||||||
|  | - `#MMMMMMMMM                   HMMMMMMM*,/  : | ||||||
|  |  :  ?MMMMMMMF                   HMMMMMM',P' :   {Name} | ||||||
|  |   .  HMMMMR'                    [MMMMP' ^' -      {Description} | ||||||
|  |    : `HMMMT                     iMMH'     .'          {Loaded} | ||||||
|  |     -.`HMH                               . | ||||||
|  |       -:*H                            . ' | ||||||
|  |         -`\,,    .                  .- | ||||||
|  |           ' .  _                 .-` | ||||||
|  |               '`~\.__,obb#q==~''' | ||||||
|  |  | ||||||
|  | $$$$$AnyShIt$$$$$$ | ||||||
|  |  | ||||||
|  |               _ood>H&H&Z?#M#b-\. | ||||||
|  |           .\HMMMMMR?`\M6b."`' ''``v. | ||||||
|  |        .. .MMMMMMMMMMHMMM#&.      ``~o. | ||||||
|  |      .   ,HMMMMMMMMMMMM*"'-`          &b. | ||||||
|  |     .   .MMMMMMMMMMMMH'               `"&\ | ||||||
|  |    -     RMMMMM#H##R'                   4Mb | ||||||
|  |   -      |7MMM'    ?::                 `|MMb | ||||||
|  |  /         HMM__#|`"\>?v..              `MMML | ||||||
|  | .           `"'#Hd|       `              9MMM: | ||||||
|  | -                |\,\?HH#bbL             `9MMb | ||||||
|  | :                   !MMMMMMMH#b,          `""T | ||||||
|  | .              .   ,MMMMMMMMMMMbo.           | | ||||||
|  | :                  4MMMMMMMMMMMMMMMHo        | | ||||||
|  | :                   ?MMMMMMMMMMMMMMM?        : | ||||||
|  | -.                   `#MMMMMMMMMMMM:        .- | ||||||
|  |  :                     |MMMMMMMMMM?         . | ||||||
|  |   -                    JMMMMMMMT'          :    {Name} | ||||||
|  |   `.                   MMMMMMH'           -       {Description} | ||||||
|  |     -.                |MMM#*`            -            {Loaded} | ||||||
|  |       .               HMH'            . ' | ||||||
|  |         -.            #H:.          .- | ||||||
|  |           ` .           .\       .- | ||||||
|  |               '-..-+oodHL_,--/-` | ||||||
|  |  | ||||||
|  |  | ||||||
|  | $$$$$AnyShIt$$$$$$ | ||||||
|  |  | ||||||
|  |               .,:,#&6dHHHb&##o\_ | ||||||
|  |           .oHHMMMMMMMMMMMMMMMMMH*\,. | ||||||
|  |         oHMMMMMMMMMMMMMMMMMMMMMMHb:'-. | ||||||
|  |      .dMMMMMMMMMMMMMMMMMMMMMMMMMH|\/'  . | ||||||
|  |     ,&HMMMMMMMMMMMMMMMMMMMMMMM/"&.,d.   -. | ||||||
|  |    dboMMHMMMMMMMMMMMMMMMMMMMMMML `'       . | ||||||
|  |   HMHMMM$Z***MMMMMMMMMMMMMMMMMM|.-         . | ||||||
|  |  dMM]MMMM#'  `9MMMH?"`MMMMR'T'  _           : | ||||||
|  | |MMMbM#''     |MM"    ``MMMH.   <_           . | ||||||
|  | dMMMM#&        *&.     .?`*"   .'&:          . | ||||||
|  | MMMMMH-         `'    -v/H   .dD "'  '       : | ||||||
|  | MMMM*                  `*M: 4MM*::-!v,_      : | ||||||
|  | MMMM                     `*?::" "'``"?9Mb::. : | ||||||
|  | &MMM,                       `"'"'|"._ "?`| - : | ||||||
|  | `MMM].H                          ,#dM[_H   ..: | ||||||
|  |  9MMi`M: .                   .ooHMMMMMMM,  .. | ||||||
|  |   9Mb `-                     1MMMMMMMMMM|  :    {Name} | ||||||
|  |    ?M                        |MM#*#MMMM*  .       {Description} | ||||||
|  |     -.                       `     |#"' ,'            {Loaded} | ||||||
|  |       .                            -" v` | ||||||
|  |         -.                          .- | ||||||
|  |            - .                   . ` | ||||||
|  |               '-*#d#HHMMMMHH#"-' | ||||||
|  |  | ||||||
|  | $$$$$AnyShIt$$$$$$ | ||||||
|  |  | ||||||
|  |               .-:?,Z?:&$dHH##b\_ | ||||||
|  |            ,:bqRMMMMMMMMMMMMMMMMMHo. | ||||||
|  |         .?HHHMMMMMMMMMMMMMMMMMMMMMMMHo. | ||||||
|  |       -o/*M9MMMMMMMMMMMMMMMMMMMMMMMMMMMv | ||||||
|  |     .:H\b\'|?#HHMMMMMMMMMMMMMMMMMMMMMM6?Z\ | ||||||
|  |    .?MMMHbdbbodMMMMHMMMMMMMMMMMMMMMMMMMM\': | ||||||
|  |   :MMMMMMMMMMM7MMMMb?6P**#MMMMMMMMMMMMMMM_ : | ||||||
|  |  \MMMMMMMMMMMMb^MMMMMM?   `*MMMM*"`MMMR<' . - | ||||||
|  | .1MMMMMMMMMMMMMb]M#""       9MR'   `?MMb  \. : | ||||||
|  | -MMMMMMMMMMMMMMMH##|`        *&.     |`*' .\ . | ||||||
|  | -?""*MMMMMMMMMMMMM'            '    |?b  ,]" : | ||||||
|  | :    MMMMMMMMMMH'                    `M_|M]r\? | ||||||
|  | .    `MMMMMMMMM'                      `$_:`'"H | ||||||
|  | -     TMMMMMMMM,                        '"``:: | ||||||
|  | :     [MMMMMMMM| oH|                      .#M- | ||||||
|  |  :    `9MMMMMM' .MP   .                 ,oMMT | ||||||
|  |   .     HMMMMP'  `'                    ,MMMP    {Name} | ||||||
|  |    -     `MMH'                         HH9*       {Description} | ||||||
|  |     '.    `                           ` .'            {Loaded} | ||||||
|  |       -                               . ' | ||||||
|  |        ` .               -          .- | ||||||
|  |           ` .                    .- | ||||||
|  |               ' -==pHMMH##HH#""" | ||||||
							
								
								
									
										49
									
								
								vendor/owner888/phpspider/hacked-emails/hacked_emails.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/owner888/phpspider/hacked-emails/hacked_emails.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | <?php | ||||||
|  | ini_set("memory_limit", "10240M"); | ||||||
|  | require_once __DIR__ . '/../autoloader.php'; | ||||||
|  | use phpspider\core\requests; | ||||||
|  | use phpspider\core\selector; | ||||||
|  |  | ||||||
|  | /* Do NOT delete this comment */ | ||||||
|  | /* 不要删除这段注释 */ | ||||||
|  |  | ||||||
|  | hacked_emails::random_banner(); | ||||||
|  | exit; | ||||||
|  | class hacked_emails | ||||||
|  | { | ||||||
|  |     // Colors | ||||||
|  |     // green - yellow - blue - red - white - magenta - cyan - reset | ||||||
|  |     public static $color_g = "\033[92m"; | ||||||
|  |     public static $color_y = "\033[93m"; | ||||||
|  |     public static $color_b = "\033[94m"; | ||||||
|  |     public static $color_r = "\033[91m"; | ||||||
|  |     public static $color_w = "\033[0m"; | ||||||
|  |     public static $color_m = "\x1b[35m"; | ||||||
|  |     public static $color_c = "\x1b[36m"; | ||||||
|  |     public static $end = "\x1b[39m"; | ||||||
|  |     public static $bold = "\033[1m"; | ||||||
|  |  | ||||||
|  |     public static function random_banner() | ||||||
|  |     { | ||||||
|  |         $banners = file_get_contents("banners.txt"); | ||||||
|  |         $banners = explode('$$$$$AnyShIt$$$$$$', $banners); | ||||||
|  |         $banner = $banners[count($banners)-1]; | ||||||
|  |         $banner_to_print = self::$color_g; | ||||||
|  |         $banner_to_print .= $banner; | ||||||
|  |         $banner_to_print .= self::$end; | ||||||
|  |  | ||||||
|  |         $name = self::$color_b."Hacked Emails By ".self::$bold."@seatle -".self::$color_m." V0.1".self::$color_g; | ||||||
|  |         $banner_to_print = str_replace("{Name}", $name, $banner_to_print); | ||||||
|  |         $description = self::$color_c."Know the dangers of email credentials reuse attacks.".self::$color_g; | ||||||
|  |         $banner_to_print = str_replace("{Description}", $description, $banner_to_print); | ||||||
|  | 	    $loaded = self::$color_b."Loaded ".self::$color_y."14".self::$color_b." website.".self::$color_g; | ||||||
|  |         $banner_to_print = str_replace("{Loaded}", $loaded, $banner_to_print); | ||||||
|  |         echo $banner_to_print; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $html = requests::get('http://www.qiushibaike.com/article/118914171'); | ||||||
|  | //echo $html; | ||||||
|  | //exit; | ||||||
|  | $data = selector::select($html, "div.author", "css"); | ||||||
|  | echo $data; | ||||||
							
								
								
									
										425
									
								
								vendor/owner888/phpspider/library/cls_curl.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										425
									
								
								vendor/owner888/phpspider/library/cls_curl.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,425 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Worker多进程操作类 | ||||||
|  |  * | ||||||
|  |  * Licensed under The MIT License | ||||||
|  |  * For full copyright and license information, please see the MIT-LICENSE.txt | ||||||
|  |  * Redistributions of files must retain the above copyright notice. | ||||||
|  |  * | ||||||
|  |  * @author seatle<seatle@foxmail.com> | ||||||
|  |  * @copyright seatle<seatle@foxmail.com> | ||||||
|  |  * @link http://www.epooll.com/ | ||||||
|  |  * @license http://www.opensource.org/licenses/mit-license.php MIT License | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | class cls_curl | ||||||
|  | { | ||||||
|  |     protected static $timeout = 10; | ||||||
|  |     protected static $ch = null; | ||||||
|  |     protected static $useragent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36'; | ||||||
|  |     protected static $http_raw = false; | ||||||
|  |     protected static $cookie = null; | ||||||
|  |     protected static $cookie_jar = null; | ||||||
|  |     protected static $cookie_file = null; | ||||||
|  |     protected static $referer = null; | ||||||
|  |     protected static $ip = null; | ||||||
|  |     protected static $proxy = null; | ||||||
|  |     protected static $headers = array(); | ||||||
|  |     protected static $hosts = array(); | ||||||
|  |     protected static $gzip = false; | ||||||
|  |     protected static $info = array(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * set timeout | ||||||
|  |      * | ||||||
|  |      * @param init $timeout | ||||||
|  |      * @return | ||||||
|  |      */ | ||||||
|  |     public static function set_timeout($timeout) | ||||||
|  |     { | ||||||
|  |         self::$timeout = $timeout; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置代理 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $proxy | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-09-18 10:17 | ||||||
|  |      */ | ||||||
|  |     public static function set_proxy($proxy) | ||||||
|  |     { | ||||||
|  |         self::$proxy = $proxy; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * set referer | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |     public static function set_referer($referer) | ||||||
|  |     { | ||||||
|  |         self::$referer = $referer; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置 user_agent | ||||||
|  |      * | ||||||
|  |      * @param string $useragent | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_useragent($useragent) | ||||||
|  |     { | ||||||
|  |         self::$useragent = $useragent; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置COOKIE | ||||||
|  |      * | ||||||
|  |      * @param string $cookie | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_cookie($cookie) | ||||||
|  |     { | ||||||
|  |         self::$cookie = $cookie; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置COOKIE JAR | ||||||
|  |      * | ||||||
|  |      * @param string $cookie_jar | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_cookie_jar($cookie_jar) | ||||||
|  |     { | ||||||
|  |         self::$cookie_jar = $cookie_jar; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置COOKIE FILE | ||||||
|  |      * | ||||||
|  |      * @param string $cookie_file | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_cookie_file($cookie_file) | ||||||
|  |     { | ||||||
|  |         self::$cookie_file = $cookie_file; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取内容的时候是不是连header也一起获取 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $http_raw | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-09-18 10:17 | ||||||
|  |      */ | ||||||
|  |     public static function set_http_raw($http_raw) | ||||||
|  |     { | ||||||
|  |         self::$http_raw = $http_raw; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置IP | ||||||
|  |      * | ||||||
|  |      * @param string $ip | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_ip($ip) | ||||||
|  |     { | ||||||
|  |         self::$ip = $ip; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置Headers | ||||||
|  |      * | ||||||
|  |      * @param string $headers | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_headers($headers) | ||||||
|  |     { | ||||||
|  |         self::$headers = $headers; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置Hosts | ||||||
|  |      * | ||||||
|  |      * @param string $hosts | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_hosts($hosts) | ||||||
|  |     { | ||||||
|  |         self::$hosts = $hosts; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置Gzip | ||||||
|  |      * | ||||||
|  |      * @param string $hosts | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function set_gzip($gzip) | ||||||
|  |     { | ||||||
|  |         self::$gzip = $gzip; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 初始化 CURL | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |     public static function init() | ||||||
|  |     { | ||||||
|  |         //if (empty ( self::$ch )) | ||||||
|  |         if (!is_resource ( self::$ch )) | ||||||
|  |         { | ||||||
|  |             self::$ch = curl_init (); | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_RETURNTRANSFER, true ); | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_CONNECTTIMEOUT, self::$timeout ); | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_HEADER, false ); | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_USERAGENT, self::$useragent ); | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_TIMEOUT, self::$timeout + 5); | ||||||
|  |             // 在多线程处理场景下使用超时选项时,会忽略signals对应的处理函数,但是无耐的是还有小概率的crash情况发生 | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_NOSIGNAL, true); | ||||||
|  |         } | ||||||
|  |         return self::$ch; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * get | ||||||
|  |      * | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |     public static function get($url, $fields = array()) | ||||||
|  |     { | ||||||
|  |         self::init (); | ||||||
|  |         return self::http_request($url, 'get', $fields); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * $fields 有三种类型:1、数组;2、http query;3、json | ||||||
|  |      * 1、array('name'=>'yangzetao') 2、http_build_query(array('name'=>'yangzetao')) 3、json_encode(array('name'=>'yangzetao')) | ||||||
|  |      * 前两种是普通的post,可以用$_POST方式获取 | ||||||
|  |      * 第三种是post stream( json rpc,其实就是webservice ),虽然是post方式,但是只能用流方式 http://input 后者 $HTTP_RAW_POST_DATA 获取  | ||||||
|  |      *  | ||||||
|  |      * @param mixed $url  | ||||||
|  |      * @param array $fields  | ||||||
|  |      * @param mixed $proxy  | ||||||
|  |      * @static | ||||||
|  |      * @access public | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public static function post($url, $fields = array()) | ||||||
|  |     { | ||||||
|  |         self::init (); | ||||||
|  |         return self::http_request($url, 'post', $fields); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function http_request($url, $type = 'get', $fields) | ||||||
|  |     { | ||||||
|  |         // 如果是 get 方式,直接拼凑一个 url 出来 | ||||||
|  |         if (strtolower($type) == 'get' && !empty($fields))  | ||||||
|  |         { | ||||||
|  |             $url = $url . (strpos($url,"?")===false ? "?" : "&") . http_build_query($fields); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 随机绑定 hosts,做负载均衡 | ||||||
|  |         if (self::$hosts)  | ||||||
|  |         { | ||||||
|  |             $parse_url = parse_url($url); | ||||||
|  |             $host = $parse_url['host']; | ||||||
|  |             $key = rand(0, count(self::$hosts)-1); | ||||||
|  |             $ip = self::$hosts[$key]; | ||||||
|  |             $url = str_replace($host, $ip, $url); | ||||||
|  |             self::$headers = array_merge( array('Host:'.$host), self::$headers ); | ||||||
|  |         } | ||||||
|  |         curl_setopt( self::$ch, CURLOPT_URL, $url ); | ||||||
|  |         // 如果是 post 方式 | ||||||
|  |         if (strtolower($type) == 'post') | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_POST, true ); | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_POSTFIELDS, $fields ); | ||||||
|  |         } | ||||||
|  |         if (self::$useragent) | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_USERAGENT, self::$useragent ); | ||||||
|  |         } | ||||||
|  |         if (self::$cookie) | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_COOKIE, self::$cookie ); | ||||||
|  |         } | ||||||
|  |         if (self::$cookie_jar) | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_COOKIEJAR, self::$cookie_jar ); | ||||||
|  |         } | ||||||
|  |         if (self::$cookie_file) | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_COOKIEFILE, self::$cookie_file ); | ||||||
|  |         } | ||||||
|  |         if (self::$referer) | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_REFERER, self::$referer ); | ||||||
|  |         } | ||||||
|  |         if (self::$ip) | ||||||
|  |         { | ||||||
|  |             self::$headers = array_merge( array('CLIENT-IP:'.self::$ip, 'X-FORWARDED-FOR:'.self::$ip), self::$headers ); | ||||||
|  |         } | ||||||
|  |         if (self::$headers) | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_HTTPHEADER, self::$headers ); | ||||||
|  |         } | ||||||
|  |         if (self::$gzip) | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_ENCODING, 'gzip' ); | ||||||
|  |         } | ||||||
|  |         if (self::$proxy) | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_PROXY, self::$proxy ); | ||||||
|  |         } | ||||||
|  |         if (self::$http_raw) | ||||||
|  |         { | ||||||
|  |             curl_setopt( self::$ch, CURLOPT_HEADER, true ); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $data = curl_exec ( self::$ch ); | ||||||
|  |         self::$info = curl_getinfo(self::$ch); | ||||||
|  |         if ($data === false) | ||||||
|  |         { | ||||||
|  |             //echo date("Y-m-d H:i:s"), ' Curl error: ' . curl_error( self::$ch ), "\n"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 关闭句柄 | ||||||
|  |         curl_close( self::$ch ); | ||||||
|  |         //$data = substr($data, 10); | ||||||
|  |         //$data = gzinflate($data); | ||||||
|  |         return $data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function get_info() | ||||||
|  |     { | ||||||
|  |         return self::$info; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function get_http_code() | ||||||
|  |     { | ||||||
|  |         return self::$info['http_code']; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function classic_curl($urls, $delay)  | ||||||
|  | { | ||||||
|  |     $queue = curl_multi_init(); | ||||||
|  |     $map = array(); | ||||||
|  |  | ||||||
|  |     foreach ($urls as $url)  | ||||||
|  |     { | ||||||
|  |         // create cURL resources | ||||||
|  |         $ch = curl_init(); | ||||||
|  |  | ||||||
|  |         // 设置 URL 和 其他参数 | ||||||
|  |         curl_setopt($ch, CURLOPT_URL, $url); | ||||||
|  |         curl_setopt($ch, CURLOPT_TIMEOUT, 1); | ||||||
|  |         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | ||||||
|  |         curl_setopt($ch, CURLOPT_HEADER, 0); | ||||||
|  |         curl_setopt($ch, CURLOPT_NOSIGNAL, true); | ||||||
|  |  | ||||||
|  |         // 把当前 curl resources 加入到 curl_multi_init 队列 | ||||||
|  |         curl_multi_add_handle($queue, $ch); | ||||||
|  |         $map[$url] = $ch; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $active = null; | ||||||
|  |  | ||||||
|  |     // execute the handles | ||||||
|  |     do { | ||||||
|  |         $mrc = curl_multi_exec($queue, $active); | ||||||
|  |     } while ($mrc == CURLM_CALL_MULTI_PERFORM); | ||||||
|  |  | ||||||
|  |     while ($active > 0 && $mrc == CURLM_OK) { | ||||||
|  |         while (curl_multi_exec($queue, $active) === CURLM_CALL_MULTI_PERFORM); | ||||||
|  |         // 这里 curl_multi_select 一直返回 -1,所以这里就死循环了,CPU就100%了 | ||||||
|  |         if (curl_multi_select($queue, 0.5) != -1)  | ||||||
|  |         { | ||||||
|  |             do { | ||||||
|  |                 $mrc = curl_multi_exec($queue, $active); | ||||||
|  |             } while ($mrc == CURLM_CALL_MULTI_PERFORM); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $responses = array(); | ||||||
|  |     foreach ($map as $url=>$ch) { | ||||||
|  |         //$responses[$url] = callback(curl_multi_getcontent($ch), $delay); | ||||||
|  |         $responses[$url] = callback(curl_multi_getcontent($ch), $delay, $url); | ||||||
|  |         curl_multi_remove_handle($queue, $ch); | ||||||
|  |         curl_close($ch); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     curl_multi_close($queue); | ||||||
|  |     return $responses; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function rolling_curl($urls, $delay)  | ||||||
|  | { | ||||||
|  |     $queue = curl_multi_init(); | ||||||
|  |     $map = array(); | ||||||
|  |  | ||||||
|  |     foreach ($urls as $url) { | ||||||
|  |         $ch = curl_init(); | ||||||
|  |  | ||||||
|  |         curl_setopt($ch, CURLOPT_URL, $url); | ||||||
|  |         curl_setopt($ch, CURLOPT_TIMEOUT, 10); | ||||||
|  |         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | ||||||
|  |         curl_setopt($ch, CURLOPT_HEADER, 0); | ||||||
|  |         curl_setopt($ch, CURLOPT_NOSIGNAL, true); | ||||||
|  |         $cookie = '_za=36643642-e546-4d60-a771-8af8dcfbd001; q_c1=a57a2b9f10964f909b8d8969febf3ab2|1437705596000|1437705596000; _xsrf=f0304fba4e44e1d008ec308d59bab029; cap_id="YWY1YmRmODlmZGVmNDc3MWJlZGFkZDg3M2E0M2Q5YjM=|1437705596|963518c454bb6f10d96775021c098c84e1e46f5a"; z_c0="QUFCQVgtRWZBQUFYQUFBQVlRSlZUVjR6NEZVUTgtRkdjTVc5UDMwZXRJZFdWZ2JaOWctNVhnPT0=|1438164574|aed6ef3707f246a7b64da4f1e8c089395d77ff2b"; __utma=51854390.1105113342.1437990174.1438160686.1438164116.10; __utmc=51854390; __utmz=51854390.1438134939.8.5.utmcsr=zhihu.com|utmccn=(referral)|utmcmd=referral|utmcct=/people/yangzetao; __utmv=51854390.100-1|2=registration_date=20131030=1^3=entry_date=20131030=1'; | ||||||
|  |         curl_setopt($ch, CURLOPT_COOKIE, $cookie); | ||||||
|  |         $useragent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36'; | ||||||
|  |         curl_setopt( $ch, CURLOPT_USERAGENT, $useragent ); | ||||||
|  |         curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); | ||||||
|  |  | ||||||
|  |         curl_multi_add_handle($queue, $ch); | ||||||
|  |         $map[(string) $ch] = $url; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $responses = array(); | ||||||
|  |     do { | ||||||
|  |         while (($code = curl_multi_exec($queue, $active)) == CURLM_CALL_MULTI_PERFORM) ; | ||||||
|  |  | ||||||
|  |         if ($code != CURLM_OK) { break; } | ||||||
|  |  | ||||||
|  |         // a request was just completed -- find out which one | ||||||
|  |         while ($done = curl_multi_info_read($queue)) { | ||||||
|  |  | ||||||
|  |             // get the info and content returned on the request | ||||||
|  |             $info = curl_getinfo($done['handle']); | ||||||
|  |             $error = curl_error($done['handle']); | ||||||
|  |             $results = callback(curl_multi_getcontent($done['handle']), $delay, $map[(string) $done['handle']]); | ||||||
|  |             $responses[$map[(string) $done['handle']]] = compact('info', 'error', 'results'); | ||||||
|  |  | ||||||
|  |             // remove the curl handle that just completed | ||||||
|  |             curl_multi_remove_handle($queue, $done['handle']); | ||||||
|  |             curl_close($done['handle']); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Block for data in / output; error handling is done by curl_multi_exec | ||||||
|  |         if ($active > 0) { | ||||||
|  |             curl_multi_select($queue, 0.5); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     } while ($active); | ||||||
|  |  | ||||||
|  |     curl_multi_close($queue); | ||||||
|  |     return $responses; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function callback($data, $delay, $url) { | ||||||
|  |     //echo $data; | ||||||
|  |     //echo date("Y-m-d H:i:s", time()) . " --- " . $url . "\n"; | ||||||
|  |     if (!empty($data))  | ||||||
|  |     { | ||||||
|  |         file_put_contents("./html2/".md5($url).".html", $data); | ||||||
|  |     } | ||||||
|  |     // usleep模拟现实中比较负责的数据处理逻辑(如提取, 分词, 写入文件或数据库等) | ||||||
|  |     //usleep(1); | ||||||
|  |     //return compact('data', 'matches'); | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										248
									
								
								vendor/owner888/phpspider/library/cls_query.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								vendor/owner888/phpspider/library/cls_query.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,248 @@ | |||||||
|  | <?php | ||||||
|  | class cls_query | ||||||
|  | { | ||||||
|  |     private static $content; | ||||||
|  |     public static $debug = false; | ||||||
|  |  | ||||||
|  |     public static function init($content) | ||||||
|  |     { | ||||||
|  |         self::$content = $content; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function query($query, $attr = "html") | ||||||
|  |     { | ||||||
|  |         $nodes = self::get_nodes($query); | ||||||
|  |         $datas = self::get_datas($nodes, $attr); | ||||||
|  |         return $datas; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected static function is_char($char) { | ||||||
|  | 		return extension_loaded('mbstring') ? mb_eregi('\w', $char) : preg_match('@\w@', $char); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 从xpath中得到节点 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $xpath | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2015-08-08 15:52 | ||||||
|  |      */ | ||||||
|  |     private static function get_nodes($query) | ||||||
|  |     { | ||||||
|  |         // 把一到多个空格 替换成 一个空格 | ||||||
|  |         // 把 > 和  ~ 符号两边的空格去掉,因为没有用这两个符号,所以这里可以不这么做 | ||||||
|  |         // ul>li.className | ||||||
|  |         $query = trim( | ||||||
|  | 			preg_replace('@\s+@', ' ', | ||||||
|  | 				preg_replace('@\s*(>|\\+|~)\s*@', '\\1', $query) | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  |  | ||||||
|  |         $nodes = array(); | ||||||
|  | 		if (! $query) | ||||||
|  |         { | ||||||
|  | 			return $nodes; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $query_arr = explode(" ", $query); | ||||||
|  |         foreach ($query_arr as $k=>$v)  | ||||||
|  |         { | ||||||
|  |             $path = $k == 0 ? $v : $path.' '.$v; | ||||||
|  |             $node = array("path"=>(string)$path, "name"=>"", "id"=>"", "class"=>"", "other"=>array()); | ||||||
|  |             // 如果存在内容选择器 | ||||||
|  |             if (preg_match('@(.*?)\[(.*?)=[\'|"](.*?)[\'|"]\]@', $v, $matches) && !empty($matches[2]) && !empty($matches[3]))  | ||||||
|  |             { | ||||||
|  |                 // 把选择器过滤掉 [rel='topic'] | ||||||
|  |                 $v = $matches[1]; | ||||||
|  |                 $node['other'] = array( | ||||||
|  |                     'key'=>$matches[2], | ||||||
|  |                     'val'=>$matches[3], | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // 如果存在 id | ||||||
|  |             $id_arr = explode("#", $v); | ||||||
|  |             $class_arr = explode(".", $v); | ||||||
|  |             if (count($id_arr) === 2)  | ||||||
|  |             { | ||||||
|  |                 $node['name'] = $id_arr[0]; | ||||||
|  |                 $node['id'] = $id_arr[1]; | ||||||
|  |             } | ||||||
|  |             // 如果存在 class | ||||||
|  |             elseif (count($class_arr) === 2)  | ||||||
|  |             { | ||||||
|  |                 $node['name'] = $class_arr[0]; | ||||||
|  |                 $node['class'] = $class_arr[1]; | ||||||
|  |             } | ||||||
|  |             // 如果没有样式 | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 $node['name'] = $v; | ||||||
|  |             } | ||||||
|  |             $nodes[] = $node; | ||||||
|  |         } | ||||||
|  |         //print_r($nodes); | ||||||
|  |         //exit; | ||||||
|  |         return $nodes; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static function get_datas($nodes, $attr = "html") | ||||||
|  |     { | ||||||
|  |         if (empty(self::$content))  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $node_datas = array(); | ||||||
|  |         $count = count($nodes); | ||||||
|  |         // 循环所有节点 | ||||||
|  |         foreach ($nodes as $i=>$node)  | ||||||
|  |         { | ||||||
|  |             $is_last = $count == $i+1 ? true : false; | ||||||
|  |             // 第一次 | ||||||
|  |             if ($i == 0)  | ||||||
|  |             { | ||||||
|  |                 $datas = array(); | ||||||
|  |                 $datas = self::get_node_datas($node, self::$content, $attr, $is_last); | ||||||
|  |                 // 如果第一次都取不到数据,直接跳出循环 | ||||||
|  |                 if(!$datas) | ||||||
|  |                 { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 $node_datas[$nodes[$i]['path']] = $datas; | ||||||
|  |             } | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 $datas = array(); | ||||||
|  |                 // 循环上一个节点的数组 | ||||||
|  |                 foreach ($node_datas[$nodes[$i-1]['path']] as $v)  | ||||||
|  |                 { | ||||||
|  |                     $datas = array_merge( $datas, self::get_node_datas($node, trim($v), $attr, $is_last) ); | ||||||
|  |                 } | ||||||
|  |                 $node_datas[$nodes[$i]['path']] = $datas; | ||||||
|  |                 // 删除上一个节点,防止内存溢出,或者缓存到本地,再次使用?! | ||||||
|  |                 unset($node_datas[$nodes[$i-1]['path']]); | ||||||
|  |             } | ||||||
|  |         }    | ||||||
|  |         //print_r($datas);exit; | ||||||
|  |         // 从数组中弹出最后一个元素 | ||||||
|  |         $node_datas = array_pop($node_datas); | ||||||
|  |         //print_r($node_datas); | ||||||
|  |         //exit; | ||||||
|  |         return $node_datas; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 从节点中获取内容 | ||||||
|  |      * $regex = '@<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i'; | ||||||
|  |      *  | ||||||
|  |      * @param mixed $node | ||||||
|  |      * @param mixed $content | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2015-08-08 15:52 | ||||||
|  |      */ | ||||||
|  |     private static function get_node_datas($node, $content, $attr = "html", $is_last = false) | ||||||
|  |     { | ||||||
|  |         $node_datas = $datas = array(); | ||||||
|  |  | ||||||
|  |         if (!empty($node['id']))  | ||||||
|  |         { | ||||||
|  |             if ($node['name'])  | ||||||
|  |                 $regex = '@<'.$node['name'].'[^>]+id\\s*=\\s*["|\']+?'.$node['id'].'\\s*[^>]+?>(.*?)</'.$node['name'].'>@is'; | ||||||
|  |             else  | ||||||
|  |                 $regex = '@id\\s*=\\s*["|\']+?'.$node['id'].'\\s*[^>]+?>(.*?)<@is'; | ||||||
|  |         } | ||||||
|  |         elseif (!empty($node['class']))  | ||||||
|  |         { | ||||||
|  |             if ($node['name'])  | ||||||
|  |                 $regex = '@<'.$node['name'].'[^>]+class\\s*=\\s*["|\']+?'.$node['class'].'\\s*[^>]+?>(.*?)</'.$node['name'].'>@is'; | ||||||
|  |             else  | ||||||
|  |                 $regex = '@class\\s*=\\s*["|\']+?'.$node['class'].'\\s*[^>]+?>(.*?)<@is'; | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             // 这里为是么是*,0次到多次,因为有可能是 <li> | ||||||
|  |             $regex = '@<'.$node['name'].'[^>]*?>(.*?)</'.$node['name'].'>@is'; | ||||||
|  |         } | ||||||
|  |         self::log("regex --- " . $regex);; | ||||||
|  |         preg_match_all($regex, $content, $matches); | ||||||
|  |         $all_datas = empty($matches[0]) ? array() : $matches[0]; | ||||||
|  |         $html_datas = empty($matches[1]) ? array() : $matches[1]; | ||||||
|  |  | ||||||
|  |         // 过滤掉选择器对不上的 | ||||||
|  |         foreach ($all_datas as $i=>$data)  | ||||||
|  |         { | ||||||
|  |             // 如果有设置其他选择器,验证一下选择器 | ||||||
|  |             if (!empty($node['other']))  | ||||||
|  |             { | ||||||
|  |                 $regex = '@'.$node['other']['key'].'=[\'|"]'.$node['other']['val'].'[\'|"]@is'; | ||||||
|  |                 self::log("regex other --- " . $regex); | ||||||
|  |                 // 过滤器对不上的,跳过 | ||||||
|  |                 if (!preg_match($regex, $data, $matches))  | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             // 获取节点的html内容 | ||||||
|  |             if ($attr != "html" && $is_last)  | ||||||
|  |             { | ||||||
|  |                 $regex = '@'.$attr.'=[\'|"](.*?)[\'|"]@is'; | ||||||
|  |                 preg_match($regex, $data, $matches);  | ||||||
|  |                 $node_datas[] = empty($matches[1]) ? '' : trim($matches[1]); | ||||||
|  |             } | ||||||
|  |             // 获取节点属性名的值 | ||||||
|  |             else  | ||||||
|  |             { | ||||||
|  |                 $node_datas[] = trim($html_datas[$i]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         //echo " 11111 ========================================= \n"; | ||||||
|  |         //print_r($node_datas); | ||||||
|  |         //echo " 22222 ========================================= \n\n\n"; | ||||||
|  |         return $node_datas; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 记录日志 | ||||||
|  |      * @param string $msg | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     private static function log($msg) | ||||||
|  |     { | ||||||
|  |         $msg = "[".date("Y-m-d H:i:s")."] " . $msg . "\n"; | ||||||
|  |         if (self::$debug)  | ||||||
|  |         { | ||||||
|  |             echo $msg; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //$xpath = "ul.top-nav-dropdown li"; | ||||||
|  | //$xpath = "i.zg-icon"; | ||||||
|  | //print_r($nodes); | ||||||
|  | //exit; | ||||||
|  | // [^>]+ 不是>的字符重复一次到多次, ? 表示不贪婪 | ||||||
|  | // \s 表示空白字符 | ||||||
|  | // * 表示0次或者多次 | ||||||
|  | // + 表示1次或者多次 | ||||||
|  | // | ||||||
|  | // 后向引用,表示表达式中,从左往右数,第一个左括号对应的括号内的内容。 | ||||||
|  | // \\0 表示整个表达式 | ||||||
|  | // \\1表示第1个表达式 | ||||||
|  | // \\2表示第2个表达式 | ||||||
|  | // $regex = '@<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i'; | ||||||
|  | //preg_match_all($regex, $content, $matches); | ||||||
|  | //print_r($matches); | ||||||
|  | //exit; | ||||||
|  |  | ||||||
|  | // 用法 | ||||||
|  | //$content = file_get_contents("./test.html"); | ||||||
|  | //$query = "ul#top-nav-profile-dropdown li a"; | ||||||
|  | //$query = "div#zh-profile-following-topic a.link[href='/topic/19550937']"; | ||||||
|  | //cls_query::init($content); | ||||||
|  | //$list = cls_query::query($query, "href"); | ||||||
|  | //print_r($list); | ||||||
|  |  | ||||||
							
								
								
									
										1263
									
								
								vendor/owner888/phpspider/library/cls_redis.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1263
									
								
								vendor/owner888/phpspider/library/cls_redis.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										121
									
								
								vendor/owner888/phpspider/library/cls_redis_client.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								vendor/owner888/phpspider/library/cls_redis_client.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * redis 客户端  | ||||||
|  |  * redis的协议可参考这个文章http://redis.cn/topics/protocol.html | ||||||
|  |  *  | ||||||
|  |  * @version 2.7.0 | ||||||
|  |  * @copyright 1997-2018 The PHP Group | ||||||
|  |  * @author seatle <seatle@foxmail.com>  | ||||||
|  |  * @created time :2018-01-03 | ||||||
|  |  */ | ||||||
|  | class cls_redis_client  | ||||||
|  | { | ||||||
|  |     private $redis_socket = false; | ||||||
|  |     //private $command = ''; | ||||||
|  |  | ||||||
|  |     public function __construct($host='127.0.0.1', $port=6379, $timeout = 3)  | ||||||
|  |     { | ||||||
|  |         $this->redis_socket = stream_socket_client("tcp://".$host.":".$port, $errno, $errstr,  $timeout); | ||||||
|  |         if ( !$this->redis_socket ) | ||||||
|  |         { | ||||||
|  |             throw new Exception("{$errno} - {$errstr}"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function __destruct() | ||||||
|  |     { | ||||||
|  |         fclose($this->redis_socket); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function __call($name, $args)  | ||||||
|  |     { | ||||||
|  |         $crlf = "\r\n"; | ||||||
|  |         array_unshift($args, $name); | ||||||
|  |         $command = '*' . count($args) . $crlf; | ||||||
|  |         foreach ($args as $arg)  | ||||||
|  |         { | ||||||
|  |             $command .= '$' . strlen($arg) . $crlf . $arg . $crlf; | ||||||
|  |         } | ||||||
|  |         //echo $command."\n"; | ||||||
|  |         $fwrite = fwrite($this->redis_socket, $command); | ||||||
|  |         if ($fwrite === FALSE || $fwrite <= 0) | ||||||
|  |         { | ||||||
|  |             throw new Exception('Failed to write entire command to stream'); | ||||||
|  |         } | ||||||
|  |         return $this->read_response(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function read_response()  | ||||||
|  |     { | ||||||
|  |         $reply = trim(fgets($this->redis_socket, 1024)); | ||||||
|  |         switch (substr($reply, 0, 1)) | ||||||
|  |         { | ||||||
|  |         case '-': | ||||||
|  |             throw new Exception(trim(substr($reply, 1))); | ||||||
|  |             break; | ||||||
|  |         case '+': | ||||||
|  |             $response = substr(trim($reply), 1); | ||||||
|  |             if ($response === 'OK')  | ||||||
|  |             { | ||||||
|  |                 $response = TRUE; | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case '$': | ||||||
|  |             $response = NULL; | ||||||
|  |             if ($reply == '$-1')  | ||||||
|  |             { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             $read = 0; | ||||||
|  |             $size = intval(substr($reply, 1)); | ||||||
|  |             if ($size > 0)  | ||||||
|  |             { | ||||||
|  |                 do  | ||||||
|  |                 { | ||||||
|  |                     $block_size = ($size - $read) > 1024 ? 1024 : ($size - $read); | ||||||
|  |                     $r = fread($this->redis_socket, $block_size); | ||||||
|  |                     if ($r === FALSE)  | ||||||
|  |                     { | ||||||
|  |                         throw new Exception('Failed to read response from stream'); | ||||||
|  |                     } | ||||||
|  |                     else  | ||||||
|  |                     { | ||||||
|  |                         $read += strlen($r); | ||||||
|  |                         $response .= $r; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 while ($read < $size); | ||||||
|  |             } | ||||||
|  |             fread($this->redis_socket, 2); /* discard crlf */ | ||||||
|  |             break; | ||||||
|  |             /* Multi-bulk reply */ | ||||||
|  |         case '*': | ||||||
|  |             $count = intval(substr($reply, 1)); | ||||||
|  |             if ($count == '-1')  | ||||||
|  |             { | ||||||
|  |                 return NULL; | ||||||
|  |             } | ||||||
|  |             $response = array(); | ||||||
|  |             for ($i = 0; $i < $count; $i++)  | ||||||
|  |             { | ||||||
|  |                 $response[] = $this->read_response(); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |             /* Integer reply */ | ||||||
|  |         case ':': | ||||||
|  |             $response = intval(substr(trim($reply), 1)); | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             throw new RedisException("Unknown response: {$reply}"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         return $response; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //$redis = new cls_redis_client(); | ||||||
|  | //var_dump($redis->auth("foobared")); | ||||||
|  | //var_dump($redis->set("name",'abc')); | ||||||
|  | //var_dump($redis->get("name")); | ||||||
|  |   | ||||||
							
								
								
									
										179
									
								
								vendor/owner888/phpspider/library/cls_redis_server.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								vendor/owner888/phpspider/library/cls_redis_server.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | |||||||
|  | <?php | ||||||
|  | ini_set("memory_limit", "128M"); | ||||||
|  | /** | ||||||
|  |  * redis 服务端  | ||||||
|  |  * 多进程阻塞式 | ||||||
|  |  * redis-benchmark -h 127.0.0.1 -p 11211 -t set -n 80000 -q | ||||||
|  |  *  | ||||||
|  |  * @version 2.7.0 | ||||||
|  |  * @copyright 1997-2018 The PHP Group | ||||||
|  |  * @author seatle <seatle@foxmail.com>  | ||||||
|  |  * @created time :2018-01-03 | ||||||
|  |  */ | ||||||
|  | class cls_redis_server | ||||||
|  | { | ||||||
|  |     private $socket = false; | ||||||
|  |     private $process_num = 3; | ||||||
|  |     public $redis_kv_data = array(); | ||||||
|  |     public $onMessage = null; | ||||||
|  |  | ||||||
|  |     public function __construct($host="0.0.0.0", $port=6379) | ||||||
|  |     { | ||||||
|  |         $this->socket = stream_socket_server("tcp://".$host.":".$port,$errno, $errstr); | ||||||
|  |         if (!$this->socket) die($errstr."--".$errno); | ||||||
|  |         echo "listen $host $port \r\n"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function parse_resp(&$conn) | ||||||
|  |     { | ||||||
|  |         // 读取一行,遇到 \r\n 为一行 | ||||||
|  |         $line = fgets($conn); | ||||||
|  |         if($line === '' || $line === false) | ||||||
|  |         { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         // 获取第一个字符作为类型 | ||||||
|  |         $type = $line[0]; | ||||||
|  |         // 去掉第一个字符,去掉结尾的 \r\n | ||||||
|  |         $line = mb_substr($line, 1, -2); | ||||||
|  |         switch ( $type ) | ||||||
|  |         { | ||||||
|  |         case "*": | ||||||
|  |             // 得到长度 | ||||||
|  |             $count = (int) $line; | ||||||
|  |             $data = array(); | ||||||
|  |             for ($i = 1; $i <= $count; $i++)  | ||||||
|  |             { | ||||||
|  |                 $data[] = $this->parse_resp($conn); | ||||||
|  |             } | ||||||
|  |             return $data; | ||||||
|  |         case "$": | ||||||
|  |             if ($line == '-1')  | ||||||
|  |             { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |             // 截取的长度要加上 \r\n 两个字符 | ||||||
|  |             $length = $line + 2; | ||||||
|  |             $data = ''; | ||||||
|  |             while ($length > 0)  | ||||||
|  |             { | ||||||
|  |                 $block = fread($conn, $length); | ||||||
|  |                 if ($length !== strlen($block))  | ||||||
|  |                 { | ||||||
|  |                     throw new Exception('RECEIVING'); | ||||||
|  |                 } | ||||||
|  |                 $data .= $block; | ||||||
|  |                 $length -= mb_strlen($block); | ||||||
|  |             } | ||||||
|  |             return mb_substr($data, 0, -2); | ||||||
|  |         } | ||||||
|  |         return $line; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function start_worker_process() | ||||||
|  |     { | ||||||
|  |         $pid = pcntl_fork(); | ||||||
|  |         switch ($pid)  | ||||||
|  |         { | ||||||
|  |         case -1: | ||||||
|  |             echo "fork error : {$i} \r\n"; | ||||||
|  |             exit; | ||||||
|  |         case 0: | ||||||
|  |             while ( true )  | ||||||
|  |             { | ||||||
|  |                 echo  "PID ".posix_getpid()." waiting...\n"; | ||||||
|  |                 // 堵塞等待 | ||||||
|  |                 $conn = stream_socket_accept($this->socket, -1); | ||||||
|  |                 if ( !$conn ) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 //"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n" | ||||||
|  |                 while( true ) | ||||||
|  |                 { | ||||||
|  |                     $arr = $this->parse_resp($conn); | ||||||
|  |                     if ( is_array($arr) )  | ||||||
|  |                     { | ||||||
|  |                         if ($this->onMessage)  | ||||||
|  |                         { | ||||||
|  |                             call_user_func($this->onMessage, $conn, $arr); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     else if ( $arr ) | ||||||
|  |                     { | ||||||
|  |                         if ($this->onMessage)  | ||||||
|  |                         { | ||||||
|  |                             call_user_func($this->onMessage, $conn, $arr); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         fclose($conn); | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         default: | ||||||
|  |             $this->pids[$pid] = $pid; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function run() | ||||||
|  |     { | ||||||
|  |         for($i = 1; $i <= $this->process_num; $i++) | ||||||
|  |         { | ||||||
|  |             $this->start_worker_process(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         while( true ) | ||||||
|  |         { | ||||||
|  |             foreach ($this->pids as $i => $pid)  | ||||||
|  |             { | ||||||
|  |                 if($pid)  | ||||||
|  |                 { | ||||||
|  |                     $res = pcntl_waitpid($pid, $status,WNOHANG); | ||||||
|  |  | ||||||
|  |                     if ( $res == -1 || $res > 0 ) | ||||||
|  |                     { | ||||||
|  |                         $this->start_worker_process(); | ||||||
|  |                         unset($this->pids[$pid]); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             sleep(1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $server = new cls_redis_server(); | ||||||
|  | $server->onMessage = function($conn, $info) use($server) | ||||||
|  | { | ||||||
|  |     if ( is_array($info) ) | ||||||
|  |     { | ||||||
|  |         $command = strtoupper($info[0]); | ||||||
|  |         if ( $command == "SET" ) | ||||||
|  |         { | ||||||
|  |             $key = $info[1]; | ||||||
|  |             $val = $info[2]; | ||||||
|  |             $server->redis_kv_data[$key] = $val; | ||||||
|  |             fwrite($conn, "+OK\r\n"); | ||||||
|  |         } | ||||||
|  |         else if ( $command == "GET" ) | ||||||
|  |         { | ||||||
|  |             $key = $info[1]; | ||||||
|  |             $val = isset($server->redis_kv_data[$key]) ? $server->redis_kv_data[$key] : ''; | ||||||
|  |             fwrite($conn, "$".strlen($val)."\r\n".$val."\r\n"); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             fwrite($conn,"+OK\r\n"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         fwrite($conn,"+OK\r\n"); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | $server->run(); | ||||||
							
								
								
									
										5727
									
								
								vendor/owner888/phpspider/library/phpquery.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5727
									
								
								vendor/owner888/phpspider/library/phpquery.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										466
									
								
								vendor/owner888/phpspider/library/rolling_curl.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								vendor/owner888/phpspider/library/rolling_curl.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,466 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Curl操作类 | ||||||
|  |  * | ||||||
|  |  * Licensed under The MIT License | ||||||
|  |  * For full copyright and license information, please see the MIT-LICENSE.txt | ||||||
|  |  * Redistributions of files must retain the above copyright notice. | ||||||
|  |  * | ||||||
|  |  * @author seatle<seatle@foxmail.com> | ||||||
|  |  * @copyright seatle<seatle@foxmail.com> | ||||||
|  |  * @link http://www.epooll.com/ | ||||||
|  |  * @license http://www.opensource.org/licenses/mit-license.php MIT License | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | class rolling_curl | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * @var float | ||||||
|  |      * | ||||||
|  |      * 同时运行任务数 | ||||||
|  |      * 例如:有8个请求,则会被分成两批,第一批5个请求,第二批3个请求 | ||||||
|  |      * 注意:采集知乎的时候,5个是比较稳定的,7个以上就开始会超时了,多进程就没有这样的问题,因为多进程很少几率会发生并发 | ||||||
|  |      */ | ||||||
|  |     public $window_size = 5; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var float | ||||||
|  |      * | ||||||
|  |      * Timeout is the timeout used for curl_multi_select. | ||||||
|  |      */ | ||||||
|  |     private $timeout = 10; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var string|array | ||||||
|  |      * | ||||||
|  |      * 应用在每个请求的回调函数 | ||||||
|  |      */ | ||||||
|  |     public $callback; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var array | ||||||
|  |      * | ||||||
|  |      * 设置默认的请求参数 | ||||||
|  |      */ | ||||||
|  |     protected $options = array( | ||||||
|  |         CURLOPT_SSL_VERIFYPEER => 0, | ||||||
|  |         CURLOPT_RETURNTRANSFER => 1, | ||||||
|  |         // 注意:TIMEOUT = CONNECTTIMEOUT + 数据获取时间,所以 TIMEOUT 一定要大于 CONNECTTIMEOUT,否则 CONNECTTIMEOUT 设置了就没意义  | ||||||
|  |         // "Connection timed out after 30001 milliseconds" | ||||||
|  |         CURLOPT_CONNECTTIMEOUT => 30, | ||||||
|  |         CURLOPT_TIMEOUT => 60, | ||||||
|  |         CURLOPT_RETURNTRANSFER => 1, | ||||||
|  |         CURLOPT_HEADER => 0, | ||||||
|  |         // 在多线程处理场景下使用超时选项时,会忽略signals对应的处理函数,但是无耐的是还有小概率的crash情况发生 | ||||||
|  |         CURLOPT_NOSIGNAL => 1, | ||||||
|  |         CURLOPT_USERAGENT => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36", | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var array | ||||||
|  |      */ | ||||||
|  |     private $headers = array(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var Request[] | ||||||
|  |      * | ||||||
|  |      * 请求队列 | ||||||
|  |      */ | ||||||
|  |     private $requests = array(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @var RequestMap[] | ||||||
|  |      * | ||||||
|  |      * Maps handles to request indexes | ||||||
|  |      */ | ||||||
|  |     private $requestMap = array(); | ||||||
|  |  | ||||||
|  |     public function __construct() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * set timeout | ||||||
|  |      * | ||||||
|  |      * @param init $timeout | ||||||
|  |      * @return | ||||||
|  |      */ | ||||||
|  |     public function set_timeout($timeout) | ||||||
|  |     { | ||||||
|  |         $this->options[CURLOPT_TIMEOUT] = $timeout; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * set proxy | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |     public function set_proxy($proxy) | ||||||
|  |     { | ||||||
|  |         $this->options[CURLOPT_PROXY] = $proxy; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * set referer | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |     public function set_referer($referer) | ||||||
|  |     { | ||||||
|  |         $this->options[CURLOPT_REFERER] = $referer; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置 user_agent | ||||||
|  |      * | ||||||
|  |      * @param string $useragent | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function set_useragent($useragent) | ||||||
|  |     { | ||||||
|  |         $this->options[CURLOPT_USERAGENT] = $useragent; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置COOKIE | ||||||
|  |      * | ||||||
|  |      * @param string $cookie | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function set_cookie($cookie) | ||||||
|  |     { | ||||||
|  |         $this->options[CURLOPT_COOKIE] = $cookie; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置COOKIE JAR | ||||||
|  |      * | ||||||
|  |      * @param string $cookie_jar | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function set_cookiejar($cookiejar) | ||||||
|  |     { | ||||||
|  |         $this->options[CURLOPT_COOKIEJAR] = $cookiejar; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置COOKIE FILE | ||||||
|  |      * | ||||||
|  |      * @param string $cookie_file | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function set_cookiefile($cookiefile) | ||||||
|  |     { | ||||||
|  |         $this->options[CURLOPT_COOKIEFILE] = $cookiefile; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取内容的时候是不是连header也一起获取 | ||||||
|  |      *  | ||||||
|  |      * @param mixed $http_raw | ||||||
|  |      * @return void | ||||||
|  |      * @author seatle <seatle@foxmail.com>  | ||||||
|  |      * @created time :2016-09-18 10:17 | ||||||
|  |      */ | ||||||
|  |     public function set_http_raw($http_raw = false) | ||||||
|  |     { | ||||||
|  |         $this->options[CURLOPT_HEADER] = $http_raw; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置IP | ||||||
|  |      * | ||||||
|  |      * @param string $ip | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function set_ip($ip) | ||||||
|  |     { | ||||||
|  |         $headers = array( | ||||||
|  |             'CLIENT-IP'=>$ip, | ||||||
|  |             'X-FORWARDED-FOR'=>$ip, | ||||||
|  |         ); | ||||||
|  |         $this->headers = $this->headers + $headers; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置Headers | ||||||
|  |      * | ||||||
|  |      * @param string $headers | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function set_headers($headers) | ||||||
|  |     { | ||||||
|  |         $this->headers = $this->headers + $headers; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置Hosts | ||||||
|  |      * | ||||||
|  |      * @param string $hosts | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function set_hosts($hosts) | ||||||
|  |     { | ||||||
|  |         $headers = array( | ||||||
|  |             'Host'=>$hosts, | ||||||
|  |         ); | ||||||
|  |         $this->headers = $this->headers + $headers; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设置Gzip | ||||||
|  |      * | ||||||
|  |      * @param string $hosts | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function set_gzip($gzip) | ||||||
|  |     { | ||||||
|  |         if ($gzip)  | ||||||
|  |         { | ||||||
|  |             $this->options[CURLOPT_ENCODING] = 'gzip'; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function request($url, $method = "GET", $fields = array(), $headers = array(), $options = array()) | ||||||
|  |     { | ||||||
|  |         $this->requests[] = array('url'=>$url,'method'=>$method,'fields'=>$fields,'headers'=>$headers,'options'=>$options); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function get_options($request) | ||||||
|  |     { | ||||||
|  |         $options = $this->options; | ||||||
|  |         $headers = $this->headers; | ||||||
|  |  | ||||||
|  |         if (ini_get('safe_mode') == 'Off' || !ini_get('safe_mode'))  | ||||||
|  |         { | ||||||
|  |             $options[CURLOPT_FOLLOWLOCATION] = 1; | ||||||
|  |             $options[CURLOPT_MAXREDIRS] = 5; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 如果是 get 方式,直接拼凑一个 url 出来 | ||||||
|  |         if (strtolower($request['method']) == 'get' && !empty($request['fields']))  | ||||||
|  |         { | ||||||
|  |             $url = $request['url'] . "?" . http_build_query($request['fields']); | ||||||
|  |         } | ||||||
|  |         // 如果是 post 方式 | ||||||
|  |         if (strtolower($request['method']) == 'post') | ||||||
|  |         { | ||||||
|  |             $options[CURLOPT_POST] = 1; | ||||||
|  |             $options[CURLOPT_POSTFIELDS] = $request['fields']; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // append custom options for this specific request | ||||||
|  |         if ($request['options'])  | ||||||
|  |         { | ||||||
|  |             $options = $request['options'] + $options; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if ($request['headers'])  | ||||||
|  |         { | ||||||
|  |             $headers = $request['headers'] + $headers; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 随机绑定 hosts,做负载均衡 | ||||||
|  |         //if (self::$hosts)  | ||||||
|  |         //{ | ||||||
|  |             //$parse_url = parse_url($url); | ||||||
|  |             //$host = $parse_url['host']; | ||||||
|  |             //$key = rand(0, count(self::$hosts)-1); | ||||||
|  |             //$ip = self::$hosts[$key]; | ||||||
|  |             //$url = str_replace($host, $ip, $url); | ||||||
|  |             //self::$headers = array_merge( array('Host:'.$host), self::$headers ); | ||||||
|  |         //} | ||||||
|  |  | ||||||
|  |         // header 要这样拼凑 | ||||||
|  |         $headers_tmp = array(); | ||||||
|  |         foreach ($headers as $k=>$v)  | ||||||
|  |         { | ||||||
|  |             $headers_tmp[] = $k.":".$v; | ||||||
|  |         } | ||||||
|  |         $headers = $headers_tmp; | ||||||
|  |  | ||||||
|  |         $options[CURLOPT_URL] = $request['url']; | ||||||
|  |         $options[CURLOPT_HTTPHEADER] = $headers; | ||||||
|  |  | ||||||
|  |         return $options; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * GET 请求 | ||||||
|  |      * | ||||||
|  |      * @param string $url | ||||||
|  |      * @param array $headers | ||||||
|  |      * @param array $options | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function get($url, $fields = array(), $headers = array(), $options = array()) | ||||||
|  |     { | ||||||
|  |         return $this->request($url, 'get', $fields, $headers, $options); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * $fields 有三种类型:1、数组;2、http query;3、json | ||||||
|  |      * 1、array('name'=>'yangzetao') 2、http_build_query(array('name'=>'yangzetao')) 3、json_encode(array('name'=>'yangzetao')) | ||||||
|  |      * 前两种是普通的post,可以用$_POST方式获取 | ||||||
|  |      * 第三种是post stream( json rpc,其实就是webservice ),虽然是post方式,但是只能用流方式 http://input 后者 $HTTP_RAW_POST_DATA 获取  | ||||||
|  |      *  | ||||||
|  |      * @param string $url  | ||||||
|  |      * @param array $fields  | ||||||
|  |      * @param array $headers | ||||||
|  |      * @param array $options | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function post($url, $fields = array(), $headers = array(), $options = array()) | ||||||
|  |     { | ||||||
|  |         return $this->request($url, 'post', $fields, $headers, $options); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Execute processing | ||||||
|  |      * | ||||||
|  |      * @param int $window_size Max number of simultaneous connections | ||||||
|  |      * @return string|bool | ||||||
|  |      */ | ||||||
|  |     public function execute($window_size = null)  | ||||||
|  |     { | ||||||
|  |         $count = sizeof($this->requests); | ||||||
|  |         if ($count == 0)  | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         // 只有一个请求 | ||||||
|  |         elseif ($count == 1)  | ||||||
|  |         { | ||||||
|  |             return $this->single_curl(); | ||||||
|  |         } | ||||||
|  |         else  | ||||||
|  |         { | ||||||
|  |             // 开始 rolling curl,window_size 是最大同时连接数 | ||||||
|  |             return $this->rolling_curl($window_size); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function single_curl()  | ||||||
|  |     { | ||||||
|  |         $ch = curl_init(); | ||||||
|  |         // 从请求队列里面弹出一个来 | ||||||
|  |         $request = array_shift($this->requests); | ||||||
|  |         $options = $this->get_options($request); | ||||||
|  |         curl_setopt_array($ch, $options); | ||||||
|  |         $output = curl_exec($ch); | ||||||
|  |         $info = curl_getinfo($ch); | ||||||
|  |         $error = null; | ||||||
|  |         if ($output === false) | ||||||
|  |         { | ||||||
|  |             $error = curl_error( $ch ); | ||||||
|  |         } | ||||||
|  |         //$output = substr($output, 10); | ||||||
|  |         //$output = gzinflate($output); | ||||||
|  |  | ||||||
|  |         // 其实一个请求的时候没是么必要回调,直接返回数据就好了,不过这里算是多一个功能吧,和多请求保持一样的操作 | ||||||
|  |         if ($this->callback) | ||||||
|  |         { | ||||||
|  |             if (is_callable($this->callback)) | ||||||
|  |             { | ||||||
|  |                 call_user_func($this->callback, $output, $info, $request, $error); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             return $output; | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function rolling_curl($window_size = null)  | ||||||
|  |     { | ||||||
|  |         // 如何设置了最大任务数 | ||||||
|  |         if ($window_size) | ||||||
|  |             $this->window_size = $window_size; | ||||||
|  |  | ||||||
|  |         // 如果请求数 小于 任务数,设置任务数为请求数 | ||||||
|  |         if (sizeof($this->requests) < $this->window_size) | ||||||
|  |             $this->window_size = sizeof($this->requests); | ||||||
|  |  | ||||||
|  |         // 如果任务数小于2个,不应该用这个方法的,用上面的single_curl方法就好了 | ||||||
|  |         if ($this->window_size < 2)  | ||||||
|  |             exit("Window size must be greater than 1"); | ||||||
|  |  | ||||||
|  |         // 初始化任务队列 | ||||||
|  |         $master = curl_multi_init(); | ||||||
|  |  | ||||||
|  |         // 开始第一批请求 | ||||||
|  |         for ($i = 0; $i < $this->window_size; $i++) | ||||||
|  |         { | ||||||
|  |             $ch = curl_init(); | ||||||
|  |             $options = $this->get_options($this->requests[$i]); | ||||||
|  |             curl_setopt_array($ch, $options); | ||||||
|  |             curl_multi_add_handle($master, $ch); | ||||||
|  |             // 添加到请求数组 | ||||||
|  |             $key = (string) $ch; | ||||||
|  |             $this->requestMap[$key] = $i; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         do { | ||||||
|  |             while (($execrun = curl_multi_exec($master, $running)) == CURLM_CALL_MULTI_PERFORM) ; | ||||||
|  |  | ||||||
|  |             // 如果 | ||||||
|  |             if ($execrun != CURLM_OK) { break; } | ||||||
|  |  | ||||||
|  |             // 一旦有一个请求完成,找出来,因为curl底层是select,所以最大受限于1024 | ||||||
|  |             while ($done = curl_multi_info_read($master))  | ||||||
|  |             { | ||||||
|  |                 // 从请求中获取信息、内容、错误 | ||||||
|  |                 $info = curl_getinfo($done['handle']); | ||||||
|  |                 $output = curl_multi_getcontent($done['handle']); | ||||||
|  |                 $error = curl_error($done['handle']); | ||||||
|  |  | ||||||
|  |                 // 如果绑定了回调函数 | ||||||
|  |                 $callback = $this->callback; | ||||||
|  |                 if (is_callable($callback))  | ||||||
|  |                 { | ||||||
|  |                     $key = (string) $done['handle']; | ||||||
|  |                     $request = $this->requests[$this->requestMap[$key]]; | ||||||
|  |                     unset($this->requestMap[$key]); | ||||||
|  |                     call_user_func($callback, $output, $info, $request, $error); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // 一个请求完了,就加一个进来,一直保证5个任务同时进行 | ||||||
|  |                 if ($i < sizeof($this->requests) && isset($this->requests[$i]) && $i < count($this->requests)) | ||||||
|  |                 { | ||||||
|  |                     $ch = curl_init(); | ||||||
|  |                     $options = $this->get_options($this->requests[$i]); | ||||||
|  |                     curl_setopt_array($ch, $options); | ||||||
|  |                     curl_multi_add_handle($master, $ch); | ||||||
|  |  | ||||||
|  |                     // 添加到请求数组 | ||||||
|  |                     $key = (string) $ch; | ||||||
|  |                     $this->requestMap[$key] = $i; | ||||||
|  |                     $i++; | ||||||
|  |                 } | ||||||
|  |                 // 把请求已经完成了得 curl handle 删除 | ||||||
|  |                 curl_multi_remove_handle($master, $done['handle']); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // 当没有数据的时候进行堵塞,把 CPU 使用权交出来,避免上面 do 死循环空跑数据导致 CPU 100% | ||||||
|  |             if ($running) | ||||||
|  |             { | ||||||
|  |                 curl_multi_select($master, $this->timeout); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         } while ($running); | ||||||
|  |         // 关闭任务 | ||||||
|  |         curl_multi_close($master); | ||||||
|  |  | ||||||
|  |         // 把请求清空,否则没有重新 new rolling_curl(); 直接再次导入一批url的时候,就会把前面已经执行过的url又执行一轮 | ||||||
|  |         unset($this->requests); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function __destruct() | ||||||
|  |     { | ||||||
|  |         unset($this->window_size, $this->callback, $this->options, $this->headers, $this->requests); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								vendor/owner888/phpspider/test.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/owner888/phpspider/test.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $arr = array('fff', 'ggg', '', ''); | ||||||
|  | $arr = array_filter($arr); | ||||||
|  | print_r($arr); | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										32
									
								
								vendor/owner888/phpspider/worker.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/owner888/phpspider/worker.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | echo "Starting\n"; | ||||||
|  |  | ||||||
|  | $gmworker = new GearmanWorker(); | ||||||
|  | $gmworker->addServer('10.10.10.238'); | ||||||
|  | $gmworker->addFunction("reverse", "reverse_fn"); | ||||||
|  |  | ||||||
|  | print "Waiting for job...\n"; | ||||||
|  | while($gmworker->work()) | ||||||
|  | { | ||||||
|  |     if ($gmworker->returnCode() != GEARMAN_SUCCESS) | ||||||
|  |     { | ||||||
|  |         echo "return_code: " . $gmworker->returnCode() . "\n"; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     //break; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function reverse_fn($job) | ||||||
|  | { | ||||||
|  |     sleep(3); | ||||||
|  |     echo $job->workload()."\n"; | ||||||
|  |     return strrev($job->workload()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | echo "hello\n"; | ||||||
|  | ?> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								wiki/Home.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								wiki/Home.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | ## 功能 | ||||||
|  | IYUU自动辅种工具,目前能对国内大部分的PT站点自动辅种;支持下载器集群,支持多盘位,支持多下载目录,支持远程连接等。 | ||||||
|  |  | ||||||
|  | ## 原理 | ||||||
|  | IYUU自动辅种工具(英文名:iyuuAutoReseed),是一款PHP语言编写的Private Tracker辅种脚本,通过计划任务或常驻内存,按指定频率调用transmission、qBittorrent下载软件的API接口,提取正在做种的info_hash提交到服务器API接口,根据API接口返回的数据拼接种子连接,提交给下载器,自动辅种各个站点。 | ||||||
|  |  | ||||||
|  | ## 运行环境 | ||||||
|  | 所有具备PHP运行环境的所有平台! | ||||||
|  | 例如:Linux、Windows、MacOS | ||||||
|  |  | ||||||
|  | ## 需求提交/错误反馈 | ||||||
|  |  - 点击链接加入群聊【IYUU自动辅种交流】:[https://jq.qq.com/?_wv=1027&k=5JOfOlM][1] | ||||||
|  |  | ||||||
|  | ## 捐助开发者 | ||||||
|  | 如果觉得我的付出,节约了您的宝贵时间,请随意打赏一杯咖啡!或者一杯水! | ||||||
|  | 您所有的打赏将用于服务器续期,增加服务的延续性。 | ||||||
|  | ![微信打赏.png][2] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | [1]: https://jq.qq.com/?_wv=1027&k=5JOfOlM | ||||||
|  | [2]: https://www.iyuu.cn/usr/uploads/2019/12/801558607.png | ||||||
							
								
								
									
										27
									
								
								wiki/合作站点鉴权配置.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								wiki/合作站点鉴权配置.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | ## 重点讲解Ourbits站点的鉴权配置 | ||||||
|  | 博客链接:https://www.iyuu.cn/archives/337/ | ||||||
|  | IYUU自动辅种工具、Ourbits双方达成合作,可以对使用接口的用户,实现认证。 | ||||||
|  | ### 申请爱语飞飞微信通知token,新用户访问:http://iyuu.cn 申请! | ||||||
|  | 1.点击`开始使用`,出现二维码,用`微信扫码` | ||||||
|  | ![微信通知1.png][1] | ||||||
|  | ![微信通知2.png][2] | ||||||
|  | ![微信通知3.png][3] | ||||||
|  | 2.复制您的token令牌到`/app/config/config.php`文件内的`iyuu.cn`对应的配置字段,保存。如图: | ||||||
|  | ![微信通知4.png][4] | ||||||
|  |  | ||||||
|  | ### 设置Ourbits: | ||||||
|  | ![编辑配置4.png][5] | ||||||
|  | `passkey`,在你的控制面板 - 密钥 | ||||||
|  | `is_vip`,根据你的实际情况填写,因站点有下载种子的流控,如果你不在限制之列,可以`设置为1` | ||||||
|  | `id`,为用户中心打开后,浏览器地址栏**http://xxxxx.xxx/userdetails.php?id=`46880`**等号=后面的几个数字,如图: | ||||||
|  | ![编辑配置6.png][6] | ||||||
|  |  | ||||||
|  | 到此,配置文件编辑完毕,请记得保存。 | ||||||
|  | 如果提示保存格式,请保存为UTF8(无BOM)格式。 | ||||||
|  |  | ||||||
|  |   [1]: https://www.iyuu.cn/usr/uploads/2019/12/2331433923.png | ||||||
|  |   [2]: https://www.iyuu.cn/usr/uploads/2019/12/3324442680.png | ||||||
|  |   [3]: https://www.iyuu.cn/usr/uploads/2019/12/3181272964.png | ||||||
|  |   [4]: https://www.iyuu.cn/usr/uploads/2019/12/3669828008.png | ||||||
|  |   [5]: https://www.iyuu.cn/usr/uploads/2019/12/3696916642.png | ||||||
|  |   [6]: https://www.iyuu.cn/usr/uploads/2019/12/1230288911.png | ||||||
							
								
								
									
										10
									
								
								wiki/命令汇总.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								wiki/命令汇总.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | ## 【特别提示】 | ||||||
|  | php命令与脚本路径之间是有个空格,请注意!请注意!请注意! | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## IYUU自动辅种命令: | ||||||
|  | `php ./iyuu.cn.php` | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### 【重要说明:实际路径,以你实际的为准,切勿生搬硬套!】 | ||||||
							
								
								
									
										83
									
								
								wiki/常见问题.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								wiki/常见问题.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | |||||||
|  | ## 常见问题FAQ | ||||||
|  |  | ||||||
|  | #### 问:这款脚本会不会泄露我的秘钥、cookie、客户端连接密码? | ||||||
|  |  | ||||||
|  | 答:绝对不会!!代码全开源,能经受审查!所有私密配置只在本地存储使用,绝不会发送给任何第三方。 | ||||||
|  |  | ||||||
|  | #### 问:只使用IYUU自动辅种,需要配置各站的cookie吗? | ||||||
|  |  | ||||||
|  | 答:只需配置全局客户端和各网站的passkey密钥(没有配置passkey的站点,在辅种时候会跳过)。2019年12月28日补充:辅种hdcity、hdchina需要配置cookie。 | ||||||
|  |  | ||||||
|  | #### 问:IYUU自动辅种工具,向服务器发送了什么实现自动辅种呢? | ||||||
|  |  | ||||||
|  | 答:1.文件`phpspider\app\torrent\cache\hashString.txt`是脚本发送给服务器的数据,是按下载器分组的种子info_hash;2.文件`phpspider\app\torrent\cache\reseed.txt`是服务器返回的可辅种数据。 | ||||||
|  |  | ||||||
|  | #### 问:本次添加成功的辅种任务,下次辅种时还会重复添加吗? | ||||||
|  |  | ||||||
|  | 答:添加成功的辅种任务,会在本地生成缓存记录,避免重复添加辅种任务,路径在:`phpspider\app\torrent\cachehash`。 | ||||||
|  |  | ||||||
|  | #### 问:为什么有些站点自动跳过? | ||||||
|  |  | ||||||
|  | 答:因为站点在下载种子时有流控或者人机验证,会导致辅种失败;但脚本会在`phpspider\app\torrent\cache`目录下生成以站点命名的手动辅种文本。 | ||||||
|  |  | ||||||
|  | #### 问:我拥有辅种时自动跳过站点的特殊权限,如何设置为可以辅种呢? | ||||||
|  |  | ||||||
|  | 答:在站点的独立配置区域,添加一行代码`'is_vip'   => 1,`即可。例如Ourbits: | ||||||
|  |  | ||||||
|  | ```php | ||||||
|  | // ourbits | ||||||
|  | 'ourbits'      => array( | ||||||
|  | 	// 如果需要用下载免费种脚本,须配置(只是自动辅种,可以不配置此项) | ||||||
|  | 	'cookie'        => '', | ||||||
|  | 	// 如果需要自动辅种,必须配置 | ||||||
|  | 	'passkey'       => '', | ||||||
|  | 	'id' 			=> 46880,	// 用户ID | ||||||
|  | 	'is_vip'		=> 1,		// 是否具有VIP或特殊权限?0 普通,1 VIP | ||||||
|  | ), | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #### 问:如何升级到最新版本? | ||||||
|  |  | ||||||
|  | 答:从github或码云仓库,下载最新的源码,覆盖到本地即可。 | ||||||
|  |  | ||||||
|  | #### 问:为啥我编辑配置后,运行的时候显示乱码? | ||||||
|  |  | ||||||
|  | 答:保存的编码格式不对,正确的格式为UTF8(无BOM);推荐编辑器:`VS code`、`EditPlu`s、`SublimeText`、`Notepad++`。 | ||||||
|  |  | ||||||
|  | #### 问:为什么用IYUU自动辅种,有些种子无法校验通过? | ||||||
|  |  | ||||||
|  | 答:首先,这个属于正常现象。 只要IYUU自动辅种匹配过来,然后校验通不过的,分为以下几种情况:  | ||||||
|  |  | ||||||
|  | 1、被改了文件名,重新做种  | ||||||
|  |  | ||||||
|  | 2、被改了顶层目录名,重新做种  | ||||||
|  |  | ||||||
|  | 3、把单文件放进了目录里面,重新做种  | ||||||
|  |  | ||||||
|  | 4、更改了部分文件,例如nfo文件,重新做种 | ||||||
|  |  | ||||||
|  | 一般情况下,通过分析种子结构,创建软连接,90%以上都可以辅种成功。 | ||||||
|  | 也可以不管他或删除校验失败的任务(不要删除数据)。  | ||||||
|  |  | ||||||
|  | #### 问:如何创建软连接、硬链接手动辅种? | ||||||
|  |  | ||||||
|  | 答:Windows命令: `mklink`, Linux命令: `ln -s`, 更详细的用法请百度。 | ||||||
|  |  | ||||||
|  | #### 问:IYUU自动辅种,添加计划任务后多久运行一次比较合适? | ||||||
|  |  | ||||||
|  | 答:为减轻服务器压力,推荐间隔3小时以上(太频繁的调用接口,可能被封禁)。 | ||||||
|  |  | ||||||
|  | #### 问:猫站的Tracker为啥是http,而不是https? | ||||||
|  |  | ||||||
|  | 答:请退出登录,在登录时勾选下面两个SSL的选项,登录后复制cookie,重新配置。 | ||||||
|  |  | ||||||
|  | #### 问:如何反馈问题? | ||||||
|  |  | ||||||
|  | 答:1、点击链接加入群聊【IYUU自动辅种交流】:[https://jq.qq.com/?_wv=1027&k=5JOfOlM][1] | ||||||
|  |  | ||||||
|  | 2、QQ群:859882209 | ||||||
|  |  | ||||||
|  | 3、issues: https://gitee.com/ledc/IYUUAutoReseed/issues  | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								wiki/开发计划.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								wiki/开发计划.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | ## 开发计划 | ||||||
|  | | 功能 | 开发状态 | 预计开发时间 | 开发完成时间 | | ||||||
|  | | - | :-: | ---- | ---- | | ||||||
|  | | 微信鉴权 | 已完成 | 2019年12月22日 | 2019年12月23日 | | ||||||
|  | | 流控站点,手动辅种 | 已完成 | 2019年12月24日 | 2019年12月24日 | | ||||||
|  | | m-team IPv4、IPv6自定义配置 | 已完成 | 2019年12月25日 | 2019年12月25日 | | ||||||
|  | | 未配置客户端智能过滤 | 已完成 | 2019年12月25日 | 2019年12月25日 | | ||||||
|  | | 自动辅种结束微信通知 | 已完成 | 2019年12月25日 | 2019年12月27日 | | ||||||
|  | | 做种客户端间转移 | 已完成 | 2019年12月25日 | 2020年1月14日 | | ||||||
|  | | 手动辅种按目录分组 | 已完成 | 2019年12月26日 | 2020年1月14日 | | ||||||
|  | | WEB页面生成配置 | 暂未开始 |  |  | | ||||||
|  | | 自动转移客户端 | 暂未开始 |  |  | | ||||||
|  | | 脚本docker容器化 | 暂未开始 |  | | | ||||||
|  | | 浏览器插件 | 暂未开始 |  | | | ||||||
|  | | 合集自动拆包辅种 | 暂未开始 |  |  | | ||||||
							
								
								
									
										109
									
								
								wiki/更新历史.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								wiki/更新历史.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | |||||||
|  | ### 2020年1月14日 | ||||||
|  |  | ||||||
|  | 更新hdbug域名,删除下载免费种冗余文件。 | ||||||
|  |  | ||||||
|  | ### 2020年1月10日 | ||||||
|  |  | ||||||
|  | 修复:qBittorrent打开自动管理时,自动辅种目录对应错误的问题。 | ||||||
|  |  | ||||||
|  | ### 2020年1月9日 | ||||||
|  |  | ||||||
|  | 优化:萌猫tracker的IP类型改为可配置; | ||||||
|  | 优化:自动辅种时添加的任务,校验后自动暂停(无需更改全局)。 | ||||||
|  |  | ||||||
|  | ### 2020年1月5日 | ||||||
|  |  | ||||||
|  | 修复:城市cuhash变化无法辅种的问题 | ||||||
|  |  | ||||||
|  | ### 2020年1月1日 | ||||||
|  |  | ||||||
|  | 新增:scg | ||||||
|  |  | ||||||
|  | 修复: | ||||||
|  |  | ||||||
|  | 1.转移客户端做种支持磁力链 | ||||||
|  |  | ||||||
|  | 2.萌猫抓取问题 | ||||||
|  |  | ||||||
|  | 3.瓷器抓取标题的问题 | ||||||
|  |  | ||||||
|  | ### 2019年12月27日 | ||||||
|  |  | ||||||
|  | 新增功能:自动辅种结束,微信通知统计信息,优化城市适配,新增discfan(GZT)。 | ||||||
|  |  | ||||||
|  | ### 2019年12月25日 | ||||||
|  |  | ||||||
|  | 1.新增支持upxin(HDU)、oshen | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年12月25日 | ||||||
|  | 1.馒头支持ipv4、ipv6选择 | ||||||
|  | 2.未配置的全局客户端智能过滤,不会再影响自动辅种 | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年12月24日 | ||||||
|  | 新增hdstreet、joyhd、u2 | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年12月23日 | ||||||
|  | 鉴权模式上线试运行 | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年12月21日 | ||||||
|  |  | ||||||
|  | 新增兽站、opencd、hdbug; | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年12月20日 | ||||||
|  |  | ||||||
|  | 新增1ptba、hdtime | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年12月17日 | ||||||
|  |  | ||||||
|  | 新增站点瓷器; | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年12月16日 | ||||||
|  |  | ||||||
|  | 新增leaguehd、聆音; | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年12月15日 | ||||||
|  |  | ||||||
|  | 1.自动辅种20个站; | ||||||
|  | 2.支持qBittorrent做种转transmission | ||||||
|  | 3.新增qBittorrent自动辅种时的状态过滤,只辅种已完成的种子 | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年12月12日 | ||||||
|  |  | ||||||
|  | 目前支持17个站点的自动辅种; | ||||||
|  | 目前支持18个站点下载免费种; | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年12月10日 | ||||||
|  |  | ||||||
|  | 自动辅种工具完成! | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ### 2019年11月19日 | ||||||
|  |  | ||||||
|  | 我堡、天空 完美适配,支持大小、做种数、下载数筛选。 | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | 技术讨论及后续更新,请加入QQ群! | ||||||
|  | **群名称:IYUU自动辅种交流** | ||||||
|  | **QQ群号:859882209** | ||||||
							
								
								
									
										102
									
								
								wiki/自动辅种最简配置(windows篇).md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								wiki/自动辅种最简配置(windows篇).md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | |||||||
|  | 以下教程以windows为基础进行讲解,其他系统同理。 | ||||||
|  | 博客链接:https://www.iyuu.cn/archives/324/ | ||||||
|  | ## 第一步 下载压缩包 | ||||||
|  | 从[码云仓库][1],下载最新源码,解压缩到D盘的根目录下。 | ||||||
|  |  | ||||||
|  | ## 第二步 复制一份配置文件 | ||||||
|  | 打开`D:\IYUUAutoReseed\app\config`目录,复制一份`config.sample.php`,另存为`config.php`。 | ||||||
|  |  | ||||||
|  | 这样操作后,需要升级新版本时,直接覆盖即可,不会影响到配置。 | ||||||
|  |  | ||||||
|  | ## 第三步 编辑配置文件 | ||||||
|  | 提醒:千万不要用windows记事本来编辑配置文件(会导致乱码)!! | ||||||
|  | 推荐编辑软件:`VS code`、`EditPlus`、`SublimeText`、`Notepad++`等(保存格式,选UTF8 无BOM); | ||||||
|  | 配置文件内容较多,新手往往很迷茫,不知道改哪里,在这里我重点强调2个步骤: | ||||||
|  | `1.编辑全局客户端; 2.编辑各站的秘钥,即passkey。` | ||||||
|  |  | ||||||
|  | 其他配置,如果不懂也没有关系;先保持默认,等脚本运行起来,再修改也不迟。另外,修改时一定要细心,仔细看教程。 | ||||||
|  | 打开`D:\IYUUAutoReseed\app\config\config.php`文件,如下图: | ||||||
|  | ![编辑配置1.png][2] | ||||||
|  |  | ||||||
|  | ### 填写全局客户端 | ||||||
|  | 上图红框内的是`transmission`的示例配置,绿框是`qBittorrent`的示例配置; | ||||||
|  | IYUU自动辅种工具,目前支持这两种下载器,支持多盘位,辅种时全自动对应资源的下载目录。 | ||||||
|  | 1,编辑`transmission`下载器 | ||||||
|  | `http://127.0.0.1:9091/transmission/rpc`是下载器的连接参数,你要修改的部分是`127.0.0.1:9091`改成你的IP与端口(本机使用无需修改),局域网内的机器请填写局域网IP与端口;远程使用请填写DDNS的远程连接域名与端口。 | ||||||
|  | username是用户名、password是密码。 | ||||||
|  | 如果你没有用到`transmission`下载器,请把红框的内容都删除。 | ||||||
|  |  | ||||||
|  | 2,编辑`qBittorrent`下载器 | ||||||
|  | 方法与上一步相同,只需填写ip、端口、用户名、密码即可。如果您是windows下的qBittorrent,请参考下图打开`WEB用户界面`: | ||||||
|  | ![qb设置WEB用户界面.png][3] | ||||||
|  |  | ||||||
|  | 因为我两个下载器都在用,编辑好后,如图: | ||||||
|  | ![编辑配置2.png][4] | ||||||
|  |  | ||||||
|  | ### 填写各站秘钥passkey | ||||||
|  | IYUU自动辅种:需要您配置各站的passkey(没有配置passkey的站点会自动跳过)。 | ||||||
|  | 从各站点的控制面板,找到您的`秘钥`复制粘贴过来即可。 | ||||||
|  | 配置好后如图: | ||||||
|  | ![编辑配置3.png][5] | ||||||
|  |  | ||||||
|  | ---------- | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## 第四步,重点讲解Ourbits站点的配置 | ||||||
|  | IYUU自动辅种工具、Ourbits双方达成合作,可以对使用接口的用户,实现认证。 | ||||||
|  | ### 申请爱语飞飞微信通知token,新用户访问:http://iyuu.cn 申请! | ||||||
|  | 1.点击`开始使用`,出现二维码,用`微信扫码` | ||||||
|  | ![微信通知1.png][6] | ||||||
|  | ![微信通知2.png][7] | ||||||
|  | ![微信通知3.png][8] | ||||||
|  | 2.复制您的token令牌到`/app/config/config.php`文件内的`iyuu.cn`对应的配置字段,保存。如图: | ||||||
|  | ![微信通知4.png][9] | ||||||
|  |  | ||||||
|  | ### 设置Ourbits: | ||||||
|  | ![编辑配置4.png][10] | ||||||
|  | `passkey`,在你的控制面板 - 密钥 | ||||||
|  | `is_vip`,根据你的实际情况填写,因站点有下载种子的流控,如果你不在限制之列,可以`设置为1` | ||||||
|  | `id`,为用户中心打开后,浏览器地址栏**http://xxxxx.xxx/userdetails.php?id=`46880`**等号=后面的几个数字,如图: | ||||||
|  | ![编辑配置6.png][11] | ||||||
|  |  | ||||||
|  | 到此,配置文件编辑完毕,请记得保存。 | ||||||
|  | 如果提示保存格式,请保存为UTF8(无BOM)格式。 | ||||||
|  |  | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ## 群晖、铁威马、威联通等Linux环境 | ||||||
|  |  | ||||||
|  | 经过上面步骤,其实已经完成了配置,只需要把脚本复制到设备内,用php命令运行脚本即可。 | ||||||
|  |  | ||||||
|  | 群晖php命令:`php` | ||||||
|  |  | ||||||
|  | 威联通php命令:`/mnt/ext/opt/apache/bin/php` | ||||||
|  |  | ||||||
|  | 铁威马php命令:`php` | ||||||
|  |  | ||||||
|  | ---------- | ||||||
|  |  | ||||||
|  | ## Windows安装PHP运行环境 | ||||||
|  | 也可以去官方下载【https://www.php.net/downloads】,官方下载的记得开启`curl、fileinfo、mbstring`,这3个扩展。 | ||||||
|  | 另外我打包了一份,下载地址: | ||||||
|  | 微云链接:https://share.weiyun.com/5EiXLfn 密码:ezsvnb | ||||||
|  | 下载回来是一个ZIP压缩包,解压到`D:\IYUUAutoReseed\`目录内,文件结构如图: | ||||||
|  | ![编辑配置7.png][12] | ||||||
|  | 点击红框内`执行辅种`即可。 | ||||||
|  | 如果你前期严格按照配置一步步操作,这里会正常显示跑动的辅种列表。正常如图: | ||||||
|  | ![编辑配置8.png][13] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | [1]: https://gitee.com/ledc/IYUUAutoReseed | ||||||
|  | [2]: https://www.iyuu.cn/usr/uploads/2019/12/2720183833.png | ||||||
|  | [3]: https://www.iyuu.cn/usr/uploads/2019/12/405587689.png | ||||||
|  | [4]: https://www.iyuu.cn/usr/uploads/2019/12/441257656.png | ||||||
|  | [5]: https://www.iyuu.cn/usr/uploads/2019/12/890327305.png | ||||||
|  | [6]: https://www.iyuu.cn/usr/uploads/2019/12/2331433923.png | ||||||
|  | [7]: https://www.iyuu.cn/usr/uploads/2019/12/3324442680.png | ||||||
|  | [8]: https://www.iyuu.cn/usr/uploads/2019/12/3181272964.png | ||||||
|  | [9]: https://www.iyuu.cn/usr/uploads/2019/12/3669828008.png | ||||||
|  | [10]: https://www.iyuu.cn/usr/uploads/2019/12/3696916642.png | ||||||
|  | [11]: https://www.iyuu.cn/usr/uploads/2019/12/1230288911.png | ||||||
|  | [12]: https://www.iyuu.cn/usr/uploads/2019/12/3189986236.png | ||||||
|  | [13]: https://www.iyuu.cn/usr/uploads/2019/12/2523845772.png | ||||||
		Reference in New Issue
	
	Block a user