3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * Rewritten from scratch during Google Summer of Code 2012
8 * by Tomek Wasilczyk (http://www.wasilczyk.pl).
10 * Previously implemented by:
11 * - Arkadiusz Miskiewicz <misiek@pld.org.pl> - first implementation (2001);
12 * - Bartosz Oler <bartosz@bzimage.us> - reimplemented during GSoC 2005;
13 * - Krzysztof Klinikowski <grommasher@gmail.com> - some parts (2009-2011).
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
30 #include "oauth-purple.h"
39 #define GGP_OAUTH_RESPONSE_MAX 10240
44 ggp_oauth_request_cb callback
;
49 gchar
*sign_method
, *sign_url
;
52 static void ggp_oauth_data_free(ggp_oauth_data
*data
);
54 static void ggp_oauth_request_token_got(PurpleHttpConnection
*http_conn
,
55 PurpleHttpResponse
*response
, gpointer user_data
);
57 static void ggp_oauth_authorization_done(PurpleHttpConnection
*http_conn
,
58 PurpleHttpResponse
*response
, gpointer user_data
);
60 static void ggp_oauth_access_token_got(PurpleHttpConnection
*http_conn
,
61 PurpleHttpResponse
*response
, gpointer user_data
);
63 static void ggp_oauth_data_free(ggp_oauth_data
*data
)
66 g_free(data
->token_secret
);
67 g_free(data
->sign_method
);
68 g_free(data
->sign_url
);
72 void ggp_oauth_request(PurpleConnection
*gc
, ggp_oauth_request_cb callback
,
73 gpointer user_data
, const gchar
*sign_method
, const gchar
*sign_url
)
75 PurpleAccount
*account
= purple_connection_get_account(gc
);
76 PurpleHttpRequest
*req
;
78 const char *method
= "POST";
79 const char *url
= "http://api.gadu-gadu.pl/request_token";
82 g_return_if_fail((method
== NULL
) == (url
== NULL
));
84 purple_debug_misc("gg", "ggp_oauth_request: requesting token...\n");
86 auth
= gg_oauth_generate_header(method
, url
,
87 purple_account_get_username(account
),
88 purple_connection_get_password(gc
), NULL
, NULL
);
90 data
= g_new0(ggp_oauth_data
, 1);
92 data
->callback
= callback
;
93 data
->user_data
= user_data
;
94 data
->sign_method
= g_strdup(sign_method
);
95 data
->sign_url
= g_strdup(sign_url
);
97 req
= purple_http_request_new(url
);
98 purple_http_request_set_max_len(req
, GGP_OAUTH_RESPONSE_MAX
);
99 purple_http_request_set_method(req
, method
);
100 purple_http_request_header_set(req
, "Authorization", auth
);
101 purple_http_request(gc
, req
, ggp_oauth_request_token_got
, data
);
102 purple_http_request_unref(req
);
107 static void ggp_oauth_request_token_got(PurpleHttpConnection
*http_conn
,
108 PurpleHttpResponse
*response
, gpointer user_data
)
110 ggp_oauth_data
*data
= user_data
;
111 PurpleAccount
*account
;
112 PurpleHttpRequest
*req
;
115 gboolean succ
= TRUE
;
116 const gchar
*xml_raw
;
118 PURPLE_ASSERT_CONNECTION_IS_VALID(data
->gc
);
120 account
= purple_connection_get_account(data
->gc
);
122 if (!purple_http_response_is_successful(response
)) {
123 purple_debug_error("gg", "ggp_oauth_request_token_got: "
124 "requested token not received\n");
125 ggp_oauth_data_free(data
);
129 purple_debug_misc("gg", "ggp_oauth_request_token_got: "
130 "got request token, doing authorization...\n");
132 xml_raw
= purple_http_response_get_data(response
, NULL
);
133 xml
= purple_xmlnode_from_str(xml_raw
, -1);
135 purple_debug_error("gg", "ggp_oauth_request_token_got: "
137 ggp_oauth_data_free(data
);
141 succ
&= ggp_xml_get_string(xml
, "oauth_token", &data
->token
);
142 succ
&= ggp_xml_get_string(xml
, "oauth_token_secret",
143 &data
->token_secret
);
144 purple_xmlnode_free(xml
);
146 purple_debug_error("gg", "ggp_oauth_request_token_got: "
147 "invalid xml - token is not present\n");
148 ggp_oauth_data_free(data
);
152 request_data
= g_strdup_printf(
153 "callback_url=http://www.mojageneracja.pl&request_token=%s&"
154 "uin=%s&password=%s", data
->token
,
155 purple_account_get_username(account
),
156 purple_connection_get_password(data
->gc
));
158 req
= purple_http_request_new("https://login.gadu-gadu.pl/authorize");
159 purple_http_request_set_max_len(req
, GGP_OAUTH_RESPONSE_MAX
);
160 /* we don't need any results, nor 302 redirection */
161 purple_http_request_set_max_redirects(req
, 0);
162 purple_http_request_set_method(req
, "POST");
163 purple_http_request_header_set(req
, "Content-Type", "application/x-www-form-urlencoded");
164 purple_http_request_set_contents(req
, request_data
, -1);
165 purple_http_request(data
->gc
, req
, ggp_oauth_authorization_done
, data
);
166 purple_http_request_unref(req
);
168 g_free(request_data
);
171 static void ggp_oauth_authorization_done(PurpleHttpConnection
*http_conn
,
172 PurpleHttpResponse
*response
, gpointer user_data
)
174 ggp_oauth_data
*data
= user_data
;
175 PurpleAccount
*account
;
176 PurpleHttpRequest
*req
;
178 const char *method
= "POST";
179 const char *url
= "http://api.gadu-gadu.pl/access_token";
182 PURPLE_ASSERT_CONNECTION_IS_VALID(data
->gc
);
184 account
= purple_connection_get_account(data
->gc
);
186 response_code
= purple_http_response_get_code(response
);
187 if (response_code
!= 302) {
188 purple_debug_error("gg", "ggp_oauth_authorization_done: "
189 "failed (code = %d)", response_code
);
190 ggp_oauth_data_free(data
);
194 purple_debug_misc("gg", "ggp_oauth_authorization_done: "
195 "authorization done, requesting access token...\n");
197 auth
= gg_oauth_generate_header(method
, url
,
198 purple_account_get_username(account
),
199 purple_connection_get_password(data
->gc
),
200 data
->token
, data
->token_secret
);
202 req
= purple_http_request_new(url
);
203 purple_http_request_set_max_len(req
, GGP_OAUTH_RESPONSE_MAX
);
204 purple_http_request_set_method(req
, method
);
205 purple_http_request_header_set(req
, "Authorization", auth
);
206 purple_http_request(data
->gc
, req
, ggp_oauth_access_token_got
, data
);
207 purple_http_request_unref(req
);
212 static void ggp_oauth_access_token_got(PurpleHttpConnection
*http_conn
,
213 PurpleHttpResponse
*response
, gpointer user_data
)
215 ggp_oauth_data
*data
= user_data
;
216 gchar
*token
, *token_secret
;
218 const gchar
*xml_raw
;
219 gboolean succ
= TRUE
;
221 xml_raw
= purple_http_response_get_data(response
, NULL
);
222 xml
= purple_xmlnode_from_str(xml_raw
, -1);
224 purple_debug_error("gg", "ggp_oauth_access_token_got: "
226 ggp_oauth_data_free(data
);
230 succ
&= ggp_xml_get_string(xml
, "oauth_token", &token
);
231 succ
&= ggp_xml_get_string(xml
, "oauth_token_secret",
233 purple_xmlnode_free(xml
);
234 if (!succ
|| strlen(token
) < 10) {
235 purple_debug_error("gg", "ggp_oauth_access_token_got: "
236 "invalid xml - token is not present\n");
237 ggp_oauth_data_free(data
);
241 if (data
->sign_url
) {
242 PurpleAccount
*account
;
245 purple_debug_misc("gg", "ggp_oauth_access_token_got: "
246 "got access token, returning signed url\n");
248 account
= purple_connection_get_account(data
->gc
);
249 auth
= gg_oauth_generate_header(
250 data
->sign_method
, data
->sign_url
,
251 purple_account_get_username(account
),
252 purple_connection_get_password(data
->gc
),
253 token
, token_secret
);
254 data
->callback(data
->gc
, auth
, data
->user_data
);
256 purple_debug_misc("gg", "ggp_oauth_access_token_got: "
257 "got access token, returning it\n");
258 data
->callback(data
->gc
, token
, data
->user_data
);
262 g_free(token_secret
);
263 ggp_oauth_data_free(data
);