├── .DS_Store
├── README.md
├── tweets.php
├── tweets.txt
└── twitteroauth
├── .DS_Store
├── .gitignore
├── LICENSE
├── README.md
├── _notes
└── dwsync.xml
├── callback.php
├── clearsessions.php
├── config-sample.php
├── connect.php
├── html.inc
├── images
├── _notes
│ └── dwsync.xml
├── darker.png
└── lighter.png
├── index.php
├── redirect.php
├── test.php
└── twitteroauth
├── .DS_Store
├── OAuth.php
├── _notes
└── dwsync.xml
└── twitteroauth.php
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewbiggart/latest-tweets-php-o-auth/03a0a2ddcc72ff174fced2c6b8240416f4118e42/.DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | latest-tweets-php-o-auth
2 | ========================
3 |
4 | Twitters API v1.0 has now been retired. Here's a way you can pull your tweets from Twitter using PHP and OAuth.
5 |
6 | Overview
7 | ========================
8 |
9 | - Tweets are cached to avoid exceeding Twitter’s limit of 150 requests for a user’s RSS and json feed per hour.
10 | - A fallback is provided in case the twitter feed fails to load. this can be edited to suit your needs.
11 | - A configuration parameter allows you to specify how many tweets are displayed
12 | - Dates can optionally be displayed in “Twitter style”, e.g. "12 minutes ago"
13 | - You can edit the HTML that wraps your tweets, tweet status and meta information
14 |
15 | Parameters
16 | ========================
17 |
18 | - Twitter handle.
19 | - Cache file location.
20 | - Tweets to display.
21 | - Ignore replies.
22 | - Include retweets.
23 | - Twitter style dates. ("16 hours ago")
24 | - Custom html.
25 |
26 | Usage
27 | ========================
28 |
29 | Firstly you will need to register your app / website with Twitters developer site. (https://dev.twitter.com) you will then get your consumer key, consumer secret, access token and your access token secret. You then need to add them to the script.
30 |
31 | You should edit the Twitter ID in the function call above before using the function (it appears at the very bottom of the code snippet).
32 |
33 | You probably also want to edit the location where the twitter feed is cached – by default it is written to the root level of your domain. To change the location, modify the $cache_file variable, or pass the new location as a function parameter.
34 |
35 | Feel free to edit any of the other parameters to suit your needs.
36 |
37 | Notes
38 | ========================
39 |
40 | Twitter feeds may contain UTF-8 characters. I have found that running PHP’s utf_decode method on tweets didn’t have the expected result, so my recommendation is to instead set the charset of your HTML page to UTF-8. Really we should all be doing this anyway. (http://www.w3.org/International/O-charset)
41 |
42 | Credits
43 | ========================
44 |
45 | I was orginally using Pixel Acres script (http://f6design.com/journal/2010/10/07/display-recent-twitter-tweets-using-php/). But since Twitter has retired API v1.0, the script no longer worked because it didn't include authentication. I have now modified the script to include authentication using API v1.1.
46 |
47 | The hashtag/username parsing in my example is from Get Twitter Tweets (http://snipplr.com/view/16221/get-twitter-tweets/) by gripnrip (http://snipplr.com/users/gripnrip/).
48 |
49 | My RSS parsing is based on replies in the forum discussion "embedding twitter tweets" on the Boagworld website. (http://boagworld.com/forum/comments.php?DiscussionID=4639)
50 |
51 | The file caching is based on the AddedBytes article "Caching output in PHP". (http://www.addedbytes.com/articles/for-beginners/output-caching-for-beginners/)
52 |
53 | Authentication with Twitter uses twitteroauth. (https://github.com/abraham/twitteroauth)
54 |
55 | License
56 | ========================
57 |
58 | The MIT License (MIT)
59 |
60 | Copyright (c) 2013 Andrew Biggart
61 |
62 | Permission is hereby granted, free of charge, to any person obtaining a copy
63 | of this software and associated documentation files (the "Software"), to deal
64 | in the Software without restriction, including without limitation the rights
65 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
66 | copies of the Software, and to permit persons to whom the Software is
67 | furnished to do so, subject to the following conditions:
68 |
69 | The above copyright notice and this permission notice shall be included in
70 | all copies or substantial portions of the Software.
71 |
72 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
77 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
78 | THE SOFTWARE.
79 |
--------------------------------------------------------------------------------
/tweets.php:
--------------------------------------------------------------------------------
1 | ',
68 | $twitter_wrap_close = '',
69 | $tweet_wrap_open = '
',
73 | $date_format = 'g:i A M jS', // Date formatting. (http://php.net/manual/en/function.date.php)
74 | $twitter_style_dates = true){ // Twitter style days. [about an hour ago] (Default : true)
75 |
76 | // Twitter keys (You'll need to visit https://dev.twitter.com and register to get these.
77 | $consumerkey = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
78 | $consumersecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
79 | $accesstoken = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
80 | $accesstokensecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
81 |
82 | // Seconds to cache feed (Default : 3 minutes).
83 | $cachetime = 60*3;
84 |
85 | // Time that the cache was last updtaed.
86 | $cache_file_created = ((file_exists($cache_file))) ? filemtime($cache_file) : 0;
87 |
88 | // A flag so we know if the feed was successfully parsed.
89 | $tweet_found = false;
90 |
91 | // Show cached version of tweets, if it's less than $cachetime.
92 | if (time() - $cachetime < $cache_file_created) {
93 | $tweet_found = true;
94 | // Display tweets from the cache.
95 | readfile($cache_file);
96 | } else {
97 |
98 | // Cache file not found, or old. Authenticae app.
99 | $connection = getConnectionWithAccessToken($consumerkey, $consumersecret, $accesstoken, $accesstokensecret);
100 |
101 | if($connection){
102 | // Get the latest tweets from Twitter
103 | $get_tweets = $connection->get("https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=".$twitter_user_id."&count=".$tweets_to_display."&include_rts=".$include_rts."&exclude_replies=".$ignore_replies);
104 |
105 | // Error check: Make sure there is at least one item.
106 | if (count($get_tweets)) {
107 |
108 | // Define tweet_count as zero
109 | $tweet_count = 0;
110 |
111 | // Start output buffering.
112 | ob_start();
113 |
114 | // Open the twitter wrapping element.
115 | $twitter_html = $twitter_wrap_open;
116 |
117 | // Iterate over tweets.
118 | foreach($get_tweets as $tweet) {
119 |
120 | $tweet_found = true;
121 | $tweet_count++;
122 | $tweet_desc = $tweet->text;
123 | // Add hyperlink html tags to any urls, twitter ids or hashtags in the tweet.
124 | $tweet_desc = preg_replace("/((http)+(s)?:\/\/[^<>\s]+)/i", "\\0", $tweet_desc );
125 | $tweet_desc = preg_replace("/[@]+([A-Za-z0-9-_]+)/", "\\0", $tweet_desc );
126 | $tweet_desc = preg_replace("/[#]+([A-Za-z0-9-_]+)/", "\\0", $tweet_desc );
127 |
128 |
129 | // replace t.co links with expanded link, if present
130 | $entities = $tweet->entities;
131 | if(!empty($entities->urls[0]->expanded_url)) {
132 | $tweet_desc = str_replace($entities->urls[0]->url, $entities->urls[0]->expanded_url, $tweet_desc);
133 | }
134 | $media_url = $entities->media[0]->media_url;
135 | if($media_url) {
136 | $img = "
";
137 | $twitter_html .= $img;
138 | }
139 |
140 |
141 | // Convert Tweet display time to a UNIX timestamp. Twitter timestamps are in UTC/GMT time.
142 | $tweet_time = strtotime($tweet->created_at);
143 |
144 | // Get Tweet ID
145 | $tweet_id = $tweet->id_str;
146 | if ($twitter_style_dates){
147 | // Current UNIX timestamp.
148 | $current_time = time();
149 | $time_diff = abs($current_time - $tweet_time);
150 | switch ($time_diff)
151 | {
152 | case ($time_diff < 60):
153 | $display_time = $time_diff.' seconds ago';
154 | break;
155 | case ($time_diff >= 60 && $time_diff < 3600):
156 | $min = floor($time_diff/60);
157 | $display_time = $min.' minutes ago';
158 | break;
159 | case ($time_diff >= 3600 && $time_diff < 86400):
160 | $hour = floor($time_diff/3600);
161 | $display_time = 'about '.$hour.' hour';
162 | if ($hour > 1){ $display_time .= 's'; }
163 | $display_time .= ' ago';
164 | break;
165 | default:
166 | $display_time = date($date_format,$tweet_time);
167 | break;
168 | }
169 | } else {
170 | $display_time = date($date_format,$tweet_time);
171 | }
172 |
173 | // Render the tweet.
174 | $twitter_html .= $tweet_wrap_open.html_entity_decode($tweet_desc).$meta_wrap_open.''.$display_time.''.$meta_wrap_close.$tweet_wrap_close;
175 |
176 | // If we have processed enough tweets, stop.
177 | if ($tweet_count >= $tweets_to_display){
178 | break;
179 | }
180 |
181 | }
182 |
183 | // Close the twitter wrapping element.
184 | $twitter_html .= $twitter_wrap_close;
185 | echo $twitter_html;
186 |
187 | // Generate a new cache file.
188 | $file = fopen($cache_file, 'w');
189 |
190 | // Save the contents of output buffer to the file, and flush the buffer.
191 | fwrite($file, ob_get_contents());
192 | fclose($file);
193 | ob_end_flush();
194 |
195 | }
196 |
197 | }
198 |
199 | }
200 |
201 | }
202 |
203 | // Display latest tweets. (Modify username to your Twitter handle)
204 | display_latest_tweets('andrew_biggart');
205 | ?>
206 |
--------------------------------------------------------------------------------
/tweets.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewbiggart/latest-tweets-php-o-auth/03a0a2ddcc72ff174fced2c6b8240416f4118e42/tweets.txt
--------------------------------------------------------------------------------
/twitteroauth/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewbiggart/latest-tweets-php-o-auth/03a0a2ddcc72ff174fced2c6b8240416f4118e42/twitteroauth/.DS_Store
--------------------------------------------------------------------------------
/twitteroauth/.gitignore:
--------------------------------------------------------------------------------
1 | config.php
2 |
--------------------------------------------------------------------------------
/twitteroauth/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009 Abraham Williams - http://abrah.am - abraham@poseurte.ch
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/twitteroauth/README.md:
--------------------------------------------------------------------------------
1 | TwitterOAuth
2 | ------------
3 |
4 | PHP library for working with Twitter's OAuth API.
5 |
6 | Flow Overview
7 | =============
8 |
9 | 1. Build TwitterOAuth object using client credentials.
10 | 2. Request temporary credentials from Twitter.
11 | 3. Build authorize URL for Twitter.
12 | 4. Redirect user to authorize URL.
13 | 5. User authorizes access and returns from Twitter.
14 | 6. Rebuild TwitterOAuth object with client credentials and temporary credentials.
15 | 7. Get token credentials from Twitter.
16 | 8. Rebuild TwitterOAuth object with client credentials and token credentials.
17 | 9. Query Twitter API.
18 |
19 | Terminology
20 | ===========
21 |
22 | The terminology has changed since 0.1.x to better match the draft-hammer-oauth IETF
23 | RFC. You can read that at http://tools.ietf.org/html/draft-hammer-oauth. Some of the
24 | terms will differ from those Twitter uses as well.
25 |
26 | client credentials - Consumer key/secret you get when registering an app with Twitter.
27 | temporary credentials - Previously known as the request token.
28 | token credentials - Previously known as the access token.
29 |
30 | Parameters
31 | ==========
32 |
33 | There are a number of parameters you can modify after creating a TwitterOAuth object.
34 |
35 | Switch an existing TwitterOAuth install to use version 1.1 of the API.
36 |
37 | $connection->$host = "https://api.twitter.com/1.1/";
38 |
39 | Custom useragent.
40 |
41 | $connection->useragent = 'Custom useragent string';
42 |
43 | Verify Twitters SSL certificate.
44 |
45 | $connection->ssl_verifypeer = TRUE;
46 |
47 | There are several more you can find in TwitterOAuth.php.
48 |
49 | Extended flow using example code
50 | ================================
51 |
52 | To use TwitterOAuth with the Twitter API you need *TwitterOAuth.php*, *OAuth.php* and
53 | client credentials. You can get client credentials by registering your application at
54 | [dev.twitter.com/apps](https://dev.twitter.com/apps).
55 |
56 | Users start out on connect.php which displays the "Sign in with Twitter" image hyperlinked
57 | to redirect.php. This button should be displayed on your homepage in your login section. The
58 | client credentials are saved in config.php as `CONSUMER_KEY` and `CONSUMER_SECRET`. You can
59 | save a static callback URL in the app settings page, in the config file or use a dynamic
60 | callback URL later in step 2. In example use https://example.com/callback.php.
61 |
62 | 1) When a user lands on redirect.php we build a new TwitterOAuth object using the client credentials.
63 | If you have your own configuration method feel free to use it instead of config.php.
64 |
65 | $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET); // Use config.php client credentials
66 | $connection = new TwitterOAuth('abc890', '123xyz');
67 |
68 | 2) Using the built $connection object you will ask Twitter for temporary credentials. The `oauth_callback` value is required.
69 |
70 | $temporary_credentials = $connection->getRequestToken(OAUTH_CALLBACK); // Use config.php callback URL.
71 |
72 | 3) Now that we have temporary credentials the user has to go to Twitter and authorize the app
73 | to access and updates their data. You can also pass a second parameter of FALSE to not use [Sign
74 | in with Twitter](https://dev.twitter.com/docs/auth/sign-twitter).
75 |
76 | $redirect_url = $connection->getAuthorizeURL($temporary_credentials); // Use Sign in with Twitter
77 | $redirect_url = $connection->getAuthorizeURL($temporary_credentials, FALSE);
78 |
79 | 4) You will now have a Twitter URL that you must send the user to.
80 |
81 | https://api.twitter.com/oauth/authenticate?oauth_token=xyz123
82 |
83 | 5) The user is now on twitter.com and may have to login. Once authenticated with Twitter they will
84 | will either have to click on allow/deny, or will be automatically redirected back to the callback.
85 |
86 | 6) Now that the user has returned to callback.php and allowed access we need to build a new
87 | TwitterOAuth object using the temporary credentials.
88 |
89 | $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $_SESSION['oauth_token'],
90 | $_SESSION['oauth_token_secret']);
91 |
92 | 7) Now we ask Twitter for long lasting token credentials. These are specific to the application
93 | and user and will act like password to make future requests. Normally the token credentials would
94 | get saved in your database but for this example we are just using sessions.
95 |
96 | $token_credentials = $connection->getAccessToken($_REQUEST['oauth_verifier']);
97 |
98 | 8) With the token credentials we build a new TwitterOAuth object.
99 |
100 | $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $token_credentials['oauth_token'],
101 | $token_credentials['oauth_token_secret']);
102 |
103 | 9) And finally we can make requests authenticated as the user. You can GET, POST, and DELETE API
104 | methods. Directly copy the path from the API documentation and add an array of any parameter
105 | you wish to include for the API method such as curser or in_reply_to_status_id.
106 |
107 | $account = $connection->get('account/verify_credentials');
108 | $status = $connection->post('statuses/update', array('status' => 'Text of status here', 'in_reply_to_status_id' => 123456));
109 | $status = $connection->delete('statuses/destroy/12345');
110 |
111 | Contributors
112 | ============
113 |
114 | * [Abraham Williams](https://twitter.com/abraham) - Main developer, current maintainer.
115 |
--------------------------------------------------------------------------------
/twitteroauth/_notes/dwsync.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/twitteroauth/callback.php:
--------------------------------------------------------------------------------
1 | getAccessToken($_REQUEST['oauth_verifier']);
24 |
25 | /* Save the access tokens. Normally these would be saved in a database for future use. */
26 | $_SESSION['access_token'] = $access_token;
27 |
28 | /* Remove no longer needed request tokens */
29 | unset($_SESSION['oauth_token']);
30 | unset($_SESSION['oauth_token_secret']);
31 |
32 | /* If HTTP response is 200 continue otherwise send to connect page to retry */
33 | if (200 == $connection->http_code) {
34 | /* The user has been verified and the access tokens can be saved for future use */
35 | $_SESSION['status'] = 'verified';
36 | header('Location: ./index.php');
37 | } else {
38 | /* Save HTTP status for error dialog on connnect page.*/
39 | header('Location: ./clearsessions.php');
40 | }
41 |
--------------------------------------------------------------------------------
/twitteroauth/clearsessions.php:
--------------------------------------------------------------------------------
1 | dev.twitter.com/apps';
14 | exit;
15 | }
16 |
17 | /* Build an image link to start the redirect process. */
18 | $content = '
';
19 |
20 | /* Include HTML to display on the page. */
21 | include('html.inc');
22 |
--------------------------------------------------------------------------------
/twitteroauth/html.inc:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 | Twitter OAuth in PHP
6 |
7 |
11 |
12 |
13 |
14 |
Welcome to a Twitter OAuth PHP example.
15 |
16 |
This site is a basic showcase of Twitters OAuth authentication method. If you are having issues try clearing your session.
17 |
18 |
19 | Links:
20 | Source Code &
21 | Documentation |
22 | Contact @abraham
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | '.$status_text.''; ?>
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/twitteroauth/images/_notes/dwsync.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/twitteroauth/images/darker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewbiggart/latest-tweets-php-o-auth/03a0a2ddcc72ff174fced2c6b8240416f4118e42/twitteroauth/images/darker.png
--------------------------------------------------------------------------------
/twitteroauth/images/lighter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewbiggart/latest-tweets-php-o-auth/03a0a2ddcc72ff174fced2c6b8240416f4118e42/twitteroauth/images/lighter.png
--------------------------------------------------------------------------------
/twitteroauth/index.php:
--------------------------------------------------------------------------------
1 | get('account/verify_credentials');
24 |
25 | /* Some example calls */
26 | //$connection->get('users/show', array('screen_name' => 'abraham'));
27 | //$connection->post('statuses/update', array('status' => date(DATE_RFC822)));
28 | //$connection->post('statuses/destroy', array('id' => 5437877770));
29 | //$connection->post('friendships/create', array('id' => 9436992));
30 | //$connection->post('friendships/destroy', array('id' => 9436992));
31 |
32 | /* Include HTML to display on the page */
33 | include('html.inc');
34 |
--------------------------------------------------------------------------------
/twitteroauth/redirect.php:
--------------------------------------------------------------------------------
1 | getRequestToken(OAUTH_CALLBACK);
13 |
14 | /* Save temporary credentials to session. */
15 | $_SESSION['oauth_token'] = $token = $request_token['oauth_token'];
16 | $_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret'];
17 |
18 | /* If last connection failed don't display authorization link. */
19 | switch ($connection->http_code) {
20 | case 200:
21 | /* Build authorize URL and redirect user to Twitter. */
22 | $url = $connection->getAuthorizeURL($token);
23 | header('Location: ' . $url);
24 | break;
25 | default:
26 | /* Show notification if something went wrong. */
27 | echo 'Could not connect to Twitter. Refresh the page or try again later.';
28 | }
29 |
--------------------------------------------------------------------------------
/twitteroauth/test.php:
--------------------------------------------------------------------------------
1 | get('account/rate_limit_status');
24 | echo "Current API hits remaining: {$content->remaining_hits}.";
25 |
26 | /* Get logged in user to help with tests. */
27 | $user = $connection->get('account/verify_credentials');
28 |
29 | $active = FALSE;
30 | if (empty($active) || empty($_GET['confirmed']) || $_GET['confirmed'] !== 'TRUE') {
31 | echo 'Warning! This page will make many requests to Twitter.
';
32 | echo 'Performing these test might max out your rate limit.
';
33 | echo 'Statuses/DMs will be created and deleted. Accounts will be un/followed.
';
34 | echo 'Profile information/design will be changed.
';
35 | echo 'USE A DEV ACCOUNT!
';
36 | echo 'Before use you must set $active = TRUE in test.php
';
37 | echo 'Continue or go back.';
38 | exit;
39 | }
40 |
41 | function twitteroauth_row($method, $response, $http_code, $parameters = '') {
42 | echo '';
43 | echo "{$method} | ";
44 | switch ($http_code) {
45 | case '200':
46 | case '304':
47 | $color = 'green';
48 | break;
49 | case '400':
50 | case '401':
51 | case '403':
52 | case '404':
53 | case '406':
54 | $color = 'red';
55 | break;
56 | case '500':
57 | case '502':
58 | case '503':
59 | $color = 'orange';
60 | break;
61 | default:
62 | $color = 'grey';
63 | }
64 | echo "{$http_code} | ";
65 | if (!is_string($response)) {
66 | $response = print_r($response, TRUE);
67 | }
68 | if (!is_string($parameters)) {
69 | $parameters = print_r($parameters, TRUE);
70 | }
71 | echo '', strlen($response), ' | ';
72 | echo '', $parameters, ' | ';
73 | echo '
';
74 | echo '', substr($response, 0, 400), '... | ';
75 | echo '
';
76 |
77 | }
78 |
79 | function twitteroauth_header($header) {
80 | echo '', $header, ' |
';
81 | }
82 |
83 | /* Start table. */
84 | echo '
';
85 | echo '';
86 | echo '';
87 | echo 'API Method | ';
88 | echo 'HTTP Code | ';
89 | echo 'Response Length | ';
90 | echo 'Parameters | ';
91 | echo '
';
92 | echo 'Response Snippet | ';
93 | echo '
';
94 |
95 | /**
96 | * Help Methods.
97 | */
98 | twitteroauth_header('Help Methods');
99 |
100 | /* help/test */
101 | twitteroauth_row('help/test', $connection->get('help/test'), $connection->http_code);
102 |
103 |
104 | /**
105 | * Timeline Methods.
106 | */
107 | twitteroauth_header('Timeline Methods');
108 |
109 | /* statuses/public_timeline */
110 | twitteroauth_row('statuses/public_timeline', $connection->get('statuses/public_timeline'), $connection->http_code);
111 |
112 | /* statuses/public_timeline */
113 | twitteroauth_row('statuses/home_timeline', $connection->get('statuses/home_timeline'), $connection->http_code);
114 |
115 | /* statuses/friends_timeline */
116 | twitteroauth_row('statuses/friends_timeline', $connection->get('statuses/friends_timeline'), $connection->http_code);
117 |
118 | /* statuses/user_timeline */
119 | twitteroauth_row('statuses/user_timeline', $connection->get('statuses/user_timeline'), $connection->http_code);
120 |
121 | /* statuses/mentions */
122 | twitteroauth_row('statuses/mentions', $connection->get('statuses/mentions'), $connection->http_code);
123 |
124 | /* statuses/retweeted_by_me */
125 | twitteroauth_row('statuses/retweeted_by_me', $connection->get('statuses/retweeted_by_me'), $connection->http_code);
126 |
127 | /* statuses/retweeted_to_me */
128 | twitteroauth_row('statuses/retweeted_to_me', $connection->get('statuses/retweeted_to_me'), $connection->http_code);
129 |
130 | /* statuses/retweets_of_me */
131 | twitteroauth_row('statuses/retweets_of_me', $connection->get('statuses/retweets_of_me'), $connection->http_code);
132 |
133 |
134 | /**
135 | * Status Methods.
136 | */
137 | twitteroauth_header('Status Methods');
138 |
139 | /* statuses/update */
140 | date_default_timezone_set('GMT');
141 | $parameters = array('status' => date(DATE_RFC822));
142 | $status = $connection->post('statuses/update', $parameters);
143 | twitteroauth_row('statuses/update', $status, $connection->http_code, $parameters);
144 |
145 | /* statuses/show */
146 | $method = "statuses/show/{$status->id}";
147 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
148 |
149 | /* statuses/destroy */
150 | $method = "statuses/destroy/{$status->id}";
151 | twitteroauth_row($method, $connection->delete($method), $connection->http_code);
152 |
153 | /* statuses/retweet */
154 | $method = 'statuses/retweet/6242973112';
155 | twitteroauth_row($method, $connection->post($method), $connection->http_code);
156 |
157 | /* statuses/retweets */
158 | $method = 'statuses/retweets/6242973112';
159 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
160 |
161 |
162 | /**
163 | * User Methods.
164 | */
165 | twitteroauth_header('User Methods');
166 |
167 | /* users/show */
168 | $method = 'users/show/27831060';
169 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
170 |
171 | /* users/search */
172 | $parameters = array('q' => 'oauth');
173 | twitteroauth_row('users/search', $connection->get('users/search', $parameters), $connection->http_code, $parameters);
174 |
175 | /* statuses/friends */
176 | $method = 'statuses/friends/27831060';
177 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
178 |
179 | /* statuses/followers */
180 | $method = 'statuses/followers/27831060';
181 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
182 |
183 |
184 | /**
185 | * List Methods.
186 | */
187 | twitteroauth_header('List Methods');
188 |
189 | /* POST lists */
190 | $method = "{$user->screen_name}/lists";
191 | $parameters = array('name' => 'Twitter OAuth');
192 | $list = $connection->post($method, $parameters);
193 | twitteroauth_row($method, $list, $connection->http_code, $parameters);
194 |
195 | /* POST lists id */
196 | $method = "{$user->screen_name}/lists/{$list->id}";
197 | $parameters = array('name' => 'Twitter OAuth List 2');
198 | $list = $connection->post($method, $parameters);
199 | twitteroauth_row($method, $list, $connection->http_code, $parameters);
200 |
201 | /* GET lists */
202 | $method = "{$user->screen_name}/lists";
203 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
204 |
205 | /* GET lists id */
206 | $method = "{$user->screen_name}/lists/{$list->id}";
207 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
208 |
209 | /* DELETE list */
210 | $method = "{$user->screen_name}/lists/{$list->id}";
211 | twitteroauth_row($method, $connection->delete($method), $connection->http_code);
212 |
213 | /* GET list statuses */
214 | $method = "oauthlib/lists/4097351/statuses";
215 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
216 |
217 | /* GET list members */
218 | $method = "{$user->screen_name}/lists/memberships";
219 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
220 |
221 |
222 | /* GET list subscriptions */
223 | $method = "{$user->screen_name}/lists/subscriptions";
224 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
225 |
226 |
227 | /**
228 | * List Members Methods.
229 | */
230 | twitteroauth_header('List Members Methods');
231 |
232 | /* Create temp list for list member methods. */
233 | $method = "{$user->screen_name}/lists";
234 | $parameters = array('name' => 'Twitter OAuth Temp');
235 | $list = $connection->post($method, $parameters);
236 |
237 |
238 | /* POST list members */
239 | $parameters = array('id' => 27831060);
240 | $method = "{$user->screen_name}/{$list->id}/members";
241 | twitteroauth_row($method, $connection->post($method, $parameters), $connection->http_code, $parameters);
242 |
243 | /* GET list members */
244 | $method = "{$user->screen_name}/{$list->id}/members";
245 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
246 |
247 | /* GET list members id */
248 | $method = "{$user->screen_name}/{$list->id}/members/27831060";
249 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
250 |
251 | /* DELETE list members */
252 | $parameters = array('id' => 27831060);
253 | $method = "{$user->screen_name}/{$list->id}/members";
254 | twitteroauth_row($method, $connection->delete($method, $parameters), $connection->http_code, $parameters);
255 |
256 | /* Delete the temp list */
257 | $method = "{$user->screen_name}/lists/{$list->id}";
258 | $connection->delete($method);
259 |
260 |
261 | /**
262 | * List Subscribers Methods.
263 | */
264 | twitteroauth_header('List Subscribers Methods');
265 |
266 |
267 | /* POST list subscribers */
268 | $method = 'oauthlib/test-list/subscribers';
269 | twitteroauth_row($method, $connection->post($method), $connection->http_code);
270 |
271 | /* GET list subscribers */
272 | $method = 'oauthlib/test-list/subscribers';
273 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
274 |
275 | /* GET list subscribers id */
276 | $method = "oauthlib/test-list/subscribers/{$user->id}";
277 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
278 |
279 | /* DELETE list subscribers */
280 | $method = 'oauthlib/test-list/subscribers';
281 | twitteroauth_row($method, $connection->delete($method), $connection->http_code);
282 |
283 |
284 | /**
285 | * Direct Message Methdos.
286 | */
287 | twitteroauth_header('Direct Message Methods');
288 |
289 | /* direct_messages/new */
290 | $parameters = array('user_id' => $user->id, 'text' => 'Testing out @oauthlib code');
291 | $method = 'direct_messages/new';
292 | $dm = $connection->post($method, $parameters);
293 | twitteroauth_row($method, $dm, $connection->http_code, $parameters);
294 |
295 | /* direct_messages */
296 | $method = 'direct_messages';
297 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
298 |
299 | /* direct_messages/sent */
300 | $method = 'direct_messages/sent';
301 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
302 |
303 | /* direct_messages/sent */
304 | $method = "direct_messages/destroy/{$dm->id}";
305 | twitteroauth_row($method, $connection->delete($method), $connection->http_code);
306 |
307 |
308 | /**
309 | * Friendships Methods.
310 | */
311 | twitteroauth_header('Friendships Methods');
312 |
313 | /* friendships/create */
314 | $method = 'friendships/create/93915746';
315 | twitteroauth_row($method, $connection->post($method), $connection->http_code);
316 |
317 | /* friendships/show */
318 | $parameters = array('target_id' => 27831060);
319 | $method = 'friendships/show';
320 | twitteroauth_row($method, $connection->get($method, $parameters), $connection->http_code, $parameters);
321 |
322 | /* friendships/destroy */
323 | $method = 'friendships/destroy/93915746';
324 | twitteroauth_row($method, $connection->post($method), $connection->http_code);
325 |
326 |
327 | /**
328 | * Social Graph Methods.
329 | */
330 | twitteroauth_header('Social Graph Methods');
331 |
332 | /* friends/ids */
333 | $method = 'friends/ids';
334 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
335 |
336 | /* friends/ids */
337 | $method = 'friends/ids';
338 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
339 |
340 |
341 | /**
342 | * Account Methods.
343 | */
344 | twitteroauth_header('Account Methods');
345 |
346 | /* account/verify_credentials */
347 | $method = 'account/verify_credentials';
348 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
349 |
350 | /* account/rate_limit_status */
351 | $method = 'account/rate_limit_status';
352 | twitteroauth_row($method, $connection->get($method), $connection->http_code);
353 |
354 | /* account/update_profile_colors */
355 | $parameters = array('profile_background_color' => 'fff');
356 | $method = 'account/update_profile_colors';
357 | twitteroauth_row($method, $connection->post($method, $parameters), $connection->http_code, $parameters);
358 |
359 | /* account/update_profile */
360 | $parameters = array('location' => 'Teh internets');
361 | $method = 'account/update_profile';
362 | twitteroauth_row($method, $connection->post($method, $parameters), $connection->http_code, $parameters);
363 |
364 |
365 |
366 |
367 | /**
368 | * OAuth Methods.
369 | */
370 | twitteroauth_header('OAuth Methods');
371 |
372 | /* oauth/request_token */
373 | $oauth = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
374 | twitteroauth_row('oauth/reqeust_token', $oauth->getRequestToken(), $oauth->http_code);
375 |
--------------------------------------------------------------------------------
/twitteroauth/twitteroauth/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewbiggart/latest-tweets-php-o-auth/03a0a2ddcc72ff174fced2c6b8240416f4118e42/twitteroauth/twitteroauth/.DS_Store
--------------------------------------------------------------------------------
/twitteroauth/twitteroauth/OAuth.php:
--------------------------------------------------------------------------------
1 | key = $key;
16 | $this->secret = $secret;
17 | $this->callback_url = $callback_url;
18 | }
19 |
20 | function __toString() {
21 | return "OAuthConsumer[key=$this->key,secret=$this->secret]";
22 | }
23 | }
24 |
25 | class OAuthToken {
26 | // access tokens and request tokens
27 | public $key;
28 | public $secret;
29 |
30 | /**
31 | * key = the token
32 | * secret = the token secret
33 | */
34 | function __construct($key, $secret) {
35 | $this->key = $key;
36 | $this->secret = $secret;
37 | }
38 |
39 | /**
40 | * generates the basic string serialization of a token that a server
41 | * would respond to request_token and access_token calls with
42 | */
43 | function to_string() {
44 | return "oauth_token=" .
45 | OAuthUtil::urlencode_rfc3986($this->key) .
46 | "&oauth_token_secret=" .
47 | OAuthUtil::urlencode_rfc3986($this->secret);
48 | }
49 |
50 | function __toString() {
51 | return $this->to_string();
52 | }
53 | }
54 |
55 | /**
56 | * A class for implementing a Signature Method
57 | * See section 9 ("Signing Requests") in the spec
58 | */
59 | abstract class OAuthSignatureMethod {
60 | /**
61 | * Needs to return the name of the Signature Method (ie HMAC-SHA1)
62 | * @return string
63 | */
64 | abstract public function get_name();
65 |
66 | /**
67 | * Build up the signature
68 | * NOTE: The output of this function MUST NOT be urlencoded.
69 | * the encoding is handled in OAuthRequest when the final
70 | * request is serialized
71 | * @param OAuthRequest $request
72 | * @param OAuthConsumer $consumer
73 | * @param OAuthToken $token
74 | * @return string
75 | */
76 | abstract public function build_signature($request, $consumer, $token);
77 |
78 | /**
79 | * Verifies that a given signature is correct
80 | * @param OAuthRequest $request
81 | * @param OAuthConsumer $consumer
82 | * @param OAuthToken $token
83 | * @param string $signature
84 | * @return bool
85 | */
86 | public function check_signature($request, $consumer, $token, $signature) {
87 | $built = $this->build_signature($request, $consumer, $token);
88 | return $built == $signature;
89 | }
90 | }
91 |
92 | /**
93 | * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]
94 | * where the Signature Base String is the text and the key is the concatenated values (each first
95 | * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'
96 | * character (ASCII code 38) even if empty.
97 | * - Chapter 9.2 ("HMAC-SHA1")
98 | */
99 | class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {
100 | function get_name() {
101 | return "HMAC-SHA1";
102 | }
103 |
104 | public function build_signature($request, $consumer, $token) {
105 | $base_string = $request->get_signature_base_string();
106 | $request->base_string = $base_string;
107 |
108 | $key_parts = array(
109 | $consumer->secret,
110 | ($token) ? $token->secret : ""
111 | );
112 |
113 | $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
114 | $key = implode('&', $key_parts);
115 |
116 | return base64_encode(hash_hmac('sha1', $base_string, $key, true));
117 | }
118 | }
119 |
120 | /**
121 | * The PLAINTEXT method does not provide any security protection and SHOULD only be used
122 | * over a secure channel such as HTTPS. It does not use the Signature Base String.
123 | * - Chapter 9.4 ("PLAINTEXT")
124 | */
125 | class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod {
126 | public function get_name() {
127 | return "PLAINTEXT";
128 | }
129 |
130 | /**
131 | * oauth_signature is set to the concatenated encoded values of the Consumer Secret and
132 | * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is
133 | * empty. The result MUST be encoded again.
134 | * - Chapter 9.4.1 ("Generating Signatures")
135 | *
136 | * Please note that the second encoding MUST NOT happen in the SignatureMethod, as
137 | * OAuthRequest handles this!
138 | */
139 | public function build_signature($request, $consumer, $token) {
140 | $key_parts = array(
141 | $consumer->secret,
142 | ($token) ? $token->secret : ""
143 | );
144 |
145 | $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
146 | $key = implode('&', $key_parts);
147 | $request->base_string = $key;
148 |
149 | return $key;
150 | }
151 | }
152 |
153 | /**
154 | * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in
155 | * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for
156 | * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a
157 | * verified way to the Service Provider, in a manner which is beyond the scope of this
158 | * specification.
159 | * - Chapter 9.3 ("RSA-SHA1")
160 | */
161 | abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {
162 | public function get_name() {
163 | return "RSA-SHA1";
164 | }
165 |
166 | // Up to the SP to implement this lookup of keys. Possible ideas are:
167 | // (1) do a lookup in a table of trusted certs keyed off of consumer
168 | // (2) fetch via http using a url provided by the requester
169 | // (3) some sort of specific discovery code based on request
170 | //
171 | // Either way should return a string representation of the certificate
172 | protected abstract function fetch_public_cert(&$request);
173 |
174 | // Up to the SP to implement this lookup of keys. Possible ideas are:
175 | // (1) do a lookup in a table of trusted certs keyed off of consumer
176 | //
177 | // Either way should return a string representation of the certificate
178 | protected abstract function fetch_private_cert(&$request);
179 |
180 | public function build_signature($request, $consumer, $token) {
181 | $base_string = $request->get_signature_base_string();
182 | $request->base_string = $base_string;
183 |
184 | // Fetch the private key cert based on the request
185 | $cert = $this->fetch_private_cert($request);
186 |
187 | // Pull the private key ID from the certificate
188 | $privatekeyid = openssl_get_privatekey($cert);
189 |
190 | // Sign using the key
191 | $ok = openssl_sign($base_string, $signature, $privatekeyid);
192 |
193 | // Release the key resource
194 | openssl_free_key($privatekeyid);
195 |
196 | return base64_encode($signature);
197 | }
198 |
199 | public function check_signature($request, $consumer, $token, $signature) {
200 | $decoded_sig = base64_decode($signature);
201 |
202 | $base_string = $request->get_signature_base_string();
203 |
204 | // Fetch the public key cert based on the request
205 | $cert = $this->fetch_public_cert($request);
206 |
207 | // Pull the public key ID from the certificate
208 | $publickeyid = openssl_get_publickey($cert);
209 |
210 | // Check the computed signature against the one passed in the query
211 | $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
212 |
213 | // Release the key resource
214 | openssl_free_key($publickeyid);
215 |
216 | return $ok == 1;
217 | }
218 | }
219 |
220 | class OAuthRequest {
221 | private $parameters;
222 | private $http_method;
223 | private $http_url;
224 | // for debug purposes
225 | public $base_string;
226 | public static $version = '1.0';
227 | public static $POST_INPUT = 'php://input';
228 |
229 | function __construct($http_method, $http_url, $parameters=NULL) {
230 | @$parameters or $parameters = array();
231 | $parameters = array_merge( OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters);
232 | $this->parameters = $parameters;
233 | $this->http_method = $http_method;
234 | $this->http_url = $http_url;
235 | }
236 |
237 |
238 | /**
239 | * attempt to build up a request from what was passed to the server
240 | */
241 | public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {
242 | $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on")
243 | ? 'http'
244 | : 'https';
245 | @$http_url or $http_url = $scheme .
246 | '://' . $_SERVER['HTTP_HOST'] .
247 | ':' .
248 | $_SERVER['SERVER_PORT'] .
249 | $_SERVER['REQUEST_URI'];
250 | @$http_method or $http_method = $_SERVER['REQUEST_METHOD'];
251 |
252 | // We weren't handed any parameters, so let's find the ones relevant to
253 | // this request.
254 | // If you run XML-RPC or similar you should use this to provide your own
255 | // parsed parameter-list
256 | if (!$parameters) {
257 | // Find request headers
258 | $request_headers = OAuthUtil::get_headers();
259 |
260 | // Parse the query-string to find GET parameters
261 | $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']);
262 |
263 | // It's a POST request of the proper content-type, so parse POST
264 | // parameters and add those overriding any duplicates from GET
265 | if ($http_method == "POST"
266 | && @strstr($request_headers["Content-Type"],
267 | "application/x-www-form-urlencoded")
268 | ) {
269 | $post_data = OAuthUtil::parse_parameters(
270 | file_get_contents(self::$POST_INPUT)
271 | );
272 | $parameters = array_merge($parameters, $post_data);
273 | }
274 |
275 | // We have a Authorization-header with OAuth data. Parse the header
276 | // and add those overriding any duplicates from GET or POST
277 | if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") {
278 | $header_parameters = OAuthUtil::split_header(
279 | $request_headers['Authorization']
280 | );
281 | $parameters = array_merge($parameters, $header_parameters);
282 | }
283 |
284 | }
285 |
286 | return new OAuthRequest($http_method, $http_url, $parameters);
287 | }
288 |
289 | /**
290 | * pretty much a helper function to set up the request
291 | */
292 | public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {
293 | @$parameters or $parameters = array();
294 | $defaults = array("oauth_version" => OAuthRequest::$version,
295 | "oauth_nonce" => OAuthRequest::generate_nonce(),
296 | "oauth_timestamp" => OAuthRequest::generate_timestamp(),
297 | "oauth_consumer_key" => $consumer->key);
298 | if ($token)
299 | $defaults['oauth_token'] = $token->key;
300 |
301 | $parameters = array_merge($defaults, $parameters);
302 |
303 | return new OAuthRequest($http_method, $http_url, $parameters);
304 | }
305 |
306 | public function set_parameter($name, $value, $allow_duplicates = true) {
307 | if ($allow_duplicates && isset($this->parameters[$name])) {
308 | // We have already added parameter(s) with this name, so add to the list
309 | if (is_scalar($this->parameters[$name])) {
310 | // This is the first duplicate, so transform scalar (string)
311 | // into an array so we can add the duplicates
312 | $this->parameters[$name] = array($this->parameters[$name]);
313 | }
314 |
315 | $this->parameters[$name][] = $value;
316 | } else {
317 | $this->parameters[$name] = $value;
318 | }
319 | }
320 |
321 | public function get_parameter($name) {
322 | return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
323 | }
324 |
325 | public function get_parameters() {
326 | return $this->parameters;
327 | }
328 |
329 | public function unset_parameter($name) {
330 | unset($this->parameters[$name]);
331 | }
332 |
333 | /**
334 | * The request parameters, sorted and concatenated into a normalized string.
335 | * @return string
336 | */
337 | public function get_signable_parameters() {
338 | // Grab all parameters
339 | $params = $this->parameters;
340 |
341 | // Remove oauth_signature if present
342 | // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
343 | if (isset($params['oauth_signature'])) {
344 | unset($params['oauth_signature']);
345 | }
346 |
347 | return OAuthUtil::build_http_query($params);
348 | }
349 |
350 | /**
351 | * Returns the base string of this request
352 | *
353 | * The base string defined as the method, the url
354 | * and the parameters (normalized), each urlencoded
355 | * and the concated with &.
356 | */
357 | public function get_signature_base_string() {
358 | $parts = array(
359 | $this->get_normalized_http_method(),
360 | $this->get_normalized_http_url(),
361 | $this->get_signable_parameters()
362 | );
363 |
364 | $parts = OAuthUtil::urlencode_rfc3986($parts);
365 |
366 | return implode('&', $parts);
367 | }
368 |
369 | /**
370 | * just uppercases the http method
371 | */
372 | public function get_normalized_http_method() {
373 | return strtoupper($this->http_method);
374 | }
375 |
376 | /**
377 | * parses the url and rebuilds it to be
378 | * scheme://host/path
379 | */
380 | public function get_normalized_http_url() {
381 | $parts = parse_url($this->http_url);
382 |
383 | $port = @$parts['port'];
384 | $scheme = $parts['scheme'];
385 | $host = $parts['host'];
386 | $path = @$parts['path'];
387 |
388 | $port or $port = ($scheme == 'https') ? '443' : '80';
389 |
390 | if (($scheme == 'https' && $port != '443')
391 | || ($scheme == 'http' && $port != '80')) {
392 | $host = "$host:$port";
393 | }
394 | return "$scheme://$host$path";
395 | }
396 |
397 | /**
398 | * builds a url usable for a GET request
399 | */
400 | public function to_url() {
401 | $post_data = $this->to_postdata();
402 | $out = $this->get_normalized_http_url();
403 | if ($post_data) {
404 | $out .= '?'.$post_data;
405 | }
406 | return $out;
407 | }
408 |
409 | /**
410 | * builds the data one would send in a POST request
411 | */
412 | public function to_postdata() {
413 | return OAuthUtil::build_http_query($this->parameters);
414 | }
415 |
416 | /**
417 | * builds the Authorization: header
418 | */
419 | public function to_header($realm=null) {
420 | $first = true;
421 | if($realm) {
422 | $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"';
423 | $first = false;
424 | } else
425 | $out = 'Authorization: OAuth';
426 |
427 | $total = array();
428 | foreach ($this->parameters as $k => $v) {
429 | if (substr($k, 0, 5) != "oauth") continue;
430 | if (is_array($v)) {
431 | throw new OAuthException('Arrays not supported in headers');
432 | }
433 | $out .= ($first) ? ' ' : ',';
434 | $out .= OAuthUtil::urlencode_rfc3986($k) .
435 | '="' .
436 | OAuthUtil::urlencode_rfc3986($v) .
437 | '"';
438 | $first = false;
439 | }
440 | return $out;
441 | }
442 |
443 | public function __toString() {
444 | return $this->to_url();
445 | }
446 |
447 |
448 | public function sign_request($signature_method, $consumer, $token) {
449 | $this->set_parameter(
450 | "oauth_signature_method",
451 | $signature_method->get_name(),
452 | false
453 | );
454 | $signature = $this->build_signature($signature_method, $consumer, $token);
455 | $this->set_parameter("oauth_signature", $signature, false);
456 | }
457 |
458 | public function build_signature($signature_method, $consumer, $token) {
459 | $signature = $signature_method->build_signature($this, $consumer, $token);
460 | return $signature;
461 | }
462 |
463 | /**
464 | * util function: current timestamp
465 | */
466 | private static function generate_timestamp() {
467 | return time();
468 | }
469 |
470 | /**
471 | * util function: current nonce
472 | */
473 | private static function generate_nonce() {
474 | $mt = microtime();
475 | $rand = mt_rand();
476 |
477 | return md5($mt . $rand); // md5s look nicer than numbers
478 | }
479 | }
480 |
481 | class OAuthServer {
482 | protected $timestamp_threshold = 300; // in seconds, five minutes
483 | protected $version = '1.0'; // hi blaine
484 | protected $signature_methods = array();
485 |
486 | protected $data_store;
487 |
488 | function __construct($data_store) {
489 | $this->data_store = $data_store;
490 | }
491 |
492 | public function add_signature_method($signature_method) {
493 | $this->signature_methods[$signature_method->get_name()] =
494 | $signature_method;
495 | }
496 |
497 | // high level functions
498 |
499 | /**
500 | * process a request_token request
501 | * returns the request token on success
502 | */
503 | public function fetch_request_token(&$request) {
504 | $this->get_version($request);
505 |
506 | $consumer = $this->get_consumer($request);
507 |
508 | // no token required for the initial token request
509 | $token = NULL;
510 |
511 | $this->check_signature($request, $consumer, $token);
512 |
513 | // Rev A change
514 | $callback = $request->get_parameter('oauth_callback');
515 | $new_token = $this->data_store->new_request_token($consumer, $callback);
516 |
517 | return $new_token;
518 | }
519 |
520 | /**
521 | * process an access_token request
522 | * returns the access token on success
523 | */
524 | public function fetch_access_token(&$request) {
525 | $this->get_version($request);
526 |
527 | $consumer = $this->get_consumer($request);
528 |
529 | // requires authorized request token
530 | $token = $this->get_token($request, $consumer, "request");
531 |
532 | $this->check_signature($request, $consumer, $token);
533 |
534 | // Rev A change
535 | $verifier = $request->get_parameter('oauth_verifier');
536 | $new_token = $this->data_store->new_access_token($token, $consumer, $verifier);
537 |
538 | return $new_token;
539 | }
540 |
541 | /**
542 | * verify an api call, checks all the parameters
543 | */
544 | public function verify_request(&$request) {
545 | $this->get_version($request);
546 | $consumer = $this->get_consumer($request);
547 | $token = $this->get_token($request, $consumer, "access");
548 | $this->check_signature($request, $consumer, $token);
549 | return array($consumer, $token);
550 | }
551 |
552 | // Internals from here
553 | /**
554 | * version 1
555 | */
556 | private function get_version(&$request) {
557 | $version = $request->get_parameter("oauth_version");
558 | if (!$version) {
559 | // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present.
560 | // Chapter 7.0 ("Accessing Protected Ressources")
561 | $version = '1.0';
562 | }
563 | if ($version !== $this->version) {
564 | throw new OAuthException("OAuth version '$version' not supported");
565 | }
566 | return $version;
567 | }
568 |
569 | /**
570 | * figure out the signature with some defaults
571 | */
572 | private function get_signature_method(&$request) {
573 | $signature_method =
574 | @$request->get_parameter("oauth_signature_method");
575 |
576 | if (!$signature_method) {
577 | // According to chapter 7 ("Accessing Protected Ressources") the signature-method
578 | // parameter is required, and we can't just fallback to PLAINTEXT
579 | throw new OAuthException('No signature method parameter. This parameter is required');
580 | }
581 |
582 | if (!in_array($signature_method,
583 | array_keys($this->signature_methods))) {
584 | throw new OAuthException(
585 | "Signature method '$signature_method' not supported " .
586 | "try one of the following: " .
587 | implode(", ", array_keys($this->signature_methods))
588 | );
589 | }
590 | return $this->signature_methods[$signature_method];
591 | }
592 |
593 | /**
594 | * try to find the consumer for the provided request's consumer key
595 | */
596 | private function get_consumer(&$request) {
597 | $consumer_key = @$request->get_parameter("oauth_consumer_key");
598 | if (!$consumer_key) {
599 | throw new OAuthException("Invalid consumer key");
600 | }
601 |
602 | $consumer = $this->data_store->lookup_consumer($consumer_key);
603 | if (!$consumer) {
604 | throw new OAuthException("Invalid consumer");
605 | }
606 |
607 | return $consumer;
608 | }
609 |
610 | /**
611 | * try to find the token for the provided request's token key
612 | */
613 | private function get_token(&$request, $consumer, $token_type="access") {
614 | $token_field = @$request->get_parameter('oauth_token');
615 | $token = $this->data_store->lookup_token(
616 | $consumer, $token_type, $token_field
617 | );
618 | if (!$token) {
619 | throw new OAuthException("Invalid $token_type token: $token_field");
620 | }
621 | return $token;
622 | }
623 |
624 | /**
625 | * all-in-one function to check the signature on a request
626 | * should guess the signature method appropriately
627 | */
628 | private function check_signature(&$request, $consumer, $token) {
629 | // this should probably be in a different method
630 | $timestamp = @$request->get_parameter('oauth_timestamp');
631 | $nonce = @$request->get_parameter('oauth_nonce');
632 |
633 | $this->check_timestamp($timestamp);
634 | $this->check_nonce($consumer, $token, $nonce, $timestamp);
635 |
636 | $signature_method = $this->get_signature_method($request);
637 |
638 | $signature = $request->get_parameter('oauth_signature');
639 | $valid_sig = $signature_method->check_signature(
640 | $request,
641 | $consumer,
642 | $token,
643 | $signature
644 | );
645 |
646 | if (!$valid_sig) {
647 | throw new OAuthException("Invalid signature");
648 | }
649 | }
650 |
651 | /**
652 | * check that the timestamp is new enough
653 | */
654 | private function check_timestamp($timestamp) {
655 | if( ! $timestamp )
656 | throw new OAuthException(
657 | 'Missing timestamp parameter. The parameter is required'
658 | );
659 |
660 | // verify that timestamp is recentish
661 | $now = time();
662 | if (abs($now - $timestamp) > $this->timestamp_threshold) {
663 | throw new OAuthException(
664 | "Expired timestamp, yours $timestamp, ours $now"
665 | );
666 | }
667 | }
668 |
669 | /**
670 | * check that the nonce is not repeated
671 | */
672 | private function check_nonce($consumer, $token, $nonce, $timestamp) {
673 | if( ! $nonce )
674 | throw new OAuthException(
675 | 'Missing nonce parameter. The parameter is required'
676 | );
677 |
678 | // verify that the nonce is uniqueish
679 | $found = $this->data_store->lookup_nonce(
680 | $consumer,
681 | $token,
682 | $nonce,
683 | $timestamp
684 | );
685 | if ($found) {
686 | throw new OAuthException("Nonce already used: $nonce");
687 | }
688 | }
689 |
690 | }
691 |
692 | class OAuthDataStore {
693 | function lookup_consumer($consumer_key) {
694 | // implement me
695 | }
696 |
697 | function lookup_token($consumer, $token_type, $token) {
698 | // implement me
699 | }
700 |
701 | function lookup_nonce($consumer, $token, $nonce, $timestamp) {
702 | // implement me
703 | }
704 |
705 | function new_request_token($consumer, $callback = null) {
706 | // return a new token attached to this consumer
707 | }
708 |
709 | function new_access_token($token, $consumer, $verifier = null) {
710 | // return a new access token attached to this consumer
711 | // for the user associated with this token if the request token
712 | // is authorized
713 | // should also invalidate the request token
714 | }
715 |
716 | }
717 |
718 | class OAuthUtil {
719 | public static function urlencode_rfc3986($input) {
720 | if (is_array($input)) {
721 | return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input);
722 | } else if (is_scalar($input)) {
723 | return str_replace(
724 | '+',
725 | ' ',
726 | str_replace('%7E', '~', rawurlencode($input))
727 | );
728 | } else {
729 | return '';
730 | }
731 | }
732 |
733 |
734 | // This decode function isn't taking into consideration the above
735 | // modifications to the encoding process. However, this method doesn't
736 | // seem to be used anywhere so leaving it as is.
737 | public static function urldecode_rfc3986($string) {
738 | return urldecode($string);
739 | }
740 |
741 | // Utility function for turning the Authorization: header into
742 | // parameters, has to do some unescaping
743 | // Can filter out any non-oauth parameters if needed (default behaviour)
744 | public static function split_header($header, $only_allow_oauth_parameters = true) {
745 | $pattern = '/(([-_a-z]*)=("([^"]*)"|([^,]*)),?)/';
746 | $offset = 0;
747 | $params = array();
748 | while (preg_match($pattern, $header, $matches, PREG_OFFSET_CAPTURE, $offset) > 0) {
749 | $match = $matches[0];
750 | $header_name = $matches[2][0];
751 | $header_content = (isset($matches[5])) ? $matches[5][0] : $matches[4][0];
752 | if (preg_match('/^oauth_/', $header_name) || !$only_allow_oauth_parameters) {
753 | $params[$header_name] = OAuthUtil::urldecode_rfc3986($header_content);
754 | }
755 | $offset = $match[1] + strlen($match[0]);
756 | }
757 |
758 | if (isset($params['realm'])) {
759 | unset($params['realm']);
760 | }
761 |
762 | return $params;
763 | }
764 |
765 | // helper to try to sort out headers for people who aren't running apache
766 | public static function get_headers() {
767 | if (function_exists('apache_request_headers')) {
768 | // we need this to get the actual Authorization: header
769 | // because apache tends to tell us it doesn't exist
770 | $headers = apache_request_headers();
771 |
772 | // sanitize the output of apache_request_headers because
773 | // we always want the keys to be Cased-Like-This and arh()
774 | // returns the headers in the same case as they are in the
775 | // request
776 | $out = array();
777 | foreach( $headers AS $key => $value ) {
778 | $key = str_replace(
779 | " ",
780 | "-",
781 | ucwords(strtolower(str_replace("-", " ", $key)))
782 | );
783 | $out[$key] = $value;
784 | }
785 | } else {
786 | // otherwise we don't have apache and are just going to have to hope
787 | // that $_SERVER actually contains what we need
788 | $out = array();
789 | if( isset($_SERVER['CONTENT_TYPE']) )
790 | $out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
791 | if( isset($_ENV['CONTENT_TYPE']) )
792 | $out['Content-Type'] = $_ENV['CONTENT_TYPE'];
793 |
794 | foreach ($_SERVER as $key => $value) {
795 | if (substr($key, 0, 5) == "HTTP_") {
796 | // this is chaos, basically it is just there to capitalize the first
797 | // letter of every word that is not an initial HTTP and strip HTTP
798 | // code from przemek
799 | $key = str_replace(
800 | " ",
801 | "-",
802 | ucwords(strtolower(str_replace("_", " ", substr($key, 5))))
803 | );
804 | $out[$key] = $value;
805 | }
806 | }
807 | }
808 | return $out;
809 | }
810 |
811 | // This function takes a input like a=b&a=c&d=e and returns the parsed
812 | // parameters like this
813 | // array('a' => array('b','c'), 'd' => 'e')
814 | public static function parse_parameters( $input ) {
815 | if (!isset($input) || !$input) return array();
816 |
817 | $pairs = explode('&', $input);
818 |
819 | $parsed_parameters = array();
820 | foreach ($pairs as $pair) {
821 | $split = explode('=', $pair, 2);
822 | $parameter = OAuthUtil::urldecode_rfc3986($split[0]);
823 | $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : '';
824 |
825 | if (isset($parsed_parameters[$parameter])) {
826 | // We have already recieved parameter(s) with this name, so add to the list
827 | // of parameters with this name
828 |
829 | if (is_scalar($parsed_parameters[$parameter])) {
830 | // This is the first duplicate, so transform scalar (string) into an array
831 | // so we can add the duplicates
832 | $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]);
833 | }
834 |
835 | $parsed_parameters[$parameter][] = $value;
836 | } else {
837 | $parsed_parameters[$parameter] = $value;
838 | }
839 | }
840 | return $parsed_parameters;
841 | }
842 |
843 | public static function build_http_query($params) {
844 | if (!$params) return '';
845 |
846 | // Urlencode both keys and values
847 | $keys = OAuthUtil::urlencode_rfc3986(array_keys($params));
848 | $values = OAuthUtil::urlencode_rfc3986(array_values($params));
849 | $params = array_combine($keys, $values);
850 |
851 | // Parameters are sorted by name, using lexicographical byte value ordering.
852 | // Ref: Spec: 9.1.1 (1)
853 | uksort($params, 'strcmp');
854 |
855 | $pairs = array();
856 | foreach ($params as $parameter => $value) {
857 | if (is_array($value)) {
858 | // If two or more parameters share the same name, they are sorted by their value
859 | // Ref: Spec: 9.1.1 (1)
860 | natsort($value);
861 | foreach ($value as $duplicate_value) {
862 | $pairs[] = $parameter . '=' . $duplicate_value;
863 | }
864 | } else {
865 | $pairs[] = $parameter . '=' . $value;
866 | }
867 | }
868 | // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61)
869 | // Each name-value pair is separated by an '&' character (ASCII code 38)
870 | return implode('&', $pairs);
871 | }
872 | }
873 |
--------------------------------------------------------------------------------
/twitteroauth/twitteroauth/_notes/dwsync.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/twitteroauth/twitteroauth/twitteroauth.php:
--------------------------------------------------------------------------------
1 | http_status; }
54 | function lastAPICall() { return $this->last_api_call; }
55 |
56 | /**
57 | * construct TwitterOAuth object
58 | */
59 | function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) {
60 | $this->sha1_method = new OAuthSignatureMethod_HMAC_SHA1();
61 | $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret);
62 | if (!empty($oauth_token) && !empty($oauth_token_secret)) {
63 | $this->token = new OAuthConsumer($oauth_token, $oauth_token_secret);
64 | } else {
65 | $this->token = NULL;
66 | }
67 | }
68 |
69 |
70 | /**
71 | * Get a request_token from Twitter
72 | *
73 | * @returns a key/value array containing oauth_token and oauth_token_secret
74 | */
75 | function getRequestToken($oauth_callback) {
76 | $parameters = array();
77 | $parameters['oauth_callback'] = $oauth_callback;
78 | $request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters);
79 | $token = OAuthUtil::parse_parameters($request);
80 | $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
81 | return $token;
82 | }
83 |
84 | /**
85 | * Get the authorize URL
86 | *
87 | * @returns a string
88 | */
89 | function getAuthorizeURL($token, $sign_in_with_twitter = TRUE) {
90 | if (is_array($token)) {
91 | $token = $token['oauth_token'];
92 | }
93 | if (empty($sign_in_with_twitter)) {
94 | return $this->authorizeURL() . "?oauth_token={$token}";
95 | } else {
96 | return $this->authenticateURL() . "?oauth_token={$token}";
97 | }
98 | }
99 |
100 | /**
101 | * Exchange request token and secret for an access token and
102 | * secret, to sign API calls.
103 | *
104 | * @returns array("oauth_token" => "the-access-token",
105 | * "oauth_token_secret" => "the-access-secret",
106 | * "user_id" => "9436992",
107 | * "screen_name" => "abraham")
108 | */
109 | function getAccessToken($oauth_verifier) {
110 | $parameters = array();
111 | $parameters['oauth_verifier'] = $oauth_verifier;
112 | $request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters);
113 | $token = OAuthUtil::parse_parameters($request);
114 | $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
115 | return $token;
116 | }
117 |
118 | /**
119 | * One time exchange of username and password for access token and secret.
120 | *
121 | * @returns array("oauth_token" => "the-access-token",
122 | * "oauth_token_secret" => "the-access-secret",
123 | * "user_id" => "9436992",
124 | * "screen_name" => "abraham",
125 | * "x_auth_expires" => "0")
126 | */
127 | function getXAuthToken($username, $password) {
128 | $parameters = array();
129 | $parameters['x_auth_username'] = $username;
130 | $parameters['x_auth_password'] = $password;
131 | $parameters['x_auth_mode'] = 'client_auth';
132 | $request = $this->oAuthRequest($this->accessTokenURL(), 'POST', $parameters);
133 | $token = OAuthUtil::parse_parameters($request);
134 | $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
135 | return $token;
136 | }
137 |
138 | /**
139 | * GET wrapper for oAuthRequest.
140 | */
141 | function get($url, $parameters = array()) {
142 | $response = $this->oAuthRequest($url, 'GET', $parameters);
143 | if ($this->format === 'json' && $this->decode_json) {
144 | return json_decode($response);
145 | }
146 | return $response;
147 | }
148 |
149 | /**
150 | * POST wrapper for oAuthRequest.
151 | */
152 | function post($url, $parameters = array()) {
153 | $response = $this->oAuthRequest($url, 'POST', $parameters);
154 | if ($this->format === 'json' && $this->decode_json) {
155 | return json_decode($response);
156 | }
157 | return $response;
158 | }
159 |
160 | /**
161 | * DELETE wrapper for oAuthReqeust.
162 | */
163 | function delete($url, $parameters = array()) {
164 | $response = $this->oAuthRequest($url, 'DELETE', $parameters);
165 | if ($this->format === 'json' && $this->decode_json) {
166 | return json_decode($response);
167 | }
168 | return $response;
169 | }
170 |
171 | /**
172 | * Format and sign an OAuth / API request
173 | */
174 | function oAuthRequest($url, $method, $parameters) {
175 | if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) {
176 | $url = "{$this->host}{$url}.{$this->format}";
177 | }
178 | $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters);
179 | $request->sign_request($this->sha1_method, $this->consumer, $this->token);
180 | switch ($method) {
181 | case 'GET':
182 | return $this->http($request->to_url(), 'GET');
183 | default:
184 | return $this->http($request->get_normalized_http_url(), $method, $request->to_postdata());
185 | }
186 | }
187 |
188 | /**
189 | * Make an HTTP request
190 | *
191 | * @return API results
192 | */
193 | function http($url, $method, $postfields = NULL) {
194 | $this->http_info = array();
195 | $ci = curl_init();
196 | /* Curl settings */
197 | curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent);
198 | curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout);
199 | curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout);
200 | curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
201 | curl_setopt($ci, CURLOPT_HTTPHEADER, array('Expect:'));
202 | curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer);
203 | curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader'));
204 | curl_setopt($ci, CURLOPT_HEADER, FALSE);
205 |
206 | switch ($method) {
207 | case 'POST':
208 | curl_setopt($ci, CURLOPT_POST, TRUE);
209 | if (!empty($postfields)) {
210 | curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
211 | }
212 | break;
213 | case 'DELETE':
214 | curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
215 | if (!empty($postfields)) {
216 | $url = "{$url}?{$postfields}";
217 | }
218 | }
219 |
220 | curl_setopt($ci, CURLOPT_URL, $url);
221 | $response = curl_exec($ci);
222 | $this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
223 | $this->http_info = array_merge($this->http_info, curl_getinfo($ci));
224 | $this->url = $url;
225 | curl_close ($ci);
226 | return $response;
227 | }
228 |
229 | /**
230 | * Get the header info to store.
231 | */
232 | function getHeader($ch, $header) {
233 | $i = strpos($header, ':');
234 | if (!empty($i)) {
235 | $key = str_replace('-', '_', strtolower(substr($header, 0, $i)));
236 | $value = trim(substr($header, $i + 2));
237 | $this->http_header[$key] = $value;
238 | }
239 | return strlen($header);
240 | }
241 | }
242 |
--------------------------------------------------------------------------------