From 393cf1cc03032c5938bcc57d54659b6aeb415aa3 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Wed, 6 Feb 2013 21:57:59 +0100 Subject: [PATCH] fix autoregistration --- backends/skype/main.cpp | 547 +------------------------------ include/transport/protocol.proto | 4 + src/usermanager.cpp | 4 +- 3 files changed, 19 insertions(+), 536 deletions(-) diff --git a/backends/skype/main.cpp b/backends/skype/main.cpp index 5d603d36..17c5ac6f 100644 --- a/backends/skype/main.cpp +++ b/backends/skype/main.cpp @@ -1,4 +1,6 @@ #include "glib.h" +#include +#include "sqlite3.h" #include #include "transport/config.h" @@ -20,16 +22,15 @@ #ifndef __FreeBSD__ #include "malloc.h" #endif -#include -#include "sqlite3.h" +#include "skype.h" DEFINE_LOGGER(logger, "backend"); using namespace Transport; -class SpectrumNetworkPlugin; +class SkypePlugin; #define GET_RESPONSE_DATA(RESP, DATA) ((RESP.find(std::string(DATA) + " ") != std::string::npos) ? RESP.substr(RESP.find(DATA) + strlen(DATA) + 1) : ""); #define GET_PROPERTY(VAR, OBJ, WHICH, PROP) std::string VAR = sk->send_command(std::string("GET ") + OBJ + " " + WHICH + " " + PROP); \ @@ -70,7 +71,7 @@ class SpectrumNetworkPlugin; LOG4CXX_ERROR(logger, NAME<< (sqlite3_errmsg(db) == NULL ? "" : sqlite3_errmsg(db)));\ } -SpectrumNetworkPlugin *np; +SkypePlugin *np; int m_sock; static int writeInput; @@ -97,50 +98,14 @@ static pbnetwork::StatusType getStatus(const std::string &st) { return status; } -class Skype { +class SkypePlugin : public NetworkPlugin { public: - Skype(const std::string &user, const std::string &username, const std::string &password); - ~Skype() { LOG4CXX_INFO(logger, "Skype instance desctuctor"); logout(); } - void login(); - void logout(); - std::string send_command(const std::string &message); - - const std::string &getUser() { - return m_user; - } - - const std::string &getUsername() { - return m_username; - } - - bool createDBusProxy(); - bool loadSkypeBuddies(); - - int getPid() { - return (int) m_pid; - } - - private: - std::string m_username; - std::string m_password; - GPid m_pid; - DBusGConnection *m_connection; - DBusGProxy *m_proxy; - std::string m_user; - int m_timer; - int m_counter; - int fd_output; - std::map m_groups; -}; - -class SpectrumNetworkPlugin : public NetworkPlugin { - public: - SpectrumNetworkPlugin(Config *config, const std::string &host, int port) : NetworkPlugin() { + SkypePlugin(Config *config, const std::string &host, int port) : NetworkPlugin() { this->config = config; LOG4CXX_INFO(logger, "Starting the backend."); } - ~SpectrumNetworkPlugin() { + ~SkypePlugin() { for (std::map::iterator it = m_accounts.begin(); it != m_accounts.end(); it++) { delete (*it).first; } @@ -153,7 +118,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin { } LOG4CXX_INFO(logger, "Creating account with name '" << name << "'"); - Skype *skype = new Skype(user, name, password); + Skype *skype = new Skype(this, user, name, password); m_sessions[user] = skype; m_accounts[skype] = user; @@ -391,495 +356,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin { }; -Skype::Skype(const std::string &user, const std::string &username, const std::string &password) { - m_username = username; - m_user = user; - m_password = password; - m_pid = 0; - m_connection = 0; - m_proxy = 0; - m_timer = -1; - m_counter = 0; -} - - -static gboolean load_skype_buddies(gpointer data) { - Skype *skype = (Skype *) data; - return skype->loadSkypeBuddies(); -} - -bool Skype::createDBusProxy() { - if (m_proxy == NULL) { - LOG4CXX_INFO(logger, "Creating DBus proxy for com.Skype.Api."); - m_counter++; - - GError *error = NULL; - m_proxy = dbus_g_proxy_new_for_name_owner (m_connection, "com.Skype.API", "/com/Skype", "com.Skype.API", &error); - if (m_proxy == NULL && error != NULL) { - LOG4CXX_INFO(logger, m_username << ":" << error->message); - - if (m_counter == 15) { - LOG4CXX_ERROR(logger, "Logging out, proxy couldn't be created: " << error->message); - np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, error->message); - logout(); - g_error_free(error); - return FALSE; - } - g_error_free(error); - } - - if (m_proxy) { - LOG4CXX_INFO(logger, "Proxy created."); - DBusObjectPathVTable vtable; - vtable.message_function = &skype_notify_handler; - dbus_connection_register_object_path(dbus_g_connection_get_connection(m_connection), "/com/Skype/Client", &vtable, this); - - m_counter = 0; - m_timer = g_timeout_add_seconds(1, load_skype_buddies, this); - return FALSE; - } - return TRUE; - } - return FALSE; -} - -static gboolean create_dbus_proxy(gpointer data) { - Skype *skype = (Skype *) data; - return skype->createDBusProxy(); -} - -void Skype::login() { - if (m_username.find("..") == 0 || m_username.find("/") != std::string::npos) { - np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Invalid username"); - return; - } - boost::filesystem::remove_all(std::string("/tmp/skype/") + m_username); - - boost::filesystem::path path(std::string("/tmp/skype/") + m_username); - if (!boost::filesystem::exists(path)) { - boost::filesystem::create_directories(path); - boost::filesystem::path path2(std::string("/tmp/skype/") + m_username + "/" + m_username ); - boost::filesystem::create_directories(path2); - } - - std::string shared_xml = "\n" - "(time(NULL)) + ".0\">\n" - "\n" - "2\n" - "en\n" - "\n" - "\n"; - g_file_set_contents(std::string(std::string("/tmp/skype/") + m_username + "/shared.xml").c_str(), shared_xml.c_str(), -1, NULL); - - std::string config_xml = "\n" - "(time(NULL)) + ".0\">\n" - "\n" - "\n" - "30000000\n" - "300000000\n" - "" + boost::lexical_cast(time(NULL)) + "\n" - "\n" - "\n" - "\n" - "\n" - "Spectrum\n" - "\n" - "\n" - "\n" - "\n"; - g_file_set_contents(std::string(std::string("/tmp/skype/") + m_username + "/" + m_username +"/config.xml").c_str(), config_xml.c_str(), -1, NULL); - - sleep(1); - std::string db_path = std::string("/tmp/skype/") + m_username; - char *db = (char *) malloc(db_path.size() + 1); - strcpy(db, db_path.c_str()); - LOG4CXX_INFO(logger, m_username << ": Spawning new Skype instance dbpath=" << db); - gchar* argv[6] = {"skype", "--disable-cleanlooks", "--pipelogin", "--dbpath", db, 0}; - - int fd; - GError *error = NULL; - bool spawned = g_spawn_async_with_pipes(NULL, - argv, - NULL /*envp*/, - G_SPAWN_SEARCH_PATH, - NULL /*child_setup*/, - NULL /*user_data*/, - &m_pid /*child_pid*/, - &fd, - NULL, - &fd_output, - &error); - - if (!spawned) { - LOG4CXX_ERROR(logger, "Error spawning the Skype instance: " << error->message) - np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Error spawning the Skype instance."); - return; - } - - std::string login_data = std::string(m_username + " " + m_password + "\n"); - LOG4CXX_INFO(logger, m_username << ": Login data=" << m_username); - write(fd, login_data.c_str(), login_data.size()); - close(fd); - - fcntl (fd_output, F_SETFL, O_NONBLOCK); - - free(db); - - //Initialise threading - dbus_threads_init_default(); - - if (m_connection == NULL) - { - LOG4CXX_INFO(logger, "Creating DBUS connection."); - GError *error = NULL; - m_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); - if (m_connection == NULL && error != NULL) - { - LOG4CXX_INFO(logger, m_username << ": Creating DBUS Connection error: " << error->message); - g_error_free(error); - return; - } - } - - sleep(1); - m_timer = g_timeout_add_seconds(1, create_dbus_proxy, this); -} - -bool Skype::loadSkypeBuddies() { -// std::string re = "CONNSTATUS OFFLINE"; -// while (re == "CONNSTATUS OFFLINE" || re.empty()) { -// sleep(1); - - gchar buffer[1024]; - int bytes_read = read(fd_output, buffer, 1023); - if (bytes_read > 0) { - buffer[bytes_read] = 0; - std::string b(buffer); - LOG4CXX_WARN(logger, "Skype wrote this on stdout '" << b << "'"); - if (b.find("Incorrect Password") != std::string::npos) { - LOG4CXX_INFO(logger, "Incorrect password, logging out") - np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_FAILED, "Incorrect password"); - close(fd_output); - logout(); - return FALSE; - } - } - - std::string re = send_command("NAME Spectrum"); - if (m_counter++ > 15) { - LOG4CXX_ERROR(logger, "Logging out, because we tried to connect the Skype over DBUS 15 times without success"); - np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon."); - close(fd_output); - logout(); - return FALSE; - } - - if (re.empty() || re == "CONNSTATUS OFFLINE" || re == "ERROR 68") { - return TRUE; - } - - close(fd_output); - - if (send_command("PROTOCOL 7") != "PROTOCOL 7") { - LOG4CXX_ERROR(logger, "PROTOCOL 7 failed, logging out"); - np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon."); - logout(); - return FALSE; - } - - np->handleConnected(m_user); - - std::map group_map; - std::string groups = send_command("SEARCH GROUPS CUSTOM"); - if (groups.find(' ') != std::string::npos) { - groups = groups.substr(groups.find(' ') + 1); - std::vector grps; - boost::split(grps, groups, boost::is_any_of(",")); - BOOST_FOREACH(std::string grp, grps) { - std::vector data; - std::string name = send_command("GET GROUP " + grp + " DISPLAYNAME"); - - if (name.find("ERROR") == 0) { - continue; - } - - boost::split(data, name, boost::is_any_of(" ")); - name = GET_RESPONSE_DATA(name, "DISPLAYNAME"); - - std::string users = send_command("GET GROUP " + data[1] + " USERS"); - try { - users = GET_RESPONSE_DATA(users, "USERS"); - } - catch (std::out_of_range& oor) { - continue; - } - boost::split(data, users, boost::is_any_of(",")); - BOOST_FOREACH(std::string u, data) { - group_map[u] = grp; - } - } - } - - std::string friends = send_command("GET AUTH_CONTACTS_PROFILES"); - - char **full_friends_list = g_strsplit((strchr(friends.c_str(), ' ')+1), ";", 0); - if (full_friends_list && full_friends_list[0]) - { - //in the format of: username;full name;phone;office phone;mobile phone; - // online status;friendly name;voicemail;mood - // (comma-seperated lines, usernames can have comma's) - - for (int i=0; full_friends_list[i] && full_friends_list[i+1] && *full_friends_list[i] != '\0'; i+=8) - { - std::string buddy = full_friends_list[i]; - - if (buddy[0] == ',') { - buddy.erase(buddy.begin()); - } - - if (buddy.rfind(",") != std::string::npos) { - buddy = buddy.substr(buddy.rfind(",")); - } - - if (buddy[0] == ',') { - buddy.erase(buddy.begin()); - } - - LOG4CXX_INFO(logger, "Got buddy " << buddy); - std::string st = full_friends_list[i + 5]; - - pbnetwork::StatusType status = getStatus(st); - - std::string alias = full_friends_list[i + 6]; - - std::string mood_text = ""; - if (full_friends_list[i + 8] && *full_friends_list[i + 8] != '\0' && *full_friends_list[i + 8] != ',') { - mood_text = full_friends_list[i + 8]; - } - - std::vector groups; - if (group_map.find(buddy) != group_map.end()) { - groups.push_back(group_map[buddy]); - } - np->handleBuddyChanged(m_user, buddy, alias, groups, status, mood_text); - } - } - g_strfreev(full_friends_list); - - send_command("SET AUTOAWAY OFF"); - send_command("SET USERSTATUS ONLINE"); - return FALSE; -} - -void Skype::logout() { - if (m_pid != 0) { - if (m_proxy) { - send_command("SET USERSTATUS INVISIBLE"); - send_command("SET USERSTATUS OFFLINE"); - sleep(2); - g_object_unref(m_proxy); - } - LOG4CXX_INFO(logger, m_username << ": Terminating Skype instance (SIGTERM)"); - kill((int) m_pid, SIGTERM); - // Give skype a chance - sleep(2); - LOG4CXX_INFO(logger, m_username << ": Killing Skype instance (SIGKILL)"); - kill((int) m_pid, SIGKILL); - m_pid = 0; - } -} - -std::string Skype::send_command(const std::string &message) { - GError *error = NULL; - gchar *str = NULL; -// int message_num; -// gchar error_return[30]; - - LOG4CXX_INFO(logger, "Sending: '" << message << "'"); - if (!dbus_g_proxy_call (m_proxy, "Invoke", &error, G_TYPE_STRING, message.c_str(), G_TYPE_INVALID, - G_TYPE_STRING, &str, G_TYPE_INVALID)) - { - if (error && error->message) - { - LOG4CXX_INFO(logger, m_username << ": DBUS Error: " << error->message); - g_error_free(error); - return ""; - } else { - LOG4CXX_INFO(logger, m_username << ": DBUS no response"); - return ""; - } - - } - if (str != NULL) - { - LOG4CXX_INFO(logger, m_username << ": DBUS:'" << str << "'"); - } - return str ? std::string(str) : std::string(); -} - -static void handle_skype_message(std::string &message, Skype *sk) { - std::vector cmd; - boost::split(cmd, message, boost::is_any_of(" ")); - - if (cmd[0] == "USER") { - if (cmd[1] == sk->getUsername()) { - return; - } - - if (cmd[2] == "ONLINESTATUS") { - if (cmd[3] == "SKYPEOUT" || cmd[3] == "UNKNOWN") { - return; - } - else { - pbnetwork::StatusType status = getStatus(cmd[3]); - GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT"); - GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME"); - - std::vector groups; - np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text); - } - } - else if (cmd[2] == "MOOD_TEXT") { - GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS"); - pbnetwork::StatusType status = getStatus(st); - - std::string mood_text = GET_RESPONSE_DATA(message, "MOOD_TEXT"); - - std::vector groups; - np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text); - } - else if (cmd[2] == "BUDDYSTATUS" && cmd[3] == "3") { - GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT"); - GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS"); - pbnetwork::StatusType status = getStatus(st); - - std::vector groups; - np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text); - } - else if (cmd[2] == "FULLNAME") { - GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME"); - GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT"); - GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS"); - pbnetwork::StatusType status = getStatus(st); - - std::vector groups; - np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text); - } - else if(cmd[2] == "RECEIVEDAUTHREQUEST") { - np->handleAuthorization(sk->getUser(), cmd[1]); - } - } - else if (cmd[0] == "GROUP") { -// if (cmd[2] == "DISPLAYNAME") { -// //GROUP 810 DISPLAYNAME My Friends -// std::string grp = GET_RESPONSE_DATA(message, "DISPLAYNAME"); -// std::string users = sk->send_command("GET GROUP " + cmd[1] + " USERS"); -// try { -// users = GET_RESPONSE_DATA(users, "USERS"); -// } -// catch (std::out_of_range& oor) { -// return; -// } -// -// std::vector data; -// boost::split(data, users, boost::is_any_of(",")); -// BOOST_FOREACH(std::string u, data) { -// GET_PROPERTY(alias, "USER", u, "FULLNAME"); -// GET_PROPERTY(mood_text, "USER", u, "MOOD_TEXT"); -// GET_PROPERTY(st, "USER", u, "ONLINESTATUS"); -// pbnetwork::StatusType status = getStatus(st); -// -// std::vector groups; -// groups.push_back(grp); -// np->handleBuddyChanged(sk->getUser(), u, alias, groups, status, mood_text); -// } -// } - if (cmd[2] == "NROFUSERS" && cmd[3] != "0") { - GET_PROPERTY(grp, "GROUP", cmd[1], "DISPLAYNAME"); - std::string users = sk->send_command("GET GROUP " + cmd[1] + " USERS"); - try { - users = GET_RESPONSE_DATA(users, "USERS"); - } - catch (std::out_of_range& oor) { - return; - } - - std::vector data; - boost::split(data, users, boost::is_any_of(",")); - BOOST_FOREACH(std::string u, data) { - GET_PROPERTY(alias, "USER", u, "FULLNAME"); - GET_PROPERTY(mood_text, "USER", u, "MOOD_TEXT"); - GET_PROPERTY(st, "USER", u, "ONLINESTATUS"); - pbnetwork::StatusType status = getStatus(st); - - std::vector groups; - groups.push_back(grp); - np->handleBuddyChanged(sk->getUser(), u, alias, groups, status, mood_text); - } - } - } - else if (cmd[0] == "CHATMESSAGE") { - if (cmd[3] == "RECEIVED") { - GET_PROPERTY(body, "CHATMESSAGE", cmd[1], "BODY"); - GET_PROPERTY(from_handle, "CHATMESSAGE", cmd[1], "FROM_HANDLE"); - - if (from_handle == sk->getUsername()) - return; - - np->handleMessage(sk->getUser(), from_handle, body); - - sk->send_command("SET CHATMESSAGE " + cmd[1] + " SEEN"); - } - } - else if (cmd[0] == "CALL") { - // CALL 884 STATUS RINGING - if (cmd[2] == "STATUS") { - if (cmd[3] == "RINGING" || cmd[3] == "MISSED") { - // handle only incoming calls - GET_PROPERTY(type, "CALL", cmd[1], "TYPE"); - if (type.find("INCOMING") != 0) { - return; - } - - GET_PROPERTY(from, "CALL", cmd[1], "PARTNER_HANDLE"); - GET_PROPERTY(dispname, "CALL", cmd[1], "PARTNER_DISPNAME"); - - if (cmd[3] == "RINGING") { - np->handleMessage(sk->getUser(), from, "User " + dispname + " is calling you."); - } - else { - np->handleMessage(sk->getUser(), from, "You have missed call from user " + dispname + "."); - } - } - } - } -} - -DBusHandlerResult skype_notify_handler(DBusConnection *connection, DBusMessage *message, gpointer user_data) { - DBusMessageIter iterator; - gchar *message_temp; - DBusMessage *temp_message; - - temp_message = dbus_message_ref(message); - dbus_message_iter_init(temp_message, &iterator); - if (dbus_message_iter_get_arg_type(&iterator) != DBUS_TYPE_STRING) - { - dbus_message_unref(message); - return (DBusHandlerResult) FALSE; - } - - do { - dbus_message_iter_get_basic(&iterator, &message_temp); - std::string m(message_temp); - LOG4CXX_INFO(logger,"DBUS message: " << m); - handle_skype_message(m, (Skype *) user_data); - } while(dbus_message_iter_has_next(&iterator) && dbus_message_iter_next(&iterator)); - - dbus_message_unref(message); - - return DBUS_HANDLER_RESULT_HANDLED; -} - static void spectrum_sigchld_handler(int sig) { int status; @@ -968,6 +444,7 @@ int main(int argc, char **argv) { Logging::initBackendLogging(cfg); g_type_init(); + m_sock = create_socket(host.c_str(), port); @@ -978,7 +455,9 @@ int main(int argc, char **argv) { channel = g_io_channel_unix_new(m_sock); g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, transportDataReceived, NULL, io_destroy); - np = new SpectrumNetworkPlugin(cfg, host, port); + dbus_threads_init_default(); + + np = new SkypePlugin(cfg, host, port); GMainLoop *m_loop; m_loop = g_main_loop_new(NULL, FALSE); diff --git a/include/transport/protocol.proto b/include/transport/protocol.proto index 796b656c..4e47ea6a 100644 --- a/include/transport/protocol.proto +++ b/include/transport/protocol.proto @@ -95,6 +95,10 @@ enum ParticipantFlag { PARTICIPANT_FLAG_NOT_AUTHORIZED = 8; PARTICIPANT_FLAG_ME = 16; PARTICIPANT_FLAG_KICKED = 32; + PARTICIPANT_FLAG_VISITOR = 64; + PARTICIPANT_FLAG_MEMBER = 128; + PARTICIPANT_FLAG_ADMIN = 256; + PARTICIPANT_FLAG_OWNER = 512; } message Participant { diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 4a36eebf..2d9a5fbf 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -252,8 +252,8 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { // We allow auto_register feature in gateway-mode. This allows IRC user to register // the transport just by joining the room. if (!m_component->inServerMode()) { - if (!registered && (CONFIG_BOOL(m_component->getConfig(), "registration.auto_register") || - !CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", true))) { + if (!registered && (CONFIG_BOOL(m_component->getConfig(), "registration.auto_register") + /*!CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", true)*/)) { res.password = ""; res.jid = userkey;