Beispiel #1
0
PSZUC
TAccountXmpp::Contact_RosterUpdateItem(const CXmlNode * pXmlNodeItemRoster)
	{
	Assert(pXmlNodeItemRoster != NULL);
	Assert(pXmlNodeItemRoster->FCompareTagName("item"));
	PSZUC pszJid = pXmlNodeItemRoster->PszFindAttributeValueJid_NZ();
	PSZUC pszSubscription = pXmlNodeItemRoster->PszuFindAttributeValue_NZ("subscription");	/* // The attribute "subscription" is not present for a "<iq type='set'>" */
	if (!FCompareStrings(pszSubscription, "remove"))
		{
		#ifdef DEBUG_DELETE_TEMP_ACCOUNTS
		if (PszrCompareStringBeginNoCase(pszJid, "temp") != NULL)
			{
			MessageLog_AppendTextFormatSev(eSeverityErrorAssert, "#$I Removing contact $s from roster...\n", ++g_cContactsRemoved, pszJid);
			if (m_paSocket != NULL)
				m_paSocket->Socket_WriteXmlFormatted("<iq type='set'><query xmlns='jabber:iq:roster'><item jid='^s' subscription='remove'></item></query></iq>", pszJid);
			return NULL;
			}
		#endif
		TContact * pContact = Contact_PFindByJID(pszJid, eFindContact_kfCreateNew);
		Endorse(pContact == NULL);	// The attribute "jid" may not be valid (for example, missing the '@' character)
		if (pContact != NULL)
			pContact->XmppRosterSubscriptionUpdate(pszSubscription);
		}
	return pszJid;
	}
Beispiel #2
0
void
TAccountXmpp::Contacts_RosterUpdate(const CXmlNode * pXmlNodeQuery)
	{
	Assert(pXmlNodeQuery != NULL);
	Assert(pXmlNodeQuery->FCompareTagName("query"));
	MessageLog_AppendTextFormatSev(eSeverityNoise, "TAccountXmpp::Contacts_RosterUpdate()\n");
	// Loop through every <item> under the <query> element
	const CXmlNode * pXmlNodeItemRoster = pXmlNodeQuery->m_pElementsList;
	while (pXmlNodeItemRoster != NULL)
		{
		Contact_RosterUpdateItem(pXmlNodeItemRoster);
		pXmlNodeItemRoster = pXmlNodeItemRoster->m_pNextSibling;
		}
	// Make sure every contact is subscribed
	TContact * pContact;
	TContact ** ppContactStop;
	TContact ** ppContact = m_arraypaContacts.PrgpGetContactsStop(OUT &ppContactStop);
	while (ppContact != ppContactStop)
		{
		pContact = *ppContact++;
		if (pContact->XmppRoster_PszGetSubscription() == NULL)
			Contact_RosterSubscribe(pContact);
			//pContact->XmppRosterSubscribed();
		}
	} // Contacts_RosterUpdate()
Beispiel #3
0
//	Append the 'chat state' to the cursor
void
WChatLog::ChatLog_ChatStateTextAppend(INOUT OCursor & oTextCursor)
	{
	TContact ** ppContactStop;
	TContact ** ppContact = m_arraypContactsComposing.PrgpGetContactsStop(OUT &ppContactStop);
	if (ppContact == ppContactStop)
		{
		oTextCursor.removeSelectedText();
		}
	else
		{
		if (g_poImageComposing == NULL)
			g_poImageComposing = new QImage(":/ico/Pencil");
		while (TRUE)
			{
			oTextCursor.insertImage(*g_poImageComposing);
			TContact * pContact = *ppContact++;
			Assert(pContact != NULL);
			Assert(pContact->EGetRuntimeClass() == RTI(TContact));
			g_strScratchBufferStatusBar.Format(d_szu_nbsp " <b>^s</b> is typing...", pContact->ChatLog_PszGetNickname());
			oTextCursor.insertHtml(g_strScratchBufferStatusBar);
			if (ppContact == ppContactStop)
				break;
			} // while
		}
	if (m_pContactOrGroup->EGetRuntimeClass() == RTI(TContact))
		((TContact *)m_pContactOrGroup)->ChatLogContact_AppendExtraTextToChatState(INOUT oTextCursor);
	Widget_ScrollToEnd(INOUT this);
	} // ChatLog_ChatStateTextAppend()
