Changeset - f742dae46248
[Not reviewed]
0 1 0
HanzZ - 14 years ago 2012-02-17 11:50:33
hanzz.k@gmail.com
wait 10s
1 file changed with 1 insertions and 1 deletions:
0 comments (0 inline, 0 general)
backends/skype/main.cpp
Show inline comments
 
@@ -177,385 +177,385 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
				skype->send_command("MESSAGE " + legacyName + " " + message);
 
			}
 
			
 
		}
 

	
 
		void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
				std::string name = legacyName;
 
				if (name.find("skype.") == 0) {
 
					name = name.substr(6);
 
				}
 
				std::string photo;
 
				gchar *filename = NULL;
 
				gchar *new_filename = NULL;
 
				gchar *image_data = NULL;
 
				gsize image_data_len = 0;
 
				gchar *ret;
 
				int fh;
 
				GError *error;
 
				const gchar *userfiles[] = {"user256", "user1024", "user4096", "user16384", "user32768", "user65536",
 
											"profile256", "profile1024", "profile4096", "profile16384", "profile32768", 
 
											NULL};
 
				char *username = g_strdup_printf("\x03\x10%s", name.c_str());
 
				for (fh = 0; userfiles[fh]; fh++) {
 
					filename = g_strconcat("/tmp/skype/", skype->getUsername().c_str(), "/", skype->getUsername().c_str(), "/", userfiles[fh], ".dbb", NULL);
 
					std::cout << "getting filename:" << filename << "\n";
 
					if (g_file_get_contents(filename, &image_data, &image_data_len, NULL))
 
					{
 
						std::cout << "got\n";
 
						char *start = (char *)memmem(image_data, image_data_len, username, strlen(username)+1);
 
						if (start != NULL)
 
						{
 
							char *next = image_data;
 
							char *last = next;
 
							//find last index of l33l
 
							while ((next = (char *)memmem(next+4, start-next-4, "l33l", 4)))
 
							{
 
								last = next;
 
							}
 
							start = last;
 
							if (start != NULL)
 
							{
 
								char *img_start;
 
								//find end of l33l block
 
								char *end = (char *)memmem(start+4, image_data+image_data_len-start-4, "l33l", 4);
 
								if (!end) end = image_data+image_data_len;
 
								
 
								//look for start of JPEG block
 
								img_start = (char *)memmem(start, end-start, "\xFF\xD8", 2);
 
								if (img_start)
 
								{
 
									//look for end of JPEG block
 
									char *img_end = (char *)memmem(img_start, end-img_start, "\xFF\xD9", 2);
 
									if (img_end)
 
									{
 
										image_data_len = img_end - img_start + 2;
 
										photo = std::string(img_start, image_data_len);
 
									}
 
								}
 
							}
 
						}
 
						g_free(image_data);
 
					}
 
					g_free(filename);
 
				}
 
				g_free(username);
 
				
 
				std::string alias = "";
 
				std::cout << skype->getUsername() << " " << name << "\n";
 
				if (skype->getUsername() == name) {
 
					alias = skype->send_command("GET PROFILE FULLNAME");
 
					alias = alias.substr(17);
 
				}
 
				handleVCard(user, id, legacyName, "", alias, photo);
 
			}
 
		}
 

	
 
		void sendData(const std::string &string) {
 
			write(m_sock, string.c_str(), string.size());
 
// 			if (writeInput == 0)
 
// 				writeInput = purple_input_add(m_sock, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
 
		}
 

	
 
		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<std::string> &groups) {
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
 

	
 
		}
 

	
 
		void handleBuddyBlockToggled(const std::string &user, const std::string &buddyName, bool blocked) {
 

	
 
		}
 

	
 
		void handleTypingRequest(const std::string &user, const std::string &buddyName) {
 

	
 
		}
 

	
 
		void handleTypedRequest(const std::string &user, const std::string &buddyName) {
 

	
 
		}
 

	
 
		void handleStoppedTypingRequest(const std::string &user, const std::string &buddyName) {
 

	
 
		}
 

	
 
		void handleAttentionRequest(const std::string &user, const std::string &buddyName, const std::string &message) {
 

	
 
		}
 

	
 
		std::map<std::string, Skype *> m_sessions;
 
		std::map<Skype *, std::string> m_accounts;
 
		std::map<std::string, unsigned int> m_vcards;
 
		Config *config;
 
		
 
};
 

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

	
 
		void Skype::login() {
 
			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 = "<?xml version=\"1.0\"?>\n"
 
									"<config version=\"1.0\" serial=\"28\" timestamp=\"" + boost::lexical_cast<std::string>(time(NULL)) + ".0\">\n"
 
									"<UI>\n"
 
										"<Installed>2</Installed>\n"
 
										"<Language>en</Language>\n"
 
									"</UI>\n"
 
									"</config>\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 = "<?xml version=\"1.0\"?>\n"
 
									"<config version=\"1.0\" serial=\"7\" timestamp=\"" + boost::lexical_cast<std::string>(time(NULL)) + ".0\">\n"
 
										"<Lib>\n"
 
											"<Account>\n"
 
											"<IdleTimeForAway>30000000</IdleTimeForAway>\n"
 
											"<IdleTimeForNA>300000000</IdleTimeForNA>\n"
 
											"<LastUsed>" + boost::lexical_cast<std::string>(time(NULL)) + "</LastUsed>\n"
 
											"</Account>\n"
 
										"</Lib>\n"
 
										"<UI>\n"
 
											"<API>\n"
 
											"<Authorizations>Spectrum</Authorizations>\n"
 
											"<BlockedPrograms></BlockedPrograms>\n"
 
											"</API>\n"
 
										"</UI>\n"
 
									"</config>\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);
 
			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;
 
			int fd_output;
 
			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,
 
				NULL /*error*/);
 
			std::string login_data = std::string(m_username + " " + m_password + "\n");
 
			LOG4CXX_INFO(logger,  m_username << ": Login data=" << login_data);
 
			write(fd, login_data.c_str(), login_data.size());
 
			close(fd);
 
			
 
			fcntl (fd_output, F_SETFL, O_NONBLOCK);
 

	
 
			free(db);
 

	
 
			sleep(2);
 
			sleep(10);
 

	
 
			GError *error = NULL;
 
			DBusObjectPathVTable vtable;
 

	
 
			//Initialise threading
 
			dbus_threads_init_default();
 
			
 
			if (m_connection == NULL)
 
			{
 
				m_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
 
				if (m_connection == NULL && error != NULL)
 
				{
 
					LOG4CXX_INFO(logger,  m_username << ": DBUS Error: " << error->message);
 
					g_error_free(error);
 
					return;
 
				}
 
			}
 
			
 
			if (m_proxy == 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);
 
					g_error_free(error);
 
				}
 
				
 
				vtable.message_function = &skype_notify_handler;
 
				dbus_connection_register_object_path(dbus_g_connection_get_connection(m_connection), "/com/Skype/Client", &vtable, this);
 
			}
 

	
 
			int counter = 0;
 
			std::string re = "CONNSTATUS OFFLINE";
 
			while (re == "CONNSTATUS OFFLINE" || re.empty()) {
 
				sleep(1);
 
				gchar buffer[1024];
 
				int bytes_read;
 
				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;
 
				}
 
				re = send_command("NAME Spectrum");
 
				if (counter++ > 15)
 
					break;
 
			}
 

	
 
			close(fd_output);
 

	
 
			if (send_command("PROTOCOL 7") != "PROTOCOL 7") {
 
				np->handleDisconnected(m_user, 0, "Skype is not ready");
 
				logout();
 
				return;
 
			}
 
			
 
			np->handleConnected(m_user);
 

	
 
			std::map<std::string, std::string> group_map;
 
			std::string groups = send_command("SEARCH GROUPS CUSTOM");
 
			groups = groups.substr(groups.find(' ') + 1);
 
			std::vector<std::string> grps;
 
			boost::split(grps, groups, boost::is_any_of(","));
 
			BOOST_FOREACH(std::string grp, grps) {
 
				std::vector<std::string> 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;
 
				}
 
			}
 

	
 
			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] != '\0'; i+=8)
 
				{
 
					std::string buddy = full_friends_list[i];
 

	
 
					if (buddy[0] == ',') {
 
						buddy.erase(buddy.begin());
 
					}
 
					std::cout << "BUDDY '" << buddy << "'\n";
 
					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];
 
						i++;
 
					}
 

	
 
					std::vector<std::string> groups;
 
					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");
 
		}
 

	
 
		void Skype::logout() {
 
			if (m_pid != 0) {
 
				send_command("SET USERSTATUS INVISIBLE");
 
				send_command("SET USERSTATUS OFFLINE");
 
				sleep(2);
 
				g_object_unref(m_proxy);
 
				LOG4CXX_INFO(logger,  m_username << ": Killing Skype instance");
 
				kill((int) m_pid, SIGTERM);
 
				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];
 
			
 
			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);
 
				} else {
 
					LOG4CXX_INFO(logger,  m_username << ": DBUS no response");
 
				}
 
				
 
			}
 
			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<std::string> 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]);
 
				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);
 

	
 
				std::vector<std::string> 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);
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10);
 

	
 
			std::vector<std::string> groups;
0 comments (0 inline, 0 general)