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
/**\r
* Signon methods\r
*/\r
- \r
+\r
/**\r
* Connect to the NS server\r
*\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
* @return void\r
*/\r
private function signonFailure($message) {\r
- if(!empty($message)) {\r
+ if(!empty($message)) {\r
$this->debug_message($message);\r
- }\r
+ }\r
$this->callHandler('ConnectFailed');\r
$this->NSRetryWait($this->retry_wait);\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
$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) = @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
/**\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
\r
if ($this->sb_writeln($socket, $id, "MSG $id N $len") === false ||\r
$this->sb_writedata($socket, $aMessage) === false) {\r
- return false;\r
+ return false;\r
}\r
\r
// Don't close the SB session, we might as well leave it open\r
*/\r
public function sendMessage($to, $message) {\r
if ($message != '') {\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
+ $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
+ return false;\r
} else {\r
$socket = $this->switchBoardSessionLookup[$recipient];\r
$intsocket = (int) $socket;\r
$this->endSBSession($socket);\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
- return false;\r
- }\r
- \r
+ if ($this->switchBoardSessions[$intsocket]['joined'] !== true) {\r
+ $this->debug_message("*** Recipient has not joined session, returning false");\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
}\r
- \r
+\r
return false;\r
}\r
}\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
\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
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
$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
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