Use correct memory functions for GG oauth.
[pidgin-git.git] / libpurple / protocols / gg / oauth / oauth-purple.c
blobd1eb60ca567ddf1b3607ee5e7172ed38bc231b5f
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 g_free(data->token);
55 g_free(data->token_secret);
56 g_free(data->sign_method);
57 g_free(data->sign_url);
58 g_free(data);
61 static void
62 ggp_oauth_access_token_got(PurpleHttpConnection *http_conn,
63 PurpleHttpResponse *response, gpointer user_data)
65 ggp_oauth_data *data = user_data;
66 gchar *token, *token_secret;
67 PurpleXmlNode *xml;
68 const gchar *xml_raw;
69 gboolean succ = TRUE;
71 xml_raw = purple_http_response_get_data(response, NULL);
72 xml = purple_xmlnode_from_str(xml_raw, -1);
73 if (xml == NULL) {
74 purple_debug_error("gg", "ggp_oauth_access_token_got: invalid xml");
75 ggp_oauth_data_free(data);
76 return;
79 succ &= ggp_xml_get_string(xml, "oauth_token", &token);
80 succ &= ggp_xml_get_string(xml, "oauth_token_secret", &token_secret);
81 purple_xmlnode_free(xml);
82 if (!succ || strlen(token) < 10) {
83 purple_debug_error("gg", "ggp_oauth_access_token_got: invalid xml - "
84 "token is not present");
85 ggp_oauth_data_free(data);
86 return;
89 if (data->sign_url) {
90 PurpleAccount *account;
91 gchar *auth;
93 purple_debug_misc("gg", "ggp_oauth_access_token_got: got access token, "
94 "returning signed url");
96 account = purple_connection_get_account(data->gc);
97 auth = gg_oauth_generate_header(
98 data->sign_method, data->sign_url,
99 purple_account_get_username(account),
100 purple_connection_get_password(data->gc), token, token_secret);
101 data->callback(data->gc, auth, data->user_data);
102 } else {
103 purple_debug_misc(
104 "gg",
105 "ggp_oauth_access_token_got: got access token, returning it");
106 data->callback(data->gc, token, data->user_data);
109 g_free(token);
110 g_free(token_secret);
111 ggp_oauth_data_free(data);
114 static void
115 ggp_oauth_authorization_done(PurpleHttpConnection *http_conn,
116 PurpleHttpResponse *response, gpointer user_data)
118 ggp_oauth_data *data = user_data;
119 PurpleAccount *account;
120 PurpleHttpRequest *req;
121 char *auth;
122 const char *method = "POST";
123 const char *url = "http://api.gadu-gadu.pl/access_token";
124 int response_code;
126 PURPLE_ASSERT_CONNECTION_IS_VALID(data->gc);
128 account = purple_connection_get_account(data->gc);
130 response_code = purple_http_response_get_code(response);
131 if (response_code != 302) {
132 purple_debug_error("gg",
133 "ggp_oauth_authorization_done: failed (code = %d)",
134 response_code);
135 ggp_oauth_data_free(data);
136 return;
139 purple_debug_misc("gg", "ggp_oauth_authorization_done: authorization done, "
140 "requesting access token...");
142 auth = gg_oauth_generate_header(method, url,
143 purple_account_get_username(account),
144 purple_connection_get_password(data->gc),
145 data->token, data->token_secret);
147 req = purple_http_request_new(url);
148 purple_http_request_set_max_len(req, GGP_OAUTH_RESPONSE_MAX);
149 purple_http_request_set_method(req, method);
150 purple_http_request_header_set(req, "Authorization", auth);
151 purple_http_request(data->gc, req, ggp_oauth_access_token_got, data);
152 purple_http_request_unref(req);
154 g_free(auth);
157 static void ggp_oauth_request_token_got(PurpleHttpConnection *http_conn,
158 PurpleHttpResponse *response, gpointer user_data)
160 ggp_oauth_data *data = user_data;
161 PurpleAccount *account;
162 PurpleHttpRequest *req;
163 PurpleXmlNode *xml;
164 gchar *request_data;
165 gboolean succ = TRUE;
166 const gchar *xml_raw;
168 PURPLE_ASSERT_CONNECTION_IS_VALID(data->gc);
170 account = purple_connection_get_account(data->gc);
172 if (!purple_http_response_is_successful(response)) {
173 purple_debug_error("gg", "ggp_oauth_request_token_got: "
174 "requested token not received\n");
175 ggp_oauth_data_free(data);
176 return;
179 purple_debug_misc("gg", "ggp_oauth_request_token_got: "
180 "got request token, doing authorization...\n");
182 xml_raw = purple_http_response_get_data(response, NULL);
183 xml = purple_xmlnode_from_str(xml_raw, -1);
184 if (xml == NULL) {
185 purple_debug_error("gg", "ggp_oauth_request_token_got: "
186 "invalid xml\n");
187 ggp_oauth_data_free(data);
188 return;
191 succ &= ggp_xml_get_string(xml, "oauth_token", &data->token);
192 succ &= ggp_xml_get_string(xml, "oauth_token_secret",
193 &data->token_secret);
194 purple_xmlnode_free(xml);
195 if (!succ) {
196 purple_debug_error("gg", "ggp_oauth_request_token_got: "
197 "invalid xml - token is not present\n");
198 ggp_oauth_data_free(data);
199 return;
202 request_data = g_strdup_printf(
203 "callback_url=http://www.mojageneracja.pl&request_token=%s&"
204 "uin=%s&password=%s", data->token,
205 purple_account_get_username(account),
206 purple_connection_get_password(data->gc));
208 req = purple_http_request_new("https://login.gadu-gadu.pl/authorize");
209 purple_http_request_set_max_len(req, GGP_OAUTH_RESPONSE_MAX);
210 /* we don't need any results, nor 302 redirection */
211 purple_http_request_set_max_redirects(req, 0);
212 purple_http_request_set_method(req, "POST");
213 purple_http_request_header_set(req, "Content-Type", "application/x-www-form-urlencoded");
214 purple_http_request_set_contents(req, request_data, -1);
215 purple_http_request(data->gc, req, ggp_oauth_authorization_done, data);
216 purple_http_request_unref(req);
218 g_free(request_data);
221 void
222 ggp_oauth_request(PurpleConnection *gc, ggp_oauth_request_cb callback,
223 gpointer user_data, const gchar *sign_method,
224 const gchar *sign_url)
226 PurpleAccount *account = purple_connection_get_account(gc);
227 PurpleHttpRequest *req;
228 char *auth;
229 const char *method = "POST";
230 const char *url = "http://api.gadu-gadu.pl/request_token";
231 ggp_oauth_data *data;
233 purple_debug_misc("gg", "ggp_oauth_request: requesting token...\n");
235 auth = gg_oauth_generate_header(
236 method, url, purple_account_get_username(account),
237 purple_connection_get_password(gc), NULL, NULL);
239 data = g_new0(ggp_oauth_data, 1);
240 data->gc = gc;
241 data->callback = callback;
242 data->user_data = user_data;
243 data->sign_method = g_strdup(sign_method);
244 data->sign_url = g_strdup(sign_url);
246 req = purple_http_request_new(url);
247 purple_http_request_set_max_len(req, GGP_OAUTH_RESPONSE_MAX);
248 purple_http_request_set_method(req, method);
249 purple_http_request_header_set(req, "Authorization", auth);
250 purple_http_request(gc, req, ggp_oauth_request_token_got, data);
251 purple_http_request_unref(req);
253 g_free(auth);