pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
closing merged branch
port-changes-from-branch-2.x.y-to-default
2020-02-03, Gary Kramlich
2f836435c33c
closing merged branch
/* purple
*
* Purple is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* Rewritten from scratch during Google Summer of Code 2012
* by Tomek Wasilczyk (http://www.wasilczyk.pl).
*
* Previously implemented by:
* - Arkadiusz Miskiewicz <misiek@pld.org.pl> - first implementation (2001);
* - Bartosz Oler <bartosz@bzimage.us> - reimplemented during GSoC 2005;
* - Krzysztof Klinikowski <grommasher@gmail.com> - some parts (2009-2011).
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include
"oauth-purple.h"
#include
"gg.h"
#include
"oauth.h"
#include
"../utils.h"
#include
"../xml.h"
#include
<debug.h>
#define GGP_OAUTH_RESPONSE_MAX 10240
typedef
struct
{
PurpleConnection
*
gc
;
ggp_oauth_request_cb
callback
;
gpointer
user_data
;
gchar
*
token
;
gchar
*
token_secret
;
gchar
*
sign_method
,
*
sign_url
;
}
ggp_oauth_data
;
static
void
ggp_oauth_data_free
(
ggp_oauth_data
*
data
)
{
g_free
(
data
->
token
);
g_free
(
data
->
token_secret
);
g_free
(
data
->
sign_method
);
g_free
(
data
->
sign_url
);
g_free
(
data
);
}
static
void
ggp_oauth_access_token_got
(
G_GNUC_UNUSED
SoupSession
*
session
,
SoupMessage
*
msg
,
gpointer
user_data
)
{
ggp_oauth_data
*
data
=
user_data
;
gchar
*
token
,
*
token_secret
;
PurpleXmlNode
*
xml
;
gboolean
succ
=
TRUE
;
xml
=
purple_xmlnode_from_str
(
msg
->
response_body
->
data
,
msg
->
response_body
->
length
);
if
(
xml
==
NULL
)
{
purple_debug_error
(
"gg"
,
"ggp_oauth_access_token_got: invalid xml"
);
ggp_oauth_data_free
(
data
);
return
;
}
succ
&=
ggp_xml_get_string
(
xml
,
"oauth_token"
,
&
token
);
succ
&=
ggp_xml_get_string
(
xml
,
"oauth_token_secret"
,
&
token_secret
);
purple_xmlnode_free
(
xml
);
if
(
!
succ
||
strlen
(
token
)
<
10
)
{
purple_debug_error
(
"gg"
,
"ggp_oauth_access_token_got: invalid xml - "
"token is not present"
);
ggp_oauth_data_free
(
data
);
return
;
}
if
(
data
->
sign_url
)
{
PurpleAccount
*
account
;
gchar
*
auth
;
purple_debug_misc
(
"gg"
,
"ggp_oauth_access_token_got: got access token, "
"returning signed url"
);
account
=
purple_connection_get_account
(
data
->
gc
);
auth
=
gg_oauth_generate_header
(
data
->
sign_method
,
data
->
sign_url
,
purple_account_get_username
(
account
),
purple_connection_get_password
(
data
->
gc
),
token
,
token_secret
);
data
->
callback
(
data
->
gc
,
auth
,
data
->
user_data
);
}
else
{
purple_debug_misc
(
"gg"
,
"ggp_oauth_access_token_got: got access token, returning it"
);
data
->
callback
(
data
->
gc
,
token
,
data
->
user_data
);
}
g_free
(
token
);
g_free
(
token_secret
);
ggp_oauth_data_free
(
data
);
}
static
void
ggp_oauth_authorization_done
(
SoupSession
*
session
,
SoupMessage
*
msg
,
gpointer
user_data
)
{
ggp_oauth_data
*
data
=
user_data
;
PurpleAccount
*
account
;
char
*
auth
;
const
char
*
method
=
"POST"
;
const
char
*
url
=
"http://api.gadu-gadu.pl/access_token"
;
PURPLE_ASSERT_CONNECTION_IS_VALID
(
data
->
gc
);
account
=
purple_connection_get_account
(
data
->
gc
);
if
(
msg
->
status_code
!=
302
)
{
purple_debug_error
(
"gg"
,
"ggp_oauth_authorization_done: failed (code = %d)"
,
msg
->
status_code
);
ggp_oauth_data_free
(
data
);
return
;
}
purple_debug_misc
(
"gg"
,
"ggp_oauth_authorization_done: authorization done, "
"requesting access token..."
);
auth
=
gg_oauth_generate_header
(
method
,
url
,
purple_account_get_username
(
account
),
purple_connection_get_password
(
data
->
gc
),
data
->
token
,
data
->
token_secret
);
msg
=
soup_message_new
(
method
,
url
);
// purple_http_request_set_max_len(req, GGP_OAUTH_RESPONSE_MAX);
soup_message_headers_replace
(
msg
->
request_headers
,
"Authorization"
,
auth
);
soup_session_queue_message
(
session
,
msg
,
ggp_oauth_access_token_got
,
data
);
g_free
(
auth
);
}
static
void
ggp_oauth_request_token_got
(
SoupSession
*
session
,
SoupMessage
*
msg
,
gpointer
user_data
)
{
ggp_oauth_data
*
data
=
user_data
;
PurpleAccount
*
account
;
PurpleXmlNode
*
xml
;
gchar
*
request_data
;
gboolean
succ
=
TRUE
;
PURPLE_ASSERT_CONNECTION_IS_VALID
(
data
->
gc
);
account
=
purple_connection_get_account
(
data
->
gc
);
if
(
!
SOUP_STATUS_IS_SUCCESSFUL
(
msg
->
status_code
))
{
purple_debug_error
(
"gg"
,
"ggp_oauth_request_token_got: "
"requested token not received
\n
"
);
ggp_oauth_data_free
(
data
);
return
;
}
purple_debug_misc
(
"gg"
,
"ggp_oauth_request_token_got: "
"got request token, doing authorization...
\n
"
);
xml
=
purple_xmlnode_from_str
(
msg
->
response_body
->
data
,
msg
->
response_body
->
length
);
if
(
xml
==
NULL
)
{
purple_debug_error
(
"gg"
,
"ggp_oauth_request_token_got: "
"invalid xml
\n
"
);
ggp_oauth_data_free
(
data
);
return
;
}
succ
&=
ggp_xml_get_string
(
xml
,
"oauth_token"
,
&
data
->
token
);
succ
&=
ggp_xml_get_string
(
xml
,
"oauth_token_secret"
,
&
data
->
token_secret
);
purple_xmlnode_free
(
xml
);
if
(
!
succ
)
{
purple_debug_error
(
"gg"
,
"ggp_oauth_request_token_got: "
"invalid xml - token is not present
\n
"
);
ggp_oauth_data_free
(
data
);
return
;
}
request_data
=
g_strdup_printf
(
"callback_url=http://www.mojageneracja.pl&request_token=%s&"
"uin=%s&password=%s"
,
data
->
token
,
purple_account_get_username
(
account
),
purple_connection_get_password
(
data
->
gc
));
msg
=
soup_message_new
(
"POST"
,
"https://login.gadu-gadu.pl/authorize"
);
// purple_http_request_set_max_len(msg, GGP_OAUTH_RESPONSE_MAX);
/* we don't need any results, nor 302 redirection */
soup_message_set_flags
(
msg
,
SOUP_MESSAGE_NO_REDIRECT
);
soup_message_set_request
(
msg
,
"application/x-www-form-urlencoded"
,
SOUP_MEMORY_TAKE
,
request_data
,
-1
);
soup_session_queue_message
(
session
,
msg
,
ggp_oauth_authorization_done
,
data
);
}
void
ggp_oauth_request
(
PurpleConnection
*
gc
,
ggp_oauth_request_cb
callback
,
gpointer
user_data
,
const
gchar
*
sign_method
,
const
gchar
*
sign_url
)
{
GGPInfo
*
info
=
purple_connection_get_protocol_data
(
gc
);
PurpleAccount
*
account
=
purple_connection_get_account
(
gc
);
SoupMessage
*
msg
;
char
*
auth
;
const
char
*
method
=
"POST"
;
const
char
*
url
=
"http://api.gadu-gadu.pl/request_token"
;
ggp_oauth_data
*
data
;
purple_debug_misc
(
"gg"
,
"ggp_oauth_request: requesting token...
\n
"
);
auth
=
gg_oauth_generate_header
(
method
,
url
,
purple_account_get_username
(
account
),
purple_connection_get_password
(
gc
),
NULL
,
NULL
);
data
=
g_new0
(
ggp_oauth_data
,
1
);
data
->
gc
=
gc
;
data
->
callback
=
callback
;
data
->
user_data
=
user_data
;
data
->
sign_method
=
g_strdup
(
sign_method
);
data
->
sign_url
=
g_strdup
(
sign_url
);
msg
=
soup_message_new
(
method
,
url
);
// purple_http_request_set_max_len(req, GGP_OAUTH_RESPONSE_MAX);
soup_message_headers_replace
(
msg
->
request_headers
,
"Authorization"
,
auth
);
soup_session_queue_message
(
info
->
http
,
msg
,
ggp_oauth_request_token_got
,
data
);
g_free
(
auth
);
}