Beispiel #4
0
TContact *
TAccountXmpp::TreeItemAccount_PContactAllocateNewToNavigationTreeInvited_NZ(PSZUC pszContactJID)
	{
	TContact * pContact = TreeItemAccount_PContactAllocateNewToNavigationTree_NZ(pszContactJID);
	pContact->SetFlagContactAsInvited();
	return pContact;
	}
Beispiel #5
0
void
TAccountXmpp::PresenceUpdateFromContextMenu(EMenuAction eMenuAction_Presence)
	{
	Assert(eMenuAction_Presence <= eMenuAction_PresenceLast);
	const UINT uFlagsAccountStatus = (m_uFlagsAccountStatus & ~FAS_kmStatusPresenceMask) | eMenuAction_Presence;
	if (uFlagsAccountStatus == m_uFlagsAccountStatus)
		return;
	m_uFlagsAccountStatus = uFlagsAccountStatus;	// Update the presence
	if (m_paSocket != NULL && m_paSocket->Socket_FuIsReadyToSendMessages())
		{
		switch (eMenuAction_Presence)
			{
		case eMenuAction_PresenceAccountOnline:
		case eMenuAction_PresenceAway:
		case eMenuAction_PresenceAwayExtended:
		case eMenuAction_PresenceBusy:
			m_paSocket->Socket_WriteXmlPresence();
			break;
		default:
			m_paSocket->Socket_Disconnect();
			TContact ** ppContactStop;
			TContact ** ppContact = m_arraypaContacts.PrgpGetContactsStop(OUT &ppContactStop);
			while (ppContact != ppContactStop)
				{
				TContact * pContact = *ppContact++;
				Assert(pContact != NULL);
				Assert(pContact->EGetRuntimeClass() == RTI(TContact));
				Assert(pContact->m_pAccount == this);
				pContact->TreeItemContact_UpdateIconOffline();
				}
			} // switch
		} // if
	TreeItemAccount_UpdateIcon();	// Update the icon according to the new presence
	} // PresenceUpdateFromContextMenu()
Beispiel #6
0
void
TAccountXmpp::RemoveAllReferencesToObjectsAboutBeingDeleted()
	{
	TContact ** ppContactStop;
	TContact ** ppContact = m_arraypaContacts.PrgpGetContactsStop(OUT &ppContactStop);
	while (ppContact != ppContactStop)
		{
		TContact * pContact = *ppContact++;
		pContact->Vault_RemoveAllReferencesToObjectsAboutBeingDeleted();
		}
	TGroup ** ppGroupStop;
	TGroup ** ppGroup = m_arraypaGroups.PrgpGetGroupsStop(OUT &ppGroupStop);
	while (ppGroup != ppGroupStop)
		{
		TGroup * pGroup = *ppGroup++;
		Assert(pGroup != NULL);
		Assert(pGroup->EGetRuntimeClass() == RTI(TGroup));
		Assert(pGroup->m_pAccount == this);
		pGroup->Group_RemoveAllReferencesToContactsAboutBeingDeleted();
		}
//	m_arraypaGroups.RemoveAllUnserializableTreeItems();
//	m_arraypaContacts.RemoveAllUnserializableTreeItems();
	m_arraypContactsComposing.RemoveAllUnserializableTreeItems();
	m_arraypContactsMessagesUnread.RemoveAllUnserializableTreeItems();
	}
