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
// 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
if(!empty($message)) {\r
$this->debug_message($message);\r
}\r
- $this->callHandler('ConnectFailed');\r
+ $this->callHandler('ConnectFailed', $message);\r
$this->NSRetryWait($this->retry_wait);\r
}\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
// 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
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
\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
+ $this->endSBSession($socket);\r
return false;\r
}\r
\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
$toParts = explode('@', $to);\r
if(count($toParts) < 3) {\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[$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
return true;\r
}\r
\r
+ $waitForSession = false;\r
return false;\r
}\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
* 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
$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