void AP_UnixDialog_CollaborationAddBuddy::_populateWindowData()
{
	// populate the account combobox
	GtkListStore* store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
	GtkTreeIter iter;
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();

	for (UT_uint32 i = 0; i < pManager->getAccounts().size(); i++)
	{
		AccountHandler* pHandler = pManager->getAccounts()[i];
		if (pHandler && pHandler->allowsManualBuddies())
		{
			gtk_list_store_append (store, &iter);
			gtk_list_store_set (store, &iter,
						DESC_COLUMN, pHandler->getDescription().utf8_str(),
						HANDLER_COLUMN, pHandler,
						-1);
		}
	}
	m_model = GTK_TREE_MODEL (store);
	gtk_combo_box_set_model(GTK_COMBO_BOX(m_wAccount), m_model);

	// if we have at least one account, then make sure the first one is selected
	if (pManager->getAccounts().size() > 0)
	{
		gtk_combo_box_set_active(GTK_COMBO_BOX(m_wAccount), 0);
	}
	else
	{
		// nope, we don't have any account :'-(
		gtk_combo_box_set_active(GTK_COMBO_BOX(m_wAccount), -1);
	}
}
void AP_UnixDialog_CollaborationAccounts::eventSelectAccount()
{
	UT_DEBUGMSG(("AP_UnixDialog_CollaborationAccounts::eventSelectAccount()\n"));
	AccountHandler* pHandler = _getSelectedAccountHandler();
	gtk_widget_set_sensitive(m_wProperties, pHandler != NULL && pHandler->canEditProperties());
	gtk_widget_set_sensitive(m_wDelete, pHandler != NULL && pHandler->canDelete());
}
bool AbiCollabSessionManager::_canInitiateSessionTakeover(AbiCollab* pSession)
{
	UT_return_val_if_fail(pSession, false);
	UT_return_val_if_fail(pSession->isLocallyControlled(), false);

	const std::map<BuddyPtr, std::string> collaborators = pSession->getCollaborators();

	if (collaborators.size() == 0)
		return false;

	/*
	NOTE: for now, we only allow session takeover, if:

	1. All buddies use the same account handler type
	2. The account handler actually supports session takeover
	3. All buddies are actually owned by the same account handler instance
	
	Condition 1 and 2 are ok, but 3 needs fixing soon.
	*/

	AccountHandler* pHandler = (*collaborators.begin()).first->getHandler();
	if (!pHandler->allowsSessionTakeover())
		return false;

	for (std::map<BuddyPtr, std::string>::const_iterator cit = ++collaborators.begin(); cit != collaborators.end(); cit++)
		if (((*cit).first)->getHandler() != pHandler)
			return false;

	return true;
}
void AbiCollab::addCollaborator(BuddyPtr pCollaborator)
{
    UT_DEBUGMSG(("AbiCollab::addCollaborator()\n"));
    UT_return_if_fail(pCollaborator)

    // check if this buddy is in the access control list if we are hosting
    // this session
    if (isLocallyControlled())
    {
        AccountHandler* pAccount = pCollaborator->getHandler();
        UT_return_if_fail(pAccount);
        if (!pAccount->hasAccess(m_vAcl, pCollaborator))
        {
            UT_ASSERT(UT_NOT_IMPLEMENTED);
            return;
        }
    }

    // check for duplicates (as long as we assume a collaborator can only be part of a collaboration session once)
    std::map<BuddyPtr, std::string>::iterator it = m_vCollaborators.find(pCollaborator);
    if (it != m_vCollaborators.end())
    {
        UT_DEBUGMSG(("Attempting to add buddy '%s' twice to a collaboration session!", pCollaborator->getDescription().utf8_str()));
        UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
        return;
    }

    m_vCollaborators[pCollaborator] = ""; // will fill the remote document UUID later once we receive a packet from this buddy
}
void AbiCollab::_restartAsMaster()
{
    UT_DEBUGMSG(("AbiCollab::_restartAsMaster()\n"));

    m_Import.masterInit();
    m_Export.masterInit();

    // the session controller will never have to revert individual changerecords,
    // so we can re-enable changerecord coalescing
    // FIXME: enable this
    //pDoc->setCoalescingMask(true);

    // inform everyone that we can restart this session
    SessionReconnectAckPacket srap(m_sId, m_pDoc->getDocUUIDString(), m_pDoc->getCRNumber());
    for (std::map<BuddyPtr, std::string>::iterator it = m_vCollaborators.begin(); it != m_vCollaborators.end(); it++)
    {
        BuddyPtr pBuddy = (*it).first;
        UT_continue_if_fail(pBuddy);

        AccountHandler* pHandler = pBuddy->getHandler();
        UT_continue_if_fail(pHandler);

        pHandler->send(&srap, pBuddy);
    }

    // we're the master now!
    m_eTakeoveState = STS_NONE;

    _pushOutgoingQueue();
}
// should we move this to AbiCollab.cpp ?
void AbiCollabSessionManager::updateAcl(AbiCollab* pSession, AccountHandler* pAccount, const std::vector<std::string> vAcl)
{
	UT_return_if_fail(pSession);
	UT_return_if_fail(pAccount);

	// check if all current collaborators are still allowed to collaborate; if not,
	// then remove them from the session
	const std::map<BuddyPtr, std::string> collaborators = pSession->getCollaborators();
	for (std::map<BuddyPtr, std::string>::const_iterator cit = collaborators.begin(); cit != collaborators.end(); cit++)
	{
		BuddyPtr pBuddy = (*cit).first;
		UT_continue_if_fail(pBuddy);
		AccountHandler* pBuddyAccount = pBuddy->getHandler();
		UT_continue_if_fail(pBuddyAccount);
		UT_continue_if_fail(pBuddyAccount == pAccount);
		if (!pBuddyAccount->hasAccess(vAcl, pBuddy))
		{
			// this current collaborator has been banned from the session, so
			// disconnect him
			UT_ASSERT_HARMLESS(UT_NOT_IMPLEMENTED);
		}
	}

	// set the new ACL on the account handler
	pAccount->setAcl(pSession, vAcl);

	// set the new access control list on the session
	pSession->setAcl(vAcl);
}
int main()
{
	AccountHandler KookminAccountHandler;
	while (KookminAccountHandler.ISBooting()) {
		KookminAccountHandler.MainMenu();
	}
	return 0;
}
void AP_Dialog_CollaborationShare::eventAccountChanged()
{
	UT_DEBUGMSG(("AP_Dialog_CollaborationShare::eventAccountChanged()\n"));
	AccountHandler* pHandler = _getActiveAccountHandler();
	UT_return_if_fail(pHandler);
	
	UT_DEBUGMSG(("Changed account handler to type: %s\n", pHandler->getDisplayType().utf8_str()));
	PD_Document *pDoc = static_cast<PD_Document*>(XAP_App::getApp()->getLastFocussedFrame()->getCurrentDoc());
	UT_return_if_fail(pDoc);
	_setAccountHint(pHandler->getShareHint(pDoc));	
	_populateBuddyModel(true);
}
void AbiCollabSessionManager::joinSessionInitiate(BuddyPtr pBuddy, DocHandle* pDocHandle)
{
	UT_return_if_fail(pBuddy);
	UT_return_if_fail(pDocHandle);

	UT_DEBUGMSG(("Initiating join on buddy |%s|, document |%s|\n", pBuddy->getDescription().utf8_str(), pDocHandle->getSessionId().utf8_str()));
	AccountHandler* pHandler = pBuddy->getHandler();
	UT_return_if_fail(pHandler);
	
	pHandler->joinSessionAsync(pBuddy, *pDocHandle);
	// TODO: do some accounting here, so we know we send an auth request in ::joinSession()
}
/*!
 *	Send this packet. Note, the specified packet does still belong to the calling class.
 *	So if we want to store it (for masking), we HAVE to clone it first
 */