Beispiel #7
0
void
TAccountXmpp::ChatLog_DisplayStanza(const CXmlNode * pXmlNodeMessageStanza)
	{
	Assert(pXmlNodeMessageStanza != NULL);
	TContact * pContact = Contact_PFindByJID(IN pXmlNodeMessageStanza->PszFindAttributeValueFrom_NZ(), eFindContact_kmCreateAsUnsolicited);	// Find the contact matching the the stanza
	if (pContact != NULL)
		pContact->ChatLogContact_DisplayStanzaToUI(pXmlNodeMessageStanza);
	else
		MessageLog_AppendTextFormatSev(eSeverityErrorWarning, "Unable to deliver message from unknown peer:\n^N", pXmlNodeMessageStanza);	// This happens when the stanza is incomplete and the JID is not adequate to create a contact
	}
QString
OJapiBallot::originator() const
	{
	if (m_pEventBallot->EGetEventClass() == CEventBallotReceived::c_eEventClass)
		{
		TContact * pContactSender = m_pEventBallot->PGetContactForReply_YZ();
		if (pContactSender != NULL)
			return pContactSender->TreeItem_SGetNameDisplay();
		}
	return m_pEventBallot->PGetProfile()->m_strNameProfile;	// At the moment, the originator is the profile/role who sent the ballot
	}
Beispiel #9
0
void
TAccountXmpp::Contact_PresenceUpdate(const CXmlNode * pXmlNodeStanzaPresence)
	{
	Assert(pXmlNodeStanzaPresence != NULL);
	Assert(pXmlNodeStanzaPresence->FCompareTagName("presence"));
	// Find the contact to update the presence
	TContact * pContact = Contact_PFindByJID(pXmlNodeStanzaPresence->PszFindAttributeValueFrom_NZ(), eFindContact_kfCreateNew);
	Endorse(pContact == NULL);	// The <presence> stanza sometimes is just a reply from the server, which means the attribute "from" is not a contact.
	if (pContact != NULL)
		pContact->XmppPresenceUpdateIcon(pXmlNodeStanzaPresence);
	}
Beispiel #10
0
TContact *
TAccountXmpp::TreeItemAccount_PContactAllocateNewTemporary(int nContact)
	{
	TContact * pContact = new TContact(this);
	pContact->m_strJidBare.Format("Temp$i$i$i#[email protected]", qrand(), qrand(), qrand(), nContact);
	pContact->m_strNameDisplayTyped = pContact->m_strJidBare;
	pContact->m_uFlagsTreeItem |= FTI_kfTreeItem_Temporary;
	m_arraypaContacts.Add(PA_CHILD pContact);
	pContact->TreeItemW_DisplayWithinNavigationTree(this);
	return pContact;
	}
Beispiel #11
0
void
CArrayPtrContacts::ForEach_ChatLogResetNickNameAndRepopulateAllEvents()
	{
	TContact ** ppContactStop;
	TContact ** ppContact = PrgpGetContactsStop(OUT &ppContactStop);
	while (ppContact != ppContactStop)
		{
		TContact * pContact = *ppContact++;
		Assert(pContact->EGetRuntimeClass() == RTI(TContact));
		pContact->m_uFlagsTreeItem |= TContact::FTI_kfChatLogEvents_RepopulateAll;
		pContact->ChatLog_ResetNickname();
		}
	}
Beispiel #12
0
void
TAccountXmpp::TreeItemAccount_UpdateIconOfAllContacts()
	{
	TContact ** ppContactStop;
	TContact ** ppContact = m_arraypaContacts.PrgpGetContactsStop(OUT &ppContactStop);
	while (ppContact != ppContactStop)
		{
		TContact * pContact = *ppContact++;
		Assert(pContact != NULL);
		Assert(pContact->EGetRuntimeClass() == RTI(TContact));
		Assert(pContact->m_pAccount == this);
		pContact->TreeItemContact_UpdateIcon();
		}
	}
Beispiel #13
0
void
TAccountXmpp::Contacts_RosterDisplayDebug(PSZAC pszName)
	{
	MessageLog_AppendTextFormatSev(eSeverityNoise, "Roster subscription for account $S: $s\n", &m_strJID, pszName);
	TContact * pContact;
	TContact ** ppContactStop;
	TContact ** ppContact = m_arraypaContacts.PrgpGetContactsStop(OUT &ppContactStop);
	while (ppContact != ppContactStop)
		{
		pContact = *ppContact++;
		PSZUC pszSubscription = pContact->XmppRoster_PszGetSubscription();
		if (pszSubscription != NULL)
			MessageLog_AppendTextFormatSev(eSeverityNoise, "\t $S: $s\n", &pContact->m_strJidBare, pszSubscription);
		}
	}
