/*
* SkypeWeb Plugin for libpurple/Pidgin
* Copyright (c) 2014-2015 Eion Robb
*
* 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 3 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, see .
*/
#ifndef LIBSKYPEWEB_H
#define LIBSKYPEWEB_H
/* Maximum number of simultaneous connections to a server */
#define SKYPEWEB_MAX_CONNECTIONS 16
#include
#include
#include
#include
#include
#ifdef __GNUC__
#include
#include
#endif
#ifndef G_GNUC_NULL_TERMINATED
# if __GNUC__ >= 4
# define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
# else
# define G_GNUC_NULL_TERMINATED
# endif /* __GNUC__ >= 4 */
#endif /* G_GNUC_NULL_TERMINATED */
#ifdef _WIN32
# include "win32dep.h"
# define dlopen(a,b) LoadLibrary(a)
# define RTLD_LAZY
# define dlsym(a,b) GetProcAddress(a,b)
# define dlclose(a) FreeLibrary(a)
#else
# include
# include
# include
# include
#endif
#include
#define json_object_get_int_member(JSON_OBJECT, MEMBER) \
(JSON_OBJECT && json_object_has_member(JSON_OBJECT, MEMBER) ? json_object_get_int_member(JSON_OBJECT, MEMBER) : 0)
#define json_object_get_string_member(JSON_OBJECT, MEMBER) \
(JSON_OBJECT && json_object_has_member(JSON_OBJECT, MEMBER) ? json_object_get_string_member(JSON_OBJECT, MEMBER) : NULL)
#define json_object_get_array_member(JSON_OBJECT, MEMBER) \
(JSON_OBJECT && json_object_has_member(JSON_OBJECT, MEMBER) ? json_object_get_array_member(JSON_OBJECT, MEMBER) : NULL)
#define json_object_get_object_member(JSON_OBJECT, MEMBER) \
(JSON_OBJECT && json_object_has_member(JSON_OBJECT, MEMBER) ? json_object_get_object_member(JSON_OBJECT, MEMBER) : NULL)
#define json_object_get_boolean_member(JSON_OBJECT, MEMBER) \
(JSON_OBJECT && json_object_has_member(JSON_OBJECT, MEMBER) ? json_object_get_boolean_member(JSON_OBJECT, MEMBER) : FALSE)
#ifndef PURPLE_PLUGINS
# define PURPLE_PLUGINS
#endif
#include "accountopt.h"
#include "core.h"
#include "cmds.h"
#include "connection.h"
#include "debug.h"
#include "dnsquery.h"
#include "proxy.h"
#include "request.h"
#include "roomlist.h"
#include "savedstatuses.h"
#include "sslconn.h"
#include "util.h"
#include "version.h"
#if !PURPLE_VERSION_CHECK(3, 0, 0)
#include "blist.h"
#include "prpl.h"
#else
#include "buddylist.h"
#include "plugins.h"
#include "http.h"
#endif
#if GLIB_MAJOR_VERSION >= 2 && GLIB_MINOR_VERSION >= 12
# define atoll(a) g_ascii_strtoll(a, NULL, 0)
#endif
#if !PURPLE_VERSION_CHECK(3, 0, 0)
#define purple_connection_error purple_connection_error_reason
#define purple_notify_user_info_add_pair_html purple_notify_user_info_add_pair
#define purple_util_fetch_url_request purple_util_fetch_url_request_len_with_account
#define PurpleConversationUpdateType PurpleConvUpdateType
#define PurpleChatConversation PurpleConvChat
#define PurpleIMConversation PurpleConvIm
#define PurpleProtocolAction PurplePluginAction
#define PURPLE_IS_BUDDY PURPLE_BLIST_NODE_IS_BUDDY
#define PurpleProtocolChatEntry struct proto_chat_entry
#define PURPLE_CONNECTION_CONNECTED PURPLE_CONNECTED
#define PURPLE_CONNECTION_CONNECTING PURPLE_CONNECTING
#define PURPLE_CONNECTION_FLAG_HTML PURPLE_CONNECTION_HTML
#define PURPLE_CONNECTION_FLAG_NO_BGCOLOR PURPLE_CONNECTION_NO_BGCOLOR
#define PURPLE_CONNECTION_FLAG_NO_FONTSIZE PURPLE_CONNECTION_NO_FONTSIZE
#define purple_connection_get_protocol_data(pc) ((pc)->proto_data)
#define purple_connection_set_protocol_data(pc, data) ((pc)->proto_data = (data))
#define purple_connection_set_flags(pc, flags) (pc->flags = flags)
#define purple_connection_get_flags(pc) (pc->flags)
#define purple_conversation_present_error purple_conv_present_error
#define purple_account_privacy_check purple_privacy_check
#define purple_account_get_private_alias purple_account_get_alias
#define purple_account_set_private_alias purple_account_set_alias
#define purple_serv_got_im serv_got_im
#define purple_serv_got_typing serv_got_typing
#define purple_serv_got_alias serv_got_alias
#define PurpleIMTypingState PurpleTypingState
#define PURPLE_IM_NOT_TYPING PURPLE_NOT_TYPING
#define PURPLE_IM_TYPING PURPLE_TYPING
#define PURPLE_IM_TYPED PURPLE_TYPED
#define purple_blist_find_buddy purple_find_buddy
#define purple_blist_find_group purple_find_group
#define PurpleChatUser PurpleConvChatBuddy
#define PurpleChatUserFlags PurpleConvChatBuddyFlags
#define PURPLE_CHAT_USER_NONE PURPLE_CBFLAGS_NONE
#define PURPLE_CHAT_USER_OP PURPLE_CBFLAGS_OP
#define PURPLE_CHAT_USER_FOUNDER PURPLE_CBFLAGS_FOUNDER
#define PURPLE_CHAT_USER_TYPING PURPLE_CBFLAGS_TYPING
#define PURPLE_CHAT_USER_AWAY PURPLE_CBFLAGS_AWAY
#define PURPLE_CHAT_USER_HALFOP PURPLE_CBFLAGS_HALFOP
#define PURPLE_CHAT_USER_VOICE PURPLE_CBFLAGS_VOICE
#define PURPLE_CHAT_USER_TYPING PURPLE_CBFLAGS_TYPING
#define purple_chat_user_get_flags(cb) purple_conv_chat_user_get_flags(
#define purple_serv_got_joined_chat(pc, id, name) PURPLE_CONV_CHAT(serv_got_joined_chat(pc, id, name))
#define purple_serv_got_chat_invite serv_got_chat_invite
#define purple_serv_got_chat_in serv_got_chat_in
#define purple_chat_conversation_get_topic purple_conv_chat_get_topic
#define purple_chat_conversation_set_topic purple_conv_chat_set_topic
#define purple_chat_conversation_find_user(chat, name) purple_conv_chat_cb_find(chat, name)
#define purple_chat_conversation_add_user purple_conv_chat_add_user
#define purple_chat_conversation_leave purple_conv_chat_left
#define purple_chat_conversation_has_left purple_conv_chat_has_left
#define purple_chat_conversation_add_user purple_conv_chat_add_user
#define purple_chat_conversation_remove_user purple_conv_chat_remove_user
#define purple_chat_conversation_clear_users purple_conv_chat_clear_users
#define purple_chat_conversation_get_id purple_conv_chat_get_id
#define purple_protocol_got_user_status purple_prpl_got_user_status
#define purple_protocol_got_user_idle purple_prpl_got_user_idle
#define PURPLE_CONVERSATION_UPDATE_TOPIC PURPLE_CONV_UPDATE_TOPIC
#define PURPLE_CONVERSATION_UPDATE_UNSEEN PURPLE_CONV_UPDATE_UNSEEN
#define purple_conversations_find_chat(pc, id) PURPLE_CONV_CHAT(purple_find_chat(pc, id))
#define purple_conversations_find_chat_with_account(name, account) PURPLE_CONV_CHAT(purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name, account))
#define purple_conversations_find_im_with_account(name, account) PURPLE_CONV_IM(purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account))
#define purple_chat_conversation_new(account, from) PURPLE_CONV_CHAT(purple_conversation_new(PURPLE_CONV_TYPE_CHAT, account, from))
#define purple_im_conversation_new(account, from) PURPLE_CONV_IM(purple_conversation_new(PURPLE_CONV_TYPE_IM, account, from))
#define PURPLE_CONVERSATION(chatorim) (chatorim == NULL ? NULL : chatorim->conv)
#define PURPLE_IM_CONVERSATION(conv) PURPLE_CONV_IM(conv)
#define PURPLE_CHAT_CONVERSATION(conv) PURPLE_CONV_CHAT(conv)
#define PURPLE_IS_IM_CONVERSATION(conv) (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
#define PURPLE_IS_CHAT_CONVERSATION(conv) (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)
#define purple_conversation_get_connection purple_conversation_get_gc
#define PurpleMessage PurpleConvMessage
#define purple_conversation_write_message(conv, msg) purple_conversation_write(conv, msg->who, msg->what, msg->flags, msg->when)
#define PurpleXmlNode xmlnode
#define purple_xmlnode_from_str xmlnode_from_str
#define purple_xmlnode_get_child xmlnode_get_child
#define purple_xmlnode_get_next_twin xmlnode_get_next_twin
#define purple_xmlnode_get_data xmlnode_get_data
#define purple_xmlnode_get_attrib xmlnode_get_attrib
#define purple_xmlnode_free xmlnode_free
#define PurpleHash PurpleCipherContext
#define purple_sha256_hash_new() purple_cipher_context_new(purple_ciphers_find_cipher("sha256"), NULL)
#define purple_hash_append purple_cipher_context_append
#define purple_hash_digest(hash, data, len) purple_cipher_context_digest(hash, len, data, NULL)
#define purple_hash_destroy purple_cipher_context_destroy
#define purple_xfer_set_protocol_data(xfer, proto_data) ((xfer)->data = (proto_data))
#define purple_xfer_get_protocol_data(xfer) ((xfer)->data)
#if !PURPLE_VERSION_CHECK(2, 10, 12) && !FEDORA
static inline gboolean
purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size) {
PurpleXferUiOps *ui_ops = purple_xfer_get_ui_ops(xfer);
purple_xfer_set_bytes_sent(xfer, purple_xfer_get_bytes_sent(xfer) +
(ui_ops && ui_ops->ui_write ? ui_ops->ui_write(xfer, buffer, size) : fwrite(buffer, 1, size, xfer->dest_fp)));
return TRUE;
}
#endif
#define PURPLE_CMD_FLAG_PROTOCOL_ONLY PURPLE_CMD_FLAG_PRPL_ONLY
#define PURPLE_CMD_P_PLUGIN PURPLE_CMD_P_PRPL
/*typedef struct {
PurpleConvChatBuddy cb;
PurpleConvChat *chat;
} PurpleChatUser;*/
typedef struct {
gchar *host;
gint port;
gchar *path;
gchar *user;
gchar *passwd;
} PurpleHttpURL;
static inline PurpleHttpURL *purple_http_url_parse(const gchar *url) {
PurpleHttpURL *ret = g_new0(PurpleHttpURL, 1);
purple_url_parse(url, &(ret->host), &(ret->port), &(ret->path), &(ret->user), &(ret->passwd));
return ret;
}
#define purple_http_url_get_host(httpurl) (httpurl->host)
#define purple_http_url_get_path(httpurl) (httpurl->path)
static inline void purple_http_url_free(PurpleHttpURL *phl) { g_free(phl->host); g_free(phl->path); g_free(phl->user); g_free(phl->passwd); g_free(phl); }
#else
#define purple_conversation_set_data(conv, key, value) g_object_set_data(G_OBJECT(conv), key, value)
#define purple_conversation_get_data(conv, key) g_object_get_data(G_OBJECT(conv), key)
#define purple_hash_destroy g_object_unref
#define PURPLE_TYPE_STRING G_TYPE_STRING
typedef struct _SkypeWebProtocol
{
PurpleProtocol parent;
} SkypeWebProtocol;
typedef struct _SkypeWebProtocolClass
{
PurpleProtocolClass parent_class;
} SkypeWebProtocolClass;
G_MODULE_EXPORT GType skypeweb_protocol_get_type(void);
#define SKYPEWEB_TYPE_PROTOCOL (skypeweb_protocol_get_type())
#define SKYPEWEB_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SKYPEWEB_TYPE_PROTOCOL, SkypeWebProtocol))
#define SKYPEWEB_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SKYPEWEB_TYPE_PROTOCOL, SkypeWebProtocolClass))
#define SKYPEWEB_IS_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SKYPEWEB_TYPE_PROTOCOL))
#define SKYPEWEB_IS_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SKYPEWEB_TYPE_PROTOCOL))
#define SKYPEWEB_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SKYPEWEB_TYPE_PROTOCOL, SkypeWebProtocolClass))
#endif
#define SKYPEWEB_MAX_MSG_RETRY 2
#define SKYPEWEB_PLUGIN_ID "prpl-skypeweb"
#define SKYPEWEB_PLUGIN_VERSION "1.2"
#define SKYPEWEB_LOCKANDKEY_APPID "msmsgs@msnmsgr.com"
#define SKYPEWEB_LOCKANDKEY_SECRET "Q1P7W2E4J9R8U3S5"
#define SKYPEWEB_CONTACTS_HOST "api.skype.com"
#define SKYPEWEB_NEW_CONTACTS_HOST "contacts.skype.com"
#define SKYPEWEB_DEFAULT_MESSAGES_HOST "client-s.gateway.messenger.live.com"
#define SKYPEWEB_LOGIN_HOST "login.skype.com"
#define SKYPEWEB_VIDEOMAIL_HOST "vm.skype.com"
#define SKYPEWEB_XFER_HOST "api.asm.skype.com"
#define SKYPEWEB_CLIENTINFO_NAME "swx-skype.com"
#define SKYPEWEB_CLIENTINFO_VERSION "908/1.50.53"
#define SKYPEWEB_BUDDY_IS_MSN(a) G_UNLIKELY((a) != NULL && strchr((a), '@') != NULL)
#define SKYPEWEB_BUDDY_IS_PHONE(a) G_UNLIKELY((a) != NULL && *(a) == '+')
typedef struct _SkypeWebAccount SkypeWebAccount;
typedef struct _SkypeWebBuddy SkypeWebBuddy;
typedef void (*SkypeWebFunc)(SkypeWebAccount *swa);
struct _SkypeWebAccount {
gchar *username;
PurpleAccount *account;
PurpleConnection *pc;
GSList *conns; /**< A list of all active SkypeWebConnections */
GQueue *waiting_conns; /**< A list of all SkypeWebConnections waiting to process */
GSList *dns_queries;
GHashTable *cookie_table;
GHashTable *hostname_ip_cache;
gchar *messages_host;
GHashTable *sent_messages_hash;
guint poll_timeout;
guint watchdog_timeout;
guint authcheck_timeout;
time_t last_authrequest;
gchar *skype_token;
gchar *registration_token;
gchar *endpoint;
gint registration_expiry;
GSList *url_datas; /**< PurpleUtilFetchUrlData to be cancelled on logout */
};
struct _SkypeWebBuddy {
SkypeWebAccount *sa;
PurpleBuddy *buddy;
/** Contact info */
gchar *skypename;
gchar *fullname;
gchar *display_name;
gboolean authorized;
gboolean blocked;
/** Profile info */
gchar *avatar_url;
gchar *mood;
};
void skypeweb_buddy_free(PurpleBuddy *buddy);
void skypeweb_do_all_the_things(SkypeWebAccount *sa);
#endif /* LIBSKYPEWEB_H */