void TContact::XmppPresenceUpdateIcon(const CXmlNode * pXmlNodeStanzaPresence) { if (FCompareStrings(pXmlNodeStanzaPresence->PszFindAttributeValueType_NZ(), "unavailable")) { TreeItemContact_UpdateIconOffline(); return; } UINT uFlagsPresence = FC_kePresenceChat; // If there is no presence value, assume online PSZUC pszPresence = pXmlNodeStanzaPresence->PszuFindElementValue_ZZ("show"); if (pszPresence != NULL && !FCompareStrings(pszPresence, "chat")) { if (FCompareStrings(pszPresence, "away")) uFlagsPresence = FC_kePresenceAway; else if (FCompareStrings(pszPresence, "xa")) uFlagsPresence = FC_kePresenceAwayExtended; else if (FCompareStrings(pszPresence, "dnd")) uFlagsPresence = FC_kePresenceBusy; // Do Not Disturb else MessageLog_AppendTextFormatSev(eSeverityErrorWarning, "Unrecognized presence value '$s'\n", pszPresence); } XmppRosterSubscribed(); if (m_uFlagsContact & FC_kfContactNeedsInvitation) { MessageLog_AppendTextFormatSev(eSeverityComment, "XmppPresenceUpdateIcon($S) - Invitation no longer needed because of presence $s\n", &m_strJidBare, pszPresence); ChatLogContact_RemoveInvitationMessage(); Assert((m_uFlagsContact & FC_kfContactNeedsInvitation) == 0); NoticeListAuxiliary_DeleteAllNoticesRelatedToTreeItem(this); } //m_uFlagsContact = (m_uFlagsContact & ~(FC_kmPresenceMask | FC_kfNoCambrianProtocol)) | uFlagsPresence; m_uFlagsContact = (m_uFlagsContact & ~(FC_kmPresenceMaskOnlineXosp)) | uFlagsPresence; // Check if the contact uses Cambrian const CXmlNode * pXmlNodeXCP = pXmlNodeStanzaPresence->PFindElement(c_sza_xcp); if (pXmlNodeXCP != NULL) { // The contact is supporting XOSP m_uFlagsContact = (m_uFlagsContact & ~FC_kfNativeXmppOnly) | FC_kfPresenceXosp; // Remember the XOSP is present, and remove the XMPP only flag if (m_uFlagsContact & FC_kfXospSynchronizeWhenPresenceOnline) { MessageLog_AppendTextFormatSev(eSeverityComment, "XmppPresenceUpdateIcon($S) - FC_kfXospSynchronizeWhenPresenceOnline\n", &m_strJidBare); XcpApi_Invoke_Synchronize(); } if (m_uFlagsContact & FC_kfContactRecommendationsNeverReceived) XcpApi_Invoke_RecommendationsGet(); //m_listaTasksSendReceive.SentTasksToContact(this); // Send any pending task } TreeItemContact_UpdateIcon(); } // XmppPresenceUpdateIcon()
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; }
// Display the content of the stanza to the local user. // Return pointer to the message body which was added to the chat history. // Return NULL if the message body was empty. PSZUC WLayoutChatLog::ChatLog_DisplayStanzaToUser(const CXmlNode * pXmlNodeMessageStanza) { Assert(pXmlNodeMessageStanza != NULL); if (m_pContactParent_YZ == NULL) return NULL; PSZUC pszuMessageBody = pXmlNodeMessageStanza->PszuFindElementValue_ZZ(c_sza_body); if (pszuMessageBody != NULL) { m_pwChatLog_NZ->ChatLog_ChatStateComposerRemovePointerOnly(m_pContactParent_YZ); // When receiving a message, assume the remote user (contact) stopped typing (composing) //m_pwChatLog->ChatLog_EventDisplay(m_pContactParent_YZ->Event_PAllocateEventMessageReceived_YZ(pXmlNodeMessageStanza, pszuMessageBody)); m_pContactParent_YZ->Vault_XmppAllocateEventMessageReceivedAndDisplayToChatLog(pXmlNodeMessageStanza, pszuMessageBody, m_pwChatLog_NZ); const CXmlNode * pXmlNodeRequest = pXmlNodeMessageStanza->PFindElement("request"); if (pXmlNodeRequest != NULL) { // The client sending the message stanza requested a confirmation receipt. Therefore send the confirmation receipt //CSocketXmpp * pSocket = m_pContactParent_YZ->Xmpp_PGetSocketOnlyIfReady(); //Endorse(pSocket == NULL); // Although this may sound obvious the socket is ready to send messages, it is not always the case, as sometimes a message is received while connecting to a server (the server cached the message) CSocketXmpp * pSocket = m_pContactParent_YZ->m_pAccount->PGetSocket_YZ(); Assert(pSocket != NULL); if (pSocket != NULL) #if 0 pSocket->Socket_WriteXmlFormatted("<message to='$s'><received xmlns='urn:xmpp:receipts' id='$s'/></message>", pXmlNodeMessageStanza->PszFindAttributeValueFrom_NZ(), pXmlNodeMessageStanza->PszFindAttributeValueId_NZ()); #else pSocket->Socket_WriteXmlFormatted("<message from='^s' to='$s'><received xmlns='urn:xmpp:receipts' id='$s'/></message>", pXmlNodeMessageStanza->PszFindAttributeValueTo_NZ(), pXmlNodeMessageStanza->PszFindAttributeValueFrom_NZ(), pXmlNodeMessageStanza->PszFindAttributeValueId_NZ()); #endif } } else { // The stanza does not contain any element <body>, therefore search if is anything else useful within the message, such as a 'delivery receipt' or a 'chat state' const CXmlNode * pXmlNodeReceived = pXmlNodeMessageStanza->PFindElement("received"); if (pXmlNodeReceived != NULL) { TIMESTAMP tsMessageReceived = pXmlNodeReceived->LFindAttributeValueIdTimestamp_ZZR(); CEventMessageTextSent * pEvent = (CEventMessageTextSent *)m_pContactParent_YZ->Vault_PFindEventByID(tsMessageReceived); // TODO: Search within the socket, it will be much faster if (pEvent != NULL) { Assert(pEvent->EGetEventClass() == CEventMessageTextSent::c_eEventClass); if (pEvent->EGetEventClass() == eEventClass_eMessageTextSent) { pEvent->Event_SetCompletedAndUpdateWidgetWithinParentChatLog(); if (m_pContactParent_YZ->m_uFlagsContact & TContact::FC_kfContactNeedsInvitation) m_pContactParent_YZ->ChatLogContact_RemoveInvitationMessage(); } } } else { const CXmlNode * pXmlNodeChatState = pXmlNodeMessageStanza->PFindElementMatchingAttributeValueXmlns("http://jabber.org/protocol/chatstates"); if (pXmlNodeChatState != NULL) m_pwChatLog_NZ->ChatLog_ChatStateTextUpdate(INOUT m_pContactParent_YZ, FCompareStrings(pXmlNodeChatState->m_pszuTagName, "composing") ? eChatState_zComposing : eChatState_Paused); } } // if...else return pszuMessageBody; } // ChatLog_DisplayStanzaToUser()
void TContact::XmppRosterSubscriptionUpdate(PSZUC pszSubscription) { Assert(pszSubscription != NULL); MessageLog_AppendTextFormatSev(eSeverityNoise, "TContact::XmppRosterSubscriptionUpdate($S) to '$s'\n", &m_strJidBare, pszSubscription); const UINT uFlagsOld = m_uFlagsContact; m_uFlagsContact = (m_uFlagsContact & ~FC_kmRosterSubscriptionBoth) | FC_kfRosterItem; if (FCompareStrings(pszSubscription, "both")) { m_uFlagsContact |= FC_kmRosterSubscriptionBoth; } else { if (FCompareStringsBeginsWith(pszSubscription, "from")) m_uFlagsContact |= FC_kfRosterSubscriptionFrom; else if (FCompareStringsBeginsWith(pszSubscription, "to")) m_uFlagsContact |= FC_kfRosterSubscriptionTo; else { Assert(FCompareStrings(pszSubscription, "none")); if ((m_uFlagsContact & FC_kfSubscribeAsk) == 0) { m_uFlagsContact |= FC_kfSubscribeAsk; m_pAccount->PGetSocket_YZ()->Socket_WriteXmlFormatted("<iq id='$p' type='set'><query xmlns='jabber:iq:roster'><item jid='^j' subscription='from' ask='subscribe'></item></query></iq>", this, this); } } if ((m_uFlagsContact & FC_kfSubscribe) == 0) { m_uFlagsContact |= FC_kfSubscribe; m_pAccount->PGetSocket_YZ()->Socket_WriteXmlFormatted("<presence to='^j' type='subscribe'/>", this); } } if (m_uFlagsContact != uFlagsOld) { MessageLog_AppendTextFormatSev(eSeverityNoise, "\t m_uFlagsContact changed from 0x$x to 0x$x\n", uFlagsOld, m_uFlagsContact); TreeItemContact_UpdateIcon(); } #ifdef DEBUG PSZUC pszSubscriptionReturned = XmppRoster_PszGetSubscription(); if (!FCompareStrings(pszSubscriptionReturned, pszSubscription)) MessageLog_AppendTextFormatSev(eSeverityErrorAssert, "XmppRosterSubscriptionUpdate($S) - XmppRoster_PszGetSubscription() returned '$s' however expecting '$s'\n", &m_strJidBare, pszSubscriptionReturned, pszSubscription); #endif } // XmppRosterSubscriptionUpdate()
ENUM EnumerationMap_EFindValueFromString(const SEnumerationMap prgzEnumerationMap[], PSZAC pszValue) { Assert(prgzEnumerationMap != NULL); if (pszValue == NULL) pszValue = c_szaEmpty; while (prgzEnumerationMap->pszValue != NULL) { Assert(prgzEnumerationMap->eEnumeration >= 0); if (FCompareStrings(pszValue, prgzEnumerationMap->pszValue)) return prgzEnumerationMap->eEnumeration; prgzEnumerationMap++; } return ENUM_NIL; }
IXmlExchange * IApplication::S_PaAllocateApplication_YZ(POBJECT poProfileParent, const CXmlNode * pXmlNodeElement) { Assert(pXmlNodeElement != NULL); TProfile * pProfileParent = (TProfile *)poProfileParent; Assert(pProfileParent->EGetRuntimeClass() == RTI(TProfile)); // Find the type of application to allocate PSZUC pszClass = pXmlNodeElement->PszuFindAttributeValue_NZ(c_szaApplicationClass_); const SApplicationAllocator * pApplicationAllocator = c_rgzApplicationAllocators; while (TRUE) { if (pApplicationAllocator->pszClass == NULL) break; Assert(pApplicationAllocator->pfnAllocator != NULL); if (FCompareStrings(pApplicationAllocator->pszClass, pszClass)) return pApplicationAllocator->pfnAllocator(pProfileParent); pApplicationAllocator++; // Search the next application } // while MessageLog_AppendTextFormatSev(eSeverityErrorWarning, "Unable to find application of class '$s'\n", pszClass); return NULL; }