Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/SpectrumIM/spectrum2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'backends/libpurple/main.cpp')
-rw-r--r--backends/libpurple/main.cpp320
1 files changed, 102 insertions, 218 deletions
diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp
index ad855558..1d2172ee 100644
--- a/backends/libpurple/main.cpp
+++ b/backends/libpurple/main.cpp
@@ -57,19 +57,6 @@ bool firstPing = true;
using namespace Transport;
-template <class T> T fromString(const std::string &str) {
- T i;
- std::istringstream os(str);
- os >> i;
- return i;
-}
-
-template <class T> std::string stringOf(T object) {
- std::ostringstream os;
- os << object;
- return (os.str());
-}
-
static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
@@ -112,14 +99,6 @@ bool caching = true;
static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info);
-static gboolean ft_ui_ready(void *data) {
- PurpleXfer *xfer = (PurpleXfer *) data;
- FTData *ftdata = (FTData *) xfer->ui_data;
- ftdata->timer = 0;
- purple_xfer_ui_ready_wrapped((PurpleXfer *) data);
- return FALSE;
-}
-
/*
Authorization requests from buddies are cached for the duration of the session.
To authorize or deny, call the cached callbacks.
@@ -241,6 +220,7 @@ static boost::mutex dblock;
static std::string OAUTH_TOKEN = "hangouts_oauth_token";
static std::string STEAM_ACCESS_TOKEN = "steammobile_access_token";
static std::string DISCORD_ACCESS_TOKEN = "discord_access_token";
+static std::string WHATSMEOW_ACCESS_TOKEN = "credentials";
static bool getUserToken(const std::string user, const std::string token_name, std::string &token_value)
{
@@ -338,7 +318,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
break;
case PURPLE_PREF_INT:
- purple_account_set_int_wrapped(account, strippedKey.c_str(), fromString<int>(keyItem.second.as<std::string>()));
+ purple_account_set_int_wrapped(account, strippedKey.c_str(), std::stoi(keyItem.second.as<std::string>()));
break;
case PURPLE_PREF_STRING:
@@ -352,7 +332,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
}
if (!found) {
- purple_account_set_string_wrapped(account, strippedKey.c_str(), keyItem.second.as<std::string>().c_str());
+ LOG4CXX_ERROR(logger, "Unknown [purple] option: " << strippedKey);
}
i++;
}
@@ -361,7 +341,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
gsize length;
gboolean ret = g_file_get_contents ("gfire.cfg", &contents, &length, NULL);
if (ret) {
- purple_account_set_int_wrapped(account, "version", fromString<int>(std::string(contents, length)));
+ purple_account_set_int_wrapped(account, "version", std::stoi(std::string(contents, length)));
}
@@ -487,6 +467,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
purple_account_set_string_wrapped(account, "token", token.c_str());
}
}
+ else if (protocol == "prpl-hehoe-whatsmeow") {
+ std::string token;
+ getUserToken(user, WHATSMEOW_ACCESS_TOKEN, token);
+ if (!token.empty()) {
+ purple_account_set_string_wrapped(account, "credentials", token.c_str());
+ }
+ }
setDefaultAccountOptions(account);
@@ -521,7 +508,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
account->ui_data = NULL;
}
if (purple_account_get_int_wrapped(account, "version", 0) != 0) {
- std::string data = stringOf(purple_account_get_int_wrapped(account, "version", 0));
+ std::string data = std::to_string(purple_account_get_int_wrapped(account, "version", 0));
g_file_set_contents ("gfire.cfg", data.c_str(), data.size(), NULL);
}
// VALGRIND_DO_LEAK_CHECK;
@@ -891,44 +878,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
purple_conversation_destroy_wrapped(conv);
}
- void handleFTStartRequest(const std::string &user, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long ftID) {
- PurpleXfer *xfer = m_unhandledXfers[user + fileName + buddyName];
- if (xfer) {
- m_unhandledXfers.erase(user + fileName + buddyName);
- FTData *ftData = (FTData *) xfer->ui_data;
-
- ftData->id = ftID;
- m_xfers[ftID] = xfer;
- purple_xfer_request_accepted_wrapped(xfer, fileName.c_str());
- purple_xfer_ui_ready_wrapped(xfer);
- }
- }
-
- void handleFTFinishRequest(const std::string &user, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long ftID) {
- PurpleXfer *xfer = m_unhandledXfers[user + fileName + buddyName];
- if (xfer) {
- m_unhandledXfers.erase(user + fileName + buddyName);
- purple_xfer_request_denied_wrapped(xfer);
- }
- }
-
- void handleFTPauseRequest(unsigned long ftID) {
- PurpleXfer *xfer = m_xfers[ftID];
- if (!xfer)
- return;
- FTData *ftData = (FTData *) xfer->ui_data;
- ftData->paused = true;
- }
-
- void handleFTContinueRequest(unsigned long ftID) {
- PurpleXfer *xfer = m_xfers[ftID];
- if (!xfer)
- return;
- FTData *ftData = (FTData *) xfer->ui_data;
- ftData->paused = false;
- purple_xfer_ui_ready_wrapped(xfer);
- }
-
void sendData(const std::string &string) {
#ifdef WIN32
::send(main_socket, string.c_str(), string.size(), 0);
@@ -939,30 +888,12 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
writeInput = purple_input_add_wrapped(main_socket, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
}
- void readyForData() {
- if (m_waitingXfers.empty())
- return;
- std::vector<PurpleXfer *> tmp;
- tmp.swap(m_waitingXfers);
-
- for (std::vector<PurpleXfer *>::const_iterator it = tmp.begin(); it != tmp.end(); it++) {
- FTData *ftData = (FTData *) (*it)->ui_data;
- if (ftData->timer == 0) {
- ftData->timer = purple_timeout_add_wrapped(1, ft_ui_ready, *it);
- }
-// purple_xfer_ui_ready_wrapped(xfer);
- }
- }
-
std::map<std::string, PurpleAccount *> m_sessions;
std::map<PurpleAccount *, std::string> m_accounts;
std::map<std::string, unsigned int> m_vcards;
AuthRequestList m_authRequests;
std::map<std::string, inputRequest *> m_inputRequests;
std::map<std::string, std::list<std::string> > m_rooms;
- std::map<unsigned long, PurpleXfer *> m_xfers;
- std::map<std::string, PurpleXfer *> m_unhandledXfers;
- std::vector<PurpleXfer *> m_waitingXfers;
std::string adminLegacyName;
std::string adminAlias;
};
@@ -1480,7 +1411,7 @@ static bool conv_msg_to_image(const char* msg, std::string* xhtml_, std::string*
static void conv_write_im(PurpleConversation *conv, const char *who, const char *msg, PurpleMessageFlags flags, time_t mtime) {
- LOG4CXX_INFO(logger, "conv_write_im()");
+ LOG4CXX_DEBUG(logger, "conv_write_im(): msg='" << msg << "', flags=" << flags);
bool isCarbon = false;
if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
@@ -1506,8 +1437,6 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char
std::string message_; //plain text
std::string xhtml_; //enhanced xhtml, if available
- LOG4CXX_DEBUG(logger, "conv_write_im(): msg='" << msg << "', flags=" << flags);
-
if (flags & PURPLE_MESSAGE_IMAGES) {
//Store image locally and adjust the message
if (!conv_msg_to_image(msg, &xhtml_, &message_))
@@ -1968,142 +1897,92 @@ static PurpleAccountUiOps accountUiOps =
NULL
};
-static void XferCreated(PurpleXfer *xfer) {
- if (!xfer) {
- return;
- }
-
- PurpleAccount *account = purple_xfer_get_account_wrapped(xfer);
- np->handleFTStart(np->m_accounts[account], xfer->who, purple_xfer_get_filename_wrapped(xfer), purple_xfer_get_size_wrapped(xfer));
-}
-
-static void XferDestroyed(PurpleXfer *xfer) {
- std::remove(np->m_waitingXfers.begin(), np->m_waitingXfers.end(), xfer);
- FTData *ftdata = (FTData *) xfer->ui_data;
- if (ftdata && ftdata->timer) {
- purple_timeout_remove_wrapped(ftdata->timer);
- }
- if (ftdata) {
- np->m_xfers.erase(ftdata->id);
+static gboolean
+ensure_path_exists(const char *dir)
+{
+ if (!g_file_test(dir, G_FILE_TEST_IS_DIR))
+ {
+ if (g_mkdir_with_parents(dir, S_IRUSR | S_IWUSR | S_IXUSR)) {
+ return FALSE;
+ }
}
+ return TRUE;
}
-static void xferCanceled(PurpleXfer *xfer) {
+static void newXfer(PurpleXfer *xfer) {
PurpleAccount *account = purple_xfer_get_account_wrapped(xfer);
- std::string filename(xfer ? purple_xfer_get_filename_wrapped(xfer) : "");
- std::string w = xfer->who;
+ std::string remote_filename(xfer ? purple_xfer_get_filename_wrapped(xfer) : "");
+ std::string w = xfer->who ? xfer->who : "";
size_t pos = w.find("/");
if (pos != std::string::npos)
w.erase((int) pos, w.length() - (int) pos);
-
- FTData *ftdata = (FTData *) xfer->ui_data;
-
- np->handleFTFinish(np->m_accounts[account], w, filename, purple_xfer_get_size_wrapped(xfer), ftdata ? ftdata->id : 0);
- std::remove(np->m_waitingXfers.begin(), np->m_waitingXfers.end(), xfer);
- if (ftdata && ftdata->timer) {
- purple_timeout_remove_wrapped(ftdata->timer);
+ int count = 1;
+ gchar **name_and_ext;
+ const gchar *name;
+ gchar *ext;
+ std::string web_dir = CONFIG_STRING(config, "service.web_directory");
+ std::string web_url = CONFIG_STRING(config, "service.web_url");
+ if (web_dir.empty() || web_url.empty()) {
+ LOG4CXX_DEBUG(logger, "Denied " << remote_filename << " from " << w << ", web_directory is disabled.");
+ purple_xfer_request_denied_wrapped(xfer);
+ return;
}
- purple_xfer_unref_wrapped(xfer);
-}
-
-static void fileSendStart(PurpleXfer *xfer) {
-// FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
-// repeater->fileSendStart();
-}
-
-static void fileRecvStart(PurpleXfer *xfer) {
-// FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
-// repeater->fileRecvStart();
- FTData *ftData = (FTData *) xfer->ui_data;
- if (ftData->timer == 0) {
- ftData->timer = purple_timeout_add_wrapped(1, ft_ui_ready, xfer);
+ LOG4CXX_INFO(logger, "Accepting " << remote_filename << " from " << w);
+ gchar *dirname = g_build_filename(web_dir.c_str(), NULL);
+ gchar *filename = g_build_filename(dirname, remote_filename.c_str(), NULL);
+ // Uniqifying code taken from Pidgin autoaccept plugin
+ /* Split at the first dot, to avoid uniquifying "foo.tar.gz" to "foo.tar-2.gz" */
+ name_and_ext = g_strsplit(filename, ".", 2);
+ name = name_and_ext[0];
+ if (name == NULL)
+ {
+ g_strfreev(name_and_ext);
+ g_return_if_reached();
}
-}
-
-static void newXfer(PurpleXfer *xfer) {
- PurpleAccount *account = purple_xfer_get_account_wrapped(xfer);
- std::string filename(xfer ? purple_xfer_get_filename_wrapped(xfer) : "");
- purple_xfer_ref_wrapped(xfer);
- std::string w = xfer->who;
- size_t pos = w.find("/");
- if (pos != std::string::npos)
- w.erase((int) pos, w.length() - (int) pos);
-
- FTData *ftdata = new FTData;
- ftdata->paused = false;
- ftdata->id = 0;
- ftdata->timer = 0;
- xfer->ui_data = (void *) ftdata;
-
- np->m_unhandledXfers[np->m_accounts[account] + filename + w] = xfer;
-
- np->handleFTStart(np->m_accounts[account], w, filename, purple_xfer_get_size_wrapped(xfer));
-}
-
-static void XferReceiveComplete(PurpleXfer *xfer) {
-// FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
-// repeater->_tryToDeleteMe();
-// GlooxMessageHandler::instance()->ftManager->handleXferFileReceiveComplete(xfer);
- std::remove(np->m_waitingXfers.begin(), np->m_waitingXfers.end(), xfer);
- FTData *ftdata = (FTData *) xfer->ui_data;
- if (ftdata && ftdata->timer) {
- purple_timeout_remove_wrapped(ftdata->timer);
- }
- purple_xfer_unref_wrapped(xfer);
-}
-
-static void XferSendComplete(PurpleXfer *xfer) {
-// FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
-// repeater->_tryToDeleteMe();
- std::remove(np->m_waitingXfers.begin(), np->m_waitingXfers.end(), xfer);
- FTData *ftdata = (FTData *) xfer->ui_data;
- if (ftdata && ftdata->timer) {
- purple_timeout_remove_wrapped(ftdata->timer);
+ if (name_and_ext[1] != NULL)
+ {
+ /* g_strsplit does not include the separator in each chunk. */
+ ext = g_strdup_printf(".%s", name_and_ext[1]);
}
- purple_xfer_unref_wrapped(xfer);
-}
-
-static gssize XferWrite(PurpleXfer *xfer, const guchar *buffer, gssize size) {
- FTData *ftData = (FTData *) xfer->ui_data;
- std::string data((const char *) buffer, (size_t) size);
-// std::cout << "xferwrite\n";
- if (!ftData->paused) {
-// std::cout << "adding xfer to waitingXfers queue\n";
- np->m_waitingXfers.push_back(xfer);
+ else
+ {
+ ext = g_strdup("");
+ }
+ /* Make sure the file doesn't exist. Do we want some better checking than this? */
+ /* FIXME: There is a race here: if the newly uniquified file name gets created between
+ * this g_file_test and the transfer starting, the file created in the meantime
+ * will be clobbered. But it's not at all straightforward to fix.
+ */
+ while (g_file_test(filename, G_FILE_TEST_EXISTS))
+ {
+ char *file = g_strdup_printf("%s-%d%s", name, count++, ext);
+ g_free(filename);
+ filename = g_build_filename(dirname, file, NULL);
+ g_free(file);
}
- np->handleFTData(ftData->id, data);
- return size;
-}
-static void XferNotSent(PurpleXfer *xfer, const guchar *buffer, gsize size) {
-// FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
-// repeater->handleDataNotSent(buffer, size);
+ purple_xfer_request_accepted_wrapped(xfer, filename);
+ g_strfreev(name_and_ext);
+ g_free(ext);
+ g_free(dirname);
+ g_free(filename);
}
-static gssize XferRead(PurpleXfer *xfer, guchar **buffer, gssize size) {
-// FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
-// int data_size = repeater->getDataToSend(buffer, size);
-// if (data_size == 0)
-// return 0;
-//
-// return data_size;
- return 0;
+static void XferReceiveComplete(PurpleXfer *xfer) {
+ std::string filename(xfer ? purple_xfer_get_local_filename_wrapped(xfer) : "");
+ std::string w = xfer->who ? xfer->who : "";
+ std::string message = xfer->message ? xfer->message : "";
+ LOG4CXX_INFO(logger, "Received " << filename << " from " << w);
+ PurpleAccount *account = purple_xfer_get_account_wrapped(xfer);
+ std::string web_url = CONFIG_STRING(config, "service.web_url");
+ pbnetwork::Attachment attachment;
+ gchar *base_filename = g_path_get_basename(filename.c_str());
+ attachment.set_url(web_url + "/" + std::string(base_filename));
+ g_free(base_filename);
+ std::vector<pbnetwork::Attachment> attachments = { attachment };
+ np->handleMessage(np->m_accounts[account], w, message, "", "", xfer->end_time? std::to_string(xfer->end_time) : "", false, false, false, attachments);
}
-static PurpleXferUiOps xferUiOps =
-{
- XferCreated,
- XferDestroyed,
- NULL,
- NULL,
- xferCanceled,
- xferCanceled,
- XferWrite,
- XferRead,
- XferNotSent,
- NULL
-};
-
static void RoomlistProgress(PurpleRoomlist *list, gboolean in_progress)
{
if (!in_progress) {
@@ -2243,7 +2122,6 @@ static void transport_core_ui_init(void)
purple_accounts_set_ui_ops_wrapped(&accountUiOps);
purple_notify_set_ui_ops_wrapped(&notifyUiOps);
purple_request_set_ui_ops_wrapped(&requestUiOps);
- purple_xfers_set_ui_ops_wrapped(&xferUiOps);
purple_connections_set_ui_ops_wrapped(&conn_ui_ops);
purple_conversations_set_ui_ops_wrapped(&conversation_ui_ops);
purple_roomlist_set_ui_ops_wrapped(&roomlist_ui_ops);
@@ -2357,6 +2235,9 @@ static void signed_on(PurpleConnection *gc, gpointer unused) {
else if (CONFIG_STRING(config, "service.protocol") == "prpl-eionrobb-discord") {
storeUserToken(np->m_accounts[account], DISCORD_ACCESS_TOKEN, purple_account_get_string_wrapped(account, "token", NULL));
}
+ else if (CONFIG_STRING(config, "service.protocol") == "prpl-hehoe-whatsmeow") {
+ storeUserToken(np->m_accounts[account], WHATSMEOW_ACCESS_TOKEN, purple_account_get_string_wrapped(account, "credentials", NULL));
+ }
}
static void printDebug(PurpleDebugLevel level, const char *category, const char *arg_s) {
@@ -2498,11 +2379,8 @@ static bool initPurple() {
purple_signal_connect_wrapped(purple_blist_get_handle_wrapped(), "blist-node-removed", &blist_handle,PURPLE_CALLBACK(NodeRemoved), NULL);
purple_signal_connect_wrapped(purple_conversations_get_handle_wrapped(), "chat-topic-changed", &conversation_handle, PURPLE_CALLBACK(conv_chat_topic_changed), NULL);
static int xfer_handle;
- purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-send-start", &xfer_handle, PURPLE_CALLBACK(fileSendStart), NULL);
- purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-recv-start", &xfer_handle, PURPLE_CALLBACK(fileRecvStart), NULL);
- purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-recv-request", &xfer_handle, PURPLE_CALLBACK(newXfer), NULL);
- purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-recv-complete", &xfer_handle, PURPLE_CALLBACK(XferReceiveComplete), NULL);
- purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-send-complete", &xfer_handle, PURPLE_CALLBACK(XferSendComplete), NULL);
+ purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-recv-request", &xfer_handle, PURPLE_CALLBACK(newXfer), &xfer_handle);
+ purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-recv-complete", &xfer_handle, PURPLE_CALLBACK(XferReceiveComplete), &xfer_handle);
//
// purple_commands_init();
@@ -2543,12 +2421,17 @@ static void transportDataReceived(gpointer data, gint source, PurpleInputConditi
cfg.setNeedRegistration(false);
}
else {
- PurplePlugin *plugin = purple_find_prpl_wrapped(CONFIG_STRING(config, "service.protocol").c_str());
- PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
- if (prpl_info) {
- bool isPasswordlessPlugin = prpl_info->options & OPT_PROTO_NO_PASSWORD;
- LOG4CXX_INFO(logger, "passwordless backend: " << isPasswordlessPlugin);
- cfg.setNeedPassword(!isPasswordlessPlugin);
+ std::string protocol = CONFIG_STRING(config, "service.protocol");
+ PurplePlugin *plugin = purple_find_prpl_wrapped(protocol.c_str());
+ if (plugin) {
+ PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
+ if (prpl_info) {
+ bool isPasswordlessPlugin = prpl_info->options & OPT_PROTO_NO_PASSWORD;
+ LOG4CXX_INFO(logger, "passwordless backend: " << isPasswordlessPlugin);
+ cfg.setNeedPassword(!isPasswordlessPlugin);
+ }
+ } else {
+ LOG4CXX_ERROR(logger, "Protocol not found: " << protocol);
}
cfg.setNeedRegistration(true);
}
@@ -2562,7 +2445,6 @@ static void transportDataReceived(gpointer data, gint source, PurpleInputConditi
purple_input_remove_wrapped(writeInput);
writeInput = 0;
}
- np->readyForData();
}
}
@@ -2593,7 +2475,9 @@ int main(int argc, char **argv) {
config = std::shared_ptr<Config>(cfg);
Logging::initBackendLogging(config.get());
- if (CONFIG_STRING(config, "service.protocol") == "prpl-hangouts" || CONFIG_STRING(config, "service.protocol") == "prpl-steam-mobile" || CONFIG_STRING(config, "service.protocol") == "prpl-eionrobb-discord") {
+ if (CONFIG_STRING(config, "service.protocol") == "prpl-hangouts" || CONFIG_STRING(config, "service.protocol") == "prpl-steam-mobile"
+ || CONFIG_STRING(config, "service.protocol") == "prpl-eionrobb-discord" || CONFIG_STRING(config, "service.protocol") == "prpl-hehoe-whatsmeow")
+ {
storagebackend = StorageBackend::createBackend(config.get(), error);
if (storagebackend == NULL) {
LOG4CXX_ERROR(logger, "Error creating StorageBackend! " << error);