diff options
author | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-10-12 14:53:57 +0000 |
---|---|---|
committer | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-10-12 14:53:57 +0000 |
commit | 3b55a62fdcb1f8222de3c2c8fbed530792c419a0 (patch) | |
tree | 5b2f628e847f61bb3e16f95ecaed6e187963362f /protocols/GTalkExt/src | |
parent | 1f9c986d82657f965462d289bf94aa012cf026fc (diff) |
GTalkExt, ICQ, IRC, Jabber: folders restructurization
git-svn-id: http://svn.miranda-ng.org/main/trunk@1890 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/GTalkExt/src')
24 files changed, 2839 insertions, 0 deletions
diff --git a/protocols/GTalkExt/src/GTalkExt.cpp b/protocols/GTalkExt/src/GTalkExt.cpp new file mode 100644 index 0000000000..7646bd10be --- /dev/null +++ b/protocols/GTalkExt/src/GTalkExt.cpp @@ -0,0 +1,91 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+// GTalkExt.cpp : Defines the exported functions for the DLL application.
+//***************************************************************************************
+
+#include "stdafx.h"
+#include "options.h"
+#include "handlers.h"
+#include "tipper_items.h"
+#include "avatar.h"
+#include "menu.h"
+
+
+int hLangpack;
+
+#define MIID_PLUGINIFACE {0x08B86253, 0xEC6E, 0x4d09, { 0xB7, 0xA9, 0x64, 0xAC, 0xDF, 0x06, 0x27, 0xB8 }}
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ PLUGIN_DESCRIPTION,
+ PLUGIN_VERSION_DWORD,
+ "Currently only mail notifications implemented",
+ "bems",
+ "bems@vingrad.ru",
+ COPYRIGHT_STRING,
+ "http://miranda-ng.org/",
+ UNICODE_AWARE, //doesn't replace anything built-in
+ MIID_PLUGINIFACE //{08B86253-EC6E-4d09-B7A9-64ACDF0627B8}
+};
+
+extern DWORD g_mirandaVersion;
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ g_mirandaVersion = mirandaVersion;
+ return &pluginInfo;
+}
+
+HANDLE hModulesLoaded = 0;
+HANDLE hAccListChanged = 0;
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ UnhookOptionsInitialization();
+ InitMenus(FALSE);
+ InitAvaUnit(FALSE);
+ if (hAccListChanged) UnhookEvent(hAccListChanged);
+ if (hModulesLoaded) UnhookEvent(hModulesLoaded);
+ return 0;
+}
+
+HICON g_hPopupIcon = 0;
+extern HINSTANCE hInst;
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+ g_hPopupIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_POPUP));
+
+
+ mir_getLP(&pluginInfo);
+ if (
+ !mir_getXI(&xi) ||
+ !(hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded)) ||
+ !(hAccListChanged = HookEvent(ME_PROTO_ACCLISTCHANGED, AccListChanged)) ||
+ !InitAvaUnit(TRUE) ||
+ !InitMenus(TRUE)
+ )
+ {Unload(); return 1;};
+
+ AddTipperItem();
+
+ return 0;
+}
\ No newline at end of file diff --git a/protocols/GTalkExt/src/avatar.cpp b/protocols/GTalkExt/src/avatar.cpp new file mode 100644 index 0000000000..1e55937a44 --- /dev/null +++ b/protocols/GTalkExt/src/avatar.cpp @@ -0,0 +1,212 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "stdafx.h"
+#include "avatar.h"
+#include "resources.h"
+#include "options.h"
+
+static const LPSTR AVA_FILE_NAME_FORMAT = "%s\\%s\\AvatarCache\\Jabber\\" SHORT_PLUGIN_NAME ".pseudoava.png";
+static const LPTSTR AVA_RES_TYPE = _T("PNG");
+static const LPSTR SRMM_MODULE_NAME = "SRMM";
+static const LPSTR SRMM_AVATAR_SETTING_NAME = "Avatar";
+
+static const int SET_AVATAR_INTERVAL = 2000;
+
+void ForceDir(LPSTR dir, int len)
+{
+ if (GetFileAttributesA(dir) != INVALID_FILE_ATTRIBUTES) return;
+ for (int i = len - 1; i >= 0; i--)
+ if ('\\' == dir[i]) {
+ dir[i] = 0;
+ __try {
+ ForceDir(dir, i);
+ }
+ __finally {
+ dir[i] = '\\';
+ }
+ CreateDirectoryA(dir, NULL);
+ }
+}
+
+void ForceFileDir(LPSTR file)
+{
+ for (int i = lstrlenA(file) - 1; i >= 0; i--)
+ if ('\\' == file[i]) {
+ file[i] = 0;
+ __try {
+ ForceDir(file, i);
+ }
+ __finally {
+ file[i] = '\\';
+ }
+ break;
+ }
+}
+
+LPSTR CreateAvaFile(HANDLE *hFile)
+{
+ char name[MAX_PATH + 2];
+ char path[MAX_PATH + 2];
+ char full[MAX_PATH + 2];
+
+ if (CallService(MS_DB_GETPROFILENAME, (WPARAM)sizeof(name), (LPARAM)&name))
+ return NULL;
+ for (int i = lstrlenA(name); i >= 0; i--)
+ if ('.' == name[i]) {
+ name[i] = 0;
+ break;
+ }
+
+ if (CallService(MS_DB_GETPROFILEPATH, (WPARAM)sizeof(path), (LPARAM)&path))
+ return NULL;
+ sprintf(&full[0], AVA_FILE_NAME_FORMAT, path, name);
+
+ ForceFileDir(&full[0]);
+
+ HANDLE h = 0;
+ __try {
+ h = CreateFileA(&full[0], GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (INVALID_HANDLE_VALUE == h) return NULL;
+
+ if (hFile) *hFile = h; else CloseHandle(h);
+ h = 0;
+ return _strdup(&full[0]);
+ }
+ __finally {
+ CloseHandle(h);
+ }
+}
+
+extern HINSTANCE hInst;
+
+BOOL SaveAvatar(HANDLE hFile)
+{
+ HRSRC hres = FindResource(hInst, MAKEINTRESOURCE(IDI_PSEUDOAVA), AVA_RES_TYPE);
+ if (!hres) return FALSE;
+
+ HGLOBAL hglob = LoadResource(hInst, hres);
+ if (!hglob) return FALSE;
+
+ PVOID p = LockResource(hglob);
+ if (!p) return FALSE;
+
+ DWORD l = SizeofResource(hInst, hres);
+ if (!l) return FALSE;
+
+ DWORD written;
+ if (!WriteFile(hFile, p, l, &written, NULL)) return FALSE;
+ return written == l;
+}
+
+struct AVACHANGED {
+ HANDLE hTimer;
+ HANDLE hContact;
+};
+
+VOID CALLBACK CallSetAvatar(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
+{
+ Thread_Push(0);
+ __try {
+ AVACHANGED *ach = (AVACHANGED*)lpParameter;
+ __try {
+ SetAvatar(ach->hContact);
+ DeleteTimerQueueTimer(NULL, ach->hTimer, NULL);
+ }
+ __finally {
+ free(ach);
+ }
+ }
+ __finally {
+ Thread_Pop();
+ }
+}
+
+int AvaChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (!lParam && DBGetContactSettingByte((HANDLE)wParam, SHORT_PLUGIN_NAME, PSEUDOCONTACT_FLAG, 0)) {
+ BOOL enqueued = FALSE;
+ AVACHANGED *ach = (AVACHANGED*)malloc(sizeof(AVACHANGED));
+ __try {
+ ach->hContact = (HANDLE)wParam;
+ enqueued = CreateTimerQueueTimer(&ach->hTimer, NULL, CallSetAvatar, ach, SET_AVATAR_INTERVAL, 0, WT_EXECUTEONLYONCE);
+ }
+ __finally {
+ if (!enqueued) free(ach);
+ }
+ }
+ return 0;
+}
+
+CRITICAL_SECTION g_csSetAvatar;
+HANDLE hAvaChanged = 0;
+BOOL initialized = FALSE;
+
+BOOL InitAvaUnit(BOOL init)
+{
+ if (init) {
+ hAvaChanged = HookEvent(ME_AV_AVATARCHANGED, AvaChanged);
+ InitializeCriticalSection(&g_csSetAvatar);
+ initialized = TRUE;
+ return hAvaChanged != 0;
+ }
+ else {
+ if (initialized) {
+ initialized = FALSE;
+ DeleteCriticalSection(&g_csSetAvatar);
+ }
+ if (hAvaChanged) {
+ UnhookEvent(hAvaChanged);
+ hAvaChanged = 0;
+ }
+ return TRUE;
+ }
+}
+
+void SetAvatar(HANDLE hContact)
+{
+ EnterCriticalSection(&g_csSetAvatar);
+ __try {
+ avatarCacheEntry *ava = (avatarCacheEntry*)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0);
+ if (ava && GetFileAttributes(&ava->szFilename[0]) != INVALID_FILE_ATTRIBUTES)
+ return;
+
+ HANDLE hFile;
+ LPSTR avaFile = CreateAvaFile(&hFile);
+ if (avaFile)
+ __try {
+ BOOL saved = SaveAvatar(hFile);
+ CloseHandle(hFile); hFile = 0;
+ if (saved){
+ if (ava) CallService(MS_AV_SETAVATAR, (WPARAM)hContact, (LPARAM)"");
+ CallService(MS_AV_SETAVATAR, (WPARAM)hContact, (LPARAM)avaFile);
+ DBWriteContactSettingString(hContact, SRMM_MODULE_NAME, SRMM_AVATAR_SETTING_NAME, avaFile);
+ }
+ }
+ __finally {
+ free(avaFile);
+ CloseHandle(hFile);
+ }
+ }
+ __finally {
+ LeaveCriticalSection(&g_csSetAvatar);
+ }
+}
\ No newline at end of file diff --git a/protocols/GTalkExt/src/avatar.h b/protocols/GTalkExt/src/avatar.h new file mode 100644 index 0000000000..f07631deff --- /dev/null +++ b/protocols/GTalkExt/src/avatar.h @@ -0,0 +1,25 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+void SetAvatar(HANDLE hContact);
+BOOL InitAvaUnit(BOOL init);
\ No newline at end of file diff --git a/protocols/GTalkExt/src/db.cpp b/protocols/GTalkExt/src/db.cpp new file mode 100644 index 0000000000..a1658dbdcf --- /dev/null +++ b/protocols/GTalkExt/src/db.cpp @@ -0,0 +1,100 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "StdAfx.h"
+#include "options.h"
+
+char *WtoA(LPCTSTR W)
+{
+ char* result = (char*)malloc(lstrlen(W) + 1);
+ __try {
+ int i;
+ for (i = 0; W[i]; i++) {
+ result[i] = W[i];
+ }
+
+ result[i] = 0;
+ }
+ __except(
+ free(result),
+ EXCEPTION_CONTINUE_SEARCH
+ ) {}
+ return result;
+}
+
+LPTSTR ReadJidSetting(LPCSTR name, LPCTSTR jid)
+{
+ char *ansiJid = WtoA(jid);
+ __try {
+ DBVARIANT dbv = {0};
+ __try {
+ if (DBGetContactSettingTString(0, name, ansiJid, &dbv))
+ {
+ LPTSTR result = (LPTSTR)malloc(2 * sizeof(TCHAR));
+ result[0] = '0';
+ result[1] = NULL;
+ return result;
+ }
+
+ return _tcsdup(dbv.ptszVal);
+ }
+ __finally {
+ DBFreeVariant(&dbv);
+ }
+ }
+ __finally {
+ free(ansiJid);
+ }
+
+ assert(false);
+ return NULL; // relax compiler
+}
+
+void WriteJidSetting(LPCSTR name, LPCTSTR jid, LPCTSTR setting)
+{
+ char *ansiJid = WtoA(jid);
+ __try {
+ DBWriteContactSettingTString(0, name, ansiJid, setting);
+ }
+ __finally {
+ free(ansiJid);
+ }
+}
+
+void RenewPseudocontactHandles()
+{
+ int count = 0;
+ PROTOACCOUNT **protos;
+ ProtoEnumAccounts(&count, &protos);
+ for (int i = 0; i < count; i++) {
+ DBDeleteContactSetting(0, protos[i]->szModuleName, PSEUDOCONTACT_LINK);
+ DBDeleteContactSetting(0, protos[i]->szModuleName, "GMailExtNotifyContact"); // remove this
+ }
+
+ HANDLE hContact = db_find_first();
+ while (hContact) {
+ if (DBGetContactSettingByte(hContact, SHORT_PLUGIN_NAME, PSEUDOCONTACT_FLAG, 0)) {
+ LPCSTR proto = (LPCSTR)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ DBWriteContactSettingDword(0, proto, PSEUDOCONTACT_LINK, (DWORD)hContact);
+ }
+ hContact = db_find_next(hContact);
+ };
+}
\ No newline at end of file diff --git a/protocols/GTalkExt/src/db.h b/protocols/GTalkExt/src/db.h new file mode 100644 index 0000000000..9db6cc94ce --- /dev/null +++ b/protocols/GTalkExt/src/db.h @@ -0,0 +1,31 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+#include "resources.h"
+
+static const LPSTR LAST_MAIL_TIME_FROM_JID = SHORT_PLUGIN_NAME ".LastMailTimeFromJid";
+static const LPSTR LAST_THREAD_ID_FROM_JID = SHORT_PLUGIN_NAME ".LastThreadIdFromJid";
+
+LPTSTR ReadJidSetting(LPCSTR name, LPCTSTR jid);
+void WriteJidSetting(LPCSTR name, LPCTSTR jid, LPCTSTR setting);
+char *WtoA(LPCTSTR W);
+void RenewPseudocontactHandles();
diff --git a/protocols/GTalkExt/src/dllmain.cpp b/protocols/GTalkExt/src/dllmain.cpp new file mode 100644 index 0000000000..e1097a3ea6 --- /dev/null +++ b/protocols/GTalkExt/src/dllmain.cpp @@ -0,0 +1,62 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "stdafx.h"
+#include "notifications.h"
+#include "options.h"
+#include "popups.h"
+
+HINSTANCE hInst = 0;
+
+DWORD itlsSettings = TLS_OUT_OF_INDEXES;
+DWORD itlsRecursion = TLS_OUT_OF_INDEXES;
+DWORD itlsPopupHook = TLS_OUT_OF_INDEXES;
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ if (((itlsSettings = TlsAlloc()) == TLS_OUT_OF_INDEXES) ||
+ ((itlsRecursion = TlsAlloc()) == TLS_OUT_OF_INDEXES) ||
+ ((itlsPopupHook = TlsAlloc()) == TLS_OUT_OF_INDEXES))
+ return FALSE;
+ break;
+
+ case DLL_THREAD_ATTACH:
+ TlsSetValue(itlsPopupHook,
+ (PVOID)SetWindowsHookEx(WH_CALLWNDPROCRET, PopupHookProc, NULL, GetCurrentThreadId()));
+ break;
+
+ case DLL_THREAD_DETACH:
+ UnhookWindowsHookEx((HHOOK)TlsGetValue(itlsPopupHook));
+ break;
+
+ case DLL_PROCESS_DETACH:
+ TlsFree(itlsSettings);
+ TlsFree(itlsRecursion);
+ TlsFree(itlsPopupHook);
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/protocols/GTalkExt/src/handlers.cpp b/protocols/GTalkExt/src/handlers.cpp new file mode 100644 index 0000000000..7bd814a802 --- /dev/null +++ b/protocols/GTalkExt/src/handlers.cpp @@ -0,0 +1,433 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "StdAfx.h"
+#include "handlers.h"
+#include "db.h"
+#include "notifications.h"
+#include "options.h"
+#include "popups.h"
+
+static const LPCTSTR JABBER_IQID = _T("mir_");
+static const LPCTSTR JABBER_IQID_FORMAT = _T("mir_%d");
+
+static const LPCTSTR NOTIFY_FEATURE_XMLNS = _T("google:mail:notify");
+static const LPCTSTR SETTING_FEATURE_XMLNS = _T("google:setting");
+static const LPCTSTR DISCOVERY_XMLNS = _T("http://jabber.org/protocol/disco#info");
+
+static const LPCTSTR MESSAGE_URL_FORMAT_STANDARD = _T("%s/#inbox/%x%08x");
+static const LPCTSTR MESSAGE_URL_FORMAT_HTML = _T("%s/h/?v=c&th=%x%08x");
+
+static const LPCTSTR ATTRNAME_TYPE = _T("type");
+static const LPCTSTR ATTRNAME_FROM = _T("from");
+static const LPCTSTR ATTRNAME_TO = _T("to");
+static const LPCTSTR ATTRNAME_URL = _T("url");
+static const LPCTSTR ATTRNAME_TID = _T("tid");
+static const LPCTSTR ATTRNAME_UNREAD = _T("unread");
+static const LPCTSTR ATTRNAME_XMLNS = _T("xmlns");
+static const LPCTSTR ATTRNAME_ID = _T("id");
+static const LPCTSTR ATTRNAME_TOTAL_MATCHED = _T("total-matched");
+static const LPCTSTR ATTRNAME_NAME = _T("name");
+static const LPCTSTR ATTRNAME_ADDRESS = _T("address");
+static const LPCTSTR ATTRNAME_RESULT_TIME = _T("result-time");
+static const LPCTSTR ATTRNAME_NEWER_THAN_TIME = _T("newer-than-time");
+static const LPCTSTR ATTRNAME_NEWER_THAN_TID = _T("newer-than-tid");
+static const LPCTSTR ATTRNAME_VALUE = _T("value");
+static const LPCTSTR ATTRNAME_VAR = _T("var");
+
+static const LPCTSTR IQTYPE_RESULT = _T("result");
+static const LPCTSTR IQTYPE_SET = _T("set");
+static const LPCTSTR IQTYPE_GET = _T("get");
+
+static const LPCTSTR NODENAME_MAILBOX = _T("mailbox");
+static const LPCTSTR NODENAME_QUERY = _T("query");
+static const LPCTSTR NODENAME_IQ = _T("iq");
+static const LPCTSTR NODENAME_USERSETTING = _T("usersetting");
+static const LPCTSTR NODENAME_MAILNOTIFICATIONS = _T("mailnotifications");
+static const LPCTSTR NODENAME_SUBJECT = _T("subject");
+static const LPCTSTR NODENAME_SNIPPET = _T("snippet");
+static const LPCTSTR NODENAME_SENDERS = _T("senders");
+static const LPCTSTR NODENAME_FEATURE = _T("feature");
+static const LPCTSTR NODENAME_NEW_MAIL = _T("new-mail");
+
+static const LPCTSTR SETTING_TRUE = _T("true");
+
+static const DWORD RESPONSE_TIMEOUT = 1000 * 60 * 60;
+static const DWORD TIMER_INTERVAL = 1000 * 60 * 2;
+
+XML_API xi = {0};
+
+#include <tchar.h>
+
+void FormatMessageUrl(LPCTSTR format, LPTSTR buf, LPCTSTR mailbox, LPCTSTR tid)
+{
+ ULARGE_INTEGER iTid; iTid.QuadPart = _tstoi64(tid);
+ int l = lstrlen(buf);
+ wsprintf(buf, format, mailbox, iTid.HighPart, iTid.LowPart);
+ assert(l >= lstrlen(buf));
+}
+
+void MakeUrlHex(LPTSTR url, LPCTSTR tid)
+{
+ ULARGE_INTEGER iTid; iTid.QuadPart = _tstoi64(tid);
+ LPTSTR tidInUrl = _tcsstr(url, tid);
+ LPTSTR trail = tidInUrl + lstrlen(tid);
+ wsprintf(tidInUrl, _T("%x%08x"), iTid.HighPart, iTid.LowPart);
+ wmemmove(tidInUrl + lstrlen(tidInUrl), trail, lstrlen(trail) + 1);
+}
+
+LPTSTR ExtractJid(LPCTSTR jidWithRes)
+{
+ int l;
+ for (l = 0; jidWithRes[l] && jidWithRes[l] != '/'; l++) {};
+ assert('/' == jidWithRes[l]);
+
+ LPTSTR result = (LPTSTR)malloc((l + 1) * sizeof(TCHAR));
+ __try {
+ memcpy(result, jidWithRes, l * sizeof(TCHAR));
+ result[l] = 0;
+ }
+ __except (
+ free(result),
+ EXCEPTION_CONTINUE_SEARCH
+ ) {};
+
+ return result;
+}
+
+BOOL TimerHandler(IJabberInterface *ji, HXML node, void *pUserData);
+
+BOOL InternalListHandler(IJabberInterface *ji, HXML node, LPCTSTR jid, LPCTSTR mailboxUrl)
+{
+ ULONGLONG maxTid = 0;
+ LPCTSTR sMaxTid = NULL;
+ int unreadCount = 0;
+ for (int i = 0; i < xi.getChildCount(node); i++) {
+ LPCTSTR sTid = xi.getAttrValue(xi.getChild(node, i), ATTRNAME_TID);
+ ULONGLONG tid = _tcstoui64(sTid, NULL, 10);
+ if (tid > maxTid) {
+ maxTid = tid;
+ sMaxTid = sTid;
+ }
+
+ HXML senders = xi.getChildByPath(xi.getChild(node, i), NODENAME_SENDERS, FALSE);
+ for (int j = 0; j < xi.getChildCount(senders); j++)
+ if (xi.getAttrValue(xi.getChild(senders, j), ATTRNAME_UNREAD)) {
+ unreadCount++;
+ break;
+ }
+ }
+
+ LPCSTR acc = GetJidAcc(jid);
+ if (!acc) return FALSE;
+
+ if (!unreadCount) {
+ SetupPseudocontact(jid, xi.getAttrValue(node, ATTRNAME_TOTAL_MATCHED), acc);
+ return TRUE;
+ }
+
+ DWORD settings = ReadNotificationSettings(acc);
+
+ if (unreadCount > 5) {
+ CloseNotifications(acc, mailboxUrl, jid, FALSE);
+ UnreadMailNotification(acc, jid, mailboxUrl, xi.getAttrValue(node, ATTRNAME_TOTAL_MATCHED));
+ }
+ else
+ for (int i = 0; i < xi.getChildCount(node); i++) {
+ MAIL_THREAD_NOTIFICATION mtn = {0};
+ HXML thread = xi.getChild(node, i);
+
+ mtn.subj = xi.getText(xi.getChildByPath(thread, NODENAME_SUBJECT, FALSE));
+ mtn.snip = xi.getText(xi.getChildByPath(thread, NODENAME_SNIPPET, FALSE));
+
+ int threadUnreadCount = 0;
+ HXML senders = xi.getChildByPath(thread, NODENAME_SENDERS, FALSE);
+ for (int j = 0; threadUnreadCount < SENDER_COUNT && j < xi.getChildCount(senders); j++) {
+ HXML sender = xi.getChild(senders, j);
+ if (xi.getAttrValue(sender, ATTRNAME_UNREAD)) {
+ mtn.senders[threadUnreadCount].name = xi.getAttrValue(sender, ATTRNAME_NAME);
+ mtn.senders[threadUnreadCount].addr = xi.getAttrValue(sender, ATTRNAME_ADDRESS);
+ threadUnreadCount++;
+ }
+ }
+
+ LPCTSTR url = xi.getAttrValue(thread, ATTRNAME_URL);
+ LPCTSTR tid = xi.getAttrValue(thread, ATTRNAME_TID);
+
+ if (ReadCheckbox(0, IDC_STANDARDVIEW, settings))
+ FormatMessageUrl(MESSAGE_URL_FORMAT_STANDARD, (LPTSTR)url, mailboxUrl, tid);
+ else
+ if (ReadCheckbox(0, IDC_HTMLVIEW, settings))
+ FormatMessageUrl(MESSAGE_URL_FORMAT_HTML, (LPTSTR)url, mailboxUrl, tid);
+ else
+ MakeUrlHex((LPTSTR)url, tid);
+
+ CloseNotifications(acc, url, jid, i);
+ UnreadThreadNotification(acc, jid, url, xi.getAttrValue(node, ATTRNAME_TOTAL_MATCHED), &mtn);
+ }
+
+ LPCTSTR time = xi.getAttrValue(node, ATTRNAME_RESULT_TIME);
+ WriteJidSetting(LAST_MAIL_TIME_FROM_JID, jid, time);
+ WriteJidSetting(LAST_THREAD_ID_FROM_JID, jid, sMaxTid);
+ return TRUE;
+}
+
+BOOL MailListHandler(IJabberInterface *ji, HXML node, void *pUserData)
+{
+ LPCTSTR jidWithRes = xi.getAttrValue(node, ATTRNAME_TO);
+ __try {
+ if (!node || lstrcmp(xi.getAttrValue(node, ATTRNAME_TYPE), IQTYPE_RESULT)) return TRUE;
+
+ LPCTSTR jid = xi.getAttrValue(node, ATTRNAME_FROM);
+ assert(jid);
+
+ node = xi.getChildByPath(node, NODENAME_MAILBOX, FALSE);
+ if (!node) return TRUE; // empty list
+
+ LPCTSTR url = xi.getAttrValue(node, ATTRNAME_URL);
+
+ return InternalListHandler(ji, node, jid, url);
+ }
+ __finally {
+ if (jidWithRes)
+ ji->Net()->AddTemporaryIqHandler(TimerHandler, JABBER_IQ_TYPE_RESULT, 0,
+ (PVOID)_tcsdup(jidWithRes), TIMER_INTERVAL);
+ // Never get a real result stanza. Results elapsed request after WAIT_TIMER_INTERVAL ms
+ }
+}
+
+void RequestMail(LPCTSTR jidWithRes, IJabberInterface *ji)
+{
+ HXML child = NULL;
+ HXML node = xi.createNode(NODENAME_IQ, NULL, FALSE);
+ __try {
+ xi.addAttr(node, ATTRNAME_TYPE, IQTYPE_GET);
+ xi.addAttr(node, ATTRNAME_FROM, jidWithRes);
+
+ UINT uID;
+ LPTSTR lastMailTime = NULL;
+ LPTSTR lastThreadId = NULL;
+ __try {
+ LPTSTR jid = ExtractJid(jidWithRes);
+ __try {
+ xi.addAttr(node, ATTRNAME_TO, jid);
+ lastMailTime = ReadJidSetting(LAST_MAIL_TIME_FROM_JID, jid);
+ lastThreadId = ReadJidSetting(LAST_THREAD_ID_FROM_JID, jid);
+ }
+ __finally {
+ free(jid);
+ }
+
+ LPTSTR id = (LPTSTR)malloc((_tcslen(JABBER_IQID) + 10 + 1) * sizeof(id[0])); // max int fits 10 chars
+ __try {
+ wsprintf(id, JABBER_IQID_FORMAT, uID = ji->Net()->SerialNext());
+ xi.addAttr(node, ATTRNAME_ID, id);
+ }
+ __finally {
+ free(id);
+ }
+
+ child = xi.addChild(node, NODENAME_QUERY, NULL);
+ xi.addAttr(child, ATTRNAME_XMLNS, NOTIFY_FEATURE_XMLNS);
+ xi.addAttr(child, ATTRNAME_NEWER_THAN_TIME, lastMailTime);
+ xi.addAttr(child, ATTRNAME_NEWER_THAN_TID, lastThreadId);
+ }
+ __finally {
+ if (lastMailTime) free(lastMailTime);
+ if (lastThreadId) free(lastThreadId);
+ }
+
+ IJabberNetInterface* piNet = ji->Net();
+ if ( piNet )
+ if (piNet->SendXmlNode(node))
+ piNet->AddTemporaryIqHandler(MailListHandler, JABBER_IQ_TYPE_RESULT, (int)uID, NULL, RESPONSE_TIMEOUT);
+ }
+ __finally {
+ if (child) xi.destroyNode(child);
+ if (node) xi.destroyNode(node);
+ }
+}
+
+BOOL TimerHandler(IJabberInterface *ji, HXML node, void *pUserData)
+{
+ __try {
+ assert(!node); // should not intercept real "mir_0" id
+ RequestMail((LPCTSTR)pUserData, ji);
+ return FALSE;
+ }
+ __finally {
+ free(pUserData);
+ }
+}
+
+BOOL NewMailHandler(IJabberInterface *ji, HXML node, void *pUserData)
+{
+ HXML response = xi.createNode(NODENAME_IQ, NULL, FALSE);
+ __try {
+ xi.addAttr(response, ATTRNAME_TYPE, IQTYPE_RESULT);
+
+ LPCTSTR attr = xi.getAttrValue(node, ATTRNAME_ID);
+ if (!attr) return FALSE;
+ xi.addAttr(response, ATTRNAME_ID, attr);
+
+ attr = xi.getAttrValue(node, ATTRNAME_FROM);
+ if (attr) xi.addAttr(response, ATTRNAME_TO, attr);
+
+ attr = xi.getAttrValue(node, ATTRNAME_TO);
+ if (!attr) return FALSE;
+ xi.addAttr(response, ATTRNAME_FROM, attr);
+
+ int bytesSent = ji->Net()->SendXmlNode(response);
+ RequestMail(attr, ji);
+ return bytesSent > 0;
+ }
+ __finally {
+ xi.destroyNode(response);
+ }
+}
+
+void SetNotificationSetting(LPCTSTR jidWithResource, IJabberInterface *ji)
+{
+ HXML child = NULL;
+ HXML node = xi.createNode(NODENAME_IQ, NULL, FALSE);
+ __try {
+ xi.addAttr(node, ATTRNAME_TYPE, IQTYPE_SET);
+ xi.addAttr(node, ATTRNAME_FROM, jidWithResource);
+
+ LPTSTR jid = ExtractJid(jidWithResource);
+ __try {
+ xi.addAttr(node, ATTRNAME_TO, jid);
+ }
+ __finally {
+ free(jid);
+ }
+
+ LPTSTR id = (LPTSTR)malloc((_tcslen(JABBER_IQID) + 10 + 1) * sizeof(id[0])); // max int fits 10 chars
+ __try {
+ wsprintf(id, JABBER_IQID_FORMAT, ji->Net()->SerialNext());
+ xi.addAttr(node, ATTRNAME_ID, id);
+ }
+ __finally {
+ free(id);
+ }
+
+ child = xi.addChild(node, NODENAME_USERSETTING, NULL);
+ xi.addAttr(child, ATTRNAME_XMLNS, SETTING_FEATURE_XMLNS);
+
+ child = xi.addChild(child, NODENAME_MAILNOTIFICATIONS, NULL);
+ xi.addAttr(child, ATTRNAME_VALUE, SETTING_TRUE);
+
+ ji->Net()->SendXmlNode(node);
+ }
+ __finally {
+ if (child) xi.destroyNode(child);
+ if (node) xi.destroyNode(node);
+ }
+}
+
+BOOL DiscoverHandler(IJabberInterface *ji, HXML node, void *pUserData)
+{
+ if (!node) return FALSE;
+
+ LPCTSTR jid = xi.getAttrValue(node, ATTRNAME_TO);
+ assert(jid);
+ node = xi.getChildByAttrValue(node, NODENAME_QUERY, ATTRNAME_XMLNS, DISCOVERY_XMLNS);
+
+ HXML child = xi.getChildByAttrValue(node, NODENAME_FEATURE, ATTRNAME_VAR, SETTING_FEATURE_XMLNS);
+ if (child) SetNotificationSetting(jid, ji);
+
+ child = xi.getChildByAttrValue(node, NODENAME_FEATURE, ATTRNAME_VAR, NOTIFY_FEATURE_XMLNS);
+ if (child) {
+ ji->Net()->AddIqHandler(NewMailHandler, JABBER_IQ_TYPE_SET, NOTIFY_FEATURE_XMLNS, NODENAME_NEW_MAIL);
+ RequestMail(jid, ji);
+ }
+
+ return FALSE;
+}
+
+extern DWORD itlsRecursion;
+
+BOOL SendHandler(IJabberInterface *ji, HXML node, void *pUserData)
+{
+ HXML queryNode = xi.getChildByAttrValue(node, NODENAME_QUERY, ATTRNAME_XMLNS, DISCOVERY_XMLNS);
+ if (!queryNode) return FALSE;
+ if (lstrcmp(xi.getName(node), NODENAME_IQ)) return FALSE;
+ if (lstrcmp(xi.getAttrValue(node, ATTRNAME_TYPE), IQTYPE_GET)) return FALSE;
+
+ if (TlsGetValue(itlsRecursion)) return FALSE;
+ TlsSetValue(itlsRecursion, (PVOID)TRUE);
+ __try {
+ UINT id = ji->Net()->SerialNext();
+ HXML newNode = xi.createNode(NODENAME_IQ, NULL, FALSE);
+ __try {
+ xi.addAttr(newNode, ATTRNAME_TYPE, IQTYPE_GET);
+ xi.addAttr(newNode, ATTRNAME_TO, xi.getAttrValue(node, ATTRNAME_TO));
+
+ LPTSTR idAttr = (LPTSTR)malloc(((int)_tcslen(JABBER_IQID) + 10) * sizeof(TCHAR));
+ __try {
+ wsprintf(idAttr, JABBER_IQID_FORMAT, id);
+ xi.addAttr(newNode, ATTRNAME_ID, idAttr);
+ }
+ __finally {
+ free(idAttr);
+ }
+
+ xi.addAttr(xi.addChild(newNode, NODENAME_QUERY, NULL), ATTRNAME_XMLNS, DISCOVERY_XMLNS);
+ ji->Net()->SendXmlNode(newNode);
+ }
+ __finally {
+ xi.destroyNode(newNode);
+ }
+
+ ji->Net()->AddTemporaryIqHandler(DiscoverHandler, JABBER_IQ_TYPE_RESULT, id, NULL, RESPONSE_TIMEOUT);
+ return FALSE;
+ }
+ __finally {
+ TlsSetValue(itlsRecursion, (PVOID)FALSE);
+ }
+}
+
+int AccListChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (PRAC_ADDED == wParam) {
+ IJabberInterface *japi = getJabberApi(((PROTOACCOUNT*)lParam)->szModuleName);
+ if (japi) japi->Net()->AddSendHandler(SendHandler);
+ }
+ return 0;
+}
+
+int ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ RenewPseudocontactHandles();
+ DetectPopupModule();
+
+ int count;
+ PROTOACCOUNT **protos;
+ ProtoEnumAccounts(&count, &protos);
+ for (int i = 0; i < count; i++) {
+ IJabberInterface *japi = getJabberApi(protos[i]->szModuleName);
+ if (japi) japi->Net()->AddSendHandler(SendHandler);
+ }
+
+ HookOptionsInitialization();
+
+ return 0;
+}
\ No newline at end of file diff --git a/protocols/GTalkExt/src/handlers.h b/protocols/GTalkExt/src/handlers.h new file mode 100644 index 0000000000..10ffa8cb81 --- /dev/null +++ b/protocols/GTalkExt/src/handlers.h @@ -0,0 +1,27 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+extern HANDLE hModulesLoaded;
+
+int ModulesLoaded(WPARAM wParam, LPARAM lParam);
+int AccListChanged(WPARAM wParam, LPARAM lParam);
\ No newline at end of file diff --git a/protocols/GTalkExt/src/inbox.cpp b/protocols/GTalkExt/src/inbox.cpp new file mode 100644 index 0000000000..53a4aa2fcb --- /dev/null +++ b/protocols/GTalkExt/src/inbox.cpp @@ -0,0 +1,402 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "stdafx.h"
+#include "inbox.h"
+#include "notifications.h"
+#include "db.h"
+#include "options.h"
+
+static const LPTSTR COMMON_GMAIL_HOST1 = _T("gmail.com");
+static const LPTSTR COMMON_GMAIL_HOST2 = _T("googlemail.com");
+
+static const LPSTR AUTH_REQUEST_URL = "https://www.google.com/accounts/ClientAuth";
+static const LPSTR AUTH_REQUEST_PARAMS = "Email=%s&Passwd=%s&"
+ "accountType=HOSTED_OR_GOOGLE&"
+ "skipvpage=true&"
+ "PersistentCookie=false";
+
+static const LPSTR ISSUE_TOKEN_REQUEST_URL = "https://www.google.com/accounts/IssueAuthToken";
+static const LPSTR ISSUE_TOKEN_REQUEST_PARAMS = "SID=%s&LSID=%s&"
+ "Session=true&"
+ "skipvpage=true&"
+ "service=gaia";
+
+static const LPSTR TOKEN_AUTH_URL = "https://www.google.com/accounts/TokenAuth?"\
+ "auth=%s&"
+ "service=mail&"
+ "continue=%s&"
+ "source=googletalk";
+
+
+static const NETLIBHTTPHEADER HEADER_URL_ENCODED = {"Content-Type", "application/x-www-form-urlencoded"};
+static const int HTTP_OK = 200;
+
+static const LPSTR SID_KEY_NAME = "SID=";
+static const LPSTR LSID_KEY_NAME = "LSID=";
+
+static const LPSTR LOGIN_PASS_SETTING_NAME = "LoginPassword";
+
+static const LPTSTR INBOX_URL_FORMAT = _T("https://mail.google.com/%s%s/#inbox");
+
+static const DWORD SIZE_OF_JABBER_OPTIONS = 243 * sizeof(DWORD);
+
+// 3 lines from netlib.h
+#define GetNetlibHandleType(h) (h?*(int*)h:NLH_INVALID)
+#define NLH_INVALID 0
+#define NLH_USER 'USER'
+
+char to_hex(char code) {
+ static char hex[] = "0123456789abcdef";
+ return hex[code & 15];
+}
+
+char *url_encode(char *str) {
+ char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
+ while (*pstr) {
+ if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == ',' || *pstr == '~')
+ *pbuf++ = *pstr;
+ else if (*pstr == ' ')
+ *pbuf++ = '+';
+ else
+ *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
+ pstr++;
+ }
+ *pbuf = '\0';
+ return buf;
+}
+
+LPSTR HttpPost(HANDLE hUser, LPSTR reqUrl, LPSTR reqParams)
+{
+ NETLIBHTTPREQUEST nlhr = {0};
+ nlhr.cbSize = sizeof(nlhr);
+ nlhr.requestType = REQUEST_POST;
+ nlhr.flags = NLHRF_GENERATEHOST | NLHRF_SMARTAUTHHEADER | NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMP | NLHRF_NODUMPHEADERS;
+ nlhr.szUrl = reqUrl;
+ nlhr.headers = (NETLIBHTTPHEADER*)&HEADER_URL_ENCODED;
+ nlhr.headersCount = 1;
+ nlhr.pData = reqParams;
+ nlhr.dataLength = lstrlenA(reqParams);
+
+ NETLIBHTTPREQUEST *pResp = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hUser, (LPARAM)&nlhr);
+ if (!pResp) return NULL;
+ __try {
+ if (HTTP_OK == pResp->resultCode)
+ return _strdup(pResp->pData);
+ else
+ return NULL;
+ }
+ __finally {
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)pResp);
+ }
+}
+
+LPSTR MakeRequest(HANDLE hUser, LPSTR reqUrl, LPSTR reqParamsFormat, LPSTR p1, LPSTR p2)
+{
+ LPSTR encodedP1 = url_encode(p1);
+ __try {
+ LPSTR encodedP2 = url_encode(p2);
+ __try {
+ LPSTR reqParams = (LPSTR)malloc(lstrlenA(reqParamsFormat) + 1 + lstrlenA(encodedP1) + lstrlenA(encodedP2));
+ __try {
+ sprintf(reqParams, reqParamsFormat, encodedP1, encodedP2);
+ return HttpPost(hUser, reqUrl, reqParams);
+ }
+ __finally {
+ free(reqParams);
+ }
+ }
+ __finally {
+ free(encodedP2);
+ }
+ }
+ __finally {
+ free(encodedP1);
+ }
+}
+
+LPSTR FindSid(LPSTR resp, LPSTR *LSID)
+{
+ LPSTR SID = strstr(resp, SID_KEY_NAME);
+ *LSID = strstr(resp, LSID_KEY_NAME);
+ if (!SID || !*LSID) return NULL;
+
+ if (SID - 1 == *LSID) SID = strstr(SID + 1, SID_KEY_NAME);
+ if (!SID) return NULL;
+
+ SID += lstrlenA(SID_KEY_NAME);
+ LPSTR term = strstr(SID, "\n");
+ if (term) term[0] = 0;
+
+ *LSID += lstrlenA(LSID_KEY_NAME);
+ term = strstr(*LSID, "\n");
+ if (term) term[0] = 0;
+
+ return SID;
+}
+
+void DoOpenUrl(LPSTR tokenResp, LPSTR url)
+{
+ LPSTR encodedUrl = url_encode(url);
+ __try {
+ LPSTR encodedToken = url_encode(tokenResp);
+ __try {
+ LPSTR composedUrl = (LPSTR)malloc(lstrlenA(TOKEN_AUTH_URL) + 1 + lstrlenA(encodedToken) + lstrlenA(encodedUrl));
+ __try {
+ sprintf(composedUrl, TOKEN_AUTH_URL, encodedToken, encodedUrl);
+ ShellExecuteA(0, NULL, composedUrl, NULL, NULL, SW_SHOW);
+ }
+ __finally {
+ free(composedUrl);
+ }
+ }
+ __finally {
+ free(encodedToken);
+ }
+ }
+ __finally {
+ free(encodedUrl);
+ }
+}
+
+BOOL AuthAndOpen(HANDLE hUser, LPSTR url, LPSTR mailbox, LPSTR pwd)
+{
+ LPSTR authResp = MakeRequest(hUser, AUTH_REQUEST_URL, AUTH_REQUEST_PARAMS, mailbox, pwd);
+ if (!authResp) return FALSE;
+
+ __try {
+ LPSTR LSID;
+ LPSTR SID = FindSid(authResp, &LSID);
+ LPSTR tokenResp = MakeRequest(hUser, ISSUE_TOKEN_REQUEST_URL, ISSUE_TOKEN_REQUEST_PARAMS, SID, LSID);
+ if (!tokenResp) return FALSE;
+
+ __try {
+ DoOpenUrl(tokenResp, url);
+ return TRUE;
+ }
+ __finally {
+ free(tokenResp);
+ }
+ }
+ __finally {
+ free(authResp);
+ }
+}
+
+struct OPEN_URL_HEADER {
+ LPSTR url;
+ LPSTR mailbox;
+ LPSTR pwd;
+ LPCSTR acc;
+};
+
+HANDLE FindNetUserHandle(LPCSTR acc)
+{
+ IJabberInterface *ji = getJabberApi(acc);
+ if (!ji) return NULL;
+
+ PBYTE m_psProto = *(PBYTE*)((PBYTE)ji + sizeof(*ji)); // see CJabberInterface in jabber_proto.h
+
+ PHANDLE pResult = (PHANDLE)(m_psProto + // see CJabberProto in jabber_proto.h
+ sizeof(PVOID) + // skip vtable ptr
+ sizeof(PVOID) + // skip m_ThreadInfo
+ SIZE_OF_JABBER_OPTIONS); // skip m_options
+
+ for (int i=0; i < 100; i++) {
+ __try {
+ if (GetNetlibHandleType(*pResult) == NLH_USER)
+ break;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER){
+ }
+ pResult++;
+ }
+
+ assert(GetNetlibHandleType(*pResult) == NLH_USER);
+ return *pResult;
+}
+
+unsigned __stdcall OpenUrlThread(OPEN_URL_HEADER* data)
+{
+ __try {
+ HANDLE hUser = FindNetUserHandle(data->acc);
+ if (!hUser || !AuthAndOpen(hUser, data->url, data->mailbox, data->pwd))
+ ShellExecuteA(0, NULL, data->url, NULL, NULL, SW_SHOW);
+ }
+ __finally {
+ free(data);
+ }
+ return 0;
+}
+
+void __forceinline DecryptString(LPSTR str, int len)
+{
+ for (--len; len >= 0; len--)
+ {
+ const char c = str[len] ^ 0xc3;
+ if (c) str[len] = c;
+ }
+}
+
+int GetMailboxPwd(LPCSTR acc, LPCTSTR mailbox, LPSTR *pwd, int buffSize)
+{
+ char buff[256];
+
+ DBCONTACTGETSETTING cgs;
+ DBVARIANT dbv;
+ cgs.szModule = acc;
+ cgs.szSetting = LOGIN_PASS_SETTING_NAME;
+ cgs.pValue = &dbv;
+ dbv.type = DBVT_ASCIIZ;
+ dbv.pszVal = &buff[0];
+ dbv.cchVal = sizeof(buff);
+ if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, 0, (LPARAM)&cgs))
+ return 0;
+
+ int result = dbv.cchVal;
+
+ if (pwd) {
+ if (buffSize < result + 1) result = buffSize - 1;
+ memcpy(*pwd, &buff, result + 1);
+ DecryptString(*pwd, result);
+ }
+
+ return result;
+}
+
+BOOL OpenUrlWithAuth(LPCSTR acc, LPCTSTR mailbox, LPCTSTR url)
+{
+ int pwdLen = GetMailboxPwd(acc, mailbox, NULL, 0);
+ if (!pwdLen++) return FALSE;
+
+ int urlLen = lstrlen(url) + 1;
+ int mailboxLen = lstrlen(mailbox) + 1;
+
+ OPEN_URL_HEADER *data = (OPEN_URL_HEADER*)malloc(sizeof(OPEN_URL_HEADER) + urlLen + mailboxLen + pwdLen);
+ __try {
+ data->url = (LPSTR)data + sizeof(OPEN_URL_HEADER);
+ LPSTR ansi = WtoA(url);
+ __try {
+ memcpy(data->url, ansi, urlLen);
+ }
+ __finally {
+ free(ansi);
+ }
+
+ data->mailbox = data->url + urlLen;
+ ansi = WtoA(mailbox);
+ __try {
+ memcpy(data->mailbox, ansi, mailboxLen);
+ }
+ __finally {
+ free(ansi);
+ }
+
+ data->pwd = data->mailbox + mailboxLen;
+ if (!GetMailboxPwd(acc, mailbox, &data->pwd, pwdLen)) return FALSE;
+
+ data->acc = acc;
+
+ if (HANDLE h = mir_forkthreadex((pThreadFuncEx)OpenUrlThread, data, NULL)) {
+ CloseHandle(h);
+ data = NULL;
+ }
+ else return FALSE;
+ }
+ __finally {
+ free(data);
+ }
+
+ return TRUE;
+}
+
+unsigned __stdcall ShellExecuteThread(PVOID param)
+{
+ __try {
+ ShellExecute(0, NULL, (LPTSTR)param, NULL, NULL, SW_SHOW);
+ }
+ __finally {
+ free(param);
+ }
+ return 0;
+}
+
+void StartShellExecuteThread(LPCTSTR url)
+{
+ LPTSTR urlCopy = _tcsdup(url);
+ __try {
+ if (HANDLE h = mir_forkthreadex(ShellExecuteThread, urlCopy, NULL)) {
+ CloseHandle(h);
+ urlCopy = NULL;
+ }
+ }
+ __finally {
+ free(urlCopy);
+ }
+}
+
+void OpenUrl(LPCSTR acc, LPCTSTR mailbox, LPCTSTR url)
+{
+ extern DWORD itlsSettings;
+ if (!ReadCheckbox(0, IDC_AUTHONMAILBOX, (DWORD)TlsGetValue(itlsSettings)) ||
+ !OpenUrlWithAuth(acc, mailbox, url))
+ StartShellExecuteThread(url);
+}
+
+LPTSTR CraftInboxUrl(LPTSTR jid)
+{
+ LPTSTR host = _tcsstr(jid, _T("@")) + 1;
+
+ LPTSTR result = (LPTSTR)malloc((lstrlen(INBOX_URL_FORMAT) + 1 + lstrlen(jid)) * sizeof(TCHAR));
+ __try {
+ if (lstrcmpi(host, COMMON_GMAIL_HOST1) && lstrcmpi(host, COMMON_GMAIL_HOST2))
+ wsprintf(result, INBOX_URL_FORMAT, _T("a/"), host); // hosted
+ else
+ wsprintf(result, INBOX_URL_FORMAT, NULL, _T("mail")); // common
+ }
+ __except (
+ free(result),
+ EXCEPTION_CONTINUE_SEARCH
+ ) {}
+
+ return result;
+}
+
+void OpenContactInbox(HANDLE hContact)
+{
+ LPSTR acc = (LPSTR)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (!acc) return;
+
+ DBVARIANT dbv;
+ if (!DBGetContactSettingTString(0, acc, "jid", &dbv))
+ __try {
+ LPTSTR url = CraftInboxUrl(dbv.ptszVal);
+ __try {
+ OpenUrl(acc, dbv.ptszVal, url);
+ }
+ __finally {
+ free(url);
+ }
+ }
+ __finally {
+ DBFreeVariant(&dbv);
+ }
+}
diff --git a/protocols/GTalkExt/src/inbox.h b/protocols/GTalkExt/src/inbox.h new file mode 100644 index 0000000000..0b00128ab9 --- /dev/null +++ b/protocols/GTalkExt/src/inbox.h @@ -0,0 +1,25 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+void OpenUrl(LPCSTR acc, LPCTSTR mailbox, LPCTSTR url);
+void OpenContactInbox(HANDLE hContact);
\ No newline at end of file diff --git a/protocols/GTalkExt/src/menu.cpp b/protocols/GTalkExt/src/menu.cpp new file mode 100644 index 0000000000..26c81a165f --- /dev/null +++ b/protocols/GTalkExt/src/menu.cpp @@ -0,0 +1,95 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "stdafx.h"
+#include "menu.h"
+#include "resources.h"
+#include "options.h"
+#include "inbox.h"
+
+static const LPSTR MS_GTALKEXT_OPENMAILBOX = SHORT_PLUGIN_NAME "/OpenMailbox";
+static const LPTSTR _T(OPEN_MAILBOX_ITEM_CAPTION) = _T("Open mailbox");
+
+HANDLE hOpenMailboxService = 0;
+HANDLE hOpenMailboxMenuItem = 0;
+HANDLE hOnPrebuildMenu = 0;
+
+INT_PTR OpenMailboxMenuHandler(WPARAM wParam, LPARAM lParam)
+{
+ if (DBGetContactSettingByte((HANDLE)wParam, SHORT_PLUGIN_NAME, PSEUDOCONTACT_FLAG, 0))
+ OpenContactInbox((HANDLE)wParam);
+ return 0;
+}
+
+int OnPrebuildMenu(WPARAM wParam, LPARAM lParam)
+{
+ CLISTMENUITEM cmi = {0};
+ cmi.cbSize = sizeof(cmi);
+ cmi.flags = CMIM_FLAGS;
+ if (!DBGetContactSettingByte((HANDLE)wParam, SHORT_PLUGIN_NAME, PSEUDOCONTACT_FLAG, 0))
+ cmi.flags |= CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hOpenMailboxMenuItem, (LPARAM)&cmi);
+ return 0;
+}
+
+BOOL InitMenus(BOOL init)
+{
+ if (init) {
+ hOpenMailboxService = (HANDLE)CreateServiceFunction(MS_GTALKEXT_OPENMAILBOX, OpenMailboxMenuHandler);
+ if (!hOpenMailboxService) {
+ InitMenus(FALSE);
+ return FALSE;
+ }
+
+ extern HICON g_hPopupIcon;
+
+ CLISTMENUITEM cmi = {0};
+ cmi.cbSize = sizeof(cmi);
+ cmi.flags = CMIF_TCHAR;
+ cmi.hIcon = g_hPopupIcon;
+ cmi.ptszName = _T(OPEN_MAILBOX_ITEM_CAPTION);
+ cmi.pszService = MS_GTALKEXT_OPENMAILBOX;
+ hOpenMailboxMenuItem = Menu_AddContactMenuItem(&cmi);
+
+ if (!hOpenMailboxMenuItem) {
+ InitMenus(FALSE);
+ return FALSE;
+ }
+
+ hOnPrebuildMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, OnPrebuildMenu);
+ if (!hOnPrebuildMenu) {
+ InitMenus(FALSE);
+ return FALSE;
+ }
+ }
+ else {
+ if (hOnPrebuildMenu) {
+ UnhookEvent(hOnPrebuildMenu);
+ hOnPrebuildMenu = 0;
+ }
+ if (hOpenMailboxService) {
+ DestroyServiceFunction(hOpenMailboxService);
+ hOpenMailboxService = 0;
+ }
+ }
+
+ return TRUE;
+}
\ No newline at end of file diff --git a/protocols/GTalkExt/src/menu.h b/protocols/GTalkExt/src/menu.h new file mode 100644 index 0000000000..c06457672a --- /dev/null +++ b/protocols/GTalkExt/src/menu.h @@ -0,0 +1,24 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+BOOL InitMenus(BOOL init);
\ No newline at end of file diff --git a/protocols/GTalkExt/src/notifications.cpp b/protocols/GTalkExt/src/notifications.cpp new file mode 100644 index 0000000000..9a1819a7f1 --- /dev/null +++ b/protocols/GTalkExt/src/notifications.cpp @@ -0,0 +1,414 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "StdAfx.h"
+#include "notifications.h"
+#include "db.h"
+#include "options.h"
+#include "avatar.h"
+#include "inbox.h"
+
+static const LPTSTR TEMP_WINDOW_CLASS_NAME = _T("AntiShittyFullscreenDetectionWindowClass");
+static const LPTSTR _T(NUMBER_EMAILS_MESSAGE) = _T("You've received an e-mail\n%s unread threads");
+
+static const LPTSTR PLUGIN_DATA_PROP_NAME = _T("{DB5CE833-C3AC-4851-831C-DDEBD9FA0508}");
+static const LPTSTR EVT_DELETED_HOOK_PROP_NAME = _T("{87CBD2BC-8806-413C-8FD5-1D61ABCA4AF8}");
+
+#define EVENT_DELETED_MSG RegisterWindowMessage(_T("{B9B00536-86A0-4BCE-B2FE-4ABD409C22AE}"))
+#define MESSAGE_CLOSEPOPUP RegisterWindowMessage(_T("{7A60EA87-3E77-41DF-8A69-59B147F0C9C6}"))
+
+static const LPSTR CLIST_MODULE_NAME = "CList";
+static const LPSTR CONTACT_DISPLAY_NAME_SETTING = "MyHandle";
+static const LPSTR STATUS_MSG_SETTING = "StatusMsg";
+static const LPSTR UNREAD_THREADS_SETTING = "UnreadThreads";
+
+struct POPUP_DATA_HEADER {
+ BOOL MarkRead;
+ HANDLE hDbEvent;
+ HANDLE hContact;
+ LPTSTR jid;
+ LPTSTR url;
+};
+
+extern DWORD itlsSettings;
+BOOL isOriginalPopups = FALSE;
+
+LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_NCCREATE:
+ return 1;
+
+ case WM_GETMINMAXINFO:
+ PMINMAXINFO info = (PMINMAXINFO)lParam;
+ info->ptMaxPosition.x = -100;
+ info->ptMaxPosition.y = -100;
+ info->ptMaxSize.x = 10;
+ info->ptMaxSize.y = 10;
+ info->ptMaxTrackSize.x = 10;
+ info->ptMaxTrackSize.y = 10;
+ info->ptMinTrackSize.x = 10;
+ info->ptMinTrackSize.y = 10;
+ return 0;
+ }
+ return DefWindowProc(wnd, msg, wParam, lParam);
+}
+
+LPCSTR GetJidAcc(LPCTSTR jid)
+{
+ int count = 0;
+ PROTOACCOUNT **protos;
+ ProtoEnumAccounts(&count, &protos);
+
+ DBVARIANT dbv;
+ for (int i = 0; i < count; i++)
+ if (getJabberApi(protos[i]->szModuleName))
+ if (!DBGetContactSettingTString(0, protos[i]->szModuleName, "jid", &dbv))
+ __try {
+ if (!lstrcmpi(jid, dbv.ptszVal)) return protos[i]->szModuleName;
+ }
+ __finally {
+ DBFreeVariant(&dbv);
+ }
+
+ return NULL;
+}
+
+void MarkEventRead(HANDLE hCnt, HANDLE hEvt)
+{
+ DWORD settings = (DWORD)TlsGetValue(itlsSettings);
+ if (ReadCheckbox(0, IDC_POPUPSENABLED, settings) &&
+ ReadCheckbox(0, IDC_PSEUDOCONTACTENABLED, settings) &&
+ ReadCheckbox(0, IDC_MARKEVENTREAD, settings) &&
+ (CallService(MS_DB_EVENT_MARKREAD, (WPARAM)hCnt, (LPARAM)hEvt) != (INT_PTR)-1))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hCnt, (LPARAM)hEvt);
+
+}
+
+int OnEventDeleted(WPARAM hContact, LPARAM hDbEvent, LPARAM wnd)
+{
+ if (DBGetContactSettingByte((HANDLE)hContact, SHORT_PLUGIN_NAME, PSEUDOCONTACT_FLAG, 0)) {
+ CallService(MS_CLIST_REMOVEEVENT, hContact, hDbEvent);
+ PostMessage((HWND)wnd, EVENT_DELETED_MSG, hContact, hDbEvent);
+ }
+
+ return 0;
+}
+
+LRESULT CALLBACK PopupProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (EVENT_DELETED_MSG == msg) {
+ POPUP_DATA_HEADER *ppdh = (POPUP_DATA_HEADER*)PUGetPluginData(wnd);
+ if ((HANDLE)lParam == ppdh->hDbEvent) ppdh->hDbEvent = NULL;
+ return 0;
+ }
+ else
+ if (MESSAGE_CLOSEPOPUP == msg) {
+ POPUP_DATA_HEADER *ppdh = (POPUP_DATA_HEADER*)PUGetPluginData(wnd);
+ ppdh->MarkRead = TRUE;
+ PUDeletePopUp(wnd);
+ }
+
+ switch (msg) {
+ case UM_INITPOPUP: {
+ POPUP_DATA_HEADER *ppdh = (POPUP_DATA_HEADER*)PUGetPluginData(wnd);
+ SetProp(wnd, PLUGIN_DATA_PROP_NAME, (HANDLE)ppdh);
+ SetProp(wnd, EVT_DELETED_HOOK_PROP_NAME,
+ HookEventParam(ME_DB_EVENT_DELETED, OnEventDeleted, (LPARAM)wnd));
+ return 0;
+ }
+
+ case UM_FREEPLUGINDATA: {
+ HANDLE hHook = GetProp(wnd, EVT_DELETED_HOOK_PROP_NAME);
+ RemoveProp(wnd, EVT_DELETED_HOOK_PROP_NAME);
+ UnhookEvent(hHook);
+
+ LPCSTR acc = NULL;
+ POPUP_DATA_HEADER *ppdh = (POPUP_DATA_HEADER*)PUGetPluginData(wnd);
+ __try {
+ if (ppdh->MarkRead && ppdh->hDbEvent && (acc = GetJidAcc(ppdh->jid))) {
+ ReadNotificationSettings(acc);
+ MarkEventRead(ppdh->hContact, ppdh->hDbEvent);
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)ppdh->hContact, (LPARAM)ppdh->hDbEvent);
+ }
+
+ }
+ __finally {
+ RemoveProp(wnd, PLUGIN_DATA_PROP_NAME);
+ free(ppdh);
+ }
+
+ return 0;
+ }
+
+ case WM_LBUTTONUP: {
+ LPCSTR acc = NULL;
+ POPUP_DATA_HEADER *ppdh = (POPUP_DATA_HEADER*)PUGetPluginData(wnd);
+ __try {
+ if (!(acc = GetJidAcc(ppdh->jid))) return 0;
+
+ ReadNotificationSettings(acc);
+ OpenUrl(acc, ppdh->jid, ppdh->url);
+ }
+ __finally {
+ CloseNotifications(acc, ppdh->url, ppdh->jid, TRUE);
+ }
+ return 0;
+ }
+
+ case WM_RBUTTONUP:
+ SendMessage(wnd, MESSAGE_CLOSEPOPUP, 0, 0);
+ return 0;
+ }
+ return DefWindowProc(wnd, msg, wParam, lParam);
+}
+
+HWND DoAddPopup(POPUPDATAT *data)
+{
+ WNDCLASS cls = {0};
+ cls.lpfnWndProc = WndProc;
+ cls.lpszClassName = TEMP_WINDOW_CLASS_NAME;
+
+ HWND result = 0;
+ HWND handle = 0;
+ __try {
+ if (ReadCheckbox(0, IDC_POPUPSINFULLSCREEN, (DWORD)TlsGetValue(itlsSettings))) {
+ RegisterClass(&cls);
+ handle = CreateWindowEx(WS_EX_TOOLWINDOW, TEMP_WINDOW_CLASS_NAME, NULL, WS_OVERLAPPED | WS_VISIBLE,
+ -100, -100, 10, 10, NULL, NULL, NULL, NULL);
+ if (handle) {
+ ShowWindow(handle, SW_MINIMIZE);
+ ShowWindow(handle, SW_RESTORE);
+ }
+ }
+ result = (HWND)CallService(MS_POPUP_ADDPOPUPT, (WPARAM) data, APF_RETURN_HWND);
+ }
+ __finally {
+ if (handle) DestroyWindow(handle);
+ }
+
+ return result;
+}
+
+void FormatPseudocontactDisplayName(LPTSTR buff, LPCTSTR jid, LPCTSTR unreadCount)
+{
+ if (lstrcmp(unreadCount, _T("0")))
+ wsprintf(buff, _T("%s [%s]"), jid, unreadCount);
+ else
+ wsprintf(buff, _T("%s"), jid);
+}
+
+HANDLE SetupPseudocontact(LPCTSTR jid, LPCTSTR unreadCount, LPCSTR acc, LPCTSTR displayName)
+{
+ HANDLE result = (HANDLE)DBGetContactSettingDword(0, acc, PSEUDOCONTACT_LINK, 0);
+ if (!result || !DBGetContactSettingByte(result, SHORT_PLUGIN_NAME, PSEUDOCONTACT_FLAG, 0)) {
+ result = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0);
+ DBWriteContactSettingDword(0, acc, PSEUDOCONTACT_LINK, (DWORD)result);
+ DBWriteContactSettingByte(result, SHORT_PLUGIN_NAME, PSEUDOCONTACT_FLAG, 1);
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)result, (LPARAM)acc);
+ }
+
+ SetAvatar(result);
+
+ BOOL allocateName = !displayName;
+ __try {
+ if (allocateName) {
+ displayName = (LPCTSTR)malloc((lstrlen(jid) + lstrlen(unreadCount) + 3 + 1) * sizeof(TCHAR));
+ FormatPseudocontactDisplayName((LPTSTR)displayName, jid, unreadCount);
+ }
+
+ DBWriteContactSettingTString(result, CLIST_MODULE_NAME, CONTACT_DISPLAY_NAME_SETTING, displayName);
+ }
+ __finally {
+ if (allocateName) free((PVOID)displayName);
+ }
+
+ DBWriteContactSettingTString(result, CLIST_MODULE_NAME, STATUS_MSG_SETTING, TranslateTS(MAIL_NOTIFICATIONS));
+ DBWriteContactSettingTString(result, SHORT_PLUGIN_NAME, UNREAD_THREADS_SETTING, unreadCount);
+
+ return result;
+}
+
+HANDLE AddCListNotification(HANDLE hContact, LPCSTR acc, POPUPDATAT *data, LPCTSTR jid, LPCTSTR url, LPCTSTR unreadCount)
+{
+ int lurl = (lstrlen(url) + 1) * sizeof(WCHAR);
+ LPSTR utf8 = (LPSTR)malloc(sizeof(data->lptzText) + sizeof(WCHAR) * 2 + lurl);
+ __try {
+ DBEVENTINFO dbei = {0};
+
+ dbei.cbBlob = WideCharToMultiByte(CP_UTF8, 0, &data->lptzText[0], -1, utf8, sizeof(data->lptzText), NULL, NULL) - 1;
+
+ if (utf8[dbei.cbBlob - 1] != 10) {
+ utf8[dbei.cbBlob++] = 13;
+ utf8[dbei.cbBlob++] = 10;
+ }
+
+ dbei.cbBlob += WideCharToMultiByte(CP_UTF8, 0, url, -1, utf8 + dbei.cbBlob, lurl, NULL, NULL);
+
+ dbei.pBlob = (PBYTE)utf8;
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = (LPSTR)acc;
+ dbei.timestamp = time(NULL);
+ dbei.flags = DBEF_UTF;
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ return (HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);
+ }
+ __finally {
+ free(utf8);
+ }
+}
+
+BOOL UsePopups()
+{
+ return ServiceExists(MS_POPUP_QUERY) &&
+ CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0) &&
+ ReadCheckbox(0, IDC_POPUPSENABLED, (DWORD)TlsGetValue(itlsSettings));
+}
+
+void ShowNotification(LPCSTR acc, POPUPDATAT *data, LPCTSTR jid, LPCTSTR url, LPCTSTR unreadCount)
+{
+ HANDLE hCnt = SetupPseudocontact(jid, unreadCount, acc, &data->lptzContactName[0]);
+ HANDLE hEvt = ReadCheckbox(0, IDC_PSEUDOCONTACTENABLED, (DWORD)TlsGetValue(itlsSettings))
+ ? AddCListNotification(hCnt, acc, data, jid, url, unreadCount) : NULL;
+
+ if (!UsePopups()) return;
+
+ extern HICON g_hPopupIcon;
+ data->lchIcon = g_hPopupIcon;
+ data->iSeconds = (int)DBGetContactSettingDword(0, SHORT_PLUGIN_NAME, TIMEOUT_SETTING, 0);
+ data->colorBack = (COLORREF)DBGetContactSettingDword(0, SHORT_PLUGIN_NAME, BACK_COLOR_SETTING, 0);
+ data->colorText = (COLORREF)DBGetContactSettingDword(0, SHORT_PLUGIN_NAME, TEXT_COLOR_SETTING, 0);
+ if (data->colorBack == data->colorText) {
+ data->colorBack = 0;
+ data->colorText = 0;
+ }
+
+ data->PluginWindowProc = PopupProc;
+ int lurl = (lstrlen(url) + 1) * sizeof(TCHAR);
+ int ljid = (lstrlen(jid) + 1) * sizeof(TCHAR);
+ data->PluginData = malloc(sizeof(POPUP_DATA_HEADER) + lurl + ljid);
+ __try {
+ POPUP_DATA_HEADER *ppdh = (POPUP_DATA_HEADER*)data->PluginData;
+
+ ppdh->MarkRead = FALSE;
+ ppdh->hContact = hCnt;
+ ppdh->hDbEvent = hEvt;
+
+ ppdh->jid = (LPTSTR)((PBYTE)ppdh + sizeof(*ppdh));
+ memcpy(ppdh->jid, jid, ljid);
+
+ ppdh->url = (LPTSTR)((PBYTE)ppdh->jid + ljid);
+ memcpy(ppdh->url, url, lurl);
+
+ HWND code = DoAddPopup(data);
+ if ((code == (HWND)-1) || (isOriginalPopups && !code))
+ return;
+ data->PluginData = NULL; // freed in popup wndproc
+ }
+ __finally {
+ free(data->PluginData);
+ }
+}
+
+void UnreadMailNotification(LPCSTR acc, LPCTSTR jid, LPCTSTR url, LPCTSTR unreadCount)
+{
+ POPUPDATAT data = {0};
+
+ FormatPseudocontactDisplayName(&data.lptzContactName[0], jid, unreadCount);
+ wsprintf(&data.lptzText[0], TranslateT(NUMBER_EMAILS_MESSAGE), unreadCount);
+
+ ShowNotification(acc, &data, jid, url, unreadCount);
+}
+
+void UnreadThreadNotification(LPCSTR acc, LPCTSTR jid, LPCTSTR url, LPCTSTR unreadCount, const MAIL_THREAD_NOTIFICATION *mtn)
+{
+ POPUPDATAT data = {0};
+
+ FormatPseudocontactDisplayName(&data.lptzContactName[0], jid, unreadCount);
+ LPTSTR senders = (LPTSTR)malloc(SENDER_COUNT * 100 * sizeof(TCHAR));
+ LPTSTR currSender = senders;
+ __try {
+ for (int i = 0; i < SENDER_COUNT && mtn->senders[i].addr; i++) {
+ wsprintf(currSender, _T(" %s <%s>\n"), mtn->senders[i].name, mtn->senders[i].addr);
+ currSender += lstrlen(currSender);
+ }
+
+ if (ReadCheckbox(0, IDC_ADDSNIP, (DWORD)TlsGetValue(itlsSettings)))
+ wsprintf(&data.lptzText[0], TranslateTS(FULL_NOTIFICATION_FORMAT), mtn->subj, senders, mtn->snip);
+ else
+ wsprintf(&data.lptzText[0], TranslateTS(SHORT_NOTIFICATION_FORMAT), mtn->subj, senders);
+ }
+ __finally {
+ free(senders);
+ }
+
+ ShowNotification(acc, &data, jid, url, unreadCount);
+}
+
+void ClearNotificationContactHistory(LPCSTR acc)
+{
+ HANDLE hEvent = 0;
+ HANDLE hContact = (HANDLE)DBGetContactSettingDword(0, acc, PSEUDOCONTACT_LINK, 0);
+ if (hContact && DBGetContactSettingByte(hContact, SHORT_PLUGIN_NAME, PSEUDOCONTACT_FLAG, 0))
+ while ((hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0)) &&
+ !CallService(MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hEvent)) {};
+}
+
+DWORD ReadNotificationSettings(LPCSTR acc)
+{
+ DWORD result = ReadCheckboxes(0, acc);
+ TlsSetValue(itlsSettings, (PVOID)result);
+ return result;
+}
+
+struct POPUP_IDENT_STRINGS {
+ LPCTSTR url;
+ LPCTSTR jid;
+};
+
+BOOL CALLBACK ClosePopupFunc(__in HWND hwnd, __in LPARAM lParam)
+{
+ DWORD pid = 0;
+ GetWindowThreadProcessId(hwnd, &pid);
+ if (pid != GetCurrentProcessId()) return TRUE;
+
+ POPUP_IDENT_STRINGS *ppis = (POPUP_IDENT_STRINGS*)lParam;
+ POPUP_DATA_HEADER *ppdh = (POPUP_DATA_HEADER*)GetProp(hwnd, PLUGIN_DATA_PROP_NAME);
+ if (!ppdh) return TRUE;
+
+ if (!lstrcmpi(ppis->url, ppdh->url) && !lstrcmpi(ppis->jid, ppdh->jid))
+ SendMessage(hwnd, MESSAGE_CLOSEPOPUP, 0, 0);
+
+ return TRUE;
+}
+
+void CloseNotifications(LPCSTR acc, LPCTSTR url, LPCTSTR jid, BOOL PopupsOnly)
+{
+ DWORD settings = (DWORD)TlsGetValue(itlsSettings);
+ if (acc &&
+ !PopupsOnly &&
+ ReadCheckbox(0, IDC_PSEUDOCONTACTENABLED, settings) &&
+ ReadCheckbox(0, IDC_CLEARPSEUDOCONTACTLOG, settings))
+ ClearNotificationContactHistory(acc);
+
+ POPUP_IDENT_STRINGS pis = {url, jid};
+ EnumWindows(ClosePopupFunc, (LPARAM)&pis);
+}
\ No newline at end of file diff --git a/protocols/GTalkExt/src/notifications.h b/protocols/GTalkExt/src/notifications.h new file mode 100644 index 0000000000..94d6e6353f --- /dev/null +++ b/protocols/GTalkExt/src/notifications.h @@ -0,0 +1,42 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+static const int SENDER_COUNT = 10;
+
+struct SENDER {
+ LPCTSTR name;
+ LPCTSTR addr;
+};
+
+struct MAIL_THREAD_NOTIFICATION {
+ LPCTSTR subj;
+ LPCTSTR snip;
+ SENDER senders[SENDER_COUNT];
+};
+
+void UnreadMailNotification(LPCSTR acc, LPCTSTR jid, LPCTSTR url, LPCTSTR unreadCount);
+void UnreadThreadNotification(LPCSTR acc, LPCTSTR jid, LPCTSTR url, LPCTSTR unreadCount, const MAIL_THREAD_NOTIFICATION *mtn);
+void CloseNotifications(LPCSTR acc, LPCTSTR url, LPCTSTR jid, BOOL PopupsOnly);
+DWORD ReadNotificationSettings(LPCSTR acc);
+HANDLE SetupPseudocontact(LPCTSTR jid, LPCTSTR unreadCount, LPCSTR acc, LPCTSTR displayName = NULL);
+LPCSTR GetJidAcc(LPCTSTR jid);
\ No newline at end of file diff --git a/protocols/GTalkExt/src/options.cpp b/protocols/GTalkExt/src/options.cpp new file mode 100644 index 0000000000..e64e23679c --- /dev/null +++ b/protocols/GTalkExt/src/options.cpp @@ -0,0 +1,297 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "stdafx.h"
+#include "options.h"
+
+static const LPTSTR ACCOUNT_PROP_NAME = _T("{BF447EBA-27AE-4DB7-893C-FC42A3F74D75}");
+static const LPTSTR DIALOG_INITIALIZED_PROP_NAME = _T("{5EE59FE5-679A-4A29-B0A1-03092E7AC20E}");
+
+static const LPTSTR POPUPS_OPTIONS_GROUP = _T("Popups");
+static const LPTSTR NETWORK_OPTIONS_GROUP = _T("Network");
+
+static const LPSTR NOTIFY_SETTINGS_FROM_MOD_NAME = SHORT_PLUGIN_NAME ".NotifySettingsFromModName";
+
+static const LPTSTR TEST_LETTER_SUBJECT = _T("Why C sucks");
+static const LPTSTR TEST_LETTER_INBOX = _T("brickstrace@gmail.com [1]");
+static const LPTSTR TEST_LETTER_SENDER = _T(" bems <bems@vingrad.ru>\n");
+static const LPTSTR TEST_LETTER_SNIP =
+ _T("* Primitive type system\n")
+ _T("* No overloading\n")
+ _T("* Limited possibility of data abstraction, polymorphism, subtyping and code reuse\n")
+ _T("* No metaprogramming except preprocessor macros\n")
+ _T("* No exceptions");
+
+HANDLE hOptionsHook = 0;
+extern HINSTANCE hInst;
+
+void CheckControlsEnabled(HWND wnd)
+{
+ BOOL PopupsEnabled = (SendMessage(GetDlgItem(wnd, IDC_POPUPSENABLED), BM_GETSTATE, 0, 0) & BST_CHECKED) == BST_CHECKED;
+ EnableWindow(GetDlgItem(wnd, IDC_POPUPSINFULLSCREEN), PopupsEnabled);
+ EnableWindow(GetDlgItem(wnd, IDC_POPUPSINFULLSCREENLABEL), PopupsEnabled);
+
+ BOOL CListEnabled = (SendMessage(GetDlgItem(wnd, IDC_PSEUDOCONTACTENABLED), BM_GETSTATE, 0, 0) & BST_CHECKED) == BST_CHECKED;
+ EnableWindow(GetDlgItem(wnd, IDC_CLEARPSEUDOCONTACTLOG), CListEnabled);
+ EnableWindow(GetDlgItem(wnd, IDC_SUPRESSFOREIGN), CListEnabled);
+
+ EnableWindow(GetDlgItem(wnd, IDC_MARKEVENTREAD), PopupsEnabled && CListEnabled);
+ EnableWindow(GetDlgItem(wnd, IDC_ADDSNIP), PopupsEnabled || CListEnabled);
+
+ EnableWindow(GetDlgItem(wnd, IDC_MAILBOXVIEWLABEL), PopupsEnabled || CListEnabled);
+ EnableWindow(GetDlgItem(wnd, IDC_UNKNOWNVIEW), PopupsEnabled || CListEnabled);
+ EnableWindow(GetDlgItem(wnd, IDC_STANDARDVIEW), PopupsEnabled || CListEnabled);
+ EnableWindow(GetDlgItem(wnd, IDC_HTMLVIEW), PopupsEnabled || CListEnabled);
+}
+
+BOOL ReadCheckbox(HWND wnd, int id, DWORD controls)
+{
+ BOOL result = ((controls >> (id - IDC_BASE)) & 1);
+ if (id != IDC_STANDARDVIEW && id != IDC_HTMLVIEW) result = !result;
+ if (wnd) Button_SetCheck(GetDlgItem(wnd, id), result);
+ return result;
+}
+
+DWORD ReadCheckboxes(HWND wnd, LPCSTR mod)
+{
+ DWORD controls = DBGetContactSettingDword(0, NOTIFY_SETTINGS_FROM_MOD_NAME, mod, 0);
+ ReadCheckbox(wnd, IDC_POPUPSENABLED, controls);
+ ReadCheckbox(wnd, IDC_PSEUDOCONTACTENABLED, controls);
+ ReadCheckbox(wnd, IDC_CLEARPSEUDOCONTACTLOG, controls);
+ ReadCheckbox(wnd, IDC_POPUPSINFULLSCREEN, controls);
+ ReadCheckbox(wnd, IDC_SUPRESSFOREIGN, controls);
+ ReadCheckbox(wnd, IDC_MARKEVENTREAD, controls);
+ ReadCheckbox(wnd, IDC_AUTHONMAILBOX, controls);
+ ReadCheckbox(wnd, IDC_ADDSNIP, controls);
+ ReadCheckbox(wnd, IDC_UNKNOWNVIEW, controls);
+ ReadCheckbox(wnd, IDC_STANDARDVIEW, controls);
+ ReadCheckbox(wnd, IDC_HTMLVIEW, controls);
+ return controls;
+}
+
+DWORD GetCheckboxSaveValue(HWND wnd, int id)
+{
+ BOOL val = Button_GetCheck(GetDlgItem(wnd, id));
+ if (id != IDC_STANDARDVIEW && id != IDC_HTMLVIEW) val = !val;
+ return val ? (1 << (id - IDC_BASE)) : 0;
+}
+
+void SaveControls(HWND wnd, LPCSTR mod)
+{
+ DWORD controls = GetCheckboxSaveValue(wnd, IDC_CLEARPSEUDOCONTACTLOG) |
+ GetCheckboxSaveValue(wnd, IDC_POPUPSINFULLSCREEN) |
+ GetCheckboxSaveValue(wnd, IDC_POPUPSENABLED) |
+ GetCheckboxSaveValue(wnd, IDC_PSEUDOCONTACTENABLED) |
+ GetCheckboxSaveValue(wnd, IDC_SUPRESSFOREIGN) |
+ GetCheckboxSaveValue(wnd, IDC_MARKEVENTREAD) |
+ GetCheckboxSaveValue(wnd, IDC_AUTHONMAILBOX) |
+ GetCheckboxSaveValue(wnd, IDC_ADDSNIP) |
+ GetCheckboxSaveValue(wnd, IDC_UNKNOWNVIEW) |
+ GetCheckboxSaveValue(wnd, IDC_STANDARDVIEW) |
+ GetCheckboxSaveValue(wnd, IDC_HTMLVIEW);
+
+ DBWriteContactSettingDword(0, NOTIFY_SETTINGS_FROM_MOD_NAME, mod, controls);
+}
+
+INT_PTR CALLBACK AccOptionsDlgProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ SetProp(wnd, ACCOUNT_PROP_NAME, (HANDLE)lParam);
+ TranslateDialogDefault(wnd);
+ ReadCheckboxes(wnd, (LPCSTR)lParam);
+ CheckControlsEnabled(wnd);
+ break;
+
+ case WM_CTLCOLORSTATIC:
+ if (GetDlgItem(wnd, IDC_WARNBAR) == (HWND)lParam)
+ return (INT_PTR)CreateSolidBrush(0x55AAFF); // orange
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_POPUPSENABLED:
+ case IDC_PSEUDOCONTACTENABLED:
+ if (HIWORD(wParam) == BN_CLICKED) CheckControlsEnabled(wnd);
+ // no break
+
+ case IDC_CLEARPSEUDOCONTACTLOG:
+ case IDC_POPUPSINFULLSCREEN:
+ case IDC_SUPRESSFOREIGN:
+ case IDC_MARKEVENTREAD:
+ case IDC_AUTHONMAILBOX:
+ case IDC_ADDSNIP:
+ case IDC_UNKNOWNVIEW:
+ case IDC_STANDARDVIEW:
+ case IDC_HTMLVIEW:
+ if (HIWORD(wParam) == BN_CLICKED) PropSheet_Changed(GetParent(wnd), wnd);
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (!((LPNMHDR)lParam)->idFrom && ((LPNMHDR)lParam)->code == PSN_APPLY)
+ SaveControls(wnd, (LPCSTR)GetProp(wnd, ACCOUNT_PROP_NAME));
+ break;
+ }
+ return 0;
+}
+
+void ShowTestPopup(HWND wnd)
+{
+ POPUPDATAT data = {0};
+ wsprintf(&data.lptzContactName[0], TEST_LETTER_INBOX);
+ wsprintf(&data.lptzText[0], TranslateTS(FULL_NOTIFICATION_FORMAT),
+ TEST_LETTER_SUBJECT, TEST_LETTER_SENDER, TEST_LETTER_SNIP);
+
+ int len = SendMessage(GetDlgItem(wnd, IDC_TIMEOUTEDIT), WM_GETTEXTLENGTH, 0, 0) + 1;
+ LPTSTR timeout = (LPTSTR)malloc(len * sizeof(TCHAR));
+ __try {
+ SendMessage(GetDlgItem(wnd, IDC_TIMEOUTEDIT), WM_GETTEXT, len, (LPARAM)timeout);
+ data.iSeconds = _ttoi(timeout);
+ }
+ __finally {
+ free(timeout);
+ }
+
+ extern HICON g_hPopupIcon;
+ data.lchIcon = g_hPopupIcon;
+ data.colorBack = (COLORREF)SendMessage(GetDlgItem(wnd, IDC_BACKCOLORPICKER), CPM_GETCOLOUR, 0, 0);
+ data.colorText = (COLORREF)SendMessage(GetDlgItem(wnd, IDC_TEXTCOLORPICKER), CPM_GETCOLOUR, 0, 0);
+ if (data.colorBack == data.colorText) {
+ data.colorBack = 0;
+ data.colorText = 0;
+ }
+ CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&data, 0);
+}
+
+INT_PTR CALLBACK PopupsOptionsDlgProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(wnd);
+ SendMessage(GetDlgItem(wnd, IDC_BACKCOLORPICKER), CPM_SETCOLOUR, 0,
+ (LPARAM)DBGetContactSettingDword(0, SHORT_PLUGIN_NAME, BACK_COLOR_SETTING, 0));
+ SendMessage(GetDlgItem(wnd, IDC_TEXTCOLORPICKER), CPM_SETCOLOUR, 0,
+ (LPARAM)DBGetContactSettingDword(0, SHORT_PLUGIN_NAME, TEXT_COLOR_SETTING, 0));
+
+ {LPTSTR timeout = (LPTSTR)malloc(11 * sizeof(TCHAR));
+ __try {
+ wsprintf(timeout, _T("%d"), DBGetContactSettingDword(0, SHORT_PLUGIN_NAME, TIMEOUT_SETTING, 0));
+ SendMessage(GetDlgItem(wnd, IDC_TIMEOUTEDIT), WM_SETTEXT, 0, (LPARAM)timeout);
+ }
+ __finally {
+ free(timeout);
+ }}
+
+ SetProp(wnd, DIALOG_INITIALIZED_PROP_NAME, (HANDLE)TRUE);
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_TESTBUTTON && HIWORD(wParam) == BN_CLICKED)
+ ShowTestPopup(wnd);
+
+ if (GetProp(wnd, DIALOG_INITIALIZED_PROP_NAME))
+ switch (LOWORD(wParam)) {
+ case IDC_BACKCOLORPICKER:
+ case IDC_TEXTCOLORPICKER:
+ if (HIWORD(wParam) == CPN_COLOURCHANGED) PropSheet_Changed(GetParent(wnd), wnd);
+ break;
+
+ case IDC_TIMEOUTEDIT:
+ if (HIWORD(wParam) == EN_CHANGE) PropSheet_Changed(GetParent(wnd), wnd);
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (!((LPNMHDR)lParam)->idFrom && ((LPNMHDR)lParam)->code == PSN_APPLY)
+ DBWriteContactSettingDword(0, SHORT_PLUGIN_NAME, BACK_COLOR_SETTING,
+ (DWORD)SendMessage(GetDlgItem(wnd, IDC_BACKCOLORPICKER), CPM_GETCOLOUR, 0, 0));
+ DBWriteContactSettingDword(0, SHORT_PLUGIN_NAME, TEXT_COLOR_SETTING,
+ (DWORD)SendMessage(GetDlgItem(wnd, IDC_TEXTCOLORPICKER), CPM_GETCOLOUR, 0, 0));
+
+ int len = SendMessage(GetDlgItem(wnd, IDC_TIMEOUTEDIT), WM_GETTEXTLENGTH, 0, 0) + 1;
+ LPTSTR timeout = (LPTSTR)malloc(len * sizeof(TCHAR));
+ __try {
+ SendMessage(GetDlgItem(wnd, IDC_TIMEOUTEDIT), WM_GETTEXT, len, (LPARAM)timeout);
+ DBWriteContactSettingDword(0, SHORT_PLUGIN_NAME, TIMEOUT_SETTING, _ttoi(timeout));
+ }
+ __finally {
+ free(timeout);
+ }
+ break;
+ }
+ return 0;
+}
+
+void AddPopupsPage(WPARAM wParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+ odp.cbSize = sizeof(odp);
+ odp.ptszTitle = MAIL_NOTIFICATIONS;
+ odp.pfnDlgProc = PopupsOptionsDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_POPUPSETTINGS);
+ odp.hInstance = hInst;
+ odp.ptszGroup = POPUPS_OPTIONS_GROUP;
+ odp.flags = ODPF_UNICODE | ODPF_USERINFOTAB;
+
+ Options_AddPage(wParam, &odp);
+}
+
+void AddAccPage(LPCTSTR acc, LPCSTR mod, WPARAM wParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+ odp.cbSize = sizeof(odp);
+ odp.pszTitle = (LPSTR)acc;
+ odp.pfnDlgProc = AccOptionsDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_MAILSETTINGS);
+ odp.hInstance = hInst;
+ odp.ptszGroup = NETWORK_OPTIONS_GROUP;
+ odp.flags = ODPF_UNICODE | ODPF_USERINFOTAB;
+ odp.ptszTab = MAIL_NOTIFICATIONS;
+ odp.dwInitParam = (LPARAM)mod;
+
+ Options_AddPage(wParam, &odp);
+}
+
+int OptionsInitialization(WPARAM wParam, LPARAM lParam)
+{
+ int count;
+ PROTOACCOUNT **accs;
+ CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&count, (LPARAM)&accs);
+ for (int i = 0; i < count; i++)
+ if (getJabberApi(accs[i]->szModuleName)) AddAccPage(accs[i]->tszAccountName, accs[i]->szModuleName, wParam);
+
+ if (ServiceExists(MS_POPUP_ADDPOPUPT)) AddPopupsPage(wParam);
+ return FALSE;
+}
+
+BOOL HookOptionsInitialization()
+{
+ return (hOptionsHook = HookEvent(ME_OPT_INITIALISE, OptionsInitialization)) != 0;
+}
+
+void UnhookOptionsInitialization()
+{
+ if (hOptionsHook) {
+ UnhookEvent(hOptionsHook);
+ hOptionsHook = 0;
+ }
+}
\ No newline at end of file diff --git a/protocols/GTalkExt/src/options.h b/protocols/GTalkExt/src/options.h new file mode 100644 index 0000000000..bc720e22ed --- /dev/null +++ b/protocols/GTalkExt/src/options.h @@ -0,0 +1,39 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+#include "resources.h"
+
+static const LPTSTR MAIL_NOTIFICATIONS = _T("GMail notifications");
+static const LPTSTR FULL_NOTIFICATION_FORMAT = _T("subject\n %s\nfrom\n%s\n%s\n");
+static const LPTSTR SHORT_NOTIFICATION_FORMAT = _T("subject\n %s\nfrom\n%s");
+
+static const LPSTR PSEUDOCONTACT_LINK = "GTalkExtNotifyContact";
+static const LPSTR PSEUDOCONTACT_FLAG = "IsNotifyContact";
+static const LPSTR BACK_COLOR_SETTING = "BackColor";
+static const LPSTR TEXT_COLOR_SETTING = "TextColor";
+static const LPSTR TIMEOUT_SETTING = "Timeout";
+
+BOOL HookOptionsInitialization();
+void UnhookOptionsInitialization();
+DWORD ReadCheckboxes(HWND wnd, LPCSTR mod);
+BOOL ReadCheckbox(HWND wnd, int id, DWORD controls);
\ No newline at end of file diff --git a/protocols/GTalkExt/src/popups.cpp b/protocols/GTalkExt/src/popups.cpp new file mode 100644 index 0000000000..99ab94470b --- /dev/null +++ b/protocols/GTalkExt/src/popups.cpp @@ -0,0 +1,104 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "stdafx.h"
+#include "popups.h"
+#include "options.h"
+
+static const LPTSTR YAPP_WND_CLASS1 = _T("YAPPYAPPWindowClass");
+static const LPTSTR YAPP_WND_CLASS2 = _T("YAPPWinClass");
+
+extern BOOL isOriginalPopups;
+
+LRESULT CALLBACK PopupHookProc(int nCode, WPARAM wParam, LPARAM lParam)
+{
+ PCWPRETSTRUCT cs = (PCWPRETSTRUCT)lParam;
+ if ((HC_ACTION == nCode) &&
+ (WM_CREATE == cs->message) &&
+ (-1 != cs->lResult) &&
+ ServiceExists(MS_POPUP_GETCONTACT)) {
+
+ // with YAPP we can't call MS_POPUP_GETCONTACT on a random window
+ TCHAR ClassName[32];
+ GetClassName(cs->hwnd, ClassName, sizeof(ClassName) / sizeof(TCHAR));
+ if (isOriginalPopups ||
+ !lstrcmp(YAPP_WND_CLASS1, ClassName) ||
+ !lstrcmp(YAPP_WND_CLASS2, ClassName)) {
+
+ HANDLE hContact = (HANDLE)CallService(MS_POPUP_GETCONTACT, (WPARAM)cs->hwnd, 0);
+ if (hContact != (HANDLE)-1 &&
+ hContact != (HANDLE)0x80000000 &&
+ DBGetContactSettingByte(hContact, SHORT_PLUGIN_NAME, PSEUDOCONTACT_FLAG, 0)) {
+ LPCSTR proto = (LPCSTR)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ DWORD checkboxes = ReadCheckboxes(0, proto);
+ if (ReadCheckbox(0, IDC_PSEUDOCONTACTENABLED, checkboxes) &&
+ ReadCheckbox(0, IDC_SUPRESSFOREIGN, checkboxes))
+ PostMessage(cs->hwnd, WM_CLOSE, 0, 0);
+ }
+ }
+ }
+ return CallNextHookEx(0, nCode, wParam, lParam);
+}
+
+typedef PLUGININFOEX* (MIRANDAPLUGININFOEX) (DWORD mirandaVersion);
+
+static GUID POPUP_GUID1 = {0x26a9125d, 0x7863, 0x4e01, {0xaf, 0xe, 0xd1, 0x4e, 0xf9, 0x5c, 0x50, 0x54}};
+static GUID POPUP_GUID2 = {0x26a9125d, 0x7863, 0x4e01, {0xaf, 0xe, 0xd1, 0x4e, 0xf9, 0x5c, 0x50, 0x53}};
+
+DWORD g_mirandaVersion = 0;
+
+BOOL IsOriginalPopupModule(HMODULE hMod)
+{
+ MIRANDAPLUGININFOEX *MirandaPluginInfoEx = (MIRANDAPLUGININFOEX*)GetProcAddress(hMod, "MirandaPluginInfoEx");
+ if (!MirandaPluginInfoEx) return FALSE;
+
+ PLUGININFOEX *PluginInfoEx = MirandaPluginInfoEx(g_mirandaVersion);
+ if (!PluginInfoEx) return FALSE;
+
+ GUID *guid1 = (GUID*)&PluginInfoEx->uuid;
+ GUID *guid2 = (GUID*)&POPUP_GUID1;
+ GUID *guid3 = (GUID*)&POPUP_GUID2;
+ return (IsEqualGUID(*guid1, *guid2) || IsEqualGUID(*guid1, *guid3));
+}
+
+extern BOOL isOriginalPopups;
+
+void DetectPopupModule()
+{
+ DWORD bytesNeeded;
+ if (!EnumProcessModules(GetCurrentProcess(), NULL, 0, &bytesNeeded))
+ return;
+
+ HMODULE *mods = (HMODULE*)malloc(bytesNeeded);
+ __try {
+ if (!EnumProcessModules(GetCurrentProcess(), mods, bytesNeeded, &bytesNeeded))
+ return;
+
+ for (DWORD i = 0; i < (bytesNeeded / sizeof(HMODULE)); i++)
+ if (IsOriginalPopupModule(mods[i])) {
+ isOriginalPopups = TRUE;
+ break;
+ }
+ }
+ __finally {
+ free(mods);
+ }
+}
diff --git a/protocols/GTalkExt/src/popups.h b/protocols/GTalkExt/src/popups.h new file mode 100644 index 0000000000..f9e142e0e6 --- /dev/null +++ b/protocols/GTalkExt/src/popups.h @@ -0,0 +1,25 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+LRESULT CALLBACK PopupHookProc(int nCode, WPARAM wParam, LPARAM lParam);
+void DetectPopupModule();
\ No newline at end of file diff --git a/protocols/GTalkExt/src/resources.h b/protocols/GTalkExt/src/resources.h new file mode 100644 index 0000000000..d72e34dcef --- /dev/null +++ b/protocols/GTalkExt/src/resources.h @@ -0,0 +1,67 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+#define SHORT_PLUGIN_NAME "GTalkExt"
+
+#define IDD_MAILSETTINGS 2001
+
+#define IDC_BASE 1001
+#define IDC_POPUPSENABLED IDC_BASE + 0
+#define IDC_PSEUDOCONTACTENABLED IDC_BASE + 1
+#define IDC_CLEARPSEUDOCONTACTLOG IDC_BASE + 2
+#define IDC_POPUPSINFULLSCREEN IDC_BASE + 3
+#define IDC_SUPRESSFOREIGN IDC_BASE + 4
+#define IDC_MARKEVENTREAD IDC_BASE + 5
+#define IDC_AUTHONMAILBOX IDC_BASE + 6
+#define IDC_ADDSNIP IDC_BASE + 7
+#define IDC_UNKNOWNVIEW IDC_BASE + 8
+#define IDC_STANDARDVIEW IDC_BASE + 9
+#define IDC_HTMLVIEW IDC_BASE + 10
+#define IDC_POPUPSINFULLSCREENLABEL IDC_BASE + 32
+#define IDC_NOTE IDC_BASE + 33
+#define IDC_WARNBAR IDC_BASE + 34
+#define IDC_AUTHONMAILBOXLABEL IDC_BASE + 35
+#define IDC_MAILBOXVIEWLABEL IDC_BASE + 36
+
+#define IDD_POPUPSETTINGS 2002
+
+#define IDC_BACKCOLORLABEL 1001
+#define IDC_BACKCOLORPICKER 1002
+#define IDC_TEXTCOLORLABEL 1003
+#define IDC_TEXTCOLORPICKER 1004
+#define IDC_TIMEOUTLABEL 1005
+#define IDC_TIMEOUTEDIT 1006
+#define IDC_DEFCOLORSLABEL 1007
+#define IDC_DEFTIMEOUTLABEL 1008
+#define IDC_TESTBUTTON 1009
+#define IDC_GROUP 1010
+
+#define IDI_POPUP 3001
+#define IDI_PSEUDOAVA 3002
+
+#define PLUGIN_VERSION_STRING "0.0.0.20 BETA"
+#define PLUGIN_FILE_VERSION 0, 0, 0, 20
+#define PLUGIN_VERSION_DWORD PLUGIN_MAKE_VERSION(0, 0, 0, 20)
+
+#define PLUGIN_DESCRIPTION "GTalk extensions for Jabber protocol"
+#define COPYRIGHT_STRING "2010, 11 bems"
diff --git a/protocols/GTalkExt/src/stdafx.cpp b/protocols/GTalkExt/src/stdafx.cpp new file mode 100644 index 0000000000..bdf32c5876 --- /dev/null +++ b/protocols/GTalkExt/src/stdafx.cpp @@ -0,0 +1,25 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/protocols/GTalkExt/src/stdafx.h b/protocols/GTalkExt/src/stdafx.h new file mode 100644 index 0000000000..d9712d7e9c --- /dev/null +++ b/protocols/GTalkExt/src/stdafx.h @@ -0,0 +1,71 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <assert.h>
+#include <malloc.h>
+#include <time.h>
+#include <stdlib.h>
+#include <tchar.h>
+
+// Windows Header Files:
+#include <windows.h>
+#include <windowsx.h>
+#include <PrSht.h>
+#include <shellapi.h>
+
+#include <psapi.h>
+#pragma comment(lib, "psapi.lib")
+
+#include <winsock.h>
+
+// Miranda&Plugins API
+#include <newpluginapi.h>
+#include <m_database.h>
+
+#pragma warning(push)
+#pragma warning(disable:4996)
+
+#include <m_system.h>
+#include <m_popup.h>
+#include <m_jabber.h>
+#include <m_langpack.h>
+#include <m_protosvc.h>
+#include <m_protomod.h>
+#include <m_options.h>
+#include <m_utils.h>
+#include <m_clist.h>
+#include <m_avatars.h>
+#include <m_netlib.h>
+#pragma warning(pop)
+
+#if _MSC_VER < 1400
+ #define _tstoi64 _ttoi
+ #define _tcstoui64(A,B,C) _ttoi(A)
+#endif
+
+#define WNDCLASS_COLOURPICKER _T("ColourPicker")
\ No newline at end of file diff --git a/protocols/GTalkExt/src/targetver.h b/protocols/GTalkExt/src/targetver.h new file mode 100644 index 0000000000..feb11bf4f2 --- /dev/null +++ b/protocols/GTalkExt/src/targetver.h @@ -0,0 +1,47 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+// The following macros define the minimum required platform. The minimum required platform
+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
+// your application. The macros work by enabling all features available on platform versions up to and
+// including the version specified.
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER // Specifies that the minimum required platform is Windows Vista.
+#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
+#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0.
+#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE.
+#endif
+
+#define MIRANDA_VER 0x0A00
diff --git a/protocols/GTalkExt/src/tipper_items.cpp b/protocols/GTalkExt/src/tipper_items.cpp new file mode 100644 index 0000000000..f09be10b32 --- /dev/null +++ b/protocols/GTalkExt/src/tipper_items.cpp @@ -0,0 +1,157 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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 "StdAfx.h"
+#include "tipper_items.h"
+#include "resources.h"
+
+static const int MAX_TIPPER_ITEM_PROP = 6 ;
+
+static const LPSTR VALUE_SETTING_PROP = "DIValue%d";
+static const LPSTR LABEL_SETTING_PROP = "DILabel%d";
+
+static const LPSTR LAST_WRITTEN_LABEL_SETTING = "LastWrittenTipperLabel";
+
+static LPSTR TipperItemProps[MAX_TIPPER_ITEM_PROP] = {
+ LABEL_SETTING_PROP,
+ "DILineAbove%d",
+ "DITipperVarsFirst%d",
+ "DIValNewline%d",
+ VALUE_SETTING_PROP,
+ "DIVisible%d"
+};
+
+static const LPSTR TIPPER_ITEMS_MOD_NAME = "Tipper_Items";
+static const LPSTR TIPPER_ITEM_COUNT_SETTING = "DINumValues";
+static const LPTSTR UNREAD_THREADS_RAW = _T("%raw:") _T(SHORT_PLUGIN_NAME) _T("/UnreadThreads%");
+static const LPTSTR UNREAD_THREADS_LABEL = _T("Unread threads:");
+
+void ShiftTipperSettings(LPSTR buff, int count, LPSTR format)
+{
+ for (int i = count; i > 0; i--) {
+ DBCONTACTWRITESETTING cws;
+ DBCONTACTGETSETTING cgs;
+ cgs.szModule = TIPPER_ITEMS_MOD_NAME;
+ sprintf(buff, format, i - 1);
+ cgs.szSetting = buff;
+ cgs.pValue = &cws.value;
+
+ if (CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&cgs)) break;
+ __try {
+ if (DBVT_ASCIIZ == cws.value.type) {
+ DBFreeVariant(&cws.value);
+ cws.value.type = DBVT_WCHAR;
+ if (CallService(MS_DB_CONTACT_GETSETTING_STR, 0, (LPARAM)&cgs)) break;
+ }
+
+ if (CallService(MS_DB_CONTACT_GETSETTING_STR, 0, (LPARAM)&cgs)) break;
+
+ cws.szModule = TIPPER_ITEMS_MOD_NAME;
+ sprintf(buff, format, i);
+ cws.szSetting = buff;
+ CallService(MS_DB_CONTACT_WRITESETTING, 0, (LPARAM)&cws);
+ }
+ __finally {
+ DBFreeVariant(&cws.value);
+ }
+ }
+}
+
+void SetLabelProp(int index, LPSTR setting)
+{
+ sprintf(setting, LABEL_SETTING_PROP, index);
+
+ DBVARIANT dbv1 = {0};
+ if (!DBGetContactSettingTString(0, TIPPER_ITEMS_MOD_NAME, setting, &dbv1))
+ __try {
+ DBVARIANT dbv2 = {0};
+ if (!DBGetContactSettingTString(0, SHORT_PLUGIN_NAME, LAST_WRITTEN_LABEL_SETTING, &dbv2))
+ __try {
+ if (!lstrcmp(dbv1.ptszVal, dbv2.ptszVal)) {
+ LPTSTR label = TranslateTS(UNREAD_THREADS_LABEL);
+ DBWriteContactSettingTString(0, SHORT_PLUGIN_NAME, LAST_WRITTEN_LABEL_SETTING, label);
+ DBWriteContactSettingTString(0, TIPPER_ITEMS_MOD_NAME, setting, label);
+ }
+ }
+ __finally {
+ DBFreeVariant(&dbv2);
+ }
+ }
+ __finally {
+ DBFreeVariant(&dbv1);
+ }
+}
+
+void AddTipperItem()
+{
+ unsigned short itemCount = DBGetContactSettingWord(0, TIPPER_ITEMS_MOD_NAME,
+ TIPPER_ITEM_COUNT_SETTING , unsigned short(-1));
+ if (unsigned short(-1) == itemCount) return;
+
+ int i, l = 0;
+ for (i = itemCount; i > 0; i /= 10) l++; // var setting path
+ l += 30; // const setting part
+
+ LPSTR setting = (LPSTR)malloc(l * sizeof(TCHAR));
+ __try {
+ for (i = 0; i < itemCount; i++) {
+ sprintf(setting, VALUE_SETTING_PROP, i);
+
+ DBVARIANT dbv = {0};
+ if (!DBGetContactSettingTString(0, TIPPER_ITEMS_MOD_NAME, setting, &dbv))
+ __try {
+ if (!lstrcmp(UNREAD_THREADS_RAW, dbv.ptszVal)) {
+ SetLabelProp(i, setting);
+ return;
+ }
+ }
+ __finally {
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ for (i = 0; i < MAX_TIPPER_ITEM_PROP; i++)
+ ShiftTipperSettings(setting, itemCount, TipperItemProps[i]);
+
+ #define WRITE_TIPPER_PROP(type, index, value)\
+ sprintf(setting, TipperItemProps[##index##], 0);\
+ DBWriteContactSetting##type##(0, TIPPER_ITEMS_MOD_NAME, setting, ##value##)
+
+ LPTSTR label = TranslateTS(UNREAD_THREADS_LABEL);
+
+ DBWriteContactSettingTString(0, SHORT_PLUGIN_NAME, LAST_WRITTEN_LABEL_SETTING, label);
+
+ WRITE_TIPPER_PROP(TString, 0, label);
+ WRITE_TIPPER_PROP(Byte, 1, 0);
+ WRITE_TIPPER_PROP(Byte, 2, 0);
+ WRITE_TIPPER_PROP(Byte, 3, 0);
+ WRITE_TIPPER_PROP(TString, 4, UNREAD_THREADS_RAW);
+ WRITE_TIPPER_PROP(Byte, 5, 1);
+
+ #undef WRITE_TIPPER_PROP
+ }
+ __finally {
+ free(setting);
+ }
+
+ DBWriteContactSettingWord(0, TIPPER_ITEMS_MOD_NAME,
+ TIPPER_ITEM_COUNT_SETTING, itemCount + 1);
+}
\ No newline at end of file diff --git a/protocols/GTalkExt/src/tipper_items.h b/protocols/GTalkExt/src/tipper_items.h new file mode 100644 index 0000000000..0b94d1fd24 --- /dev/null +++ b/protocols/GTalkExt/src/tipper_items.h @@ -0,0 +1,24 @@ +//***************************************************************************************
+//
+// Google Extension plugin for the Miranda IM's Jabber protocol
+// Copyright (c) 2011 bems@jabber.org, George Hazan (ghazan@jabber.ru)
+//
+// 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.
+//
+//***************************************************************************************
+
+#pragma once
+
+void AddTipperItem();
\ No newline at end of file |