From 48f5bf16ff9e2c8acd095bed521ff7951a8afddf Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Fri, 7 May 2010 10:55:02 +0000
Subject: Don't segfault when someone leaves a MUC


diff --git a/Swiften/Roster/Roster.cpp b/Swiften/Roster/Roster.cpp
index 9226a63..caf2b5e 100644
--- a/Swiften/Roster/Roster.cpp
+++ b/Swiften/Roster/Roster.cpp
@@ -82,9 +82,9 @@ struct JIDEqualsTo {
 };
 
 void Roster::removeContact(const JID& jid) {
-	std::vector<ContactRosterItem*> items = itemMap_[jid.toBare()];
-	items.erase(std::remove_if(items.begin(), items.end(), JIDEqualsTo(jid)), items.end());
-	if (items.size() == 0) {
+	std::vector<ContactRosterItem*>* items = &itemMap_[jid.toBare()];
+	items->erase(std::remove_if(items->begin(), items->end(), JIDEqualsTo(jid)), items->end());
+	if (items->size() == 0) {
 		itemMap_.erase(jid.toBare());
 	}
 	//Causes the delete
@@ -98,8 +98,8 @@ void Roster::removeContactFromGroup(const JID& jid, const String& groupName) {
 		GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it);
 		if (group && group->getDisplayName() == groupName) {
 			ContactRosterItem* deleted = group->removeChild(jid);
-			std::vector<ContactRosterItem*> items = itemMap_[jid.toBare()];
-			items.erase(std::remove(items.begin(), items.end(), deleted), items.end());
+			std::vector<ContactRosterItem*>* items = &itemMap_[jid.toBare()];
+			items->erase(std::remove(items->begin(), items->end(), deleted), items->end());
 		}
 		it++;
 	}
@@ -116,6 +116,7 @@ void Roster::applyOnItems(const RosterItemOperation& operation) {
 
 void Roster::applyOnItem(const RosterItemOperation& operation, const JID& jid) {
 	foreach (ContactRosterItem* item, itemMap_[jid.toBare()]) {
+		//std::cout << "Applying on item " << item << " : " << item->getDisplayName() << std::endl;
 		operation(item);
 		filterContact(item, item->getParent());
 	}
diff --git a/Swiften/Roster/UnitTest/RosterTest.cpp b/Swiften/Roster/UnitTest/RosterTest.cpp
index 2697747..d170396 100644
--- a/Swiften/Roster/UnitTest/RosterTest.cpp
+++ b/Swiften/Roster/UnitTest/RosterTest.cpp
@@ -10,6 +10,7 @@
 
 #include "Swiften/Roster/Roster.h"
 #include "Swiften/Roster/GroupRosterItem.h"
+#include "Swiften/Roster/SetPresence.h"
 
 using namespace Swift;
 
@@ -20,6 +21,7 @@ class RosterTest : public CppUnit::TestFixture
 		CPPUNIT_TEST(testRemoveContact);
 		CPPUNIT_TEST(testRemoveSecondContact);
 		CPPUNIT_TEST(testRemoveSecondContactSameBare);
+		CPPUNIT_TEST(testApplyPresenceLikeMUC);
 		CPPUNIT_TEST_SUITE_END();
 
 	private:
@@ -84,6 +86,44 @@ class RosterTest : public CppUnit::TestFixture
 			CPPUNIT_ASSERT_EQUAL(String("Bert"), ((GroupRosterItem*)roster_->getRoot()->getChildren()[0])->getChildren()[0]->getDisplayName());
 		}
 
+		void testApplyPresenceLikeMUC() {
+			JID jid4a("a@b/c");
+			JID jid4b("a@b/d");
+			JID jid4c("a@b/e");
+			roster_->addContact(jid4a, "Bird", "group1");
+			roster_->addContact(jid4b, "Cookie", "group1");
+			roster_->removeContact(jid4b);
+			roster_->addContact(jid4c, "Bert", "group1");
+			roster_->addContact(jid4b, "Ernie", "group1");
+			boost::shared_ptr<Presence> presence(new Presence());
+			presence->setShow(StatusShow::DND);
+			presence->setFrom(jid4a);
+			roster_->applyOnItems(SetPresence(presence, JID::WithResource));
+			presence->setFrom(jid4b);
+			roster_->applyOnItems(SetPresence(presence, JID::WithResource));
+			presence->setFrom(jid4c);
+			roster_->applyOnItems(SetPresence(presence, JID::WithResource));
+			
+			presence = boost::shared_ptr<Presence>(new Presence());
+			presence->setFrom(jid4b);
+			presence->setShow(StatusShow::Online);
+			roster_->applyOnItems(SetPresence(presence, JID::WithResource));
+			std::vector<RosterItem*> children = ((GroupRosterItem*)roster_->getRoot()->getDisplayedChildren()[0])->getDisplayedChildren();
+			CPPUNIT_ASSERT_EQUAL(3, (int)children.size());
+			
+			/* Check order */
+			CPPUNIT_ASSERT_EQUAL(String("Ernie"), children[0]->getDisplayName());
+			CPPUNIT_ASSERT_EQUAL(String("Bert"), children[1]->getDisplayName());
+			CPPUNIT_ASSERT_EQUAL(String("Bird"), children[2]->getDisplayName());
+
+			presence = boost::shared_ptr<Presence>(new Presence());
+			presence->setFrom(jid4c);
+			presence->setType(Presence::Unavailable);
+			roster_->removeContact(jid4c);
+			roster_->applyOnItems(SetPresence(presence, JID::WithResource));
+
+		}
+
 };
 CPPUNIT_TEST_SUITE_REGISTRATION(RosterTest);
 
-- 
cgit v0.10.2-6-g49f6