Changeset - de8114d2da06
[Not reviewed]
0 3 0
Jan Kaluza - 10 years ago 2016-02-09 08:01:04
jkaluza@redhat.com
Libpurple: Do not change the nickname when joining the room when it is the same as the one used by the user
3 files changed with 6 insertions and 6 deletions:
0 comments (0 inline, 0 general)
backends/libpurple/main.cpp
Show inline comments
 
@@ -329,776 +329,776 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
				}
 
				if (!CONFIG_STRING_DEFAULTED(config, "proxy.username", "").empty()) {
 
					purple_proxy_info_set_username_wrapped(info, CONFIG_STRING_DEFAULTED(config, "proxy.username", "").c_str());
 
				}
 

	
 
				if (!CONFIG_STRING_DEFAULTED(config, "proxy.password", "").empty()) {
 
					purple_proxy_info_set_password_wrapped(info, CONFIG_STRING_DEFAULTED(config, "proxy.password", "").c_str());
 
				}
 

	
 
				purple_account_set_proxy_info_wrapped(account, info);
 
			}
 
		}
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
			PurpleAccount *account = NULL;
 

	
 
			std::string name;
 
			std::string protocol;
 
			getProtocolAndName(legacyName, name, protocol);
 

	
 
			if (password.empty() && CONFIG_STRING(config, "service.protocol") != "prpl-telegram") {
 
				LOG4CXX_INFO(logger,  name.c_str() << ": Empty password");
 
				np->handleDisconnected(user, 0, "Empty password.");
 
				return;
 
			}
 

	
 
			if (!purple_find_prpl_wrapped(protocol.c_str())) {
 
				LOG4CXX_INFO(logger,  name.c_str() << ": Invalid protocol '" << protocol << "'");
 
				np->handleDisconnected(user, 0, "Invalid protocol " + protocol);
 
				return;
 
			}
 

	
 
			if (purple_accounts_find_wrapped(name.c_str(), protocol.c_str()) != NULL) {
 
				account = purple_accounts_find_wrapped(name.c_str(), protocol.c_str());
 
				if (m_accounts.find(account) != m_accounts.end() && m_accounts[account] != user) {
 
					LOG4CXX_INFO(logger, "Account '" << name << "' is already used by '" << m_accounts[account] << "'");
 
					np->handleDisconnected(user, 0, "Account '" + name + "' is already used by '" + m_accounts[account] + "'");
 
					return;
 
				}
 
				LOG4CXX_INFO(logger, "Using previously created account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
 
			}
 
			else {
 
				LOG4CXX_INFO(logger, "Creating account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
 
				account = purple_account_new_wrapped(name.c_str(), protocol.c_str());
 
				purple_accounts_add_wrapped(account);
 
			}
 

	
 
			m_sessions[user] = account;
 
			m_accounts[account] = user;
 

	
 
			// Default avatar
 
			setDefaultAvatar(account, legacyName);
 

	
 
			purple_account_set_password_wrapped(account, password.c_str());
 
			purple_account_set_bool_wrapped(account, "custom_smileys", FALSE);
 
			purple_account_set_bool_wrapped(account, "direct_connect", FALSE);
 
			purple_account_set_bool_wrapped(account, "compat-verification", TRUE);
 

	
 
			setDefaultAccountOptions(account);
 

	
 
			// Enable account + privacy lists
 
			purple_account_set_enabled_wrapped(account, "spectrum", TRUE);
 

	
 
#if PURPLE_MAJOR_VERSION >= 2 && PURPLE_MINOR_VERSION >= 7
 
			if (CONFIG_BOOL(config, "service.enable_privacy_lists")) {
 
				purple_account_set_privacy_type_wrapped(account, PURPLE_PRIVACY_DENY_USERS);
 
			}
 
#endif
 

	
 
			// Set the status
 
			const PurpleStatusType *status_type = purple_account_get_status_type_with_primitive_wrapped(account, PURPLE_STATUS_AVAILABLE);
 
			if (status_type != NULL) {
 
				purple_account_set_status_wrapped(account, purple_status_type_get_id_wrapped(status_type), TRUE, NULL);
 
			}
 
		}
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				if (account->ui_data) {
 
					NodeCache *cache = (NodeCache *) account->ui_data;
 
					purple_timeout_remove_wrapped(cache->timer);
 
					delete cache;
 
					account->ui_data = NULL;
 
				}
 
				if (purple_account_get_int_wrapped(account, "version", 0) != 0) {
 
					std::string data = stringOf(purple_account_get_int_wrapped(account, "version", 0));
 
					g_file_set_contents ("gfire.cfg", data.c_str(), data.size(), NULL);
 
				}
 
// 				VALGRIND_DO_LEAK_CHECK;
 
				m_sessions.erase(user);
 
				purple_account_disconnect_wrapped(account);
 
				purple_account_set_enabled_wrapped(account, "spectrum", FALSE);
 

	
 
				m_accounts.erase(account);
 

	
 
				purple_accounts_delete_wrapped(account);
 
#ifndef WIN32
 
#if !defined(__FreeBSD__) && !defined(__APPLE__)
 
				malloc_trim(0);
 
#endif
 
#endif
 
// 				VALGRIND_DO_LEAK_CHECK;
 
			}
 
		}
 

	
 
		void handleStatusChangeRequest(const std::string &user, int status, const std::string &statusMessage) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				int st;
 
				switch(status) {
 
					case pbnetwork::STATUS_AWAY: {
 
						st = PURPLE_STATUS_AWAY;
 
						if (!purple_account_get_status_type_with_primitive_wrapped(account, PURPLE_STATUS_AWAY))
 
							st = PURPLE_STATUS_EXTENDED_AWAY;
 
						else
 
							st = PURPLE_STATUS_AWAY;
 
						break;
 
					}
 
					case pbnetwork::STATUS_DND: {
 
						st = PURPLE_STATUS_UNAVAILABLE;
 
						break;
 
					}
 
					case pbnetwork::STATUS_XA: {
 
						if (!purple_account_get_status_type_with_primitive_wrapped(account, PURPLE_STATUS_EXTENDED_AWAY))
 
							st = PURPLE_STATUS_AWAY;
 
						else
 
							st = PURPLE_STATUS_EXTENDED_AWAY;
 
						break;
 
					}
 
					case pbnetwork::STATUS_NONE: {
 
						st = PURPLE_STATUS_OFFLINE;
 
						break;
 
					}
 
					case pbnetwork::STATUS_INVISIBLE:
 
						st = PURPLE_STATUS_INVISIBLE;
 
						break;
 
					default:
 
						st = PURPLE_STATUS_AVAILABLE;
 
						break;
 
				}
 
				gchar *_markup = purple_markup_escape_text_wrapped(statusMessage.c_str(), -1);
 
				std::string markup(_markup);
 
				g_free(_markup);
 

	
 
				// we are already connected so we have to change status
 
				const PurpleStatusType *status_type = purple_account_get_status_type_with_primitive_wrapped(account, (PurpleStatusPrimitive) st);
 
				if (status_type != NULL) {
 
					// send presence to legacy network
 
					if (!markup.empty()) {
 
						purple_account_set_status_wrapped(account, purple_status_type_get_id_wrapped(status_type), TRUE, "message", markup.c_str(), NULL);
 
					}
 
					else {
 
						purple_account_set_status_wrapped(account, purple_status_type_get_id_wrapped(status_type), TRUE, NULL);
 
					}
 
				}
 
			}
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml, const std::string &id) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				LOG4CXX_INFO(logger, "Sending message to '" << legacyName << "'");
 
				PurpleConversation *conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_CHAT, legacyName.c_str(), account);
 
				if (!conv) {
 
					conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_IM, legacyName.c_str(), account);
 
					if (!conv) {
 
						conv = purple_conversation_new_wrapped(PURPLE_CONV_TYPE_IM, account, legacyName.c_str());
 
					}
 
				}
 
				if (xhtml.empty()) {
 
					gchar *_markup = purple_markup_escape_text_wrapped(message.c_str(), -1);
 
					if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
 
						purple_conv_im_send_wrapped(PURPLE_CONV_IM_WRAPPED(conv), _markup);
 
					}
 
					else if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_CHAT) {
 
						purple_conv_chat_send_wrapped(PURPLE_CONV_CHAT_WRAPPED(conv), _markup);
 
					}
 
					g_free(_markup);
 
				}
 
				else {
 
					if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
 
						purple_conv_im_send_wrapped(PURPLE_CONV_IM_WRAPPED(conv), xhtml.c_str());
 
					}
 
					else if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_CHAT) {
 
						purple_conv_chat_send_wrapped(PURPLE_CONV_CHAT_WRAPPED(conv), xhtml.c_str());
 
					}
 
				}
 
			}
 
		}
 

	
 
		void handleRoomSubjectChangedRequest(const std::string &user, const std::string &legacyName, const std::string &message) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				PurpleConversation *conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_CHAT, legacyName.c_str(), account);
 
				if (!conv) {
 
					LOG4CXX_ERROR(logger, user << ": Cannot set room subject. There is now conversation " << legacyName);
 
					return;
 
				}
 

	
 
				PurplePlugin *prpl = purple_find_prpl_wrapped(purple_account_get_protocol_id_wrapped(account));
 
				PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
				bool support_set_chat_topic = prpl_info && prpl_info->set_chat_topic;
 
				if (support_set_chat_topic) {
 
					LOG4CXX_INFO(logger, user << ": Setting room subject for room " << legacyName);
 
					prpl_info->set_chat_topic(purple_account_get_connection_wrapped(account),
 
											  purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)),
 
											  message.c_str());
 
				}
 
			}
 
		}
 

	
 
		void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				std::string name = legacyName;
 
				if (CONFIG_STRING(config, "service.protocol") == "any" && legacyName.find("prpl-") == 0) {
 
					name = name.substr(name.find(".") + 1);
 
				}
 
				m_vcards[user + name] = id;
 

	
 
				PurplePlugin *prpl = purple_find_prpl_wrapped(purple_account_get_protocol_id_wrapped(account));
 
				PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
				bool support_get_info = prpl_info && prpl_info->get_info;
 

	
 
				if (!support_get_info || (CONFIG_BOOL(config, "backend.no_vcard_fetch") && name != purple_account_get_username_wrapped(account))) {
 
					PurpleNotifyUserInfo *user_info = purple_notify_user_info_new_wrapped();
 
					notify_user_info(purple_account_get_connection_wrapped(account), name.c_str(), user_info);
 
					purple_notify_user_info_destroy_wrapped(user_info);
 
				}
 
				else {
 
					serv_get_info_wrapped(purple_account_get_connection_wrapped(account), name.c_str());
 
				}
 
			}
 
		}
 

	
 
		void handleVCardUpdatedRequest(const std::string &user, const std::string &image, const std::string &nickname) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				purple_account_set_alias_wrapped(account, nickname.c_str());
 
