/* * 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 #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.1" #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.22.117" #define SKYPEWEB_BUDDY_IS_MSN(a) G_UNLIKELY((a) != NULL && strchr((a), '@') != NULL) 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 */