Changeset - 3c53e1f86e45
[Not reviewed]
Merge
0 1 0
vitalyster - 11 years ago 2014-09-02 18:42:28
vitalyster@gmail.com
Merge pull request #51 from drJeckyll/poll_messages

Skype: check for new messages every 10 seconds
1 file changed with 24 insertions and 1 deletions:
0 comments (0 inline, 0 general)
backends/skype/skype.cpp
Show inline comments
 
@@ -12,188 +12,197 @@
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "skype.h"
 
#include "skypeplugin.h"
 
#include "skypedb.h"
 

	
 
#include "transport/config.h"
 
#include "transport/logging.h"
 
#include "transport/transport.h"
 
#include "transport/usermanager.h"
 
#include "transport/memoryusage.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/userregistration.h"
 
#include "transport/user.h"
 
#include "transport/storagebackend.h"
 
#include "transport/rostermanager.h"
 
#include "transport/conversation.h"
 
#include "transport/networkplugin.h"
 
#include <boost/filesystem.hpp>
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
// #include "valgrind/memcheck.h"
 
#ifndef __FreeBSD__
 
#include "malloc.h"
 
#endif
 

	
 

	
 
DEFINE_LOGGER(logger, "Skype");
 

	
 
Skype::Skype(SkypePlugin *np, 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;
 
	m_np = np;
 
}
 

	
 
static gboolean skype_check_missedmessages(gpointer data) {
 
	Skype *skype = (Skype *) data;
 

	
 
	skype->send_command("SEARCH MISSEDCHATMESSAGES");
 

	
 
	return TRUE;
 
}
 

	
 
static gboolean load_skype_buddies(gpointer data) {
 
	Skype *skype = (Skype *) data;
 
	return skype->loadSkypeBuddies();
 
}
 

	
 
static gboolean create_dbus_proxy(gpointer data) {
 
	Skype *skype = (Skype *) data;
 
	return skype->createDBusProxy();
 
}
 

	
 
static pbnetwork::StatusType getStatus(const std::string &st) {
 
	pbnetwork::StatusType status = pbnetwork::STATUS_ONLINE;
 
	if (st == "SKYPEOUT" || st == "OFFLINE") {
 
		status = pbnetwork::STATUS_NONE;
 
	}
 
	else if (st == "DND") {
 
		status = pbnetwork::STATUS_DND;
 
	}
 
	else if (st == "NA") {
 
		status = pbnetwork::STATUS_XA;
 
	}
 
	else if (st == "AWAY") {
 
		status = pbnetwork::STATUS_AWAY;
 
	}
 
	return status;
 
}
 

	
 
DBusHandlerResult skype_notify_handler(DBusConnection *connection, DBusMessage *message, gpointer data) {
 
	Skype *skype = (Skype *) data;
 
	return skype->dbusMessageReceived(connection, message);
 
}
 

	
 
void Skype::login() {
 
	// Do not allow usernames with unsecure symbols
 
	if (m_username.find("..") == 0 || m_username.find("/") != std::string::npos) {
 
		m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Invalid username");
 
		return;
 
	}
 

	
 
	m_db = createSkypeDirectory();
 

	
 
	bool spawned = spawnSkype(m_db);
 
	if (!spawned) {
 
		m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Error spawning the Skype instance.");
 
		return;
 
	}
 

	
 
	m_db += "/" + getUsername() + "/main.db";
 

	
 
	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;
 
		}
 
	}
 

	
 
	m_timer = g_timeout_add_seconds(1, create_dbus_proxy, this);
 
}
 

	
 
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);
 
				m_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);
 
			g_timeout_add_seconds(10, skype_check_missedmessages, this);
 
			return FALSE;
 
		}
 
		return TRUE;
 
	}
 
	return FALSE;
 
}
 

	
 
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")
 
			m_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");
 
		m_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");
 
		m_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;
 
	}
 
@@ -388,103 +397,117 @@ void Skype::handleSkypeMessage(std::string &message) {
 
// 		if (cmd[2] == "DISPLAYNAME") {
 
// 			//GROUP 810 DISPLAYNAME My Friends
 
// 			std::string grp = GET_RESPONSE_DATA(message, "DISPLAYNAME");
 
// 			std::string users = send_command("GET GROUP " + cmd[1] + " USERS");
 
// 			try {
 
// 				users = GET_RESPONSE_DATA(users, "USERS");
 
// 			}
 
// 			catch (std::out_of_range& oor) {
 
// 				return;
 
// 			}
 
// 
 
// 			std::vector<std::string> 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<std::string> groups;
 
// 				groups.push_back(grp);
 
// 				m_np->handleBuddyChanged(getUser(), u, alias, groups, status, mood_text);
 
// 			}
 
// 		}
 
		if (cmd[2] == "NROFUSERS" && cmd[3] != "0") {
 
			GET_PROPERTY(grp, "GROUP", cmd[1], "DISPLAYNAME");
 
			std::string users = send_command("GET GROUP " + cmd[1] + " USERS");
 
			try {
 
				users = GET_RESPONSE_DATA(users, "USERS");
 
			}
 
			catch (std::out_of_range& oor) {
 
				return;
 
			}
 

	
 
			std::vector<std::string> 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<std::string> groups;
 
				groups.push_back(grp);
 
				m_np->handleBuddyChanged(getUser(), u, alias, groups, status, mood_text);
 
			}
 
		}
 
	}
 
	else if ((cmd[0] == "MESSAGES") || (cmd[0] == "CHATMESSAGES")) {
 
		std::string msgs = GET_RESPONSE_DATA(message, "CHATMESSAGES");
 
		std::vector<std::string> data;
 
		boost::split(data, msgs, boost::is_any_of(","));
 
		BOOST_FOREACH(std::string str, data) {
 
			boost::trim(str);
 
			if (!str.empty()) {
 
			    std::string re = send_command("GET CHATMESSAGE " + str + " STATUS");
 
			    handleSkypeMessage(re);
 
			}
 
		}
 
	}
 
	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 == getUsername())
 
			if (from_handle == getUsername()) {
 
				send_command("SET CHATMESSAGE " + cmd[1] + " SEEN");
 
				return;
 
			}
 

	
 
			m_np->handleMessage(getUser(), from_handle, body);
 

	
 
			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") {
 
					m_np->handleMessage(getUser(), from, "User " + dispname + " is calling you.");
 
				}
 
				else {
 
					m_np->handleMessage(getUser(), from, "You have missed call from user " + dispname + ".");
 
				}
 
			}
 
		}
 
	}
 
}
 

	
 
DBusHandlerResult Skype::dbusMessageReceived(DBusConnection *connection, DBusMessage *message) {
 
	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);
 
		handleSkypeMessage(m);
0 comments (0 inline, 0 general)