#if PURPLE_MAJOR_VERSION >= 2 && PURPLE_MINOR_VERSION >= 7
 
				purple_account_set_public_alias_wrapped(account, nickname.c_str(), NULL, NULL);
 
#endif
 
				gssize size = image.size();
 
				// this will be freed by libpurple
 
				guchar *photo = (guchar *) g_malloc(size * sizeof(guchar));
 
				memcpy(photo, image.c_str(), size);
 

	
 
				if (!photo)
 
					return;
 
				purple_buddy_icons_set_account_icon_wrapped(account, photo, size);
 
			}
 
		}
 

	
 
		void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				if (m_authRequests.find(user + buddyName) != m_authRequests.end()) {
 
					m_authRequests[user + buddyName]->deny_cb(m_authRequests[user + buddyName]->user_data);
 
					m_authRequests.erase(user + buddyName);
 
				}
 
				PurpleBuddy *buddy = purple_find_buddy_wrapped(account, buddyName.c_str());
 
				if (buddy) {
 
					purple_account_remove_buddy_wrapped(account, buddy, purple_buddy_get_group_wrapped(buddy));
 
					purple_blist_remove_buddy_wrapped(buddy);
 
				}
 
			}
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups_) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				std::string groups = groups_.empty() ? "" : groups_[0];
 

	
 
				if (m_authRequests.find(user + buddyName) != m_authRequests.end()) {
 
					m_authRequests[user + buddyName]->authorize_cb(m_authRequests[user + buddyName]->user_data);
 
					m_authRequests.erase(user + buddyName);
 
				}
 

	
 
				PurpleBuddy *buddy = purple_find_buddy_wrapped(account, buddyName.c_str());
 
				if (buddy) {
 
					if (getAlias(buddy) != alias) {
 
						purple_blist_alias_buddy_wrapped(buddy, alias.c_str());
 
						purple_blist_server_alias_buddy_wrapped(buddy, alias.c_str());
 
						serv_alias_buddy_wrapped(buddy);
 
					}
 

	
 
					PurpleGroup *group = purple_find_group_wrapped(groups.c_str());
 
					if (!group) {
 
						group = purple_group_new_wrapped(groups.c_str());
 
					}
 
					purple_blist_add_contact_wrapped(purple_buddy_get_contact_wrapped(buddy), group ,NULL);
 
				}
 
				else {
 
					PurpleBuddy *buddy = purple_buddy_new_wrapped(account, buddyName.c_str(), alias.c_str());
 

	
 
					// Add newly created buddy to legacy network roster.
 
					PurpleGroup *group = purple_find_group_wrapped(groups.c_str());
 
					if (!group) {
 
						group = purple_group_new_wrapped(groups.c_str());
 
					}
 
					purple_blist_add_buddy_wrapped(buddy, NULL, group ,NULL);
 
					purple_account_add_buddy_wrapped(account, buddy);
 
					LOG4CXX_INFO(logger, "Adding new buddy " << buddyName.c_str() << " to legacy network roster");
 
				}
 
			}
 
		}
 

	
 
		void handleBuddyBlockToggled(const std::string &user, const std::string &buddyName, bool blocked) {
 
			if (CONFIG_BOOL(config, "service.enable_privacy_lists")) {
 
				PurpleAccount *account = m_sessions[user];
 
				if (account) {
 
					if (blocked) {
 
						purple_privacy_deny_wrapped(account, buddyName.c_str(), FALSE, FALSE);
 
					}
 
					else {
 
						purple_privacy_allow_wrapped(account, buddyName.c_str(), FALSE, FALSE);
 
					}
 
				}
 
			}
 
		}
 

	
 
		void handleTypingRequest(const std::string &user, const std::string &buddyName) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				LOG4CXX_INFO(logger, user << ": sending typing notify to " << buddyName);
 
				serv_send_typing_wrapped(purple_account_get_connection_wrapped(account), buddyName.c_str(), PURPLE_TYPING);
 
			}
 
		}
 

	
 
		void handleTypedRequest(const std::string &user, const std::string &buddyName) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				serv_send_typing_wrapped(purple_account_get_connection_wrapped(account), buddyName.c_str(), PURPLE_TYPED);
 
			}
 
		}
 

	
 
		void handleStoppedTypingRequest(const std::string &user, const std::string &buddyName) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				serv_send_typing_wrapped(purple_account_get_connection_wrapped(account), buddyName.c_str(), PURPLE_NOT_TYPING);
 
				PurpleConversation *conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_CHAT, buddyName.c_str(), account);
 
				if (!conv) {
 
					conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_IM, buddyName.c_str(), account);
 
				}
 
				if (conv) {
 
					purple_conversation_set_data_wrapped(conv, "unseen_count", 0);
 
					purple_conversation_update_wrapped(conv, PURPLE_CONV_UPDATE_UNSEEN);
 
				}
 
			}
 
		}
 

	
 
		void handleAttentionRequest(const std::string &user, const std::string &buddyName, const std::string &message) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				purple_prpl_send_attention_wrapped(purple_account_get_connection_wrapped(account), buddyName.c_str(), 0);
 
			}
 
		}
 

	
 
		void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &pasword) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (!account) {
 
				return;
 
			}
 

	
 
			PurpleConnection *gc = purple_account_get_connection_wrapped(account);
 
			GHashTable *comps = NULL;
 

	
 
			// Check if the PurpleChat is not stored in buddy list
 
			PurpleChat *chat = purple_blist_find_chat_wrapped(account, room.c_str());
 
			if (chat) {
 
				comps = purple_chat_get_components_wrapped(chat);
 
			}
 
			else if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) {
 
				if (CONFIG_STRING(config, "service.protocol") == "prpl-jabber") {
 
					comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, (room + "/" + nickname).c_str());
 
				} else {
 
					comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, room.c_str());
 
				}
 
			}
 

	
 
			if (CONFIG_STRING(config, "service.protocol") != "prpl-jabber") {
 
				np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE);
 
				const char *disp;
 
				if ((disp = purple_connection_get_display_name(account->gc))) {
 
				if ((disp = purple_connection_get_display_name(account->gc)) == NULL) {
 
					disp = purple_account_get_username(account);
 
				}
 

	
 
				if (nickname != disp) {
 
					handleRoomNicknameChanged(np->m_accounts[account], room, disp);
 
					np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE, "", disp);
 
				}
 
				else {
 
					handleRoomNicknameChanged(np->m_accounts[account], room, purple_account_get_username(account));
 
					np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE, "", purple_account_get_username(account));
 
				}
 
			}
 

	
 
			LOG4CXX_INFO(logger, user << ": Joining the room " << room);
 
			if (comps) {
 
				serv_join_chat_wrapped(gc, comps);
 
				g_hash_table_destroy(comps);
 
			}
 
		}
 

	
 
		void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (!account) {
 
				return;
 
			}
 

	
 
			PurpleConversation *conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_CHAT, room.c_str(), account);
 
			purple_conversation_destroy_wrapped(conv);
 
		}
 

	
 
		void handleFTStartRequest(const std::string &user, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long ftID) {
 
			PurpleXfer *xfer = m_unhandledXfers[user + fileName + buddyName];
 
			if (xfer) {
 
				m_unhandledXfers.erase(user + fileName + buddyName);
 
				FTData *ftData = (FTData *) xfer->ui_data;
 
				
 
				ftData->id = ftID;
 
				m_xfers[ftID] = xfer;
 
				purple_xfer_request_accepted_wrapped(xfer, fileName.c_str());
 
				purple_xfer_ui_ready_wrapped(xfer);
 
			}
 
		}
 

	
 
		void handleFTFinishRequest(const std::string &user, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long ftID) {
 
			PurpleXfer *xfer = m_unhandledXfers[user + fileName + buddyName];
 
			if (xfer) {
 
				m_unhandledXfers.erase(user + fileName + buddyName);
 
				purple_xfer_request_denied_wrapped(xfer);
 
			}
 
		}
 

	
 
		void handleFTPauseRequest(unsigned long ftID) {
 
			PurpleXfer *xfer = m_xfers[ftID];
 
			if (!xfer)
 
				return;
 
			FTData *ftData = (FTData *) xfer->ui_data;
 
			ftData->paused = true;
 
		}
 

	
 
		void handleFTContinueRequest(unsigned long ftID) {
 
			PurpleXfer *xfer = m_xfers[ftID];
 
			if (!xfer)
 
				return;
 
			FTData *ftData = (FTData *) xfer->ui_data;
 
			ftData->paused = false;
 
			purple_xfer_ui_ready_wrapped(xfer);
 
		}
 

	
 
		void sendData(const std::string &string) {
 
#ifdef WIN32
 
			::send(main_socket, string.c_str(), string.size(), 0);
 
#else
 
			write(main_socket, string.c_str(), string.size());
 
#endif
 
			if (writeInput == 0)
 
				writeInput = purple_input_add_wrapped(main_socket, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
 
		}
 

	
 
		void readyForData() {
 
			if (m_waitingXfers.empty())
 
				return;
 
			std::vector<PurpleXfer *> tmp;
 
			tmp.swap(m_waitingXfers);
 

	
 
			for (std::vector<PurpleXfer *>::const_iterator it = tmp.begin(); it != tmp.end(); it++) {
 
				FTData *ftData = (FTData *) (*it)->ui_data;
 
				if (ftData->timer == 0) {
 
					ftData->timer = purple_timeout_add_wrapped(1, ft_ui_ready, *it);
 
				}
 
// 				purple_xfer_ui_ready_wrapped(xfer);
 
			}
 
		}
 

	
 
		std::map<std::string, PurpleAccount *> m_sessions;
 
		std::map<PurpleAccount *, std::string> m_accounts;
 
		std::map<std::string, unsigned int> m_vcards;
 
		std::map<std::string, authRequest *> m_authRequests;
 
		std::map<unsigned long, PurpleXfer *> m_xfers;
 
		std::map<std::string, PurpleXfer *> m_unhandledXfers;
 
		std::vector<PurpleXfer *> m_waitingXfers;
 
};
 

	
 
