package.xml100644 0 0 32577 100644 6121 oauth pecl.php.net oauth consumer extension OAuth is an authorization protocol built on top of HTTP which allows applications to securely access data without having to store usernames and passwords. Requirements: ext/hash (now a part of PHP core) John Jawed jawed jawed@php.net yes Rasmus Lerdorf rasmus rasmus@php.net yes Felipe Pena felipe felipe@php.net yes Tjerk Meesters datibbaw datibbaw@php.net yes 2012-10-01 1.2.3 1.2 stable stable BSD - Fix reference counts not being incremented in OAuthProvider 5.1.0 1.4.0b1 hash oauth 2011-07-22 1.2.2 1.2 stable stable BSD - Bug 22834 2011-07-19 1.2.1 1.2 stable stable BSD - Fixed bugs: 22819, 22824 2011-06-27 1.2 1.2 stable stable - Fixed bugs: 22337, 22485, 22628, 22630, 22484 (and others!) - Added ability to coerce HTTP method when calling OAuth::fetch() 2011-02-06 1.1.0 1.1.0 stable stable - Fixed bugs: 17782, 18214, 21426, 22093 - Added PLAINTEXT signature method support (stas@) - Added OAuth::getRequestHeader and OAuth::setSSLChecks (hirokawa@) 2011-06-02 1.0.0 1.0.0 stable stable - Added php streams support (libcurl is no longer required) - Added OAuthProvider support (http://php.net/oauthprovider) - Added RSA-SHA1 signature support - Added SHA256 signature support - Added OAuth::setTimeout, OAuth::generateSignature, OAuth::setRequestEngine - Send the User-Agent header for pecl/oauth - Lots of other improvements... 2009-05-09 0.99.9 0.99.9 beta beta - Added 1.0a support (based on implementer Draft 2, http://oauth.googlecode.com/svn/spec/core/1.0a/drafts/2/oauth-core-1_0a.html) - Added support for empty parameters - Added oauth_callback support to getRequestToken - Added oauth_verifier support to getAccessToken - Fixed build failures for PHP5.1 2010-06-02 1.0.0 1.0.0 stable stable - Added php streams support (libcurl is no longer required) - Added OAuthProvider support (http://php.net/oauthprovider) - Added RSA-SHA1 signature support - Added SHA256 signature support - Added OAuth::setTimeout, OAuth::generateSignature, OAuth::setRequestEngine - Send the User-Agent header for pecl/oauth - Lots of other improvements... 2009-05-09 0.99.9 0.99.9 beta beta - Added 1.0a support (based on implementer Draft 2, http://oauth.googlecode.com/svn/spec/core/1.0a/drafts/2/oauth-core-1_0a.html) - Added support for empty parameters - Added oauth_callback support to getRequestToken - Added oauth_verifier support to getAccessToken - Fixed build failures for PHP5.1 2009-04-30 0.99.8 0.99.8 beta beta - Throw an exception if a caller attempts to use something other than HTTP POST with an auth type set to FORM - Do not use pear package version number (bug #16404) - Please read http://oauth.net/advisories/2009-1 2009-04-23 0.99.7 0.99.7 beta beta - Throw an exception if a caller attempts to use something other than HTTP POST with an auth type set to FORM - Do not use pear package version number (bug #16404) - Please read http://oauth.net/advisories/2009-1 2009-04-20 0.99.6 0.99.6 beta beta - Win32 support (pierre) - Fixed bug #16398 - Use pear package version number 2009-04-20 0.99.5 0.99.5 beta beta - Added support for multiple protocols (Tjerk Meesters) - Signature generation fix for quoted values - Added disableSSLChecks and enableSSLChecks (enabled by default) - Added support for following and signing redirects 2009-03-26 0.99.5 0.99.5 beta beta BSD - Added extra constants for Google Portable Contact API's 2008-26-03 0.99.3 0.99 beta beta BSD - Fixed double free with Zend object (Rasmus) - Fixed memory leaks if ext/hash was not available - Encode consumer secret first for the properties hash - Added enableDebug and disableDebug functions (docs coming soon) - More examples (Twitter, Google Portable Contacts, Netflix) 2008-12-03 0.99.2 0.99 beta beta BSD - Fixed PECL bug #15110 #15111 (ZTS build, Segfault and memory leak, hannes/felipe) + other memleaks - Fixed PECL bug #15112 (incorrect cvs branch) - Updated fetch to respect additional request params, added examples and TODO - Updates for 5.3 - Support for older libcurl versions - Added arginfo - Marking as beta 2008-11-20 0.99.1 0.99 alpha alpha BSD - Initial release. oauth-1.2.3/examples/config.inc.php100644 0 0 473 100644 12055 oauth-1.2.3/examples/request_signing.php100644 0 0 1507 100644 13265 setToken(GENERAL_PURPOSE_TOKEN,GENERAL_PURPOSE_TOKEN_SECRET); $o->fetch("https://www.some.tld/1.0/an_api"); $response_info = $o->getLastResponseInfo(); header("Content-Type: {$response_info["content_type"]}"); echo $o->getLastResponse(); } catch(Exception $E) { echo "Error: [".$E->errorMessage."]
\n"; echo "Response: [".$E->lastResponse."]
\n"; exit; } oauth-1.2.3/examples/request_token.php100644 0 0 1136 100644 12745 getRequestToken("https://www.foo.tld/oauth/requestToken"); file_put_contents(OAUTH_TMP_DIR ."/request_token_resp",serialize($arrayResp)); /* note: on the redirect there is no need to pass anything other than the oauth_token parameter */ header("Location: https://www.foo.tld/oauth/authorize?oauth_token={$arrayResp["oauth_token"]}"); } catch(OAuthException $E) { print_r($E); echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/access_token.php100644 0 0 1174 100644 12520 setToken($request_token_info["oauth_token"],$request_token_info["oauth_token_secret"]); $arrayResp = $o->getAccessToken("https://www.foo.tld/oauth/accessToken"); file_put_contents(OAUTH_TMP_DIR . "/access_token_resp",serialize($arrayResp)); echo "Finished getting the access token!"; } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/exec_api.php100644 0 0 1040 100644 11624 setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); $arrayResp = $o->fetch("https://www.foo.tld/oauth/an_api_for_user_info",array("extra" => "arg(h)")); echo $o->getLastResponse(); } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/README100644 0 0 1507 100644 10226 === CONFIGURATION === 2 things need updated with information from the OAuth service provider: * config.inc.php * the URL's of the providers resources (to get tokens, manipulate user info, etc.) === RUNNING EXAMPLES === To run the examples: 1) Execute request_token.php 2) Direct your web browser to the URL provided and authorize the access 3) Execute access_token.php After the above steps, the application examples can be run. There are several directories here which relate to OAuth service providers and their interfaces. The current directory contains generic examples. Please contribute to example code for new providers as they come along accordingly. The example code writes token information to /tmp in a static file, this is not a good idea for anything beyond tinkering, you should store these tokens somewhere safer. oauth-1.2.3/examples/yahoo/config.inc.php100644 0 0 663 100644 13175 oauth-1.2.3/examples/yahoo/request_signing.php100644 0 0 1270 100644 14401 fetch("http://query.yahooapis.com/v1/yql?q=show%20tables&format=xml"); $response_info = $o->getLastResponseInfo(); header("Content-Type: {$response_info["content_type"]}"); echo $o->getLastResponse(); } catch(Exception $E) { echo "Error: [".$E->getMessage()."]
\n"; echo "Response: [".$E->lastResponse."]
\n"; exit; } oauth-1.2.3/examples/yahoo/request_token.php100644 0 0 1107 100644 14062 getRequestToken("https://api.login.yahoo.com/oauth/v2/get_request_token"); file_put_contents(OAUTH_TMP_DIR . "/request_token_resp",serialize($arrayResp)); $authorizeUrl = $arrayResp["xoauth_request_auth_url"]; if(PHP_SAPI=="cli") { echo "Navigate your http client to: {$authorizeUrl}\n"; } else { header("Location: {$authorizeUrl}"); } } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/yahoo/access_token.php100644 0 0 1151 100644 13632 setToken($request_token_info["oauth_token"],$request_token_info["oauth_token_secret"]); $arrayResp = $o->getAccessToken("https://api.login.yahoo.com/oauth/v2/get_token"); file_put_contents(OAUTH_TMP_DIR . "/access_token_resp",serialize($arrayResp)); echo "Finished getting the access token!\n"; } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/yahoo/exec_yql.php100644 0 0 1314 100644 13003 setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); $query = rawurlencode("select * from social.profile where guid=me"); $o->fetch("http://query.yahooapis.com/v1/yql?q=$query&format=xml"); $response_info = $o->getLastResponseInfo(); header("Content-Type: {$response_info["content_type"]}"); echo $o->getLastResponse(); } catch(OAuthException $E) { echo "Exception caught!\n"; echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/yahoo/exec_yql_refresh_token.php100644 0 0 2755 100644 15733 setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); /* the following bit refreshes the token using the session handle (http://wiki.oauth.net/ScalableOAuth) ... you don't need it unless your original access token is invalid but you'll need to audit this yourself, for example sakes we'll pretend it has expired. */ if(!empty($access_token_info["oauth_session_handle"])) { $o->setAuthType(OAUTH_AUTH_TYPE_URI); $access_token_info = $o->getAccessToken("https://api.login.yahoo.com/oauth/v2/get_token",$access_token_info["oauth_session_handle"]); $o->setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); $o->setAuthType(OAUTH_AUTH_TYPE_AUTHORIZATION); file_put_contents(OAUTH_TMP_DIR . "/access_token_resp",serialize($access_token_info)); } /* done refreshing access token, time to do some fetching! */ $query = rawurlencode("select * from social.profile where guid=me"); $o->fetch("http://query.yahooapis.com/v1/yql?q=$query&format=xml"); $response_info = $o->getLastResponseInfo(); header("Content-Type: {$response_info["content_type"]}"); echo $o->getLastResponse(); } catch(OAuthException $E) { echo "Exception caught!\n"; echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/fireeagle/config.inc.php100644 0 0 723 100644 13776 oauth-1.2.3/examples/fireeagle/request_signing.php100644 0 0 1536 100644 15212 setToken(GENERAL_PURPOSE_TOKEN,GENERAL_PURPOSE_TOKEN_SECRET); $o->fetch("https://fireeagle.yahooapis.com/api/0.1/recent.xml"); $response_info = $o->getLastResponseInfo(); header("Content-Type: {$response_info["content_type"]}"); echo $o->getLastResponse(); } catch(Exception $E) { echo "Error: [".$E->errorMessage."]
\n"; echo "Response: [".$E->lastResponse."]
\n"; exit; } oauth-1.2.3/examples/fireeagle/request_token.php100644 0 0 1333 100644 14667 getRequestToken("https://fireeagle.yahooapis.com/oauth/request_token"); file_put_contents(OAUTH_TMP_DIR . "/request_token_resp",serialize($arrayResp)); $authorizeUrl = "https://fireeagle.yahoo.net/oauth/authorize?oauth_token={$arrayResp["oauth_token"]}"; if(PHP_SAPI=="cli") { echo "Navigate your http client to: {$authorizeUrl}\n"; } else { /* note: on the redirect there is no need to pass anything other than the oauth_token parameter */ header("Location: {$authorizeUrl}"); } } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/fireeagle/access_token.php100644 0 0 1176 100644 14445 setToken($request_token_info["oauth_token"],$request_token_info["oauth_token_secret"]); $arrayResp = $o->getAccessToken("https://fireeagle.yahooapis.com/oauth/access_token"); file_put_contents(OAUTH_TMP_DIR . "/access_token_resp",serialize($arrayResp)); echo "Finished getting the access token!\n"; } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/fireeagle/exec_update_user.php100644 0 0 1150 100644 15320 setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); /* https://fireeagle.yahoo.net/developer/documentation/updating */ $arrayResp = $o->fetch("https://fireeagle.yahooapis.com/api/0.1/update",array("postal" => "95054")); echo $o->getLastResponse(); } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/netflix/config.inc.php100644 0 0 544 100644 13525 oauth-1.2.3/examples/netflix/request_token.php100644 0 0 1223 100644 14413 getRequestToken("http://api.netflix.com/oauth/request_token"); file_put_contents(OAUTH_TMP_DIR . "/request_token_resp",serialize($arrayResp)); $authorizeUrl = $arrayResp["login_url"] . "&oauth_consumer_key=" . OAUTH_CONSUMER_KEY . "&application_name=" . $arrayResp["application_name"]; if(PHP_SAPI=="cli") { echo "Navigate your http client to: {$authorizeUrl}\n"; } else { header("Location: {$authorizeUrl}"); } } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/netflix/access_token.php100644 0 0 1144 100644 14166 setToken($request_token_info["oauth_token"],$request_token_info["oauth_token_secret"]); $arrayResp = $o->getAccessToken("http://api.netflix.com/oauth/access_token"); file_put_contents(OAUTH_TMP_DIR . "/access_token_resp",serialize($arrayResp)); echo "Finished getting the access token!\n"; } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/netflix/feeds.php100644 0 0 1324 100644 12613 setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); $feeds_url = "http://api.netflix.com/users/". oauth_urlencode($access_token_info["user_id"]) ."/feeds"; $o->fetch($feeds_url); $response_info = $o->getLastResponseInfo(); header("Content-Type: {$response_info["content_type"]}"); echo $o->getLastResponse(); } catch(OAuthException $E) { echo "Exception caught!\n"; echo "Response: ". $E->lastResponse . "\n"; var_dump($E); } oauth-1.2.3/examples/netflix/rental_history_atom.php100644 0 0 2233 100644 15613 setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); $feeds_url = "http://api.netflix.com/users/". oauth_urlencode($access_token_info["user_id"]) ."/feeds"; $o->fetch($feeds_url); $feeds = $o->getLastResponse(); /* we need to pick the rental history feed (returned rentals) */ $feeds_xml = new SimpleXMLElement($feeds); /* if you want to access other feeds, change the following rel attribute */ $feed_rel = "http://schemas.netflix.com/feed.rental_history.returned"; $returned_feed = current($feeds_xml->xpath("/resource/link[@rel=\"{$feed_rel}\"]"))->attributes(); /* don't sign the feed requests */ $curl = curl_init($returned_feed["href"]); curl_exec($curl); } catch(OAuthException $E) { echo "Exception caught!\n"; echo "Response: ". $E->lastResponse . "\n"; var_dump($E); } oauth-1.2.3/examples/twitter/README100644 0 0 70 100644 11662 Run fetchTimeline.php through with your php-cli binary. oauth-1.2.3/examples/twitter/constants.php100644 0 0 1601 100644 13570 oauth-1.2.3/examples/twitter/fetchTimeline.php100644 0 0 3053 100644 14337 enableDebug(); $request_token_info = $oauth->getRequestToken(TWITTER_REQUEST_TOKEN_URL); printf("I think I got a valid request token, navigate your www client to:\n\n%s?oauth_token=%s\n\nOnce you finish authorizing, hit ENTER or INTERRUPT to exit\n\n", TWITTER_AUTHORIZE_URL, $request_token_info["oauth_token"]); $in = fopen("php://stdin", "r"); fgets($in, 255); printf("Grabbing an access token...\n"); /* grab the access token, which is your persistent token which you use for future requests */ $oauth->setToken($request_token_info["oauth_token"],$request_token_info["oauth_token_secret"]); $access_token_info = $oauth->getAccessToken(TWITTER_ACCESS_TOKEN_URL); printf("Access token: %s\n",$access_token_info["oauth_token"]); printf("Access token secret: %s\n",$access_token_info["oauth_token_secret"]); printf("Fetching the public timeline JSON via %s\n",TWITTER_PUBLIC_TIMELINE_API); $oauth->setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); $oauth->fetch(TWITTER_PUBLIC_TIMELINE_API); /* from this point on OAuth is over, now handling the JSON response is in order */ $json = json_decode($oauth->getLastResponse()); printf("An item in the decoded JSON: %s\n",print_r($json[0],true)); } catch(OAuthException $E) { print_r($E); } ?> oauth-1.2.3/examples/twitter/updateStatus.php100644 0 0 3607 100644 14252 disableSSLChecks(); /* Uncomment either of the lines below to get the debugInfo member populated in $oauth */ //$oauth->debug = 1; //$oauth->enableDebug(); $request_token_info = $oauth->getRequestToken(TWITTER_REQUEST_TOKEN_URL); printf("I think I got a valid request token, navigate your www client to:\n\n%s?oauth_token=%s\n\nOnce you finish authorizing, hit ENTER or INTERRUPT to exit\n\n", TWITTER_AUTHORIZE_URL, $request_token_info["oauth_token"]); $in = fopen("php://stdin", "r"); fgets($in, 255); printf("Grabbing an access token...\n"); /* grab the access token, which is your persistent token which you use for future requests */ $oauth->setToken($request_token_info["oauth_token"],$request_token_info["oauth_token_secret"]); $access_token_info = $oauth->getAccessToken(TWITTER_ACCESS_TOKEN_URL); printf("Access token: %s\n",$access_token_info["oauth_token"]); printf("Access token secret: %s\n",$access_token_info["oauth_token_secret"]); printf("Updating the status via %s\n",TWITTER_UPDATE_STATUS_API); $oauth->setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); $api_args = array("status" => "'hi' from pecl/oauth", "empty_param" => NULL); $oauth->fetch(TWITTER_UPDATE_STATUS_API, $api_args, OAUTH_HTTP_METHOD_POST, array("User-Agent" => "pecl/oauth")); if(!empty($oauth->debug)) { print_r($oauth->debugInfo); } /* from this point on OAuth is over, now handling the JSON response is in order */ $json = json_decode($oauth->getLastResponse()); printf("JSON Result: %s\n",print_r($json,true)); } catch(OAuthException $E) { print_r($E); } ?> oauth-1.2.3/examples/google/README100644 0 0 71 100644 11435 Run getContactInfo.php through with your php-cli binary. oauth-1.2.3/examples/google/config.inc.php100644 0 0 1705 100644 13350 oauth-1.2.3/examples/google/request_token.php100644 0 0 1531 100644 14220 getRequestToken("https://www.google.com/accounts/OAuthGetRequestToken?scope={$scopes}"); file_put_contents(OAUTH_TMP_DIR . "/request_token_resp",serialize($arrayResp)); $authorizeUrl = "https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token={$arrayResp["oauth_token"]}"; if(PHP_SAPI=="cli") { echo "Navigate your http client to: {$authorizeUrl}\n"; } else { header("Location: {$authorizeUrl}"); } } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/google/access_token.php100644 0 0 1156 100644 13774 setToken($request_token_info["oauth_token"],$request_token_info["oauth_token_secret"]); $arrayResp = $o->getAccessToken("https://www.google.com/accounts/OAuthGetAccessToken"); file_put_contents(OAUTH_TMP_DIR . "/access_token_resp",serialize($arrayResp)); echo "Finished getting the access token!\n"; } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/google/getContactInfo.php100755 0 0 5266 100755 14256 #!/usr/bin/env php getRequestToken(GOOGLE_OAUTH_REQUEST_TOKEN_API . "?scope={$scopes}"); printf("Request token: %s\n",$request_token_info["oauth_token"]); printf("Request token secret: %s\n\n",$request_token_info["oauth_token_secret"]); printf("I think I got a valid request token, navigate your www client to:\n\n%s?oauth_token=%s\n\nOnce you finish authorizing, hit ENTER or INTERRUPT to exit\n", GOOGLE_OAUTH_AUTHORIZE_API, $request_token_info["oauth_token"]); $in = fopen("php://stdin", "r"); fgets($in, 255); $oauth->setToken($request_token_info["oauth_token"],$request_token_info["oauth_token_secret"]); /* grab the access token, which is your persistent token which you use for future requests */ printf("Grabbing an access token...\n"); $access_token_info = $oauth->getAccessToken(GOOGLE_OAUTH_ACCESS_TOKEN_API); printf("Access token: %s\n",$access_token_info["oauth_token"]); printf("Access token secret: %s\n\n",$access_token_info["oauth_token_secret"]); printf("Fetching contacts in JSON via %s\n",GOOGLE_POCO_CONTACT_INFO_API); $oauth->setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); /* put the OAuth params into the Authorization header */ $oauth->setAuthType(OAUTH_AUTH_TYPE_AUTHORIZATION); $oauth->fetch(GOOGLE_POCO_CONTACT_INFO_API); /* from this point on OAuth is over, now handling the JSON response is in order */ $json = json_decode($oauth->getLastResponse()); printf("My contact information at Google: \nGiven name: %s\nFamily name: %s\nDisplay name: %s\n\n",$json->entry->name->givenName,$json->entry->name->familyName,$json->entry->displayName); printf("Fetching all of {$json->entry->displayName}'s contacts in JSON via %s\n",GOOGLE_POCO_ALL_CONTACTS); $oauth->fetch(GOOGLE_POCO_ALL_CONTACTS); $json = json_decode($oauth->getLastResponse()); printf("=== Total contacts: %d, showing: %d-%d ===\n",$json->totalResults,$json->startIndex+1,sizeof($json->entry)); foreach($json->entry as $n => $contact_object) { printf("#%d: %s\n",$n+1,$contact_object->displayName); } } catch(OAuthException $E) { echo "[EXCEPTION] Response: ". $E->lastResponse . "\n"; echo "[EXCEPTION] More Info: ". $E . "\n"; } oauth-1.2.3/examples/wepay/README100644 0 0 2627 100644 11357 WePay is a group payment service which makes managing money for groups simple. These example scripts come with a test consumer key and secret which you can use to test the API, but they may be rate limited or disabled entirely at any point, so you should go to https://www.wepay.com/developer/register to register your own consumer key and shared secret which you can put in the config.inc.php file. Once you have your own consumer key and secret, run the request_token.php script. This script returns what is known as an unauthorized request token. In order to authorize it, you will need to visit the URL the request_token.php script returns. Once you have visited this URL you will be redirected to a page on http://progphp.com. This is just a stub callback page that acts as a placeholder in order for these example scripts to work. When you build you own oauth consumer you will be writing your own callback endpoint which WePay will redirect users to. This callback URL is configured on WePay's /developer/register page on a per-app basis. Next, run the access_token.php script. This script will fetch the verifier from the progphp.com stuf callback endpoint and contact WePay to exchange the authorized request token for an access token. This access token will now allow your application to access the API on behalf of the user who athoried it. Run the balances.php script to see an example of calling the API. oauth-1.2.3/examples/wepay/config.inc.php100644 0 0 717 100644 13203 getRequestToken("https://wepayapi.com/v1/oauth/request_token"); // And save it file_put_contents(OAUTH_TMP_DIR . "/wepay_request_token_resp",serialize($arrayResp)); // Get the authorizating URL that the user needs to click on to authorize the request token $authorizeUrl = $arrayResp["login_url"]; if(PHP_SAPI=="cli") { echo "Point your Web browser at: {$authorizeUrl}\n"; } else { header("Location: {$authorizeUrl}"); } } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/wepay/access_token.php100644 0 0 2725 100644 13650 setToken($request_token_info["oauth_token"],$request_token_info["oauth_token_secret"]); // This next step is a bit odd - it is because WePay is an OAuth 1.0a web service which requires a verifier in the // callback from the user authorizing the request token. In a real OAuth application you would, of course, capture // this verifier with your own callback endpoint, but in order for this example script to work, we wrote a stub // callback endpoint which saves the verifier and lets us fetch it from here. $vdata = json_decode(file_get_contents("http://progphp.com/oauth/".urlencode($request_token_info["oauth_token"]))); // Exchange the authorized request token by sending it to WePay's access_token endpoint along with the verifier $arrayResp = $o->getAccessToken("https://wepayapi.com/v1/oauth/access_token", NULL, $vdata->verifier); // And we store this access token which we can use from now on to execute API calls against the WePay web API file_put_contents(OAUTH_TMP_DIR . "/wepay_access_token_resp",serialize($arrayResp)); echo "Finished getting the access token!\n"; } catch(OAuthException $E) { echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/wepay/balances.php100644 0 0 1642 100644 12754 enableDebug(); $access_token_info = unserialize(file_get_contents(OAUTH_TMP_DIR . "/wepay_access_token_resp")); $o->setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); $resp = $o->fetch("https://wepayapi.com/v1/group/list"); $response_info = $o->getLastResponseInfo(); $json = $o->getLastResponse(); $data = json_decode($json); foreach($data->result as $gr) { $resp = $o->fetch("https://wepayapi.com/v1/group/{$gr->id}"); $group = json_decode($o->getLastResponse()); $bal = $group->result->balance; $pending = $group->result->pending_balance; echo "\$$pending ($bal available) for {$gr->id} \"{$gr->name}\"\n"; } } catch(OAuthException $E) { echo "Exception caught!\n"; echo "Response: ". $E->lastResponse . "\n"; } oauth-1.2.3/examples/digg/config.inc.php100644 0 0 220 100644 12755 oauth-1.2.3/examples/digg/digg_a_story.php100644 0 0 2217 100644 13442 getRequestToken("http://services.digg.com/1.0/endpoint?method=oauth.getRequestToken"); echo "Go to http://digg.com/oauth/authorize?oauth_token={$request_token["oauth_token"]} and enter the code (PIN) given at the end of the flow @ digg\n"; $in = fopen("php://stdin", "r"); $verifier = fgets($in, 255); echo "Grabbing an access token...\n"; $oauth->setToken($request_token["oauth_token"], $request_token["oauth_token_secret"]); $access_token = $oauth->getAccessToken("http://services.digg.com/1.0/endpoint?method=oauth.getAccessToken", NULL, $verifier); echo "Got an access token: " . $access_token["oauth_token"]; $oauth->setToken($access_token["oauth_token"], $access_token["oauth_token_secret"]); $oauth->fetch("http://services.digg.com/1.0/endpoint?method=story.digg", array("story_id" => "21595036")); $xml = simplexml_load_string($oauth->getLastResponse()); echo "http://digg.com/programming/PHP_OAuth_Manual has been dugg\n"; } catch (OAuthException $E) { var_dump($E); } ?> oauth-1.2.3/config.m4100644 0 0 1416 100644 7236 dnl dnl $Id: config.m4 299931 2010-05-29 04:55:04Z datibbaw $ dnl PHP_ARG_ENABLE(oauth, for oauth support, [ --enable-oauth Include oauth support]) if test "$PHP_OAUTH" != "no"; then PHP_SUBST(OAUTH_SHARED_LIBADD) PHP_NEW_EXTENSION(oauth, oauth.c provider.c, $ext_shared) CFLAGS="$CFLAGS -Wall -g" AC_MSG_CHECKING(for cURL in default path) for i in /usr/local /usr; do if test -r $i/include/curl/easy.h; then CURL_DIR=$i AC_MSG_RESULT(found in $i) break fi done if test -z "$CURL_DIR"; then AC_MSG_RESULT(cURL not found, cURL support disabled) else PHP_ADD_LIBRARY(curl,,OAUTH_SHARED_LIBADD) AC_DEFINE(OAUTH_USE_CURL, 1, [Whether cURL is present and should be used]) fi PHP_ADD_EXTENSION_DEP(oauth, hash) fi oauth-1.2.3/config.w32100644 0 0 1745 100644 7336 // $Id: config.w32 308606 2011-02-23 15:06:07Z pajoye $ // vim:ft=javascript ARG_WITH("oauth", "oAuth support", "no"); if (PHP_OAUTH != "no") { if (CHECK_LIB("libcurl_a.lib;libcurl.lib", "oauth", PHP_OAUTH) && CHECK_HEADER_ADD_INCLUDE("curl/easy.h", "CFLAGS_OAUTH") && CHECK_LIB("ssleay32.lib", "oauth", PHP_OAUTH) && CHECK_LIB("libeay32.lib", "oauth", PHP_OAUTH) && CHECK_LIB("winmm.lib", "oauth", PHP_OAUTH) && CHECK_LIB("wldap32.lib", "oauth", PHP_OAUTH) && (((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib", "oauth", PHP_OAUTH) || CHECK_LIB("zlib.lib", "oauth", PHP_OAUTH))) || (PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "oauth", PHP_OAUTH)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED))) ) { EXTENSION("oauth", "oauth.c provider.c", true); ADD_FLAG("CFLAGS_OAUTH", "/D CURL_STATICLIB"); ADD_FLAG("CFLAGS_OAUTH", "/D OAUTH_USE_CURL"); ADD_FLAG("LDFLAGS_OAUTH", "/D /FORCE:MULTIPLE "); } else { WARNING("oauth not enabled; libraries and headers not found"); } } oauth-1.2.3/oauth.c100644 0 0 262773 100644 7072 /* +----------------------------------------------------------------------+ | See LICENSE file for further copyright information | +----------------------------------------------------------------------+ | Authors: John Jawed | | Felipe Pena | | Rasmus Lerdorf | | Tjerk Meesters | +----------------------------------------------------------------------+ */ /* $Id: oauth.c 325799 2012-05-24 21:07:51Z jawed $ */ #include "php_oauth.h" #include "provider.h" static zend_class_entry *soo_class_entry; static zend_class_entry *soo_exception_ce; static zend_object_handlers so_object_handlers; static zend_object_value oauth_clone_obj(zval *this_ptr TSRMLS_DC); static php_so_object* php_so_object_new(zend_class_entry *ce TSRMLS_DC); static zend_object_value php_so_register_object(php_so_object *soo TSRMLS_DC); static zend_object_value oauth_clone_obj(zval *this_ptr TSRMLS_DC) /* {{{ */ { php_so_object *old_obj = (php_so_object *)zend_object_store_get_object(this_ptr TSRMLS_CC); php_so_object *new_obj = php_so_object_new(old_obj->zo.ce TSRMLS_CC); zend_object_value new_ov = php_so_register_object(new_obj TSRMLS_CC); zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); return new_ov; } /* }}} */ static int oauth_parse_str(char *params, zval *dest_array TSRMLS_DC) /* {{{ */ { char *res = NULL, *var, *val, *separator = NULL; char *strtok_buf = NULL; if (!params) { return FAILURE; } res = params; separator = (char *) estrdup(PG(arg_separator).input); var = php_strtok_r(res, separator, &strtok_buf); while (var) { val = strchr(var, '='); if (val) { /* have a value */ int val_len; *val++ = '\0'; php_url_decode(var, strlen(var)); val_len = php_url_decode(val, strlen(val)); val = estrndup(val, val_len); } else { int val_len; php_url_decode(var, strlen(var)); val_len = 0; val = estrndup("", val_len); } #if (PHP_MAJOR_VERSION >= 6) add_ascii_assoc_string(dest_array, var, val, 1); #else add_assoc_string(dest_array, var, val, 1); #endif efree(val); var = php_strtok_r(NULL, separator, &strtok_buf); } efree(separator); return SUCCESS; } /* }}} */ static inline php_so_object *fetch_so_object(zval *obj TSRMLS_DC) /* {{{ */ { php_so_object *soo = (php_so_object *)zend_object_store_get_object(obj TSRMLS_CC); soo->this_ptr = obj; return soo; } /* }}} */ static int so_set_response_args(HashTable *hasht, zval *data, zval *retarray TSRMLS_DC) /* {{{ */ { if (data && Z_TYPE_P(data) == IS_STRING) { ulong h = zend_hash_func(OAUTH_RAW_LAST_RES, sizeof(OAUTH_RAW_LAST_RES)); #if jawed_0 /* don't need this till we fully implement error reporting ... */ if (!onlyraw) { zend_hash_quick_update(hasht, OAUTH_ATTR_LAST_RES, sizeof(OAUTH_ATTR_LAST_RES), h, &arrayArg, sizeof(zval *), NULL); } else { zend_hash_quick_update(hasht, OAUTH_ATTR_LAST_RES, sizeof(OAUTH_ATTR_LAST_RES), h, &rawval, sizeof(zval *), NULL); h = zend_hash_func(OAUTH_RAW_LAST_RES, sizeof(OAUTH_RAW_LAST_RES)); zend_hash_quick_update(hasht, OAUTH_RAW_LAST_RES, sizeof(OAUTH_RAW_LAST_RES), h, &rawval, sizeof(zval *), NULL); } return data; #endif if (retarray) { char *res = NULL; res = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data)); /* do not use oauth_parse_str here, we want the result to pass through input filters */ sapi_module.treat_data(PARSE_STRING, res, retarray TSRMLS_CC); } return zend_hash_quick_update(hasht, OAUTH_RAW_LAST_RES, sizeof(OAUTH_RAW_LAST_RES), h, &data, sizeof(zval *), NULL); } return FAILURE; } /* }}} */ static zval *so_set_response_info(HashTable *hasht, zval *info) /* {{{ */ { ulong h = zend_hash_func(OAUTH_ATTR_LAST_RES_INFO, sizeof(OAUTH_ATTR_LAST_RES_INFO)); if (zend_hash_quick_update(hasht, OAUTH_ATTR_LAST_RES_INFO, sizeof(OAUTH_ATTR_LAST_RES_INFO), h, &info, sizeof(zval *), NULL) != SUCCESS) { return NULL; } return info; } /* }}} */ static void so_object_free_storage(void *obj TSRMLS_DC) /* {{{ */ { php_so_object *soo; soo = (php_so_object *) obj; #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) if (soo->zo.guards) { zend_hash_destroy(soo->zo.guards); FREE_HASHTABLE(soo->zo.guards); } if (soo->zo.properties) { zend_hash_destroy(soo->zo.properties); FREE_HASHTABLE(soo->zo.properties); } #else zend_object_std_dtor(&soo->zo TSRMLS_CC); #endif if (soo->lastresponse.c) { smart_str_free(&soo->lastresponse); } if (soo->headers_in.c) { smart_str_free(&soo->headers_in); } if (soo->headers_out.c) { smart_str_free(&soo->headers_out); } efree(obj); } /* }}} */ static zend_object_value php_so_register_object(php_so_object *soo TSRMLS_DC) /* {{{ */ { zend_object_value rv; rv.handle = zend_objects_store_put(soo, (zend_objects_store_dtor_t)zend_objects_destroy_object, so_object_free_storage, NULL TSRMLS_CC); rv.handlers = (zend_object_handlers *) &so_object_handlers; return rv; } /* }}} */ static php_so_object* php_so_object_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */ { php_so_object *nos; #ifndef ZEND_ENGINE_2_4 zval *tmp; #endif nos = ecalloc(1, sizeof(php_so_object)); nos->signature = NULL; nos->timeout = 0; #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) ALLOC_HASHTABLE(nos->zo.properties); zend_hash_init(nos->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0); nos->zo.ce = ce; nos->zo.guards = NULL; #else zend_object_std_init(&nos->zo, ce TSRMLS_CC); #ifdef ZEND_ENGINE_2_4 object_properties_init(&nos->zo, ce); #else zend_hash_copy(nos->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); #endif #endif return nos; } /* }}} */ static zend_object_value new_so_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */ { php_so_object *soo; soo = php_so_object_new(ce TSRMLS_CC); return php_so_register_object(soo TSRMLS_CC); } /* }}} */ void soo_handle_error(php_so_object *soo, long errorCode, char *msg, char *response, char *additional_info TSRMLS_DC) /* {{{ */ { zval *ex; #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) zend_class_entry *dex = zend_exception_get_default(), *soox = soo_exception_ce; #else zend_class_entry *dex = zend_exception_get_default(TSRMLS_C), *soox = soo_exception_ce; #endif MAKE_STD_ZVAL(ex); object_init_ex(ex, soox); if (!errorCode) { php_error(E_WARNING, "caller did not pass an errorcode!"); } else { zend_update_property_long(dex, ex, "code", sizeof("code")-1, errorCode TSRMLS_CC); } if (response) { zend_update_property_string(dex, ex, "lastResponse", sizeof("lastResponse")-1, response TSRMLS_CC); } if(soo && soo->debug && soo->debugArr) { zend_update_property(dex, ex, "debugInfo", sizeof("debugInfo") - 1, soo->debugArr TSRMLS_CC); } if(additional_info) { zend_update_property_string(dex, ex, "additionalInfo", sizeof("additionalInfo")-1, additional_info TSRMLS_CC); } zend_update_property_string(dex, ex, "message", sizeof("message")-1, msg TSRMLS_CC); zend_throw_exception_object(ex TSRMLS_CC); } /* }}} */ static void oauth_prop_hash_dtor(php_so_object *soo TSRMLS_DC) /* {{{ */ { HashTable *ht; ht = soo->properties; FREE_ARGS_HASH(ht); } /* }}} */ static char *soo_sign_hmac(php_so_object *soo, char *message, const char *cs, const char *ts, const oauth_sig_context *ctx TSRMLS_DC) /* {{{ */ { zval *args[4],*retval,*func; char *tret; int ret,retlen; unsigned char *result; MAKE_STD_ZVAL(func); ZVAL_STRING(func, "hash_hmac", 0); if (!zend_is_callable(func, 0, NULL OAUTH_IS_CALLABLE_CC)) { FREE_ZVAL(func); soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "HMAC signature generation failed, is ext/hash installed?", NULL, NULL TSRMLS_CC); return NULL; } /* cs and ts would at best be empty, so this should be safe ;-) */ spprintf(&tret, 0, "%s&%s", cs, ts); MAKE_STD_ZVAL(retval); MAKE_STD_ZVAL(args[0]); MAKE_STD_ZVAL(args[1]); MAKE_STD_ZVAL(args[2]); MAKE_STD_ZVAL(args[3]); ZVAL_STRING(args[0], ctx->hash_algo, 0); ZVAL_STRING(args[1], message, 0); ZVAL_STRING(args[2], tret, 0); ZVAL_BOOL(args[3], 1); ret = call_user_function(EG(function_table), NULL, func, retval, 4, args TSRMLS_CC); result = php_base64_encode((unsigned char *)Z_STRVAL_P(retval), Z_STRLEN_P(retval), &retlen); efree(tret); zval_ptr_dtor(&retval); FREE_ZVAL(func); FREE_ZVAL(args[0]); FREE_ZVAL(args[1]); FREE_ZVAL(args[2]); FREE_ZVAL(args[3]); return (char *)result; } /* }}} */ static char *soo_sign_rsa(php_so_object *soo, char *message, const oauth_sig_context *ctx TSRMLS_DC) { zval *args[3], *func, *retval; unsigned char *result; int ret, retlen; /* check for empty private key */ if (!ctx->privatekey) { return NULL; } MAKE_STD_ZVAL(func); ZVAL_STRING(func, "openssl_sign", 0); MAKE_STD_ZVAL(retval); MAKE_STD_ZVAL(args[0]); MAKE_STD_ZVAL(args[1]); /* TODO: add support for other algorithms instead of OPENSSL_ALGO_SHA1 */ ZVAL_STRING(args[0], message, 0); /* Bug 17545 - segfault when zval_dtor is attempted on this argument */ ZVAL_EMPTY_STRING(args[1]); /* args[1] is filled by function */ args[2] = ctx->privatekey; ret = call_user_function(EG(function_table), NULL, func, retval, 3, args TSRMLS_CC); if (Z_BVAL_P(retval)) { result = php_base64_encode((unsigned char *)Z_STRVAL_P(args[1]), Z_STRLEN_P(args[1]), &retlen); zval_ptr_dtor(&args[1]); } else { result = NULL; } zval_ptr_dtor(&retval); FREE_ZVAL(func); FREE_ZVAL(args[0]); return (char *)result; } /* }}} */ static char *soo_sign_plain(php_so_object *soo, const char *cs, const char *ts TSRMLS_DC) /* {{{ */ { char *tret; spprintf(&tret, 0, "%s&%s", cs, ts); return tret; } /* }}} */ oauth_sig_context *oauth_create_sig_context(const char *sigmethod) { oauth_sig_context *ctx; OAUTH_SIGCTX_INIT(ctx); if (0==strcmp(sigmethod, OAUTH_SIG_METHOD_HMACSHA1)) { OAUTH_SIGCTX_HMAC(ctx, "sha1"); } else if (0==strcmp(sigmethod, OAUTH_SIG_METHOD_HMACSHA256)) { OAUTH_SIGCTX_HMAC(ctx, "sha256"); } else if (0==strcmp(sigmethod, OAUTH_SIG_METHOD_RSASHA1)) { OAUTH_SIGCTX_RSA(ctx, "sha1"); } else if (0==strcmp(sigmethod, OAUTH_SIG_METHOD_PLAINTEXT)) { OAUTH_SIGCTX_PLAIN(ctx); } return ctx; } char *soo_sign(php_so_object *soo, char *message, zval *cs, zval *ts, const oauth_sig_context *ctx TSRMLS_DC) { const char *csec = cs?Z_STRVAL_P(cs):"", *tsec = ts?Z_STRVAL_P(ts):""; if (OAUTH_SIGCTX_TYPE_HMAC==ctx->type) { return soo_sign_hmac(soo, message, csec, tsec, ctx TSRMLS_CC); } else if (OAUTH_SIGCTX_TYPE_RSA==ctx->type) { return soo_sign_rsa(soo, message, ctx TSRMLS_CC); } else if(OAUTH_SIGCTX_TYPE_PLAIN==ctx->type) { return soo_sign_plain(soo, csec, tsec TSRMLS_CC); } return NULL; } static inline zval **soo_get_property(php_so_object *soo, char *prop_name TSRMLS_DC) /* {{{ */ { size_t prop_len = 0; void *data_ptr; ulong h; prop_len = strlen(prop_name); h = zend_hash_func(prop_name, prop_len+1); if (zend_hash_quick_find(soo->properties, prop_name, prop_len+1, h, (void **)&data_ptr) == SUCCESS) { return (zval **)data_ptr; } return NULL; } /* }}} */ /* XXX for auth type, need to make sure that the auth type is actually supported before setting */ static inline int soo_set_property(php_so_object *soo, zval *prop, char *prop_name TSRMLS_DC) /* {{{ */ { size_t prop_len = 0; ulong h; prop_len = strlen(prop_name); h = zend_hash_func(prop_name, prop_len+1); return zend_hash_quick_update(soo->properties, prop_name, prop_len+1, h, (void *)&prop, sizeof(zval *), NULL); } /* }}} */ char *oauth_url_encode(char *url, int url_len) /* {{{ */ { char *urlencoded = NULL, *ret; int out_len, ret_len; if (url) { if (url_len < 0) { url_len = strlen(url); } urlencoded = php_raw_url_encode(url, url_len, &out_len); } if (urlencoded) { ret = php_str_to_str_ex(urlencoded, out_len, "%7E", sizeof("%7E")-1, "~", sizeof("~")-1, &ret_len, 0, NULL); efree(urlencoded); return ret; } return NULL; } /* }}} */ char* oauth_http_encode_value(zval **v TSRMLS_DC) { char *param_value = NULL; switch (Z_TYPE_PP(v)) { case IS_STRING: param_value = oauth_url_encode(Z_STRVAL_PP(v), Z_STRLEN_PP(v)); break; #if (PHP_MAJOR_VERSION >= 6) case IS_UNICODE: { char *temp; int temp_len; zend_unicode_to_string(UG(utf8_conv), &temp, &temp_len, Z_USTRVAL_PP(v), Z_USTRLEN_PP(v) TSRMLS_CC); param_value = oauth_url_encode(temp, temp_len); efree(temp); } break; #endif default: SEPARATE_ZVAL(v); convert_to_string_ex(v); param_value = oauth_url_encode(Z_STRVAL_PP(v), Z_STRLEN_PP(v)); } return param_value; } static int oauth_strcmp(zval *first, zval *second TSRMLS_DC) { zval result; if (FAILURE==string_compare_function(&result, first, second TSRMLS_CC)) { return 0; } if (Z_LVAL(result) < 0) { return -1; } else if (Z_LVAL(result) > 0) { return 1; } return 0; } static int oauth_compare_value(const void *a, const void *b TSRMLS_DC) { Bucket *f, *s; zval *first, *second; f = *(Bucket **)a; s = *(Bucket **)b; first = *(zval **)f->pData; second = *(zval **)s->pData; return oauth_strcmp(first, second TSRMLS_CC); } static int oauth_compare_key(const void *a, const void *b TSRMLS_DC) { Bucket *f, *s; zval first, second; f = *(Bucket **)a; s = *(Bucket **)b; if (f->nKeyLength == 0) { Z_TYPE(first) = IS_LONG; Z_LVAL(first) = f->h; } else { Z_TYPE(first) = IS_STRING; Z_STRVAL(first) = f->arKey; Z_STRLEN(first) = f->nKeyLength - 1; } if (s->nKeyLength == 0) { Z_TYPE(second) = IS_LONG; Z_LVAL(second) = s->h; } else { Z_TYPE(second) = IS_STRING; Z_STRVAL(second) = s->arKey; Z_STRLEN(second) = s->nKeyLength - 1; } return oauth_strcmp(&first, &second TSRMLS_CC); } /* build url-encoded string from args, optionally starting with & */ int oauth_http_build_query(php_so_object *soo, smart_str *s, HashTable *args, zend_bool prepend_amp TSRMLS_DC) { zval **cur_val; char *arg_key = NULL, *param_value; zend_hash_key_type cur_key; uint cur_key_len; int numargs = 0, hash_key_type, skip_append = 0, i, found; ulong num_index; HashPosition pos; smart_str keyname; smart_str_0(s); if (args) { if (soo && !soo->is_multipart) { for (zend_hash_internal_pointer_reset_ex(args, &pos); HASH_KEY_NON_EXISTANT!=(hash_key_type=zend_hash_get_current_key_ex(args, &cur_key, &cur_key_len, &num_index, 0, &pos)); zend_hash_move_forward_ex(args, &pos)) { zend_hash_get_current_data_ex(args, (void *)&cur_val, &pos); if (hash_key_type == HASH_KEY_IS_STRING && (*(ZEND_HASH_KEY_STRVAL(cur_key))=='@' && *(Z_STRVAL_PP(cur_val))=='@')) { soo->is_multipart = 1; break; } } } for (zend_hash_internal_pointer_reset_ex(args, &pos); HASH_KEY_NON_EXISTANT!=(hash_key_type=zend_hash_get_current_key_ex(args, &cur_key, &cur_key_len, &num_index, 0, &pos)); zend_hash_move_forward_ex(args, &pos)) { zend_hash_get_current_data_ex(args, (void *)&cur_val, &pos); skip_append = 0; switch (hash_key_type) { case HASH_KEY_IS_STRING: if (soo && soo->is_multipart && strncmp(ZEND_HASH_KEY_STRVAL(cur_key), "oauth_", 6) != 0) { found = 0; for (i=0; imultipart_files_num; ++i) { if (0 == strcmp(soo->multipart_params[i], ZEND_HASH_KEY_STRVAL(cur_key))) { found = 1; break; } } if (found) { continue; } soo->multipart_files = erealloc(soo->multipart_files, sizeof(char *) * (soo->multipart_files_num + 1)); soo->multipart_params = erealloc(soo->multipart_params, sizeof(char *) * (soo->multipart_files_num + 1)); convert_to_string_ex(cur_val); soo->multipart_files[soo->multipart_files_num] = Z_STRVAL_PP(cur_val); soo->multipart_params[soo->multipart_files_num] = ZEND_HASH_KEY_STRVAL(cur_key); ++soo->multipart_files_num; /* we don't add multipart files to the params */ skip_append = 1; } else { arg_key = oauth_url_encode(ZEND_HASH_KEY_STRVAL(cur_key), cur_key_len-1); } break; case HASH_KEY_IS_LONG: /* take value of num_index instead */ arg_key = NULL; break; #if (PHP_MAJOR_VERSION >= 6) case HASH_KEY_IS_UNICODE: { char *temp; int temp_len; zend_unicode_to_string(UG(utf8_conv), &temp, &temp_len, cur_key.u, cur_key_len-1 TSRMLS_CC); arg_key = oauth_url_encode(temp, temp_len); efree(temp); } break; #endif default: continue; } if (skip_append) { continue; } INIT_SMART_STR(keyname); if (arg_key) { smart_str_appends(&keyname, arg_key); efree(arg_key); } else { smart_str_append_unsigned(&keyname, num_index); } if (IS_ARRAY==Z_TYPE_PP(cur_val)) { HashPosition val_pos; zval **val_cur_val; /* make shallow copy */ SEPARATE_ZVAL(cur_val); /* sort array based on string comparison */ zend_hash_sort(Z_ARRVAL_PP(cur_val), zend_qsort, oauth_compare_value, 1 TSRMLS_CC); /* traverse array */ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(cur_val), &val_pos); while (SUCCESS==zend_hash_get_current_data_ex(Z_ARRVAL_PP(cur_val), (void **)&val_cur_val, &val_pos)) { if (prepend_amp) { smart_str_appendc(s, '&'); } smart_str_append(s, &keyname); param_value = oauth_http_encode_value(val_cur_val TSRMLS_CC); if (param_value) { smart_str_appendc(s, '='); smart_str_appends(s, param_value); efree(param_value); } prepend_amp = TRUE; ++numargs; zend_hash_move_forward_ex(Z_ARRVAL_PP(cur_val), &val_pos); } /* clean up */ } else { if (prepend_amp) { smart_str_appendc(s, '&'); } smart_str_append(s, &keyname); param_value = oauth_http_encode_value(cur_val TSRMLS_CC); if (param_value) { smart_str_appendc(s, '='); smart_str_appends(s, param_value); efree(param_value); } prepend_amp = TRUE; ++numargs; } smart_str_free(&keyname); smart_str_0(s); } } return numargs; } /* retrieves parameter value from the _GET or _POST superglobal */ void get_request_param(char *arg_name, char **return_val, int *return_len TSRMLS_DC) { zval **ptr; if ( (PG(http_globals)[TRACK_VARS_GET] && SUCCESS==zend_hash_find(HASH_OF(PG(http_globals)[TRACK_VARS_GET]), arg_name, strlen(arg_name)+1, (void*)&ptr) && IS_STRING==Z_TYPE_PP(ptr)) || (PG(http_globals)[TRACK_VARS_POST] && SUCCESS==zend_hash_find(HASH_OF(PG(http_globals)[TRACK_VARS_POST]), arg_name, strlen(arg_name)+1, (void*)&ptr) && IS_STRING==Z_TYPE_PP(ptr)) ) { *return_val = Z_STRVAL_PP(ptr); *return_len = Z_STRLEN_PP(ptr); return; } *return_val = NULL; *return_len = 0; } /* * This function does not currently care to respect parameter precedence, in the sense that if a common param is defined * in POST/GET or Authorization header, the precendence is defined by: OAuth Core 1.0 section 9.1.1 */ char *oauth_generate_sig_base(php_so_object *soo, const char *http_method, const char *uri, HashTable *post_args, HashTable *extra_args TSRMLS_DC) /* {{{ */ { zval *params; char *query; char *s_port = NULL, *bufz = NULL, *sbs_query_part = NULL, *sbs_scheme_part = NULL; php_url *urlparts; smart_str sbuf = {0}; urlparts = php_url_parse_ex(uri, strlen(uri)); if (urlparts) { if (!urlparts->host || !urlparts->scheme) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid url when trying to build base signature string", NULL, NULL TSRMLS_CC); php_url_free(urlparts); return NULL; } smart_str_appends(&sbuf, urlparts->scheme); smart_str_appends(&sbuf, "://"); smart_str_appends(&sbuf, urlparts->host); if (urlparts->port && ((!strcmp("http", urlparts->scheme) && OAUTH_HTTP_PORT != urlparts->port) || (!strcmp("https", urlparts->scheme) && OAUTH_HTTPS_PORT != urlparts->port))) { spprintf(&s_port, 0, "%d", urlparts->port); smart_str_appendc(&sbuf, ':'); smart_str_appends(&sbuf, s_port); efree(s_port); } if (urlparts->path) { smart_str squery = {0}; smart_str_appends(&sbuf, urlparts->path); smart_str_0(&sbuf); MAKE_STD_ZVAL(params); array_init(params); /* merge order = oauth_args - extra_args - query */ if (post_args) { zval *tmp_copy; zend_hash_merge(Z_ARRVAL_P(params), post_args, (copy_ctor_func_t) zval_add_ref, (void *)&tmp_copy, sizeof(zval *), 0); } if (extra_args) { zval *tmp_copy; zend_hash_merge(Z_ARRVAL_P(params), extra_args, (copy_ctor_func_t) zval_add_ref, (void *)&tmp_copy, sizeof(zval *), 0); } if (urlparts->query) { query = estrdup(urlparts->query); oauth_parse_str(query, params TSRMLS_CC); efree(query); } /* remove oauth_signature if it's in the hash */ #if (PHP_MAJOR_VERSION >= 6) zend_ascii_hash_del(Z_ARRVAL_P(params), OAUTH_PARAM_SIGNATURE, sizeof(OAUTH_PARAM_SIGNATURE)); #else zend_hash_del(Z_ARRVAL_P(params), OAUTH_PARAM_SIGNATURE, sizeof(OAUTH_PARAM_SIGNATURE)); #endif /* exret2 = uksort(&exargs2[0], "strnatcmp") */ zend_hash_sort(Z_ARRVAL_P(params), zend_qsort, oauth_compare_key, 0 TSRMLS_CC); oauth_http_build_query(soo, &squery, Z_ARRVAL_P(params), FALSE TSRMLS_CC); smart_str_0(&squery); zval_ptr_dtor(¶ms); sbs_query_part = oauth_url_encode(squery.c, squery.len); sbs_scheme_part = oauth_url_encode(sbuf.c, sbuf.len); spprintf(&bufz, 0, "%s&%s&%s", http_method, sbs_scheme_part, sbs_query_part?sbs_query_part:""); /* TODO move this into oauth_get_http_method() soo_handle_error(OAUTH_ERR_INTERNAL_ERROR, "Invalid auth type", NULL TSRMLS_CC); */ if(sbs_query_part) { efree(sbs_query_part); } if(sbs_scheme_part) { efree(sbs_scheme_part); } smart_str_free(&squery); } else { /* Bug 22630 - throw exception if no path given */ soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid path (perhaps you only specified the hostname? try adding a slash at the end)", NULL, NULL TSRMLS_CC); return NULL; } smart_str_free(&sbuf); php_url_free(urlparts); if(soo && soo->debug) { if(soo->debug_info->sbs) { efree(soo->debug_info->sbs); } soo->debug_info->sbs = bufz?estrdup(bufz):NULL; } return bufz; } return NULL; } /* }}} */ static void oauth_set_debug_info(php_so_object *soo TSRMLS_DC) { zval *debugInfo; char *tmp; if (soo->debug_info) { debugInfo = soo->debugArr; if(!debugInfo) { ALLOC_INIT_ZVAL(debugInfo); array_init(debugInfo); } else { FREE_ARGS_HASH(HASH_OF(debugInfo)); array_init(debugInfo); } if(soo->debug_info->sbs) { add_assoc_string(debugInfo, "sbs", soo->debug_info->sbs, 1); } ADD_DEBUG_INFO(debugInfo, "headers_sent", soo->debug_info->headers_out, 1); ADD_DEBUG_INFO(debugInfo, "headers_recv", soo->headers_in, 1); ADD_DEBUG_INFO(debugInfo, "body_sent", soo->debug_info->body_out, 0); ADD_DEBUG_INFO(debugInfo, "body_recv", soo->debug_info->body_in, 0); ADD_DEBUG_INFO(debugInfo, "info", soo->debug_info->curl_info, 0); zend_update_property(soo_class_entry, soo->this_ptr, "debugInfo", sizeof("debugInfo") - 1, debugInfo TSRMLS_CC); soo->debugArr = debugInfo; } else { soo->debugArr = NULL; } } static int add_arg_for_req(HashTable *ht, const char *arg, const char *val TSRMLS_DC) /* {{{ */ { zval *varg; ulong h; MAKE_STD_ZVAL(varg); ZVAL_STRING(varg, (char *)val, 1); h = zend_hash_func((char *)arg, strlen(arg)+1); zend_hash_quick_update(ht, (char *)arg, strlen(arg)+1, h, &varg, sizeof(zval *), NULL); return SUCCESS; } /* }}} */ void oauth_add_signature_header(HashTable *request_headers, HashTable *oauth_args, smart_str *header TSRMLS_DC) { smart_str sheader = {0}; zend_bool prepend_comma = FALSE; zval **curval; char *param_name, *param_val; zend_hash_key_type cur_key; uint cur_key_len; ulong num_key; smart_str_appends(&sheader, "OAuth "); for (zend_hash_internal_pointer_reset(oauth_args); zend_hash_get_current_data(oauth_args, (void *)&curval) == SUCCESS; zend_hash_move_forward(oauth_args)) { zend_hash_get_current_key_ex(oauth_args, &cur_key, &cur_key_len, &num_key, 0, NULL); if (prepend_comma) { smart_str_appendc(&sheader, ','); } param_name = oauth_url_encode(ZEND_HASH_KEY_STRVAL(cur_key), cur_key_len-1); param_val = oauth_url_encode(Z_STRVAL_PP(curval), Z_STRLEN_PP(curval)); smart_str_appends(&sheader, param_name); smart_str_appendc(&sheader, '='); smart_str_appends(&sheader, "\""); smart_str_appends(&sheader, param_val); smart_str_appends(&sheader, "\""); efree(param_name); efree(param_val); prepend_comma = TRUE; } smart_str_0(&sheader); if (!header) { add_arg_for_req(request_headers, "Authorization", sheader.c TSRMLS_CC); } else { smart_str_appends(header, sheader.c); } smart_str_free(&sheader); } #define HTTP_RESPONSE_CAAS(zvalpp, header, storkey) { \ if (0==strncasecmp(Z_STRVAL_PP(zvalpp),header,sizeof(header)-1)) { \ CAAS(storkey, (Z_STRVAL_PP(zvalpp)+sizeof(header)-1)); \ } \ } #define HTTP_RESPONSE_CAAD(zvalpp, header, storkey) { \ if (0==strncasecmp(Z_STRVAL_PP(zvalpp),header,sizeof(header)-1)) { \ CAAD(storkey, strtoul(Z_STRVAL_PP(zvalpp)+sizeof(header)-1,NULL,10)); \ } \ } #define HTTP_RESPONSE_CODE(zvalpp) \ if (response_code < 0 && 0==strncasecmp(Z_STRVAL_PP(zvalpp),"HTTP/", 5) && Z_STRLEN_PP(zvalpp)>=12) { \ response_code = strtol(Z_STRVAL_PP(zvalpp)+9, NULL, 10); \ CAAL("http_code", response_code); \ } #define HTTP_RESPONSE_LOCATION(zvalpp) \ if (0==strncasecmp(Z_STRVAL_PP(zvalpp), "Location: ", 10)) { \ strlcpy(soo->last_location_header, Z_STRVAL_PP(zvalpp)+10, OAUTH_MAX_HEADER_LEN); \ } static long make_req_streams(php_so_object *soo, const char *url, const smart_str *payload, const char *http_method, HashTable *request_headers TSRMLS_DC) /* {{{ */ { php_stream_context *sc; zval zpayload, zmethod, zredirects, zerrign; long response_code = -1; php_stream *s; int set_form_content_type = 0; php_netstream_data_t *sock; struct timeval tv; int secs = 0; #ifdef ZEND_ENGINE_2_4 sc = php_stream_context_alloc(TSRMLS_C); #else sc = php_stream_context_alloc(); #endif if (payload->len) { smart_str_0(payload); ZVAL_STRINGL(&zpayload, payload->c, payload->len, 0); php_stream_context_set_option(sc, "http", "content", &zpayload); /** * remember to set application/x-www-form-urlencoded content-type later on * lest the php streams guys come and beat you up */ set_form_content_type = 1; } if (request_headers) { zval **cur_val, zheaders; zend_hash_key_type cur_key; uint cur_key_len; ulong num_key; smart_str sheaders = {0}; int first = 1; for (zend_hash_internal_pointer_reset(request_headers); zend_hash_get_current_data(request_headers, (void *)&cur_val) == SUCCESS; zend_hash_move_forward(request_headers)) { /* check if a string based key is used */ smart_str sheaderline = {0}; switch (zend_hash_get_current_key_ex(request_headers, &cur_key, &cur_key_len, &num_key, 0, NULL)) { #if (PHP_MAJOR_VERSION >= 6) case HASH_KEY_IS_UNICODE: { char *temp; int temp_len; zend_unicode_to_string(UG(utf8_conv), &temp, &temp_len, cur_key.u, cur_key_len-1 TSRMLS_CC); smart_str_appendl(&sheaderline, temp, temp_len); efree(temp); } break; #endif case HASH_KEY_IS_STRING: smart_str_appendl(&sheaderline, ZEND_HASH_KEY_STRVAL(cur_key), cur_key_len-1); break; default: continue; } smart_str_0(&sheaderline); if (!strcasecmp(sheaderline.c,"content-type")) { set_form_content_type = 0; } smart_str_appends(&sheaderline, ": "); switch (Z_TYPE_PP(cur_val)) { case IS_STRING: smart_str_appendl(&sheaderline, Z_STRVAL_PP(cur_val), Z_STRLEN_PP(cur_val)); break; #if (PHP_MAJOR_VERSION >= 6) case IS_UNICODE: { char *temp; int temp_len; zend_unicode_to_string(UG(utf8_conv), &temp, &temp_len, Z_USTRVAL_PP(cur_val), Z_USTRLEN_PP(cur_val) TSRMLS_CC); smart_str_appendl(&sheaderline, temp, temp_len); efree(temp); } break; #endif default: smart_str_free(&sheaderline); continue; } if (!first) { smart_str_appends(&sheaders, "\r\n"); } else { first = 0; } smart_str_append(&sheaders, &sheaderline); smart_str_free(&sheaderline); } if (set_form_content_type) { /* still need to add our own content-type? */ if (!first) { smart_str_appends(&sheaders, "\r\n"); } smart_str_appends(&sheaders, "Content-Type: application/x-www-form-urlencoded"); } if (sheaders.len) { smart_str_0(&sheaders); ZVAL_STRINGL(&zheaders, sheaders.c, sheaders.len, 0); php_stream_context_set_option(sc, "http", "header", &zheaders); if (soo->debug) { smart_str_append(&soo->debug_info->headers_out, &sheaders); } } smart_str_free(&sheaders); } /* set method */ ZVAL_STRING(&zmethod, (char*)http_method, 0); php_stream_context_set_option(sc, "http", "method", &zmethod); /* set maximum redirects; who came up with the ridiculous logic of <= 1 means no redirects ?? */ ZVAL_LONG(&zredirects, 1L); php_stream_context_set_option(sc, "http", "max_redirects", &zredirects); /* using special extension to treat redirects as regular document (requires patch in php) */ ZVAL_BOOL(&zerrign, TRUE); php_stream_context_set_option(sc, "http", "ignore_errors", &zerrign); smart_str_free(&soo->lastresponse); smart_str_free(&soo->headers_in); if ((s = php_stream_open_wrapper_ex((char*)url, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL, sc))) { zval *info; char *buf; size_t rb; ALLOC_INIT_ZVAL(info); array_init(info); CAAS("url", url); if (s->wrapperdata) { zval **tmp; zend_hash_internal_pointer_reset(Z_ARRVAL_P(s->wrapperdata)); while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(s->wrapperdata), (void *)&tmp)) { smart_str_appendl(&soo->headers_in, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); smart_str_appends(&soo->headers_in, "\r\n"); HTTP_RESPONSE_CODE(tmp); HTTP_RESPONSE_LOCATION(tmp); HTTP_RESPONSE_CAAS(tmp, "Content-Type: ", "content_type"); HTTP_RESPONSE_CAAD(tmp, "Content-Length: ", "download_content_length"); zend_hash_move_forward(Z_ARRVAL_P(s->wrapperdata)); } if (HTTP_IS_REDIRECT(response_code) && soo->last_location_header) { CAAS("redirect_url", soo->last_location_header); } } if(soo->timeout) { sock = (php_netstream_data_t*)s->abstract; secs = soo->timeout / 1000; tv.tv_sec = secs; tv.tv_usec = ((soo->timeout - (secs * 1000)) * 1000) % 1000000; sock->timeout = tv; } if ((rb = php_stream_copy_to_mem(s, (void*)&buf, PHP_STREAM_COPY_ALL, 0)) > 0) { smart_str_appendl(&soo->lastresponse, buf, rb); pefree(buf, 0); } smart_str_0(&soo->lastresponse); smart_str_0(&soo->headers_in); CAAD("size_download", rb); CAAD("size_upload", payload->len); so_set_response_info(soo->properties, info); php_stream_close(s); } else { char *bufz; spprintf(&bufz, 0, "making the request failed (%s)", "dunno why"); soo_handle_error(soo, -1, bufz, soo->lastresponse.c, NULL TSRMLS_CC); efree(bufz); } if(soo->debug) { smart_str_append(&soo->debug_info->body_in, &soo->lastresponse); smart_str_append(&soo->debug_info->body_out, payload); } return response_code; } /* }}} */ #if OAUTH_USE_CURL static size_t soo_read_response(char *ptr, size_t size, size_t nmemb, void *ctx) /* {{{ */ { uint relsize; php_so_object *soo = (php_so_object *)ctx; relsize = size * nmemb; smart_str_appendl(&soo->lastresponse, ptr, relsize); return relsize; } /* }}} */ int oauth_debug_handler(CURL *ch, curl_infotype type, char *data, size_t data_len, void *ctx) /* {{{ */ { php_so_debug *sdbg; char *z_data = NULL; smart_str *dest; if(data_len > 1 && data[0]=='\r' && data[1]=='\n') { /* ignore \r\n */ return 0; } sdbg = (php_so_debug *)ctx; z_data = emalloc(data_len + 2); memset(z_data, 0, data_len + 2); memcpy(z_data, data, data_len); z_data[data_len] = '\0'; switch(type) { case CURLINFO_TEXT: dest = &sdbg->curl_info; break; case CURLINFO_HEADER_OUT: dest = &sdbg->headers_out; break; case CURLINFO_DATA_IN: dest = &sdbg->body_in; break; case CURLINFO_DATA_OUT: dest = &sdbg->body_out; break; default: dest = NULL; } if(dest) { smart_str_appends(dest, z_data); } efree(z_data); return 0; } /* }}} */ static size_t soo_read_header(void *ptr, size_t size, size_t nmemb, void *ctx) { char *header; size_t hlen, vpos = sizeof("Location:") - 1; php_so_object *soo; header = (char *)ptr; hlen = nmemb * size; soo = (php_so_object *)ctx; /* handle Location header */ if (hlen > vpos && 0==strncasecmp(header, "Location:", vpos)) { size_t eol = hlen; /* find value start */ while (vpos != eol && ' '==header[vpos]) { ++vpos; } /* POST: vpos == eol OR vpos < eol => value start found */ while (vpos != eol && strchr("\r\n\0", header[eol - 1])) { --eol; } /* POST: vpos == eol OR vpos < eol => value end found */ if (vpos != eol) { if (eol - vpos >= OAUTH_MAX_HEADER_LEN) { eol = vpos + OAUTH_MAX_HEADER_LEN - 1; } /* POST: eol - vpos <= OAUTH_MAX_HEADER_LEN */ strncpy(soo->last_location_header, header + vpos, eol - vpos); } soo->last_location_header[eol - vpos] = '\0'; } if(strncasecmp(header, "\r\n", 2)) { smart_str_appendl(&soo->headers_in, header, hlen); } return hlen; } long make_req_curl(php_so_object *soo, const char *url, const smart_str *payload, const char *http_method, HashTable *request_headers TSRMLS_DC) /* {{{ */ { CURLcode cres, ctres, crres; CURL *curl; struct curl_slist *curl_headers = NULL; long l_code, response_code = -1; double d_code; zval *info, **zca_info, **zca_path, **cur_val; char *s_code, *content_type = NULL, *bufz = NULL; char *auth_type = NULL; uint cur_key_len, sslcheck; ulong num_key; smart_str sheader = {0}; zend_hash_key_type cur_key; auth_type = Z_STRVAL_PP(soo_get_property(soo, OAUTH_ATTR_AUTHMETHOD TSRMLS_CC)); zca_info = soo_get_property(soo, OAUTH_ATTR_CA_INFO TSRMLS_CC); zca_path = soo_get_property(soo, OAUTH_ATTR_CA_PATH TSRMLS_CC); sslcheck = soo->sslcheck; curl = curl_easy_init(); if (request_headers) { for (zend_hash_internal_pointer_reset(request_headers); zend_hash_get_current_data(request_headers, (void *)&cur_val) == SUCCESS; zend_hash_move_forward(request_headers)) { /* check if a string based key is used */ switch (zend_hash_get_current_key_ex(request_headers, &cur_key, &cur_key_len, &num_key, 0, NULL)) { #if (PHP_MAJOR_VERSION >= 6) case HASH_KEY_IS_UNICODE: { char *temp; int temp_len; zend_unicode_to_string(UG(utf8_conv), &temp, &temp_len, cur_key.u, cur_key_len-1 TSRMLS_CC); smart_str_appendl(&sheader, temp, temp_len); efree(temp); } break; #endif case HASH_KEY_IS_STRING: smart_str_appendl(&sheader, ZEND_HASH_KEY_STRVAL(cur_key), cur_key_len-1); break; default: continue; } smart_str_appends(&sheader, ": "); switch (Z_TYPE_PP(cur_val)) { case IS_STRING: smart_str_appendl(&sheader, Z_STRVAL_PP(cur_val), Z_STRLEN_PP(cur_val)); break; #if (PHP_MAJOR_VERSION >= 6) case IS_UNICODE: { char *temp; int temp_len; zend_unicode_to_string(UG(utf8_conv), &temp, &temp_len, Z_USTRVAL_PP(cur_val), Z_USTRLEN_PP(cur_val) TSRMLS_CC); smart_str_appendl(&sheader, temp, temp_len); efree(temp); } break; #endif default: smart_str_free(&sheader); continue; } smart_str_0(&sheader); curl_headers = curl_slist_append(curl_headers, sheader.c); smart_str_free(&sheader); } } if(soo->is_multipart) { struct curl_httppost *ff = NULL; struct curl_httppost *lf = NULL; int i; for(i=0; i < soo->multipart_files_num; i++) { char *type, *filename, *postval; /* swiped from ext/curl/interface.c to help with consistency */ postval = estrdup(soo->multipart_files[i]); if (postval[0] == '@' && soo->multipart_params[i][0] == '@') { /* :< (chomp) @ */ ++soo->multipart_params[i]; ++postval; if((type = php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + strlen(soo->multipart_files[i]) - 1))) { *type = '\0'; } if((filename = php_memnstr(postval, ";filename=", sizeof(";filename=") - 1, postval + strlen(soo->multipart_files[i]) - 1))) { *filename = '\0'; } /* open_basedir check */ if(php_check_open_basedir(postval TSRMLS_CC)) { char *em; spprintf(&em, 0, "failed to open file for multipart request: %s", postval); soo_handle_error(soo, -1, em, NULL, NULL TSRMLS_CC); efree(em); return 1; } curl_formadd(&ff, &lf, CURLFORM_COPYNAME, soo->multipart_params[i], CURLFORM_NAMELENGTH, (long)strlen(soo->multipart_params[i]), CURLFORM_FILENAME, filename ? filename + sizeof(";filename=") - 1 : soo->multipart_files[i], CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream", CURLFORM_FILE, postval, CURLFORM_END); } else { curl_formadd(&ff, &lf, CURLFORM_COPYNAME, soo->multipart_params[i], CURLFORM_NAMELENGTH, (long)strlen(soo->multipart_params[i]), CURLFORM_COPYCONTENTS, postval, CURLFORM_CONTENTSLENGTH, (long)strlen(postval), CURLFORM_END); } } curl_easy_setopt(curl, CURLOPT_HTTPPOST, ff); } else if (payload->len) { curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload->c); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, payload->len); } curl_easy_setopt(curl, CURLOPT_URL, url); /* the fetch method takes precedence so figure it out after we've added the OAuth params */ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_method); /* Disable sending the 100 Expect header for POST requests */ /* Other notes: if there is a redirect the POST becomes a GET request, see curl_easy_setopt(3) and the CURLOPT_POSTREDIR option for more information */ curl_headers = curl_slist_append(curl_headers, "Expect:"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers); curl_easy_setopt(curl, CURLOPT_USERAGENT, OAUTH_USER_AGENT); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, soo_read_response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, soo); if(sslcheck == OAUTH_SSLCHECK_NONE) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); } else { if (!(sslcheck & OAUTH_SSLCHECK_HOST)) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); } if (!(sslcheck & OAUTH_SSLCHECK_PEER)) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); } if(zca_path && Z_STRLEN_PP(zca_path)) { curl_easy_setopt(curl, CURLOPT_CAPATH, Z_STRVAL_PP(zca_path)); } if(zca_info && Z_STRLEN_PP(zca_info)) { curl_easy_setopt(curl, CURLOPT_CAINFO, Z_STRVAL_PP(zca_info)); } } curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, soo_read_header); curl_easy_setopt(curl, CURLOPT_WRITEHEADER, soo); if(soo->debug) { curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); } #if defined(ZTS) curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); #endif #if LIBCURL_VERSION_NUM >= 0x071304 curl_easy_setopt(curl, CURLOPT_PROTOCOLS, OAUTH_PROTOCOLS_ALLOWED); #endif #if LIBCURL_VERSION_NUM > 0x071002 if(soo->timeout) { curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, soo->timeout); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, soo->timeout); } #endif smart_str_free(&soo->lastresponse); smart_str_free(&soo->headers_in); if(soo->debug) { curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, oauth_debug_handler); curl_easy_setopt(curl, CURLOPT_DEBUGDATA, soo->debug_info); } cres = curl_easy_perform(curl); smart_str_0(&soo->lastresponse); smart_str_0(&soo->headers_in); if (curl_headers) { curl_slist_free_all(curl_headers); } if (CURLE_OK == cres) { ctres = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &content_type); crres = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); if (CURLE_OK == crres && ctres == CURLE_OK) { ALLOC_INIT_ZVAL(info); array_init(info); CAAL("http_code", response_code); if (HTTP_IS_REDIRECT(response_code) && soo->last_location_header) { CAAS("redirect_url", soo->last_location_header); } if (content_type != NULL) { CAAS("content_type", content_type); } if (curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &s_code) == CURLE_OK) { CAAS("url", s_code); } if (curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &l_code) == CURLE_OK) { CAAL("header_size", l_code); } if (curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &l_code) == CURLE_OK) { CAAL("request_size", l_code); } if (curl_easy_getinfo(curl, CURLINFO_FILETIME, &l_code) == CURLE_OK) { CAAL("filetime", l_code); } if (curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT, &l_code) == CURLE_OK) { CAAL("ssl_verify_result", l_code); } if (curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &l_code) == CURLE_OK) { CAAL("redirect_count", l_code); } if (curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME,&d_code) == CURLE_OK) { CAAD("total_time", d_code); } if (curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME, &d_code) == CURLE_OK) { CAAD("namelookup_time", d_code); } if (curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &d_code) == CURLE_OK) { CAAD("connect_time", d_code); } if (curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &d_code) == CURLE_OK) { CAAD("pretransfer_time", d_code); } if (curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &d_code) == CURLE_OK){ CAAD("size_upload", d_code); } if (curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK){ CAAD("size_download", d_code); } if (curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK){ CAAD("speed_download", d_code); } if (curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &d_code) == CURLE_OK){ CAAD("speed_upload", d_code); } if (curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d_code) == CURLE_OK) { CAAD("download_content_length", d_code); } if (curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD, &d_code) == CURLE_OK) { CAAD("upload_content_length", d_code); } if (curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &d_code) == CURLE_OK){ CAAD("starttransfer_time", d_code); } if (curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME, &d_code) == CURLE_OK){ CAAD("redirect_time", d_code); } CAAS("headers_recv", soo->headers_in.c); so_set_response_info(soo->properties, info); } } else { spprintf(&bufz, 0, "making the request failed (%s)", curl_easy_strerror(cres)); soo_handle_error(soo, -1, bufz, soo->lastresponse.c, NULL TSRMLS_CC); efree(bufz); } curl_easy_cleanup(curl); return response_code; } /* }}} */ #endif static void make_standard_query(HashTable *ht, php_so_object *soo TSRMLS_DC) /* {{{ */ { char *ts, *nonce; if (soo->timestamp) { ts = estrdup(soo->timestamp); } else { time_t now = time(NULL); /* XXX allow caller to set timestamp, if none set, then default to "now" */ spprintf(&ts, 0, "%d", (int)now); } if (soo->nonce) { nonce = estrdup(soo->nonce); } else { struct timeval tv; int sec, usec; /* XXX maybe find a better way to generate a nonce... */ gettimeofday((struct timeval *) &tv, (struct timezone *) NULL); sec = (int) tv.tv_sec; usec = (int) (tv.tv_usec % 0x100000); spprintf(&nonce, 0, "%ld%08x%05x%.8f", php_rand(TSRMLS_C), sec, usec, php_combined_lcg(TSRMLS_C) * 10); } add_arg_for_req(ht, OAUTH_PARAM_CONSUMER_KEY, Z_STRVAL_PP(soo_get_property(soo, OAUTH_ATTR_CONSUMER_KEY TSRMLS_CC)) TSRMLS_CC); add_arg_for_req(ht, OAUTH_PARAM_SIGNATURE_METHOD, Z_STRVAL_PP(soo_get_property(soo, OAUTH_ATTR_SIGMETHOD TSRMLS_CC)) TSRMLS_CC); add_arg_for_req(ht, OAUTH_PARAM_NONCE, nonce TSRMLS_CC); add_arg_for_req(ht, OAUTH_PARAM_TIMESTAMP, ts TSRMLS_CC); add_arg_for_req(ht, OAUTH_PARAM_VERSION, Z_STRVAL_PP(soo_get_property(soo, OAUTH_ATTR_OAUTH_VERSION TSRMLS_CC)) TSRMLS_CC); efree(ts); efree(nonce); } /* }}} */ /* Returns the default http method to use with the different auth types */ static const char *oauth_get_http_method(php_so_object *soo, const char *http_method TSRMLS_DC) /* {{{ */ { long auth_type = Z_LVAL_PP(soo_get_property(soo, OAUTH_ATTR_AUTHMETHOD TSRMLS_CC)); if (http_method) { /* TODO handle conflict with FORM auth and anything but POST or PUT */ return http_method; } /* http method not explicitly given, choose default one */ if (OAUTH_AUTH_TYPE_FORM==auth_type) { return OAUTH_HTTP_METHOD_POST; } else { return OAUTH_HTTP_METHOD_GET; } } /* }}} */ /* Modifies (and returns) passed url parameter to be used for additional parameter appending */ static smart_str *http_prepare_url_concat(smart_str *surl) /* {{{ */ { smart_str_0(surl); if (!strchr(surl->c, '?')) { smart_str_appendc(surl, '?'); } else { smart_str_appendc(surl, '&'); } return surl; } /* }}} */ /* Modifies passed url based on the location header that was received in the response headers, depending on whether the redirection was relative or absolute */ static void oauth_apply_url_redirect(smart_str *surl, const char *location) /* {{{ */ { php_url *urlparts; /* determine whether location is relative */ if ('/'==*location) { urlparts = php_url_parse_ex(surl->c, surl->len); /* rebuild url from scratch */ smart_str_free(surl); if (urlparts->scheme) { smart_str_appends(surl, urlparts->scheme); smart_str_appends(surl, "://"); } if (urlparts->host) { smart_str_appends(surl, urlparts->host); } if (urlparts->port) { smart_str_appendc(surl, ':'); smart_str_append_unsigned(surl, urlparts->port); } smart_str_appends(surl, location); php_url_free(urlparts); } else { smart_str_free(surl); smart_str_appends(surl, location); } } /* }}} */ /* Prepares the request elements to be used by make_req(); this should allow for supporting streams in the future */ static long oauth_fetch(php_so_object *soo, const char *url, const char *method, zval *request_params, zval *request_headers, HashTable *init_oauth_args, int fetch_flags TSRMLS_DC) /* {{{ */ { char *sbs = NULL, *sig = NULL, *bufz = NULL; const char *final_http_method; zval **token = NULL, **cs; zval *ts = NULL, **token_secret = NULL; zval *zret; HashTable *oauth_args = NULL; HashTable *rargs = NULL, *rheaders = NULL; long http_response_code, auth_type; smart_str surl = {0}, payload = {0}, postdata = {0}; uint is_redirect = FALSE, follow_redirects = 0, need_to_free_rheaders = 0; auth_type = Z_LVAL_PP(soo_get_property(soo, OAUTH_ATTR_AUTHMETHOD TSRMLS_CC)); if(fetch_flags & OAUTH_OVERRIDE_HTTP_METHOD) { final_http_method = method; } else { final_http_method = oauth_get_http_method(soo, method ? method : OAUTH_HTTP_METHOD_POST TSRMLS_CC); if (OAUTH_AUTH_TYPE_FORM==auth_type && strcasecmp(final_http_method, OAUTH_HTTP_METHOD_POST)) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "auth type is set to HTTP POST with a non-POST http method, use setAuthType to put OAuth parameters somewhere else in the request", NULL, NULL TSRMLS_CC); } } if(!final_http_method) { final_http_method = "GET"; } follow_redirects = soo->follow_redirects; soo->redirects = 0; soo->multipart_files = NULL; soo->multipart_params = NULL; soo->multipart_files_num = 0; soo->is_multipart = 0; /* request_params can be either NULL, a string containing arbitrary text (such as XML) or an array */ if (request_params) { switch (Z_TYPE_P(request_params)) { case IS_ARRAY: rargs = HASH_OF(request_params); oauth_http_build_query(soo, &postdata, rargs, FALSE TSRMLS_CC); break; case IS_STRING: smart_str_appendl(&postdata, Z_STRVAL_P(request_params), Z_STRLEN_P(request_params)); break; } } /* additional http headers can be passed */ if (!request_headers) { ALLOC_HASHTABLE(rheaders); zend_hash_init(rheaders, 0, NULL, ZVAL_PTR_DTOR, 0); need_to_free_rheaders = 1; } else { rheaders = HASH_OF(request_headers); } /* initialize base url */ smart_str_appends(&surl, url); do { /* initialize response code */ http_response_code = -1; /* prepare oauth arguments to be signed */ ALLOC_HASHTABLE(oauth_args); zend_hash_init(oauth_args, 0, NULL, ZVAL_PTR_DTOR, 0); /* an array can be passed to prime special oauth parameters */ if (init_oauth_args) { zval *tmp_copy; /* populate oauth_args with given parameters */ zend_hash_copy(oauth_args, init_oauth_args, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); } /* fill in the standard set of oauth parameters */ make_standard_query(oauth_args, soo TSRMLS_CC); /* use token where applicable */ if (fetch_flags & OAUTH_FETCH_USETOKEN) { token = soo_get_property(soo, OAUTH_ATTR_TOKEN TSRMLS_CC); if (token) { add_arg_for_req(oauth_args, OAUTH_PARAM_TOKEN, Z_STRVAL_PP(token) TSRMLS_CC); } } /* generate sig base on the semi-final url */ smart_str_0(&surl); sbs = oauth_generate_sig_base(soo, final_http_method, surl.c, oauth_args, rargs TSRMLS_CC); if (!sbs) { FREE_ARGS_HASH(oauth_args); soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid protected resource url, unable to generate signature base string", NULL, NULL TSRMLS_CC); break; } cs = soo_get_property(soo, OAUTH_ATTR_CONSUMER_SECRET TSRMLS_CC); SEPARATE_ZVAL(cs); /* determine whether token should be used to sign the request */ if (fetch_flags & OAUTH_FETCH_USETOKEN) { token_secret = soo_get_property(soo, OAUTH_ATTR_TOKEN_SECRET TSRMLS_CC); if (token_secret && Z_STRLEN_PP(token_secret) > 0) { ts = *token_secret; } } if(soo->signature) { efree(soo->signature); } /* sign the request */ sig = soo_sign(soo, sbs, *cs, ts, soo->sig_ctx TSRMLS_CC); soo->signature = sig; efree(sbs); if(fetch_flags & OAUTH_FETCH_SIGONLY) { FREE_ARGS_HASH(oauth_args); smart_str_free(&surl); smart_str_free(&postdata); if(need_to_free_rheaders) { FREE_ARGS_HASH(rheaders); } return SUCCESS; } if (!sig) { FREE_ARGS_HASH(oauth_args); soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Signature generation failed", NULL, NULL TSRMLS_CC); break; } /* and add signature to the oauth parameters */ add_arg_for_req(oauth_args, OAUTH_PARAM_SIGNATURE, sig TSRMLS_CC); if(fetch_flags & OAUTH_FETCH_HEADONLY) { INIT_SMART_STR(soo->headers_out); oauth_add_signature_header(rheaders, oauth_args, &soo->headers_out TSRMLS_CC); smart_str_0(&payload); FREE_ARGS_HASH(oauth_args); smart_str_free(&surl); smart_str_free(&postdata); if(need_to_free_rheaders) { FREE_ARGS_HASH(rheaders); } return SUCCESS; } if (!strcmp(final_http_method, OAUTH_HTTP_METHOD_GET)) { /* GET request means to extend the url, but not for redirects obviously */ if (!is_redirect && postdata.len) { smart_str_append(http_prepare_url_concat(&surl), &postdata); } } else { /* otherwise populate post data */ smart_str_append(&payload, &postdata); } switch (auth_type) { case OAUTH_AUTH_TYPE_FORM: /* append/set post data with oauth parameters */ oauth_http_build_query(soo, &payload, oauth_args, payload.len TSRMLS_CC); smart_str_0(&payload); break; case OAUTH_AUTH_TYPE_URI: /* extend url request with oauth parameters */ if (!is_redirect) { oauth_http_build_query(soo, http_prepare_url_concat(&surl), oauth_args, FALSE TSRMLS_CC); } /* TODO look into merging oauth parameters if they occur in the current url */ break; case OAUTH_AUTH_TYPE_AUTHORIZATION: /* add http header with oauth parameters */ oauth_add_signature_header(rheaders, oauth_args, NULL TSRMLS_CC); break; } /* finalize endpoint url */ smart_str_0(&surl); if (soo->debug) { if(soo->debug_info->sbs) { FREE_DEBUG_INFO(soo->debug_info); } INIT_DEBUG_INFO(soo->debug_info); } switch (soo->reqengine) { case OAUTH_REQENGINE_STREAMS: http_response_code = make_req_streams(soo, surl.c, &payload, final_http_method, rheaders TSRMLS_CC); break; #if OAUTH_USE_CURL case OAUTH_REQENGINE_CURL: http_response_code = make_req_curl(soo, surl.c, &payload, final_http_method, rheaders TSRMLS_CC); if (soo->multipart_files_num) { efree(soo->multipart_files); efree(soo->multipart_params); soo->multipart_files_num = 0; soo->is_multipart = 0; } break; #endif } is_redirect = HTTP_IS_REDIRECT(http_response_code); if(soo->debug) { oauth_set_debug_info(soo TSRMLS_CC); } FREE_ARGS_HASH(oauth_args); smart_str_free(&payload); if (is_redirect) { if (follow_redirects) { if (soo->redirects >= OAUTH_MAX_REDIRS) { spprintf(&bufz, 0, "max redirections exceeded (max: %ld last redirect url: %s)", OAUTH_MAX_REDIRS, soo->last_location_header); MAKE_STD_ZVAL(zret); if (soo->lastresponse.len) { ZVAL_STRING(zret, soo->lastresponse.c, 1); } else { ZVAL_STRING(zret, "", 1); } so_set_response_args(soo->properties, zret, NULL TSRMLS_CC); soo_handle_error(soo, http_response_code, bufz, soo->lastresponse.c, NULL TSRMLS_CC); efree(bufz); /* set http_response_code to error value */ http_response_code = -1; break; } else { ++soo->redirects; oauth_apply_url_redirect(&surl, soo->last_location_header); smart_str_0(&surl); /* bug 22628; keep same method when following redirects final_http_method = OAUTH_HTTP_METHOD_GET; */ } } } else if (http_response_code < 0) { /* exception would have been thrown already */ } else if (http_response_code < 200 || http_response_code > 206) { spprintf(&bufz, 0, "Invalid auth/bad request (got a %ld, expected HTTP/1.1 20X or a redirect)", http_response_code); MAKE_STD_ZVAL(zret); if(soo->lastresponse.c) { ZVAL_STRING(zret, soo->lastresponse.c, 1); } else { ZVAL_STRING(zret, "", 1); } so_set_response_args(soo->properties, zret, NULL TSRMLS_CC); soo_handle_error(soo, http_response_code, bufz, soo->lastresponse.c, NULL TSRMLS_CC); efree(bufz); /* set http_response_code to error value */ http_response_code = -1; break; } else { /* valid response, time to get out of this loop */ } } while (is_redirect && follow_redirects); smart_str_free(&surl); smart_str_free(&postdata); if(need_to_free_rheaders) { FREE_ARGS_HASH(rheaders); } return http_response_code; } /* }}} */ SO_METHOD(setRSACertificate) { char *key; int key_len; zval *args[1], *func, *retval; php_so_object *soo; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) { return; } MAKE_STD_ZVAL(func); ZVAL_STRING(func, "openssl_get_privatekey", 0); MAKE_STD_ZVAL(args[0]); ZVAL_STRINGL(args[0], key, key_len, 0); MAKE_STD_ZVAL(retval); call_user_function(EG(function_table), NULL, func, retval, 1, args TSRMLS_CC); FREE_ZVAL(args[0]); FREE_ZVAL(func); if (Z_TYPE_P(retval)==IS_RESOURCE) { OAUTH_SIGCTX_SET_PRIVATEKEY(soo->sig_ctx, retval); RETURN_TRUE; } else { zval_ptr_dtor(&retval); soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Could not parse RSA certificate", NULL, NULL TSRMLS_CC); return; } } /* {{{ proto string oauth_urlencode(string uri) URI encoding according to RFC 3986, note: is not utf8 capable until the underlying phpapi is */ PHP_FUNCTION(oauth_urlencode) { int uri_len; char *uri; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &uri, &uri_len) == FAILURE) { return; } if (uri_len < 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid uri length (0)"); RETURN_FALSE; } RETURN_STRING(oauth_url_encode(uri, uri_len), 0); } /* }}} */ /* {{{ proto string oauth_get_sbs(string http_method, string uri, array parameters) Get a signature base string */ PHP_FUNCTION(oauth_get_sbs) { char *uri, *http_method, *sbs; int uri_len, http_method_len; zval *req_params = NULL; HashTable *rparams = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a", &http_method, &http_method_len, &uri, &uri_len, &req_params) == FAILURE) { return; } if (uri_len < 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid uri length (0)"); RETURN_FALSE; } if (http_method_len < 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid http method length (0)"); RETURN_FALSE; } if (req_params) { rparams = HASH_OF(req_params); } if ((sbs = oauth_generate_sig_base(NULL, http_method, uri, NULL, rparams TSRMLS_CC))) { RETURN_STRING(sbs, 0); } else { RETURN_FALSE; } } /* }}} */ /* only hmac-sha1 is supported at the moment (it is the most common implementation), still need to lay down the ground work for supporting plaintext and others */ /* {{{ proto void OAuth::__construct(string consumer_key, string consumer_secret [, string signature_method, [, string auth_type ]]) Instantiate a new OAuth object */ SO_METHOD(__construct) { HashTable *hasht; char *ck, *cs, *sig_method = NULL; long auth_method = 0; zval *zck, *zcs, *zsm, *zam, *zver, *obj; int ck_len, cs_len, sig_method_len = 0; php_so_object *soo; obj = getThis(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|sl", &ck, &ck_len, &cs, &cs_len, &sig_method, &sig_method_len, &auth_method) == FAILURE) { ZVAL_NULL(obj); return; } soo = fetch_so_object(obj TSRMLS_CC); if(!ck_len) { soo_handle_error(soo, -1, "The consumer key cannot be empty", NULL, NULL TSRMLS_CC); return; } /* if(!cs_len) { soo_handle_error(soo, -1, "The consumer secret cannot be empty", NULL, NULL TSRMLS_CC); php_error(E_ERROR, "the consumer secret cannot be empty"); return; } */ memset(soo->last_location_header, 0, OAUTH_MAX_HEADER_LEN); soo->redirects = 0; soo->debug = 0; soo->debug_info = emalloc(sizeof(php_so_debug)); soo->debug_info->sbs = NULL; soo->debugArr = NULL; soo->nonce = NULL; soo->timestamp = NULL; soo->sig_ctx = NULL; INIT_DEBUG_INFO(soo->debug_info); INIT_SMART_STR(soo->headers_in); /* set default class members */ zend_update_property_null(soo_class_entry, obj, "debugInfo", sizeof("debugInfo") - 1 TSRMLS_CC); zend_update_property_bool(soo_class_entry, obj, "debug", sizeof("debug") - 1, soo->debug TSRMLS_CC); zend_update_property_long(soo_class_entry, obj, "sslChecks", sizeof("sslChecks") - 1, soo->sslcheck TSRMLS_CC); TSRMLS_SET_CTX(soo->thread_ctx); if (!sig_method_len) { sig_method = OAUTH_SIG_METHOD_HMACSHA1; } soo->sig_ctx = oauth_create_sig_context(sig_method); if (!auth_method) { auth_method = OAUTH_AUTH_TYPE_AUTHORIZATION; } if (soo->properties) { zend_hash_clean(soo->properties); hasht = soo->properties; } else { ALLOC_HASHTABLE(hasht); zend_hash_init(hasht, 0, NULL, ZVAL_PTR_DTOR, 0); soo->properties = hasht; } MAKE_STD_ZVAL(zck); ZVAL_STRING(zck, ck, 1); if (soo_set_property(soo, zck, OAUTH_ATTR_CONSUMER_KEY TSRMLS_CC) != SUCCESS) { return; } MAKE_STD_ZVAL(zcs); if (cs_len > 0) { ZVAL_STRING(zcs, oauth_url_encode(cs, cs_len), 0); } else { ZVAL_EMPTY_STRING(zcs); } if (soo_set_property(soo, zcs, OAUTH_ATTR_CONSUMER_SECRET TSRMLS_CC) != SUCCESS) { return; } MAKE_STD_ZVAL(zsm); ZVAL_STRING(zsm, sig_method, 1); if (soo_set_property(soo, zsm, OAUTH_ATTR_SIGMETHOD TSRMLS_CC) != SUCCESS) { return; } MAKE_STD_ZVAL(zam); ZVAL_LONG(zam, auth_method); if (soo_set_property(soo, zam, OAUTH_ATTR_AUTHMETHOD TSRMLS_CC) != SUCCESS) { return; } MAKE_STD_ZVAL(zver); ZVAL_STRING(zver, OAUTH_DEFAULT_VERSION, 1); if (soo_set_property(soo, zver, OAUTH_ATTR_OAUTH_VERSION TSRMLS_CC) != SUCCESS) { return; } soo->debug = 0; soo->sslcheck = OAUTH_SSLCHECK_BOTH; soo->follow_redirects = 1; soo->lastresponse.c = NULL; #if OAUTH_USE_CURL soo->reqengine = OAUTH_REQENGINE_CURL; #else soo->reqengine = OAUTH_REQENGINE_STREAMS; #endif } /* }}} */ void oauth_free_privatekey(zval *privatekey TSRMLS_DC) { zval *func, *retval; zval *args[1]; if (Z_TYPE_P(privatekey)==IS_RESOURCE) { MAKE_STD_ZVAL(retval); MAKE_STD_ZVAL(func); ZVAL_STRING(func, "openssl_freekey", 0); args[0] = privatekey; call_user_function(EG(function_table), NULL, func, retval, 1, args TSRMLS_CC); FREE_ZVAL(func); FREE_ZVAL(retval); } zval_ptr_dtor(&privatekey); } /* {{{ proto void OAuth::__destruct(void) clean up of OAuth object */ SO_METHOD(__destruct) { php_so_object *soo; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } oauth_prop_hash_dtor(soo TSRMLS_CC); if (soo->debug_info) { FREE_DEBUG_INFO(soo->debug_info); if (soo->debug_info->sbs) { efree(soo->debug_info->sbs); } efree(soo->debug_info); soo->debug_info = NULL; } smart_str_free(&soo->headers_in); if (soo->headers_out.c) { smart_str_free(&soo->headers_out); } if(soo->debugArr) { zval_ptr_dtor(&soo->debugArr); } OAUTH_SIGCTX_FREE(soo->sig_ctx); if (soo->nonce) { efree(soo->nonce); } if (soo->timestamp) { efree(soo->timestamp); } if(soo->signature) { efree(soo->signature); } } /* }}} */ /* {{{ proto array OAuth::setCAPath(string ca_path, string ca_info) Set the Certificate Authority information */ SO_METHOD(setCAPath) { php_so_object *soo; char *ca_path, *ca_info; int ca_path_len = 0, ca_info_len = 0; zval *zca_path, *zca_info; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &ca_path, &ca_path_len, &ca_info, &ca_info_len) == FAILURE) { return; } if (ca_path_len) { MAKE_STD_ZVAL(zca_path); ZVAL_STRINGL(zca_path, ca_path, ca_path_len, 1); if (soo_set_property(soo, zca_path, OAUTH_ATTR_CA_PATH TSRMLS_CC) != SUCCESS) { RETURN_FALSE; } } if (ca_info_len) { MAKE_STD_ZVAL(zca_info); ZVAL_STRINGL(zca_info, ca_info, ca_info_len, 1); if (soo_set_property(soo, zca_info, OAUTH_ATTR_CA_INFO TSRMLS_CC) != SUCCESS) { RETURN_FALSE; } } RETURN_TRUE; } /* }}} */ /* {{{ proto array OAuth::getCAPath(void) Get the Certificate Authority information */ SO_METHOD(getCAPath) { /* perhaps make this information available via members too? */ php_so_object *soo; zval **zca_path, **zca_info; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } zca_info = soo_get_property(soo, OAUTH_ATTR_CA_INFO TSRMLS_CC); zca_path = soo_get_property(soo, OAUTH_ATTR_CA_PATH TSRMLS_CC); array_init(return_value); if (zca_info || zca_path) { if(zca_info) { add_assoc_stringl(return_value, "ca_info", Z_STRVAL_PP(zca_info), Z_STRLEN_PP(zca_info), 1); } if(zca_path) { add_assoc_stringl(return_value, "ca_path", Z_STRVAL_PP(zca_path), Z_STRLEN_PP(zca_path), 1); } } } /* }}} */ /* {{{ proto array OAuth::getRequestToken(string request_token_url [, string callback_url ]) Get request token */ SO_METHOD(getRequestToken) { php_so_object *soo; zval *zret = NULL, *callback_url = NULL; char *url, *http_method = NULL; int url_len = 0, http_method_len = 0; long retcode; HashTable *args = NULL; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zs", &url, &url_len, &callback_url, &http_method, &http_method_len) == FAILURE) { return; } if (url_len < 1) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid request token url length", NULL, NULL TSRMLS_CC); RETURN_FALSE; } if (callback_url && IS_STRING==Z_TYPE_P(callback_url)) { ALLOC_HASHTABLE(args); zend_hash_init(args, 0, NULL, ZVAL_PTR_DTOR, 0); if (Z_STRLEN_P(callback_url) > 0) { add_arg_for_req(args, OAUTH_PARAM_CALLBACK, Z_STRVAL_P(callback_url) TSRMLS_CC); } else { /* empty callback url specified, treat as 1.0a */ add_arg_for_req(args, OAUTH_PARAM_CALLBACK, OAUTH_CALLBACK_OOB TSRMLS_CC); } } retcode = oauth_fetch(soo, url, oauth_get_http_method(soo, http_method TSRMLS_CC), NULL, NULL, args, 0 TSRMLS_CC); if (args) { FREE_ARGS_HASH(args); } if (retcode != -1 && soo->lastresponse.c) { array_init(return_value); MAKE_STD_ZVAL(zret); ZVAL_STRINGL(zret, soo->lastresponse.c, soo->lastresponse.len, 1); so_set_response_args(soo->properties, zret, return_value TSRMLS_CC); return; } RETURN_FALSE; } /* }}} */ /* {{{ proto bool OAuth::enableRedirects(void) Follow and sign redirects automatically (enabled by default) */ SO_METHOD(enableRedirects) { php_so_object *soo; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } soo->follow_redirects = 1; RETURN_TRUE; } /* }}} */ /* {{{ proto bool OAuth::disableRedirects(void) Don't follow redirects automatically, thus allowing the request to be manually redirected (enabled by default) */ SO_METHOD(disableRedirects) { php_so_object *soo; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } soo->follow_redirects = 0; RETURN_TRUE; } /* }}} */ /* {{{ proto bool OAuth::disableDebug(void) Disable debug mode */ SO_METHOD(disableDebug) { php_so_object *soo; zval *obj; obj = getThis(); soo = fetch_so_object(obj TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } soo->debug = 0; zend_update_property_bool(soo_class_entry, obj, "debug", sizeof("debug") - 1, 0 TSRMLS_CC); RETURN_TRUE; } /* }}} */ /* {{{ proto bool OAuth::enableDebug(void) Enable debug mode, will verbosely output http information about requests */ SO_METHOD(enableDebug) { php_so_object *soo; zval *obj; obj = getThis(); soo = fetch_so_object(obj TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } soo->debug = 1; zend_update_property_bool(soo_class_entry, obj, "debug", sizeof("debug") - 1, 1 TSRMLS_CC); RETURN_TRUE; } /* }}} */ /* {{{ proto bool OAuth::enableSSLChecks(void) Enable SSL verification for requests, enabled by default */ SO_METHOD(enableSSLChecks) { php_so_object *soo; zval *obj; obj = getThis(); soo = fetch_so_object(obj TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } soo->sslcheck = OAUTH_SSLCHECK_BOTH; zend_update_property_long(soo_class_entry, obj, "sslChecks", sizeof("sslChecks") - 1, 1 TSRMLS_CC); RETURN_TRUE; } /* }}} */ /* {{{ proto bool OAuth::disableSSLChecks(void) Disable SSL verification for requests (be careful using this for production) */ SO_METHOD(disableSSLChecks) { php_so_object *soo; zval *obj; obj = getThis(); soo = fetch_so_object(obj TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } soo->sslcheck = OAUTH_SSLCHECK_NONE; zend_update_property_long(soo_class_entry, obj, "sslChecks", sizeof("sslChecks") - 1, 0 TSRMLS_CC); RETURN_TRUE; } /* }}} */ /* {{{ proto bool OAuth::setSSLChecks(long sslcheck) Tweak specific SSL checks for requests (be careful using this for production) */ SO_METHOD(setSSLChecks) { php_so_object *soo; zval *obj; long sslcheck = OAUTH_SSLCHECK_BOTH; obj = getThis(); soo = fetch_so_object(obj TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &sslcheck) == FAILURE) { return; } soo->sslcheck = sslcheck & OAUTH_SSLCHECK_BOTH; zend_update_property_long(soo_class_entry, obj, "sslChecks", sizeof("sslChecks") - 1, soo->sslcheck TSRMLS_CC); RETURN_TRUE; } /* }}} */ /* {{{ proto bool OAuth::setVersion(string version) Set oauth_version for requests (default 1.0) */ SO_METHOD(setVersion) { php_so_object *soo; int ver_len = 0; char *vers; zval *zver; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &vers, &ver_len) == FAILURE) { return; } if (ver_len < 1) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid version", NULL, NULL TSRMLS_CC); RETURN_FALSE; } MAKE_STD_ZVAL(zver); ZVAL_STRING(zver, vers, 1); if (SUCCESS==soo_set_property(soo, zver, OAUTH_ATTR_OAUTH_VERSION TSRMLS_CC)) { RETURN_TRUE; } RETURN_FALSE; } /* }}} */ /* {{{ proto bool OAuth::setAuthType(string auth_type) Set the manner in which to send oauth parameters */ SO_METHOD(setAuthType) { php_so_object *soo; long auth; zval *zauth; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &auth) == FAILURE) { return; } switch (auth) { case OAUTH_AUTH_TYPE_URI: case OAUTH_AUTH_TYPE_FORM: case OAUTH_AUTH_TYPE_AUTHORIZATION: case OAUTH_AUTH_TYPE_NONE: MAKE_STD_ZVAL(zauth); ZVAL_LONG(zauth, auth); if (SUCCESS==soo_set_property(soo, zauth, OAUTH_ATTR_AUTHMETHOD TSRMLS_CC)) { RETURN_TRUE; } default: soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid auth type", NULL, NULL TSRMLS_CC); RETURN_FALSE; } RETURN_FALSE; } /* }}} */ /* {{{ proto bool OAuth::setTimeout(int milliseconds) Set the timeout, in milliseconds, for requests */ SO_METHOD(setTimeout) { php_so_object *soo; long timeout; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &timeout) == FAILURE) { return; } if (timeout < 0) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid timeout", NULL, NULL TSRMLS_CC); RETURN_FALSE; } soo->timeout = timeout; RETURN_TRUE; } /* }}} */ /* {{{ proto bool OAuth::setNonce(string nonce) Set oauth_nonce for subsequent requests, if none is set a random nonce will be generated using uniqid */ SO_METHOD(setNonce) { php_so_object *soo; int nonce_len; char *nonce; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &nonce, &nonce_len) == FAILURE) { return; } if (nonce_len < 1) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid nonce", NULL, NULL TSRMLS_CC); RETURN_FALSE; } if (soo->nonce) { efree(soo->nonce); } soo->nonce = estrndup(nonce, nonce_len); RETURN_TRUE; } /* }}} */ SO_METHOD(setTimestamp) { php_so_object *soo; int ts_len; char *ts; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ts, &ts_len) == FAILURE) { return; } if (ts_len < 1) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid timestamp", NULL, NULL TSRMLS_CC); RETURN_FALSE; } if (soo->timestamp) { efree(soo->timestamp); } soo->timestamp = estrndup(ts, ts_len); RETURN_TRUE; } /* {{{ proto bool OAuth::setToken(string token, string token_secret) Set a request or access token and token secret to be used in subsequent requests */ SO_METHOD(setToken) { php_so_object *soo; int token_len, token_secret_len; char *token, *token_secret; zval *t,*ts; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &token, &token_len, &token_secret, &token_secret_len) == FAILURE) { return; } MAKE_STD_ZVAL(t); ZVAL_STRING(t, token, 1); soo_set_property(soo, t, OAUTH_ATTR_TOKEN TSRMLS_CC); if (token_secret_len > 1) { MAKE_STD_ZVAL(ts); ZVAL_STRING(ts, oauth_url_encode(token_secret, token_secret_len), 0); soo_set_property(soo, ts, OAUTH_ATTR_TOKEN_SECRET TSRMLS_CC); } RETURN_TRUE; } /* }}} */ /* {{{ proto void OAuth::setRequestEngine(long reqengine) */ SO_METHOD(setRequestEngine) { php_so_object *soo; long reqengine; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &reqengine) == FAILURE) { return; } soo = fetch_so_object(getThis() TSRMLS_CC); switch (reqengine) { case OAUTH_REQENGINE_STREAMS: #if OAUTH_USE_CURL case OAUTH_REQENGINE_CURL: #endif soo->reqengine = reqengine; break; default: soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid request engine specified", NULL, NULL TSRMLS_CC); } } /* }}} */ /* {{{ proto bool OAuth::generateSignature(string http_method, string url [, string|array extra_parameters ]) Generate a signature based on the final HTTP method, URL and a string/array of parameters */ SO_METHOD(generateSignature) { php_so_object *soo; int url_len, http_method_len = 0; char *url; zval *request_args = NULL; char *http_method = NULL; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|z", &http_method, &http_method_len, &url, &url_len, &request_args) == FAILURE) { return; } if (url_len < 1) { RETURN_BOOL(FALSE); } if (oauth_fetch(soo, url, http_method, request_args, NULL, NULL, (OAUTH_FETCH_USETOKEN | OAUTH_FETCH_SIGONLY) TSRMLS_CC) < 0) { RETURN_BOOL(FALSE); } else { RETURN_STRING(soo->signature, 1); } } /* }}} */ /* {{{ proto bool OAuth::fetch(string protected_resource_url [, string|array extra_parameters [, string request_type [, array request_headers]]]) fetch a protected resource, pass in extra_parameters (array(name => value) or "custom body") */ SO_METHOD(fetch) { php_so_object *soo; int fetchurl_len, http_method_len = 0; char *fetchurl; zval *zret = NULL, *request_args = NULL, *request_headers = NULL; char *http_method = NULL; long retcode; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zsa", &fetchurl, &fetchurl_len, &request_args, &http_method, &http_method_len, &request_headers) == FAILURE) { return; } if (fetchurl_len < 1) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid protected resource url length", NULL, NULL TSRMLS_CC); RETURN_FALSE; } retcode = oauth_fetch(soo, fetchurl, http_method, request_args, request_headers, NULL, OAUTH_FETCH_USETOKEN | OAUTH_OVERRIDE_HTTP_METHOD TSRMLS_CC); MAKE_STD_ZVAL(zret); ZVAL_STRINGL(zret, soo->lastresponse.c, soo->lastresponse.len, 1); so_set_response_args(soo->properties, zret, NULL TSRMLS_CC); if ((retcode < 200 || retcode > 206)) { RETURN_FALSE; } else { RETURN_BOOL(TRUE); } } /* }}} */ /* {{{ proto array OAuth::getAccessToken(string access_token_url [, string auth_session_handle [, string auth_verifier ]]) Get access token, If the server supports Scalable OAuth pass in the auth_session_handle to refresh the token (http://wiki.oauth.net/ScalableOAuth) For 1.0a implementation, a verifier token must be passed; this token is not passed unless a value is explicitly assigned via the function arguments or $_GET/$_POST['oauth_verifier'] is set */ SO_METHOD(getAccessToken) { php_so_object *soo; int aturi_len = 0, ash_len = 0, verifier_len = 0, http_method_len = 0; char *aturi, *ash, *verifier, *http_method = NULL; zval *zret = NULL; HashTable *args = NULL; long retcode; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sss", &aturi, &aturi_len, &ash, &ash_len, &verifier, &verifier_len, &http_method, &http_method_len) == FAILURE) { return; } if (aturi_len < 1) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid access token url length", NULL, NULL TSRMLS_CC); RETURN_FALSE; } if (!verifier_len) { /* try to get from _GET/_POST */ get_request_param(OAUTH_PARAM_VERIFIER, &verifier, &verifier_len TSRMLS_CC); } if (ash_len > 0 || verifier_len > 0) { ALLOC_HASHTABLE(args); zend_hash_init(args, 0, NULL, ZVAL_PTR_DTOR, 0); if (ash_len > 0) { add_arg_for_req(args, OAUTH_PARAM_ASH, ash TSRMLS_CC); } if (verifier_len > 0) { add_arg_for_req(args, OAUTH_PARAM_VERIFIER, verifier TSRMLS_CC); } } retcode = oauth_fetch(soo, aturi, oauth_get_http_method(soo, http_method TSRMLS_CC), NULL, NULL, args, OAUTH_FETCH_USETOKEN TSRMLS_CC); if (args) { FREE_ARGS_HASH(args); } if (retcode != -1 && soo->lastresponse.c) { array_init(return_value); MAKE_STD_ZVAL(zret); ZVAL_STRINGL(zret, soo->lastresponse.c, soo->lastresponse.len, 1); so_set_response_args(soo->properties, zret, return_value TSRMLS_CC); return; } RETURN_FALSE; } /* }}} */ /* {{{ proto array OAuth::getLastResponseInfo(void) Get information about the last response */ SO_METHOD(getLastResponseInfo) { php_so_object *soo; zval **data_ptr; ulong hf = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } soo = fetch_so_object(getThis() TSRMLS_CC); hf = zend_hash_func(OAUTH_ATTR_LAST_RES_INFO, sizeof(OAUTH_ATTR_LAST_RES_INFO)); if (zend_hash_quick_find(soo->properties, OAUTH_ATTR_LAST_RES_INFO, sizeof(OAUTH_ATTR_LAST_RES_INFO), hf, (void *)&data_ptr) == SUCCESS) { if (Z_TYPE_PP(data_ptr) == IS_ARRAY) { convert_to_array_ex(data_ptr); } RETURN_ZVAL(*data_ptr, 1, 0); } RETURN_FALSE; } /* }}} */ /* {{{ proto array OAuth::getLastResponse(void) Get last response */ SO_METHOD(getLastResponse) { php_so_object *soo; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } soo = fetch_so_object(getThis() TSRMLS_CC); if (soo->lastresponse.c) { RETURN_STRINGL(soo->lastresponse.c, soo->lastresponse.len, 1); } #if jawed_0 void *p_data_ptr; zval **data_ptr; ulong hf = 0; ulong hlen = 0; char *hkey = OAUTH_ATTR_LAST_RES; hkey = OAUTH_RAW_LAST_RES; hlen = strlen(hkey)+1; hf = zend_hash_func(hkey,hlen); if (zend_hash_quick_find(soo->properties, hkey, hlen, hf, &p_data_ptr) == SUCCESS) { data_ptr = p_data_ptr; RETURN_STRING(Z_STRVAL_P(*data_ptr), 0); } RETURN_FALSE; #endif } /* }}} */ SO_METHOD(getLastResponseHeaders) { php_so_object *soo; if (FAILURE==zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { return; } soo = fetch_so_object(getThis() TSRMLS_CC); if (soo->headers_in.c) { RETURN_STRINGL(soo->headers_in.c, soo->headers_in.len, 1); } RETURN_FALSE; } /* {{{ proto string OAuth::getRequestHeader(string http_method, string url [, string|array extra_parameters ]) Generate OAuth header string signature based on the final HTTP method, URL and a string/array of parameters */ SO_METHOD(getRequestHeader) { php_so_object *soo; int url_len, http_method_len = 0; char *url; zval *request_args = NULL; char *http_method = NULL; soo = fetch_so_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|z", &http_method, &http_method_len, &url, &url_len, &request_args) == FAILURE) { return; } if (url_len < 1) { RETURN_BOOL(FALSE); } if (oauth_fetch(soo, url, http_method, request_args, NULL, NULL, (OAUTH_FETCH_USETOKEN | OAUTH_FETCH_HEADONLY) TSRMLS_CC) < 0) { RETURN_BOOL(FALSE); } else { RETURN_STRINGL(soo->headers_out.c, soo->headers_out.len, 1); } RETURN_FALSE; } /* {{{ arginfo */ OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_urlencode, 0, 0, 1) ZEND_ARG_INFO(0, uri) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_sbs, 0, 0, 3) ZEND_ARG_INFO(0, http_method) ZEND_ARG_INFO(0, uri) ZEND_ARG_INFO(0, parameters) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth__construct, 0, 0, 2) ZEND_ARG_INFO(0, consumer_key) ZEND_ARG_INFO(0, consumer_secret) ZEND_ARG_INFO(0, signature_method) ZEND_ARG_INFO(0, auth_type) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_getrequesttoken, 0, 0, 1) ZEND_ARG_INFO(0, request_token_url) ZEND_ARG_INFO(0, callback_url) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setversion, 0, 0, 1) ZEND_ARG_INFO(0, version) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_noparams, 0, 0, 0) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setauthtype, 0, 0, 1) ZEND_ARG_INFO(0, auth_type) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setnonce, 0, 0, 1) ZEND_ARG_INFO(0, nonce) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_settimestamp, 0, 0, 1) ZEND_ARG_INFO(0, ts) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_settimeout, 0, 0, 1) ZEND_ARG_INFO(0, timeout_in_milliseconds) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setcapath, 0, 0, 2) ZEND_ARG_INFO(0, ca_path) ZEND_ARG_INFO(0, ca_info) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_settoken, 0, 0, 2) ZEND_ARG_INFO(0, token) ZEND_ARG_INFO(0, token_secret) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setrequestengine, 0, 0, 1) ZEND_ARG_INFO(0, reqengine) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_fetch, 0, 0, 1) ZEND_ARG_INFO(0, protected_resource_url) ZEND_ARG_INFO(0, extra_parameters) /* ARRAY_INFO(1, arg, 0) */ ZEND_ARG_INFO(0, http_method) ZEND_ARG_INFO(0, request_headers) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_getaccesstoken, 0, 0, 1) ZEND_ARG_INFO(0, access_token_url) ZEND_ARG_INFO(0, auth_session_handle) ZEND_ARG_INFO(0, auth_verifier) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setrsacertificate, 0, 0, 1) ZEND_ARG_INFO(0, cert) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_gensig, 0, 0, 2) ZEND_ARG_INFO(0, http_method) ZEND_ARG_INFO(0, url) ZEND_ARG_INFO(0, extra_parameters) /* ARRAY_INFO(1, arg, 0) */ ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setsslchecks, 0, 0, 1) ZEND_ARG_INFO(0, sslcheck) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_getrequestheader, 0, 0, 2) ZEND_ARG_INFO(0, http_method) ZEND_ARG_INFO(0, url) ZEND_ARG_INFO(0, extra_parameters) /* ARRAY_INFO(1, arg, 0) */ ZEND_END_ARG_INFO() /* }}} */ static zend_function_entry so_functions[] = { /* {{{ */ SO_ME(__construct, arginfo_oauth__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) SO_ME(setRSACertificate, arginfo_oauth_setrsacertificate, ZEND_ACC_PUBLIC) SO_ME(getRequestToken, arginfo_oauth_getrequesttoken, ZEND_ACC_PUBLIC) SO_ME(getAccessToken, arginfo_oauth_getaccesstoken, ZEND_ACC_PUBLIC) SO_ME(getLastResponse, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) SO_ME(getLastResponseInfo, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) SO_ME(getLastResponseHeaders, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) SO_ME(setToken, arginfo_oauth_settoken, ZEND_ACC_PUBLIC) SO_ME(setRequestEngine, arginfo_oauth_setrequestengine, ZEND_ACC_PUBLIC) SO_ME(setVersion, arginfo_oauth_setversion, ZEND_ACC_PUBLIC) SO_ME(setAuthType, arginfo_oauth_setauthtype, ZEND_ACC_PUBLIC) SO_ME(setNonce, arginfo_oauth_setnonce, ZEND_ACC_PUBLIC) SO_ME(setTimestamp, arginfo_oauth_settimestamp, ZEND_ACC_PUBLIC) SO_ME(fetch, arginfo_oauth_fetch, ZEND_ACC_PUBLIC) SO_ME(enableDebug, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) SO_ME(disableDebug, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) SO_ME(enableSSLChecks, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) SO_ME(disableSSLChecks, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) SO_ME(enableRedirects, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) SO_ME(disableRedirects, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) SO_ME(setCAPath, arginfo_oauth_setcapath, ZEND_ACC_PUBLIC) SO_ME(getCAPath, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) SO_ME(generateSignature, arginfo_oauth_gensig, ZEND_ACC_PUBLIC) SO_ME(setTimeout, arginfo_oauth_settimeout, ZEND_ACC_PUBLIC) SO_ME(setSSLChecks, arginfo_oauth_setsslchecks, ZEND_ACC_PUBLIC) SO_ME(getRequestHeader, arginfo_oauth_getrequestheader, ZEND_ACC_PUBLIC) SO_ME(__destruct, arginfo_oauth_noparams, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; /* }}} */ #ifdef ZEND_ENGINE_2_4 static zval *oauth_read_member(zval *obj, zval *mem, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ #else static zval *oauth_read_member(zval *obj, zval *mem, int type TSRMLS_DC) /* {{{ */ #endif { zval *return_value = NULL; php_so_object *soo; soo = fetch_so_object(obj TSRMLS_CC); return_value = OAUTH_READ_PROPERTY(obj, mem, type); if(!strcasecmp(Z_STRVAL_P(mem),"debug")) { convert_to_boolean(return_value); ZVAL_BOOL(return_value, soo->debug); } else if(!strcasecmp(Z_STRVAL_P(mem),"sslChecks")) { ZVAL_LONG(return_value, soo->sslcheck); } return return_value; } /* }}} */ #ifdef ZEND_ENGINE_2_4 static void oauth_write_member(zval *obj, zval *mem, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */ #else static void oauth_write_member(zval *obj, zval *mem, zval *value TSRMLS_DC) /* {{{ */ #endif { char *property; php_so_object *soo; property = Z_STRVAL_P(mem); soo = fetch_so_object(obj TSRMLS_CC); if(!strcmp(property,"debug")) { soo->debug = Z_LVAL_P(value); } else if(!strcmp(property,"sslChecks")) { soo->sslcheck = Z_LVAL_P(value); } OAUTH_WRITE_PROPERTY(obj, mem, value); } /* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(oauth) { zend_class_entry soce, soo_ex_ce; #if OAUTH_USE_CURL if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) { return FAILURE; } #endif INIT_CLASS_ENTRY(soce, "OAuth", so_functions); soce.create_object = new_so_object; soo_class_entry = zend_register_internal_class(&soce TSRMLS_CC); memcpy(&so_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); so_object_handlers.read_property = oauth_read_member; so_object_handlers.write_property = oauth_write_member; so_object_handlers.clone_obj = oauth_clone_obj; zend_declare_property_long(soo_class_entry, "debug", sizeof("debug")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_long(soo_class_entry, "sslChecks", sizeof("sslChecks")-1, 1, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_string(soo_class_entry, "debugInfo", sizeof("debugInfo")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(soo_ex_ce, "OAuthException", NULL); #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) soo_exception_ce = zend_register_internal_class_ex(&soo_ex_ce, zend_exception_get_default(), NULL TSRMLS_CC); #else soo_exception_ce = zend_register_internal_class_ex(&soo_ex_ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC); #endif zend_declare_property_null(soo_exception_ce, "lastResponse", sizeof("lastResponse")-1, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_null(soo_exception_ce, "debugInfo", sizeof("debugInfo")-1, ZEND_ACC_PUBLIC TSRMLS_CC); REGISTER_STRING_CONSTANT("OAUTH_SIG_METHOD_HMACSHA1", OAUTH_SIG_METHOD_HMACSHA1, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("OAUTH_SIG_METHOD_HMACSHA256", OAUTH_SIG_METHOD_HMACSHA256, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("OAUTH_SIG_METHOD_RSASHA1", OAUTH_SIG_METHOD_RSASHA1, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("OAUTH_SIG_METHOD_PLAINTEXT", OAUTH_SIG_METHOD_PLAINTEXT, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_AUTH_TYPE_AUTHORIZATION", OAUTH_AUTH_TYPE_AUTHORIZATION, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_AUTH_TYPE_URI", OAUTH_AUTH_TYPE_URI, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_AUTH_TYPE_FORM", OAUTH_AUTH_TYPE_FORM, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_AUTH_TYPE_NONE", OAUTH_AUTH_TYPE_NONE, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("OAUTH_HTTP_METHOD_GET", OAUTH_HTTP_METHOD_GET, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("OAUTH_HTTP_METHOD_POST", OAUTH_HTTP_METHOD_POST, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("OAUTH_HTTP_METHOD_PUT", OAUTH_HTTP_METHOD_PUT, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("OAUTH_HTTP_METHOD_HEAD", OAUTH_HTTP_METHOD_HEAD, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("OAUTH_HTTP_METHOD_DELETE", OAUTH_HTTP_METHOD_DELETE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_REQENGINE_STREAMS", OAUTH_REQENGINE_STREAMS, CONST_CS | CONST_PERSISTENT); #ifdef OAUTH_USE_CURL REGISTER_LONG_CONSTANT("OAUTH_REQENGINE_CURL", OAUTH_REQENGINE_CURL, CONST_CS | CONST_PERSISTENT); #endif REGISTER_LONG_CONSTANT("OAUTH_SSLCHECK_NONE", OAUTH_SSLCHECK_NONE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_SSLCHECK_HOST", OAUTH_SSLCHECK_HOST, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_SSLCHECK_PEER", OAUTH_SSLCHECK_PEER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_SSLCHECK_BOTH", OAUTH_SSLCHECK_BOTH, CONST_CS | CONST_PERSISTENT); oauth_provider_register_class(TSRMLS_C); REGISTER_LONG_CONSTANT("OAUTH_OK", OAUTH_OK, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_BAD_NONCE", OAUTH_BAD_NONCE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_BAD_TIMESTAMP", OAUTH_BAD_TIMESTAMP, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_CONSUMER_KEY_UNKNOWN", OAUTH_CONSUMER_KEY_UNKNOWN, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_CONSUMER_KEY_REFUSED", OAUTH_CONSUMER_KEY_REFUSED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_INVALID_SIGNATURE", OAUTH_INVALID_SIGNATURE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_TOKEN_USED", OAUTH_TOKEN_USED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_TOKEN_EXPIRED", OAUTH_TOKEN_EXPIRED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_TOKEN_REVOKED", OAUTH_TOKEN_REVOKED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_TOKEN_REJECTED", OAUTH_TOKEN_REJECTED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_VERIFIER_INVALID", OAUTH_VERIFIER_INVALID, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_PARAMETER_ABSENT", OAUTH_PARAMETER_ABSENT, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OAUTH_SIGNATURE_METHOD_REJECTED", OAUTH_SIGNATURE_METHOD_REJECTED, CONST_CS | CONST_PERSISTENT); return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(oauth) { soo_class_entry = NULL; soo_exception_ce = NULL; #if OAUTH_USE_CURL curl_global_cleanup(); #endif return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(oauth) { php_info_print_table_start(); php_info_print_table_header(2, "OAuth support", "enabled"); php_info_print_table_row(2, "PLAINTEXT support", "enabled"); #if HAVE_OPENSSL_EXT php_info_print_table_row(2, "RSA-SHA1 support", "enabled"); #else php_info_print_table_row(2, "RSA-SHA1 support", "not supported"); #endif php_info_print_table_row(2, "HMAC-SHA1 support", "enabled"); #if OAUTH_USE_CURL php_info_print_table_row(2, "Request engine support", "php_streams, curl"); #else php_info_print_table_row(2, "Request engine support", "php_streams"); #endif php_info_print_table_row(2, "source version", "$Id: oauth.c 325799 2012-05-24 21:07:51Z jawed $"); php_info_print_table_row(2, "version", OAUTH_EXT_VER); php_info_print_table_end(); } /* }}} */ /* TODO expose a function for base sig string */ zend_function_entry oauth_functions[] = { /* {{{ */ PHP_FE(oauth_urlencode, arginfo_oauth_urlencode) PHP_FE(oauth_get_sbs, arginfo_oauth_sbs) { NULL, NULL, NULL } }; /* }}} */ /* {{{ oauth_module_entry */ zend_module_entry oauth_module_entry = { STANDARD_MODULE_HEADER_EX, NULL, NULL, "OAuth", oauth_functions, PHP_MINIT(oauth), PHP_MSHUTDOWN(oauth), NULL, NULL, PHP_MINFO(oauth), OAUTH_EXT_VER, STANDARD_MODULE_PROPERTIES }; /* }}} */ #if COMPILE_DL_OAUTH ZEND_GET_MODULE(oauth) #endif /** * Local Variables: * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: t * End: * vim600: fdm=marker * vim: noet sw=4 ts=4 noexpandtab */ oauth-1.2.3/provider.c100644 0 0 122657 100644 7600 /* +----------------------------------------------------------------------+ | See LICENSE file for further copyright information | +----------------------------------------------------------------------+ | Authors: John Jawed | | Felipe Pena | | Rasmus Lerdorf | | Tjerk Meesters | +----------------------------------------------------------------------+ */ /* $Id: oauth.c,v 1.60 2009/05/16 15:46:09 jawed Exp $ */ #include "php_oauth.h" #include "provider.h" #if PHP_WIN32 # include # include #endif #include "fcntl.h" static zend_object_handlers oauth_provider_obj_hndlrs; static zend_class_entry *oauthprovider; static inline void oauth_provider_set_param_member(zval *provider_obj, char *prop_name, zval *prop TSRMLS_DC) /* {{{ */ { zend_update_property(Z_OBJCE_P(provider_obj), provider_obj, prop_name, strlen(prop_name), prop TSRMLS_CC); } /* }}} */ static inline php_oauth_provider *fetch_sop_object(zval *obj TSRMLS_DC) /* {{{ */ { php_oauth_provider *sop = (php_oauth_provider *)zend_object_store_get_object(obj TSRMLS_CC); sop->this_ptr = obj; return sop; } /* }}} */ static int oauth_provider_set_default_required_params(HashTable *ht) /* {{{ */ { char *required_params[] = {"oauth_consumer_key", "oauth_signature", "oauth_signature_method", "oauth_nonce", "oauth_timestamp", "oauth_token", NULL}; unsigned int idx = 0; do { zval *tmp; MAKE_STD_ZVAL(tmp); ZVAL_NULL(tmp); if(zend_hash_add(ht, required_params[idx], strlen(required_params[idx]) + 1, &tmp, sizeof(zval *), NULL)==FAILURE) { return FAILURE; } ++idx; } while(required_params[idx]); return SUCCESS; } /* }}} */ static int oauth_provider_remove_required_param(HashTable *ht, char *required_param) /* {{{ */ { zval **dest_entry; char *key; uint key_len; ulong num_key; HashPosition hpos; if(zend_hash_find(ht, required_param, strlen(required_param) + 1, (void **)&dest_entry)==FAILURE) { return FAILURE; } else { zend_hash_internal_pointer_reset_ex(ht, &hpos); do { if(zend_hash_get_current_key_ex(ht, &key, &key_len, &num_key, 0, &hpos)!=FAILURE) { if(!strcmp(key, required_param)) { zend_hash_del(ht, key, key_len); return SUCCESS; } } } while(zend_hash_move_forward_ex(ht, &hpos)==SUCCESS); } return FAILURE; } /* }}} */ static int oauth_provider_add_required_param(HashTable *ht, char *required_param) /* {{{ */ { zval *zparam, **dest_entry; if(zend_hash_find(ht, required_param, strlen(required_param) + 1, (void **)&dest_entry)==FAILURE) { MAKE_STD_ZVAL(zparam); ZVAL_NULL(zparam); if(zend_hash_add(ht, required_param, strlen(required_param) + 1, &zparam, sizeof(zval *), NULL)==FAILURE) { return FAILURE; } } return SUCCESS; } /* }}} */ static void oauth_provider_apply_custom_param(HashTable *ht, HashTable *custom) /* {{{ */ { HashPosition custompos; zval **entry; char *key; uint key_len; ulong num_key; zend_hash_internal_pointer_reset_ex(custom, &custompos); do { if (SUCCESS==zend_hash_get_current_data_ex(custom, (void**)&entry, &custompos) && HASH_KEY_IS_STRING==zend_hash_get_current_key_ex(custom, &key, &key_len, &num_key, 0, &custompos)) { if (IS_NULL==Z_TYPE_PP(entry)) { zend_hash_del(ht, key, key_len); } else { zend_hash_update(ht, key, key_len, entry, sizeof(zval **), NULL); } } } while (SUCCESS==zend_hash_move_forward_ex(custom, &custompos)); } /* }}} */ static int oauth_provider_token_required(zval *provider_obj, char* uri TSRMLS_DC) { zval *is_req_token_api; is_req_token_api = zend_read_property(Z_OBJCE_P(provider_obj), provider_obj, "request_token_endpoint", sizeof("request_token_endpoint") - 1, 1 TSRMLS_CC); if (!Z_BVAL_P(is_req_token_api)) { php_oauth_provider *sop; sop = fetch_sop_object(provider_obj TSRMLS_CC); /* do uri matching on the relative path */ if (sop->endpoint_paths[OAUTH_PROVIDER_PATH_REQUEST]) { const char *reqtoken_path = sop->endpoint_paths[OAUTH_PROVIDER_PATH_REQUEST]; int uri_matched = 0; if (reqtoken_path[0]=='/') { /* match against relative url */ php_url *urlparts = php_url_parse_ex(uri, strlen(uri)); uri_matched = urlparts && 0==strncmp(urlparts->path, reqtoken_path, strlen(reqtoken_path)); php_url_free(urlparts); } else { /* match against full uri */ uri_matched = 0==strncmp(uri, reqtoken_path, strlen(reqtoken_path)); } /* token required if no match was found */ if (uri_matched) { ZVAL_BOOL(is_req_token_api, 1); return 0; } } /* no matches, token required */ return 1; } return 0; } static void oauth_provider_check_required_params(HashTable *required_params, HashTable *params, HashTable *missing_params TSRMLS_DC) /* {{{ */ { HashPosition hpos, reqhpos, paramhpos; zval **dest_entry, *param; char *key; ulong num_key; uint key_len; zend_hash_internal_pointer_reset_ex(required_params, &hpos); zend_hash_internal_pointer_reset_ex(params, &reqhpos); zend_hash_internal_pointer_reset_ex(missing_params, ¶mhpos); do { if(zend_hash_get_current_key_ex(required_params, &key, &key_len, &num_key, 0, &hpos)==HASH_KEY_IS_STRING) { if(zend_hash_find(params, key, key_len, (void **)&dest_entry)==FAILURE) { MAKE_STD_ZVAL(param); ZVAL_STRING(param, key, 1); zend_hash_next_index_insert(missing_params, ¶m, sizeof(zval *), NULL); } } } while(zend_hash_move_forward_ex(required_params, &hpos)==SUCCESS); } /* }}} */ static void oauth_provider_set_std_params(zval *provider_obj, HashTable *sbs_vars TSRMLS_DC) /* {{{ */ { zval **dest_entry; if(!provider_obj || !sbs_vars) { return; } OAUTH_PROVIDER_SET_STD_PARAM(sbs_vars, OAUTH_PARAM_CONSUMER_KEY, OAUTH_PROVIDER_CONSUMER_KEY); OAUTH_PROVIDER_SET_STD_PARAM(sbs_vars, OAUTH_PARAM_TOKEN, OAUTH_PROVIDER_TOKEN); OAUTH_PROVIDER_SET_STD_PARAM(sbs_vars, OAUTH_PARAM_SIGNATURE, OAUTH_PROVIDER_SIGNATURE); OAUTH_PROVIDER_SET_STD_PARAM(sbs_vars, OAUTH_PARAM_NONCE, OAUTH_PROVIDER_NONCE); OAUTH_PROVIDER_SET_STD_PARAM(sbs_vars, OAUTH_PARAM_TIMESTAMP, OAUTH_PROVIDER_TIMESTAMP); OAUTH_PROVIDER_SET_STD_PARAM(sbs_vars, OAUTH_PARAM_VERSION, OAUTH_PROVIDER_VERSION); OAUTH_PROVIDER_SET_STD_PARAM(sbs_vars, OAUTH_PARAM_SIGNATURE_METHOD, OAUTH_PROVIDER_SIGNATURE_METHOD); OAUTH_PROVIDER_SET_STD_PARAM(sbs_vars, OAUTH_PARAM_CALLBACK, OAUTH_PROVIDER_CALLBACK); OAUTH_PROVIDER_SET_STD_PARAM(sbs_vars, OAUTH_PARAM_VERIFIER, OAUTH_PROVIDER_VERIFIER); } /* }}} */ static inline int oauth_provider_set_param_value(HashTable *ht, char *key, zval **val) /* {{{ */ { ulong h; ulong key_len = 0; key_len = strlen(key); h = zend_hash_func(key, key_len+1); Z_ADDREF_P(*val); return zend_hash_quick_update(ht, key, key_len+1, h, val, sizeof(zval **), NULL); } /* }}} */ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_header TSRMLS_DC) /* {{{ */ { pcre_cache_entry *pce; zval *subpats = NULL, *return_value = NULL, **item_param = NULL, **current_param = NULL, **current_val = NULL; HashPosition hpos; /* the following regex is also used at http://oauth.googlecode.com/svn/code/php/OAuth.php to help ensure uniform behavior between libs, credit goes to the original author(s) */ char *regex = "/(oauth_[a-z_-]*)=(?:\"([^\"]*)\"|([^,]*))/"; if(!auth_header || strncasecmp(auth_header, "oauth", 4) || !sop) { return FAILURE; } /* pass "OAuth " */ auth_header += 5; if ((pce = pcre_get_compiled_regex_cache(regex, sizeof(regex)-1 TSRMLS_CC)) == NULL) { return FAILURE; } MAKE_STD_ZVAL(return_value); ALLOC_INIT_ZVAL(subpats); php_pcre_match_impl( pce, auth_header, strlen(auth_header), return_value, subpats, 1, /* global */ 1, /* use flags */ 2, /* PREG_SET_ORDER */ 0 TSRMLS_CC ); if (0==Z_LVAL_P(return_value)) { return FAILURE; } zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(subpats), &hpos); /* walk the oauth param names */ do { if (SUCCESS==zend_hash_get_current_data_ex(Z_ARRVAL_P(subpats), (void **)&item_param, &hpos)) { zval *decoded_val; char *tmp; int decoded_len; /* * item = array( * 1 => param name * 2 => quoted value * 3 => unquoted value (defined if matched) * ) */ zend_hash_index_find(Z_ARRVAL_PP(item_param), 1, (void **)¤t_param); if (FAILURE==zend_hash_index_find(Z_ARRVAL_PP(item_param), 3, (void**)¤t_val)) { zend_hash_index_find(Z_ARRVAL_PP(item_param), 2, (void**)¤t_val); } tmp = estrndup(Z_STRVAL_PP(current_val), Z_STRLEN_PP(current_val)); decoded_len = php_url_decode(tmp, Z_STRLEN_PP(current_val)); MAKE_STD_ZVAL(decoded_val); ZVAL_STRINGL(decoded_val, tmp, decoded_len, 0); if (oauth_provider_set_param_value(sop->oauth_params, Z_STRVAL_PP(current_param), &decoded_val)==FAILURE) { return FAILURE; } Z_DELREF_P(decoded_val); } } while (SUCCESS==zend_hash_move_forward_ex(Z_ARRVAL_P(subpats), &hpos)); zval_ptr_dtor(&return_value); zval_ptr_dtor(&subpats); return SUCCESS; } /* }}} */ static void oauth_provider_register_cb(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ { zend_fcall_info fci; zend_fcall_info_cache fci_cache; php_oauth_provider *sop; php_oauth_provider_fcall *cb; php_oauth_provider_fcall **tgt_cb; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f", &fci, &fci_cache)==FAILURE) { return; } sop = fetch_sop_object(getThis() TSRMLS_CC); cb = emalloc(sizeof(php_oauth_provider_fcall)); cb->fcall_info = emalloc(sizeof(zend_fcall_info)); memcpy(cb->fcall_info, &fci, sizeof(zend_fcall_info)); cb->fcall_info_cache = fci_cache; Z_ADDREF_P(cb->fcall_info->function_name); switch(type) { case OAUTH_PROVIDER_CONSUMER_CB: tgt_cb = &sop->consumer_handler; break; case OAUTH_PROVIDER_TOKEN_CB: tgt_cb = &sop->token_handler; break; case OAUTH_PROVIDER_TSNONCE_CB: tgt_cb = &sop->tsnonce_handler; break; default: php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid callback type for OAuthProvider"); return; } OAUTH_PROVIDER_FREE_CB((*tgt_cb)); (*tgt_cb) = cb; } /* }}} */ static zval *oauth_provider_call_cb(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ { php_oauth_provider *sop; php_oauth_provider_fcall *cb = NULL; zval *retval = NULL, *args, *pthis; char *errstr = "", *callable_name = NULL; zend_bool is_callable; pthis = getThis(); sop = fetch_sop_object(pthis TSRMLS_CC); switch(type) { case OAUTH_PROVIDER_CONSUMER_CB: cb = sop->consumer_handler; errstr = "Consumer key/secret handler not specified, did you set a valid callback via OAuthProvider::consumerHandler()?"; break; case OAUTH_PROVIDER_TOKEN_CB: cb = sop->token_handler; errstr = "Token handler not specified, did you set a valid callback via OAuthProvider::tokenHandler()?"; break; case OAUTH_PROVIDER_TSNONCE_CB: cb = sop->tsnonce_handler; errstr = "Timestamp/nonce handler not specified, did you set a valid callback via OAuthProvider::timestampNonceHandler()?"; break; default: php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid callback type for OAuthProvider"); return NULL; } if(!cb) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "%s", errstr); return NULL; } MAKE_STD_ZVAL(args); array_init(args); add_next_index_zval(args, pthis); Z_ADDREF_P(pthis); Z_ADDREF_P(args); errstr = NULL; #if PHP_VERSION_ID < 50300 is_callable = zend_is_callable_ex(cb->fcall_info->function_name, 0, &callable_name, NULL, NULL, NULL, NULL TSRMLS_CC); #else is_callable = zend_is_callable_ex(cb->fcall_info->function_name, cb->fcall_info->object_ptr, IS_CALLABLE_CHECK_SILENT, &callable_name, NULL, &cb->fcall_info_cache, &errstr TSRMLS_CC); #endif if (!is_callable) { if (errstr) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid callback %s, %s", callable_name, errstr); efree(errstr); } } else if (errstr) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errstr); efree(errstr); } if (zend_fcall_info_call(cb->fcall_info, &cb->fcall_info_cache, &retval, args TSRMLS_CC)!=SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed calling callback %s", callable_name); } zval_ptr_dtor(&args); efree(callable_name); return retval; } /* }}} */ static char *oauth_provider_get_http_verb(TSRMLS_D) /* {{{ */ { zval **tmp; zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); if(PG(http_globals)[TRACK_VARS_SERVER]) { if(zend_hash_find(HASH_OF(PG(http_globals)[TRACK_VARS_SERVER]), "REQUEST_METHOD", sizeof("REQUEST_METHOD"), (void **) &tmp)!=FAILURE || zend_hash_find(HASH_OF(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_METHOD", sizeof("HTTP_METHOD"), (void **) &tmp)!=FAILURE) { return Z_STRVAL_PP(tmp); } } return NULL; } /* }}} */ static char *oauth_provider_get_current_uri(TSRMLS_D) { zval **host = NULL, **port = NULL, **uri = NULL, **proto = NULL, **https=NULL; zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_HOST", sizeof("HTTP_HOST"), (void**)&host); zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "SERVER_PORT", sizeof("SERVER_PORT"), (void**)&port); zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "REQUEST_URI", sizeof("REQUEST_URI"), (void**)&uri); zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_X_FORWARDED_PROTO", sizeof("HTTP_X_FORWARDED_PROTO"), (void **)&proto); zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTPS", sizeof("HTTPS"), (void **)&https); if (host && port && uri) { char *tmp,*hostname,*colon_in_hostname; spprintf(&hostname, 0, "%s", Z_STRVAL_PP(host)); colon_in_hostname=strrchr(hostname,':'); if(colon_in_hostname && ((https && Z_LVAL_PP(port)==443) || (!https && Z_LVAL_PP(port)==80))) { *colon_in_hostname=0; } if(proto && Z_STRLEN_PP(proto)) { spprintf(&tmp, 0, "%s://%s%s", Z_STRVAL_PP(proto), hostname, Z_STRVAL_PP(uri)); } else if(https && strcasecmp(Z_STRVAL_PP(https),"off")!=0) { spprintf(&tmp, 0, "https://%s%s", hostname, Z_STRVAL_PP(uri)); } else { spprintf(&tmp, 0, "http://%s%s", hostname, Z_STRVAL_PP(uri)); } efree(hostname); return tmp; } return NULL; } /* {{{ proto void OAuthProvider::__construct() Instantiate a new OAuthProvider object */ SOP_METHOD(__construct) { php_oauth_provider *sop; zval *params = NULL, *pthis = NULL, *auth_header = NULL, *apache_get_headers = NULL, *retval = NULL, **tmpzval = NULL, **item_param = NULL; char *authorization_header = NULL, *key = NULL; ulong num_key = 0, param_count = 0; HashPosition hpos; pthis = getThis(); sop = fetch_sop_object(pthis TSRMLS_CC); /* XXX throw E_NOTICE if filter!='unsafe_raw' */ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", ¶ms)==FAILURE) { soo_handle_error(NULL, OAUTH_ERR_INTERNAL_ERROR, "Failed to instantiate OAuthProvider", NULL, NULL TSRMLS_CC); return; } if (params && Z_TYPE_P(params)==IS_ARRAY) { param_count = zend_hash_num_elements(Z_ARRVAL_P(params)); } else { param_count = 0; } if(!strcasecmp("cli", sapi_module.name) && !param_count) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "For the CLI sapi parameters must be set first via OAuthProvider::__construct(array(\"oauth_param\" => \"value\", ...))"); return; } /* hashes for storing parameter info/checks */ ALLOC_HASHTABLE(sop->oauth_params); zend_hash_init(sop->oauth_params, 0, NULL, ZVAL_PTR_DTOR, 0); ALLOC_HASHTABLE(sop->missing_params); zend_hash_init(sop->missing_params, 0, NULL, ZVAL_PTR_DTOR, 0); ALLOC_HASHTABLE(sop->required_params); zend_hash_init(sop->required_params, 0, NULL, ZVAL_PTR_DTOR, 0); ALLOC_HASHTABLE(sop->custom_params); zend_hash_init(sop->custom_params, 0, NULL, ZVAL_PTR_DTOR, 0); memset(sop->endpoint_paths, 0, sizeof(sop->endpoint_paths)); sop->consumer_handler = NULL; sop->token_handler = NULL; sop->tsnonce_handler = NULL; sop->handle_errors = 1; oauth_provider_set_default_required_params(sop->required_params); zend_update_property_null(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_CONSUMER_KEY, sizeof(OAUTH_PROVIDER_CONSUMER_KEY)-1 TSRMLS_CC); zend_update_property_null(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_CONSUMER_SECRET, sizeof(OAUTH_PROVIDER_CONSUMER_SECRET)-1 TSRMLS_CC); zend_update_property_null(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_NONCE, sizeof(OAUTH_PROVIDER_NONCE)-1 TSRMLS_CC); zend_update_property_null(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_TOKEN, sizeof(OAUTH_PROVIDER_TOKEN)-1 TSRMLS_CC); zend_update_property_null(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_TOKEN_SECRET, sizeof(OAUTH_PROVIDER_TOKEN_SECRET)-1 TSRMLS_CC); zend_update_property_null(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_TIMESTAMP, sizeof(OAUTH_PROVIDER_TIMESTAMP)-1 TSRMLS_CC); zend_update_property_null(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_VERSION, sizeof(OAUTH_PROVIDER_VERSION)-1 TSRMLS_CC); zend_update_property_null(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_SIGNATURE_METHOD, sizeof(OAUTH_PROVIDER_SIGNATURE_METHOD)-1 TSRMLS_CC); zend_update_property_null(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_CALLBACK, sizeof(OAUTH_PROVIDER_CALLBACK)-1 TSRMLS_CC); zend_update_property_bool(Z_OBJCE_P(pthis), pthis, "request_token_endpoint", sizeof("request_token_endpoint")-1, 0 TSRMLS_CC); if(!param_count) { /* TODO: support NSAPI */ /* mod_php */ if(!strncasecmp(sapi_module.name, "apache", sizeof("apache") - 1)) { MAKE_STD_ZVAL(apache_get_headers); MAKE_STD_ZVAL(retval); ZVAL_STRING(apache_get_headers, "apache_request_headers", 0); if(zend_is_callable(apache_get_headers, 0, NULL OAUTH_IS_CALLABLE_CC)) { if(call_user_function(EG(function_table), NULL, apache_get_headers, retval, 0, NULL TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to get HTTP Request headers"); } if(SUCCESS == zend_hash_find(HASH_OF(retval), "Authorization", sizeof("Authorization"), (void **) &tmpzval)) { auth_header = *tmpzval; authorization_header = estrdup(Z_STRVAL_P(auth_header)); } else if (SUCCESS==zend_hash_find(HASH_OF(retval), "authorization", sizeof("authorization"), (void **) &tmpzval)) { auth_header = *tmpzval; authorization_header = estrdup(Z_STRVAL_P(auth_header)); } else { /* search one by one */ zend_hash_internal_pointer_reset_ex(HASH_OF(retval), &hpos); do { uint key_len; if (FAILURE!=zend_hash_get_current_key_ex(HASH_OF(retval), &key, &key_len, &num_key, 0, &hpos) && key_len==sizeof("authorization") && 0==strcasecmp(key, "authorization") && SUCCESS==zend_hash_get_current_data_ex(HASH_OF(retval), (void**)&tmpzval, &hpos)) { auth_header = *tmpzval; authorization_header = estrdup(Z_STRVAL_P(auth_header)); break; } } while (SUCCESS==zend_hash_move_forward_ex(HASH_OF(retval), &hpos)); } } else { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to call apache_request_headers while running under the Apache SAPI"); } FREE_ZVAL(apache_get_headers); zval_ptr_dtor(&retval); } else { /* not mod_php, look in _SERVER and _ENV for Authorization header */ if(!zend_is_auto_global("_SERVER", sizeof("_SERVER") - 1 TSRMLS_CC) && !zend_is_auto_global("_ENV", sizeof("_ENV") - 1 TSRMLS_CC)) { return; } /* first look in _SERVER */ if (!PG(http_globals)[TRACK_VARS_SERVER] || zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION"), (void **) &tmpzval)==FAILURE) { /* well that didn't work out, so let's check out _ENV */ if (!PG(http_globals)[TRACK_VARS_ENV] || zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV]), "HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION"), (void **) &tmpzval)==FAILURE) { /* not found, [bf]ail */ return; } } auth_header = *tmpzval; authorization_header = estrdup(Z_STRVAL_P(auth_header)); } if (authorization_header) { int ret = oauth_provider_parse_auth_header(sop, authorization_header TSRMLS_CC); efree(authorization_header); if (FAILURE==ret) { soo_handle_error(NULL, OAUTH_SIGNATURE_METHOD_REJECTED, "Unknown signature method", NULL, NULL TSRMLS_CC); return; } } } /* let constructor params override any values that may have been found in auth headers */ if (param_count) { zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(params), &hpos); do { if(zend_hash_get_current_key_ex(Z_ARRVAL_P(params), &key, NULL, &num_key, 0, &hpos)==HASH_KEY_IS_STRING) { if(zend_hash_get_current_data_ex(Z_ARRVAL_P(params), (void **)&item_param, &hpos)!=FAILURE) { if(oauth_provider_set_param_value(sop->oauth_params, key, item_param)==FAILURE) { return; } } } } while(zend_hash_move_forward_ex(Z_ARRVAL_P(params), &hpos)==SUCCESS); } } /* }}} */ /* {{{ proto void OAuthProvider::callConsumerHandler() calls the registered consumer key handler function */ SOP_METHOD(callconsumerHandler) { OAUTH_PROVIDER_CALL_CB(INTERNAL_FUNCTION_PARAM_PASSTHRU, OAUTH_PROVIDER_CONSUMER_CB); } /* }}} */ /* {{{ proto void OAuthProvider::callTokenHandler() calls the registered token handler function */ SOP_METHOD(calltokenHandler) { OAUTH_PROVIDER_CALL_CB(INTERNAL_FUNCTION_PARAM_PASSTHRU, OAUTH_PROVIDER_TOKEN_CB); } /* }}} */ /* {{{ proto void OAuthProvider::callTokenHandler() calls the registered token handler function */ SOP_METHOD(callTimestampNonceHandler) { OAUTH_PROVIDER_CALL_CB(INTERNAL_FUNCTION_PARAM_PASSTHRU, OAUTH_PROVIDER_TSNONCE_CB); } /* }}} */ /* {{{ proto void OAuthProvider::consumerHandler(callback cb) */ SOP_METHOD(consumerHandler) { oauth_provider_register_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, OAUTH_PROVIDER_CONSUMER_CB); } /* }}} */ /* {{{ proto void OAuthProvider::tokenHandler(callback cb) */ SOP_METHOD(tokenHandler) { oauth_provider_register_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, OAUTH_PROVIDER_TOKEN_CB); } /* }}} */ /* {{{ proto void OAuthProvider::timestampNonceHandler(callback cb) */ SOP_METHOD(timestampNonceHandler) { oauth_provider_register_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, OAUTH_PROVIDER_TSNONCE_CB); } /* }}} */ /* {{{ proto void OAuthProvider::isRequestTokenEndpoint(bool will_issue_request_token) */ SOP_METHOD(isRequestTokenEndpoint) { zend_bool req_api = 0; zval *pthis; php_oauth_provider *sop; if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ob", &pthis, oauthprovider, &req_api)==FAILURE) { return; } sop = fetch_sop_object(pthis TSRMLS_CC); zend_update_property_bool(Z_OBJCE_P(pthis), pthis, "request_token_endpoint", sizeof("request_token_endpoint") - 1, req_api TSRMLS_CC); } /* }}} */ SOP_METHOD(setRequestTokenPath) { zval *pthis; php_oauth_provider *sop; char *path; int path_len; if (FAILURE==zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &pthis, oauthprovider, &path, &path_len)) { return; } sop = fetch_sop_object(pthis TSRMLS_CC); OAUTH_PROVIDER_SET_ENDPOINT(sop->endpoint_paths[OAUTH_PROVIDER_PATH_REQUEST], path) RETURN_TRUE; } /* {{{ proto void OAuthProvider::checkOAuthRequest([string url [, string request_method]]) */ SOP_METHOD(checkOAuthRequest) { zval *retval = NULL, **param, *pthis, *token_secret = NULL, *consumer_secret, *req_signature, *sig_method; oauth_sig_context *sig_ctx = NULL; php_oauth_provider *sop; ulong missing_param_count = 0, mp_count = 1; char additional_info[512] = "", *http_verb = NULL, *uri = NULL, *sbs = NULL, *signature = NULL, *current_uri = NULL; HashPosition hpos; HashTable *sbs_vars = NULL; int http_verb_len = 0, uri_len = 0, is_token_required = 0; if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|ss", &pthis, oauthprovider, &uri, &uri_len, &http_verb, &http_verb_len)==FAILURE) { return; } sop = fetch_sop_object(pthis TSRMLS_CC); if(!http_verb_len) { http_verb = oauth_provider_get_http_verb(TSRMLS_C); } if(!http_verb) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to detect HTTP method, set a HTTP method via OAuthProvider::checkOAuthRequest()"); return; } ALLOC_HASHTABLE(sbs_vars); zend_hash_init(sbs_vars, 0, NULL, ZVAL_PTR_DTOR, 0); if(PG(http_globals)[TRACK_VARS_GET]) { zval *tmp_copy; zend_hash_merge(sbs_vars, HASH_OF(PG(http_globals)[TRACK_VARS_GET]), (copy_ctor_func_t)zval_add_ref, (void *)&tmp_copy, sizeof(zval *), 0); } if(PG(http_globals)[TRACK_VARS_POST]) { zval *tmp_copy; zend_hash_merge(sbs_vars, HASH_OF(PG(http_globals)[TRACK_VARS_POST]), (copy_ctor_func_t)zval_add_ref, (void *)&tmp_copy, sizeof(zval *), 0); } if(zend_hash_num_elements(sop->oauth_params)) { zval *tmp_copy; zend_hash_merge(sbs_vars, sop->oauth_params, (copy_ctor_func_t)zval_add_ref, (void *)&tmp_copy, sizeof(zval *), 0); } if (zend_hash_num_elements(sop->custom_params)) { /* apply custom params */ oauth_provider_apply_custom_param(sbs_vars, sop->custom_params); } zend_hash_internal_pointer_reset_ex(sbs_vars, &hpos); /* set the standard stuff present in every request if its found in sbs_vars, IE if we find oauth_consumer_key, set $oauth->consumer_key */ oauth_provider_set_std_params(pthis, sbs_vars TSRMLS_CC); if (!uri) { /* get current uri */ uri = current_uri = oauth_provider_get_current_uri(TSRMLS_C); } /* if we are in an API which issues a request token, there are is no token handler called */ if (!(is_token_required=oauth_provider_token_required(pthis, uri TSRMLS_CC))) { /* by default, oauth_token is required; remove from the required list */ oauth_provider_remove_required_param(sop->required_params, "oauth_token"); } oauth_provider_check_required_params(sop->required_params, sbs_vars, sop->missing_params TSRMLS_CC); missing_param_count = zend_hash_num_elements(sop->missing_params); if(missing_param_count) { zend_hash_internal_pointer_reset_ex(sop->missing_params, &hpos); do { if(zend_hash_get_current_data_ex(sop->missing_params, (void **)¶m, &hpos)==SUCCESS) { snprintf(additional_info, 512, "%s%s%s", additional_info, Z_STRVAL_PP(param), (missing_param_count > 1 && missing_param_count!=mp_count++) ? "%26" : ""); } } while(zend_hash_move_forward_ex(sop->missing_params, &hpos)==SUCCESS); soo_handle_error(NULL, OAUTH_PARAMETER_ABSENT, "Missing required parameters", NULL, additional_info TSRMLS_CC); FREE_ARGS_HASH(sbs_vars); OAUTH_PROVIDER_FREE_STRING(current_uri); return; } sig_method = zend_read_property(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_SIGNATURE_METHOD, sizeof(OAUTH_PROVIDER_SIGNATURE_METHOD) - 1, 1 TSRMLS_CC); do { if (sig_method && Z_STRLEN_P(sig_method)) { sig_ctx = oauth_create_sig_context(Z_STRVAL_P(sig_method)); if (OAUTH_SIGCTX_TYPE_NONE!=sig_ctx->type) { break; } OAUTH_SIGCTX_FREE(sig_ctx); } soo_handle_error(NULL, OAUTH_SIGNATURE_METHOD_REJECTED, "Unknown signature method", NULL, NULL TSRMLS_CC); FREE_ARGS_HASH(sbs_vars); OAUTH_PROVIDER_FREE_STRING(current_uri); return; } while (0); do { long cb_res; retval = oauth_provider_call_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, OAUTH_PROVIDER_CONSUMER_CB); if (retval) { convert_to_long(retval); cb_res = Z_LVAL_P(retval); zval_ptr_dtor(&retval); if (OAUTH_OK!=cb_res) { soo_handle_error(NULL, cb_res, "Invalid consumer key", NULL, additional_info TSRMLS_CC); break; } } else if (EG(exception)) { /* pass exceptions */ break; } if (is_token_required) { retval = oauth_provider_call_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, OAUTH_PROVIDER_TOKEN_CB); if (retval) { convert_to_long(retval); cb_res = Z_LVAL_P(retval); zval_ptr_dtor(&retval); if (OAUTH_OK!=cb_res) { soo_handle_error(NULL, cb_res, "Invalid token", NULL, additional_info TSRMLS_CC); break; } } else if (EG(exception)) { /* pass exceptions */ break; } } retval = oauth_provider_call_cb(INTERNAL_FUNCTION_PARAM_PASSTHRU, OAUTH_PROVIDER_TSNONCE_CB); if (retval) { convert_to_long(retval); cb_res = Z_LVAL_P(retval); zval_ptr_dtor(&retval); if (OAUTH_OK!=cb_res) { soo_handle_error(NULL, cb_res, "Invalid nonce/timestamp combination", NULL, additional_info TSRMLS_CC); break; } } else if (EG(exception)) { /* pass exceptions */ break; } /* now for the signature stuff */ sbs = oauth_generate_sig_base(NULL, http_verb, uri, sbs_vars, NULL TSRMLS_CC); if (sbs) { consumer_secret = zend_read_property(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_CONSUMER_SECRET, sizeof(OAUTH_PROVIDER_CONSUMER_SECRET) - 1, 1 TSRMLS_CC); convert_to_string_ex(&consumer_secret); if (is_token_required) { token_secret = zend_read_property(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_TOKEN_SECRET, sizeof(OAUTH_PROVIDER_TOKEN_SECRET) - 1, 1 TSRMLS_CC); convert_to_string_ex(&token_secret); } signature = soo_sign(NULL, sbs, consumer_secret, token_secret, sig_ctx TSRMLS_CC); } req_signature = zend_read_property(Z_OBJCE_P(pthis), pthis, OAUTH_PROVIDER_SIGNATURE, sizeof(OAUTH_PROVIDER_SIGNATURE) - 1, 1 TSRMLS_CC); if (!signature || !Z_STRLEN_P(req_signature) || strcmp(signature, Z_STRVAL_P(req_signature))) { soo_handle_error(NULL, OAUTH_INVALID_SIGNATURE, "Signatures do not match", NULL, sbs TSRMLS_CC); } OAUTH_PROVIDER_FREE_STRING(sbs); OAUTH_PROVIDER_FREE_STRING(signature); } while (0); OAUTH_SIGCTX_FREE(sig_ctx); OAUTH_PROVIDER_FREE_STRING(current_uri); FREE_ARGS_HASH(sbs_vars); } /* }}} */ /* {{{ proto void OAuthProvider::addRequiredParameter(string $required_param) */ SOP_METHOD(addRequiredParameter) { zval *pthis; char *required_param; php_oauth_provider *sop; ulong req_param_len; if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &pthis, oauthprovider, &required_param, &req_param_len)==FAILURE) { return; } sop = fetch_sop_object(pthis TSRMLS_CC); if(oauth_provider_add_required_param(sop->required_params, required_param)==SUCCESS) { RETURN_TRUE; } RETURN_FALSE; } /* }}} */ /* {{{ proto void OAuthProvider::setParam(string $key, mixed $val) */ SOP_METHOD(setParam) { zval *pthis, *param_val = NULL; char *param_key; ulong param_key_len; php_oauth_provider *sop; if (FAILURE==zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|z/", &pthis, oauthprovider, ¶m_key, ¶m_key_len, ¶m_val)) { return; } sop = fetch_sop_object(pthis TSRMLS_CC); if (!param_val) { RETURN_BOOL(SUCCESS==zend_hash_del(sop->custom_params, param_key, param_key_len+1)); } else { Z_ADDREF_P(param_val); RETURN_BOOL(SUCCESS==zend_hash_add(sop->custom_params, param_key, param_key_len+1, ¶m_val, sizeof(zval **), NULL)); } } /* }}} */ /* {{{ proto void OAuthProvider::removeRequiredParameter(string $required_param) */ SOP_METHOD(removeRequiredParameter) { zval *pthis; char *required_param; php_oauth_provider *sop; ulong req_param_len; if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &pthis, oauthprovider, &required_param, &req_param_len)==FAILURE) { return; } sop = fetch_sop_object(pthis TSRMLS_CC); if(oauth_provider_remove_required_param(sop->required_params, required_param)==SUCCESS) { RETURN_TRUE; } RETURN_FALSE; } /* }}} */ /* {{{ proto string OAuthProvider::generateToken(int $size[, bool $string = false]) */ SOP_METHOD(generateToken) { long size, reaped = 0; int strong = 0; char *iv = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|b", &size, &strong)==FAILURE) { return; } if (size < 1 || size > INT_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot generate token with a size of less than 1 or greater than %d", INT_MAX); return; } iv = ecalloc(size+1, 1); do { #if PHP_WIN32 /* * The Windows port has been ripped from the mcrypt extension; thanks guys! ;-) */ HCRYPTPROV hCryptProv; BYTE *iv_b = (BYTE *) iv; if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { break; } if (!CryptGenRandom(hCryptProv, size, iv_b)) { break; } reaped = size; #else int fd; fd = open(strong?"/dev/random":"/dev/urandom", O_RDONLY); if (fd < 0) { break; } while (reaped < size) { register int n; n = read(fd, iv + reaped, size - reaped); if (n < 0) { break; } reaped += n; } close(fd); #endif } while (0); if (reaped < size) { if (strong) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not gather enough random data, falling back on rand()"); } while (reaped < size) { iv[reaped++] = (char) (255.0 * php_rand(TSRMLS_C) / RAND_MAX); } } RETURN_STRINGL(iv, size, 0); } /* }}} */ /* {{{ proto void OAuthProvider::reportProblem(Exception $e) */ SOP_METHOD(reportProblem) { zval *exception, *code, *sbs, *missing_params; zend_class_entry *ex_ce; zend_bool out_malloced = 0; char *out, *tmp_out, *http_header_line; size_t pr_len; ulong lcode; uint http_code; sapi_header_line ctr = {0}; zend_bool send_headers = 1; #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) ex_ce = zend_exception_get_default(); #else ex_ce = zend_exception_get_default(TSRMLS_C); #endif if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &exception, ex_ce, &send_headers)==FAILURE) { return; } /* XXX good candidate for refactoring */ code = zend_read_property(Z_OBJCE_P(exception), exception, "code", sizeof("code") - 1, 1 TSRMLS_CC); lcode = Z_LVAL_P(code); switch(lcode) { case OAUTH_BAD_TIMESTAMP: http_code = OAUTH_ERR_BAD_AUTH; out = "oauth_problem=timestamp_refused"; break; case OAUTH_BAD_NONCE: http_code = OAUTH_ERR_BAD_AUTH; out = "oauth_problem=nonce_used"; break; case OAUTH_CONSUMER_KEY_UNKNOWN: http_code = OAUTH_ERR_BAD_AUTH; out = "oauth_problem=consumer_key_unknown"; break; case OAUTH_CONSUMER_KEY_REFUSED: http_code = OAUTH_ERR_BAD_AUTH; out = "oauth_problem=consumer_key_refused"; break; case OAUTH_TOKEN_USED: http_code = OAUTH_ERR_BAD_AUTH; out = "oauth_problem=token_used"; break; case OAUTH_TOKEN_EXPIRED: http_code = OAUTH_ERR_BAD_AUTH; out = "oauth_problem=token_expired"; break; case OAUTH_TOKEN_REVOKED: http_code = OAUTH_ERR_BAD_AUTH; out = "oauth_problem=token_revoked"; break; case OAUTH_TOKEN_REJECTED: http_code = OAUTH_ERR_BAD_AUTH; out = "oauth_problem=token_rejected"; break; case OAUTH_VERIFIER_INVALID: http_code = OAUTH_ERR_BAD_AUTH; out = "oauth_problem=verifier_invalid"; break; case OAUTH_INVALID_SIGNATURE: http_code = OAUTH_ERR_BAD_AUTH; out = "oauth_problem=signature_invalid"; sbs = zend_read_property(Z_OBJCE_P(exception), exception, "additionalInfo", sizeof("additionalInfo") - 1, 1 TSRMLS_CC); if (sbs && IS_NULL!=Z_TYPE_P(sbs)) { convert_to_string_ex(&sbs); if(Z_STRLEN_P(sbs)) { pr_len = Z_STRLEN_P(sbs) + strlen(out) + sizeof("&debug_sbs="); tmp_out = emalloc(pr_len); /* sbs url encoded so XSS shouldn't be an issue here */ snprintf(tmp_out, pr_len, "%s&debug_sbs=%s", out, Z_STRVAL_P(sbs)); out = tmp_out; out_malloced = 1; } } break; case OAUTH_SIGNATURE_METHOD_REJECTED: http_code = OAUTH_ERR_BAD_REQUEST; out = "oauth_problem=signature_method_rejected"; break; case OAUTH_PARAMETER_ABSENT: http_code = OAUTH_ERR_BAD_REQUEST; out = "oauth_problem=parameter_absent"; missing_params = zend_read_property(Z_OBJCE_P(exception), exception, "additionalInfo", sizeof("additionalInfo") - 1, 1 TSRMLS_CC); if(missing_params) { convert_to_string_ex(&missing_params); if(Z_STRLEN_P(missing_params)) { pr_len = Z_STRLEN_P(missing_params) + strlen(out) + sizeof("&oauth_parameters_absent="); tmp_out = emalloc(pr_len); snprintf(tmp_out, pr_len, "%s&oauth_parameters_absent=%s", out, Z_STRVAL_P(missing_params)); out = tmp_out; out_malloced = 1; } } break; default: http_code = OAUTH_ERR_INTERNAL_ERROR; out = emalloc(48); snprintf(out, 48, "oauth_problem=unknown_problem&code=%d", lcode); out_malloced = 1; } ZVAL_STRINGL(return_value, out, strlen(out), 1); if(send_headers) { if(http_code==OAUTH_ERR_BAD_REQUEST) { http_header_line = "HTTP/1.1 400 Bad Request"; } else { http_header_line = "HTTP/1.1 401 Unauthorized"; } ctr.line = http_header_line; ctr.line_len = strlen(http_header_line); ctr.response_code = http_code; sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); } if(out_malloced) { efree(out); } } /* }}} */ static void oauth_provider_free_storage(void *obj TSRMLS_DC) /* {{{ */ { php_oauth_provider *sop; sop = (php_oauth_provider *)obj; #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) if (sop->zo.guards) { zend_hash_destroy(sop->zo.guards); FREE_HASHTABLE(sop->zo.guards); } if (sop->zo.properties) { zend_hash_destroy(sop->zo.properties); FREE_HASHTABLE(sop->zo.properties); } #else zend_object_std_dtor(&sop->zo TSRMLS_CC); #endif OAUTH_PROVIDER_FREE_FCALL_INFO(sop->consumer_handler); OAUTH_PROVIDER_FREE_FCALL_INFO(sop->token_handler); OAUTH_PROVIDER_FREE_FCALL_INFO(sop->tsnonce_handler); FREE_ARGS_HASH(sop->missing_params); FREE_ARGS_HASH(sop->oauth_params); FREE_ARGS_HASH(sop->required_params); FREE_ARGS_HASH(sop->custom_params); OAUTH_PROVIDER_FREE_STRING(sop->endpoint_paths[OAUTH_PROVIDER_PATH_REQUEST]); OAUTH_PROVIDER_FREE_STRING(sop->endpoint_paths[OAUTH_PROVIDER_PATH_ACCESS]); OAUTH_PROVIDER_FREE_STRING(sop->endpoint_paths[OAUTH_PROVIDER_PATH_AUTH]); efree(sop); } /* }}} */ static zend_object_value oauth_provider_register(php_oauth_provider *soo TSRMLS_DC) /* {{{ */ { zend_object_value rv; rv.handle = zend_objects_store_put(soo, (zend_objects_store_dtor_t)zend_objects_destroy_object, oauth_provider_free_storage, NULL TSRMLS_CC); rv.handlers = (zend_object_handlers *)&oauth_provider_obj_hndlrs; return rv; } static php_oauth_provider* oauth_provider_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */ { php_oauth_provider *nos; #ifndef ZEND_ENGINE_2_4 zval *tmp; #endif nos = ecalloc(1, sizeof(php_oauth_provider)); #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) ALLOC_HASHTABLE(nos->zo.properties); zend_hash_init(nos->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0); nos->zo.ce = ce; nos->zo.guards = NULL; #else zend_object_std_init(&nos->zo, ce TSRMLS_CC); #ifdef ZEND_ENGINE_2_4 object_properties_init(&nos->zo, ce); #else zend_hash_copy(nos->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); #endif #endif return nos; } OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider__construct, 0, 0, 0) ZEND_ARG_INFO(0, params_array) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_noparams, 0, 0, 0) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_check, 0, 0, 0) ZEND_ARG_INFO(0, uri) ZEND_ARG_INFO(0, method) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_handler, 0, 0, 1) ZEND_ARG_INFO(0, function_name) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_reportproblem, 0, 0, 1) ZEND_ARG_INFO(0, oauthexception) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_req_token, 0, 0, 1) ZEND_ARG_INFO(0, params_array) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_set_req_param, 0, 0, 1) ZEND_ARG_INFO(0, req_params) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_set_param, 0, 0, 1) ZEND_ARG_INFO(0, param_key) ZEND_ARG_INFO(0, param_val) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_set_path, 0, 0, 1) ZEND_ARG_INFO(0, path) ZEND_END_ARG_INFO() OAUTH_ARGINFO ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_generate_token, 0, 0, 1) ZEND_ARG_INFO(0, size) ZEND_ARG_INFO(0, strong) ZEND_END_ARG_INFO() static zend_function_entry oauth_provider_methods[] = { /* {{{ */ SOP_ME(__construct, arginfo_oauth_provider__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) SOP_ME(consumerHandler, arginfo_oauth_provider_handler, ZEND_ACC_PUBLIC) SOP_ME(tokenHandler, arginfo_oauth_provider_handler, ZEND_ACC_PUBLIC) SOP_ME(timestampNonceHandler, arginfo_oauth_provider_handler, ZEND_ACC_PUBLIC) SOP_ME(callconsumerHandler, arginfo_oauth_provider_noparams, ZEND_ACC_PUBLIC) SOP_ME(calltokenHandler, arginfo_oauth_provider_noparams, ZEND_ACC_PUBLIC) SOP_ME(callTimestampNonceHandler, arginfo_oauth_provider_noparams, ZEND_ACC_PUBLIC) SOP_ME(checkOAuthRequest, arginfo_oauth_provider_check, ZEND_ACC_PUBLIC) SOP_ME(isRequestTokenEndpoint, arginfo_oauth_provider_req_token, ZEND_ACC_PUBLIC) SOP_ME(setRequestTokenPath, arginfo_oauth_provider_set_path, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) SOP_ME(addRequiredParameter, arginfo_oauth_provider_set_req_param, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) SOP_ME(reportProblem, arginfo_oauth_provider_reportproblem, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) SOP_ME(setParam, arginfo_oauth_provider_set_param, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) SOP_ME(removeRequiredParameter, arginfo_oauth_provider_set_req_param, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) SOP_ME(generateToken, arginfo_oauth_provider_generate_token, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) PHP_MALIAS(oauthprovider, is2LeggedEndpoint, isRequestTokenEndpoint, arginfo_oauth_provider_req_token, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; static zend_object_value oauth_provider_create_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */ { php_oauth_provider *oprovider; oprovider = oauth_provider_new(ce TSRMLS_CC); return oauth_provider_register(oprovider TSRMLS_CC); } /* }}} */ extern int oauth_provider_register_class(TSRMLS_D) /* {{{ */ { zend_class_entry osce; INIT_CLASS_ENTRY(osce, "OAuthProvider", oauth_provider_methods); osce.create_object = oauth_provider_create_object; oauthprovider = zend_register_internal_class(&osce TSRMLS_CC); memcpy(&oauth_provider_obj_hndlrs, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); return SUCCESS; } /* }}} */ /** * Local Variables: * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: t * End: * vim600: fdm=marker * vim: noet sw=4 ts=4 noexpandtab */ oauth-1.2.3/php_oauth.h100644 0 0 25110 100644 7704 /* +----------------------------------------------------------------------+ | See LICENSE file for further copyright information | +----------------------------------------------------------------------+ | Authors: John Jawed | | Felipe Pena | | Rasmus Lerdorf | +----------------------------------------------------------------------+ */ /* $Id: php_oauth.h 327854 2012-10-01 20:34:34Z jawed $ */ #ifndef PHP_OAUTH_H #define PHP_OAUTH_H #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #ifdef PHP_WIN32 #include "win32/time.h" #endif #include "SAPI.h" #include "zend_API.h" #include "zend_variables.h" #include "ext/standard/head.h" #include "php_globals.h" #include "php_main.h" #include "php_ini.h" #include "ext/standard/php_string.h" #include "ext/standard/php_rand.h" #include "ext/standard/php_smart_str.h" #include "ext/standard/info.h" #include "ext/standard/php_string.h" #include "ext/standard/php_versioning.h" #include "ext/standard/url.h" #include "php_variables.h" #include "zend_exceptions.h" #include "zend_interfaces.h" #include "php_globals.h" #include "ext/standard/file.h" #include "ext/standard/base64.h" #include "ext/standard/php_lcg.h" #include "ext/pcre/php_pcre.h" #include "php_network.h" #if OAUTH_USE_CURL #include #define CLEANUP_CURL_AND_FORM(f,h) \ curl_easy_cleanup(h); \ curl_formfree(f); #endif #ifndef Z_ADDREF_P #define Z_ADDREF_P(pz) (++(pz)->refcount) #define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz)) #endif #ifndef Z_DELREF_P #define Z_DELREF_P(pz) (--(pz)->refcount) #endif #if ZEND_MODULE_API_NO >= 20100409 #ifndef ZEND_ENGINE_2_4 #define ZEND_ENGINE_2_4 #endif #endif #define PHP_OAUTH_VERSION 1.2.3 #ifdef ZEND_ENGINE_2_4 # define OAUTH_READ_PROPERTY(_obj, _mem, _type) zend_get_std_object_handlers()->read_property(_obj, _mem, _type, key TSRMLS_CC) # define OAUTH_WRITE_PROPERTY(_obj, _mem, _val) zend_get_std_object_handlers()->write_property(_obj, _mem, _val, key TSRMLS_CC) #else # define OAUTH_READ_PROPERTY(_obj, _mem, _type) zend_get_std_object_handlers()->read_property(_obj, _mem, _type TSRMLS_CC) # define OAUTH_WRITE_PROPERTY(_obj, _mem, _val) zend_get_std_object_handlers()->write_property(_obj, _mem, _val TSRMLS_CC) #endif #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || PHP_MAJOR_VERSION > 5 # define OAUTH_ARGINFO # define OAUTH_IS_CALLABLE_CC TSRMLS_CC #else # define OAUTH_ARGINFO static # define OAUTH_IS_CALLABLE_CC #endif #define __stringify_1(x) #x #define __stringify(x) __stringify_1(x) #define __OAUTH_EXT_VER PHP_OAUTH_VERSION #define OAUTH_EXT_VER __stringify(__OAUTH_EXT_VER) #define OAUTH_USER_AGENT "PECL-OAuth/" __stringify(__OAUTH_EXT_VER) #define OAUTH_HTTP_PORT 80 #define OAUTH_HTTPS_PORT 443 #define OAUTH_MAX_REDIRS 4L #define OAUTH_MAX_HEADER_LEN 512L #define OAUTH_AUTH_TYPE_URI 0x01 #define OAUTH_AUTH_TYPE_FORM 0x02 #define OAUTH_AUTH_TYPE_AUTHORIZATION 0x03 #define OAUTH_AUTH_TYPE_NONE 0x04 #define OAUTH_SIG_METHOD_HMACSHA1 "HMAC-SHA1" #define OAUTH_SIG_METHOD_HMACSHA256 "HMAC-SHA256" #define OAUTH_SIG_METHOD_RSASHA1 "RSA-SHA1" #define OAUTH_SIG_METHOD_PLAINTEXT "PLAINTEXT" extern zend_module_entry oauth_module_entry; #define phpext_oauth_ptr &oauth_module_entry #define PHP_OAUTH_API #define OAUTH_ATTR_CONSUMER_KEY "oauth_consumer_key" #define OAUTH_ATTR_CONSUMER_SECRET "oauth_consumer_secret" #define OAUTH_ATTR_ACCESS_TOKEN "oauth_access_token" #define OAUTH_RAW_LAST_RES "oauth_last_response_raw" #define OAUTH_ATTR_LAST_RES_INFO "oauth_last_response_info" #define OAUTH_ATTR_SIGMETHOD "oauth_sig_method" #define OAUTH_ATTR_TOKEN "oauth_token" #define OAUTH_ATTR_TOKEN_SECRET "oauth_token_secret" #define OAUTH_ATTR_AUTHMETHOD "oauth_auth_method" #define OAUTH_ATTR_OAUTH_VERSION "oauth_version" #define OAUTH_ATTR_OAUTH_NONCE "oauth_nonce" #define OAUTH_ATTR_OAUTH_USER_NONCE "oauth_user_nonce" #define OAUTH_ATTR_CA_PATH "oauth_ssl_ca_path" #define OAUTH_ATTR_CA_INFO "oauth_ssl_ca_info" #define OAUTH_HTTP_METHOD_GET "GET" #define OAUTH_HTTP_METHOD_POST "POST" #define OAUTH_HTTP_METHOD_PUT "PUT" #define OAUTH_HTTP_METHOD_HEAD "HEAD" #define OAUTH_HTTP_METHOD_DELETE "DELETE" #define OAUTH_REQENGINE_STREAMS 1 #define OAUTH_REQENGINE_CURL 2 #define OAUTH_FETCH_USETOKEN 1 #define OAUTH_FETCH_SIGONLY 2 #define OAUTH_FETCH_HEADONLY 4 #define OAUTH_OVERRIDE_HTTP_METHOD 8 #define OAUTH_SSLCHECK_NONE 0 #define OAUTH_SSLCHECK_HOST 1 #define OAUTH_SSLCHECK_PEER 2 #define OAUTH_SSLCHECK_BOTH (OAUTH_SSLCHECK_HOST | OAUTH_SSLCHECK_PEER) #define OAUTH_DEFAULT_VERSION "1.0" /* errors */ #define OAUTH_ERR_CONTENT_TYPE "invalidcontentttype" #define OAUTH_ERR_BAD_REQUEST 400 #define OAUTH_ERR_BAD_AUTH 401 #define OAUTH_ERR_INTERNAL_ERROR 503 /* params */ #define OAUTH_PARAM_CONSUMER_KEY "oauth_consumer_key" #define OAUTH_PARAM_SIGNATURE "oauth_signature" #define OAUTH_PARAM_SIGNATURE_METHOD "oauth_signature_method" #define OAUTH_PARAM_TIMESTAMP "oauth_timestamp" #define OAUTH_PARAM_NONCE "oauth_nonce" #define OAUTH_PARAM_VERSION "oauth_version" #define OAUTH_PARAM_TOKEN "oauth_token" #define OAUTH_PARAM_ASH "oauth_session_handle" #define OAUTH_PARAM_VERIFIER "oauth_verifier" #define OAUTH_PARAM_CALLBACK "oauth_callback" /* values */ #define OAUTH_CALLBACK_OOB "oob" #define OAUTH_PARAM_PREFIX "oauth_" #define OAUTH_PARAM_PREFIX_LEN 6 #ifdef ZTS #include "TSRM.h" #endif PHP_MINIT_FUNCTION(oauth); PHP_MSHUTDOWN_FUNCTION(oauth); PHP_MINFO_FUNCTION(oauth); #ifdef ZTS #define OAUTH(v) TSRMG(oauth_globals_id, zend_oauth_globals *, v) #else #define OAUTH(v) (oauth_globals.v) #endif typedef enum { OAUTH_SIGCTX_TYPE_NONE, OAUTH_SIGCTX_TYPE_HMAC, OAUTH_SIGCTX_TYPE_RSA, OAUTH_SIGCTX_TYPE_PLAIN } oauth_sigctx_type; typedef struct { oauth_sigctx_type type; char *hash_algo; zval *privatekey; } oauth_sig_context; #define OAUTH_SIGCTX_INIT(ctx) { \ (ctx) = emalloc(sizeof(*(ctx))); \ (ctx)->type = OAUTH_SIGCTX_TYPE_NONE; \ (ctx)->hash_algo = NULL; \ (ctx)->privatekey = NULL; \ } #define OAUTH_SIGCTX_HMAC(ctx, algo) { \ (ctx)->type = OAUTH_SIGCTX_TYPE_HMAC; \ (ctx)->hash_algo = algo; \ } #define OAUTH_SIGCTX_PLAIN(ctx) { \ (ctx)->type = OAUTH_SIGCTX_TYPE_PLAIN; \ } #define OAUTH_SIGCTX_FREE_PRIVATEKEY(ctx) { \ if ((ctx)->privatekey) { \ oauth_free_privatekey((ctx)->privatekey TSRMLS_CC); \ (ctx)->privatekey = NULL; \ } \ } #define OAUTH_SIGCTX_SET_PRIVATEKEY(ctx, privkey) { \ OAUTH_SIGCTX_FREE_PRIVATEKEY(ctx) \ (ctx)->privatekey = privkey; \ } #define OAUTH_SIGCTX_RSA(ctx, algo) { \ (ctx)->type = OAUTH_SIGCTX_TYPE_RSA; \ (ctx)->hash_algo = algo; \ } #define OAUTH_SIGCTX_FREE(ctx) { \ if (ctx) { \ OAUTH_SIGCTX_FREE_PRIVATEKEY(ctx) \ efree((ctx)); \ } \ } typedef struct { char *sbs; smart_str headers_in; smart_str headers_out; smart_str body_in; smart_str body_out; smart_str curl_info; } php_so_debug; typedef struct { zend_object zo; HashTable *properties; smart_str lastresponse; smart_str headers_in; smart_str headers_out; char last_location_header[OAUTH_MAX_HEADER_LEN]; uint redirects; uint multipart_files_num; uint sslcheck; /* whether we check for SSL verification or not */ uint debug; /* verbose output */ uint follow_redirects; /* follow and sign redirects? */ uint reqengine; /* streams or curl */ long timeout; /* timeout in milliseconds */ char *nonce; char *timestamp; char *signature; zval *this_ptr; zval *debugArr; oauth_sig_context *sig_ctx; php_so_debug *debug_info; char **multipart_files; char **multipart_params; uint is_multipart; void ***thread_ctx; } php_so_object; #if (PHP_MAJOR_VERSION >= 6) #define ZEND_HASH_KEY_STRVAL(key) key.s typedef zstr zend_hash_key_type; #else #define ZEND_HASH_KEY_STRVAL(key) key typedef char * zend_hash_key_type; #endif #ifndef Z_ADDREF_P #define Z_ADDREF_P(x) ZVAL_ADDREF(x) #endif #ifndef zend_parse_parameters_none #define zend_parse_parameters_none() \ zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") #endif void soo_handle_error(php_so_object *soo, long errorCode, char *msg, char *response, char *additional_info TSRMLS_DC); char *oauth_generate_sig_base(php_so_object *soo, const char *http_method, const char *uri, HashTable *post_args, HashTable *extra_args TSRMLS_DC); #ifndef zend_hash_quick_del #define HASH_DEL_KEY_QUICK 2 #define zend_hash_quick_del(ht, arKey, nKeyLength, h) \ zend_hash_del_key_or_index(ht, arKey, nKeyLength, h, HASH_DEL_KEY_QUICK) #endif #define SO_ME(func, arg_info, flags) PHP_ME(oauth, func, arg_info, flags) #define SO_MALIAS(func, alias, arg_info, flags) PHP_MALIAS(oauth, func, alias, arg_info, flags) #define SO_METHOD(func) PHP_METHOD(oauth, func) #define FREE_ARGS_HASH(a) \ if (a) { \ zend_hash_destroy(a); \ FREE_HASHTABLE(a); \ } #define INIT_SMART_STR(a) \ (a).len = 0; \ (a).c = NULL; #define HTTP_IS_REDIRECT(http_response_code) \ (http_response_code > 300 && http_response_code < 304) #define INIT_DEBUG_INFO(a) \ INIT_SMART_STR((a)->headers_out); \ INIT_SMART_STR((a)->body_in); \ INIT_SMART_STR((a)->body_out); \ INIT_SMART_STR((a)->curl_info); #define FREE_DEBUG_INFO(a) \ smart_str_free(&(a)->headers_out); \ smart_str_free(&(a)->body_in); \ smart_str_free(&(a)->body_out); \ smart_str_free(&(a)->curl_info); /* this and code that uses it is from ext/curl/interface.c */ #define CAAL(s, v) add_assoc_long_ex(info, s, sizeof(s), (long) v); #define CAAD(s, v) add_assoc_double_ex(info, s, sizeof(s), (double) v); #define CAAS(s, v) add_assoc_string_ex(info, s, sizeof(s), (char *) (v ? v : ""), 1); #define ADD_DEBUG_INFO(a, k, s, t) \ if(s.len) { \ smart_str_0(&(s)); \ if(t) { \ tmp = php_trim((s).c, (s).len, NULL, 0, NULL, 3 TSRMLS_CC); \ add_assoc_string((a), k, tmp, 1); \ efree(tmp); \ } else { \ add_assoc_string((a), k, (s).c, 1); \ } \ } #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define OAUTH_OK SUCCESS #if OAUTH_USE_CURL long make_req_curl(php_so_object *soo, const char *url, const smart_str *payload, const char *http_method, HashTable *request_headers TSRMLS_DC); #if LIBCURL_VERSION_NUM >= 0x071304 #define OAUTH_PROTOCOLS_ALLOWED CURLPROTO_HTTP | CURLPROTO_HTTPS #endif #endif void oauth_free_privatekey(zval *privatekey TSRMLS_DC); char *soo_sign(php_so_object *soo, char *message, zval *cs, zval *ts, const oauth_sig_context *ctx TSRMLS_DC); oauth_sig_context *oauth_create_sig_context(const char *sigmethod); char *oauth_url_encode(char *url, int url_len); #endif /** * Local Variables: * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: t * End: * vim600: fdm=marker * vim: noet sw=4 ts=4 noexpandtab */ oauth-1.2.3/provider.h100644 0 0 11015 100644 7546 /* +----------------------------------------------------------------------+ | See LICENSE file for further copyright information | +----------------------------------------------------------------------+ | Authors: John Jawed | | Felipe Pena | | Rasmus Lerdorf | | Tjerk Meesters | +----------------------------------------------------------------------+ */ /* $Id: php_oauth.h,v 1.18 2009/05/10 06:40:59 jawed Exp $ */ #ifndef PHP_OAUTH_P_H #define PHP_OAUTH_P_H #ifdef HAVE_CONFIG_H #include "config.h" #endif #define OAUTH_PROVIDER_COPY_ZVAL_FROM_PZVAL(dest, src) \ MAKE_STD_ZVAL(dest); \ *dest = *src; \ zval_copy_ctor(dest); #define OAUTH_PROVIDER_COPY_HASH_FROM_PZVAL(dest, src) \ if(dest) { zval_ptr_dtor(&dest); } \ OAUTH_PROVIDER_COPY_ZVAL_FROM_PZVAL(dest, src, 0) #define OAUTH_PROVIDER_CALL_CB(pt, m) \ zval *retval = NULL; \ retval = oauth_provider_call_cb(pt, m); \ COPY_PZVAL_TO_ZVAL(*return_value, retval); \ zval_ptr_dtor(&retval); #define OAUTH_PROVIDER_FREE_FCALL_INFO(o) \ if(o) { \ if(o->fcall_info->function_name) { zval_ptr_dtor(&o->fcall_info->function_name); } \ efree(o->fcall_info); \ efree(o); \ } #define OAUTH_PROVIDER_FREE_STRING(a) \ if(a) { \ efree(a); \ a = NULL; \ } #define OAUTH_PROVIDER_FREE_CB(c) \ if(c) { \ OAUTH_PROVIDER_FREE_FCALL_INFO(c); \ } \ #define OAUTH_PROVIDER_CHECK_PARAMS(s, r) \ if(oauth_provider_check_sapi(s, TRUE TSRMLS_CC)) { \ if(r) {\ RETURN_FALSE\ } \ } \ #define OAUTH_PROVIDER_SET_PARAM(tgt_param, param, exp, val) \ if(!strncasecmp(param, exp, strlen(exp))) { \ tgt_param = val;\ return SUCCESS;\ } #define OAUTH_PROVIDER_REQ_PARAM(a,b) \ if(!a) { \ oauth_provider_add_missing_param(sop,a,b);\ } #define OAUTH_PROVIDER_SET_PARAM_VALUE(ht,k,m,v) \ zend_hash_update(ht, k, strlen(k) + 1, (void**)v, Z_STRLEN_PP(v) + 1, NULL) #define OAUTH_PROVIDER_SET_STD_PARAM(h,k,m) \ if(zend_hash_find(h, k, sizeof(k), (void **) &dest_entry)!=FAILURE) { \ oauth_provider_set_param_member(provider_obj, m, *dest_entry TSRMLS_CC); \ } enum { OAUTH_PROVIDER_PATH_REQUEST, OAUTH_PROVIDER_PATH_ACCESS, OAUTH_PROVIDER_PATH_AUTH }; #define OAUTH_PROVIDER_SET_ENDPOINT(epp, path) \ OAUTH_PROVIDER_FREE_STRING(epp) \ epp = estrdup(path); typedef struct { zend_fcall_info *fcall_info; zend_fcall_info_cache fcall_info_cache; } php_oauth_provider_fcall; typedef struct { zend_object zo; HashTable *properties; HashTable *missing_params; /* oauth params which might be passed in requests */ HashTable *oauth_params; HashTable *required_params; HashTable *custom_params; char *endpoint_paths[3]; zval *zrequired_params; zval *this_ptr; php_oauth_provider_fcall *consumer_handler; php_oauth_provider_fcall *token_handler; php_oauth_provider_fcall *tsnonce_handler; unsigned int params_via_method; /* will ext/oauth set the proper header and error message? */ unsigned int handle_errors; } php_oauth_provider; extern int oauth_provider_register_class(TSRMLS_D); #define SOP_METHOD(func) PHP_METHOD(oauthprovider, func) #define SOP_ME(func, arg_info, flags) PHP_ME(oauthprovider, func, arg_info, flags) #ifndef OAUTH_PROVIDER_DEFAULT_METHODS #define OAUTH_PROVIDER_DEFAULT_METHODS OAUTH_AUTH_TYPE_AUTHORIZATION | OAUTH_AUTH_TYPE_FORM | OAUTH_AUTH_TYPE_URI #endif #define OAUTH_PROVIDER_CONSUMER_CB (1<<0) #define OAUTH_PROVIDER_TOKEN_CB (1<<1) #define OAUTH_PROVIDER_TSNONCE_CB (1<<2) #define OAUTH_PROVIDER_CONSUMER_KEY "consumer_key" #define OAUTH_PROVIDER_CONSUMER_SECRET "consumer_secret" #define OAUTH_PROVIDER_SIGNATURE "signature" #define OAUTH_PROVIDER_SIGNATURE_METHOD "signature_method" #define OAUTH_PROVIDER_TOKEN "token" #define OAUTH_PROVIDER_TOKEN_SECRET "token_secret" #define OAUTH_PROVIDER_NONCE "nonce" #define OAUTH_PROVIDER_TIMESTAMP "timestamp" #define OAUTH_PROVIDER_VERSION "version" #define OAUTH_PROVIDER_CALLBACK "callback" #define OAUTH_PROVIDER_VERIFIER "verifier" #define OAUTH_BAD_NONCE (1<<2) #define OAUTH_BAD_TIMESTAMP (1<<3) #define OAUTH_CONSUMER_KEY_UNKNOWN (1<<4) #define OAUTH_CONSUMER_KEY_REFUSED (1<<5) #define OAUTH_INVALID_SIGNATURE (1<<6) #define OAUTH_TOKEN_USED (1<<7) #define OAUTH_TOKEN_EXPIRED (1<<8) #define OAUTH_TOKEN_REVOKED (1<<9) #define OAUTH_TOKEN_REJECTED (1<<10) #define OAUTH_VERIFIER_INVALID (1<<11) #define OAUTH_PARAMETER_ABSENT (1<<12) #define OAUTH_SIGNATURE_METHOD_REJECTED (1<<13) #endif oauth-1.2.3/LICENSE100644 0 0 3040 100644 6527 Software Copyright License Agreement (BSD License) Copyright (c) 2008, Yahoo! Inc. All rights reserved. Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Yahoo! Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of Yahoo! Inc. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.