X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=plugins%2FMsn%2Fextlib%2Fphpmsnclass%2Fmsn.class.php;h=996c5571c20bd2c0a29458b7b1a00ef654f2e97b;hb=5bf0c9f610d2fe7852ffafbcd51436c9e057b0a7;hp=6cb917768f546aa47b03d8078c32555c6a91f3bc;hpb=6aa8ce08ae86ba7bbae958fcd10d2e6a5a0aea30;p=quix0rs-gnu-social.git
diff --git a/plugins/Msn/extlib/phpmsnclass/msn.class.php b/plugins/Msn/extlib/phpmsnclass/msn.class.php
index 6cb917768f..996c5571c2 100644
--- a/plugins/Msn/extlib/phpmsnclass/msn.class.php
+++ b/plugins/Msn/extlib/phpmsnclass/msn.class.php
@@ -12,7 +12,7 @@ Documentation on the MSN protocol can be found at: http://msnpiki.msnfanatic.com
This class uses MSNP15.
In addition to PHP5, the additional php modules required are:
-curl pcre mhash mcrypt bcmath
+curl pcre mcrypt bcmath
*/
@@ -23,10 +23,10 @@ class MSN {
const PROD_KEY = 'PK}_A_0N_K%O?A9S';
const PROD_ID = 'PROD0114ES4Z%Q5W';
const LOGIN_METHOD = 'SSO';
-
+
const OIM_SEND_URL = 'https://ows.messenger.msn.com/OimWS/oim.asmx';
const OIM_SEND_SOAP = 'http://messenger.live.com/ws/2006/09/oim/Store2';
-
+
const OIM_MAILDATA_URL = 'https://rsi.hotmail.com/rsi/rsi.asmx';
const OIM_MAILDATA_SOAP = 'http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMetadata';
const OIM_READ_URL = 'https://rsi.hotmail.com/rsi/rsi.asmx';
@@ -42,16 +42,16 @@ class MSN {
const DELMEMBER_URL = 'https://contacts.msn.com/abservice/SharingService.asmx';
const DELMEMBER_SOAP = 'http://www.msn.com/webservices/AddressBook/DeleteMember';
-
+
// the message length (include header) is limited (maybe since WLM 8.5 released)
// for WLM: 1664 bytes
// for YIM: 518 bytes
const MAX_MSN_MESSAGE_LEN = 1664;
const MAX_YAHOO_MESSAGE_LEN = 518;
-
+
private $debug;
private $timeout;
-
+
private $id;
private $ticket;
private $user = '';
@@ -76,7 +76,7 @@ class MSN {
private $port = 1863;
private $clientid = '';
-
+
private $error = '';
private $authed = false;
@@ -156,7 +156,6 @@ class MSN {
// Check support
if (!function_exists('curl_init')) throw new Exception("curl module not found!\n");
if (!function_exists('preg_match')) throw new Exception("pcre module not found!\n");
- if (!function_exists('mhash')) throw new Exception("mhash module not found!\n");
if (!function_exists('mcrypt_cbc')) throw new Exception("mcrypt module not found!\n");
if (!function_exists('bcmod')) throw new Exception("bcmath module not found!\n");
@@ -181,7 +180,7 @@ class MSN {
/**
* Signon methods
*/
-
+
/**
* Connect to the NS server
*
@@ -262,7 +261,7 @@ class MSN {
$this->user = $user;
$this->password = $password;
// NS: <<< USR {id} SSO S {policy} {nonce}
- @list(/* USR */, /* id */, /* SSO */, /* S */, $policy, $nonce,) = @explode(' ', $data);
+ @list(/* USR */, /* id */, /* SSO */, /* S */, $policy, $nonce) = @explode(' ', $data);
$this->passport_policy = $policy;
$aTickets = $this->get_passport_ticket();
@@ -271,7 +270,7 @@ class MSN {
// NS: >>> OUT
$this->ns_writeln("OUT");
@fclose($this->NSfp);
- $this->error = 'Passport authenticated fail!';
+ $this->error = 'Passport authentication failed!';
return false;
}
@@ -291,7 +290,7 @@ class MSN {
// NS: <<< XFR {id} NS {server} 0 {server}
// MSNP15
// NS: <<< XFR {id} NS {server} U D
- @list(/* XFR */, /* id */, $Type, $server, /* ... */) = @explode(' ', $data);
+ @list(/* XFR */, /* id */, $Type, $server) = @explode(' ', $data);
if ($Type!='NS') break;
@list($ip, $port) = @explode(':', $server);
// this connection will close after XFR
@@ -313,7 +312,7 @@ class MSN {
case 'GCF':
// return some policy data after 'USR {id} SSO I {user}' command
// NS: <<< GCF 0 {size}
- @list(/* GCF */, /* 0 */, $size,) = @explode(' ', $data);
+ @list(/* GCF */, /* 0 */, $size) = @explode(' ', $data);
// we don't need the data, just read it and drop
if (is_numeric($size) && $size > 0)
$this->ns_readdata($size);
@@ -345,7 +344,7 @@ class MSN {
/* FIXME Don't implement the signon as a loop or we could hang
* the queue handler! */
$this->debug_message('*** Trying to connect to MSN network');
-
+
// Remove any remaining switchboard sessions
$this->switchBoardSessions = array();
$this->switchBoardSessionLookup = array();
@@ -358,7 +357,10 @@ class MSN {
}
// Update contacts
- if ($this->UpdateContacts() === false) continue;
+ if ($this->UpdateContacts() === false) {
+ $this->signonFailure('');
+ continue;
+ }
// Get membership lists
if (($this->aContactList = $this->getMembershipList()) === false) {
@@ -480,8 +482,10 @@ class MSN {
* @return void
*/
private function signonFailure($message) {
- $this->debug_message($message);
- $this->callHandler('ConnectFailed');
+ if(!empty($message)) {
+ $this->debug_message($message);
+ }
+ $this->callHandler('ConnectFailed', $message);
$this->NSRetryWait($this->retry_wait);
}
@@ -504,7 +508,7 @@ class MSN {
/**
* NS and SB command handling methods
*/
-
+
/**
* Read and handle incoming command from NS
*
@@ -527,7 +531,7 @@ class MSN {
$this->signon();
return;
}
-
+
switch (substr($data, 0, 3)) {
case 'SBS':
// after 'USR {id} OK {user} {verify} 0' response, the server will send SBS and profile to us
@@ -550,7 +554,7 @@ class MSN {
case 'LST':
// NS: <<< LST {email} {alias} 11 0
- @list(/* LST */, $email, /* alias */,) = @explode(' ', $data);
+ @list(/* LST */, $email) = @explode(' ', $data);
@list($u_name, $u_domain) = @explode('@', $email);
if (!isset($this->aContactList[$u_domain][$u_name][1])) {
$this->aContactList[$u_domain][$u_name][1]['Allow'] = 'Allow';
@@ -561,7 +565,7 @@ class MSN {
case 'ADL':
// randomly, we get ADL command, someone add us to their contact list for MSNP15
// NS: <<< ADL 0 {size}
- @list(/* ADL */, /* 0 */, $size,) = @explode(' ', $data);
+ @list(/* ADL */, /* 0 */, $size) = @explode(' ', $data);
if (is_numeric($size) && $size > 0) {
$data = $this->ns_readdata($size);
preg_match('##', $data, $matches);
@@ -613,7 +617,7 @@ class MSN {
case 'RML':
// randomly, we get RML command, someome remove us to their contact list for MSNP15
// NS: <<< RML 0 {size}
- @list(/* RML */, /* 0 */, $size,) = @explode(' ', $data);
+ @list(/* RML */, /* 0 */, $size) = @explode(' ', $data);
if (is_numeric($size) && $size > 0) {
$data = $this->ns_readdata($size);
preg_match('##', $data, $matches);
@@ -643,7 +647,7 @@ class MSN {
case 'MSG':
// randomly, we get MSG notification from server
// NS: <<< MSG Hotmail Hotmail {size}
- @list(/* MSG */, /* Hotmail */, /* Hotmail */, $size,) = @explode(' ', $data);
+ @list(/* MSG */, /* Hotmail */, /* Hotmail */, $size) = @explode(' ', $data);
if (is_numeric($size) && $size > 0) {
$data = $this->ns_readdata($size);
$aLines = @explode("\n", $data);
@@ -788,7 +792,7 @@ class MSN {
case 'UBM':
// randomly, we get UBM, this is the message from other network, like Yahoo!
// NS: <<< UBM {email} $network $type {size}
- @list(/* UBM */, $from_email, $network, $type, $size,) = @explode(' ', $data);
+ @list(/* UBM */, $from_email, $network, $type, $size) = @explode(' ', $data);
if (is_numeric($size) && $size > 0) {
$data = $this->ns_readdata($size);
$aLines = @explode("\n", $data);
@@ -827,7 +831,7 @@ class MSN {
case 'UBX':
// randomly, we get UBX notification from server
// NS: <<< UBX email {network} {size}
- @list(/* UBX */, /* email */, /* network */, $size,) = @explode(' ', $data);
+ @list(/* UBX */, /* email */, /* network */, $size) = @explode(' ', $data);
// we don't need the notification data, so just ignore it
if (is_numeric($size) && $size > 0)
$this->ns_readdata($size);
@@ -836,7 +840,7 @@ class MSN {
case 'CHL':
// randomly, we'll get challenge from server
// NS: <<< CHL 0 {code}
- @list(/* CHL */, /* 0 */, $chl_code,) = @explode(' ', $data);
+ @list(/* CHL */, /* 0 */, $chl_code) = @explode(' ', $data);
$fingerprint = $this->getChallenge($chl_code);
// NS: >>> QRY {id} {product_id} 32
// NS: >>> fingerprint
@@ -860,7 +864,7 @@ class MSN {
// NS: <<< XFR {id} NS {server} U D
// for normal switchboard XFR
// NS: <<< XFR {id} SB {server} CKI {cki} U messenger.msn.com 0
- @list(/* XFR */, /* {id} */, $server_type, $server, /* CKI */, $cki_code, /* ... */) = @explode(' ', $data);
+ @list(/* XFR */, /* {id} */, $server_type, $server, /* CKI */, $cki_code) = @explode(' ', $data);
@list($ip, $port) = @explode(':', $server);
if ($server_type != 'SB') {
// maybe exit?
@@ -887,20 +891,19 @@ class MSN {
// someone is trying to talk to us
// NS: <<< RNG {session_id} {server} {auth_type} {ticket} {email} {alias} U {client} 0
$this->debug_message("NS: <<< RNG $data");
- @list(/* RNG */, $sid, $server, /* auth_type */, $ticket, $email, $name,) = @explode(' ', $data);
+ @list(/* RNG */, $sid, $server, /* auth_type */, $ticket, $email, $name) = @explode(' ', $data);
@list($sb_ip, $sb_port) = @explode(':', $server);
$this->debug_message("*** RING from $email, $sb_ip:$sb_port");
$this->addContact($email, 1, $email, true);
$this->connectToSBSession('Passive', $sb_ip, $sb_port, $email, array('sid' => $sid, 'ticket' => $ticket));
break;
-
+
case 'NLN':
// NS: <<< NLN {status} {email} {networkid} {nickname} {clientid} {dpobj}
- // NS: <<< NLN NLN darkip@inflatablegoldfish.com 1 Luke 2685403136 0
- @list(/* NLN */, $status, $email, $network, $nickname, /* clientid */, /* dbobj */,) = @explode(' ', $data);
+ @list(/* NLN */, $status, $email, $network, $nickname) = @explode(' ', $data);
$this->callHandler('StatusChange', array('screenname' => $email, 'status' => $status, 'network' => $network, 'nickname' => $nickname));
break;
-
+
case 'OUT':
// force logout from NS
// NS: <<< OUT xxx
@@ -945,7 +948,10 @@ class MSN {
// SB: <<< IRO {id} {rooster} {roostercount} {email} {alias} {clientid}
@list(/* IRO */, /* id */, $cur_num, $total, $email, $alias, $clientid) = @explode(' ', $data);
$this->debug_message("*** $email joined session");
- $session['joined'] = true;
+ if ($email == $session['to']) {
+ $session['joined'] = true;
+ $this->callHandler('SessionReady', array('to' => $email));
+ }
break;
case 'BYE':
$this->debug_message("*** Quit for BYE");
@@ -966,13 +972,15 @@ class MSN {
case 'JOI':
// SB: <<< JOI {user} {alias} {clientid?}
// someone join us
- // we don't need the data, just ignore it
- // no more user here
- $session['joined'] = true;
+ @list(/* JOI */, $email) = @explode(' ', $data);
+ if ($email == $session['to']) {
+ $session['joined'] = true;
+ $this->callHandler('SessionReady', array('to' => $email));
+ }
break;
case 'MSG':
// SB: <<< MSG {email} {alias} {len}
- @list(/* MSG */, $from_email, /* alias */, $len, ) = @explode(' ', $data);
+ @list(/* MSG */, $from_email, /* alias */, $len) = @explode(' ', $data);
$len = trim($len);
$data = $this->sb_readdata($socket, $len);
$aLines = @explode("\n", $data);
@@ -1352,7 +1360,7 @@ class MSN {
/**
* Switchboard related methods
*/
-
+
/**
* Send a request for a switchboard session
*
@@ -1405,12 +1413,12 @@ class MSN {
'offline' => false,
'XFRReqTime' => time()
);
-
+
// Change the index of the session to the socket
$intsocket = (int) $socket;
$this->switchBoardSessions[$intsocket] = $this->switchBoardSessions[$to];
unset($this->switchBoardSessions[$to]);
-
+
$id = &$this->switchBoardSessions[$intsocket]['id'];
if ($mode == 'Active') {
@@ -1427,7 +1435,7 @@ class MSN {
$this->sb_writeln($socket, $id, "ANS $id $this->user $ticket $sid");
}
}
-
+
/**
* Called when we want to end a switchboard session
* or a switchboard session ends
@@ -1474,6 +1482,7 @@ class MSN {
if ($this->sb_writeln($socket, $id, "MSG $id N $len") === false ||
$this->sb_writedata($socket, $SendString) === false) {
+ $this->endSBSession($socket);
return false;
}
}
@@ -1481,7 +1490,8 @@ class MSN {
if ($this->sb_writeln($socket, $id, "MSG $id N $len") === false ||
$this->sb_writedata($socket, $aMessage) === false) {
- return false;
+ $this->endSBSession($socket);
+ return false;
}
// Don't close the SB session, we might as well leave it open
@@ -1514,40 +1524,57 @@ class MSN {
* where network is 1 for MSN, 32 for Yahoo
* and 'Offline' for offline messages
* @param string $message Message
+ * @param boolean &$waitForSession Boolean passed by reference,
+ * if set to true on return, message
+ * did not fail to send but is
+ * waiting for a valid session
+ *
+ * @return boolean true on success
*/
- public function sendMessage($to, $message) {
+ public function sendMessage($to, $message, &$waitForSession) {
if ($message != '') {
- @list($name, $host, $network) = @explode('@', $to);
- $network = $network == '' ? 1 : $network;
+ $toParts = explode('@', $to);
+ if(count($toParts) < 3) {
+ list($name, $host) = $toParts;
+ $network = 1;
+ } else {
+ list($name, $host, $network) = $toParts;
+ }
+
$recipient = $name.'@'.$host;
if ($network === 1) {
if (!isset($this->switchBoardSessionLookup[$recipient])) {
- if (!isset($this->switchBoardSessions[$recipient]) || time() - $this->switchBoardSessions[$recipient]['XFRReqTime'] > $this->XFRReqTimeout) {
- $this->debug_message("*** No existing SB session or request has timed out");
- $this->reqSBSession($recipient);
- }
- return false;
+ if (!isset($this->switchBoardSessions[$recipient]) || time() - $this->switchBoardSessions[$recipient]['XFRReqTime'] > $this->XFRReqTimeout) {
+ $this->debug_message("*** No existing SB session or request has timed out");
+ $this->reqSBSession($recipient);
+ }
+
+ $waitForSession = true;
+ return false;
} else {
$socket = $this->switchBoardSessionLookup[$recipient];
$intsocket = (int) $socket;
if ($this->switchBoardSessions[$intsocket]['offline']) {
$this->debug_message("*** Contact ($recipient) offline, sending OIM");
$this->endSBSession($socket);
+ $waitForSession = false;
return $this->sendMessage($recipient.'@Offline', $message);
} else {
- if ($this->switchBoardSessions[$intsocket]['joined'] !== true) {
- $this->debug_message("*** Recipient has not joined session, returning false");
- return false;
- }
-
+ if ($this->switchBoardSessions[$intsocket]['joined'] !== true) {
+ $this->debug_message("*** Recipient has not joined session, returning false");
+ $waitForSession = true;
+ return false;
+ }
+
$this->debug_message("*** Attempting to send message to $recipient using existing SB session");
if ($this->sendMessageViaSB($recipient, $message)) {
$this->debug_message('*** Message sent successfully');
return true;
}
-
+
+ $waitForSession = false;
return false;
}
}
@@ -1592,7 +1619,7 @@ class MSN {
/**
* OIM methods
*/
-
+
/**
* Get OIM mail data
*
@@ -1795,7 +1822,7 @@ class MSN {
$this->debug_message("*** OIM ($msgid) deleted");
return $sMsg;
}
-
+
/**
* Send offline message
*
@@ -1907,11 +1934,11 @@ X-OIM-Sequence-Num: 1
}
return array('challenge' => $challenge, 'auth_policy' => $auth_policy);
}
-
+
/**
* Contact / Membership list methods
*/
-
+
/**
* Fetch contact list
*
@@ -2336,7 +2363,7 @@ X-OIM-Sequence-Num: 1
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$this->debug_message("*** Get Result:\n$data");
-
+
if ($http_code != 200) return false;
$p = $data;
$aMemberships = array();
@@ -2416,11 +2443,11 @@ X-OIM-Sequence-Num: 1
}
return $aContactList;
}
-
+
/**
* MsnObj related methods
*/
-
+
/**
*
* @param $FilePath åæªè·¯å¾
@@ -2460,14 +2487,14 @@ X-OIM-Sequence-Num: 1
}
return $DefineString;
}
-
+
/**
* Socket methods
*/
-
+
/**
* Read data of specified size from NS socket
- *
+ *
* @param integer $size Size to read
* @return string Data read
*/
@@ -2486,7 +2513,7 @@ X-OIM-Sequence-Num: 1
/**
* Read line from the NS socket
- *
+ *
* @return string Data read
*/
private function ns_readln() {
@@ -2500,9 +2527,9 @@ X-OIM-Sequence-Num: 1
/**
* Write line to NS socket
- *
+ *
* Also increments id
- *
+ *
* @param string $data Line to write to socket
* @return mixed Bytes written or false on failure
*/
@@ -2517,7 +2544,7 @@ X-OIM-Sequence-Num: 1
/**
* Write data to NS socket
- *
+ *
* @param string $data Data to write to socket
* @return mixed Bytes written or false on failure
*/
@@ -2531,7 +2558,7 @@ X-OIM-Sequence-Num: 1
/**
* Read data of specified size from given SB socket
- *
+ *
* @param resource $socket SB socket
* @param integer $size Size to read
* @return string Data read
@@ -2551,7 +2578,7 @@ X-OIM-Sequence-Num: 1
/**
* Read line from given SB socket
- *
+ *
* @param resource $socket SB Socket
* @return string Line read
*/
@@ -2566,9 +2593,9 @@ X-OIM-Sequence-Num: 1
/**
* Write line to given SB socket
- *
+ *
* Also increments id
- *
+ *
* @param resource $socket SB socket
* @param integer $id Reference to SB id
* @param string $data Line to write
@@ -2585,7 +2612,7 @@ X-OIM-Sequence-Num: 1
/**
* Write data to given SB socket
- *
+ *
* @param resource $socket SB socket
* @param $data Data to write to socket
* @return mixed Bytes written or false on error
@@ -2617,16 +2644,16 @@ X-OIM-Sequence-Num: 1
$info = stream_get_meta_data($socket);
return $info['eof'];
}
-
+
/**
* Key generation methods
*/
-
+
private function derive_key($key, $magic) {
- $hash1 = mhash(MHASH_SHA1, $magic, $key);
- $hash2 = mhash(MHASH_SHA1, $hash1.$magic, $key);
- $hash3 = mhash(MHASH_SHA1, $hash1, $key);
- $hash4 = mhash(MHASH_SHA1, $hash3.$magic, $key);
+ $hash1 = $this->mhash_sha1($magic, $key);
+ $hash2 = $this->mhash_sha1($hash1.$magic, $key);
+ $hash3 = $this->mhash_sha1($hash1, $key);
+ $hash4 = $this->mhash_sha1($hash3.$magic, $key);
return $hash2.substr($hash4, 0, 4);
}
@@ -2636,7 +2663,7 @@ X-OIM-Sequence-Num: 1
$key3 = $this->derive_key($key1, 'WS-SecureConversationSESSION KEY ENCRYPTION');
// get hash of challenge using key2
- $hash = mhash(MHASH_SHA1, $challenge, $key2);
+ $hash = $this->mhash_sha1($challenge, $key2);
// get 8 bytes random data
$iv = substr(base64_encode(rand(1000,9999).rand(1000,9999)), 2, 8);
@@ -2650,7 +2677,7 @@ X-OIM-Sequence-Num: 1
return base64_encode($blob);
}
-
+
/**
* Generate challenge response
*
@@ -2730,11 +2757,11 @@ X-OIM-Sequence-Num: 1
return $hash;
}
-
+
/**
* Utility methods
*/
-
+
private function Array2SoapVar($Array, $ReturnSoapVarObj = true, $TypeName = null, $TypeNameSpace = null) {
$ArrayString = '';
foreach($Array as $Key => $Val) {
@@ -2762,7 +2789,7 @@ X-OIM-Sequence-Num: 1
if ($ReturnSoapVarObj) return new SoapVar($ArrayString, XSD_ANYXML, $TypeName, $TypeNameSpace);
return $ArrayString;
}
-
+
private function linetoArray($lines) {
$lines = str_replace("\r", '', $lines);
$lines = explode("\n", $lines);
@@ -2773,7 +2800,7 @@ X-OIM-Sequence-Num: 1
}
return $Data;
}
-
+
/**
* Get Passport ticket
*
@@ -3020,7 +3047,7 @@ X-OIM-Sequence-Num: 1
$this->ABAuthHeader = new SoapHeader('http://www.msn.com/webservices/AddressBook', 'ABAuthHeader', $this->Array2SoapVar($ABAuthHeaderArray));
return $aTickets;
}
-
+
/**
* Generate the data to send a message
*
@@ -3039,7 +3066,7 @@ X-OIM-Sequence-Num: 1
$msg = substr($sMessage, 0, $maxlen);
return $msg_header.$msg;
}
-
+
/**
* Sleep for the given number of seconds
*
@@ -3049,7 +3076,7 @@ X-OIM-Sequence-Num: 1
$this->debug_message("*** Sleeping for $wait seconds before retrying");
sleep($wait);
}
-
+
/**
* Sends a ping command
*
@@ -3061,7 +3088,7 @@ X-OIM-Sequence-Num: 1
// NS: >>> PNG
$this->ns_writeln("PNG");
}
-
+
/**
* Methods to add / call callbacks
*/
@@ -3090,7 +3117,7 @@ X-OIM-Sequence-Num: 1
* Registers a user handler
*
* Handler List
- * IMIn, Pong, ConnectFailed, Reconnect,
+ * IMIn, SessionReady, Pong, ConnectFailed, Reconnect,
* AddedToList, RemovedFromList, StatusChange
*
* @param string $event Event name
@@ -3106,24 +3133,24 @@ X-OIM-Sequence-Num: 1
return false;
}
}
-
+
/**
* Debugging methods
*/
-
+
/**
* Print message if debugging is enabled
- *
+ *
* @param string $str Message to print
*/
private function debug_message($str) {
if (!$this->debug) return;
echo $str."\n";
}
-
+
/**
* Dump binary data
- *
+ *
* @param string $str Data string
* @return Binary data
*/
@@ -3152,4 +3179,32 @@ X-OIM-Sequence-Num: 1
$buf .= "$h_str $a_str\n";
return $buf;
}
+
+ function mhash_sha1($data, $key)
+ {
+ if (extension_loaded("mhash"))
+ return mhash(MHASH_SHA1, $data, $key);
+
+ if (function_exists("hash_hmac"))
+ return hash_hmac('sha1', $data, $key, true);
+
+ // RFC 2104 HMAC implementation for php. Hacked by Lance Rushing
+ $b = 64;
+ if (strlen($key) > $b)
+ $key = pack("H*", sha1($key));
+ $key = str_pad($key, $b, chr(0x00));
+ $ipad = str_pad("", $b, chr(0x36));
+ $opad = str_pad("", $b, chr(0x5c));
+ $k_ipad = $key ^ $ipad ;
+ $k_opad = $key ^ $opad;
+
+ $sha1_value = sha1($k_opad . pack("H*", sha1($k_ipad . $data)));
+
+ $hash_data = '';
+ $str = join('',explode('\x', $sha1_value));
+ $len = strlen($str);
+ for ($i = 0; $i < $len; $i += 2)
+ $hash_data .= chr(hexdec(substr($str, $i, 2)));
+ return $hash_data;
+ }
}