void AbiCollab::push(SessionPacket* pPacket)
{
    UT_DEBUGMSG(("AbiCollab::push()\n"));
    UT_return_if_fail(pPacket);

    if (m_bIsReverting)
    {
        UT_DEBUGMSG(("This packet was generated by a local revert triggerd in the import; dropping on the floor!\n"));
        return;
    }

    if (m_bExportMasked)
    {
        m_vecMaskedPackets.push_back(static_cast<SessionPacket*>(pPacket->clone())); // TODO: make this a shared ptr, so we don't need to clone the packet
        return;
    }

    if (!isLocallyControlled() && m_eTakeoveState != STS_NONE)
    {
        // TODO: revert ack packets should still go to old master
        // (or be dropped on the floor, as he probably is not even around anymore)
        UT_DEBUGMSG(("We're in the middle of a session takeover; holding on to the packet until the new master is ready"));
        m_vOutgoingQueue.push_back(static_cast<SessionPacket*>(pPacket->clone())); // TODO: make this a shared ptr, so we don't need to clone the packet
        return;
    }

    // record
    if (m_pRecorder)
        m_pRecorder->storeOutgoing( const_cast<const SessionPacket*>( pPacket ) );

    // TODO: this could go in the session manager
    UT_DEBUGMSG(("Pusing packet to %d collaborators\n", m_vCollaborators.size()));
    for (std::map<BuddyPtr, std::string>::iterator it = m_vCollaborators.begin(); it != m_vCollaborators.end(); it++)
    {
        BuddyPtr pCollaborator = (*it).first;
        UT_continue_if_fail(pCollaborator);

        UT_DEBUGMSG(("Pushing packet to collaborator with descriptor: %s\n", pCollaborator->getDescriptor(true).utf8_str()));
        AccountHandler* pHandler = pCollaborator->getHandler();
        UT_continue_if_fail(pHandler);

        // overwrite remote revision for this collaborator
        _fillRemoteRev(pPacket, pCollaborator);

        // send!
        bool res = pHandler->send(pPacket, pCollaborator);
        if (!res)
        {
            UT_DEBUGMSG(("Error sending a packet!\n"));
        }
    }
}
void AP_UnixDialog_CollaborationShare::_populateBuddyModel(bool refresh)
{
	UT_DEBUGMSG(("AP_UnixDialog_CollaborationShare::_populateBuddyModel()\n"));
	
	UT_return_if_fail(m_pBuddyModel);
	
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);
	
	AccountHandler* pHandler = _getActiveAccountHandler();
	UT_return_if_fail(pHandler);
	
	if (refresh)
	{
		// signal the account to refresh its buddy list ...
		pHandler->getBuddiesAsync(); // this function is really sync() atm; we need to rework this dialog to make it proper async

		// fetch the current ACL
		m_vAcl = _getSessionACL();
	}

	// clear out the old contents, if any
	_freeBuddyList();

	GtkTreeIter iter;
	for (UT_uint32 i = 0; i < pHandler->getBuddies().size(); i++)
	{
		BuddyPtr pBuddy = pHandler->getBuddies()[i];
		UT_continue_if_fail(pBuddy);
		
		if (!pBuddy->getHandler()->canShare(pBuddy))
		{
			UT_DEBUGMSG(("Not allowed to share with buddy: %s\n", pBuddy->getDescription().utf8_str()));
			continue;
		}

		// crap, we can't store shared pointers in the list store; use a 
		// hack to do it (which kinda defies the whole shared pointer thingy, 
		// but alas...)
		BuddyPtrWrapper* pWrapper = new BuddyPtrWrapper(pBuddy);
		gtk_list_store_append (m_pBuddyModel, &iter);
		gtk_list_store_set (m_pBuddyModel, &iter, 
				SHARE_COLUMN, _populateShareState(pBuddy),
				DESC_COLUMN, pBuddy->getDescription().utf8_str(), 
				BUDDY_COLUMN, pWrapper, 
				-1);
	}
	
	gtk_widget_show_all(m_wBuddyTree);
}
std::vector<std::string> AP_Dialog_CollaborationShare::_getSessionACL()
{
	AbiCollab* pSession = _getActiveSession();
	if (!pSession)
		return std::vector<std::string>();

	AccountHandler* pAclAccount = pSession->getAclAccount();
	UT_return_val_if_fail(pAclAccount, std::vector<std::string>());

	std::vector<std::string> vAcl = pSession->getAcl();
	if (!pAclAccount->getAcl(pSession, vAcl))
	{
		UT_return_val_if_fail(false, vAcl); // TODO; this return is probably not correct
	}
	return vAcl;
}
BuddyPtr AbiCollabSessionManager::constructBuddy(const std::string& identifier, BuddyPtr pBuddy)
{
	UT_DEBUGMSG(("AbiCollabSessionManager::constructBuddy() - identifier: %s\n", identifier.c_str()));

	// find an account hander to handle this identifier
	for (UT_uint32 i = 0; i < m_vecAccounts.size(); i++)
	{
		AccountHandler* pHandler = m_vecAccounts[i];
		UT_continue_if_fail(pHandler);

		if (pHandler->recognizeBuddyIdentifier(identifier))
			return pHandler->constructBuddy(identifier, pBuddy);
	}

	UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
	return BuddyPtr();
}
bool AP_Dialog_CollaborationShare::_populateShareState(BuddyPtr pBuddy)
{
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, false);

	PD_Document *pDoc = static_cast<PD_Document*>(XAP_App::getApp()->getLastFocussedFrame()->getCurrentDoc());
	UT_return_val_if_fail(pDoc, false);

	if (!pManager->isInSession(pDoc))
	{
		AccountHandler* pHandler = pBuddy->getHandler();
		UT_return_val_if_fail(pHandler, false);
	
		return pHandler->defaultShareState(pBuddy);
	}

	return _inAcl(m_vAcl, pBuddy);
}
void AP_UnixDialog_CollaborationAccounts::eventDelete()
{
	UT_DEBUGMSG(("AP_UnixDialog_CollaborationAccounts::eventDelete()\n"));
	AccountHandler* pHandler = _getSelectedAccountHandler();
	UT_return_if_fail(pHandler);

	// TODO: we should ask for confirmation, as this account handler
	//		 could be in use by serveral AbiCollab Sessions
	UT_DEBUGMSG(("Delete account: %s of type %s\n",
			pHandler->getDescription().utf8_str(),
			pHandler->getDisplayType().utf8_str()
		));

	_deleteAccount(pHandler);

	// for now, recreate the whole model; but we should really just delete
	// the iter we got above
	_setModel(_constructModel());
}
bool AbiCollabSessionManager::registerAccountHandlers()
{
	UT_DEBUGMSG(("AbiCollabSessionManager::registerAccountHandlers()\n"));

#ifdef ABICOLLAB_HANDLER_TELEPATHY
	UT_DEBUGMSG(("Registering the telepathy account handler!\n"));
	AccountHandler* pTelepathyHandler = new TelepathyAccountHandler();
	addAccount(pTelepathyHandler);
	// TODO: check if we really want to auto-connect this account
	pTelepathyHandler->connect();
#endif
#ifdef ABICOLLAB_HANDLER_XMPP
	m_regAccountHandlers[XMPPAccountHandler::getStaticStorageType()] = XMPPAccountHandlerConstructor;
#endif
#ifdef ABICOLLAB_HANDLER_TCP
	m_regAccountHandlers[TCPAccountHandler::getStaticStorageType()] = TCPAccountHandlerConstructor;
#endif
#ifdef ABICOLLAB_HANDLER_SUGAR
	// we don't want to register a sugar account handler here so
	// we can construct multiple sugar account handlers later: the 
	// sugar account handler is a singleton, that should always
	// be active if it is compiled in
	UT_DEBUGMSG(("Registering the sugar account handler!\n"));
	AccountHandler* pSugarHandler = new SugarAccountHandler();
	addAccount(pSugarHandler);
#endif
#ifdef ABICOLLAB_HANDLER_SERVICE
	if (tls_tunnel::Proxy::tls_tunnel_init())
		m_regAccountHandlers[ServiceAccountHandler::getStaticStorageType()] = ServiceAccountHandlerConstructor;
	IE_Imp_AbiCollabSniffer* pAbiCollabSniffer = new IE_Imp_AbiCollabSniffer();
	IE_Imp::registerImporter(pAbiCollabSniffer);
	m_vImpSniffers.push_back(pAbiCollabSniffer);
#endif
#ifdef ABICOLLAB_HANDLER_SIPSIMPLE
	m_regAccountHandlers[SIPSimpleAccountHandler::getStaticStorageType()] = SIPSimpleAccountHandlerConstructor;
#endif
#ifdef ABICOLLAB_HANDLER_FAKE
	AccountHandler *pFakeHandler = new FakeAccountHandler("FakeAbiCollabBackend", NULL);
	addAccount(pFakeHandler);
#endif
	return true;
}
Example #17
0
/*!
 * returns true if at least one account is online
 */