void
DDialogSendBitcoin::SL_ButtonSendBitcoins()
	{
	TContact * pContact = NavigationTree_PGetSelectedTreeItemMatchingInterfaceTContact();
	if (pContact == NULL)
		return;
	//IEventWalletTransaction * pEvent = TWallet::S_PAllocateEventTransaction(pContact);
	IEventWalletTransaction * pEvent = new CEventWalletTransactionSent(NULL);
	pEvent->m_amtQuantity = m_pwEditQuantity->text().toDouble() * -d_cSatoshisPerBitcoin;	// Use a negative value to indicate a withdraw
	pEvent->m_strComment = *m_pwEditComment;
	pContact->Vault_AddEventToChatLogAndSendToContacts(PA_CHILD pEvent);
	TWallet::S_SaveAll();		// Save all wallets (in case of a crash)
	pContact->TreeItem_GotFocus();	// Refresh the layout
	close();
	}
Beispiel #15
0
PSZUC
CArrayPtrContacts::PszFormatDisplayNames(OUT CStr * pstrScratchBuffer) const
	{
	pstrScratchBuffer->Empty();
	TContact ** ppContactStop;
	TContact ** ppContact = PrgpGetContactsStop(OUT &ppContactStop);
	while (ppContact != ppContactStop)
		{
		TContact * pContact = *ppContact++;
		Assert(pContact->EGetRuntimeClass() == RTI(TContact));
		if (!pstrScratchBuffer->FIsEmptyBinary())
			pstrScratchBuffer->BinAppendText(", ");
		pstrScratchBuffer->BinAppendText((PSZAC)pContact->TreeItem_PszGetNameDisplay());
		}
	return pstrScratchBuffer->BinAppendNullTerminatorSz();
	}
//	Core routine to add a new event to the vault and send it to the contact(s).
//	Optionally this method may also send an 'Updater' event
void
CVaultEvents::EventAddAndDispatchToContacts(PA_CHILD IEvent * paEvent, PA_CHILD CEventUpdaterSent * paEventUpdater)
	{
	Assert(paEvent != NULL);
	Assert(paEvent->m_tsOther == d_ts_zNA);
	Assert(paEvent->m_pVaultParent_NZ == NULL);
	Assert(paEvent->Event_FIsEventTypeSent());
	//MessageLog_AppendTextFormatSev(eSeverityWarningToErrorLog, "EventAddAndDispatchToContacts() - tsEventID $t\n", paEvent->m_tsEventID);
	if (paEventUpdater != NULL)
		{
		// Always include the Updater before the updated event
		paEventUpdater->m_pVaultParent_NZ = this;
		m_arraypaEvents.Add(PA_CHILD paEventUpdater);
		}
	paEvent->m_pVaultParent_NZ = this;
	m_arraypaEvents.Add(PA_CHILD paEvent);
	SetModified();	// Make sure the events are saved to disk

	if (paEvent->EGetEventClass() & eEventClass_kfNeverSerializeToXCP)
		return;	// The event is never serialized to XOSP, therefore there is nothing else to do

	CBinXcpStanza binXcpStanza;			// All events are sent as XMPP 'messages' so they may be cached
	TGroup * pGroup = (TGroup *)m_pParent;
	TContact * pContact = (TContact *)m_pParent;
	if (pContact->EGetRuntimeClass() == RTI(TContact))
		{
		// Send the message to a contact
		MessageLog_AppendTextFormatCo(d_coGrayDark, "\t Sending message to $S\n\t\t m_tsEventIdLastSentCached $t, m_tsOtherLastSynchronized $t\n", &pContact->m_strJidBare, pContact->m_tsEventIdLastSentCached, pContact->m_tsOtherLastSynchronized);
		binXcpStanza.BinXmlAppendXcpApiCall_SendEventToContact(pContact, paEvent, paEventUpdater);
		}
	else
		{
		// Broadcast the message to every [active] group member
		Assert(pGroup->EGetRuntimeClass() == RTI(TGroup));
		TGroupMember ** ppMemberStop;
		TGroupMember ** ppMember = pGroup->m_arraypaMembers.PrgpGetMembersStop(OUT &ppMemberStop);
		while (ppMember != ppMemberStop)
			{
			TGroupMember * pMember = *ppMember++;
			Assert(pMember != NULL);
			Assert(pMember->EGetRuntimeClass() == RTI(TGroupMember));
			binXcpStanza.BinXmlAppendXcpApiCall_SendEventToContact(pMember->m_pContact, paEvent, paEventUpdater);
			} // while
		} // if...else
	m_pParent->m_tsEventIdLastSentCached = paEvent->m_tsEventID;
	} // EventAddAndDispatchToContacts()
