+ continue;\r
+ }\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
+<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
+ <DeleteMessages xmlns="http://www.hotmail.msn.com/ws/2004/09/oim/rsi">\r
+ <messageIds>\r
+ <messageId>'.$msgid.'</messageId>\r
+ </messageIds>\r
+ </DeleteMessages>\r
+</soap:Body>\r
+</soap:Envelope>';\r
+\r
+ $header_array = array(\r
+ 'SOAPAction: '.self::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 '.self::BUILDVER.')'\r
+ );\r
+\r
+ $this->debug_message('*** URL: '.self::OIM_DEL_URL);\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, self::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("*** Could not delete OIM: $msgid, http code = $http_code");\r
+ else\r
+ $this->debug_message("*** OIM ($msgid) deleted");\r
+ return $sMsg;\r
+ }\r
+\r
+ /**\r
+ * Send offline message\r
+ *\r
+ * @param string $to Intended recipient\r
+ * @param string $sMessage Message\r
+ * @param string $lockkey Lock key\r
+ * @return mixed true on success or error data\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="'.self::PROTOCOL.'"\r
+ buildVer="'.self::BUILDVER.'"/>\r
+ <To memberName="'.$to.'" xmlns="http://messenger.msn.com/ws/2004/09/oim/"/>\r
+ <Ticket passport="'.htmlspecialchars($this->ticket['oim_ticket']).'"\r
+ appid="'.self::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: '.self::OIM_SEND_SOAP,\r
+ 'Content-Type: text/xml',\r
+ 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Messenger '.self::BUILDVER.')'\r
+ );\r
+\r
+ $this->debug_message('*** URL: '.self::OIM_SEND_URL);\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, self::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
+ * Contact / Membership list methods\r
+ */\r
+\r
+ /**\r
+ * Fetch contact list\r
+ *\r
+ * @return boolean true on success\r
+ */\r
+ private function UpdateContacts() {\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
+\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
+ $this->debug_message('*** Updating 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
+ } catch(Exception $e) {\r
+ $this->debug_message("*** Update Contacts Error \nRequest:".$this->ABService->__getLastRequest()."\nError:".$e->getMessage());\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Add contact\r
+ *\r
+ * @param string $email\r
+ * @param integer $network\r
+ * @param string $display\r
+ * @param boolean $sendADL\r
+ * @return boolean true on success\r
+ */\r
+ private function addContact($email, $network, $display = '', $sendADL = false) {\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
+ );\r
+ $ABContactAdd = new SoapParam($this->Array2SoapVar($ABContactAddArray), 'ABContactAdd');\r
+ try {\r
+ $this->debug_message("*** Adding Contact $email...");\r
+ $this->ABService->ABContactAdd($ABContactAdd);\r
+ } catch(Exception $e) {\r
+ $this->debug_message("*** Add Contact 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
+ foreach (array('1', '2') as $l) {\r
+ $str = '<ml l="1"><d n="'.$u_domain.'"><c n="'.$u_name.'" l="'.$l.'" t="'.$network.'" /></d></ml>';\r
+ $len = strlen($str);\r
+ // NS: >>> ADL {id} {size}\r
+ $this->ns_writeln("ADL $this->id $len");\r
+ $this->ns_writedata($str);\r
+ }\r
+ }\r
+ $this->UpdateContacts();\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Remove contact from list\r
+ *\r
+ * @param integer $memberID\r
+ * @param string $email\r
+ * @param integer $network\r
+ * @param string $list\r
+ */\r
+ function delMemberFromList($memberID, $email, $network, $list) {\r
+ if ($network != 1 && $network != 32) return true;\r
+ if ($memberID === false) return true;\r
+ $user = $email;\r
+ $ticket = htmlspecialchars($this->ticket['contact_ticket']);\r
+ if ($network == 1)\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
+ xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">\r
+<soap:Header>\r
+ <ABApplicationHeader xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <ApplicationId>996CDE1E-AA53-4477-B943-2BE802EA6166</ApplicationId>\r
+ <IsMigration>false</IsMigration>\r
+ <PartnerScenario>ContactMsgrAPI</PartnerScenario>\r
+ </ABApplicationHeader>\r
+ <ABAuthHeader xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <ManagedGroupRequest>false</ManagedGroupRequest>\r
+ <TicketToken>'.$ticket.'</TicketToken>\r
+ </ABAuthHeader>\r
+</soap:Header>\r
+<soap:Body>\r
+ <DeleteMember xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <serviceHandle>\r
+ <Id>0</Id>\r
+ <Type>Messenger</Type>\r
+ <ForeignId></ForeignId>\r
+ </serviceHandle>\r
+ <memberships>\r
+ <Membership>\r
+ <MemberRole>'.$list.'</MemberRole>\r
+ <Members>\r
+ <Member xsi:type="PassportMember" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <Type>Passport</Type>\r
+ <MembershipId>'.$memberID.'</MembershipId>\r
+ <State>Accepted</State>\r
+ </Member>\r
+ </Members>\r
+ </Membership>\r
+ </memberships>\r
+ </DeleteMember>\r
+</soap:Body>\r
+</soap:Envelope>';\r
+ else\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
+ xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">\r
+<soap:Header>\r
+ <ABApplicationHeader xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <ApplicationId>996CDE1E-AA53-4477-B943-2BE802EA6166</ApplicationId>\r
+ <IsMigration>false</IsMigration>\r
+ <PartnerScenario>ContactMsgrAPI</PartnerScenario>\r
+ </ABApplicationHeader>\r
+ <ABAuthHeader xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <ManagedGroupRequest>false</ManagedGroupRequest>\r
+ <TicketToken>'.$ticket.'</TicketToken>\r
+ </ABAuthHeader>\r
+</soap:Header>\r
+<soap:Body>\r
+ <DeleteMember xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <serviceHandle>\r
+ <Id>0</Id>\r
+ <Type>Messenger</Type>\r
+ <ForeignId></ForeignId>\r
+ </serviceHandle>\r
+ <memberships>\r
+ <Membership>\r
+ <MemberRole>'.$list.'</MemberRole>\r
+ <Members>\r
+ <Member xsi:type="EmailMember" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <Type>Email</Type>\r
+ <MembershipId>'.$memberID.'</MembershipId>\r
+ <State>Accepted</State>\r
+ </Member>\r
+ </Members>\r
+ </Membership>\r
+ </memberships>\r
+ </DeleteMember>\r
+</soap:Body>\r
+</soap:Envelope>';\r
+\r
+ $header_array = array(\r
+ 'SOAPAction: '.self::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: '.self::DELMEMBER_URL);\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, self::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->debug_message("*** Could not delete member (network: $network) $email ($memberID) from $list 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->debug_message("*** Could not delete member (network: $network) $email ($memberID) from $list list, error code: $faultcode, $faultstring");\r
+ return false;\r
+ }\r
+ $this->debug_message("*** Could not delete member (network: $network) $email ($memberID) from $list list, not present in list");\r
+ return true;\r
+ }\r
+ $this->debug_message("*** Member successfully deleted (network: $network) $email ($memberID) from $list list");\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Add contact to list\r
+ *\r
+ * @param string $email\r
+ * @param integer $network\r
+ * @param string $list\r
+ */\r
+ function addMemberToList($email, $network, $list) {\r
+ if ($network != 1 && $network != 32) return true;\r
+ $ticket = htmlspecialchars($this->ticket['contact_ticket']);\r
+ $user = $email;\r
+\r
+ if ($network == 1)\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
+ xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">\r
+<soap:Header>\r
+ <ABApplicationHeader xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <ApplicationId>996CDE1E-AA53-4477-B943-2BE802EA6166</ApplicationId>\r
+ <IsMigration>false</IsMigration>\r
+ <PartnerScenario>ContactMsgrAPI</PartnerScenario>\r
+ </ABApplicationHeader>\r
+ <ABAuthHeader xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <ManagedGroupRequest>false</ManagedGroupRequest>\r
+ <TicketToken>'.$ticket.'</TicketToken>\r
+ </ABAuthHeader>\r
+</soap:Header>\r
+<soap:Body>\r
+ <AddMember xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <serviceHandle>\r
+ <Id>0</Id>\r
+ <Type>Messenger</Type>\r
+ <ForeignId></ForeignId>\r
+ </serviceHandle>\r
+ <memberships>\r
+ <Membership>\r
+ <MemberRole>'.$list.'</MemberRole>\r
+ <Members>\r
+ <Member xsi:type="PassportMember" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <Type>Passport</Type>\r
+ <State>Accepted</State>\r
+ <PassportName>'.$user.'</PassportName>\r
+ </Member>\r
+ </Members>\r
+ </Membership>\r
+ </memberships>\r
+ </AddMember>\r
+</soap:Body>\r
+</soap:Envelope>';\r
+ else\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
+ xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">\r
+<soap:Header>\r
+ <ABApplicationHeader xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <ApplicationId>996CDE1E-AA53-4477-B943-2BE802EA6166</ApplicationId>\r
+ <IsMigration>false</IsMigration>\r
+ <PartnerScenario>ContactMsgrAPI</PartnerScenario>\r
+ </ABApplicationHeader>\r
+ <ABAuthHeader xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <ManagedGroupRequest>false</ManagedGroupRequest>\r
+ <TicketToken>'.$ticket.'</TicketToken>\r
+ </ABAuthHeader>\r
+</soap:Header>\r
+<soap:Body>\r
+ <AddMember xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <serviceHandle>\r
+ <Id>0</Id>\r
+ <Type>Messenger</Type>\r
+ <ForeignId></ForeignId>\r
+ </serviceHandle>\r
+ <memberships>\r
+ <Membership>\r
+ <MemberRole>'.$list.'</MemberRole>\r
+ <Members>\r
+ <Member xsi:type="EmailMember" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <Type>Email</Type>\r
+ <State>Accepted</State>\r
+ <Email>'.$user.'</Email>\r
+ <Annotations>\r
+ <Annotation>\r
+ <Name>MSN.IM.BuddyType</Name>\r
+ <Value>32:YAHOO</Value>\r
+ </Annotation>\r
+ </Annotations>\r
+ </Member>\r
+ </Members>\r
+ </Membership>\r
+ </memberships>\r
+ </AddMember>\r
+</soap:Body>\r
+</soap:Envelope>';\r
+ $header_array = array(\r
+ 'SOAPAction: '.self::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: '.self::ADDMEMBER_URL);\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, self::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->debug_message("*** Could not add member (network: $network) $email to $list 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->debug_message("*** Could not add member (network: $network) $email to $list list, error code: $faultcode, $faultstring");\r
+ return false;\r
+ }\r
+ $this->debug_message("*** Could not add member (network: $network) $email to $list list, already present");\r
+ return true;\r
+ }\r
+ $this->debug_message("*** Member successfully added (network: $network) $email to $list list");\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Get membership lists\r
+ *\r
+ * @param mixed $returnData Membership list or false on failure\r
+ */\r
+ function getMembershipList($returnData = false) {\r
+ $ticket = htmlspecialchars($this->ticket['contact_ticket']);\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
+ xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">\r
+<soap:Header>\r
+ <ABApplicationHeader xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <ApplicationId>996CDE1E-AA53-4477-B943-2BE802EA6166</ApplicationId>\r
+ <IsMigration>false</IsMigration>\r
+ <PartnerScenario>Initial</PartnerScenario>\r
+ </ABApplicationHeader>\r
+ <ABAuthHeader xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <ManagedGroupRequest>false</ManagedGroupRequest>\r
+ <TicketToken>'.$ticket.'</TicketToken>\r
+ </ABAuthHeader>\r
+</soap:Header>\r
+<soap:Body>\r
+ <FindMembership xmlns="http://www.msn.com/webservices/AddressBook">\r
+ <serviceFilter>\r
+ <Types>\r
+ <ServiceType>Messenger</ServiceType>\r
+ <ServiceType>Invitation</ServiceType>\r
+ <ServiceType>SocialNetwork</ServiceType>\r
+ <ServiceType>Space</ServiceType>\r
+ <ServiceType>Profile</ServiceType>\r
+ </Types>\r
+ </serviceFilter>\r
+ </FindMembership>\r
+</soap:Body>\r
+</soap:Envelope>';\r
+ $header_array = array(\r
+ 'SOAPAction: '.self::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: '.self::MEMBERSHIP_URL);\r
+ $this->debug_message("*** Sending SOAP:\n$XML");\r
+ $curl = curl_init();\r
+ curl_setopt($curl, CURLOPT_URL, self::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
+\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, '<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
+ }\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
+ 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->debug_message("*** Adding new contact (network: $network, status: $sMemberRole): $u_name@$u_domain ($id)");\r
+ }\r
+ }\r
+ }\r
+ return $aContactList;\r
+ }\r