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)