Beispiel #17
0
TContact *
CArrayPtrContacts::PFindContactByNameDisplay(PSZUC pszContactNameDisplay, const TContact * pContactExclude) const
	{
	TContact ** ppContactStop;
	TContact ** ppContact = PrgpGetContactsStop(OUT &ppContactStop);
	while (ppContact != ppContactStop)
		{
		TContact * pContact = *ppContact++;
		Assert(pContact->EGetRuntimeClass() == RTI(TContact));
		if (pContact != pContactExclude)
			{
			if (pContact->m_strNameDisplayTyped.FCompareStringsNoCase(pszContactNameDisplay))
				return pContact;
			}
		} // while
	return NULL;
	}
void
CArrayPtrContacts::RemoveAllContactsComposingWhoAreIdle()
	{
	if (m_paArrayHdr == NULL)
		return;
	TContact ** ppContactStop;
	TContact ** ppContactStart = PrgpGetContactsStop(OUT &ppContactStop);
	TContact ** ppContactDst = ppContactStart;
	TContact ** ppContactSrc = ppContactStart;
	while (ppContactSrc != ppContactStop)
		{
		TContact * pContact = *ppContactSrc++;
		Assert(pContact->EGetRuntimeClass() == RTI(TContact));
		MessageLog_AppendTextFormatSev(eSeverityNoise, "\t[$@] $S ($s) is still typing for $i minutes...\n", &pContact->m_strJidBare, pContact->ChatLog_PszGetNickname(), g_tsmMinutesSinceApplicationStarted - pContact->m_tsmLastStanzaReceived);
		if (g_tsmMinutesSinceApplicationStarted - pContact->m_tsmLastStanzaReceived >= 4)
			pContact->ChatLogContact_ChatStateIconUpdateComposingStopped();	// If the user has not typed anything during the past 4 minutes, then assume he stopped typing.
		else
			*ppContactDst++ = pContact;
		}
	m_paArrayHdr->cElements = ppContactDst - ppContactStart;
	} // RemoveAllContactsComposingWhoAreIdle()
Beispiel #19
0
TContact *
TAccountXmpp::TreeItemAccount_PContactAllocateNewToNavigationTree_NZ(PSZUC pszContactJID, PSZUC pszContactNameDisplay)
	{
	Assert(pszContactJID != NULL);
	Endorse(pszContactNameDisplay == NULL);	// Automatically generate a display name
	Assert(Contact_PFindByJID(pszContactJID, eFindContact_zDefault) == NULL && "The JID is already present!");
	Assert(!m_strJID.FCompareStringsJIDs(pszContactJID) && "The contact JID is the same as the JID of the XMPP account!");
	Assert(m_paTreeItemW_YZ != NULL && "No Tree Item to attach to");	// This line of code has to be revised
	TContact * pContact = new TContact(this);
	pContact->m_strRessource = pContact->m_strJidBare.AppendTextUntilCharacterPszr(pszContactJID, '/');
	pContact->m_strNameDisplayTyped = pszContactNameDisplay;
	pContact->TreeItemContact_GenerateDisplayNameFromJid();
	m_arraypaContacts.Add(PA_CHILD pContact);
	#ifdef WANT_TREE_NODE_NEW_CONTACT
	pContact->TreeItemW_DisplayWithinNavigationTreeBefore(m_pTreeItemContactNew);
	#else
	pContact->TreeItemW_DisplayWithinNavigationTree(this);
	#endif
	pContact->TreeItemContact_UpdateIcon();
	pContact->TreeItemW_EnsureVisible();	// Make sure the new contact is visible in the Navigation Tree
	pContact->m_tsCreated = Timestamp_GetCurrentDateTime();
	if (m_paSocket != NULL)
		Contact_RosterSubscribe(pContact);
	Configuration_Save();		// Save the configuration after adding a new contact (just in case the application crashes)
	TWallet::S_ContactAdded(pContact);	// Notify the wallet(s) there is a new contact
	return pContact;
	}
