This class uses MSNP15.\r
\r
In addition to PHP5, the additional php modules required are:\r
-curl pcre mhash mcrypt bcmath\r
+curl pcre mcrypt bcmath\r
\r
*/\r
\r
const PROD_KEY = 'PK}_A_0N_K%O?A9S';\r
const PROD_ID = 'PROD0114ES4Z%Q5W';\r
const LOGIN_METHOD = 'SSO';\r
- \r
+\r
const OIM_SEND_URL = 'https://ows.messenger.msn.com/OimWS/oim.asmx';\r
const OIM_SEND_SOAP = 'http://messenger.live.com/ws/2006/09/oim/Store2';\r
- \r
+\r
const OIM_MAILDATA_URL = 'https://rsi.hotmail.com/rsi/rsi.asmx';\r
const OIM_MAILDATA_SOAP = 'http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMetadata';\r
const OIM_READ_URL = 'https://rsi.hotmail.com/rsi/rsi.asmx';\r
\r
const DELMEMBER_URL = 'https://contacts.msn.com/abservice/SharingService.asmx';\r
const DELMEMBER_SOAP = 'http://www.msn.com/webservices/AddressBook/DeleteMember';\r
- \r
+\r
// the message length (include header) is limited (maybe since WLM 8.5 released)\r
// for WLM: 1664 bytes\r
// for YIM: 518 bytes\r
const MAX_MSN_MESSAGE_LEN = 1664;\r
const MAX_YAHOO_MESSAGE_LEN = 518;\r
- \r
+\r
private $debug;\r
private $timeout;\r
- \r
+\r
private $id;\r
private $ticket;\r
private $user = '';\r
private $port = 1863;\r
\r
private $clientid = '';\r
- \r
+\r
private $error = '';\r
\r
private $authed = false;\r
// Check support\r
if (!function_exists('curl_init')) throw new Exception("curl module not found!\n");\r
if (!function_exists('preg_match')) throw new Exception("pcre module not found!\n");\r
- if (!function_exists('mhash')) throw new Exception("mhash module not found!\n");\r
if (!function_exists('mcrypt_cbc')) throw new Exception("mcrypt module not found!\n");\r
if (!function_exists('bcmod')) throw new Exception("bcmath module not found!\n");\r
\r
/**\r
* Signon methods\r
*/\r
- \r
+\r
/**\r
* Connect to the NS server\r
*\r
$this->user = $user;\r
$this->password = $password;\r
// NS: <<< USR {id} SSO S {policy} {nonce}\r
- @list(/* USR */, /* id */, /* SSO */, /* S */, $policy, $nonce,) = @explode(' ', $data);\r
+ @list(/* USR */, /* id */, /* SSO */, /* S */, $policy, $nonce) = @explode(' ', $data);\r
\r
$this->passport_policy = $policy;\r
$aTickets = $this->get_passport_ticket();\r
// NS: >>> OUT\r
$this->ns_writeln("OUT");\r
@fclose($this->NSfp);\r
- $this->error = 'Passport authenticated fail!';\r
+ $this->error = 'Passport authentication failed!';\r
return false;\r
}\r
\r
// NS: <<< XFR {id} NS {server} 0 {server}\r
// MSNP15\r
// NS: <<< XFR {id} NS {server} U D\r
- @list(/* XFR */, /* id */, $Type, $server, /* ... */) = @explode(' ', $data);\r
+ @list(/* XFR */, /* id */, $Type, $server) = @explode(' ', $data);\r
if ($Type!='NS') break;\r
@list($ip, $port) = @explode(':', $server);\r
// this connection will close after XFR\r
case 'GCF':\r
// return some policy data after 'USR {id} SSO I {user}' command\r
// NS: <<< GCF 0 {size}\r
- @list(/* GCF */, /* 0 */, $size,) = @explode(' ', $data);\r
+ @list(/* GCF */, /* 0 */, $size) = @explode(' ', $data);\r
// we don't need the data, just read it and drop\r
if (is_numeric($size) && $size > 0)\r
$this->ns_readdata($size);\r
/* FIXME Don't implement the signon as a loop or we could hang\r
* the queue handler! */\r
$this->debug_message('*** Trying to connect to MSN network');\r
- \r
+\r
// Remove any remaining switchboard sessions\r
$this->switchBoardSessions = array();\r
$this->switchBoardSessionLookup = array();\r
}\r
\r
// Update contacts\r
- if ($this->UpdateContacts() === false) continue;\r
+ if ($this->UpdateContacts() === false) {\r
+ $this->signonFailure('');\r
+ continue;\r
+ }\r
\r
// Get membership lists\r
if (($this->aContactList = $this->getMembershipList()) === false) {\r
* @return void\r
*/\r
private function signonFailure($message) {\r
- $this->debug_message($message);\r
- $this->callHandler('ConnectFailed');\r
+ if(!empty($message)) {\r
+ $this->debug_message($message);\r
+ }\r
+ $this->callHandler('ConnectFailed', $message);\r
$this->NSRetryWait($this->retry_wait);\r
}\r
\r
/**\r
* NS and SB command handling methods\r
*/\r
- \r
+\r
/**\r
* Read and handle incoming command from NS\r
*\r
$this->signon();\r
return;\r
}\r
- \r
+\r
switch (substr($data, 0, 3)) {\r
case 'SBS':\r
// after 'USR {id} OK {user} {verify} 0' response, the server will send SBS and profile to us\r
\r
case 'LST':\r
// NS: <<< LST {email} {alias} 11 0\r
- @list(/* LST */, $email, /* alias */,) = @explode(' ', $data);\r
+ @list(/* LST */, $email) = @explode(' ', $data);\r
@list($u_name, $u_domain) = @explode('@', $email);\r
if (!isset($this->aContactList[$u_domain][$u_name][1])) {\r
$this->aContactList[$u_domain][$u_name][1]['Allow'] = 'Allow';\r
case 'ADL':\r
// randomly, we get ADL command, someone add us to their contact list for MSNP15\r
// NS: <<< ADL 0 {size}\r
- @list(/* ADL */, /* 0 */, $size,) = @explode(' ', $data);\r
+ @list(/* ADL */, /* 0 */, $size) = @explode(' ', $data);\r
if (is_numeric($size) && $size > 0) {\r
$data = $this->ns_readdata($size);\r
preg_match('#<ml><d n="([^"]+)"><c n="([^"]+)"(.*) t="(\d*)"(.*) /></d></ml>#', $data, $matches);\r
case 'RML':\r
// randomly, we get RML command, someome remove us to their contact list for MSNP15\r
// NS: <<< RML 0 {size}\r
- @list(/* RML */, /* 0 */, $size,) = @explode(' ', $data);\r
+ @list(/* RML */, /* 0 */, $size) = @explode(' ', $data);\r
if (is_numeric($size) && $size > 0) {\r
$data = $this->ns_readdata($size);\r
preg_match('#<ml><d n="([^"]+)"><c n="([^"]+)"(.*) t="(\d*)"(.*) /></d></ml>#', $data, $matches);\r
case 'MSG':\r
// randomly, we get MSG notification from server\r
// NS: <<< MSG Hotmail Hotmail {size}\r
- @list(/* MSG */, /* Hotmail */, /* Hotmail */, $size,) = @explode(' ', $data);\r
+ @list(/* MSG */, /* Hotmail */, /* Hotmail */, $size) = @explode(' ', $data);\r
if (is_numeric($size) && $size > 0) {\r
$data = $this->ns_readdata($size);\r
$aLines = @explode("\n", $data);\r
case 'UBM':\r
// randomly, we get UBM, this is the message from other network, like Yahoo!\r
// NS: <<< UBM {email} $network $type {size}\r
- @list(/* UBM */, $from_email, $network, $type, $size,) = @explode(' ', $data);\r
+ @list(/* UBM */, $from_email, $network, $type, $size) = @explode(' ', $data);\r
if (is_numeric($size) && $size > 0) {\r
$data = $this->ns_readdata($size);\r
$aLines = @explode("\n", $data);\r
case 'UBX':\r
// randomly, we get UBX notification from server\r
// NS: <<< UBX email {network} {size}\r
- @list(/* UBX */, /* email */, /* network */, $size,) = @explode(' ', $data);\r
+ @list(/* UBX */, /* email */, /* network */, $size) = @explode(' ', $data);\r
// we don't need the notification data, so just ignore it\r
if (is_numeric($size) && $size > 0)\r
$this->ns_readdata($size);\r
case 'CHL':\r
// randomly, we'll get challenge from server\r
// NS: <<< CHL 0 {code}\r
- @list(/* CHL */, /* 0 */, $chl_code,) = @explode(' ', $data);\r
+ @list(/* CHL */, /* 0 */, $chl_code) = @explode(' ', $data);\r
$fingerprint = $this->getChallenge($chl_code);\r
// NS: >>> QRY {id} {product_id} 32\r
// NS: >>> fingerprint\r
// NS: <<< XFR {id} NS {server} U D\r
// for normal switchboard XFR\r
// NS: <<< XFR {id} SB {server} CKI {cki} U messenger.msn.com 0\r
- @list(/* XFR */, /* {id} */, $server_type, $server, /* CKI */, $cki_code, /* ... */) = @explode(' ', $data);\r
+ @list(/* XFR */, /* {id} */, $server_type, $server, /* CKI */, $cki_code) = @explode(' ', $data);\r
@list($ip, $port) = @explode(':', $server);\r
if ($server_type != 'SB') {\r
// maybe exit?\r
// someone is trying to talk to us\r
// NS: <<< RNG {session_id} {server} {auth_type} {ticket} {email} {alias} U {client} 0\r
$this->debug_message("NS: <<< RNG $data");\r
- @list(/* RNG */, $sid, $server, /* auth_type */, $ticket, $email, $name,) = @explode(' ', $data);\r
+ @list(/* RNG */, $sid, $server, /* auth_type */, $ticket, $email, $name) = @explode(' ', $data);\r
@list($sb_ip, $sb_port) = @explode(':', $server);\r
$this->debug_message("*** RING from $email, $sb_ip:$sb_port");\r
$this->addContact($email, 1, $email, true);\r
$this->connectToSBSession('Passive', $sb_ip, $sb_port, $email, array('sid' => $sid, 'ticket' => $ticket));\r
break;\r
- \r
+\r
case 'NLN':\r
// NS: <<< NLN {status} {email} {networkid} {nickname} {clientid} {dpobj}\r
- // NS: <<< NLN NLN darkip@inflatablegoldfish.com 1 Luke 2685403136 0\r
- @list(/* NLN */, $status, $email, $network, $nickname, /* clientid */, /* dbobj */,) = @explode(' ', $data);\r
+ @list(/* NLN */, $status, $email, $network, $nickname) = @explode(' ', $data);\r
$this->callHandler('StatusChange', array('screenname' => $email, 'status' => $status, 'network' => $network, 'nickname' => $nickname));\r
break;\r
- \r
+\r
case 'OUT':\r
// force logout from NS\r
// NS: <<< OUT xxx\r
// SB: <<< IRO {id} {rooster} {roostercount} {email} {alias} {clientid}\r
@list(/* IRO */, /* id */, $cur_num, $total, $email, $alias, $clientid) = @explode(' ', $data);\r
$this->debug_message("*** $email joined session");\r
- $session['joined'] = true;\r
+ if ($email == $session['to']) {\r
+ $session['joined'] = true;\r
+ $this->callHandler('SessionReady', array('to' => $email));\r
+ }\r
break;\r
case 'BYE':\r
$this->debug_message("*** Quit for BYE");\r
- $this->endSBSession();\r
+ $this->endSBSession($socket);\r
break;\r
case 'USR':\r
// SB: <<< USR {id} OK {user} {alias}\r
case 'JOI':\r
// SB: <<< JOI {user} {alias} {clientid?}\r
// someone join us\r
- // we don't need the data, just ignore it\r
- // no more user here\r
- $session['joined'] = true;\r
+ @list(/* JOI */, $email) = @explode(' ', $data);\r
+ if ($email == $session['to']) {\r
+ $session['joined'] = true;\r
+ $this->callHandler('SessionReady', array('to' => $email));\r
+ }\r
break;\r
case 'MSG':\r
// SB: <<< MSG {email} {alias} {len}\r
- @list(/* MSG */, $from_email, /* alias */, $len, ) = @explode(' ', $data);\r
+ @list(/* MSG */, $from_email, /* alias */, $len) = @explode(' ', $data);\r
$len = trim($len);\r
$data = $this->sb_readdata($socket, $len);\r
$aLines = @explode("\n", $data);\r
break;\r
}\r
$this->debug_message("*** MSG from $from_email: $sMsg");\r
- $this->callHandler('IMin', array('sender' => $from_email, 'message' => $sMsg, 'network' => $network, 'offline' => false));\r
+ $this->callHandler('IMin', array('sender' => $from_email, 'message' => $sMsg, 'network' => 1, 'offline' => false));\r
break;\r
case '217':\r
$this->debug_message('*** User '.$session['to'].' is offline. Trying OIM.');\r
if (is_numeric($code)) {\r
$this->error = "Error code: $code, please check the detail information from: http://msnpiki.msnfanatic.com/index.php/Reference:Error_List";\r
$this->debug_message("*** SB: $this->error");\r
- $sessionEnd=true;\r
}\r
break;\r
}\r
/**\r
* Switchboard related methods\r
*/\r
- \r
+\r
/**\r
* Send a request for a switchboard session\r
*\r
'offline' => false,\r
'XFRReqTime' => time()\r
);\r
- \r
+\r
// Change the index of the session to the socket\r
$intsocket = (int) $socket;\r
$this->switchBoardSessions[$intsocket] = $this->switchBoardSessions[$to];\r
unset($this->switchBoardSessions[$to]);\r
- \r
+\r
$id = &$this->switchBoardSessions[$intsocket]['id'];\r
\r
if ($mode == 'Active') {\r
$this->sb_writeln($socket, $id, "ANS $id $this->user $ticket $sid");\r
}\r
}\r
- \r
+\r
/**\r
* Called when we want to end a switchboard session\r
* or a switchboard session ends\r
if (self::socketcheck($socket)) {\r
return false;\r
}\r
- \r
- $intsocket = (int) $socket;\r
- if (!$this->switchBoardSessions[$intsocket]['joined']) {\r
- // If our participant has not joined the session yet we can't message them!\r
- return false;\r
- }\r
\r
- $id = &$this->switchBoardSessions[$intsocket]['id'];\r
+ $id = &$this->switchBoardSessions[(int) $socket]['id'];\r
\r
$aMessage = $this->getMessage($message);\r
// CheckEmotion...\r
\r
if ($this->sb_writeln($socket, $id, "MSG $id N $len") === false ||\r
$this->sb_writedata($socket, $SendString) === false) {\r
+ $this->endSBSession($socket);\r
return false;\r
}\r
}\r
\r
if ($this->sb_writeln($socket, $id, "MSG $id N $len") === false ||\r
$this->sb_writedata($socket, $aMessage) === false) {\r
- return false;\r
+ $this->endSBSession($socket);\r
+ return false;\r
}\r
\r
// Don't close the SB session, we might as well leave it open\r
* where network is 1 for MSN, 32 for Yahoo\r
* and 'Offline' for offline messages\r
* @param string $message Message\r
+ * @param boolean &$waitForSession Boolean passed by reference,\r
+ * if set to true on return, message\r
+ * did not fail to send but is\r
+ * waiting for a valid session\r
+ *\r
+ * @return boolean true on success\r
*/\r
- public function sendMessage($to, $message) {\r
+ public function sendMessage($to, $message, &$waitForSession) {\r
if ($message != '') {\r
- list($name, $host, $network) = explode('@', $to);\r
- $network = $network == '' ? 1 : $network;\r
+ $toParts = explode('@', $to);\r
+ if(count($toParts) < 3) {\r
+ list($name, $host) = $toParts;\r
+ $network = 1;\r
+ } else {\r
+ list($name, $host, $network) = $toParts;\r
+ }\r
+\r
$recipient = $name.'@'.$host;\r
\r
if ($network === 1) {\r
if (!isset($this->switchBoardSessionLookup[$recipient])) {\r
- if (!isset($this->switchBoardSessions[$recipient]) || time() - $this->switchBoardSessions[$recipient]['XFRReqTime'] > $this->XFRReqTimeout) {\r
- $this->debug_message("*** No existing SB session or request has timed out");\r
- $this->reqSBSession($recipient);\r
- }\r
- return false;\r
+ if (!isset($this->switchBoardSessions[$recipient]) || time() - $this->switchBoardSessions[$recipient]['XFRReqTime'] > $this->XFRReqTimeout) {\r
+ $this->debug_message("*** No existing SB session or request has timed out");\r
+ $this->reqSBSession($recipient);\r
+ }\r
+\r
+ $waitForSession = true;\r
+ return false;\r
} else {\r
$socket = $this->switchBoardSessionLookup[$recipient];\r
- if ($this->switchBoardSessions[(int) $socket]['offline']) {\r
+ $intsocket = (int) $socket;\r
+ if ($this->switchBoardSessions[$intsocket]['offline']) {\r
$this->debug_message("*** Contact ($recipient) offline, sending OIM");\r
$this->endSBSession($socket);\r
+ $waitForSession = false;\r
return $this->sendMessage($recipient.'@Offline', $message);\r
} else {\r
+ if ($this->switchBoardSessions[$intsocket]['joined'] !== true) {\r
+ $this->debug_message("*** Recipient has not joined session, returning false");\r
+ $waitForSession = true;\r
+ return false;\r
+ }\r
+\r
$this->debug_message("*** Attempting to send message to $recipient using existing SB session");\r
\r
if ($this->sendMessageViaSB($recipient, $message)) {\r
$this->debug_message('*** Message sent successfully');\r
return true;\r
- } else {\r
- $this->debug_message('*** Message sending failed, requesting new SB session');\r
- $this->reqSBSession($recipient);\r
- return false;\r
}\r
+\r
+ $waitForSession = false;\r
+ return false;\r
}\r
}\r
} elseif ($network == 'Offline') {\r
/**\r
* OIM methods\r
*/\r
- \r
+\r
/**\r
* Get OIM mail data\r
*\r
$this->debug_message("*** OIM ($msgid) deleted");\r
return $sMsg;\r
}\r
- \r
+\r
/**\r
* Send offline message\r
*\r
}\r
return array('challenge' => $challenge, 'auth_policy' => $auth_policy);\r
}\r
- \r
+\r
/**\r
* Contact / Membership list methods\r
*/\r
- \r
+\r
/**\r
* Fetch contact list\r
*\r
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);\r
curl_close($curl);\r
$this->debug_message("*** Get Result:\n$data");\r
- \r
+\r
if ($http_code != 200) return false;\r
$p = $data;\r
$aMemberships = array();\r
}\r
return $aContactList;\r
}\r
- \r
+\r
/**\r
* MsnObj related methods\r
*/\r
- \r
+\r
/**\r
*\r
* @param $FilePath 圖檔路徑\r
}\r
return $DefineString;\r
}\r
- \r
+\r
/**\r
* Socket methods\r
*/\r
- \r
+\r
/**\r
* Read data of specified size from NS socket\r
- * \r
+ *\r
* @param integer $size Size to read\r
* @return string Data read\r
*/\r
\r
/**\r
* Read line from the NS socket\r
- * \r
+ *\r
* @return string Data read\r
*/\r
private function ns_readln() {\r
\r
/**\r
* Write line to NS socket\r
- * \r
+ *\r
* Also increments id\r
- * \r
+ *\r
* @param string $data Line to write to socket\r
* @return mixed Bytes written or false on failure\r
*/\r
\r
/**\r
* Write data to NS socket\r
- * \r
+ *\r
* @param string $data Data to write to socket\r
* @return mixed Bytes written or false on failure\r
*/\r
\r
/**\r
* Read data of specified size from given SB socket\r
- * \r
+ *\r
* @param resource $socket SB socket\r
* @param integer $size Size to read\r
* @return string Data read\r
\r
/**\r
* Read line from given SB socket\r
- * \r
+ *\r
* @param resource $socket SB Socket\r
* @return string Line read\r
*/\r
\r
/**\r
* Write line to given SB socket\r
- * \r
+ *\r
* Also increments id\r
- * \r
+ *\r
* @param resource $socket SB socket\r
* @param integer $id Reference to SB id\r
* @param string $data Line to write\r
\r
/**\r
* Write data to given SB socket\r
- * \r
+ *\r
* @param resource $socket SB socket\r
* @param $data Data to write to socket\r
* @return mixed Bytes written or false on error\r
$info = stream_get_meta_data($socket);\r
return $info['eof'];\r
}\r
- \r
+\r
/**\r
* Key generation methods\r
*/\r
- \r
+\r
private 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
+ $hash1 = $this->mhash_sha1($magic, $key);\r
+ $hash2 = $this->mhash_sha1($hash1.$magic, $key);\r
+ $hash3 = $this->mhash_sha1($hash1, $key);\r
+ $hash4 = $this->mhash_sha1($hash3.$magic, $key);\r
return $hash2.substr($hash4, 0, 4);\r
}\r
\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
+ $hash = $this->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
return base64_encode($blob);\r
}\r
- \r
+\r
/**\r
* Generate challenge response\r
*\r
\r
return $hash;\r
}\r
- \r
+\r
/**\r
* Utility methods\r
*/\r
- \r
+\r
private function Array2SoapVar($Array, $ReturnSoapVarObj = true, $TypeName = null, $TypeNameSpace = null) {\r
$ArrayString = '';\r
foreach($Array as $Key => $Val) {\r
$Attrib = '';\r
if (is_array($Val[':'])) {\r
foreach ($Val[':'] as $AttribName => $AttribVal)\r
- $Attrib .= " $AttribName = '$AttribVal'";\r
+ $Attrib .= " $AttribName = '$AttribVal'";\r
}\r
if ($Key{0} == '!') {\r
//List Type Define\r
if ($ReturnSoapVarObj) return new SoapVar($ArrayString, XSD_ANYXML, $TypeName, $TypeNameSpace);\r
return $ArrayString;\r
}\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
+\r
/**\r
* Get Passport ticket\r
*\r
// <wsse:BinarySecurityToken Id="Compact1">t=tick&p=</wsse:BinarySecurityToken>\r
// <wst:BinarySecret>binary secret</wst:BinarySecret>\r
// RST2: messenger.msn.com\r
- // <wsse:BinarySecurityToken Id="PPToken2">t=tick</wsse:BinarySecurityToken>\r
+ // <wsse:BinarySecurityToken Id="Compact2">t=tick</wsse:BinarySecurityToken>\r
// RST3: contacts.msn.com\r
// <wsse:BinarySecurityToken Id="Compact3">t=tick&p=</wsse:BinarySecurityToken>\r
// RST4: messengersecure.live.com\r
preg_match("#".\r
"<wsse\:BinarySecurityToken Id=\"Compact1\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
"<wst\:BinarySecret>(.*)</wst\:BinarySecret>(.*)".\r
- "<wsse\:BinarySecurityToken Id=\"PPToken2\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
+ "<wsse\:BinarySecurityToken Id=\"Compact2\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
"<wsse\:BinarySecurityToken Id=\"Compact3\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
"<wsse\:BinarySecurityToken Id=\"Compact4\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
"<wsse\:BinarySecurityToken Id=\"Compact5\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
\r
// no ticket found!\r
if (count($matches) == 0) {\r
- $this->debug_message('*** Could not get passport ticket!');\r
- return false;\r
+ // Since 2011/2/15, the return value will be Compact2, not PPToken2\r
+\r
+ // we need ticket and secret code\r
+ // RST1: messengerclear.live.com\r
+ // <wsse:BinarySecurityToken Id="Compact1">t=tick&p=</wsse:BinarySecurityToken>\r
+ // <wst:BinarySecret>binary secret</wst:BinarySecret>\r
+ // RST2: messenger.msn.com\r
+ // <wsse:BinarySecurityToken Id="PPToken2">t=tick</wsse:BinarySecurityToken>\r
+ // RST3: contacts.msn.com\r
+ // <wsse:BinarySecurityToken Id="Compact3">t=tick&p=</wsse:BinarySecurityToken>\r
+ // RST4: messengersecure.live.com\r
+ // <wsse:BinarySecurityToken Id="Compact4">t=tick&p=</wsse:BinarySecurityToken>\r
+ // RST5: spaces.live.com\r
+ // <wsse:BinarySecurityToken Id="Compact5">t=tick&p=</wsse:BinarySecurityToken>\r
+ // RST6: storage.msn.com\r
+ // <wsse:BinarySecurityToken Id="Compact6">t=tick&p=</wsse:BinarySecurityToken>\r
+ preg_match("#".\r
+ "<wsse\:BinarySecurityToken Id=\"Compact1\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
+ "<wst\:BinarySecret>(.*)</wst\:BinarySecret>(.*)".\r
+ "<wsse\:BinarySecurityToken Id=\"Compact2\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
+ "<wsse\:BinarySecurityToken Id=\"Compact3\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
+ "<wsse\:BinarySecurityToken Id=\"Compact4\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
+ "<wsse\:BinarySecurityToken Id=\"Compact5\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
+ "<wsse\:BinarySecurityToken Id=\"Compact6\">(.*)</wsse\:BinarySecurityToken>(.*)".\r
+ "#",\r
+ $data, $matches);\r
+ // no ticket found!\r
+ if (count($matches) == 0) {\r
+ $this->debug_message("*** Can't get passport ticket!");\r
+ return false;\r
+ }\r
}\r
\r
//$this->debug_message(var_export($matches, true));\r
$this->ABAuthHeader = new SoapHeader('http://www.msn.com/webservices/AddressBook', 'ABAuthHeader', $this->Array2SoapVar($ABAuthHeaderArray));\r
return $aTickets;\r
}\r
- \r
+\r
/**\r
* Generate the data to send a message\r
*\r
$msg = substr($sMessage, 0, $maxlen);\r
return $msg_header.$msg;\r
}\r
- \r
+\r
/**\r
* Sleep for the given number of seconds\r
*\r
$this->debug_message("*** Sleeping for $wait seconds before retrying");\r
sleep($wait);\r
}\r
- \r
+\r
/**\r
* Sends a ping command\r
*\r
// NS: >>> PNG\r
$this->ns_writeln("PNG");\r
}\r
- \r
+\r
/**\r
* Methods to add / call callbacks\r
*/\r
* Registers a user handler\r
*\r
* Handler List\r
- * IMIn, Pong, ConnectFailed, Reconnect,\r
+ * IMIn, SessionReady, Pong, ConnectFailed, Reconnect,\r
* AddedToList, RemovedFromList, StatusChange\r
*\r
* @param string $event Event name\r
return false;\r
}\r
}\r
- \r
+\r
/**\r
* Debugging methods\r
*/\r
- \r
+\r
/**\r
* Print message if debugging is enabled\r
- * \r
+ *\r
* @param string $str Message to print\r
*/\r
private function debug_message($str) {\r
if (!$this->debug) return;\r
echo $str."\n";\r
}\r
- \r
+\r
/**\r
* Dump binary data\r
- * \r
+ *\r
* @param string $str Data string\r
* @return Binary data\r
*/\r
$buf .= "$h_str $a_str\n";\r
return $buf;\r
}\r
+\r
+ function mhash_sha1($data, $key)\r
+ {\r
+ if (extension_loaded("mhash"))\r
+ return mhash(MHASH_SHA1, $data, $key);\r
+\r
+ if (function_exists("hash_hmac"))\r
+ return hash_hmac('sha1', $data, $key, true);\r
+\r
+ // RFC 2104 HMAC implementation for php. Hacked by Lance Rushing\r
+ $b = 64;\r
+ if (strlen($key) > $b)\r
+ $key = pack("H*", sha1($key));\r
+ $key = str_pad($key, $b, chr(0x00));\r
+ $ipad = str_pad("", $b, chr(0x36));\r
+ $opad = str_pad("", $b, chr(0x5c));\r
+ $k_ipad = $key ^ $ipad ;\r
+ $k_opad = $key ^ $opad;\r
+\r
+ $sha1_value = sha1($k_opad . pack("H*", sha1($k_ipad . $data)));\r
+\r
+ $hash_data = '';\r
+ $str = join('',explode('\x', $sha1_value));\r
+ $len = strlen($str);\r
+ for ($i = 0; $i < $len; $i += 2)\r
+ $hash_data .= chr(hexdec(substr($str, $i, 2)));\r
+ return $hash_data;\r
+ }\r
}\r