package.xml0000644000175000001440000005224313731057347012057 0ustar mikeusers 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 Sean DuBois SeanDer SeanDer@php.net yes Michael Wallner mike mike@php.net yes Felipe Pena felipe felipe@php.net yes Tjerk Meesters datibbaw datibbaw@php.net yes 2020-09-18 2.0.7 2.0 stable stable BSD * PHP 8 compatibility 7.0.0 1.4.0b1 hash oauth 2020-09-09 2.0.6 2.0 stable stable BSD * Fix github issue #14 (Fixes for 7.3/7.4 and opcache) * Fix PHP-7.4 compatibility of object handler * Fix memory leaks in OAuthProvider * Fix crash in OAuthProvider's handler registration methods due to unconditional addref * Fix crash in OAuth::fetch() due to modifying hash tables with a refcount>1 2020-02-06 2.0.5 2.0 stable stable BSD * fix config.w32 (cmb) * fix 7.3 segfault (rlerdorf) * replace uint-uint32_t, ulong-zend_ulong (Jan-E) * handle cases where a passed in array might be a const (keyurdg) * Fix configure for recent cURL versions (cmb) * Bug #76722 cURL library headers not recognized on Debian 9 (js361014) 2019-12-02 2.0.4 2.0 stable stable BSD * fix php_pcre_match_impl call in 7.4+ (Remi) 2018-09-30 2.0.3 2.0 stable stable BSD * Use _ex versions to avoid SIGABRT of during use of hash functions in 7.2+ (Derick Rethans) 2018-06-28 2.0.2 2.0 stable stable BSD * Fix bug #74163: Segfault in oauth_compare_value * Fix bug #73434: Null byte at end of array keys in getLastResponseInfo * Fix compatibility with PHP 7.3 2016-06-17 2.0.2 2.0-dev stable stable BSD * Fix #72006 2016-03-11 2.0.1 2.0 stable stable BSD * Fix multiple segfaults (kgovande, rlerdorf) 2016-01-02 2.0.0 2.0 stable stable BSD - PHP 7 Support - Bug 67658: configure does not detect missing pcre.h - Bug 67665: update fetch to accept 20X HTTP ranges - Bug 67883: check SERVER[REDIRECT_HTTP_AUTHORIZATION] for the Authorization header 2012-10-01 1.2.3 1.2 stable stable BSD - Fix reference counts not being incremented in OAuthProvider 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-2.0.7/examples/config.inc.php0000644000175000001440000000047313731057347016066 0ustar mikeusers oauth-2.0.7/examples/request_signing.php0000644000175000001440000000150713731057347017256 0ustar mikeuserssetToken(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-2.0.7/examples/request_token.php0000644000175000001440000000113613731057347016736 0ustar mikeusersgetRequestToken("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-2.0.7/examples/access_token.php0000644000175000001440000000117413731057347016511 0ustar mikeuserssetToken($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-2.0.7/examples/exec_api.php0000644000175000001440000000104013731057347015615 0ustar mikeuserssetToken($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-2.0.7/examples/README0000644000175000001440000000150713731057347014217 0ustar mikeusers=== 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-2.0.7/examples/yahoo/config.inc.php0000644000175000001440000000066313731057347017206 0ustar mikeusers oauth-2.0.7/examples/yahoo/request_signing.php0000644000175000001440000000127013731057347020372 0ustar mikeusersfetch("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-2.0.7/examples/yahoo/request_token.php0000644000175000001440000000110713731057347020053 0ustar mikeusersgetRequestToken("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-2.0.7/examples/yahoo/access_token.php0000644000175000001440000000115113731057347017623 0ustar mikeuserssetToken($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-2.0.7/examples/yahoo/exec_yql.php0000644000175000001440000000131413731057347016774 0ustar mikeuserssetToken($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-2.0.7/examples/yahoo/exec_yql_refresh_token.php0000644000175000001440000000275513731057347021724 0ustar mikeuserssetToken($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-2.0.7/examples/fireeagle/config.inc.php0000644000175000001440000000072313731057347020007 0ustar mikeusers oauth-2.0.7/examples/fireeagle/request_signing.php0000644000175000001440000000153613731057347021203 0ustar mikeuserssetToken(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-2.0.7/examples/fireeagle/request_token.php0000644000175000001440000000133313731057347020660 0ustar mikeusersgetRequestToken("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-2.0.7/examples/fireeagle/access_token.php0000644000175000001440000000117613731057347020436 0ustar mikeuserssetToken($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-2.0.7/examples/fireeagle/exec_update_user.php0000644000175000001440000000115013731057347021311 0ustar mikeuserssetToken($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-2.0.7/examples/netflix/config.inc.php0000644000175000001440000000054413731057347017536 0ustar mikeusers oauth-2.0.7/examples/netflix/request_token.php0000644000175000001440000000122313731057347020404 0ustar mikeusersgetRequestToken("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-2.0.7/examples/netflix/access_token.php0000644000175000001440000000114413731057347020157 0ustar mikeuserssetToken($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-2.0.7/examples/netflix/feeds.php0000644000175000001440000000132413731057347016604 0ustar mikeuserssetToken($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-2.0.7/examples/netflix/rental_history_atom.php0000644000175000001440000000223313731057347021604 0ustar mikeuserssetToken($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-2.0.7/examples/twitter/README0000644000175000001440000000007013731057347015713 0ustar mikeusersRun fetchTimeline.php through with your php-cli binary. oauth-2.0.7/examples/twitter/constants.php0000644000175000001440000000160113731057347017561 0ustar mikeusers oauth-2.0.7/examples/twitter/fetchTimeline.php0000644000175000001440000000305313731057347020330 0ustar mikeusersenableDebug(); $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-2.0.7/examples/twitter/php.jpg0000644000175000001440000005471213731057347016340 0ustar mikeusersJFIFHHCreated with GIMPC   C,  o   # !"312CScs$ABRb4QaqrDT%Ut&W')57:VYdeguw<!1"AQ2aq#B$3RS4T ?00000y@΁W,(]'-ĊL턧e%$l|߳GAo|EDZVrmLH\4lbG86*my]`f}R טaĕcaC: 7w=NV*+̵i|ji%ԧn峘;`֡8#JGwR78AA.7\XU_cy]=s3^MTo ƮpnkQc>v3:m/ďOg2E8~ю+4cIUbyiЮ{Zq\R}=tukU:;6R=T00000002 |w^0P0A$ ?.i zRBQACQjPt`wGH<["4}Keo>Qv|(\ v}LI]2C0$s:&AO Fd<]Mby3xäIk }>zT*BKe%7?m4뇸 v}_֩֟,K^c (EO:VA/OnebY9|Iil%RQtr%iI5 zdm^)Nkr+ &=&$%:VtpbpX S{zmUH9i<ŹJؽA1P'AL?m_Oeu/GةrΗj]ԣM5.YYCSɞCThꤥdEĕbIPIj+(̺|MN]GHsH[KdF 7m-D)l_+-${ E#$' E*3e Z5/%ΌkV {vpɦqHF6ThS  jũ&PjJ(7RGw_VدЀeaGL/RrQ#ۧZƐ};Ŏ7tUɱi λNxVʪ׾32(7'FFDy&&tL%&_k*S,1?L;x6z_;dH?,)Y:S*J=!diCAʉnWӆr0FCc=(b|olp7XWʙ¥o MB+uM$j%А scPNP{䏧bBOүё3Ef'>*aŮ({ Tߨ<c8wsFnkOU۬Z .L#Yl>wMk Kӊ >MNiΑمL5i;v_zrJV04ӥBcƟ~(ZÚR{6Ʀ{!0XU%='4фV4nmN6)4]RN__]Fǯ':*}{?FzҍԪiFGztq{}sѴ~]7$=&96[!-lb".( t4s·i+Zf4}TF4`[5G#bg;]a:c3׈̰'" fXXN w>0aGN'Xo=Ay4O (dԨB[I&.kVX|3'/\4:m]c )[w9+zZF&dLOPopZg7$#cѓAW^,0:Ai'/0HG)P?cT&V=s[^'oJIe:Za^n},kSJwZ78ɳ܍߂Syt">l)ֱ^3M{1C>Uv]4ULd#b_h62ۼ&p+j-5eh]0ڽ="|5 ;B6DKJ~s}Zx'Q*>57Չ${q*}zFu*N{6%{]Y5#s%O{6G1ɑ8i@!"dpx=6»J\_+-]YZ'MmRI$w_]x#}=#sA>h& |/_'l0+jpM^m@&ԐqKn~b>p]^=MMA|6Ssϳ ګU[!%M%yM҂J+a[ p/E47YQx[VY\nԜyԾ7n~i5L#27^m?Bmg|-uZmMM =SHN zJ&W;C Zjdz!tPD3 V+o@^[NH '%&#1O@Iv7D !DZ59v H^ۭ6`]TXzk+}4:tri1o83ITu7̃0ńZQV)ȱQ<iO>ѵiZuENڎs2,z o!Yfbje[* ~0io.*uh̚-E"e*E+K)uKЧG.][=Mx ՛ݑFe[&2 pj0*]m\'( mc&E1.FlbRM8;G<c.e;620Uu"#>kxDNfrKHU}"M )PǧIj2V5lI*Q6=1׳o|]Nq=s5V^T'qJCl!8yO9إL }+lǸ>GÃQ6,&OɶiW7@W4Jڊc.ƧҬ<ڵ*?P.B|+@ 'r|F5Q*6zlc+VG Bx8RP7i8ەH4H^Ǚ\ %SP3MG<,bJ-!?Ĕ?f"_e֕s9]ݯ{ mZ$Y%WF]HQµcyEiCVTm$m 1(Pk`|8ƛcs*SR] >˵thJЖUa$Бu&RR5cgiƥSnUʓlNK&s ib+m2C/BpƱXBcosksܣb0ܘEX0@x?PQ%#NP˦AQrR^'c6RE?' #SJԨ敡tSzh xM.Gx|JHETBvƠ}Bn9;y1k&MC!|cʅn| [V}~`qXMF rvd<1|cvfְK,x'j4ghlcJE$ !KC8c)ńcĺ!tI˂]bX01w Ѷ>q1WNĮ = դ=THܓv՗V *r?TK͸}4ͱN*iX MBy1MBx4^!ilIaʔSRWB Qtn=t+|p$R䈖 `P}A6n>Q̱_',Jb3[&\n壞RtyUj&Rę $lVhuR|%Q߻lyѤ"NBXxTyn>lq2)u4;u-#u(vRGUJkKsNO EpnR$Of0GukceAKʀ9z#Or!awI@4#bƉ4!6jE\_^UJ;=L\ꤪ&Z!ldС8-y6Msp#zA)]?x@''vFkJ]7v'xny ڞ`WOR*WuD^Ccܯ ea ~{5>^/&/ZxYSXZR U9ǿY}iN6'i6돖뇬3̦yjF {q.y1QES9Se#ljު|aSӮWO}٬W+U'!6U-(2?FݍӮ27*Hr/cqcά6+L>dzl u.JeϠ5jɑ˜|FTd/)[/LHo4ml}mޟEEi<Ґ$<ŵA8A |c@K&zzbrA!@'e*3x+۲SMNBLt`&(pi?㏴o8kPtz|Ntm5#IY;{5?悾ӵ_>Fj̱?gޏgNWJֿ-GԽ>2:1F㺸n tŏVSA6O+R}| =?ǰ ט.'PꂵuNTRhN8F݅{;ٚ~uu)^_SQ i߹:%&ЈkA(G]QG/e3 ?nDmk33Xye_nl$V{`vA<%1,;08onqW)? $^-zC=Oч3Gk]Ohz2V.'G'YnRS,#2[ђ='Ͱ7/&|yRиm-_A&=LAq5:1O㚹\ۯu]!yY`. Gl.8ef~BrxAGJԡWd^4CQcNzY&QQRfFq+7B %ti,!WyGuIdNd&Pѯl:ƿMX5RCA,O؋;wȭ88Hsvc􍢿֕L{40mUk(/WG=5DA]11beGed 9SB7[o,t mȒ)(pA*,~4c6Rwii$SqJW6%u G䣚2r.)]ELGtm%K2KC7üU_[mI(e/9WG|zn dR1F7=*Ty#.e[,ruPM1u'I5T@xAۢvkuR?ƽWM-Sw2Dd1ں, *c7n?&H6?p{U=iOdTRe("*GH#ѭ:~q/r(i3•/ZW׶VǾzr4* S#\5vI~=S+ei\)ZgZjjȫhX|? Eps=c[H 铓D~NԒn}{~#l nn┓*4Ž( w?u =ߞyI.5͝{Ÿ>}p* Dc{7{K Wx^M;S+51{8*?dhyo|Lwl}}| d YTxM3ɞ,9QE'O<4:x{72,Ic&eALJTBrE=c &S%ZY(8ENgۯQҊi\> '2ߩOW!sRjiM˚N8亨w&=0GK=$پQΣOG9D̝isaT=```^gw8sW'QO۩┑YHAAmzAVJ u wStζGSF-ՂfF]w6B<ŴdZ?J\u_?oV%M\|cvd1%Dy4ԀzHg]#yT׬?'|vAlsjwAM[ܫ8[EᩘM8= (Qjՠ?RG[y<\7&VM|,K?(IpXU DJoiMFүܿKM3Wzc9[4PEKqP?Q7q*K fCJ#trnK緶8;29@%#m6;~{ߗmfQz.Ϲo8S؃nIZHc T 0 Sp]6F}JoLRQJۂ>pzȚ{"yc74qSRQxـxK55\RP4tFA4A @]h<2ş%/YG+9[Γ`vzuҠ000Z]mL7ޞsg( `]ăeƤ"C̪ LΧUTA '7IzM~ "7<#}nK) &.1c\|pjmo540*ThBpښhQrDdRmaDEbxFU RjtZ7(okJW~6%ZZQGAxXۥU5?-˞:hޯ]j7@MF_ʟ^ȕp/YI|nL^{uf uGQ'!;<#'7yt"\ |BR:V:.%YYF8I=j>+6*VI}`*HΒ>+kEE/5Ptƪxm߮H5oDBYt2Ƴ#RX{`0t;m.-?53]jsАtpn/kmNBT9PVU$+ z$y Lcq;cEiIn[/UYy~\na[.׵iwiÏp|pxG|zmn5+;1a.OL8FaUCM->4,|fˎ@4Ꚃi;?)^ݝ eRPi2wuإEc000wJZa487j *Ej[.Yf|ĵ(Yl0CgSA4rA7roJʣ?j9L1"qj=$vUW\b%s8_H%PY(9r27_Յ5,~),_o<7*BZ87LHHD*!'suf83Ai#*G&S4]C }ʭEԵ*ڳNUdDe.N?wB nwOQJQmʸKf<5cX"畐kN=|'*;84}I\^PO__#U{.TXGKU6"y+P.M۠qv;xS>M\qlt6ʓ"}_U&K$PE/tu12_wV0qZ[e+@>6H3=#}70Y.>CvD\dNo`F6T mAPECeԍNyX: A UNz/2J9tq] 'tO(:mXUItnQEI6QXY3gQ'԰|؁ ^[UB!"zT> d"∪25ӼO%\ (Xu6XâU]6q3i7>=[#äSe֘̃c/oeoӎXuiGk~O->X!柉}㗡^8X -k /7Dj#nXBQ]˓܌|ǫJ,J5TT:0%^5 l6q՗*7,˲`i,fBDG,s}84EDxs7 ϙ0,/,S|Cyk~| e@5DArcj8H4h}?}Ǩ'9ib'6oJ辟t2S X| t\#F3 sP>#r~YWI$)6zYҒi Eg,#yӝ\`uKTG-geR]-3:"id3=ګ^OmN4,d ?D1Ae.r)C5#Ԍ'嶺 2n[֤vRE3c%;$RI :&qui+/|kO-~nX$RM!}_mxNSsi.&{*D zc˰Z߆+p "?4SU&&mXz`<,tP M>kA + *dfʁQsx'YI;" Y+o1:=7 ~S1M.Q8y=QnA8Uwq>)|gi²X0Mp3޽ǚhǡSԃU)Uk^ o᲌nYl"bO r9@|oK"Q09A#HN'W;RR^r^~$)1c$kߋ1xsb[~Yo̒QsF*PDc\h c{m8OjլQO;}q%э3ɏ7wC>m|_NEFƹrD0\}'=m_CӋHo{xhdI-䑂WRRcc"d|(#p{dƜ0\S +}m%iÜ. {=ƴ\000$E>텀߬g.6βE'k5?S~)(&'WSU`hc6lD_$T&kgf$Pu=:zdo;Xn}ZtSei C ^Jd2s}aO^qTO3l&34)gAoh:PWcQe&[5|򑔹)iq 5=Gpe^^z =Sr(n[BdJ=O8ӭOnw;j|܅qN,py$&C9OF2(P?t'pXǕ#vBDW R.?ۙ^ҺyIsp 06Gwa!Ċjsp-`&Kc>'#c`MrO܃5rTNx|-(1p>d?^#cF&}aS#Rx=La&VTLG>8N# &Efs3 1ip6(%8 0!yMUԮn)lգLk%5<ܑ < ?'#~|ŚUJulicۇ {tfH` ?齡Vܙhat P/?&wSx["-VY5˚aygR?e]O)?C\ܻBHM?A9(=TיY+Ųo..)+9-(ρQ8~'ɦY#|Uth(G m#srR(=|8ẐDL` ăr8"8c,18(jewCHw(N].㏿~h>Q|%Z4k%SQ/#0joyRM- Q*'#+"Ac>G͓x չﭞS91jqDL+%s3Urn29#H hٷo}_N%s\} 3(ӃOOo'ۨӗ"Iy4.WMF]I{Qz} pO'k56p }©\10Fznw4Č 0u6ĩ2ꉋڑm#&1yA5$ 9J:76ފt̑8fƴ}r.ObQ݂mG?T ԷDl[```ǔ8RTKzz8Λ2&^Po{=Ď=KĞ!C6 W/E*!2ri11DÓyn%֨=I[x $|/#|G^NPgXx/{f)QQvŽ\@ ׏Hk5@0<1(@D$[]Q Q\㔳R/dbH:7^z_OFOrWkP:10 %bQ޹3:PL~Pd7;jԜoU em#wJ*q|%)t- Hp ( }n麳S{j}A(-+.KE;rx';F:MԊڬ^0)yiҩU<4 oٟ뚯5JU1F&vV|˱u='md*{%:]tuǤE_F]#:Nuh1=/!uId 1)Tv[=4`ZEZqj-&:#|};:9tUM̕R|x) ȓj'|?(x6m8:j;dwVRaN ~20K j1%->6Cs](@zM3L%۾1h PoM߶Ěқqd̂n61gHMUh0JD 9@Oys[Kۚoii˪4/ma.˧7_* {?QnతcKK/#\yK ~AtuCD6\]4<9Ɛ:`c?_9av&Hφ~VJx{Rw:8 W}YtU5Z> @߹WC/_XkxL8skjեd֞1kdFN\橡FKI: ăP|F_Yw+owcsOfhT4}a+э1| Ԁo#SOqxhw\us6l}j`AxeG\:*jMV8?$?pt7DPXfM6Uv>0#0H/Ϥ;n:G ق-͚8 Td''mZڧHĨ0000qܮANӗj~arM{*}#gOf4equ]uS ?gv]U==]<8I Fv 钒~fO ,Dr}<a 2}2j̔8 ̍ԩQKuo.205(=&yF"Pn|t+V?mC?xY5+$D|['ALO&2j1c+t᪗xX#ڔa/ -s*njmKM`##.GP3^7CS]7m*Z!T&߃u.1,Bzx [P딝ߏk2s"Bm銥8oӁl>@mk 詗?$g$Z ̲:9>b Ro̓y,ΌI 5k% =o?Jycz~ < ݝ+`R50P F#99gVsGofp;FA@,2L&m Zu(U)Q2;AF7i u-Ư5wӎ=v>[ e٬H+P"/lHV8]Atw= 5Xӣ/63OT&ĄV2OeonEhuj2\Dc=8AMu#h9IZ/ASВ9?3>OHS**\d)^I\mk49&Q1m*nHҖֳ87:QIy7wإ`c16K9b*Rpِɐm?aHdl3@,N& 3c<o;0)Vc 咷9a_wNK\C̰ki9T$h3<#r *֭)͒{pIn}SQj*g_Ju}%90汑ajyA^1{ 4-/{}H8+SK᷷>G;2!8vKߏ״=O"K5vڬwj'#r.֩M~#-LV4c }f.UxIl̶pH8wԁ?7_WWQ% {ntXCn8#t-7ouiq_8}RrbAӜdcm{D)=9\%r2lO0J@jD҃I>| ?!yVT )t㹮jﴊxFCݗJ`R[(VBZm'#I(.LDXA/*Sq2Q7FM(GT G7FZT'PG6\WI7 ^n}8<7V ;mWx箓*J4IFHtOHDF1#n-: ֔E1bi8hUA֣9&ۄ{Ejz71 aZƥS PHj31 iu ?ByAi5__\!hqI [K1r(\uEIE\󍧡uPQf]Y*Kwv[Z6"qK&j.Kdi~ ۩7[V%<~8xfĪobuP````0yL}+HhSM$uIM 8pGGGu9^h7Lwa^Nh?it=F;i%B5# w0n巩=ϦlSHM@ɩƝROtiv9s"9>5ExUSsHΎH  HH;pLn])[$`moh&!>M͎b~_w/m\|;+ƤQ.*>{9:;Ams*kK|Nᒽ%&"]-C1d\Sy>soi_rKۺyĈ`^oK*FpA9FsJG9QdyYP@!cxg:x&-֗R oWtF#XR\A[(("pŧ9)mnBrL#m,ƂN$-f7SvOl88TpAij{56-.IT둟s qЕ>5J003_\[FZ&7 TT!L AݭeGr<;9%e j ^86V\>wly\r70hF-fiqغnOɺDH8S7Mtuzzcsn8[-[WIi!"4 7mM|iҝz#Y=7|FY*o@G#rIL)#Nq! I?smmN?OJ|~ҶwzsnhGbt%raNB60:]jv:<]I{3&@WA ,C,2y\Q0\G٤Noo@MVuomU^4WT9Zo#ص׀T[ t%J9,8viewtaft*\Ǩm&44ΧQB{F^2D){}\w RI\98յڹfaqIB^}Plu4#J>d}1{ޕE*.Hb]Zj/ WsdOE m[;N#8'+|a֐ʄWNIoif8QF?iԭ&*c$exh] 9i@w* 鏴6-iRLyNT Yr4ӏ H7"R4N ]vElxnQycʿ+J_JxĂ}CSjC%];AWsn:4'iۉzJ&ʚؿ> 'F!$ F"( klw`>j~&y5ͭĆkNK<2Қ8CPsyAy48XnrW~:.PN'ɵyFWG,/ ! T160zaƢzwٶ8$@P >C${8߳6d `````````8ssyDcq"T|[>L>},VWҲ`BZ|)Vq:nD6vJ4G=A*,K=tH Z|*U]<od;XnYl0"/WdԿKS=?4*Đ;yUh& f:ȑ;}okM)i`v h my jà>?yCoauth-2.0.7/examples/twitter/updateBackgroundImage.php0000644000175000001440000000331113731057347021772 0ustar mikeusersenableDebug(); /* multipart only works with the cURL engine at the moment */ $oauth->setRequestEngine(OAUTH_REQENGINE_CURL); $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"]); $oauth->setToken($access_token_info["oauth_token"],$access_token_info["oauth_token_secret"]); printf("Sending the background image...\n"); $oauth->fetch(TWITTER_UPDATE_PROFILE_BG_API, array("tile" => "true", "@image" => "@". dirname(__FILE__) ."/php.jpg;filename=php.jpg;type=image/jpg"), OAUTH_HTTP_METHOD_POST); /* from this point on OAuth is over, now handling the JSON response is in order */ $res = json_decode($oauth->getLastResponse()); printf("Twitter background image URL: %s\n", $res->profile_background_image_url); } catch(OAuthException $E) { print_r($E); } ?> oauth-2.0.7/examples/twitter/updateStatus.php0000644000175000001440000000360713731057347020243 0ustar mikeusersdisableSSLChecks(); /* 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-2.0.7/examples/google/README0000644000175000001440000000007113731057347015466 0ustar mikeusersRun getContactInfo.php through with your php-cli binary. oauth-2.0.7/examples/google/config.inc.php0000644000175000001440000000170513731057347017341 0ustar mikeusers oauth-2.0.7/examples/google/request_token.php0000644000175000001440000000153113731057347020211 0ustar mikeusersgetRequestToken("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-2.0.7/examples/google/access_token.php0000644000175000001440000000115613731057347017765 0ustar mikeuserssetToken($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-2.0.7/examples/google/getContactInfo.php0000755000175000001440000000526613731057347020244 0ustar mikeusers#!/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-2.0.7/examples/wepay/README0000644000175000001440000000262713731057347015350 0ustar mikeusersWePay 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-2.0.7/examples/wepay/config.inc.php0000644000175000001440000000071713731057347017214 0ustar mikeusersgetRequestToken("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-2.0.7/examples/wepay/access_token.php0000644000175000001440000000272513731057347017641 0ustar mikeuserssetToken($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-2.0.7/examples/wepay/balances.php0000644000175000001440000000164213731057347016745 0ustar mikeusersenableDebug(); $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-2.0.7/examples/digg/config.inc.php0000644000175000001440000000022013731057347016766 0ustar mikeusers oauth-2.0.7/examples/digg/digg_a_story.php0000644000175000001440000000221713731057347017433 0ustar mikeusersgetRequestToken("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-2.0.7/examples/provider/2legged.php0000644000175000001440000000257113731057347017215 0ustar mikeusersis2LeggedEndpoint(true); /* OAuthProvider will call this callback with the $provider object as an argument, you can throw errors from that handler and set the $provider->consumer_key if all is good */ $provider->consumerHandler('lookupConsumer'); /* similar to consumerHandler, throw errors related to the timestamp/nonce in this callback */ $provider->timestampNonceHandler('timestampNonceChecker'); /* this is the meat of request authorization, the first argument is the URL of this endpoint as the outside world sees it * the optional second argument is the HTTP method, GET, POST, etc ... the provider will try to detect this via $_SERVER["REQUEST_METHOD"] (usually reliable) when it's not set */ $provider->checkOAuthRequest("http://localhost/request_signing.php", PHP_SAPI=="cli" ? OAUTH_HTTP_METHOD_GET : NULL); } catch (OAuthException $E) { /* when you catch OAuthException and echo OAuthProvider::reportProblem with it, you'll get the problem reporting extension described here: * http://wiki.oauth.net/ProblemReporting for free, it also sets the most appropriate HTTP response code */ echo OAuthProvider::reportProblem($E); } ?> oauth-2.0.7/examples/provider/access_token.php0000644000175000001440000000065313731057347020344 0ustar mikeusersconsumerHandler('lookupConsumer'); $provider->timestampNonceHandler('timestampNonceChecker'); $provider->tokenHandler('tokenHandler'); $provider->checkOAuthRequest("http://localhost/access_token.php", PHP_SAPI=="cli" ? OAUTH_HTTP_METHOD_GET : NULL); } catch (OAuthException $E) { echo OAuthProvider::reportProblem($E); } ?> oauth-2.0.7/examples/provider/a_private_api.php0000644000175000001440000000075713731057347020513 0ustar mikeusersyour_own_member = "this is passed to every callback"; $provider->consumerHandler('lookupConsumer'); $provider->timestampNonceHandler('timestampNonceChecker'); $provider->tokenHandler('tokenHandler'); $provider->checkOAuthRequest("http://localhost/a_private_api.php", PHP_SAPI=="cli" ? OAUTH_HTTP_METHOD_GET : NULL); } catch (OAuthException $E) { echo OAuthProvider::reportProblem($E); } ?> oauth-2.0.7/examples/provider/common.inc.php0000644000175000001440000000355413731057347017746 0ustar mikeusers foo */ if(PHP_SAPI=="cli") { $params = array("oauth_token" => "a_good_token", "oauth_timestamp" => "12345", "oauth_nonce" => "raNdOM", "oauth_consumer_key" => "api_key", "oauth_signature" => "invalid", "oauth_signature_method" => OAUTH_SIG_METHOD_HMACSHA1); } else { $params = array(); } function lookupConsumer($provider) { if($provider->consumer_key=="unknown") { return OAUTH_CONSUMER_KEY_UNKNOWN; } else if($provider->consumer_key=="blacklisted" || $provider->consumer_key=="throttled") { return OAUTH_CONSUMER_KEY_REFUSED; } $provider->consumer_secret = "the_consumers_secret"; /* we must have the caller send us a callback for 1.0a ... addRequiredParameter takes any parameter name and reports it as part of * OAuthProvider::reportProblem() */ $provider->addRequiredParameter("oauth_callback"); /* changed our mind heh */ $provider->removeRequiredParameter("oauth_callback"); return OAUTH_OK; } function timestampNonceChecker($provider) { if($provider->nonce=="bad") { return OAUTH_BAD_NONCE; } else if($provider->timestamp=="0") { return OAUTH_BAD_TIMESTAMP; } return OAUTH_OK; } function tokenHandler($provider) { if($provider->token=="rejected") { return OAUTH_TOKEN_REJECTED; } else if($provider->token=="revoked") { return OAUTH_TOKEN_REVOKED; } $provider->token_secret = "the_tokens_secret"; return OAUTH_OK; } /* Problem Reporting constants supported (can be returned from any callback) * OAUTH_BAD_TIMESTAMP * OAUTH_BAD_NONCE * OAUTH_CONSUMER_KEY_UNKNOWN * OAUTH_CONSUMER_KEY_REFUSED * OAUTH_TOKEN_USED * OAUTH_TOKEN_EXPIRED * OAUTH_TOKEN_REVOKED * OAUTH_TOKEN_REJECTED * OAUTH_VERIFIER_INVALID * OAUTH_INVALID_SIGNATURE * OAUTH_PARAMETER_ABSENT * check out http://wiki.oauth.net/ProblemReporting for more info */ ?> oauth-2.0.7/examples/provider/request_token.php0000644000175000001440000000256213731057347020574 0ustar mikeusersisRequestTokenEndpoint(true); /* OAuthProvider will call this callback with the $provider object as an argument, you can throw errors from that handler and set the $provider->consumer_key if all is good */ $provider->consumerHandler('lookupConsumer'); /* similar to consumerHandler, throw errors related to the timestamp/nonce in this callback */ $provider->timestampNonceHandler('timestampNonceChecker'); /* this is the meat of request authorization, the first argument is the URL of this endpoint as the outside world sees it * the optional second argument is the HTTP method, GET, POST, etc ... the provider will try to detect this via $_SERVER["REQUEST_METHOD"] (usually reliable) when it's not set */ $provider->checkOAuthRequest("http://localhost/request_token.php", PHP_SAPI=="cli" ? OAUTH_HTTP_METHOD_GET : NULL); } catch (OAuthException $E) { /* when you catch OAuthException and echo OAuthProvider::reportProblem with it, you'll get the problem reporting extension described here: * http://wiki.oauth.net/ProblemReporting for free, it also sets the most appropriate HTTP response code */ echo OAuthProvider::reportProblem($E); } ?> oauth-2.0.7/tests/bug16946.phpt0000644000175000001440000000341113731057347014743 0ustar mikeusers--TEST-- OAuth getRequestToken --SKIPIF-- --FILE-- setRequestEngine(OAUTH_REQENGINE_CURL); $pid = http_server("tcp://127.0.0.1:12342", array( "HTTP/1.0 302 Found\r\nLocation: http://127.0.0.1:12342/some_url_that_goes_nowhere_and_could_be_very_long.html?bla=bla&mekker=mekker\r\n\r\n", "HTTP/1.0 302 Found\r\nLocation: http://127.0.0.1:12342/some_other_url.html\r\n\r\n", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", ), $output); try { $x->setAuthType(OAUTH_AUTH_TYPE_AUTHORIZATION); var_dump($x->getRequestToken('http://127.0.0.1:12342/test', null, 'GET')); } catch (Exception $e) { var_dump($x->debugInfo); } fseek($output, 0, SEEK_SET); var_dump(stream_get_contents($output)); http_server_kill($pid); ?> --EXPECTF-- array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } string(%d) "GET /test HTTP/%f %a Accept: */* Authorization: OAuth oauth_consumer_key="1234",oauth_signature_method="HMAC-SHA1",oauth_nonce="%s.%d",oauth_timestamp="%d",oauth_version="1.0",oauth_signature="%s" GET /some_url_that_goes_nowhere_and_could_be_very_long.html?bla=bla&mekker=mekker HTTP/%f %a Accept: */* Authorization: OAuth oauth_consumer_key="1234",oauth_signature_method="HMAC-SHA1",oauth_nonce="%s.%d",oauth_timestamp="%d",oauth_version="1.0",oauth_signature="%s" GET /some_other_url.html HTTP/%f %a Accept: */* Authorization: OAuth oauth_consumer_key="1234",oauth_signature_method="HMAC-SHA1",oauth_nonce="%s.%d",oauth_timestamp="%d",oauth_version="1.0",oauth_signature="%s" " oauth-2.0.7/tests/bug21426.phpt0000644000175000001440000000045013731057347014730 0ustar mikeusers--TEST-- Child class of OAuth cannot access its own attributes --FILE-- foo; } } $foo = new Foo('key', 'secret'); var_dump($foo->getFoo()); ?> --EXPECTF-- string(3) "bar" oauth-2.0.7/tests/bug_64308.phpt0000644000175000001440000000053413731057347015100 0ustar mikeusers--TEST-- PECL oauth: Bug #64308 (Protocol and host name not lowercased when generating signature base string) --SKIPIF-- --FILE-- --EXPECT-- GET&http%3A%2F%2Fsimonwpt.trovebox.com%2Fhello.json& oauth-2.0.7/tests/oauth.inc0000644000175000001440000000042213731057347014471 0ustar mikeusers "a_good_token", "oauth_timestamp" => "12345", "oauth_nonce" => "raNdOM", "oauth_consumer_key" => "api_key", "oauth_signature" => "invalid", "oauth_signature_method" => OAUTH_SIG_METHOD_HMACSHA1 ]; } oauth-2.0.7/tests/oauthprovider_001.phpt0000644000175000001440000000067013731057347017033 0ustar mikeusers--TEST-- OauthProvider Creation --FILE-- 'bar']); var_dump($provider); --EXPECT-- object(OAuthProvider)#1 (10) { ["consumer_key"]=> NULL ["consumer_secret"]=> NULL ["nonce"]=> NULL ["token"]=> NULL ["token_secret"]=> NULL ["timestamp"]=> NULL ["version"]=> NULL ["signature_method"]=> NULL ["callback"]=> NULL ["request_token_endpoint"]=> bool(false) } oauth-2.0.7/tests/oauthprovider_002.phpt0000644000175000001440000000050213731057347017026 0ustar mikeusers--TEST-- OauthProvider isRequestTokenEndpoint --FILE-- isRequestTokenEndpoint(true); var_dump($provider->request_token_endpoint); } catch (OAuthException $E) { echo OAuthProvider::reportProblem($E); } --EXPECT-- bool(true) oauth-2.0.7/tests/oauthprovider_003.phpt0000644000175000001440000000065113731057347017034 0ustar mikeusers--TEST-- OauthProvider consumerHandler/callConsumerHandler --FILE-- consumerHandler('consumerHandler'); $provider->callConsumerHandler(); } catch (OAuthException $E) { echo OAuthProvider::reportProblem($E); } --EXPECT-- consumerHandler called oauth-2.0.7/tests/oauthprovider_004.phpt0000644000175000001440000000062113731057347017032 0ustar mikeusers--TEST-- OauthProvider tokenHandler/callTokenHandler --FILE-- tokenHandler('tokenHandler'); $provider->callTokenHandler(); } catch (OAuthException $E) { echo OAuthProvider::reportProblem($E); } --EXPECT-- tokenHandler called oauth-2.0.7/tests/oauthprovider_005.phpt0000644000175000001440000000073113731057347017035 0ustar mikeusers--TEST-- OauthProvider timestampNonceHandler/callTimestampNonceHandler --FILE-- timestampNonceHandler('timestampNonceHandler'); $provider->callTimestampNonceHandler(); } catch (OAuthException $E) { echo OAuthProvider::reportProblem($E); } --EXPECT-- timestampNonceHandler called oauth-2.0.7/tests/oauthprovider_006.phpt0000644000175000001440000000140713731057347017037 0ustar mikeusers--TEST-- OauthProvider checkOauthRequest --FILE-- consumerHandler(function() { return OAUTH_OK; }); $provider->timestampNonceHandler(function() { return OAUTH_OK; }); $provider->tokenHandler(function() { return OAUTH_OK; }); $provider->checkOAuthRequest("http://localhost/request_token.php", OAUTH_HTTP_METHOD_GET); } catch (OAuthException $E) { echo OAuthProvider::reportProblem($E); } --EXPECT-- oauth_problem=signature_invalid&debug_sbs=GET&http%3A%2F%2Flocalhost%2Frequest_token.php&oauth_consumer_key%3Dapi_key%26oauth_nonce%3DraNdOM%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D12345%26oauth_token%3Da_good_token oauth-2.0.7/tests/oauthprovider_007.phpt0000644000175000001440000000164013731057347017037 0ustar mikeusers--TEST-- OauthProvider checkOauthRequest --FILE-- consumerHandler(function() { return OAUTH_OK; }); $provider->timestampNonceHandler(function() { return OAUTH_OK; }); $provider->tokenHandler(function() { return OAUTH_OK; }); $provider->setParam('should_remove_this_param', NULL); $provider->checkOAuthRequest("http://localhost/request_token.php", OAUTH_HTTP_METHOD_GET); } catch (OAuthException $E) { echo OAuthProvider::reportProblem($E); } --EXPECT-- oauth_problem=signature_invalid&debug_sbs=GET&http%3A%2F%2Flocalhost%2Frequest_token.php&oauth_consumer_key%3Dapi_key%26oauth_nonce%3DraNdOM%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D12345%26oauth_token%3Da_good_token oauth-2.0.7/tests/oauthprovider_008.phpt0000644000175000001440000000031113731057347017032 0ustar mikeusers--TEST-- OauthProvider setParam addref segfault --FILE-- 1]); $provider->setParam('long_var', 2); echo 'here'; --EXPECT-- here oauth-2.0.7/tests/oauth_curl_debug_handler.phpt0000644000175000001440000000154513731057347020572 0ustar mikeusers--TEST-- Oauth curl debug handler --SKIPIF-- --FILE-- setRequestEngine(OAUTH_REQENGINE_STREAMS); $x->setTimestamp(12345); $x->setNonce('testing'); $x->enableDebug(); $x->setRequestEngine(OAUTH_REQENGINE_CURL); $pid = http_server("tcp://127.0.0.1:12342", array( "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", ), $output); $x->setAuthType(OAUTH_AUTH_TYPE_URI); $x->getRequestToken('http://127.0.0.1:12342/test'); fseek($output, 0, SEEK_SET); stream_get_contents($output); var_dump(count($x->debugInfo)); http_server_kill($pid); ?> --EXPECTF-- int(5) oauth-2.0.7/tests/oauth_reqtoken.phpt0000644000175000001440000000475613731057347016621 0ustar mikeusers--TEST-- OAuth getRequestToken --SKIPIF-- --FILE-- setRequestEngine(OAUTH_REQENGINE_STREAMS); $pid = http_server("tcp://127.0.0.1:12342", array( "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", ), $output); $x->setAuthType(OAUTH_AUTH_TYPE_AUTHORIZATION); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); $x->setAuthType(OAUTH_AUTH_TYPE_FORM); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); $x->setAuthType(OAUTH_AUTH_TYPE_URI); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); var_dump($x->getRequestToken('http://127.0.0.1:12342/test', null, 'POST')); fseek($output, 0, SEEK_SET); var_dump(stream_get_contents($output)); http_server_kill($pid); ?> --EXPECTF-- array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } string(%d) "POST /test HTTP/%f Host: 127.0.0.1:12342 Connection: close Authorization: OAuth oauth_consumer_key="1234",oauth_signature_method="HMAC-SHA1",oauth_nonce="%s.%d",oauth_timestamp="%d",oauth_version="1.0",oauth_signature="%s" POST /test HTTP/%f Host: 127.0.0.1:12342 Connection: close Content-Length: %d Content-Type: application/x-www-form-urlencoded oauth_consumer_key=1234&oauth_signature_method=HMAC-SHA1&oauth_nonce=%s.%d&oauth_timestamp=%d&oauth_version=1.0&oauth_signature=%s POST /test?oauth_consumer_key=1234&oauth_signature_method=HMAC-SHA1&oauth_nonce=%s.%d&oauth_timestamp=%d&oauth_version=1.0&oauth_signature=%s HTTP/%f Host: 127.0.0.1:12342 Connection: close POST /test?oauth_consumer_key=1234&oauth_signature_method=HMAC-SHA1&oauth_nonce=%s.%d&oauth_timestamp=%d&oauth_version=1.0&oauth_signature=%s HTTP/%f Host: 127.0.0.1:12342 Connection: close " oauth-2.0.7/tests/oauth_sbs.phpt0000644000175000001440000000416413731057347015551 0ustar mikeusers--TEST-- OAuth SBS function --FILE-- getMessage()."\n"; } echo "-- using numeric keys masked as a string --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/',array('1'=>'hello')),"\n"; echo "-- using string keys --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/',array('test'=>'hello')),"\n"; echo "-- using same var in url and params --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/?test=hi',array('test'=>'hello')),"\n"; echo "-- using null inside params --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/',array('test'=>null)),"\n"; echo "-- putting oauth_signature inside by mistake --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/',array('oauth_signature'=>'hello world')),"\n"; echo "-- merging url query and extra params --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/script?arg1=1',array('arg2' => '2')),"\n"; echo "-- with array value --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/script',array('arg2' => [1, 2, 3])),"\n"; ?> --EXPECTF-- -- only two parameters -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F& -- using empty array -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F& -- using string instead of array -- %Astring given%A -- using numeric keys masked as a string -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F&1%3Dhello -- using string keys -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F&test%3Dhello -- using same var in url and params -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F&test%3Dhi -- using null inside params -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F&test%3D -- putting oauth_signature inside by mistake -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F& -- merging url query and extra params -- GET&http%3A%2F%2F127.0.0.1%3A12342%2Fscript&arg1%3D1%26arg2%3D2 -- with array value -- GET&http%3A%2F%2F127.0.0.1%3A12342%2Fscript&arg2%3D1%26arg2%3D2%26arg2%3D3 oauth-2.0.7/tests/oauth_standard.phpt0000644000175000001440000000617413731057347016565 0ustar mikeusers--TEST-- OAuth Standard functions --FILE-- debug, $v->sslChecks, $v->debugInfo); return; } echo "NOT_OAUTH\n"; } echo "-- empty params --\n"; try { $x = new OAuth; } catch (Exception $e) { echo "EXCEPTION {$e->getCode()}: {$e->getMessage()}\n"; } echo "-- one param --\n"; try { $x = new OAuth(''); } catch (Exception $e) { echo "EXCEPTION {$e->getCode()}: {$e->getMessage()}\n"; } echo "-- empty consumer key and secret --\n"; try { $x = new OAuth('', ''); } catch (Exception $e) { echo "EXCEPTION {$e->getCode()}: {$e->getMessage()}\n"; } echo "-- empty consumer secret --\n"; try { $x = new OAuth('1234', ''); } catch (Exception $e) { echo "EXCEPTION {$e->getCode()}: {$e->getMessage()}\n"; } echo "-- normal constructor --\n"; $x = new OAuth('1234', '5678'); oauth_dump($x); echo "-- enable debug --\n"; $x->enableDebug(); oauth_dump($x); echo "-- disable debug --\n"; $x->disableDebug(); oauth_dump($x); try { echo "-- set version without parameters --\n"; var_dump($x->setVersion()); } catch (Exception $e) { echo "EXCEPTION {$e->getCode()}: {$e->getMessage()}\n"; } catch (ArgumentCountError $e) { echo "EXCEPTION {$e->getCode()}: {$e->getMessage()}\n"; } try { echo "-- set version with boolean --\n"; var_dump($x->setVersion(true)); } catch (Exception $e) { echo "EXCEPTION {$e->getCode()}: {$e->getMessage()}\n"; } try { echo "-- set version with empty string --\n"; var_dump($x->setVersion('')); } catch (Exception $e) { echo "EXCEPTION {$e->getCode()}: {$e->getMessage()}\n"; } echo "-- set version to 1 --\n"; var_dump($x->setVersion('1')); try { echo "-- set auth type to invalid type 99 --\n"; var_dump($x->setAuthType(99)); } catch (Exception $e) { echo "EXCEPTION {$e->getCode()}: {$e->getMessage()}\n"; } echo "-- generate a signature --\n"; var_dump(is_string($x->generateSignature('GET', 'http://www.friendface.com/foo', array('param' => 'value')))); echo "-- set a timeout (100 ms) --\n"; var_dump($x->setTimeout(100)); echo "-- set an invalid timeout --\n"; try { $x->setTimeout(-1); } catch (Exception $E) { echo "EXCEPTION {$E->getCode()}: {$E->getMessage()}\n"; } ?> --EXPECTF-- -- empty params -- EXCEPTION -1: The consumer key cannot be empty -- one param -- EXCEPTION -1: The consumer key cannot be empty -- empty consumer key and secret -- EXCEPTION -1: The consumer key cannot be empty -- empty consumer secret -- EXCEPTION -1: The consumer secret cannot be empty -- normal constructor -- OAuth[debug=0,sslChecks=3,debugInfo=] -- enable debug -- OAuth[debug=1,sslChecks=3,debugInfo=] -- disable debug -- OAuth[debug=0,sslChecks=3,debugInfo=] -- set version without parameters -- %A expects exactly 1 %A -- set version with boolean -- bool(true) -- set version with empty string -- EXCEPTION 503: Invalid version -- set version to 1 -- bool(true) -- set auth type to invalid type 99 -- EXCEPTION 503: Invalid auth type -- generate a signature -- bool(true) -- set a timeout (100 ms) -- bool(true) -- set an invalid timeout -- EXCEPTION 503: Invalid timeout oauth-2.0.7/tests/oauth_urlencode.phpt0000644000175000001440000000035313731057347016736 0ustar mikeusers--TEST-- OAuth urlencode --FILE-- --EXPECTF-- http%3A%2F%2Fwww.example.com http%3A%2F%2Fwww.example.com%2F~user oauth-2.0.7/tests/overflow_redir.phpt0000644000175000001440000000353013731057347016606 0ustar mikeusers--TEST-- OAuth Overflow in header redirect --SKIPIF-- --FILE-- setRequestEngine(OAUTH_REQENGINE_CURL); $pid = http_server("tcp://127.0.0.1:12342", array( "HTTP/1.0 302 Found\r\nLocation: http://127.0.0.1:12342/" . str_repeat('a', 512) . "bbb\r\n\r\n", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", ), $output); try { $x->setAuthType(OAUTH_AUTH_TYPE_AUTHORIZATION); var_dump($x->getRequestToken('http://127.0.0.1:12342/test', null, 'GET')); } catch (Exception $e) { var_dump($x->debugInfo); } fseek($output, 0, SEEK_SET); var_dump(stream_get_contents($output)); http_server_kill($pid); ?> --EXPECTF-- array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } string(%d) "GET /test HTTP/%f %a Accept: */* Authorization: OAuth oauth_consumer_key="1234",oauth_signature_method="HMAC-SHA1",oauth_nonce="%s.%d",oauth_timestamp="%d",oauth_version="1.0",oauth_signature="%s" GET /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa HTTP/%f %a Accept: */* Authorization: OAuth oauth_consumer_key="1234",oauth_signature_method="HMAC-SHA1",oauth_nonce="%s.%d",oauth_timestamp="%d",oauth_version="1.0",oauth_signature="%s" " oauth-2.0.7/tests/plaintext.phpt0000644000175000001440000000203713731057347015567 0ustar mikeusers--TEST-- OAuth plaintext --SKIPIF-- --FILE-- setRequestEngine(OAUTH_REQENGINE_STREAMS); $x->setTimestamp(12345); $x->setNonce('testing'); $pid = http_server("tcp://127.0.0.1:12342", array( "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", ), $output); $x->setAuthType(OAUTH_AUTH_TYPE_URI); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); fseek($output, 0, SEEK_SET); var_dump(stream_get_contents($output)); http_server_kill($pid); ?> --EXPECTF-- array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } string(%d) "POST /test?oauth_consumer_key=conskey&oauth_signature_method=PLAINTEXT&oauth_nonce=testing&oauth_timestamp=12345&oauth_version=1.0&oauth_signature=conssecret%26 HTTP/1.%d Host: 127.0.0.1:12342 Connection: close " oauth-2.0.7/tests/plaintext2.phpt0000644000175000001440000000315513731057347015653 0ustar mikeusers--TEST-- OAuth plaintext access token --SKIPIF-- --FILE-- setRequestEngine(OAUTH_REQENGINE_STREAMS); $x->setTimestamp(12345); $x->setNonce('testing'); $pid = http_server("tcp://127.0.0.1:12342", array( "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=4567&oauth_token_secret=8901", ), $output); $x->setAuthType(OAUTH_AUTH_TYPE_URI); $x->setToken("key", "secret"); var_dump($x->getAccessToken('http://127.0.0.1:12342/test')); var_dump($x->getAccessToken('http://127.0.0.1:12342/test', '', '', 'GET')); fseek($output, 0, SEEK_SET); var_dump(stream_get_contents($output)); http_server_kill($pid); ?> --EXPECTF-- array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } array(2) { ["oauth_token"]=> string(4) "4567" ["oauth_token_secret"]=> string(4) "8901" } string(%d) "POST /test?oauth_consumer_key=conskey&oauth_signature_method=PLAINTEXT&oauth_nonce=testing&oauth_timestamp=12345&oauth_version=1.0&oauth_token=key&oauth_signature=conssecret%26secret HTTP/1.%d Host: 127.0.0.1:12342 Connection: close GET /test?oauth_consumer_key=conskey&oauth_signature_method=PLAINTEXT&oauth_nonce=testing&oauth_timestamp=12345&oauth_version=1.0&oauth_token=key&oauth_signature=conssecret%26secret HTTP/1.%d Host: 127.0.0.1:12342 Connection: close " oauth-2.0.7/tests/reqtoken_bug44603.phpt0000644000175000001440000000403713731057347016647 0ustar mikeusers--TEST-- OAuth getRequestToken --SKIPIF-- --FILE-- setRequestEngine(OAUTH_REQENGINE_STREAMS); $pid = http_server("tcp://127.0.0.1:12342", array( "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", ), $output); $x->setAuthType(OAUTH_AUTH_TYPE_AUTHORIZATION); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); $x->setAuthType(OAUTH_AUTH_TYPE_FORM); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); $x->setAuthType(OAUTH_AUTH_TYPE_URI); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); fseek($output, 0, SEEK_SET); var_dump(stream_get_contents($output)); http_server_kill($pid); ?> --EXPECTF-- array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } string(%d) "POST /test HTTP/%f Host: 127.0.0.1:12342 Connection: close Authorization: OAuth oauth_consumer_key="1234",oauth_signature_method="HMAC-SHA1",oauth_nonce="%s.%d",oauth_timestamp="%d",oauth_version="1.0",oauth_signature="%s" POST /test HTTP/%f Host: 127.0.0.1:12342 Connection: close Content-Length: %d Content-Type: application/x-www-form-urlencoded oauth_consumer_key=1234&oauth_signature_method=HMAC-SHA1&oauth_nonce=%s.%d&oauth_timestamp=%d&oauth_version=1.0&oauth_signature=%s POST /test?oauth_consumer_key=1234&oauth_signature_method=HMAC-SHA1&oauth_nonce=%s.%d&oauth_timestamp=%d&oauth_version=1.0&oauth_signature=%s HTTP/%f Host: 127.0.0.1:12342 Connection: close " oauth-2.0.7/tests/reqtoken_php.phpt0000644000175000001440000000426213731057347016260 0ustar mikeusers--TEST-- OAuth getRequestToken --SKIPIF-- --FILE-- setRequestEngine(OAUTH_REQENGINE_STREAMS); $x->setTimestamp(12345); $x->setNonce('testing'); $pid = http_server("tcp://127.0.0.1:12342", array( "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", ), $output); $x->setAuthType(OAUTH_AUTH_TYPE_AUTHORIZATION); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); $x->setAuthType(OAUTH_AUTH_TYPE_FORM); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); $x->setAuthType(OAUTH_AUTH_TYPE_URI); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); fseek($output, 0, SEEK_SET); var_dump(stream_get_contents($output)); http_server_kill($pid); ?> --EXPECTF-- array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } string(%d) "POST /test HTTP/%f Host: 127.0.0.1:12342 Connection: close Authorization: OAuth oauth_consumer_key="1234",oauth_signature_method="HMAC-SHA1",oauth_nonce="testing",oauth_timestamp="12345",oauth_version="1.0",oauth_signature="%s" POST /test HTTP/%f Host: 127.0.0.1:12342 Connection: close Content-Length: %d Content-Type: application/x-www-form-urlencoded oauth_consumer_key=1234&oauth_signature_method=HMAC-SHA1&oauth_nonce=testing&oauth_timestamp=12345&oauth_version=1.0&oauth_signature=pwOAI3vHnKHd%2FLUYcJOr36Ed5Vg%3D POST /test?oauth_consumer_key=1234&oauth_signature_method=HMAC-SHA1&oauth_nonce=testing&oauth_timestamp=12345&oauth_version=1.0&oauth_signature=pwOAI3vHnKHd%2FLUYcJOr36Ed5Vg%3D HTTP/%f Host: 127.0.0.1:12342 Connection: close " oauth-2.0.7/tests/rsa.phpt0000644000175000001440000000234413731057347014345 0ustar mikeusers--TEST-- OAuth getRequestToken --SKIPIF-- --FILE-- setRequestEngine(OAUTH_REQENGINE_STREAMS); $x->setTimestamp(12345); $x->setNonce('testing'); $x->setRSACertificate(file_get_contents(dirname(__FILE__).'/test.pem')); $pid = http_server("tcp://127.0.0.1:12342", array( "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 40\r\n\r\noauth_token=1234&oauth_token_secret=4567", ), $output); $x->setAuthType(OAUTH_AUTH_TYPE_URI); var_dump($x->getRequestToken('http://127.0.0.1:12342/test')); fseek($output, 0, SEEK_SET); var_dump(stream_get_contents($output)); http_server_kill($pid); ?> --EXPECTF-- array(2) { ["oauth_token"]=> string(4) "1234" ["oauth_token_secret"]=> string(4) "4567" } string(%d) "POST /test?oauth_consumer_key=1234&oauth_signature_method=RSA-SHA1&oauth_nonce=testing&oauth_timestamp=12345&oauth_version=1.0&oauth_signature=AxTdf9nwR0Z54JCKIKAne%2BXKmNtuKerXchcK8axD792sk7cphqMBvNqbPVoJmKYcm0vAkq2ICto0NVz4%2F6WxqA%3D%3D HTTP/1.%d Host: 127.0.0.1:12342 Connection: close " oauth-2.0.7/tests/sbs.phpt0000644000175000001440000000362513731057347014352 0ustar mikeusers--TEST-- OAuth SBS function --FILE-- getMessage()."\n"; } echo "-- using numeric keys masked as a string --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/',array('1'=>'hello')),"\n"; echo "-- using string keys --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/',array('test'=>'hello')),"\n"; echo "-- using same var in url and params --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/?test=hi',array('test'=>'hello')),"\n"; echo "-- using null inside params --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/',array('test'=>null)),"\n"; echo "-- putting oauth_signature inside by mistake --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/',array('oauth_signature'=>'hello world')),"\n"; echo "-- merging url query and extra params --\n"; echo oauth_get_sbs('GET', 'http://127.0.0.1:12342/script?arg1=1',array('arg2' => '2')),"\n"; ?> --EXPECTF-- -- only two parameters -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F& -- using empty array -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F& -- using string instead of array -- %Astring given%A -- using numeric keys masked as a string -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F&1%3Dhello -- using string keys -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F&test%3Dhello -- using same var in url and params -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F&test%3Dhi -- using null inside params -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F&test%3D -- putting oauth_signature inside by mistake -- GET&http%3A%2F%2F127.0.0.1%3A12342%2F& -- merging url query and extra params -- GET&http%3A%2F%2F127.0.0.1%3A12342%2Fscript&arg1%3D1%26arg2%3D2 oauth-2.0.7/tests/server.inc0000644000175000001440000000333713731057347014667 0ustar mikeusers 0) { $line = fread($sock, $content_length); fwrite($output, "$line\r\n"); } // send response fputs($sock, $file); fclose($sock); } exit(0); } function http_server_kill($pid) { posix_kill($pid, SIGTERM); pcntl_waitpid($pid, $status); } ?> oauth-2.0.7/tests/skip.inc0000644000175000001440000000234013731057347014320 0ustar mikeusers= 5.1.0 && < 5.2.6 return (PHP_MAJOR_VERSION==5) && (PHP_MINOR_VERSION==1 || (PHP_MINOR_VERSION==2 && PHP_RELEASE_VERSION<6)); } return false; } function skip_without_bug($bugid) { if (!has_bug($bugid)) { die('skip Only for bug #'.$bugid); } } function skip_with_bug($bugid) { if (has_bug($bugid)) { die('skip Not for bug #'.$bugid); } } ?>oauth-2.0.7/tests/test.pem0000644000175000001440000000075513731057347014351 0ustar mikeusers-----BEGIN RSA PRIVATE KEY----- MIIBOQIBAAJBALkBSThnaneNdYKgt+r+r0Ttbm6tXpiby5ywK0SIT9Q9zuml/qIO GX9f43DgoCpK6Ju1+GjhZ5jmRD0ITUMgSx0CAwEAAQJAPoKwut42my6xBfJIMp7b me6f4cWysN3zbn4YII/uaUflGTvYwwZYMAjZjqXYNcepZQhL8g6Fclsn9IAXbqRG AQIhAPQMXKJuHjlGYHs/EhiEHuIPLaQ09f9X9TShLjeu1p3jAiEAwhCyle1J08F+ jmWbB1RqjivF6bmIXGfHUsHc5+fxwv8CIGdVGJ/56jgsEUv974aL4puq+5NMjWA5 eOx41p3jHKIrAiAKrxCl4GJoHgbxn/Zg+OzE1vQWYfh33d7DV5jpy4Mr0QIgIR95 BrFdH6fnl11HEZt2hSdvM8G1C/t0i6u5ApW/8Ko= -----END RSA PRIVATE KEY----- oauth-2.0.7/tests/urlencode.phpt0000644000175000001440000000035313731057347015536 0ustar mikeusers--TEST-- OAuth urlencode --FILE-- --EXPECTF-- http%3A%2F%2Fwww.example.com http%3A%2F%2Fwww.example.com%2F~user oauth-2.0.7/config.m40000644000175000001440000000233113731057347013224 0ustar mikeusersPHP_ARG_ENABLE(oauth, for oauth support, [ --enable-oauth Include oauth support]) AC_ARG_WITH([curl], AS_HELP_STRING([--without-curl], [Ignore presence of cURL and disable it])) 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_CHECK_HEADER(pcre.h, , [AC_MSG_ERROR([Couldn't find pcre.h, try installing the libpcre development/headers package])]) AS_IF([test "x$with_curl" != "xno"], [ AC_MSG_CHECKING(for cURL in default path) have_curl=no for i in /usr/local /usr; do if test -r $i/include/curl/easy.h -o -r $i/include/x86_64-linux-gnu/curl/easy.h; then have_curl=yes CURL_DIR=$i AC_MSG_RESULT(found in $i) break fi done ], [have_curl=no]) AS_IF([test "x$have_curl" = "xyes"], [ PHP_ADD_LIBRARY(curl,,OAUTH_SHARED_LIBADD) AC_DEFINE(OAUTH_USE_CURL, 1, [Whether cURL is present and should be used]) ], [AS_IF([test "x$with_curl" = "xyes"], [AC_MSG_ERROR([cURL requested but not found]) ]) ]) PHP_ADD_EXTENSION_DEP(oauth, hash) fi oauth-2.0.7/config.w320000644000175000001440000000216713731057347013326 0ustar mikeusers// 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("libssl.lib;ssleay32.lib", "oauth", PHP_OAUTH) && CHECK_LIB("libcrypto.lib;libeay32.lib", "oauth", PHP_OAUTH) && CHECK_LIB("winmm.lib", "oauth", PHP_OAUTH) && CHECK_LIB("wldap32.lib", "oauth", PHP_OAUTH) && CHECK_LIB("libssh2.lib;libssh2_a.lib", "oauth", PHP_OAUTH) && CHECK_LIB("nghttp2.lib;nghttp2_a.lib", "oauth", PHP_OAUTH) && CHECK_LIB("normaliz.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-2.0.7/oauth.c0000644000175000001440000024376013731057347013016 0ustar mikeusers/* +----------------------------------------------------------------------+ | See LICENSE file for further copyright information | +----------------------------------------------------------------------+ | Authors: John Jawed | | Felipe Pena | | Rasmus Lerdorf | | Tjerk Meesters | +----------------------------------------------------------------------+ */ #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* php_so_object_new(zend_class_entry *ce) /* {{{ */ { php_so_object *nos; nos = ecalloc(1, sizeof(php_so_object) + zend_object_properties_size(ce)); nos->signature = NULL; nos->timeout = 0; zend_object_std_init(&nos->zo, ce); object_properties_init(&nos->zo, ce); nos->zo.handlers = &so_object_handlers; return &nos->zo; } /* }}} */ #if PHP_VERSION_ID < 80000 static zend_object *oauth_clone_obj(zval *this_ptr) /* {{{ */ { php_so_object *old_obj = Z_SOO_P(this_ptr); #else static zend_object *oauth_clone_obj(zend_object *this_ptr) /* {{{ */ { php_so_object *old_obj = so_object_from_obj(this_ptr); #endif php_so_object *new_obj = so_object_from_obj(php_so_object_new(old_obj->zo.ce)); zend_objects_clone_members(&new_obj->zo, &old_obj->zo); return &new_obj->zo; } /* }}} */ static int oauth_parse_str(char *params, zval *dest_array) /* {{{ */ { 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); } add_assoc_string(dest_array, var, val); efree(val); var = php_strtok_r(NULL, separator, &strtok_buf); } efree(separator); return SUCCESS; } /* }}} */ static int so_set_response_args(HashTable *hasht, zval *data, zval *retarray) /* {{{ */ { if (data && Z_TYPE_P(data) == IS_STRING) { 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); } return (zend_hash_str_update(hasht, OAUTH_RAW_LAST_RES, sizeof(OAUTH_RAW_LAST_RES) -1, data) == NULL) ? FAILURE : SUCCESS; } return FAILURE; } /* }}} */ static zval *so_set_response_info(HashTable *hasht, zval *info) /* {{{ */ { return zend_hash_str_update(hasht, OAUTH_ATTR_LAST_RES_INFO, sizeof(OAUTH_ATTR_LAST_RES_INFO) - 1, info); } /* }}} */ static void oauth_prop_hash_dtor(php_so_object *soo) /* {{{ */ { HashTable *ht; ht = soo->properties; FREE_ARGS_HASH(ht); } /* }}} */ static void so_object_free_storage(zend_object *obj) /* {{{ */ { php_so_object *soo; soo = so_object_from_obj(obj); zend_object_std_dtor(&soo->zo); if (soo->lastresponse.c) { smart_string_free(&soo->lastresponse); } if (soo->headers_in.c) { smart_string_free(&soo->headers_in); } if (soo->headers_out.c) { smart_string_free(&soo->headers_out); } if (soo->signature) { zend_string_release(soo->signature); } oauth_prop_hash_dtor(soo); 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_string_free(&soo->headers_in); if (soo->headers_out.c) { smart_string_free(&soo->headers_out); } if(Z_TYPE(soo->debugArr) != IS_UNDEF) { zval_ptr_dtor(&soo->debugArr); } OAUTH_SIGCTX_FREE(soo->sig_ctx); if (soo->nonce) { efree(soo->nonce); } if (soo->timestamp) { efree(soo->timestamp); } } /* }}} */ void soo_handle_error(php_so_object *soo, long errorCode, char *msg, char *response, char *additional_info) /* {{{ */ { zval ex; zend_class_entry *dex = zend_exception_get_default(), *soox = soo_exception_ce; object_init_ex(&ex, soox); if (!errorCode) { php_error(E_WARNING, "caller did not pass an errorcode!"); } else { zend_update_property_long(dex, OBJ_FOR_PROP(&ex), "code", sizeof("code")-1, errorCode); } if (response) { zend_update_property_string(dex, OBJ_FOR_PROP(&ex), "lastResponse", sizeof("lastResponse")-1, response); } if(soo && soo->debug && Z_TYPE(soo->debugArr) != IS_UNDEF) { zend_update_property(dex, OBJ_FOR_PROP(&ex), "debugInfo", sizeof("debugInfo") - 1, &soo->debugArr); } if(additional_info) { zend_update_property_string(dex, OBJ_FOR_PROP(&ex), "additionalInfo", sizeof("additionalInfo")-1, additional_info); } zend_update_property_string(dex, OBJ_FOR_PROP(&ex), "message", sizeof("message")-1, msg); zend_throw_exception_object(&ex); } /* }}} */ zend_string *soo_sign_hmac(php_so_object *soo, char *message, const char *cs, const char *ts, const oauth_sig_context *ctx) /* {{{ */ { zval args[4], retval, func; char *tret; zend_string *result; ZVAL_STRING(&func, "hash_hmac"); if (!zend_is_callable(&func, 0, NULL)) { zval_ptr_dtor(&func); soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "HMAC signature generation failed, is ext/hash installed?", NULL, NULL); return NULL; } /* cs and ts would at best be empty, so this should be safe ;-) */ spprintf(&tret, 0, "%s&%s", cs, ts); ZVAL_STRING(&args[0], ctx->hash_algo); ZVAL_STRING(&args[1], message); ZVAL_STRING(&args[2], tret); ZVAL_BOOL(&args[3], 1); call_user_function(EG(function_table), NULL, &func, &retval, 4, args); result = php_base64_encode((unsigned char *)Z_STRVAL(retval), Z_STRLEN(retval)); efree(tret); zval_ptr_dtor(&retval); zval_ptr_dtor(&func); zval_ptr_dtor(&args[0]); zval_ptr_dtor(&args[1]); zval_ptr_dtor(&args[2]); zval_ptr_dtor(&args[3]); return result; } /* }}} */ zend_string *soo_sign_rsa(php_so_object *soo, char *message, const oauth_sig_context *ctx) /* {{{ */ { zval args[3], func, retval; zend_string *result; /* check for empty private key */ if (Z_TYPE(ctx->privatekey) == IS_UNDEF) { return NULL; } ZVAL_STRING(&func, "openssl_sign"); /* TODO: add support for other algorithms instead of OPENSSL_ALGO_SHA1 */ ZVAL_STRING(&args[0], message); ZVAL_NULL(&args[1]); ZVAL_MAKE_REF(&args[1]); ZVAL_DUP(&args[2], &ctx->privatekey); call_user_function(EG(function_table), NULL, &func, &retval, 3, args); if (Z_TYPE(retval) == IS_TRUE || Z_TYPE(retval) == IS_FALSE) { zend_string *sig_str = zval_get_string(&args[1]); result = php_base64_encode((unsigned char *) sig_str->val, sig_str->len); zend_string_release(sig_str); zval_ptr_dtor(&args[1]); } else { result = NULL; } zval_ptr_dtor(&retval); zval_ptr_dtor(&func); zval_ptr_dtor(&args[0]); return result; } /* }}} */ zend_string *soo_sign_plain(php_so_object *soo, const char *cs, const char *ts) /* {{{ */ { return strpprintf(0, "%s&%s", cs, ts); } /* }}} */ 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; } /* }}} */ zend_string *soo_sign(php_so_object *soo, char *message, zval *cs, zval *ts, const oauth_sig_context *ctx) /* {{{ */ { 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); } else if (OAUTH_SIGCTX_TYPE_RSA==ctx->type) { return soo_sign_rsa(soo, message, ctx); } else if(OAUTH_SIGCTX_TYPE_PLAIN==ctx->type) { return soo_sign_plain(soo, csec, tsec); } return NULL; } /* }}} */ static inline zval *soo_get_property(php_so_object *soo, char *prop_name) /* {{{ */ { return zend_hash_str_find(soo->properties, prop_name, strlen(prop_name)); } /* }}} */ /* 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) /* {{{ */ { return (zend_hash_str_update(soo->properties, prop_name, strlen(prop_name), prop) == NULL) ? FAILURE : SUCCESS; } /* }}} */ zend_string *oauth_url_encode(char *url, int url_len) /* {{{ */ { zend_string *urlencoded = NULL; zend_string *ret = NULL; if (url) { if (url_len < 0) { url_len = strlen(url); } urlencoded = php_raw_url_encode(url, url_len); } if (urlencoded) { ret = php_str_to_str(ZSTR_VAL(urlencoded), ZSTR_LEN(urlencoded), "%7E", sizeof("%7E")-1, "~", sizeof("~")-1); zend_string_free(urlencoded); return ret; } return NULL; } /* }}} */ zend_string *oauth_http_encode_value(zval *v) /* {{{ */ { zend_string *param_value = NULL; switch (Z_TYPE_P(v)) { case IS_STRING: param_value = oauth_url_encode(Z_STRVAL_P(v), Z_STRLEN_P(v)); break; default: SEPARATE_ZVAL(v); convert_to_string_ex(v); param_value = oauth_url_encode(Z_STRVAL_P(v), Z_STRLEN_P(v)); } return param_value; } /* }}} */ static int oauth_strcmp(zval *first, zval *second) /* {{{ */ { int result; result = string_compare_function(first, second); if (result < 0) { return -1; } else if (result > 0) { return 1; } return 0; } /* }}} */ #if PHP_VERSION_ID < 80000 static int oauth_compare_value(const void *a, const void *b) /* {{{ */ { Bucket *f, *s; f = (Bucket *)a; s = (Bucket *)b; #else static int oauth_compare_value(Bucket *f, Bucket *s) /* {{{ */ { #endif return oauth_strcmp(&f->val, &s->val); } /* }}} */ #if PHP_VERSION_ID < 80000 static int oauth_compare_key(const void *a, const void *b) /* {{{ */ { Bucket *f = (Bucket *)a, *s = (Bucket *)b; #else static int oauth_compare_key(Bucket *f, Bucket *s) /* {{{ */ { #endif zval first, second; int result; if (f->key == NULL) { ZVAL_LONG(&first, f->h); } else { ZVAL_STRINGL(&first, ZSTR_VAL(f->key), ZSTR_LEN(f->key)); } if (s->key == NULL) { ZVAL_LONG(&second, s->h); } else { ZVAL_STRINGL(&second, ZSTR_VAL(s->key), ZSTR_LEN(s->key)); } result = oauth_strcmp(&first, &second); zval_ptr_dtor(&first); zval_ptr_dtor(&second); return result; } /* }}} */ /* build url-encoded string from args, optionally starting with & */ int oauth_http_build_query(php_so_object *soo, smart_string *s, HashTable *args, zend_bool prepend_amp) /* {{{ */ { zval *cur_val; zend_string *cur_key, *arg_key, *param_value; int numargs = 0, hash_key_type, skip_append = 0, i, found; zend_ulong num_index; HashPosition pos; smart_string keyname; smart_string_0(s); if (args) { if (soo && !soo->is_multipart) { for (zend_hash_internal_pointer_reset_ex(args, &pos); HASH_KEY_NON_EXISTENT != (hash_key_type = zend_hash_get_current_key_ex(args, &cur_key, &num_index, &pos)); zend_hash_move_forward_ex(args, &pos)) { cur_val = zend_hash_get_current_data_ex(args, &pos); if (hash_key_type == HASH_KEY_IS_STRING && *ZSTR_VAL(cur_key) =='@' && *Z_STRVAL_P(cur_val) =='@') { soo->is_multipart = 1; break; } } } for (zend_hash_internal_pointer_reset_ex(args, &pos); HASH_KEY_NON_EXISTENT != (hash_key_type = zend_hash_get_current_key_ex(args, &cur_key, &num_index, &pos)); zend_hash_move_forward_ex(args, &pos)) { (cur_val = zend_hash_get_current_data_ex(args, &pos)); skip_append = 0; switch (hash_key_type) { case HASH_KEY_IS_STRING: if (soo && soo->is_multipart && strncmp(ZSTR_VAL(cur_key), "oauth_", 6) != 0) { found = 0; for (i=0; imultipart_files_num; ++i) { if (0 == strcmp(soo->multipart_params[i], ZSTR_VAL(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_P(cur_val); soo->multipart_params[soo->multipart_files_num] = ZSTR_VAL(cur_key); ++soo->multipart_files_num; /* we don't add multipart files to the params */ skip_append = 1; } else { arg_key = oauth_url_encode(ZSTR_VAL(cur_key), ZSTR_LEN(cur_key)); } break; case HASH_KEY_IS_LONG: /* take value of num_index instead */ arg_key = NULL; break; default: continue; } if (skip_append) { continue; } INIT_smart_string(keyname); if (arg_key) { smart_string_appends(&keyname, ZSTR_VAL(arg_key)); zend_string_release(arg_key); } else { smart_string_append_unsigned(&keyname, num_index); } if (IS_ARRAY == Z_TYPE_P(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_P(cur_val), oauth_compare_value, 1); /* traverse array */ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(cur_val), &val_pos); while ((val_cur_val = zend_hash_get_current_data_ex(Z_ARRVAL_P(cur_val), &val_pos)) != NULL) { if (prepend_amp) { smart_string_appendc(s, '&'); } smart_string_append(s, &keyname); param_value = oauth_http_encode_value(val_cur_val); if (param_value) { smart_string_appendc(s, '='); smart_string_appends(s, ZSTR_VAL(param_value)); zend_string_release(param_value); } prepend_amp = TRUE; ++numargs; zend_hash_move_forward_ex(Z_ARRVAL_P(cur_val), &val_pos); } /* clean up */ } else { if (prepend_amp) { smart_string_appendc(s, '&'); } smart_string_append(s, &keyname); param_value = oauth_http_encode_value(cur_val); if (param_value) { smart_string_appendc(s, '='); smart_string_appends(s, ZSTR_VAL(param_value)); zend_string_release(param_value); } prepend_amp = TRUE; ++numargs; } smart_string_free(&keyname); smart_string_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) /* {{{ */ { zval *ptr; if ( (Z_TYPE(PG(http_globals)[TRACK_VARS_GET]) != IS_UNDEF && (ptr = zend_hash_str_find(HASH_OF(&(PG(http_globals)[TRACK_VARS_GET])), arg_name, strlen(arg_name))) != NULL && IS_STRING == Z_TYPE_P(ptr)) || (Z_TYPE(PG(http_globals)[TRACK_VARS_POST])!= IS_UNDEF && (ptr = zend_hash_str_find(HASH_OF(&(PG(http_globals)[TRACK_VARS_POST])), arg_name, strlen(arg_name))) != NULL && IS_STRING == Z_TYPE_P(ptr)) ) { *return_val = Z_STRVAL_P(ptr); *return_len = Z_STRLEN_P(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 */ zend_string *oauth_generate_sig_base(php_so_object *soo, const char *http_method, const char *uri, HashTable *post_args, HashTable *extra_args) /* {{{ */ { zval params; char *query; char *s_port = NULL; zend_string *bufz = NULL; zend_string *sbs_query_part = NULL, *sbs_scheme_part = NULL; php_url *urlparts; smart_string 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); php_url_free(urlparts); return NULL; } php_strtolower(OAUTH_URL_STR(urlparts->scheme), OAUTH_URL_LEN(urlparts->scheme)); php_strtolower(OAUTH_URL_STR(urlparts->host), OAUTH_URL_LEN(urlparts->host)); smart_string_appends(&sbuf, OAUTH_URL_STR(urlparts->scheme)); smart_string_appends(&sbuf, "://"); smart_string_appends(&sbuf, OAUTH_URL_STR(urlparts->host)); if (urlparts->port && ((!strcmp("http", OAUTH_URL_STR(urlparts->scheme)) && OAUTH_HTTP_PORT != urlparts->port) || (!strcmp("https", OAUTH_URL_STR(urlparts->scheme)) && OAUTH_HTTPS_PORT != urlparts->port))) { spprintf(&s_port, 0, "%d", urlparts->port); smart_string_appendc(&sbuf, ':'); smart_string_appends(&sbuf, s_port); efree(s_port); } if (urlparts->path) { smart_string squery = {0}; smart_string_appends(&sbuf, OAUTH_URL_STR(urlparts->path)); smart_string_0(&sbuf); array_init(¶ms); /* merge order = oauth_args - extra_args - query */ if (post_args) { zend_hash_merge(Z_ARRVAL(params), post_args, (copy_ctor_func_t) zval_add_ref, 0); } if (extra_args) { zend_hash_merge(Z_ARRVAL(params), extra_args, (copy_ctor_func_t) zval_add_ref, 0); } if (urlparts->query) { query = estrdup(OAUTH_URL_STR(urlparts->query)); oauth_parse_str(query, ¶ms); efree(query); } /* remove oauth_signature if it's in the hash */ zend_hash_str_del(Z_ARRVAL(params), OAUTH_PARAM_SIGNATURE, sizeof(OAUTH_PARAM_SIGNATURE) - 1); /* exret2 = uksort(&exargs2[0], "strnatcmp") */ zend_hash_sort(Z_ARRVAL(params), oauth_compare_key, 0); oauth_http_build_query(soo, &squery, Z_ARRVAL(params), FALSE); smart_string_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); bufz = strpprintf(0, "%s&%s&%s", http_method, ZSTR_VAL(sbs_scheme_part), sbs_query_part ? ZSTR_VAL(sbs_query_part) : ""); /* TODO move this into oauth_get_http_method() soo_handle_error(OAUTH_ERR_INTERNAL_ERROR, "Invalid auth type", NULL); */ if(sbs_query_part) { zend_string_release(sbs_query_part); } if(sbs_scheme_part) { zend_string_release(sbs_scheme_part); } smart_string_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); return NULL; } smart_string_free(&sbuf); php_url_free(urlparts); if(soo && soo->debug) { if(soo->debug_info->sbs) { zend_string_release(soo->debug_info->sbs); } if (bufz) { soo->debug_info->sbs = bufz; zend_string_addref(soo->debug_info->sbs); } else { soo->debug_info->sbs = NULL; } } return bufz; } return NULL; } /* }}} */ static void oauth_set_debug_info(php_so_object *soo) /* {{{ */ { zval *debugInfo; if (soo->debug_info) { debugInfo = &soo->debugArr; if (Z_TYPE_P(debugInfo) != IS_UNDEF) { zval_ptr_dtor(debugInfo); } array_init(debugInfo); if(soo->debug_info->sbs) { add_assoc_string(debugInfo, "sbs", ZSTR_VAL(soo->debug_info->sbs)); } 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, OBJ_FOR_PROP(soo->this_ptr), "debugInfo", sizeof("debugInfo") - 1, debugInfo); } else { ZVAL_UNDEF(&soo->debugArr); } } /* }}} */ static int add_arg_for_req(HashTable *ht, const char *arg, const char *val) /* {{{ */ { zval varg; ZVAL_STRING(&varg, (char *)val); zend_hash_str_update(ht, (char *)arg, strlen(arg), &varg); return SUCCESS; } /* }}} */ void oauth_add_signature_header(HashTable *request_headers, HashTable *oauth_args, smart_string *header) /* {{{ */ { smart_string sheader = {0}; zend_bool prepend_comma = FALSE; zval *curval; zend_string *param_name, *param_val; zend_string *cur_key; zend_ulong num_key; HashPosition pos; smart_string_appends(&sheader, "OAuth "); for (zend_hash_internal_pointer_reset_ex(oauth_args, &pos); (curval = zend_hash_get_current_data_ex(oauth_args, &pos)) != NULL; zend_hash_move_forward_ex(oauth_args, &pos)) { zend_hash_get_current_key_ex(oauth_args, &cur_key, &num_key, &pos); if (prepend_comma) { smart_string_appendc(&sheader, ','); } param_name = oauth_url_encode(ZSTR_VAL(cur_key), ZSTR_LEN(cur_key)); param_val = oauth_url_encode(Z_STRVAL_P(curval), Z_STRLEN_P(curval)); smart_string_appends(&sheader, ZSTR_VAL(param_name)); smart_string_appendc(&sheader, '='); smart_string_appends(&sheader, "\""); smart_string_appends(&sheader, ZSTR_VAL(param_val)); smart_string_appends(&sheader, "\""); efree(param_name); efree(param_val); prepend_comma = TRUE; } smart_string_0(&sheader); if (!header) { add_arg_for_req(request_headers, "Authorization", sheader.c); } else { smart_string_appends(header, sheader.c); } smart_string_free(&sheader); } /* }}} */ #define HTTP_RESPONSE_CAAS(zvalp, header, storkey) { \ if (0==strncasecmp(Z_STRVAL_P(zvalp),header,sizeof(header)-1)) { \ CAAS(storkey, (Z_STRVAL_P(zvalp)+sizeof(header)-1)); \ } \ } #define HTTP_RESPONSE_CAAD(zvalp, header, storkey) { \ if (0==strncasecmp(Z_STRVAL_P(zvalp),header,sizeof(header)-1)) { \ CAAD(storkey, strtoul(Z_STRVAL_P(zvalp)+sizeof(header)-1,NULL,10)); \ } \ } #define HTTP_RESPONSE_CODE(zvalp) \ if (response_code < 0 && 0==strncasecmp(Z_STRVAL_P(zvalp),"HTTP/", 5) && Z_STRLEN_P(zvalp)>=12) { \ response_code = strtol(Z_STRVAL_P(zvalp)+9, NULL, 10); \ CAAL("http_code", response_code); \ } #define HTTP_RESPONSE_LOCATION(zvalp) \ if (0==strncasecmp(Z_STRVAL_P(zvalp), "Location: ", 10)) { \ strlcpy(soo->last_location_header, Z_STRVAL_P(zvalp)+10, OAUTH_MAX_HEADER_LEN); \ } static long make_req_streams(php_so_object *soo, const char *url, const smart_string *payload, const char *http_method, HashTable *request_headers) /* {{{ */ { 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; sc = php_stream_context_alloc(); if (payload->len) { ZVAL_STRINGL(&zpayload, payload->c, payload->len); Z_STRVAL(zpayload)[Z_STRLEN(zpayload)] = '\0'; php_stream_context_set_option(sc, "http", "content", &zpayload); zval_ptr_dtor(&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) { HashPosition pos; zval *cur_val, zheaders; zend_string *cur_key; zend_ulong num_key; smart_string sheaders = {0}; int first = 1; for (zend_hash_internal_pointer_reset_ex(request_headers, &pos); (cur_val = zend_hash_get_current_data_ex(request_headers, &pos)) != NULL; zend_hash_move_forward_ex(request_headers, &pos)) { /* check if a string based key is used */ smart_string sheaderline = {0}; switch ((int)zend_hash_get_current_key_ex(request_headers, &cur_key, &num_key, &pos)) { case HASH_KEY_IS_STRING: smart_string_appendl(&sheaderline, ZSTR_VAL(cur_key), ZSTR_LEN(cur_key)); break; default: continue; } smart_string_0(&sheaderline); if (!strcasecmp(sheaderline.c,"content-type")) { set_form_content_type = 0; } smart_string_appends(&sheaderline, ": "); switch (Z_TYPE_P(cur_val)) { case IS_STRING: smart_string_appendl(&sheaderline, Z_STRVAL_P(cur_val), Z_STRLEN_P(cur_val)); break; default: smart_string_free(&sheaderline); continue; } if (!first) { smart_string_appends(&sheaders, "\r\n"); } else { first = 0; } smart_string_append(&sheaders, &sheaderline); smart_string_free(&sheaderline); } if (set_form_content_type) { /* still need to add our own content-type? */ if (!first) { smart_string_appends(&sheaders, "\r\n"); } smart_string_appends(&sheaders, "Content-Type: application/x-www-form-urlencoded"); } if (sheaders.len) { smart_string_0(&sheaders); ZVAL_STRINGL(&zheaders, sheaders.c, sheaders.len); php_stream_context_set_option(sc, "http", "header", &zheaders); zval_ptr_dtor(&zheaders); if (soo->debug) { smart_string_append(&soo->debug_info->headers_out, &sheaders); } } smart_string_free(&sheaders); } /* set method */ ZVAL_STRING(&zmethod, http_method); php_stream_context_set_option(sc, "http", "method", &zmethod); zval_ptr_dtor(&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_string_free(&soo->lastresponse); smart_string_free(&soo->headers_in); if ((s = php_stream_open_wrapper_ex((char*)url, "rb", REPORT_ERRORS, NULL, sc))) { zval info; zend_string *buf; size_t rb = 0; array_init(&info); CAAS("url", url); if (Z_TYPE(s->wrapperdata) != IS_UNDEF) { zval *tmp; HashPosition pos; zend_hash_internal_pointer_reset_ex(Z_ARRVAL(s->wrapperdata), &pos); while ((tmp = zend_hash_get_current_data_ex(Z_ARRVAL(s->wrapperdata), &pos)) != NULL) { smart_string_appendl(&soo->headers_in, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); smart_string_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_ex(Z_ARRVAL(s->wrapperdata), &pos); } 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 ((buf = php_stream_copy_to_mem(s, PHP_STREAM_COPY_ALL, 0)) != NULL) { smart_string_appendl(&soo->lastresponse, ZSTR_VAL(buf), ZSTR_LEN(buf)); rb = ZSTR_LEN(buf); zend_string_release(buf); } smart_string_0(&soo->lastresponse); smart_string_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); efree(bufz); } if(soo->debug) { smart_string_append(&soo->debug_info->body_in, &soo->lastresponse); smart_string_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) /* {{{ */ { size_t relsize; php_so_object *soo = (php_so_object *)ctx; relsize = size * nmemb; smart_string_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_string *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_string_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_string_appendl(&soo->headers_in, header, hlen); } return hlen; } /* }}} */ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payload, const char *http_method, HashTable *request_headers) /* {{{ */ { 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; uint32_t sslcheck; zend_ulong num_key; smart_string sheader = {0}; zend_string *cur_key; HashPosition pos; zca_info = soo_get_property(soo, OAUTH_ATTR_CA_INFO); zca_path = soo_get_property(soo, OAUTH_ATTR_CA_PATH); sslcheck = soo->sslcheck; curl = curl_easy_init(); if (request_headers) { for (zend_hash_internal_pointer_reset_ex(request_headers, &pos); (cur_val = zend_hash_get_current_data_ex(request_headers, &pos)) != NULL; zend_hash_move_forward_ex(request_headers, &pos)) { /* check if a string based key is used */ switch ((int)zend_hash_get_current_key_ex(request_headers, &cur_key, &num_key, &pos)) { case HASH_KEY_IS_STRING: smart_string_appendl(&sheader, ZSTR_VAL(cur_key), ZSTR_LEN(cur_key)); break; default: continue; } smart_string_appends(&sheader, ": "); switch (Z_TYPE_P(cur_val)) { case IS_STRING: smart_string_appendl(&sheader, Z_STRVAL_P(cur_val), Z_STRLEN_P(cur_val)); break; default: smart_string_free(&sheader); continue; } smart_string_0(&sheader); curl_headers = curl_slist_append(curl_headers, sheader.c); smart_string_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 = (char *) php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + strlen(soo->multipart_files[i]) - 1))) { *type = '\0'; } if((filename = (char *) 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)) { char *em; spprintf(&em, 0, "failed to open file for multipart request: %s", postval); soo_handle_error(soo, -1, em, NULL, NULL); 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_P(zca_path)) { curl_easy_setopt(curl, CURLOPT_CAPATH, Z_STRVAL_P(zca_path)); } if(zca_info && Z_STRLEN_P(zca_info)) { curl_easy_setopt(curl, CURLOPT_CAINFO, Z_STRVAL_P(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_string_free(&soo->lastresponse); smart_string_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_string_0(&soo->lastresponse); smart_string_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) { 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); efree(bufz); } curl_easy_cleanup(curl); return response_code; } /* }}} */ #endif static void make_standard_query(HashTable *ht, php_so_object *soo) /* {{{ */ { 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(), sec, usec, php_combined_lcg() * 10); } add_arg_for_req(ht, OAUTH_PARAM_CONSUMER_KEY, Z_STRVAL_P(soo_get_property(soo, OAUTH_ATTR_CONSUMER_KEY))); add_arg_for_req(ht, OAUTH_PARAM_SIGNATURE_METHOD, Z_STRVAL_P(soo_get_property(soo, OAUTH_ATTR_SIGMETHOD))); add_arg_for_req(ht, OAUTH_PARAM_NONCE, nonce); add_arg_for_req(ht, OAUTH_PARAM_TIMESTAMP, ts); add_arg_for_req(ht, OAUTH_PARAM_VERSION, Z_STRVAL_P(soo_get_property(soo, OAUTH_ATTR_OAUTH_VERSION))); 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) /* {{{ */ { long auth_type = Z_LVAL_P(soo_get_property(soo, OAUTH_ATTR_AUTHMETHOD)); 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_string *http_prepare_url_concat(smart_string *surl) /* {{{ */ { smart_string_0(surl); if (!strchr(surl->c, '?')) { smart_string_appendc(surl, '?'); } else { smart_string_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_string *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_string_free(surl); if (urlparts->scheme) { smart_string_appends(surl, OAUTH_URL_STR(urlparts->scheme)); smart_string_appends(surl, "://"); } if (urlparts->host) { smart_string_appends(surl, OAUTH_URL_STR(urlparts->host)); } if (urlparts->port) { smart_string_appendc(surl, ':'); smart_string_append_unsigned(surl, urlparts->port); } smart_string_appends(surl, location); php_url_free(urlparts); } else { smart_string_free(surl); smart_string_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) /* {{{ */ { char *bufz = NULL; zend_string *sbs = NULL, *sig; 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; long http_response_code, auth_type; smart_string surl = {0}, payload = {0}, postdata = {0}; uint32_t is_redirect = FALSE, follow_redirects = 0; auth_type = Z_LVAL_P(soo_get_property(soo, OAUTH_ATTR_AUTHMETHOD)); 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); 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); } } 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); break; case IS_STRING: smart_string_appendl(&postdata, Z_STRVAL_P(request_params), Z_STRLEN_P(request_params)); break; } } /* additional http headers can be passed */ zend_hash_init(&rheaders, 0, NULL, ZVAL_PTR_DTOR, 0); if (request_headers && zend_hash_num_elements(Z_ARRVAL_P(request_headers))) { zend_hash_copy(&rheaders, Z_ARRVAL_P(request_headers), (copy_ctor_func_t) zval_add_ref); } /* initialize base url */ smart_string_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) { /* populate oauth_args with given parameters */ zend_hash_copy(oauth_args, init_oauth_args, (copy_ctor_func_t) zval_add_ref); } /* fill in the standard set of oauth parameters */ make_standard_query(oauth_args, soo); /* use token where applicable */ if (fetch_flags & OAUTH_FETCH_USETOKEN) { token = soo_get_property(soo, OAUTH_ATTR_TOKEN); if (token) { add_arg_for_req(oauth_args, OAUTH_PARAM_TOKEN, Z_STRVAL_P(token)); } } /* generate sig base on the semi-final url */ smart_string_0(&surl); sbs = oauth_generate_sig_base(soo, final_http_method, surl.c, oauth_args, rargs); 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); break; } cs = soo_get_property(soo, OAUTH_ATTR_CONSUMER_SECRET); 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); if (token_secret && Z_STRLEN_P(token_secret) > 0) { ts = token_secret; } } if(soo->signature) { zend_string_release(soo->signature); } /* sign the request */ sig = soo_sign(soo, ZSTR_VAL(sbs), cs, ts, soo->sig_ctx); soo->signature = sig; zend_string_release(sbs); if(fetch_flags & OAUTH_FETCH_SIGONLY) { FREE_ARGS_HASH(oauth_args); smart_string_free(&surl); smart_string_free(&postdata); zend_hash_destroy(&rheaders); return SUCCESS; } if (!sig) { FREE_ARGS_HASH(oauth_args); soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Signature generation failed", NULL, NULL); break; } /* and add signature to the oauth parameters */ add_arg_for_req(oauth_args, OAUTH_PARAM_SIGNATURE, ZSTR_VAL(sig)); if(fetch_flags & OAUTH_FETCH_HEADONLY) { INIT_smart_string(soo->headers_out); oauth_add_signature_header(&rheaders, oauth_args, &soo->headers_out); smart_string_0(&payload); FREE_ARGS_HASH(oauth_args); smart_string_free(&surl); smart_string_free(&postdata); zend_hash_destroy(&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_string_append(http_prepare_url_concat(&surl), &postdata); } } else { /* otherwise populate post data */ smart_string_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); smart_string_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); } /* 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); break; } /* finalize endpoint url */ smart_string_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); break; #if OAUTH_USE_CURL case OAUTH_REQENGINE_CURL: http_response_code = make_req_curl(soo, surl.c, &payload, final_http_method, &rheaders); 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); } FREE_ARGS_HASH(oauth_args); smart_string_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); if (soo->lastresponse.len) { ZVAL_STRING(&zret, soo->lastresponse.c); } else { ZVAL_STRING(&zret, ""); } so_set_response_args(soo->properties, &zret, NULL); soo_handle_error(soo, http_response_code, bufz, soo->lastresponse.c, NULL); 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_string_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 > 209) { spprintf(&bufz, 0, "Invalid auth/bad request (got a %ld, expected HTTP/1.1 20X or a redirect)", http_response_code); if(soo->lastresponse.c) { ZVAL_STRING(&zret, soo->lastresponse.c); } else { ZVAL_STRING(&zret, ""); } so_set_response_args(soo->properties, &zret, NULL); soo_handle_error(soo, http_response_code, bufz, soo->lastresponse.c, NULL); 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_string_free(&surl); smart_string_free(&postdata); zend_hash_destroy(&rheaders); return http_response_code; } /* }}} */ /* {{{ proto bool setRSACertificate(string $cert) Sets the RSA certificate */ SO_METHOD(setRSACertificate) { char *key; size_t key_len; zval args[1], func, retval; php_so_object *soo; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &key_len) == FAILURE) { return; } ZVAL_STRING(&func, "openssl_get_privatekey"); ZVAL_STRINGL(&args[0], key, key_len); call_user_function(EG(function_table), NULL, &func, &retval, 1, args); zval_ptr_dtor(&args[0]); zval_ptr_dtor(&func); switch (Z_TYPE(retval)) { case IS_RESOURCE: case IS_OBJECT: OAUTH_SIGCTX_SET_PRIVATEKEY(soo->sig_ctx, retval); RETURN_TRUE; break; default: zval_ptr_dtor(&retval); soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Could not parse RSA certificate", NULL, NULL); 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) { size_t uri_len; char *uri; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &uri, &uri_len) == FAILURE) { return; } if (uri_len < 1) { php_error_docref(NULL, E_WARNING, "Invalid uri length (0)"); RETURN_FALSE; } RETURN_STR(oauth_url_encode(uri, uri_len)); } /* }}} */ /* {{{ 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; zend_string *sbs; size_t uri_len, http_method_len; zval *req_params = NULL; HashTable *rparams = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a", &http_method, &http_method_len, &uri, &uri_len, &req_params) == FAILURE) { return; } if (uri_len < 1) { php_error_docref(NULL, E_WARNING, "Invalid uri length (0)"); RETURN_FALSE; } if (http_method_len < 1) { php_error_docref(NULL, 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))) { RETURN_STR(sbs); } 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; zend_long auth_method = 0; zval zck, zcs, zsm, zam, zver, *obj; size_t ck_len = 0, cs_len = 0, sig_method_len = 0; php_so_object *soo; obj = getThis(); if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sssl", &ck, &ck_len, &cs, &cs_len, &sig_method, &sig_method_len, &auth_method) == FAILURE) { return; } soo = Z_SOO_P(obj); if(ck_len == 0) { soo_handle_error(soo, -1, "The consumer key cannot be empty", NULL, NULL); return; } if(cs_len == 0) { soo_handle_error(soo, -1, "The consumer secret cannot be empty", NULL, NULL); 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; ZVAL_UNDEF(&soo->debugArr); soo->nonce = NULL; soo->timestamp = NULL; soo->sig_ctx = NULL; soo->signature = NULL; INIT_DEBUG_INFO(soo->debug_info); INIT_smart_string(soo->headers_in); /* set default class members */ zend_update_property_null(soo_class_entry, OBJ_FOR_PROP(obj), "debugInfo", sizeof("debugInfo") - 1); zend_update_property_bool(soo_class_entry, OBJ_FOR_PROP(obj), "debug", sizeof("debug") - 1, soo->debug); zend_update_property_long(soo_class_entry, OBJ_FOR_PROP(obj), "sslChecks", sizeof("sslChecks") - 1, soo->sslcheck); #if PHP_VERSION_ID < 80000 TSRMLS_SET_CTX(soo->thread_ctx); #endif 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; } ZVAL_STRING(&zck, ck); if (soo_set_property(soo, &zck, OAUTH_ATTR_CONSUMER_KEY) != SUCCESS) { return; } if (cs_len > 0) { ZVAL_STR(&zcs, oauth_url_encode(cs, cs_len)); } else { ZVAL_EMPTY_STRING(&zcs); } if (soo_set_property(soo, &zcs, OAUTH_ATTR_CONSUMER_SECRET) != SUCCESS) { return; } ZVAL_STRING(&zsm, sig_method); if (soo_set_property(soo, &zsm, OAUTH_ATTR_SIGMETHOD) != SUCCESS) { return; } ZVAL_LONG(&zam, auth_method); if (soo_set_property(soo, &zam, OAUTH_ATTR_AUTHMETHOD) != SUCCESS) { return; } ZVAL_STRING(&zver, OAUTH_DEFAULT_VERSION); if (soo_set_property(soo, &zver, OAUTH_ATTR_OAUTH_VERSION) != 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) /* {{{ */ { zval func, retval; zval args[1]; if (Z_TYPE_P(privatekey)==IS_RESOURCE) { ZVAL_STRING(&func, "openssl_freekey"); ZVAL_DUP(&args[0], privatekey); call_user_function(EG(function_table), NULL, &func, &retval, 1, args); zval_ptr_dtor(&func); zval_ptr_dtor(&retval); } zval_ptr_dtor(privatekey); } /* }}} */ /* {{{ 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; size_t ca_path_len = 0, ca_info_len = 0; zval zca_path, zca_info; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ss", &ca_path, &ca_path_len, &ca_info, &ca_info_len) == FAILURE) { return; } if (ca_path_len) { ZVAL_STRINGL(&zca_path, ca_path, ca_path_len); if (soo_set_property(soo, &zca_path, OAUTH_ATTR_CA_PATH) != SUCCESS) { RETURN_FALSE; } } if (ca_info_len) { ZVAL_STRINGL(&zca_info, ca_info, ca_info_len); if (soo_set_property(soo, &zca_info, OAUTH_ATTR_CA_INFO) != 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 = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) { return; } zca_info = soo_get_property(soo, OAUTH_ATTR_CA_INFO); zca_path = soo_get_property(soo, OAUTH_ATTR_CA_PATH); array_init(return_value); if (zca_info || zca_path) { if(zca_info) { add_assoc_stringl(return_value, "ca_info", Z_STRVAL_P(zca_info), Z_STRLEN_P(zca_info)); } if(zca_path) { add_assoc_stringl(return_value, "ca_path", Z_STRVAL_P(zca_path), Z_STRLEN_P(zca_path)); } } } /* }}} */ /* {{{ proto array OAuth::getRequestToken(string request_token_url [, string callback_url [, http_method ] ]) Get request token */ SO_METHOD(getRequestToken) { php_so_object *soo; zval zret, *callback_url = NULL; char *url, *http_method = OAUTH_HTTP_METHOD_POST; size_t url_len = 0, http_method_len = sizeof(OAUTH_HTTP_METHOD_POST) - 1; long retcode; HashTable *args = NULL; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "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); 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)); } else { /* empty callback url specified, treat as 1.0a */ add_arg_for_req(args, OAUTH_PARAM_CALLBACK, OAUTH_CALLBACK_OOB); } } retcode = oauth_fetch(soo, url, oauth_get_http_method(soo, http_method), NULL, NULL, args, 0); if (args) { FREE_ARGS_HASH(args); } if (retcode != -1 && soo->lastresponse.c) { array_init(return_value); ZVAL_STRINGL(&zret, soo->lastresponse.c, soo->lastresponse.len); so_set_response_args(soo->properties, &zret, return_value); return; } RETURN_FALSE; } /* }}} */ /* {{{ proto bool OAuth::enableRedirects(void) Follow and sign redirects automatically (enabled by default) */ SO_METHOD(enableRedirects) { php_so_object *soo; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == 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 = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == 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 = Z_SOO_P(obj); if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) { return; } soo->debug = 0; zend_update_property_bool(soo_class_entry, OBJ_FOR_PROP(obj), "debug", sizeof("debug") - 1, 0); 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 = Z_SOO_P(obj); if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) { return; } soo->debug = 1; zend_update_property_bool(soo_class_entry, OBJ_FOR_PROP(obj), "debug", sizeof("debug") - 1, 1); 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 = Z_SOO_P(obj); if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) { return; } soo->sslcheck = OAUTH_SSLCHECK_BOTH; zend_update_property_long(soo_class_entry, OBJ_FOR_PROP(obj), "sslChecks", sizeof("sslChecks") - 1, 1); 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 = Z_SOO_P(obj); if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) { return; } soo->sslcheck = OAUTH_SSLCHECK_NONE; zend_update_property_long(soo_class_entry, OBJ_FOR_PROP(obj), "sslChecks", sizeof("sslChecks") - 1, 0); 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; zend_long sslcheck = OAUTH_SSLCHECK_BOTH; obj = getThis(); soo = Z_SOO_P(obj); if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &sslcheck) == FAILURE) { return; } soo->sslcheck = sslcheck & OAUTH_SSLCHECK_BOTH; zend_update_property_long(soo_class_entry, OBJ_FOR_PROP(obj), "sslChecks", sizeof("sslChecks") - 1, soo->sslcheck); RETURN_TRUE; } /* }}} */ /* {{{ proto bool OAuth::setVersion(string version) Set oauth_version for requests (default 1.0) */ SO_METHOD(setVersion) { php_so_object *soo; size_t ver_len = 0; char *vers; zval zver; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &vers, &ver_len) == FAILURE) { return; } if (ver_len < 1) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid version", NULL, NULL); RETURN_FALSE; } ZVAL_STRING(&zver, vers); if (SUCCESS == soo_set_property(soo, &zver, OAUTH_ATTR_OAUTH_VERSION)) { 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; zend_long auth; zval zauth; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "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: ZVAL_LONG(&zauth, auth); if (SUCCESS == soo_set_property(soo, &zauth, OAUTH_ATTR_AUTHMETHOD)) { RETURN_TRUE; } default: soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid auth type", NULL, NULL); RETURN_FALSE; } RETURN_FALSE; } /* }}} */ /* {{{ proto bool OAuth::setTimeout(int milliseconds) Set the timeout, in milliseconds, for requests */ SO_METHOD(setTimeout) { php_so_object *soo; zend_long timeout; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &timeout) == FAILURE) { return; } if (timeout < 0) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid timeout", NULL, NULL); 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; size_t nonce_len; char *nonce; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &nonce, &nonce_len) == FAILURE) { return; } if (nonce_len < 1) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid nonce", NULL, NULL); RETURN_FALSE; } if (soo->nonce) { efree(soo->nonce); } soo->nonce = estrndup(nonce, nonce_len); RETURN_TRUE; } /* }}} */ /* {{{ proto bool setTimestamp(string $timestamp) Sets the OAuth timestamp for subsequent requests */ SO_METHOD(setTimestamp) { php_so_object *soo; size_t ts_len; char *ts; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &ts, &ts_len) == FAILURE) { return; } if (ts_len < 1) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid timestamp", NULL, NULL); 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; size_t token_len, token_secret_len; char *token, *token_secret; zval t,ts; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &token, &token_len, &token_secret, &token_secret_len) == FAILURE) { return; } ZVAL_STRING(&t, token); soo_set_property(soo, &t, OAUTH_ATTR_TOKEN); if (token_secret_len > 1) { ZVAL_STR(&ts, oauth_url_encode(token_secret, token_secret_len)); soo_set_property(soo, &ts, OAUTH_ATTR_TOKEN_SECRET); } RETURN_TRUE; } /* }}} */ /* {{{ proto void OAuth::setRequestEngine(long reqengine) */ SO_METHOD(setRequestEngine) { php_so_object *soo; zend_long reqengine; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &reqengine) == FAILURE) { return; } soo = Z_SOO_P(getThis()); 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); } } /* }}} */ /* {{{ 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; size_t url_len, http_method_len = 0; char *url; zval *request_args = NULL; char *http_method = NULL; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "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)) < 0) { RETURN_BOOL(FALSE); } else { zend_string_addref(soo->signature); RETURN_STR(soo->signature); } } /* }}} */ /* {{{ 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; size_t fetchurl_len, http_method_len = 0; char *fetchurl; zval zret, *request_args = NULL, *request_headers = NULL; char *http_method = NULL; long retcode; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "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); RETURN_FALSE; } retcode = oauth_fetch(soo, fetchurl, http_method, request_args, request_headers, NULL, OAUTH_FETCH_USETOKEN | OAUTH_OVERRIDE_HTTP_METHOD); ZVAL_STRINGL(&zret, soo->lastresponse.c, soo->lastresponse.len); so_set_response_args(soo->properties, &zret, NULL); 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 [, http_method ]]]) 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; size_t aturi_len = 0, ash_len = 0, verifier_len_size_t = 0, http_method_len = sizeof(OAUTH_HTTP_METHOD_POST) - 1; int verifier_len; char *aturi, *ash, *verifier, *http_method = OAUTH_HTTP_METHOD_POST; zval zret; HashTable *args = NULL; long retcode; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sss", &aturi, &aturi_len, &ash, &ash_len, &verifier, &verifier_len_size_t, &http_method, &http_method_len) == FAILURE) { return; } verifier_len = verifier_len_size_t; if (aturi_len < 1) { soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid access token url length", NULL, NULL); RETURN_FALSE; } if (!verifier_len) { /* try to get from _GET/_POST */ get_request_param(OAUTH_PARAM_VERIFIER, &verifier, &verifier_len); } 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); } if (verifier_len > 0) { add_arg_for_req(args, OAUTH_PARAM_VERIFIER, verifier); } } retcode = oauth_fetch(soo, aturi, oauth_get_http_method(soo, http_method), NULL, NULL, args, OAUTH_FETCH_USETOKEN); if (args) { FREE_ARGS_HASH(args); } if (retcode != -1 && soo->lastresponse.c) { array_init(return_value); ZVAL_STRINGL(&zret, soo->lastresponse.c, soo->lastresponse.len); so_set_response_args(soo->properties, &zret, return_value); return; } RETURN_FALSE; } /* }}} */ /* {{{ proto array OAuth::getLastResponseInfo(void) Get information about the last response */ SO_METHOD(getLastResponseInfo) { php_so_object *soo; zval *data_ptr; if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) { return; } soo = Z_SOO_P(getThis()); if ((data_ptr = zend_hash_str_find(soo->properties, OAUTH_ATTR_LAST_RES_INFO, sizeof(OAUTH_ATTR_LAST_RES_INFO) - 1)) != NULL) { if (Z_TYPE_P(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(), "") == FAILURE) { return; } soo = Z_SOO_P(getThis()); if (soo->lastresponse.c) { RETURN_STRINGL(soo->lastresponse.c, soo->lastresponse.len); } } /* }}} */ /* {{{ proto string getLastResponseHeaders(void) Get headers for last response */ SO_METHOD(getLastResponseHeaders) { php_so_object *soo; if (FAILURE==zend_parse_parameters(ZEND_NUM_ARGS(), "")) { return; } soo = Z_SOO_P(getThis()); if (soo->headers_in.c) { RETURN_STRINGL(soo->headers_in.c, soo->headers_in.len); } 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; size_t url_len, http_method_len = 0; char *url; zval *request_args = NULL; char *http_method = NULL; soo = Z_SOO_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "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)) < 0) { RETURN_BOOL(FALSE); } else { RETURN_STRINGL(soo->headers_out.c, soo->headers_out.len); } RETURN_FALSE; } /* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_urlencode, 0, 0, 1) ZEND_ARG_INFO(0, uri) ZEND_END_ARG_INFO() 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() 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() 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() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setversion, 0, 0, 1) ZEND_ARG_INFO(0, version) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_noparams, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setauthtype, 0, 0, 1) ZEND_ARG_INFO(0, auth_type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setnonce, 0, 0, 1) ZEND_ARG_INFO(0, nonce) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_settimestamp, 0, 0, 1) ZEND_ARG_INFO(0, ts) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_settimeout, 0, 0, 1) ZEND_ARG_INFO(0, timeout_in_milliseconds) ZEND_END_ARG_INFO() 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() 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() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setrequestengine, 0, 0, 1) ZEND_ARG_INFO(0, reqengine) ZEND_END_ARG_INFO() 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() 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() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setrsacertificate, 0, 0, 1) ZEND_ARG_INFO(0, cert) ZEND_END_ARG_INFO() 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() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setsslchecks, 0, 0, 1) ZEND_ARG_INFO(0, sslcheck) ZEND_END_ARG_INFO() 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) {NULL, NULL, NULL} }; /* }}} */ #if PHP_VERSION_ID < 80000 zval *oauth_read_member(zval *obj, zval *mem, int type, void **cache_slot, zval *rv) /* {{{ */ { php_so_object *soo = Z_SOO_P(obj); char *name = Z_STRVAL_P(mem); #else zval *oauth_read_member(zend_object *obj, zend_string *mem, int type, void **cache_slot, zval *rv) /* {{{ */ { php_so_object *soo = so_object_from_obj(obj); char *name = ZSTR_VAL(mem); #endif zval *return_value = NULL; return_value = std_object_handlers.read_property(obj, mem, type, cache_slot, rv); if(!strcasecmp(name, "debug")) { convert_to_boolean(return_value); ZVAL_BOOL(return_value, soo->debug); } else if(!strcasecmp(name, "sslChecks")) { ZVAL_LONG(return_value, soo->sslcheck); } return return_value; } /* }}} */ #if PHP_VERSION_ID < 80000 static #if PHP_VERSION_ID >= 70400 zval * #else void #endif oauth_write_member(zval *obj, zval *mem, zval *value, void **cache_slot) /* {{{ */ { php_so_object *soo = Z_SOO_P(obj); char *property = Z_STRVAL_P(mem); #else static zval *oauth_write_member(zend_object *obj, zend_string *mem, zval *value, void **cache_slot) /* {{{ */ { php_so_object *soo = so_object_from_obj(obj); char *property = ZSTR_VAL(mem); #endif if(!strcmp(property,"debug")) { soo->debug = Z_TYPE_P(value) == IS_TRUE ? 1 : 0; } else if(!strcmp(property,"sslChecks")) { soo->sslcheck = Z_LVAL_P(value); } #if PHP_VERSION_ID >= 70400 return #endif std_object_handlers.write_property(obj, mem, value, cache_slot); } /* }}} */ /* {{{ 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 = php_so_object_new; soo_class_entry = zend_register_internal_class(&soce); memcpy(&so_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); so_object_handlers.offset = XtOffsetOf(php_so_object, zo); so_object_handlers.read_property = oauth_read_member; so_object_handlers.write_property = oauth_write_member; so_object_handlers.clone_obj = oauth_clone_obj; so_object_handlers.free_obj = so_object_free_storage; zend_declare_property_long(soo_class_entry, "debug", sizeof("debug")-1, 0, ZEND_ACC_PUBLIC); zend_declare_property_long(soo_class_entry, "sslChecks", sizeof("sslChecks")-1, 1, ZEND_ACC_PUBLIC); zend_declare_property_string(soo_class_entry, "debugInfo", sizeof("debugInfo")-1, "", ZEND_ACC_PUBLIC); INIT_CLASS_ENTRY(soo_ex_ce, "OAuthException", NULL); soo_exception_ce = zend_register_internal_class_ex(&soo_ex_ce, zend_exception_get_default()); zend_declare_property_null(soo_exception_ce, "lastResponse", sizeof("lastResponse")-1, ZEND_ACC_PUBLIC); zend_declare_property_null(soo_exception_ce, "debugInfo", sizeof("debugInfo")-1, ZEND_ACC_PUBLIC); 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(); 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, "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-2.0.7/provider.c0000644000175000001440000011533113731057347013520 0ustar mikeusers/* +----------------------------------------------------------------------+ | See LICENSE file for further copyright information | +----------------------------------------------------------------------+ | Authors: John Jawed | | Felipe Pena | | Rasmus Lerdorf | | Tjerk Meesters | +----------------------------------------------------------------------+ */ #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) /* {{{ */ { zend_update_property(Z_OBJCE_P(provider_obj), OBJ_FOR_PROP(provider_obj), prop_name, strlen(prop_name), prop); } /* }}} */ static inline php_oauth_provider *fetch_sop_object(zval *obj) /* {{{ */ { php_oauth_provider *sop = Z_SOP_P(obj); 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; ZVAL_NULL(&tmp); if(zend_hash_str_add(ht, required_params[idx], strlen(required_params[idx]), &tmp) == NULL) { return FAILURE; } ++idx; } while(required_params[idx]); return SUCCESS; } /* }}} */ static int oauth_provider_remove_required_param(HashTable *ht, char *required_param) /* {{{ */ { zval *dest_entry; zend_string *key; zend_ulong num_key; HashPosition hpos; if((dest_entry = zend_hash_str_find(ht, required_param, strlen(required_param))) == NULL) { return FAILURE; } else { zend_hash_internal_pointer_reset_ex(ht, &hpos); do { if(zend_hash_get_current_key_ex(ht, &key, &num_key, &hpos)!=FAILURE) { if(!strcmp(ZSTR_VAL(key), required_param)) { zend_hash_del(ht, key); 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((dest_entry = zend_hash_str_find(ht, required_param, strlen(required_param))) == NULL) { ZVAL_NULL(&zparam); if(zend_hash_str_add(ht, required_param, strlen(required_param), &zparam) == NULL) { return FAILURE; } } return SUCCESS; } /* }}} */ static void oauth_provider_apply_custom_param(HashTable *ht, HashTable *custom) /* {{{ */ { HashPosition custompos; zval *entry; zend_string *key; zend_ulong num_key; zend_hash_internal_pointer_reset_ex(custom, &custompos); do { if ((entry = zend_hash_get_current_data_ex(custom, &custompos)) != NULL && HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(custom, &key, &num_key, &custompos)) { if (IS_NULL == Z_TYPE_P(entry)) { zend_hash_del(ht, key); } else { Z_TRY_ADDREF_P(entry); zend_hash_update(ht, key, entry); } } } while (SUCCESS==zend_hash_move_forward_ex(custom, &custompos)); } /* }}} */ static int oauth_provider_token_required(zval *provider_obj, char* uri) { zval *is_req_token_api, rv; is_req_token_api = zend_read_property(Z_OBJCE_P(provider_obj), OBJ_FOR_PROP(provider_obj), "request_token_endpoint", sizeof("request_token_endpoint") - 1, 1, &rv); if (Z_TYPE_P(is_req_token_api) == IS_FALSE) { php_oauth_provider *sop; sop = fetch_sop_object(provider_obj); /* 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(OAUTH_URL_STR(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) /* {{{ */ { HashPosition hpos, reqhpos, paramhpos; zval *dest_entry, param; zend_string *key; zend_ulong num_key; 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, &num_key, &hpos) == HASH_KEY_IS_STRING) { if((dest_entry = zend_hash_find(params, key)) == NULL) { ZVAL_STRING(¶m, ZSTR_VAL(key)); zend_hash_next_index_insert(missing_params, ¶m); } } } while(zend_hash_move_forward_ex(required_params, &hpos)==SUCCESS); } /* }}} */ static void oauth_provider_set_std_params(zval *provider_obj, HashTable *sbs_vars) /* {{{ */ { 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) /* {{{ */ { Z_TRY_ADDREF_P(val); return zend_hash_str_update(ht, key, strlen(key), val) != NULL; } /* }}} */ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_header) /* {{{ */ { pcre_cache_entry *pce; zval subpats, return_value, *item_param, *current_param, *current_val; HashPosition hpos; zend_string *regex = zend_string_init(OAUTH_REGEX, sizeof(OAUTH_REGEX) - 1, 0); #if PHP_VERSION_ID >= 70400 zend_string *s_auth_header = zend_string_init(auth_header, strlen(auth_header), 0); #endif size_t decoded_len; if(!auth_header || strncasecmp(auth_header, "oauth", 4) || !sop) { return FAILURE; } /* pass "OAuth " */ auth_header += 5; if ((pce = pcre_get_compiled_regex_cache(regex)) == NULL) { zend_string_release(regex); return FAILURE; } zend_string_release(regex); ZVAL_NULL(&subpats); ZVAL_NULL(&return_value); php_pcre_match_impl( pce, #if PHP_VERSION_ID >= 70400 s_auth_header, #else auth_header, strlen(auth_header), #endif &return_value, &subpats, 1, /* global */ 1, /* use flags */ 2, /* PREG_SET_ORDER */ 0 ); if (0 == Z_LVAL(return_value)) { return FAILURE; } zend_hash_internal_pointer_reset_ex(Z_ARRVAL(subpats), &hpos); /* walk the oauth param names */ do { if ((item_param = zend_hash_get_current_data_ex(Z_ARRVAL(subpats), &hpos)) != NULL) { zval decoded_val; char *tmp; /* * item = array( * 1 => param name * 2 => quoted value * 3 => unquoted value (defined if matched) * ) */ current_param = zend_hash_index_find(Z_ARRVAL_P(item_param), 1); if ((current_val =zend_hash_index_find(Z_ARRVAL_P(item_param), 3)) == NULL) { current_val = zend_hash_index_find(Z_ARRVAL_P(item_param), 2); } tmp = estrndup(Z_STRVAL_P(current_val), Z_STRLEN_P(current_val)); decoded_len = php_url_decode(tmp, Z_STRLEN_P(current_val)); ZVAL_STRINGL(&decoded_val, tmp, decoded_len); if (oauth_provider_set_param_value(sop->oauth_params, Z_STRVAL_P(current_param), &decoded_val)==FAILURE) { return FAILURE; } Z_DELREF(decoded_val); } } while (SUCCESS==zend_hash_move_forward_ex(Z_ARRVAL(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(), "f", &fci, &fci_cache)==FAILURE) { return; } sop = fetch_sop_object(getThis()); 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_TRY_ADDREF(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, 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 args, *pthis; char *errstr = ""; pthis = getThis(); sop = fetch_sop_object(pthis); 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, E_ERROR, "Invalid callback type for OAuthProvider"); return NULL; } if(!cb) { php_error_docref(NULL, E_ERROR, "%s", errstr); return NULL; } array_init(&args); add_next_index_zval(&args, pthis); Z_ADDREF_P(pthis); errstr = NULL; if (!zend_is_callable(&cb->fcall_info->function_name, 0, NULL)) { if (errstr) { php_error_docref(NULL, E_WARNING, "Invalid callback: %s, %s", Z_STRVAL(cb->fcall_info->function_name), errstr); efree(errstr); } else { php_error_docref(NULL, E_WARNING, "Invalid callback: %s.", Z_STRVAL(cb->fcall_info->function_name)); } } else if (errstr) { php_error_docref(NULL, E_WARNING, "%s", errstr); efree(errstr); } if (zend_fcall_info_call(cb->fcall_info, &cb->fcall_info_cache, return_value, &args)!=SUCCESS) { php_error_docref(NULL, E_ERROR, "Failed calling callback %s", Z_STRVAL(cb->fcall_info->function_name)); } zval_ptr_dtor(&args); return return_value; } /* }}} */ static char *oauth_provider_get_http_verb() /* {{{ */ { zval *tmp; zend_is_auto_global_str("_SERVER", sizeof("_SERVER")-1); if(Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) != IS_UNDEF) { if((tmp = zend_hash_str_find(HASH_OF(&PG(http_globals)[TRACK_VARS_SERVER]), "REQUEST_METHOD", sizeof("REQUEST_METHOD") - 1)) != NULL || (tmp = zend_hash_str_find(HASH_OF(&PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_METHOD", sizeof("HTTP_METHOD") - 1)) != NULL ) { return Z_STRVAL_P(tmp); } } return NULL; } /* }}} */ static char *oauth_provider_get_current_uri() { zval *host, *port, *uri, *proto, *https; zend_is_auto_global_str("_SERVER", sizeof("_SERVER")-1); host = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_HOST", sizeof("HTTP_HOST") - 1); port = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "SERVER_PORT", sizeof("SERVER_PORT") - 1); uri = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "REQUEST_URI", sizeof("REQUEST_URI") - 1); proto = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_X_FORWARDED_PROTO", sizeof("HTTP_X_FORWARDED_PROTO") - 1); https = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "HTTPS", sizeof("HTTPS") - 1); if (host && port && uri) { char *tmp,*hostname,*colon_in_hostname; spprintf(&hostname, 0, "%s", Z_STRVAL_P(host)); colon_in_hostname=strrchr(hostname,':'); if(colon_in_hostname && ((https && Z_LVAL_P(port)==443) || (!https && Z_LVAL_P(port)==80))) { *colon_in_hostname=0; } if(proto && Z_STRLEN_P(proto)) { spprintf(&tmp, 0, "%s://%s%s", Z_STRVAL_P(proto), hostname, Z_STRVAL_P(uri)); } else if(https && Z_STRLEN_P(https)>0 && strcasecmp(Z_STRVAL_P(https),"off")!=0) { spprintf(&tmp, 0, "https://%s%s", hostname, Z_STRVAL_P(uri)); } else { spprintf(&tmp, 0, "http://%s%s", hostname, Z_STRVAL_P(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, apache_get_headers, retval, *tmpzval, *item_param; char *authorization_header = NULL; zend_string *key; zend_ulong num_key = 0, param_count = 0; HashPosition hpos; pthis = getThis(); sop = fetch_sop_object(pthis); /* XXX throw E_NOTICE if filter!='unsafe_raw' */ if(zend_parse_parameters(ZEND_NUM_ARGS(), "|z", ¶ms)==FAILURE) { soo_handle_error(NULL, OAUTH_ERR_INTERNAL_ERROR, "Failed to instantiate OAuthProvider", NULL, NULL); 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, 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), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_CONSUMER_KEY, sizeof(OAUTH_PROVIDER_CONSUMER_KEY)-1); zend_update_property_null(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_CONSUMER_SECRET, sizeof(OAUTH_PROVIDER_CONSUMER_SECRET)-1); zend_update_property_null(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_NONCE, sizeof(OAUTH_PROVIDER_NONCE)-1); zend_update_property_null(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_TOKEN, sizeof(OAUTH_PROVIDER_TOKEN)-1); zend_update_property_null(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_TOKEN_SECRET, sizeof(OAUTH_PROVIDER_TOKEN_SECRET)-1); zend_update_property_null(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_TIMESTAMP, sizeof(OAUTH_PROVIDER_TIMESTAMP)-1); zend_update_property_null(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_VERSION, sizeof(OAUTH_PROVIDER_VERSION)-1); zend_update_property_null(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_SIGNATURE_METHOD, sizeof(OAUTH_PROVIDER_SIGNATURE_METHOD)-1); zend_update_property_null(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_CALLBACK, sizeof(OAUTH_PROVIDER_CALLBACK)-1); zend_update_property_bool(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), "request_token_endpoint", sizeof("request_token_endpoint")-1, 0); if(!param_count) { /* TODO: support NSAPI */ /* mod_php */ if(!strncasecmp(sapi_module.name, "apache", sizeof("apache") - 1)) { ZVAL_STRING(&apache_get_headers, "apache_request_headers"); if(zend_is_callable(&apache_get_headers, 0, NULL)) { if(call_user_function(EG(function_table), NULL, &apache_get_headers, &retval, 0, NULL)) { php_error_docref(NULL, E_ERROR, "Failed to get HTTP Request headers"); } if((tmpzval = zend_hash_str_find(HASH_OF(&retval), "Authorization", sizeof("Authorization") - 1)) != NULL) { authorization_header = estrdup(Z_STRVAL_P(tmpzval)); } else if ((tmpzval = zend_hash_str_find(HASH_OF(&retval), "authorization", sizeof("authorization") - 1)) != NULL) { authorization_header = estrdup(Z_STRVAL_P(tmpzval)); } else { /* search one by one */ zend_hash_internal_pointer_reset_ex(HASH_OF(&retval), &hpos); do { if (FAILURE != zend_hash_get_current_key_ex(HASH_OF(&retval), &key, &num_key, &hpos) && ZSTR_LEN(key) == sizeof("authorization") && 0 == strcasecmp(ZSTR_VAL(key), "authorization") && (tmpzval = zend_hash_get_current_data_ex(HASH_OF(&retval), &hpos)) != NULL) { authorization_header = estrdup(Z_STRVAL_P(tmpzval)); break; } } while (SUCCESS==zend_hash_move_forward_ex(HASH_OF(&retval), &hpos)); } } else { php_error_docref(NULL, E_ERROR, "Failed to call apache_request_headers while running under the Apache SAPI"); } zval_ptr_dtor(&apache_get_headers); zval_ptr_dtor(&retval); } else { /* not mod_php, look in _SERVER and _ENV for Authorization header */ if(!zend_is_auto_global_str("_SERVER", sizeof("_SERVER") - 1) && !zend_is_auto_global_str("_ENV", sizeof("_ENV") - 1)) { return; } /* first look in _SERVER */ if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_UNDEF || ((tmpzval = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION") - 1)) == NULL && (tmpzval = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "REDIRECT_HTTP_AUTHORIZATION", sizeof("REDIRECT_HTTP_AUTHORIZATION") -1)) == NULL)) { /* well that didn't work out, so let's check out _ENV */ if (Z_TYPE(PG(http_globals)[TRACK_VARS_ENV]) == IS_UNDEF || (tmpzval = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_ENV]), "HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION"))) == NULL) { /* not found, [bf]ail */ return; } } authorization_header = estrdup(Z_STRVAL_P(tmpzval)); } if (authorization_header) { int ret = oauth_provider_parse_auth_header(sop, authorization_header); efree(authorization_header); if (FAILURE==ret) { soo_handle_error(NULL, OAUTH_SIGNATURE_METHOD_REJECTED, "Unknown signature method", NULL, NULL); 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, &num_key, &hpos) == HASH_KEY_IS_STRING) { if((item_param = zend_hash_get_current_data_ex(Z_ARRVAL_P(params), &hpos)) != NULL) { if(oauth_provider_set_param_value(sop->oauth_params, ZSTR_VAL(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; if(zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ob", &pthis, oauthprovider, &req_api)==FAILURE) { return; } zend_update_property_bool(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), "request_token_endpoint", sizeof("request_token_endpoint") - 1, req_api); } /* }}} */ SOP_METHOD(setRequestTokenPath) { zval *pthis; php_oauth_provider *sop; char *path; size_t path_len; if (FAILURE==zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &pthis, oauthprovider, &path, &path_len)) { return; } sop = fetch_sop_object(pthis); 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 = NULL, rv; oauth_sig_context *sig_ctx = NULL; php_oauth_provider *sop; zend_ulong missing_param_count = 0, mp_count = 1; char additional_info[512] = "", *http_verb = NULL, *uri = NULL, *current_uri = NULL; zend_string *sbs, *signature = NULL; HashPosition hpos; HashTable *sbs_vars = NULL; size_t http_verb_len = 0, uri_len = 0; int is_token_required = 0; if(zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ss", &pthis, oauthprovider, &uri, &uri_len, &http_verb, &http_verb_len)==FAILURE) { return; } sop = fetch_sop_object(pthis); if(!http_verb_len) { http_verb = oauth_provider_get_http_verb(); } if(!http_verb) { php_error_docref(NULL, 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(Z_TYPE(PG(http_globals)[TRACK_VARS_GET]) != IS_UNDEF) { zend_hash_merge(sbs_vars, HASH_OF(&PG(http_globals)[TRACK_VARS_GET]), (copy_ctor_func_t)zval_add_ref, 0); } if(Z_TYPE(PG(http_globals)[TRACK_VARS_POST]) != IS_UNDEF) { zend_hash_merge(sbs_vars, HASH_OF(&PG(http_globals)[TRACK_VARS_POST]), (copy_ctor_func_t)zval_add_ref, 0); } if(zend_hash_num_elements(sop->oauth_params)) { zend_hash_merge(sbs_vars, sop->oauth_params, (copy_ctor_func_t)zval_add_ref, 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); if (!uri) { /* get current uri */ uri = current_uri = oauth_provider_get_current_uri(); } /* 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))) { /* 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); 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((param = zend_hash_get_current_data_ex(sop->missing_params, &hpos)) != NULL) { snprintf(additional_info, 512, "%s%s%s", additional_info, Z_STRVAL_P(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); FREE_ARGS_HASH(sbs_vars); OAUTH_PROVIDER_FREE_STRING(current_uri); return; } sig_method = zend_read_property(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_SIGNATURE_METHOD, sizeof(OAUTH_PROVIDER_SIGNATURE_METHOD) - 1, 1, &rv); do { if (sig_method && (Z_TYPE_P(sig_method) == IS_STRING) && 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); 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); 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); 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); 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); if (sbs) { consumer_secret = zend_read_property(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_CONSUMER_SECRET, sizeof(OAUTH_PROVIDER_CONSUMER_SECRET) - 1, 1, &rv); convert_to_string_ex(consumer_secret); if (is_token_required) { token_secret = zend_read_property(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_TOKEN_SECRET, sizeof(OAUTH_PROVIDER_TOKEN_SECRET) - 1, 1, &rv); convert_to_string_ex(token_secret); } signature = soo_sign(NULL, ZSTR_VAL(sbs), consumer_secret, token_secret, sig_ctx); } req_signature = zend_read_property(Z_OBJCE_P(pthis), OBJ_FOR_PROP(pthis), OAUTH_PROVIDER_SIGNATURE, sizeof(OAUTH_PROVIDER_SIGNATURE) - 1, 1, &rv); if (!signature || !Z_STRLEN_P(req_signature) || strcmp(ZSTR_VAL(signature), Z_STRVAL_P(req_signature))) { soo_handle_error(NULL, OAUTH_INVALID_SIGNATURE, "Signatures do not match", NULL, sbs ? ZSTR_VAL(sbs) : NULL); } if (sbs) { zend_string_release(sbs); } if (signature) { zend_string_release(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; size_t req_param_len; if(zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &pthis, oauthprovider, &required_param, &req_param_len)==FAILURE) { return; } sop = fetch_sop_object(pthis); 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; size_t param_key_len; php_oauth_provider *sop; if (FAILURE==zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|z/", &pthis, oauthprovider, ¶m_key, ¶m_key_len, ¶m_val)) { return; } sop = fetch_sop_object(pthis); if (!param_val) { RETURN_BOOL(SUCCESS == zend_hash_str_del(sop->custom_params, param_key, param_key_len)); } else { Z_TRY_ADDREF_P(param_val); RETURN_BOOL(NULL != zend_hash_str_add(sop->custom_params, param_key, param_key_len, param_val)); } } /* }}} */ /* {{{ proto void OAuthProvider::removeRequiredParameter(string $required_param) */ SOP_METHOD(removeRequiredParameter) { zval *pthis; char *required_param; php_oauth_provider *sop; size_t req_param_len; if(zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &pthis, oauthprovider, &required_param, &req_param_len)==FAILURE) { return; } sop = fetch_sop_object(pthis); 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(), "l|b", &size, &strong)==FAILURE) { return; } if (size < 1 || size > INT_MAX) { php_error_docref(NULL, 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, E_WARNING, "Could not gather enough random data, falling back on rand()"); } while (reaped < size) { iv[reaped++] = (char) (255.0 * php_rand() / RAND_MAX); } } RETURN_STRINGL(iv, size); } /* }}} */ /* {{{ proto void OAuthProvider::reportProblem(Exception $e) */ SOP_METHOD(reportProblem) { zval *exception, *code, *sbs, *missing_params, rv; zend_class_entry *ex_ce; zend_bool out_malloced = 0; char *out, *tmp_out, *http_header_line; size_t pr_len; zend_ulong lcode; uint32_t http_code; sapi_header_line ctr = {0}; zend_bool send_headers = 1; ex_ce = zend_exception_get_default(); if(zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &exception, ex_ce, &send_headers)==FAILURE) { return; } /* XXX good candidate for refactoring */ code = zend_read_property(Z_OBJCE_P(exception), OBJ_FOR_PROP(exception), "code", sizeof("code") - 1, 1, &rv); 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), OBJ_FOR_PROP(exception), "additionalInfo", sizeof("additionalInfo") - 1, 1, &rv); 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), OBJ_FOR_PROP(exception), "additionalInfo", sizeof("additionalInfo") - 1, 1, &rv); 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=%lu", lcode); out_malloced = 1; } ZVAL_STRINGL(return_value, out, strlen(out)); 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); } if(out_malloced) { efree(out); } } /* }}} */ static void oauth_provider_free_storage(zend_object *obj) /* {{{ */ { php_oauth_provider *sop; sop = sop_object_from_obj(obj); zend_object_std_dtor(&sop->zo); 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]); } /* }}} */ static zend_object* oauth_provider_new(zend_class_entry *ce) /* {{{ */ { php_oauth_provider *nos; nos = ecalloc(1, sizeof(php_oauth_provider) + zend_object_properties_size(ce)); zend_object_std_init(&nos->zo, ce); object_properties_init(&nos->zo, ce); nos->zo.handlers = &oauth_provider_obj_hndlrs; return &nos->zo; } /* }}} */ ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider__construct, 0, 0, 0) ZEND_ARG_INFO(0, params_array) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_noparams, 0, 0, 0) ZEND_END_ARG_INFO() 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() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_handler, 0, 0, 1) ZEND_ARG_INFO(0, function_name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_reportproblem, 0, 0, 1) ZEND_ARG_INFO(0, oauthexception) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_req_token, 0, 0, 1) ZEND_ARG_INFO(0, params_array) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_set_req_param, 0, 0, 1) ZEND_ARG_INFO(0, req_params) ZEND_END_ARG_INFO() 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() ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_provider_set_path, 0, 0, 1) ZEND_ARG_INFO(0, path) ZEND_END_ARG_INFO() 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} }; extern int oauth_provider_register_class(void) /* {{{ */ { zend_class_entry osce; INIT_CLASS_ENTRY(osce, "OAuthProvider", oauth_provider_methods); osce.create_object = oauth_provider_new; oauthprovider = zend_register_internal_class(&osce); memcpy(&oauth_provider_obj_hndlrs, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); oauth_provider_obj_hndlrs.offset = XtOffsetOf(php_oauth_provider, zo); oauth_provider_obj_hndlrs.free_obj = oauth_provider_free_storage; 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-2.0.7/php_oauth.h0000644000175000001440000002410513731057347013660 0ustar mikeusers/* +----------------------------------------------------------------------+ | See LICENSE file for further copyright information | +----------------------------------------------------------------------+ | Authors: John Jawed | | Felipe Pena | | Rasmus Lerdorf | +----------------------------------------------------------------------+ */ #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_string.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 #define PHP_OAUTH_VERSION 2.0.7 #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; \ ZVAL_UNDEF(&ctx->privatekey); \ } #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 (Z_TYPE(ctx->privatekey) != IS_UNDEF) { \ oauth_free_privatekey(&ctx->privatekey); \ ZVAL_UNDEF(&ctx->privatekey); \ } \ } #define OAUTH_SIGCTX_SET_PRIVATEKEY(ctx, privkey) { \ OAUTH_SIGCTX_FREE_PRIVATEKEY(ctx) \ ZVAL_DUP(&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 { zend_string *sbs; smart_string headers_in; smart_string headers_out; smart_string body_in; smart_string body_out; smart_string curl_info; } php_so_debug; typedef struct { HashTable *properties; smart_string lastresponse; smart_string headers_in; smart_string headers_out; char last_location_header[OAUTH_MAX_HEADER_LEN]; uint32_t redirects; uint32_t multipart_files_num; uint32_t sslcheck; /* whether we check for SSL verification or not */ uint32_t debug; /* verbose output */ uint32_t follow_redirects; /* follow and sign redirects? */ uint32_t reqengine; /* streams or curl */ long timeout; /* timeout in milliseconds */ char *nonce; char *timestamp; zend_string *signature; zval *this_ptr; zval debugArr; oauth_sig_context *sig_ctx; php_so_debug *debug_info; char **multipart_files; char **multipart_params; uint32_t is_multipart; void ***thread_ctx; zend_object zo; } php_so_object; static inline php_so_object *so_object_from_obj(zend_object *obj) /* {{{ */ { return (php_so_object*)((char*)(obj) - XtOffsetOf(php_so_object, zo)); } /* }}} */ static inline php_so_object *Z_SOO_P(zval *zv) /* {{{ */ { php_so_object *soo = so_object_from_obj(Z_OBJ_P((zv))); soo->this_ptr = zv; return soo; } /* }}} */ #ifndef zend_parse_parameters_none #define zend_parse_parameters_none() \ zend_parse_parameters(ZEND_NUM_ARGS(), "") #endif void soo_handle_error(php_so_object *soo, long errorCode, char *msg, char *response, char *additional_info); zend_string *oauth_generate_sig_base(php_so_object *soo, const char *http_method, const char *uri, HashTable *post_args, HashTable *extra_args); #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_string(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_string((a)->headers_out); \ INIT_smart_string((a)->body_in); \ INIT_smart_string((a)->body_out); \ INIT_smart_string((a)->curl_info); #define FREE_DEBUG_INFO(a) \ smart_string_free(&(a)->headers_out); \ smart_string_free(&(a)->body_in); \ smart_string_free(&(a)->body_out); \ smart_string_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) - 1, (long) v); #define CAAD(s, v) add_assoc_double_ex(&info, s, sizeof(s) - 1, (double) v); #define CAAS(s, v) add_assoc_string_ex(&info, s, sizeof(s) - 1, (char *) (v ? v : "")); #define ADD_DEBUG_INFO(a, k, s, t) \ if(s.len) { \ smart_string_0(&(s)); \ if(t) { \ zend_string *tmp, *s_zstr = zend_string_init((s).c, (s).len, 0); \ tmp = php_trim(s_zstr, NULL, 0, 3); \ add_assoc_string((a), k, ZSTR_VAL(tmp)); \ zend_string_release(tmp); \ zend_string_release(s_zstr); \ } else { \ add_assoc_string((a), k, (s).c); \ } \ } #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_string *payload, const char *http_method, HashTable *request_headers); #if LIBCURL_VERSION_NUM >= 0x071304 #define OAUTH_PROTOCOLS_ALLOWED CURLPROTO_HTTP | CURLPROTO_HTTPS #endif #endif void oauth_free_privatekey(zval *privatekey); zend_string *soo_sign(php_so_object *soo, char *message, zval *cs, zval *ts, const oauth_sig_context *ctx); oauth_sig_context *oauth_create_sig_context(const char *sigmethod); zend_string *oauth_url_encode(char *url, int url_len); // Compatibility macros #if PHP_VERSION_ID < 70300 #define OAUTH_URL_STR(a) (a) #define OAUTH_URL_LEN(a) strlen(a) #else #define OAUTH_URL_STR(a) ZSTR_VAL(a) #define OAUTH_URL_LEN(a) ZSTR_LEN(a) #endif #if PHP_VERSION_ID < 80000 #define OBJ_FOR_PROP(zv) (zv) #else #define OBJ_FOR_PROP(zv) Z_OBJ_P(zv) #endif #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-2.0.7/provider.h0000644000175000001440000001152613731057347013526 0ustar mikeusers/* +----------------------------------------------------------------------+ | See LICENSE file for further copyright information | +----------------------------------------------------------------------+ | Authors: John Jawed | | Felipe Pena | | Rasmus Lerdorf | | Tjerk Meesters | +----------------------------------------------------------------------+ */ #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_DUP(return_value, oauth_provider_call_cb(pt, m)); \ #define OAUTH_PROVIDER_FREE_FCALL_INFO(o) \ if(o) { \ if(Z_TYPE(o->fcall_info->function_name) != IS_UNDEF) { 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)) { \ 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((dest_entry = zend_hash_str_find(h, k, sizeof(k) - 1)) != NULL) { \ oauth_provider_set_param_member(provider_obj, m, dest_entry); \ } 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 { 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; zend_object zo; } php_oauth_provider; static inline php_oauth_provider *sop_object_from_obj(zend_object *obj) /* {{{ */ { return (php_oauth_provider*)((char*)(obj) - XtOffsetOf(php_oauth_provider, zo)); } /* }}} */ #define Z_SOP_P(zv) sop_object_from_obj(Z_OBJ_P((zv))) extern int oauth_provider_register_class(void); #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" /* 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) */ #define OAUTH_REGEX "/(oauth_[a-z_-]*)=(?:\"([^\"]*)\"|([^,]*))/" #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-2.0.7/INSTALL0000644000175000001440000000042513731057347012550 0ustar mikeusersThis extension needs to be compiled and enabled in your PHP installation. Basic instructions: 1) phpize 2) ./configure 3) make && make install For Debian/Ubuntu users: The following packages need to be installed before running the steps above: 1) php5-dev 2) libpcre3-dev oauth-2.0.7/LICENSE0000644000175000001440000000304013731057347012520 0ustar mikeusersSoftware 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. oauth-2.0.7/README.md0000644000175000001440000000017713731057347013002 0ustar mikeusers# pecl-web_services-oauth oauth consumer extension You probably shouldn't be using this extension. This is only for OAuth v1. oauth-2.0.7/TODO0000644000175000001440000000102613731057347012205 0ustar mikeusers- Respect param precedence, * This ext 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 - Add tests * need there be anymore said? - Allow runtime setting of Expect header for POST requests * Don't know if always disabling the Expect header is going to have a big enough impact, if it does, we'll need to allow setting it dynamically for API's which can't handle it properly