static bool getStatus(PurpleBuddy *m_buddy, pbnetwork::StatusType &status, std::string &statusMessage) {
 
	PurplePresence *pres = purple_buddy_get_presence_wrapped(m_buddy);
 
	if (pres == NULL)
 
		return false;
 
	PurpleStatus *stat = purple_presence_get_active_status_wrapped(pres);
 
	if (stat == NULL)
 
		return false;
 
	int st = purple_status_type_get_primitive_wrapped(purple_status_get_type_wrapped(stat));
 

	
 
	switch(st) {
 
		case PURPLE_STATUS_AVAILABLE: {
 
			status = pbnetwork::STATUS_ONLINE;
 
			break;
 
		}
 
		case PURPLE_STATUS_AWAY: {
 
			status = pbnetwork::STATUS_AWAY;
 
			break;
 
		}
 
		case PURPLE_STATUS_UNAVAILABLE: {
 
			status = pbnetwork::STATUS_DND;
 
			break;
 
		}
 
		case PURPLE_STATUS_EXTENDED_AWAY: {
 
			status = pbnetwork::STATUS_XA;
 
			break;
 
		}
 
		case PURPLE_STATUS_OFFLINE: {
 
			status = pbnetwork::STATUS_NONE;
 
			break;
 
		}
 
		default:
 
			status = pbnetwork::STATUS_ONLINE;
 
			break;
 
	}
 

	
 
	const char *message = purple_status_get_attr_string_wrapped(stat, "message");
 

	
 
	if (message != NULL) {
 
		char *stripped = purple_markup_strip_html_wrapped(message);
 
		statusMessage = std::string(stripped);
 
		g_free(stripped);
 
	}
 
	else
 
		statusMessage = "";
 
	return true;
 
}
 

	
 
