Skip to content
Commits on Source (10)
......@@ -228,6 +228,7 @@ static std::string DISCORD_ACCESS_TOKEN = "discord_access_token";
static bool getUserToken(const std::string user, const std::string token_name, std::string &token_value) {
boost::mutex::scoped_lock lock(dblock);
UserInfo info;
return false;
if (storagebackend->getUser(user, info) == false) {
LOG4CXX_ERROR(logger, "Didn't find entry for " << user << " in the database!");
return false;
......@@ -239,6 +240,7 @@ static bool getUserToken(const std::string user, const std::string token_name, s
}
static bool storeUserToken(const std::string user, const std::string token_name, const std::string token_value) {
return false;
boost::mutex::scoped_lock lock(dblock);
UserInfo info;
if (storagebackend->getUser(user, info) == false) {
......@@ -394,16 +396,8 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
np->handleDisconnected(user, 1, "Empty password.");
return;
}
if (protocol == "prpl-hangouts") {
adminLegacyName = "hangouts";
adminAlias = "hangouts";
} else if (protocol == "prpl-steam-mobile") {
adminLegacyName = "steam-mobile";
adminAlias = "steam-mobile";
} else if (protocol == "prpl-eionrobb-discord") {
adminLegacyName = "discord";
adminAlias = "discord";
}
adminLegacyName = "spectrum2-libpurple-admin";
adminAlias = "libpurple admin";
if (!purple_find_prpl(protocol.c_str())) {
LOG4CXX_INFO(logger, name.c_str() << ": Invalid protocol '" << protocol << "'");
......@@ -569,11 +563,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
PurpleConversation *conv = purple_find_conversation_with_account(
PURPLE_CONV_TYPE_CHAT, LegacyNameToName(account, 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 << "'");
LOG4CXX_INFO(logger, "Input request for '" << user << "'");
m_inputRequests[user]->ok_cb(m_inputRequests[user]->user_data, message.c_str());
m_inputRequests.erase(user);
np->handleMessage(np->m_accounts[account], np->adminLegacyName, "Input submitted.");
} else {
np->handleMessage(np->m_accounts[account], np->adminLegacyName, "There's nothing to reply to.");
}
return;
}
......@@ -843,7 +839,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
}
if (CONFIG_STRING(config, "service.protocol") != "prpl-jabber") {
np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE);
// np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE);
const char *disp;
if ((disp = purple_account_get_name_for_display(account)) == NULL) {
if ((disp = purple_connection_get_display_name(account->gc)) == NULL) {
......@@ -852,9 +848,9 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
}
LOG4CXX_INFO(logger, user << ": Display name is " << disp << ", nickname is " << nickname);
if (nickname != disp) {
handleRoomNicknameChanged(np->m_accounts[account], room, disp);
np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE, "",
disp);
//handleRoomNicknameChanged(np->m_accounts[account], room, disp);
// np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE, "",
// disp);
}
}
......@@ -1589,6 +1585,7 @@ static void conv_chat_topic_changed(PurpleConversation *conv, const char *who, c
}
static void conv_present(PurpleConversation *conv) {
PurpleAccount *account = purple_conversation_get_account(conv);
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
LOG4CXX_INFO(logger, "Conversation presented");
conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE);
......@@ -1600,6 +1597,7 @@ static void conv_present(PurpleConversation *conv) {
}
std::string conversationName = purple_conversation_get_name(conv);
std::string conversationTitle = purple_conversation_get_title(conv);
np->handleRoomPresented(np->m_accounts[account], np->NameToLegacyName(account, conversationName));
PurpleAccount *account = purple_conversation_get_account(conv);
if (conversationName != conversationTitle) {
LOG4CXX_INFO(logger, "Conversation has a useful title, adding room information");
......@@ -1753,67 +1751,18 @@ void *requestInput(const char *title, const char *primary, const char *secondary
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") ||
boost::starts_with(primaryString, "https://www.youtube.com/watch?v=hlDhp-eNLMU")) {
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: "));
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 if (primaryString == "Set your Steam Guard Code" || primaryString == "Steam two-factor authentication") {
LOG4CXX_INFO(logger, "prpl-steam-mobile steam guard request");
np->handleMessage(np->m_accounts[account], np->adminLegacyName, std::string("Steam Guard code: "));
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 if (boost::starts_with(primaryString, "Enter the six-digit code")) {
LOG4CXX_INFO(logger, "prpl-discord 2FA request");
np->handleMessage(np->m_accounts[account], np->adminLegacyName, std::string("2FA code: "));
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);
}
LOG4CXX_INFO(logger, "Input request: " << primaryString);
np->handleMessage(np->m_accounts[account], np->adminLegacyName, 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 (void *)0x1;
} 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);
}
LOG4CXX_WARN(logger, "Unhandled request input. title=" << titleString);
} else {
LOG4CXX_WARN(logger, "Request input without primary string");
}
......@@ -1889,18 +1838,24 @@ static void RoomlistProgress(PurpleRoomlist *list, gboolean in_progress) {
GList *rooms;
std::list<std::string> m_topics;
PurplePlugin *plugin = purple_find_prpl(purple_account_get_protocol_id(list->account));
const char *protocol_id = purple_account_get_protocol_id(list->account);
PurplePlugin *plugin = purple_find_prpl(protocol_id);
PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
for (rooms = list->rooms; rooms != NULL; rooms = rooms->next) {
PurpleRoomlistRoom *room = (PurpleRoomlistRoom *)rooms->data;
std::string roomIdentifier = room->name;
if (roomId != -1) {
std::string roomIdentifier = "";
// prpl-slack specific hack: this prpl will put room IDs in its room list, and then refuse
// to accept said room IDs when joining channels. This is stupid, so hack around it.
if (roomId != -1 && strcmp(protocol_id, "prpl-slack") != 0) {
char *roomIdField = (char *)g_list_nth_data(purple_roomlist_room_get_fields(room), roomId);
if (roomIdField) {
roomIdentifier = std::string(roomIdField);
}
}
if (roomIdentifier == "") {
continue;
}
np->m_rooms[np->m_accounts[list->account]].push_back(roomIdentifier);
std::string roomName = "";
......@@ -1914,37 +1869,7 @@ static void RoomlistProgress(PurpleRoomlist *list, gboolean in_progress) {
parentRoom = purple_roomlist_room_get_parent(parentRoom);
}
if (nestedLevel > 0) {
/*
std::string roomNamePrefix = std::string(nestedLevel, '-');
if (roomNamePrefix != "") {
roomNamePrefix = roomNamePrefix + "> ";
}
roomName = roomNamePrefix;
*/
}
if (CONFIG_BOOL_DEFAULTED(config, "service.use_room_names", false)) {
roomName += room->name;
} else if (topicId == -1) {
roomName += room->name;
} else {
char *topic = (char *)g_list_nth_data(purple_roomlist_room_get_fields(room), topicId);
if (topic) {
roomName += topic;
} else if (usersId) {
char *users = (char *)g_list_nth_data(purple_roomlist_room_get_fields(room), usersId);
if (users) {
roomName += users;
} else {
// LOG4CXX_WARN(logger, "RoomList topic and users is NULL");
roomName += room->name;
}
} else {
// LOG4CXX_WARN(logger, "RoomList topic is NULL");
roomName += room->name;
}
}
roomName += room->name;
if (descriptionId != -1) {
char *description = (char *)g_list_nth_data(purple_roomlist_room_get_fields(room), descriptionId);
......@@ -2143,6 +2068,12 @@ static bool initPurple() {
purple_plugins_add_search_path(pluginsDir.c_str());
}
char *plugin_search_path = std::getenv("PURPLE_PLUGINS_DIR");
if (plugin_search_path) {
LOG4CXX_INFO(logger, "Adding plugin dir " << plugin_search_path << " from env var");
purple_plugins_add_search_path(plugin_search_path);
}
if (CONFIG_HAS_KEY(config, "purple.load_plugin")) {
std::string file = CONFIG_STRING(config, "purple.load_plugin");
PurplePlugin *plugin = purple_plugin_probe(file.c_str());
......@@ -2153,11 +2084,17 @@ static bool initPurple() {
}
}
std::string tempDir = "/tmp/" + boost::filesystem::unique_path().string();
boost::filesystem::create_directories(tempDir);
LOG4CXX_INFO(logger, "Setting libpurple user directory to: " << tempDir);
purple_util_set_user_dir(tempDir.c_str());
if (CONFIG_HAS_KEY(config, "purple.user_dir")) {
std::string userDir = CONFIG_STRING(config, "purple.user_dir");
LOG4CXX_WARN(logger, "Setting libpurple user directory to: " << userDir);
LOG4CXX_WARN(logger, "This is hacky and not recommended unless necessary!");
purple_util_set_user_dir(userDir.c_str());
} else {
std::string tempDir = "/tmp/" + boost::filesystem::unique_path().string();
boost::filesystem::create_directories(tempDir);
LOG4CXX_INFO(logger, "Setting libpurple user directory to: " << tempDir);
purple_util_set_user_dir(tempDir.c_str());
}
purple_core_set_ui_ops(&coreUiOps);
if (CONFIG_STRING_DEFAULTED(config, "service.eventloop", "") == "libev") {
......@@ -2305,21 +2242,6 @@ 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") {
storagebackend = StorageBackend::createBackend(config.get(), error);
if (storagebackend == NULL) {
LOG4CXX_ERROR(logger, "Error creating StorageBackend! " << error);
LOG4CXX_ERROR(logger, "Selected libpurple protocol need storage backend "
"configured to work! "
<< error);
return NetworkPlugin::StorageBackendNeeded;
} else if (!storagebackend->connect()) {
LOG4CXX_ERROR(logger, "Can't connect to database!");
return -1;
}
}
initPurple();
......
......@@ -362,6 +362,8 @@ class NetworkPlugin {
shared = 0;
}
virtual void handleRoomPresented(const std::string &user, const std::string &r);
virtual void handleExitRequest() {
exit(1);
}
......
......@@ -258,7 +258,7 @@ void Conversation::handleMessage(std::shared_ptr<Swift::Message> &message, const
std::string n = nickname;
if (n.empty()) {
n = " ";
n = "[empty]";
}
std::map<std::string, Participant>::iterator it = m_participants.find(n);
......
......@@ -1189,7 +1189,7 @@ void NetworkPluginServer::send(std::shared_ptr<Swift::Connection> &c, const std:
}
void NetworkPluginServer::pingTimeout() {
LOG4CXX_DEBUG(logger, "Sending PING to backends");
LOG4CXX_TRACE(logger, "Sending PING to backends");
// TODO: move to separate timer, those 2 loops could be expensive
// Some users are connected for weeks and they are blocking backend to be
// destroyed and its memory to be freed. We are finding users who are inactive
......@@ -1977,7 +1977,7 @@ void NetworkPluginServer::sendPing(Backend *c) {
wrap.SerializeToString(&message);
if (c->connection) {
LOG4CXX_DEBUG(logger, "PING to " << c << " (ID=" << c->id << ")");
LOG4CXX_TRACE(logger, "PING to " << c << " (ID=" << c->id << ")");
send(c->connection, message);
c->pongReceived = false;
} else {
......
......@@ -534,6 +534,7 @@ bool PQXXBackend::messageSeen(long userId, const std::string &msgId) {
} catch (std::exception &e) {
LOG4CXX_ERROR(logger, e.what());
connect();
return false;
}
}
std::vector<Swift::Message> PQXXBackend::getHistory(long userId, const std::string &mucId,
......
......@@ -137,23 +137,6 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) {
LOG4CXX_DEBUG(logger, "PRESENCE " << presence->getFrom().toString() << " " << presence->getTo().toString());
std::shared_ptr<Swift::VCardUpdate> vcardUpdate = presence->getPayload<Swift::VCardUpdate>();
/*
if (vcardUpdate) {
std::string value = "";
int type = (int) TYPE_STRING;
if (m_storageBackend) {
m_storageBackend->getUserSetting(m_userInfo.id, "photohash",
type, value);
}
if (value != vcardUpdate->getPhotoHash()) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Requesting
VCard"); if (m_storageBackend) {
m_storageBackend->updateUserSetting(m_userInfo.id,
"photohash", vcardUpdate->getPhotoHash());
}
requestVCard();
}
}*/
if (!m_connected) {
// we are not connected to legacy network, so we should do it when
......@@ -190,7 +173,7 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) {
}
if (getUserSetting("stay_connected") != "1") {
LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << room);
LOG4CXX_INFO(logger, m_jid.toString() << ": Leaving room " << room);
onRawPresenceReceived(presence);
leaveRoom(room);
}
......@@ -291,16 +274,6 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Last client disconnected");
}
}
if (presence->getType() != Swift::Presence::Unavailable) {
sendCurrentPresence();
}
// This resource is new, so we have to send buddies presences
if (presence->getType() != Swift::Presence::Unavailable && currentResourcesCount != m_resources) {
m_rosterManager->sendCurrentPresences(presence->getFrom());
}
m_resources = currentResourcesCount;
// Change legacy network presence
......
......@@ -34,10 +34,26 @@ let
sha256 = "1xxhramzm135v4g8vjapy2gnc7hfwhmgr0ya8y520m1wh16q5csp";
};
});
purple-tdlib = pkgs.stdenv.mkDerivation {
pname = "purple-tdlib";
version = "unstable-2020-07-05";
src = pkgs.fetchFromGitHub {
owner = "ars3niy";
repo = "tdlib-purple";
rev = "a7af4854ead8c945489b8b5041d21d5f42f4d622";
sha256 = "07d74bri4dr3kfm652h9z06wnasrsh6za6s45y94cd8ch68h5mnx";
};
nativeBuildInputs = [ pkgs.pkgconfig pkgs.cmake ];
buildInputs = [ libpurple pkgs.tdlib pkgs.glib pkgs.pcre pkgs.libwebp pkgs.libpng ];
PKG_CONFIG_PURPLE_PLUGINDIR = "${placeholder "out"}/lib/purple-2";
PKG_CONFIG_PURPLE_DATAROOTDIR = "${placeholder "out"}/share";
};
in
pkgs.dockerTools.buildLayeredImage {
name = "eu.gcr.io/etainfra/spectrum2";
tag = "latest";
contents = [ spectrum2 purple-discord purple-slack purple-facebook ];
contents = [ spectrum2 purple-discord purple-slack purple-facebook purple-tdlib ];
config.Entrypoint = [ "${spectrum2}/bin/spectrum2" ];
config.Env = [ "PURPLE_PLUGINS_DIR=/lib/purple-2" ];
}
......@@ -323,6 +323,21 @@ void NetworkPlugin::handleRoomNicknameChanged(const std::string &user, const std
send(message);
}
void NetworkPlugin::handleRoomPresented(const std::string &user, const std::string &r) {
pbnetwork::Room room;
room.set_username(user);
room.set_nickname("");
room.set_room(r);
room.set_password("");
std::string message;
room.SerializeToString(&message);
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_JOIN_ROOM);
send(message);
}
void NetworkPlugin::handleFTStart(const std::string &user, const std::string &buddyName, const std::string fileName,
unsigned long size) {
pbnetwork::File room;
......
......@@ -192,8 +192,8 @@ void XMPPFrontend::addRoomToRoomList(const std::string &handle, const std::strin
void XMPPFrontend::sendPresence(Swift::Presence::ref presence) {
if (!presence->getFrom().getNode().empty()) {
presence->addPayload(std::shared_ptr<Swift::Payload>(new Swift::CapsInfo(
static_cast<XMPPUserManager *>(m_userManager)->getDiscoItemsResponder()->getBuddyCapsInfo())));
//presence->addPayload(std::shared_ptr<Swift::Payload>(new Swift::CapsInfo(
// static_cast<XMPPUserManager *>(m_userManager)->getDiscoItemsResponder()->getBuddyCapsInfo())));
}
m_stanzaChannel->sendPresence(presence);
......
......@@ -89,10 +89,8 @@ void DiscoInfoResponder::updateFeatures() {
features2.push_back("http://jabber.org/protocol/disco#info");
features2.push_back("http://jabber.org/protocol/disco#items");
features2.push_back("http://jabber.org/protocol/commands");
if (CONFIG_BOOL_DEFAULTED(m_config, "features.muc", false)) {
features2.push_back("http://jabber.org/protocol/muc");
}
features2.insert(features2.end(), this->m_transportFeatures.begin(), this->m_transportFeatures.end());
features2.push_back("http://jabber.org/protocol/muc");
features2.insert(features2.end(), this->m_transportFeatures.begin(), this->m_transportFeatures.end());
setTransportFeatures(features2);
std::list<std::string> features;
......