static bool s_any_accounts_online(bool bIncludeNonManualShareAccounts = true)
{
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, false);
	
	const std::vector<AccountHandler *>& vecAccounts = pManager->getAccounts();
	
	for (UT_uint32 i = 0; i < vecAccounts.size(); i++)
	{
		AccountHandler* pHandler = vecAccounts[i];
		if (pHandler && pHandler->isOnline())
		{
			if (bIncludeNonManualShareAccounts)
				return true;
			if (pHandler->canManuallyStartSession())
				return true;
		}
	}
	return false;
}
GtkListStore* AP_UnixDialog_CollaborationAccounts::_constructModel()
{
	GtkTreeIter iter;
	GtkListStore* model = gtk_list_store_new (4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	for (UT_uint32 i = 0; i < pManager->getAccounts().size(); i++)
	{
		AccountHandler* pHandler = pManager->getAccounts()[i];
		if (pHandler)
		{
			UT_DEBUGMSG(("Got account: %s of type %s\n", 
					pHandler->getDescription().utf8_str(), 
					pHandler->getDisplayType().utf8_str()
				));
			
			gtk_list_store_append (model, &iter);	
			gtk_list_store_set (model, &iter, 
					ONLINE_COLUMN, pHandler->isOnline(),
					DESC_COLUMN, pHandler->getDescription().utf8_str(), 
					TYPE_COLUMN, pHandler->getDisplayType().utf8_str(), 
					HANDLER_COLUMN, pHandler,
					-1);
		}
	}
	
	return model;
}
void AP_Win32Dialog_CollaborationAccounts::_populateWindowData()
{
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);

	m_bPopulating = true;

	// clear out the old contents, if any
	ListView_DeleteAllItems(m_hAccountList);

	for (UT_uint32 i = 0; i < pManager->getAccounts().size(); i++)
	{
		AccountHandler* pAccount = pManager->getAccounts()[i];
		UT_continue_if_fail(pAccount);

		UT_Win32LocaleString sAccountText = AP_Win32App::s_fromUTF8ToWinLocale(pAccount->getDescription().utf8_str());
		UT_Win32LocaleString sAccountTypeText = AP_Win32App::s_fromUTF8ToWinLocale(pAccount->getDisplayType().utf8_str());

		// insert a new account record
		LVITEMW lviAccount;
		lviAccount.mask = LVIF_STATE | LVIF_IMAGE | LVIF_PARAM;
		lviAccount.state = 1;
		lviAccount.iItem = i;
		lviAccount.iSubItem = 0;
		lviAccount.lParam = (LPARAM)pAccount;
		SendMessageW(m_hAccountList, LVM_INSERTITEMW, 0, (LPARAM) &lviAccount);
		ListView_SetCheckState(m_hAccountList, i, pAccount->isOnline());
		lviAccount.iSubItem=1;
		lviAccount.pszText= const_cast<LPWSTR>(sAccountText.c_str());
		SendMessageW(m_hAccountList, LVM_SETITEMTEXTW, i, (LPARAM) &lviAccount);
		lviAccount.iSubItem=2;
		lviAccount.pszText= const_cast<LPWSTR>(sAccountTypeText.c_str());
		SendMessageW(m_hAccountList, LVM_SETITEMTEXTW, i, (LPARAM) &lviAccount);
	}

	_updateSelection();

	m_bPopulating = false;
}
bool AbiCollab::push(SessionPacket* pPacket, BuddyPtr collaborator)
{
    UT_return_val_if_fail(pPacket, false);
    UT_return_val_if_fail(collaborator, false);
    AccountHandler* pHandler = collaborator->getHandler();
    UT_return_val_if_fail(pHandler, false);

    // record
    if (m_pRecorder)
        m_pRecorder->storeOutgoing(const_cast<const SessionPacket*>( pPacket ), collaborator);

    // overwrite remote revision for this collaborator
    _fillRemoteRev(pPacket, collaborator);

    // send!
    bool res = pHandler->send(pPacket, collaborator);
    if (!res)
    {
        UT_DEBUGMSG(("Error sending a packet to collaborator %s!\n", collaborator->getDescription().utf8_str()));
    }

    return res;
}
void AP_UnixDialog_CollaborationShare::_populateWindowData()
{
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);

	// populate the account combobox
	GtkListStore* store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
	GtkTreeIter iter;

	AccountHandler* pShareeableAcount = _getShareableAccountHandler();
	if (pShareeableAcount)
	{
			gtk_list_store_append (store, &iter);
			gtk_list_store_set (store, &iter,
						0, pShareeableAcount->getDescription().utf8_str(),
						1, pShareeableAcount,
						-1);
			gtk_widget_set_sensitive(m_wAccount, false);
	}
	else
	{
		for (std::vector<AccountHandler*>::const_iterator cit = pManager->getAccounts().begin(); cit != pManager->getAccounts().end(); cit++)
		{
			AccountHandler* pAccount = *cit;
			UT_continue_if_fail(pAccount);

			if (!pAccount->isOnline() || !pAccount->canManuallyStartSession())
				continue;

			gtk_list_store_append (store, &iter);
			gtk_list_store_set (store, &iter,
						0, pAccount->getDescription().utf8_str(),
						1, pAccount,
						-1);
		}
		gtk_widget_set_sensitive(m_wAccount, true);
	}
	m_pAccountModel = GTK_TREE_MODEL (store);
	gtk_combo_box_set_model(GTK_COMBO_BOX(m_wAccount), m_pAccountModel);

	// if we have at least one account handler, then make sure the first one is selected
	if (pManager->getRegisteredAccountHandlers().size() > 0)
	{
		gtk_combo_box_set_active(GTK_COMBO_BOX(m_wAccount), 0);
	}
	else
	{
		// nope, we don't have any account handler :'-(
		gtk_combo_box_set_active(GTK_COMBO_BOX(m_wAccount), -1);
	}
}
int main()
{
	char Menu;
	AccountHandler ah;

//	try
//	{
		while (true)
		{
			ah.MenuView();
			cin >> Menu;
			cout << endl;

			switch (Menu)
			{
			case '1':
				ah.MakeAccount();
				break;
			case '2':
				ah.DepositORWithdraw(Menu);
				break;
			case '3':
				ah.DepositORWithdraw(Menu);
				break;
			case '4':
				ah.AllPrint();
				break;
			case '5':
				return 0;
			default:
				break;
			}

			system("pause");
			system("cls");
		}
//	}
//	catch (Exception e)
//	{
//		e.ShowExceptionInfo();
//	}
}
void AbiCollabSessionManager::loadProfile()
{
	UT_DEBUGMSG(("AbiCollabSessionManager::loadProfile()\n"));

	gchar *s = g_build_filename(XAP_App::getApp()->getUserPrivateDirectory(), 
								"AbiCollab.Profile", (void*)0);
	UT_UTF8String profile(s);
	FREEP(s);

	GsfInput* in = NULL;
	char *uri = UT_go_filename_to_uri(profile.utf8_str());
	UT_return_if_fail(uri);

	in = UT_go_file_open(uri, NULL); // TODO: shouldn't use NULL here, but check for errors
	FREEP(uri);
	if (!in)
		return;

	guint8 const* contents = gsf_input_read(in, gsf_input_size(in), NULL);
	if (contents)
	{
		xmlDocPtr reader = xmlReadMemory(reinterpret_cast<const char*>(contents), 
							strlen(reinterpret_cast<const char*>(contents)), 0, "UTF-8", 0);
		if (reader)
		{
			xmlNode* node = xmlDocGetRootElement(reader);
			if (node)
			{
				if (strcmp(reinterpret_cast<const char*>(node->name), "AbiCollabProfile") == 0)
				{
					for (xmlNode* accountNode = node->children; accountNode; accountNode = accountNode->next)
					{
						// TODO: check if this node is really an AccountHandler node

						// find the account handler belonging to this type
						xmlChar* prop = xmlGetProp(accountNode, BAD_CAST "type");
						UT_UTF8String handlerType = reinterpret_cast<char *>(prop); 
						xmlFree(prop);
						std::map<UT_UTF8String, AccountHandlerConstructor>::iterator handler_iter = m_regAccountHandlers.find(handlerType);
						if (handler_iter == m_regAccountHandlers.end())
						    continue; // could happen for example when the sugar backend is found in the profile, which does not have a registered account handler belowing to it for now
						
						AccountHandlerConstructor constructor = handler_iter->second;
						AccountHandler* pHandler = constructor();
						UT_continue_if_fail(pHandler);

						for (xmlNode* accountProp = accountNode->children; accountProp; accountProp = accountProp->next)
						{
							if (accountProp->type == XML_ELEMENT_NODE)
							{
								// some node names are pre-defined...
								if (strcmp(reinterpret_cast<const char*>(accountProp->name), "buddies") == 0)
								{
									for (xmlNode* buddyNode = accountProp->children; buddyNode; buddyNode = buddyNode->next)
									{
										if (buddyNode->type != XML_ELEMENT_NODE)
										    continue;
										UT_continue_if_fail(strcmp(reinterpret_cast<const char*>(buddyNode->name), "buddy") == 0);
										UT_continue_if_fail(buddyNode->children);
										
										// read all buddy properties
										PropertyMap vBuddyProps;
										for (xmlNode* buddyPropertyNode = buddyNode->children; buddyPropertyNode; buddyPropertyNode = buddyPropertyNode->next)
										{
											UT_continue_if_fail(buddyPropertyNode->type == XML_ELEMENT_NODE);
											
											UT_UTF8String buddyPropValue = reinterpret_cast<const char*>(xmlNodeGetContent(buddyPropertyNode));
											UT_continue_if_fail(buddyPropertyNode->name && *buddyPropertyNode->name && buddyPropValue.size() > 0);
											
											vBuddyProps.insert(PropertyMap::value_type(
													reinterpret_cast<const char*>(buddyPropertyNode->name), 
													buddyPropValue.utf8_str())
												);
										}
										
										// construct the buddy	
										BuddyPtr pBuddy = pHandler->constructBuddy(vBuddyProps);
										if (pBuddy)
										{
											// add the buddy to the account handler
											pHandler->addBuddy(pBuddy);
										}
									}
								}
								else
								{
									// ... the rest are generic properties
									UT_UTF8String propValue = reinterpret_cast<const char*>(xmlNodeGetContent(accountProp));
									pHandler->addProperty(reinterpret_cast<const char*>(accountProp->name), propValue.utf8_str());
								}
							}
						}

						// add the account to the account list if it is not a duplicate
						if (addAccount(pHandler))
						{
							if (pHandler->autoConnect())
								pHandler->connect();
						}
						else
						{
							_deleteAccount(pHandler);
						}
					}
				}
			}
			xmlFreeDoc(reader);
		}
	}
	g_object_unref(G_OBJECT(in));
}
void AbiCollabSessionManager::storeProfile()
{
	UT_DEBUGMSG(("AbiCollabSessionManager::storeProfile()\n"));

	xmlBufferPtr doc = xmlBufferCreate();
	if (doc)
	{
		xmlTextWriterPtr writer = xmlNewTextWriterMemory(doc, 0);
		if (writer)
		{
			int rc = xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL);
			if (rc >= 0)
			{
				// TODO: one could check every return value here, but I'm lazy right now
				xmlTextWriterStartElement(writer, reinterpret_cast<const xmlChar*>("AbiCollabProfile"));
				
				for (UT_uint32 i = 0; i < m_vecAccounts.size(); i++)
				{
					AccountHandler* pHandler = m_vecAccounts[i];
					UT_continue_if_fail(pHandler);
					
					xmlTextWriterStartElement(writer, reinterpret_cast<const xmlChar*>("AccountHandler"));
					
					// write out the account handler type
					xmlTextWriterWriteAttribute(writer, reinterpret_cast<const xmlChar*>("type"), BAD_CAST pHandler->getStorageType().utf8_str());
					
					// write out the account handler properties
					for (PropertyMap::const_iterator cit = pHandler->getProperties().begin(); cit != pHandler->getProperties().end(); cit++)
					{
						xmlTextWriterWriteElement(writer, BAD_CAST cit->first.c_str(), BAD_CAST BAD_CAST cit->second.c_str());
					}
					
					// write out the account handler buddies
					xmlTextWriterStartElement(writer, reinterpret_cast<const xmlChar*>("buddies"));
					
					for (UT_uint32 j = 0; j < pHandler->getBuddies().size(); j++)
					{
						BuddyPtr pBuddy = pHandler->getBuddies()[j];
						UT_continue_if_fail(pBuddy);
						if (!pBuddy->isVolatile())
						{
							// we need to be able to store buddy properties
							UT_ASSERT_HARMLESS(UT_NOT_IMPLEMENTED);
							/*xmlTextWriterStartElement(writer, reinterpret_cast<const xmlChar*>("buddy"));
							// write out the buddy properties
							// TODO: for now, the only useful property a buddy has is its "name";
							// However in the future we really should write out a generic property list
							xmlTextWriterWriteElement(
									writer,
									reinterpret_cast<const xmlChar*>("name"), 
									reinterpret_cast<const xmlChar*>(pBuddy->getName().utf8_str())
								);
							xmlTextWriterEndElement(writer);*/ /* end buddy */
						}
					}
					
					xmlTextWriterEndElement(writer); /* end buddies */
					xmlTextWriterEndElement(writer); /* end AccountHandler */
				}
				
				xmlTextWriterEndElement(writer); /* end AbiCollabProfile */
			}
			xmlTextWriterEndDocument(writer);
			xmlFreeTextWriter(writer);

			gchar * s = g_build_filename(XAP_App::getApp()->getUserPrivateDirectory(), 
										 "AbiCollab.Profile",NULL);
			UT_UTF8String profile(s);
			FREEP(s);

			char *uri = UT_go_filename_to_uri(profile.utf8_str());
			GError* error = 0;
			GsfOutput* out = UT_go_file_create (uri, &error);
			if (out)
			{
				gsf_output_write(out, 
							strlen(reinterpret_cast<const char*>(const_cast<const xmlChar*>(doc->content))), 
							reinterpret_cast<const guint8*>(const_cast<const xmlChar*>(doc->content))
						);
				gsf_output_close(out);
				g_object_unref(G_OBJECT(out));
			}
			else
            {
				UT_DEBUGMSG(("Error creating AbiCollab Profile %s: %s!\n", profile.utf8_str(), error ? error->message : "unknown error"));
            }
			FREEP(uri);
		}
		else
        {
			UT_DEBUGMSG(("Error creating XML output writer\n"));
        }
		xmlBufferFree(doc);
	}
	else
    {
		UT_DEBUGMSG(("Error creating XML output buffer\n"));
    }
}
// return true if we process the command, false otherwise
BOOL AP_Win32Dialog_CollaborationAccounts::_onCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
	WORD wNotifyCode = HIWORD(wParam);
	WORD wId = LOWORD(wParam);

	switch (wId)
	{
	case AP_RID_DIALOG_COLLABORATIONACCOUNTS_CLOSE_BUTTON:
		m_answer=AP_Dialog_CollaborationAccounts::a_CLOSE;
		EndDialog(hWnd,0);
		return true;
		
	case AP_RID_DIALOG_COLLABORATIONACCOUNTS_ADD_BUTTON:
		// open the Add dialog
		createNewAccount();
		// TODO: only refresh if it actually changed.
		_populateWindowData();
		return true;
	
	case AP_RID_DIALOG_COLLABORATIONACCOUNTS_DELETE_BUTTON:
		{
			AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
			UT_return_val_if_fail(pManager, false);

			bool hasSelection = ListView_GetSelectedCount(m_hAccountList);
			if (!hasSelection)
				return true;

			UT_sint32 iIndex = ListView_GetSelectionMark(m_hAccountList);
			UT_return_val_if_fail(iIndex >= 0, false);

			LVITEM lviAccount;
			lviAccount.mask = LVIF_PARAM;
			lviAccount.iItem = iIndex;
			lviAccount.iSubItem = 0;
			UT_return_val_if_fail(ListView_GetItem(m_hAccountList, &lviAccount), false);
			UT_return_val_if_fail(lviAccount.lParam, false);

			AccountHandler* pAccount = reinterpret_cast<AccountHandler*>(lviAccount.lParam);
			// TODO: we should ask for confirmation, as this account handler
			//		 could be in use by serveral AbiCollab Sessions
			UT_DEBUGMSG(("Delete account: %s of type %s\n", 
					pAccount->getDescription().utf8_str(), 
					pAccount->getDisplayType().utf8_str()
				));
			pManager->destroyAccount(pAccount);

			// for now, recreate the whole model; but we should really just delete
			// the iter we got above
			_populateWindowData();
		}
		return true;

	case AP_RID_DIALOG_COLLABORATIONACCOUNTS_PROPERTIES_BUTTON:
		// open the Properties dialog.  This does not exist yet, but when it does, we'll be ready.
		UT_DEBUGMSG(("AP_Win32Dialog_CollaborationAccounts::eventProperties()\n"));
		// TODO: implement me
		return true;

	default:
		// WM_COMMAND message NOT processed
		return false;
	}	
}