static std::string getIconHash(PurpleBuddy *m_buddy) {
 
	char *avatarHash = NULL;
 
	PurpleBuddyIcon *icon = purple_buddy_icons_find_wrapped(purple_buddy_get_account_wrapped(m_buddy), purple_buddy_get_name_wrapped(m_buddy));
 
	if (icon) {
 
		avatarHash = purple_buddy_icon_get_full_path_wrapped(icon);
 
		purple_buddy_icon_unref_wrapped(icon);
 
	}
 

	
 
	if (avatarHash) {
 
		// Check if it's patched libpurple which saves icons to directories
 
		char *hash = strrchr(avatarHash,'/');
 
		std::string h;
 
		if (hash) {
 
			char *dot;
 
			hash++;
 
			dot = strchr(hash, '.');
 
			if (dot)
 
				*dot = '\0';
 

	
 
			std::string ret(hash);
 
			g_free(avatarHash);
 
			return ret;
 
		}
 
		else {
 
			std::string ret(avatarHash);
 
			g_free(avatarHash);
 
			return ret;
 
		}
 
	}
 

	
 
	return "";
 
}
 

	
 
static std::vector<std::string> getGroups(PurpleBuddy *m_buddy) {
 
	std::vector<std::string> groups;
 
	if (purple_buddy_get_name_wrapped(m_buddy)) {
 
		GSList *buddies = purple_find_buddies_wrapped(purple_buddy_get_account_wrapped(m_buddy), purple_buddy_get_name_wrapped(m_buddy));
 
		while(buddies) {
 
			PurpleGroup *g = purple_buddy_get_group_wrapped((PurpleBuddy *) buddies->data);
 
			buddies = g_slist_delete_link(buddies, buddies);
 

	
 
			if(g && purple_group_get_name_wrapped(g)) {
 
				groups.push_back(purple_group_get_name_wrapped(g));
 
			}
 
		}
 
	}
 

	
 
	if (groups.empty()) {
 
		groups.push_back("Buddies");
 
	}
 

	
 
	return groups;
 
}
 

	
 
void buddyListNewNode(PurpleBlistNode *node);
 

	
 
static gboolean new_node_cache(void *data) {
 
	NodeCache *cache = (NodeCache *) data;
 
	caching = false;
 
	for (std::map<PurpleBlistNode *, int>::const_iterator it = cache->nodes.begin(); it != cache->nodes.end(); it++) {
 
		buddyListNewNode(it->first);
 
	}
 
	caching = true;
 

	
 
	cache->account->ui_data = NULL;
 
	delete cache;
 

	
 
	return FALSE;
 
}
 

	
 
static void buddyNodeRemoved(PurpleBuddyList *list, PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
	PurpleBuddy *buddy = (PurpleBuddy *) node;
 
	PurpleAccount *account = purple_buddy_get_account_wrapped(buddy);
 

	
 
	if (!account->ui_data) {
 
		return;
 
	}
 

	
 
	NodeCache *cache = (NodeCache *) account->ui_data;
 
	cache->nodes.erase(node);
 
}
 

	
 