void
TAccountXmpp::TreeItemAccount_DisplayWithinNavigationTree()
	{
	Endorse(g_pTreeItemInbox == NULL);	// Display the account at the root of the Navigation Tree
	TreeItemW_DisplayWithinNavigationTree(g_pTreeItemInbox);
	TContact ** ppContactStop;
	TContact ** ppContact = m_arraypaContacts.PrgpGetContactsStop(OUT &ppContactStop);
	while (ppContact != ppContactStop)
		{
		TContact * pContact = *ppContact++;
		Assert(pContact != NULL);
		Assert(pContact->EGetRuntimeClass() == RTI(TContact));
		Assert(pContact->m_pAccount == this);
		pContact->TreeItemContact_DisplayWithinNavigationTree();
		} // while
	#ifdef WANT_TREE_NODE_NEW_CONTACT
	m_pTreeItemContactNew = new TContactNew(this);
	#endif

	TGroup ** ppGroupStop;
	TGroup ** ppGroup = m_arraypaGroups.PrgpGetGroupsStop(OUT &ppGroupStop);
	while (ppGroup != ppGroupStop)
		{
		TGroup * pGroup = *ppGroup++;
		Assert(pGroup != NULL);
		Assert(pGroup->EGetRuntimeClass() == RTI(TGroup));
		Assert(pGroup->m_pAccount == this);
		if (pGroup->TreeItemGroup_FCanDisplayWithinNavigationTree())
			pGroup->TreeItemGroup_DisplayWithinNavigationTree();
		}
	TreeItemW_ExpandAccordingToSavedState();
	TreeItemAccount_UpdateIcon();

	#if FIX_THIS
	// Display the alias as well
	m_paAlias->TreeItem_DisplayWithinNavigationTree(m_pProfileParent, m_strJID, eMenuIconXmpp);
	#endif
	} // TreeItemAccount_DisplayWithinNavigationTree()
