From b0a439bfd5fe43d23bac6f8c98080cf1cd33e2cc Mon Sep 17 00:00:00 2001 From: Stancu Florin Date: Sat, 29 Sep 2012 17:20:19 +0300 Subject: [PATCH] Added wordpress social-connect plugin for google / yahoo / facebook account integration. --- db/hartapoliticii_mock_data.sql | 2 +- .../plugins/social-connect/admin.php | 118 ++ .../plugins/social-connect/constants.php | 8 + .../social-connect/diagnostics/test.php | 26 + .../social-connect/facebook/callback.php | 41 + .../social-connect/facebook/facebook.php | 959 ++++++++++ .../plugins/social-connect/google/connect.php | 45 + .../languages/social_connect-pl_PL.mo | Bin 0 -> 8439 bytes .../languages/social_connect-pl_PL.po | 212 +++ .../social-connect/liveid/callback.php | 110 ++ .../plugins/social-connect/liveid/connect.php | 182 ++ .../liveid/windowslivelogin.php | 1606 +++++++++++++++++ .../plugins/social-connect/media.php | 47 + .../social-connect/media/css/style.css | 52 + .../social-connect/media/img/facebook_16.png | Bin 0 -> 502 bytes .../social-connect/media/img/facebook_32.png | Bin 0 -> 888 bytes .../media/img/facebook_small.png | Bin 0 -> 644 bytes .../social-connect/media/img/google_16.png | Bin 0 -> 751 bytes .../social-connect/media/img/google_32.png | Bin 0 -> 1523 bytes .../social-connect/media/img/google_small.png | Bin 0 -> 797 bytes .../social-connect/media/img/liveid_16.png | Bin 0 -> 792 bytes .../social-connect/media/img/liveid_32.png | Bin 0 -> 1668 bytes .../social-connect/media/img/openid_16.png | Bin 0 -> 671 bytes .../social-connect/media/img/openid_32.png | Bin 0 -> 1204 bytes .../social-connect/media/img/readme.txt | 1 + .../social-connect/media/img/twitter_16.png | Bin 0 -> 608 bytes .../social-connect/media/img/twitter_32.png | Bin 0 -> 1089 bytes .../media/img/twitter_small.png | Bin 0 -> 708 bytes .../social-connect/media/img/windows_16.png | Bin 0 -> 792 bytes .../social-connect/media/img/windows_32.png | Bin 0 -> 1668 bytes .../social-connect/media/img/wordpress_16.png | Bin 0 -> 783 bytes .../social-connect/media/img/wordpress_32.png | Bin 0 -> 1740 bytes .../media/img/wordpress_small.png | Bin 0 -> 858 bytes .../social-connect/media/img/yahoo_16.png | Bin 0 -> 763 bytes .../social-connect/media/img/yahoo_32.png | Bin 0 -> 1301 bytes .../social-connect/media/js/connect.js | 143 ++ .../plugins/social-connect/openid/connect.php | 45 + .../plugins/social-connect/openid/openid.php | 706 ++++++++ .../plugins/social-connect/readme.txt | 161 ++ .../plugins/social-connect/screenshot-1.png | Bin 0 -> 26656 bytes .../plugins/social-connect/screenshot-2.png | Bin 0 -> 32249 bytes .../plugins/social-connect/social-connect.php | 203 +++ .../social-connect/twitter/EpiCurl.php | 128 ++ .../social-connect/twitter/EpiOAuth.php | 258 +++ .../social-connect/twitter/EpiTwitter.php | 118 ++ .../social-connect/twitter/callback.php | 39 + .../social-connect/twitter/connect.php | 18 + www/wp-content/plugins/social-connect/ui.php | 192 ++ .../plugins/social-connect/utils.php | 35 + .../social-connect/wordpress/connect.php | 61 + .../plugins/social-connect/yahoo/connect.php | 45 + www/wp-login.php | 29 +- 52 files changed, 5577 insertions(+), 13 deletions(-) create mode 100755 www/wp-content/plugins/social-connect/admin.php create mode 100755 www/wp-content/plugins/social-connect/constants.php create mode 100755 www/wp-content/plugins/social-connect/diagnostics/test.php create mode 100755 www/wp-content/plugins/social-connect/facebook/callback.php create mode 100755 www/wp-content/plugins/social-connect/facebook/facebook.php create mode 100755 www/wp-content/plugins/social-connect/google/connect.php create mode 100755 www/wp-content/plugins/social-connect/languages/social_connect-pl_PL.mo create mode 100755 www/wp-content/plugins/social-connect/languages/social_connect-pl_PL.po create mode 100755 www/wp-content/plugins/social-connect/liveid/callback.php create mode 100755 www/wp-content/plugins/social-connect/liveid/connect.php create mode 100755 www/wp-content/plugins/social-connect/liveid/windowslivelogin.php create mode 100755 www/wp-content/plugins/social-connect/media.php create mode 100755 www/wp-content/plugins/social-connect/media/css/style.css create mode 100755 www/wp-content/plugins/social-connect/media/img/facebook_16.png create mode 100755 www/wp-content/plugins/social-connect/media/img/facebook_32.png create mode 100755 www/wp-content/plugins/social-connect/media/img/facebook_small.png create mode 100755 www/wp-content/plugins/social-connect/media/img/google_16.png create mode 100755 www/wp-content/plugins/social-connect/media/img/google_32.png create mode 100755 www/wp-content/plugins/social-connect/media/img/google_small.png create mode 100755 www/wp-content/plugins/social-connect/media/img/liveid_16.png create mode 100755 www/wp-content/plugins/social-connect/media/img/liveid_32.png create mode 100755 www/wp-content/plugins/social-connect/media/img/openid_16.png create mode 100755 www/wp-content/plugins/social-connect/media/img/openid_32.png create mode 100755 www/wp-content/plugins/social-connect/media/img/readme.txt create mode 100755 www/wp-content/plugins/social-connect/media/img/twitter_16.png create mode 100755 www/wp-content/plugins/social-connect/media/img/twitter_32.png create mode 100755 www/wp-content/plugins/social-connect/media/img/twitter_small.png create mode 100755 www/wp-content/plugins/social-connect/media/img/windows_16.png create mode 100755 www/wp-content/plugins/social-connect/media/img/windows_32.png create mode 100755 www/wp-content/plugins/social-connect/media/img/wordpress_16.png create mode 100755 www/wp-content/plugins/social-connect/media/img/wordpress_32.png create mode 100755 www/wp-content/plugins/social-connect/media/img/wordpress_small.png create mode 100755 www/wp-content/plugins/social-connect/media/img/yahoo_16.png create mode 100755 www/wp-content/plugins/social-connect/media/img/yahoo_32.png create mode 100755 www/wp-content/plugins/social-connect/media/js/connect.js create mode 100755 www/wp-content/plugins/social-connect/openid/connect.php create mode 100755 www/wp-content/plugins/social-connect/openid/openid.php create mode 100755 www/wp-content/plugins/social-connect/readme.txt create mode 100755 www/wp-content/plugins/social-connect/screenshot-1.png create mode 100755 www/wp-content/plugins/social-connect/screenshot-2.png create mode 100755 www/wp-content/plugins/social-connect/social-connect.php create mode 100755 www/wp-content/plugins/social-connect/twitter/EpiCurl.php create mode 100755 www/wp-content/plugins/social-connect/twitter/EpiOAuth.php create mode 100755 www/wp-content/plugins/social-connect/twitter/EpiTwitter.php create mode 100755 www/wp-content/plugins/social-connect/twitter/callback.php create mode 100755 www/wp-content/plugins/social-connect/twitter/connect.php create mode 100755 www/wp-content/plugins/social-connect/ui.php create mode 100755 www/wp-content/plugins/social-connect/utils.php create mode 100755 www/wp-content/plugins/social-connect/wordpress/connect.php create mode 100755 www/wp-content/plugins/social-connect/yahoo/connect.php diff --git a/db/hartapoliticii_mock_data.sql b/db/hartapoliticii_mock_data.sql index fcd1d1c..e3f35e0 100644 --- a/db/hartapoliticii_mock_data.sql +++ b/db/hartapoliticii_mock_data.sql @@ -2113,7 +2113,7 @@ INSERT INTO `wp_options` (`option_id`, `blog_id`, `option_name`, `option_value`, (35, 0, 'hack_file', '', 'yes'), (36, 0, 'blog_charset', 'UTF-8', 'yes'), (37, 0, 'moderation_keys', '', 'no'), -(38, 0, 'active_plugins', 'a:3:{i:0;s:19:"akismet/akismet.php";i:1;s:63:"feedburner_feedsmith_plugin_2.3/FeedBurner_FeedSmith_Plugin.php";i:2;s:47:"subscribe-to-comments/subscribe-to-comments.php";}', 'yes'), +(38, 0, 'active_plugins', 'a:4:{i:0;s:19:"akismet/akismet.php";i:1;s:63:"feedburner_feedsmith_plugin_2.3/FeedBurner_FeedSmith_Plugin.php";i:2;s:33:"social-connect/social-connect.php";i:3;s:47:"subscribe-to-comments/subscribe-to-comments.php";}', 'yes'), (39, 0, 'home', 'http://zen.dev', 'yes'), (40, 0, 'category_base', '', 'yes'), (41, 0, 'ping_sites', 'http://rpc.pingomatic.com/', 'yes'), diff --git a/www/wp-content/plugins/social-connect/admin.php b/www/wp-content/plugins/social-connect/admin.php new file mode 100755 index 0000000..40413af --- /dev/null +++ b/www/wp-content/plugins/social-connect/admin.php @@ -0,0 +1,118 @@ + +
+

+ +
+ +

+

+

%1$s Application List', 'social_connect'), 'Facebook', 'http://www.facebook.com/developers/apps.php'); ?> +

+
    +
  1. Facebook Application Setup page', 'social_connect'), 'http://www.facebook.com/developers/createapp.php'); ?>
  2. +
  3. Facebook Application List', 'social_connect'), 'http://www.facebook.com/developers/apps.php'); ?>
  4. +
  5. +
+ + + + + + + + + + + + + + +
+ />
+ +
+ +

+

Consumer Key, a Consumer Secret, an Access Token and an Access Token Secret.', 'social_connect'); ?>

+

%1$s Application List', 'social_connect'), 'Twitter', 'https://dev.twitter.com/apps'); ?>

+

Register an Application and fill the form with the details below:', 'social_connect'), 'http://dev.twitter.com/apps/new'); ?> +

    +
  1. Browser', 'social_connect'); ?>
  2. +
  3. %1$s', 'social_connect'), SOCIAL_CONNECT_PLUGIN_URL . '/twitter/callback.php'); ?>
  4. +
  5. Read & Write', 'social_connect'); ?>
  6. +
+ + + + + + + + + + + + + +
+ />
+ Please check with your domain administrator as this may require changes to your mail server.', 'social_connect'); ?> +
+ +

+

+ + + + + + + + + + + + + +
Google + /> +
Yahoo + /> +
WordPress.com + /> +
+ +

+ +

+ +

+

+

+

If you web server fails this test, please have your hosting provider whitelist your domain on mod_security. Learn more on the Social Connect FAQ. +

+
\ No newline at end of file diff --git a/www/wp-content/plugins/social-connect/diagnostics/test.php b/www/wp-content/plugins/social-connect/diagnostics/test.php new file mode 100755 index 0000000..356bafa --- /dev/null +++ b/www/wp-content/plugins/social-connect/diagnostics/test.php @@ -0,0 +1,26 @@ +
The rewrite rules on your server appear to be setup correctly for Social Connect to work.', 'social_connect' ); +} else { + $msg = sprintf( __( 'Test was unsuccessful. Expected "http://www.example.com", received "%s".', 'social_connect' ), $testing ); +} +?> + + + + + + +
+

+

+
+ + + + diff --git a/www/wp-content/plugins/social-connect/facebook/callback.php b/www/wp-content/plugins/social-connect/facebook/callback.php new file mode 100755 index 0000000..932ee68 --- /dev/null +++ b/www/wp-content/plugins/social-connect/facebook/callback.php @@ -0,0 +1,41 @@ + + + + + + + + + diff --git a/www/wp-content/plugins/social-connect/facebook/facebook.php b/www/wp-content/plugins/social-connect/facebook/facebook.php new file mode 100755 index 0000000..ca9cd65 --- /dev/null +++ b/www/wp-content/plugins/social-connect/facebook/facebook.php @@ -0,0 +1,959 @@ + + */ +if (!class_exists('FacebookApiException')) : +class FacebookApiException extends Exception +{ + /** + * The result from the API server that represents the exception information. + */ + protected $result; + + /** + * Make a new API Exception with the given result. + * + * @param Array $result the result from the API server + */ + public function __construct($result) { + $this->result = $result; + + $code = isset($result['error_code']) ? $result['error_code'] : 0; + + if (isset($result['error_description'])) { + // OAuth 2.0 Draft 10 style + $msg = $result['error_description']; + } else if (isset($result['error']) && is_array($result['error'])) { + // OAuth 2.0 Draft 00 style + $msg = $result['error']['message']; + } else if (isset($result['error_msg'])) { + // Rest server style + $msg = $result['error_msg']; + } else { + $msg = 'Unknown Error. Check getResult()'; + } + + parent::__construct($msg, $code); + } + + /** + * Return the associated result object returned by the API server. + * + * @returns Array the result from the API server + */ + public function getResult() { + return $this->result; + } + + /** + * Returns the associated type for the error. This will default to + * 'Exception' when a type is not available. + * + * @return String + */ + public function getType() { + if (isset($this->result['error'])) { + $error = $this->result['error']; + if (is_string($error)) { + // OAuth 2.0 Draft 10 style + return $error; + } else if (is_array($error)) { + // OAuth 2.0 Draft 00 style + if (isset($error['type'])) { + return $error['type']; + } + } + } + return 'Exception'; + } + + /** + * To make debugging easier. + * + * @returns String the string representation of the error + */ + public function __toString() { + $str = $this->getType() . ': '; + if ($this->code != 0) { + $str .= $this->code . ': '; + } + return $str . $this->message; + } +} +endif; + +if (!class_exists('Facebook')) : +/** + * Provides access to the Facebook Platform. + * + * @author Naitik Shah + */ +class Facebook +{ + /** + * Version. + */ + const VERSION = '2.1.2'; + + /** + * Default options for curl. + */ + public static $CURL_OPTS = array( + CURLOPT_CONNECTTIMEOUT => 10, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 60, + CURLOPT_USERAGENT => 'facebook-php-2.0', + ); + + /** + * List of query parameters that get automatically dropped when rebuilding + * the current URL. + */ + protected static $DROP_QUERY_PARAMS = array( + 'session', + 'signed_request', + ); + + /** + * Maps aliases to Facebook domains. + */ + public static $DOMAIN_MAP = array( + 'api' => 'https://api.facebook.com/', + 'api_read' => 'https://api-read.facebook.com/', + 'graph' => 'https://graph.facebook.com/', + 'www' => 'https://www.facebook.com/', + ); + + /** + * The Application ID. + */ + protected $appId; + + /** + * The Application API Secret. + */ + protected $apiSecret; + + /** + * The active user session, if one is available. + */ + protected $session; + + /** + * The data from the signed_request token. + */ + protected $signedRequest; + + /** + * Indicates that we already loaded the session as best as we could. + */ + protected $sessionLoaded = false; + + /** + * Indicates if Cookie support should be enabled. + */ + protected $cookieSupport = false; + + /** + * Base domain for the Cookie. + */ + protected $baseDomain = ''; + + /** + * Indicates if the CURL based @ syntax for file uploads is enabled. + */ + protected $fileUploadSupport = false; + + /** + * Initialize a Facebook Application. + * + * The configuration: + * - appId: the application ID + * - secret: the application secret + * - cookie: (optional) boolean true to enable cookie support + * - domain: (optional) domain for the cookie + * - fileUpload: (optional) boolean indicating if file uploads are enabled + * + * @param Array $config the application configuration + */ + public function __construct($config) { + $this->setAppId($config['appId']); + $this->setApiSecret($config['secret']); + if (isset($config['cookie'])) { + $this->setCookieSupport($config['cookie']); + } + if (isset($config['domain'])) { + $this->setBaseDomain($config['domain']); + } + if (isset($config['fileUpload'])) { + $this->setFileUploadSupport($config['fileUpload']); + } + } + + /** + * Set the Application ID. + * + * @param String $appId the Application ID + */ + public function setAppId($appId) { + $this->appId = $appId; + return $this; + } + + /** + * Get the Application ID. + * + * @return String the Application ID + */ + public function getAppId() { + return $this->appId; + } + + /** + * Set the API Secret. + * + * @param String $appId the API Secret + */ + public function setApiSecret($apiSecret) { + $this->apiSecret = $apiSecret; + return $this; + } + + /** + * Get the API Secret. + * + * @return String the API Secret + */ + public function getApiSecret() { + return $this->apiSecret; + } + + /** + * Set the Cookie Support status. + * + * @param Boolean $cookieSupport the Cookie Support status + */ + public function setCookieSupport($cookieSupport) { + $this->cookieSupport = $cookieSupport; + return $this; + } + + /** + * Get the Cookie Support status. + * + * @return Boolean the Cookie Support status + */ + public function useCookieSupport() { + return $this->cookieSupport; + } + + /** + * Set the base domain for the Cookie. + * + * @param String $domain the base domain + */ + public function setBaseDomain($domain) { + $this->baseDomain = $domain; + return $this; + } + + /** + * Get the base domain for the Cookie. + * + * @return String the base domain + */ + public function getBaseDomain() { + return $this->baseDomain; + } + + /** + * Set the file upload support status. + * + * @param String $domain the base domain + */ + public function setFileUploadSupport($fileUploadSupport) { + $this->fileUploadSupport = $fileUploadSupport; + return $this; + } + + /** + * Get the file upload support status. + * + * @return String the base domain + */ + public function useFileUploadSupport() { + return $this->fileUploadSupport; + } + + /** + * Get the data from a signed_request token + * + * @return String the base domain + */ + public function getSignedRequest() { + if (!$this->signedRequest) { + if (isset($_REQUEST['signed_request'])) { + $this->signedRequest = $this->parseSignedRequest( + $_REQUEST['signed_request']); + } + } + return $this->signedRequest; + } + + /** + * Set the Session. + * + * @param Array $session the session + * @param Boolean $write_cookie indicate if a cookie should be written. this + * value is ignored if cookie support has been disabled. + */ + public function setSession($session=null, $write_cookie=true) { + $session = $this->validateSessionObject($session); + $this->sessionLoaded = true; + $this->session = $session; + if ($write_cookie) { + $this->setCookieFromSession($session); + } + return $this; + } + + /** + * Get the session object. This will automatically look for a signed session + * sent via the signed_request, Cookie or Query Parameters if needed. + * + * @return Array the session + */ + public function getSession() { + if (!$this->sessionLoaded) { + $session = null; + $write_cookie = true; + + // try loading session from signed_request in $_REQUEST + $signedRequest = $this->getSignedRequest(); + if ($signedRequest) { + // sig is good, use the signedRequest + $session = $this->createSessionFromSignedRequest($signedRequest); + } + + // try loading session from $_REQUEST + if (!$session && isset($_REQUEST['session'])) { + $session = json_decode( + get_magic_quotes_gpc() + ? stripslashes($_REQUEST['session']) + : $_REQUEST['session'], + true + ); + $session = $this->validateSessionObject($session); + } + + // try loading session from cookie if necessary + if (!$session && $this->useCookieSupport()) { + $cookieName = $this->getSessionCookieName(); + if (isset($_COOKIE[$cookieName])) { + $session = array(); + parse_str(trim( + get_magic_quotes_gpc() + ? stripslashes($_COOKIE[$cookieName]) + : $_COOKIE[$cookieName], + '"' + ), $session); + $session = $this->validateSessionObject($session); + // write only if we need to delete a invalid session cookie + $write_cookie = empty($session); + } + } + + $this->setSession($session, $write_cookie); + } + + return $this->session; + } + + /** + * Get the UID from the session. + * + * @return String the UID if available + */ + public function getUser() { + $session = $this->getSession(); + return $session ? $session['uid'] : null; + } + + /** + * Gets a OAuth access token. + * + * @return String the access token + */ + public function getAccessToken() { + $session = $this->getSession(); + // either user session signed, or app signed + if ($session) { + return $session['access_token']; + } else { + return $this->getAppId() .'|'. $this->getApiSecret(); + } + } + + /** + * Get a Login URL for use with redirects. By default, full page redirect is + * assumed. If you are using the generated URL with a window.open() call in + * JavaScript, you can pass in display=popup as part of the $params. + * + * The parameters: + * - next: the url to go to after a successful login + * - cancel_url: the url to go to after the user cancels + * - req_perms: comma separated list of requested extended perms + * - display: can be "page" (default, full page) or "popup" + * + * @param Array $params provide custom parameters + * @return String the URL for the login flow + */ + public function getLoginUrl($params=array()) { + $currentUrl = $this->getCurrentUrl(); + return $this->getUrl( + 'www', + 'login.php', + array_merge(array( + 'api_key' => $this->getAppId(), + 'cancel_url' => $currentUrl, + 'display' => 'page', + 'fbconnect' => 1, + 'next' => $currentUrl, + 'return_session' => 1, + 'session_version' => 3, + 'v' => '1.0', + ), $params) + ); + } + + /** + * Get a Logout URL suitable for use with redirects. + * + * The parameters: + * - next: the url to go to after a successful logout + * + * @param Array $params provide custom parameters + * @return String the URL for the logout flow + */ + public function getLogoutUrl($params=array()) { + return $this->getUrl( + 'www', + 'logout.php', + array_merge(array( + 'next' => $this->getCurrentUrl(), + 'access_token' => $this->getAccessToken(), + ), $params) + ); + } + + /** + * Get a login status URL to fetch the status from facebook. + * + * The parameters: + * - ok_session: the URL to go to if a session is found + * - no_session: the URL to go to if the user is not connected + * - no_user: the URL to go to if the user is not signed into facebook + * + * @param Array $params provide custom parameters + * @return String the URL for the logout flow + */ + public function getLoginStatusUrl($params=array()) { + return $this->getUrl( + 'www', + 'extern/login_status.php', + array_merge(array( + 'api_key' => $this->getAppId(), + 'no_session' => $this->getCurrentUrl(), + 'no_user' => $this->getCurrentUrl(), + 'ok_session' => $this->getCurrentUrl(), + 'session_version' => 3, + ), $params) + ); + } + + /** + * Make an API call. + * + * @param Array $params the API call parameters + * @return the decoded response + */ + public function api(/* polymorphic */) { + $args = func_get_args(); + if (is_array($args[0])) { + return $this->_restserver($args[0]); + } else { + return call_user_func_array(array($this, '_graph'), $args); + } + } + + /** + * Invoke the old restserver.php endpoint. + * + * @param Array $params method call object + * @return the decoded response object + * @throws FacebookApiException + */ + protected function _restserver($params) { + // generic application level parameters + $params['api_key'] = $this->getAppId(); + $params['format'] = 'json-strings'; + + $result = json_decode($this->_oauthRequest( + $this->getApiUrl($params['method']), + $params + ), true); + + // results are returned, errors are thrown + if (is_array($result) && isset($result['error_code'])) { + throw new FacebookApiException($result); + } + return $result; + } + + /** + * Invoke the Graph API. + * + * @param String $path the path (required) + * @param String $method the http method (default 'GET') + * @param Array $params the query/post data + * @return the decoded response object + * @throws FacebookApiException + */ + protected function _graph($path, $method='GET', $params=array()) { + if (is_array($method) && empty($params)) { + $params = $method; + $method = 'GET'; + } + $params['method'] = $method; // method override as we always do a POST + + $result = json_decode($this->_oauthRequest( + $this->getUrl('graph', $path), + $params + ), true); + + // results are returned, errors are thrown + if (is_array($result) && isset($result['error'])) { + $e = new FacebookApiException($result); + switch ($e->getType()) { + // OAuth 2.0 Draft 00 style + case 'OAuthException': + // OAuth 2.0 Draft 10 style + case 'invalid_token': + $this->setSession(null); + } + throw $e; + } + return $result; + } + + /** + * Make a OAuth Request + * + * @param String $path the path (required) + * @param Array $params the query/post data + * @return the decoded response object + * @throws FacebookApiException + */ + protected function _oauthRequest($url, $params) { + if (!isset($params['access_token'])) { + $params['access_token'] = $this->getAccessToken(); + } + + // json_encode all params values that are not strings + foreach ($params as $key => $value) { + if (!is_string($value)) { + $params[$key] = json_encode($value); + } + } + return $this->makeRequest($url, $params); + } + + /** + * Makes an HTTP request. This method can be overriden by subclasses if + * developers want to do fancier things or use something other than curl to + * make the request. + * + * @param String $url the URL to make the request to + * @param Array $params the parameters to use for the POST body + * @param CurlHandler $ch optional initialized curl handle + * @return String the response text + */ + protected function makeRequest($url, $params, $ch=null) { + if (!$ch) { + $ch = curl_init(); + } + + $opts = self::$CURL_OPTS; + if ($this->useFileUploadSupport()) { + $opts[CURLOPT_POSTFIELDS] = $params; + } else { + $opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&'); + } + $opts[CURLOPT_URL] = $url; + + // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait + // for 2 seconds if the server does not support this header. + if (isset($opts[CURLOPT_HTTPHEADER])) { + $existing_headers = $opts[CURLOPT_HTTPHEADER]; + $existing_headers[] = 'Expect:'; + $opts[CURLOPT_HTTPHEADER] = $existing_headers; + } else { + $opts[CURLOPT_HTTPHEADER] = array('Expect:'); + } + + curl_setopt_array($ch, $opts); + $result = curl_exec($ch); + if ($result === false) { + $e = new FacebookApiException(array( + 'error_code' => curl_errno($ch), + 'error' => array( + 'message' => curl_error($ch), + 'type' => 'CurlException', + ), + )); + curl_close($ch); + throw $e; + } + curl_close($ch); + return $result; + } + + /** + * The name of the Cookie that contains the session. + * + * @return String the cookie name + */ + protected function getSessionCookieName() { + return 'fbs_' . $this->getAppId(); + } + + /** + * Set a JS Cookie based on the _passed in_ session. It does not use the + * currently stored session -- you need to explicitly pass it in. + * + * @param Array $session the session to use for setting the cookie + */ + protected function setCookieFromSession($session=null) { + if (!$this->useCookieSupport()) { + return; + } + + $cookieName = $this->getSessionCookieName(); + $value = 'deleted'; + $expires = time() - 3600; + $domain = $this->getBaseDomain(); + if ($session) { + $value = '"' . http_build_query($session, null, '&') . '"'; + if (isset($session['base_domain'])) { + $domain = $session['base_domain']; + } + $expires = $session['expires']; + } + + // prepend dot if a domain is found + if ($domain) { + $domain = '.' . $domain; + } + + // if an existing cookie is not set, we dont need to delete it + if ($value == 'deleted' && empty($_COOKIE[$cookieName])) { + return; + } + + if (headers_sent()) { + self::errorLog('Could not set cookie. Headers already sent.'); + + // ignore for code coverage as we will never be able to setcookie in a CLI + // environment + // @codeCoverageIgnoreStart + } else { + setcookie($cookieName, $value, $expires, '/', $domain); + } + // @codeCoverageIgnoreEnd + } + + /** + * Validates a session_version=3 style session object. + * + * @param Array $session the session object + * @return Array the session object if it validates, null otherwise + */ + protected function validateSessionObject($session) { + // make sure some essential fields exist + if (is_array($session) && + isset($session['uid']) && + isset($session['access_token']) && + isset($session['sig'])) { + // validate the signature + $session_without_sig = $session; + unset($session_without_sig['sig']); + $expected_sig = self::generateSignature( + $session_without_sig, + $this->getApiSecret() + ); + if ($session['sig'] != $expected_sig) { + self::errorLog('Got invalid session signature in cookie.'); + $session = null; + } + // check expiry time + } else { + $session = null; + } + return $session; + } + + /** + * Returns something that looks like our JS session object from the + * signed token's data + * + * TODO: Nuke this once the login flow uses OAuth2 + * + * @param Array the output of getSignedRequest + * @return Array Something that will work as a session + */ + protected function createSessionFromSignedRequest($data) { + if (!isset($data['oauth_token'])) { + return null; + } + + $session = array( + 'uid' => $data['user_id'], + 'access_token' => $data['oauth_token'], + 'expires' => $data['expires'], + ); + + // put a real sig, so that validateSignature works + $session['sig'] = self::generateSignature( + $session, + $this->getApiSecret() + ); + + return $session; + } + + /** + * Parses a signed_request and validates the signature. + * Then saves it in $this->signed_data + * + * @param String A signed token + * @param Boolean Should we remove the parts of the payload that + * are used by the algorithm? + * @return Array the payload inside it or null if the sig is wrong + */ + protected function parseSignedRequest($signed_request) { + list($encoded_sig, $payload) = explode('.', $signed_request, 2); + + // decode the data + $sig = self::base64UrlDecode($encoded_sig); + $data = json_decode(self::base64UrlDecode($payload), true); + + if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') { + self::errorLog('Unknown algorithm. Expected HMAC-SHA256'); + return null; + } + + // check sig + $expected_sig = hash_hmac('sha256', $payload, + $this->getApiSecret(), $raw = true); + if ($sig !== $expected_sig) { + self::errorLog('Bad Signed JSON signature!'); + return null; + } + + return $data; + } + + /** + * Build the URL for api given parameters. + * + * @param $method String the method name. + * @return String the URL for the given parameters + */ + protected function getApiUrl($method) { + static $READ_ONLY_CALLS = + array('admin.getallocation' => 1, + 'admin.getappproperties' => 1, + 'admin.getbannedusers' => 1, + 'admin.getlivestreamvialink' => 1, + 'admin.getmetrics' => 1, + 'admin.getrestrictioninfo' => 1, + 'application.getpublicinfo' => 1, + 'auth.getapppublickey' => 1, + 'auth.getsession' => 1, + 'auth.getsignedpublicsessiondata' => 1, + 'comments.get' => 1, + 'connect.getunconnectedfriendscount' => 1, + 'dashboard.getactivity' => 1, + 'dashboard.getcount' => 1, + 'dashboard.getglobalnews' => 1, + 'dashboard.getnews' => 1, + 'dashboard.multigetcount' => 1, + 'dashboard.multigetnews' => 1, + 'data.getcookies' => 1, + 'events.get' => 1, + 'events.getmembers' => 1, + 'fbml.getcustomtags' => 1, + 'feed.getappfriendstories' => 1, + 'feed.getregisteredtemplatebundlebyid' => 1, + 'feed.getregisteredtemplatebundles' => 1, + 'fql.multiquery' => 1, + 'fql.query' => 1, + 'friends.arefriends' => 1, + 'friends.get' => 1, + 'friends.getappusers' => 1, + 'friends.getlists' => 1, + 'friends.getmutualfriends' => 1, + 'gifts.get' => 1, + 'groups.get' => 1, + 'groups.getmembers' => 1, + 'intl.gettranslations' => 1, + 'links.get' => 1, + 'notes.get' => 1, + 'notifications.get' => 1, + 'pages.getinfo' => 1, + 'pages.isadmin' => 1, + 'pages.isappadded' => 1, + 'pages.isfan' => 1, + 'permissions.checkavailableapiaccess' => 1, + 'permissions.checkgrantedapiaccess' => 1, + 'photos.get' => 1, + 'photos.getalbums' => 1, + 'photos.gettags' => 1, + 'profile.getinfo' => 1, + 'profile.getinfooptions' => 1, + 'stream.get' => 1, + 'stream.getcomments' => 1, + 'stream.getfilters' => 1, + 'users.getinfo' => 1, + 'users.getloggedinuser' => 1, + 'users.getstandardinfo' => 1, + 'users.hasapppermission' => 1, + 'users.isappuser' => 1, + 'users.isverified' => 1, + 'video.getuploadlimits' => 1); + $name = 'api'; + if (isset($READ_ONLY_CALLS[strtolower($method)])) { + $name = 'api_read'; + } + return self::getUrl($name, 'restserver.php'); + } + + /** + * Build the URL for given domain alias, path and parameters. + * + * @param $name String the name of the domain + * @param $path String optional path (without a leading slash) + * @param $params Array optional query parameters + * @return String the URL for the given parameters + */ + protected function getUrl($name, $path='', $params=array()) { + $url = self::$DOMAIN_MAP[$name]; + if ($path) { + if ($path[0] === '/') { + $path = substr($path, 1); + } + $url .= $path; + } + if ($params) { + $url .= '?' . http_build_query($params, null, '&'); + } + return $url; + } + + /** + * Returns the Current URL, stripping it of known FB parameters that should + * not persist. + * + * @return String the current URL + */ + protected function getCurrentUrl() { + $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' + ? 'https://' + : 'http://'; + $currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; + $parts = parse_url($currentUrl); + + // drop known fb params + $query = ''; + if (!empty($parts['query'])) { + $params = array(); + parse_str($parts['query'], $params); + foreach(self::$DROP_QUERY_PARAMS as $key) { + unset($params[$key]); + } + if (!empty($params)) { + $query = '?' . http_build_query($params, null, '&'); + } + } + + // use port if non default + $port = + isset($parts['port']) && + (($protocol === 'http://' && $parts['port'] !== 80) || + ($protocol === 'https://' && $parts['port'] !== 443)) + ? ':' . $parts['port'] : ''; + + // rebuild + return $protocol . $parts['host'] . $port . $parts['path'] . $query; + } + + /** + * Generate a signature for the given params and secret. + * + * @param Array $params the parameters to sign + * @param String $secret the secret to sign with + * @return String the generated signature + */ + protected static function generateSignature($params, $secret) { + // work with sorted data + ksort($params); + + // generate the base string + $base_string = ''; + foreach($params as $key => $value) { + $base_string .= $key . '=' . $value; + } + $base_string .= $secret; + + return md5($base_string); + } + + /** + * Prints to the error log if you aren't in command line mode. + * + * @param String log message + */ + protected static function errorLog($msg) { + // disable error log if we are running in a CLI environment + // @codeCoverageIgnoreStart + if (php_sapi_name() != 'cli') { + error_log($msg); + } + // uncomment this if you want to see the errors on the page + // print 'error_log: '.$msg."\n"; + // @codeCoverageIgnoreEnd + } + + /** + * Base64 encoding that doesn't need to be urlencode()ed. + * Exactly the same as base64_encode except it uses + * - instead of + + * _ instead of / + * + * @param String base64UrlEncodeded string + */ + protected static function base64UrlDecode($input) { + return base64_decode(strtr($input, '-_', '+/')); + } +} +endif; \ No newline at end of file diff --git a/www/wp-content/plugins/social-connect/google/connect.php b/www/wp-content/plugins/social-connect/google/connect.php new file mode 100755 index 0000000..e447d4a --- /dev/null +++ b/www/wp-content/plugins/social-connect/google/connect.php @@ -0,0 +1,45 @@ +identity = 'https://www.google.com/accounts/o8/id'; + $openid->required = array('namePerson/first', 'namePerson/last', 'contact/email'); + header('Location: ' . $openid->authUrl()); + } else { + $openid = new LightOpenID; + if($openid->validate()) { + $google_id = $openid->identity; + $attributes = $openid->getAttributes(); + $email = $attributes['contact/email']; + $first_name = $attributes['namePerson/first']; + $last_name = $attributes['namePerson/last']; + $signature = social_connect_generate_signature($google_id); + ?> + + + + + + + + getMessage(); +} +?> \ No newline at end of file diff --git a/www/wp-content/plugins/social-connect/languages/social_connect-pl_PL.mo b/www/wp-content/plugins/social-connect/languages/social_connect-pl_PL.mo new file mode 100755 index 0000000000000000000000000000000000000000..3e3a23272a29c80fdad0de8b23bd02685bdd8b0e GIT binary patch literal 8439 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 Hnfm`1yDaZY literal 0 HcmV?d00001 diff --git a/www/wp-content/plugins/social-connect/languages/social_connect-pl_PL.po b/www/wp-content/plugins/social-connect/languages/social_connect-pl_PL.po new file mode 100755 index 0000000..6a8a907 --- /dev/null +++ b/www/wp-content/plugins/social-connect/languages/social_connect-pl_PL.po @@ -0,0 +1,212 @@ +msgid "" +msgstr "" +"Project-Id-Version: Social Connect\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-04-26 18:34+0100\n" +"PO-Revision-Date: 2011-04-26 18:36+0100\n" +"Last-Translator: Grzegorz Korba \n" +"Language-Team: app2technologies\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-KeywordsList: __;gettext;gettext_noop;_;_e\n" +"X-Poedit-Basepath: .\n" +"X-Poedit-Language: Polish\n" +"X-Poedit-Country: POLAND\n" +"X-Poedit-SourceCharset: utf-8\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Poedit-SearchPath-0: ../.\n" + +#: .././admin.php:26 +msgid "Social Connect Settings" +msgstr "Ustawienia Social Connect" + +#: .././admin.php:30 +msgid "Facebook Settings" +msgstr "Ustawienia Facebooka" + +#: .././admin.php:31 +msgid "To connect your site to Facebook, you need a Facebook Application. If you have already created one, please insert your API & Secret key below." +msgstr "Aby połączyć swoją witrynę z Facebookiem musisz utworzyć aplikację Facebook. Jeśli już takową zarejestrowałeś wpisz proszę poniżej Twój klucz API oraz klucz sekretny." + +#: .././admin.php:32 +#: .././admin.php:60 +#, php-format +msgid "Already registered? Find your keys in your %1$s Application List" +msgstr "Posiadasz zarejestrowaną aplikację? Znajdź jej klucze na liście swoich aplikacji %1$s" + +#: .././admin.php:33 +msgid "Need to register?" +msgstr "Potrzebujesz zarejestrować?" + +#: .././admin.php:35 +#, php-format +msgid "Visit the Facebook Application Setup page" +msgstr "Odwiedź kreatora aplikacji Facebook" + +#: .././admin.php:36 +#, php-format +msgid "Get the API information from the Facebook Application List" +msgstr "Znajdź informacje o API na liście swoich aplikacji" + +#: .././admin.php:37 +msgid "Select the application you created, then copy and paste the API key & Application Secret from there." +msgstr "Wybierz utworzoną przez siebie aplikację, a następnie skopiuj klucz API i Sekretny Klucz i wklej poniżej." + +#: .././admin.php:41 +#: .././admin.php:69 +msgid "Enable?" +msgstr "Włączyć?" + +#: .././admin.php:44 +msgid "Check this box to enable register/login using Facebook." +msgstr "Zaznacz to pole by włączyć opcję logowania/rejestracji przy użyciu konta Facebook" + +#: .././admin.php:48 +msgid "API Key" +msgstr "Klucz API" + +#: .././admin.php:53 +msgid "Secret Key" +msgstr "Sekretny klucz" + +#: .././admin.php:58 +msgid "Twitter Settings" +msgstr "Ustawienia Twittera" + +#: .././admin.php:59 +msgid "To offer login via Twitter, you need to register your site as a Twitter Application and get a Consumer Key, a Consumer Secret, an Access Token and an Access Token Secret." +msgstr "Aby połączyć witrynę z Twitterem musisz ją zarejestrować jako aplikację Twitter i zdobyć Klucz Konsumenta, Klucz Sekretny, Klucz (token) Dostępu oraz Seretny klucz (token) dostępu." + +#: .././admin.php:61 +#, php-format +msgid "Need to register? Register an Application and fill the form with the details below:" +msgstr "Musisz zarejestrować? Zrób to wykorzystując informacje wyszczególnione poniżej:" + +#: .././admin.php:63 +msgid "Application Type: Browser" +msgstr "Typ aplikacji: Przeglądarka (Browser)" + +#: .././admin.php:64 +#, php-format +msgid "Callback URL: %1$s" +msgstr "Adres zwrotny: %1$s" + +#: .././admin.php:65 +msgid "Default Access: Read & Write" +msgstr "Domyślny dostęp: Odczyt & Zapis" + +#: .././admin.php:72 +msgid "Twitter integration requires the generation of dummy email addresses for authenticating users.
Please check with your domain administrator as this may require changes to your mail server." +msgstr "Integracja z Twitterem wymaga generowania fikcyjnych adresów email w celu autoryzowania użytkowników.
Proszę sprawdź u swojego administratora serwera czy to wymaga zmian w Twoim serwerze poczty." + +#: .././admin.php:76 +msgid "Consumer Key" +msgstr "Klucz konsumenta (API)" + +#: .././admin.php:80 +msgid "Consumer Secret" +msgstr "Sekretny klucz" + +#: .././admin.php:85 +msgid "OpenID Providers" +msgstr "Dostawcy OpenID" + +#: .././admin.php:86 +msgid "Choose the OpenID providers your visitors can use to register, comment and login." +msgstr "Wybierz dostawców OpenID dzięki którym odwiedzający będą mogli się logować, rejestrować i komentować wpisy." + +#: .././admin.php:109 +msgid "Save Changes" +msgstr "Zapisz zmiany" + +#: .././admin.php:112 +msgid "Rewrite Diagnostics" +msgstr "Diagnostyka przekierowań" + +#: .././admin.php:113 +msgid "Click on the link below to confirm your URL rewriting and query string parameter passing are setup correctly on your server. If you see a \"Test was successful\" message after clicking the link then you are good to go. If you see a 404 error or some other error then you need to update rewrite rules or ask your service provider to configure your server settings such that the below URL works correctly." +msgstr "Kliknij w link poniżej aby sprawdzić czy ustawienia serwera dotyczące przekierowań są prawidłowe. Jeśli widzisz komunikat \"Pozytywny wynik testu\" po kliknięciu poniższego linku to znaczy, że konfiguracja jest prawidłowa. Jeśli widzisz błąd 404 lub jakiś inny błąd musisz zaktualizować ustawienia przekierowań lub skontaktować się z dostawcą hostingu w sprawie odpowiedniej konfiguracji serwera." + +#: .././admin.php:114 +msgid "Test server redirection settings" +msgstr "Sprawdź ustawienia serwera" + +#: .././social-connect.php:20 +#, php-format +msgid "Sorry, but you can not run Social Connect. It requires WordPress 3.0 or newer. Consider upgrading your WordPress installation, it's worth the effort.
Return to Plugins Admin page »" +msgstr "Przykro nam, ale nie możesz korzystać z Social Connect. Wymagany jest WordPress w wersji 3.0 lub wyższej. Proszę rozważyć aktualizację WordPressa.
Return to Plugins Admin page »" + +#: .././social-connect.php:22 +#, php-format +msgid "Sorry, but you can not run Social Connect. It requires the PHP libcurl extension be installed. Please contact your web host and request libcurl be installed.
Return to Plugins Admin page »" +msgstr "Przykro nam, ale nie możesz korzystać z Social Connect. Wymagana jest rozszerzenie PHP libcurl. Proszę skontaktować się z obsługą hostingu w celu zainstalowania tego rozszerzenia.
Wróć do listy wtyczek »" + +#: .././social-connect.php:24 +#, php-format +msgid "Sorry, but you can not run Social Connect. It requires PHP 5.1.2 or newer. Please contact your web host and request they migrate your PHP installation to run Social Connect.
Return to Plugins Admin page »" +msgstr "Przykro nam, ale nie możesz korzystać z Social Connect. Wymagana wersja PHP to 5.1.2 lub nowsza. Proszę skontaktować się z obsługą hostingu w celu uruchomienia odpowiedniej wersji PHP.
Wróć do listy wtyczek »" + +#: .././ui.php:21 +msgid "Connect with" +msgstr "Połącz z" + +#: .././ui.php:63 +#, php-format +msgid "Welcome back %s, %scontinue?%s" +msgstr "Witaj %s, %skontynuujemy?%s" + +#: .././ui.php:66 +msgid "Not you?" +msgstr "To nie Ty?" + +#: .././ui.php:67 +msgid "Use another account" +msgstr "Użyj innego konta" + +#: .././ui.php:82 +msgid "Enter your OpenID URL" +msgstr "Wprowadź adres URL dostawcy OpenID" + +#: .././ui.php:85 +#: .././ui.php:93 +msgid "Proceed" +msgstr "Dalej" + +#: .././ui.php:90 +msgid "Enter your WordPress.com blog URL" +msgstr "Uzupełnij adres swojego bloga na WordPress.com" + +#: .././ui.php:162 +msgid "Login or register with Facebook, Twitter, Yahoo, Google or a Wordpress.com account" +msgstr "Logowanie oraz rejestracja za pomocą konta Facebook, Twitter, Yahoo, Google lub WordPress.com." + +#: .././ui.php:214 +msgid "Title:" +msgstr "Tytuł:" + +#: .././ui.php:216 +msgid "Before widget content:" +msgstr "Dodaj przed treścią:" + +#: .././ui.php:218 +msgid "After widget content:" +msgstr "Dodaj za treścią:" + +#: .././ui.php:220 +msgid "Hide for logged in users:" +msgstr "Ukryj dla zalogowanych:" + +#: .././diagnostics/test.php:8 +msgid "Test was successful!

The rewrite rules on your server appear to be setup correctly for Social Connect to work." +msgstr "Pozytywny wynik testu!

Zasady przepisywania adresów na Twoim serwerze są odpowiednie dla poprawnego działania Social Connect." + +#: .././diagnostics/test.php:10 +#, php-format +msgid "Test was unsuccessful. Expected \"http://www.example.com\", received \"%s\"." +msgstr "Test nieudany. Oczekiwano \"http://www.example.com\", otrzymano \"%s\"." + +#: .././diagnostics/test.php:20 +msgid "Social Connect Diagnostics" +msgstr "Diagnostyka Social Connect" + diff --git a/www/wp-content/plugins/social-connect/liveid/callback.php b/www/wp-content/plugins/social-connect/liveid/callback.php new file mode 100755 index 0000000..6107370 --- /dev/null +++ b/www/wp-content/plugins/social-connect/liveid/callback.php @@ -0,0 +1,110 @@ +$liveid_appid,"secret"=>$liveid_secret,"securityalgorithm"=>$liveid_secalgo,"returnurl"=>$liveid_return,"policyurl"=>$liveid_policy); + +// Initialize the WindowsLiveLogin module. +$wll = WindowsLiveLogin::initFromXml(false,$liveid_settings); +$wll->setDebug($DEBUG); + +// Extract the 'action' parameter, if any, from the request. +$action = @$_REQUEST['action']; + +// If action is 'logout', clear the login cookie and redirect to the +// logout page. +// +// If action is 'clearcookie', clear the login cookie and return a GIF +// as a response to signify success. +// +// If action is 'login', try to process sign-in. If the sign-in is +// successful, cache the user token in a cookie and redirect to the +// site's main page. If sign-in failed, clear the cookie and redirect +// to the main page. +// +// If action is 'delauth', get user token from the cookie. Process the +// consent token. If the consent token is valid, store the raw consent +// token in persistent storage. Redirect to the site's main page. +switch ($action) { + case 'logout': + setcookie($WEBAUTHCOOKIE); + header("Location: $LOGOUT"); + break; + case "clearcookie": + ob_start(); + setcookie($WEBAUTHCOOKIE); + + list($type, $response) = $wll->getClearCookieResponse(); + header("Content-Type: $type"); + print($response); + + ob_end_flush(); + break; + case 'login': + $user = $wll->processLogin($_REQUEST); + + if ($user) { + if ($user->usePersistentCookie()) { + setcookie($WEBAUTHCOOKIE, $user->getToken(), $COOKIETTL); + } + else { + setcookie($WEBAUTHCOOKIE, $user->getToken()); + } + header("Location: $LOGIN"); + } + else { + setcookie($WEBAUTHCOOKIE); + header("Location: $LOGIN"); + } + break; + case 'delauth': + $user = null; + $logintoken = @$_COOKIE[$WEBAUTHCOOKIE]; + + if ($logintoken) { + $user = $wll->processToken($logintoken); + } + + if ($user) { + $consent = $wll->processConsent(@$_REQUEST); + if ($consent && $consent->isValid()) { + //$tokens = new TokenDB($TOKENDB); + //$tokens->setToken($user->getId(), $consent->getToken()); + update_option($user->getId(),$consent->getToken()); + } else { + update_option($user->getId(),""); + } + } + header("Location: $LOGIN"); + break; + default: + header("Location: $LOGIN"); + break; +} +?> diff --git a/www/wp-content/plugins/social-connect/liveid/connect.php b/www/wp-content/plugins/social-connect/liveid/connect.php new file mode 100755 index 0000000..be4a37f --- /dev/null +++ b/www/wp-content/plugins/social-connect/liveid/connect.php @@ -0,0 +1,182 @@ +$liveid_appid,"secret"=>$liveid_secret,"securityalgorithm"=>$liveid_secalgo,"returnurl"=>$liveid_return,"policyurl"=>$liveid_policy); + + +if($liveid_appid && $liveid_secret && $liveid_secalgo) { + // Initialize the WindowsLiveLogin module. + $wll = WindowsLiveLogin::initFromXml(false,$liveid_settings); + $wll->setDebug($DEBUG); + $APPID = $wll->getAppId(); + + $login_html = "

This application does not know who you are! Click the Sign in link above.

"; + $consent_html = null; + + // If the user token obtained from sign-in through Web Authentication + // has been cached in a site cookie, attempt to process it and extract + // the user ID. + $token = @$_COOKIE[$WEBAUTHCOOKIE]; + + $userid = null; + if ($token) { + $user = $wll->processToken($token); + if ($user) { + $userid = $user->getId(); + } + } + + // If the user ID is obtained successfully, prepare the message + // to include the consent URL if a valid token is not present in the + // persistent store; otherwise display the contents of the token. + if ($userid) { + $login_html = "

Now this application knows that you are the user with ID = \"$userid\".

"; + + $consenturl = $wll->getConsentUrl($OFFERS); + + $consent_html = "

Please click here to grant consent so that we may access your Windows Live data.

"; + + // Attempt to get the raw consent token from persistent store for the + // current user ID. + //$tokens = new TokenDB($TOKENDB); + //$token = $tokens->getToken($userid); + $token = get_option($userid); + + $consenttoken = $wll->processConsentToken($token); + + if ($consenttoken) { + if (!$consenttoken->isValid()) { + wp_redirect($consenturl); + } + } + + + // If a consent token is found and is stale, try to refresh it and store + // it in persistent storage. + if ($consenttoken) { + if (!$consenttoken->isValid()) { + if ($consenttoken->refresh() && $consenttoken->isValid()) { + //$tokens->setToken($userid, $consenttoken->getToken()); + update_option($userid,$consenttoken->getToken()); + } + } + + if ($consenttoken->isValid()) { + // Convert Unix epoch time stamp to user-friendly format. + $expiry = $consenttoken->getExpiry(); + $expiry = date(DATE_RFC2822, $expiry); + //Prepare the message to display the consent token contents. + $consent_html = <<Consent token found! The following are its contents..

+ + + + + + + + + +
Delegation token{$consenttoken->getDelegationToken()}
Location ID{$consenttoken->getLocationID()}
Refresh token{$consenttoken->getRefreshToken()}
Expiry{$expiry}
Offers{$consenttoken->getOffersString()}
Context{$consenttoken->getContext()}
Token{$consenttoken->getToken()}
+END; + + } + } + } + +// This code embeds the Web Authentication control on your Web page +// to display the appropriate application Sign in/Sign out link. +$control_html = << + +END; +} + +if ($consenttoken) { + + $dt = $consenttoken->getDelegationToken(); + $header = array("Authorization: DelegatedToken dt=\"$dt\"\r\n"); + + $opts = array( + 'http'=>array( + 'method'=>'GET', + 'header'=>$header + ) + ); + + $context = stream_context_create($opts); + + $xml = file_get_contents("https://livecontacts.services.live.com/users/@L@" . $consenttoken->getLocationID() . "/rest/livecontacts", false, $context); + + if($xml) { + $oSimpleXML = new SimpleXMLElement($xml); + $contactsArray = array(); + $i = 0; + $owner = $oSimpleXML->Owner; + $liveid = $owner->WindowsLiveID; + $email = $owner->Emails->Email->Address; + if (trim($email) == "") {$email = $liveid;} + $first_name = $owner->Profiles->Personal->FirstName; + $last_name = $owner->Profiles->Personal->LastName; + $signature = social_connect_generate_signature($liveid); + + } +} +?> + + + + + + + + + diff --git a/www/wp-content/plugins/social-connect/liveid/windowslivelogin.php b/www/wp-content/plugins/social-connect/liveid/windowslivelogin.php new file mode 100755 index 0000000..3cdc9ca --- /dev/null +++ b/www/wp-content/plugins/social-connect/liveid/windowslivelogin.php @@ -0,0 +1,1606 @@ +_timestamp; + } + + /** + * Sets the Unix timestamp. + */ + private function setTimestamp($timestamp) + { + if (!$timestamp) { + throw new Exception('Error: WLL_User: Null timestamp.'); + } + + if (!preg_match('/^\d+$/', $timestamp) || ($timestamp <= 0)) { + throw new Exception('Error: WLL_User: Invalid timestamp: ' + . $timestamp); + } + + $this->_timestamp = $timestamp; + } + + private $_id; + + /** + * Returns the pairwise unique ID for the user. + */ + public function getId() + { + return $this->_id; + } + + /** + * Sets the pairwise unique ID for the user. + */ + private function setId($id) + { + if (!$id) { + throw new Exception('Error: WLL_User: Null id.'); + } + + if (!preg_match('/^\w+$/', $id)) { + throw new Exception('Error: WLL_User: Invalid id: ' . $id); + } + + $this->_id = $id; + } + + private $_usePersistentCookie; + + /** + * Indicates whether the application is expected to store the + * user token in a session or persistent cookie. + */ + public function usePersistentCookie() + { + return $this->_usePersistentCookie; + } + + /** + * Sets the usePersistentCookie flag for the user. + */ + private function setFlags($flags) + { + $this->_usePersistentCookie = false; + if (preg_match('/^\d+$/', $flags)) { + $this->_usePersistentCookie = (($flags % 2) == 1); + } + } + + private $_context; + + /** + * Returns the application context that was originally passed + * to the sign-in request, if any. + */ + public function getContext() + { + return $this->_context; + } + + /** + * Sets the the Application context. + */ + private function setContext($context) + { + $this->_context = $context; + } + + private $_token; + + /** + * Returns the encrypted Web Authentication token containing + * the UID. This can be cached in a cookie and the UID can be + * retrieved by calling the ProcessToken method. + */ + public function getToken() + { + return $this->_token; + } + + /** + * Sets the the User token. + */ + private function setToken($token) + { + $this->_token = $token; + } +} + +/** + * Holds the Consent Token object corresponding to consent granted. + */ +class WLL_ConsentToken +{ + /** + * Indicates whether the delegation token is set and has not expired. + */ + public function isValid() + { + if (!self::getDelegationToken()) { + return false; + } + + $now = time(); + return (($now-300) < self::getExpiry()); + } + + /** + * Refreshes the current token and replace it. If operation succeeds + * true is returned to signify success. + */ + public function refresh() + { + $wll = $this->_wll; + $ct = $wll->refreshConsentToken($this); + if (!$ct) { + return false; + } + self::copy($ct); + return true; + } + + private $_wll; + + /** + * Initialize the ConsentToken module with the WindowsLiveLogin, + * delegation token, refresh token, session key, expiry, offers, + * location ID, context, decoded token, and raw token. + */ + public function __construct($wll, $delegationtoken, $refreshtoken, + $sessionkey, $expiry, $offers, $locationID, $context, + $decodedtoken, $token) + { + $this->_wll = $wll; + self::setDelegationToken($delegationtoken); + self::setRefreshToken($refreshtoken); + self::setSessionKey($sessionkey); + self::setExpiry($expiry); + self::setOffers($offers); + self::setLocationID($locationID); + self::setContext($context); + self::setDecodedToken($decodedtoken); + self::setToken($token); + } + + private $_delegationtoken; + + /** + * Gets the Delegation token. + */ + public function getDelegationToken() + { + return $this->_delegationtoken; + } + + /** + * Sets the Delegation token. + */ + private function setDelegationToken($delegationtoken) + { + if (!$delegationtoken) { + throw new Exception('Error: WLL_ConsentToken: Null delegation token.'); + } + $this->_delegationtoken = $delegationtoken; + } + + private $_refreshtoken; + + /** + * Gets the refresh token. + */ + public function getRefreshToken() + { + return $this->_refreshtoken; + } + + /** + * Sets the refresh token. + */ + private function setRefreshToken($refreshtoken) + { + $this->_refreshtoken = $refreshtoken; + } + + private $_sessionkey; + + /** + * Gets the session key. + */ + public function getSessionKey() + { + return $this->_sessionkey; + } + + /** + * Sets the session key. + */ + private function setSessionKey($sessionkey) + { + if (!$sessionkey) { + throw new Exception('Error: WLL_ConsentToken: Null session key.'); + } + $this->_sessionkey = base64_decode(urldecode($sessionkey)); + } + + private $_expiry; + + /** + * Gets the expiry time of delegation token. + */ + public function getExpiry() + { + return $this->_expiry; + } + + /** + * Sets the expiry time of delegation token. + */ + private function setExpiry($expiry) + { + if (!$expiry) { + throw new Exception('Error: WLL_ConsentToken: Null expiry time.'); + } + + if (!preg_match('/^\d+$/', $expiry) || ($expiry <= 0)) { + throw new Exception('Error: WLL_ConsentToken: Invalid expiry time: ' + . $expiry); + } + $this->_expiry = $expiry; + } + + private $_offers; + + /** + * Gets the list of offers/actions for which the user granted consent. + */ + public function getOffers() + { + return $this->_offers; + } + + private $_offers_string; + + /** + * Gets the string representation of all the offers/actions for which + * the user granted consent. + */ + public function getOffersString() + { + return $this->_offers_string; + } + + /** + * Sets the offers/actions for which user granted consent. + */ + private function setOffers($offers) + { + if (!$offers) { + throw new Exception('Error: WLL_ConsentToken: Null offers.'); + } + + $off_s = ""; + $off = array(); + + $offers = urldecode($offers); + $offers = split(";", $offers); + foreach ($offers as $offer) { + $offer = split(":", $offer); + $offer = $offer[0]; + if ($off_s) { + $off_s .= ","; + } + $off_s .= $offer; + $off[] = $offer; + } + + $this->_offers_string = $off_s; + $this->_offers = $off; + } + + private $_locationID; + /** + * Gets the location ID. + */ + public function getLocationID() + { + return $this->_locationID; + } + + /** + * Sets the location ID. + */ + private function setLocationID($locationID) + { + if (!$locationID) { + throw new Exception('Error: WLL_ConsentToken: Null Location ID.'); + } + $this->_locationID = $locationID; + } + + private $_context; + /** + * Returns the application context that was originally passed + * to the sign-in request, if any. + */ + public function getContext() + { + return $this->_context; + } + + /** + * Sets the application context. + */ + private function setContext($context) + { + $this->_context = $context; + } + + private $_decodedtoken; + /** + * Gets the decoded token. + */ + public function getDecodedToken() + { + return $this->_decodedtoken; + } + + /** + * Sets the decoded token. + */ + private function setDecodedToken($decodedtoken) + { + $this->_decodedtoken = $decodedtoken; + } + + private $_token; + + /** + * Gets the raw token. + */ + public function getToken() + { + return $this->_token; + } + + /** + * Sets the raw token. + */ + private function setToken($token) + { + $this->_token = $token; + } + + /** + * Makes a copy of the ConsentToken object. + */ + private function copy($ct) + { + $this->_delegationtoken = $ct->_delegationtoken; + $this->_refreshtoken = $ct->_refreshtoken; + $this->_sessionkey = $ct->_sessionkey; + $this->_expiry = $ct->_expiry; + $this->_offers = $ct->_offers; + $this->_offers_string = $ct->_offers_string; + $this->_locationID = $ct->_locationID; + $this->_decodedtoken = $ct->_decodedtoken; + $this->_token = $ct->_token; + } +} + +class WindowsLiveLogin +{ + /* Implementation of basic methods for Web Authentication support. */ + + private $_debug = false; + + /** + * Stub implementation for logging errors. If you want to enable + * debugging output, set this to true. In this implementation + * errors will be logged using the PHP error_log function. + */ + public function setDebug($debug) + { + $this->_debug = $debug; + } + + /** + * Stub implementation for logging errors. By default, this + * function does nothing if the debug flag has not been set with + * setDebug. Otherwise, errors are logged using the PHP error_log + * function. + */ + private function debug($string) + { + if ($this->_debug) { + error_log($string); + } + } + + /** + * Stub implementation for handling a fatal error. + */ + private function fatal($string) + { + self::debug($string); + throw new Exception($string); + } + + /** + * Initialize the WindowsLiveLogin module with the application ID, + * secret key, and security algorithm. + * + * We recommend that you employ strong measures to protect the + * secret key. The secret key should never be exposed to the Web + * or other users. + * + * Be aware that if you do not supply these settings at + * initialization time, you may need to set the corresponding + * properties manually. + * + * For Delegated Authentication, you may optionally specify the + * privacy policy URL and return URL. If you do not specify these + * values here, the default values that you specified when you + * registered your application will be used. + * + * The 'force_delauth_nonprovisioned' flag also indicates whether + * your application is registered for Delegated Authentication + * (that is, whether it uses an application ID and secret key). We + * recommend that your Delegated Authentication application always + * be registered for enhanced security and functionality. + */ + public function __construct($appid=null, $secret=null, $securityalgorithm=null, + $force_delauth_nonprovisioned=null, + $policyurl=null, $returnurl=null) + { + self::setForceDelAuthNonProvisioned($force_delauth_nonprovisioned); + + if ($appid) { + self::setAppId($appid); + } + if ($secret) { + self::setSecret($secret); + } + if ($securityalgorithm) { + self::setSecurityAlgorithm($securityalgorithm); + } + if ($policyurl) { + self::setPolicyUrl($policyurl); + } + if ($returnurl) { + self::setReturnUrl($returnurl); + } + } + + /** + * Initialize the WindowsLiveLogin module from a settings file. + * + * 'settingsFile' specifies the location of the XML settings file + * that contains the application ID, secret key, and security + * algorithm. The file is of the following format: + * + * + * APPID + * SECRET + * wsignin1.0 + * + * + * In a Delegated Authentication scenario, you may also specify + * 'returnurl' and 'policyurl' in the settings file, as shown in the + * Delegated Authentication samples. + * + * We recommend that you store the WindowsLiveLogin settings file + * in an area on your server that cannot be accessed through the + * Internet. This file contains important confidential information. + * + * Function modified for social-connect to accept passed hash when + * xml file is not to be used. + */ + public static function initFromXml($settingsFile, $settings = array()) + { + $o = new WindowsLiveLogin(); + + if($settingsFile) { + $settings = $o->parseSettings($settingsFile); + } + + if (@$settings['debug'] == 'true') { + $o->setDebug(true); + } + else { + $o->setDebug(false); + } + + if (@$settings['force_delauth_nonprovisioned'] == 'true') { + $o->setForceDelAuthNonProvisioned(true); + } + else { + $o->setForceDelAuthNonProvisioned(false); + } + + $o->setAppId(@$settings['appid']); + $o->setSecret(@$settings['secret']); + $o->setOldSecret(@$settings['oldsecret']); + $o->setOldSecretExpiry(@$settings['oldsecretexpiry']); + $o->setSecurityAlgorithm(@$settings['securityalgorithm']); + $o->setPolicyUrl(@$settings['policyurl']); + $o->setReturnUrl(@$settings['returnurl']); + $o->setBaseUrl(@$settings['baseurl']); + $o->setSecureUrl(@$settings['secureurl']); + $o->setConsentBaseUrl(@$settings['consenturl']); + return $o; + } + + private $_appid; + + /** + * Sets the application ID. Use this method if you did not specify + * an application ID at initialization. + **/ + public function setAppId($appid) + { + $_force_delauth_nonprovisioned = $this->_force_delauth_nonprovisioned; + if (!$appid) { + if ($_force_delauth_nonprovisioned) { + return; + } + self::fatal('Error: setAppId: Null application ID.'); + } + if (!preg_match('/^\w+$/', $appid)) { + self::fatal("Error: setAppId: Application ID must be alpha-numeric: $appid"); + } + $this->_appid = $appid; + } + + /** + * Returns the application ID. + */ + public function getAppId() + { + if (!$this->_appid) { + self::fatal('Error: getAppId: Application ID was not set. Aborting.'); + } + return $this->_appid; + } + + private $_signkey; + private $_cryptkey; + + /** + * Sets your secret key. Use this method if you did not specify + * a secret key at initialization. + */ + public function setSecret($secret) + { + $_force_delauth_nonprovisioned = $this->_force_delauth_nonprovisioned; + if (!$secret || (strlen($secret) < 16)) { + if ($_force_delauth_nonprovisioned) { + return; + } + self::fatal("Error: setSecret: Secret key is expected to be non-null and longer than 16 characters."); + } + + $this->_signkey = self::derive($secret, "SIGNATURE"); + $this->_cryptkey = self::derive($secret, "ENCRYPTION"); + } + + private $_oldsignkey; + private $_oldcryptkey; + + /** + * Sets your old secret key. + * + * Use this property to set your old secret key if you are in the + * process of transitioning to a new secret key. You may need this + * property because the Windows Live ID servers can take up to + * 24 hours to propagate a new secret key after you have updated + * your application settings. + * + * If an old secret key is specified here and has not expired + * (as determined by the oldsecretexpiry setting), it will be used + * as a fallback if token decryption fails with the new secret + * key. + */ + public function setOldSecret($secret) + { + if (!$secret) { + return; + } + if (strlen($secret) < 16) { + self::fatal("Error: setOldSecret: Secret key is expected to be non-null and longer than 16 characters."); + } + + $this->_oldsignkey = self::derive($secret, "SIGNATURE"); + $this->_oldcryptkey = self::derive($secret, "ENCRYPTION"); + } + + private $_oldsecretexpiry; + + /** + * Sets the expiry time for your old secret key. + * + * After this time has passed, the old secret key will no longer be + * used even if token decryption fails with the new secret key. + * + * The old secret expiry time is represented as the number of seconds + * elapsed since January 1, 1970. + */ + public function setOldSecretExpiry($timestamp) + { + if (!$timestamp) { + return; + } + + if (!preg_match('/^\d+$/', $timestamp) || ($timestamp <= 0)) { + self::fatal('Error: setOldSecretExpiry Invalid timestamp: ' + . $timestamp); + } + + $this->_oldsecretexpiry = $timestamp; + } + + /** + * Gets the old secret key expiry time. + */ + public function getOldSecretExpiry() + { + return $this->_oldsecretexpiry; + } + + private $_securityalgorithm; + + /** + * Sets the version of the security algorithm being used. + */ + public function setSecurityAlgorithm($securityalgorithm) + { + $this->_securityalgorithm = $securityalgorithm; + } + + /** + * Gets the version of the security algorithm being used. + */ + public function getSecurityAlgorithm() + { + $securityalgorithm = $this->_securityalgorithm; + if (!$securityalgorithm) { + return 'wsignin1.0'; + } + return $securityalgorithm; + } + + private $_force_delauth_nonprovisioned; + + /** + * Sets a flag that indicates whether Delegated Authentication + * is non-provisioned (i.e. does not use an application ID or secret + * key). + */ + public function setForceDelAuthNonProvisioned($force_delauth_nonprovisioned) + { + $this->_force_delauth_nonprovisioned = $force_delauth_nonprovisioned; + } + + private $_policyurl; + + /** + * Sets the privacy policy URL if you did not provide one at initialization time. + */ + public function setPolicyUrl($policyurl) + { + $_force_delauth_nonprovisioned = $this->_force_delauth_nonprovisioned; + if (!$policyurl) { + if ($_force_delauth_nonprovisioned) { + self::fatal("Error: setPolicyUrl: Null policy URL given."); + } + } + $this->_policyurl = $policyurl; + } + + /** + * Gets the privacy policy URL for your site. + */ + public function getPolicyUrl() + { + $policyurl = $this->_policyurl; + $_force_delauth_nonprovisioned = $this->_force_delauth_nonprovisioned; + if (!$policyurl) { + self::debug("Warning: In the initial release of Delegated Auth, a Policy URL must be configured in the SDK for both provisioned and non-provisioned scenarios."); + if ($_force_delauth_nonprovisioned) { + self::fatal("Error: getPolicyUrl: Policy URL must be set in a Del Auth non-provisioned scenario. Aborting."); + } + } + return $policyurl; + } + + private $_returnurl; + + /** + * Sets the return URL--the URL on your site to which the consent + * service redirects users (along with the action, consent token, + * and application context) after they have successfully provided + * consent information for Delegated Authentication. This value will + * override the return URL specified during registration. + */ + public function setReturnUrl($returnurl) + { + $_force_delauth_nonprovisioned = $this->_force_delauth_nonprovisioned; + if (!$returnurl) { + if ($_force_delauth_nonprovisioned) { + self::fatal("Error: setReturnUrl: Null return URL given."); + } + } + $this->_returnurl = $returnurl; + } + + /** + * Returns the return URL of your site. + */ + public function getReturnUrl() + { + $_force_delauth_nonprovisioned = $this->_force_delauth_nonprovisioned; + $returnurl = $this->_returnurl; + if (!$returnurl) { + if ($_force_delauth_nonprovisioned) { + self::fatal("Error: getReturnUrl: Return URL must be set in a Del Auth non-provisioned scenario. Aborting."); + } + } + return $returnurl; + } + + private $_baseurl; + + /** + * Sets the base URL to use for the Windows Live Login server. + * You should not have to change this property. Furthermore, we recommend + * that you use the Sign In control instead of the URL methods + * provided here. + */ + public function setBaseUrl($baseurl) + { + $this->_baseurl = $baseurl; + } + + /** + * Gets the base URL to use for the Windows Live Login server. + * You should not have to use this property. Furthermore, we recommend + * that you use the Sign In control instead of the URL methods + * provided here. + */ + public function getBaseUrl() + { + $baseurl = $this->_baseurl; + if (!$baseurl) { + return "http://login.live.com/"; + } + return $baseurl; + } + + private $_secureurl; + + /** + * Sets the secure (HTTPS) URL to use for the Windows Live Login + * server. You should not have to change this property. + */ + public function setSecureUrl($secureurl) + { + $this->_secureurl = $secureurl; + } + + /** + * Gets the secure (HTTPS) URL to use for the Windows Live Login + * server. You should not have to use this functon directly. + */ + public function getSecureUrl() + { + $secureurl = $this->_secureurl; + if (!$secureurl) { + return "https://login.live.com/"; + } + return $secureurl; + } + + private $_consenturl; + + /** + * Sets the Consent Base URL to use for the Windows Live Consent + * server. You should not have to use or change this property directly. + */ + public function setConsentBaseUrl($consenturl) + { + $this->_consenturl = $consenturl; + } + + /** + * Gets the URL to use for the Windows Live Consent server. You + * should not have to use or change this directly. + */ + public function getConsentBaseUrl() + { + $consenturl = $this->_consenturl; + if (!$consenturl) { + return "https://consent.live.com/"; + } + return $consenturl; + } + + /* Methods for Web Authentication support. */ + + /** + * Returns the sign-in URL to use for the Windows Live Login server. + * We recommend that you use the Sign In control instead. + * + * If you specify it, 'context' will be returned as-is in the sign-in + * response for site-specific use. + */ + public function getLoginUrl($context=null, $market=null) + { + $url = self::getBaseUrl(); + $url .= 'wlogin.srf?appid=' . self::getAppId(); + $url .= '&alg=' . self::getSecurityAlgorithm(); + $url .= ($context ? '&appctx=' . urlencode($context) : ''); + $url .= ($market ? '&mkt=' . urlencode($market) : ''); + return $url; + } + + /** + * Returns the sign-out URL to use for the Windows Live Login server. + * We recommend that you use the Sign In control instead. + */ + public function getLogoutUrl($market=null) + { + $url = self::getBaseUrl(); + $url .= "logout.srf?appid=" . self::getAppId(); + $url .= ($market ? '&mkt=' . urlencode($market) : ''); + return $url; + } + + /** + * Processes the sign-in response from Windows Live Login server. + * + * @param query contains the preprocessed POST query, a map of + * Strings to an an array of Strings, such as that + * returned by ServletRequest.getParameterMap(). + * @return a User object on successful sign-in; otherwise null. + */ + public function processLogin($query) + { + $action = @$query['action']; + if ($action != 'login') { + self::debug("Warning: processLogin: query action ignored: $action"); + return; + } + $token = @$query['stoken']; + $context = urldecode(@$query['appctx']); + return self::processToken($token, $context); + } + + /** + * Decodes and validates a Web Authentication token. Returns a User + * object on success. If a context is passed in, it will be returned + * as the context field in the User object. + */ + public function processToken($token, $context=null) + { + if (!$token) { + self::debug('Error: processToken: Invalid token specified.'); + return; + } + + $decodedToken = self::decodeAndValidateToken($token); + if (!$decodedToken) { + self::debug("Error: processToken: Failed to decode/validate token: $token"); + return; + } + + $parsedToken = self::parse($decodedToken); + if (!$parsedToken) { + self::debug("Error: processToken: Failed to parse token after decoding: $token"); + return; + } + + $appid = self::getAppId(); + $tokenappid = @$parsedToken['appid']; + if ($appid != $tokenappid) { + self::debug("Error: processToken: Application ID in token did not match ours: $tokenappid, $appid"); + return; + } + + $user = null; + + try { + $user = new WLL_User(@$parsedToken['ts'], + @$parsedToken['uid'], + @$parsedToken['flags'], + $context, $token); + } catch (Exception $e) { + self::debug("Error: processToken: Contents of token considered invalid: " + $e->getMessage()); + } + + return $user; + } + + /** + * Returns an appropriate content type and body response that the + * application handler can return to signify a successful sign-out + * from the application. + * + * When a user signs out of Windows Live or a Windows Live + * application, a best-effort attempt is made at signing the user out + * from all other Windows Live applications the user might be signed + * in to. This is done by calling the handler page for each + * application with 'action' set to 'clearcookie' in the query + * string. The application handler is then responsible for clearing + * any cookies or data associated with the sign-in. After successfully + * signing the user out, the handler should return a GIF (any GIF) + * image as response to the 'action=clearcookie' query. + */ + public function getClearCookieResponse() + { + $type = "image/gif"; + $content = "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7"; + $content = base64_decode($content); + return array($type, $content); + } + + /* Methods for Delegated Authentication. */ + + /* + * Returns the consent URL to use for Delegated Authentication for + * the given comma-delimited list of offers. + * + * If you specify it, 'context' will be returned as-is in the consent + * response for site-specific use. + * + * The registered/configured return URL can also be overridden by + * specifying 'ru' here. + * + * You can change the language in which the consent page is displayed + * by specifying a culture ID (For example, 'fr-fr' or 'en-us') in the + * 'market' parameter. + */ + public function getConsentUrl($offers, $context=null, $ru=null, $market=null) + { + if (!$offers) { + throw new Exception('Error: getConsentUrl: Invalid offers list.'); + } + $url = self::getConsentBaseUrl(); + $url .= 'Delegation.aspx?ps=' . urlencode($offers); + $ru = ($ru ? $ru : self::getReturnUrl()); + $url .= ($ru ? '&ru=' . urlencode($ru) : ''); + $pl = self::getPolicyUrl(); + $url .= ($pl ? '&pl=' . urlencode($pl) : ''); + $url .= ($market ? '&mkt=' . urlencode($market) : ''); + if (!$this->_force_delauth_nonprovisioned) { + $url .= '&app=' . self::getAppVerifier(); + } + $url .= ($context ? '&appctx=' . urlencode($context) : ''); + return $url; + } + + /* + * Returns the URL to use to download a new consent token, given the + * offers and refresh token. + * + * The registered/configured return URL can also be overridden by + * specifying 'ru' here. + */ + public function getRefreshConsentTokenUrl($offers, $refreshtoken, $ru=null) + { + $_force_delauth_nonprovisioned = $this->_force_delauth_nonprovisioned; + if (!$offers) { + throw new Exception('Error: getRefreshConsentTokenUrl: Invalid offers list.'); + } + if (!$refreshtoken) { + throw new Exception('Error: getRefreshConsentTokenUrl: Invalid refresh token.'); + } + + $url = self::getConsentBaseUrl(); + $url .= 'RefreshToken.aspx?ps=' . urlencode($offers); + $url .= '&reft=' . $refreshtoken; + $ru = ($ru ? $ru : self::getReturnUrl()); + $url .= ($ru ? '&ru=' . urlencode($ru) : ''); + + if (!$this->_force_delauth_nonprovisioned) { + $url .= '&app=' . self::getAppVerifier(); + } + + return $url; + } + + /* + * Returns the URL for the consent-management user interface. + * + * You can change the language in which the consent page is displayed + * by specifying a culture ID (For example, 'fr-fr' or 'en-us') in the + * 'market' parameter. + */ + public function getManageConsentUrl($market=null) + { + $url = self::getConsentBaseUrl(); + $url .= 'ManageConsent.aspx'; + $url .= ($market ? '?mkt=' . urlencode($market) : ''); + return $url; + } + + /* + * Processes the POST response from the Delegated Authentication + * service after a user has granted consent. The processConsent + * function extracts the consent token string and returns the result + * of invoking the processConsentToken method. + */ + public function processConsent($query) + { + $action = @$query['action']; + if ($action != 'delauth') { + self::debug("Warning: processConsent: query action ignored: $action"); + return; + } + $responsecode = @$query['ResponseCode']; + if ($responsecode != 'RequestApproved') { + self::debug("Warning: processConsent: consent was not successfully granted: $responsecode"); + return; + } + $token = @$query['ConsentToken']; + $context = urldecode(@$query['appctx']); + return self::processConsentToken($token, $context); + } + + /* + * Processes the consent token string that is returned in the POST + * response by the Delegated Authentication service after a + * user has granted consent. + */ + public function processConsentToken($token, $context=null) + { + if (!$token) { + self::debug('Error: processConsentToken: Null token.'); + return; + } + + $decodedToken = $token; + $parsedToken = self::parse(urldecode($decodedToken)); + if (!$parsedToken) { + self::debug("Error: processConsentToken: Failed to parse token: $token"); + return; + } + + $eact = @$parsedToken['eact']; + if ($eact) { + $decodedToken = self::decodeAndValidateToken($eact); + if (!$decodedToken) { + self::debug("Error: processConsentToken: Failed to decode/validate token: $token"); + return; + } + $parsedToken = self::parse($decodedToken); + if (!$parsedToken) { + self::debug("Error: processConsentToken: Failed to parse token after decoding: $token"); + return; + } + $decodedToken = urlencode($decodedToken); + } + + $consenttoken = null; + + try { + $consenttoken = new WLL_ConsentToken($this, + @$parsedToken['delt'], + @$parsedToken['reft'], + @$parsedToken['skey'], + @$parsedToken['exp'], + @$parsedToken['offer'], + @$parsedToken['lid'], + $context, $decodedToken, $token); + } catch (Exception $e) { + self::debug("Error: processConsentToken: Contents of token considered invalid: " + $e->getMessage()); + } + return $consenttoken; + } + + /* + * Attempts to obtain a new, refreshed token and return it. The + * original token is not modified. + */ + public function refreshConsentToken($token, $ru=null) + { + if (!$token) { + self::debug("Error: refreshConsentToken: Null consent token."); + return; + } + self::refreshConsentToken2($token->getOffersString(), $token->getRefreshToken(), $ru); + } + + /* + * Helper function to obtain a new, refreshed token and return it. + * The original token is not modified. + */ + public function refreshConsentToken2($offers_string, $refreshtoken, $ru=null) + { + $body = self::fetch(self::getRefreshConsentTokenUrl($offers_string, $refreshtoken, $ru)); + if (!$body) { + self::debug("Error: refreshConsentToken2: Failed to obtain a new token."); + return; + } + + preg_match('/\{"ConsentToken":"(.*)"\}/', $body, $matches); + if(count($matches) == 2) { + return $matches[1]; + } + else { + self::debug("Error: refreshConsentToken2: Failed to extract token: $body"); + return; + } + } + + /* Common methods. */ + + /* + * Decodes and validates the token. + */ + public function decodeAndValidateToken($token, $cryptkey=null, $signkey=null, + $internal_allow_recursion=true) + { + if (!$cryptkey) { + $cryptkey = $this->_cryptkey; + } + if (!$signkey) { + $signkey = $this->_signkey; + } + + $haveoldsecret = false; + $oldsecretexpiry = self::getOldSecretExpiry(); + $oldcryptkey = $this->_oldcryptkey; + $oldsignkey = $this->_oldsignkey; + + if ($oldsecretexpiry and (time() < $oldsecretexpiry)) { + if ($oldcryptkey and $oldsignkey) { + $haveoldsecret = true; + } + } + $haveoldsecret = ($haveoldsecret and $internal_allow_recursion); + + $stoken = self::decodeToken($token, $cryptkey); + + if ($stoken) { + $stoken = self::validateToken($stoken, $signkey); + } + + if (!$stoken and $haveoldsecret) { + self::debug("Warning: Failed to validate token with current secret, attempting old secret."); + $stoken = + self::decodeAndValidateToken($token, $oldcryptkey, $oldsignkey, false); + } + + return $stoken; + } + + /** + * Decodes the given token string; returns undef on failure. + * + * First, the string is URL-unescaped and base64 decoded. + * Second, the IV is extracted from the first 16 bytes of the string. + * Finally, the string is decrypted using the encryption key. + */ + public function decodeToken($token, $cryptkey=null) + { + if (!$cryptkey) { + $cryptkey = $this->_cryptkey; + } + if (!$cryptkey) { + self::fatal("Error: decodeToken: Secret key was not set. Aborting."); + } + + $ivLen = 16; + $token = self::u64($token); + $len = strlen($token); + + if (!$token || ($len <= $ivLen) || (($len % $ivLen) != 0)) { + self::debug("Error: decodeToken: Attempted to decode invalid token."); + return; + } + + $iv = substr($token, 0, 16); + $crypted = substr($token, 16); + $mode = MCRYPT_MODE_CBC; + $enc = MCRYPT_RIJNDAEL_128; + return mcrypt_decrypt($enc, $cryptkey, $crypted, $mode, $iv); + } + + /** + * Creates a signature for the given string by using the signature + * key. + */ + public function signToken($token, $signkey=null) + { + if (!$signkey) { + $signkey = $this->_signkey; + } + if (!$signkey) { + self::fatal("Error: signToken: Secret key was not set. Aborting."); + } + + if (!$token) { + self::debug("Attempted to sign null token."); + return; + } + + return hash_hmac("sha256", $token, $signkey, true); + } + + /** + * Extracts the signature from the token and validates it. + */ + public function validateToken($token, $signkey=null) + { + if (!$signkey) { + $signkey = $this->_signkey; + } + if (!$token) { + self::debug("Error: validateToken: Invalid token."); + return; + } + + $split = split("&sig=", $token); + if (count($split) != 2) { + self::debug("ERROR: validateToken: Invalid token: $token"); + return; + } + list($body, $sig) = $split; + + $sig = self::u64($sig); + if (!$sig) { + self::debug("Error: validateToken: Could not extract signature from token."); + return; + } + + $sig2 = self::signToken($body, $signkey); + if (!$sig2) { + self::debug("Error: validateToken: Could not generate signature for the token."); + return; + } + + + if ($sig == $sig2) { + return $token; + } + + self::debug("Error: validateToken: Signature did not match."); + return; + } + + /* Implementation of the methods needed to perform Windows Live + application verification as well as trusted sign-in. */ + + /** + * Generates an application verifier token. An IP address can + * optionally be included in the token. + */ + public function getAppVerifier($ip=null) + { + $token = 'appid=' . self::getAppId() . '&ts=' . self::getTimestamp(); + $token .= ($ip ? "&ip={$ip}" : ''); + $token .= '&sig=' . self::e64(self::signToken($token)); + return urlencode($token); + } + + /** + * Returns the URL that is required to retrieve the application + * security token. + * + * By default, the application security token is generated for + * the Windows Live site; a specific Site ID can optionally be + * specified in 'siteid'. The IP address can also optionally be + * included in 'ip'. + * + * If 'js' is nil, a JavaScript Output Notation (JSON) response is + * returned in the following format: + * + * {"token":""} + * + * Otherwise, a JavaScript response is returned. It is assumed that + * WLIDResultCallback is a custom function implemented to handle the + * token value: + * + * WLIDResultCallback(""); + */ + public function getAppLoginUrl($siteid=null, $ip=null, $js=null) + { + $url = self::getSecureUrl(); + $url .= 'wapplogin.srf?app=' . self::getAppVerifier($ip); + $url .= '&alg=' . self::getSecurityAlgorithm(); + $url .= ($siteid ? "&id=$siteid" : ''); + $url .= ($js ? '&js=1' : ''); + return $url; + } + + /** + * Retrieves the application security token for application + * verification from the application sign-in URL. + * + * By default, the application security token will be generated for + * the Windows Live site; a specific Site ID can optionally be + * specified in 'siteid'. The IP address can also optionally be + * included in 'ip'. + * + * Implementation note: The application security token is downloaded + * from the application sign-in URL in JSON format: + * + * {"token":""} + * + * Therefore we must extract from the string and return it as + * seen here. + */ + public function getAppSecurityToken($siteid=null, $ip=null) + { + $body = self::fetch(self::getAppLoginUrl($siteid, $ip)); + if (!$body) { + self::debug("Error: getAppSecurityToken: Could not fetch the application security token."); + return; + } + + preg_match('/\{"token":"(.*)"\}/', $body, $matches); + if(count($matches) == 2) { + return $matches[1]; + } + else { + self::debug("Error: getAppSecurityToken: Failed to extract token: $body"); + return; + } + } + + /** + * Returns a string that can be passed to the getTrustedParams + * function as the 'retcode' parameter. If this is specified as the + * 'retcode', the application will be used as return URL after it + * finishes trusted sign-in. + */ + public function getAppRetCode() + { + return 'appid=' . self::getAppId(); + } + + /** + * Returns a table of key-value pairs that must be posted to the + * sign-in URL for trusted sign-in. Use HTTP POST to do this. Be aware + * that the values in the table are neither URL nor HTML escaped and + * may have to be escaped if you are inserting them in code such as + * an HTML form. + * + * The user to be trusted on the local site is passed in as string + * 'user'. + * + * Optionally, 'retcode' specifies the resource to which successful + * sign-in is redirected, such as Windows Live Mail, and is typically + * a string in the format 'id=2000'. If you pass in the value from + * getAppRetCode instead, sign-in will be redirected to the + * application. Otherwise, an HTTP 200 response is returned. + */ + public function getTrustedParams($user, $retcode=null) + { + $token = self::getTrustedToken($user); + if (!$token) { + return; + } + $token = "$tokenuri:WindowsLiveID"; + + $params = array(); + $params['wa'] = self::getSecurityAlgorithm(); + $params['wresult'] = $token; + + if ($retcode) { + $params['wctx'] = $retcode; + } + + return $params; + } + + /** + * Returns the trusted sign-in token in the format that is needed by a + * control doing trusted sign-in. + * + * The user to be trusted on the local site is passed in as string + * 'user'. + */ + public function getTrustedToken($user) + { + if (!$user) { + self::debug('Error: getTrustedToken: Null user specified.'); + return; + } + + $token = "appid=" . self::getAppId() . "&uid=" . urlencode($user) + . "&ts=". self::getTimestamp(); + $token .= "&sig=" . self::e64(self::signToken($token)); + return urlencode($token); + } + + /** + * Returns the trusted sign-in URL to use for Windows Live Login server. + */ + public function getTrustedLoginUrl() + { + return self::getSecureUrl() . 'wlogin.srf'; + } + + /** + * Returns the trusted sign-in URL to use for Windows Live + * Login server. + */ + public function getTrustedLogoutUrl() + { + return self::getSecureUrl() . "logout.srf?appid=" + self::getAppId(); + } + + /* Helper methods */ + + /** + * Function to parse the settings file. + */ + private function parseSettings($settingsFile) + { + $settings = array(); + $doc = new DOMDocument(); + if (!$doc->load($settingsFile)) { + self::fatal("Error: parseSettings: Error while reading $settingsFile"); + } + + $nl = $doc->getElementsByTagName('windowslivelogin'); + if($nl->length != 1) { + self::fatal("error: parseSettings: Failed to parse settings file:" + . $settingsFile); + } + + $topnode = $nl->item(0); + foreach ($topnode->childNodes as $node) { + if ($node->nodeType == XML_ELEMENT_NODE) { + $firstChild = $node->firstChild; + if (!$firstChild) { + self::fatal("error: parseSettings: Failed to parse settings file:" + . $settingsFile); + } + $settings[$node->nodeName] = $firstChild->nodeValue; + } + } + + return $settings; + } + + /** + * Derives the key, given the secret key and prefix as described in the + * Web Authentication SDK documentation. + */ + private function derive($secret, $prefix) + { + if (!$secret || !$prefix) { + self::fatal("Error: derive: secret or prefix is null."); + } + + $keyLen = 16; + $key = $prefix . $secret; + $key = mhash(MHASH_SHA256, $key); + if (!$key || (strlen($key) < $keyLen)) { + self::debug("Error: derive: Unable to derive key."); + return; + } + + return substr($key, 0, $keyLen); + } + + /** + * Parses query string and returns a hash. + * + * If a hash ref is passed in from CGI->Var, it is dereferenced and + * returned. + */ + private function parse($input) + { + if (!$input) { + self::debug("Error: parse: Null input."); + return; + } + + $input = split('&', $input); + $pairs = array(); + + foreach ($input as $pair) { + $kv = split('=', $pair); + if (count($kv) != 2) { + self::debug("Error: parse: Bad input to parse: " . $pair); + return; + } + $pairs[$kv[0]] = $kv[1]; + } + + return $pairs; + } + + /** + * Generates a time stamp suitable for the application verifier + * token. + */ + private function getTimestamp() + { + return time(); + } + + /** + * Base64-encodes and URL-escapes a string. + */ + private function e64($input) + { + if (is_null($input)) { + return; + } + return urlencode(base64_encode($input)); + } + + /** + * URL-unescapes and Base64-decodes a string. + */ + private function u64($input) + { + if(is_null($input)) + return; + return base64_decode(urldecode($input)); + } + + /** + * Fetches the contents given a URL. + */ + private function fetch($url) + { + if (!($handle = fopen($url, "rb"))) { + self::debug("error: fetch: Could not open url: $url"); + return; + } + + if (!($contents = stream_get_contents($handle))) { + self::debug("Error: fetch: Could not read from url: $url"); + } + + fclose($handle); + return $contents; + } +} +?> diff --git a/www/wp-content/plugins/social-connect/media.php b/www/wp-content/plugins/social-connect/media.php new file mode 100755 index 0000000..a8e863a --- /dev/null +++ b/www/wp-content/plugins/social-connect/media.php @@ -0,0 +1,47 @@ +dbVG7wVRUJ4ZXi@?ZDjy9FETVQ zFgfL9Ke+nA~Ys>BZDYUUupTH(XEW}69H?R~7K@e=x2wL04 zSFkaOxCWEBVSnzuV-XXwL3TH{ngjPcoHH}(sB%*PW~#N;br}JZfwWzAYP}xdP;jPh`Bmi==8HAy-H3_5b`iTIA9z6HE56>^5?fM{L zXeI`;B*K@KZLF;p0RV?*4*&orh9(xUm{^005g5R5pID%Y2_*3e*8kvx)B9*LruYhO z`y-+|tp)&KF29(r!t-_cU%gkp8>^6TiQ_Za?^lRPuyt|^0C>7Oj_AQK3p5iYKI145 z(L~TBjFshlDueMo=e-UsEadbVG7wVRUJ4ZXi@?ZDjy9FETVQ zFgf6G0Tmzq7kdsx3_@h(BtvLTYL8Pas}v9{nvJqT(~t^Nzvi-_P| zER`UFP(-}<;K3dwTBQ}+`U7p6wMm+6c6Mi;hbG%>vQ21r7yLqCCvW$CKRfTuu)~N5 zj4=Sf+JcpZUjWPpFCJf= z)Br#Tb+q$P4B5;kY;Ff?T#@7gS-k))q9Jx52K{$t6hH-lbuop3m#k3CtHn(lk=6)= zU|j&90e~a|=NyvAS8}6Zz$hBf(|TPjF_74XsPfVPfTV=5{MB4f>o|V64W|bCaD8O3 zEBHh$!?^I<13#9Q8^*sceshhFCVE_B-#zetc4AlY3wM&PaZL{dUxHfI zEkg=$AJ`Lss|U#6KHz0my)vG?PSx)N?itwn?MCNr&N$a^pImXp6vkX}Psp-gXeDTt z&sBmjny@KAbqPpFke{v4L(TG$_@8D#l0>Oc2o#`MJ{Lf|y#qbH!5#$?P4X?9_BH^B zkpG)UbYCSmmD7=Ci&WG8oBix%%T~%u~{^cThC!_H4S2t&n3r)7~49PMgYVCL{AS- z%`zD|Ndmzh49j9FBq==g?&aip049J97eE-M4dehY04+c`Z{0u=fb|b(*|CUdl@4qG O0000_z#58A&e-L2s#)D2H|hkl@&`@5J|K&cW0cLogcmT)u~-~!Uu1L`M&pg z?|nY+J0c-lTHOSj5axBEB?+Kpg4?%lKuk`Tlks;8C>C-T0-F=OP~!1@1*xUPrD6_6 zTeo>fq5Uk)>nvCZd>>NE)42uB-|T!=cLN;PeYhu$wiqEGsJV0~sFVQnN{wWJL*U^j z_we$?0G>VVr9xgNMR`;^!EfrqMN$i+7&p7S@Sx|q0d7?Hp_R-optZvK)=xwPVmjPC zjuUj)mH|wDuHeK_XJ~eS3*%x~k($1>Ka@O)_(Yu^u0bA03}m#s}1*1@8no!2ITHEBcMkV${h4KY-xh`R&vUT({0YM&@lhf5dbVG7wVRUJ4ZXi@?ZDjy9FETVQ zFgfaHio$&NVcR;JMSnWO?t&2zu!`M@==XtCrbaW$C77HjxM@``}x18S*l(Ws| zuWu-48#iYGP*Pq;xaKI~nj-*IhXu;f(SVXU5^2}BgRmxebfcAqhI$$!0)W}YEEC^N z#%F8*5@}FU5>QSS<(Bvsc-D6wVFr2nI?0u`FxNXO_&B-52; zvmUpQ&Nd&uSeQakAE_wvl(Z3AX3^62VVWkVTMm(58^c-{#WYQFsDD7^=iH1^sus>1Yl4yaF~t%Zx8qbxD$u!N;^TA7kL{ zG`$apnP0NFcdO$cGsqy+UlDpPouaC;oX0QTv6Gzp>7?5B h)cvOnF=ZH{>o<|zluEHsF;oBm002ovPDHLkV1f+#Ofmof literal 0 HcmV?d00001 diff --git a/www/wp-content/plugins/social-connect/media/img/google_32.png b/www/wp-content/plugins/social-connect/media/img/google_32.png new file mode 100755 index 0000000000000000000000000000000000000000..b67a62a2a468bf494901227339ac99c3a120dd79 GIT binary patch literal 1523 zcmVdbVG7wVRUJ4ZXi@?ZDjy9FETVQ zFgfYBO$_EmjR`koa)S3{c$@-n&Y)Ch#s2|akwln`|Ffjd!^r)v{%hk&jWXu7~3 z48;Y~!T|!V7J?o}%)FGWLQ=AdM(q28V6zBxT`2&t0vMW#+plA2vCAIv_mHf%@xoK{ zSh;j{%-qUqFO?TOqsH8R14D~cI#K~mMG0#$0S#ScPOh768_N;W!m;1_==G>PT$0MN z;xsew*r_XA@5!OhGj=N#J#wZ=z|g}OdYs-5w6gv66{I95^4SRojkf~;G`9I@?+&tl zbv6L2mQ3aBkya9H8F9W)7yucmKp0(9WBR&Br;(PLgp`7YR&P}7^u<2<+(D!i6i&-# zMy?(gPuGSJFmyGp7Zzk71xNw98XOU?y4-EXONuhbg=w}RQh{*Hk_imt9c{9zeS|Gp zQSmm1&x~6vN$8p{Cf?wACV_Y}AQP-e8CgG6B)RZU5FxE*+}+=A#xFH_q!36U*!;{AbWa0n$cL`01icQ*=1xKiL4AvxmJZLjFiir6rpEQ(FFL4iaU%pw z$+5G4=UP&fCS0vmtSC<8x$?!-x47ANw0>N8gE}Apil6?*uw^_Dvt)y|Vae8Ua@`3+Lpp>Deb)yr77*l*AEv z_B0y@c5URt11C9qRY6G0*qBj|(U5B~npr~~9NzsrOXe5i8wl~^=_Y=yx=ClRAAr2< zRQByy&Wvf90KEHhIp?>ZAfP3WiK!27!C0<^2l(jCHIywV#6O_0ZTA_z{pku0r`ybN zINiMV=^3sxbRh)T)00^^E500?1O}yeG|$bj@YwQFq!gU1ZlbZpIclEA>*wRItIV00 zU6dOWH%f|!G8%6Ale0~YZ|~@gDY5Mir{o4x_nylU&p%Luqy(Ntwb zo~9~fCArMpnmR|^C;9FS7-RRTp}C8un@*&Jsrgy#duJ`yU@Jja3yRl);&l*owO|dl za(M3+q=Z8!s_E!*#hw9Uh!p3SZ8s8AbCFitsO6ell*3oMD#*{Z1K{-qIDe^;YmK)6 zD49K-Ws7H#o@V3N&$aA6bZ*SjL*(~F$lr~l=1UPFu;^7sQc6Z13HC8RWKXlP?umIk z{>V(0&Yu<)YiM>-ef1XKovfj~%N_G@0Ky)Wf&NZM?brDNAaBttpBsk0BQZ4>VHqhf z6KRGPBINHz2zjux_Rw2`NE@uV^S4|BG1HP{M_O!1Ytn=stg8yT7DQ7#fN`Vy?;|CE zDu4ta9Z1M2-tY<1QUOe!(9`dl6J0yiQ~$#UKp5~w5n#xl)q8BlPy&L8APuhnF9HUj Z{tIR;Z$0OcwZZ@Z002ovPDHLkV1hPK(H#H) literal 0 HcmV?d00001 diff --git a/www/wp-content/plugins/social-connect/media/img/google_small.png b/www/wp-content/plugins/social-connect/media/img/google_small.png new file mode 100755 index 0000000000000000000000000000000000000000..e6907a2ea275365e9791386814023a8dcb3f98bf GIT binary patch literal 797 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 O0000dbVG7wVRUJ4ZXi@?ZDjy9FETVQ zFgfcmkPxlXU zXtB<+gOG(}tgL~v&u}}Jf*d3QNAgIcm1g#v`M#N5Ydju*dU|^5y}Z0A-e8{R>1;N8 zXx-f0{8CGM3m&aCT5D|wL7>vXKqoOZiS5CjYc14LxW zz!a)oK;b^Oh1E3)is_5w5PTI5;?DKHExzyL`#$eJ zerA7v|J8S}TI0jR14=0#A0Nr*^X%^K;<_#(!Ym9i^Z5o?YrQOxN~QF0I8-8nQi?DP z3Bzz}$G^dMcXy;xDedNRxkIgWuix*#={sh#S*?^h{0$N2aLV)6RV)Ai002ovPDHLk FV1lU+C+q+K literal 0 HcmV?d00001 diff --git a/www/wp-content/plugins/social-connect/media/img/openid_32.png b/www/wp-content/plugins/social-connect/media/img/openid_32.png new file mode 100755 index 0000000000000000000000000000000000000000..073c0e6fb403c4ed07712d763138acd136b2c58a GIT binary patch literal 1204 zcmV;l1WWsgP)dbVG7wVRUJ4ZXi@?ZDjy9FETVQ zFgfHNGZ4w7p@ij0J`@J2o7CzQC!S?1i@9Q zFv}@Ya3P4U+z4vp3r3R)(b1?7o41?$+J(uT#3Xj&OAkB{F6Z3yJOAgL=gAf1*~!Vt zdtk=4?RH+lgb?Sz@4daf@0@43AHiU7ANZl8ql2odDufWF-tlC!ZJSIcLnIObI8YR2 zzyUZuK7Mam*1V!90GOtUWmzu@AW0G~mkWSkFo+~cANuwSYkN_;pdh$wyxA^R`8f*<3k3kSZ8JAFM`L3nJv}}6d_H_W zU)lE+O+h(;P$&bH^YioN z0ZK`@y1L5N))oM6w;O=Awl)R^2CyuvXbYyNrwN5Z1Ofq6RmC(-Ha9nml75u}D=RDP z?d>7UG63D(-AqhO(9+U^X`1M|UbF>+gM;|}ekLa;Sz21+^767swUPj~Z5PmOZ*OyW zc<59;H8sW1&=8qShEyu$_&roW(=?*dDC_I%+}_?g@ud_fn1Y82?C$P5m5+^$(cj-+ zkT_?qJc3+&b#*o4!rTF z9w7u>U0wHnl7tX~bUIxgAYYzb^#Gct6-nv%BE^|ZFO($v(%n`c}`|9KE4 zlSu{#2kGqWBoGL2eSHnwPe?c%CL9j)HVa_4{PcW)QW7SUNjx48V`F1vG8xX!&bYa` z;qLAZUDq++&SEzINal?nE0K5}Ks+AD>-82n>bib^>`D^d-Q6gPg3IMX2*F)CjbRuV z@pwha6NyA20PtB=)$eO+Y91vv45Ok%rtrjJN*K SneTxB0000dbVG7wVRUJ4ZXi@?ZDjy9FETVQ zFgfpozInVzolurkvfHew2jZmO$({jX{|c-4w8S(bHyEaDUvAlTI^Xi#eH z#+C4Fy%vQC{4%2L-_VLwSuBLI_{kh0V%w}PYG6bI{X-eaqIfJgTi z(0ICfBH$=D$gMyb23SgO?!>4})zI9Dz4$0M43J@lg%o6p&KIj2A7zFaWLUsX9#tyE z{^iti6t6lBakz-eLg(;=oWPnHBtfD2#-8S4+RIu;?#hk>{6zJtxL;_T*p z1N`ax=D`IGKjQ_zjm^zYXVF}8f~R9H{Qd&S`|7_9^gy2hrSRxiN#?z18Ei0 uxlpZi61%$_r0000~X@ literal 0 HcmV?d00001 diff --git a/www/wp-content/plugins/social-connect/media/img/twitter_32.png b/www/wp-content/plugins/social-connect/media/img/twitter_32.png new file mode 100755 index 0000000000000000000000000000000000000000..38d05450fd8c400d7cb0b6207b4049e4ea46471b GIT binary patch literal 1089 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 O0000dbVG7wVRUJ4ZXi@?ZDjy9FETVQ zFgfMCB3i~sX0b6un;0_uk#zLA)Fu_6vf+AiivEVdOsex9Uens8lL{ z6sVF2&xim3->Ow4lgWQ#f7;l9y!QftB!WUjARh7nJ~%iC zBEsb4Bpz~#M+A}*pEo!0JQl|KCZ2Sq=ff7!B{4P z4@*nf+uQRC9LE6>;o#r^0MP68FgrVou}tQXfIQFNYkqznKW}cZzrT-myN%Z6B~n8} za2y8!VB0p{&CU7yljl7WG#U-W<8e$(Ou)8n*tU&aE{Bzs73}Wr;_B)OtyT*Q3kzs8 z8a@F+p%6zR5iS;s%*?#Av%`r*f=5S3xn8exr_nVGp*EOI0g;ZP{V zFbsoD(`3uC*mYg*bUJLBCa2SBe$e{*I-91+wOWl`*JaDH*fdQx41*QV^B|=}x7$Ub zP{75-1r`?wCS0Qc!Szepze z>-M%!a9ppm)!)y3y3WBsfCHMwnx?U)s%KCXB`Sny3L*H3r>Q7P^cT~kRon5z2?hWF N002ovPDHLkV1k0GPniG! literal 0 HcmV?d00001 diff --git a/www/wp-content/plugins/social-connect/media/img/wordpress_32.png b/www/wp-content/plugins/social-connect/media/img/wordpress_32.png new file mode 100755 index 0000000000000000000000000000000000000000..7aa7ec11bf71c4f0b33ac5ef6a44b0f8ddbfcccb GIT binary patch literal 1740 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 LNkvXXu0mjf^uuSG literal 0 HcmV?d00001 diff --git a/www/wp-content/plugins/social-connect/media/js/connect.js b/www/wp-content/plugins/social-connect/media/js/connect.js new file mode 100755 index 0000000..b566cbc --- /dev/null +++ b/www/wp-content/plugins/social-connect/media/js/connect.js @@ -0,0 +1,143 @@ +jQuery.noConflict(); +(function($) { + $(function() { + // ready to roll + var _social_connect_wordpress_form = $($('.social_connect_wordpress_form')[0]); + _social_connect_wordpress_form.dialog({ autoOpen: false, modal: true, dialogClass: 'social-connect-dialog', resizable: false, maxHeight: 400, width:350, maxWidth: 600 }); + + var _do_google_connect = function() { + var google_auth = $('#social_connect_google_auth'); + var redirect_uri = google_auth.find('input[type=hidden][name=redirect_uri]').val(); + + window.open(redirect_uri,'','scrollbars=no,menubar=no,height=400,width=800,resizable=yes,toolbar=no,status=no'); + }; + + var _do_yahoo_connect = function() { + var yahoo_auth = $('#social_connect_yahoo_auth'); + var redirect_uri = yahoo_auth.find('input[type=hidden][name=redirect_uri]').val(); + + window.open(redirect_uri,'','scrollbars=no,menubar=no,height=400,width=800,resizable=yes,toolbar=no,status=no'); + }; + + var _do_openid_connect = function() { + var openid_auth = $('#social_connect_openid_auth'); + var redirect_uri = openid_auth.find('input[type=hidden][name=redirect_uri]').val(); + + window.open(redirect_uri,'','scrollbars=no,menubar=no,height=400,width=800,resizable=yes,toolbar=no,status=no'); + }; + + var _do_twitter_connect = function() { + var twitter_auth = $('#social_connect_twitter_auth'); + var redirect_uri = twitter_auth.find('input[type=hidden][name=redirect_uri]').val(); + + window.open(redirect_uri,'','scrollbars=no,menubar=no,height=400,width=800,resizable=yes,toolbar=no,status=no'); + }; + + var _do_wordpress_connect = function(e) { + var wordpress_auth = $('#social_connect_wordpress_auth'); + var redirect_uri = wordpress_auth.find('input[type=hidden][name=redirect_uri]').val(); + var context = $(e.target).parents('.social_connect_wordpress_form')[0]; + var blog_name = $('.wordpress_blog_url', context).val(); + var blog_url = "http://" + blog_name + ".wordpress.com"; + redirect_uri = redirect_uri + "?wordpress_blog_url=" + encodeURIComponent(blog_url); + + window.open(redirect_uri,'','scrollbars=yes,menubar=no,height=400,width=800,resizable=yes,toolbar=no,status=no'); + }; + + var _do_facebook_connect = function() { + var facebook_auth = $('#social_connect_facebook_auth'); + var client_id = facebook_auth.find('input[type=hidden][name=client_id]').val(); + var redirect_uri = facebook_auth.find('input[type=hidden][name=redirect_uri]').val(); + + if(client_id == "") { + alert("Social Connect plugin has not been configured for this provider") + } else { + window.open('https://graph.facebook.com/oauth/authorize?client_id=' + client_id + '&redirect_uri=' + redirect_uri + '&scope=email', + '','scrollbars=no,menubar=no,height=400,width=800,resizable=yes,toolbar=no,status=no'); + } + }; + + // Close dialog if open and user clicks anywhere outside of it + function overlay_click_close() { + if (closedialog) { + _social_connect_already_connected_form.dialog('close'); + } + closedialog = 1; + } + + $(".social_connect_login_facebook").click(function() { + _do_facebook_connect(); + }); + + $(".social_connect_login_continue_facebook").click(function() { + _do_facebook_connect(); + }); + + $(".social_connect_login_twitter").click(function() { + _do_twitter_connect(); + }); + + $(".social_connect_login_continue_twitter").click(function() { + _do_twitter_connect(); + }); + + $(".social_connect_login_google").click(function() { + _do_google_connect(); + }); + + $(".social_connect_login_continue_google").click(function() { + _do_google_connect(); + }); + + $(".social_connect_login_yahoo").click(function() { + _do_yahoo_connect(); + }); + $(".social_connect_login_openid").click(function() { + _do_openid_connect(); + }); + + $(".social_connect_login_continue_yahoo").click(function() { + _do_yahoo_connect(); + }); + + $(".social_connect_login_wordpress").click(function() { + _social_connect_wordpress_form.dialog('open'); + }); + + $(".social_connect_wordpress_proceed").click(function(e) { + _do_wordpress_connect(e); + }); + }); +})(jQuery); + + +window.wp_social_connect = function(config) { + jQuery('#loginform').unbind('submit.simplemodal-login'); + + var form_id = '#loginform'; + + if(!jQuery('#loginform').length) { + // if register form exists, just use that + if(jQuery('#registerform').length) { + form_id = '#registerform'; + } else { + // create the login form + var login_uri = jQuery("#social_connect_login_form_uri").val(); + jQuery('body').append("
"); + jQuery('#loginform').append(""); + } + } + + jQuery.each(config, function(key, value) { + jQuery("#" + key).remove(); + jQuery(form_id).append(""); + }); + + if(jQuery("#simplemodal-login-form").length) { + var current_url = window.location.href; + jQuery("#redirect_to").remove(); + jQuery(form_id).append(""); + } + + jQuery(form_id).submit(); +} diff --git a/www/wp-content/plugins/social-connect/openid/connect.php b/www/wp-content/plugins/social-connect/openid/connect.php new file mode 100755 index 0000000..02391e1 --- /dev/null +++ b/www/wp-content/plugins/social-connect/openid/connect.php @@ -0,0 +1,45 @@ +identity = urldecode($_GET['openid_url']); + $openid->required = array('namePerson/first', 'namePerson/last', 'contact/email'); + header('Location: ' . $openid->authUrl()); + } else { + $openid = new LightOpenID; + if($openid->validate()) { + $open_id = $openid->identity; + $attributes = $openid->getAttributes(); + $email = $attributes['contact/email']; + $first_name = $attributes['namePerson/first']; + $last_name = $attributes['namePerson/last']; + $signature = social_connect_generate_signature($open_id); + ?> + + + + + + + + getMessage(); +} +?> diff --git a/www/wp-content/plugins/social-connect/openid/openid.php b/www/wp-content/plugins/social-connect/openid/openid.php new file mode 100755 index 0000000..126896b --- /dev/null +++ b/www/wp-content/plugins/social-connect/openid/openid.php @@ -0,0 +1,706 @@ + +* $openid = new LightOpenID; +* $openid->identity = 'ID supplied by user'; +* header('Location: ' . $openid->authUrl()); +* +* The provider then sends various parameters via GET, one of them is openid_mode. +* Step two is verification: +* +* if ($this->data['openid_mode']) { +* $openid = new LightOpenID; +* echo $openid->validate() ? 'Logged in.' : 'Failed'; +* } +* +* +* Optionally, you can set $returnUrl and $realm (or $trustRoot, which is an alias). +* The default values for those are: +* $openid->realm = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; +* $openid->returnUrl = $openid->realm . $_SERVER['REQUEST_URI']; # without the query part, if present +* If you don't know their meaning, refer to any openid tutorial, or specification. Or just guess. +* +* AX and SREG extensions are supported. +* To use them, specify $openid->required and/or $openid->optional before calling $openid->authUrl(). +* These are arrays, with values being AX schema paths (the 'path' part of the URL). +* For example: +* $openid->required = array('namePerson/friendly', 'contact/email'); +* $openid->optional = array('namePerson/first'); +* If the server supports only SREG or OpenID 1.1, these are automaticaly +* mapped to SREG names, so that user doesn't have to know anything about the server. +* +* To get the values, use $openid->getAttributes(). +* +* +* The library requires PHP >= 5.1.2 with curl or http/https stream wrappers enabled.. +* @author Mewp +* @copyright Copyright (c) 2010, Mewp +* @license http://www.opensource.org/licenses/mit-license.php MIT +*/ +class LightOpenID +{ + public $returnUrl + , $required = array() + , $optional = array(); + private $identity, $claimed_id; + protected $server, $version, $trustRoot, $aliases, $identifier_select = false + , $ax = false, $sreg = false, $data; + static protected $ax_to_sreg = array( + 'namePerson/friendly' => 'nickname', + 'contact/email' => 'email', + 'namePerson' => 'fullname', + 'birthDate' => 'dob', + 'person/gender' => 'gender', + 'contact/postalCode/home' => 'postcode', + 'contact/country/home' => 'country', + 'pref/language' => 'language', + 'pref/timezone' => 'timezone', + ); + + function __construct() + { + $this->trustRoot = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; + $uri = $_SERVER['REQUEST_URI']; + $uri = strpos($uri, '?') ? substr($uri, 0, strpos($uri, '?')) : $uri; + $this->returnUrl = $this->trustRoot . $uri; + + $this->data = $_POST + $_GET; # OPs may send data as POST or GET. + } + + function __set($name, $value) + { + switch ($name) { + case 'identity': + if (strlen($value = trim((String) $value))) { + if (preg_match('#^xri:/*#i', $value, $m)) { + $value = substr($value, strlen($m[0])); + } elseif (!preg_match('/^(?:[=@+\$!\(]|https?:)/i', $value)) { + $value = "http://$value"; + } + if (preg_match('#^https?://[^/]+$#i', $value, $m)) { + $value .= '/'; + } + } + $this->$name = $this->claimed_id = $value; + break; + case 'trustRoot': + case 'realm': + $this->trustRoot = trim($value); + } + } + + function __get($name) + { + switch ($name) { + case 'identity': + # We return claimed_id instead of identity, + # because the developer should see the claimed identifier, + # i.e. what he set as identity, not the op-local identifier (which is what we verify) + return $this->claimed_id; + case 'trustRoot': + case 'realm': + return $this->trustRoot; + } + } + + /** + * Checks if the server specified in the url exists. + * + * @param $url url to check + * @return true, if the server exists; false otherwise + */ + function hostExists($url) + { + if (strpos($url, '/') === false) { + $server = $url; + } else { + $server = @parse_url($url, PHP_URL_HOST); + } + + if (!$server) { + return false; + } + + return !!gethostbynamel($server); + } + + protected function request_curl($url, $method='GET', $params=array()) + { + $params = http_build_query($params, '', '&'); + $curl = curl_init($url . ($method == 'GET' && $params ? '?' . $params : '')); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl, CURLOPT_HEADER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/xrds+xml, */*')); + if ($method == 'POST') { + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $params); + } elseif ($method == 'HEAD') { + curl_setopt($curl, CURLOPT_HEADER, true); + curl_setopt($curl, CURLOPT_NOBODY, true); + } else { + curl_setopt($curl, CURLOPT_HTTPGET, true); + } + $response = curl_exec($curl); + + if($method == 'HEAD') { + $headers = array(); + foreach(explode("\n", $response) as $header) { + $pos = strpos($header,':'); + $name = strtolower(trim(substr($header, 0, $pos))); + $headers[$name] = trim(substr($header, $pos+1)); + } + + # Updating claimed_id in case of redirections. + $effective_url = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL); + if($effective_url != $url) { + $this->claimed_id = $effective_url; + } + + return $headers; + } + + if (curl_errno($curl)) { + throw new ErrorException(curl_error($curl), curl_errno($curl)); + } + + return $response; + } + + protected function request_streams($url, $method='GET', $params=array()) + { + if(!$this->hostExists($url)) { + throw new ErrorException('Invalid request.'); + } + + $params = http_build_query($params, '', '&'); + switch($method) { + case 'GET': + $opts = array( + 'http' => array( + 'method' => 'GET', + 'header' => 'Accept: application/xrds+xml, */*', + 'ignore_errors' => true, + ) + ); + $url = $url . ($params ? '?' . $params : ''); + break; + case 'POST': + $opts = array( + 'http' => array( + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'content' => $params, + 'ignore_errors' => true, + ) + ); + break; + case 'HEAD': + # We want to send a HEAD request, + # but since get_headers doesn't accept $context parameter, + # we have to change the defaults. + $default = stream_context_get_options(stream_context_get_default()); + stream_context_get_default( + array('http' => array( + 'method' => 'HEAD', + 'header' => 'Accept: application/xrds+xml, */*', + 'ignore_errors' => true, + )) + ); + + $url = $url . ($params ? '?' . $params : ''); + $headers_tmp = get_headers ($url); + if(!$headers_tmp) { + return array(); + } + + # Parsing headers. + $headers = array(); + foreach($headers_tmp as $header) { + $pos = strpos($header,':'); + $name = strtolower(trim(substr($header, 0, $pos))); + $headers[$name] = trim(substr($header, $pos+1)); + + # Following possible redirections. The point is just to have + # claimed_id change with them, because get_headers() will + # follow redirections automatically. + # We ignore redirections with relative paths. + # If any known provider uses them, file a bug report. + if($name == 'location') { + if(strpos($headers[$name], 'http') === 0) { + $this->claimed_id = $headers[$name]; + } elseif($headers[$name][0] == '/') { + $parsed_url = parse_url($this->claimed_id); + $this->claimed_id = $parsed_url['scheme'] . '://' + . $parsed_url['host'] + . $headers[$name]; + } + } + } + + # And restore them. + stream_context_get_default($default); + return $headers; + } + $context = stream_context_create ($opts); + + return file_get_contents($url, false, $context); + } + + protected function request($url, $method='GET', $params=array()) + { + if(function_exists('curl_init') && !ini_get('safe_mode')) { + return $this->request_curl($url, $method, $params); + } + return $this->request_streams($url, $method, $params); + } + + protected function build_url($url, $parts) + { + if (isset($url['query'], $parts['query'])) { + $parts['query'] = $url['query'] . '&' . $parts['query']; + } + + $url = $parts + $url; + $url = $url['scheme'] . '://' + . (empty($url['username'])?'' + :(empty($url['password'])? "{$url['username']}@" + :"{$url['username']}:{$url['password']}@")) + . $url['host'] + . (empty($url['port'])?'':":{$url['port']}") + . (empty($url['path'])?'':$url['path']) + . (empty($url['query'])?'':"?{$url['query']}") + . (empty($url['fragment'])?'':":{$url['fragment']}"); + return $url; + } + + /** + * Helper function used to scan for / tags and extract information + * from them + */ + protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName) + { + preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$valueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1); + preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2); + + $result = array_merge($matches1[1], $matches2[1]); + return empty($result)?false:$result[0]; + } + + /** + * Performs Yadis and HTML discovery. Normally not used. + * @param $url Identity URL. + * @return String OP Endpoint (i.e. OpenID provider address). + * @throws ErrorException + */ + function discover($url) + { + if (!$url) throw new ErrorException('No identity supplied.'); + # Use xri.net proxy to resolve i-name identities + if (!preg_match('#^https?:#', $url)) { + $url = "https://xri.net/$url"; + } + + # We save the original url in case of Yadis discovery failure. + # It can happen when we'll be lead to an XRDS document + # which does not have any OpenID2 services. + $originalUrl = $url; + + # A flag to disable yadis discovery in case of failure in headers. + $yadis = true; + + # We'll jump a maximum of 5 times, to avoid endless redirections. + for ($i = 0; $i < 5; $i ++) { + if ($yadis) { + $headers = $this->request($url, 'HEAD'); + + $next = false; + if (isset($headers['x-xrds-location'])) { + $url = $this->build_url(parse_url($url), parse_url(trim($headers['x-xrds-location']))); + $next = true; + } + + if (isset($headers['content-type']) + && strpos($headers['content-type'], 'application/xrds+xml') !== false + ) { + # Found an XRDS document, now let's find the server, and optionally delegate. + $content = $this->request($url, 'GET'); + + preg_match_all('#(.*?)#s', $content, $m); + foreach($m[1] as $content) { + $content = ' ' . $content; # The space is added, so that strpos doesn't return 0. + + # OpenID 2 + $ns = preg_quote('http://specs.openid.net/auth/2.0/'); + if(preg_match('#\s*'.$ns.'(server|signon)\s*#s', $content, $type)) { + if ($type[1] == 'server') $this->identifier_select = true; + + preg_match('#(.*)#', $content, $server); + preg_match('#<(Local|Canonical)ID>(.*)#', $content, $delegate); + if (empty($server)) { + return false; + } + # Does the server advertise support for either AX or SREG? + $this->ax = (bool) strpos($content, 'http://openid.net/srv/ax/1.0'); + $this->sreg = strpos($content, 'http://openid.net/sreg/1.0') + || strpos($content, 'http://openid.net/extensions/sreg/1.1'); + + $server = $server[1]; + if (isset($delegate[2])) $this->identity = trim($delegate[2]); + $this->version = 2; + + $this->server = $server; + return $server; + } + + # OpenID 1.1 + $ns = preg_quote('http://openid.net/signon/1.1'); + if (preg_match('#\s*'.$ns.'\s*#s', $content)) { + + preg_match('#(.*)#', $content, $server); + preg_match('#<.*?Delegate>(.*)#', $content, $delegate); + if (empty($server)) { + return false; + } + # AX can be used only with OpenID 2.0, so checking only SREG + $this->sreg = strpos($content, 'http://openid.net/sreg/1.0') + || strpos($content, 'http://openid.net/extensions/sreg/1.1'); + + $server = $server[1]; + if (isset($delegate[1])) $this->identity = $delegate[1]; + $this->version = 1; + + $this->server = $server; + return $server; + } + } + + $next = true; + $yadis = false; + $url = $originalUrl; + $content = null; + break; + } + if ($next) continue; + + # There are no relevant information in headers, so we search the body. + $content = $this->request($url, 'GET'); + if ($location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'content')) { + $url = $this->build_url(parse_url($url), parse_url($location)); + continue; + } + } + + if (!$content) $content = $this->request($url, 'GET'); + + # At this point, the YADIS Discovery has failed, so we'll switch + # to openid2 HTML discovery, then fallback to openid 1.1 discovery. + $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href'); + $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href'); + $this->version = 2; + + if (!$server) { + # The same with openid 1.1 + $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href'); + $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href'); + $this->version = 1; + } + + if ($server) { + # We found an OpenID2 OP Endpoint + if ($delegate) { + # We have also found an OP-Local ID. + $this->identity = $delegate; + } + $this->server = $server; + return $server; + } + + throw new ErrorException('No servers found!'); + } + throw new ErrorException('Endless redirection!'); + } + + protected function sregParams() + { + $params = array(); + # We always use SREG 1.1, even if the server is advertising only support for 1.0. + # That's because it's fully backwards compatibile with 1.0, and some providers + # advertise 1.0 even if they accept only 1.1. One such provider is myopenid.com + $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1'; + if ($this->required) { + $params['openid.sreg.required'] = array(); + foreach ($this->required as $required) { + if (!isset(self::$ax_to_sreg[$required])) continue; + $params['openid.sreg.required'][] = self::$ax_to_sreg[$required]; + } + $params['openid.sreg.required'] = implode(',', $params['openid.sreg.required']); + } + + if ($this->optional) { + $params['openid.sreg.optional'] = array(); + foreach ($this->optional as $optional) { + if (!isset(self::$ax_to_sreg[$optional])) continue; + $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional]; + } + $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.optional']); + } + return $params; + } + + protected function axParams() + { + $params = array(); + if ($this->required || $this->optional) { + $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0'; + $params['openid.ax.mode'] = 'fetch_request'; + $this->aliases = array(); + $counts = array(); + $required = array(); + $optional = array(); + foreach (array('required','optional') as $type) { + foreach ($this->$type as $alias => $field) { + if (is_int($alias)) $alias = strtr($field, '/', '_'); + $this->aliases[$alias] = 'http://axschema.org/' . $field; + if (empty($counts[$alias])) $counts[$alias] = 0; + $counts[$alias] += 1; + ${$type}[] = $alias; + } + } + foreach ($this->aliases as $alias => $ns) { + $params['openid.ax.type.' . $alias] = $ns; + } + foreach ($counts as $alias => $count) { + if ($count == 1) continue; + $params['openid.ax.count.' . $alias] = $count; + } + + # Don't send empty ax.requied and ax.if_available. + # Google and possibly other providers refuse to support ax when one of these is empty. + if($required) { + $params['openid.ax.required'] = implode(',', $required); + } + if($optional) { + $params['openid.ax.if_available'] = implode(',', $optional); + } + } + return $params; + } + + protected function authUrl_v1() + { + $returnUrl = $this->returnUrl; + # If we have an openid.delegate that is different from our claimed id, + # we need to somehow preserve the claimed id between requests. + # The simplest way is to just send it along with the return_to url. + if($this->identity != $this->claimed_id) { + $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claimed_id=' . $this->claimed_id; + } + + $params = array( + 'openid.return_to' => $returnUrl, + 'openid.mode' => 'checkid_setup', + 'openid.identity' => $this->identity, + 'openid.trust_root' => $this->trustRoot, + ) + $this->sregParams(); + + return $this->build_url(parse_url($this->server) + , array('query' => http_build_query($params, '', '&'))); + } + + protected function authUrl_v2($identifier_select) + { + $params = array( + 'openid.ns' => 'http://specs.openid.net/auth/2.0', + 'openid.mode' => 'checkid_setup', + 'openid.return_to' => $this->returnUrl, + 'openid.realm' => $this->trustRoot, + ); + if ($this->ax) { + $params += $this->axParams(); + } + if ($this->sreg) { + $params += $this->sregParams(); + } + if (!$this->ax && !$this->sreg) { + # If OP doesn't advertise either SREG, nor AX, let's send them both + # in worst case we don't get anything in return. + $params += $this->axParams() + $this->sregParams(); + } + + if ($identifier_select) { + $params['openid.identity'] = $params['openid.claimed_id'] + = 'http://specs.openid.net/auth/2.0/identifier_select'; + } else { + $params['openid.identity'] = $this->identity; + $params['openid.claimed_id'] = $this->claimed_id; + } + + return $this->build_url(parse_url($this->server) + , array('query' => http_build_query($params, '', '&'))); + } + + /** + * Returns authentication url. Usually, you want to redirect your user to it. + * @return String The authentication url. + * @param String $select_identifier Whether to request OP to select identity for an user in OpenID 2. Does not affect OpenID 1. + * @throws ErrorException + */ +function authUrl($identifier_select = null) +{ + if (!$this->server) $this->discover($this->identity); + + if ($this->version == 2) { + if ($identifier_select === null) { + return $this->authUrl_v2($this->identifier_select); + } + return $this->authUrl_v2($identifier_select); + } + return $this->authUrl_v1(); +} + +/** +* Performs OpenID verification with the OP. +* @return Bool Whether the verification was successful. +* @throws ErrorException +*/ +function validate() +{ + $this->claimed_id = isset($this->data['openid_claimed_id'])?$this->data['openid_claimed_id']:$this->data['openid_identity']; + $params = array( + 'openid.assoc_handle' => $this->data['openid_assoc_handle'], + 'openid.signed' => $this->data['openid_signed'], + 'openid.sig' => $this->data['openid_sig'], + ); + + if (isset($this->data['openid_ns'])) { + # We're dealing with an OpenID 2.0 server, so let's set an ns + # Even though we should know location of the endpoint, + # we still need to verify it by discovery, so $server is not set here + $params['openid.ns'] = 'http://specs.openid.net/auth/2.0'; + } elseif(isset($this->data['openid_claimed_id'])) { + # If it's an OpenID 1 provider, and we've got claimed_id, + # we have to append it to the returnUrl, like authUrl_v1 does. + $this->returnUrl .= (strpos($this->returnUrl, '?') ? '&' : '?') + . 'openid.claimed_id=' . $this->claimed_id; + } + + if ($this->data['openid_return_to'] != $this->returnUrl) { + # The return_to url must match the url of current request. + # I'm assuing that noone will set the returnUrl to something that doesn't make sense. + return false; + } + + $server = $this->discover($this->data['openid_identity']); + + foreach (explode(',', $this->data['openid_signed']) as $item) { + # Checking whether magic_quotes_gpc is turned on, because + # the function may fail if it is. For example, when fetching + # AX namePerson, it might containg an apostrophe, which will be escaped. + # In such case, validation would fail, since we'd send different data than OP + # wants to verify. stripslashes() should solve that problem, but we can't + # use it when magic_quotes is off. + $value = $this->data['openid_' . str_replace('.','_',$item)]; + $params['openid.' . $item] = get_magic_quotes_gpc() ? stripslashes($value) : $value; + + } + + $params['openid.mode'] = 'check_authentication'; + + $response = $this->request($server, 'POST', $params); + + return preg_match('/is_valid\s*:\s*true/i', $response); + } + + protected function getAxAttributes() + { + $alias = null; + if (isset($this->data['openid_ns_ax']) + && $this->data['openid_ns_ax'] != 'http://openid.net/srv/ax/1.0' + ) { # It's the most likely case, so we'll check it before + $alias = 'ax'; + } else { + # 'ax' prefix is either undefined, or points to another extension, + # so we search for another prefix + foreach ($this->data as $key => $val) { + if (substr($key, 0, strlen('openid_ns_')) == 'openid_ns_' + && $val == 'http://openid.net/srv/ax/1.0' + ) { + $alias = substr($key, strlen('openid_ns_')); + break; + } + } + } + if (!$alias) { + # An alias for AX schema has not been found, + # so there is no AX data in the OP's response + return array(); + } + + $attributes = array(); + foreach ($this->data as $key => $value) { + $keyMatch = 'openid_' . $alias . '_value_'; + if (substr($key, 0, strlen($keyMatch)) != $keyMatch) { + continue; + } + $key = substr($key, strlen($keyMatch)); + if (!isset($this->data['openid_' . $alias . '_type_' . $key])) { + # OP is breaking the spec by returning a field without + # associated ns. This shouldn't happen, but it's better + # to check, than cause an E_NOTICE. + continue; + } + $key = substr($this->data['openid_' . $alias . '_type_' . $key], + strlen('http://axschema.org/')); + $attributes[$key] = $value; + } + return $attributes; +} + +protected function getSregAttributes() +{ + $attributes = array(); + $sreg_to_ax = array_flip(self::$ax_to_sreg); + foreach ($this->data as $key => $value) { + $keyMatch = 'openid_sreg_'; + if (substr($key, 0, strlen($keyMatch)) != $keyMatch) { + continue; + } + $key = substr($key, strlen($keyMatch)); + if (!isset($sreg_to_ax[$key])) { + # The field name isn't part of the SREG spec, so we ignore it. + continue; + } + $attributes[$sreg_to_ax[$key]] = $value; + } + return $attributes; +} + +/** +* Gets AX/SREG attributes provided by OP. should be used only after successful validaton. +* Note that it does not guarantee that any of the required/optional parameters will be present, +* or that there will be no other attributes besides those specified. +* In other words. OP may provide whatever information it wants to. +* * SREG names will be mapped to AX names. +* * @return Array Array of attributes with keys being the AX schema names, e.g. 'contact/email' +* @see http://www.axschema.org/types/ +*/ +function getAttributes() +{ + if (isset($this->data['openid_ns']) + && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0' + ) { # OpenID 2.0 + # We search for both AX and SREG attributes, with AX taking precedence. + return $this->getAxAttributes() + $this->getSregAttributes(); + } + return $this->getSregAttributes(); +} +} diff --git a/www/wp-content/plugins/social-connect/readme.txt b/www/wp-content/plugins/social-connect/readme.txt new file mode 100755 index 0000000..dd48846 --- /dev/null +++ b/www/wp-content/plugins/social-connect/readme.txt @@ -0,0 +1,161 @@ +=== Social Connect === +Contributors: thenbrent +Tags: facebook, wordpress.com, twitter, google, yahoo, social, login, register +Requires at least: 3.0 +Tested up to: 3.2.1 +Stable tag: 0.9 + +Allow your visitors to comment, login and register with their Twitter, Facebook, Google, Yahoo or WordPress.com account. + +== Description == + +Social Connect adds social login buttons on the login, register and comment forms of your WordPress site. + +The buttons offer login and registration using a Twitter, Facebook, Google, Yahoo or WordPress.com account. + +It makes it super easy for new members to register with your site and existing members to login. + += Props = + +Special thanks to: + +* [markusdrake](http://wordpress.org/support/profile/markusdrake) for patches and helping in the support forums; +* [L D](http://wordpress.org/support/profile/enochfung) for patches and helping in the support forums; +* [Geodanny](http://wordpress.org/support/profile/geodanny) for helping in the support forums; and +* [Wirone](http://blog.wirone.info/) for polish translation and patches. + +And everyone else in the forums sharing the fixes they find and answering each others questions. + += Contribute = + +Social Connect is rapidly growing in popularity and help with the growing pains is appreciated. + +If you're a developer, you can contribute fixes & optimisations via [Social Connect on GitHub](https://github.com/thenbrent/social-connect). + +Everyone can help out by answering questions in the [Support Forums](http://wordpress.org/tags/social-connect?forum_id=10#postform). + + +== Installation == + +1. Upload everything into the "/wp-content/plugins/" directory of your WordPress site. +2. Activate in the "Plugins" admin panel. +3. Visit the "Settings | Social Connect" administration page to configure social media providers. + +== Frequently Asked Questions == + += Does Social Connect work with WordPress Multisite? = + +Yes. + += Does Social Connect work with the Theme My Login plugin? = + +Yes. + += Can visitors connect with Social Connect to make a comment? = + +Yes. + += Do I need to add template tags to my theme? = + +Social Connect attempts to work with the default WordPress comment, login and registration forms. + +If you want to add the social connect login or registration forms to another location in your theme, you can insert the following code in that location: + +`` + += What do I do if the Rewrite Diagnostics fail? = + +If you get a 403 and 404 on the Rewrite Diagnostics test, please request your hosting provider whitelist your domain on mod_security. This problem has been encountered with **Host Gator* and **GoDaddy**. + +For more information, see [Geodanny's](http://wordpress.org/support/profile/geodanny) kind responses in the forums to similar issues [here](http://wordpress.org/support/topic/plugin-social-connect-url-rewriting-and-query-string-parameter-passing) and [here](http://wordpress.org/support/topic/plugin-social-connect-url-rewrite). + += Where can I report bugs & get support? = + +First, a few caveats on support. + +This is free software. Please be patient. I attempt to answer all questions, just not on the same day or even week. Polite and descriptive questions will always be given priority. + +Please search the support forums before asking a question - duplicate questions will not receive a reply. + +With those caveats in mind, ask questions in the [Support Forums](http://wordpress.org/tags/social-connect?forum_id=10#postform). + +To help me diagnose the issue, please include the following information in your post on the [Forums](http://wordpress.org/tags/social-connect?forum_id=10#postform): + +* what specifically is broken in Social Connect (eg. the buttons don't show up or it doesn't redirect back form Google) +* what you did just before Social Connect stopped working (eg. activated, enabled all OpenID providers, clicked the Google login button) +* version of the plugin +* version of WordPress +* list of other plugins installed +* error messages you receive (if any) + += Why doesn't Social Connect Work? = + +Please make sure you are running the latest version of Social Connect and the latest version of WordPress. + +If you have White Label CMS installed, the javascript it adds to your login page breaks all other plugins which run javascript on the login form. + +For a quick fix and for more information see this [forum topic](http://wordpress.org/support/topic/social-connect-does-not-work-at-all?replies=7#post-2029255). + +If you don't have White Label CMS installed, please double check your settings then post a question in the [Support Forums](http://wordpress.org/tags/social-connect?forum_id=10#postform). + +== Screenshots == + +1. **Login** - on the login and registration form, buttons for 3rd party services are provided. +2. **Comment** - buttons for 3rd party services are also provided on the comment form. + +== Changelog == + += 0.9 = +* Setting CURLOPT_SSL_VERIFYPEER to false + += 0.8 = +* Moving comments icons to top of comment form (using `comment_form_top` hook instead of `comment_form` hook) +* No longer relying on `file_get_contents()` function (using custom `sc_curl_get_contents()` function) +* Removing "Not You?" double-dialogue. +* Adding `social_connect_form` action to replace template tag with `do_action( 'social_connect_form' )`. + += 0.7 = +* Social Connect widget can now be customised +* l10n implemented +* Polish translation. + += 0.6 = +* Fixing 'email_exists' bug + += 0.5 = +* Removing Windows Live due to broken implementation +* Fixing IE7 Bug reported here: http://wordpress.org/support/topic/plugin-social-connect-social-connect-fails-on-ie7?replies=9 +* Returning to a single admin page as diagnostics is smaller without Windows Live + += 0.4 = +* Removing generic OpenID for security concerns: http://wordpress.org/support/topic/545420 +* Only calling deprecated registration.php file if WP < 3.1 http://wordpress.org/support/topic/540156 + += 0.3 = +* Social Connect moved to it's own top level menu in wp-admin. +* Enable/disable integration with each social provider. +* Simplified setup for Windows Live. +* Introduced diagnostics to check for required cryptographic extensions and server rewrite rules. + += 0.2 = +* Fix for directory name + += 0.1 = +* Initial beta release. + +== Upgrade Notice == + += 0.9 = +* Upgrade to fix Facebook connect SSL bug effecting some servers. + += 0.8 = +* Upgrade to fix bugs affecting Facebook connect on certain servers. + += 0.7 = +* Upgrade to be able to customise Social Connect widget & use in Polish. + += 0.6 = +* Important Upgrade: If you are running WordPress 3.0, you must upgrade. For versions 3.1 and above, this is an optional upgrade. + += 0.5 = +Important upgrade to fix a bug in versions of Internet Explorer prior to version 8. diff --git a/www/wp-content/plugins/social-connect/screenshot-1.png b/www/wp-content/plugins/social-connect/screenshot-1.png new file mode 100755 index 0000000000000000000000000000000000000000..78147533fed45ad0b6e4f22e9e8161d9a08ce936 GIT binary patch literal 26656 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 Rg+~%1yq8gimP;A>{~sC374854 literal 0 HcmV?d00001 diff --git a/www/wp-content/plugins/social-connect/screenshot-2.png b/www/wp-content/plugins/social-connect/screenshot-2.png new file mode 100755 index 0000000000000000000000000000000000000000..c5e16fe504de37851c02767e7ea3712033245ad2 GIT binary patch literal 32249 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͗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 your WordPress installation, it's worth the effort.
Return to Plugins Admin page »", 'social_connect'), admin_url( 'plugins.php' ) ), 'social-connect' ); + elseif ( !function_exists( 'curl_version' ) ) + wp_die( sprintf( __( "Sorry, but you can not run Social Connect. It requires the PHP libcurl extension be installed. Please contact your web host and request libcurl be installed.
Return to Plugins Admin page »", 'social_connect'), admin_url( 'plugins.php' ) ), 'social-connect' ); + elseif ( !function_exists( 'hash' ) ) + wp_die( sprintf( __( "Sorry, but you can not run Social Connect. It requires the PHP Hash Engine. Please contact your web host and request Hash engine be installed.
Return to Plugins Admin page »", 'social_connect'), admin_url( 'plugins.php' ) ), 'social-connect' ); + else + wp_die( sprintf( __( "Sorry, but you can not run Social Connect. It requires PHP 5.1.2 or newer. Please contact your web host and request they migrate your PHP installation to run Social Connect.
Return to Plugins Admin page »", 'social_connect'), admin_url( 'plugins.php' ) ), 'social-connect' ); + } + do_action( 'sc_activation' ); +} +register_activation_hook( __FILE__, 'sc_activate' ); + + +/** + * Registration.php is deprecated since version 3.1 with no alternative available. + * registration.php functions moved to user.php, everything is now included by default + * This file only need to be included for versions before 3.1. + */ +if ( !function_exists( 'email_exists' ) ) + require_once( ABSPATH . WPINC . '/registration.php' ); + +/** + * Internationalization of the plugin + **/ +function sc_social_connect_l10n() { + $plugin_dir = basename( dirname( __FILE__ ) ); + load_plugin_textdomain( 'social_connect', null, "$plugin_dir/languages" ); +} +add_action( 'init', 'sc_social_connect_l10n', -1000 ); + +require_once( dirname( __FILE__ ) . '/constants.php' ); +require_once( dirname( __FILE__ ) . '/utils.php' ); +require_once( dirname( __FILE__ ) . '/media.php' ); +require_once( dirname( __FILE__ ) . '/admin.php' ); +require_once( dirname( __FILE__ ) . '/ui.php' ); + + +function sc_social_connect_process_login( $is_ajax = false ){ + if ( isset( $_REQUEST[ 'redirect_to' ] ) && $_REQUEST[ 'redirect_to' ] != '' ) { + $redirect_to = $_REQUEST[ 'redirect_to' ]; + // Redirect to https if user wants ssl + if ( isset( $secure_cookie ) && $secure_cookie && false !== strpos( $redirect_to, 'wp-admin') ) + $redirect_to = preg_replace( '|^http://|', 'https://', $redirect_to ); + } else { + $redirect_to = admin_url(); + } + $redirect_to = apply_filters( 'social_connect_redirect_to', $redirect_to ); + + $social_connect_provider = $_REQUEST[ 'social_connect_provider' ]; + $sc_provider_identity_key = 'social_connect_' . $social_connect_provider . '_id'; + $sc_provided_signature = $_REQUEST[ 'social_connect_signature' ]; + + switch( $social_connect_provider ) { + case 'facebook': + social_connect_verify_signature( $_REQUEST[ 'social_connect_access_token' ], $sc_provided_signature, $redirect_to ); + $fb_json = json_decode( sc_curl_get_contents("https://graph.facebook.com/me?access_token=" . $_REQUEST[ 'social_connect_access_token' ]) ); + $sc_provider_identity = $fb_json->{ 'id' }; + $sc_email = $fb_json->{ 'email' }; + $sc_first_name = $fb_json->{ 'first_name' }; + $sc_last_name = $fb_json->{ 'last_name' }; + $sc_profile_url = $fb_json->{ 'link' }; + $sc_name = $sc_first_name . ' ' . $sc_last_name; + $user_login = strtolower( $sc_first_name.$sc_last_name ); + break; + + case 'twitter': + $sc_provider_identity = $_REQUEST[ 'social_connect_twitter_identity' ]; + social_connect_verify_signature( $sc_provider_identity, $sc_provided_signature, $redirect_to ); + $sc_name = $_REQUEST[ 'social_connect_name' ]; + $names = explode(" ", $sc_name ); + $sc_first_name = $names[0]; + $sc_last_name = $names[1]; + $sc_screen_name = $_REQUEST[ 'social_connect_screen_name' ]; + $sc_profile_url = ''; + // Get host name from URL + $site_url = parse_url( site_url() ); + $sc_email = 'tw_' . md5( $sc_provider_identity ) . '@' . $site_url['host']; + $user_login = $sc_screen_name; + break; + + case 'google': + $sc_provider_identity = $_REQUEST[ 'social_connect_openid_identity' ]; + social_connect_verify_signature( $sc_provider_identity, $sc_provided_signature, $redirect_to ); + $sc_email = $_REQUEST[ 'social_connect_email' ]; + $sc_first_name = $_REQUEST[ 'social_connect_first_name' ]; + $sc_last_name = $_REQUEST[ 'social_connect_last_name' ]; + $sc_profile_url = ''; + $sc_name = $sc_first_name . ' ' . $sc_last_name; + $user_login = strtolower( $sc_first_name.$sc_last_name ); + break; + + case 'yahoo': + $sc_provider_identity = $_REQUEST[ 'social_connect_openid_identity' ]; + social_connect_verify_signature( $sc_provider_identity, $sc_provided_signature, $redirect_to ); + $sc_email = $_REQUEST[ 'social_connect_email' ]; + $sc_name = $_REQUEST[ 'social_connect_name' ]; + $sc_username = $_REQUEST[ 'social_connect_username' ]; + $sc_profile_url = ''; + if ( $sc_name == '') { + if ( $sc_username == '') { + $names = explode("@", $sc_email ); + $sc_name = $names[0]; + $sc_first_name = $sc_name; + $sc_last_name = ''; + } else { + $names = explode(" ", $sc_username ); + $sc_first_name = $names[0]; + $sc_last_name = $names[1]; + } + } else { + $names = explode(" ", $sc_name ); + $sc_first_name = $names[0]; + $sc_last_name = $names[1]; + } + $user_login = strtolower( $sc_first_name.$sc_last_name ); + break; + + case 'wordpress': + $sc_provider_identity = $_REQUEST[ 'social_connect_openid_identity' ]; + social_connect_verify_signature( $sc_provider_identity, $sc_provided_signature, $redirect_to ); + $sc_email = $_REQUEST[ 'social_connect_email' ]; + $sc_name = $_REQUEST[ 'social_connect_name' ]; + $sc_profile_url = ''; + if ( trim( $sc_name ) == '') { + $names = explode("@", $sc_email ); + $sc_name = $names[0]; + $sc_first_name = $sc_name; + $sc_last_name = ''; + } else { + $names = explode(" ", $sc_name ); + $sc_first_name = $names[0]; + $sc_last_name = $names[1]; + } + $user_login = strtolower( $sc_first_name.$sc_last_name ); + break; + } + + // Cookies used to display welcome message if already signed in recently using some provider + setcookie("social_connect_current_provider", $social_connect_provider, time()+3600, SITECOOKIEPATH, COOKIE_DOMAIN, false, true ); + + // Get user by meta + $user_id = social_connect_get_user_by_meta( $sc_provider_identity_key, $sc_provider_identity ); + if ( $user_id ) { + $user_data = get_userdata( $user_id ); + $user_login = $user_data->user_login; + } elseif ( $user_id = email_exists( $sc_email ) ) { // User not found by provider identity, check by email + update_user_meta( $user_id, $sc_provider_identity_key, $sc_provider_identity ); + + $user_data = get_userdata( $user_id ); + $user_login = $user_data->user_login; + + } else { // Create new user and associate provider identity + if ( username_exists( $user_login ) ) + $user_login = apply_filters( 'social_connect_username_exists', strtolower("sc_". md5( $social_connect_provider . $sc_provider_identity ) ) ); + + $userdata = array( 'user_login' => $user_login, 'user_email' => $sc_email, 'first_name' => $sc_first_name, 'last_name' => $sc_last_name, 'user_url' => $sc_profile_url, 'user_pass' => wp_generate_password() ); + + // Create a new user + $user_id = wp_insert_user( $userdata ); + + if ( $user_id && is_integer( $user_id ) ) + update_user_meta( $user_id, $sc_provider_identity_key, $sc_provider_identity ); + } + + wp_set_auth_cookie( $user_id ); + + do_action( 'social_connect_login', $user_login ); + + if ( $is_ajax ) + echo '{"redirect":"' . $redirect_to . '"}'; + else + wp_safe_redirect( $redirect_to ); + exit(); +} +// Hook to 'login_form_' . $action +add_action( 'login_form_social_connect', 'sc_social_connect_process_login'); + +// Handle calls from plugins that use an Ajax for login +function sc_ajax_login(){ + if ( isset( $_POST[ 'login_submit' ] ) && $_POST[ 'login_submit' ] == 'ajax' && // Plugins will need to pass this param + isset( $_POST[ 'action' ] ) && $_POST[ 'action' ] == 'social_connect' ) + sc_social_connect_process_login( true ); +} +add_action( 'init', 'sc_ajax_login'); diff --git a/www/wp-content/plugins/social-connect/twitter/EpiCurl.php b/www/wp-content/plugins/social-connect/twitter/EpiCurl.php new file mode 100755 index 0000000..8cf18ea --- /dev/null +++ b/www/wp-content/plugins/social-connect/twitter/EpiCurl.php @@ -0,0 +1,128 @@ +mc = curl_multi_init(); + $this->properties = array( + 'code' => CURLINFO_HTTP_CODE, + 'time' => CURLINFO_TOTAL_TIME, + 'length'=> CURLINFO_CONTENT_LENGTH_DOWNLOAD, + 'type' => CURLINFO_CONTENT_TYPE + ); + } + + public function addCurl($ch) + { + $key = (string)$ch; + $this->requests[$key] = $ch; + + $res = curl_multi_add_handle($this->mc, $ch); + + // (1) + if($res === CURLM_OK || $res === CURLM_CALL_MULTI_PERFORM) + { + do { + $mrc = curl_multi_exec($this->mc, $active); + } while ($mrc === CURLM_CALL_MULTI_PERFORM); + + return new EpiCurlManager($key); + } + else + { + return $res; + } + } + + public function getResult($key = null) + { + if($key != null) + { + if(isset($this->responses[$key])) + { + return $this->responses[$key]; + } + + $running = null; + do + { + $resp = curl_multi_exec($this->mc, $runningCurrent); + if($running !== null && $runningCurrent != $running) + { + $this->storeResponses($key); + if(isset($this->responses[$key])) + { + return $this->responses[$key]; + } + } + $running = $runningCurrent; + }while($runningCurrent > 0); + } + + return false; + } + + private function storeResponses() + { + while($done = curl_multi_info_read($this->mc)) + { + $key = (string)$done['handle']; + $this->responses[$key]['data'] = curl_multi_getcontent($done['handle']); + foreach($this->properties as $name => $const) + { + $this->responses[$key][$name] = curl_getinfo($done['handle'], $const); + curl_multi_remove_handle($this->mc, $done['handle']); + } + } + } + + static function getInstance() + { + if(self::$inst == null) + { + self::$singleton = 1; + self::$inst = new EpiCurl(); + } + + return self::$inst; + } +} + +class EpiCurlManager +{ + private $key; + private $epiCurl; + + function __construct($key) + { + $this->key = $key; + $this->epiCurl = EpiCurl::getInstance(); + } + + function __get($name) + { + $responses = $this->epiCurl->getResult($this->key); + return $responses[$name]; + } +} + +/* + * Credits: + * - (1) Alistair pointed out that curl_multi_add_handle can return CURLM_CALL_MULTI_PERFORM on success. + */ +?> diff --git a/www/wp-content/plugins/social-connect/twitter/EpiOAuth.php b/www/wp-content/plugins/social-connect/twitter/EpiOAuth.php new file mode 100755 index 0000000..86fd329 --- /dev/null +++ b/www/wp-content/plugins/social-connect/twitter/EpiOAuth.php @@ -0,0 +1,258 @@ +httpRequest('GET', $this->accessTokenUrl); + return new EpiOAuthResponse($resp); + } + + public function getAuthenticateUrl() + { + $token = $this->getRequestToken(); + return $this->authenticateUrl . '?oauth_token=' . $token->oauth_token; + } + + public function getAuthorizationUrl() + { + $token = $this->getRequestToken(); + return $this->authorizeUrl . '?oauth_token=' . $token->oauth_token; + } + + public function getRequestToken() + { + $resp = $this->httpRequest('GET', $this->requestTokenUrl); + return new EpiOAuthResponse($resp); + } + + public function httpRequest($method = null, $url = null, $params = null) + { + if(empty($method) || empty($url)) + return false; + + if(empty($params['oauth_signature'])) + $params = $this->prepareParameters($method, $url, $params); + + switch($method) + { + case 'GET': + return $this->httpGet($url, $params); + break; + case 'POST': + return $this->httpPost($url, $params); + break; + } + } + + public function setToken($token = null, $secret = null) + { + $params = func_get_args(); + $this->token = $token; + $this->tokenSecret = $secret; + } + + protected function encode_rfc3986($string) + { + return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode(($string)))); + } + + protected function addOAuthHeaders(&$ch, $url, $oauthHeaders) + { + $_h = array('Expect:'); + $urlParts = parse_url($url); + $oauth = 'Authorization: OAuth realm="' . $urlParts['path'] . '",'; + foreach($oauthHeaders as $name => $value) + { + $oauth .= "{$name}=\"{$value}\","; + } + $_h[] = substr($oauth, 0, -1); + + curl_setopt($ch, CURLOPT_HTTPHEADER, $_h); + } + + protected function generateNonce() + { + if(isset($this->nonce)) // for unit testing + return $this->nonce; + + return md5(uniqid(rand(), true)); + } + + protected function generateSignature($method = null, $url = null, $params = null) + { + if(empty($method) || empty($url)) + return false; + + + // concatenating + $concatenatedParams = ''; + foreach($params as $k => $v) + { + $v = $this->encode_rfc3986($v); + $concatenatedParams .= "{$k}={$v}&"; + } + $concatenatedParams = $this->encode_rfc3986(substr($concatenatedParams, 0, -1)); + + // normalize url + $normalizedUrl = $this->encode_rfc3986($this->normalizeUrl($url)); + $method = $this->encode_rfc3986($method); // don't need this but why not? + + $signatureBaseString = "{$method}&{$normalizedUrl}&{$concatenatedParams}"; + return $this->signString($signatureBaseString); + } + + protected function httpGet($url, $params = null) + { + if(count($params['request']) > 0) + { + $url .= '?'; + foreach($params['request'] as $k => $v) + { + $url .= "{$k}={$v}&"; + } + $url = substr($url, 0, -1); + } + $ch = curl_init($url); + $this->addOAuthHeaders($ch, $url, $params['oauth']); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $resp = $this->curl->addCurl($ch); + + return $resp; + } + + protected function httpPost($url, $params = null) + { + $ch = curl_init($url); + $this->addOAuthHeaders($ch, $url, $params['oauth']); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params['request'])); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $resp = $this->curl->addCurl($ch); + return $resp; + } + + protected function normalizeUrl($url = null) + { + $urlParts = parse_url($url); + $scheme = strtolower($urlParts['scheme']); + $host = strtolower($urlParts['host']); + $port = intval($urlParts['port']); + + $retval = "{$scheme}://{$host}"; + if($port > 0 && ($scheme === 'http' && $port !== 80) || ($scheme === 'https' && $port !== 443)) + { + $retval .= ":{$port}"; + } + $retval .= $urlParts['path']; + if(!empty($urlParts['query'])) + { + $retval .= "?{$urlParts['query']}"; + } + + return $retval; + } + + protected function prepareParameters($method = null, $url = null, $params = null) + { + if(empty($method) || empty($url)) + return false; + + $oauth['oauth_consumer_key'] = $this->consumerKey; + $oauth['oauth_token'] = $this->token; + $oauth['oauth_nonce'] = $this->generateNonce(); + $oauth['oauth_timestamp'] = !isset($this->timestamp) ? time() : $this->timestamp; // for unit test + $oauth['oauth_signature_method'] = $this->signatureMethod; + $oauth['oauth_version'] = $this->version; + + // encoding + array_walk($oauth, array($this, 'encode_rfc3986')); + if(is_array($params)) + array_walk($params, array($this, 'encode_rfc3986')); + $encodedParams = array_merge($oauth, (array)$params); + + // sorting + ksort($encodedParams); + + // signing + $oauth['oauth_signature'] = $this->encode_rfc3986($this->generateSignature($method, $url, $encodedParams)); + return array('request' => $params, 'oauth' => $oauth); + } + + protected function signString($string = null) + { + $retval = false; + switch($this->signatureMethod) + { + case 'HMAC-SHA1': + $key = $this->encode_rfc3986($this->consumerSecret) . '&' . $this->encode_rfc3986($this->tokenSecret); + $retval = base64_encode(hash_hmac('sha1', $string, $key, true)); + break; + } + + return $retval; + } + + public function __construct($consumerKey, $consumerSecret, $signatureMethod='HMAC-SHA1') + { + $this->consumerKey = $consumerKey; + $this->consumerSecret = $consumerSecret; + $this->signatureMethod = $signatureMethod; + $this->curl = EpiCurl::getInstance(); + } +} + +class EpiOAuthResponse +{ + private $__resp; + + public function __construct($resp) + { + $this->__resp = $resp; + } + + public function __get($name) + { + if($this->__resp->code != 200) + EpiOAuthException::raise($this->__resp->data, $this->__resp->code); + + parse_str($this->__resp->data, $result); + foreach($result as $k => $v) + { + $this->$k = $v; + } + + return $result[$name]; + } +} + +class EpiOAuthException extends Exception +{ + public static function raise($message, $code) + { + switch($code) + { + case 400: + throw new EpiOAuthBadRequestException($message, $code); + case 401: + throw new EpiOAuthUnauthorizedException($message, $code); + default: + throw new EpiOAuthException($message, $code); + } + } +} + + +class EpiOAuthBadRequestException extends EpiOAuthException{} +class EpiOAuthUnauthorizedException extends EpiOAuthException{} diff --git a/www/wp-content/plugins/social-connect/twitter/EpiTwitter.php b/www/wp-content/plugins/social-connect/twitter/EpiTwitter.php new file mode 100755 index 0000000..ef7669f --- /dev/null +++ b/www/wp-content/plugins/social-connect/twitter/EpiTwitter.php @@ -0,0 +1,118 @@ + + */ +class EpiTwitter extends EpiOAuth +{ + const EPITWITTER_SIGNATURE_METHOD = 'HMAC-SHA1'; + protected $requestTokenUrl= 'http://twitter.com/oauth/request_token'; + protected $accessTokenUrl = 'http://twitter.com/oauth/access_token'; + protected $authorizeUrl = 'http://twitter.com/oauth/authorize'; + protected $authenticateUrl= 'http://twitter.com/oauth/authenticate'; + protected $apiUrl = 'http://twitter.com'; + protected $searchUrl = 'http://search.twitter.com'; + + public function __call($name, $params = null) + { + $parts = explode('_', $name); + $method = strtoupper(array_shift($parts)); + $parts = implode('_', $parts); + $path = '/' . preg_replace('/[A-Z]|[0-9]+/e', "'/'.strtolower('\\0')", $parts) . '.json'; + if(!empty($params)) + $args = array_shift($params); + + // intercept calls to the search api + if(preg_match('/^(search|trends)/', $parts)) + { + $query = isset($args) ? http_build_query($args) : ''; + $url = "{$this->searchUrl}{$path}?{$query}"; + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + return new EpiTwitterJson(EpiCurl::getInstance()->addCurl($ch)); + } + + return new EpiTwitterJson(call_user_func(array($this, 'httpRequest'), $method, "{$this->apiUrl}{$path}", $args)); + } + + public function __construct($consumerKey = null, $consumerSecret = null, $oauthToken = null, $oauthTokenSecret = null) + { + parent::__construct($consumerKey, $consumerSecret, self::EPITWITTER_SIGNATURE_METHOD); + $this->setToken($oauthToken, $oauthTokenSecret); + } +} + +class EpiTwitterJson implements ArrayAccess, Countable, IteratorAggregate +{ + private $__resp; + public function __construct($response) + { + $this->__resp = $response; + } + + // Implementation of the IteratorAggregate::getIterator() to support foreach ($this as $...) + public function getIterator () + { + return new ArrayIterator($this->__obj); + } + + // Implementation of Countable::count() to support count($this) + public function count () + { + return count($this->__obj); + } + + // Next four functions are to support ArrayAccess interface + // 1 + public function offsetSet($offset, $value) + { + $this->response[$offset] = $value; + } + + // 2 + public function offsetExists($offset) + { + return isset($this->response[$offset]); + } + + // 3 + public function offsetUnset($offset) + { + unset($this->response[$offset]); + } + + // 4 + public function offsetGet($offset) + { + return isset($this->response[$offset]) ? $this->response[$offset] : null; + } + + public function __get($name) + { + if($this->__resp->code != 200) + EpiOAuthException::raise($this->__resp->data, $this->__resp->code); + + $this->responseText = $this->__resp->data; + $this->response = json_decode($this->responseText, 1); + $this->__obj = json_decode($this->responseText); + foreach($this->__obj as $k => $v) + { + $this->$k = $v; + } + + return $this->$name; + } + + public function __isset($name) + { + $value = self::__get($name); + return empty($name); + } +} diff --git a/www/wp-content/plugins/social-connect/twitter/callback.php b/www/wp-content/plugins/social-connect/twitter/callback.php new file mode 100755 index 0000000..4110c3f --- /dev/null +++ b/www/wp-content/plugins/social-connect/twitter/callback.php @@ -0,0 +1,39 @@ +setToken($_GET['oauth_token']); +$token = $twitter_api->getAccessToken(); +$twitter_api->setToken($token->oauth_token, $token->oauth_token_secret); + +$user = $twitter_api->get_accountVerify_credentials(); +$name = $user->name; +$screen_name = $user->screen_name; +$twitter_id = $user->id; +$signature = social_connect_generate_signature($twitter_id); +?> + + + + + + + + diff --git a/www/wp-content/plugins/social-connect/twitter/connect.php b/www/wp-content/plugins/social-connect/twitter/connect.php new file mode 100755 index 0000000..8c3b90b --- /dev/null +++ b/www/wp-content/plugins/social-connect/twitter/connect.php @@ -0,0 +1,18 @@ +getAuthenticateUrl()); + exit(); +} +?> +

Social Connect plugin has not been configured for Twitter

+ diff --git a/www/wp-content/plugins/social-connect/ui.php b/www/wp-content/plugins/social-connect/ui.php new file mode 100755 index 0000000..2b46ae4 --- /dev/null +++ b/www/wp-content/plugins/social-connect/ui.php @@ -0,0 +1,192 @@ + + +comment_ID, 'social_connect_comment_via_provider', true ); + if( $social_connect_comment_via_provider && current_user_can( 'manage_options' )) { + return $link . ' '; + } else { + return $link; + } +} +add_action( 'get_comment_author_link', 'sc_social_connect_render_comment_meta' ); + + +function sc_render_comment_form_social_connect() { + if( comments_open() && !is_user_logged_in()) { + sc_render_login_form_social_connect(); + } +} +add_action( 'comment_form_top', 'sc_render_comment_form_social_connect' ); + + +function sc_render_login_page_uri(){ + ?> + + __( 'Login or register with Facebook, Twitter, Yahoo, Google or a Wordpress.com account', 'social_connect' )) + ); + } + + /** This is rendered widget content */ + function widget( $args, $instance ) { + extract( $args ); + + if($instance['hide_for_logged_in']==1 && is_user_logged_in()) return; + + echo $before_widget; + + if( !empty( $instance['title'] ) ){ + $title = apply_filters( 'widget_title', $instance[ 'title' ] ); + echo $before_title . $title . $after_title; + } + + if( !empty( $instance['before_widget_content'] ) ){ + echo $instance['before_widget_content']; + } + + sc_render_login_form_social_connect( array( 'display_label' => false ) ); + + if( !empty( $instance['after_widget_content'] ) ){ + echo $instance['after_widget_content']; + } + + echo $after_widget; + } + + /** Everything which should happen when user edit widget at admin panel */ + function update( $new_instance, $old_instance ) { + $instance = $old_instance; + $instance['title'] = strip_tags( $new_instance['title'] ); + $instance['before_widget_content'] = $new_instance['before_widget_content']; + $instance['after_widget_content'] = $new_instance['after_widget_content']; + $instance['hide_for_logged_in'] = $new_instance['hide_for_logged_in']; + + return $instance; + } + + /** Widget edit form at admin panel */ + function form( $instance ) { + /* Set up default widget settings. */ + $defaults = array( 'title' => '', 'before_widget_content' => '', 'after_widget_content' => '' ); + + foreach( $instance as $key => $value ) + $instance[ $key ] = esc_attr( $value ); + + $instance = wp_parse_args( (array)$instance, $defaults ); + ?> +

+ + + + + + +

+ /> +

+ usermeta WHERE meta_key = '%s' AND meta_value = '%s'"; + return $wpdb->get_var( $wpdb->prepare( $sql, $meta_key, $meta_value ) ); +} + +function social_connect_generate_signature( $data ) { + return hash( 'SHA256', AUTH_KEY . $data ); +} + +function social_connect_verify_signature( $data, $signature, $redirect_to ) { + $generated_signature = social_connect_generate_signature( $data ); + + if( $generated_signature != $signature ) { + wp_safe_redirect( $redirect_to ); + exit(); + } +} + +function sc_curl_get_contents( $url ) { + $curl = curl_init(); + curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 ); + curl_setopt( $curl, CURLOPT_URL, $url ); + curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false ); + + $html = curl_exec( $curl ); + + curl_close( $curl ); + + return $html; +} diff --git a/www/wp-content/plugins/social-connect/wordpress/connect.php b/www/wp-content/plugins/social-connect/wordpress/connect.php new file mode 100755 index 0000000..dcfab04 --- /dev/null +++ b/www/wp-content/plugins/social-connect/wordpress/connect.php @@ -0,0 +1,61 @@ +identity = urldecode($_GET['wordpress_blog_url']); + $openid->required = array('namePerson', 'namePerson/friendly', 'contact/email'); + header('Location: ' . $openid->authUrl()); + } elseif($_GET['openid_mode'] == 'cancel') { + ?> + + +

+ + + validate()) { + $wordpress_id = $openid->identity; + $attributes = $openid->getAttributes(); + $email = isset($attributes['contact/email']) ? $attributes['contact/email'] : ''; + $name = isset($attributes['namePerson']) ? $attributes['namePerson'] : ''; + $signature = social_connect_generate_signature($wordpress_id); + if($email == '') { + ?> + + +

+ + + + + + + + + + +getMessage(); +} +?> \ No newline at end of file diff --git a/www/wp-content/plugins/social-connect/yahoo/connect.php b/www/wp-content/plugins/social-connect/yahoo/connect.php new file mode 100755 index 0000000..752cb0b --- /dev/null +++ b/www/wp-content/plugins/social-connect/yahoo/connect.php @@ -0,0 +1,45 @@ +identity = 'me.yahoo.com'; + $openid->required = array('namePerson', 'namePerson/friendly', 'contact/email'); + header('Location: ' . $openid->authUrl()); + } else { + $openid = new LightOpenID; + if($openid->validate()) { + $yahoo_id = $openid->identity; + $attributes = $openid->getAttributes(); + $email = $attributes['contact/email']; + $name = $attributes['namePerson']; + $username = $attributes['namePerson/friendly']; + $signature = social_connect_generate_signature($yahoo_id); + ?> + + + + + + + + getMessage(); +} +?> diff --git a/www/wp-login.php b/www/wp-login.php index c5c4e8f..f5945c6 100644 --- a/www/wp-login.php +++ b/www/wp-login.php @@ -55,8 +55,8 @@ function login_header($title = 'Log In', $message = '', $wp_error = '') { $shake_error_codes = array( 'empty_password', 'empty_email', 'invalid_email', 'invalidcombo', 'empty_username', 'invalid_username', 'incorrect_password' ); $shake_error_codes = apply_filters( 'shake_error_codes', $shake_error_codes ); - if ( $shake_error_codes && $wp_error->get_error_code() && in_array( $wp_error->get_error_code(), $shake_error_codes ) ) - add_action( 'login_head', 'wp_shake_js', 12 ); + //if ( $shake_error_codes && $wp_error->get_error_code() && in_array( $wp_error->get_error_code(), $shake_error_codes ) ) + //add_action( 'login_head', 'wp_shake_js', 12 ); ?> @@ -68,6 +68,7 @@ function login_header($title = 'Log In', $message = '', $wp_error = '') { include('header.php'); ?> +

- + + +

-

- - - - - - - -

+

+ + + + + + + +

+ +