void buddyListNewNode(PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
	PurpleBuddy *buddy = (PurpleBuddy *) node;
 
	PurpleAccount *account = purple_buddy_get_account_wrapped(buddy);
 

	
 
	if (caching) {
 
		if (!account->ui_data) {
 
			NodeCache *cache = new NodeCache;
 
			cache->account = account;
 
			cache->timer = purple_timeout_add_wrapped(400, new_node_cache, cache);
 
			account->ui_data = (void *) cache;
 
		}
 

	
 
		NodeCache *cache = (NodeCache *) account->ui_data;
 
		cache->nodes[node] = 1;
 
		return;
 
	}
 
	
 

	
 
	std::vector<std::string> groups = getGroups(buddy);
 
	LOG4CXX_INFO(logger, "Buddy updated " << np->m_accounts[account] << " " << purple_buddy_get_name_wrapped(buddy) << " " << getAlias(buddy) << " group (" << groups.size() << ")=" << groups[0]);
 

	
 
	// Status
 
	pbnetwork::StatusType status = pbnetwork::STATUS_NONE;
 
	std::string message;
 
	getStatus(buddy, status, message);
 

	
 
	// Tooltip
 
	PurplePlugin *prpl = purple_find_prpl_wrapped(purple_account_get_protocol_id_wrapped(account));
 
	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 

	
 
	bool blocked = false;
 
	if (CONFIG_BOOL(config, "service.enable_privacy_lists")) {
 
		if (prpl_info && prpl_info->tooltip_text) {
 
			PurpleNotifyUserInfo *user_info = purple_notify_user_info_new_wrapped();
 
			prpl_info->tooltip_text(buddy, user_info, true);
 
			GList *entries = purple_notify_user_info_get_entries_wrapped(user_info);
 

	
 
			while (entries) {
 
				PurpleNotifyUserInfoEntry *entry = (PurpleNotifyUserInfoEntry *)(entries->data);
 
				if (purple_notify_user_info_entry_get_label_wrapped(entry) && purple_notify_user_info_entry_get_value_wrapped(entry)) {
 
					std::string label = purple_notify_user_info_entry_get_label_wrapped(entry);
 
					if (label == "Blocked" ) {
 
						if (std::string(purple_notify_user_info_entry_get_value_wrapped(entry)) == "Yes") {
 
							blocked = true;
 
							break;
 
						}
 
					}
 
				}
 
				entries = entries->next;
 
			}
 
			purple_notify_user_info_destroy_wrapped(user_info);
 
		}
 

	
 
		if (!blocked) {
 
			blocked = purple_privacy_check_wrapped(account, purple_buddy_get_name_wrapped(buddy)) == false;
 
		}
 
		else {
 
			bool purpleBlocked = purple_privacy_check_wrapped(account, purple_buddy_get_name_wrapped(buddy)) == false;
 
			if (blocked != purpleBlocked) {
 
				purple_privacy_deny_wrapped(account, purple_buddy_get_name_wrapped(buddy), FALSE, FALSE);
 
			}
 
		}
 
	}
 

	
 
	np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name_wrapped(buddy), getAlias(buddy), getGroups(buddy), status, message, getIconHash(buddy),
 
		blocked
 
	);
 
}
 

	
 
static void buddyListUpdate(PurpleBuddyList *list, PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
	buddyListNewNode(node);
 
}
 

	
 
static void buddyPrivacyChanged(PurpleBlistNode *node, void *data) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
	buddyListUpdate(NULL, node);
 
}
 

	
 
static void NodeRemoved(PurpleBlistNode *node, void *data) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
// 	PurpleBuddy *buddy = (PurpleBuddy *) node;
 
}
 

	
 
static void buddyListSaveNode(PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
}
 

	
 
static void buddyListSaveAccount(PurpleAccount *account) {
 
}
 

	
 
static void buddyListRemoveNode(PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
}
 

	
 
static PurpleBlistUiOps blistUiOps =
 
{
 
	NULL,
 
	buddyListNewNode,
 
	NULL,
 
	buddyListUpdate,
 
	buddyNodeRemoved,
 
	NULL,
 
	NULL,
 
	NULL, // buddyListAddBuddy,
 
	NULL,
 
	NULL,
 
	buddyListSaveNode,
 
	buddyListRemoveNode,
 
	buddyListSaveAccount,
 
	NULL
 
};
 

	
 
static void conv_write(PurpleConversation *conv, const char *who, const char *alias, const char *msg, PurpleMessageFlags flags, time_t mtime) {
 
	if (flags & PURPLE_MESSAGE_SYSTEM && CONFIG_STRING(config, "service.protocol") == "prpl-telegram") {
 
		PurpleAccount *account = purple_conversation_get_account_wrapped(conv);
 

	
 
	// 	char *striped = purple_markup_strip_html_wrapped(message);
 
	// 	std::string msg = striped;
 
	// 	g_free(striped);
 

	
 

	
 
		// Escape HTML characters.
 
		char *newline = purple_strdup_withhtml_wrapped(msg);
 
		char *strip, *xhtml;
 
		purple_markup_html_to_xhtml_wrapped(newline, &xhtml, &strip);
 
	// 	xhtml_linkified = spectrum_markup_linkify(xhtml);
 
		std::string message_(strip);
 

	
 
		std::string xhtml_(xhtml);
 
		g_free(newline);
 
		g_free(xhtml);
 
	// 	g_free(xhtml_linkified);
 
		g_free(strip);
 

	
 
		// AIM and XMPP adds <body>...</body> here...
 
		if (xhtml_.find("<body>") == 0) {
 
			xhtml_ = xhtml_.substr(6);
 
			if (xhtml_.find("</body>") != std::string::npos) {
 
				xhtml_ = xhtml_.substr(0, xhtml_.find("</body>"));
 
			}
 
		}
 

	
 
		if (xhtml_ == message_) {
 
			xhtml_ = "";
 
		}
 

	
 
		std::string timestamp;
 
		if (mtime && (unsigned long) time(NULL)-10 > (unsigned long) mtime/* && (unsigned long) time(NULL) - 31536000 < (unsigned long) mtime*/) {
 
			char buf[80];
 
			strftime(buf, sizeof(buf), "%Y%m%dT%H%M%S", gmtime(&mtime));
 
			timestamp = buf;
 
		}
 

	
 
	// 	LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "'");
libtransport/Conversation.cpp
Show inline comments
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * 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 <iostream>
 
#include "transport/Conversation.h"
 
#include "transport/ConversationManager.h"
 
#include "transport/User.h"
 
#include "transport/Transport.h"
 
#include "transport/Buddy.h"
 
#include "transport/RosterManager.h"
 
#include "transport/Frontend.h"
 
#include "transport/Config.h"
 
#include "transport/Logging.h"
 

	
 
#include "Swiften/Elements/MUCItem.h"
 
#include "Swiften/Elements/MUCOccupant.h"
 
#include "Swiften/Elements/MUCUserPayload.h"
 
#include "Swiften/Elements/Delay.h"
 
#include "Swiften/Elements/MUCPayload.h"
 
#include "Swiften/Elements/VCardUpdate.h"
 

	
 
namespace Transport {
 
	
 
DEFINE_LOGGER(logger, "Conversation");
 

	
 
Conversation::Conversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMUC) : m_conversationManager(conversationManager) {
 
	m_legacyName = legacyName;
 
	m_muc = isMUC;
 
	m_jid = m_conversationManager->getUser()->getJID().toBare();
 
	m_sentInitialPresence = false;
 
	m_nicknameChanged = false;
 
	m_mucEscaping = false;
 

	
 
	if (CONFIG_BOOL_DEFAULTED(conversationManager->getComponent()->getConfig(), "features.rawxml", false)) {
 
		m_sentInitialPresence = true;
 
	}
 
}
 

	
 
Conversation::~Conversation() {
 
}
 

	
 
void Conversation::setMUCEscaping(bool mucEscaping) {
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Setting MUC escaping to " << mucEscaping);
 
	m_mucEscaping = mucEscaping;
 
}
 

	
 
void Conversation::destroyRoom() {
 
	if (m_muc) {
 
		Swift::Presence::ref presence = Swift::Presence::create();
 
		std::string legacyName = m_legacyName;
 
		if (!m_mucEscaping && legacyName.find_last_of("@") != std::string::npos) {
 
			legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
		}
 
		legacyName = Swift::JID::getEscapedNode(legacyName);
 
		presence->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), m_nickname));
 
		presence->setType(Swift::Presence::Unavailable);
 

	
 
		Swift::MUCItem item;
 
		item.affiliation = Swift::MUCOccupant::NoAffiliation;
 
		item.role = Swift::MUCOccupant::NoRole;
 
		item.actor = "Transport";
 
		item.reason = "Spectrum 2 transport is being shut down.";
 
		Swift::MUCUserPayload *p = new Swift::MUCUserPayload ();
 
		p->addItem(item);
 

	
 
		Swift::MUCUserPayload::StatusCode c;
 
		c.code = 332;
 
		p->addStatusCode(c);
 
		Swift::MUCUserPayload::StatusCode c2;
 
		c2.code = 307;
 
		p->addStatusCode(c2);
 

	
 
		presence->addPayload(boost::shared_ptr<Swift::Payload>(p));
 
		BOOST_FOREACH(const Swift::JID &jid, m_jids) {
 
			presence->setTo(jid);
 
			m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 
		}
 
	}
 
}
 

	
 
