summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorRozhuk Ivan <rozhuk.im@gmail.com>2014-11-29 20:25:42 +0000
committerRozhuk Ivan <rozhuk.im@gmail.com>2014-11-29 20:25:42 +0000
commitf73897a8ca83abe24a15016808790e01d061cb36 (patch)
tree3e62a5d4cabf5b5e573109a6df3cba61cb9ff11a /protocols
parent9da683d81d193e7885fae9b804e633b05d863389 (diff)
SkypeClassic: code cleanup
git-svn-id: http://svn.miranda-ng.org/main/trunk@11161 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols')
-rw-r--r--protocols/SkypeClassic/src/gchat.cpp1713
1 files changed, 858 insertions, 855 deletions
diff --git a/protocols/SkypeClassic/src/gchat.cpp b/protocols/SkypeClassic/src/gchat.cpp
index 37e075544e..82a66c8fcb 100644
--- a/protocols/SkypeClassic/src/gchat.cpp
+++ b/protocols/SkypeClassic/src/gchat.cpp
@@ -1,855 +1,858 @@
-#include "skype.h"
-#include "skypeapi.h"
-#include "gchat.h"
-#include "contacts.h"
-#include "debug.h"
-#include "utf8.h"
-#include "pthread.h"
-
-#include <m_langpack.h>
-#include <m_userinfo.h>
-#include <m_history.h>
-#include <m_contacts.h>
-
-#ifndef DWLP_USER
-#define DWLP_USER DWL_USER
-#endif
-
-#ifdef _UNICODE
-#define STR "%S"
-#else
-#define STR "%s"
-#endif
-
-#pragma warning (disable: 4706) // assignment within conditional expression
-
-extern HANDLE hInitChat;
-extern HINSTANCE hInst;
-extern char protocol, g_szProtoName[];
-extern DWORD mirandaVersion;
-
-static gchat_contacts *chats=NULL;
-static int chatcount=0;
-static CRITICAL_SECTION m_GCMutex;
-
-// TODO: Disable groupchat for Protocol verisons <5
-
-/****************************************************************************/
-/* Chat management helper functions */
-/****************************************************************************/
-
-/* Get the gchat_contacts entry for the chat with the id szChatId
- If the chat doesn't already exist in the list, it is added.
-
- Parameters: szChatId - String with the chat ID of the chat to be found
- Returns: Pointer to the gchat_contacts entry for the given id.
- NULL on failure (not enough memory)
-*/
-gchat_contacts *GetChat(const TCHAR *szChatId) {
- int i;
-
- for (i=0;i<chatcount;i++)
- if (!_tcscmp(chats[i].szChatName, szChatId)) return &chats[i];
- if (chats = (gchat_contacts *)realloc(chats, sizeof(gchat_contacts)*(++chatcount))) {
- memset(&chats[chatcount-1], 0, sizeof(gchat_contacts));
- chats[chatcount-1].szChatName=_tcsdup(szChatId);
- return &chats[chatcount-1];
- }
- return NULL;
-}
-
-/* Removes the gchat_contacts entry for the chat with the id szChatId,
- if it exists.
-
- Parameters: szChatId - String with the chat ID to be removed from list
- */
-void RemChat(TCHAR *szChatId) {
- int i;
-
- for (i=0;i<chatcount;i++)
- if (!_tcscmp(chats[i].szChatName, szChatId)) {
- if (chats[i].szChatName) free(chats[i].szChatName);
- if (chats[i].mJoinedContacts) free(chats[i].mJoinedContacts);
- if (i<--chatcount) memmove(&chats[i], &chats[i+1], (chatcount-i)*sizeof(gchat_contacts));
- chats = (gchat_contacts *)realloc(chats, sizeof(gchat_contacts)*chatcount);
- return;
- }
-}
-
-/* Checks, if the contact with the handle hContact exists in the groupchat
- given in gc
-
- Parameters: gc - gchat_contacts entry for the chat session to be searched
- who - Name of member
- Returns: -1 = Not found
- >=0 = Number of found item
- */
-static int ExistsChatContact(gchat_contacts *gc, const TCHAR *who) {
- int i;
-
- for (i=0;i<gc->mJoinedCount;i++)
- if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) return i;
- return -1;
-}
-
-gchat_contact *GetChatContact(gchat_contacts *gc, const TCHAR *who) {
- int i = ExistsChatContact (gc, who);
-
- if (i==-1) return NULL;
- return &gc->mJoinedContacts[i];
-}
-
-/* Adds contact with the name who to the groupchat given in gc
-
- Parameters: gc -
- Returns: -1 = Contact not found
- -2 = On failure
- >=0 = Number of added item
- */
-static int AddChatContact(gchat_contacts *gc, char *who, TCHAR *pszRole)
-{
- LOG (("AddChatContact %s", who));
- TCHAR *twho = make_nonutf_tchar_string((const unsigned char*)who);
- if (!twho)
- return -2;
-
- int i = ExistsChatContact(gc, twho);
- if (i >= 0)
- return i;
-
- MCONTACT hContact = find_contact(who);
-
- GCDEST gcd = { SKYPE_PROTONAME, gc->szChatName, GC_EVENT_JOIN };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.time = (DWORD)time(NULL);
- gce.dwFlags = GCEF_ADDTOLOG;
- gce.ptszStatus = pszRole ? pszRole : _T("USER");
-
- CONTACTINFO ci = {0};
- ci.cbSize = sizeof(ci);
- ci.szProto = SKYPE_PROTONAME;
- ci.dwFlag = CNF_DISPLAY | CNF_TCHAR;
- ci.hContact = hContact;
-
- if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci))
- gce.ptszNick=ci.pszVal;
- else
- gce.ptszNick=twho;
-
- gce.ptszUID=twho;
- if (!CallService(MS_GC_EVENT, 0, (LPARAM)&gce)) {
- if ((gc->mJoinedContacts=(gchat_contact*)realloc(gc->mJoinedContacts, (gc->mJoinedCount+1)*sizeof(gchat_contact))))
- {
- gc->mJoinedContacts[i=gc->mJoinedCount].hContact=hContact;
- _tcscpy (gc->mJoinedContacts[i].szRole, gce.ptszStatus);
- _tcscpy (gc->mJoinedContacts[i].who, twho);
- gc->mJoinedCount++;
- }
- }
- if (ci.pszVal) mir_free (ci.pszVal);
- free_nonutf_tchar_string (twho);
- return i;
-}
-
-void RemChatContact(gchat_contacts *gc, const TCHAR *who) {
- int i;
-
- if (!gc) return;
- for (i=0;i<gc->mJoinedCount;i++)
- if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) {
- if (i<--gc->mJoinedCount)
- memmove(&gc->mJoinedContacts[i], &gc->mJoinedContacts[i+1], (gc->mJoinedCount-i)*sizeof(gchat_contact));
- if (gc->mJoinedCount) gc->mJoinedContacts = (gchat_contact*)realloc(gc->mJoinedContacts, sizeof(gchat_contact)*gc->mJoinedCount);
- else {free (gc->mJoinedContacts); gc->mJoinedContacts = NULL; }
- return;
- }
-}
-
-MCONTACT find_chat(LPCTSTR chatname) {
- for (MCONTACT hContact=db_find_first(SKYPE_PROTONAME);hContact != NULL;hContact=db_find_next(hContact,SKYPE_PROTONAME)) {
- if (db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1)
- {
- DBVARIANT dbv;
- if (!db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) {
- int tCompareResult = _tcscmp(dbv.ptszVal, chatname);
- db_free(&dbv);
- if (!tCompareResult)
- return hContact; // already there, return handle
- }
- }
- }
- return NULL;
-}
-
-#ifdef _UNICODE
-MCONTACT find_chatA(char *chatname) {
- for (MCONTACT hContact=db_find_first(SKYPE_PROTONAME);hContact != NULL;hContact=db_find_next(hContact,SKYPE_PROTONAME)) {
- if (db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1)
- {
- DBVARIANT dbv;
- if (!db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) {
- int tCompareResult = strcmp(dbv.pszVal, chatname);
- db_free(&dbv);
- if (!tCompareResult)
- return hContact; // already there, return handle
- }
- }
- }
- return NULL;
-}
-#endif
-
-
-
-int __cdecl AddMembers(char *szSkypeMsg) {
- BYTE *contactmask=NULL;
- DBVARIANT dbv2;
- CONTACTINFO ci={0};
- char *who, *nextoken;
- int i, iRet = 0;
- gchat_contacts *gc;
-
- LOG(("AddMembers STARTED"));
- char *ptr=strstr(szSkypeMsg, " MEMBERS");
- if (!ptr)
- return -1;
- EnterCriticalSection(&m_GCMutex);
- ptr[0]=0;
- TCHAR *szChatId = make_nonutf_tchar_string((const unsigned char*)szSkypeMsg+5);
- ptr+=9;
- if (find_chat(szChatId) && (gc=GetChat(szChatId)) &&
- !db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2))
- {
- char *pszMemObjs, *token;
-
- if (protocol>=7 && (pszMemObjs = SkypeGet ("CHAT", szSkypeMsg+5, "MEMBEROBJECTS"))) {
- // Add new contacts (protocol 7+ with memberobjects, supports roles)
- for (token=strtok_r(pszMemObjs, ", ", &nextoken); token; token=strtok_r(NULL, ", ", &nextoken)) {
- if (!contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) {
- iRet = -1;
- break;
- }
- if (!(who = SkypeGet ("CHATMEMBER", token, "IDENTITY"))) continue;
- if (strcmp(who, dbv2.pszVal)) {
- TCHAR *ptszRole = NULL;
-
- char *pszRole = SkypeGet("CHATMEMBER", token, "ROLE");
- if (pszRole)
- ptszRole = make_nonutf_tchar_string((const unsigned char*)pszRole);
-
- i=AddChatContact(gc, who, ptszRole);
- free_nonutf_tchar_string (ptszRole);
- if (pszRole) free (pszRole);
- if (!(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) {
- iRet = -1;
- free (who);
- break;
- }
- contactmask[i]=TRUE;
- }
- free (who);
- }
- free (pszMemObjs);
- }
- else
- {
- // Add new contacts (normal)
- for (who=strtok_r(ptr, " ", &nextoken); who; who=strtok_r(NULL, " ", &nextoken)) {
- if (!contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) {
- iRet = -1;
- break;
- }
- if (strcmp(who, dbv2.pszVal)) {
- i=AddChatContact(gc, who, NULL);
- if (i<0 || !(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) {
- iRet = -1;
- break;
- }
- contactmask[i]=TRUE;
- }
- }
- }
- // Quit contacts which are no longer there
- if (iRet == 0 && contactmask) {
- GCDEST gcd = { SKYPE_PROTONAME, szChatId, GC_EVENT_QUIT };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.time = (DWORD)time(NULL);
- gce.dwFlags = GCEF_ADDTOLOG;
-
- ci.cbSize = sizeof(ci);
- ci.szProto = SKYPE_PROTONAME;
- ci.dwFlag = CNF_DISPLAY;
-
- for (i=0;i<gc->mJoinedCount;i++)
- if (!contactmask[i])
- {
- ci.hContact = gc->mJoinedContacts[i].hContact;
- ci.dwFlag = CNF_TCHAR;
- if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal;
- else gce.ptszNick=gc->mJoinedContacts[i].who;
- gce.ptszUID = gc->mJoinedContacts[i].who;
- CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
- if (ci.pszVal) {
- mir_free (ci.pszVal);
- ci.pszVal=NULL;
- }
- RemChatContact(gc, gc->mJoinedContacts[i].who);
- }
- // We don't do this, because the dialog group-chat may have been started intentionally
- /*
- if (gc->mJoinedCount == 1) {
- // switch back to normal session
- KillChatSession(&gcd);
- }
- */
- }
- if (contactmask) free(contactmask);
- db_free(&dbv2);
- } else iRet = -1;
- free_nonutf_tchar_string (szChatId);
- LeaveCriticalSection(&m_GCMutex);
- LOG(("AddMembers DONE"));
- return iRet;
-}
-
-void AddMembersThread(char *szSkypeMsg)
-{
- AddMembers(szSkypeMsg);
- free(szSkypeMsg);
-}
-
-/****************************************************************************/
-/* Window procedures */
-/****************************************************************************/
-INT_PTR CALLBACK InputBoxDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_INITDIALOG:
- {
- TranslateDialogDefault(hwndDlg);
- SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
- SetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)lParam);
- return TRUE;
- }
-
- case WM_COMMAND:
- switch ( LOWORD( wParam )) {
- case IDOK:
- {
- GetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER), (MAX_BUF-1)*sizeof(TCHAR));
- EndDialog(hwndDlg, 1);
- break;
- }
- case IDCANCEL:
- EndDialog(hwndDlg, 0);
- break;
- } }
- return FALSE;
-}
-
-/****************************************************************************/
-/* Core Chat management functions */
-/****************************************************************************/
-
-/* We have a new Groupchat
-
- This hook is called when a new chat is initialised.
- Parameters: wParam = (char *)Name of new chat session [Has to be ASCIIZ/UTF8]
- lParam = 1 - Create groupchat, but don't open it
- 0 - Default - open groupchat after init
-*/
-
-int __cdecl ChatInit(WPARAM wParam, LPARAM lParam)
-{
- if (!wParam) return -1;
-
- DBVARIANT dbv, dbv2;
- int iRet = -1;
-
- GCSESSION gcw = { sizeof(gcw) };
- gcw.iType = GCW_CHATROOM;
- gcw.pszModule = SKYPE_PROTONAME;
-
- char *szChatName = SkypeGet ("CHAT", (char *)wParam, "FRIENDLYNAME");
- if (!szChatName || !*szChatName)
- gcw.ptszName=TranslateT("Unknown"); else {
-#ifdef _UNICODE
- gcw.ptszName=make_unicode_string((const unsigned char*)szChatName);
- free (szChatName);
- szChatName = (char*)gcw.ptszName;
-#else
- gcw.ptszName=szChatName;
-#endif
- }
- gcw.ptszID = make_nonutf_tchar_string((const unsigned char*)wParam);
- gcw.ptszStatusbarText = NULL;
- EnterCriticalSection(&m_GCMutex);
- if (!CallService(MS_GC_NEWSESSION, 0, (LPARAM)&gcw)) {
- char *szChatRole;
-
- GCDEST gcd = { SKYPE_PROTONAME, gcw.ptszID, GC_EVENT_ADDGROUP };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.ptszStatus = _T("CREATOR");
- // BUG: Groupchat returns nonzero on success here in earlier versions, so we don't check
- // it here
- CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
- gce.ptszStatus = _T("MASTER");
- CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
- gce.ptszStatus = _T("HELPER");
- CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
- gce.ptszStatus = _T("USER");
- CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
- gce.ptszStatus = _T("LISTENER");
- CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
- gce.ptszStatus = _T("APPLICANT");
- CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
-
- gcd.iType = GC_EVENT_JOIN;
- gce.ptszStatus = NULL;
- if (protocol >=7 && (szChatRole = SkypeGet ("CHAT", (char *)wParam, "MYROLE"))) {
- if (strncmp(szChatRole, "ERROR", 5))
- {
-#ifdef _UNICODE
- gce.ptszStatus = make_unicode_string((const unsigned char*)szChatRole);
- free (szChatRole);
-#else
- gce.ptszStatus = szChatRole;
-#endif
- }
- }
- if (!gce.ptszStatus) gce.ptszStatus=_tcsdup(_T("CREATOR"));
-
- if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) {
- if (!db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2)) {
- gce.ptszNick = dbv.ptszVal;
- gce.ptszUID = dbv2.ptszVal;
- gce.time = 0;
- gce.bIsMe = TRUE;
- gce.dwFlags |= GCEF_ADDTOLOG;
- if (!CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce)) {
- gcd.iType = GC_EVENT_CONTROL;
- if (!lParam)
- CallService(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce);
- CallService(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);
- CallService(MS_GC_EVENT, lParam ? WINDOW_HIDDEN : WINDOW_VISIBLE, (LPARAM)&gce);
- SkypeSend ("GET CHAT %s MEMBERS", (char *)wParam);
- iRet = 0;
- }
- else {LOG (("ChatInit: Joining 'me' failed."));}
- }
- db_free(&dbv2);
- }
- free ((void*)gce.ptszStatus);
- db_free(&dbv);
- }
- free (szChatName);
- free_nonutf_tchar_string ((void*)gcw.ptszID);
- LeaveCriticalSection(&m_GCMutex);
- return iRet;
-}
-
-/* Open new Groupchat
-
- Parameters: szChatId = (char *)Name of new chat session
-*/
-int __cdecl ChatStart(char *szChatId, BOOL bJustCreate) {
- LOG(("ChatStart: New groupchat started"));
- if (!szChatId || NotifyEventHooks(hInitChat, (WPARAM)szChatId, bJustCreate)) return -1;
- return 0;
-}
-
-
-void KillChatSession(GCDEST *gcd)
-{
- GCEVENT gce = { sizeof(gce), gcd };
- EnterCriticalSection(&m_GCMutex);
- LOG(("KillChatSession: Groupchatsession terminated."));
- gcd->iType = GC_EVENT_CONTROL;
- if (SkypeSend ("ALTER CHAT "STR" LEAVE", gcd->ptszID) == 0)
- {
- CallService(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce);
- CallService(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce);
- }
- LeaveCriticalSection(&m_GCMutex);
-}
-
-void InviteUser(const TCHAR *szChatId)
-{
- if (!szChatId)
- return;
-
- gchat_contacts *gc=GetChat(szChatId);
- if (!gc)
- return;
-
- // add the heading
- HMENU tMenu = CreatePopupMenu();
- AppendMenu(tMenu, MF_STRING|MF_GRAYED|MF_DISABLED, 0, TranslateT("&Invite user..."));
- AppendMenu(tMenu, MF_SEPARATOR, 1, NULL);
-
- DBVARIANT dbv;
- POINT pt;
- int j;
-
- // generate a list of contact
- for (MCONTACT hContact = db_find_first(SKYPE_PROTONAME);hContact;hContact = db_find_next(hContact,SKYPE_PROTONAME)) {
- if (!db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) &&
- db_get_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)!=ID_STATUS_OFFLINE)
- {
- BOOL alreadyInSession = FALSE;
- for (j=0; j<gc->mJoinedCount; j++) {
- if (gc->mJoinedContacts[j].hContact==hContact) {
- alreadyInSession = TRUE;
- break;
- }
- }
- if (!alreadyInSession)
- AppendMenu(tMenu, MF_STRING, (UINT_PTR)hContact,
- (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR));
- }
-
- }
-
- HWND tWindow = CreateWindow(_T("EDIT"),_T(""),0,1,1,1,1,NULL,NULL,hInst,NULL);
-
- GetCursorPos (&pt);
- MCONTACT hInvitedUser = (MCONTACT)TrackPopupMenu(tMenu, TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, tWindow, NULL);
- DestroyMenu(tMenu);
- DestroyWindow(tWindow);
-
- if (!hInvitedUser || db_get_s(hInvitedUser, SKYPE_PROTONAME, SKYPE_NAME, &dbv))
- return;
- SkypeSend ("ALTER CHAT "STR" ADDMEMBERS %s", szChatId, dbv.pszVal);
- db_free(&dbv);
-
-}
-
-static void KickUser (MCONTACT hContact, GCHOOK *gch)
-{
- EnterCriticalSection(&m_GCMutex);
- if (SkypeSend ("ALTER CHAT "STR" KICK "STR, gch->pDest->ptszID, gch->ptszUID)!=-1) {
- char *ptr = SkypeRcv("ALTER CHAT KICK", 2000);
- if (ptr) {
- if (strncmp(ptr, "ERROR", 5)) {
- GCDEST gcd = { SKYPE_PROTONAME, gch->pDest->ptszID, GC_EVENT_KICK };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.time = (DWORD)time(NULL);
- gce.dwFlags = GCEF_ADDTOLOG;
- gce.ptszUID = gch->ptszUID;
-
- CONTACTINFO ci = {0};
- ci.cbSize = sizeof(ci);
- ci.szProto = SKYPE_PROTONAME;
- ci.dwFlag = CNF_DISPLAY | CNF_TCHAR;
- ci.hContact = hContact;
- if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal;
- else gce.ptszNick=gce.ptszUID;
-
- DBVARIANT dbv;
- if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) {
- gce.ptszStatus = dbv.ptszVal;
- CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
- RemChatContact (GetChat(gcd.ptszID), gch->ptszUID);
- db_free(&dbv);
- }
- if (ci.pszVal) mir_free (ci.pszVal);
- }
- free (ptr);
- }
- }
- LeaveCriticalSection(&m_GCMutex);
-}
-
-void SetChatTopic(const TCHAR *szChatId, TCHAR *szTopic, BOOL bSet)
-{
- MCONTACT hContact = find_chat (szChatId);
- char *szUTFTopic;
-
- GCDEST gcd = { SKYPE_PROTONAME, szChatId, GC_EVENT_TOPIC };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.ptszText = szTopic;
- gce.dwFlags = GCEF_ADDTOLOG;
- gce.time = (DWORD)time (NULL);
- CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
-
- gcd.iType = GC_EVENT_SETSBTEXT;
- CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
-
- if (bSet) {
-#ifdef _UNICODE
- szUTFTopic=(char*)make_utf8_string(szTopic);
-#else
- if (utf8_encode(szTopic, &szUTFTopic)==-1) szUTFTopic = NULL;
-#endif
- if (szUTFTopic) {
- SkypeSend ("ALTER CHAT "STR" SETTOPIC %s", szChatId, szUTFTopic);
- free (szUTFTopic);
- }
- testfor ("ALTER CHAT SETTOPIC", INFINITE);
- }
-
- if (hContact)
- db_set_ts(hContact, SKYPE_PROTONAME, "Nick", szTopic);
-}
-
-
-int GCEventHook(WPARAM,LPARAM lParam) {
- GCHOOK *gch = (GCHOOK*) lParam;
- if(gch) {
- gchat_contacts *gc = GetChat(gch->pDest->ptszID);
- if (!_stricmp(gch->pDest->pszModule, SKYPE_PROTONAME)) {
-
- switch (gch->pDest->iType) {
- case GC_SESSION_TERMINATE: {
- MCONTACT hContact;
-
- if (gc->mJoinedCount == 1) {
- // switch back to normal session
- // I don't know if this behaviour isn't a bit annoying, therefore, we
- // don't do this now, until a user requests this feature :)
-
- // open up srmm dialog when quit while 1 person left
-// CallService(MS_MSG_SENDMESSAGE, (WPARAM)gc->mJoinedContacts[0].hContact, 0);
-
- RemChatContact(gc, gc->mJoinedContacts[0].who);
- }
- // Delete Chatroom from Contact list, as we don't need it anymore...?
- if (hContact = find_chat(gc->szChatName))
- CallService(MS_DB_CONTACT_DELETE, hContact, 0);
- RemChat(gc->szChatName);
-
- break;
- }
- case GC_USER_MESSAGE:
- if(gch && gch->ptszText && _tcslen(gch->ptszText) > 0) {
- DBVARIANT dbv, dbv2;
- CCSDATA ccs = {0};
- TCHAR *pEnd;
-
- // remove the ending linebreak
- for (pEnd = &gch->ptszText[_tcslen(gch->ptszText) - 1];
- *pEnd==_T('\r') || *pEnd==_T('\n'); pEnd--) *pEnd=0;
- // Send message to the chat-contact
- if (ccs.hContact = find_chat(gch->pDest->ptszID)) {
-#ifdef _UNICODE
- // If PREF_UTF is supported, just convert it to UTF8 and pass the buffer to PSS_MESSAGE
- if (mirandaVersion >= 0x070000) {
- ccs.lParam = (LPARAM)make_utf8_string(gch->ptszText);
- ccs.wParam = PREF_UTF;
- CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs);
- free ((void*)ccs.lParam);
- } else {
- // Otherwise create this strange dual miranda-format
- ccs.lParam = (LPARAM)calloc(3, _tcslen(gch->ptszText)+1);
- wcstombs ((char*)ccs.lParam, gch->ptszText, _tcslen(gch->ptszText)+1);
- _tcscpy ((TCHAR*)((char*)ccs.lParam+strlen((char*)ccs.lParam)+1), gch->ptszText);
- ccs.wParam = PREF_UNICODE;
- CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs);
- free ((void*)ccs.lParam);
- }
-#else
- ccs.lParam = (LPARAM)gch->ptszText;
- ccs.wParam = PREF_TCHAR;
- CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs);
-#endif
- }
-
- // Add our line to the chatlog
- GCDEST gcd = { gch->pDest->pszModule, gch->pDest->ptszID, 0 };
- GCEVENT gce = { sizeof(gce), &gcd };
- if ( _tcsncmp(gch->ptszText, _T("/me "), 4)==0 && _tcslen(gch->ptszText)>4) {
- gce.ptszText = gch->ptszText+4;
- gcd.iType = GC_EVENT_ACTION;
- }
- else {
- gce.ptszText = gch->ptszText;
- gcd.iType = GC_EVENT_MESSAGE;
- }
-
- if (db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv))
- gce.ptszNick = TranslateT("Me");
- else
- gce.ptszNick = dbv.ptszVal;
- db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2);
- gce.ptszUID = dbv2.ptszVal;
- gce.time = (DWORD)time(NULL);
- gce.dwFlags = GCEF_ADDTOLOG;
- gce.bIsMe = TRUE;
- CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
- if (dbv.pszVal) db_free(&dbv);
- if (dbv2.pszVal) db_free(&dbv2);
- }
- break;
- case GC_USER_CHANMGR:
- InviteUser(gch->pDest->ptszID);
- break;
- case GC_USER_PRIVMESS: {
- MCONTACT hContact = find_contactT(gch->ptszUID);
- if (hContact) CallService(MS_MSG_SENDMESSAGE, hContact, 0);
- break;
-
- }
- case GC_USER_LOGMENU:
- switch(gch->dwData) {
- case 10: InviteUser(gch->pDest->ptszID); break;
- case 20: KillChatSession(gch->pDest); break;
- case 30:
- {
- TCHAR *ptr, buf[MAX_BUF];
-
- ptr = SkypeGetT ("CHAT", (TCHAR*)gch->pDest->ptszID, "TOPIC");
- _tcscpy(buf, ptr);
- free(ptr);
- if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_INPUTBOX), NULL, InputBoxDlgProc, (LPARAM)&buf))
- SetChatTopic(gch->pDest->ptszID, buf, TRUE);
- break;
- }
- }
- break;
- case GC_USER_NICKLISTMENU: {
- MCONTACT hContact = find_contactT(gch->ptszUID);
-
- switch(gch->dwData) {
- case 10:CallService(MS_USERINFO_SHOWDIALOG, hContact, 0); break;
- case 20:CallService(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0); break;
- case 30: KickUser(hContact, gch); break;
- case 110: KillChatSession(gch->pDest); break;
- }
- break;
- }
- default:
- break;
- }
- }
-
- }
- return 0;
-}
-
-int __cdecl GCMenuHook(WPARAM,LPARAM lParam) {
- GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam;
- DBVARIANT dbv;
- TCHAR* szInvite = TranslateT("&Invite user...");
- TCHAR* szLeave = TranslateT("&Leave chat session");
- TCHAR* szTopic = TranslateT("Set &Topic...");
- TCHAR* szDetails = TranslateT("User &details");
- TCHAR* szHistory = TranslateT("User &history");
- TCHAR* szKick = TranslateT("&Kick user");
-
- static struct gc_item Item_log[] = {
- {NULL, 10, MENU_ITEM, FALSE},
- {NULL, 30, MENU_ITEM, FALSE},
- {NULL, 20, MENU_ITEM, FALSE}
- };
- static struct gc_item Item_nicklist_me[] = {
- {NULL, 20, MENU_ITEM, FALSE},
- {_T(""), 100, MENU_SEPARATOR, FALSE},
- {NULL, 110, MENU_ITEM, FALSE}
- };
- static struct gc_item Item_nicklist[] = {
- {NULL, 10, MENU_ITEM, FALSE},
- {NULL, 20, MENU_ITEM, FALSE},
- {NULL, 30, MENU_ITEM, FALSE}
- };
-
- Item_log[0].pszDesc = szInvite;
- Item_log[1].pszDesc = szTopic;
- Item_log[2].pszDesc = szLeave;
- Item_nicklist_me[0].pszDesc = szHistory;
- Item_nicklist_me[2].pszDesc = szLeave;
- Item_nicklist[0].pszDesc = szDetails;
- Item_nicklist[1].pszDesc = szHistory;
- Item_nicklist[2].pszDesc = szKick;
-
- LOG (("GCMenuHook started."));
- if(gcmi) {
- if (!_stricmp(gcmi->pszModule, SKYPE_PROTONAME)) {
- switch (gcmi->Type)
- {
- case MENU_ON_LOG:
- gcmi->nItems = sizeof(Item_log)/sizeof(Item_log[0]);
- gcmi->Item = &Item_log[0];
- LOG (("GCMenuHook: Items in log window: %d", gcmi->nItems));
- break;
- case MENU_ON_NICKLIST:
- if (db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1;
- if (!lstrcmp(dbv.ptszVal, gcmi->pszUID)) {
- gcmi->nItems = sizeof(Item_nicklist_me)/sizeof(Item_nicklist_me[0]);
- gcmi->Item = &Item_nicklist_me[0];
- } else {
- gchat_contacts *gcs = GetChat(gcmi->pszID);
- gchat_contact *gc = gcs?GetChatContact(gcs, gcmi->pszUID):NULL;
- gcmi->nItems = sizeof(Item_nicklist)/sizeof(Item_nicklist[0]);
-
- Item_nicklist[2].bDisabled = FALSE;
- if (gc && !gc->hContact)
- {
- gcmi->nItems -= 2;
- gcmi->Item = &Item_nicklist[2];
- }
- else
- gcmi->Item = &Item_nicklist[0];
- /*
- if (protocol<7) Item_nicklist[2].bDisabled = TRUE;
- else {
- TCHAR *szChatRole;
- if (szChatRole = SkypeGetT ("CHAT", gcmi->pszID, "MYROLE")) {
- if (_tcscmp(szChatRole, _T("MASTER")) && _tcscmp(szChatRole, _T("CREATOR")))
- Item_nicklist[2].bDisabled = TRUE;
- free (szChatRole);
- }
- }*/
-
- }
- db_free(&dbv);
- break;
- }
- } else {LOG (("GCMenuHook: ERROR: Not our protocol."));}
- } else {LOG (("GCMenuHook: ERROR: No gcmi"));}
- LOG (("GCMenuHook: terminated."));
- return 0;
-}
-
-INT_PTR GCOnLeaveChat(WPARAM wParam,LPARAM)
-{
- MCONTACT hContact = (MCONTACT)wParam;
- DBVARIANT dbv;
-
- if (db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0)
- {
- GCDEST gcd = { SKYPE_PROTONAME, dbv.ptszVal, GC_EVENT_CONTROL };
- KillChatSession(&gcd);
- db_free(&dbv);
- }
- return 0;
-}
-
-INT_PTR GCOnJoinChat(WPARAM wParam,LPARAM)
-{
- MCONTACT hContact = (MCONTACT)wParam;
- DBVARIANT dbv;
-
- if (db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0)
- {
- ChatStart (dbv.pszVal, FALSE);
- db_free(&dbv);
- }
- return 0;
-}
-
-void GCInit(void)
-{
- InitializeCriticalSection (&m_GCMutex);
-}
-
-void GCExit(void)
-{
- DeleteCriticalSection (&m_GCMutex);
-
- for (int i=0; i < chatcount; i++) {
- free(chats[i].szChatName);
- free(chats[i].mJoinedContacts);
- }
- free(chats); chats = NULL;
- chatcount = 0;
-}
+#include "skype.h"
+#include "skypeapi.h"
+#include "gchat.h"
+#include "contacts.h"
+#include "debug.h"
+#include "utf8.h"
+#include "pthread.h"
+
+#include <m_langpack.h>
+#include <m_userinfo.h>
+#include <m_history.h>
+#include <m_contacts.h>
+
+#ifndef DWLP_USER
+#define DWLP_USER DWL_USER
+#endif
+
+#ifdef _UNICODE
+#define STR "%S"
+#else
+#define STR "%s"
+#endif
+
+#pragma warning (disable: 4706) // assignment within conditional expression
+
+extern HANDLE hInitChat;
+extern HINSTANCE hInst;
+extern char protocol, g_szProtoName[];
+extern DWORD mirandaVersion;
+
+static gchat_contacts *chats=NULL;
+static int chatcount=0;
+static CRITICAL_SECTION m_GCMutex;
+
+// TODO: Disable groupchat for Protocol verisons <5
+
+/****************************************************************************/
+/* Chat management helper functions */
+/****************************************************************************/
+
+/* Get the gchat_contacts entry for the chat with the id szChatId
+ If the chat doesn't already exist in the list, it is added.
+
+ Parameters: szChatId - String with the chat ID of the chat to be found
+ Returns: Pointer to the gchat_contacts entry for the given id.
+ NULL on failure (not enough memory)
+*/
+gchat_contacts *GetChat(const TCHAR *szChatId) {
+ int i;
+
+ for (i=0;i<chatcount;i++)
+ if (!_tcscmp(chats[i].szChatName, szChatId)) return &chats[i];
+ if (chats = (gchat_contacts *)realloc(chats, sizeof(gchat_contacts)*(++chatcount))) {
+ memset(&chats[chatcount-1], 0, sizeof(gchat_contacts));
+ chats[chatcount-1].szChatName=_tcsdup(szChatId);
+ return &chats[chatcount-1];
+ }
+ return NULL;
+}
+
+/* Removes the gchat_contacts entry for the chat with the id szChatId,
+ if it exists.
+
+ Parameters: szChatId - String with the chat ID to be removed from list
+ */
+void RemChat(TCHAR *szChatId) {
+ int i;
+
+ for (i=0;i<chatcount;i++)
+ if (!_tcscmp(chats[i].szChatName, szChatId)) {
+ if (chats[i].szChatName) free(chats[i].szChatName);
+ if (chats[i].mJoinedContacts) free(chats[i].mJoinedContacts);
+ if (i<--chatcount) memmove(&chats[i], &chats[i+1], (chatcount-i)*sizeof(gchat_contacts));
+ chats = (gchat_contacts *)realloc(chats, sizeof(gchat_contacts)*chatcount);
+ return;
+ }
+}
+
+/* Checks, if the contact with the handle hContact exists in the groupchat
+ given in gc
+
+ Parameters: gc - gchat_contacts entry for the chat session to be searched
+ who - Name of member
+ Returns: -1 = Not found
+ >=0 = Number of found item
+ */
+static int ExistsChatContact(gchat_contacts *gc, const TCHAR *who) {
+ int i;
+
+ for (i=0;i<gc->mJoinedCount;i++)
+ if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) return i;
+ return -1;
+}
+
+gchat_contact *GetChatContact(gchat_contacts *gc, const TCHAR *who) {
+ int i = ExistsChatContact (gc, who);
+
+ if (i==-1) return NULL;
+ return &gc->mJoinedContacts[i];
+}
+
+/* Adds contact with the name who to the groupchat given in gc
+
+ Parameters: gc -
+ Returns: -1 = Contact not found
+ -2 = On failure
+ >=0 = Number of added item
+ */
+static int AddChatContact(gchat_contacts *gc, char *who, TCHAR *pszRole)
+{
+ LOG (("AddChatContact %s", who));
+ TCHAR *twho = make_nonutf_tchar_string((const unsigned char*)who);
+ if (!twho)
+ return -2;
+
+ int i = ExistsChatContact(gc, twho);
+ if (i >= 0)
+ return i;
+
+ MCONTACT hContact = find_contact(who);
+
+ GCDEST gcd = { SKYPE_PROTONAME, gc->szChatName, GC_EVENT_JOIN };
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.time = (DWORD)time(NULL);
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.ptszStatus = pszRole ? pszRole : _T("USER");
+
+ CONTACTINFO ci = {0};
+ ci.cbSize = sizeof(ci);
+ ci.szProto = SKYPE_PROTONAME;
+ ci.dwFlag = CNF_DISPLAY | CNF_TCHAR;
+ ci.hContact = hContact;
+
+ if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci))
+ gce.ptszNick=ci.pszVal;
+ else
+ gce.ptszNick=twho;
+
+ gce.ptszUID=twho;
+ if (!CallService(MS_GC_EVENT, 0, (LPARAM)&gce)) {
+ if ((gc->mJoinedContacts=(gchat_contact*)realloc(gc->mJoinedContacts, (gc->mJoinedCount+1)*sizeof(gchat_contact))))
+ {
+ gc->mJoinedContacts[i=gc->mJoinedCount].hContact=hContact;
+ _tcscpy (gc->mJoinedContacts[i].szRole, gce.ptszStatus);
+ _tcscpy (gc->mJoinedContacts[i].who, twho);
+ gc->mJoinedCount++;
+ }
+ }
+ if (ci.pszVal) mir_free (ci.pszVal);
+ free_nonutf_tchar_string (twho);
+ return i;
+}
+
+void RemChatContact(gchat_contacts *gc, const TCHAR *who) {
+ int i;
+
+ if (!gc) return;
+ for (i=0;i<gc->mJoinedCount;i++)
+ if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) {
+ if (i<--gc->mJoinedCount)
+ memmove(&gc->mJoinedContacts[i], &gc->mJoinedContacts[i+1], (gc->mJoinedCount-i)*sizeof(gchat_contact));
+ if (gc->mJoinedCount) gc->mJoinedContacts = (gchat_contact*)realloc(gc->mJoinedContacts, sizeof(gchat_contact)*gc->mJoinedCount);
+ else {free (gc->mJoinedContacts); gc->mJoinedContacts = NULL; }
+ return;
+ }
+}
+
+MCONTACT find_chat(LPCTSTR chatname) {
+ for (MCONTACT hContact=db_find_first(SKYPE_PROTONAME);hContact != NULL;hContact=db_find_next(hContact,SKYPE_PROTONAME)) {
+ if (db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1)
+ {
+ DBVARIANT dbv;
+ if (!db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) {
+ int tCompareResult = _tcscmp(dbv.ptszVal, chatname);
+ db_free(&dbv);
+ if (!tCompareResult)
+ return hContact; // already there, return handle
+ }
+ }
+ }
+ return NULL;
+}
+
+#ifdef _UNICODE
+MCONTACT find_chatA(char *chatname) {
+ for (MCONTACT hContact=db_find_first(SKYPE_PROTONAME);hContact != NULL;hContact=db_find_next(hContact,SKYPE_PROTONAME)) {
+ if (db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1)
+ {
+ DBVARIANT dbv;
+ if (!db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) {
+ int tCompareResult = strcmp(dbv.pszVal, chatname);
+ db_free(&dbv);
+ if (!tCompareResult)
+ return hContact; // already there, return handle
+ }
+ }
+ }
+ return NULL;
+}
+#endif
+
+
+
+int __cdecl AddMembers(char *szSkypeMsg) {
+ BYTE *contactmask=NULL;
+ DBVARIANT dbv2;
+ CONTACTINFO ci={0};
+ char *who, *nextoken;
+ int i, iRet = 0;
+ gchat_contacts *gc;
+
+ LOG(("AddMembers STARTED"));
+ char *ptr=strstr(szSkypeMsg, " MEMBERS");
+ if (!ptr)
+ return -1;
+ EnterCriticalSection(&m_GCMutex);
+ ptr[0]=0;
+ TCHAR *szChatId = make_nonutf_tchar_string((const unsigned char*)szSkypeMsg+5);
+ ptr+=9;
+ if (find_chat(szChatId) && (gc=GetChat(szChatId)) &&
+ !db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2))
+ {
+ char *pszMemObjs, *token;
+
+ if (protocol>=7 && (pszMemObjs = SkypeGet ("CHAT", szSkypeMsg+5, "MEMBEROBJECTS"))) {
+ // Add new contacts (protocol 7+ with memberobjects, supports roles)
+ for (token=strtok_r(pszMemObjs, ", ", &nextoken); token; token=strtok_r(NULL, ", ", &nextoken)) {
+ if (!contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) {
+ iRet = -1;
+ break;
+ }
+ if (!(who = SkypeGet ("CHATMEMBER", token, "IDENTITY"))) continue;
+ if (strcmp(who, dbv2.pszVal)) {
+ TCHAR *ptszRole = NULL;
+
+ char *pszRole = SkypeGet("CHATMEMBER", token, "ROLE");
+ if (pszRole)
+ ptszRole = make_nonutf_tchar_string((const unsigned char*)pszRole);
+
+ i=AddChatContact(gc, who, ptszRole);
+ free_nonutf_tchar_string (ptszRole);
+ if (pszRole) free (pszRole);
+ if (!(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) {
+ iRet = -1;
+ free (who);
+ break;
+ }
+ contactmask[i]=TRUE;
+ }
+ free (who);
+ }
+ free (pszMemObjs);
+ }
+ else
+ {
+ // Add new contacts (normal)
+ for (who=strtok_r(ptr, " ", &nextoken); who; who=strtok_r(NULL, " ", &nextoken)) {
+ if (!contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) {
+ iRet = -1;
+ break;
+ }
+ if (strcmp(who, dbv2.pszVal)) {
+ i=AddChatContact(gc, who, NULL);
+ if (i<0 || !(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) {
+ iRet = -1;
+ break;
+ }
+ contactmask[i]=TRUE;
+ }
+ }
+ }
+ // Quit contacts which are no longer there
+ if (iRet == 0 && contactmask) {
+ GCDEST gcd = { SKYPE_PROTONAME, szChatId, GC_EVENT_QUIT };
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.time = (DWORD)time(NULL);
+ gce.dwFlags = GCEF_ADDTOLOG;
+
+ ci.cbSize = sizeof(ci);
+ ci.szProto = SKYPE_PROTONAME;
+ ci.dwFlag = CNF_DISPLAY;
+
+ for (i=0;i<gc->mJoinedCount;i++)
+ if (!contactmask[i])
+ {
+ ci.hContact = gc->mJoinedContacts[i].hContact;
+ ci.dwFlag = CNF_TCHAR;
+ if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal;
+ else gce.ptszNick=gc->mJoinedContacts[i].who;
+ gce.ptszUID = gc->mJoinedContacts[i].who;
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
+ if (ci.pszVal) {
+ mir_free (ci.pszVal);
+ ci.pszVal=NULL;
+ }
+ RemChatContact(gc, gc->mJoinedContacts[i].who);
+ }
+ // We don't do this, because the dialog group-chat may have been started intentionally
+ /*
+ if (gc->mJoinedCount == 1) {
+ // switch back to normal session
+ KillChatSession(&gcd);
+ }
+ */
+ }
+ if (contactmask) free(contactmask);
+ db_free(&dbv2);
+ } else iRet = -1;
+ free_nonutf_tchar_string (szChatId);
+ LeaveCriticalSection(&m_GCMutex);
+ LOG(("AddMembers DONE"));
+ return iRet;
+}
+
+void AddMembersThread(char *szSkypeMsg)
+{
+ AddMembers(szSkypeMsg);
+ free(szSkypeMsg);
+}
+
+/****************************************************************************/
+/* Window procedures */
+/****************************************************************************/
+INT_PTR CALLBACK InputBoxDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
+ SetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)lParam);
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ switch ( LOWORD( wParam )) {
+ case IDOK:
+ {
+ GetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER), (MAX_BUF-1)*sizeof(TCHAR));
+ EndDialog(hwndDlg, 1);
+ break;
+ }
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ break;
+ } }
+ return FALSE;
+}
+
+/****************************************************************************/
+/* Core Chat management functions */
+/****************************************************************************/
+
+/* We have a new Groupchat
+
+ This hook is called when a new chat is initialised.
+ Parameters: wParam = (char *)Name of new chat session [Has to be ASCIIZ/UTF8]
+ lParam = 1 - Create groupchat, but don't open it
+ 0 - Default - open groupchat after init
+*/
+
+int __cdecl ChatInit(WPARAM wParam, LPARAM lParam)
+{
+ if (!wParam) return -1;
+
+ DBVARIANT dbv, dbv2;
+ int iRet = -1;
+
+ GCSESSION gcw = { sizeof(gcw) };
+ gcw.iType = GCW_CHATROOM;
+ gcw.pszModule = SKYPE_PROTONAME;
+
+ char *szChatName = SkypeGet ("CHAT", (char *)wParam, "FRIENDLYNAME");
+ if (!szChatName || !*szChatName)
+ gcw.ptszName=TranslateT("Unknown"); else {
+#ifdef _UNICODE
+ gcw.ptszName=make_unicode_string((const unsigned char*)szChatName);
+ free (szChatName);
+ szChatName = (char*)gcw.ptszName;
+#else
+ gcw.ptszName=szChatName;
+#endif
+ }
+ gcw.ptszID = make_nonutf_tchar_string((const unsigned char*)wParam);
+ gcw.ptszStatusbarText = NULL;
+ EnterCriticalSection(&m_GCMutex);
+ if (!CallService(MS_GC_NEWSESSION, 0, (LPARAM)&gcw)) {
+ char *szChatRole;
+
+ GCDEST gcd = { SKYPE_PROTONAME, gcw.ptszID, GC_EVENT_ADDGROUP };
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.ptszStatus = _T("CREATOR");
+ // BUG: Groupchat returns nonzero on success here in earlier versions, so we don't check
+ // it here
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
+ gce.ptszStatus = _T("MASTER");
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
+ gce.ptszStatus = _T("HELPER");
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
+ gce.ptszStatus = _T("USER");
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
+ gce.ptszStatus = _T("LISTENER");
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
+ gce.ptszStatus = _T("APPLICANT");
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
+
+ gcd.iType = GC_EVENT_JOIN;
+ gce.ptszStatus = NULL;
+ if (protocol >=7 && (szChatRole = SkypeGet ("CHAT", (char *)wParam, "MYROLE"))) {
+ if (strncmp(szChatRole, "ERROR", 5))
+ {
+#ifdef _UNICODE
+ gce.ptszStatus = make_unicode_string((const unsigned char*)szChatRole);
+ free (szChatRole);
+#else
+ gce.ptszStatus = szChatRole;
+#endif
+ }
+ }
+ if (!gce.ptszStatus) gce.ptszStatus=_tcsdup(_T("CREATOR"));
+
+ if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) {
+ if (!db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2)) {
+ gce.ptszNick = dbv.ptszVal;
+ gce.ptszUID = dbv2.ptszVal;
+ gce.time = 0;
+ gce.bIsMe = TRUE;
+ gce.dwFlags |= GCEF_ADDTOLOG;
+ if (!CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce)) {
+ gcd.iType = GC_EVENT_CONTROL;
+ if (!lParam)
+ CallService(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce);
+ CallService(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);
+ CallService(MS_GC_EVENT, lParam ? WINDOW_HIDDEN : WINDOW_VISIBLE, (LPARAM)&gce);
+ SkypeSend ("GET CHAT %s MEMBERS", (char *)wParam);
+ iRet = 0;
+ }
+ else {LOG (("ChatInit: Joining 'me' failed."));}
+ }
+ db_free(&dbv2);
+ }
+ free ((void*)gce.ptszStatus);
+ db_free(&dbv);
+ }
+ free (szChatName);
+ free_nonutf_tchar_string ((void*)gcw.ptszID);
+ LeaveCriticalSection(&m_GCMutex);
+ return iRet;
+}
+
+/* Open new Groupchat
+
+ Parameters: szChatId = (char *)Name of new chat session
+*/
+int __cdecl ChatStart(char *szChatId, BOOL bJustCreate) {
+ LOG(("ChatStart: New groupchat started"));
+ if (!szChatId || NotifyEventHooks(hInitChat, (WPARAM)szChatId, bJustCreate)) return -1;
+ return 0;
+}
+
+
+void KillChatSession(GCDEST *gcd)
+{
+ GCEVENT gce = { sizeof(gce), gcd };
+ EnterCriticalSection(&m_GCMutex);
+ LOG(("KillChatSession: Groupchatsession terminated."));
+ gcd->iType = GC_EVENT_CONTROL;
+ if (SkypeSend ("ALTER CHAT "STR" LEAVE", gcd->ptszID) == 0)
+ {
+ CallService(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce);
+ CallService(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce);
+ }
+ LeaveCriticalSection(&m_GCMutex);
+}
+
+void InviteUser(const TCHAR *szChatId)
+{
+ if (!szChatId)
+ return;
+
+ gchat_contacts *gc=GetChat(szChatId);
+ if (!gc)
+ return;
+
+ // add the heading
+ HMENU tMenu = CreatePopupMenu();
+ AppendMenu(tMenu, MF_STRING|MF_GRAYED|MF_DISABLED, 0, TranslateT("&Invite user..."));
+ AppendMenu(tMenu, MF_SEPARATOR, 1, NULL);
+
+ DBVARIANT dbv;
+ POINT pt;
+ int j;
+
+ // generate a list of contact
+ for (MCONTACT hContact = db_find_first(SKYPE_PROTONAME);hContact;hContact = db_find_next(hContact,SKYPE_PROTONAME)) {
+ if (!db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) &&
+ db_get_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)!=ID_STATUS_OFFLINE)
+ {
+ BOOL alreadyInSession = FALSE;
+ for (j=0; j<gc->mJoinedCount; j++) {
+ if (gc->mJoinedContacts[j].hContact==hContact) {
+ alreadyInSession = TRUE;
+ break;
+ }
+ }
+ if (!alreadyInSession)
+ AppendMenu(tMenu, MF_STRING, (UINT_PTR)hContact,
+ (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR));
+ }
+
+ }
+
+ HWND tWindow = CreateWindow(_T("EDIT"),_T(""),0,1,1,1,1,NULL,NULL,hInst,NULL);
+
+ GetCursorPos (&pt);
+ MCONTACT hInvitedUser = (MCONTACT)TrackPopupMenu(tMenu, TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, tWindow, NULL);
+ DestroyMenu(tMenu);
+ DestroyWindow(tWindow);
+
+ if (!hInvitedUser || db_get_s(hInvitedUser, SKYPE_PROTONAME, SKYPE_NAME, &dbv))
+ return;
+ SkypeSend ("ALTER CHAT "STR" ADDMEMBERS %s", szChatId, dbv.pszVal);
+ db_free(&dbv);
+
+}
+
+static void KickUser (MCONTACT hContact, GCHOOK *gch)
+{
+ EnterCriticalSection(&m_GCMutex);
+ if (SkypeSend ("ALTER CHAT "STR" KICK "STR, gch->pDest->ptszID, gch->ptszUID)!=-1) {
+ char *ptr = SkypeRcv("ALTER CHAT KICK", 2000);
+ if (ptr) {
+ if (strncmp(ptr, "ERROR", 5)) {
+ GCDEST gcd = { SKYPE_PROTONAME, gch->pDest->ptszID, GC_EVENT_KICK };
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.time = (DWORD)time(NULL);
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.ptszUID = gch->ptszUID;
+
+ CONTACTINFO ci = {0};
+ ci.cbSize = sizeof(ci);
+ ci.szProto = SKYPE_PROTONAME;
+ ci.dwFlag = CNF_DISPLAY | CNF_TCHAR;
+ ci.hContact = hContact;
+ if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal;
+ else gce.ptszNick=gce.ptszUID;
+
+ DBVARIANT dbv;
+ if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) {
+ gce.ptszStatus = dbv.ptszVal;
+ CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
+ RemChatContact (GetChat(gcd.ptszID), gch->ptszUID);
+ db_free(&dbv);
+ }
+ if (ci.pszVal) mir_free (ci.pszVal);
+ }
+ free (ptr);
+ }
+ }
+ LeaveCriticalSection(&m_GCMutex);
+}
+
+void SetChatTopic(const TCHAR *szChatId, TCHAR *szTopic, BOOL bSet)
+{
+ MCONTACT hContact = find_chat (szChatId);
+ char *szUTFTopic;
+
+ GCDEST gcd = { SKYPE_PROTONAME, szChatId, GC_EVENT_TOPIC };
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.ptszText = szTopic;
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.time = (DWORD)time (NULL);
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
+
+ gcd.iType = GC_EVENT_SETSBTEXT;
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
+
+ if (bSet) {
+#ifdef _UNICODE
+ szUTFTopic=(char*)make_utf8_string(szTopic);
+#else
+ if (utf8_encode(szTopic, &szUTFTopic)==-1) szUTFTopic = NULL;
+#endif
+ if (szUTFTopic) {
+ SkypeSend ("ALTER CHAT "STR" SETTOPIC %s", szChatId, szUTFTopic);
+ free (szUTFTopic);
+ }
+ testfor ("ALTER CHAT SETTOPIC", INFINITE);
+ }
+
+ if (hContact)
+ db_set_ts(hContact, SKYPE_PROTONAME, "Nick", szTopic);
+}
+
+
+int GCEventHook(WPARAM,LPARAM lParam) {
+ GCHOOK *gch = (GCHOOK*)lParam;
+ gchat_contacts *gc;
+
+ if (gch == NULL || gch->pDest == NULL)
+ return 0;
+ if (_stricmp(gch->pDest->pszModule, SKYPE_PROTONAME))
+ return 0;
+ gc = GetChat(gch->pDest->ptszID);
+
+ switch (gch->pDest->iType) {
+ case GC_SESSION_TERMINATE: {
+ MCONTACT hContact;
+
+ if (gc->mJoinedCount == 1) {
+ // switch back to normal session
+ // I don't know if this behaviour isn't a bit annoying, therefore, we
+ // don't do this now, until a user requests this feature :)
+
+ // open up srmm dialog when quit while 1 person left
+ // CallService(MS_MSG_SENDMESSAGE, (WPARAM)gc->mJoinedContacts[0].hContact, 0);
+
+ RemChatContact(gc, gc->mJoinedContacts[0].who);
+ }
+ // Delete Chatroom from Contact list, as we don't need it anymore...?
+ if (hContact = find_chat(gc->szChatName))
+ CallService(MS_DB_CONTACT_DELETE, hContact, 0);
+ RemChat(gc->szChatName);
+
+ break;
+ }
+ case GC_USER_MESSAGE:
+ if(gch->ptszText && _tcslen(gch->ptszText) > 0) {
+ DBVARIANT dbv, dbv2;
+ CCSDATA ccs = {0};
+ TCHAR *pEnd;
+
+ // remove the ending linebreak
+ for (pEnd = &gch->ptszText[_tcslen(gch->ptszText) - 1];
+ *pEnd==_T('\r') || *pEnd==_T('\n'); pEnd--) *pEnd=0;
+ // Send message to the chat-contact
+ if (ccs.hContact = find_chat(gch->pDest->ptszID)) {
+#ifdef _UNICODE
+ // If PREF_UTF is supported, just convert it to UTF8 and pass the buffer to PSS_MESSAGE
+ if (mirandaVersion >= 0x070000) {
+ ccs.lParam = (LPARAM)make_utf8_string(gch->ptszText);
+ ccs.wParam = PREF_UTF;
+ CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs);
+ free ((void*)ccs.lParam);
+ } else {
+ // Otherwise create this strange dual miranda-format
+ ccs.lParam = (LPARAM)calloc(3, _tcslen(gch->ptszText)+1);
+ wcstombs ((char*)ccs.lParam, gch->ptszText, _tcslen(gch->ptszText)+1);
+ _tcscpy ((TCHAR*)((char*)ccs.lParam+strlen((char*)ccs.lParam)+1), gch->ptszText);
+ ccs.wParam = PREF_UNICODE;
+ CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs);
+ free ((void*)ccs.lParam);
+ }
+#else
+ ccs.lParam = (LPARAM)gch->ptszText;
+ ccs.wParam = PREF_TCHAR;
+ CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs);
+#endif
+ }
+
+ // Add our line to the chatlog
+ GCDEST gcd = { gch->pDest->pszModule, gch->pDest->ptszID, 0 };
+ GCEVENT gce = { sizeof(gce), &gcd };
+ if ( _tcsncmp(gch->ptszText, _T("/me "), 4)==0 && _tcslen(gch->ptszText)>4) {
+ gce.ptszText = gch->ptszText+4;
+ gcd.iType = GC_EVENT_ACTION;
+ }
+ else {
+ gce.ptszText = gch->ptszText;
+ gcd.iType = GC_EVENT_MESSAGE;
+ }
+
+ if (db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv))
+ gce.ptszNick = TranslateT("Me");
+ else
+ gce.ptszNick = dbv.ptszVal;
+ db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2);
+ gce.ptszUID = dbv2.ptszVal;
+ gce.time = (DWORD)time(NULL);
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.bIsMe = TRUE;
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
+ if (dbv.pszVal) db_free(&dbv);
+ if (dbv2.pszVal) db_free(&dbv2);
+ }
+ break;
+ case GC_USER_CHANMGR:
+ InviteUser(gch->pDest->ptszID);
+ break;
+ case GC_USER_PRIVMESS: {
+ MCONTACT hContact = find_contactT(gch->ptszUID);
+ if (hContact) CallService(MS_MSG_SENDMESSAGE, hContact, 0);
+ break;
+
+ }
+ case GC_USER_LOGMENU:
+ switch(gch->dwData) {
+ case 10: InviteUser(gch->pDest->ptszID); break;
+ case 20: KillChatSession(gch->pDest); break;
+ case 30:
+ {
+ TCHAR *ptr, buf[MAX_BUF];
+
+ ptr = SkypeGetT ("CHAT", (TCHAR*)gch->pDest->ptszID, "TOPIC");
+ _tcscpy(buf, ptr);
+ free(ptr);
+ if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_INPUTBOX), NULL, InputBoxDlgProc, (LPARAM)&buf))
+ SetChatTopic(gch->pDest->ptszID, buf, TRUE);
+ break;
+ }
+ }
+ break;
+ case GC_USER_NICKLISTMENU: {
+ MCONTACT hContact = find_contactT(gch->ptszUID);
+
+ switch(gch->dwData) {
+ case 10:CallService(MS_USERINFO_SHOWDIALOG, hContact, 0); break;
+ case 20:CallService(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0); break;
+ case 30: KickUser(hContact, gch); break;
+ case 110: KillChatSession(gch->pDest); break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int __cdecl GCMenuHook(WPARAM,LPARAM lParam) {
+ GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam;
+ DBVARIANT dbv;
+ TCHAR* szInvite = TranslateT("&Invite user...");
+ TCHAR* szLeave = TranslateT("&Leave chat session");
+ TCHAR* szTopic = TranslateT("Set &Topic...");
+ TCHAR* szDetails = TranslateT("User &details");
+ TCHAR* szHistory = TranslateT("User &history");
+ TCHAR* szKick = TranslateT("&Kick user");
+
+ static struct gc_item Item_log[] = {
+ {NULL, 10, MENU_ITEM, FALSE},
+ {NULL, 30, MENU_ITEM, FALSE},
+ {NULL, 20, MENU_ITEM, FALSE}
+ };
+ static struct gc_item Item_nicklist_me[] = {
+ {NULL, 20, MENU_ITEM, FALSE},
+ {_T(""), 100, MENU_SEPARATOR, FALSE},
+ {NULL, 110, MENU_ITEM, FALSE}
+ };
+ static struct gc_item Item_nicklist[] = {
+ {NULL, 10, MENU_ITEM, FALSE},
+ {NULL, 20, MENU_ITEM, FALSE},
+ {NULL, 30, MENU_ITEM, FALSE}
+ };
+
+ Item_log[0].pszDesc = szInvite;
+ Item_log[1].pszDesc = szTopic;
+ Item_log[2].pszDesc = szLeave;
+ Item_nicklist_me[0].pszDesc = szHistory;
+ Item_nicklist_me[2].pszDesc = szLeave;
+ Item_nicklist[0].pszDesc = szDetails;
+ Item_nicklist[1].pszDesc = szHistory;
+ Item_nicklist[2].pszDesc = szKick;
+
+ LOG (("GCMenuHook started."));
+ if(gcmi) {
+ if (!_stricmp(gcmi->pszModule, SKYPE_PROTONAME)) {
+ switch (gcmi->Type)
+ {
+ case MENU_ON_LOG:
+ gcmi->nItems = sizeof(Item_log)/sizeof(Item_log[0]);
+ gcmi->Item = &Item_log[0];
+ LOG (("GCMenuHook: Items in log window: %d", gcmi->nItems));
+ break;
+ case MENU_ON_NICKLIST:
+ if (db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1;
+ if (!lstrcmp(dbv.ptszVal, gcmi->pszUID)) {
+ gcmi->nItems = sizeof(Item_nicklist_me)/sizeof(Item_nicklist_me[0]);
+ gcmi->Item = &Item_nicklist_me[0];
+ } else {
+ gchat_contacts *gcs = GetChat(gcmi->pszID);
+ gchat_contact *gc = gcs?GetChatContact(gcs, gcmi->pszUID):NULL;
+ gcmi->nItems = sizeof(Item_nicklist)/sizeof(Item_nicklist[0]);
+
+ Item_nicklist[2].bDisabled = FALSE;
+ if (gc && !gc->hContact)
+ {
+ gcmi->nItems -= 2;
+ gcmi->Item = &Item_nicklist[2];
+ }
+ else
+ gcmi->Item = &Item_nicklist[0];
+ /*
+ if (protocol<7) Item_nicklist[2].bDisabled = TRUE;
+ else {
+ TCHAR *szChatRole;
+ if (szChatRole = SkypeGetT ("CHAT", gcmi->pszID, "MYROLE")) {
+ if (_tcscmp(szChatRole, _T("MASTER")) && _tcscmp(szChatRole, _T("CREATOR")))
+ Item_nicklist[2].bDisabled = TRUE;
+ free (szChatRole);
+ }
+ }*/
+
+ }
+ db_free(&dbv);
+ break;
+ }
+ } else {LOG (("GCMenuHook: ERROR: Not our protocol."));}
+ } else {LOG (("GCMenuHook: ERROR: No gcmi"));}
+ LOG (("GCMenuHook: terminated."));
+ return 0;
+}
+
+INT_PTR GCOnLeaveChat(WPARAM wParam,LPARAM)
+{
+ MCONTACT hContact = (MCONTACT)wParam;
+ DBVARIANT dbv;
+
+ if (db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0)
+ {
+ GCDEST gcd = { SKYPE_PROTONAME, dbv.ptszVal, GC_EVENT_CONTROL };
+ KillChatSession(&gcd);
+ db_free(&dbv);
+ }
+ return 0;
+}
+
+INT_PTR GCOnJoinChat(WPARAM wParam,LPARAM)
+{
+ MCONTACT hContact = (MCONTACT)wParam;
+ DBVARIANT dbv;
+
+ if (db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0)
+ {
+ ChatStart (dbv.pszVal, FALSE);
+ db_free(&dbv);
+ }
+ return 0;
+}
+
+void GCInit(void)
+{
+ InitializeCriticalSection (&m_GCMutex);
+}
+
+void GCExit(void)
+{
+ DeleteCriticalSection (&m_GCMutex);
+
+ for (int i=0; i < chatcount; i++) {
+ free(chats[i].szChatName);
+ free(chats[i].mJoinedContacts);
+ }
+ free(chats);
+ chats = NULL;
+ chatcount = 0;
+}