From cb16a2d7494a354b60c8fb8133e6ad0d3c48fd25 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Wed, 25 May 2016 02:20:21 +0300 Subject: [PATCH] libpurple: add prpl-hangouts oauth support --- backends/libpurple/main.cpp | 123 ++++++++++++++++++++++++------------ 1 file changed, 83 insertions(+), 40 deletions(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index ccee5aa6..a5726cb4 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -118,44 +118,13 @@ struct authRequest { std::string mainJID; // JID of user connected with this request }; -static void * requestInput(const char *title, const char *primary,const char *secondary, const char *default_value, gboolean multiline, gboolean masked, gchar *hint,const char *ok_text, GCallback ok_cb,const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who,PurpleConversation *conv, void *user_data) { - if (primary) { - std::string primaryString(primary); - if (primaryString == "Authorization Request Message:") { - LOG4CXX_INFO(logger, "Authorization Request Message: calling ok_cb(...)"); - ((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me."); - return NULL; - } - else if (primaryString == "Authorization Request Message:") { - LOG4CXX_INFO(logger, "Authorization Request Message: calling ok_cb(...)"); - ((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me."); - return NULL; - } - else if (primaryString == "Authorization Denied Message:") { - LOG4CXX_INFO(logger, "Authorization Deined Message: calling ok_cb(...)"); - ((PurpleRequestInputCb) ok_cb)(user_data, "Authorization denied."); - return NULL; - } - else { - LOG4CXX_WARN(logger, "Unhandled request input. primary=" << primaryString); - } - } - else if (title) { - std::string titleString(title); - if (titleString == "Xfire Invitation Message") { - LOG4CXX_INFO(logger, "Authorization Request Message: calling ok_cb(...)"); - ((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me."); - return NULL; - } - else { - LOG4CXX_WARN(logger, "Unhandled request input. title=" << titleString); - } - } - else { - LOG4CXX_WARN(logger, "Request input without primary string"); - } - return NULL; -} +struct inputRequest { + PurpleRequestInputCb ok_cb; + void *user_data; + std::string who; + PurpleAccount *account; + std::string mainJID; // JID of user connected with this request +}; static void *requestAction(const char *title, const char *primary, const char *secondary, int default_action, PurpleAccount *account, const char *who,PurpleConversation *conv, void *user_data, size_t action_count, va_list actions){ std::string t(title ? title : "NULL"); @@ -357,7 +326,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin { std::string protocol; getProtocolAndName(legacyName, name, protocol); - if (password.empty() && CONFIG_STRING(config, "service.protocol") != "prpl-telegram") { + if (password.empty() && protocol != "prpl-telegram" && protocol != "prpl-hangouts") { LOG4CXX_INFO(logger, name.c_str() << ": Empty password"); np->handleDisconnected(user, 1, "Empty password."); return; @@ -411,6 +380,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin { if (status_type != NULL) { purple_account_set_status_wrapped(account, purple_status_type_get_id_wrapped(status_type), TRUE, NULL); } + // OAuth helper + if (protocol == "prpl-hangouts") { + adminLegacyName = "hangouts"; + adminAlias = "hangouts"; + LOG4CXX_INFO(logger, user << ": Adding Buddy " << adminLegacyName << " " << adminAlias) + handleBuddyChanged(user, adminLegacyName, adminAlias, std::vector(), pbnetwork::STATUS_ONLINE); + } } void handleLogoutRequest(const std::string &user, const std::string &legacyName) { @@ -501,6 +477,16 @@ class SpectrumNetworkPlugin : public NetworkPlugin { if (account) { LOG4CXX_INFO(logger, "Sending message to '" << legacyName << "'"); PurpleConversation *conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_CHAT, legacyName.c_str(), account); + if (legacyName == adminLegacyName) { + // expect OAuth code + if (m_inputRequests.find(user) != m_inputRequests.end()) { + LOG4CXX_INFO(logger, "Updating token for '" << user << "'"); + m_inputRequests[user]->ok_cb(m_inputRequests[user]->user_data, message.c_str()); + m_inputRequests.erase(user); + } + return; + } + if (!conv) { conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_IM, legacyName.c_str(), account); if (!conv) { @@ -822,9 +808,12 @@ class SpectrumNetworkPlugin : public NetworkPlugin { std::map m_accounts; std::map m_vcards; std::map m_authRequests; + std::map m_inputRequests; std::map m_xfers; std::map m_unhandledXfers; std::vector m_waitingXfers; + std::string adminLegacyName; + std::string adminAlias; }; static bool getStatus(PurpleBuddy *m_buddy, pbnetwork::StatusType &status, std::string &statusMessage) { @@ -1519,13 +1508,64 @@ static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotif purple_buddy_icon_unref_wrapped(icon); } } - + np->handleVCard(np->m_accounts[account], np->m_vcards[np->m_accounts[account] + name], name, fullName, nickname, photo); np->m_vcards.erase(np->m_accounts[account] + name); return NULL; } +void * requestInput(const char *title, const char *primary,const char *secondary, const char *default_value, gboolean multiline, gboolean masked, gchar *hint,const char *ok_text, GCallback ok_cb,const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who,PurpleConversation *conv, void *user_data) { + if (primary) { + std::string primaryString(primary); + if (primaryString == "Authorization Request Message:") { + LOG4CXX_INFO(logger, "Authorization Request Message: calling ok_cb(...)"); + ((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me."); + return NULL; + } + else if (primaryString == "Authorization Request Message:") { + LOG4CXX_INFO(logger, "Authorization Request Message: calling ok_cb(...)"); + ((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me."); + return NULL; + } + else if (primaryString == "Authorization Denied Message:") { + LOG4CXX_INFO(logger, "Authorization Deined Message: calling ok_cb(...)"); + ((PurpleRequestInputCb) ok_cb)(user_data, "Authorization denied."); + return NULL; + } + else if (boost::starts_with(primaryString, "https://accounts.google.com/o/oauth2/auth")) { + LOG4CXX_INFO(logger, "prpl-hangouts oauth request"); + np->handleMessage(np->m_accounts[account], np->adminLegacyName, std::string("Please visit the following link and authorize this application: ") + primaryString, ""); + np->handleMessage(np->m_accounts[account], np->adminLegacyName, std::string("Reply with code provided by Google: ") + primaryString, ""); + inputRequest *req = new inputRequest; + req->ok_cb = (PurpleRequestInputCb)ok_cb; + req->user_data = user_data; + req->account = account; + req->mainJID = np->m_accounts[account]; + np->m_inputRequests[req->mainJID] = req; + return NULL; + } + else { + LOG4CXX_WARN(logger, "Unhandled request input. primary=" << primaryString); + } + } + else if (title) { + std::string titleString(title); + if (titleString == "Xfire Invitation Message") { + LOG4CXX_INFO(logger, "Authorization Request Message: calling ok_cb(...)"); + ((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me."); + return NULL; + } + else { + LOG4CXX_WARN(logger, "Unhandled request input. title=" << titleString); + } + } + else { + LOG4CXX_WARN(logger, "Request input without primary string"); + } + return NULL; +} + static PurpleNotifyUiOps notifyUiOps = { NULL, @@ -2103,6 +2143,9 @@ static void transportDataReceived(gpointer data, gint source, PurpleInputConditi if (CONFIG_STRING(config, "service.protocol") == "prpl-telegram") { cfg.setNeedPassword(false); } + if (CONFIG_STRING(config, "service.protocol") == "prpl-hangouts") { + cfg.setNeedPassword(false); + } if (CONFIG_STRING(config, "service.protocol") == "prpl-irc") { cfg.setNeedRegistration(false); }