void Conversation::setRoom(const std::string &room) {
 
	m_room = room;
 
	m_legacyName = m_room + "/" + m_legacyName;
 
}
 

	
 
void Conversation::cacheMessage(boost::shared_ptr<Swift::Message> &message) {
 
	boost::posix_time::ptime timestamp = boost::posix_time::second_clock::universal_time();
 
	boost::shared_ptr<Swift::Delay> delay(boost::make_shared<Swift::Delay>());
 
	delay->setStamp(timestamp);
 
	message->addPayload(delay);
 
	m_cachedMessages.push_back(message);
 
	if (m_cachedMessages.size() > 100) {
 
		m_cachedMessages.pop_front();
 
	}
 
}
 

	
 
void Conversation::handleRawMessage(boost::shared_ptr<Swift::Message> &message) {
 
	if (message->getType() != Swift::Message::Groupchat) {
 
		if (m_conversationManager->getComponent()->inServerMode() && m_conversationManager->getUser()->shouldCacheMessages()) {
 
			cacheMessage(message);
 
		}
 
		else {
 
			m_conversationManager->getComponent()->getFrontend()->sendMessage(message);
 
		}
 
	}
 
	else {
 
		if (m_jids.empty()) {
 
			cacheMessage(message);
 
		}
 
		else {
 
			BOOST_FOREACH(const Swift::JID &jid, m_jids) {
 
				message->setTo(jid);
 
				// Subject has to be sent after our own presence (the one with code 110)
 
				if (!message->getSubject().empty() && m_sentInitialPresence == false) {
 
					m_subject = message;
 
					return;
 
				}
 
				m_conversationManager->getComponent()->getFrontend()->sendMessage(message);
 
			}
 
		}
 
	}
 
}
 

	
 
void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, const std::string &nickname) {
 
	if (m_muc) {
 
		message->setType(Swift::Message::Groupchat);
 
	}
 
	else {
 
		if (message->getType() == Swift::Message::Headline) {
 
			if (m_conversationManager->getUser()->getUserSetting("send_headlines") != "1") {
 
				message->setType(Swift::Message::Chat);
 
			}
 
		}
 
		else {
 
			message->setType(Swift::Message::Chat);
 
		}
 
	}
 

	
 
	std::string n = nickname;
 
	if (n.empty() && !m_room.empty() && !m_muc) {
 
		n = m_nickname;
 
	}
 

	
 
	if (message->getType() != Swift::Message::Groupchat) {
 
		message->setTo(m_jid);
 
		// normal message
 
		if (n.empty()) {
 
			Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName);
 
			if (buddy) {
 
				message->setFrom(buddy->getJID());
 
			}
 
			else {
 
				std::string name = m_legacyName;
 
				if (CONFIG_BOOL_DEFAULTED(m_conversationManager->getComponent()->getConfig(), "service.jid_escaping", true)) {
 
					name = Swift::JID::getEscapedNode(m_legacyName);
 
				}
 
				else {
 
					if (name.find_last_of("@") != std::string::npos) {
 
						name.replace(name.find_last_of("@"), 1, "%");
 
					}
 
				}
 

	
 
				message->setFrom(Swift::JID(name, m_conversationManager->getComponent()->getJID().toBare(), "bot"));
 
			}
 
		}
 
		// PM message
 
		else {
 
			if (m_room.empty()) {
 
				message->setFrom(Swift::JID(n, m_conversationManager->getComponent()->getJID().toBare(), "user"));
 
			}
 
			else {
 
				std::string legacyName = m_room;
 
				if (!m_mucEscaping && legacyName.find_last_of("@") != std::string::npos) {
 
					legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
				}
 
				legacyName = Swift::JID::getEscapedNode(legacyName);
 
				message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n));
 
			}
 
		}
 
	}
 
	else {
 
		std::string legacyName = m_legacyName;
 
		if (!m_mucEscaping && legacyName.find_last_of("@") != std::string::npos) {
 
			legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
		}
 
		legacyName = Swift::JID::getEscapedNode(legacyName);
 

	
 
		std::string n = nickname;
 
		if (n.empty()) {
 
			n = " ";
 
		}
 

	
 
		std::map<std::string, Participant>::iterator it = m_participants.find(n);
 
		if (it != m_participants.end() && !it->second.alias.empty()) {
 
			n = it->second.alias;
 
		}
 

	
 
		message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n));
 
		LOG4CXX_INFO(logger, "MSG FROM " << message->getFrom().toString());
 
	}
 

	
 
	handleRawMessage(message);
 
}
 

	
 
