summaryrefslogtreecommitdiff
path: root/protocols/Tlen/src/tlen_presence.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Tlen/src/tlen_presence.cpp')
-rw-r--r--protocols/Tlen/src/tlen_presence.cpp318
1 files changed, 318 insertions, 0 deletions
diff --git a/protocols/Tlen/src/tlen_presence.cpp b/protocols/Tlen/src/tlen_presence.cpp
new file mode 100644
index 0000000000..7dc15f41f6
--- /dev/null
+++ b/protocols/Tlen/src/tlen_presence.cpp
@@ -0,0 +1,318 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2009 Piotr Piastucki
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "jabber.h"
+#include "jabber_list.h"
+#include "tlen_avatar.h"
+
+void TlenProcessPresence(XmlNode *node, TlenProtocol *proto)
+{
+ HANDLE hContact;
+ XmlNode *showNode, *statusNode;
+ JABBER_LIST_ITEM *item;
+ char *from, *type, *nick, *show;
+ int status, laststatus = ID_STATUS_OFFLINE;
+ char *p;
+
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (JabberListExist(proto, LIST_CHATROOM, from)); //JabberGroupchatProcessPresence(node, userdata);
+
+ else {
+ type = JabberXmlGetAttrValue(node, "type");
+ item = JabberListGetItemPtr(proto, LIST_ROSTER, from);
+ if (item != NULL) {
+ if (proto->tlenOptions.enableAvatars) {
+ TlenProcessPresenceAvatar(proto, node, item);
+ }
+ }
+ if (type == NULL || (!strcmp(type, "available"))) {
+ if ((nick=JabberLocalNickFromJID(from)) != NULL) {
+ if ((hContact=JabberHContactFromJID(proto, from)) == NULL)
+ hContact = JabberDBCreateContact(proto, from, nick, FALSE);
+ if (!JabberListExist(proto, LIST_ROSTER, from)) {
+ JabberLog(proto, "Receive presence online from %s (who is not in my roster)", from);
+ JabberListAdd(proto, LIST_ROSTER, from);
+ }
+ status = ID_STATUS_ONLINE;
+ if ((showNode=JabberXmlGetChild(node, "show")) != NULL) {
+ if ((show=showNode->text) != NULL) {
+ if (!strcmp(show, "away")) status = ID_STATUS_AWAY;
+ else if (!strcmp(show, "xa")) status = ID_STATUS_NA;
+ else if (!strcmp(show, "dnd")) status = ID_STATUS_DND;
+ else if (!strcmp(show, "chat")) status = ID_STATUS_FREECHAT;
+ else if (!strcmp(show, "unavailable")) {
+ // Always show invisible (on old Tlen client) as invisible (not offline)
+ status = ID_STATUS_OFFLINE;
+ }
+ }
+ }
+
+ statusNode = JabberXmlGetChild(node, "status");
+ if (statusNode)
+ p = JabberTextDecode(statusNode->text);
+ else
+ p = NULL;
+ JabberListAddResource(proto, LIST_ROSTER, from, status, statusNode?p:NULL);
+ if (p) {
+ DBWriteContactSettingString(hContact, "CList", "StatusMsg", p);
+ mir_free(p);
+ } else {
+ DBDeleteContactSetting(hContact, "CList", "StatusMsg");
+ }
+ // Determine status to show for the contact and request version information
+ if (item != NULL) {
+ laststatus = item->status;
+ item->status = status;
+ }
+ if (strchr(from, '@') != NULL || DBGetContactSettingByte(NULL, proto->m_szModuleName, "ShowTransport", TRUE) == TRUE) {
+ if (DBGetContactSettingWord(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != status)
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "Status", (WORD) status);
+ }
+ if (item != NULL) {
+ if (!item->infoRequested) {
+ int iqId = JabberSerialNext(proto);
+ item->infoRequested = TRUE;
+ JabberSend( proto, "<iq type='get' id='"JABBER_IQID"%d'><query xmlns='jabber:iq:info' to='%s'></query></iq>", iqId, from);
+ }
+ if (proto->tlenOptions.enableVersion && !item->versionRequested) {
+ item->versionRequested = TRUE;
+ if (proto->m_iStatus != ID_STATUS_INVISIBLE) {
+ JabberSend( proto, "<message to='%s' type='iq'><iq type='get'><query xmlns='jabber:iq:version'/></iq></message>", from );
+ }
+ }
+ }
+ JabberLog(proto, "%s (%s) online, set contact status to %d", nick, from, status);
+ mir_free(nick);
+ }
+ }
+ else if (!strcmp(type, "unavailable")) {
+ if (!JabberListExist(proto, LIST_ROSTER, from)) {
+ JabberLog(proto, "Receive presence offline from %s (who is not in my roster)", from);
+ JabberListAdd(proto, LIST_ROSTER, from);
+ }
+ else {
+ JabberListRemoveResource(proto, LIST_ROSTER, from);
+ }
+ status = ID_STATUS_OFFLINE;
+ statusNode = JabberXmlGetChild(node, "status");
+ if (statusNode) {
+ if (proto->tlenOptions.offlineAsInvisible) {
+ status = ID_STATUS_INVISIBLE;
+ }
+ p = JabberTextDecode(statusNode->text);
+ JabberListAddResource(proto, LIST_ROSTER, from, status, p);
+ if ((hContact=JabberHContactFromJID(proto, from)) != NULL) {
+ if (p) {
+ DBWriteContactSettingString(hContact, "CList", "StatusMsg", p);
+ } else {
+ DBDeleteContactSetting(hContact, "CList", "StatusMsg");
+ }
+ }
+ if (p) mir_free(p);
+ }
+ if ((item=JabberListGetItemPtr(proto, LIST_ROSTER, from)) != NULL) {
+ // Determine status to show for the contact based on the remaining resources
+ item->status = status;
+ item->versionRequested = FALSE;
+ item->infoRequested = FALSE;
+ }
+ if ((hContact=JabberHContactFromJID(proto, from)) != NULL) {
+ if (strchr(from, '@') != NULL || DBGetContactSettingByte(NULL, proto->m_szModuleName, "ShowTransport", TRUE) == TRUE) {
+ if (DBGetContactSettingWord(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != status)
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "Status", (WORD) status);
+ }
+ if (item != NULL && item->isTyping) {
+ item->isTyping = FALSE;
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM) hContact, PROTOTYPE_CONTACTTYPING_OFF);
+ }
+ JabberLog(proto, "%s offline, set contact status to %d", from, status);
+ }
+ }
+ else if (!strcmp(type, "subscribe")) {
+ if (strchr(from, '@') == NULL) {
+ // automatically send authorization allowed to agent/transport
+ JabberSend(proto, "<presence to='%s' type='subscribed'/>", from);
+ }
+ else if ((nick=JabberNickFromJID(from)) != NULL) {
+ JabberLog(proto, "%s (%s) requests authorization", nick, from);
+ JabberDBAddAuthRequest(proto, from, nick);
+ mir_free(nick);
+ }
+ }
+ else if (!strcmp(type, "subscribed")) {
+ if ((item=JabberListGetItemPtr(proto, LIST_ROSTER, from)) != NULL) {
+ if (item->subscription == SUB_FROM) item->subscription = SUB_BOTH;
+ else if (item->subscription == SUB_NONE) {
+ item->subscription = SUB_TO;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void JabberSendPresenceTo(TlenProtocol *proto, int status, char *to)
+{
+ char *showBody, *statusMsg, *presenceType;
+ char *ptr = NULL;
+
+ if (!proto->isOnline) return;
+
+ // Send <presence/> update for status (we won't handle ID_STATUS_OFFLINE here)
+ // Note: jabberModeMsg is already encoded using JabberTextEncode()
+ EnterCriticalSection(&proto->modeMsgMutex);
+
+ showBody = NULL;
+ statusMsg = NULL;
+ presenceType = NULL;
+ switch (status) {
+ case ID_STATUS_ONLINE:
+ showBody = "available";
+ statusMsg = proto->modeMsgs.szOnline;
+ break;
+ case ID_STATUS_AWAY:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ showBody = "away";
+ statusMsg = proto->modeMsgs.szAway;
+ break;
+ case ID_STATUS_NA:
+ showBody = "xa";
+ statusMsg = proto->modeMsgs.szNa;
+ break;
+ case ID_STATUS_DND:
+ case ID_STATUS_OCCUPIED:
+ showBody = "dnd";
+ statusMsg = proto->modeMsgs.szDnd;
+ break;
+ case ID_STATUS_FREECHAT:
+ showBody = "chat";
+ statusMsg = proto->modeMsgs.szFreechat;
+ break;
+ case ID_STATUS_INVISIBLE:
+ presenceType = "invisible";
+ statusMsg = proto->modeMsgs.szInvisible;
+ break;
+ case ID_STATUS_OFFLINE:
+ presenceType = "unavailable";
+ if (DBGetContactSettingByte(NULL, proto->m_szModuleName, "LeaveOfflineMessage", FALSE)) {
+ int offlineMessageOption = DBGetContactSettingWord(NULL, proto->m_szModuleName, "OfflineMessageOption", 0);
+ if (offlineMessageOption == 0) {
+ switch (proto->m_iStatus) {
+ case ID_STATUS_ONLINE:
+ ptr = mir_strdup(proto->modeMsgs.szOnline);
+ break;
+ case ID_STATUS_AWAY:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ ptr = mir_strdup(proto->modeMsgs.szAway);
+ break;
+ case ID_STATUS_NA:
+ ptr = mir_strdup(proto->modeMsgs.szNa);
+ break;
+ case ID_STATUS_DND:
+ case ID_STATUS_OCCUPIED:
+ ptr = mir_strdup(proto->modeMsgs.szDnd);
+ break;
+ case ID_STATUS_FREECHAT:
+ ptr = mir_strdup(proto->modeMsgs.szFreechat);
+ break;
+ case ID_STATUS_INVISIBLE:
+ ptr = mir_strdup(proto->modeMsgs.szInvisible);
+ break;
+ }
+ } else if (offlineMessageOption == 99) {
+
+ } else if (offlineMessageOption < 7) {
+ DBVARIANT dbv;
+ const char *statusNames[] = {"OnDefault", "AwayDefault", "NaDefault", "DndDefault", "FreeChatDefault", "InvDefault"};
+ if (!DBGetContactSetting(NULL, "SRAway", statusNames[offlineMessageOption-1], &dbv)) {
+ int i;
+ char substituteStr[128];
+ ptr = mir_strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ for (i=0;ptr[i];i++) {
+ if (ptr[i] != '%') continue;
+ if (!_strnicmp(ptr+i,"%time%",6))
+ GetTimeFormatA(LOCALE_USER_DEFAULT,TIME_NOSECONDS,NULL,NULL,substituteStr,sizeof(substituteStr));
+ else if (!_strnicmp(ptr+i,"%date%",6))
+ GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,NULL,NULL,substituteStr,sizeof(substituteStr));
+ else continue;
+ if (strlen(substituteStr)>6) ptr=(char*)mir_realloc(ptr,strlen(ptr)+1+strlen(substituteStr)-6);
+ MoveMemory(ptr+i+strlen(substituteStr),ptr+i+6,strlen(ptr)-i-5);
+ CopyMemory(ptr+i,substituteStr,strlen(substituteStr));
+ }
+ }
+ }
+ }
+ statusMsg = ptr;
+ break;
+ default:
+ // Should not reach here
+ break;
+ }
+ proto->m_iStatus = status;
+ if (presenceType) {
+ if (statusMsg)
+ JabberSend(proto, "<presence type='%s'><status>%s</status></presence>", presenceType, statusMsg);
+ else
+ JabberSend(proto, "<presence type='%s'></presence>", presenceType);
+ } else {
+ if (statusMsg)
+ JabberSend(proto, "<presence><show>%s</show><status>%s</status></presence>", showBody, statusMsg);
+ else
+ JabberSend(proto, "<presence><show>%s</show></presence>", showBody);
+ }
+ if (ptr) {
+ mir_free(ptr);
+ }
+ LeaveCriticalSection(&proto->modeMsgMutex);
+}
+
+
+
+void JabberSendPresence(TlenProtocol *proto, int statusIn)
+{
+ int statusOut;
+ switch (statusIn) {
+ case ID_STATUS_ONLINE:
+ case ID_STATUS_OFFLINE:
+ case ID_STATUS_NA:
+ case ID_STATUS_FREECHAT:
+ case ID_STATUS_INVISIBLE:
+ statusOut = statusIn;
+ break;
+ case ID_STATUS_AWAY:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ default:
+ statusOut = ID_STATUS_AWAY;
+ break;
+ case ID_STATUS_DND:
+ case ID_STATUS_OCCUPIED:
+ statusOut = ID_STATUS_DND;
+ break;
+ }
+ JabberSendPresenceTo(proto, statusOut, NULL);
+}
+
+