Mercurial > pidgin-twitter
comparison twitter_api.c @ 355:0fe895195132
implement OAuth authentication.
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Thu, 26 Aug 2010 15:05:33 +0900 |
parents | ff078879e68e |
children | 732de90812d8 |
comparison
equal
deleted
inserted
replaced
354:ff078879e68e | 355:0fe895195132 |
---|---|
11 static void free_status(status_t *st); | 11 static void free_status(status_t *st); |
12 static gboolean is_posted_message(status_t *status, guint64 lastid); | 12 static gboolean is_posted_message(status_t *status, guint64 lastid); |
13 static void get_status_with_api_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message); | 13 static void get_status_with_api_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message); |
14 static void post_status_with_api_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message); | 14 static void post_status_with_api_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message); |
15 | 15 |
16 /* oauth */ | |
17 #define TYPE_GET 0 | |
18 #define TYPE_POST 1 | |
19 | |
20 typedef struct oauth_request { | |
21 char *url; | |
22 char *c_key; | |
23 char *c_sec; | |
24 char *a_key; | |
25 char *a_sec; | |
26 char *verifier; | |
27 char *status; | |
28 PurpleConversation *conv; | |
29 guint64 msgid; | |
30 int count; | |
31 int type; | |
32 gboolean notoken; | |
33 } oauth_request_t; | |
34 | |
35 char *make_oauth_get(oauth_request_t *oauth_req); | |
36 char *make_oauth_post(oauth_request_t *auth_req); | |
37 static void oauth_setup_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message); | |
38 | |
39 | |
16 #ifdef _WIN32 | 40 #ifdef _WIN32 |
17 extern gboolean blink_state; | 41 extern gboolean blink_state; |
18 extern gboolean blink_modified; | 42 extern gboolean blink_modified; |
19 #endif | 43 #endif |
20 | 44 |
21 extern guint64 reply_to_msgid; | 45 extern guint64 reply_to_msgid; |
22 extern PurpleAccount *account_for_twitter; | 46 extern PurpleAccount *account_for_twitter; |
47 | |
48 char *request_token_url = "http://twitter.com/oauth/request_token"; | |
49 char *access_token_url = "http://twitter.com/oauth/access_token"; | |
50 char *authorize_url = "http://twitter.com/oauth/authorize"; | |
51 | |
52 char *c_key = "wrD3WGIh2P31d3fIjRkfcw"; | |
53 char *c_sec = "ZEhViGY8P5IPjwgV8EVOkdjHhShRAZ9yhlYw0ZDXU"; | |
54 char *SAMPLE_NONCE = "0123456789abcdefghijk"; | |
55 | |
56 void | |
57 oauth_access_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, | |
58 const gchar *url_text, size_t len, | |
59 const gchar *error_message) | |
60 { | |
61 char *f = NULL, *e = NULL; | |
62 oauth_request_t *oauth_req = (oauth_request_t *)user_data; | |
63 | |
64 /* separate key and secret */ | |
65 f = strstr(url_text, "oauth_token="); | |
66 if(!f) | |
67 return; | |
68 e = strstr(f, "&"); | |
69 if(!e) | |
70 return; | |
71 g_free(oauth_req->a_key); | |
72 oauth_req->a_key = g_strndup(f+12, e-f-12); | |
73 | |
74 f = strstr(e+1, "oauth_token_secret="); | |
75 if(!f) | |
76 return; | |
77 e = strstr(f, "&"); | |
78 if(!e) | |
79 return; | |
80 g_free(oauth_req->a_sec); | |
81 oauth_req->a_sec = g_strndup(f+19, e-f-19); | |
82 | |
83 /* write a_key and a_sec to prefs */ | |
84 purple_prefs_set_string(OPT_AKEY_TWITTER, oauth_req->a_key); | |
85 purple_prefs_set_string(OPT_ASEC_TWITTER, oauth_req->a_sec); | |
86 | |
87 /* invoke fetch xxx */ | |
88 g_usleep(3*1000000); /* wait for server configuration */ | |
89 get_status_with_api((gpointer)oauth_req->conv); | |
90 | |
91 /* all done */ | |
92 g_free(oauth_req->url); | |
93 g_free(oauth_req->c_key); | |
94 g_free(oauth_req->c_sec); | |
95 g_free(oauth_req->a_key); | |
96 g_free(oauth_req->a_sec); | |
97 g_free(oauth_req); | |
98 } | |
99 | |
100 | |
101 void | |
102 pin_dialog_ok_cb(gpointer data, char *pin) | |
103 { | |
104 char *oauth = NULL; | |
105 char *request = NULL; | |
106 oauth_request_t *oauth_req = (oauth_request_t *)data; | |
107 /* | |
108 request URL:http://twitter.com/oauth/access_token? | |
109 oauth_consumer_key=wrD3WGIh2P31d3fIjRkfcw& | |
110 oauth_nonce=QUzhkt0AO3tjNrR& | |
111 oauth_signature_method=HMAC-SHA1& | |
112 oauth_timestamp=1282450223& | |
113 | |
114 oauth_token=VL126k8KRNXid7Q7ZHYHh05PuASunVaPzyzrozf14& | |
115 oauth_verifier=9772286& | |
116 oauth_version=1.0& | |
117 oauth_signature=OyBsxqWdsvLkV4LBnN8tMBnImVY%3D | |
118 */ | |
119 | |
120 /* access token*/ | |
121 g_free(oauth_req->url); | |
122 oauth_req->url = g_strdup(access_token_url); | |
123 oauth_req->verifier = g_strdup(pin); | |
124 oauth_req->type = TYPE_GET; | |
125 oauth_req->notoken = FALSE; | |
126 | |
127 twitter_debug("a_key=%s\n", oauth_req->a_key); | |
128 | |
129 oauth = make_oauth_get(oauth_req); | |
130 | |
131 request = g_strdup_printf("%s?%s", access_token_url, oauth); | |
132 twitter_debug("request=%s\n", request); | |
133 | |
134 purple_util_fetch_url_request(request, TRUE, | |
135 NULL, TRUE, NULL, TRUE, | |
136 oauth_access_cb, data); | |
137 g_free(oauth); | |
138 g_free(request); | |
139 } | |
140 | |
141 | |
142 static void | |
143 oauth_setup_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, | |
144 const gchar *url_text, size_t len, | |
145 const gchar *error_message) | |
146 { | |
147 char *f = NULL, *e = NULL; | |
148 oauth_request_t *oauth_req = (oauth_request_t *)user_data; | |
149 PurpleConversation *conv = oauth_req->conv; | |
150 PurpleAccount *account = purple_conversation_get_account(conv); | |
151 PurpleConnection *conn = purple_conversation_get_gc(conv); | |
152 | |
153 g_return_if_fail(url_text != NULL); | |
154 twitter_debug("len=%d\n", (int)len); | |
155 twitter_debug("url_text=%s\n", url_text); | |
156 | |
157 /* | |
158 HTTP-reply: | |
159 oauth_token=zKILrNcVPGRtUE6Rlh1KU6upYNJWW51mzt7btZx5Ac& | |
160 oauth_token_secret=EMD3u1piAKPsQnq44Its9f8WmIReYnUFcJIgd3niu4& | |
161 oauth_callback_confirmed=true | |
162 */ | |
163 /* separate key and secret */ | |
164 f = strstr(url_text, "oauth_token="); | |
165 if(!f) | |
166 return; | |
167 e = strstr(f, "&"); | |
168 if(!e) | |
169 return; | |
170 g_free(oauth_req->a_key); | |
171 oauth_req->a_key = g_strndup(f+12, e-f-12); | |
172 | |
173 f = strstr(e+1, "oauth_token_secret="); | |
174 if(!f) | |
175 return; | |
176 e = strstr(f, "&"); | |
177 if(!e) | |
178 return; | |
179 g_free(oauth_req->a_sec); | |
180 oauth_req->a_sec = g_strndup(f+19, e-f-19); | |
181 | |
182 /* redirect twitter's authorization url */ | |
183 char *uri = g_strdup_printf("%s?oauth_token=%s", authorize_url, oauth_req->a_key); | |
184 twitter_debug("auth uri=%s\n", uri); | |
185 purple_notify_uri(conn, uri); | |
186 | |
187 /* show dialog to wait PIN number*/ | |
188 purple_request_input(conn, | |
189 "PIN", | |
190 "Enter PIN", | |
191 "Press allow button in the browser, then enter the PIN to complete process.", | |
192 "", | |
193 FALSE, | |
194 FALSE, | |
195 NULL, | |
196 "OK", G_CALLBACK(pin_dialog_ok_cb), | |
197 "Cancel", NULL, | |
198 account, | |
199 NULL, | |
200 NULL, | |
201 user_data); | |
202 | |
203 g_free(uri); | |
204 } | |
205 | |
206 void | |
207 oauth_setup(gpointer data) | |
208 { | |
209 char *oauth = NULL; | |
210 char *request = NULL; | |
211 oauth_request_t *oauth_req = g_new0(oauth_request_t, 1); | |
212 /* | |
213 http://twitter.com/oauth/request_token? | |
214 oauth_consumer_key=wrD3WGIh2P31d3fIjRkfcw& | |
215 oauth_nonce=HCUxu1D3qN4Nklr9QVAymve40PtJyU& | |
216 oauth_signature_method=HMAC-SHA1& | |
217 oauth_timestamp=1282446611&oauth_version=1.0& | |
218 oauth_signature=A%2BZIiUVsQv5ZR8u%2F2oLmUFX1eHE%3D | |
219 */ | |
220 | |
221 oauth_req->url = strdup(request_token_url); | |
222 oauth_req->c_key = strdup(c_key); | |
223 oauth_req->c_sec = strdup(c_sec); | |
224 oauth_req->a_key = NULL; | |
225 oauth_req->a_sec = NULL; | |
226 oauth_req->type = TYPE_GET; | |
227 oauth_req->notoken = TRUE; | |
228 oauth_req->conv = (PurpleConversation *)data; | |
229 | |
230 /* request token*/ | |
231 oauth = make_oauth_get(oauth_req); | |
232 request = g_strdup_printf("%s?%s", request_token_url, oauth); | |
233 | |
234 twitter_debug("request=%s\n", request); | |
235 | |
236 purple_util_fetch_url_request(request, TRUE, | |
237 NULL, TRUE, NULL, TRUE, | |
238 oauth_setup_cb, oauth_req); | |
239 } | |
240 | |
241 | |
242 char * | |
243 hmac_sha1(char *text, char *key) { | |
244 PurpleCipherContext *context = NULL; | |
245 size_t len; | |
246 guchar digest[255]; | |
247 char *signature = NULL; | |
248 | |
249 twitter_debug("text=%s\n", text); | |
250 twitter_debug("key=%s\n", key); | |
251 | |
252 context = purple_cipher_context_new_by_name("hmac", NULL); | |
253 if(!context) | |
254 return NULL; | |
255 | |
256 purple_cipher_context_set_option(context, "hash", "sha1"); | |
257 purple_cipher_context_set_key(context, (guchar *)key); | |
258 purple_cipher_context_append(context, (guchar *)text, strlen(text)); | |
259 | |
260 if(purple_cipher_context_digest(context, sizeof(digest), digest, &len)) { | |
261 signature = purple_base64_encode(digest, len); | |
262 twitter_debug("hmac1 signature=%s\n", signature); | |
263 } | |
264 else { | |
265 twitter_debug("digest signature failed\n"); | |
266 } | |
267 | |
268 purple_cipher_context_destroy(context); | |
269 | |
270 return signature; | |
271 } | |
272 | |
273 char * | |
274 make_oauth_get(oauth_request_t *req) | |
275 { | |
276 gchar *tmp = NULL; | |
277 char *signature = NULL; | |
278 time_t current_time = time(NULL); | |
279 char *params = NULL; | |
280 char *oauth; | |
281 char *count_str = NULL; | |
282 char *token_str = NULL; | |
283 char *verifier_str = NULL; | |
284 | |
285 if(req->count) | |
286 count_str = g_strdup_printf("count=%d&", req->count); | |
287 else | |
288 count_str = g_strdup(""); | |
289 | |
290 if(req->notoken) { | |
291 twitter_debug("notoken\n"); | |
292 token_str = g_strdup(""); | |
293 } | |
294 else | |
295 token_str = g_strdup_printf("oauth_token=%s&", req->a_key?req->a_key:req->c_key); | |
296 | |
297 if(req->verifier) | |
298 verifier_str = g_strdup_printf("oauth_verifier=%s&", req->verifier); | |
299 else | |
300 verifier_str = g_strdup(""); | |
301 | |
302 params = g_strdup_printf("%soauth_consumer_key=%s&oauth_nonce=%s&oauth_signature_method=HMAC-SHA1&oauth_timestamp=%d&%s%soauth_version=1.0", | |
303 count_str, | |
304 req->c_key, | |
305 SAMPLE_NONCE, | |
306 (int)current_time, | |
307 token_str, | |
308 verifier_str); | |
309 | |
310 g_free(count_str); | |
311 g_free(token_str); | |
312 g_free(verifier_str); | |
313 | |
314 const char *url_encoded = g_uri_escape_string(req->url, "", FALSE); | |
315 const char *params_encoded = g_uri_escape_string(params, "", FALSE); | |
316 | |
317 tmp = g_strdup_printf("GET&%s&%s", url_encoded, params_encoded); | |
318 char *key = g_strdup_printf("%s&%s", req->c_sec, req->a_sec?req->a_sec:""); | |
319 signature = hmac_sha1(tmp, key); | |
320 g_free(key); | |
321 | |
322 const char *signature_encoded = g_uri_escape_string(signature, "", FALSE); | |
323 | |
324 oauth = g_strdup_printf("%s&oauth_signature=%s", params, signature_encoded); | |
325 | |
326 g_free(tmp); | |
327 g_free(signature); | |
328 g_free(params); | |
329 | |
330 twitter_debug("oauth_block=%s\n", oauth); | |
331 return oauth; | |
332 } | |
333 | |
334 char * | |
335 make_oauth_post(oauth_request_t *req) | |
336 { | |
337 gchar *tmp = NULL; | |
338 char *signature = NULL; | |
339 time_t current_time = time(NULL); | |
340 char *params = NULL; | |
341 char *oauth; | |
342 char *status_str = NULL; | |
343 char *msgid_str = NULL; | |
344 | |
345 if(req->status) | |
346 status_str = g_strdup_printf("&status=%s", req->status); | |
347 else | |
348 status_str = g_strdup(""); | |
349 | |
350 if(req->msgid) | |
351 msgid_str = g_strdup_printf("in_reply_to_status_id=%llu&", | |
352 (long long unsigned int)req->msgid); | |
353 else | |
354 msgid_str = g_strdup(""); | |
355 | |
356 params = g_strdup_printf("%soauth_consumer_key=%s&oauth_nonce=%s&oauth_signature_method=HMAC-SHA1&oauth_timestamp=%d&oauth_token=%s&oauth_version=1.0%s", | |
357 msgid_str, | |
358 req->c_key, | |
359 SAMPLE_NONCE, | |
360 (int)current_time, | |
361 req->a_key, | |
362 status_str); | |
363 | |
364 g_free(status_str); | |
365 g_free(msgid_str); | |
366 | |
367 const char *url_encoded = g_uri_escape_string(req->url, "", FALSE); | |
368 const char *params_encoded = g_uri_escape_string(params, "", FALSE); | |
369 | |
370 tmp = g_strdup_printf("POST&%s&%s", url_encoded, params_encoded); | |
371 char *key = g_strdup_printf("%s&%s", req->c_sec, req->a_sec); | |
372 signature = hmac_sha1(tmp, key); | |
373 g_free(key); | |
374 | |
375 const char *signature_encoded = g_uri_escape_string(signature, "", FALSE); | |
376 | |
377 oauth = g_strdup_printf("%s&oauth_signature=%s", params, signature_encoded); | |
378 | |
379 g_free(tmp); | |
380 g_free(signature); | |
381 g_free(params); | |
382 | |
383 twitter_debug("oauth_block=%s\n", oauth); | |
384 return oauth; | |
385 } | |
23 | 386 |
24 /**************************/ | 387 /**************************/ |
25 /* API base get functions */ | 388 /* API base get functions */ |
26 /**************************/ | 389 /**************************/ |
27 /* xml parser */ | 390 /* xml parser */ |
315 { | 678 { |
316 twitter_debug("called\n"); | 679 twitter_debug("called\n"); |
317 | 680 |
318 /* fetch friends time line */ | 681 /* fetch friends time line */ |
319 char *request, *header; | 682 char *request, *header; |
320 char *basic_auth, *basic_auth_encoded; | |
321 gint count = purple_prefs_get_int(OPT_RETRIEVE_COUNT); | 683 gint count = purple_prefs_get_int(OPT_RETRIEVE_COUNT); |
684 char *oauth; | |
685 const char *a_key = NULL; | |
686 const char *a_sec = NULL; | |
687 static gboolean setup = FALSE; | |
688 oauth_request_t oauth_req; | |
689 | |
690 a_key = purple_prefs_get_string(OPT_AKEY_TWITTER); | |
691 a_sec = purple_prefs_get_string(OPT_ASEC_TWITTER); | |
692 | |
693 if(!a_key || !a_sec) { | |
694 if(!setup) { | |
695 oauth_setup(data); | |
696 setup = TRUE; | |
697 } | |
698 return TRUE; | |
699 } | |
322 | 700 |
323 if(count < TWITTER_DEFAULT_RETRIEVE_COUNT) | 701 if(count < TWITTER_DEFAULT_RETRIEVE_COUNT) |
324 count = TWITTER_DEFAULT_RETRIEVE_COUNT; | 702 count = TWITTER_DEFAULT_RETRIEVE_COUNT; |
325 | 703 |
326 /* if disabled, just return */ | 704 /* if disabled, just return */ |
327 if(!purple_prefs_get_bool(OPT_API_BASE_POST)) | 705 if(!purple_prefs_get_bool(OPT_API_BASE_POST)) |
328 return TRUE; | 706 return TRUE; |
329 | 707 |
330 const char *screen_name = | 708 /* oauth */ |
331 purple_prefs_get_string(OPT_SCREEN_NAME_TWITTER); | 709 char *url0 = g_strdup_printf(TWITTER_API_BASE_URL "/1/statuses/home_timeline.xml"); |
332 const char *password = | 710 oauth_req.url = url0; |
333 purple_prefs_get_string(OPT_PASSWORD_TWITTER); | 711 oauth_req.c_key = c_key; |
334 | 712 oauth_req.c_sec = c_sec; |
335 if (!screen_name || !password || !screen_name[0] || !password[0]) { | 713 oauth_req.a_key = (char *)a_key; |
336 twitter_debug("screen_name or password is empty\n"); | 714 oauth_req.a_sec = (char *)a_sec; |
337 return TRUE; | 715 oauth_req.verifier = NULL; |
338 } | 716 oauth_req.status = NULL; |
339 | 717 oauth_req.type = TYPE_GET; |
340 /* auth */ | 718 oauth_req.count = count; |
341 basic_auth = g_strdup_printf("%s:%s", screen_name, password); | 719 oauth_req.msgid = 0; |
342 basic_auth_encoded = purple_base64_encode((unsigned char *)basic_auth, | 720 oauth_req.notoken = FALSE; |
343 strlen(basic_auth)); | 721 |
344 g_free(basic_auth); | 722 oauth = make_oauth_get(&oauth_req); |
345 | 723 |
346 /* header */ | 724 /* header */ |
347 header = g_strdup_printf(TWITTER_STATUS_GET, count, basic_auth_encoded); | 725 header = g_strdup_printf(TWITTER_STATUS_GET, oauth); |
348 request = g_strconcat(header, "\r\n", NULL); | 726 request = g_strconcat(header, "\r\n", NULL); |
727 | |
728 twitter_debug("request=%s\n", request); | |
349 | 729 |
350 /* invoke fetch */ | 730 /* invoke fetch */ |
351 purple_util_fetch_url_request(TWITTER_API_BASE_URL, FALSE, | 731 purple_util_fetch_url_request(TWITTER_API_BASE_URL, FALSE, |
352 NULL, TRUE, request, TRUE, | 732 NULL, TRUE, request, TRUE, |
353 get_status_with_api_cb, data); | 733 get_status_with_api_cb, data); |
354 | 734 |
355 g_free(header); | 735 g_free(header); |
356 g_free(basic_auth_encoded); | |
357 g_free(request); | 736 g_free(request); |
358 | 737 g_free(oauth); |
738 g_free(url0); | |
359 return TRUE; | 739 return TRUE; |
360 } | 740 } |
361 | 741 |
362 /****************************/ | 742 /****************************/ |
363 /* API based post functions */ | 743 /* API based post functions */ |
512 } | 892 } |
513 | 893 |
514 void | 894 void |
515 post_status_with_api(PurpleAccount *account, char **buffer) | 895 post_status_with_api(PurpleAccount *account, char **buffer) |
516 { | 896 { |
517 char *request, *status, *header; | 897 char *request, *header; |
518 const char *url_encoded = g_uri_escape_string(*buffer, "!$'()*,;=:@/?#[]", FALSE); | 898 const char *url_encoded = g_uri_escape_string(*buffer, "", FALSE); |
519 char *basic_auth, *basic_auth_encoded; | 899 PurpleConversation *conv; |
520 | 900 char *oauth; |
521 twitter_message_t *tm; | 901 twitter_message_t *tm; |
522 | 902 const char *a_key = NULL; |
523 const char *screen_name = | 903 const char *a_sec = NULL; |
524 purple_prefs_get_string(OPT_SCREEN_NAME_TWITTER); | 904 oauth_request_t oauth_req; |
525 const char *password = purple_prefs_get_string(OPT_PASSWORD_TWITTER); | 905 |
526 | 906 conv = purple_find_conversation_with_account( |
527 twitter_debug("tm.account: %s\n", | 907 PURPLE_CONV_TYPE_ANY, "twitter@twitter.com", |
528 purple_account_get_username(account)); | 908 account_for_twitter); /* xxx */ |
529 | 909 |
530 if (!screen_name || !password || !screen_name[0] || !password[0]) { | 910 a_key = purple_prefs_get_string(OPT_AKEY_TWITTER); |
531 twitter_debug("screen_name or password is empty\n"); | 911 a_sec = purple_prefs_get_string(OPT_ASEC_TWITTER); |
912 | |
913 if(!a_key || !a_sec) { | |
532 return; | 914 return; |
533 } | 915 } |
534 | 916 |
535 tm = g_new(twitter_message_t, 1); | 917 tm = g_new(twitter_message_t, 1); |
536 tm->account = account; | 918 tm->account = account; |
537 tm->status = g_strdup(*buffer); | 919 tm->status = g_strdup(*buffer); |
538 tm->time = time(NULL); | 920 tm->time = time(NULL); |
539 | 921 |
540 basic_auth = g_strdup_printf("%s:%s", screen_name, password); | 922 /* oauth */ |
541 basic_auth_encoded = purple_base64_encode((unsigned char *)basic_auth, | 923 char *url0 = g_strdup_printf(TWITTER_API_BASE_URL "/1/statuses/update.xml"); |
542 strlen(basic_auth)); | 924 |
543 g_free(basic_auth); | 925 oauth_req.url = url0; |
544 | 926 oauth_req.c_key = c_key; |
545 if(reply_to_msgid > 0) { | 927 oauth_req.c_sec = c_sec; |
546 status = g_strdup_printf(TWITTER_REPLY_FORMAT, url_encoded, | 928 oauth_req.a_key = (char *)purple_prefs_get_string(OPT_AKEY_TWITTER); |
547 (long long unsigned int)reply_to_msgid); | 929 oauth_req.a_sec = (char *)purple_prefs_get_string(OPT_ASEC_TWITTER); |
548 header = g_strdup_printf(TWITTER_STATUS_POST, basic_auth_encoded, | 930 oauth_req.verifier = NULL; |
549 (int)strlen(status)); | 931 oauth_req.status = (char *)url_encoded; |
550 reply_to_msgid = 0; | 932 oauth_req.type = TYPE_POST; |
551 } | 933 oauth_req.count = 0; |
552 else { | 934 oauth_req.msgid = reply_to_msgid; |
553 status = g_strdup_printf(TWITTER_STATUS_FORMAT, url_encoded); | 935 oauth_req.notoken = FALSE; |
554 header = g_strdup_printf(TWITTER_STATUS_POST, basic_auth_encoded, | 936 |
555 (int)strlen(status)); | 937 oauth = make_oauth_post(&oauth_req); |
556 } | 938 |
557 | 939 reply_to_msgid = 0; |
558 request = g_strconcat(header, "\r\n", status, "\r\n", NULL); | 940 |
941 | |
942 header = g_strdup_printf(TWITTER_STATUS_POST, | |
943 (int)strlen(oauth)); | |
944 | |
945 request = g_strconcat(header, "\r\n", oauth, "\r\n", NULL); | |
946 twitter_debug("request=%s\n", request); | |
559 purple_util_fetch_url_request(TWITTER_BASE_URL, FALSE, | 947 purple_util_fetch_url_request(TWITTER_BASE_URL, FALSE, |
560 NULL, TRUE, request, TRUE, | 948 NULL, TRUE, request, TRUE, |
561 post_status_with_api_cb, tm); | 949 post_status_with_api_cb, tm); |
562 | 950 |
563 g_free(header); | 951 g_free(header); |
564 g_free(basic_auth_encoded); | 952 g_free(oauth); |
565 g_free(status); | |
566 g_free(request); | 953 g_free(request); |
567 | 954 |
568 } | 955 } |
569 | 956 |
570 static void | 957 static void |
577 | 964 |
578 void | 965 void |
579 fav_with_api(guint64 id) | 966 fav_with_api(guint64 id) |
580 { | 967 { |
581 char *header, *request; | 968 char *header, *request; |
582 char *basic_auth, *basic_auth_encoded; | 969 char *oauth; |
583 | 970 const char *a_key = NULL; |
584 const char *screen_name = | 971 const char *a_sec = NULL; |
585 purple_prefs_get_string(OPT_SCREEN_NAME_TWITTER); | 972 PurpleConversation *conv; |
586 const char *password = purple_prefs_get_string(OPT_PASSWORD_TWITTER); | 973 oauth_request_t oauth_req; |
587 | 974 |
588 if(id == 0) { | 975 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, |
589 twitter_debug("invalid message id\n"); | 976 "twitter@twitter.com", |
590 return; | 977 account_for_twitter); /* xxx */ |
591 } | 978 |
592 | 979 |
593 if (!screen_name || !password || !screen_name[0] || !password[0]) { | 980 a_key = purple_prefs_get_string(OPT_AKEY_TWITTER); |
594 twitter_debug("screen_name or password is empty\n"); | 981 a_sec = purple_prefs_get_string(OPT_ASEC_TWITTER); |
595 return; | 982 |
596 } | 983 if(!a_key || !a_sec) { |
597 | 984 return; |
598 basic_auth = g_strdup_printf("%s:%s", screen_name, password); | 985 } |
599 basic_auth_encoded = purple_base64_encode((unsigned char *)basic_auth, | 986 |
600 strlen(basic_auth)); | 987 /* oauth */ |
601 g_free(basic_auth); | 988 char *url0 = g_strdup_printf(TWITTER_API_BASE_URL "/1/favorites/create/%llu.xml", (long long unsigned int)id); |
602 | 989 |
990 oauth_req.url = url0; | |
991 oauth_req.c_key = c_key; | |
992 oauth_req.c_sec = c_sec; | |
993 oauth_req.a_key = (char *)a_key; | |
994 oauth_req.a_sec = (char *)a_sec; | |
995 oauth_req.verifier = NULL; | |
996 oauth_req.status = NULL; | |
997 oauth_req.type = TYPE_POST; | |
998 oauth_req.count = 0; | |
999 oauth_req.msgid = 0; | |
1000 oauth_req.notoken = FALSE; | |
1001 | |
1002 oauth = make_oauth_post(&oauth_req); | |
603 | 1003 |
604 header = g_strdup_printf(TWITTER_FAV_POST, | 1004 header = g_strdup_printf(TWITTER_FAV_POST, |
605 (long long unsigned int)id, | 1005 (long long unsigned int)id, |
606 basic_auth_encoded); | 1006 (int)strlen(oauth)); |
607 request = g_strconcat(header, "\r\n", NULL); | 1007 |
1008 request = g_strconcat(header, "\r\n", oauth, NULL); | |
1009 twitter_debug("request=%s\n", request); | |
608 | 1010 |
609 purple_util_fetch_url_request(TWITTER_BASE_URL, FALSE, | 1011 purple_util_fetch_url_request(TWITTER_BASE_URL, FALSE, |
610 NULL, TRUE, request, TRUE, | 1012 NULL, TRUE, request, TRUE, |
611 fav_with_api_cb, NULL); | 1013 fav_with_api_cb, NULL); |
612 twitter_debug("request = %s\n", request); | |
613 | 1014 |
614 g_free(header); | 1015 g_free(header); |
615 g_free(basic_auth_encoded); | 1016 g_free(oauth); |
616 g_free(request); | 1017 g_free(request); |
617 } | 1018 } |
618 | 1019 |
619 static void | 1020 static void |
620 retweet_with_api_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, | 1021 retweet_with_api_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, |
626 | 1027 |
627 void | 1028 void |
628 retweet_with_api(guint64 id) | 1029 retweet_with_api(guint64 id) |
629 { | 1030 { |
630 char *header, *request; | 1031 char *header, *request; |
631 char *basic_auth, *basic_auth_encoded; | 1032 char *oauth; |
632 | 1033 const char *a_key = NULL; |
633 const char *screen_name = | 1034 const char *a_sec = NULL; |
634 purple_prefs_get_string(OPT_SCREEN_NAME_TWITTER); | 1035 PurpleConversation *conv; |
635 const char *password = purple_prefs_get_string(OPT_PASSWORD_TWITTER); | 1036 oauth_request_t oauth_req; |
1037 | |
1038 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, | |
1039 "twitter@twitter.com", | |
1040 account_for_twitter); /* xxx */ | |
1041 | |
1042 a_key = purple_prefs_get_string(OPT_AKEY_TWITTER); | |
1043 a_sec = purple_prefs_get_string(OPT_ASEC_TWITTER); | |
1044 | |
1045 if(!a_key || !a_sec) { | |
1046 return; | |
1047 } | |
636 | 1048 |
637 if(id == 0) { | 1049 if(id == 0) { |
638 twitter_debug("invalid message id\n"); | 1050 twitter_debug("invalid message id\n"); |
639 return; | 1051 return; |
640 } | 1052 } |
641 | 1053 |
642 if (!screen_name || !password || !screen_name[0] || !password[0]) { | 1054 /* oauth */ |
643 twitter_debug("screen_name or password is empty\n"); | 1055 char *url0 = g_strdup_printf(TWITTER_API_BASE_URL "/1/statuses/retweet%llu.xml", (long long unsigned int)id); |
644 return; | 1056 |
645 } | 1057 oauth_req.url = url0; |
646 | 1058 oauth_req.c_key = c_key; |
647 basic_auth = g_strdup_printf("%s:%s", screen_name, password); | 1059 oauth_req.c_sec = c_sec; |
648 basic_auth_encoded = purple_base64_encode((unsigned char *)basic_auth, | 1060 oauth_req.a_key = (char *)a_key; |
649 strlen(basic_auth)); | 1061 oauth_req.a_sec = (char *)a_sec; |
650 g_free(basic_auth); | 1062 oauth_req.verifier = NULL; |
651 | 1063 oauth_req.status = NULL; |
1064 oauth_req.type = TYPE_POST; | |
1065 oauth_req.count = 0; | |
1066 oauth_req.msgid = 0; | |
1067 oauth_req.notoken = FALSE; | |
1068 | |
1069 oauth = make_oauth_post(&oauth_req); | |
652 | 1070 |
653 header = g_strdup_printf(TWITTER_RETWEET_POST, | 1071 header = g_strdup_printf(TWITTER_RETWEET_POST, |
654 (long long unsigned int)id, | 1072 (long long unsigned int)id, |
655 basic_auth_encoded); | 1073 (int)strlen(oauth)); |
656 request = g_strconcat(header, "\r\n", NULL); | 1074 |
1075 request = g_strconcat(header, "\r\n", oauth, NULL); | |
1076 twitter_debug("request=%s\n", request); | |
657 | 1077 |
658 purple_util_fetch_url_request(TWITTER_API_BASE_URL, FALSE, | 1078 purple_util_fetch_url_request(TWITTER_API_BASE_URL, FALSE, |
659 NULL, TRUE, request, TRUE, | 1079 NULL, TRUE, request, TRUE, |
660 retweet_with_api_cb, NULL); | 1080 retweet_with_api_cb, NULL); |
661 twitter_debug("request = %s\n", request); | |
662 | 1081 |
663 g_free(header); | 1082 g_free(header); |
664 g_free(basic_auth_encoded); | 1083 g_free(oauth); |
665 g_free(request); | 1084 g_free(request); |
666 } | 1085 } |
667 | 1086 |
668 void | 1087 void |
669 signed_on_cb(PurpleConnection *gc) | 1088 signed_on_cb(PurpleConnection *gc) |