void
CVaultEvents::ReadEventsFromDisk(const SHashSha1 * pHashFileName)
	{
	Assert(pHashFileName != NULL);
	CWaitCursor wait;
	CXmlTree oXmlTreeEvents;
	m_sPathFileName = m_pParent->PGetConfiguration()->SGetPathOfFileName(IN pHashFileName);
	if (oXmlTreeEvents.m_binXmlFileData.BinFileReadE(m_sPathFileName) == errSuccess)
		{
		if (oXmlTreeEvents.EParseFileDataToXmlNodes_ML() == errSuccess)
			{
			EventsUnserialize(IN &oXmlTreeEvents);
			// TODO: We need to check if this is the first vault in the chain.  So far, there is always only one vault, however this code will have to be revised when chaining vaults.
			}
		}
	m_pParent->m_tsEventIdLastSentCached = m_arraypaEvents.TsEventIdLastEventSent();	// Update the timestamp so it is what is from the vault, rather than what was loaded from the configuration, as the Chat Log may have been deleted.
	MessageLog_AppendTextFormatSev(eSeverityNoise, "CVaultEvents::ReadEventsFromDisk(\"{h!}.dat\") for '$s': $I events, m_tsEventIdLastSentCached=$t\n", pHashFileName, m_pParent->TreeItem_PszGetNameDisplay(), m_arraypaEvents.GetSize(), m_pParent->m_tsEventIdLastSentCached);

	if (m_pParent->EGetRuntimeClass() == RTI(TContact))
		{
		TContact * pContact = (TContact *)m_pParent;
		TIMESTAMP tsOtherLastReceived = m_arraypaEvents.TsEventOtherLastEventReceived();		
		if (tsOtherLastReceived > 0)
			pContact->SetFlagContactAsInvited();	// If there is one event received, then the contact does not need an invitation
		if (tsOtherLastReceived < pContact->m_tsOtherLastReceived)
			{
			MessageLog_AppendTextFormatSev(eSeverityErrorWarning, "\t Adjusting m_tsOtherLastReceived by -$T from $t to $t for '$s'\n", pContact->m_tsOtherLastReceived - tsOtherLastReceived, pContact->m_tsOtherLastReceived, tsOtherLastReceived, m_pParent->TreeItem_PszGetNameDisplay());
			pContact->m_tsOtherLastReceived = tsOtherLastReceived;
			pContact->ContactFlag_SynchronizeWhenPresenceOnline_Set();	// If the timestamp is adjusted, then trigger a synchronization
			}
		if (tsOtherLastReceived < pContact->m_tsOtherLastSynchronized || pContact->m_tsOtherLastSynchronized == d_ts_zNA)
			{
			if (pContact->m_tsOtherLastSynchronized != tsOtherLastReceived)
				MessageLog_AppendTextFormatSev(eSeverityErrorWarning, "\t Adjusting m_tsOtherLastSynchronized by -$T from $t ({tL}) to $t ({tL}) for '$s'\n", pContact->m_tsOtherLastSynchronized - tsOtherLastReceived, pContact->m_tsOtherLastSynchronized, pContact->m_tsOtherLastSynchronized, tsOtherLastReceived, tsOtherLastReceived, m_pParent->TreeItem_PszGetNameDisplay());
			pContact->m_tsOtherLastSynchronized = tsOtherLastReceived;
			pContact->ContactFlag_SynchronizeWhenPresenceOnline_Set();	// If the timestamp is adjusted, then trigger a synchronization
			}
		if (pContact->m_tsGuiLastActivity < tsOtherLastReceived)
			pContact->m_tsGuiLastActivity = tsOtherLastReceived;
		}
	else
		{
		Assert(m_pParent->EGetRuntimeClass() == RTI(TGroup));
		if (m_arraypaEvents.FIsEmpty())
			{
			// If there are no events, this means the Chat Log is new or was deleted.  In any regards, make sure the timestamps are initialized to zero to make sure the Chat Log is properly reconstructed.
			TGroupMember ** ppMemberStop;
			TGroupMember ** ppMember = ((TGroup *)m_pParent)->m_arraypaMembers.PrgpGetMembersStop(OUT &ppMemberStop);
			while (ppMember != ppMemberStop)
				{
				TGroupMember * pMember = *ppMember++;
				Assert(pMember != NULL);
				Assert(pMember->EGetRuntimeClass() == RTI(TGroupMember));
				if (pMember->m_tsOtherLastSynchronized != d_ts_zNULL)
					{
					MessageLog_AppendTextFormatSev(eSeverityErrorWarning, "\t Clearing m_tsOtherLastSynchronized $t for group member ^j\n", pMember->m_tsOtherLastSynchronized, pMember->m_pContact);
					pMember->m_tsOtherLastSynchronized = d_ts_zNULL;
					}
				} // while
			}
		} // if...else
	} // ReadEventsFromDisk()