std::string Conversation::getParticipants() {
 
	std::string ret;
 
	for (std::map<std::string, Participant>::iterator it = m_participants.begin(); it != m_participants.end(); it++) {
 
		ret += (*it).second.presence->getFrom().getResource() + ", ";
 
	}
 
	return ret;
 
}
 

	
 
void Conversation::sendParticipants(const Swift::JID &to) {
 
	for (std::map<std::string, Participant>::iterator it = m_participants.begin(); it != m_participants.end(); it++) {
 
		(*it).second.presence->setTo(to);
 
		m_conversationManager->getComponent()->getFrontend()->sendPresence((*it).second.presence);
 
	}
 
}
 

	
 
void Conversation::sendCachedMessages(const Swift::JID &to) {
 
	for (std::list<boost::shared_ptr<Swift::Message> >::const_iterator it = m_cachedMessages.begin(); it != m_cachedMessages.end(); it++) {
 
		if (to.isValid()) {
 
			(*it)->setTo(to);
 
		}
 
		else {
 
			(*it)->setTo(m_jid.toBare());
 
		}
 
		m_conversationManager->getComponent()->getFrontend()->sendMessage(*it);
 
	}
 

	
 
	if (m_subject) {
 
		if (to.isValid()) {
 
			m_subject->setTo(to);
 
		}
 
		else {
 
			m_subject->setTo(m_jid.toBare());
 
		}
 
		m_conversationManager->getComponent()->getFrontend()->sendMessage(m_subject);
 
	}
 

	
 
	m_cachedMessages.clear();
 
}
 

	
 
Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname, const std::string &iconhash) {
 
	std::string nickname = nick;
 
	Swift::Presence::ref presence = Swift::Presence::create();
 
	std::string legacyName = m_legacyName;
 
	if (m_muc) {
 
		if (!m_mucEscaping && legacyName.find_last_of("@") != std::string::npos) {
 
			legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
		}
 
		legacyName = Swift::JID::getEscapedNode(legacyName);
 
	}
 
	presence->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
 
	presence->setType(Swift::Presence::Available);
 

	
 
	if (!statusMessage.empty())
 
		presence->setStatus(statusMessage);
 

	
 
	Swift::StatusShow s((Swift::StatusShow::Type) status);
 

	
 
	if (s.getType() == Swift::StatusShow::None) {
 
		presence->setType(Swift::Presence::Unavailable);
 
	}
 

	
 
	presence->setShow(s.getType());
 

	
 
	Swift::MUCUserPayload *p = new Swift::MUCUserPayload ();
 
	if (m_nickname == nickname) {
 
		if (flag & PARTICIPANT_FLAG_CONFLICT) {
 
			delete p;
 
			presence->setType(Swift::Presence::Error);
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::MUCPayload()));
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::ErrorPayload(Swift::ErrorPayload::Conflict)));
 
			return presence;
 
		}
 
		else if (flag & PARTICIPANT_FLAG_NOT_AUTHORIZED) {
 
			delete p;
 
			presence->setType(Swift::Presence::Error);
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::MUCPayload()));
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::ErrorPayload(Swift::ErrorPayload::NotAuthorized, Swift::ErrorPayload::Auth, statusMessage)));
 
			return presence;
 
		}
 
		else if (flag & PARTICIPANT_FLAG_ROOM_NOT_FOUD) {
 
			delete p;
 
			presence->setType(Swift::Presence::Error);
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::MUCPayload()));
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::ErrorPayload(Swift::ErrorPayload::ItemNotFound, Swift::ErrorPayload::Cancel, statusMessage)));
 
			return presence;
 
		}
 
		else {
 
			Swift::MUCUserPayload::StatusCode c;
 
			c.code = 110;
 
			p->addStatusCode(c);
 
			if (m_nicknameChanged) {
 
				Swift::MUCUserPayload::StatusCode c;
 
				c.code = 210;
 
				p->addStatusCode(c);
 
				m_nicknameChanged = false;
 
			}
 
			m_sentInitialPresence = true;
 
		}
 
	}
 

	
 

	
 
	Swift::MUCItem item;
 
	
 
	item.affiliation = Swift::MUCOccupant::Member;
 
	item.role = Swift::MUCOccupant::Participant;
 

	
 
	if (flag & PARTICIPANT_FLAG_MODERATOR) {
 
		item.affiliation = Swift::MUCOccupant::Admin;
 
		item.role = Swift::MUCOccupant::Moderator;
 
	}
 

	
 
	if (!newname.empty()) {
 
		item.nick = newname;
 
		Swift::MUCUserPayload::StatusCode c;
 
		c.code = 303;
 
		p->addStatusCode(c);
 
		presence->setType(Swift::Presence::Unavailable);
 
	}
 

	
 
	if (!iconhash.empty()) {
 
		presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::VCardUpdate (iconhash)));
 
	}
 
	
 
	p->addItem(item);
 
	presence->addPayload(boost::shared_ptr<Swift::Payload>(p));
 
	return presence;
 
}
 

	
 

	
 
void Conversation::setNickname(const std::string &nickname) {
 
	if (!nickname.empty() && m_nickname != nickname) {
 
		m_nicknameChanged = true;
 
	}
 
	m_nickname = nickname;
 
}
 

	
 
void Conversation::handleRawPresence(Swift::Presence::ref presence) {
 
	// TODO: Detect nickname change.
 
	m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 
	m_participants[presence->getFrom().getResource()].presence = presence;
 
}
 

	
 
void Conversation::removeJID(const Swift::JID &jid) {
 
	m_jids.remove(jid);
 
}
 

	
 
void Conversation::handleParticipantChanged(const std::string &nick, Conversation::ParticipantFlag flag, int status, const std::string &statusMessage, const std::string &newname, const std::string &iconhash, const std::string &alias) {
 
	Swift::Presence::ref presence = generatePresence(alias.empty() ? nick : alias, flag, status, statusMessage, newname, iconhash);
 

	
 
	if (presence->getType() == Swift::Presence::Unavailable) {
 
		m_participants.erase(nick);
 
	}
 
	else {
 
		m_participants[nick].presence = presence;
 
		m_participants[nick].alias = alias;
 
	}
 

	
 

	
 
	BOOST_FOREACH(const Swift::JID &jid, m_jids) {
 
		presence->setTo(jid);
 
		m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 
	}
 
	if (!newname.empty()) {
 
		handleParticipantChanged(newname, flag, status, statusMessage, "", iconhash);
 
	}
 

	
 
	if (m_sentInitialPresence && m_subject) {
 
		m_conversationManager->getComponent()->getFrontend()->sendMessage(m_subject);
 
		m_subject.reset();
 
	}
 

	
 
	// We send error presences only to inform user that he is disconnected
 
	// from the room. This code must be extended in case we start sending error
 
	// presences in other situations.
 
	if (presence->getType() == Swift::Presence::Error) {
 
		m_conversationManager->getUser()->leaveRoom(m_legacyName);
 
	}
 
}
 

	
 
}
tests/libtransport/localbuddy.cpp
Show inline comments
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "basictest.h"
 

	
 
