mark PurpleImageClass as private
[pidgin-git.git] / libpurple / protocols / gg / oauth / oauth-purple.c
blob40faca4f7bc7764063cf3d7c4d8d1e155df14611
1 /* purple
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
5 * source distribution.
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"
32 #include "oauth.h"
33 #include "../utils.h"
34 #include "../xml.h"
36 #include <debug.h>
37 #include <http.h>
39 #define GGP_OAUTH_RESPONSE_MAX 10240
41 typedef struct
43 PurpleConnection *gc;
44 ggp_oauth_request_cb callback;
45 gpointer user_data;
46 gchar *token;
47 gchar *token_secret;
49 gchar *sign_method, *sign_url;
50 } ggp_oauth_data;
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)
65 g_free(data->token);
66 g_free(data->token_secret);
67 g_free(data->sign_method);
68 g_free(data->sign_url);
69 g_free(data);
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;
77 char *auth;
78 const char *method = "POST";
79 const char *url = "http://api.gadu-gadu.pl/request_token";
80 ggp_oauth_data *data;
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);
91 data->gc = gc;
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);
104 free(auth);
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;
113 PurpleXmlNode *xml;
114 gchar *request_data;
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);
126 return;
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);
134 if (xml == NULL) {
135 purple_debug_error("gg", "ggp_oauth_request_token_got: "
136 "invalid xml\n");
137 ggp_oauth_data_free(data);
138 return;
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);
145 if (!succ) {
146 purple_debug_error("gg", "ggp_oauth_request_token_got: "
147 "invalid xml - token is not present\n");
148 ggp_oauth_data_free(data);
149 return;
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;
177 char *auth;
178 const char *method = "POST";
179 const char *url = "http://api.gadu-gadu.pl/access_token";
180 int response_code;
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);
191 return;
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);
209 free(auth);
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;
217 PurpleXmlNode *xml;
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);
223 if (xml == NULL) {
224 purple_debug_error("gg", "ggp_oauth_access_token_got: "
225 "invalid xml\n");
226 ggp_oauth_data_free(data);
227 return;
230 succ &= ggp_xml_get_string(xml, "oauth_token", &token);
231 succ &= ggp_xml_get_string(xml, "oauth_token_secret",
232 &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);
238 return;
241 if (data->sign_url) {
242 PurpleAccount *account;
243 gchar *auth;
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);
255 } else {
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);
261 g_free(token);
262 g_free(token_secret);
263 ggp_oauth_data_free(data);