Beispiel #22
0
//	Find the contact matching the JID and update the contact resource (if any).
//	If the JID is not in the contact list, the method will create a new contact to the list according to the value of eFindContact.
//	This method may return NULL if the JID is empty/invalid because a new contact cannot not be created.
//
//	IMPLEMENTATION NOTES
//	This method should use a hash table to quickly find a contact from its JID and/or use a pointer to cache the last contact found.
TContact *
TAccountXmpp::Contact_PFindByJID(PSZUC pszContactJID, EFindContact eFindContact)
	{
	Assert(pszContactJID != NULL);
	if (pszContactJID != NULL)
		{
		// Find the resource
		PSZUC pszResource = pszContactJID;
		while (TRUE)
			{
			if (*pszResource == '/')
				break;
			if (*pszResource == '\0')
				break;
			pszResource++;
			} // while
		const int cchJID = pszResource - pszContactJID;
		if (cchJID > 0)
			{
			TContact * pContact;
			TContact ** ppContactStop;
			TContact ** ppContact = m_arraypaContacts.PrgpGetContactsStop(OUT &ppContactStop);
			while (ppContact != ppContactStop)
				{
				pContact = *ppContact++;
//				Assert(!m_strJID.FCompareStringsJIDs(pContact->m_strJidBare) && "Contact should not have the same JID as its parent XMPP account!");
				//MessageLog_AppendTextFormatCo(d_coBlack, "Comparing $s with $S\n", pszContactJID, &pContact->m_strJidBare);
				if (pContact->m_strJidBare.FCompareStringsNoCaseCch(pszContactJID, cchJID))
					{
					// We have found our contact
					if (pContact->TreeItemFlags_FuIsInvisible())
						{
						Endorse(pContact->m_paTreeItemW_YZ != NULL);	// Typically an invisible contact should not appear in the Navigation Tree, however there are situations where it is. For instance, if the contact was just deleted, or if displayed into the list of "Deleted Items"
						if (eFindContact & eFindContact_kfMakeVisible)
							pContact->TreeItemContact_DisplayWithinNavigationTreeAndClearInvisibleFlag();
						}
					if (*pszResource != '\0')
						{
						// Update the contact resource
						if (!pContact->m_strRessource.FCompareStringsExactCase(pszResource))
							{
							if (pContact->m_strRessource.FIsEmptyString())
								MessageLog_AppendTextFormatCo(d_coBlack, "Contact $S: Assigning resource '$s' (m_uFlagsTreeItem = 0x$x)\n", &pContact->m_strJidBare, pszResource, m_uFlagsTreeItem);
							else
								MessageLog_AppendTextFormatCo(COX_MakeBold(d_coBlack), "Contact $S: Updating resource from '$S' to '$s'\n", &pContact->m_strJidBare, &pContact->m_strRessource, pszResource);
							//pContact->Xcp_ServiceDiscovery();	// The resource changed, therefore query the remote client for its capabilities
							pContact->SetFlagXcpComposingSendTimestampsOfLastKnownEvents();	// Each time the resource change, re-send the timestamps of the last known events so we give an opportunity to synchronize
							//pContact->m_cVersionXCP = 0;	// Also, reset the XCP version, to make sure the device connects properly
							}
						pContact->m_strRessource.InitFromStringU(pszResource);
						}
					return pContact;
					}
				} // while
			// We could not find the contact, so create a new one if the JID meets the minimal conditions
			if ((eFindContact & eFindContact_kfCreateNew) &&
				PcheValidateJID(pszContactJID) == NULL &&			// Make sure the JID is somewhat valid to create a new contact
				!m_strJID.FCompareStringsJIDs(pszContactJID))		// Make sure the JID is not the same as the account.  It makes no sense to create a contact with the same JID as its parent account.  This situation occurs rarely when the server sends a stanza where the 'from' contains the JID of the account.
				{
				MessageLog_AppendTextFormatSev(eSeverityInfoTextBlack, "Contact_PFindByJID('$s') - Creating contact for account $S\n", pszContactJID, &m_strJID);
				pContact = TreeItemAccount_PContactAllocateNewToNavigationTree_NZ(IN pszContactJID);
				if (eFindContact & eFindContact_kfCreateAsUnsolicited)
					pContact->SetFlagContactAsUnsolicited();
				return pContact;
				}
			} // if
		} // if
	return NULL;
	} // Contact_PFindByJID()