using namespace Transport;
 

	
 
class LocalBuddyTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(LocalBuddyTest);
 
	CPPUNIT_TEST(localBuddySize);
 
	CPPUNIT_TEST(createWithInvalidName);
 
	CPPUNIT_TEST(buddyFlagsFromJID);
 
	CPPUNIT_TEST(JIDToLegacyName);
 
	CPPUNIT_TEST(getSafeName);
 
	CPPUNIT_TEST(sendPresence);
 
	CPPUNIT_TEST(setAlias);
 
	CPPUNIT_TEST(sendPresenceTypeNone);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		void setUp (void) {
 
			setMeUp();
 
			connectUser();
 
			received.clear();
 
		}
 

	
 
		void tearDown (void) {
 
			received.clear();
 
			disconnectUser();
 
			tearMeDown();
 
		}
 

	
 
	void localBuddySize() {
 
		std::cout << " = " << sizeof(LocalBuddy) << " B";
 
	}
 

	
 
	void createWithInvalidName() {
 
		User *user = userManager->getUser("user@localhost");
 
		CPPUNIT_ASSERT(user);
 

	
 
		std::vector<std::string> grp;
 
		grp.push_back("group");
 

	
 
		// with BUDDY_JID_ESCAPING it escapes /
 
		LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "msn/something", "Buddy 1", grp, BUDDY_JID_ESCAPING);
 
		CPPUNIT_ASSERT(buddy->isValid());
 
		CPPUNIT_ASSERT_EQUAL(std::string("msn\\2fsomething@localhost/bot"), buddy->getJID().toString());
 
		delete buddy;
 

	
 
		// without BUDDY_JID_ESCAPING it shoudl fail
 
		buddy = new LocalBuddy(user->getRosterManager(), -1, "msn/something", "Buddy 1", grp);
 
		CPPUNIT_ASSERT(!buddy->isValid());
 
		delete buddy;
 

	
 
		buddy = new LocalBuddy(user->getRosterManager(), -1, "\xd7\x92\xd7\x9c\xd7\x99\xd7\x9d@nimbuzz.com", "Buddy 1", grp);
 
		CPPUNIT_ASSERT(!buddy->isValid());
 
		delete buddy;
 
	}
 

	
 
	void JIDToLegacyName() {
 
		CPPUNIT_ASSERT_EQUAL(std::string("hanzz@test"), Buddy::JIDToLegacyName("hanzz\\40test@localhost/bot"));
 
		CPPUNIT_ASSERT_EQUAL(std::string("hanzz@test"), Buddy::JIDToLegacyName("hanzz%test@localhost/bot"));
 
	}
 

	
 
	void getSafeName() {
 
		User *user = userManager->getUser("user@localhost");
 
		CPPUNIT_ASSERT(user);
 

	
 
		std::vector<std::string> grp;
 
		grp.push_back("group1");
 
		LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1@test", "Buddy 1", grp, BUDDY_JID_ESCAPING);
 

	
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test"), buddy->getSafeName());
 

	
 
		buddy->setFlags(BUDDY_NO_FLAG);
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1%test"), buddy->getSafeName());
 
	}
 

	
 
	void buddyFlagsFromJID() {
 
		CPPUNIT_ASSERT_EQUAL(BUDDY_JID_ESCAPING, Buddy::buddyFlagsFromJID("hanzz\\40test@localhost/bot"));
 
		CPPUNIT_ASSERT_EQUAL(BUDDY_NO_FLAG, Buddy::buddyFlagsFromJID("hanzz%test@localhost/bot"));
 
	}
 

	
 
	void sendPresence() {
 
		User *user = userManager->getUser("user@localhost");
 
		CPPUNIT_ASSERT(user);
 

	
 
		std::vector<std::string> grp;
 
		grp.push_back("group1");
 
		LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1", "Buddy 1", grp, BUDDY_JID_ESCAPING);
 
		buddy->setStatus(Swift::StatusShow(Swift::StatusShow::Away), "status1");
 
		user->getRosterManager()->setBuddy(buddy);
 
		received.clear();
 

	
 
		buddy->sendPresence();
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getShow());
 
		CPPUNIT_ASSERT_EQUAL(std::string("status1"), dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getStatus());
 
	}
 

	
 
	void setAlias() {
 
		User *user = userManager->getUser("user@localhost");
 
		CPPUNIT_ASSERT(user);
 

	
 
		std::vector<std::string> grp;
 
		grp.push_back("group1");
 
		LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1", "Buddy 1", grp, BUDDY_JID_ESCAPING);
 
		buddy->setStatus(Swift::StatusShow(Swift::StatusShow::Away), "status1");
 
		user->getRosterManager()->setBuddy(buddy);
 
		received.clear();
 

	
 
		buddy->setAlias("Buddy 2");
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		Swift::RosterPayload::ref payload1 = getStanza(received[0])->getPayload<Swift::RosterPayload>();
 
		CPPUNIT_ASSERT(payload1);
 
		CPPUNIT_ASSERT_EQUAL(1, (int) payload1->getItems().size());
 
		Swift::RosterItemPayload item = payload1->getItems()[0];
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1"), Buddy::JIDToLegacyName(item.getJID()));
 
		CPPUNIT_ASSERT_EQUAL(std::string("Buddy 2"), item.getName());
 
	}
 

	
 
	void sendPresenceTypeNone() {
 
		User *user = userManager->getUser("user@localhost");
 
		CPPUNIT_ASSERT(user);
 

	
 
		std::vector<std::string> grp;
 
		grp.push_back("group1");
 
		LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1", "Buddy 1", grp, BUDDY_JID_ESCAPING);
 
		buddy->setStatus(Swift::StatusShow(Swift::StatusShow::Away), "");
 
		user->getRosterManager()->setBuddy(buddy);
 
		received.clear();
 

	
 
		buddy->setStatus(Swift::StatusShow(Swift::StatusShow::None), "");
 
		dumpReceived();
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::None, dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getShow());
 
	}
 

	
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (LocalBuddyTest);
0 comments (0 inline, 0 general)