private $login_method = 'SSO';\r
private $oim_send_url = 'https://ows.messenger.msn.com/OimWS/oim.asmx';\r
private $oim_send_soap = 'http://messenger.live.com/ws/2006/09/oim/Store2';\r
- private $windows;\r
- private $kill_me = false;\r
private $id;\r
private $ticket;\r
private $user = '';\r
private $password = '';\r
private $NSfp=false;\r
- private $SBfp;\r
private $passport_policy = '';\r
private $alias;\r
private $psm;\r
private $ChildProcess=array();\r
private $MAXChildProcess=3;\r
private $ReqSBXFRTimeout=60;\r
- private $SBTimeout=2;\r
private $LastPing;\r
private $ping_wait=50;\r
private $SBIdleTimeout=10;\r
- private $SBStreamTimeout=10;\r
+ private $SBStreamTimeout=2;\r
private $NSStreamTimeout=2;\r
private $MsnObjArray=array();\r
private $MsnObjMap=array();\r
\r
private $aContactList = array();\r
private $aADL = array();\r
+ private $re_login;\r
private $switchBoardSessions = array();\r
+ private $switchBoardSockets = array();\r
+ private $waitingForXFR = array();\r
\r
/**\r
* Event Handler Functions\r
private $myEventHandlers = array();\r
\r
// End added for StatusNet\r
-\r
- private function Array2SoapVar($Array,$ReturnSoapVarObj=true,$TypeName=null,$TypeNameSpace=null)\r
- {\r
- $ArrayString='';\r
- foreach($Array as $Key => $Val)\r
- {\r
- if($Key{0}==':') continue;\r
- $Attrib='';\r
- if(is_array($Val[':']))\r
- {\r
- foreach($Val[':'] as $AttribName => $AttribVal)\r
- $Attrib.=" $AttribName='$AttribVal'";\r
- }\r
- if($Key{0}=='!')\r
- {\r
- //List Type Define\r
- $Key=substr($Key,1);\r
- foreach($Val as $ListKey => $ListVal)\r
- {\r
- if($ListKey{0}==':') continue;\r
- if(is_array($ListVal)) $ListVal=$this->Array2SoapVar($ListVal,false);\r
- elseif(is_bool($ListVal)) $ListVal=$ListVal?'true':'false';\r
- $ArrayString.="<$Key$Attrib>$ListVal</$Key>";\r
- }\r
- continue;\r
- }\r
- if(is_array($Val)) $Val=$this->Array2SoapVar($Val,false);\r
- elseif(is_bool($Val)) $Val=$Val?'true':'false';\r
- $ArrayString.="<$Key$Attrib>$Val</$Key>";\r
- }\r
- if($ReturnSoapVarObj) return new SoapVar($ArrayString,XSD_ANYXML,$TypeName,$TypeNameSpace);\r
- return $ArrayString;\r
- }\r
-\r
- public function End()\r
- {\r
- $this->log_message("*** someone kill me ***");\r
- $this->kill_me=true;\r
- }\r
- private function IsIgnoreMail($Email)\r
- { \r
- if($this->IgnoreList==false) return false;\r
- foreach($this->IgnoreList as $Pattern)\r
- {\r
- if(preg_match($Pattern,$Email)) return true;\r
- }\r
- return false;\r
- }\r
+ \r
public function __construct ($Configs=array(), $timeout = 15, $client_id = 0x7000800C)\r
{\r
$this->user = $Configs['user'];\r
$this->password = $Configs['password'];\r
$this->alias = isset($Configs['alias']) ? $Configs['alias'] : '';\r
$this->psm = isset($Configs['psm']) ? $Configs['psm'] : '';\r
- $my_add_function = isset($Configs['add_user_function']) ? $Configs['add_user_function'] : false;\r
- $my_rem_function = isset($Configs['remove_user_function']) ? $Configs['remove_user_function'] : false;\r
$this->use_ping = isset($Configs['use_ping']) ? $Configs['use_ping'] : false;\r
$this->retry_wait = isset($Configs['retry_wait']) ? $Configs['retry_wait'] : 30;\r
$this->backup_file = isset($Configs['backup_file']) ? $Configs['backup_file'] : true;\r
$this->update_pending = isset($Configs['update_pending']) ? $Configs['update_pending'] : true;\r
$this->PhotoStickerFile=isset($Configs['PhotoSticker']) ? $Configs['PhotoSticker'] : false;\r
- $this->IgnoreList=isset($Configs['IgnoreList'])?$Configs['IgnoreList']:false;\r
if($this->Emotions = isset($Configs['Emotions']) ? $Configs['Emotions']:false)\r
{\r
foreach($this->Emotions as $EmotionFilePath)\r
- $this->MsnObj($EmotionFilePath,$Type=2);\r
+ $this->MsnObj($EmotionFilePath,$Type=2);\r
} \r
$this->debug = isset($Configs['debug']) ? $Configs['debug'] : false;\r
$this->timeout = $timeout;\r
= 0x7000800C;\r
*/\r
$this->clientid = $client_id;\r
- $this->windows =(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');\r
$this->ABService=new SoapClient(realpath(dirname(__FILE__)).'/soap/msnab_sharingservice.wsdl',array('trace' => 1));\r
}\r
\r
+ private function Array2SoapVar($Array,$ReturnSoapVarObj=true,$TypeName=null,$TypeNameSpace=null)\r
+ {\r
+ $ArrayString='';\r
+ foreach($Array as $Key => $Val)\r
+ {\r
+ if($Key{0}==':') continue;\r
+ $Attrib='';\r
+ if(is_array($Val[':']))\r
+ {\r
+ foreach($Val[':'] as $AttribName => $AttribVal)\r
+ $Attrib.=" $AttribName='$AttribVal'";\r
+ }\r
+ if($Key{0}=='!')\r
+ {\r
+ //List Type Define\r
+ $Key=substr($Key,1);\r
+ foreach($Val as $ListKey => $ListVal)\r
+ {\r
+ if($ListKey{0}==':') continue;\r
+ if(is_array($ListVal)) $ListVal=$this->Array2SoapVar($ListVal,false);\r
+ elseif(is_bool($ListVal)) $ListVal=$ListVal?'true':'false';\r
+ $ArrayString.="<$Key$Attrib>$ListVal</$Key>";\r
+ }\r
+ continue;\r
+ }\r
+ if(is_array($Val)) $Val=$this->Array2SoapVar($Val,false);\r
+ elseif(is_bool($Val)) $Val=$Val?'true':'false';\r
+ $ArrayString.="<$Key$Attrib>$Val</$Key>";\r
+ }\r
+ if($ReturnSoapVarObj) return new SoapVar($ArrayString,XSD_ANYXML,$TypeName,$TypeNameSpace);\r
+ return $ArrayString;\r
+ }\r
+ \r
private function get_passport_ticket($url = '')\r
{\r
$user = $this->user;\r
$password = htmlspecialchars($this->password);\r
\r
if ($url === '')\r
- $passport_url = $this->passport_url;\r
+ $passport_url = $this->passport_url;\r
else\r
- $passport_url = $url;\r
+ $passport_url = $url;\r
\r
$XML = '<?xml version="1.0" encoding="UTF-8"?>\r
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"\r
$this->ticket=$aTickets;\r
$this->debug_message(var_export($aTickets, true));\r
$ABAuthHeaderArray=array(\r
- 'ABAuthHeader'=>array(\r
- ':'=>array('xmlns'=>'http://www.msn.com/webservices/AddressBook'),\r
- 'ManagedGroupRequest'=>false,\r
- 'TicketToken'=>htmlspecialchars($this->ticket['contact_ticket']),\r
- )\r
+ 'ABAuthHeader'=>array(\r
+ ':'=>array('xmlns'=>'http://www.msn.com/webservices/AddressBook'),\r
+ 'ManagedGroupRequest'=>false,\r
+ 'TicketToken'=>htmlspecialchars($this->ticket['contact_ticket']),\r
+ )\r
);\r
$this->ABAuthHeader=new SoapHeader("http://www.msn.com/webservices/AddressBook","ABAuthHeader", $this->Array2SoapVar($ABAuthHeaderArray));\r
- file_put_contents('/tmp/STTicket.txt',htmlspecialchars($this->ticket['storage_ticket']));\r
- //$this->debug_message("StorageTicket:\n",htmlspecialchars($this->ticket['storage_ticket']));\r
return $aTickets;\r
}\r
+ \r
private function UpdateContacts()\r
{\r
$ABApplicationHeaderArray=array(\r
- 'ABApplicationHeader'=>array(\r
- ':'=>array('xmlns'=>'http://www.msn.com/webservices/AddressBook'),\r
- 'ApplicationId'=>'CFE80F9D-180F-4399-82AB-413F33A1FA11',\r
- 'IsMigration'=>false,\r
- 'PartnerScenario'=>'ContactSave'\r
- )\r
- );\r
- $ABApplicationHeader=new SoapHeader("http://www.msn.com/webservices/AddressBook",'ABApplicationHeader', $this->Array2SoapVar($ABApplicationHeaderArray));\r
- $ABFindAllArray=array(\r
- 'ABFindAll'=>array(\r
- ':'=>array('xmlns'=>'http://www.msn.com/webservices/AddressBook'),\r
- 'abId'=>'00000000-0000-0000-0000-000000000000',\r
- 'abView'=>'Full',\r
- 'lastChange'=>'0001-01-01T00:00:00.0000000-08:00',\r
- )\r
- );\r
- $ABFindAll=new SoapParam($this->Array2SoapVar($ABFindAllArray),'ABFindAll');\r
- $this->ABService->__setSoapHeaders(array($ABApplicationHeader,$this->ABAuthHeader));\r
- $this->Contacts=array();\r
- try\r
- {\r
- $this->debug_message("*** Update Contacts...");\r
- $Result=$this->ABService->ABFindAll($ABFindAll);\r
- $this->debug_message("*** Result:\n".print_r($Result,true)."\n".$this->ABService->__getLastResponse());\r
- foreach($Result->ABFindAllResult->contacts->Contact as $Contact)\r
- $this->Contacts[$Contact->contactInfo->passportName]=$Contact;\r
- }\r
- catch(Exception $e)\r
- {\r
- $this->debug_message("*** Update Contacts Error \nRequest:".$this->ABService->__getLastRequest()."\nError:".$e->getMessage());\r
- }\r
+ 'ABApplicationHeader'=>array(\r
+ ':'=>array('xmlns'=>'http://www.msn.com/webservices/AddressBook'),\r
+ 'ApplicationId'=>'CFE80F9D-180F-4399-82AB-413F33A1FA11',\r
+ 'IsMigration'=>false,\r
+ 'PartnerScenario'=>'ContactSave'\r
+ )\r
+ );\r
+ \r
+ $ABApplicationHeader=new SoapHeader("http://www.msn.com/webservices/AddressBook",'ABApplicationHeader', $this->Array2SoapVar($ABApplicationHeaderArray));\r
+ $ABFindAllArray=array(\r
+ 'ABFindAll'=>array(\r
+ ':'=>array('xmlns'=>'http://www.msn.com/webservices/AddressBook'),\r
+ 'abId'=>'00000000-0000-0000-0000-000000000000',\r
+ 'abView'=>'Full',\r
+ 'lastChange'=>'0001-01-01T00:00:00.0000000-08:00',\r
+ )\r
+ );\r
+ $ABFindAll=new SoapParam($this->Array2SoapVar($ABFindAllArray),'ABFindAll');\r
+ $this->ABService->__setSoapHeaders(array($ABApplicationHeader,$this->ABAuthHeader));\r
+ $this->Contacts=array();\r
+ try\r
+ {\r
+ $this->debug_message("*** Update Contacts...");\r
+ $Result=$this->ABService->ABFindAll($ABFindAll);\r
+ $this->debug_message("*** Result:\n".print_r($Result,true)."\n".$this->ABService->__getLastResponse());\r
+ foreach($Result->ABFindAllResult->contacts->Contact as $Contact)\r
+ $this->Contacts[$Contact->contactInfo->passportName]=$Contact;\r
+ }\r
+ catch(Exception $e)\r
+ {\r
+ $this->debug_message("*** Update Contacts Error \nRequest:".$this->ABService->__getLastRequest()."\nError:".$e->getMessage());\r
+ return false;\r
+ }\r
+ return true;\r
}\r
- protected function addContact($email, $network, $display = '', $sendADL = false)\r
+ \r
+ private function addContact($email, $network, $display = '', $sendADL = false)\r
{\r
if ($network != 1) return true;\r
if(isset($this->Contacts[$email])) return true;\r
\r
$ABContactAddArray=array(\r
- 'ABContactAdd'=>array(\r
- ':'=>array('xmlns'=>'http://www.msn.com/webservices/AddressBook'),\r
- 'abId'=>'00000000-0000-0000-0000-000000000000',\r
- 'contacts'=>array(\r
- 'Contact'=>array(\r
- ':'=>array('xmlns'=>'http://www.msn.com/webservices/AddressBook'),\r
- 'contactInfo'=>array(\r
- 'contactType'=>'LivePending',\r
- 'passportName'=>$email,\r
- 'isMessengerUser'=>true,\r
- 'MessengerMemberInfo'=>array(\r
- 'DisplayName'=>$email\r
- )\r
- )\r
- )\r
- ),\r
- 'options'=>array(\r
- 'EnableAllowListManagement'=>true\r
- )\r
- )\r
+ 'ABContactAdd'=>array(\r
+ ':'=>array('xmlns'=>'http://www.msn.com/webservices/AddressBook'),\r
+ 'abId'=>'00000000-0000-0000-0000-000000000000',\r
+ 'contacts'=>array(\r
+ 'Contact'=>array(\r
+ ':'=>array('xmlns'=>'http://www.msn.com/webservices/AddressBook'),\r
+ 'contactInfo'=>array(\r
+ 'contactType'=>'LivePending',\r
+ 'passportName'=>$email,\r
+ 'isMessengerUser'=>true,\r
+ 'MessengerMemberInfo'=>array(\r
+ 'DisplayName'=>$email\r
+ )\r
+ )\r
+ )\r
+ ),\r
+ 'options'=>array(\r
+ 'EnableAllowListManagement'=>true\r
+ )\r
+ )\r
);\r
$ABContactAdd=new SoapParam($this->Array2SoapVar($ABContactAddArray),'ABContactAdd');\r
try\r
catch(Exception $e)\r
{\r
$this->debug_message("*** Add Contacts Error \nRequest:".$this->ABService->__getLastRequest()."\nError:".$e->getMessage());\r
+ return false;\r
}\r
if ($sendADL && !feof($this->NSfp)) {\r
@list($u_name, $u_domain) = @explode('@', $email);\r
$user = $email;\r
$ticket = htmlspecialchars($this->ticket['contact_ticket']);\r
if ($network == 1)\r
- $XML = '<?xml version="1.0" encoding="utf-8"?>\r
+ $XML = '<?xml version="1.0" encoding="utf-8"?>\r
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"\r
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
</soap:Body>\r
</soap:Envelope>';\r
else\r
- $XML = '<?xml version="1.0" encoding="utf-8"?>\r
+ $XML = '<?xml version="1.0" encoding="utf-8"?>\r
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"\r
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
'SOAPAction: '.$this->delmember_soap,\r
'Content-Type: text/xml; charset=utf-8',\r
'User-Agent: MSN Explorer/9.0 (MSN 8.0; TmstmpExt)'\r
- );\r
-\r
- $this->debug_message("*** URL: $this->delmember_url");\r
- $this->debug_message("*** Sending SOAP:\n$XML");\r
- $curl = curl_init();\r
- curl_setopt($curl, CURLOPT_URL, $this->delmember_url);\r
- curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
- if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
- curl_setopt($curl, CURLOPT_POST, 1);\r
- curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
- $data = curl_exec($curl);\r
- $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
- curl_close($curl);\r
- $this->debug_message("*** Get Result:\n$data");\r
-\r
- if ($http_code != 200) {\r
- preg_match('#<faultcode>(.*)</faultcode><faultstring>(.*)</faultstring>#', $data, $matches);\r
- if (count($matches) == 0) {\r
- $this->log_message("*** can't delete member (network: $network) $email ($memberID) to $list");\r
- return false;\r
- }\r
- $faultcode = trim($matches[1]);\r
- $faultstring = trim($matches[2]);\r
- if (strcasecmp($faultcode, 'soap:Client') || stripos($faultstring, 'Member does not exist') === false) {\r
- $this->log_message("*** can't delete member (network: $network) $email ($memberID) to $list, error code: $faultcode, $faultstring");\r
- return false;\r
- }\r
- $this->log_message("*** delete member (network: $network) $email ($memberID) from $list, not exist");\r
- return true;\r
+ );\r
+\r
+ $this->debug_message("*** URL: $this->delmember_url");\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, $this->delmember_url);\r
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
+ if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
+ curl_setopt($curl, CURLOPT_POST, 1);\r
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
+ $data = curl_exec($curl);\r
+ $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
+ curl_close($curl);\r
+ $this->debug_message("*** Get Result:\n$data");\r
+\r
+ if ($http_code != 200) {\r
+ preg_match('#<faultcode>(.*)</faultcode><faultstring>(.*)</faultstring>#', $data, $matches);\r
+ if (count($matches) == 0) {\r
+ $this->log_message("*** can't delete member (network: $network) $email ($memberID) to $list");\r
+ return false;\r
+ }\r
+ $faultcode = trim($matches[1]);\r
+ $faultstring = trim($matches[2]);\r
+ if (strcasecmp($faultcode, 'soap:Client') || stripos($faultstring, 'Member does not exist') === false) {\r
+ $this->log_message("*** can't delete member (network: $network) $email ($memberID) to $list, error code: $faultcode, $faultstring");\r
+ return false;\r
}\r
- $this->log_message("*** delete member (network: $network) $email ($memberID) from $list");\r
+ $this->log_message("*** delete member (network: $network) $email ($memberID) from $list, not exist");\r
return true;\r
+ }\r
+ $this->log_message("*** delete member (network: $network) $email ($memberID) from $list");\r
+ return true;\r
}\r
\r
function addMemberToList($email, $network, $list) {\r
$user = $email;\r
\r
if ($network == 1)\r
- $XML = '<?xml version="1.0" encoding="utf-8"?>\r
+ $XML = '<?xml version="1.0" encoding="utf-8"?>\r
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"\r
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
</soap:Body>\r
</soap:Envelope>';\r
else\r
- $XML = '<?xml version="1.0" encoding="utf-8"?>\r
+ $XML = '<?xml version="1.0" encoding="utf-8"?>\r
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"\r
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
'SOAPAction: '.$this->addmember_soap,\r
'Content-Type: text/xml; charset=utf-8',\r
'User-Agent: MSN Explorer/9.0 (MSN 8.0; TmstmpExt)'\r
- );\r
-\r
- $this->debug_message("*** URL: $this->addmember_url");\r
- $this->debug_message("*** Sending SOAP:\n$XML");\r
- $curl = curl_init();\r
- curl_setopt($curl, CURLOPT_URL, $this->addmember_url);\r
- curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
- if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
- curl_setopt($curl, CURLOPT_POST, 1);\r
- curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
- $data = curl_exec($curl);\r
- $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
- curl_close($curl);\r
- $this->debug_message("*** Get Result:\n$data");\r
-\r
- if ($http_code != 200) {\r
- preg_match('#<faultcode>(.*)</faultcode><faultstring>(.*)</faultstring>#', $data, $matches);\r
- if (count($matches) == 0) {\r
- $this->log_message("*** can't add member (network: $network) $email to $list");\r
- return false;\r
- }\r
- $faultcode = trim($matches[1]);\r
- $faultstring = trim($matches[2]);\r
- if (strcasecmp($faultcode, 'soap:Client') || stripos($faultstring, 'Member already exists') === false) {\r
- $this->log_message("*** can't add member (network: $network) $email to $list, error code: $faultcode, $faultstring");\r
- return false;\r
- }\r
- $this->log_message("*** add member (network: $network) $email to $list, already exist!");\r
- return true;\r
+ );\r
+\r
+ $this->debug_message("*** URL: $this->addmember_url");\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, $this->addmember_url);\r
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
+ if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
+ curl_setopt($curl, CURLOPT_POST, 1);\r
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
+ $data = curl_exec($curl);\r
+ $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
+ curl_close($curl);\r
+ $this->debug_message("*** Get Result:\n$data");\r
+\r
+ if ($http_code != 200) {\r
+ preg_match('#<faultcode>(.*)</faultcode><faultstring>(.*)</faultstring>#', $data, $matches);\r
+ if (count($matches) == 0) {\r
+ $this->log_message("*** can't add member (network: $network) $email to $list");\r
+ return false;\r
+ }\r
+ $faultcode = trim($matches[1]);\r
+ $faultstring = trim($matches[2]);\r
+ if (strcasecmp($faultcode, 'soap:Client') || stripos($faultstring, 'Member already exists') === false) {\r
+ $this->log_message("*** can't add member (network: $network) $email to $list, error code: $faultcode, $faultstring");\r
+ return false;\r
}\r
- $this->log_message("*** add member (network: $network) $email to $list");\r
+ $this->log_message("*** add member (network: $network) $email to $list, already exist!");\r
return true;\r
+ }\r
+ $this->log_message("*** add member (network: $network) $email to $list");\r
+ return true;\r
}\r
\r
function getMembershipList($returnData=false) {\r
'SOAPAction: '.$this->membership_soap,\r
'Content-Type: text/xml; charset=utf-8',\r
'User-Agent: MSN Explorer/9.0 (MSN 8.0; TmstmpExt)'\r
- );\r
- $this->debug_message("*** URL: $this->membership_url");\r
- $this->debug_message("*** Sending SOAP:\n$XML");\r
- $curl = curl_init();\r
- curl_setopt($curl, CURLOPT_URL, $this->membership_url);\r
- curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
- if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
- curl_setopt($curl, CURLOPT_POST, 1);\r
- curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
- $data = curl_exec($curl);\r
- $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
- curl_close($curl);\r
- $this->debug_message("*** Get Result:\n$data");\r
- if($http_code != 200) return array();\r
- $p = $data;\r
- $aMemberships = array();\r
+ );\r
+ $this->debug_message("*** URL: $this->membership_url");\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, $this->membership_url);\r
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
+ if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
+ curl_setopt($curl, CURLOPT_POST, 1);\r
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
+ $data = curl_exec($curl);\r
+ $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
+ curl_close($curl);\r
+ $this->debug_message("*** Get Result:\n$data");\r
+ if($http_code != 200) return false;\r
+ $p = $data;\r
+ $aMemberships = array();\r
+ while (1) {\r
+ //$this->debug_message("search p = $p");\r
+ $start = strpos($p, '<Membership>');\r
+ $end = strpos($p, '</Membership>');\r
+ if ($start === false || $end === false || $start > $end) break;\r
+ //$this->debug_message("start = $start, end = $end");\r
+ $end += 13;\r
+ $sMembership = substr($p, $start, $end - $start);\r
+ $aMemberships[] = $sMembership;\r
+ //$this->debug_message("add sMembership = $sMembership");\r
+ $p = substr($p, $end);\r
+ }\r
+ //$this->debug_message("aMemberships = ".var_export($aMemberships, true));\r
+\r
+ $aContactList = array();\r
+ foreach ($aMemberships as $sMembership) {\r
+ //$this->debug_message("sMembership = $sMembership");\r
+ if (isset($matches)) unset($matches);\r
+ preg_match('#<MemberRole>(.*)</MemberRole>#', $sMembership, $matches);\r
+ if (count($matches) == 0) continue;\r
+ $sMemberRole = $matches[1];\r
+ //$this->debug_message("MemberRole = $sMemberRole");\r
+ if ($sMemberRole != 'Allow' && $sMemberRole != 'Reverse' && $sMemberRole != 'Pending') continue;\r
+ $p = $sMembership;\r
+ if (isset($aMembers)) unset($aMembers);\r
+ $aMembers = array();\r
while (1) {\r
//$this->debug_message("search p = $p");\r
- $start = strpos($p, '<Membership>');\r
- $end = strpos($p, '</Membership>');\r
+ $start = strpos($p, '<Member xsi:type="');\r
+ $end = strpos($p, '</Member>');\r
if ($start === false || $end === false || $start > $end) break;\r
//$this->debug_message("start = $start, end = $end");\r
- $end += 13;\r
- $sMembership = substr($p, $start, $end - $start);\r
- $aMemberships[] = $sMembership;\r
- //$this->debug_message("add sMembership = $sMembership");\r
+ $end += 9;\r
+ $sMember = substr($p, $start, $end - $start);\r
+ $aMembers[] = $sMember;\r
+ //$this->debug_message("add sMember = $sMember");\r
$p = substr($p, $end);\r
}\r
- //$this->debug_message("aMemberships = ".var_export($aMemberships, true));\r
-\r
- $aContactList = array();\r
- foreach ($aMemberships as $sMembership) {\r
- //$this->debug_message("sMembership = $sMembership");\r
+ //$this->debug_message("aMembers = ".var_export($aMembers, true));\r
+ foreach ($aMembers as $sMember) {\r
+ //$this->debug_message("sMember = $sMember");\r
if (isset($matches)) unset($matches);\r
- preg_match('#<MemberRole>(.*)</MemberRole>#', $sMembership, $matches);\r
+ preg_match('#<Member xsi\:type="([^"]*)">#', $sMember, $matches);\r
+ if (count($matches) == 0) continue;\r
+ $sMemberType = $matches[1];\r
+ //$this->debug_message("MemberType = $sMemberType");\r
+ $network = -1;\r
+ preg_match('#<MembershipId>(.*)</MembershipId>#', $sMember, $matches);\r
if (count($matches) == 0) continue;\r
- $sMemberRole = $matches[1];\r
- //$this->debug_message("MemberRole = $sMemberRole");\r
- if ($sMemberRole != 'Allow' && $sMemberRole != 'Reverse' && $sMemberRole != 'Pending') continue;\r
- $p = $sMembership;\r
- if (isset($aMembers)) unset($aMembers);\r
- $aMembers = array();\r
- while (1) {\r
- //$this->debug_message("search p = $p");\r
- $start = strpos($p, '<Member xsi:type="');\r
- $end = strpos($p, '</Member>');\r
- if ($start === false || $end === false || $start > $end) break;\r
- //$this->debug_message("start = $start, end = $end");\r
- $end += 9;\r
- $sMember = substr($p, $start, $end - $start);\r
- $aMembers[] = $sMember;\r
- //$this->debug_message("add sMember = $sMember");\r
- $p = substr($p, $end);\r
+ $id = $matches[1];\r
+ if ($sMemberType == 'PassportMember') {\r
+ if (strpos($sMember, '<Type>Passport</Type>') === false) continue;\r
+ $network = 1;\r
+ preg_match('#<PassportName>(.*)</PassportName>#', $sMember, $matches);\r
}\r
- //$this->debug_message("aMembers = ".var_export($aMembers, true));\r
- foreach ($aMembers as $sMember) {\r
- //$this->debug_message("sMember = $sMember");\r
- if (isset($matches)) unset($matches);\r
- preg_match('#<Member xsi\:type="([^"]*)">#', $sMember, $matches);\r
+ else if ($sMemberType == 'EmailMember') {\r
+ if (strpos($sMember, '<Type>Email</Type>') === false) continue;\r
+ // Value is 32: or 32:YAHOO\r
+ preg_match('#<Annotation><Name>MSN.IM.BuddyType</Name><Value>(.*):(.*)</Value></Annotation>#', $sMember, $matches);\r
if (count($matches) == 0) continue;\r
- $sMemberType = $matches[1];\r
- //$this->debug_message("MemberType = $sMemberType");\r
- $network = -1;\r
- preg_match('#<MembershipId>(.*)</MembershipId>#', $sMember, $matches);\r
- if (count($matches) == 0) continue;\r
- $id = $matches[1];\r
- if ($sMemberType == 'PassportMember') {\r
- if (strpos($sMember, '<Type>Passport</Type>') === false) continue;\r
- $network = 1;\r
- preg_match('#<PassportName>(.*)</PassportName>#', $sMember, $matches);\r
- }\r
- else if ($sMemberType == 'EmailMember') {\r
- if (strpos($sMember, '<Type>Email</Type>') === false) continue;\r
- // Value is 32: or 32:YAHOO\r
- preg_match('#<Annotation><Name>MSN.IM.BuddyType</Name><Value>(.*):(.*)</Value></Annotation>#', $sMember, $matches);\r
- if (count($matches) == 0) continue;\r
- if ($matches[1] != 32) continue;\r
- $network = 32;\r
- preg_match('#<Email>(.*)</Email>#', $sMember, $matches);\r
- }\r
- if ($network == -1) continue;\r
- if (count($matches) > 0) {\r
- $email = $matches[1];\r
- @list($u_name, $u_domain) = @explode('@', $email);\r
- if ($u_domain == NULL) continue;\r
- $aContactList[$u_domain][$u_name][$network][$sMemberRole] = $id;\r
- $this->log_message("*** add new contact (network: $network, status: $sMemberRole): $u_name@$u_domain ($id)");\r
- }\r
+ if ($matches[1] != 32) continue;\r
+ $network = 32;\r
+ preg_match('#<Email>(.*)</Email>#', $sMember, $matches);\r
+ }\r
+ if ($network == -1) continue;\r
+ if (count($matches) > 0) {\r
+ $email = $matches[1];\r
+ @list($u_name, $u_domain) = @explode('@', $email);\r
+ if ($u_domain == NULL) continue;\r
+ $aContactList[$u_domain][$u_name][$network][$sMemberRole] = $id;\r
+ $this->log_message("*** add new contact (network: $network, status: $sMemberRole): $u_name@$u_domain ($id)");\r
}\r
}\r
- return $aContactList;\r
+ }\r
+ return $aContactList;\r
}\r
\r
+ /**\r
+ * Connect to the NS server\r
+ * @param $user Username\r
+ * @param $password Password\r
+ * @param $redirect_server Redirect server\r
+ * @param $redirect_port Redirect port\r
+ */\r
private function connect($user, $password, $redirect_server = '', $redirect_port = 1863) {\r
$this->id = 1;\r
if ($redirect_server === '') {\r
// never goto here\r
}\r
\r
- function derive_key($key, $magic) {\r
- $hash1 = mhash(MHASH_SHA1, $magic, $key);\r
- $hash2 = mhash(MHASH_SHA1, $hash1.$magic, $key);\r
- $hash3 = mhash(MHASH_SHA1, $hash1, $key);\r
- $hash4 = mhash(MHASH_SHA1, $hash3.$magic, $key);\r
- return $hash2.substr($hash4, 0, 4);\r
- }\r
-\r
- function generateLoginBLOB($key, $challenge) {\r
- $key1 = base64_decode($key);\r
- $key2 = $this->derive_key($key1, 'WS-SecureConversationSESSION KEY HASH');\r
- $key3 = $this->derive_key($key1, 'WS-SecureConversationSESSION KEY ENCRYPTION');\r
-\r
- // get hash of challenge using key2\r
- $hash = mhash(MHASH_SHA1, $challenge, $key2);\r
-\r
- // get 8 bytes random data\r
- $iv = substr(base64_encode(rand(1000,9999).rand(1000,9999)), 2, 8);\r
-\r
- $cipher = mcrypt_cbc(MCRYPT_3DES, $key3, $challenge."\x08\x08\x08\x08\x08\x08\x08\x08", MCRYPT_ENCRYPT, $iv);\r
-\r
- $blob = pack('LLLLLLL', 28, 1, 0x6603, 0x8004, 8, 20, 72);\r
- $blob .= $iv;\r
- $blob .= $hash;\r
- $blob .= $cipher;\r
-\r
- return base64_encode($blob);\r
- }\r
-\r
- function getOIM_maildata() {\r
- preg_match('#t=(.*)&p=(.*)#', $this->ticket['web_ticket'], $matches);\r
- if (count($matches) == 0) {\r
- $this->debug_message('*** no web ticket?');\r
- return false;\r
+ /**\r
+ * Sign onto the NS server and retrieve the address book\r
+ */\r
+ public function signon() {\r
+ $this->log_message("*** try to connect to MSN network");\r
+ while(!$this->connect($this->user, $this->password))\r
+ {\r
+ $this->signonFailed("!!! Can't connect to server: $this->error");\r
}\r
- $t = htmlspecialchars($matches[1]);\r
- $p = htmlspecialchars($matches[2]);\r
- $XML = '<?xml version="1.0" encoding="utf-8"?>\r
-<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
- xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\r
-<soap:Header>\r
- <PassportCookie xmlns="http://www.hotmail.msn.com/ws/2004/09/oim/rsi">\r
- <t>'.$t.'</t>\r
- <p>'.$p.'</p>\r
- </PassportCookie>\r
-</soap:Header>\r
-<soap:Body>\r
- <GetMetadata xmlns="http://www.hotmail.msn.com/ws/2004/09/oim/rsi" />\r
-</soap:Body>\r
-</soap:Envelope>';\r
-\r
- $header_array = array(\r
- 'SOAPAction: '.$this->oim_maildata_soap,\r
- 'Content-Type: text/xml; charset=utf-8',\r
- 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Messenger '.$this->buildver.')'\r
- );\r
-\r
- $this->debug_message("*** URL: $this->oim_maildata_url");\r
- $this->debug_message("*** Sending SOAP:\n$XML");\r
- $curl = curl_init();\r
- curl_setopt($curl, CURLOPT_URL, $this->oim_maildata_url);\r
- curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
- if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
- curl_setopt($curl, CURLOPT_POST, 1);\r
- curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
- $data = curl_exec($curl);\r
- $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
- curl_close($curl);\r
- $this->debug_message("*** Get Result:\n$data");\r
-\r
- if ($http_code != 200) {\r
- $this->debug_message("*** Can't get OIM maildata! http code: $http_code");\r
- return false;\r
- }\r
-\r
- // <GetMetadataResponse xmlns="http://www.hotmail.msn.com/ws/2004/09/oim/rsi">See #XML_Data</GetMetadataResponse>\r
- preg_match('#<GetMetadataResponse([^>]*)>(.*)</GetMetadataResponse>#', $data, $matches);\r
- if (count($matches) == 0) {\r
- $this->debug_message("*** Can't get OIM maildata");\r
- return '';\r
- }\r
- return $matches[2];\r
- }\r
-\r
- function getOIM_message($msgid) {\r
- preg_match('#t=(.*)&p=(.*)#', $this->ticket['web_ticket'], $matches);\r
- if (count($matches) == 0) {\r
- $this->debug_message('*** no web ticket?');\r
- return false;\r
+ if(!$this->UpdateContacts()) {\r
+ $this->signonFailed('!!! Could not update contacts');\r
+ return $this->signon();\r
}\r
- $t = htmlspecialchars($matches[1]);\r
- $p = htmlspecialchars($matches[2]);\r
-\r
- // read OIM\r
- $XML = '<?xml version="1.0" encoding="utf-8"?>\r
-<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ $this->LastPing=time();\r
+ $this->log_message("*** connected, wait for command");\r
+ $start_tm = time();\r
+ $ping_tm = time();\r
+ if(($this->aContactList = $this->getMembershipList()) === false) {\r
+ $this->signonFailed('!!! Could not get Membership List');\r
+ return $this->signon();\r
+ }\r
+ if ($this->update_pending) {\r
+ if (is_array($this->aContactList)) {\r
+ $pending = 'Pending';\r
+ foreach ($this->aContactList as $u_domain => $aUserList) {\r
+ foreach ($aUserList as $u_name => $aNetworks) {\r
+ foreach ($aNetworks as $network => $aData) {\r
+ if (isset($aData[$pending])) {\r
+ // pending list\r
+ $cnt = 0;\r
+ foreach (array('Allow', 'Reverse') as $list) {\r
+ if (isset($aData[$list]))\r
+ $cnt++;\r
+ else {\r
+ if ($this->addMemberToList($u_name.'@'.$u_domain, $network, $list)) {\r
+ $this->aContactList[$u_domain][$u_name][$network][$list] = false;\r
+ $cnt++;\r
+ }\r
+ }\r
+ }\r
+ if ($cnt >= 2) {\r
+ $id = $aData[$pending];\r
+ // we can delete it from pending now\r
+ if ($this->delMemberFromList($id, $u_name.'@'.$u_domain, $network, $pending))\r
+ unset($this->aContactList[$u_domain][$u_name][$network][$pending]);\r
+ }\r
+ }\r
+ else {\r
+ // sync list\r
+ foreach (array('Allow', 'Reverse') as $list) {\r
+ if (!isset($aData[$list])) {\r
+ if ($this->addMemberToList($u_name.'@'.$u_domain, $network, $list))\r
+ $this->aContactList[$u_domain][$u_name][$network][$list] = false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ $n = 0;\r
+ $sList = '';\r
+ $len = 0;\r
+ if (is_array($this->aContactList)) {\r
+ foreach ($this->aContactList as $u_domain => $aUserList) {\r
+ $str = '<d n="'.$u_domain.'">';\r
+ $len += strlen($str);\r
+ if ($len > 7400) {\r
+ $this->aADL[$n] = '<ml l="1">'.$sList.'</ml>';\r
+ $n++;\r
+ $sList = '';\r
+ $len = strlen($str);\r
+ }\r
+ $sList .= $str;\r
+ foreach ($aUserList as $u_name => $aNetworks) {\r
+ foreach ($aNetworks as $network => $status) {\r
+ $str = '<c n="'.$u_name.'" l="3" t="'.$network.'" />';\r
+ $len += strlen($str);\r
+ // max: 7500, but <ml l="1"></d></ml> is 19,\r
+ // so we use 7475\r
+ if ($len > 7475) {\r
+ $sList .= '</d>';\r
+ $this->aADL[$n] = '<ml l="1">'.$sList.'</ml>';\r
+ $n++;\r
+ $sList = '<d n="'.$u_domain.'">'.$str;\r
+ $len = strlen($sList);\r
+ }\r
+ else\r
+ $sList .= $str;\r
+ }\r
+ }\r
+ $sList .= '</d>';\r
+ }\r
+ }\r
+ $this->aADL[$n] = '<ml l="1">'.$sList.'</ml>';\r
+ // NS: >>> BLP {id} BL\r
+ $this->ns_writeln("BLP $this->id BL");\r
+ foreach ($this->aADL as $str) {\r
+ $len = strlen($str);\r
+ // NS: >>> ADL {id} {size}\r
+ $this->ns_writeln("ADL $this->id $len");\r
+ $this->ns_writedata($str);\r
+ }\r
+ // NS: >>> PRP {id} MFN name\r
+ if ($this->alias == '') $this->alias = $user;\r
+ $aliasname = rawurlencode($this->alias);\r
+ $this->ns_writeln("PRP $this->id MFN $aliasname");\r
+ //設定個人大頭貼\r
+ //$MsnObj=$this->PhotoStckObj();\r
+ // NS: >>> CHG {id} {status} {clientid} {msnobj}\r
+ $this->ns_writeln("CHG $this->id NLN $this->clientid");\r
+ if($this->PhotoStickerFile!==false)\r
+ $this->ns_writeln("CHG $this->id NLN $this->clientid ".rawurlencode($this->MsnObj($this->PhotoStickerFile)));\r
+ // NS: >>> UUX {id} length\r
+ $str = '<Data><PSM>'.htmlspecialchars($this->psm).'</PSM><CurrentMedia></CurrentMedia><MachineGuid></MachineGuid></Data>';\r
+ $len = strlen($str);\r
+ $this->ns_writeln("UUX $this->id $len");\r
+ $this->ns_writedata($str);\r
+ }\r
+ \r
+ private function signonFailed($message) {\r
+ $this->log_message($message);\r
+ $this->callHandler('ConnectFailed', NULL);\r
+ $this->NSRetryWait($this->retry_wait);\r
+ }\r
+ \r
+ function derive_key($key, $magic) {\r
+ $hash1 = mhash(MHASH_SHA1, $magic, $key);\r
+ $hash2 = mhash(MHASH_SHA1, $hash1.$magic, $key);\r
+ $hash3 = mhash(MHASH_SHA1, $hash1, $key);\r
+ $hash4 = mhash(MHASH_SHA1, $hash3.$magic, $key);\r
+ return $hash2.substr($hash4, 0, 4);\r
+ }\r
+\r
+ function generateLoginBLOB($key, $challenge) {\r
+ $key1 = base64_decode($key);\r
+ $key2 = $this->derive_key($key1, 'WS-SecureConversationSESSION KEY HASH');\r
+ $key3 = $this->derive_key($key1, 'WS-SecureConversationSESSION KEY ENCRYPTION');\r
+\r
+ // get hash of challenge using key2\r
+ $hash = mhash(MHASH_SHA1, $challenge, $key2);\r
+\r
+ // get 8 bytes random data\r
+ $iv = substr(base64_encode(rand(1000,9999).rand(1000,9999)), 2, 8);\r
+\r
+ $cipher = mcrypt_cbc(MCRYPT_3DES, $key3, $challenge."\x08\x08\x08\x08\x08\x08\x08\x08", MCRYPT_ENCRYPT, $iv);\r
+\r
+ $blob = pack('LLLLLLL', 28, 1, 0x6603, 0x8004, 8, 20, 72);\r
+ $blob .= $iv;\r
+ $blob .= $hash;\r
+ $blob .= $cipher;\r
+\r
+ return base64_encode($blob);\r
+ }\r
+\r
+ function getOIM_maildata() {\r
+ preg_match('#t=(.*)&p=(.*)#', $this->ticket['web_ticket'], $matches);\r
+ if (count($matches) == 0) {\r
+ $this->debug_message('*** no web ticket?');\r
+ return false;\r
+ }\r
+ $t = htmlspecialchars($matches[1]);\r
+ $p = htmlspecialchars($matches[2]);\r
+ $XML = '<?xml version="1.0" encoding="utf-8"?>\r
+<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
+ xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\r
+<soap:Header>\r
+ <PassportCookie xmlns="http://www.hotmail.msn.com/ws/2004/09/oim/rsi">\r
+ <t>'.$t.'</t>\r
+ <p>'.$p.'</p>\r
+ </PassportCookie>\r
+</soap:Header>\r
+<soap:Body>\r
+ <GetMetadata xmlns="http://www.hotmail.msn.com/ws/2004/09/oim/rsi" />\r
+</soap:Body>\r
+</soap:Envelope>';\r
+\r
+ $header_array = array(\r
+ 'SOAPAction: '.$this->oim_maildata_soap,\r
+ 'Content-Type: text/xml; charset=utf-8',\r
+ 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Messenger '.$this->buildver.')'\r
+ );\r
+\r
+ $this->debug_message("*** URL: $this->oim_maildata_url");\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, $this->oim_maildata_url);\r
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
+ if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
+ curl_setopt($curl, CURLOPT_POST, 1);\r
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
+ $data = curl_exec($curl);\r
+ $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
+ curl_close($curl);\r
+ $this->debug_message("*** Get Result:\n$data");\r
+\r
+ if ($http_code != 200) {\r
+ $this->debug_message("*** Can't get OIM maildata! http code: $http_code");\r
+ return false;\r
+ }\r
+\r
+ // <GetMetadataResponse xmlns="http://www.hotmail.msn.com/ws/2004/09/oim/rsi">See #XML_Data</GetMetadataResponse>\r
+ preg_match('#<GetMetadataResponse([^>]*)>(.*)</GetMetadataResponse>#', $data, $matches);\r
+ if (count($matches) == 0) {\r
+ $this->debug_message("*** Can't get OIM maildata");\r
+ return '';\r
+ }\r
+ return $matches[2];\r
+ }\r
+\r
+ function getOIM_message($msgid) {\r
+ preg_match('#t=(.*)&p=(.*)#', $this->ticket['web_ticket'], $matches);\r
+ if (count($matches) == 0) {\r
+ $this->debug_message('*** no web ticket?');\r
+ return false;\r
+ }\r
+ $t = htmlspecialchars($matches[1]);\r
+ $p = htmlspecialchars($matches[2]);\r
+\r
+ // read OIM\r
+ $XML = '<?xml version="1.0" encoding="utf-8"?>\r
+<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\r
<soap:Header>\r
'SOAPAction: '.$this->oim_read_soap,\r
'Content-Type: text/xml; charset=utf-8',\r
'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Messenger '.$this->buildver.')'\r
- );\r
-\r
- $this->debug_message("*** URL: $this->oim_read_url");\r
- $this->debug_message("*** Sending SOAP:\n$XML");\r
- $curl = curl_init();\r
- curl_setopt($curl, CURLOPT_URL, $this->oim_read_url);\r
- curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
- if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
- curl_setopt($curl, CURLOPT_POST, 1);\r
- curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
- $data = curl_exec($curl);\r
- $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
- curl_close($curl);\r
- $this->debug_message("*** Get Result:\n$data");\r
-\r
- if ($http_code != 200) {\r
- $this->debug_message("*** Can't get OIM: $msgid, http code = $http_code");\r
- return false;\r
- }\r
+ );\r
\r
- // why can't use preg_match('#<GetMessageResult>(.*)</GetMessageResult>#', $data, $matches)?\r
- // multi-lines?\r
- $start = strpos($data, '<GetMessageResult>');\r
- $end = strpos($data, '</GetMessageResult>');\r
- if ($start === false || $end === false || $start > $end) {\r
- $this->debug_message("*** Can't get OIM: $msgid");\r
- return false;\r
- }\r
- $lines = substr($data, $start + 18, $end - $start);\r
- $aLines = @explode("\n", $lines);\r
- $header = true;\r
- $ignore = false;\r
- $sOIM = '';\r
- foreach ($aLines as $line) {\r
- $line = rtrim($line);\r
- if ($header) {\r
- if ($line === '') {\r
- $header = false;\r
- continue;\r
- }\r
+ $this->debug_message("*** URL: $this->oim_read_url");\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, $this->oim_read_url);\r
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
+ if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
+ curl_setopt($curl, CURLOPT_POST, 1);\r
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
+ $data = curl_exec($curl);\r
+ $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
+ curl_close($curl);\r
+ $this->debug_message("*** Get Result:\n$data");\r
+\r
+ if ($http_code != 200) {\r
+ $this->debug_message("*** Can't get OIM: $msgid, http code = $http_code");\r
+ return false;\r
+ }\r
+\r
+ // why can't use preg_match('#<GetMessageResult>(.*)</GetMessageResult>#', $data, $matches)?\r
+ // multi-lines?\r
+ $start = strpos($data, '<GetMessageResult>');\r
+ $end = strpos($data, '</GetMessageResult>');\r
+ if ($start === false || $end === false || $start > $end) {\r
+ $this->debug_message("*** Can't get OIM: $msgid");\r
+ return false;\r
+ }\r
+ $lines = substr($data, $start + 18, $end - $start);\r
+ $aLines = @explode("\n", $lines);\r
+ $header = true;\r
+ $ignore = false;\r
+ $sOIM = '';\r
+ foreach ($aLines as $line) {\r
+ $line = rtrim($line);\r
+ if ($header) {\r
+ if ($line === '') {\r
+ $header = false;\r
continue;\r
}\r
- // stop at empty lines\r
- if ($line === '') break;\r
- $sOIM .= $line;\r
+ continue;\r
}\r
- $sMsg = base64_decode($sOIM);\r
- $this->debug_message("*** we get OIM ($msgid): $sMsg");\r
+ // stop at empty lines\r
+ if ($line === '') break;\r
+ $sOIM .= $line;\r
+ }\r
+ $sMsg = base64_decode($sOIM);\r
+ $this->debug_message("*** we get OIM ($msgid): $sMsg");\r
\r
- // delete OIM\r
- $XML = '<?xml version="1.0" encoding="utf-8"?>\r
+ // delete OIM\r
+ $XML = '<?xml version="1.0" encoding="utf-8"?>\r
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\r
</soap:Body>\r
</soap:Envelope>';\r
\r
- $header_array = array(\r
+ $header_array = array(\r
'SOAPAction: '.$this->oim_del_soap,\r
'Content-Type: text/xml; charset=utf-8',\r
'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Messenger '.$this->buildver.')'\r
- );\r
-\r
- $this->debug_message("*** URL: $this->oim_del_url");\r
- $this->debug_message("*** Sending SOAP:\n$XML");\r
- $curl = curl_init();\r
- curl_setopt($curl, CURLOPT_URL, $this->oim_del_url);\r
- curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
- if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
- curl_setopt($curl, CURLOPT_POST, 1);\r
- curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
- $data = curl_exec($curl);\r
- $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
- curl_close($curl);\r
- $this->debug_message("*** Get Result:\n$data");\r
-\r
- if ($http_code != 200)\r
+ );\r
+\r
+ $this->debug_message("*** URL: $this->oim_del_url");\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, $this->oim_del_url);\r
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
+ if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
+ curl_setopt($curl, CURLOPT_POST, 1);\r
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
+ $data = curl_exec($curl);\r
+ $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
+ curl_close($curl);\r
+ $this->debug_message("*** Get Result:\n$data");\r
+\r
+ if ($http_code != 200)\r
$this->debug_message("*** Can't delete OIM: $msgid, http code = $http_code");\r
- else\r
+ else\r
$this->debug_message("*** OIM ($msgid) deleted");\r
- return $sMsg;\r
+ return $sMsg;\r
}\r
private function NSLogout() {\r
if (is_resource($this->NSfp) && !feof($this->NSfp)) {\r
}\r
if ($oim_result === false || $oim_result['auth_policy'] !== false)\r
{\r
- if ($re_login)\r
+ if ($this->re_login)\r
{\r
$this->log_message("*** can't send OIM, but we already re-login again, so ignore this OIM");\r
break;\r
$this->log_message("*** connected, wait for command");\r
$start_tm = time();\r
$ping_tm = time();\r
- stream_set_timeout($this->NSfp, $this->NSStreamTimeout);\r
$aContactList = $this->getMembershipList();\r
if ($this->update_pending) {\r
if (is_array($aContactList)) {\r
$this->log_message("*** someone (network: $network) add us to their list (but already in our list): $u_name@$u_domain");\r
else\r
{\r
- $re_login = false;\r
+ $this->re_login = false;\r
$cnt = 0;\r
foreach (array('Allow', 'Reverse') as $list)\r
{\r
if (!$this->addMemberToList($u_name.'@'.$u_domain, $network, $list))\r
{\r
- if ($re_login) {\r
+ if ($this->re_login) {\r
$this->log_message("*** can't add $u_name@$u_domain (network: $network) to $list");\r
continue;\r
}\r
$this->log_message("*** can't add $u_name@$u_domain (network: $network) to $list");\r
continue;\r
}\r
- $re_login = true;\r
+ $this->re_login = true;\r
$this->ticket = $aTickets;\r
$this->log_message("**** get new ticket, try it again");\r
if (!$this->addMemberToList($u_name.'@'.$u_domain, $network, $list))\r
$this->log_message("*** ingnore MSG not for OIM");\r
break;\r
}\r
- $re_login = false;\r
+ $this->re_login = false;\r
if (strcasecmp($maildata, 'too-large') == 0) {\r
$this->log_message("*** large mail-data, need to get the data via SOAP");\r
$maildata = $this->getOIM_maildata();\r
$this->log_message("*** can't re-login, something wrong here, ignore this OIM");\r
break;\r
}\r
- $re_login = true;\r
+ $this->re_login = true;\r
$this->ticket = $aTickets;\r
$this->log_message("**** get new ticket, try it again");\r
$maildata = $this->getOIM_maildata();\r
$sMsg = $this->getOIM_message($oim_msgid);\r
if ($sMsg === false) {\r
$this->log_message("*** can't get OIM, msgid = $oim_msgid");\r
- if ($re_login) {\r
+ if ($this->re_login) {\r
$this->log_message("*** can't get OIM via SOAP, and we already re-login again, so ignore this OIM");\r
continue;\r
}\r
$this->log_message("*** can't re-login, something wrong here, ignore this OIM");\r
continue;\r
}\r
- $re_login = true;\r
+ $this->re_login = true;\r
$this->ticket = $aTickets;\r
$this->log_message("**** get new ticket, try it again");\r
$sMsg = $this->getOIM_message($oim_msgid);\r
return $this->NsLogout();\r
}\r
\r
- /*public function SendMessage($Message, $To)\r
- {\r
- $FileName = MSN_CLASS_SPOOL_DIR.'/'.strftime('%Y%m%d%H%M%S',time()).'_'.posix_getpid().'_sendMessage.msn';\r
- if(!is_array($To))\r
- $To=array($To);\r
- $Receiver='';\r
- foreach($To as $Email)\r
- {\r
- list($name,$host,$network)=explode('@',$Email);\r
- $network=$network==''?1:$network;\r
- if($network==1 && $this->SwitchBoardProcess && $this->SwitchBoardSessionUser=="$name@$host" )\r
- {\r
- $this->debug_message("*** SendMessage to $Receiver use SB message queue.");\r
- array_push($this->SwitchBoardMessageQueue,$Message);\r
- continue;\r
- }\r
- $Receiver.="$name@$host@$network,";\r
- }\r
- if($Receiver=='') return;\r
- $Receiver=substr($Receiver,0,-1);\r
- $this->debug_message("*** SendMessage to $Receiver use File queue.");\r
- file_put_contents($FileName,"TO: $Receiver\n$Message\n");\r
- }*/\r
-\r
function getChallenge($code)\r
{\r
// MSNP15\r
{\r
$SessionEnd=false;\r
$Joined=false;\r
- $id=1;\r
+ $this->id=1;\r
$LastActive=time();\r
- stream_set_timeout($this->SBFp, $this->SBTimeout);\r
+ stream_set_timeout($this->SBfp, $this->SBStreamTimeout);\r
switch($Action)\r
{\r
case 'Active':\r
$user=$Param['user'];\r
$this->SwitchBoardMessageQueue=$Param['Msg'];\r
// SB: >>> USR {id} {user} {cki}\r
- $this->SB_writeln("USR $id $this->user $cki_code");\r
- $id++;\r
+ $this->SB_writeln("USR $this->id $this->user $cki_code");\r
$this->SwitchBoardSessionUser=$user;\r
break;\r
case 'Passive':\r
$sid=$Param['sid'];\r
$user=$Param['user'];\r
// SB: >>> ANS {id} {user} {ticket} {session_id}\r
- $this->SB_writeln("ANS $id $this->user $ticket $sid");\r
- $id++;\r
+ $this->SB_writeln("ANS $this->id $this->user $ticket $sid");\r
$this->SwitchBoardSessionUser=$user;\r
break;\r
default:\r
return false;\r
}\r
- while((!feof($this->SBFp))&&(!$SessionEnd))\r
+ while((!feof($this->SBfp))&&(!$SessionEnd))\r
{\r
$data = $this->SB_readln();\r
if($this->kill_me)\r
{\r
$SendString="MIME-Version: 1.0\r\nContent-Type: text/x-mms-emoticon\r\n\r\n$MsnObjDefine";\r
$len = strlen($SendString);\r
- $this->SB_writeln("MSG $id N $len");\r
- $id++;\r
+ $this->SB_writeln("MSG $this->id N $len");\r
$this->SB_writedata($SendString);\r
$this->id++;\r
}\r
$len = strlen($aMessage);\r
- $this->SB_writeln("MSG $id N $len");\r
- $id++;\r
+ $this->SB_writeln("MSG $this->id N $len");\r
$this->SB_writedata($aMessage);\r
}\r
$this->SwitchBoardMessageQueue=array();\r
// we don't need the data, just ignore it\r
// request user to join this switchboard\r
// SB: >>> CAL {id} {user}\r
- $this->SB_writeln("CAL $id $user");\r
- $id++;\r
+ $this->SB_writeln("CAL $this->id $user");\r
break;\r
case 'CAL':\r
// SB: <<< CAL {id} RINGING {?}\r
$footer = pack("L", 0);\r
$message = "MIME-Version: 1.0\r\nContent-Type: application/x-msnmsgrp2p\r\nP2P-Dest: $from_email\r\n\r\n$hdr$footer";\r
$len = strlen($message);\r
- $this->SB_writeln("MSG $id D $len");\r
- $id++;\r
+ $this->SB_writeln("MSG $this->id D $len");\r
$this->SB_writedata($message);\r
$this->log_message("*** p2p: send display picture acknowledgement for $hdr_SessionID");\r
$this->debug_message("*** p2p: Invite ACK message:\n".$this->dump_binary($message)); \r
"MIME-Version: 1.0\r\n".\r
"Content-Type: application/x-msnmsgrp2p\r\n".\r
"P2P-Dest: $from_email\r\n\r\n$hdr$MessagePayload$footer";\r
- $this->SB_writeln("MSG $id D ".strlen($message));\r
- $id++;\r
+ $this->SB_writeln("MSG $this->id D ".strlen($message));\r
$this->SB_writedata($message);\r
$this->debug_message("*** p2p: dump 200 ok message:\n".$this->dump_binary($message));\r
$this->SB_readln();//Read ACK;\r
"MIME-Version: 1.0\r\n".\r
"Content-Type: application/x-msnmsgrp2p\r\n".\r
"P2P-Dest: $from_email\r\n\r\n$hdr".pack('L',0)."$footer";\r
- $this->SB_writeln("MSG $id D ".strlen($message));\r
- $id++;\r
+ $this->SB_writeln("MSG $this->id D ".strlen($message));\r
$this->SB_writedata($message);\r
$this->debug_message("*** p2p: dump send Data preparation message:\n".$this->dump_binary($message));\r
$this->debug_message("*** p2p: Data Prepare Hdr:\n".$this->dump_binary($hdr));\r
"MIME-Version: 1.0\r\n".\r
"Content-Type: application/x-msnmsgrp2p\r\n".\r
"P2P-Dest: $from_email\r\n\r\n$hdr$FileContent$footer";\r
- $this->SB_writeln("MSG $id D ".strlen($message));\r
- $id++;\r
+ $this->SB_writeln("MSG $this->id D ".strlen($message));\r
$this->SB_writedata($message);\r
$this->debug_message("*** p2p: dump send Data Content message $Offset / $FileSize :\n".$this->dump_binary($message));\r
$this->debug_message("*** p2p: Data Content Hdr:\n".$this->dump_binary($hdr));\r
}\r
if(!$this->IsIgnoreMail($user)) $LastActive = time();\r
}\r
- if (feof($this->SBFp))\r
+ if (feof($this->SBfp))\r
{\r
// lost connection? error? try OIM later\r
- @fclose($this->SBFp);\r
+ @fclose($this->SBfp);\r
return false;\r
}\r
$this->SB_writeln("OUT");\r
- @fclose($this->SBFp);\r
+ @fclose($this->SBfp);\r
return true;\r
}\r
- private function switchboard_control($ip, $port, $cki_code, $user, $Messages)\r
+ /*private function switchboard_control($ip, $port, $cki_code, $user, $Messages)\r
{\r
$this->SwitchBoardProcess=1;\r
$this->debug_message("*** SB: try to connect to switchboard server $ip:$port");\r
- $this->SBFp = @fsockopen($ip, $port, $errno, $errstr, 5);\r
- if (!$this->SBFp)\r
+ $this->SBfp = @fsockopen($ip, $port, $errno, $errstr, 5);\r
+ if (!$this->SBfp)\r
{\r
$this->debug_message("*** SB: Can't connect to $ip:$port, error => $errno, $errstr");\r
return false;\r
{\r
$this->SwitchBoardProcess=2;\r
$this->debug_message("*** SB: try to connect to switchboard server $ip:$port");\r
- $this->SBFp = @fsockopen($ip, $port, $errno, $errstr, 5);\r
- if (!$this->SBFp)\r
+ $this->SBfp = @fsockopen($ip, $port, $errno, $errstr, 5);\r
+ if (!$this->SBfp)\r
{\r
$this->debug_message("*** SB: Can't connect to $ip:$port, error => $errno, $errstr");\r
return false;\r
}\r
return $this->DoSwitchBoard('Passive',array('sid'=>$sid,'user'=>$user,'ticket'=>$ticket));\r
- }\r
-\r
- private function sendOIM($to, $sMessage, $lockkey)\r
- {\r
- $XML = '<?xml version="1.0" encoding="utf-8"?>\r
-<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
- xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\r
-<soap:Header>\r
- <From memberName="'.$this->user.'"\r
- friendlyName="=?utf-8?B?'.base64_encode($this->user).'?="\r
- xml:lang="zh-TW"\r
- proxy="MSNMSGR"\r
- xmlns="http://messenger.msn.com/ws/2004/09/oim/"\r
- msnpVer="'.$this->protocol.'"\r
- buildVer="'.$this->buildver.'"/>\r
- <To memberName="'.$to.'" xmlns="http://messenger.msn.com/ws/2004/09/oim/"/>\r
- <Ticket passport="'.htmlspecialchars($this->ticket['oim_ticket']).'"\r
- appid="'.$this->prod_id.'"\r
- lockkey="'.$lockkey.'"\r
- xmlns="http://messenger.msn.com/ws/2004/09/oim/"/>\r
- <Sequence xmlns="http://schemas.xmlsoap.org/ws/2003/03/rm">\r
- <Identifier xmlns="http://schemas.xmlsoap.org/ws/2002/07/utility">http://messenger.msn.com</Identifier>\r
- <MessageNumber>1</MessageNumber>\r
- </Sequence>\r
-</soap:Header>\r
-<soap:Body>\r
- <MessageType xmlns="http://messenger.msn.com/ws/2004/09/oim/">text</MessageType>\r
- <Content xmlns="http://messenger.msn.com/ws/2004/09/oim/">MIME-Version: 1.0\r
-Content-Type: text/plain; charset=UTF-8\r
-Content-Transfer-Encoding: base64\r
-X-OIM-Message-Type: OfflineMessage\r
-X-OIM-Run-Id: {DAB68CFA-38C9-449B-945E-38AFA51E50A7}\r
-X-OIM-Sequence-Num: 1\r
-\r
-'.chunk_split(base64_encode($sMessage)).'\r
- </Content>\r
-</soap:Body>\r
-</soap:Envelope>';\r
-\r
- $header_array = array(\r
- 'SOAPAction: '.$this->oim_send_soap,\r
- 'Content-Type: text/xml',\r
- 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Messenger '.$this->buildver.')'\r
- );\r
-\r
- $this->debug_message("*** URL: $this->oim_send_url");\r
- $this->debug_message("*** Sending SOAP:\n$XML");\r
- $curl = curl_init();\r
- curl_setopt($curl, CURLOPT_URL, $this->oim_send_url);\r
- curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
- if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
- curl_setopt($curl, CURLOPT_POST, 1);\r
- curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
- $data = curl_exec($curl);\r
- $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
- curl_close($curl);\r
- $this->debug_message("*** Get Result:\n$data");\r
-\r
- if ($http_code == 200) {\r
- $this->debug_message("*** OIM sent for $to");\r
- return true;\r
- }\r
-\r
- $challenge = false;\r
- $auth_policy = false;\r
- // the lockkey is invalid, authenticated fail, we need challenge it again\r
- // <LockKeyChallenge xmlns="http://messenger.msn.com/ws/2004/09/oim/">364763969</LockKeyChallenge>\r
- preg_match("#<LockKeyChallenge (.*)>(.*)</LockKeyChallenge>#", $data, $matches);\r
- if (count($matches) != 0) {\r
- // yes, we get new LockKeyChallenge\r
- $challenge = $matches[2];\r
- $this->debug_message("*** OIM need new challenge ($challenge) for $to");\r
- }\r
- // auth policy error\r
- // <RequiredAuthPolicy xmlns="http://messenger.msn.com/ws/2004/09/oim/">MBI_SSL</RequiredAuthPolicy>\r
- preg_match("#<RequiredAuthPolicy (.*)>(.*)</RequiredAuthPolicy>#", $data, $matches);\r
- if (count($matches) != 0) {\r
- $auth_policy = $matches[2];\r
- $this->debug_message("*** OIM need new auth policy ($auth_policy) for $to");\r
- }\r
- if ($auth_policy === false && $challenge === false) {\r
- //<faultcode xmlns:q0="http://messenger.msn.com/ws/2004/09/oim/">q0:AuthenticationFailed</faultcode>\r
- preg_match("#<faultcode (.*)>(.*)</faultcode>#", $data, $matches);\r
- if (count($matches) == 0) {\r
- // no error, we assume the OIM is sent\r
- $this->debug_message("*** OIM sent for $to");\r
- return true;\r
- }\r
- $err_code = $matches[2];\r
- //<faultstring>Exception of type 'System.Web.Services.Protocols.SoapException' was thrown.</faultstring>\r
- preg_match("#<faultstring>(.*)</faultstring>#", $data, $matches);\r
- if (count($matches) > 0)\r
- $err_msg = $matches[1];\r
- else\r
- $err_msg = '';\r
- $this->debug_message("*** OIM failed for $to");\r
- $this->debug_message("*** OIM Error code: $err_code");\r
- $this->debug_message("*** OIM Error Message: $err_msg");\r
- return false;\r
- }\r
- return array('challenge' => $challenge, 'auth_policy' => $auth_policy);\r
- }\r
+ }*/\r
\r
// read data for specified size\r
private function ns_readdata($size) {\r
}\r
\r
// read data for specified size for SB\r
- private function sb_readdata($size) {\r
+ private function sb_readdata($socket, $size) {\r
$data = '';\r
$count = 0;\r
- while (!feof($this->SBFp)) {\r
- $buf = @fread($this->SBFp, $size - $count);\r
+ while (!feof($this->SBfp)) {\r
+ $buf = @fread($this->SBfp, $size - $count);\r
$data .= $buf;\r
$count += strlen($buf);\r
if ($count >= $size) break;\r
}\r
\r
// read one line for SB\r
- private function sb_readln() {\r
- $data = @fgets($this->SBFp, 4096);\r
+ private function sb_readln($socket) {\r
+ $data = @fgets($socket, 4096);\r
if ($data !== false) {\r
$data = trim($data);\r
$this->debug_message("SB: <<< $data");\r
\r
// write to server for SB, append \r\n, also increase id\r
// switchboard server only accept \r\n, it will lost connection if just \n only\r
- private function sb_writeln($data) {\r
- @fwrite($this->SBFp, $data."\r\n");\r
+ private function sb_writeln($socket, &$id, $data) {\r
+ @fwrite($socket, $data."\r\n");\r
$this->debug_message("SB: >>> $data");\r
- $this->id++;\r
+ $id++;\r
return;\r
}\r
\r
// write data to server\r
- private function sb_writedata($data) {\r
- @fwrite($this->SBFp, $data);\r
+ private function sb_writedata($socket, $data) {\r
+ @fwrite($socket, $data);\r
$this->debug_message("SB: >>> $data");\r
return;\r
}\r
$this->debug_message("*** p2p: addMsnObj $FilePath::$MsnObj\n");\r
return $MsnObj;\r
}\r
+ \r
private function linetoArray($lines) {\r
$lines=str_replace("\r",'',$lines);\r
$lines=explode("\n",$lines);\r
}\r
return $Data;\r
}\r
+ \r
private function GetPictureFilePath($Context)\r
{\r
$MsnObj=base64_decode($Context);\r
return $this->MsnObjArray[$location];\r
return false;\r
}\r
+ \r
private function GetMsnObjDefine($Message)\r
{\r
$DefineString='';\r
}\r
return $DefineString;\r
}\r
+ \r
/**\r
- * Receive Message Overload Function\r
- * @param $Sender\r
- * @param $Message\r
- * @param $Network 1 => msn , 32 =>yahoo\r
- * @param $IsOIM\r
- * @return unknown_type\r
- */\r
- protected function ReceivedMessage($Sender,$Message,$Network,$IsOIM=false){}\r
- /**\r
- * Remove Us From Member List Overload Function\r
- * @param $User\r
- * @param $Message\r
- * @param $Network 1 => msn , 32 =>yahoo\r
- * @return unknown_type\r
- */\r
- protected function RemoveUsFromMemberList($User,$Network){}\r
- /**\r
- * Add Us to Member List Overload Function\r
- * @param $User\r
- * @param $Message\r
- * @param $Network 1 => msn , 32 =>yahoo\r
- * @return unknown_type\r
+ * Read and handle incoming command from NS\r
*/\r
- protected function AddUsToMemberList($User,$Network){}\r
- \r
- public function signon() {\r
- $this->log_message("*** try to connect to MSN network");\r
- while(!$this->connect($this->user, $this->password))\r
- {\r
- $this->log_message("!!! Can't connect to server: $this->error");\r
- $this->callHandler('ConnectFailed', NULL);\r
- $this->NSRetryWait($this->retry_wait);\r
- }\r
- $this->UpdateContacts();\r
- $this->LastPing=time();\r
- $this->log_message("*** connected, wait for command");\r
- $start_tm = time();\r
- $ping_tm = time();\r
- stream_set_timeout($this->NSfp, $this->NSStreamTimeout);\r
- $this->aContactList = $this->getMembershipList();\r
- if ($this->update_pending) {\r
- if (is_array($this->aContactList)) {\r
- $pending = 'Pending';\r
- foreach ($this->aContactList as $u_domain => $aUserList) {\r
- foreach ($aUserList as $u_name => $aNetworks) {\r
- foreach ($aNetworks as $network => $aData) {\r
- if (isset($aData[$pending])) {\r
- // pending list\r
- $cnt = 0;\r
- foreach (array('Allow', 'Reverse') as $list) {\r
- if (isset($aData[$list]))\r
- $cnt++;\r
- else {\r
- if ($this->addMemberToList($u_name.'@'.$u_domain, $network, $list)) {\r
- $this->aContactList[$u_domain][$u_name][$network][$list] = false;\r
- $cnt++;\r
- }\r
- }\r
- }\r
- if ($cnt >= 2) {\r
- $id = $aData[$pending];\r
- // we can delete it from pending now\r
- if ($this->delMemberFromList($id, $u_name.'@'.$u_domain, $network, $pending))\r
- unset($this->aContactList[$u_domain][$u_name][$network][$pending]);\r
- }\r
- }\r
- else {\r
- // sync list\r
- foreach (array('Allow', 'Reverse') as $list) {\r
- if (!isset($aData[$list])) {\r
- if ($this->addMemberToList($u_name.'@'.$u_domain, $network, $list))\r
- $this->aContactList[$u_domain][$u_name][$network][$list] = false;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- $n = 0;\r
- $sList = '';\r
- $len = 0;\r
- if (is_array($this->aContactList)) {\r
- foreach ($this->aContactList as $u_domain => $aUserList) {\r
- $str = '<d n="'.$u_domain.'">';\r
- $len += strlen($str);\r
- if ($len > 7400) {\r
- $this->aADL[$n] = '<ml l="1">'.$sList.'</ml>';\r
- $n++;\r
- $sList = '';\r
- $len = strlen($str);\r
- }\r
- $sList .= $str;\r
- foreach ($aUserList as $u_name => $aNetworks) {\r
- foreach ($aNetworks as $network => $status) {\r
- $str = '<c n="'.$u_name.'" l="3" t="'.$network.'" />';\r
- $len += strlen($str);\r
- // max: 7500, but <ml l="1"></d></ml> is 19,\r
- // so we use 7475\r
- if ($len > 7475) {\r
- $sList .= '</d>';\r
- $this->aADL[$n] = '<ml l="1">'.$sList.'</ml>';\r
- $n++;\r
- $sList = '<d n="'.$u_domain.'">'.$str;\r
- $len = strlen($sList);\r
- }\r
- else\r
- $sList .= $str;\r
- }\r
- }\r
- $sList .= '</d>';\r
- }\r
- }\r
- $this->aADL[$n] = '<ml l="1">'.$sList.'</ml>';\r
- // NS: >>> BLP {id} BL\r
- $this->ns_writeln("BLP $this->id BL");\r
- foreach ($this->aADL as $str) {\r
- $len = strlen($str);\r
- // NS: >>> ADL {id} {size}\r
- $this->ns_writeln("ADL $this->id $len");\r
- $this->ns_writedata($str);\r
- }\r
- // NS: >>> PRP {id} MFN name\r
- if ($this->alias == '') $this->alias = $user;\r
- $aliasname = rawurlencode($this->alias);\r
- $this->ns_writeln("PRP $this->id MFN $aliasname");\r
- //設定個人大頭貼\r
- //$MsnObj=$this->PhotoStckObj();\r
- // NS: >>> CHG {id} {status} {clientid} {msnobj}\r
- $this->ns_writeln("CHG $this->id NLN $this->clientid");\r
- if($this->PhotoStickerFile!==false)\r
- $this->ns_writeln("CHG $this->id NLN $this->clientid ".rawurlencode($this->MsnObj($this->PhotoStickerFile)));\r
- // NS: >>> UUX {id} length\r
- $str = '<Data><PSM>'.htmlspecialchars($this->psm).'</PSM><CurrentMedia></CurrentMedia><MachineGuid></MachineGuid></Data>';\r
- $len = strlen($str);\r
- $this->ns_writeln("UUX $this->id $len");\r
- $this->ns_writedata($str);\r
- }\r
- \r
- public function NSreceive() {\r
- $this->log_message("*** startup ***");\r
- \r
+ public function nsReceive() {\r
// Sign in again if not signed in or socket failed\r
if (!is_resource($this->NSfp) || feof($this->NSfp)) {\r
$this->callHandler('Reconnect', NULL);\r
$this->signon();\r
+ return;\r
}\r
\r
$data = $this->ns_readln();\r
$this->log_message("*** someone (network: $network) add us to their list (but already in our list): $u_name@$u_domain");\r
else\r
{\r
- $re_login = false;\r
+ $this->re_login = false;\r
$cnt = 0;\r
foreach (array('Allow', 'Reverse') as $list)\r
{\r
if (!$this->addMemberToList($u_name.'@'.$u_domain, $network, $list))\r
{\r
- if ($re_login) {\r
+ if ($this->re_login) {\r
$this->log_message("*** can't add $u_name@$u_domain (network: $network) to $list");\r
continue;\r
}\r
$this->log_message("*** can't add $u_name@$u_domain (network: $network) to $list");\r
continue;\r
}\r
- $re_login = true;\r
+ $this->re_login = true;\r
$this->ticket = $aTickets;\r
$this->log_message("**** get new ticket, try it again");\r
if (!$this->addMemberToList($u_name.'@'.$u_domain, $network, $list))\r
$this->log_message("*** ingnore MSG not for OIM");\r
break;\r
}\r
- $re_login = false;\r
+ $this->re_login = false;\r
if (strcasecmp($maildata, 'too-large') == 0) {\r
$this->log_message("*** large mail-data, need to get the data via SOAP");\r
$maildata = $this->getOIM_maildata();\r
$this->log_message("*** can't re-login, something wrong here, ignore this OIM");\r
break;\r
}\r
- $re_login = true;\r
+ $this->re_login = true;\r
$this->ticket = $aTickets;\r
$this->log_message("**** get new ticket, try it again");\r
$maildata = $this->getOIM_maildata();\r
$sMsg = $this->getOIM_message($oim_msgid);\r
if ($sMsg === false) {\r
$this->log_message("*** can't get OIM, msgid = $oim_msgid");\r
- if ($re_login) {\r
+ if ($this->re_login) {\r
$this->log_message("*** can't get OIM via SOAP, and we already re-login again, so ignore this OIM");\r
continue;\r
}\r
$this->log_message("*** can't re-login, something wrong here, ignore this OIM");\r
continue;\r
}\r
- $re_login = true;\r
+ $this->re_login = true;\r
$this->ticket = $aTickets;\r
$this->log_message("**** get new ticket, try it again");\r
$sMsg = $this->getOIM_message($oim_msgid);\r
}\r
}\r
\r
- public function sendMessageViaSB($message, $to) {\r
+ /**\r
+ * Read and handle incoming command/message from\r
+ * a switchboard session socket\r
+ */\r
+ public function sbReceive() {\r
+ \r
+ }\r
+\r
+ /**\r
+ * Send a request for a switchboard session\r
+ * @param $to Target email for switchboard session\r
+ */\r
+ private function reqSBSession($to) {\r
+ $this->log_message("*** Request SB for $to");\r
+ $this->ns_writeln("XFR $this->id SB");\r
+ \r
+ // Add to the queue of those waiting for a switchboard session reponse\r
+ $this->switchBoardSessions[$to] = array('socket' => NULL, 'id' => 1, 'lastActive' => NULL, 'joined' => false, 'XFRReqTime' => time());\r
+ $this->waitingForXFR[] = &$this->switchBoardSessions[$to];\r
+ }\r
+ \r
+ /**\r
+ * Following an XFR or RNG, connect to the switchboard session\r
+ * @param $mode Mode, either 'Active' (in the case of XFR) or 'Passive' (in the case or RNG)\r
+ * @param $ip IP of Switchboard\r
+ * @param $port Port of Switchboard\r
+ * @param $to User on other end of Switchboard\r
+ * @param $param Array of parameters - 'cki', 'ticket', 'sid'\r
+ * @return Whether successful\r
+ */\r
+ private function connectToSBSession($mode, $ip, $port, $to, $param) {\r
+ $this->debug_message("*** SB: try to connect to switchboard server $ip:$port");\r
+ \r
+ $this->switchBoardSessions[$to]['socket'] = @fsockopen($ip, $port, $errno, $errstr, 5);\r
$socket = $this->switchBoardSessions[$to]['socket'];\r
- $lastActive = $this->switchBoardSessions[$to]['lastActive'];\r
- $joined = $this->switchBoardSessions[$to]['joined'];\r
+ if(!$socket) {\r
+ $this->debug_message("*** SB: Can't connect to $ip:$port, error => $errno, $errstr");\r
+ return false;\r
+ }\r
+ $this->switchBoardSockets[$socket] = $socket;\r
\r
- //FIXME Probably not needed (we're not running in a loop anymore)\r
- /*if($this->kill_me)\r
- {\r
- $this->log_message("*** SB Okay, kill me now!");\r
- endSBSession($socket);\r
- }*/\r
+ stream_set_timeout($socket, $this->SBStreamTimeout);\r
+ \r
+ $id = &$this->switchBoardSessions[$to]['id'];\r
+ \r
+ if($mode == 'Active') {\r
+ $cki_code = $param['cki'];\r
+ \r
+ // SB: >>> USR {id} {user} {cki}\r
+ $this->sb_writeln($socket, $id, "USR $id $this->user $cki_code");\r
+ } else {\r
+ // Passive\r
+ $ticket = $param['ticket'];\r
+ $sid = $param['sid'];\r
+ \r
+ // SB: >>> ANS {id} {user} {ticket} {session_id}\r
+ $this->sb_writeln($socket, $id, "ANS $id $this->user $ticket $sid");\r
+ }\r
+ \r
+ $this->switchBoardSessions[$to]['lastActive'] = time();\r
+ }\r
+ \r
+ /**\r
+ * Send a message via an existing SB session\r
+ * @param $message Message\r
+ * @param $to Recipient for message\r
+ * @return Whether successful\r
+ */\r
+ private function sendMessageViaSB($message, $to) {\r
+ if(socketcheck($this->switchBoardSessions[$to]['socket'])) {\r
+ $this->reqSBSession($to);\r
+ return false;\r
+ }\r
\r
- if(!$Joined) {\r
+ if(!$this->switchBoardSessions[$to]['joined']) {\r
// If our participant has not joined the session yet we can't message them!\r
- //TODO Check the behaviour of the queue runner when we return false\r
return false;\r
}\r
\r
+ $id = &$this->switchBoardSessions[$to]['id'];\r
+ $socket = $this->switchBoardSessions[$to]['socket'];\r
+ \r
$aMessage = $this->getMessage($Message);\r
//CheckEmotion...\r
$MsnObjDefine=$this->GetMsnObjDefine($aMessage);\r
{\r
$SendString="MIME-Version: 1.0\r\nContent-Type: text/x-mms-emoticon\r\n\r\n$MsnObjDefine";\r
$len = strlen($SendString);\r
- $this->SB_writeln("MSG $id N $len");\r
- $id++;\r
- $this->SB_writedata($SendString);\r
- $this->id++;\r
+ // TODO handle failure during write to socket\r
+ $this->sb_writeln($socket, $id, "MSG $id N $len");\r
+ $this->sb_writedata($socket, $SendString);\r
}\r
$len = strlen($aMessage);\r
- $this->SB_writeln("MSG $id N $len");\r
- \r
- // Increment the trID\r
- $this->switchBoardSessions[$to]['id']++;\r
- \r
- $this->SB_writedata($aMessage);\r
+ // TODO handle failure during write to socket\r
+ $this->sb_writeln($socket, $id, "MSG $id N $len");\r
+ $this->sb_writedata($socket, $aMessage);\r
\r
// Don't close the SB session, we might as well leave it open\r
\r
return true;\r
}\r
\r
- //FIXME Not sure if this is needed?\r
- private function endSBSession($socket) {\r
- if (feof($this->SBFp))\r
- {\r
- // lost connection? error? try OIM later\r
- @fclose($this->SBFp);\r
+ /**\r
+ * \r
+ * @param $to\r
+ * @param $sMessage\r
+ * @param $lockkey\r
+ */\r
+ private function sendOIM($to, $sMessage, $lockkey) {\r
+ $XML = '<?xml version="1.0" encoding="utf-8"?>\r
+<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
+ xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\r
+<soap:Header>\r
+ <From memberName="'.$this->user.'"\r
+ friendlyName="=?utf-8?B?'.base64_encode($this->user).'?="\r
+ xml:lang="zh-TW"\r
+ proxy="MSNMSGR"\r
+ xmlns="http://messenger.msn.com/ws/2004/09/oim/"\r
+ msnpVer="'.$this->protocol.'"\r
+ buildVer="'.$this->buildver.'"/>\r
+ <To memberName="'.$to.'" xmlns="http://messenger.msn.com/ws/2004/09/oim/"/>\r
+ <Ticket passport="'.htmlspecialchars($this->ticket['oim_ticket']).'"\r
+ appid="'.$this->prod_id.'"\r
+ lockkey="'.$lockkey.'"\r
+ xmlns="http://messenger.msn.com/ws/2004/09/oim/"/>\r
+ <Sequence xmlns="http://schemas.xmlsoap.org/ws/2003/03/rm">\r
+ <Identifier xmlns="http://schemas.xmlsoap.org/ws/2002/07/utility">http://messenger.msn.com</Identifier>\r
+ <MessageNumber>1</MessageNumber>\r
+ </Sequence>\r
+</soap:Header>\r
+<soap:Body>\r
+ <MessageType xmlns="http://messenger.msn.com/ws/2004/09/oim/">text</MessageType>\r
+ <Content xmlns="http://messenger.msn.com/ws/2004/09/oim/">MIME-Version: 1.0\r
+Content-Type: text/plain; charset=UTF-8\r
+Content-Transfer-Encoding: base64\r
+X-OIM-Message-Type: OfflineMessage\r
+X-OIM-Run-Id: {DAB68CFA-38C9-449B-945E-38AFA51E50A7}\r
+X-OIM-Sequence-Num: 1\r
+\r
+'.chunk_split(base64_encode($sMessage)).'\r
+ </Content>\r
+</soap:Body>\r
+</soap:Envelope>';\r
+\r
+ $header_array = array(\r
+ 'SOAPAction: '.$this->oim_send_soap,\r
+ 'Content-Type: text/xml',\r
+ 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Messenger '.$this->buildver.')'\r
+ );\r
+\r
+ $this->debug_message("*** URL: $this->oim_send_url");\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, $this->oim_send_url);\r
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header_array);\r
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);\r
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);\r
+ if ($this->debug) curl_setopt($curl, CURLOPT_HEADER, 1);\r
+ curl_setopt($curl, CURLOPT_POST, 1);\r
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $XML);\r
+ $data = curl_exec($curl);\r
+ $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
+ curl_close($curl);\r
+ $this->debug_message("*** Get Result:\n$data");\r
+\r
+ if ($http_code == 200) {\r
+ $this->debug_message("*** OIM sent for $to");\r
+ return true;\r
+ }\r
+\r
+ $challenge = false;\r
+ $auth_policy = false;\r
+ // the lockkey is invalid, authenticated fail, we need challenge it again\r
+ // <LockKeyChallenge xmlns="http://messenger.msn.com/ws/2004/09/oim/">364763969</LockKeyChallenge>\r
+ preg_match("#<LockKeyChallenge (.*)>(.*)</LockKeyChallenge>#", $data, $matches);\r
+ if (count($matches) != 0) {\r
+ // yes, we get new LockKeyChallenge\r
+ $challenge = $matches[2];\r
+ $this->debug_message("*** OIM need new challenge ($challenge) for $to");\r
+ }\r
+ // auth policy error\r
+ // <RequiredAuthPolicy xmlns="http://messenger.msn.com/ws/2004/09/oim/">MBI_SSL</RequiredAuthPolicy>\r
+ preg_match("#<RequiredAuthPolicy (.*)>(.*)</RequiredAuthPolicy>#", $data, $matches);\r
+ if (count($matches) != 0) {\r
+ $auth_policy = $matches[2];\r
+ $this->debug_message("*** OIM need new auth policy ($auth_policy) for $to");\r
+ }\r
+ if ($auth_policy === false && $challenge === false) {\r
+ //<faultcode xmlns:q0="http://messenger.msn.com/ws/2004/09/oim/">q0:AuthenticationFailed</faultcode>\r
+ preg_match("#<faultcode (.*)>(.*)</faultcode>#", $data, $matches);\r
+ if (count($matches) == 0) {\r
+ // no error, we assume the OIM is sent\r
+ $this->debug_message("*** OIM sent for $to");\r
+ return true;\r
+ }\r
+ $err_code = $matches[2];\r
+ //<faultstring>Exception of type 'System.Web.Services.Protocols.SoapException' was thrown.</faultstring>\r
+ preg_match("#<faultstring>(.*)</faultstring>#", $data, $matches);\r
+ if (count($matches) > 0)\r
+ $err_msg = $matches[1];\r
+ else\r
+ $err_msg = '';\r
+ $this->debug_message("*** OIM failed for $to");\r
+ $this->debug_message("*** OIM Error code: $err_code");\r
+ $this->debug_message("*** OIM Error Message: $err_msg");\r
return false;\r
}\r
- $this->SB_writeln("OUT");\r
- @fclose($this->SBFp);\r
- return true;\r
+ return array('challenge' => $challenge, 'auth_policy' => $auth_policy);\r
}\r
\r
- private function getSBSession($to) {\r
- \r
+ /**\r
+ * Send a message to a user on another network\r
+ * @param $message Message\r
+ * @param $to Intended recipient\r
+ * @param $network Network\r
+ */\r
+ private function sendOtherNetworkMessage($message, $to, $network) {\r
+ $message=$this->getMessage($nessage, $network);\r
+ $len = strlen($message);\r
+ $this->ns_writeln("UUM $this->id $to $network 1 $len");\r
+ $this->ns_writedata($Message);\r
+ $this->log_message("*** sent to $to (network: $network):\n$Message");\r
}\r
\r
+ /**\r
+ * Send a message\r
+ * @param $message Message\r
+ * @param $to To address in form user@host.com@network\r
+ * where network is 1 for MSN, 32 for Yahoo\r
+ * and 'Offline' for offline messages\r
+ */\r
public function sendMessage($message, $to) {\r
if($message != '') {\r
list($name,$host,$network)=explode('@',$to);\r
$network=$network==''?1:$network;\r
\r
- if($network === 1 && isset($this->switchBoardSessions[$to])) {\r
+ if($network === 1 && $this->switchBoardSessions[$to]['socket'] != NULL && time()-$this->switchBoardSessions[$to]['lastActive'] < $this->SBIdleTimeout) {\r
$recipient = $name . $host;\r
$this->debug_message("*** Sending Message to $recipient using existing SB session");\r
return $this->sendMessageViaSB($message, $recipient);\r
+ } elseif($network == 'Offline') {\r
+ //Send OIM\r
+ //FIXME: 修正Send OIM\r
+ $lockkey='';\r
+ for ($i = 0; $i < $this->oim_try; $i++)\r
+ {\r
+ if(($oim_result = $this->sendOIM($To, $Message, $lockkey))===true) break;\r
+ if (is_array($oim_result) && $oim_result['challenge'] !== false) {\r
+ // need challenge lockkey\r
+ $this->log_message("*** we need a new challenge code for ".$oim_result['challenge']);\r
+ $lockkey = $this->getChallenge($oim_result['challenge']);\r
+ continue;\r
+ }\r
+ if ($oim_result === false || $oim_result['auth_policy'] !== false)\r
+ {\r
+ if ($this->re_login)\r
+ {\r
+ $this->log_message("*** can't send OIM, but we already re-login again, so ignore this OIM");\r
+ break;\r
+ }\r
+ $this->log_message("*** can't send OIM, maybe ticket expired, try to login again");\r
+ // maybe we need to re-login again\r
+ if(!$this->get_passport_ticket())\r
+ {\r
+ $this->log_message("*** can't re-login, something wrong here, ignore this OIM");\r
+ break;\r
+ }\r
+ $this->log_message("**** get new ticket, try it again");\r
+ continue;\r
+ }\r
+ }\r
} else {\r
$this->debug_message("*** Not MSN network or no existing SB session");\r
- //TODO implement creation of SB session etc\r
+ $this->reqSBSession($to);\r
+ return false;\r
}\r
}\r
return true;\r
}\r
\r
+ //FIXME Not sure if this is needed?\r
+ private function endSBSession($socket) {\r
+ if (feof($socket))\r
+ {\r
+ // lost connection? error? try OIM later\r
+ @fclose($socket);\r
+ return false;\r
+ }\r
+ $fake = 0;\r
+ $this->sb_writeln($socket, $fake, "OUT");\r
+ @fclose($socket);\r
+ return true;\r
+ }\r
+ \r
/**\r
* Sends a ping command\r
* \r
* Should be called about every 50 seconds\r
*/\r
- public function send_ping() {\r
+ public function sendPing() {\r
// NS: >>> PNG\r
$this->ns_writeln("PNG");\r
}\r
\r
+ /**\r
+ * Get the NS socket\r
+ */\r
public function getNSSocket() {\r
return $this->NSfp;\r
}\r
\r
- // TODO Allow for multiple SB session sockets\r
- public function getSBSocket() {\r
- return $this->SBfp;\r
+ /**\r
+ * Get the Switchboard sockets currently in use\r
+ */\r
+ public function getSBSockets() {\r
+ return $this->switchBoardSockets;\r
}\r
\r
+ /**\r
+ * Get all the sockets currently in use\r
+ */\r
public function getSockets() {\r
- return array($this->NSfp, $this->SBfp);\r
+ return array_merge($this->NSfp, $this->switchBoardSockets);\r
+ }\r
+ \r
+ /** \r
+ * Checks socket for end of file\r
+ *\r
+ * @access public\r
+ * @param Resource $socket Socket to check\r
+ * @return boolean true if end of file (socket) \r
+ */\r
+ private static function socketcheck($socket){\r
+ $info = stream_get_meta_data($socket);\r
+ return $info['eof'];\r
}\r
\r
/**\r