/* Tlen Protocol Plugin for Miranda NG Copyright (C) 2004-2007 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 "tlen.h" #include "tlen_list.h" #include "tlen_iq.h" #include "resource.h" #include "tlen_muc.h" static int TlenMUCHandleEvent(void *ptr, WPARAM wParam, LPARAM lParam); static int TlenMUCQueryContacts(TlenProtocol *proto, const char *roomId); static int TlenMUCSendInvitation(TlenProtocol *proto, const char *roomID, const char *user); static int TlenMUCSendPresence(TlenProtocol *proto, const char *roomID, const char *nick, int desiredStatus); static int TlenMUCSendMessage(TlenProtocol *proto, MUCCEVENT *event); static int TlenMUCSendTopic(TlenProtocol *proto, MUCCEVENT *event); static int TlenMUCSendQuery(TlenProtocol *proto, int type, const char *parent, int page); static int isSelf(TlenProtocol *proto, const char *roomID, const char *nick) { TLEN_LIST_ITEM *item; int result; result=0; item = TlenListGetItemPtr(proto, LIST_CHATROOM, roomID); if (item != NULL) { if (item->nick == NULL) { if (!strcmp(nick, proto->threadData->username)) result = 1; } else if (nick[0] == '~') { if (!strcmp(nick+1, item->nick)) { result = 1; } } } return result; } static int stringToHex(const char *str) { int i, val; val = 0; for (i=0;i<2;i++) { val <<= 4; if (str[i] >= 'A' && str[i] <= 'F') { val += 10 + str[i]-'A'; } else if (str[i] >= '0' && str[i] <= '9') { val += str[i]-'0'; } } return val; } static char *getDisplayName(TlenProtocol *proto, const char *id) { char jid[256]; MCONTACT hContact; DBVARIANT dbv; if (!db_get(NULL, proto->m_szModuleName, "LoginServer", &dbv)) { mir_snprintf(jid, sizeof(jid), "%s@%s", id, dbv.pszVal); db_free(&dbv); if (((hContact=TlenHContactFromJID(proto, jid)) != NULL) || !strcmp(id, proto->threadData->username)) { CONTACTINFO ci = { sizeof(ci) }; ci.hContact = hContact; ci.szProto = (char *)proto->m_szModuleName; ci.dwFlag = CNF_DISPLAY; if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { if (ci.type == CNFT_ASCIIZ) { if (ci.pszVal) { char* str = mir_t2a(ci.pszVal); mir_free(ci.pszVal); return str; } } } } } return mir_strdup(id); } BOOL TlenMUCInit(TlenProtocol *proto) { proto->HookProtoEvent(ME_MUCC_EVENT, &TlenProtocol::MUCHandleEvent); return 0; } int TlenProtocol::MUCHandleEvent(WPARAM wParam, LPARAM lParam) { MCONTACT hContact; int id; MUCCEVENT *mucce=(MUCCEVENT *) lParam; if (!strcmp(mucce->pszModule, m_szModuleName)) { switch (mucce->iType) { case MUCC_EVENT_INVITE: TlenMUCSendInvitation(this, mucce->pszID, mucce->pszNick); break; case MUCC_EVENT_MESSAGE: TlenMUCSendMessage(this, mucce); break; case MUCC_EVENT_TOPIC: TlenMUCSendTopic(this, mucce); break; case MUCC_EVENT_LEAVE: TlenMUCSendPresence(this, mucce->pszID, NULL, ID_STATUS_OFFLINE); break; case MUCC_EVENT_QUERY_GROUPS: TlenMUCSendQuery(this, 1, mucce->pszID, 0); break; case MUCC_EVENT_QUERY_ROOMS: TlenMUCSendQuery(this, 2, mucce->pszID, mucce->dwData); break; case MUCC_EVENT_QUERY_SEARCH: TlenMUCSendQuery(this, 3, mucce->pszName, 0); break; case MUCC_EVENT_QUERY_USERS: switch (mucce->dwFlags) { case MUCC_EF_USER_OWNER: id = 1; break; case MUCC_EF_USER_ADMIN: id = 2; break; case MUCC_EF_USER_MEMBER: id = 3; break; case MUCC_EF_USER_BANNED: id = 4; break; case MUCC_EF_USER_MODERATOR: id = 6; break; default: id = 0; } TlenMUCSendQuery(this, 4, mucce->pszID, id); break; case MUCC_EVENT_REGISTER_NICK: TlenMUCSendQuery(this, 6, mucce->pszNick, 0); break; case MUCC_EVENT_REMOVE_NICK: TlenMUCSendQuery(this, 6, mucce->pszNick, 1); break; case MUCC_EVENT_REGISTER_ROOM: id = TlenSerialNext(this); if (isOnline) { if (mucce->pszNick != NULL) TlenSend(this, "

", id, mucce->dwFlags | 0x10, mucce->pszName, mucce->pszID); else TlenSend(this, "

", id, mucce->dwFlags | 0x10, mucce->pszName, mucce->pszID); } break; case MUCC_EVENT_REMOVE_ROOM: if (isOnline) { TlenSend(this, "

", mucce->pszID); TlenListRemove(this, LIST_CHATROOM, mucce->pszID); // TlenMUCSendPresence(mucce->pszID, NULL, ID_STATUS_OFFLINE); } break; case MUCC_EVENT_KICK_BAN: if (isOnline) { char *nick; nick = TlenResourceFromJID(mucce->pszUID); if (!isSelf(this, mucce->pszID, nick)) { char *reason = TlenTextEncode(mucce->pszText); TlenSend(this, "

", mucce->pszID, nick, mucce->dwData, reason); mir_free(reason); } mir_free(nick); } break; case MUCC_EVENT_UNBAN: if (isOnline) { char *nick; nick = TlenResourceFromJID(mucce->pszUID); if (!isSelf(this, mucce->pszID, nick)) { TlenSend(this, "

", mucce->pszID, nick); } mir_free(nick); } break; case MUCC_EVENT_SET_USER_ROLE: if (isOnline) { char *nick; nick = TlenResourceFromJID(mucce->pszUID); if (!isSelf(this, mucce->pszID, nick)) { if (mucce->dwFlags == MUCC_EF_USER_ADMIN) { id = 2; } else if (mucce->dwFlags == MUCC_EF_USER_MEMBER) { id = 3; } else { id = 0; } TlenSend(this, "

", mucce->pszID, nick, id); } mir_free(nick); } break; case MUCC_EVENT_QUERY_USER_NICKS: TlenMUCSendQuery(this, 7, mucce->pszID, 0); break; case MUCC_EVENT_QUERY_USER_ROOMS: TlenMUCSendQuery(this, 8, mucce->pszID, 0); break; case MUCC_EVENT_QUERY_CONTACTS: TlenMUCQueryContacts(this, mucce->pszID); break; case MUCC_EVENT_JOIN: if (isOnline) { if (mucce->pszID == NULL || strlen(mucce->pszID) == 0) { if (mucce->pszName == NULL || strlen(mucce->pszName) == 0) { // create a new chat room id = TlenSerialNext(this); TlenSend(this, "

", id); } else TlenMUCSendQuery(this, 3, mucce->pszName, 0); // find a chat room by name } else // join existing chat room if (!TlenMUCCreateWindow(this, mucce->pszID, mucce->pszName, mucce->dwFlags, mucce->pszNick, NULL)) TlenMUCSendPresence(this, mucce->pszID, mucce->pszNick, ID_STATUS_ONLINE); } break; case MUCC_EVENT_START_PRIV: if (isOnline) { TLEN_LIST_ITEM *item = TlenListGetItemPtr(this, LIST_CHATROOM, mucce->pszID); if (item != NULL) { char *nick = TlenResourceFromJID(mucce->pszUID); if (!isSelf(this, mucce->pszID, nick)) { if (nick[0] == '~' || item->nick != NULL) { char str[256]; mir_snprintf(str, SIZEOF(str), "%s/%s", mucce->pszID, nick); hContact = TlenDBCreateContact(this, str, nick, TRUE); //(char *)mucce->pszUID db_set_b(hContact, m_szModuleName, "bChat", TRUE); CallService(MS_MSG_SENDMESSAGE, (WPARAM) hContact, (LPARAM) NULL); } else { DBVARIANT dbv; if (!db_get(NULL, m_szModuleName, "LoginServer", &dbv)) { char str[512]; mir_snprintf(str, sizeof(str), "%s@%s", nick, dbv.pszVal); db_free(&dbv); hContact = TlenDBCreateContact(this, str, nick, TRUE); CallService(MS_MSG_SENDMESSAGE, (WPARAM) hContact, (LPARAM) NULL); } } } mir_free(nick); } } break; } } return 0; } int TlenMUCRecvInvitation(TlenProtocol *proto, const char *roomId, const char *roomName, const char *from, const char *reason) { char *nick; int ignore, ask, groupChatPolicy; if (roomId == NULL) return 1; groupChatPolicy = db_get_w(NULL, proto->m_szModuleName, "GroupChatPolicy", 0); ask = TRUE; ignore = FALSE; if (groupChatPolicy == TLEN_MUC_ASK) { ignore = FALSE; ask = TRUE; } else if (groupChatPolicy == TLEN_MUC_IGNORE_ALL) { ignore = TRUE; } else if (groupChatPolicy == TLEN_MUC_IGNORE_NIR) { char jid[256]; DBVARIANT dbv; if (!db_get(NULL, proto->m_szModuleName, "LoginServer", &dbv)) { mir_snprintf(jid, sizeof(jid), "%s@%s", from, dbv.pszVal); db_free(&dbv); } else { strcpy(jid, from); } ignore = !IsAuthorized(proto, jid); ask = TRUE; } else if (groupChatPolicy == TLEN_MUC_ACCEPT_IR) { char jid[256]; TLEN_LIST_ITEM *item; DBVARIANT dbv; if (!db_get(NULL, proto->m_szModuleName, "LoginServer", &dbv)) { mir_snprintf(jid, sizeof(jid), "%s@%s", from, dbv.pszVal); db_free(&dbv); } else { strcpy(jid, from); } item = TlenListGetItemPtr(proto, LIST_ROSTER, jid); ask = !IsAuthorized(proto, jid); ignore = FALSE; } else if (groupChatPolicy == TLEN_MUC_ACCEPT_ALL) { ask = FALSE; ignore = FALSE; } if (!ignore) { if (ask) { MUCCEVENT mucce; mucce.cbSize = sizeof(MUCCEVENT); mucce.pszModule = proto->m_szModuleName; mucce.pszID = roomId; mucce.pszName = roomName; mucce.iType = MUCC_EVENT_INVITATION; mucce.pszUID = from; nick = getDisplayName(proto, from); mucce.pszNick = nick; mucce.pszText = reason; CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce); mir_free(nick); } else { if (!TlenMUCCreateWindow(proto, roomId, roomName, 0, NULL, NULL)) { TlenMUCSendPresence(proto, roomId, NULL, ID_STATUS_ONLINE); } } } return 0; } int TlenMUCRecvPresence(TlenProtocol *proto, const char *from, int status, int flags, const char *kick) { char str[512]; // if (TlenListExist(LIST_CHATROOM, from)) { char *nick, *roomId, *userId; MUCCEVENT mucce; roomId = TlenLoginFromJID(from); userId = TlenResourceFromJID(from); nick = getDisplayName(proto, userId); mucce.cbSize = sizeof(MUCCEVENT); mucce.pszModule = proto->m_szModuleName; mucce.pszID = roomId; mucce.iType = MUCC_EVENT_STATUS; mucce.pszUID = userId;//from; mucce.pszNick = nick; mucce.time = time(NULL); mucce.bIsMe = isSelf(proto, roomId, userId); mucce.dwData = status; mucce.dwFlags = 0; if (flags & USER_FLAGS_GLOBALOWNER) mucce.dwFlags |= MUCC_EF_USER_GLOBALOWNER; if (flags & USER_FLAGS_OWNER) mucce.dwFlags |= MUCC_EF_USER_OWNER; if (flags & USER_FLAGS_ADMIN) mucce.dwFlags |= MUCC_EF_USER_ADMIN; if (flags & USER_FLAGS_REGISTERED) mucce.dwFlags |= MUCC_EF_USER_REGISTERED; if (status == ID_STATUS_OFFLINE && mucce.bIsMe && kick != NULL) { mucce.iType = MUCC_EVENT_ERROR; mir_snprintf(str, SIZEOF(str), Translate("You have been kicked. Reason: %s "), kick); mucce.pszText = str; } CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce); mir_free(roomId); mir_free(userId); mir_free(nick); // } return 0; } int TlenMUCRecvMessage(TlenProtocol *proto, const char *from, long timestamp, XmlNode *bodyNode) { // if (TlenListExist(LIST_CHATROOM, from)) { char *localMessage; char *nick, *style, *roomId, *userId; int iStyle; MUCCEVENT mucce; roomId = TlenLoginFromJID(from); userId = TlenResourceFromJID(from); nick = getDisplayName(proto, userId); localMessage = TlenTextDecode(bodyNode->text); mucce.cbSize = sizeof(MUCCEVENT); mucce.iType = MUCC_EVENT_MESSAGE; mucce.pszID = roomId; mucce.pszModule = proto->m_szModuleName; mucce.pszText = localMessage; mucce.pszUID = userId;//from; mucce.pszNick = nick; mucce.time = timestamp; mucce.bIsMe = isSelf(proto, roomId, userId); mucce.dwFlags = 0; mucce.iFontSize = 0; style = TlenXmlGetAttrValue(bodyNode, "f"); if (style != NULL) { iStyle = atoi(style); if (iStyle & 1) mucce.dwFlags |= MUCC_EF_FONT_BOLD; if (iStyle & 2) mucce.dwFlags |= MUCC_EF_FONT_ITALIC; if (iStyle & 4) mucce.dwFlags |= MUCC_EF_FONT_UNDERLINE; } style = TlenXmlGetAttrValue(bodyNode, "c"); if (style != NULL && strlen(style) > 5) { iStyle = (stringToHex(style)<<16) | (stringToHex(style+2)<<8) | stringToHex(style+4); } else { iStyle = 0xFFFFFFFF; } mucce.color = (COLORREF) iStyle; style = TlenXmlGetAttrValue(bodyNode, "s"); if (style != NULL) { iStyle = atoi(style); } else { iStyle = 0; } mucce.iFontSize = iStyle; style = TlenXmlGetAttrValue(bodyNode, "n"); if (style != NULL) { iStyle = atoi(style)-1; } else { iStyle = 0; } mucce.iFont = iStyle; CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce); mir_free(roomId); mir_free(userId); mir_free(nick); mir_free(localMessage); // } return 0; } int TlenMUCRecvTopic(TlenProtocol *proto, const char *from, const char *subject) { // if (TlenListExist(LIST_CHATROOM, from)) { MUCCEVENT mucce; mucce.cbSize = sizeof(MUCCEVENT); mucce.iType = MUCC_EVENT_TOPIC; mucce.pszID = from; mucce.pszModule = proto->m_szModuleName; mucce.pszText = subject; mucce.time = time(NULL); CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce); // } return 0; } int TlenMUCRecvError(TlenProtocol *proto, const char *from, XmlNode *errorNode) { int errCode; char str[512]; TLEN_LIST_ITEM *item; MUCCEVENT mucce; mucce.cbSize = sizeof(MUCCEVENT); mucce.iType = MUCC_EVENT_ERROR; mucce.pszID = from; mucce.pszModule = proto->m_szModuleName; errCode = atoi(TlenXmlGetAttrValue(errorNode, "code")); switch (errCode) { case 403: mir_snprintf(str, SIZEOF(str), Translate("You cannot join this chat room, because you are banned.")); break; case 404: mir_snprintf(str, SIZEOF(str), Translate("Chat room not found.")); break; case 407: mir_snprintf(str, SIZEOF(str), Translate("This is a private chat room and you are not one of the members.")); break; case 408: mir_snprintf(str, SIZEOF(str), Translate("You cannot send any message unless you join this chat room.")); break; case 410: mir_snprintf(str, SIZEOF(str), Translate("Chat room with already created.")); break; case 411: mir_snprintf(str, SIZEOF(str), Translate("Nickname '%s' is already registered."), TlenXmlGetAttrValue(errorNode, "n")); break; case 412: mir_snprintf(str, SIZEOF(str), Translate("Nickname already in use, please try another one. Hint: '%s' is free."), TlenXmlGetAttrValue(errorNode, "free")); break; case 413: mir_snprintf(str, SIZEOF(str), Translate("You cannot register more than %s nicknames."), TlenXmlGetAttrValue(errorNode, "num")); break; case 414: mir_snprintf(str, SIZEOF(str), Translate("You cannot create more than %s chat rooms."), TlenXmlGetAttrValue(errorNode, "num")); break; case 415: mir_snprintf(str, SIZEOF(str), Translate("You cannot join more than %s chat rooms."), TlenXmlGetAttrValue(errorNode, "num")); break; case 601: mir_snprintf(str, SIZEOF(str), Translate("Anonymous nicknames are not allowed in this chat room.")); break; default: mir_snprintf(str, SIZEOF(str), Translate("Unknown error code: %d"), errCode); break; } mucce.pszText = str; CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce); if (proto->isOnline) { switch (errCode) { case 412: item = TlenListGetItemPtr(proto, LIST_CHATROOM, from); if (item != NULL) { mucce.iType = MUCC_EVENT_JOIN; mucce.dwFlags = MUCC_EF_ROOM_NICKNAMES; mucce.pszModule = proto->m_szModuleName; mucce.pszID = from; mucce.pszName = item->roomName; mucce.pszNick = TlenXmlGetAttrValue(errorNode, "free"); CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce); } break; case 601: item = TlenListGetItemPtr(proto, LIST_CHATROOM, from); if (item != NULL) { mucce.iType = MUCC_EVENT_JOIN; mucce.dwFlags = 0; mucce.pszModule = proto->m_szModuleName; mucce.pszID = from; mucce.pszName = item->roomName; mucce.pszNick = NULL; CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce); } break; } } return 1; } static int TlenMUCSendInvitation(TlenProtocol *proto, const char *roomID, const char *user) { if (!proto->isOnline) { return 1; } TlenSend(proto, "", roomID, user); return 0; } static int TlenMUCSendPresence(TlenProtocol *proto, const char *roomID, const char *nick, int desiredStatus) { char str[512]; char *jid; TLEN_LIST_ITEM *item; if (!proto->isOnline) { return 1; } if (nick != NULL) { mir_snprintf(str, sizeof(str), "%s/%s", roomID, nick); } else { mir_snprintf(str, sizeof(str), "%s", roomID); } if ((jid = TlenTextEncode(str)) != NULL) { switch (desiredStatus) { case ID_STATUS_ONLINE: TlenSend(proto, "

", jid); item = TlenListGetItemPtr(proto, LIST_CHATROOM, roomID); if (item != NULL) { if (item->nick != NULL) mir_free(item->nick); item->nick = NULL; if (nick != NULL) { item->nick = mir_strdup(nick); } } break; default: item = TlenListGetItemPtr(proto, LIST_CHATROOM, roomID); if (item != NULL) { TlenSend(proto, "

unavailable

", jid); TlenListRemove(proto, LIST_CHATROOM, roomID); } break; } mir_free(jid); } return 0; } static int TlenMUCSendMessage(TlenProtocol *proto, MUCCEVENT *event) { char *msg, *jid; int style; if (!proto->isOnline) { return 1; } if ((msg = TlenTextEncode(event->pszText)) != NULL) { if ((jid = TlenTextEncode(event->pszID)) != NULL) { style = 0; if (event->dwFlags & MUCC_EF_FONT_BOLD) style |=1; if (event->dwFlags & MUCC_EF_FONT_ITALIC) style |=2; if (event->dwFlags & MUCC_EF_FONT_UNDERLINE) style |=4; TlenSend(proto, "%s", jid, event->iFont+1, event->iFontSize, style, event->color, msg); mir_free(jid); } mir_free(msg); } return 0; } static int TlenMUCSendTopic(TlenProtocol *proto, MUCCEVENT *event) { char *msg, *jid; if (!proto->isOnline) { return 1; } if ((msg = TlenTextEncode(event->pszText)) != NULL) { if ((jid = TlenTextEncode(event->pszID)) != NULL) { TlenSend(proto, "%s", jid, msg); mir_free(jid); } mir_free(msg); } return 0; } static int TlenMUCSendQuery(TlenProtocol *proto, int type, const char *parent, int page) { if (!proto->isOnline) { return 1; } if (type == 3) { // find chat room by name char serialId[32]; TLEN_LIST_ITEM *item; mir_snprintf(serialId, SIZEOF(serialId), TLEN_IQID"%d", TlenSerialNext(proto)); item = TlenListAdd(proto, LIST_SEARCH, serialId); item->roomName = mir_strdup(parent); TlenSend(proto, "", parent, serialId); } else { if (parent == NULL) { TlenSend(proto, "", type); } else { // 1 - groups, 2 - chat rooms, 7 - user nicks, 8 - user rooms if (type == 1 || (type == 2 && page == 0) || type == 7 || type == 8) { TlenSend(proto, "", type, parent); } else if (type == 2) { TlenSend(proto, "", type, parent, page); } else if (type == 6) { if (page) { TlenSend(proto, "", type, parent); } else { TlenSend(proto, "", type, parent); } } else if (type == 4) { // list of users, admins etc. TlenSend(proto, "", parent, type, page); } } } return 0; } int TlenMUCCreateWindow(TlenProtocol *proto, const char *roomID, const char *roomName, int roomFlags, const char *nick, const char *iqId) { TLEN_LIST_ITEM *item; MUCCWINDOW mucw; if (!proto->isOnline || roomID == NULL) { return 1; } if (TlenListExist(proto, LIST_CHATROOM, roomID)) { return 0; } item = TlenListAdd(proto, LIST_CHATROOM, roomID); if (roomName != NULL) { item->roomName = mir_strdup(roomName); } if (nick != NULL) { item->nick = mir_strdup(nick); } mucw.cbSize = sizeof(MUCCWINDOW); mucw.iType = MUCC_WINDOW_CHATROOM; mucw.pszModule = proto->m_szModuleName; mucw.pszModuleName = proto->m_szModuleName; mucw.pszID = roomID; mucw.pszName = roomName; mucw.pszNick = nick; mucw.dwFlags = roomFlags; mucw.pszStatusbarText = "hello"; CallService(MS_MUCC_NEW_WINDOW, 0, (LPARAM) &mucw); if (iqId != NULL) { item = TlenListGetItemPtr(proto, LIST_INVITATIONS, iqId); if (item !=NULL) { TlenMUCSendInvitation(proto, roomID, item->nick); } TlenListRemove(proto, LIST_INVITATIONS, iqId); } return 0; } static void TlenMUCFreeQueryResult(MUCCQUERYRESULT *result) { int i; for (i=0; iiItemsNum; i++) { if (result->pItems[i].pszID != NULL) { mir_free((char *) result->pItems[i].pszID); } if (result->pItems[i].pszName != NULL) { mir_free((char *) result->pItems[i].pszName); } if (result->pItems[i].pszNick != NULL) { mir_free((char *) result->pItems[i].pszNick); } if (result->pItems[i].pszText != NULL) { mir_free((char *) result->pItems[i].pszText); } } mir_free((MUCCQUERYITEM *)result->pItems); } void TlenIqResultChatGroups(TlenProtocol *proto, XmlNode *iqNode) { XmlNode *lNode, *itemNode; char *p, *n, *id, *f; int i, j; MUCCQUERYRESULT queryResult; if ((lNode=TlenXmlGetChild(iqNode, "l")) == NULL) return; p = TlenXmlGetAttrValue(iqNode, "p"); if (p == NULL) { p=""; } p = TlenTextDecode(p); queryResult.cbSize = sizeof (MUCCQUERYRESULT); queryResult.iType = MUCC_EVENT_QUERY_GROUPS; queryResult.pszModule = proto->m_szModuleName; queryResult.pszParent = p; queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * lNode->numChild); memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * lNode->numChild); for (i=j=0; inumChild; i++) { itemNode = lNode->child[i]; if (!strcmp(itemNode->name, "i")) { queryResult.pItems[j].iCount = 0; if ((f = TlenXmlGetAttrValue(itemNode, "f")) != NULL) { queryResult.pItems[j].iCount = !strcmp(f, "3"); } n = TlenXmlGetAttrValue(itemNode, "n"); id = TlenXmlGetAttrValue(itemNode, "i"); if (n != NULL && id != NULL) { queryResult.pItems[j].pszID = TlenTextDecode(id); queryResult.pItems[j].pszName = TlenTextDecode(n); j++; } } } queryResult.iItemsNum = j; CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult); TlenMUCFreeQueryResult(&queryResult); mir_free(p); } void TlenIqResultChatRooms(TlenProtocol *proto, XmlNode *iqNode) { XmlNode *lNode, *itemNode; char *id, *c, *n, *x, *p, *px, *pn; int i, j; MUCCQUERYRESULT queryResult; if ((lNode=TlenXmlGetChild(iqNode, "l")) == NULL) return; if ((p = TlenXmlGetAttrValue(iqNode, "p")) == NULL) return; pn = TlenXmlGetAttrValue(lNode, "n"); if (pn == NULL) pn = "0"; px = TlenXmlGetAttrValue(lNode, "x"); if (px == NULL) px = "0"; p = TlenTextDecode(p); queryResult.cbSize = sizeof (MUCCQUERYRESULT); queryResult.iType = MUCC_EVENT_QUERY_ROOMS; queryResult.pszModule = proto->m_szModuleName; queryResult.pszParent = p; queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * lNode->numChild); memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * lNode->numChild); queryResult.iPage = atoi(pn); queryResult.iLastPage = atoi(px)&2?1:0; for (i=j=0; inumChild; i++) { itemNode = lNode->child[i]; if (!strcmp(itemNode->name, "i")) { n = TlenXmlGetAttrValue(itemNode, "n"); c = TlenXmlGetAttrValue(itemNode, "c"); x = TlenXmlGetAttrValue(itemNode, "x"); if ((id=TlenXmlGetAttrValue(itemNode, "i")) != NULL) { queryResult.pItems[j].pszID = TlenTextDecode(id); queryResult.pItems[j].pszName = TlenTextDecode(n); queryResult.pItems[j].iCount = atoi(c); queryResult.pItems[j].dwFlags = atoi(x); j++; } } } queryResult.iItemsNum = j; CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult); TlenMUCFreeQueryResult(&queryResult); mir_free(p); } void TlenIqResultUserRooms(TlenProtocol *proto, XmlNode *iqNode) { XmlNode *lNode, *itemNode; char *id, *n; int i, j; MUCCQUERYRESULT queryResult; if ((lNode=TlenXmlGetChild(iqNode, "l")) == NULL) return; queryResult.cbSize = sizeof (MUCCQUERYRESULT); queryResult.iType = MUCC_EVENT_QUERY_USER_ROOMS; queryResult.pszModule = proto->m_szModuleName; queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * lNode->numChild); memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * lNode->numChild); for (i=j=0; inumChild; i++) { itemNode = lNode->child[i]; if (!strcmp(itemNode->name, "i")) { n = TlenXmlGetAttrValue(itemNode, "n"); id = TlenXmlGetAttrValue(itemNode, "i"); if (n != NULL && id != NULL) { queryResult.pItems[j].pszID = TlenTextDecode(id); queryResult.pItems[j].pszName = TlenTextDecode(n); j++; } } } queryResult.iItemsNum = j; CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult); TlenMUCFreeQueryResult(&queryResult); } void TlenIqResultUserNicks(TlenProtocol *proto, XmlNode *iqNode) { XmlNode *lNode, *itemNode; char *n; int i, j; MUCCQUERYRESULT queryResult; if ((lNode=TlenXmlGetChild(iqNode, "l")) == NULL) return; queryResult.cbSize = sizeof (MUCCQUERYRESULT); queryResult.iType = MUCC_EVENT_QUERY_USER_NICKS; queryResult.pszModule = proto->m_szModuleName; queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * lNode->numChild); memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * lNode->numChild); for (i=j=0; inumChild; i++) { itemNode = lNode->child[i]; if (!strcmp(itemNode->name, "i")) { n = TlenXmlGetAttrValue(itemNode, "n"); queryResult.pItems[j].pszID = NULL;//TlenTextDecode(n); queryResult.pItems[j].pszName = TlenTextDecode(n); j++; } } queryResult.iItemsNum = j; CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult); TlenMUCFreeQueryResult(&queryResult); } void TlenIqResultChatRoomUsers(TlenProtocol *proto, XmlNode *iqNode) { XmlNode *lNode, *itemNode; char *id, *n; int i, j; MUCCQUERYRESULT queryResult; if ((lNode=TlenXmlGetChild(iqNode, "l")) == NULL) return; if ((id=TlenXmlGetAttrValue(iqNode, "from")) == NULL) return; queryResult.cbSize = sizeof (MUCCQUERYRESULT); queryResult.iType = MUCC_EVENT_QUERY_USERS; queryResult.pszModule = proto->m_szModuleName; queryResult.pszParent = id; queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * lNode->numChild); memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * lNode->numChild); for (i=j=0; inumChild; i++) { itemNode = lNode->child[i]; if (!strcmp(itemNode->name, "i")) { id = TlenXmlGetAttrValue(itemNode, "i"); if (id != NULL) { queryResult.pItems[j].pszID = TlenTextDecode(id); n = TlenXmlGetAttrValue(itemNode, "n"); if (n != NULL) { queryResult.pItems[j].pszName = TlenTextDecode(n); } n = TlenXmlGetAttrValue(itemNode, "a"); if (n != NULL) { queryResult.pItems[j].pszNick = TlenTextDecode(n); } n = TlenXmlGetAttrValue(itemNode, "r"); if (n != NULL) { queryResult.pItems[j].pszText = TlenTextDecode(n); } n = TlenXmlGetAttrValue(itemNode, "e"); if (n != NULL) { queryResult.pItems[j].iCount = atoi(n); } n = TlenXmlGetAttrValue(itemNode, "s"); if (n != NULL) { queryResult.pItems[j].dwFlags = atoi(n); } j++; } } } queryResult.iItemsNum = j; CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult); TlenMUCFreeQueryResult(&queryResult); } void TlenIqResultRoomSearch(TlenProtocol *proto, XmlNode *iqNode) { char *iqId, *id; TLEN_LIST_ITEM *item; iqId=TlenXmlGetAttrValue(iqNode, "id"); item=TlenListGetItemPtr(proto, LIST_SEARCH, iqId); if ((id=TlenXmlGetAttrValue(iqNode, "i")) != NULL) { MUCCEVENT mucce; id = TlenTextDecode(id); mucce.cbSize = sizeof(MUCCEVENT); mucce.iType = MUCC_EVENT_JOIN; mucce.pszModule = proto->m_szModuleName; mucce.pszID = id; mucce.pszName = id; if (item != NULL) { mucce.pszName = item->roomName; } mucce.pszNick = NULL; mucce.dwFlags = MUCC_EF_ROOM_NICKNAMES; CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce); mir_free(id); } TlenListRemove(proto, LIST_SEARCH, iqId); } void TlenIqResultRoomInfo(TlenProtocol *proto, XmlNode *iqNode) { char *id, *name, *group, *flags; if ((id=TlenXmlGetAttrValue(iqNode, "from")) != NULL) { if ((name=TlenXmlGetAttrValue(iqNode, "n")) != NULL) { MUCCEVENT mucce; group = TlenXmlGetAttrValue(iqNode, "cn"); flags = TlenXmlGetAttrValue(iqNode, "x"); id = TlenTextDecode(id); name = TlenTextDecode(name); mucce.cbSize = sizeof(MUCCEVENT); mucce.iType = MUCC_EVENT_ROOM_INFO; mucce.pszModule = proto->m_szModuleName; mucce.pszID = id; mucce.pszName = name; mucce.dwFlags = atoi(flags); CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce); mir_free(id); mir_free(name); } } } typedef struct { TlenProtocol *proto; char *roomId; } MUCSENDQUERYTHREADDATA; static void __cdecl TlenMUCCSendQueryResultThread(void *ptr) { DBVARIANT dbv; MUCSENDQUERYTHREADDATA* threadData = (MUCSENDQUERYTHREADDATA*)ptr; char *szProto = threadData->proto->m_szModuleName; MUCCQUERYRESULT queryResult; queryResult.cbSize = sizeof (MUCCQUERYRESULT); queryResult.iType = MUCC_EVENT_QUERY_CONTACTS; queryResult.pszModule = szProto; queryResult.pszParent = threadData->roomId; queryResult.iItemsNum = 0; for (MCONTACT hContact = db_find_first(szProto); hContact; hContact = db_find_next(hContact, szProto)) { if ( db_get_b(hContact, szProto, "bChat", FALSE)) continue; if ( !db_get_s(hContact, szProto, "jid", &dbv)) { if (strcmp(dbv.pszVal, "b73@tlen.pl")) queryResult.iItemsNum++; db_free(&dbv); } } queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * queryResult.iItemsNum); memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * queryResult.iItemsNum); queryResult.iItemsNum = 0; for (MCONTACT hContact = db_find_first(szProto); hContact; hContact = db_find_next(hContact, szProto)) { if ( db_get_b(hContact, szProto, "bChat", FALSE)) continue; if (!db_get(hContact, szProto, "jid", &dbv)) { if (strcmp(dbv.pszVal, "b73@tlen.pl")) { queryResult.pItems[queryResult.iItemsNum].pszID = mir_strdup(dbv.pszVal); queryResult.pItems[queryResult.iItemsNum].pszName = mir_strdup((char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, 0)); queryResult.iItemsNum++; } db_free(&dbv); } } CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult); TlenMUCFreeQueryResult(&queryResult); mir_free(threadData->roomId); mir_free(threadData); } static int TlenMUCQueryContacts(TlenProtocol *proto, const char *roomId) { MUCSENDQUERYTHREADDATA *threadData = (MUCSENDQUERYTHREADDATA *)mir_alloc(sizeof(MUCSENDQUERYTHREADDATA)); threadData->proto = proto; threadData->roomId = mir_strdup(roomId); forkthread(TlenMUCCSendQueryResultThread, 0, (void *)threadData); return 1; } INT_PTR TlenProtocol::MUCMenuHandleMUC(WPARAM wParam, LPARAM lParam) { if (!isOnline) return 1; TlenSend(this, "

", TlenSerialNext(this)); return 0; } INT_PTR TlenProtocol::MUCMenuHandleChats(WPARAM wParam, LPARAM lParam) { if (!isOnline) return 1; MUCCWINDOW mucw; mucw.cbSize = sizeof(MUCCWINDOW); mucw.iType = MUCC_WINDOW_CHATLIST; mucw.pszModule = m_szModuleName; mucw.pszModuleName = m_szModuleName; CallService(MS_MUCC_NEW_WINDOW, 0, (LPARAM) &mucw); return 0; } INT_PTR TlenProtocol::MUCContactMenuHandleMUC(WPARAM wParam, LPARAM lParam) { MCONTACT hContact; DBVARIANT dbv; TLEN_LIST_ITEM *item; if (!isOnline) return 1; if ((hContact=wParam) != NULL && isOnline) { if (!db_get(hContact, m_szModuleName, "jid", &dbv)) { char serialId[32]; mir_snprintf(serialId, SIZEOF(serialId), TLEN_IQID"%d", TlenSerialNext(this)); item = TlenListAdd(this, LIST_INVITATIONS, serialId); item->nick = mir_strdup(dbv.pszVal); TlenSend(this, "

", serialId); db_free(&dbv); } } return 0; }