diff --git a/backends/skype/main.cpp b/backends/skype/main.cpp index 9ede8a7fcc8769506611bfb1595d78cff265d23f..ccb60559257b2ce0093a5a5c3e8ee7c03e431354 100644 --- a/backends/skype/main.cpp +++ b/backends/skype/main.cpp @@ -2,8 +2,10 @@ #include #include "transport/config.h" +#include "transport/logging.h" #include "transport/transport.h" #include "transport/usermanager.h" +#include "transport/memoryusage.h" #include "transport/logger.h" #include "transport/sqlite3backend.h" #include "transport/userregistration.h" @@ -34,6 +36,10 @@ using namespace Transport; class SpectrumNetworkPlugin; +#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); \ + VAR = GET_RESPONSE_DATA(VAR, PROP); + SpectrumNetworkPlugin *np; @@ -81,7 +87,7 @@ static pbnetwork::StatusType getStatus(const std::string &st) { class Skype { public: Skype(const std::string &user, const std::string &username, const std::string &password); - ~Skype() { logout(); } + ~Skype() { LOG4CXX_INFO(logger, "Skype instance desctuctor"); logout(); } void login(); void logout(); std::string send_command(const std::string &message); @@ -97,6 +103,10 @@ class Skype { bool createDBusProxy(); bool loadSkypeBuddies(); + int getPid() { + return (int) m_pid; + } + private: std::string m_username; std::string m_password; @@ -124,7 +134,9 @@ class SpectrumNetworkPlugin : public NetworkPlugin { void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { std::string name = legacyName; - name = name.substr(name.find(".") + 1); + if (name.find("skype.") == 0 || name.find("prpl-skype.") == 0) { + name = name.substr(name.find(".") + 1); + } LOG4CXX_INFO(logger, "Creating account with name '" << name << "'"); Skype *skype = new Skype(user, name, password); @@ -134,9 +146,25 @@ class SpectrumNetworkPlugin : public NetworkPlugin { skype->login(); } + void handleMemoryUsage(double &res, double &shared) { + res = 0; + shared = 0; + for(std::map::const_iterator it = m_sessions.begin(); it != m_sessions.end(); it++) { + Skype *skype = it->second; + if (skype) { + double r; + double s; + process_mem_usage(s, r, skype->getPid()); + res += r; + shared += s; + } + } + } + void handleLogoutRequest(const std::string &user, const std::string &legacyName) { Skype *skype = m_sessions[user]; if (skype) { + LOG4CXX_INFO(logger, "User wants to logout, logging out"); skype->logout(); exit(1); } @@ -178,6 +206,21 @@ class SpectrumNetworkPlugin : public NetworkPlugin { } } + void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector &groups) { + Skype *skype = m_sessions[user]; + if (skype) { + skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 2 Please authorize me"); + skype->send_command("SET USER " + buddyName + " ISAUTHORIZED TRUE"); + } + } + + void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector &groups) { + Skype *skype = m_sessions[user]; + if (skype) { + skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 1"); + } + } + void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) { Skype *skype = m_sessions[user]; if (skype) { @@ -253,7 +296,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin { std::cout << skype->getUsername() << " " << name << "\n"; if (skype->getUsername() == name) { alias = skype->send_command("GET PROFILE FULLNAME"); - alias = alias.substr(17); + alias = GET_RESPONSE_DATA(alias, "FULLNAME") } handleVCard(user, id, legacyName, "", alias, photo); } @@ -268,13 +311,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin { void handleVCardUpdatedRequest(const std::string &user, const std::string &p, const std::string &nickname) { } - void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector &groups) { - } - - void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector &groups) { - - } - void handleBuddyBlockToggled(const std::string &user, const std::string &buddyName, bool blocked) { } @@ -331,7 +367,8 @@ bool Skype::createDBusProxy() { LOG4CXX_INFO(logger, m_username << ":" << error->message); if (m_counter == 15) { - np->handleDisconnected(m_user, 0, error->message); + LOG4CXX_ERROR(logger, "Logging out, proxy couldn't be created"); + np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, error->message); logout(); g_error_free(error); return FALSE; @@ -360,6 +397,12 @@ static gboolean create_dbus_proxy(gpointer data) { } 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); @@ -394,6 +437,7 @@ void Skype::login() { "\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()); @@ -437,6 +481,7 @@ void Skype::login() { } } + sleep(1); m_timer = g_timeout_add_seconds(1, create_dbus_proxy, this); } @@ -449,28 +494,35 @@ bool Skype::loadSkypeBuddies() { int bytes_read = read(fd_output, buffer, 1023); if (bytes_read > 0) { buffer[bytes_read] = 0; - np->handleDisconnected(m_user, 0, buffer); - close(fd_output); - logout(); - return FALSE; + 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) { - np->handleDisconnected(m_user, 0, ""); + 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") { + if (re.empty() || re == "CONNSTATUS OFFLINE" || re == "ERROR 68") { return TRUE; } close(fd_output); if (send_command("PROTOCOL 7") != "PROTOCOL 7") { - np->handleDisconnected(m_user, 0, "Skype is not ready"); + 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; } @@ -479,20 +531,27 @@ bool Skype::loadSkypeBuddies() { std::map group_map; std::string groups = send_command("SEARCH GROUPS CUSTOM"); - 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"); - boost::split(data, name, boost::is_any_of(" ")); - name = name.substr(name.find("DISPLAYNAME") + 12); - - std::string users = send_command("GET GROUP " + data[1] + " USERS"); - users = name.substr(name.find("USERS") + 6); - boost::split(data, users, boost::is_any_of(",")); - BOOST_FOREACH(std::string u, data) { - group_map[u] = grp; + 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"); + users = GET_RESPONSE_DATA(users, "USERS"); + boost::split(data, users, boost::is_any_of(",")); + BOOST_FOREACH(std::string u, data) { + group_map[u] = grp; + } } } @@ -565,6 +624,7 @@ std::string Skype::send_command(const std::string &message) { // 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)) { @@ -572,14 +632,16 @@ std::string Skype::send_command(const std::string &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); + LOG4CXX_INFO(logger, m_username << ": DBUS:'" << str << "'"); } return str ? std::string(str) : std::string(); } @@ -599,70 +661,73 @@ static void handle_skype_message(std::string &message, Skype *sk) { } else { pbnetwork::StatusType status = getStatus(cmd[3]); - std::string mood_text = sk->send_command("GET USER " + cmd[1] + " MOOD_TEXT"); - mood_text = mood_text.substr(mood_text.find("MOOD_TEXT") + 10); - - std::string alias = sk->send_command("GET USER " + cmd[1] + " FULLNAME"); - alias = alias.substr(alias.find("FULLNAME") + 9); + 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") { - std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS"); - st = st.substr(st.find("ONLINESTATUS") + 13); + GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS"); pbnetwork::StatusType status = getStatus(st); - std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10); + 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") { - std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS"); - st = st.substr(st.find("ONLINESTATUS") + 13); + GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT"); + GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS"); pbnetwork::StatusType status = getStatus(st); - std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10); - std::vector groups; np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text); } else if (cmd[2] == "FULLNAME") { - std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS"); - st = st.substr(st.find("ONLINESTATUS") + 13); + 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::string mood_text = sk->send_command("GET USER " + cmd[1] + " MOOD_TEXT"); - mood_text = mood_text.substr(mood_text.find("MOOD_TEXT") + 10); - - std::string alias = message.substr(message.find("FULLNAME") + 9); - std::vector groups; np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text); } } else if (cmd[0] == "CHATMESSAGE") { if (cmd[3] == "RECEIVED") { - std::string body = sk->send_command("GET CHATMESSAGE " + cmd[1] + " BODY"); - body = body.substr(body.find("BODY") + 5); + GET_PROPERTY(body, "CHATMESSAGE", cmd[1], "BODY"); + GET_PROPERTY(from_handle, "CHATMESSAGE", cmd[1], "FROM_HANDLE"); - std::string chatname = sk->send_command("GET CHATMESSAGE " + cmd[1] + " CHATNAME"); - size_t start = chatname.find("$") + 1; - size_t len = chatname.find(";") - start; - std::string from = chatname.substr(start, len); - - std::string from_handle = sk->send_command("GET CHATMESSAGE " + cmd[1] + " FROM_HANDLE"); - from_handle = from_handle.substr(from_handle.find("FROM_HANDLE") + 12); - -// if (from_handle != sk->getUsername()) { - from = from_handle; -// } if (from_handle == sk->getUsername()) return; - np->handleMessage(sk->getUser(), from, body); + 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 + "."); + } + } } } } @@ -825,18 +890,7 @@ int main(int argc, char **argv) { return 1; } - if (CONFIG_STRING(&config, "logging.backend_config").empty()) { - LoggerPtr root = log4cxx::Logger::getRootLogger(); - root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n"))); - } - else { - log4cxx::helpers::Properties p; - log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config")); - - p.load(istream); - p.setProperty("pid", boost::lexical_cast(getpid())); - log4cxx::PropertyConfigurator::configure(p); - } + Logging::initBackendLogging(&config); // initPurple(config);