diff options
Diffstat (limited to 'icqj_mod')
180 files changed, 48948 insertions, 0 deletions
diff --git a/icqj_mod/UI/askauthentication.c b/icqj_mod/UI/askauthentication.c new file mode 100644 index 0000000..0bde5d7 --- /dev/null +++ b/icqj_mod/UI/askauthentication.c @@ -0,0 +1,120 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/askauthentication.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-17 01:38:00 +0400 $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static BOOL CALLBACK AskAuthProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+int icq_RequestAuthorization(WPARAM wParam, LPARAM lParam)
+{
+ DialogBoxUtf(TRUE, hInst, MAKEINTRESOURCEA(IDD_ASKAUTH), NULL, AskAuthProc, (LPARAM)wParam);
+
+ return 0;
+}
+
+
+
+static BOOL CALLBACK AskAuthProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact;
+
+ switch (msg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ char str[MAX_PATH];
+
+ hContact = (HANDLE)lParam;
+
+ if (!hContact || !icqOnline)
+ EndDialog(hwndDlg, 0);
+
+ ICQTranslateDialog(hwndDlg);
+ SetWindowLong(hwndDlg, GWL_USERDATA, lParam);
+ SendDlgItemMessage(hwndDlg, IDC_EDITAUTH, EM_LIMITTEXT, (WPARAM)255, 0);
+ SetDlgItemTextUtf(hwndDlg, IDC_EDITAUTH, ICQTranslateUtfStatic("Please authorize me to add you to my contact list.", str));
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ DWORD dwUin;
+ uid_str szUid;
+ char* szReason;
+
+ hContact = (HANDLE)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ if (!icqOnline)
+ return TRUE;
+
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ return TRUE; // Invalid contact
+
+ szReason = GetDlgItemTextUtf(hwndDlg, IDC_EDITAUTH);
+ icq_sendAuthReqServ(dwUin, szUid, szReason);
+ SAFE_FREE(&szReason);
+ EndDialog(hwndDlg, 0);
+
+ return TRUE;
+ }
+ break;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+
+ default:
+ break;
+
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hwndDlg,0);
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/icqj_mod/UI/askauthentication.h b/icqj_mod/UI/askauthentication.h new file mode 100644 index 0000000..6de4bb4 --- /dev/null +++ b/icqj_mod/UI/askauthentication.h @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/askauthentication.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-17 01:38:00 +0400 $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+int icq_RequestAuthorization(WPARAM wParam, LPARAM lParam);
+
diff --git a/icqj_mod/UI/loginpassword.c b/icqj_mod/UI/loginpassword.c new file mode 100644 index 0000000..f603ed7 --- /dev/null +++ b/icqj_mod/UI/loginpassword.c @@ -0,0 +1,106 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/loginpassword.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-17 01:38:00 +0400 $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+BOOL CALLBACK LoginPasswdDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+void RequestPassword()
+{
+ DialogBox(hInst, MAKEINTRESOURCE(IDD_LOGINPW), NULL, LoginPasswdDlgProc);
+}
+
+
+BOOL CALLBACK LoginPasswdDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ char pszUIN[MAX_PATH];
+ char str[MAX_PATH];
+ DWORD dwUin;
+
+ ICQTranslateDialog(hwndDlg);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICQ)));
+ dwUin = ICQGetContactSettingUIN(NULL);
+ null_snprintf(pszUIN, 128, ICQTranslateUtfStatic("Enter a password for UIN %u:", str), dwUin);
+ SetDlgItemTextUtf(hwndDlg, IDC_INSTRUCTION, pszUIN);
+
+ SendDlgItemMessage(hwndDlg, IDC_LOGINPW, EM_LIMITTEXT, 10, 0);
+
+ CheckDlgButton(hwndDlg, IDC_SAVEPASS, ICQGetContactSettingByte(NULL, "RememberPass", 0));
+ }
+ break;
+
+ case WM_CLOSE:
+
+ EndDialog(hwndDlg, 0);
+ break;
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ gbRememberPwd = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SAVEPASS);
+ ICQWriteContactSettingByte(NULL, "RememberPass", gbRememberPwd);
+
+ GetDlgItemTextA(hwndDlg, IDC_LOGINPW, gpszPassword, sizeof(gpszPassword));
+
+ icq_login(gpszPassword);
+
+ EndDialog(hwndDlg, IDOK);
+ }
+ break;
+
+ case IDCANCEL:
+ {
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+
+ EndDialog(hwndDlg, IDCANCEL);
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/icqj_mod/UI/loginpassword.h b/icqj_mod/UI/loginpassword.h new file mode 100644 index 0000000..80c546e --- /dev/null +++ b/icqj_mod/UI/loginpassword.h @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/loginpassword.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-17 01:38:00 +0400 $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+void RequestPassword(void);
diff --git a/icqj_mod/UI/m_flash.h b/icqj_mod/UI/m_flash.h new file mode 100644 index 0000000..299bf3f --- /dev/null +++ b/icqj_mod/UI/m_flash.h @@ -0,0 +1,71 @@ +/*
+Miranda FlashAvatars Plugin
+Plugin support header file
+Copyright (C) 2006 Big Muscle
+
+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.
+*/
+
+// Service functions
+
+/**
+ WPARAM FLASHAVATAR* (hContact, hParentWindow)
+ LPARAM not used
+ */
+#define MS_FAVATAR_DESTROY "FlashAvatar/Destroy"
+
+/**
+ WPARAM FLASHAVATAR* (hContact, hParentWindow)
+ LPARAM not used
+ */
+#define MS_FAVATAR_MAKE "FlashAvatar/Make"
+
+/**
+ WPARAM FLASHAVATAR* (hContact, hParentWindow)
+ LPARAM LPRECT
+ */
+#define MS_FAVATAR_RESIZE "FlashAvatar/Resize"
+
+/**
+ WPARAM FLASHAVATAR* (hContact, hParentWindow)
+ LPARAM not used
+ */
+#define MS_FAVATAR_GETINFO "FlashAvatar/GetInfo"
+
+/**
+ WPARAM FLASHAVATAR* (hContact, hParentWindow)
+ LPARAM BSTR
+ */
+#define MS_FAVATAR_SETEMOFACE "FlashAvatar/SetEmoFace"
+
+// Avatar emotion faces
+#define AV_SMILE "smile"
+#define AV_SAD "sad"
+#define AV_LAUGH "laugh"
+#define AV_MAD "mad"
+#define AV_CRY "cry"
+#define AV_OFFLINE "offline"
+#define AV_BUSY "busy"
+#define AV_LOVE "love"
+#define AV_NORMAL "stam"
+
+typedef struct {
+ HANDLE hContact; // contact who flash avatar belongs to
+ HWND hWindow; // handle of flash avatar object
+ HWND hParentWindow; // handle of flash avatar's parent object
+ char* cUrl; // url of .swf file
+ int id; // unique number of plugin which wants to use avatar service
+ char* cProto; // contact's protocol
+} FLASHAVATAR;
diff --git a/icqj_mod/UI/userinfotab.c b/icqj_mod/UI/userinfotab.c new file mode 100644 index 0000000..7f109ae --- /dev/null +++ b/icqj_mod/UI/userinfotab.c @@ -0,0 +1,875 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/userinfotab.c,v $
+// Revision : $Revision: 3250 $
+// Last change on : $Date: 2006-06-30 02:08:42 +0400 (Пт, 30 июн 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Code for User details ICQ specific pages
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#include "m_flash.h"
+
+// icqj magic id
+#define FA_MAGIC_ID 0x4943516A
+
+
+extern WORD wListenPort;
+
+extern char* calcMD5Hash(char* szFile);
+extern char* MirandaVersionToString(char* szStr, int v, int m);
+
+extern char* nameXStatus[29];
+
+static BOOL CALLBACK IcqDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static void SetValue(HWND hwndDlg, int idCtrl, HANDLE hContact, char *szModule, char *szSetting, int special);
+
+#define SVS_NORMAL 0
+#define SVS_ZEROISUNSPEC 2
+#define SVS_IP 3
+#define SVS_SIGNED 6
+#define SVS_ICQVERSION 8
+#define SVS_TIMESTAMP 9
+#define SVS_STATUSID 10
+
+
+int OnDetailsInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+
+ if ((!IsICQContact((HANDLE)lParam)) && lParam)
+ return 0;
+
+ odp.cbSize = sizeof(odp);
+ odp.hIcon = NULL;
+ odp.hInstance = hInst;
+ odp.pfnDlgProc = IcqDlgProc;
+ odp.position = -1900000000;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_ICQ);
+ AddUserInfoPageUtf(&odp, wParam, gpszICQProtoName);
+
+ if (((lParam != 0) && gbAvatarsEnabled) || (gbSsiEnabled && gbAvatarsEnabled))
+ {
+ DWORD dwUin;
+ uid_str dwUid;
+
+ if (!ICQGetContactSettingUID((HANDLE)lParam, &dwUin, &dwUid))
+ { // Avatar page only for valid contacts
+ char *szAvtTitle;
+
+ odp.pfnDlgProc = AvatarDlgProc;
+ odp.position = -1899999998;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_AVATAR);
+ if (lParam)
+ szAvtTitle = "Avatar";
+ else
+ szAvtTitle = "%s Avatar";
+
+ AddUserInfoPageUtf(&odp, wParam, szAvtTitle);
+ }
+ }
+
+ InitChangeDetails(wParam, lParam);
+
+ return 0;
+}
+
+#define HM_DBCHANGE (WM_USER+200)
+#define HM_PROTOACK (WM_USER+201)
+#define TIMERID 1
+#define TIMEOUT_IGNORE 2
+//#define TIMEOUT_CAPS 3
+#define TIMEOUT_IP 4
+typedef struct infoflag_s
+{
+ char *Descr;
+ char *szSetting;
+ DWORD mask;
+} infoflag;
+
+
+struct UserData {
+ HANDLE hContact;
+ DWORD dwUin;
+ HANDLE hEventDbSettingChange;
+ int nTimer;
+ HANDLE hProtoAck;
+ DWORD dwCookie;
+};
+
+
+static infoflag infoflags[] =
+{
+ {"Hidden", NULL, WAS_FOUND},
+ {"WebAware", "WebAware", 0},
+ {"Auth", "AddAuth", 0},
+ {"UTF", NULL, CAPF_UTF},
+ {"MTN", NULL, CAPF_TYPING},
+ {"Xtraz", NULL, CAPF_XTRAZ},
+ {"ServerRelay", NULL, CAPF_SRV_RELAY},
+ {"AIMFile", NULL, CAPF_AIM_FILE},
+ {"Push2Talk", NULL, CAPF_PUSH2TALK},
+ {"ICQLite", NULL, CAPF_ICQ_LITE},
+ {"RTF", NULL, CAPF_RTF},
+ {"XTrazChat", NULL, CAPF_XTRAZ_CHAT},
+ {"VoiceChat", NULL, CAPF_VOICE_CHAT},
+ {"ICQDevil", NULL, CAPF_ICQ_DEVIL},
+ {"DirectConnect", NULL, CAPF_DIRECT},
+};
+static BOOL CALLBACK IcqDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct UserData *dat=(struct UserData*)GetWindowLong(hwndDlg,GWL_USERDATA);
+ switch (msg)
+ {
+
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ dat=(struct UserData*)malloc(sizeof(struct UserData));
+ SetWindowLong(hwndDlg,GWL_USERDATA,(LONG)dat);
+
+ dat->hEventDbSettingChange=HookEventMessage(ME_DB_CONTACT_SETTINGCHANGED,hwndDlg,HM_DBCHANGE);
+ dat->hContact=(HANDLE)lParam;
+ dat->nTimer=0;
+ dat->dwUin=ICQGetContactSettingDword(dat->hContact, UNIQUEIDSETTING, 0);
+ dat->hProtoAck=NULL;
+ dat->dwCookie=0;
+ if ((HANDLE)lParam == NULL)
+ {
+
+ ShowWindow(GetDlgItem(hwndDlg, IDC_FLAGS), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_FLAGSTEXT), SW_HIDE);
+ }
+ return TRUE;
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ case PSN_INFOCHANGED:
+ {
+ char* szProto;
+ HANDLE hContact = (HANDLE)((LPPSHNOTIFY)lParam)->lParam;
+WORD wStatus = ICQGetContactSettingWord(hContact, "Status", 0);
+char str[128] = {0};
+int i;
+ if (hContact == NULL)
+ szProto = gpszICQProtoName;
+ else{
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ }
+ if (szProto == NULL)
+ break;
+
+ SetValue(hwndDlg, IDC_UIN, hContact, szProto, UNIQUEIDSETTING, SVS_NORMAL);
+ SetValue(hwndDlg, IDC_ONLINESINCE, hContact, szProto, "LogonTS", SVS_TIMESTAMP);
+ SetValue(hwndDlg, IDC_IDLETIME, hContact, szProto, "IdleTS", SVS_TIMESTAMP);
+ SetValue(hwndDlg, IDC_IP, hContact, szProto, "IP", SVS_IP);
+ SetValue(hwndDlg, IDC_REALIP, hContact, szProto, "RealIP", SVS_IP);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_GETSTATUS),(ASD)?SW_SHOW:SW_HIDE);
+ //ShowWindow(GetDlgItem(hwndDlg,IDC_GETCAPS),(wStatus != ID_STATUS_OFFLINE)?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_RETRIEVE),(wStatus != ID_STATUS_OFFLINE)?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_IGNORECHECK), TRUE);//,(wStatus != ID_STATUS_OFFLINE)?SW_SHOW:SW_HIDE);
+ for (i=0; i < sizeof(infoflags)/sizeof(infoflags[0]); i++)
+ {
+ if ((infoflags[i].szSetting && ICQGetContactSettingByte(hContact, infoflags[i].szSetting,0))
+ || (infoflags[i].szSetting == NULL && CheckContactCapabilities(hContact, infoflags[i].mask)))
+ mir_snprintf(str, sizeof(str), (str[0]==0)?"%s%s":"%s, %s", str, Translate(infoflags[i].Descr));
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FLAGSTEXT), (str[0] != 0));
+ if (str[0]==0)
+ SetDlgItemText(hwndDlg, IDC_FLAGSTEXT, ICQTranslate("<not specified>"));
+ else
+ SetDlgItemText(hwndDlg, IDC_FLAGSTEXT, str);
+ // Gray flags if miranda offline
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_FLAGSTEXT), GWL_USERDATA, (!icqOnline && str[0] != 0));
+ if (hContact)
+ {
+ SetValue(hwndDlg, IDC_PORT, hContact, szProto, "UserPort", SVS_ZEROISUNSPEC);
+ SetValue(hwndDlg, IDC_VERSION, hContact, szProto, "Version", SVS_ICQVERSION);
+ SetValue(hwndDlg, IDC_MIRVER, hContact, szProto, "MirVer", SVS_ZEROISUNSPEC);
+ ICQWriteContactSettingDword(hContact, "TickTS", 0);
+ SetValue(hwndDlg, IDC_SYSTEMUPTIME, hContact, szProto, "TickTS", SVS_TIMESTAMP);
+ SetValue(hwndDlg, IDC_STATUS, hContact, szProto, "Status", SVS_STATUSID);
+ }
+ else
+ {
+ char str[MAX_PATH];
+
+ SetValue(hwndDlg, IDC_PORT, hContact, (char*)DBVT_WORD, (char*)wListenPort, SVS_ZEROISUNSPEC);
+ SetValue(hwndDlg, IDC_VERSION, hContact, (char*)DBVT_WORD, (char*)ICQ_VERSION, SVS_ICQVERSION);
+ SetValue(hwndDlg, IDC_MIRVER, hContact, (char*)DBVT_ASCIIZ, MirandaVersionToString(str, ICQ_PLUG_VERSION, MIRANDA_VERSION), SVS_ZEROISUNSPEC);
+ SetDlgItemTextUtf(hwndDlg, IDC_SUPTIME, ICQTranslateUtfStatic("Member since:", str));
+ SetValue(hwndDlg, IDC_SYSTEMUPTIME, hContact, szProto, "MemberTS", SVS_TIMESTAMP);
+ SetValue(hwndDlg, IDC_STATUS, hContact, (char*)DBVT_WORD, (char*)gnCurrentStatus, SVS_STATUSID);
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDCANCEL:
+ SendMessage(GetParent(hwndDlg),msg,wParam,lParam);
+ break;
+
+ case IDC_GETSTATUS:
+ if (icqOnline)
+ icq_GetUserStatus(dat->hContact, 1);
+ break;
+
+ case IDC_RETRIEVE:
+ if (icqOnline && dat->dwUin)
+ {
+
+ int wMessageType = 0;
+
+ switch(ICQGetContactSettingWord(dat->hContact, "Status",ID_STATUS_OFFLINE))
+ {
+ case ID_STATUS_OFFLINE:
+ break;
+ case ID_STATUS_NA:
+ wMessageType = MTYPE_AUTONA;
+ break;
+ case ID_STATUS_OCCUPIED:
+ wMessageType = MTYPE_AUTOBUSY;
+ break;
+ case ID_STATUS_DND:
+ wMessageType = MTYPE_AUTODND;
+ break;
+ case ID_STATUS_FREECHAT:
+ wMessageType = MTYPE_AUTOFFC;
+ break;
+ case ID_STATUS_AWAY:
+ default:
+ wMessageType = MTYPE_AUTOAWAY;
+ break;
+ }
+
+ icq_sendGetAwayMsgServ(dat->dwUin, wMessageType, (WORD)(ICQGetContactSettingWord(dat->hContact, "Version", 0)==9?9:ICQ_VERSION));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RETRIEVE), FALSE);
+ SetTimer(hwndDlg, TIMEOUT_IP, 10000, NULL);
+
+ }
+ break;
+
+ case IDC_IGNORECHECK:
+ if (icqOnline &&
+ ICQGetContactSettingWord(dat->hContact, "Status", 0) != ID_STATUS_OFFLINE)
+ {
+ message_cookie_data* pCookieData;
+
+ if (!dat->hProtoAck)
+ dat->hProtoAck = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_PROTOACK);
+
+ SetDlgItemText(hwndDlg, IDC_IGNORE, Translate("Checking..."));
+
+ pCookieData = malloc(sizeof(message_cookie_data));
+ pCookieData->bMessageType = MTYPE_PLAIN;
+ pCookieData->nAckType = ACKTYPE_SERVER;
+ dat->dwCookie = icq_SendChannel4Message(dat->dwUin, 0, 0, "", pCookieData);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IGNORECHECK), FALSE);
+ SetTimer(hwndDlg, TIMEOUT_IGNORE, 10000, NULL);
+ }
+ break;
+ }
+ break;
+ case HM_DBCHANGE:
+ {
+ DBCONTACTWRITESETTING *cws=(DBCONTACTWRITESETTING*)lParam;
+
+ if (!dat->nTimer &&
+ (cws->szModule != NULL) &&
+ (dat->hContact == (HANDLE)wParam) &&
+ !strcmp(cws->szModule, gpszICQProtoName))
+ {
+ dat->nTimer = 1;
+ SetTimer(hwndDlg, TIMERID, 1000, NULL);
+ }
+ }
+ break;
+
+ case HM_PROTOACK:
+ {
+ ACKDATA *ack = (ACKDATA*)lParam;
+
+ if (!ack || !ack->szModule ||
+ ack->hProcess != (HANDLE)dat->dwCookie ||
+ ack->hContact != dat->hContact ||
+ strcmp(ack->szModule, gpszICQProtoName))
+ break;
+
+ if (dat->hProtoAck)
+ {
+ UnhookEvent(dat->hProtoAck);
+ dat->hProtoAck = NULL;
+ }
+
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ SetDlgItemText(hwndDlg, IDC_IGNORE, Translate("Msg Accepted!"));
+ Netlib_Logf(ghServerNetlibUser, "User %u accepts your messages", dat->dwUin);
+ }
+ else
+ if (ack->result == ACKRESULT_FAILED)
+ {
+ SetDlgItemText(hwndDlg, IDC_IGNORE, Translate("Msg Ignored!"));
+ Netlib_Logf(ghServerNetlibUser, "User %u ignores your messages", dat->dwUin);
+ }
+
+ }
+ break;
+
+ case WM_TIMER:
+ if (wParam==TIMERID)
+ {
+ PSHNOTIFY pshn;
+ pshn.hdr.code=PSN_INFOCHANGED;
+ pshn.hdr.hwndFrom=hwndDlg;
+ pshn.hdr.idFrom=0;
+ pshn.lParam=(LPARAM)wParam;
+
+ KillTimer(hwndDlg, TIMERID);
+ dat->nTimer = 0;
+
+ SendMessage(hwndDlg,WM_NOTIFY,0,(LPARAM)&pshn);
+ }
+ else
+ if (wParam==TIMEOUT_IGNORE)
+ {
+ KillTimer(hwndDlg, TIMEOUT_IGNORE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IGNORECHECK), TRUE);
+ }
+ else
+ if (wParam==TIMEOUT_IP)
+ {
+ KillTimer(hwndDlg, TIMEOUT_IP);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RETRIEVE), TRUE);
+ }
+ break;
+
+ case WM_DESTROY:
+ if (dat->hEventDbSettingChange)
+ UnhookEvent(dat->hEventDbSettingChange);
+ if (dat->nTimer)
+ KillTimer(hwndDlg, TIMERID);
+ if (dat->hProtoAck)
+ UnhookEvent(dat->hProtoAck);
+ free(dat);
+ break;
+ }
+
+ return FALSE;
+}
+
+typedef struct AvtDlgProcData_t
+{
+ HANDLE hContact;
+ HANDLE hEventHook;
+ HWND hFlashAvatar;
+ HBITMAP hImageAvatar;
+} AvtDlgProcData;
+
+#define HM_REBIND_AVATAR (WM_USER + 1024)
+
+static char* ChooseAvatarFileName()
+{
+ char* szDest = (char*)SAFE_MALLOC(MAX_PATH+0x10);
+ char str[MAX_PATH];
+ char szFilter[512];
+ OPENFILENAME ofn = {0};
+
+ str[0] = 0;
+ CallService(MS_UTILS_GETBITMAPFILTERSTRINGS,sizeof(szFilter),(LPARAM)szFilter);
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.lpstrFilter = szFilter;
+ ofn.lpstrFile = szDest;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = "jpg";
+ if (!GetOpenFileName(&ofn))
+ {
+ SAFE_FREE(&szDest);
+ return NULL;
+ }
+
+ return szDest;
+}
+
+
+
+static void PrepareFlashAvatar(HWND hwndDlg, AvtDlgProcData* pData)
+{
+ FLASHAVATAR fa = {0};
+
+ fa.hContact = pData->hContact;
+ fa.cProto = gpszICQProtoName;
+ fa.id = FA_MAGIC_ID;
+ CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0);
+ if (fa.hWindow)
+ {
+ pData->hFlashAvatar = fa.hWindow;
+ SetParent(fa.hWindow, GetDlgItem(hwndDlg, IDC_AVATAR));
+ }
+ else
+ {
+ fa.hParentWindow = GetDlgItem(hwndDlg, IDC_AVATAR);
+ CallService(MS_FAVATAR_MAKE, (WPARAM)&fa, 0);
+ if (fa.hWindow)
+ pData->hFlashAvatar = fa.hWindow;
+ }
+}
+
+
+
+static void ReleaseFlashAvatar(AvtDlgProcData* pData)
+{
+ if (pData->hFlashAvatar)
+ { // release expired flash avatar object
+ FLASHAVATAR fa;
+
+ fa.hContact = pData->hContact;
+ fa.cProto = gpszICQProtoName;
+ fa.id = FA_MAGIC_ID; // icqj magic id
+ CallService(MS_FAVATAR_DESTROY, (WPARAM)&fa, 0);
+ pData->hFlashAvatar = NULL;
+ }
+}
+
+
+
+static void PrepareImageAvatar(HWND hwndDlg, AvtDlgProcData* pData, char* szFile)
+{
+ pData->hImageAvatar = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szFile);
+
+ SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)pData->hImageAvatar);
+}
+
+
+
+static void ReleaseImageAvatar(HWND hwndDlg, AvtDlgProcData* pData)
+{
+ if (pData->hImageAvatar)
+ {
+ HBITMAP avt = (HBITMAP)SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
+
+ // force re-draw avatar window
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, FALSE);
+
+ // in XP you can get different image, and it is leaked if not Destroy()ed
+ if (avt != pData->hImageAvatar)
+ DeleteObject(avt);
+
+ DeleteObject(pData->hImageAvatar);
+ pData->hImageAvatar = NULL;
+ }
+}
+
+
+
+static BOOL CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ {
+ DBVARIANT dbvHash;
+ AvtDlgProcData* pData = (AvtDlgProcData*)SAFE_MALLOC(sizeof(AvtDlgProcData));
+ DWORD dwUIN;
+ uid_str szUID;
+ char szAvatar[MAX_PATH];
+ DWORD dwPaFormat;
+ int bValid = 0;
+
+ pData->hContact = (HANDLE)lParam;
+
+ if (pData->hContact)
+ pData->hEventHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_REBIND_AVATAR);
+ else
+ {
+ ShowWindow(GetDlgItem(hwndDlg, IDC_SETAVATAR), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_DELETEAVATAR), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, -1), SW_SHOW);
+ if (!icqOnline)
+ {
+ EnableDlgItem(hwndDlg, IDC_SETAVATAR, FALSE);
+ EnableDlgItem(hwndDlg, IDC_DELETEAVATAR, FALSE);
+ }
+ }
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)pData);
+
+ if (!ICQGetContactSettingUID((HANDLE)lParam, &dwUIN, &szUID))
+ {
+ if (!ICQGetContactSetting((HANDLE)lParam, "AvatarHash", &dbvHash))
+ {
+ dwPaFormat = ICQGetContactSettingByte((HANDLE)lParam, "AvatarType", PA_FORMAT_UNKNOWN);
+ if (!pData->hContact || (dwPaFormat != PA_FORMAT_UNKNOWN))
+ { // we do not know avatar format, so neither filename is known, not valid
+ if (pData->hContact)
+ GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, szAvatar, 255);
+ else
+ { // owner's avatar
+ char* file = loadMyAvatarFileName();
+
+ if (file)
+ {
+ strcpy(szAvatar, file);
+ SAFE_FREE(&file);
+ if (dbvHash.pbVal[1] == 8) // we do this by hand, as owner's format is not saved
+ dwPaFormat = PA_FORMAT_XML;
+ }
+ else
+ szAvatar[0] = '\0';
+ }
+
+ if (!pData->hContact || !IsAvatarSaved((HANDLE)lParam, dbvHash.pbVal))
+ { // if the file exists, we know we have the current avatar
+ if (!access(szAvatar, 0)) bValid = 1;
+ }
+ }
+ }
+ else
+ return TRUE;
+
+ if (bValid)
+ { //load avatar
+ if ((dwPaFormat == PA_FORMAT_XML || dwPaFormat == PA_FORMAT_SWF) && ServiceExists(MS_FAVATAR_GETINFO))
+ { // flash avatar and we have FlashAvatars installed, init flash avatar
+ PrepareFlashAvatar(hwndDlg, pData);
+ }
+ else
+ { // static avatar processing
+ PrepareImageAvatar(hwndDlg, pData, szAvatar);
+ }
+ }
+ else if (pData->hContact) // only retrieve users avatars
+ {
+ GetAvatarFileName(dwUIN, szUID, szAvatar, 255);
+ GetAvatarData((HANDLE)lParam, dwUIN, szUID, dbvHash.pbVal, 0x14, szAvatar);
+ }
+ }
+
+ ICQFreeVariant(&dbvHash);
+ }
+ return TRUE;
+
+ case HM_REBIND_AVATAR:
+ {
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+ ACKDATA* ack = (ACKDATA*)lParam;
+
+ if (!pData->hContact) break; // we do not use this for us
+
+ if (ack->type == ACKTYPE_AVATAR && ack->hContact == pData->hContact)
+ {
+ if (ack->result == ACKRESULT_SUCCESS)
+ { // load avatar
+ PROTO_AVATAR_INFORMATION* AI = (PROTO_AVATAR_INFORMATION*)ack->hProcess;
+
+ ReleaseFlashAvatar(pData);
+ ReleaseImageAvatar(hwndDlg, pData);
+
+ if ((AI->format == PA_FORMAT_XML || AI->format == PA_FORMAT_SWF) && ServiceExists(MS_FAVATAR_GETINFO))
+ { // flash avatar and we have FlashAvatars installed, init flash avatar
+ PrepareFlashAvatar(hwndDlg, pData);
+ }
+ else
+ { // process image avatar
+ PrepareImageAvatar(hwndDlg, pData, AI->filename);
+ }
+ }
+ else if (ack->result == ACKRESULT_STATUS)
+ { // contact has changed avatar
+ DWORD dwUIN;
+ uid_str szUID;
+ DBVARIANT dbvHash;
+
+ if (!ICQGetContactSettingUID(pData->hContact, &dwUIN, &szUID))
+ {
+ if (!ICQGetContactSetting(pData->hContact, "AvatarHash", &dbvHash))
+ {
+ char szAvatar[MAX_PATH];
+
+ GetAvatarFileName(dwUIN, szUID, szAvatar, 255);
+ GetAvatarData(pData->hContact, dwUIN, szUID, dbvHash.pbVal, 0x14, szAvatar);
+ }
+ ICQFreeVariant(&dbvHash);
+ }
+ }
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_SETAVATAR:
+ {
+ char* szFile;
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ if (szFile = ChooseAvatarFileName())
+ { // user selected file for his avatar
+ DWORD dwPaFormat = DetectAvatarFormat(szFile);
+
+ if (dwPaFormat == PA_FORMAT_XML || dwPaFormat == PA_FORMAT_JPEG || dwPaFormat == PA_FORMAT_GIF || dwPaFormat == PA_FORMAT_BMP)
+ { // a valid file
+ if (!IcqSetMyAvatar(0, (LPARAM)szFile)) // set avatar
+ {
+ ReleaseFlashAvatar(pData);
+ ReleaseImageAvatar(hwndDlg, pData);
+
+ if (dwPaFormat != PA_FORMAT_XML || !ServiceExists(MS_FAVATAR_GETINFO))
+ { // it is not flash
+ PrepareImageAvatar(hwndDlg, pData, szFile);
+ }
+ else
+ { // is is flash load it
+ PrepareFlashAvatar(hwndDlg, pData);
+ }
+ }
+ }
+ SAFE_FREE(&szFile);
+ }
+ }
+ break;
+ case IDC_DELETEAVATAR:
+ {
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ ReleaseFlashAvatar(pData);
+ ReleaseImageAvatar(hwndDlg, pData);
+
+ IcqSetMyAvatar(0, 0); // clear hash on server
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+ if (pData->hContact)
+ UnhookEvent(pData->hEventHook);
+
+ ReleaseFlashAvatar(pData);
+ ReleaseImageAvatar(hwndDlg, pData);
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)0);
+ SAFE_FREE(&pData);
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+
+static void SetValue(HWND hwndDlg, int idCtrl, HANDLE hContact, char* szModule, char* szSetting, int special)
+{
+ DBVARIANT dbv = {0};
+ char str[MAX_PATH];
+ char* pstr = NULL;
+ int unspecified = 0;
+ int bUtf = 0, bDbv = 0, bAlloc = 0;
+
+ dbv.type = DBVT_DELETED;
+
+ if ((hContact == NULL) && ((int)szModule<0x100))
+ {
+ dbv.type = (BYTE)szModule;
+
+ switch((int)szModule)
+ {
+ case DBVT_BYTE:
+ dbv.cVal = (BYTE)szSetting;
+ break;
+ case DBVT_WORD:
+ dbv.wVal = (WORD)szSetting;
+ break;
+ case DBVT_DWORD:
+ dbv.dVal = (DWORD)szSetting;
+ break;
+ case DBVT_ASCIIZ:
+ dbv.pszVal = pstr = szSetting;
+ break;
+ default:
+ unspecified = 1;
+ dbv.type = DBVT_DELETED;
+ }
+ }
+ else
+ {
+ if (szModule == NULL)
+ unspecified = 1;
+ else
+ {
+ unspecified = DBGetContactSetting(hContact, szModule, szSetting, &dbv);
+ bDbv = 1;
+ }
+ }
+
+ if (!unspecified)
+ {
+ switch (dbv.type)
+ {
+
+ case DBVT_BYTE:
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.bVal == 0);
+ pstr = itoa(special == SVS_SIGNED ? dbv.cVal:dbv.bVal, str, 10);
+ break;
+
+ case DBVT_WORD:
+ if (special == SVS_ICQVERSION)
+ {
+ if (dbv.wVal != 0)
+ {
+ char szExtra[80];
+
+ null_snprintf(str, 250, "%d", dbv.wVal);
+ pstr = str;
+
+ if (hContact && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD))
+ {
+ ICQTranslateUtfStatic(" (DC Established)", szExtra);
+ strcat(str, szExtra);
+ bUtf = 1;
+ }
+ }
+ else
+ unspecified = 1;
+ }
+ else if (special == SVS_STATUSID)
+ {
+ char* pXName;
+ char* pszStatus;
+ BYTE bXStatus = ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, 0);
+
+ pszStatus = MirandaStatusToStringUtf(dbv.wVal);
+ if (bXStatus)
+ {
+ pXName = ICQGetContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, "");
+ if (!strlennull(pXName))
+ { // give default name
+ pXName = ICQTranslateUtf(nameXStatus[bXStatus-1]);
+ }
+ null_snprintf(str, sizeof(str), "%s (%s)", pszStatus, pXName);
+ SAFE_FREE(&pXName);
+ }
+ else
+ null_snprintf(str, sizeof(str), pszStatus);
+
+ bUtf = 1;
+ SAFE_FREE(&pszStatus);
+ pstr = str;
+ unspecified = 0;
+ }
+ else
+ {
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.wVal == 0);
+ pstr = itoa(special == SVS_SIGNED ? dbv.sVal:dbv.wVal, str, 10);
+ }
+ break;
+
+ case DBVT_DWORD:
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.dVal == 0);
+ if (special == SVS_IP)
+ {
+ struct in_addr ia;
+ ia.S_un.S_addr = htonl(dbv.dVal);
+ pstr = inet_ntoa(ia);
+ if (dbv.dVal == 0)
+ unspecified=1;
+ }
+ else if (special == SVS_TIMESTAMP)
+ {
+ if (dbv.dVal == 0)
+ unspecified = 1;
+ else
+ {
+ pstr = asctime(localtime(&dbv.dVal));
+ pstr[24] = '\0'; // Remove newline
+ }
+ }
+ else
+ pstr = itoa(special == SVS_SIGNED ? dbv.lVal:dbv.dVal, str, 10);
+ break;
+
+ case DBVT_ASCIIZ:
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.pszVal[0] == '\0');
+ if (!unspecified && pstr != szSetting)
+ {
+ pstr = UniGetContactSettingUtf(hContact, szModule, szSetting, NULL);
+ bUtf = 1;
+ bAlloc = 1;
+ }
+ if (idCtrl == IDC_UIN)
+ SetDlgItemTextUtf(hwndDlg, IDC_UINSTATIC, ICQTranslateUtfStatic("ScreenName:", str));
+ break;
+
+ default:
+ pstr = str;
+ lstrcpy(str,"???");
+ break;
+ }
+ }
+
+ EnableDlgItem(hwndDlg, idCtrl, !unspecified);
+ if (unspecified)
+ SetDlgItemTextUtf(hwndDlg, idCtrl, ICQTranslateUtfStatic("<not specified>", str));
+ else if (bUtf)
+ SetDlgItemTextUtf(hwndDlg, idCtrl, pstr);
+ else
+ SetDlgItemText(hwndDlg, idCtrl, pstr);
+
+ if (bDbv)
+ ICQFreeVariant(&dbv);
+
+ if (bAlloc)
+ SAFE_FREE(&pstr);
+}
diff --git a/icqj_mod/UI/userinfotab.c.old b/icqj_mod/UI/userinfotab.c.old new file mode 100644 index 0000000..b8f5fa3 --- /dev/null +++ b/icqj_mod/UI/userinfotab.c.old @@ -0,0 +1,929 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/userinfotab.c,v $
+// Revision : $Revision: 1.38 $
+// Last change on : $Date: 2006/04/23 11:57:14 $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Code for User details ICQ specific pages
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#include "m_flash.h"
+
+// icqj magic id
+#define FA_MAGIC_ID 0x4943516A
+
+
+extern WORD wListenPort;
+
+extern char* calcMD5Hash(char* szFile);
+extern char* MirandaVersionToString(char* szStr, int v, int m);
+
+extern char* nameXStatus[29];
+
+static BOOL CALLBACK IcqDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BYTE SetValue(HWND hwndDlg, int idCtrl, HANDLE hContact, char *szModule, char *szSetting, WORD type);
+
+#define SVS_NORMAL 0
+#define SVS_ZEROISUNSPEC 2
+#define SVS_IP 3
+#define SVS_SIGNED 6
+#define SVS_ICQVERSION 8
+#define SVS_TIMESTAMP 9
+#define SVS_STATUSID 10
+
+#define SVS_FLAGS 0xFF
+#define SVSF_GRAYED 0x100
+#define SVSF_NORMAL 0x200
+
+
+int OnDetailsInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+
+ if ((!IsICQContact((HANDLE)lParam)) && lParam)
+ return 0;
+
+ odp.cbSize = sizeof(odp);
+ odp.hIcon = NULL;
+ odp.hInstance = hInst;
+ odp.pfnDlgProc = IcqDlgProc;
+ odp.position = -1900000000;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_ICQ);
+ AddUserInfoPageUtf(&odp, wParam, gpszICQProtoName);
+
+ if (((lParam != 0) && gbAvatarsEnabled) || (gbSsiEnabled && gbAvatarsEnabled))
+ {
+ DWORD dwUin;
+ uid_str dwUid;
+
+ if (!ICQGetContactSettingUID((HANDLE)lParam, &dwUin, &dwUid))
+ { // Avatar page only for valid contacts
+ char *szAvtTitle;
+
+ odp.pfnDlgProc = AvatarDlgProc;
+ odp.position = -1899999998;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_AVATAR);
+ if (lParam)
+ szAvtTitle = "Avatar";
+ else
+ szAvtTitle = "%s Avatar";
+
+ AddUserInfoPageUtf(&odp, wParam, szAvtTitle);
+ }
+ }
+
+ InitChangeDetails(wParam, lParam);
+
+ return 0;
+}
+
+
+#define HM_DBCHANGE (WM_USER+200)
+#define HM_PROTOACK (WM_USER+201)
+#define TIMERID 1
+#define TIMEOUT_IGNORE 2
+//#define TIMEOUT_CAPS 3
+#define TIMEOUT_IP 4
+
+typedef struct infoflag_s
+{
+ char *Descr;
+ char *szSetting;
+ DWORD mask;
+} infoflag;
+
+
+struct UserData {
+ HANDLE hContact;
+ DWORD dwUin;
+ HANDLE hEventDbSettingChange;
+ int nTimer;
+ HANDLE hProtoAck;
+ DWORD dwCookie;
+};
+
+
+static infoflag infoflags[] =
+{
+ {"Hidden", NULL, WAS_FOUND},
+ {"WebAware", "WebAware", 0},
+ {"Auth", "AddAuth", 0},
+ {"UTF", NULL, CAPF_UTF},
+ {"MTN", NULL, CAPF_TYPING},
+ {"Xtraz", NULL, CAPF_XTRAZ},
+ {"ServerRelay", NULL, CAPF_SRV_RELAY},
+ {"AIMFile", NULL, CAPF_AIM_FILE},
+ {"Push2Talk", NULL, CAPF_PUSH2TALK},
+ {"ICQLite", NULL, CAPF_ICQ_LITE},
+ {"RTF", NULL, CAPF_RTF},
+ {"XTrazChat", NULL, CAPF_XTRAZ_CHAT},
+ {"VoiceChat", NULL, CAPF_VOICE_CHAT},
+ {"ICQDevil", NULL, CAPF_ICQ_DEVIL},
+ {"DirectConnect", NULL, CAPF_DIRECT},
+};
+static BOOL CALLBACK IcqDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+ struct UserData *dat=(struct UserData*)GetWindowLong(hwndDlg,GWL_USERDATA);
+
+ switch (msg)
+ {
+
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ dat=(struct UserData*)malloc(sizeof(struct UserData));
+ SetWindowLong(hwndDlg,GWL_USERDATA,(LONG)dat);
+
+ dat->hEventDbSettingChange=HookEventMessage(ME_DB_CONTACT_SETTINGCHANGED,hwndDlg,HM_DBCHANGE);
+ dat->hContact=(HANDLE)lParam;
+ dat->nTimer=0;
+ dat->dwUin=ICQGetContactSettingDword(dat->hContact, UNIQUEIDSETTING, 0);
+ dat->hProtoAck=NULL;
+ dat->dwCookie=0;
+ if ((HANDLE)lParam == NULL)
+ {
+
+ ShowWindow(GetDlgItem(hwndDlg, IDC_FLAGS), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_FLAGSTEXT), SW_HIDE);
+ }
+ return TRUE;
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ case PSN_INFOCHANGED:
+ {
+ HANDLE hContact = dat->hContact;
+ WORD flag = SVSF_NORMAL;
+ int was_found = 0;
+ char szUin[20];
+ char szStatus[64];
+
+ mir_snprintf(szUin, 20, "%u", dat->dwUin);
+
+ if (hContact == NULL)
+ {
+ SetValue(hwndDlg, IDC_SYSTEMUPTIME, NULL, gpszICQProtoName, "MemberTS", (icqOnline)?SVS_TIMESTAMP|SVSF_NORMAL:SVS_TIMESTAMP|SVSF_GRAYED);
+ _snprintf(szStatus, sizeof(szStatus), MirandaStatusToString(gnCurrentStatus));
+ SetDlgItemText(hwndDlg, IDC_STATUS, szStatus);
+ }
+ else
+ {
+ WORD wStatus = ICQGetContactSettingWord(hContact, "Status", 0);
+ char str[128] = {0};
+ int i;
+
+ SetValue(hwndDlg, IDC_STATUS, hContact, gpszICQProtoName, "Status", SVS_STATUSID);
+
+ ShowWindow(GetDlgItem(hwndDlg,IDC_GETSTATUS),(ASD)?SW_SHOW:SW_HIDE);
+ //ShowWindow(GetDlgItem(hwndDlg,IDC_GETCAPS),(wStatus != ID_STATUS_OFFLINE)?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_RETRIEVE),(wStatus != ID_STATUS_OFFLINE)?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_IGNORECHECK),(wStatus != ID_STATUS_OFFLINE)?SW_SHOW:SW_HIDE);
+
+ // Subnets
+ //DBGetStaticString(hContact, gpszICQProtoName, "SubNets", str, sizeof(str));
+
+ // Set flags
+ for (i=0; i < sizeof(infoflags)/sizeof(infoflags[0]); i++)
+ {
+ if ((infoflags[i].szSetting && ICQGetContactSettingByte(hContact, infoflags[i].szSetting,0))
+ || (infoflags[i].szSetting == NULL && CheckContactCapabilities(hContact, infoflags[i].mask)))
+ mir_snprintf(str, sizeof(str), (str[0]==0)?"%s%s":"%s, %s", str, Translate(infoflags[i].Descr));
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FLAGSTEXT), (str[0] != 0));
+ if (str[0]==0)
+ SetDlgItemText(hwndDlg, IDC_FLAGSTEXT, ICQTranslate("<not specified>"));
+ else
+ SetDlgItemText(hwndDlg, IDC_FLAGSTEXT, str);
+ // Gray flags if miranda offline
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_FLAGSTEXT), GWL_USERDATA, (!icqOnline && str[0] != 0));
+ }
+
+ //SetValue(hwndDlg, IDC_UIN, hContact, gpszICQProtoName, UNIQUEIDSETTING, 0);
+ SetDlgItemText(hwndDlg, IDC_UIN, szUin);
+
+ // Client version
+ SetValue(hwndDlg, IDC_MIRVER, hContact, gpszICQProtoName, "MirVer", SVS_ZEROISUNSPEC|flag);
+
+ // Proto version.
+ if (!SetValue(hwndDlg, IDC_VERSION, hContact, gpszICQProtoName, "Version", SVS_ZEROISUNSPEC|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_VERSION, hContact, gpszICQProtoName, "OldVersion", SVS_ZEROISUNSPEC|SVSF_GRAYED);
+
+ // IP
+ if (!SetValue(hwndDlg, IDC_IP, hContact, gpszICQProtoName, "IP", SVS_IP|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_IP, hContact, gpszICQProtoName, "OldIP", SVS_IP|SVSF_GRAYED);
+ // Real IP
+ if (!SetValue(hwndDlg, IDC_REALIP, hContact, gpszICQProtoName, "RealIP", SVS_IP|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_REALIP, hContact, gpszICQProtoName, "OldRealIP", SVS_IP|SVSF_GRAYED);
+ // Port
+ if (!SetValue(hwndDlg, IDC_PORT, hContact, gpszICQProtoName, "UserPort", SVS_ZEROISUNSPEC|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_PORT, hContact, gpszICQProtoName, "OldUserPort", SVS_ZEROISUNSPEC|SVSF_GRAYED);
+ // Online since time
+ if (!SetValue(hwndDlg, IDC_ONLINESINCE, hContact, gpszICQProtoName, "LogonTS", SVS_TIMESTAMP|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_ONLINESINCE, hContact, gpszICQProtoName, "OldLogonTS", SVS_TIMESTAMP|SVSF_GRAYED);
+ // Idle time
+ if (was_found)
+ SetValue(hwndDlg, IDC_IDLETIME, hContact, NULL, NULL, 0);
+ else
+ if (!SetValue(hwndDlg, IDC_IDLETIME, hContact, gpszICQProtoName, "IdleTS", SVS_TIMESTAMP|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_IDLETIME, hContact, gpszICQProtoName, "OldIdleTS", SVS_TIMESTAMP|SVSF_GRAYED);
+
+ if (ICQGetContactSettingByte(hContact, "ClientID", 0) == 1)
+ SetValue(hwndDlg, IDC_SYSTEMUPTIME, hContact, NULL, "TickTS", SVS_TIMESTAMP);
+ else
+ SetValue(hwndDlg, IDC_SYSTEMUPTIME, hContact, gpszICQProtoName, "TickTS", SVS_TIMESTAMP);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDCANCEL:
+ SendMessage(GetParent(hwndDlg),msg,wParam,lParam);
+ break;
+
+ case IDC_GETSTATUS:
+ if (icqOnline)
+ icq_GetUserStatus(dat->hContact, 1);
+ break;
+
+ case IDC_RETRIEVE:
+ if (icqOnline && dat->dwUin)
+ {
+
+ int wMessageType = 0;
+
+ switch(ICQGetContactSettingWord(dat->hContact, "Status",ID_STATUS_OFFLINE))
+ {
+ case ID_STATUS_OFFLINE:
+ break;
+ case ID_STATUS_NA:
+ wMessageType = MTYPE_AUTONA;
+ break;
+ case ID_STATUS_OCCUPIED:
+ wMessageType = MTYPE_AUTOBUSY;
+ break;
+ case ID_STATUS_DND:
+ wMessageType = MTYPE_AUTODND;
+ break;
+ case ID_STATUS_FREECHAT:
+ wMessageType = MTYPE_AUTOFFC;
+ break;
+ case ID_STATUS_AWAY:
+ default:
+ wMessageType = MTYPE_AUTOAWAY;
+ break;
+ }
+
+ icq_sendGetAwayMsgServ(dat->dwUin, wMessageType, (WORD)(ICQGetContactSettingWord(dat->hContact, "Version", 0)==9?9:ICQ_VERSION));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RETRIEVE), FALSE);
+ SetTimer(hwndDlg, TIMEOUT_IP, 10000, NULL);
+
+ }
+ break;
+
+ case IDC_IGNORECHECK:
+ if (icqOnline &&
+ ICQGetContactSettingWord(dat->hContact, "Status", 0) != ID_STATUS_OFFLINE)
+ {
+ message_cookie_data* pCookieData;
+
+ if (!dat->hProtoAck)
+ dat->hProtoAck = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_PROTOACK);
+
+ SetDlgItemText(hwndDlg, IDC_IGNORE, Translate("Checking..."));
+
+ pCookieData = malloc(sizeof(message_cookie_data));
+ pCookieData->bMessageType = MTYPE_PLAIN;
+ pCookieData->nAckType = ACKTYPE_SERVER;
+ dat->dwCookie = icq_SendChannel4Message(dat->dwUin, 0, 0, "", pCookieData);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IGNORECHECK), FALSE);
+ SetTimer(hwndDlg, TIMEOUT_IGNORE, 10000, NULL);
+ }
+ break;
+ }
+ break;
+ case HM_DBCHANGE:
+ {
+ DBCONTACTWRITESETTING *cws=(DBCONTACTWRITESETTING*)lParam;
+
+ if (!dat->nTimer &&
+ (cws->szModule != NULL) &&
+ (dat->hContact == (HANDLE)wParam) &&
+ !strcmp(cws->szModule, gpszICQProtoName))
+ {
+ dat->nTimer = 1;
+ SetTimer(hwndDlg, TIMERID, 1000, NULL);
+ }
+ }
+ break;
+
+ case HM_PROTOACK:
+ {
+ ACKDATA *ack = (ACKDATA*)lParam;
+
+ if (!ack || !ack->szModule ||
+ ack->hProcess != (HANDLE)dat->dwCookie ||
+ ack->hContact != dat->hContact ||
+ strcmp(ack->szModule, gpszICQProtoName))
+ break;
+
+ if (dat->hProtoAck)
+ {
+ UnhookEvent(dat->hProtoAck);
+ dat->hProtoAck = NULL;
+ }
+
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ SetDlgItemText(hwndDlg, IDC_IGNORE, Translate("Msg Accepted!"));
+ Netlib_Logf(ghServerNetlibUser, "User %u accepts your messages", dat->dwUin);
+ }
+ else
+ if (ack->result == ACKRESULT_FAILED)
+ {
+ SetDlgItemText(hwndDlg, IDC_IGNORE, Translate("Msg Ignored!"));
+ Netlib_Logf(ghServerNetlibUser, "User %u ignores your messages", dat->dwUin);
+ }
+
+ }
+ break;
+
+ case WM_TIMER:
+ if (wParam==TIMERID)
+ {
+ PSHNOTIFY pshn;
+ pshn.hdr.code=PSN_INFOCHANGED;
+ pshn.hdr.hwndFrom=hwndDlg;
+ pshn.hdr.idFrom=0;
+ pshn.lParam=(LPARAM)wParam;
+
+ KillTimer(hwndDlg, TIMERID);
+ dat->nTimer = 0;
+
+ SendMessage(hwndDlg,WM_NOTIFY,0,(LPARAM)&pshn);
+ }
+ else
+ if (wParam==TIMEOUT_IGNORE)
+ {
+ KillTimer(hwndDlg, TIMEOUT_IGNORE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IGNORECHECK), TRUE);
+ }
+ else
+ if (wParam==TIMEOUT_IP)
+ {
+ KillTimer(hwndDlg, TIMEOUT_IP);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RETRIEVE), TRUE);
+ }
+ break;
+
+ case WM_DESTROY:
+ if (dat->hEventDbSettingChange)
+ UnhookEvent(dat->hEventDbSettingChange);
+ if (dat->nTimer)
+ KillTimer(hwndDlg, TIMERID);
+ if (dat->hProtoAck)
+ UnhookEvent(dat->hProtoAck);
+ free(dat);
+ break;
+ }
+
+ return FALSE;
+}
+
+typedef struct AvtDlgProcData_t
+{
+ HANDLE hContact;
+ HANDLE hEventHook;
+ HWND hFlashAvatar;
+} AvtDlgProcData;
+
+#define HM_REBIND_AVATAR (WM_USER + 1024)
+
+static char* ChooseAvatarFileName()
+{
+ char* szDest = (char*)SAFE_MALLOC(MAX_PATH+0x10);
+ char str[MAX_PATH];
+ char szFilter[512];
+ OPENFILENAME ofn = {0};
+
+ str[0] = 0;
+ CallService(MS_UTILS_GETBITMAPFILTERSTRINGS,sizeof(szFilter),(LPARAM)szFilter);
+ if (ServiceExists(MS_FAVATAR_GETINFO)) //Flash avatars are supported
+ {
+ char * allimages;
+ char b2[255];
+ int l,i;
+ char flashfilt[520]={0};
+ allimages=szFilter+strlen(szFilter)+1;
+ l=sizeof(szFilter)-strlen(szFilter)-1;
+ sprintf(flashfilt,"%s (%s;*.XML)",Translate("All Bitmaps"),allimages);
+ memcpy(flashfilt+strlen(flashfilt)+1,"*.XML;",6);
+ memcpy(flashfilt+6+strlen(flashfilt)+1,allimages,l-(6+strlen(flashfilt)+1));
+ {
+ int z0=0,z1=0;
+ for (i=0;i<sizeof(flashfilt)-1;i++)
+ {
+ if (flashfilt[i]=='\0' && flashfilt[i+1]!='\0')
+ {
+ if (z1>0) z0=z1;
+ z1=i;
+ }
+ if (flashfilt[i]=='\0' && flashfilt[i+1]=='\0')
+ {
+ sprintf(b2,"%s (*.xml)",Translate("flash avatars"));
+ memcpy(flashfilt+z0+1,b2,strlen(b2)+1);
+ z0=z0+strlen(b2)+1;
+ memcpy(flashfilt+z0+1,"*.XML\0",6);
+ z0+=6;
+ sprintf(b2,"%s(*.*)",Translate("All files"));
+ memcpy(flashfilt+z0+1,b2,strlen(b2)+1);
+ z0=z0+strlen(b2)+1;
+ memcpy(flashfilt+z0+1,"*\0\0",4);
+ memcpy(szFilter,flashfilt,sizeof(szFilter));
+ break;
+ }
+ }
+ }
+ }
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.lpstrFilter = szFilter;
+ ofn.lpstrFile = szDest;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = "jpg";
+ if (!GetOpenFileName(&ofn))
+ {
+ SAFE_FREE(&szDest);
+ return NULL;
+ }
+
+ return szDest;
+}
+
+
+
+static void PrepareFlashAvatar(HWND hwndDlg, AvtDlgProcData* pData)
+{
+ FLASHAVATAR fa = {0};
+
+ fa.hContact = pData->hContact;
+ fa.id = FA_MAGIC_ID;
+ CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0);
+ if (fa.hWindow)
+ {
+ pData->hFlashAvatar = fa.hWindow;
+ SetParent(fa.hWindow, GetDlgItem(hwndDlg, IDC_AVATAR));
+ }
+ else
+ {
+ fa.hParentWindow = GetDlgItem(hwndDlg, IDC_AVATAR);
+ CallService(MS_FAVATAR_MAKE, (WPARAM)&fa, 0);
+ if (fa.hWindow)
+ pData->hFlashAvatar = fa.hWindow;
+ }
+}
+
+
+
+static void ReleaseFlashAvatar(AvtDlgProcData* pData)
+{
+ if (pData->hFlashAvatar)
+ { // release expired flash avatar object
+ FLASHAVATAR fa;
+
+ fa.hContact = pData->hContact;
+ fa.id = FA_MAGIC_ID; // icqj magic id
+ CallService(MS_FAVATAR_DESTROY, (WPARAM)&fa, 0);
+ pData->hFlashAvatar = NULL;
+ }
+}
+
+
+static BOOL CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ {
+ DBVARIANT dbvHash;
+ AvtDlgProcData* pData = (AvtDlgProcData*)SAFE_MALLOC(sizeof(AvtDlgProcData));
+ DWORD dwUIN;
+ uid_str szUID;
+ char szAvatar[MAX_PATH];
+ DWORD dwPaFormat;
+ int bValid = 0;
+
+ pData->hContact = (HANDLE)lParam;
+
+ if (pData->hContact)
+ pData->hEventHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_REBIND_AVATAR);
+ else
+ {
+ ShowWindow(GetDlgItem(hwndDlg, IDC_SETAVATAR), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_DELETEAVATAR), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, -1), SW_SHOW);
+ if (!icqOnline)
+ {
+ EnableDlgItem(hwndDlg, IDC_SETAVATAR, FALSE);
+ EnableDlgItem(hwndDlg, IDC_DELETEAVATAR, FALSE);
+ }
+ }
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)pData);
+
+ if (!ICQGetContactSettingUID((HANDLE)lParam, &dwUIN, &szUID))
+ {
+ if (!ICQGetContactSetting((HANDLE)lParam, "AvatarHash", &dbvHash))
+ {
+ dwPaFormat = ICQGetContactSettingByte((HANDLE)lParam, "AvatarType", PA_FORMAT_UNKNOWN);
+ if (!pData->hContact || (dwPaFormat != PA_FORMAT_UNKNOWN))
+ { // we do not know avatar format, so neither filename is known, not valid
+ if (pData->hContact)
+ GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, szAvatar, 255);
+ else
+ { // owner's avatar
+ char* file = loadMyAvatarFileName();
+
+ if (file)
+ {
+ strcpy(szAvatar, file);
+ SAFE_FREE(&file);
+ if (dbvHash.pbVal[1] == 8) // we do this by hand, as owner's format is not saved
+ dwPaFormat = PA_FORMAT_XML;
+ }
+ else
+ szAvatar[0] = '\0';
+ }
+
+ if (!pData->hContact || !IsAvatarSaved((HANDLE)lParam, dbvHash.pbVal))
+ { // if the file exists, we know we have the current avatar
+ if (!access(szAvatar, 0)) bValid = 1;
+ }
+ }
+ }
+ else
+ return TRUE;
+
+ if (bValid)
+ { //load avatar
+ if ((dwPaFormat == PA_FORMAT_XML || dwPaFormat == PA_FORMAT_SWF) && ServiceExists(MS_FAVATAR_GETINFO))
+ { // flash avatar and we have FlashAvatars installed, init flash avatar
+ PrepareFlashAvatar(hwndDlg, pData);
+ }
+ else
+ { // static avatar processing
+ HBITMAP avt = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szAvatar);
+
+ if (avt)
+ SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)avt);
+ }
+ }
+ else if (pData->hContact) // only retrieve users avatars
+ {
+ GetAvatarFileName(dwUIN, szUID, szAvatar, 255);
+ GetAvatarData((HANDLE)lParam, dwUIN, szUID, dbvHash.pbVal, 0x14, szAvatar);
+ }
+ }
+
+ ICQFreeVariant(&dbvHash);
+ }
+ return TRUE;
+
+ case HM_REBIND_AVATAR:
+ {
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+ ACKDATA* ack = (ACKDATA*)lParam;
+
+ if (!pData->hContact) break; // we do not use this for us
+
+ if (ack->type == ACKTYPE_AVATAR && ack->hContact == pData->hContact)
+ {
+ if (ack->result == ACKRESULT_SUCCESS)
+ { // load avatar
+ PROTO_AVATAR_INFORMATION* AI = (PROTO_AVATAR_INFORMATION*)ack->hProcess;
+ HBITMAP avt = NULL;
+
+ ReleaseFlashAvatar(pData);
+ if ((AI->format == PA_FORMAT_XML || AI->format == PA_FORMAT_SWF) && ServiceExists(MS_FAVATAR_GETINFO))
+ { // flash avatar and we have FlashAvatars installed, init flash avatar
+ PrepareFlashAvatar(hwndDlg, pData);
+ }
+ else
+ {
+ avt = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)AI->filename);
+ }
+ if (avt) avt = (HBITMAP)SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)avt);
+ if (avt) DeleteObject(avt); // we release old avatar if any
+ }
+ else if (ack->result == ACKRESULT_STATUS)
+ { // contact has changed avatar
+ DWORD dwUIN;
+ uid_str szUID;
+ DBVARIANT dbvHash;
+
+ if (!ICQGetContactSettingUID(pData->hContact, &dwUIN, &szUID))
+ {
+ if (!ICQGetContactSetting(pData->hContact, "AvatarHash", &dbvHash))
+ {
+ char szAvatar[MAX_PATH];
+
+ GetAvatarFileName(dwUIN, szUID, szAvatar, 255);
+ GetAvatarData(pData->hContact, dwUIN, szUID, dbvHash.pbVal, 0x14, szAvatar);
+ }
+ ICQFreeVariant(&dbvHash);
+ }
+ }
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_SETAVATAR:
+ {
+ char* szFile;
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ if (szFile = ChooseAvatarFileName())
+ { // user selected file for his avatar
+ DWORD dwPaFormat = DetectAvatarFormat(szFile);
+
+ if (dwPaFormat == PA_FORMAT_XML || dwPaFormat == PA_FORMAT_JPEG || dwPaFormat == PA_FORMAT_GIF || dwPaFormat == PA_FORMAT_BMP)
+ { // a valid file
+ HBITMAP avt = NULL;
+
+ if (dwPaFormat != PA_FORMAT_XML || !ServiceExists(MS_FAVATAR_GETINFO))
+ avt = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szFile);
+
+ if (!IcqSetMyAvatar(0, (LPARAM)szFile)) // set avatar
+ {
+ ReleaseFlashAvatar(pData);
+ if (dwPaFormat != PA_FORMAT_XML || !ServiceExists(MS_FAVATAR_GETINFO))
+ { // it is not flash, release possible previous
+ avt = (HBITMAP)SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)avt);
+ }
+ else
+ { // is is flash load it
+ PrepareFlashAvatar(hwndDlg, pData);
+ }
+
+ }
+ if (avt) DeleteObject(avt); // we release old avatar if any
+ }
+ SAFE_FREE(&szFile);
+ }
+ }
+ break;
+ case IDC_DELETEAVATAR:
+ {
+ HBITMAP avt;
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ avt = (HBITMAP)SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, NULL, RDW_INVALIDATE);
+ if (avt) DeleteObject(avt); // we release old avatar if any
+ ReleaseFlashAvatar(pData);
+ IcqSetMyAvatar(0, 0); // clear hash on server
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+ if (pData->hContact)
+ UnhookEvent(pData->hEventHook);
+
+ ReleaseFlashAvatar(pData);
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)0);
+ SAFE_FREE(&pData);
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+
+static BYTE SetValue(HWND hwndDlg, int idCtrl, HANDLE hContact, char* szModule, char* szSetting, WORD type)
+{
+ DBVARIANT dbv = {0};
+ char str[MAX_PATH];
+ char* pstr = NULL;
+ int unspecified = 0;
+ int special = type & SVS_FLAGS;
+ int bUtf = 0, bDbv = 0, bAlloc = 0;
+
+ dbv.type = DBVT_DELETED;
+
+ if ((hContact == NULL) && ((int)szModule<0x100))
+ {
+ dbv.type = (BYTE)szModule;
+
+ switch((int)szModule)
+ {
+ case DBVT_BYTE:
+ dbv.cVal = (BYTE)szSetting;
+ break;
+ case DBVT_WORD:
+ dbv.wVal = (WORD)szSetting;
+ break;
+ case DBVT_DWORD:
+ dbv.dVal = (DWORD)szSetting;
+ break;
+ case DBVT_ASCIIZ:
+ dbv.pszVal = pstr = szSetting;
+ break;
+ default:
+ unspecified = 1;
+ dbv.type = DBVT_DELETED;
+ }
+ }
+ else
+ {
+ if (szModule == NULL)
+ unspecified = 1;
+ else
+ {
+ unspecified = DBGetContactSetting(hContact, szModule, szSetting, &dbv);
+ bDbv = 1;
+ }
+ }
+
+ if (!unspecified)
+ {
+ switch (dbv.type)
+ {
+
+ case DBVT_BYTE:
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.bVal == 0);
+ pstr = itoa(special == SVS_SIGNED ? dbv.cVal:dbv.bVal, str, 10);
+ break;
+
+ case DBVT_WORD:
+ if (special == SVS_ICQVERSION)
+ {
+ if (dbv.wVal != 0)
+ {
+ char szExtra[80];
+
+ null_snprintf(str, 250, "%d", dbv.wVal);
+ pstr = str;
+
+ if (hContact && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD))
+ {
+ ICQTranslateUtfStatic(" (DC Established)", szExtra);
+ strcat(str, szExtra);
+ bUtf = 1;
+ }
+ }
+ else
+ unspecified = 1;
+ }
+ else if (special == SVS_STATUSID)
+ {
+ char* pXName;
+ char* pszStatus;
+ BYTE bXStatus = ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, 0);
+
+ pszStatus = MirandaStatusToStringUtf(dbv.wVal);
+ if (bXStatus)
+ {
+ pXName = ICQGetContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, "");
+ if (!strlennull(pXName))
+ { // give default name
+ pXName = ICQTranslateUtf(nameXStatus[bXStatus-1]);
+ }
+ null_snprintf(str, sizeof(str), "%s (%s)", pszStatus, pXName);
+ SAFE_FREE(&pXName);
+ }
+ else
+ null_snprintf(str, sizeof(str), pszStatus);
+
+ bUtf = 1;
+ SAFE_FREE(&pszStatus);
+ pstr = str;
+ unspecified = 0;
+ }
+ else
+ {
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.wVal == 0);
+ pstr = itoa(special == SVS_SIGNED ? dbv.sVal:dbv.wVal, str, 10);
+ }
+ break;
+
+ case DBVT_DWORD:
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.dVal == 0);
+ if (special == SVS_IP)
+ {
+ struct in_addr ia;
+ ia.S_un.S_addr = htonl(dbv.dVal);
+ pstr = inet_ntoa(ia);
+ if (dbv.dVal == 0)
+ unspecified=1;
+ }
+ else if (special == SVS_TIMESTAMP)
+ {
+ if (dbv.dVal == 0)
+ unspecified = 1;
+ else
+ {
+ pstr = asctime(localtime(&dbv.dVal));
+ pstr[24] = '\0'; // Remove newline
+ }
+ }
+ else
+ pstr = itoa(special == SVS_SIGNED ? dbv.lVal:dbv.dVal, str, 10);
+ break;
+
+ case DBVT_ASCIIZ:
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.pszVal[0] == '\0');
+ if (!unspecified && pstr != szSetting)
+ {
+ pstr = UniGetContactSettingUtf(hContact, szModule, szSetting, NULL);
+ bUtf = 1;
+ bAlloc = 1;
+ }
+ if (idCtrl == IDC_UIN)
+ SetDlgItemTextUtf(hwndDlg, IDC_UINSTATIC, ICQTranslateUtfStatic("ScreenName:", str));
+ break;
+
+ default:
+ pstr = str;
+ lstrcpy(str,"???");
+ break;
+ }
+ }
+
+ EnableDlgItem(hwndDlg, idCtrl, !unspecified);
+ if (unspecified)
+ SetDlgItemTextUtf(hwndDlg, idCtrl, ICQTranslateUtfStatic("<not specified>", str));
+ else if (bUtf)
+ SetDlgItemTextUtf(hwndDlg, idCtrl, pstr);
+ else
+ SetDlgItemText(hwndDlg, idCtrl, pstr);
+
+ if (bDbv)
+ ICQFreeVariant(&dbv);
+
+ if (bAlloc)
+ SAFE_FREE(&pstr);
+
+ if (type > SVS_FLAGS)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, idCtrl), !(type & SVSF_GRAYED));
+ }
+ return !unspecified;
+}
diff --git a/icqj_mod/UI/userinfotab.h b/icqj_mod/UI/userinfotab.h new file mode 100644 index 0000000..8dcc215 --- /dev/null +++ b/icqj_mod/UI/userinfotab.h @@ -0,0 +1,38 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/userinfotab.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-17 01:38:00 +0400 $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+int OnDetailsInit(WPARAM wParam, LPARAM lParam);
diff --git a/icqj_mod/UI/userinfotab1.c b/icqj_mod/UI/userinfotab1.c new file mode 100644 index 0000000..266bfeb --- /dev/null +++ b/icqj_mod/UI/userinfotab1.c @@ -0,0 +1,953 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/userinfotab.c,v $
+// Revision : $Revision: 3250 $
+// Last change on : $Date: 2006-06-30 00:08:42 +0200 (Fri, 30 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Code for User details ICQ specific pages
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#include "m_flash.h"
+
+// icqj magic id
+#define FA_MAGIC_ID 0x4943516A
+
+
+extern WORD wListenPort;
+
+extern char* calcMD5Hash(char* szFile);
+extern char* MirandaVersionToString(char* szStr, int v, int m);
+
+extern char* nameXStatus[29];
+
+static BOOL CALLBACK IcqDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BYTE SetValue(HWND hwndDlg, int idCtrl, HANDLE hContact, char *szModule, char *szSetting, WORD type);
+
+#define SVS_NORMAL 0
+#define SVS_ZEROISUNSPEC 2
+#define SVS_IP 3
+#define SVS_SIGNED 6
+#define SVS_ICQVERSION 8
+#define SVS_TIMESTAMP 9
+#define SVS_STATUSID 10
+
+#define SVS_FLAGS 0xFF
+#define SVSF_GRAYED 0x100
+#define SVSF_NORMAL 0x200
+
+
+int OnDetailsInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+
+ if ((!IsICQContact((HANDLE)lParam)) && lParam)
+ return 0;
+
+ odp.cbSize = sizeof(odp);
+ odp.hIcon = NULL;
+ odp.hInstance = hInst;
+ odp.pfnDlgProc = IcqDlgProc;
+ odp.position = -1900000000;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_ICQ);
+ AddUserInfoPageUtf(&odp, wParam, gpszICQProtoName);
+
+ if (((lParam != 0) && gbAvatarsEnabled) || (gbSsiEnabled && gbAvatarsEnabled))
+ {
+ DWORD dwUin;
+ uid_str dwUid;
+
+ if (!ICQGetContactSettingUID((HANDLE)lParam, &dwUin, &dwUid))
+ { // Avatar page only for valid contacts
+ char *szAvtTitle;
+
+ odp.pfnDlgProc = AvatarDlgProc;
+ odp.position = -1899999998;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_AVATAR);
+ if (lParam)
+ szAvtTitle = "Avatar";
+ else
+ szAvtTitle = "%s Avatar";
+
+ AddUserInfoPageUtf(&odp, wParam, szAvtTitle);
+ }
+ }
+
+ InitChangeDetails(wParam, lParam);
+
+ return 0;
+}
+
+
+#define HM_DBCHANGE (WM_USER+200)
+#define HM_PROTOACK (WM_USER+201)
+#define TIMERID 1
+#define TIMEOUT_IGNORE 2
+//#define TIMEOUT_CAPS 3
+#define TIMEOUT_IP 4
+
+typedef struct infoflag_s
+{
+ char *Descr;
+ char *szSetting;
+ DWORD mask;
+} infoflag;
+
+
+struct UserData {
+ HANDLE hContact;
+ DWORD dwUin;
+ HANDLE hEventDbSettingChange;
+ int nTimer;
+ HANDLE hProtoAck;
+ DWORD dwCookie;
+};
+
+
+static infoflag infoflags[] =
+{
+ {"Hidden", NULL, WAS_FOUND},
+ {"WebAware", "WebAware", 0},
+ {"Auth", "AddAuth", 0},
+ {"UTF", NULL, CAPF_UTF},
+ {"MTN", NULL, CAPF_TYPING},
+ {"Xtraz", NULL, CAPF_XTRAZ},
+ {"ServerRelay", NULL, CAPF_SRV_RELAY},
+ {"AIMFile", NULL, CAPF_AIM_FILE},
+ {"Push2Talk", NULL, CAPF_PUSH2TALK},
+ {"ICQLite", NULL, CAPF_ICQ_LITE},
+ {"RTF", NULL, CAPF_RTF},
+ {"XTrazChat", NULL, CAPF_XTRAZ_CHAT},
+ {"VoiceChat", NULL, CAPF_VOICE_CHAT},
+ {"ICQDevil", NULL, CAPF_ICQ_DEVIL},
+ {"DirectConnect", NULL, CAPF_DIRECT},
+};
+static BOOL CALLBACK IcqDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+ struct UserData *dat=(struct UserData*)GetWindowLong(hwndDlg,GWL_USERDATA);
+
+ switch (msg)
+ {
+
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ dat=(struct UserData*)malloc(sizeof(struct UserData));
+ SetWindowLong(hwndDlg,GWL_USERDATA,(LONG)dat);
+
+ dat->hEventDbSettingChange=HookEventMessage(ME_DB_CONTACT_SETTINGCHANGED,hwndDlg,HM_DBCHANGE);
+ dat->hContact=(HANDLE)lParam;
+ dat->nTimer=0;
+ dat->dwUin=ICQGetContactSettingDword(dat->hContact, UNIQUEIDSETTING, 0);
+ dat->hProtoAck=NULL;
+ dat->dwCookie=0;
+ if ((HANDLE)lParam == NULL)
+ {
+
+ ShowWindow(GetDlgItem(hwndDlg, IDC_FLAGS), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_FLAGSTEXT), SW_HIDE);
+ }
+ return TRUE;
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ case PSN_INFOCHANGED:
+ {
+ //HANDLE hContact = (HANDLE)((LPPSHNOTIFY)lParam)->lParam;
+ HANDLE hContact = dat->hContact;
+ WORD flag = SVSF_NORMAL;
+ int was_found = 0;
+ char szUin[20];
+ char szStatus[64];
+
+ mir_snprintf(szUin, 20, "%u", dat->dwUin);
+
+ if (hContact == NULL)
+ {
+ SetValue(hwndDlg, IDC_SYSTEMUPTIME, NULL, gpszICQProtoName, "MemberTS", (icqOnline)?SVS_TIMESTAMP|SVSF_NORMAL:SVS_TIMESTAMP|SVSF_GRAYED);
+ _snprintf(szStatus, sizeof(szStatus), MirandaStatusToString(gnCurrentStatus));
+ SetDlgItemText(hwndDlg, IDC_STATUS, szStatus);
+ }
+ else
+ {
+ WORD wStatus = ICQGetContactSettingWord(hContact, "Status", 0);
+ char str[128] = {0};
+ int i;
+
+ SetValue(hwndDlg, IDC_STATUS, hContact, gpszICQProtoName, "Status", SVS_STATUSID);
+
+ ShowWindow(GetDlgItem(hwndDlg,IDC_GETSTATUS),(ASD)?SW_SHOW:SW_HIDE);
+ //ShowWindow(GetDlgItem(hwndDlg,IDC_GETCAPS),(wStatus != ID_STATUS_OFFLINE)?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_RETRIEVE),(wStatus != ID_STATUS_OFFLINE)?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_IGNORECHECK),(wStatus != ID_STATUS_OFFLINE)?SW_SHOW:SW_HIDE);
+
+ // Subnets
+ //DBGetStaticString(hContact, gpszICQProtoName, "SubNets", str, sizeof(str));
+
+ // Set flags
+ for (i=0; i < sizeof(infoflags)/sizeof(infoflags[0]); i++)
+ {
+ if ((infoflags[i].szSetting && ICQGetContactSettingByte(hContact, infoflags[i].szSetting,0))
+ || (infoflags[i].szSetting == NULL && CheckContactCapabilities(hContact, infoflags[i].mask)))
+ mir_snprintf(str, sizeof(str), (str[0]==0)?"%s%s":"%s, %s", str, Translate(infoflags[i].Descr));
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FLAGSTEXT), (str[0] != 0));
+ if (str[0]==0)
+ SetDlgItemText(hwndDlg, IDC_FLAGSTEXT, ICQTranslate("<not specified>"));
+ else
+ SetDlgItemText(hwndDlg, IDC_FLAGSTEXT, str);
+ // Gray flags if miranda offline
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_FLAGSTEXT), GWL_USERDATA, (!icqOnline && str[0] != 0));
+ }
+
+ //SetValue(hwndDlg, IDC_UIN, hContact, gpszICQProtoName, UNIQUEIDSETTING, 0);
+ SetDlgItemText(hwndDlg, IDC_UIN, szUin);
+
+ // Client version
+ SetValue(hwndDlg, IDC_MIRVER, hContact, gpszICQProtoName, "MirVer", SVS_ZEROISUNSPEC|flag);
+
+ // Proto version.
+ if (!SetValue(hwndDlg, IDC_VERSION, hContact, gpszICQProtoName, "Version", SVS_ZEROISUNSPEC|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_VERSION, hContact, gpszICQProtoName, "OldVersion", SVS_ZEROISUNSPEC|SVSF_GRAYED);
+
+ // IP
+ if (!SetValue(hwndDlg, IDC_IP, hContact, gpszICQProtoName, "IP", SVS_IP|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_IP, hContact, gpszICQProtoName, "OldIP", SVS_IP|SVSF_GRAYED);
+ // Real IP
+ if (!SetValue(hwndDlg, IDC_REALIP, hContact, gpszICQProtoName, "RealIP", SVS_IP|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_REALIP, hContact, gpszICQProtoName, "OldRealIP", SVS_IP|SVSF_GRAYED);
+ // Port
+ if (!SetValue(hwndDlg, IDC_PORT, hContact, gpszICQProtoName, "UserPort", SVS_ZEROISUNSPEC|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_PORT, hContact, gpszICQProtoName, "OldUserPort", SVS_ZEROISUNSPEC|SVSF_GRAYED);
+ // Online since time
+ if (!SetValue(hwndDlg, IDC_ONLINESINCE, hContact, gpszICQProtoName, "LogonTS", SVS_TIMESTAMP|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_ONLINESINCE, hContact, gpszICQProtoName, "OldLogonTS", SVS_TIMESTAMP|SVSF_GRAYED);
+ // Idle time
+ if (was_found)
+ SetValue(hwndDlg, IDC_IDLETIME, hContact, NULL, NULL, 0);
+ else
+ if (!SetValue(hwndDlg, IDC_IDLETIME, hContact, gpszICQProtoName, "IdleTS", SVS_TIMESTAMP|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_IDLETIME, hContact, gpszICQProtoName, "OldIdleTS", SVS_TIMESTAMP|SVSF_GRAYED);
+
+ if (ICQGetContactSettingByte(hContact, "ClientID", 0) == 1)
+ SetValue(hwndDlg, IDC_SYSTEMUPTIME, hContact, NULL, "TickTS", SVS_TIMESTAMP);
+ else
+ SetValue(hwndDlg, IDC_SYSTEMUPTIME, hContact, gpszICQProtoName, "TickTS", SVS_TIMESTAMP);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDCANCEL:
+ SendMessage(GetParent(hwndDlg),msg,wParam,lParam);
+ break;
+
+ case IDC_GETSTATUS:
+ if (icqOnline)
+ icq_GetUserStatus(dat->hContact, 1);
+ break;
+
+ case IDC_RETRIEVE:
+ if (icqOnline && dat->dwUin)
+ {
+
+ int wMessageType = 0;
+
+ switch(ICQGetContactSettingWord(dat->hContact, "Status",ID_STATUS_OFFLINE))
+ {
+ case ID_STATUS_OFFLINE:
+ break;
+ case ID_STATUS_NA:
+ wMessageType = MTYPE_AUTONA;
+ break;
+ case ID_STATUS_OCCUPIED:
+ wMessageType = MTYPE_AUTOBUSY;
+ break;
+ case ID_STATUS_DND:
+ wMessageType = MTYPE_AUTODND;
+ break;
+ case ID_STATUS_FREECHAT:
+ wMessageType = MTYPE_AUTOFFC;
+ break;
+ case ID_STATUS_AWAY:
+ default:
+ wMessageType = MTYPE_AUTOAWAY;
+ break;
+ }
+
+ icq_sendGetAwayMsgServ(dat->dwUin, wMessageType, (WORD)(ICQGetContactSettingWord(dat->hContact, "Version", 0)==9?9:ICQ_VERSION));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RETRIEVE), FALSE);
+ SetTimer(hwndDlg, TIMEOUT_IP, 10000, NULL);
+
+ }
+ break;
+
+ case IDC_IGNORECHECK:
+ if (icqOnline &&
+ ICQGetContactSettingWord(dat->hContact, "Status", 0) != ID_STATUS_OFFLINE)
+ {
+ message_cookie_data* pCookieData;
+
+ if (!dat->hProtoAck)
+ dat->hProtoAck = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_PROTOACK);
+
+ SetDlgItemText(hwndDlg, IDC_IGNORE, Translate("Checking..."));
+
+ pCookieData = malloc(sizeof(message_cookie_data));
+ pCookieData->bMessageType = MTYPE_PLAIN;
+ pCookieData->nAckType = ACKTYPE_SERVER;
+ dat->dwCookie = icq_SendChannel4Message(dat->dwUin, 0, 0, "", pCookieData);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IGNORECHECK), FALSE);
+ SetTimer(hwndDlg, TIMEOUT_IGNORE, 10000, NULL);
+ }
+ break;
+ }
+ break;
+ case HM_DBCHANGE:
+ {
+ DBCONTACTWRITESETTING *cws=(DBCONTACTWRITESETTING*)lParam;
+
+ if (!dat->nTimer &&
+ (cws->szModule != NULL) &&
+ (dat->hContact == (HANDLE)wParam) &&
+ !strcmp(cws->szModule, gpszICQProtoName))
+ {
+ dat->nTimer = 1;
+ SetTimer(hwndDlg, TIMERID, 1000, NULL);
+ }
+ }
+ break;
+
+ case HM_PROTOACK:
+ {
+ ACKDATA *ack = (ACKDATA*)lParam;
+
+ if (!ack || !ack->szModule ||
+ ack->hProcess != (HANDLE)dat->dwCookie ||
+ ack->hContact != dat->hContact ||
+ strcmp(ack->szModule, gpszICQProtoName))
+ break;
+
+ if (dat->hProtoAck)
+ {
+ UnhookEvent(dat->hProtoAck);
+ dat->hProtoAck = NULL;
+ }
+
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ SetDlgItemText(hwndDlg, IDC_IGNORE, Translate("Msg Accepted!"));
+ Netlib_Logf(ghServerNetlibUser, "User %u accepts your messages", dat->dwUin);
+ }
+ else
+ if (ack->result == ACKRESULT_FAILED)
+ {
+ SetDlgItemText(hwndDlg, IDC_IGNORE, Translate("Msg Ignored!"));
+ Netlib_Logf(ghServerNetlibUser, "User %u ignores your messages", dat->dwUin);
+ }
+
+ }
+ break;
+
+ case WM_TIMER:
+ if (wParam==TIMERID)
+ {
+ PSHNOTIFY pshn;
+ pshn.hdr.code=PSN_INFOCHANGED;
+ pshn.hdr.hwndFrom=hwndDlg;
+ pshn.hdr.idFrom=0;
+ pshn.lParam=(LPARAM)wParam;
+
+ KillTimer(hwndDlg, TIMERID);
+ dat->nTimer = 0;
+
+ SendMessage(hwndDlg,WM_NOTIFY,0,(LPARAM)&pshn);
+ }
+ else
+ if (wParam==TIMEOUT_IGNORE)
+ {
+ KillTimer(hwndDlg, TIMEOUT_IGNORE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IGNORECHECK), TRUE);
+ }
+ else
+ if (wParam==TIMEOUT_IP)
+ {
+ KillTimer(hwndDlg, TIMEOUT_IP);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RETRIEVE), TRUE);
+ }
+ break;
+
+ case WM_DESTROY:
+ if (dat->hEventDbSettingChange)
+ UnhookEvent(dat->hEventDbSettingChange);
+ if (dat->nTimer)
+ KillTimer(hwndDlg, TIMERID);
+ if (dat->hProtoAck)
+ UnhookEvent(dat->hProtoAck);
+ free(dat);
+ break;
+ }
+
+ return FALSE;
+}
+
+typedef struct AvtDlgProcData_t
+{
+ HANDLE hContact;
+ HANDLE hEventHook;
+ HWND hFlashAvatar;
+ HBITMAP hImageAvatar;
+} AvtDlgProcData;
+
+#define HM_REBIND_AVATAR (WM_USER + 1024)
+
+static char* ChooseAvatarFileName()
+{
+ char* szDest = (char*)SAFE_MALLOC(MAX_PATH+0x10);
+ char str[MAX_PATH];
+ char szFilter[512];
+ OPENFILENAME ofn = {0};
+
+ str[0] = 0;
+ CallService(MS_UTILS_GETBITMAPFILTERSTRINGS,sizeof(szFilter),(LPARAM)szFilter);
+ if (ServiceExists(MS_FAVATAR_GETINFO)) //Flash avatars are supported
+ {
+ char * allimages;
+ char b2[255];
+ int l,i;
+ char flashfilt[520]={0};
+ allimages=szFilter+strlen(szFilter)+1;
+ l=sizeof(szFilter)-strlen(szFilter)-1;
+ sprintf(flashfilt,"%s (%s;*.XML)",Translate("All Bitmaps"),allimages);
+ memcpy(flashfilt+strlen(flashfilt)+1,"*.XML;",6);
+ memcpy(flashfilt+6+strlen(flashfilt)+1,allimages,l-(6+strlen(flashfilt)+1));
+ {
+ int z0=0,z1=0;
+ for (i=0;i<sizeof(flashfilt)-1;i++)
+ {
+ if (flashfilt[i]=='\0' && flashfilt[i+1]!='\0')
+ {
+ if (z1>0) z0=z1;
+ z1=i;
+ }
+ if (flashfilt[i]=='\0' && flashfilt[i+1]=='\0')
+ {
+ sprintf(b2,"%s (*.xml)",Translate("flash avatars"));
+ memcpy(flashfilt+z0+1,b2,strlen(b2)+1);
+ z0=z0+strlen(b2)+1;
+ memcpy(flashfilt+z0+1,"*.XML\0",6);
+ z0+=6;
+ sprintf(b2,"%s(*.*)",Translate("All files"));
+ memcpy(flashfilt+z0+1,b2,strlen(b2)+1);
+ z0=z0+strlen(b2)+1;
+ memcpy(flashfilt+z0+1,"*\0\0",4);
+ memcpy(szFilter,flashfilt,sizeof(szFilter));
+ break;
+ }
+ }
+ }
+ }
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.lpstrFilter = szFilter;
+ ofn.lpstrFile = szDest;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = "jpg";
+ if (!GetOpenFileName(&ofn))
+ {
+ SAFE_FREE(&szDest);
+ return NULL;
+ }
+
+ return szDest;
+}
+
+
+
+static void PrepareFlashAvatar(HWND hwndDlg, AvtDlgProcData* pData)
+{
+ FLASHAVATAR fa = {0};
+
+ fa.hContact = pData->hContact;
+ fa.cProto = gpszICQProtoName;
+ fa.id = FA_MAGIC_ID;
+ CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0);
+ if (fa.hWindow)
+ {
+ pData->hFlashAvatar = fa.hWindow;
+ SetParent(fa.hWindow, GetDlgItem(hwndDlg, IDC_AVATAR));
+ }
+ else
+ {
+ fa.hParentWindow = GetDlgItem(hwndDlg, IDC_AVATAR);
+ CallService(MS_FAVATAR_MAKE, (WPARAM)&fa, 0);
+ if (fa.hWindow)
+ pData->hFlashAvatar = fa.hWindow;
+ }
+}
+
+
+
+static void ReleaseFlashAvatar(AvtDlgProcData* pData)
+{
+ if (pData->hFlashAvatar)
+ { // release expired flash avatar object
+ FLASHAVATAR fa;
+
+ fa.hContact = pData->hContact;
+ fa.cProto = gpszICQProtoName;
+ fa.id = FA_MAGIC_ID; // icqj magic id
+ CallService(MS_FAVATAR_DESTROY, (WPARAM)&fa, 0);
+ pData->hFlashAvatar = NULL;
+ }
+}
+
+
+
+static void PrepareImageAvatar(HWND hwndDlg, AvtDlgProcData* pData, char* szFile)
+{
+ pData->hImageAvatar = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szFile);
+
+ SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)pData->hImageAvatar);
+}
+
+
+
+static void ReleaseImageAvatar(HWND hwndDlg, AvtDlgProcData* pData)
+{
+ if (pData->hImageAvatar)
+ {
+ HBITMAP avt = (HBITMAP)SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
+
+ // force re-draw avatar window
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, FALSE);
+
+ // in XP you can get different image, and it is leaked if not Destroy()ed
+ if (avt != pData->hImageAvatar)
+ DeleteObject(avt);
+
+ DeleteObject(pData->hImageAvatar);
+ pData->hImageAvatar = NULL;
+ }
+}
+
+
+
+static BOOL CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ {
+ DBVARIANT dbvHash;
+ AvtDlgProcData* pData = (AvtDlgProcData*)SAFE_MALLOC(sizeof(AvtDlgProcData));
+ DWORD dwUIN;
+ uid_str szUID;
+ char szAvatar[MAX_PATH];
+ DWORD dwPaFormat;
+ int bValid = 0;
+
+ pData->hContact = (HANDLE)lParam;
+
+ if (pData->hContact)
+ pData->hEventHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_REBIND_AVATAR);
+ else
+ {
+ ShowWindow(GetDlgItem(hwndDlg, IDC_SETAVATAR), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_DELETEAVATAR), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, -1), SW_SHOW);
+ if (!icqOnline)
+ {
+ EnableDlgItem(hwndDlg, IDC_SETAVATAR, FALSE);
+ EnableDlgItem(hwndDlg, IDC_DELETEAVATAR, FALSE);
+ }
+ }
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)pData);
+
+ if (!ICQGetContactSettingUID((HANDLE)lParam, &dwUIN, &szUID))
+ {
+ if (!ICQGetContactSetting((HANDLE)lParam, "AvatarHash", &dbvHash))
+ {
+ dwPaFormat = ICQGetContactSettingByte((HANDLE)lParam, "AvatarType", PA_FORMAT_UNKNOWN);
+ if (!pData->hContact || (dwPaFormat != PA_FORMAT_UNKNOWN))
+ { // we do not know avatar format, so neither filename is known, not valid
+ if (pData->hContact)
+ GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, szAvatar, 255);
+ else
+ { // owner's avatar
+ char* file = loadMyAvatarFileName();
+
+ if (file)
+ {
+ strcpy(szAvatar, file);
+ SAFE_FREE(&file);
+ if (dbvHash.pbVal[1] == 8) // we do this by hand, as owner's format is not saved
+ dwPaFormat = PA_FORMAT_XML;
+ }
+ else
+ szAvatar[0] = '\0';
+ }
+
+ if (!pData->hContact || !IsAvatarSaved((HANDLE)lParam, dbvHash.pbVal))
+ { // if the file exists, we know we have the current avatar
+ if (!access(szAvatar, 0)) bValid = 1;
+ }
+ }
+ }
+ else
+ return TRUE;
+
+ if (bValid)
+ { //load avatar
+ if ((dwPaFormat == PA_FORMAT_XML || dwPaFormat == PA_FORMAT_SWF) && ServiceExists(MS_FAVATAR_GETINFO))
+ { // flash avatar and we have FlashAvatars installed, init flash avatar
+ PrepareFlashAvatar(hwndDlg, pData);
+ }
+ else
+ { // static avatar processing
+ PrepareImageAvatar(hwndDlg, pData, szAvatar);
+ }
+ }
+ else if (pData->hContact) // only retrieve users avatars
+ {
+ GetAvatarFileName(dwUIN, szUID, szAvatar, 255);
+ GetAvatarData((HANDLE)lParam, dwUIN, szUID, dbvHash.pbVal, 0x14, szAvatar);
+ }
+ }
+
+ ICQFreeVariant(&dbvHash);
+ }
+ return TRUE;
+
+ case HM_REBIND_AVATAR:
+ {
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+ ACKDATA* ack = (ACKDATA*)lParam;
+
+ if (!pData->hContact) break; // we do not use this for us
+
+ if (ack->type == ACKTYPE_AVATAR && ack->hContact == pData->hContact)
+ {
+ if (ack->result == ACKRESULT_SUCCESS)
+ { // load avatar
+ PROTO_AVATAR_INFORMATION* AI = (PROTO_AVATAR_INFORMATION*)ack->hProcess;
+
+ ReleaseFlashAvatar(pData);
+ ReleaseImageAvatar(hwndDlg, pData);
+
+ if ((AI->format == PA_FORMAT_XML || AI->format == PA_FORMAT_SWF) && ServiceExists(MS_FAVATAR_GETINFO))
+ { // flash avatar and we have FlashAvatars installed, init flash avatar
+ PrepareFlashAvatar(hwndDlg, pData);
+ }
+ else
+ { // process image avatar
+ PrepareImageAvatar(hwndDlg, pData, AI->filename);
+ }
+ }
+ else if (ack->result == ACKRESULT_STATUS)
+ { // contact has changed avatar
+ DWORD dwUIN;
+ uid_str szUID;
+ DBVARIANT dbvHash;
+
+ if (!ICQGetContactSettingUID(pData->hContact, &dwUIN, &szUID))
+ {
+ if (!ICQGetContactSetting(pData->hContact, "AvatarHash", &dbvHash))
+ {
+ char szAvatar[MAX_PATH];
+
+ GetAvatarFileName(dwUIN, szUID, szAvatar, 255);
+ GetAvatarData(pData->hContact, dwUIN, szUID, dbvHash.pbVal, 0x14, szAvatar);
+ }
+ ICQFreeVariant(&dbvHash);
+ }
+ }
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_SETAVATAR:
+ {
+ char* szFile;
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ if (szFile = ChooseAvatarFileName())
+ { // user selected file for his avatar
+ DWORD dwPaFormat = DetectAvatarFormat(szFile);
+
+ if (dwPaFormat == PA_FORMAT_XML || dwPaFormat == PA_FORMAT_JPEG || dwPaFormat == PA_FORMAT_GIF || dwPaFormat == PA_FORMAT_BMP)
+ { // a valid file
+ if (!IcqSetMyAvatar(0, (LPARAM)szFile)) // set avatar
+ {
+ ReleaseFlashAvatar(pData);
+ ReleaseImageAvatar(hwndDlg, pData);
+
+ if (dwPaFormat != PA_FORMAT_XML || !ServiceExists(MS_FAVATAR_GETINFO))
+ { // it is not flash
+ PrepareImageAvatar(hwndDlg, pData, szFile);
+ }
+ else
+ { // is is flash load it
+ PrepareFlashAvatar(hwndDlg, pData);
+ }
+ }
+ }
+ SAFE_FREE(&szFile);
+ }
+ }
+ break;
+ case IDC_DELETEAVATAR:
+ {
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ ReleaseFlashAvatar(pData);
+ ReleaseImageAvatar(hwndDlg, pData);
+
+ IcqSetMyAvatar(0, 0); // clear hash on server
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ AvtDlgProcData* pData = (AvtDlgProcData*)GetWindowLong(hwndDlg, GWL_USERDATA);
+ if (pData->hContact)
+ UnhookEvent(pData->hEventHook);
+
+ ReleaseFlashAvatar(pData);
+ ReleaseImageAvatar(hwndDlg, pData);
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)0);
+ SAFE_FREE(&pData);
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+
+static BYTE SetValue(HWND hwndDlg, int idCtrl, HANDLE hContact, char* szModule, char* szSetting, WORD type)
+{
+ DBVARIANT dbv = {0};
+ char str[MAX_PATH];
+ char* pstr = NULL;
+ int unspecified = 0;
+ int special = type & SVS_FLAGS;
+ int bUtf = 0, bDbv = 0, bAlloc = 0;
+
+ dbv.type = DBVT_DELETED;
+
+ if ((hContact == NULL) && ((int)szModule<0x100))
+ {
+ dbv.type = (BYTE)szModule;
+
+ switch((int)szModule)
+ {
+ case DBVT_BYTE:
+ dbv.cVal = (BYTE)szSetting;
+ break;
+ case DBVT_WORD:
+ dbv.wVal = (WORD)szSetting;
+ break;
+ case DBVT_DWORD:
+ dbv.dVal = (DWORD)szSetting;
+ break;
+ case DBVT_ASCIIZ:
+ dbv.pszVal = pstr = szSetting;
+ break;
+ default:
+ unspecified = 1;
+ dbv.type = DBVT_DELETED;
+ }
+ }
+ else
+ {
+ if (szModule == NULL)
+ unspecified = 1;
+ else
+ {
+ unspecified = DBGetContactSetting(hContact, szModule, szSetting, &dbv);
+ bDbv = 1;
+ }
+ }
+
+ if (!unspecified)
+ {
+ switch (dbv.type)
+ {
+
+ case DBVT_BYTE:
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.bVal == 0);
+ pstr = itoa(special == SVS_SIGNED ? dbv.cVal:dbv.bVal, str, 10);
+ break;
+
+ case DBVT_WORD:
+ if (special == SVS_ICQVERSION)
+ {
+ if (dbv.wVal != 0)
+ {
+ char szExtra[80];
+
+ null_snprintf(str, 250, "%d", dbv.wVal);
+ pstr = str;
+
+ if (hContact && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD))
+ {
+ ICQTranslateUtfStatic(" (DC Established)", szExtra);
+ strcat(str, szExtra);
+ bUtf = 1;
+ }
+ }
+ else
+ unspecified = 1;
+ }
+ else if (special == SVS_STATUSID)
+ {
+ char* pXName;
+ char* pszStatus;
+ BYTE bXStatus = ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, 0);
+
+ pszStatus = MirandaStatusToStringUtf(dbv.wVal);
+ if (bXStatus)
+ {
+ pXName = ICQGetContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, "");
+ if (!strlennull(pXName))
+ { // give default name
+ pXName = ICQTranslateUtf(nameXStatus[bXStatus-1]);
+ }
+ null_snprintf(str, sizeof(str), "%s (%s)", pszStatus, pXName);
+ SAFE_FREE(&pXName);
+ }
+ else
+ null_snprintf(str, sizeof(str), pszStatus);
+
+ bUtf = 1;
+ SAFE_FREE(&pszStatus);
+ pstr = str;
+ unspecified = 0;
+ }
+ else
+ {
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.wVal == 0);
+ pstr = itoa(special == SVS_SIGNED ? dbv.sVal:dbv.wVal, str, 10);
+ }
+ break;
+
+ case DBVT_DWORD:
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.dVal == 0);
+ if (special == SVS_IP)
+ {
+ struct in_addr ia;
+ ia.S_un.S_addr = htonl(dbv.dVal);
+ pstr = inet_ntoa(ia);
+ if (dbv.dVal == 0)
+ unspecified=1;
+ }
+ else if (special == SVS_TIMESTAMP)
+ {
+ if (dbv.dVal == 0)
+ unspecified = 1;
+ else
+ {
+ pstr = asctime(localtime(&dbv.dVal));
+ pstr[24] = '\0'; // Remove newline
+ }
+ }
+ else
+ pstr = itoa(special == SVS_SIGNED ? dbv.lVal:dbv.dVal, str, 10);
+ break;
+
+ case DBVT_ASCIIZ:
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.pszVal[0] == '\0');
+ if (!unspecified && pstr != szSetting)
+ {
+ pstr = UniGetContactSettingUtf(hContact, szModule, szSetting, NULL);
+ bUtf = 1;
+ bAlloc = 1;
+ }
+ if (idCtrl == IDC_UIN)
+ SetDlgItemTextUtf(hwndDlg, IDC_UINSTATIC, ICQTranslateUtfStatic("ScreenName:", str));
+ break;
+
+ default:
+ pstr = str;
+ lstrcpy(str,"???");
+ break;
+ }
+ }
+
+ EnableDlgItem(hwndDlg, idCtrl, !unspecified);
+ if (unspecified)
+ SetDlgItemTextUtf(hwndDlg, idCtrl, ICQTranslateUtfStatic("<not specified>", str));
+ else if (bUtf)
+ SetDlgItemTextUtf(hwndDlg, idCtrl, pstr);
+ else
+ SetDlgItemText(hwndDlg, idCtrl, pstr);
+
+ if (bDbv)
+ ICQFreeVariant(&dbv);
+
+ if (bAlloc)
+ SAFE_FREE(&pstr);
+
+ if (type > SVS_FLAGS)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, idCtrl), !(type & SVSF_GRAYED));
+ }
+ return !unspecified;
+}
diff --git a/icqj_mod/UpgradeLog.XML b/icqj_mod/UpgradeLog.XML new file mode 100644 index 0000000..5a5da94 --- /dev/null +++ b/icqj_mod/UpgradeLog.XML @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type='text/xsl' href='_UpgradeReport_Files/UpgradeReport.xslt'?><UpgradeLog>
+<Properties><Property Name="Solution" Value="icqoscar8">
+</Property><Property Name="Solution File" Value="F:\svn\miranda\miranda\protocols\ICQJ_BM\icqoscar8.sln">
+</Property><Property Name="Date" Value="13 июля 2006 г.">
+</Property><Property Name="Time" Value="21:01">
+</Property></Properties><Event ErrorLevel="0" Project="icqoscar8" Source="icqoscar8.vcproj" Description="Visual C++ now supports a secure version of the C Runtime Library. Use of this library is turned on by default. You may see some warnings about deprecated functions when you build your project. It is advised that you correct these warnings, in order to make your code more secure.">
+</Event><Event ErrorLevel="0" Project="icqoscar8" Source="icqoscar8.vcproj" Description="The C/C++ compiler default settings have been modified to be more compliant with ISO Standard C++. Included in those changes are enforcing Standard C++ for loop scoping and supporting wchar_t as a native type. These changes may cause existing code to no longer compile without changes to the code or the compiler options with which it is built.">
+</Event><Event ErrorLevel="1" Project="icqoscar8" Source="icqoscar8.vcproj" Description="The C/C++ compiler switch /YX is lo longer supported. /YX has been removed from your project settings.">
+</Event><Event ErrorLevel="1" Project="icqoscar8" Source="icqoscar8.vcproj" Description="Due to the requirement that Visual C++ projects produce an embedded (by default) Windows SxS manifest, manifest files in the project are automatically excluded from building with the Manifest Tool. It is recommended that the dependency information contained in any manifest files be converted to "#pragma comment(linker,"<insert dependency here>")" in a header file that is included from your source code. If your project already embeds a manifest in the RT_MANIFEST resource section through a resource (.rc) file, the line will need to be commented out before the project will build correctly.">
+</Event><Event ErrorLevel="1" Project="icqoscar8" Source="icqoscar8.vcproj" Description="Due to a conformance change in the C++ compiler, code change may be required before your project will build without errors. Previous versions of the C++ compiler allowed specification of member function pointers by member function name (e.g. MemberFunctionName). The C++ standard requires a fully qualified name with the use of the address-of operator (e.g. &ClassName::MemberFunctionName). If your project contains forms or controls used in the Windows Forms Designer, you may have to change code in InitializeComponent because the designer generated code used the non-conformant syntax in delegate construction (used in event handlers).">
+</Event><Event ErrorLevel="0" Project="icqoscar8" Source="icqoscar8.vcproj" Description="Project upgraded successfully.">
+</Event><Event ErrorLevel="3" Project="icqoscar8" Source="icqoscar8.vcproj" Description="Converted">
+</Event><Event ErrorLevel="0" Project="" Source="icqoscar8.sln" Description="Solution converted successfully">
+</Event><Event ErrorLevel="3" Project="" Source="icqoscar8.sln" Description="Converted">
+</Event></UpgradeLog>
\ No newline at end of file diff --git a/icqj_mod/capabilities.c b/icqj_mod/capabilities.c new file mode 100644 index 0000000..d1c933c --- /dev/null +++ b/icqj_mod/capabilities.c @@ -0,0 +1,177 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/capabilities.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Contains helper functions to handle oscar user capabilities. Scanning and
+// adding capabilities are assumed to be more timecritical than looking up
+// capabilites. During the login sequence there could possibly be many hundred
+// scans but only a few lookups. So when you add or change something in this
+// code you must have this in mind, dont do anything that will slow down the
+// adding process too much.
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+typedef struct icq_capability_s
+{
+ DWORD fdwMirandaID; // A bitmask, we use it in order to save database space
+ BYTE CapCLSID[BINARY_CAP_SIZE]; // A binary representation of a oscar capability
+} icq_capability;
+
+static icq_capability CapabilityRecord[] =
+{
+ {CAPF_SRV_RELAY, {CAP_SRV_RELAY}},
+ {CAPF_UTF, {CAP_UTF }},
+ {CAPF_TYPING, {CAP_TYPING }},
+ {CAPF_XTRAZ, {CAP_XTRAZ }},
+ {CAPF_AIM_FILE, {CAP_AIM_FILE }},
+ {CAPF_PUSH2TALK, {CAP_PUSH2TALK }},
+ {CAPF_ICQ_LITE, {CAP_ICQ_LITE }},
+ {CAPF_RTF, {CAP_RTF }},
+ {CAPF_XTRAZ_CHAT, {CAP_XTRAZ_CHAT}},
+ {CAPF_VOICE_CHAT, {CAP_VOICE_CHAT}},
+ {CAPF_ICQ_DEVIL, {CAP_ICQ_DEVIL }},
+ {CAPF_DIRECT, {CAP_DIRECT }}
+};
+
+
+
+// Deletes all oscar capabilities for a given contact
+void ClearAllContactCapabilities(HANDLE hContact)
+{
+ ICQWriteContactSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+}
+
+
+
+// Deletes one or many oscar capabilities for a given contact
+void ClearContactCapabilities(HANDLE hContact, DWORD fdwCapabilities)
+{
+ DWORD fdwContactCaps;
+
+
+ // Get current capability flags
+ fdwContactCaps = ICQGetContactSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+
+ // Clear unwanted capabilities
+ fdwContactCaps &= ~fdwCapabilities;
+
+ // And write it back to disk
+ ICQWriteContactSettingDword(hContact, DBSETTING_CAPABILITIES, fdwContactCaps);
+}
+
+
+
+// Sets one or many oscar capabilities for a given contact
+void SetContactCapabilities(HANDLE hContact, DWORD fdwCapabilities)
+{
+ DWORD fdwContactCaps;
+
+
+ // Get current capability flags
+ fdwContactCaps = ICQGetContactSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+
+ // Update them
+ fdwContactCaps |= fdwCapabilities;
+
+ // And write it back to disk
+ ICQWriteContactSettingDword(hContact, DBSETTING_CAPABILITIES, fdwContactCaps);
+}
+
+
+
+// Returns true if the given contact supports the requested capabilites
+BOOL CheckContactCapabilities(HANDLE hContact, DWORD fdwCapabilities)
+{
+ DWORD fdwContactCaps;
+
+
+ // Get current capability flags
+ fdwContactCaps = ICQGetContactSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+
+ // Check if all requested capabilities are supported
+ if ((fdwContactCaps & fdwCapabilities) == fdwCapabilities)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+
+// Scans a binary buffer for oscar capabilities and adds them to the contact.
+// You probably want to call ClearAllContactCapabilities() first.
+void AddCapabilitiesFromBuffer(HANDLE hContact, BYTE* pbyBuffer, int nLength)
+{
+ DWORD fdwContactCaps;
+ int iCapability;
+ int nIndex;
+ int nRecordSize;
+
+
+ // Calculate the number of records
+ nRecordSize = sizeof(CapabilityRecord)/sizeof(icq_capability);
+
+ // Get current capability flags
+ fdwContactCaps = ICQGetContactSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+
+ // Loop over all capabilities in the buffer and
+ // compare them to our own record of capabilities
+ for (iCapability = 0; (iCapability + BINARY_CAP_SIZE) <= nLength; iCapability += BINARY_CAP_SIZE)
+ {
+ BOOL knownCAP = FALSE;
+ for (nIndex = 0; nIndex < nRecordSize; nIndex++)
+ {
+ if (!memcmp(pbyBuffer + iCapability, CapabilityRecord[nIndex].CapCLSID, BINARY_CAP_SIZE))
+ {
+ // Match
+ fdwContactCaps |= CapabilityRecord[nIndex].fdwMirandaID;
+ knownCAP = TRUE;
+ break;
+ }
+ }
+ if(!knownCAP) {
+ char szCap[64];
+ int i;
+ for (i = 0; i < 16; i++)
+ wsprintf(szCap+i*3, " %02X", (BYTE)((BYTE*)(pbyBuffer + iCapability)[i]));
+ Netlib_Logf(ghServerNetlibUser, "Found unknown CAP%s", szCap);
+ }
+ }
+
+ // And write it back to disk
+ ICQWriteContactSettingDword(hContact, DBSETTING_CAPABILITIES, fdwContactCaps);
+}
diff --git a/icqj_mod/capabilities.h b/icqj_mod/capabilities.h new file mode 100644 index 0000000..b7c34ae --- /dev/null +++ b/icqj_mod/capabilities.h @@ -0,0 +1,51 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/capabilities.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Contains helper functions to handle oscar user capabilities.
+//
+// -----------------------------------------------------------------------------
+
+
+
+// Deletes all oscar capabilities for a given contact.
+void ClearAllContactCapabilities(HANDLE hContact);
+
+// Deletes one or many oscar capabilities for a given contact.
+void ClearContactCapabilities(HANDLE hContact, DWORD fdwCapabilities);
+
+// Sets one or many oscar capabilities for a given contact.
+void SetContactCapabilities(HANDLE hContact, DWORD fdwCapabilities);
+
+// Returns true if the given contact supports the requested capabilites.
+BOOL CheckContactCapabilities(HANDLE hContact, DWORD fdwCapabilities);
+
+// Scans a binary buffer for oscar capabilities and adds them to the db.
+void AddCapabilitiesFromBuffer(HANDLE hContact, BYTE* pbyBuffer, int nLength);
diff --git a/icqj_mod/chan_01login.c b/icqj_mod/chan_01login.c new file mode 100644 index 0000000..a330324 --- /dev/null +++ b/icqj_mod/chan_01login.c @@ -0,0 +1,115 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/chan_01login.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern WORD wLocalSequence;
+
+
+void handleLoginChannel(unsigned char *buf, WORD datalen, serverthread_info *info)
+{
+ icq_packet packet;
+
+ // isLoginServer is "1" if we just received SRV_HELLO
+ if (info->isLoginServer)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Received SRV_HELLO from login server");
+#endif
+ if (gbSecureLogin)
+ {
+ char szUin[UINMAXLEN];
+ WORD wUinLen;
+
+#ifdef _DEBUG
+ NetLog_Server("Sending %s to login server", "CLI_HELLO");
+#endif
+ packet.wLen = 4;
+ write_flap(&packet, ICQ_LOGIN_CHAN);
+ packDWord(&packet, 0x00000001);
+ sendServPacket(&packet); // greet login server
+
+ wUinLen = strlennull(strUID(dwLocalUIN, szUin));
+#ifdef _DEBUG
+ NetLog_Server("Sending %s to login server", "ICQ_SIGNON_AUTH_REQUEST");
+#endif
+
+ serverPacketInit(&packet, (WORD)(18 + wUinLen));
+ packFNACHeaderFull(&packet, ICQ_AUTHORIZATION_FAMILY, ICQ_SIGNON_AUTH_REQUEST, 0, 0);
+ packTLV(&packet, 0x0001, wUinLen, szUin);
+ packDWord(&packet, 0x004B0000);
+ sendServPacket(&packet); // request login digest
+ }
+ else
+ {
+ sendClientAuth(info->szAuthKey, info->wAuthKeyLen, FALSE);
+#ifdef _DEBUG
+ NetLog_Server("Sent CLI_IDENT to %s server", "login");
+#endif
+ }
+
+ info->isLoginServer = 0;
+ if (info->cookieDataLen)
+ {
+ SAFE_FREE(&info->cookieData);
+ info->cookieDataLen = 0;
+ }
+ }
+ else
+ {
+ if (info->cookieDataLen)
+ {
+ wLocalSequence = (WORD)RandRange(0, 0xffff);
+
+ serverCookieInit(&packet, info->cookieData, (WORD)info->cookieDataLen);
+ sendServPacket(&packet);
+
+#ifdef _DEBUG
+ NetLog_Server("Sent CLI_IDENT to %s server", "communication");
+#endif
+
+ SAFE_FREE(&info->cookieData);
+ info->cookieDataLen = 0;
+ }
+ else
+ {
+ // We need a cookie to identify us to the communication server
+ NetLog_Server("Something went wrong...");
+ }
+ }
+}
diff --git a/icqj_mod/chan_02data.c b/icqj_mod/chan_02data.c new file mode 100644 index 0000000..d916746 --- /dev/null +++ b/icqj_mod/chan_02data.c @@ -0,0 +1,216 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/chan_02data.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Handle channel 2 (Data) packets
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void handleDataChannel(unsigned char *pBuffer, WORD wBufferLength, serverthread_info *info)
+{
+ snac_header snacHeader = {0};
+
+
+ if (!unpackSnacHeader(&snacHeader, &pBuffer, &wBufferLength) || !snacHeader.bValid)
+ {
+ NetLog_Server("Error: Failed to parse SNAC header");
+ }
+ else
+ {
+#ifdef _DEBUG
+ NetLog_Server(" Received SNAC(x%02X,x%02X)", snacHeader.wFamily, snacHeader.wSubtype);
+#endif
+
+ switch (snacHeader.wFamily)
+ {
+
+ case ICQ_SERVICE_FAMILY:
+ handleServiceFam(pBuffer, wBufferLength, &snacHeader, info);
+ break;
+
+ case ICQ_LOCATION_FAMILY:
+ handleLocationFam(pBuffer, wBufferLength, &snacHeader);
+ break;
+
+ case ICQ_BUDDY_FAMILY:
+ handleBuddyFam(pBuffer, wBufferLength, &snacHeader);
+ break;
+
+ case ICQ_MSG_FAMILY:
+ handleMsgFam(pBuffer, wBufferLength, &snacHeader);
+ break;
+
+ case ICQ_BOS_FAMILY:
+ handleBosFam(pBuffer, wBufferLength, &snacHeader);
+ break;
+
+ case ICQ_LOOKUP_FAMILY:
+ handleLookupFam(pBuffer, wBufferLength, &snacHeader);
+ break;
+
+ case ICQ_STATS_FAMILY:
+ handleStatusFam(pBuffer, wBufferLength, &snacHeader);
+ break;
+
+ case ICQ_LISTS_FAMILY:
+ handleServClistFam(pBuffer, wBufferLength, &snacHeader, info);
+ break;
+
+ case ICQ_EXTENSIONS_FAMILY:
+ handleIcqExtensionsFam(pBuffer, wBufferLength, &snacHeader);
+ break;
+
+ case ICQ_AUTHORIZATION_FAMILY:
+ handleAuthorizationFam(pBuffer, wBufferLength, &snacHeader, info);
+ break;
+
+ default:
+ NetLog_Server("Ignoring SNAC(x%02X,x%02X) - FAMILYx%02X not implemented", snacHeader.wFamily, snacHeader.wSubtype, snacHeader.wFamily);
+ break;
+
+ }
+ }
+}
+
+
+
+int unpackSnacHeader(snac_header* pSnacHeader, unsigned char **pBuffer, WORD* pwBufferLength)
+{
+ WORD wRef1, wRef2;
+
+ // Check header
+ if (!pSnacHeader) return 0;
+
+ // 10 bytes is the minimum size of a header
+ if (*pwBufferLength < 10)
+ {
+ // Buffer overflow
+ pSnacHeader->bValid = FALSE;
+ return 1;
+ }
+
+ // Unpack all the standard data
+ unpackWord(pBuffer, &(pSnacHeader->wFamily));
+ unpackWord(pBuffer, &(pSnacHeader->wSubtype));
+ unpackWord(pBuffer, &(pSnacHeader->wFlags));
+ unpackWord(pBuffer, &wRef1); // unpack reference id (sequence)
+ unpackWord(pBuffer, &wRef2); // command
+ pSnacHeader->dwRef = wRef1 | (wRef2<<0x10);
+
+ *pwBufferLength -= 10;
+
+ // If flag bit 15 is set, we also have a version tag
+ // (...at least that is what I think it is)
+ if (pSnacHeader->wFlags & 0x8000)
+ {
+ if (*pwBufferLength >= 2)
+ {
+ WORD wExtraBytes = 0;
+
+ unpackWord(pBuffer, &wExtraBytes);
+ *pwBufferLength -= 2;
+
+ if (*pwBufferLength >= wExtraBytes)
+ {
+ if (wExtraBytes == 6)
+ {
+ *pBuffer += 4; // TLV type and length?
+ unpackWord(pBuffer, &(pSnacHeader->wVersion));
+ *pwBufferLength -= 6;
+ pSnacHeader->bValid = TRUE;
+ }
+ else
+ {
+ *pwBufferLength -= wExtraBytes;
+ *pBuffer += wExtraBytes;
+ pSnacHeader->bValid = TRUE;
+ }
+ }
+ else
+ {
+ // Buffer overflow
+ pSnacHeader->bValid = FALSE;
+ }
+ }
+ else
+ {
+ // Buffer overflow
+ pSnacHeader->bValid = FALSE;
+ }
+ }
+ else
+ {
+ pSnacHeader->bValid = TRUE;
+ }
+
+ return 1;
+}
+
+
+
+void LogFamilyError(WORD wFamily, WORD wError)
+{
+ char *msg;
+
+ switch(wError)
+ {
+ case 0x01: msg = "Invalid SNAC header"; break;
+ case 0x02: msg = "Server rate limit exceeded"; break;
+ case 0x03: msg = "Client rate limit exceeded"; break;
+ case 0x04: msg = "Recipient is not logged in"; break;
+ case 0x05: msg = "Requested service unavailable"; break;
+ case 0x06: msg = "Requested service not defined"; break;
+ case 0x07: msg = "You sent obsolete SNAC"; break;
+ case 0x08: msg = "Not supported by server"; break;
+ case 0x09: msg = "Not supported by client"; break;
+ case 0x0A: msg = "Refused by client"; break;
+ case 0x0B: msg = "Reply too big"; break;
+ case 0x0C: msg = "Responses lost"; break;
+ case 0x0D: msg = "Request denied"; break;
+ case 0x0E: msg = "Incorrect SNAC format"; break;
+ case 0x0F: msg = "Insufficient rights"; break;
+ case 0x10: msg = "In local permit/deny (recipient blocked)"; break;
+ case 0x11: msg = "Sender too evil"; break;
+ case 0x12: msg = "Receiver too evil"; break;
+ case 0x13: msg = "User temporarily unavailable"; break;
+ case 0x14: msg = "No match"; break;
+ case 0x15: msg = "List overflow"; break;
+ case 0x16: msg = "Request ambiguous"; break;
+ case 0x17: msg = "Server queue full"; break;
+ case 0x18: msg = "Not while on AOL"; break;
+ default: msg = ""; break;
+ }
+
+ NetLog_Server("SNAC(x%02X,x01) - Error(%u): %s", wFamily, wError, msg);
+}
diff --git a/icqj_mod/chan_03error.c b/icqj_mod/chan_03error.c new file mode 100644 index 0000000..08ae054 --- /dev/null +++ b/icqj_mod/chan_03error.c @@ -0,0 +1,43 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/chan_03error.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void handleErrorChannel(unsigned char* buf, WORD datalen)
+{
+ NetLog_Server("Ignoring server packet on ERROR channel");
+}
diff --git a/icqj_mod/chan_04close.c b/icqj_mod/chan_04close.c new file mode 100644 index 0000000..e7636af --- /dev/null +++ b/icqj_mod/chan_04close.c @@ -0,0 +1,339 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/chan_04close.c,v $
+// Revision : $Revision: 3316 $
+// Last change on : $Date: 2006-07-12 20:26:25 +0400 (Ср, 12 июл 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+extern HANDLE hServerConn;
+extern HANDLE hServerPacketRecver;
+
+static void handleMigration(serverthread_info *info);
+static int connectNewServer(serverthread_info *info);
+static void handleRuntimeError(WORD wError);
+static void handleSignonError(WORD wError);
+
+static void NetLib_SafeCloseHandle(HANDLE *hConnection);
+
+
+void handleCloseChannel(unsigned char *buf, WORD datalen, serverthread_info *info)
+{
+ oscar_tlv_chain* chain = NULL;
+ WORD wError;
+
+
+ // Parse server reply, prepare reconnection
+ if (!info->bLoggedIn && datalen && !info->newServerReady)
+ handleLoginReply(buf, datalen, info);
+
+ if (info->isMigrating)
+ handleMigration(info);
+
+ if (!info->bLoggedIn && info->newServerReady)
+ {
+ if (!connectNewServer(info))
+ { // Connecting failed
+ if (info->isMigrating)
+ icq_LogUsingErrorCode(LOG_ERROR, GetLastError(), "Unable to connect to migrated ICQ communication server");
+ else
+ icq_LogUsingErrorCode(LOG_ERROR, GetLastError(), "Unable to connect to ICQ communication server");
+
+ info->isMigrating = 0;
+ }
+ info->newServerReady = 0;
+
+ return;
+ }
+
+ if (chain = readIntoTLVChain(&buf, datalen, 0))
+ {
+ // TLV 9 errors (runtime errors?)
+ wError = getWordFromChain(chain, 0x09, 1);
+ if (wError)
+ {
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+
+ handleRuntimeError(wError);
+ }
+
+ disposeChain(&chain);
+ }
+ // Server closed connection on error, or sign off
+ NetLib_SafeCloseHandle(&hServerConn);
+}
+
+
+
+static int IsGatewayModeActive()
+{
+ return ICQGetContactSettingByte(NULL, "UseGateway", 0) && ICQGetContactSettingByte(NULL, "NLUseProxy", 0);
+}
+
+
+
+static void NetLib_SafeCloseHandle(HANDLE *hConnection)
+{
+ if (*hConnection) Netlib_MyCloseHandle(*hConnection);
+
+ *hConnection = NULL;
+}
+
+
+
+void handleLoginReply(unsigned char *buf, WORD datalen, serverthread_info *info)
+{
+ oscar_tlv_chain* chain = NULL;
+ WORD wError;
+
+ icq_sendCloseConnection(); // imitate icq5 behaviour
+
+ if (!(chain = readIntoTLVChain(&buf, datalen, 0)))
+ {
+ NetLog_Server("Error: Missing chain on close channel");
+ NetLib_SafeCloseHandle(&hServerConn);
+ return; // Invalid data
+ }
+
+ // TLV 8 errors (signon errors?)
+ wError = getWordFromChain(chain, 0x08, 1);
+ if (wError)
+ {
+ handleSignonError(wError);
+
+ // we return only if the server did not gave us cookie (possible to connect with soft error)
+ if (!getLenFromChain(chain, 0x06, 1))
+ {
+ disposeChain(&chain);
+ NetLib_SafeCloseHandle(&hServerConn);
+ return; // Failure
+ }
+ }
+
+ // We are in the login phase and no errors were reported.
+ // Extract communication server info.
+ info->newServer = getStrFromChain(chain, 0x05, 1);
+ info->cookieData = getStrFromChain(chain, 0x06, 1);
+ info->cookieDataLen = getLenFromChain(chain, 0x06, 1);
+
+ // We dont need this anymore
+ disposeChain(&chain);
+
+ if (!info->newServer || !info->cookieData)
+ {
+ icq_LogMessage(LOG_FATAL, "You could not sign on because the server returned invalid data. Try again.");
+
+ SAFE_FREE(&info->newServer);
+ SAFE_FREE(&info->cookieData);
+ info->cookieDataLen = 0;
+
+ NetLib_SafeCloseHandle(&hServerConn);
+ return; // Failure
+ }
+
+ NetLog_Server("Authenticated.");
+ info->newServerReady = 1;
+
+ return;
+}
+
+
+
+static int connectNewServer(serverthread_info *info)
+{
+ WORD servport;
+ NETLIBOPENCONNECTION nloc = {0};
+ int res = 0;
+
+ if (!IsGatewayModeActive())
+ { // close connection only if not in gateway mode
+ Netlib_CloseHandle(hServerConn);
+ hServerConn = NULL;
+ }
+
+ /* Get the ip and port */
+ parseServerAddress(info->newServer, &servport);
+
+ nloc.cbSize = sizeof(nloc);
+ nloc.flags = 0;
+ nloc.szHost = info->newServer;
+ nloc.wPort = servport;
+
+ if (!IsGatewayModeActive())
+ {
+ { /* Time to release packet receiver, connection already closed */
+ Netlib_CloseHandle(hServerPacketRecver);
+ hServerPacketRecver = NULL; // clear the variable
+
+ NetLog_Server("Closed connection to login server");
+ }
+
+ NetLog_Server("Connecting to %s", info->newServer);
+ hServerConn = NetLib_OpenConnection(ghServerNetlibUser, &nloc);
+ if (hServerConn)
+ { /* Time to recreate the packet receiver */
+ hServerPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 8192);
+ if (!hServerPacketRecver)
+ {
+ NetLog_Server("Error: Failed to create packet receiver.");
+ }
+ else // we need to reset receiving structs
+ {
+ info->bReinitRecver = 1;
+ res = 1;
+ }
+ }
+ }
+ else
+ { // TODO: We should really do some checks here
+ NetLog_Server("Walking in Gateway to %s", info->newServer);
+ // TODO: This REQUIRES more work (most probably some kind of mid-netlib module)
+ icq_httpGatewayWalkTo(hServerConn, &nloc);
+ res = 1;
+ }
+ if (!res) SAFE_FREE(&info->cookieData);
+
+ // Free allocated memory
+ // NOTE: "cookie" will get freed when we have connected to the communication server.
+ SAFE_FREE(&info->newServer);
+
+ return res;
+}
+
+
+
+static void handleMigration(serverthread_info *info)
+{
+ // Check the data that was saved when the migration was announced
+ NetLog_Server("Migrating to %s", info->newServer);
+ if (!info->newServer || !info->cookieData)
+ {
+ icq_LogMessage(LOG_FATAL, "You have been disconnected from the ICQ network because the current server shut down.");
+
+ SAFE_FREE(&info->newServer);
+ SAFE_FREE(&info->cookieData);
+ info->newServerReady = 0;
+ info->isMigrating = 0;
+ }
+}
+
+
+
+static void handleSignonError(WORD wError)
+{
+ switch (wError)
+ {
+
+ case 0x01: // Unregistered uin
+ case 0x04: // Incorrect uin or password
+ case 0x05: // Mismatch uin or password
+ case 0x06: // Internal Client error (bad input to authorizer)
+ case 0x07: // Invalid account
+ ICQBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPASSWORD);
+ icq_LogFatalParam("Connection failed.\nYour ICQ number or password was rejected (%d).", wError);
+ break;
+
+ case 0x02: // Service temporarily unavailable
+ case 0x0D: // Bad database status
+ case 0x10: // Service temporarily offline
+ case 0x14: // Reservation map error
+ case 0x15: // Reservation link error
+ case 0x1A: // Reservation timeout
+ icq_LogFatalParam("Connection failed.\nThe server is temporarily unavailable (%d).", wError);
+ break;
+
+ case 0x16: // The users num connected from this IP has reached the maximum
+ case 0x17: // The users num connected from this IP has reached the maximum (reserved)
+ icq_LogFatalParam("Connection failed.\nServer has too many connections from your IP (%d).", wError);
+ break;
+
+ case 0x18: // Rate limit exceeded (reserved)
+ case 0x1D: // Rate limit exceeded
+ icq_LogFatalParam("Connection failed.\nYou have connected too quickly,\nplease wait and retry 10 to 20 minutes later (%d).", wError);
+ break;
+
+ case 0x1B: // You are using an older version of ICQ. Upgrade required
+ icq_LogMessage(LOG_FATAL, "Connection failed.\nThe server did not accept this client version.");
+ break;
+
+ case 0x1C: // You are using an older version of ICQ. Upgrade recommended
+ icq_LogMessage(LOG_WARNING, "The server sent warning, this version is getting old.\nTry to look for a new one.");
+ break;
+
+ case 0x1E: // Can't register on the ICQ network
+ icq_LogMessage(LOG_FATAL, "Connection failed.\nYou were rejected by the server for an unknown reason.\nThis can happen if the UIN is already connected.");
+ break;
+
+ case 0x0C: // Invalid database fields, MD5 login not supported
+ icq_LogMessage(LOG_FATAL, "Connection failed.\nSecure (MD5) login is not supported on this account.");
+ break;
+
+ case 0:
+ break;
+
+ case 0x08: // Deleted account
+ case 0x09: // Expired account
+ case 0x0A: // No access to database
+ case 0x0B: // No access to resolver
+ case 0x0E: // Bad resolver status
+ case 0x11: // Suspended account
+ case 0x19: // User too heavily warned
+ case 0x22: // Account suspended due to your age
+ case 0x2A: // Blocked account
+
+ default:
+ icq_LogFatalParam("Connection failed.\nUnknown error during sign on: 0x%02x", wError);
+ break;
+ }
+}
+
+
+
+static void handleRuntimeError(WORD wError)
+{
+ switch (wError)
+ {
+
+ case 0x01:
+ {
+ ICQBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_OTHERLOCATION);
+ icq_LogMessage(LOG_FATAL, "You have been disconnected from the ICQ network because you logged on from another location using the same ICQ number.");
+ break;
+ }
+
+ default:
+ icq_LogFatalParam("Unknown runtime error: 0x%02x", wError);
+ break;
+ }
+}
diff --git a/icqj_mod/chan_05ping.c b/icqj_mod/chan_05ping.c new file mode 100644 index 0000000..a84b0e7 --- /dev/null +++ b/icqj_mod/chan_05ping.c @@ -0,0 +1,105 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/chan_05ping.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern HANDLE hServerConn;
+static HANDLE hKeepAliveEvent = NULL;
+
+
+void handlePingChannel(unsigned char* buf, WORD datalen)
+{
+ NetLog_Server("Warning: Ignoring server packet on PING channel");
+}
+
+
+
+static void __cdecl icq_keepAliveThread(void* fa)
+{
+ icq_packet packet;
+
+ NetLog_Server("Keep alive thread starting.");
+
+ hKeepAliveEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ for(;;)
+ {
+ DWORD dwWait = WaitForSingleObjectEx(hKeepAliveEvent, 57000, TRUE);
+
+ if (dwWait == WAIT_OBJECT_0) break; // we should end
+ else if (dwWait == WAIT_TIMEOUT)
+ {
+ // Send a keep alive packet to server
+ packet.wLen = 0;
+ write_flap(&packet, ICQ_PING_CHAN);
+ if (hServerConn) // connection lost, end
+ sendServPacket(&packet);
+ else
+ break;
+ }
+ else if (dwWait == WAIT_IO_COMPLETION)
+ // Possible shutdown in progress
+ if (Miranda_Terminated()) break;
+ }
+
+ NetLog_Server("Keep alive thread shutting down.");
+
+ CloseHandle(hKeepAliveEvent);
+ hKeepAliveEvent = NULL;
+
+ return;
+}
+
+
+
+void StartKeepAlive()
+{
+ if (hKeepAliveEvent) // start only once
+ return;
+
+ if (ICQGetContactSettingByte(NULL, "KeepAlive", 0))
+ forkthread(icq_keepAliveThread, 0, NULL);
+}
+
+
+
+void StopKeepAlive()
+{ // finish keep alive thread
+ if (hKeepAliveEvent)
+ SetEvent(hKeepAliveEvent);
+}
diff --git a/icqj_mod/changeinfo/changeinfo.h b/icqj_mod/changeinfo/changeinfo.h new file mode 100644 index 0000000..37398a5 --- /dev/null +++ b/icqj_mod/changeinfo/changeinfo.h @@ -0,0 +1,116 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2001,2002,2003,2004 Richard Hughes, Martin Öberg
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/changeinfo/changeinfo.h,v $
+// Revision : $Revision: 2991 $
+// Last change on : $Date: 2006-05-30 21:55:48 +0400 $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+
+#ifndef __CHANGEINFO_H
+#define __CHANGEINFO_H
+
+
+#ifndef AW_SLIDE
+#define SPI_GETCOMBOBOXANIMATION 0x1004
+#define AW_SLIDE 0x40000
+#define AW_ACTIVATE 0x20000
+#define AW_VER_POSITIVE 0x4
+#define UDM_SETPOS32 (WM_USER+113)
+#define UDM_GETPOS32 (WM_USER+114)
+#endif
+
+
+#define LI_DIVIDER 0
+#define LI_STRING 1
+#define LI_LIST 2
+#define LI_LONGSTRING 3
+#define LI_NUMBER 4
+#define LIM_TYPE 0x0000FFFF
+#define LIF_ZEROISVALID 0x80000000
+#define LIF_SIGNED 0x40000000
+#define LIF_PASSWORD 0x20000000
+#define LIF_CHANGEONLY 0x10000000
+
+char Password[10];
+HANDLE hUpload[2];
+HWND hwndList;
+HFONT hListFont;
+int iEditItem;
+
+typedef struct {
+ char *szDescription;
+ unsigned displayType; //LI_ constant
+ int dbType; //DBVT_ constant
+ char *szDbSetting;
+ void *pList;
+ int listCount;
+ LPARAM value;
+ int changed;
+} SettingItem;
+
+typedef struct {
+ int id;
+ char *szValue;
+} ListTypeDataItem;
+
+// contants.c
+extern SettingItem setting[];
+extern const int settingCount;
+
+//main.c
+int InitChangeDetails(WPARAM wParam,LPARAM lParam);
+
+//dlgproc.c
+BOOL CALLBACK ChangeInfoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+//db.c
+void LoadSettingsFromDb(int keepChanged);
+void FreeStoredDbSettings(void);
+void ClearChangeFlags(void);
+int ChangesMade(void);
+int SaveSettingsToDb(HWND hwndDlg);
+
+//editstring.c
+void BeginStringEdit(int iItem,RECT *rc,int i,WORD wVKey);
+void EndStringEdit(int save);
+int IsStringEditWindow(HWND hwnd);
+char *BinaryToEscapes(char *str);
+
+//editlist.c
+void BeginListEdit(int iItem,RECT *rc,int i,WORD wVKey);
+void EndListEdit(int save);
+int IsListEditWindow(HWND hwnd);
+
+//upload.c
+int StringToListItemId(const char *szSetting,int def);
+int UploadSettings(HWND hwndParent);
+
+
+#endif /* __CHANGEINFO_H */
diff --git a/icqj_mod/changeinfo/constants.c b/icqj_mod/changeinfo/constants.c new file mode 100644 index 0000000..990f3ab --- /dev/null +++ b/icqj_mod/changeinfo/constants.c @@ -0,0 +1,658 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2001,2002,2003,2004 Richard Hughes, Martin Öberg
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/changeinfo/constants.c,v $
+// Revision : $Revision: 3292 $
+// Last change on : $Date: 2006-07-09 17:27:51 +0400 (Đ’Ń, 09 июл 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+static ListTypeDataItem countries[]={
+ {0 ,"Unspecified"},
+ {9999,"Other"},
+ {93 ,"Afghanistan"},
+ {355 ,"Albania"},
+ {213 ,"Algeria"},
+ {684 ,"American Samoa"},
+ {376 ,"Andorra"},
+ {244 ,"Angola"},
+ {101 ,"Anguilla"},
+ {102 ,"Antigua and Barbuda"},
+ {5902,"Antilles"},
+ {54 ,"Argentina"},
+ {374 ,"Armenia"},
+ {297 ,"Aruba"},
+ {247 ,"Ascension Island"},
+ {61 ,"Australia"},
+ {43 ,"Austria"},
+ {994 ,"Azerbaijan"},
+ {103 ,"Bahamas"},
+ {973 ,"Bahrain"},
+ {880 ,"Bangladesh"},
+ {104 ,"Barbados"},
+ {120 ,"Barbuda"},
+ {375 ,"Belarus"},
+ {32 ,"Belgium"},
+ {501 ,"Belize"},
+ {229 ,"Benin"},
+ {105 ,"Bermuda"},
+ {975 ,"Bhutan"},
+ {591 ,"Bolivia"},
+ {387 ,"Bosnia and Herzegovina"},
+ {267 ,"Botswana"},
+ {55 ,"Brazil"},
+ {106 ,"British Virgin Islands"},
+ {673 ,"Brunei"},
+ {359 ,"Bulgaria"},
+ {226 ,"Burkina Faso"},
+ {257 ,"Burundi"},
+ {855 ,"Cambodia"},
+ {237 ,"Cameroon"},
+ {107 ,"Canada"},
+ {178 ,"Canary Islands"},
+ {238 ,"Cape Verde Islands"},
+ {108 ,"Cayman Islands"},
+ {236 ,"Central African Republic"},
+ {235 ,"Chad"},
+ {56 ,"Chile, Republic of"},
+ {86 ,"China"},
+ {672 ,"Christmas Island"},
+ {6101,"Cocos-Keeling Islands"},
+ {6102,"Cocos (Keeling) Islands"},
+ {57 ,"Colombia"},
+ {2691,"Comoros"},
+ {243 ,"Congo, Democratic Republic of (Zaire)"},
+ {242 ,"Congo, Republic of the"},
+ {682 ,"Cook Islands"},
+ {506 ,"Costa Rica"},
+ {225 ,"Cote d'Ivoire (Ivory Coast)"},
+ {385 ,"Croatia"},
+ {53 ,"Cuba"},
+ {357 ,"Cyprus"},
+ {420 ,"Czech Republic"},
+ {45 ,"Denmark"},
+ {246 ,"Diego Garcia"},
+ {253 ,"Djibouti"},
+ {109 ,"Dominica"},
+ {110 ,"Dominican Republic"},
+ {593 ,"Ecuador"},
+ {20 ,"Egypt"},
+ {503 ,"El Salvador"},
+ {240 ,"Equatorial Guinea"},
+ {291 ,"Eritrea"},
+ {372 ,"Estonia"},
+ {251 ,"Ethiopia"},
+ {298 ,"Faeroe Islands"},
+ {500 ,"Falkland Islands"},
+ {679 ,"Fiji"},
+ {358 ,"Finland"},
+ {33 ,"France"},
+ {5901,"French Antilles"},
+ {594 ,"French Guiana"},
+ {689 ,"French Polynesia"},
+ {241 ,"Gabon"},
+ {220 ,"Gambia"},
+ {995 ,"Georgia"},
+ {49 ,"Germany"},
+ {233 ,"Ghana"},
+ {350 ,"Gibraltar"},
+ {30 ,"Greece"},
+ {299 ,"Greenland"},
+ {111 ,"Grenada"},
+ {590 ,"Guadeloupe"},
+ {671 ,"Guam, US Territory of"},
+ {502 ,"Guatemala"},
+ {224 ,"Guinea"},
+ {245 ,"Guinea-Bissau"},
+ {592 ,"Guyana"},
+ {509 ,"Haiti"},
+ {504 ,"Honduras"},
+ {852 ,"Hong Kong"},
+ {36 ,"Hungary"},
+ {354 ,"Iceland"},
+ {91 ,"India"},
+ {62 ,"Indonesia"},
+ {98 ,"Iran (Islamic Republic of)"},
+ {964 ,"Iraq"},
+ {353 ,"Ireland"},
+ {972 ,"Israel"},
+ {39 ,"Italy"},
+ {112 ,"Jamaica"},
+ {81 ,"Japan"},
+ {962 ,"Jordan"},
+ {705 ,"Kazakhstan"},
+ {254 ,"Kenya"},
+ {686 ,"Kiribati"},
+ {850 ,"Korea, North"},
+ {82 ,"Korea, South"},
+ {965 ,"Kuwait"},
+ {706 ,"Kyrgyzstan"},
+ {856 ,"Laos"},
+ {371 ,"Latvia"},
+ {961 ,"Lebanon"},
+ {266 ,"Lesotho"},
+ {231 ,"Liberia"},
+ {218 ,"Libyan Arab Jamahiriya"},
+ {4101,"Liechtenstein"},
+ {370 ,"Lithuania"},
+ {352 ,"Luxembourg"},
+ {853 ,"Macau"},
+ {389 ,"Macedonia (F.Y.R.O.M.)"},
+ {261 ,"Madagascar"},
+ {265 ,"Malawi"},
+ {60 ,"Malaysia"},
+ {960 ,"Maldives"},
+ {223 ,"Mali"},
+ {356 ,"Malta"},
+ {692 ,"Marshall Islands"},
+ {596 ,"Martinique"},
+ {222 ,"Mauritania"},
+ {230 ,"Mauritius"},
+ {269 ,"Mayotte Island"},
+ {52 ,"Mexico"},
+ {691 ,"Micronesia, Federated States of"},
+ {373 ,"Moldova, Republic of"},
+ {377 ,"Monaco"},
+ {976 ,"Mongolia"},
+ {113 ,"Montserrat"},
+ {212 ,"Morocco"},
+ {258 ,"Mozambique"},
+ {95 ,"Myanmar"},
+ {264 ,"Namibia"},
+ {674 ,"Nauru"},
+ {977 ,"Nepal"},
+ {31 ,"Netherlands"},
+ {599 ,"Netherlands Antilles"},
+ {114 ,"Nevis"},
+ {687 ,"New Caledonia"},
+ {64 ,"New Zealand"},
+ {505 ,"Nicaragua"},
+ {227 ,"Niger"},
+ {234 ,"Nigeria"},
+ {683 ,"Niue"},
+ {6722,"Norfolk Island"},
+ {47 ,"Norway"},
+ {968 ,"Oman"},
+ {92 ,"Pakistan"},
+ {680 ,"Palau"},
+ {507 ,"Panama"},
+ {675 ,"Papua New Guinea"},
+ {595 ,"Paraguay"},
+ {51 ,"Peru"},
+ {63 ,"Philippines"},
+ {48 ,"Poland"},
+ {351 ,"Portugal"},
+ {121 ,"Puerto Rico"},
+ {974 ,"Qatar"},
+ {262 ,"Reunion Island"},
+ {40 ,"Romania"},
+ {6701,"Rota Island"},
+ {7 ,"Russia"},
+ {250 ,"Rwanda"},
+ {290 ,"Saint Helena"},
+ {115 ,"Saint Kitts"},
+ {1141,"Saint Kitts and Nevis"},
+ {122 ,"Saint Lucia"},
+ {508 ,"Saint Pierre and Miquelon"},
+ {116 ,"Saint Vincent and the Grenadines"},
+ {670 ,"Saipan Island"},
+ {378 ,"San Marino"},
+ {239 ,"Sao Tome and Principe"},
+ {966 ,"Saudi Arabia"},
+ {442 ,"Scotland"},
+ {221 ,"Senegal"},
+ {248 ,"Seychelles"},
+ {232 ,"Sierra Leone"},
+ {65 ,"Singapore"},
+ {421 ,"Slovakia"},
+ {386 ,"Slovenia"},
+ {677 ,"Solomon Islands"},
+ {252 ,"Somalia"},
+ {27 ,"South Africa"},
+ {34 ,"Spain"},
+ {94 ,"Sri Lanka"},
+ {249 ,"Sudan"},
+ {597 ,"Suriname"},
+ {268 ,"Swaziland"},
+ {46 ,"Sweden"},
+ {41 ,"Switzerland"},
+ {963 ,"Syrian Arab Republic"},
+ {886 ,"Taiwan"},
+ {708 ,"Tajikistan"},
+ {255 ,"Tanzania"},
+ {66 ,"Thailand"},
+ {6702,"Tinian Island"},
+ {228 ,"Togo"},
+ {690 ,"Tokelau"},
+ {676 ,"Tonga"},
+ {117 ,"Trinidad and Tobago"},
+ {216 ,"Tunisia"},
+ {90 ,"Turkey"},
+ {709 ,"Turkmenistan"},
+ {118 ,"Turks and Caicos Islands"},
+ {688 ,"Tuvalu"},
+ {256 ,"Uganda"},
+ {380 ,"Ukraine"},
+ {971 ,"United Arab Emirates"},
+ {44 ,"United Kingdom"},
+ {598 ,"Uruguay"},
+ {1 ,"USA"},
+ {711 ,"Uzbekistan"},
+ {678 ,"Vanuatu"},
+ {379 ,"Vatican City"},
+ {58 ,"Venezuela"},
+ {84 ,"Vietnam"},
+ {123 ,"Virgin Islands (USA)"},
+ {441 ,"Wales"},
+ {681 ,"Wallis and Futuna Islands"},
+ {685 ,"Western Samoa"},
+ {967 ,"Yemen"},
+ {381 ,"Yugoslavia"},
+ {3811,"Yugoslavia - Serbia"},
+ {382 ,"Yugoslavia - Montenegro"},
+ {260 ,"Zambia"},
+ {263 ,"Zimbabwe"},
+};
+
+static ListTypeDataItem timezones[]={
+ {-100,"Unspecified"},
+ {24 ,"GMT-12:00 Eniwetok; Kwajalein"},
+ {23 ,"GMT-11:30"},
+ {22 ,"GMT-11:00 Midway Island; Samoa"},
+ {21 ,"GMT-10:30"},
+ {20 ,"GMT-10:00 Hawaii"},
+ {19 ,"GMT-9:30"},
+ {18 ,"GMT-9:00 Alaska"},
+ {17 ,"GMT-8:30"},
+ {16 ,"GMT-8:00 Pacific Time; Tijuana"},
+ {15 ,"GMT-7:30"},
+ {14 ,"GMT-7:00 Arizona; Mountain Time"},
+ {13 ,"GMT-6:30"},
+ {12 ,"GMT-6:00 Central Time; Central America; Saskatchewan"},
+ {11 ,"GMT-5:30"},
+ {10 ,"GMT-5:00 Eastern Time; Bogota; Lima; Quito"},
+ {9 ,"GMT-4:30"},
+ {8 ,"GMT-4:00 Atlantic Time; Santiago; Caracas; La Paz"},
+ {7 ,"GMT-3:30 Newfoundland"},
+ {6 ,"GMT-3:00 Greenland; Buenos Aires; Georgetown"},
+ {5 ,"GMT-2:30"},
+ {4 ,"GMT-2:00 Mid-Atlantic"},
+ {3 ,"GMT-1:30"},
+ {2 ,"GMT-1:00 Cape Verde Islands; Azores"},
+ {1 ,"GMT-0:30"},
+ {0 ,"GMT+0:00 London; Dublin; Edinburgh; Lisbon; Casablanca"},
+ {-1 ,"GMT+0:30"},
+ {-2 ,"GMT+1:00 Central European Time; West Central Africa; Warsaw"},
+ {-3 ,"GMT+1:30"},
+ {-4 ,"GMT+2:00 Jerusalem; Helsinki; Harare; Cairo; Bucharest; Athens"},
+ {-5 ,"GMT+2:30"},
+ {-6 ,"GMT+3:00 Moscow; St. Petersburg; Nairobi; Kuwait; Baghdad"},
+ {-7 ,"GMT+3:30 Tehran"},
+ {-8 ,"GMT+4:00 Baku; Tbilisi; Yerevan; Abu Dhabi; Muscat"},
+ {-9 ,"GMT+4:30 Kabul"},
+ {-10 ,"GMT+5:00 Calcutta; Chennai; Mumbai; New Delhi; Ekaterinburg"},
+ {-11 ,"GMT+5:30"},
+ {-12 ,"GMT+6:00 Astana; Dhaka; Almaty; Novosibirsk; Sri Jayawardenepura"},
+ {-13 ,"GMT+6:30 Rangoon"},
+ {-14 ,"GMT+7:00 Bankok; Hanoi; Jakarta; Krasnoyarsk"},
+ {-15 ,"GMT+7:30"},
+ {-16 ,"GMT+8:00 Perth; Taipei; Singapore; Hong Kong; Beijing"},
+ {-17 ,"GMT+8:30"},
+ {-18 ,"GMT+9:00 Tokyo; Osaka; Seoul; Sapporo; Yakutsk"},
+ {-19 ,"GMT+9:30 Darwin; Adelaide"},
+ {-20 ,"GMT+10:00 East Australia; Guam; Vladivostok"},
+ {-21 ,"GMT+10:30"},
+ {-22 ,"GMT+11:00 Magadan; Solomon Is.; New Caledonia"},
+ {-23 ,"GMT+11:30"},
+ {-24 ,"GMT+12:00 Auckland; Wellington; Fiji; Kamchatka; Marshall Is."},
+};
+
+static ListTypeDataItem occupations[] = {
+ {0, "Unspecified"},
+ {1, "Academic"},
+ {2, "Administrative"},
+ {3, "Art/Entertainment"},
+ {4, "College Student"},
+ {5, "Computers"},
+ {6, "Community & Social"},
+ {7, "Education"},
+ {8, "Engineering"},
+ {9, "Financial Services"},
+ {10, "Government"},
+ {11, "High School Student"},
+ {12, "Home"},
+ {13, "ICQ - Providing Help"},
+ {14, "Law"},
+ {15, "Managerial"},
+ {16, "Manufacturing"},
+ {17, "Medical/Health"},
+ {18, "Military"},
+ {19, "Non-Government Organization"},
+ {20, "Professional"},
+ {21, "Retail"},
+ {22, "Retired"},
+ {23, "Science & Research"},
+ {24, "Sports"},
+ {25, "Technical"},
+ {26, "University Student"},
+ {27, "Web Building"},
+ {99, "Other Services"}
+};
+
+static ListTypeDataItem genders[]={
+ {0,"Unspecified"},
+ {'M',"Male"},
+ {'F',"Female"},
+};
+
+static ListTypeDataItem months[]={
+ {0, "Unspecified"},
+ {1, "January"},
+ {2, "February"},
+ {3, "March"},
+ {4, "April"},
+ {5, "May"},
+ {6, "June"},
+ {7, "July"},
+ {8, "August"},
+ {9, "September"},
+ {10,"October"},
+ {11,"November"},
+ {12,"December"},
+};
+
+static ListTypeDataItem languages[]={
+ {0, "None"},
+ {55,"Afrikaans"},
+ {58,"Albanian"},
+ {1, "Arabic"},
+ {59,"Armenian"},
+ {68,"Azerbaijani"},
+ {72,"Belorussian"},
+ {2, "Bhojpuri"},
+ {56,"Bosnian"},
+ {3, "Bulgarian"},
+ {4, "Burmese"},
+ {5, "Cantonese"},
+ {6, "Catalan"},
+ {61,"Chamorro"},
+ {7, "Chinese"},
+ {8, "Croatian"},
+ {9, "Czech"},
+ {10,"Danish"},
+ {11,"Dutch"},
+ {12,"English"},
+ {13,"Esperanto"},
+ {14,"Estonian"},
+ {15,"Farci"},
+ {16,"Finnish"},
+ {17,"French"},
+ {18,"Gaelic"},
+ {19,"German"},
+ {20,"Greek"},
+ {70,"Gujarati"},
+ {21,"Hebrew"},
+ {22,"Hindi"},
+ {23,"Hungarian"},
+ {24,"Icelandic"},
+ {25,"Indonesian"},
+ {26,"Italian"},
+ {27,"Japanese"},
+ {28,"Khmer"},
+ {29,"Korean"},
+ {69,"Kurdish"},
+ {30,"Lao"},
+ {31,"Latvian"},
+ {32,"Lithuanian"},
+ {65,"Macedonian"},
+ {33,"Malay"},
+ {63,"Mandarin"},
+ {62,"Mongolian"},
+ {34,"Norwegian"},
+ {57,"Persian"},
+ {35,"Polish"},
+ {36,"Portuguese"},
+ {60,"Punjabi"},
+ {37,"Romanian"},
+ {38,"Russian"},
+ {39,"Serbo-Croatian"},
+ {66,"Sindhi"},
+ {40,"Slovak"},
+ {41,"Slovenian"},
+ {42,"Somali"},
+ {43,"Spanish"},
+ {44,"Swahili"},
+ {45,"Swedish"},
+ {46,"Tagalog"},
+ {64,"Taiwaness"},
+ {71,"Tamil"},
+ {47,"Tatar"},
+ {48,"Thai"},
+ {49,"Turkish"},
+ {50,"Ukrainian"},
+ {51,"Urdu"},
+ {52,"Vietnamese"},
+ {67,"Welsh"},
+ {53,"Yiddish"},
+ {54,"Yoruba"},
+};
+
+static ListTypeDataItem interests[]={
+ {0, "Unspecified"},
+ {100, "Art"},
+ {101, "Cars"},
+ {102, "Celebrity Fans"},
+ {103, "Collections"},
+ {104, "Computers"},
+ {105, "Culture & Literature"},
+ {106, "Fitness"},
+ {107, "Games"},
+ {108, "Hobbies"},
+ {109, "ICQ - Providing Help"},
+ {110, "Internet"},
+ {111, "Lifestyle"},
+ {112, "Movies/TV"},
+ {113, "Music"},
+ {114, "Outdoor Activities"},
+ {115, "Parenting"},
+ {116, "Pets/Animals"},
+ {117, "Religion"},
+ {118, "Science/Technology"},
+ {119, "Skills"},
+ {120, "Sports"},
+ {121, "Web Design"},
+ {122, "Nature and Environment"},
+ {123, "News & Media"},
+ {124, "Government"},
+ {125, "Business & Economy"},
+ {126, "Mystics"},
+ {127, "Travel"},
+ {128, "Astronomy"},
+ {129, "Space"},
+ {130, "Clothing"},
+ {131, "Parties"},
+ {132, "Women"},
+ {133, "Social science"},
+ {134, "60's"},
+ {135, "70's"},
+ {136, "80's"},
+ {137, "50's"},
+ {138, "Finance and corporate"},
+ {139, "Entertainment"},
+ {140, "Consumer electronics"},
+ {141, "Retail stores"},
+ {142, "Health and beauty"},
+ {143, "Media"},
+ {144, "Household products"},
+ {145, "Mail order catalog"},
+ {146, "Business services"},
+ {147, "Audio and visual"},
+ {148, "Sporting and athletic"},
+ {149, "Publishing"},
+ {150, "Home automation"}
+};
+
+static ListTypeDataItem pastbackground[]={
+ {0, "Unspecified"},
+ {300, "Elementary School"},
+ {301, "High School"},
+ {302, "College"},
+ {303, "University"},
+ {304, "Military"},
+ {305, "Past Work Place"},
+ {306, "Past Organization"},
+ {399, "Other"}
+};
+
+static ListTypeDataItem affiliation[]={
+ {0, "Unspecified"},
+ {200, "Alumni Org."},
+ {201, "Charity Org."},
+ {202, "Club/Social Org."},
+ {203, "Community Org."},
+ {204, "Cultural Org."},
+ {205, "Fan Clubs"},
+ {206, "Fraternity/Sorority"},
+ {207, "Hobbyists Org."},
+ {208, "International Org."},
+ {209, "Nature and Environment Org."},
+ {210, "Professional Org."},
+ {211, "Scientific/Technical Org."},
+ {212, "Self Improvement Group"},
+ {213, "Spiritual/Religious Org."},
+ {214, "Sports Org."},
+ {215, "Support Org."},
+ {216, "Trade and Business Org."},
+ {217, "Union"},
+ {218, "Volunteer Org."},
+ {299, "Other"},
+};
+
+static ListTypeDataItem maritalstatuses[]={
+ {0, "Unspecified"},
+ {10, "Single"},
+ {11, "Close relationships"},
+ {12, "Engaged"},
+ {20, "Married"},
+ {30, "Divorced"},
+ {31, "Separated"},
+ {40, "Widowed"}
+};
+
+
+const int ageRange[]={13,0x7FFF}; // 14, 130
+const int yearRange[]={1753,0x7FFF}; // 1880, 2000
+const int dayRange[]={1,31};
+
+
+SettingItem setting[]={
+ //personal
+ {"Personal", LI_DIVIDER},
+ {"Nickname", LI_STRING, DBVT_ASCIIZ, "Nick"},
+ {"First name", LI_STRING, DBVT_ASCIIZ, "FirstName"},
+ {"Last name", LI_STRING, DBVT_ASCIIZ, "LastName"},
+ {"Age", LI_NUMBER, DBVT_WORD, "Age", (void*)ageRange},
+ {"Gender", LI_LIST, DBVT_BYTE, "Gender", genders, sizeof(genders)/sizeof(genders[0])},
+ {"About", LI_LONGSTRING, DBVT_ASCIIZ, "About"},
+ //password
+ {"Password", LI_DIVIDER},
+ {"Password", LI_STRING|LIF_PASSWORD,DBVT_ASCIIZ, "Password"},
+ //contact
+ {"Contact", LI_DIVIDER},
+ {"Primary e-mail", LI_STRING, DBVT_ASCIIZ, "e-mail"},
+ {"Secondary e-mail", LI_STRING, DBVT_ASCIIZ, "e-mail0"},
+ {"Tertiary e-mail", LI_STRING, DBVT_ASCIIZ, "e-mail1"},
+ {"Homepage", LI_STRING, DBVT_ASCIIZ, "Homepage"},
+ {"Street", LI_STRING, DBVT_ASCIIZ, "Street"},
+ {"City", LI_STRING, DBVT_ASCIIZ, "City"},
+ {"State", LI_STRING, DBVT_ASCIIZ, "State"},
+ {"ZIP/postcode", LI_STRING, DBVT_ASCIIZ, "ZIP"},
+ {"Country", LI_LIST, DBVT_WORD, "Country", countries, sizeof(countries)/sizeof(countries[0])},
+ {"Phone number", LI_STRING, DBVT_ASCIIZ, "Phone"},
+ {"Fax number", LI_STRING, DBVT_ASCIIZ, "Fax"},
+ {"Cellular number",LI_STRING, DBVT_ASCIIZ, "Cellular"},
+ //more
+ {"Personal Detail",LI_DIVIDER},
+ {"Timezone", LI_LIST|LIF_ZEROISVALID|LIF_SIGNED,DBVT_BYTE, "Timezone", timezones, sizeof(timezones)/sizeof(timezones[0])},
+ {"Year of birth", LI_NUMBER, DBVT_WORD, "BirthYear", (void*)yearRange},
+ {"Month of birth", LI_LIST, DBVT_BYTE, "BirthMonth", months, sizeof(months)/sizeof(months[0])},
+ {"Day of birth", LI_NUMBER, DBVT_BYTE, "BirthDay", (void*)dayRange},
+ {"Marital Status", LI_LIST, DBVT_BYTE, "MaritalStatus", maritalstatuses, sizeof(maritalstatuses)/sizeof(maritalstatuses[0])},
+ {"Spoken language 1", LI_LIST, DBVT_ASCIIZ, "Language1", languages, sizeof(languages)/sizeof(languages[0])},
+ {"Spoken language 2", LI_LIST, DBVT_ASCIIZ, "Language2", languages, sizeof(languages)/sizeof(languages[0])},
+ {"Spoken language 3", LI_LIST, DBVT_ASCIIZ, "Language3", languages, sizeof(languages)/sizeof(languages[0])},
+ //more
+ {"Originally from",LI_DIVIDER},
+ {"City", LI_STRING, DBVT_ASCIIZ, "OriginCity"},
+ {"State", LI_STRING, DBVT_ASCIIZ, "OriginState"},
+ {"Country", LI_LIST, DBVT_WORD, "OriginCountry", countries, sizeof(countries)/sizeof(countries[0])},
+ //work
+ {"Work", LI_DIVIDER},
+ {"Company name", LI_STRING, DBVT_ASCIIZ, "Company"},
+ {"Company homepage",LI_STRING, DBVT_ASCIIZ, "CompanyHomepage"},
+ {"Company street", LI_STRING, DBVT_ASCIIZ, "CompanyStreet"},
+ {"Company city", LI_STRING, DBVT_ASCIIZ, "CompanyCity"},
+ {"Company state", LI_STRING, DBVT_ASCIIZ, "CompanyState"},
+ {"Company phone", LI_STRING, DBVT_ASCIIZ, "CompanyPhone"},
+ {"Company fax", LI_STRING, DBVT_ASCIIZ, "CompanyFax"},
+ {"Company ZIP/postcode",LI_STRING,DBVT_ASCIIZ, "CompanyZIP"},
+ {"Company country",LI_LIST, DBVT_WORD, "CompanyCountry",countries, sizeof(countries)/sizeof(countries[0])},
+ {"Company department",LI_STRING, DBVT_ASCIIZ, "CompanyDepartment"},
+ {"Company position",LI_STRING, DBVT_ASCIIZ, "CompanyPosition"},
+ {"Company occupation",LI_LIST, DBVT_WORD, "CompanyOccupation", occupations, sizeof(occupations)/sizeof(occupations[0])},
+ //interests
+ {"Personal Interests", LI_DIVIDER},
+ {"Interest category 1",LI_LIST, DBVT_ASCIIZ, "Interest0Cat", interests, sizeof(interests)/sizeof(interests[0])},
+ {"Interest areas 1",LI_STRING, DBVT_ASCIIZ, "Interest0Text"},
+ {"Interest category 2",LI_LIST, DBVT_ASCIIZ, "Interest1Cat", interests, sizeof(interests)/sizeof(interests[0])},
+ {"Interest areas 2",LI_STRING, DBVT_ASCIIZ, "Interest1Text"},
+ {"Interest category 3",LI_LIST, DBVT_ASCIIZ, "Interest2Cat", interests, sizeof(interests)/sizeof(interests[0])},
+ {"Interest areas 3",LI_STRING, DBVT_ASCIIZ, "Interest2Text"},
+ {"Interest category 4",LI_LIST, DBVT_ASCIIZ, "Interest3Cat", interests, sizeof(interests)/sizeof(interests[0])},
+ {"Interest areas 4",LI_STRING, DBVT_ASCIIZ, "Interest3Text"},
+ //pastbackground
+ {"Past Background", LI_DIVIDER},
+ {"Category 1",LI_LIST, DBVT_ASCIIZ, "Past0", pastbackground, sizeof(pastbackground)/sizeof(pastbackground[0])},
+ {"Past Background 1",LI_STRING, DBVT_ASCIIZ, "Past0Text"},
+ {"Category 2",LI_LIST, DBVT_ASCIIZ, "Past1", pastbackground, sizeof(pastbackground)/sizeof(pastbackground[0])},
+ {"Past Background 2",LI_STRING, DBVT_ASCIIZ, "Past1Text"},
+ {"Category 3",LI_LIST, DBVT_ASCIIZ, "Past2", pastbackground, sizeof(pastbackground)/sizeof(pastbackground[0])},
+ {"Past Background 3",LI_STRING, DBVT_ASCIIZ, "Past2Text"},
+ //affiliation
+ {"Affiliations", LI_DIVIDER},
+ {"Affiliation category 1",LI_LIST,DBVT_ASCIIZ, "Affiliation0", affiliation, sizeof(affiliation)/sizeof(affiliation[0])},
+ {"Affiliation 1",LI_STRING, DBVT_ASCIIZ, "Affiliation0Text"},
+ {"Affiliation category 2",LI_LIST,DBVT_ASCIIZ, "Affiliation1", affiliation, sizeof(affiliation)/sizeof(affiliation[0])},
+ {"Affiliation 2",LI_STRING, DBVT_ASCIIZ, "Affiliation1Text"},
+ {"Affiliation category 3",LI_LIST,DBVT_ASCIIZ, "Affiliation2", affiliation, sizeof(affiliation)/sizeof(affiliation[0])},
+ {"Affiliation 3",LI_STRING, DBVT_ASCIIZ, "Affiliation2Text"}
+};
+
+const int settingCount=sizeof(setting)/sizeof(setting[0]);
diff --git a/icqj_mod/changeinfo/db.c b/icqj_mod/changeinfo/db.c new file mode 100644 index 0000000..2e0ba46 --- /dev/null +++ b/icqj_mod/changeinfo/db.c @@ -0,0 +1,226 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2001,2002,2003,2004 Richard Hughes, Martin Öberg
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/changeinfo/db.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-17 01:38:00 +0400 $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void LoadSettingsFromDb(int keepChanged)
+{
+ int i;
+ DBVARIANT dbv;
+
+ for(i=0;i<settingCount;i++)
+ {
+ if (setting[i].displayType==LI_DIVIDER) continue;
+ if (keepChanged && setting[i].changed) continue;
+ if (setting[i].dbType==DBVT_ASCIIZ)
+ {
+ SAFE_FREE((char**)&setting[i].value);
+ }
+ else if (!keepChanged)
+ setting[i].value = 0;
+
+ setting[i].changed=0;
+
+ if (setting[i].displayType&LIF_PASSWORD) continue;
+
+ if (!ICQGetContactSetting(NULL,setting[i].szDbSetting,&dbv))
+ {
+#ifdef _DEBUG
+ if(dbv.type!=setting[i].dbType)
+ MessageBoxA(NULL,"That's not supposed to happen","Huh?",MB_OK);
+#endif
+ switch(dbv.type)
+ {
+ case DBVT_ASCIIZ:
+ setting[i].value=(LPARAM)ICQGetContactSettingUtf(NULL,setting[i].szDbSetting, NULL);
+ break;
+ case DBVT_WORD:
+ if(setting[i].displayType&LIF_SIGNED)
+ setting[i].value=dbv.sVal;
+ else
+ setting[i].value=dbv.wVal;
+ break;
+ case DBVT_BYTE:
+ if(setting[i].displayType&LIF_SIGNED)
+ setting[i].value=dbv.cVal;
+ else
+ setting[i].value=dbv.bVal;
+ break;
+#ifdef _DEBUG
+ default:
+ MessageBoxA(NULL,"That's not supposed to happen either","Huh?",MB_OK);
+ break;
+#endif
+ }
+ ICQFreeVariant(&dbv);
+ }
+ }
+}
+
+
+
+void FreeStoredDbSettings(void)
+{
+ int i;
+
+ for(i=0;i<settingCount;i++)
+ if(setting[i].dbType==DBVT_ASCIIZ)
+ SAFE_FREE((char**)&setting[i].value);
+}
+
+
+
+int ChangesMade(void)
+{
+ int i;
+
+ for(i=0;i<settingCount;i++)
+ if(setting[i].changed) return 1;
+ return 0;
+}
+
+
+
+void ClearChangeFlags(void)
+{
+ int i;
+
+ for(i=0;i<settingCount;i++)
+ setting[i].changed=0;
+}
+
+
+
+static BOOL CALLBACK PwConfirmDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static char *Pass;
+
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ Pass = (char*)lParam;
+ SendDlgItemMessage(hwndDlg,IDC_PASSWORD,EM_LIMITTEXT,15,0);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ char szTest[16], str[1024], cap[MAX_PATH];
+
+ GetDlgItemTextA(hwndDlg,IDC_OLDPASS,szTest,sizeof(szTest));
+
+ if (strcmpnull(szTest, GetUserPassword(TRUE)))
+ {
+ MessageBoxUtf(hwndDlg,ICQTranslateUtfStatic("The password does not match your current password. Check Caps Lock and try again.", str), ICQTranslateUtfStatic("Change ICQ Details", cap), MB_OK);
+ SendDlgItemMessage(hwndDlg,IDC_OLDPASS,EM_SETSEL,0,(LPARAM)-1);
+ SetFocus(GetDlgItem(hwndDlg,IDC_OLDPASS));
+ break;
+ }
+
+ GetDlgItemTextA(hwndDlg,IDC_PASSWORD,szTest,sizeof(szTest));
+ if(strcmpnull(szTest, Pass))
+ {
+ MessageBoxUtf(hwndDlg,ICQTranslateUtfStatic("The password does not match the password you originally entered. Check Caps Lock and try again.", str), ICQTranslateUtfStatic("Change ICQ Details", cap), MB_OK);
+ SendDlgItemMessage(hwndDlg,IDC_PASSWORD,EM_SETSEL,0,(LPARAM)-1);
+ SetFocus(GetDlgItem(hwndDlg,IDC_PASSWORD));
+ break;
+ }
+ }
+ case IDCANCEL:
+ EndDialog(hwndDlg,wParam);
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+
+int SaveSettingsToDb(HWND hwndDlg)
+{
+ int i,ret=1;
+
+ for(i=0;i<settingCount;i++)
+ {
+ if(!setting[i].changed) continue;
+ if(!(setting[i].displayType&LIF_ZEROISVALID) && setting[i].value==0)
+ {
+ ICQDeleteContactSetting(NULL,setting[i].szDbSetting);
+ continue;
+ }
+ switch(setting[i].dbType)
+ {
+ case DBVT_ASCIIZ:
+ if(setting[i].displayType&LIF_PASSWORD)
+ {
+ int nSettingLen = strlennull((char*)setting[i].value);
+
+ if (nSettingLen>8 || nSettingLen<1)
+ {
+ char str[1024], cap[MAX_PATH];
+
+ MessageBoxUtf(hwndDlg, ICQTranslateUtfStatic("The ICQ server does not support passwords longer than 8 characters. Please use a shorter password.", str), ICQTranslateUtfStatic("Change ICQ Details", cap), MB_OK);
+ ret=0;
+ break;
+ }
+ if (IDOK!=DialogBoxParam(hInst,MAKEINTRESOURCE(IDD_PWCONFIRM),hwndDlg,PwConfirmDlgProc,(LPARAM)setting[i].value))
+ {
+ ret=0;
+ break;
+ }
+ strcpy(gpszPassword, (char*)setting[i].value);
+ }
+ else
+ {
+ if(*(char*)setting[i].value)
+ ICQWriteContactSettingUtf(NULL,setting[i].szDbSetting,(char*)setting[i].value);
+ else
+ ICQDeleteContactSetting(NULL,setting[i].szDbSetting);
+ }
+ break;
+ case DBVT_WORD:
+ ICQWriteContactSettingWord(NULL,setting[i].szDbSetting,(WORD)setting[i].value);
+ break;
+ case DBVT_BYTE:
+ ICQWriteContactSettingByte(NULL,setting[i].szDbSetting,(BYTE)setting[i].value);
+ break;
+ }
+ }
+ return ret;
+}
diff --git a/icqj_mod/changeinfo/dlgproc.c b/icqj_mod/changeinfo/dlgproc.c new file mode 100644 index 0000000..23bae32 --- /dev/null +++ b/icqj_mod/changeinfo/dlgproc.c @@ -0,0 +1,560 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2001,2002,2003,2004 Richard Hughes, Martin Öberg
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/changeinfo/dlgproc.c,v $
+// Revision : $Revision: 3183 $
+// Last change on : $Date: 2006-06-20 13:50:04 +0400 $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static int editTopIndex;
+static HANDLE hAckHook = NULL;
+static HFONT hMyFont = NULL;
+
+#define DM_PROTOACK (WM_USER+10)
+
+static int DrawTextUtf(HDC hDC, char* text, LPRECT lpRect, UINT uFormat, LPSIZE lpSize)
+{
+ int res;
+
+ if (gbUnicodeAPI)
+ {
+ wchar_t *tmp = make_unicode_string(text);
+
+ res = DrawTextW(hDC, tmp, -1, lpRect, uFormat);
+ if (lpSize)
+ GetTextExtentPoint32W(hDC, tmp, wcslen(tmp), lpSize);
+ SAFE_FREE(&tmp);
+ }
+ else
+ {
+ // caution, here we change text's contents
+ utf8_decode_static(text, text, strlennull(text)+1);
+ res = DrawTextA(hDC, text, -1, lpRect, uFormat);
+ if (lpSize)
+ GetTextExtentPoint32A(hDC, text, strlennull(text), lpSize);
+ }
+ return res;
+}
+
+
+
+static void PaintItemSetting(HDC hdc,RECT *rc,int i,UINT itemState)
+{
+ char *text;
+ int alloced=0;
+ char str[MAX_PATH];
+
+ if (setting[i].value==0 && !(setting[i].displayType&LIF_ZEROISVALID))
+ {
+ SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
+
+ if (setting[i].displayType & LIF_CHANGEONLY)
+ text = ICQTranslateUtfStatic("<unremovable once applied>", str);
+ else
+ text = ICQTranslateUtfStatic("<empty>", str);
+ }
+ else
+ {
+ switch (setting[i].displayType & LIM_TYPE)
+ {
+ case LI_STRING:
+ case LI_LONGSTRING:
+ {
+ text = BinaryToEscapes((char*)setting[i].value);
+ alloced = 1;
+ break;
+ }
+
+ case LI_NUMBER:
+ text = str;
+ itoa(setting[i].value, text, 10);
+ break;
+
+ case LI_LIST:
+ if (setting[i].dbType == DBVT_ASCIIZ)
+ {
+ text = ICQTranslateUtfStatic((char*)setting[i].value, str);
+ }
+ else
+ {
+ int j;
+
+ text = ICQTranslateUtfStatic("Unknown value", str);
+
+ for(j=0; j < setting[i].listCount; j++)
+ if (((ListTypeDataItem*)setting[i].pList)[j].id == setting[i].value)
+ {
+ text = ICQTranslateUtfStatic(((ListTypeDataItem*)setting[i].pList)[j].szValue, str);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ if (setting[i].displayType & LIF_PASSWORD)
+ {
+ if (setting[i].changed)
+ {
+ int i;
+ for (i=0; text[i]; i++) text[i] = '*';
+ }
+ else
+ {
+ if (alloced)
+ {
+ SAFE_FREE(&text);
+ alloced=0;
+ }
+ text = "********";
+ }
+ }
+ if ((setting[i].displayType & LIM_TYPE) == LI_LIST && (itemState & CDIS_SELECTED || iEditItem == i))
+ {
+ RECT rcBtn;
+
+ rcBtn = *rc;
+ rcBtn.left = rcBtn.right - rc->bottom + rc->top;
+ InflateRect(&rcBtn,-2,-2);
+ rc->right = rcBtn.left;
+ DrawFrameControl(hdc, &rcBtn, DFC_SCROLL, iEditItem == i ? DFCS_SCROLLDOWN|DFCS_PUSHED : DFCS_SCROLLDOWN);
+ }
+ DrawTextUtf(hdc, text, rc, DT_END_ELLIPSIS|DT_LEFT|DT_NOCLIP|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER, NULL);
+
+ if (alloced) SAFE_FREE(&text);
+}
+
+
+static int InfoDlg_Resize(HWND hwndDlg,LPARAM lParam,UTILRESIZECONTROL *urc)
+{
+ switch (urc->wId)
+ {
+ case IDC_LIST:
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
+ break;
+ case IDC_SAVE:
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
+ break;
+ case IDC_UPLOADING:
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM;
+ break;
+ }
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; // default
+}
+
+
+
+BOOL CALLBACK ChangeInfoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ hwndList=GetDlgItem(hwndDlg,IDC_LIST);
+ LoadSettingsFromDb(0);
+ ListView_SetExtendedListViewStyle(hwndList,LVS_EX_FULLROWSELECT);
+ iEditItem=-1;
+ {
+ LOGFONT lf;
+
+ hListFont=(HFONT)SendMessage(hwndList,WM_GETFONT,0,0);
+ GetObject(hListFont,sizeof(lf),&lf);
+ lf.lfHeight-=5;
+ hMyFont=CreateFontIndirect(&lf);
+ SendMessage(hwndList,WM_SETFONT,(WPARAM)hMyFont,0);
+ }
+ {
+ LV_COLUMN lvc={0};
+ RECT rc;
+
+ GetClientRect(hwndList,&rc);
+ rc.right-=GetSystemMetrics(SM_CXVSCROLL);
+ lvc.mask = LVCF_WIDTH;
+ lvc.cx = rc.right/3;
+ ListView_InsertColumn(hwndList, 0, &lvc);
+ lvc.cx = rc.right-lvc.cx;
+ ListView_InsertColumn(hwndList, 1, &lvc);
+ }
+ {
+ LV_ITEM lvi={0};
+ lvi.mask = LVIF_PARAM;
+
+ for (lvi.iItem=0;lvi.iItem<settingCount;lvi.iItem++)
+ {
+ lvi.lParam=lvi.iItem;
+ ListView_InsertItem(hwndList, &lvi);
+ }
+ }
+ {
+ char *pwd = GetUserPassword(TRUE);
+
+ if (pwd)
+ strcpy(Password, pwd);
+ else
+ strcpy(Password, "");
+ }
+
+ SendMessage(GetParent(hwndDlg),PSM_CHANGED,0,0);
+ return TRUE;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_INFOCHANGED:
+ LoadSettingsFromDb(1);
+ break;
+
+ case PSN_KILLACTIVE:
+ EndStringEdit(1);
+ EndListEdit(1);
+ break;
+
+ case PSN_APPLY:
+ if(ChangesMade())
+ {
+ char str[1024], cap[MAX_PATH];
+
+ if (IDYES!=MessageBoxUtf(hwndDlg, ICQTranslateUtfStatic("You've made some changes to your ICQ details but it has not been saved to the server. Are you sure you want to close this dialog?", str), ICQTranslateUtfStatic("Change ICQ Details", cap), MB_YESNOCANCEL))
+ {
+ SetWindowLongUtf(hwndDlg,DWL_MSGRESULT,PSNRET_INVALID_NOCHANGEPAGE);
+ return TRUE;
+ }
+ }
+ PostMessage(hwndList,WM_SETFONT,(WPARAM)hListFont,0);
+ break;
+ }
+ break;
+
+ case IDC_LIST:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case LVN_GETDISPINFOW:
+ case LVN_GETDISPINFO:
+ if (iEditItem != -1)
+ {
+ if (editTopIndex != ListView_GetTopIndex(hwndList))
+ {
+ EndStringEdit(1);
+ EndListEdit(1);
+ }
+ }
+ break;
+
+ case NM_CUSTOMDRAW:
+ {
+ LPNMLVCUSTOMDRAW cd=(LPNMLVCUSTOMDRAW)lParam;
+
+ switch(cd->nmcd.dwDrawStage)
+ {
+ case CDDS_PREPAINT:
+ SetWindowLongUtf(hwndDlg,DWL_MSGRESULT,CDRF_NOTIFYSUBITEMDRAW);
+ return TRUE;
+
+ case CDDS_ITEMPREPAINT:
+ {
+ RECT rc;
+
+ ListView_GetItemRect(hwndList, cd->nmcd.dwItemSpec, &rc, LVIR_BOUNDS);
+
+ if (GetWindowLong(hwndList, GWL_STYLE) & WS_DISABLED)
+ { // Disabled List
+ SetTextColor(cd->nmcd.hdc, cd->clrText);
+ FillRect(cd->nmcd.hdc, &rc, GetSysColorBrush(COLOR_3DFACE));
+ }
+ else if ((cd->nmcd.uItemState & CDIS_SELECTED || iEditItem == (int)cd->nmcd.dwItemSpec)
+ && setting[cd->nmcd.lItemlParam].displayType != LI_DIVIDER)
+ { // Selected item
+ SetTextColor(cd->nmcd.hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ FillRect(cd->nmcd.hdc, &rc, GetSysColorBrush(COLOR_HIGHLIGHT));
+ }
+ else
+ { // Unselected item
+ SetTextColor(cd->nmcd.hdc, GetSysColor(COLOR_WINDOWTEXT));
+ FillRect(cd->nmcd.hdc, &rc, GetSysColorBrush(COLOR_WINDOW));
+ }
+
+ if (setting[cd->nmcd.lItemlParam].displayType == LI_DIVIDER)
+ {
+ RECT rcLine;
+ SIZE textSize;
+ char str[MAX_PATH];
+ char *szText = ICQTranslateUtfStatic(setting[cd->nmcd.lItemlParam].szDescription, str);
+ HFONT hoFont;
+
+ hoFont = (HFONT)SelectObject(cd->nmcd.hdc, hListFont);
+ SetTextColor(cd->nmcd.hdc, GetSysColor(COLOR_3DSHADOW));
+ ListView_GetItemRect(hwndList, cd->nmcd.dwItemSpec, &rc, LVIR_BOUNDS);
+ DrawTextUtf(cd->nmcd.hdc, szText, &rc, DT_CENTER|DT_NOCLIP|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER, &textSize);
+ rcLine.top = (rc.top + rc.bottom)/2-1;
+ rcLine.bottom = rcLine.top+2;
+ rcLine.left = rc.left + 3;
+ rcLine.right = (rc.left+rc.right-textSize.cx)/2-3;
+ DrawEdge(cd->nmcd.hdc, &rcLine, BDR_SUNKENOUTER, BF_RECT);
+ rcLine.left = (rc.left + rc.right + textSize.cx)/2 + 3;
+ rcLine.right = rc.right-3;
+ DrawEdge(cd->nmcd.hdc, &rcLine, BDR_SUNKENOUTER, BF_RECT);
+ SetWindowLongUtf(hwndDlg, DWL_MSGRESULT, CDRF_SKIPDEFAULT);
+ }
+ else
+ {
+ SetWindowLongUtf(hwndDlg, DWL_MSGRESULT, CDRF_NOTIFYSUBITEMDRAW|CDRF_NOTIFYPOSTPAINT);
+ }
+
+ return TRUE;
+ }
+
+ case CDDS_SUBITEM|CDDS_ITEMPREPAINT:
+ {
+ RECT rc;
+ HFONT hoFont;
+
+ hoFont=(HFONT)SelectObject(cd->nmcd.hdc,hListFont);
+ ListView_GetSubItemRect(hwndList,cd->nmcd.dwItemSpec,cd->iSubItem,LVIR_BOUNDS,&rc);
+
+ if (cd->iSubItem==0)
+ {
+ RECT rc2;
+ char str[MAX_PATH];
+
+ ListView_GetSubItemRect(hwndList,cd->nmcd.dwItemSpec,1,LVIR_BOUNDS,&rc2);
+ rc.right=rc2.left;
+ rc.left+=2;
+ DrawTextUtf(cd->nmcd.hdc, ICQTranslateUtfStatic(setting[cd->nmcd.lItemlParam].szDescription, str), &rc, DT_END_ELLIPSIS|DT_LEFT|DT_NOCLIP|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER, NULL);
+ }
+ else
+ PaintItemSetting(cd->nmcd.hdc, &rc, cd->nmcd.lItemlParam, cd->nmcd.uItemState);
+ SetWindowLongUtf(hwndDlg,DWL_MSGRESULT,CDRF_SKIPDEFAULT);
+
+ return TRUE;
+ }
+/*
+ case CDDS_ITEMPOSTPAINT:
+ { RECT rc;
+ ListView_GetItemRect(hwndList,cd->nmcd.dwItemSpec,&rc,LVIR_BOUNDS);
+ if(cd->nmcd.uItemState&CDIS_FOCUS) {
+ HDC hdc2
+ hdc2=GetDC(hwndList); //I don't know what the listview's done to its DC, but I can't figure out how to undo it
+ DrawFocusRect(hdc2,&rc);
+ ReleaseDC(hwndList,hdc2);
+ }
+ break;
+ }
+*/
+
+ }
+ break;
+ }
+ case NM_CLICK:
+ {
+ LPNMLISTVIEW nm=(LPNMLISTVIEW)lParam;
+ LV_ITEM lvi;
+ RECT rc;
+
+ EndStringEdit(1);
+ EndListEdit(1);
+ if (nm->iSubItem != 1) break;
+ lvi.mask = LVIF_PARAM|LVIF_STATE;
+ lvi.stateMask = 0xFFFFFFFF;
+ lvi.iItem = nm->iItem; lvi.iSubItem = nm->iSubItem;
+ ListView_GetItem(hwndList, &lvi);
+ if (!(lvi.state & LVIS_SELECTED)) break;
+ ListView_EnsureVisible(hwndList, lvi.iItem, FALSE);
+ ListView_GetSubItemRect(hwndList, lvi.iItem, lvi.iSubItem, LVIR_BOUNDS, &rc);
+ editTopIndex = ListView_GetTopIndex(hwndList);
+ switch (setting[lvi.lParam].displayType & LIM_TYPE)
+ {
+ case LI_STRING:
+ case LI_LONGSTRING:
+ case LI_NUMBER:
+ BeginStringEdit(nm->iItem, &rc, lvi. lParam, 0);
+ break;
+ case LI_LIST:
+ BeginListEdit(nm->iItem, &rc, lvi. lParam, 0);
+ break;
+ }
+ break;
+ }
+ case LVN_KEYDOWN:
+ {
+ LPNMLVKEYDOWN nm=(LPNMLVKEYDOWN)lParam;
+ LV_ITEM lvi;
+ RECT rc;
+
+ EndStringEdit(1);
+ EndListEdit(1);
+ if(nm->wVKey==VK_SPACE || nm->wVKey==VK_RETURN) nm->wVKey=0;
+ if(nm->wVKey && (nm->wVKey<'0' || (nm->wVKey>'9' && nm->wVKey<'A') || (nm->wVKey>'Z' && nm->wVKey<VK_NUMPAD0) || nm->wVKey>=VK_F1))
+ break;
+ lvi.mask=LVIF_PARAM|LVIF_STATE;
+ lvi.stateMask=0xFFFFFFFF;
+ lvi.iItem=ListView_GetNextItem(hwndList,-1,LVNI_ALL|LVNI_SELECTED);
+ if(lvi.iItem==-1) break;
+ lvi.iSubItem=1;
+ ListView_GetItem(hwndList,&lvi);
+ ListView_EnsureVisible(hwndList,lvi.iItem,FALSE);
+ ListView_GetSubItemRect(hwndList,lvi.iItem,lvi.iSubItem,LVIR_BOUNDS,&rc);
+ editTopIndex=ListView_GetTopIndex(hwndList);
+ switch(setting[lvi.lParam].displayType&LIM_TYPE)
+ {
+ case LI_STRING:
+ case LI_LONGSTRING:
+ case LI_NUMBER:
+ BeginStringEdit(lvi.iItem,&rc,lvi.lParam,nm->wVKey);
+ break;
+ case LI_LIST:
+ BeginListEdit(lvi.iItem,&rc,lvi.lParam,nm->wVKey);
+ break;
+ }
+ SetWindowLongUtf(hwndDlg,DWL_MSGRESULT,TRUE);
+ return TRUE;
+ }
+ case NM_KILLFOCUS:
+ if(!IsStringEditWindow(GetFocus())) EndStringEdit(1);
+ if(!IsListEditWindow(GetFocus())) EndListEdit(1);
+ break;
+ }
+ break;
+ }
+ break;
+ case WM_KILLFOCUS:
+ EndStringEdit(1);
+ EndListEdit(1);
+ break;
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDCANCEL:
+ SendMessage(GetParent(hwndDlg), msg, wParam, lParam);
+ break;
+
+ case IDC_SAVE:
+ if (!SaveSettingsToDb(hwndDlg)) break;
+ EnableDlgItem(hwndDlg, IDC_SAVE, FALSE);
+ EnableDlgItem(hwndDlg, IDC_LIST, FALSE);
+ {
+ char str[MAX_PATH];
+
+ SetDlgItemTextUtf(hwndDlg, IDC_UPLOADING, ICQTranslateUtfStatic("Upload in progress...", str));
+ }
+ EnableDlgItem(hwndDlg, IDC_UPLOADING, TRUE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_UPLOADING), SW_SHOW);
+ hAckHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, DM_PROTOACK);
+
+ if (!UploadSettings(hwndDlg))
+ {
+ EnableDlgItem(hwndDlg, IDC_SAVE, TRUE);
+ EnableDlgItem(hwndDlg, IDC_LIST, TRUE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_UPLOADING), SW_HIDE);
+ UnhookEvent(hAckHook);
+ hAckHook = NULL;
+ }
+ break;
+ }
+ break;
+
+ case WM_SIZE:
+ { // make the dlg resizeable
+ UTILRESIZEDIALOG urd = {0};
+
+ if (IsIconic(hwndDlg)) break;
+ urd.cbSize = sizeof(urd);
+ urd.hInstance = hInst;
+ urd.hwndDlg = hwndDlg;
+ urd.lParam = 0; // user-defined
+ urd.lpTemplate = MAKEINTRESOURCEA(IDD_INFO_CHANGEINFO);
+ urd.pfnResizer = InfoDlg_Resize;
+ CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM) &urd);
+
+ { // update listview column widths
+ RECT rc;
+
+ GetClientRect(hwndList,&rc);
+ rc.right-=GetSystemMetrics(SM_CXVSCROLL);
+ ListView_SetColumnWidth(hwndList, 0, rc.right/3);
+ ListView_SetColumnWidth(hwndList, 1, rc.right - rc.right/3);
+ }
+ break;
+ }
+
+ case DM_PROTOACK:
+ {
+ ACKDATA *ack=(ACKDATA*)lParam;
+ int i,done;
+ char str[MAX_PATH];
+
+ if (ack->type != ACKTYPE_SETINFO) break;
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ for (i=0; i<sizeof(hUpload)/sizeof(hUpload[0]); i++)
+ if (hUpload[i] && ack->hProcess == hUpload[i]) break;
+
+ if (i == sizeof(hUpload)/sizeof(hUpload[0])) break;
+ hUpload[i] = NULL;
+ for (done = 0, i = 0; i < sizeof(hUpload)/sizeof(hUpload[0]); i++)
+ done += hUpload[i] == NULL;
+ wsprintf(str,"%s%d%%", ICQTranslateUtfStatic("Upload in progress...", str), 100*done/(sizeof(hUpload)/sizeof(hUpload[0])));
+ SetDlgItemTextUtf(hwndDlg, IDC_UPLOADING, str);
+ if (done < sizeof(hUpload)/sizeof(hUpload[0])) break;
+
+ ClearChangeFlags();
+ UnhookEvent(hAckHook); hAckHook = NULL;
+ EnableDlgItem(hwndDlg, IDC_LIST, TRUE);
+ EnableDlgItem(hwndDlg, IDC_UPLOADING, FALSE);
+ SetDlgItemTextUtf(hwndDlg, IDC_UPLOADING, ICQTranslateUtfStatic("Upload complete", str));
+ SendMessage(GetParent(hwndDlg),PSM_FORCECHANGED,0,0);
+ }
+ else if (ack->result==ACKRESULT_FAILED)
+ {
+ UnhookEvent(hAckHook);
+ hAckHook = NULL;
+ EnableDlgItem(hwndDlg, IDC_LIST, TRUE);
+ EnableDlgItem(hwndDlg, IDC_UPLOADING, FALSE);
+ SetDlgItemTextUtf(hwndDlg, IDC_UPLOADING, ICQTranslateUtfStatic("Upload FAILED", str));
+ SendMessage(GetParent(hwndDlg), PSM_FORCECHANGED, 0, 0);
+ }
+ break;
+ }
+ case WM_DESTROY:
+ if(hAckHook)
+ {
+ UnhookEvent(hAckHook);
+ hAckHook=NULL;
+ }
+ //SendMessage(hwndList,WM_GETFONT,0,0);
+ DeleteObject(hMyFont);
+ FreeStoredDbSettings();
+ break;
+ }
+ return FALSE;
+}
diff --git a/icqj_mod/changeinfo/editlist.c b/icqj_mod/changeinfo/editlist.c new file mode 100644 index 0000000..47dba03 --- /dev/null +++ b/icqj_mod/changeinfo/editlist.c @@ -0,0 +1,173 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2001,2002,2003,2004 Richard Hughes, Martin Öberg
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/changeinfo/editlist.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-17 01:38:00 +0400 $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static HWND hwndListEdit=NULL;
+static BOOL (WINAPI *MyAnimateWindow)(HWND,DWORD,DWORD);
+static WNDPROC OldListEditProc;
+
+static LRESULT CALLBACK ListEditSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_LBUTTONUP:
+ CallWindowProcUtf(OldListEditProc,hwnd,msg,wParam,lParam);
+ {
+ POINT pt;
+
+ pt.x=(short)LOWORD(lParam);
+ pt.y=(short)HIWORD(lParam);
+ ClientToScreen(hwnd,&pt);
+ if(SendMessage(hwnd,WM_NCHITTEST,0,MAKELPARAM(pt.x,pt.y))==HTVSCROLL) break;
+ }
+ {
+ int i;
+
+ i=SendMessage(hwnd,LB_GETCURSEL,0,0);
+ EndListEdit(i!=LB_ERR);
+ }
+ return 0;
+ case WM_CHAR:
+ if(wParam!='\r') break;
+ {
+ int i;
+
+ i=SendMessage(hwnd,LB_GETCURSEL,0,0);
+ EndListEdit(i!=LB_ERR);
+ }
+ return 0;
+ case WM_KILLFOCUS:
+ EndListEdit(1);
+ return 0;
+ }
+ return CallWindowProcUtf(OldListEditProc,hwnd,msg,wParam,lParam);
+}
+
+
+
+void BeginListEdit(int iItem,RECT *rc,int i,WORD wVKey)
+{
+ int j,n;
+ POINT pt;
+ int itemHeight;
+ char str[MAX_PATH];
+
+ EndListEdit(0);
+ pt.x=pt.y=0;
+ ClientToScreen(hwndList,&pt);
+ OffsetRect(rc,pt.x,pt.y);
+ InflateRect(rc,-2,-2);
+ rc->left-=2;
+ iEditItem=iItem;
+ ListView_RedrawItems(hwndList,iEditItem,iEditItem);
+ UpdateWindow(hwndList);
+
+ hwndListEdit=CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_TOPMOST,"LISTBOX","",WS_POPUP|WS_BORDER|WS_VSCROLL,rc->left,rc->bottom,rc->right-rc->left,150,NULL,NULL,hInst,NULL);
+ SendMessage(hwndListEdit,WM_SETFONT,(WPARAM)hListFont,0);
+ itemHeight=SendMessage(hwndListEdit,LB_GETITEMHEIGHT,0,0);
+ for(j=0;j<setting[i].listCount;j++)
+ {
+ n = ListBoxAddStringUtf(hwndListEdit, ((ListTypeDataItem*)setting[i].pList)[j].szValue);
+ SendMessage(hwndListEdit,LB_SETITEMDATA,n,((ListTypeDataItem*)setting[i].pList)[j].id);
+ if ((setting[i].dbType==DBVT_ASCIIZ && (!strcmpnull((char*)setting[i].value,((ListTypeDataItem*)setting[i].pList)[j].szValue))
+ || (setting[i].dbType==DBVT_ASCIIZ && (!strcmpnull((char*)setting[i].value,ICQTranslateUtfStatic(((ListTypeDataItem*)setting[i].pList)[j].szValue, str))))
+ || ((char*)setting[i].value==NULL && ((ListTypeDataItem*)setting[i].pList)[j].id==0))
+ || (setting[i].dbType!=DBVT_ASCIIZ && setting[i].value==((ListTypeDataItem*)setting[i].pList)[j].id))
+ SendMessage(hwndListEdit,LB_SETCURSEL,n,0);
+ }
+ SendMessage(hwndListEdit,LB_SETTOPINDEX,SendMessage(hwndListEdit,LB_GETCURSEL,0,0)-3,0);
+ if(itemHeight*setting[i].listCount<150)
+ SetWindowPos(hwndListEdit,0,0,0,rc->right-rc->left,itemHeight*setting[i].listCount+GetSystemMetrics(SM_CYBORDER)*2,SWP_NOZORDER|SWP_NOMOVE);
+ OldListEditProc=(WNDPROC)SetWindowLongUtf(hwndListEdit,GWL_WNDPROC,(LONG)ListEditSubclassProc);
+ if (MyAnimateWindow=(BOOL (WINAPI*)(HWND,DWORD,DWORD))GetProcAddress(GetModuleHandle("user32"),"AnimateWindow"))
+ {
+ BOOL enabled;
+
+ SystemParametersInfo(SPI_GETCOMBOBOXANIMATION,0,&enabled,FALSE);
+ if(enabled) MyAnimateWindow(hwndListEdit,200,AW_SLIDE|AW_ACTIVATE|AW_VER_POSITIVE);
+ }
+ ShowWindow(hwndListEdit,SW_SHOW);
+ SetFocus(hwndListEdit);
+ if(wVKey)
+ PostMessage(hwndListEdit,WM_KEYDOWN,wVKey,0);
+}
+
+
+
+void EndListEdit(int save)
+{
+ if(hwndListEdit==NULL || iEditItem==-1) return;
+ if(save)
+ {
+ int i;
+ LPARAM newValue;
+ i=SendMessage(hwndListEdit,LB_GETCURSEL,0,0);
+ newValue=SendMessage(hwndListEdit,LB_GETITEMDATA,i,0);
+ if (setting[iEditItem].dbType==DBVT_ASCIIZ)
+ {
+ char *szNewValue = (((ListTypeDataItem*)setting[iEditItem].pList)[i].szValue);
+ if(newValue || setting[iEditItem].displayType&LIF_ZEROISVALID)
+ {
+ setting[iEditItem].changed=strcmpnull(szNewValue,(char*)setting[iEditItem].value);
+ SAFE_FREE((char**)&setting[iEditItem].value);
+ setting[iEditItem].value=(LPARAM)null_strdup(szNewValue);
+ }
+ else
+ {
+ setting[iEditItem].changed=(char*)setting[iEditItem].value!=NULL;
+ SAFE_FREE((char**)&setting[iEditItem].value);
+ }
+ }
+ else
+ {
+ setting[iEditItem].changed=newValue!=setting[iEditItem].value;
+ setting[iEditItem].value=newValue;
+ }
+ if (setting[iEditItem].changed) EnableDlgItem(GetParent(hwndList), IDC_SAVE, TRUE);
+ }
+ ListView_RedrawItems(hwndList, iEditItem, iEditItem);
+ iEditItem = -1;
+ DestroyWindow(hwndListEdit);
+ hwndListEdit = NULL;
+}
+
+
+
+int IsListEditWindow(HWND hwnd)
+{
+ if (hwnd == hwndListEdit) return 1;
+ return 0;
+}
diff --git a/icqj_mod/changeinfo/editstring.c b/icqj_mod/changeinfo/editstring.c new file mode 100644 index 0000000..0cb2438 --- /dev/null +++ b/icqj_mod/changeinfo/editstring.c @@ -0,0 +1,362 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2001,2002,2003,2004 Richard Hughes, Martin Öberg
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/changeinfo/editstring.c,v $
+// Revision : $Revision: 3177 $
+// Last change on : $Date: 2006-06-20 03:48:02 +0400 $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static WNDPROC OldStringEditProc,OldExpandButtonProc;
+static HWND hwndEdit=NULL,hwndExpandButton=NULL,hwndUpDown=NULL;
+
+static const char escapes[]={'a','\a',
+ 'b','\b',
+ 'e',27,
+ 'f','\f',
+ 'r','\r',
+ 't','\t',
+ 'v','\v',
+ '\\','\\'};
+
+static void EscapesToMultiline(wchar_t *str,PDWORD selStart,PDWORD selEnd)
+{ //converts "\\n" and "\\t" to "\r\n" and "\t" because a multi-line edit box can show them properly
+ DWORD i;
+
+ for(i=0; *str; str++, i++)
+ {
+ if (*str != '\\') continue;
+ if (str[1] == 'n')
+ {
+ *str++ = '\r';
+ i++;
+ *str = '\n';
+ }
+ else if (str[1] == 't')
+ {
+ *str = '\t';
+ memmove(str+1, str+2, sizeof(wchar_t)*(wcslen(str)-1));
+
+ if (*selStart>i) --*selStart;
+ if (*selEnd>i) --*selEnd;
+ }
+ }
+}
+
+
+
+static void EscapesToBinary(char *str)
+{
+ int i;
+
+ for(;*str;str++)
+ {
+ if(*str!='\\') continue;
+ if(str[1]=='n') {*str++='\r'; i++; *str='\n'; continue;}
+ if(str[1]=='0')
+ {
+ char *codeend;
+ *str=(char)strtol(str+1,&codeend,8);
+ if(*str==0) {*str='\\'; continue;}
+ memmove(str+1,codeend,strlennull(codeend)+1);
+ continue;
+ }
+ for(i=0;i<sizeof(escapes)/sizeof(escapes[0]);i+=2)
+ if(str[1]==escapes[i])
+ {
+ *str=escapes[i+1];
+ memmove(str+1,str+2,strlennull(str)-1);
+ break;
+ }
+ }
+}
+
+
+
+char *BinaryToEscapes(char *str)
+{
+ int extra=10,len=strlennull(str)+11,i;
+ char *out,*pout;
+
+ out=pout=(char*)SAFE_MALLOC(len);
+ for(;*str;str++)
+ {
+ if((unsigned char)*str>=' ')
+ {
+ *pout++=*str;
+ continue;
+ }
+ if(str[0]=='\r' && str[1]=='\n')
+ {
+ *pout++='\\';
+ *pout++='n';
+ str++;
+ continue;
+ }
+ if(extra<3)
+ {
+ extra+=8; len+=8;
+ pout=out=(char*)realloc(out,len);
+ }
+ *pout++='\\';
+ for(i=0;i<sizeof(escapes)/sizeof(escapes[0]);i+=2)
+ if(*str==escapes[i+1])
+ {
+ *pout++=escapes[i];
+ extra--;
+ break;
+ }
+ if(i<sizeof(escapes)/sizeof(escapes[0])) continue;
+ *pout++='0'; extra--;
+ if(*str>=8)
+ {
+ *pout++=(*str>>3)+'0';
+ extra--;
+ }
+ *pout++=(*str&7)+'0'; extra--;
+ }
+ *pout='\0';
+ return out;
+}
+
+
+
+static LRESULT CALLBACK StringEditSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_KEYDOWN:
+ if(wParam==VK_ESCAPE)
+ {
+ EndStringEdit(0);
+ return 0;
+ }
+ if(wParam==VK_RETURN)
+ {
+ if(GetWindowLong(hwnd,GWL_STYLE)&ES_MULTILINE && !(GetKeyState(VK_CONTROL)&0x8000)) break;
+ EndStringEdit(1);
+ return 0;
+ }
+ break;
+ case WM_GETDLGCODE:
+ return DLGC_WANTALLKEYS|CallWindowProcUtf(OldStringEditProc,hwnd,msg,wParam,lParam);
+ case WM_KILLFOCUS:
+ if((HWND)wParam==hwndExpandButton) break;
+ EndStringEdit(1);
+ return 0;
+ }
+ return CallWindowProcUtf(OldStringEditProc,hwnd,msg,wParam,lParam);
+}
+
+
+
+static LRESULT CALLBACK ExpandButtonSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_LBUTTONUP:
+ if(GetCapture()==hwnd)
+ {
+ //do expand
+ RECT rcStart,rcEnd;
+ DWORD selStart,selEnd;
+ wchar_t *text;
+ BOOL animEnabled=TRUE;
+
+ GetWindowRect(hwndEdit,&rcStart);
+ InflateRect(&rcStart,2,2);
+
+ text = GetWindowTextUcs(hwndEdit);
+ SendMessage(hwndEdit,EM_GETSEL,(WPARAM)&selStart,(LPARAM)&selEnd);
+ DestroyWindow(hwndEdit);
+ EscapesToMultiline(text,&selStart,&selEnd);
+ hwndEdit=CreateWindowEx(WS_EX_TOOLWINDOW,"EDIT","",WS_POPUP|WS_BORDER|WS_VISIBLE|ES_WANTRETURN|ES_AUTOVSCROLL|WS_VSCROLL|ES_MULTILINE,rcStart.left,rcStart.top,rcStart.right-rcStart.left,rcStart.bottom-rcStart.top,NULL,NULL,hInst,NULL);
+ SetWindowTextUcs(hwndEdit, text);
+ OldStringEditProc=(WNDPROC)SetWindowLongUtf(hwndEdit,GWL_WNDPROC,(LONG)StringEditSubclassProc);
+ SendMessage(hwndEdit,WM_SETFONT,(WPARAM)hListFont,0);
+ SendMessage(hwndEdit,EM_SETSEL,selStart,selEnd);
+ SetFocus(hwndEdit);
+
+ rcEnd.left=rcStart.left; rcEnd.top=rcStart.top;
+ rcEnd.right=rcEnd.left+350;
+ rcEnd.bottom=rcEnd.top+150;
+ if (LOBYTE(LOWORD(GetVersion()))>4 || HIBYTE(LOWORD(GetVersion()))>0)
+ SystemParametersInfo(SPI_GETCOMBOBOXANIMATION,0,&animEnabled,FALSE);
+ if(animEnabled)
+ {
+ DWORD startTime,timeNow;
+ startTime=GetTickCount();
+ for(;;)
+ {
+ UpdateWindow(hwndEdit);
+ timeNow=GetTickCount();
+ if(timeNow>startTime+200) break;
+ SetWindowPos(hwndEdit,0,rcEnd.left,rcEnd.top,(rcEnd.right-rcStart.right)*(timeNow-startTime)/200+rcStart.right-rcEnd.left,(rcEnd.bottom-rcStart.bottom)*(timeNow-startTime)/200+rcStart.bottom-rcEnd.top,SWP_NOZORDER);
+ }
+ }
+ SetWindowPos(hwndEdit,0,rcEnd.left,rcEnd.top,rcEnd.right-rcEnd.left,rcEnd.bottom-rcEnd.top,SWP_NOZORDER);
+
+ DestroyWindow(hwnd);
+ hwndExpandButton=NULL;
+
+ SAFE_FREE(&text);
+ }
+ break;
+ }
+ return CallWindowProcUtf(OldExpandButtonProc,hwnd,msg,wParam,lParam);
+}
+
+
+
+void BeginStringEdit(int iItem,RECT *rc,int i,WORD wVKey)
+{
+ char *szValue;
+ char str[80];
+ int alloced=0;
+
+ EndStringEdit(0);
+ InflateRect(rc,-2,-2);
+ rc->left-=2;
+ if(setting[i].displayType&LIF_PASSWORD && !setting[i].changed)
+ szValue=" ";
+ else if ((setting[i].displayType&LIM_TYPE)==LI_NUMBER)
+ {
+ szValue=str;
+ wsprintf(str,"%d",setting[i].value);
+ }
+ else if(setting[i].value)
+ {
+ szValue=BinaryToEscapes((char*)setting[i].value);
+ alloced=1;
+ }
+ else szValue="";
+ iEditItem=iItem;
+
+ if ((setting[i].displayType&LIM_TYPE)==LI_LONGSTRING)
+ {
+ rc->right-=rc->bottom-rc->top;
+ hwndExpandButton=CreateWindow("BUTTON","",WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON|BS_ICON,rc->right,rc->top,rc->bottom-rc->top,rc->bottom-rc->top,hwndList,NULL,hInst,NULL);
+ SendMessage(hwndExpandButton,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadImage(hInst,MAKEINTRESOURCE(IDI_EXPANDSTRINGEDIT),IMAGE_ICON,0,0,LR_SHARED));
+ OldExpandButtonProc=(WNDPROC)SetWindowLongUtf(hwndExpandButton,GWL_WNDPROC,(LONG)ExpandButtonSubclassProc);
+ }
+
+ hwndEdit=CreateWindow("EDIT","",WS_VISIBLE|WS_CHILD|ES_AUTOHSCROLL|((setting[i].displayType&LIM_TYPE)==LI_NUMBER?ES_NUMBER:0)|(setting[i].displayType&LIF_PASSWORD?ES_PASSWORD:0),rc->left,rc->top,rc->right-rc->left,rc->bottom-rc->top,hwndList,NULL,hInst,NULL);
+ SetWindowTextUtf(hwndEdit, szValue);
+ if (alloced) SAFE_FREE(&szValue);
+ OldStringEditProc=(WNDPROC)SetWindowLongUtf(hwndEdit,GWL_WNDPROC,(LONG)StringEditSubclassProc);
+ SendMessage(hwndEdit,WM_SETFONT,(WPARAM)hListFont,0);
+ if ((setting[i].displayType&LIM_TYPE)==LI_NUMBER)
+ {
+ int *range=(int*)setting[i].pList;
+ RECT rcUpDown;
+ hwndUpDown=CreateWindow(UPDOWN_CLASS,"",WS_VISIBLE|WS_CHILD|UDS_AUTOBUDDY|UDS_ALIGNRIGHT|UDS_HOTTRACK|UDS_NOTHOUSANDS|UDS_SETBUDDYINT,0,0,0,0,hwndList,NULL,hInst,NULL);
+ SendMessage(hwndUpDown,UDM_SETRANGE32,range[0],range[1]);
+ SendMessage(hwndUpDown,UDM_SETPOS32,0,setting[i].value);
+ if(!(setting[i].displayType&LIF_ZEROISVALID) && setting[i].value==0)
+ SetWindowTextA(hwndEdit,"");
+ GetClientRect(hwndUpDown,&rcUpDown);
+ rc->right-=rcUpDown.right;
+ SetWindowPos(hwndEdit,0,0,0,rc->right-rc->left,rc->bottom-rc->top,SWP_NOZORDER|SWP_NOMOVE);
+ }
+ SendMessage(hwndEdit,EM_SETSEL,0,(LPARAM)-1);
+ SetFocus(hwndEdit);
+ PostMessage(hwndEdit,WM_KEYDOWN,wVKey,0);
+}
+
+
+
+void EndStringEdit(int save)
+{
+ if (hwndEdit == NULL || iEditItem == -1) return;
+ if (save)
+ {
+ char *text = NULL;
+
+ text=(char*)SAFE_MALLOC(GetWindowTextLength(hwndEdit)+1);
+ GetWindowText(hwndEdit,text,GetWindowTextLength(hwndEdit)+1);
+ EscapesToBinary(text);
+ if((setting[iEditItem].displayType&LIM_TYPE)==LI_NUMBER)
+ {
+ LPARAM newValue;
+ int *range=(int*)setting[iEditItem].pList;
+ newValue=atoi(text);
+ if(newValue)
+ {
+ if(newValue<range[0]) newValue=range[0];
+ if(newValue>range[1]) newValue=range[1];
+ }
+ setting[iEditItem].changed=setting[iEditItem].value!=newValue;
+ setting[iEditItem].value=newValue;
+ SAFE_FREE(&text);
+ }
+ else
+ {
+ if (!(setting[iEditItem].displayType&LIF_PASSWORD))
+ {
+ SAFE_FREE(&text);
+ text = GetWindowTextUtf(hwndEdit);
+ EscapesToBinary(text);
+ }
+ if ((setting[iEditItem].displayType&LIF_PASSWORD && strcmpnull(text," ")) ||
+ (!(setting[iEditItem].displayType&LIF_PASSWORD) && strcmpnull(text,(char*)setting[iEditItem].value) && (strlennull(text) + strlennull((char*)setting[iEditItem].value))))
+ {
+ SAFE_FREE((char**)&setting[iEditItem].value);
+ if (text[0])
+ setting[iEditItem].value=(LPARAM)text;
+ else
+ {
+ setting[iEditItem].value=0;
+ SAFE_FREE(&text);
+ }
+ setting[iEditItem].changed=1;
+ }
+ }
+ if (setting[iEditItem].changed) EnableDlgItem(GetParent(hwndList), IDC_SAVE, TRUE);
+ }
+ ListView_RedrawItems(hwndList, iEditItem, iEditItem);
+ iEditItem = -1;
+ DestroyWindow(hwndEdit);
+ hwndEdit = NULL;
+ if (hwndExpandButton) DestroyWindow(hwndExpandButton);
+ hwndExpandButton = NULL;
+ if (hwndUpDown) DestroyWindow(hwndUpDown);
+ hwndUpDown = NULL;
+}
+
+
+
+int IsStringEditWindow(HWND hwnd)
+{
+ if (hwnd == hwndEdit) return 1;
+ if (hwnd == hwndExpandButton) return 1;
+ if (hwnd == hwndUpDown) return 1;
+ return 0;
+}
diff --git a/icqj_mod/changeinfo/expandst.ico b/icqj_mod/changeinfo/expandst.ico Binary files differnew file mode 100644 index 0000000..17367fe --- /dev/null +++ b/icqj_mod/changeinfo/expandst.ico diff --git a/icqj_mod/changeinfo/main.c b/icqj_mod/changeinfo/main.c new file mode 100644 index 0000000..44c3307 --- /dev/null +++ b/icqj_mod/changeinfo/main.c @@ -0,0 +1,54 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2001,2002,2003,2004 Richard Hughes, Martin Öberg
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/changeinfo/main.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-17 01:38:00 +0400 $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+int InitChangeDetails(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+
+ if (lParam) return 0;
+
+ odp.cbSize = sizeof(odp);
+ odp.hIcon = NULL;
+ odp.hInstance = hInst;
+ odp.position = -1899999999;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_CHANGEINFO);
+ odp.pfnDlgProc = ChangeInfoDlgProc;
+
+ AddUserInfoPageUtf(&odp, wParam, "%s Details");
+
+ return 0;
+}
diff --git a/icqj_mod/changeinfo/upload.c b/icqj_mod/changeinfo/upload.c new file mode 100644 index 0000000..a771894 --- /dev/null +++ b/icqj_mod/changeinfo/upload.c @@ -0,0 +1,204 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2001,2002,2003,2004 Richard Hughes, Martin Öberg
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/changeinfo/upload.c,v $
+// Revision : $Revision: 2991 $
+// Last change on : $Date: 2006-05-30 21:55:48 +0400 $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+int StringToListItemId(const char *szSetting,int def)
+{
+ int i,listCount;
+ char szTmp[256];
+ ListTypeDataItem *list;
+
+ for(i=0;i<settingCount;i++)
+ if(!strcmpnull(szSetting,setting[i].szDbSetting))
+ break;
+
+ if(i==settingCount) return def;
+
+ list=(ListTypeDataItem*)setting[i].pList;
+ listCount=setting[i].listCount;
+
+ if(ICQGetContactStaticString(NULL, szSetting, szTmp, sizeof(szTmp)))
+ return def;
+
+ for(i=0;i<listCount;i++)
+ if(!strcmpnull(list[i].szValue, szTmp)) break;
+
+ if(i==listCount) return def;
+
+ return list[i].id;
+}
+
+
+
+int UploadSettings(HWND hwndParent)
+{
+ PBYTE buf = NULL;
+ int buflen = 0;
+/* BYTE b;
+ WORD w;*/
+
+ if (!icqOnline)
+ {
+ char str[1024],cap[MAX_PATH];
+
+ MessageBoxUtf(hwndParent, ICQTranslateUtfStatic("You are not currently connected to the ICQ network. You must be online in order to update your information on the server.", str), ICQTranslateUtfStatic("Change ICQ Details", cap), MB_OK);
+ return 0;
+ }
+
+/* // userinfo
+ ppackTLVWord(&buf, &buflen, (WORD)GetACP(), TLV_CODEPAGE, 0);
+
+ b = !ICQGetContactSettingByte(NULL, "PublishPrimaryEmail", 0);
+ ppackTLVLNTSBytefromDB(&buf, &buflen, "e-mail", b, TLV_EMAIL);
+ ppackTLVLNTSBytefromDB(&buf, &buflen, "e-mail0", 0, TLV_EMAIL);
+ ppackTLVLNTSBytefromDB(&buf, &buflen, "e-mail1", 0, TLV_EMAIL);
+
+ ppackTLVByte(&buf, &buflen, ICQGetContactSettingByte(NULL, "AllowSpam", 0), TLV_ALLOWSPAM, 1);
+
+ ppackTLVLNTSfromDB(&buf, &buflen, "Phone", TLV_PHONE);
+ ppackTLVLNTSfromDB(&buf, &buflen, "Fax", TLV_FAX);
+ ppackTLVLNTSfromDB(&buf, &buflen, "Cellular", TLV_MOBILE);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyPhone", TLV_WORKPHONE);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyFax", TLV_WORKFAX);
+
+ ppackTLVLNTSfromDB(&buf, &buflen, "Nick", TLV_NICKNAME);
+ ppackTLVLNTSfromDB(&buf, &buflen, "FirstName", TLV_FIRSTNAME);
+ ppackTLVLNTSfromDB(&buf, &buflen, "LastName", TLV_LASTNAME);
+ ppackTLVLNTSfromDB(&buf, &buflen, "About", TLV_ABOUT);
+
+ ppackTLVWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "Age", 0), TLV_AGE, 1);
+ b = ICQGetContactSettingByte(NULL, "Gender", 0);
+ ppackTLVByte(&buf, &buflen, (BYTE)(b ? (b == 'M' ? 2 : 1) : 0), TLV_GENDER, 1);
+ ppackLEWord(&buf, &buflen, TLV_BIRTH);
+ ppackLEWord(&buf, &buflen, 0x06);
+ ppackLEWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "BirthYear", 0));
+ ppackLEWord(&buf, &buflen, (WORD)ICQGetContactSettingByte(NULL, "BirthMonth", 0));
+ ppackLEWord(&buf, &buflen, (WORD)ICQGetContactSettingByte(NULL, "BirthDay", 0));
+
+ ppackTLVWord(&buf, &buflen, (WORD)StringToListItemId("Language1", 0), TLV_LANGUAGE, 1);
+ ppackTLVWord(&buf, &buflen, (WORD)StringToListItemId("Language2", 0), TLV_LANGUAGE, 1);
+ ppackTLVWord(&buf, &buflen, (WORD)StringToListItemId("Language3", 0), TLV_LANGUAGE, 1);
+
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyDepartment", TLV_DEPARTMENT);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyPosition", TLV_POSITION);
+ ppackTLVLNTSfromDB(&buf, &buflen, "Company", TLV_COMPANY);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyStreet", TLV_WORKSTREET);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyState", TLV_WORKSTATE);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyCity", TLV_WORKCITY);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyHomepage", TLV_WORKURL);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyZIP", TLV_WORKZIPCODE);
+ ppackTLVWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "CompanyCountry", 0), TLV_WORKCOUNTRY, 1);
+ ppackTLVWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "CompanyOccupation", 0), TLV_OCUPATION, 1);
+
+ ppackTLVLNTSfromDB(&buf, &buflen, "City", TLV_CITY);
+ ppackTLVLNTSfromDB(&buf, &buflen, "State", TLV_STATE);
+ ppackTLVWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "Country", 0), TLV_COUNTRY, 1);
+ ppackTLVLNTSfromDB(&buf, &buflen, "OriginCity", TLV_ORGCITY);
+ ppackTLVLNTSfromDB(&buf, &buflen, "OriginState", TLV_ORGSTATE);
+ ppackTLVWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "OriginCountry", 0), TLV_ORGCOUNTRY, 1);
+ ppackTLVLNTSfromDB(&buf, &buflen, "Street", TLV_STREET);
+ ppackTLVLNTSfromDB(&buf, &buflen, "ZIP", TLV_ZIPCODE);
+
+ ppackTLVLNTSfromDB(&buf, &buflen, "Homepage", TLV_URL);
+
+ ppackTLVByte(&buf, &buflen, ICQGetContactSettingByte(NULL, "Timezone", 0), TLV_TIMEZONE, 1);
+
+ ppackTLVByte(&buf, &buflen, ICQGetContactSettingByte(NULL, "MaritalStatus", 0), TLV_MARITAL, 1);
+
+ w = StringToListItemId("Interest0Cat", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Interest0Text", TLV_INTERESTS);
+ w = StringToListItemId("Interest1Cat", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Interest1Text", TLV_INTERESTS);
+ w = StringToListItemId("Interest2Cat", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Interest2Text", TLV_INTERESTS);
+ w = StringToListItemId("Interest3Cat", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Interest3Text", TLV_INTERESTS);
+
+ w = StringToListItemId("Past0", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Past0Text", TLV_PASTINFO);
+ w = StringToListItemId("Past1", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Past1Text", TLV_PASTINFO);
+ w = StringToListItemId("Past2", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Past2Text", TLV_PASTINFO);
+
+ w = StringToListItemId("Affiliation0", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Affiliation0Text", TLV_AFFILATIONS);
+ w = StringToListItemId("Affiliation1", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Affiliation1Text", TLV_AFFILATIONS);
+ w = StringToListItemId("Affiliation2", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Affiliation2Text", TLV_AFFILATIONS);
+
+ hUpload[0] = (HANDLE)icq_changeUserDetailsServ(META_SET_FULLINFO_REQ, buf, (WORD)buflen);*/
+ hUpload[0] = (HANDLE)IcqChangeInfoEx(CIXT_FULL, 0);
+
+ //password
+ {
+ char* tmp;
+
+ tmp = GetUserPassword(TRUE);
+ if(tmp)
+ {
+ if (strlennull(Password) > 0 && strcmpnull(Password, tmp))
+ {
+ buflen = 0; // re-init buffer
+
+ ppackLELNTS(&buf, &buflen, tmp);
+
+ hUpload[1] = (HANDLE)icq_changeUserDetailsServ(META_SET_PASSWORD_REQ, buf, (WORD)buflen);
+
+ {
+ char szPwd[16] = {0};
+
+ if (!ICQGetContactStaticString(NULL, "Password", szPwd, 16) && strlennull(szPwd))
+ { // password is stored in DB, update
+ char ptmp[16];
+
+ strcpy(ptmp, tmp);
+
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(ptmp), (LPARAM)ptmp);
+
+ ICQWriteContactSettingString(NULL, "Password", ptmp);
+ }
+ }
+ }
+ }
+ }
+
+ SAFE_FREE(&buf);
+
+ return 1;
+}
diff --git a/icqj_mod/channels.h b/icqj_mod/channels.h new file mode 100644 index 0000000..2fc9eea --- /dev/null +++ b/icqj_mod/channels.h @@ -0,0 +1,52 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/channels.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __CHANNELS_H
+#define __CHANNELS_H
+
+int unpackSnacHeader(snac_header* pSnacHeader, unsigned char **pBuffer, WORD* pwBufferLength);
+void handleLoginChannel(unsigned char *buf, WORD datalen, serverthread_info *info);
+void handleErrorChannel(unsigned char *buf, WORD datalen);
+void handleDataChannel(unsigned char *buf, WORD wLen, serverthread_info *info);
+void handlePingChannel(unsigned char *buf, WORD wLen);
+void handleCloseChannel(unsigned char *buf, WORD datalen, serverthread_info *info);
+
+void LogFamilyError(WORD wFamily, WORD wError);
+
+void StartKeepAlive();
+void StopKeepAlive();
+
+#endif /* __CHANNELS_H */
diff --git a/icqj_mod/cookies.c b/icqj_mod/cookies.c new file mode 100644 index 0000000..23919a1 --- /dev/null +++ b/icqj_mod/cookies.c @@ -0,0 +1,365 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/cookies.c,v $
+// Revision : $Revision: 3069 $
+// Last change on : $Date: 2006-06-07 20:05:39 +0200 (st, 07 VI 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Handles packet & message cookies
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+static WORD wCookieSeq;
+static icq_cookie_info *cookie = NULL;
+static int cookieCount = 0;
+static int cookieSize = 0;
+CRITICAL_SECTION cookieMutex; // we want this in avatar thread, used as queue lock
+
+static int ResizeCookieList(int nSize)
+{
+ if ((cookieSize < nSize) || ((cookieSize > nSize + 6) && nSize))
+ {
+ icq_cookie_info *pNew;
+ int newSize;
+
+ if (cookieSize < nSize)
+ newSize = cookieSize + 4;
+ else
+ newSize = cookieSize - 4;
+
+ pNew = (icq_cookie_info *)realloc(cookie, sizeof(icq_cookie_info) * newSize);
+
+ if (!pNew)
+ { // realloc failed, cookies intact... try again
+ NetLog_Server("ResizeCookieList: realloc failed.");
+
+ return 1; // Failure
+ }
+ else
+ {
+ cookie = pNew;
+ cookieSize = newSize;
+ }
+ }
+ return 0; // Success
+}
+
+
+#define INVALID_COOKIE_INDEX -1
+
+static int FindCookieIndex(DWORD dwCookie)
+{
+ int i;
+
+ for (i = 0; i < cookieCount; i++)
+ {
+ if (dwCookie == cookie[i].dwCookie)
+ {
+ return i;
+ }
+ }
+ return INVALID_COOKIE_INDEX;
+}
+
+
+
+static void RemoveCookieIndex(int iCookie)
+{
+ cookieCount--;
+ memmove(&cookie[iCookie], &cookie[iCookie + 1], sizeof(icq_cookie_info) * (cookieCount - iCookie));
+ ResizeCookieList(cookieCount);
+}
+
+
+
+static void RemoveExpiredCookies()
+{
+ int i;
+ DWORD tNow = time(NULL);
+
+ for (i = 0; i < cookieCount; i++)
+ {
+ if ((cookie[i].dwTime + COOKIE_TIMEOUT) < tNow)
+ { // cookie expired, remove too
+ RemoveCookieIndex(i);
+ i--; // fix the loop
+ }
+ }
+}
+
+
+
+void InitCookies(void)
+{
+ InitializeCriticalSection(&cookieMutex);
+
+ cookieCount = 0;
+ cookieSize = 0;
+ cookie = NULL;
+ wCookieSeq = 2;
+
+ ResizeCookieList(4);
+}
+
+
+
+void UninitCookies(void)
+{
+ SAFE_FREE(&cookie);
+
+ DeleteCriticalSection(&cookieMutex);
+}
+
+
+
+// Generate and allocate cookie
+DWORD AllocateCookie(BYTE bType, WORD wIdent, DWORD dwUin, void *pvExtra)
+{
+ DWORD dwThisSeq;
+
+ EnterCriticalSection(&cookieMutex);
+
+ if (ResizeCookieList(cookieCount + 1))
+ { // resizing failed...
+ LeaveCriticalSection(&cookieMutex);
+ // this is horrible, but can't do anything better
+ return GenerateCookie(wIdent);
+ }
+
+ dwThisSeq = wCookieSeq++;
+ dwThisSeq &= 0x7FFF;
+ dwThisSeq |= wIdent<<0x10;
+
+ cookie[cookieCount].bType = bType;
+ cookie[cookieCount].dwCookie = dwThisSeq;
+ cookie[cookieCount].dwUin = dwUin;
+ cookie[cookieCount].pvExtra = pvExtra;
+ cookie[cookieCount].dwTime = time(NULL);
+ cookieCount++;
+
+ LeaveCriticalSection(&cookieMutex);
+
+ return dwThisSeq;
+}
+
+
+
+DWORD GenerateCookie(WORD wIdent)
+{
+ DWORD dwThisSeq;
+
+ EnterCriticalSection(&cookieMutex);
+ dwThisSeq = wCookieSeq++;
+ dwThisSeq &= 0x7FFF;
+ dwThisSeq |= wIdent<<0x10;
+ LeaveCriticalSection(&cookieMutex);
+
+ return dwThisSeq;
+}
+
+
+
+int GetCookieType(DWORD dwCookie)
+{
+ int i;
+
+ EnterCriticalSection(&cookieMutex);
+
+ i = FindCookieIndex(dwCookie);
+
+ if (i != INVALID_COOKIE_INDEX)
+ i = cookie[i].bType;
+
+ LeaveCriticalSection(&cookieMutex);
+
+ return i;
+}
+
+
+
+int FindCookie(DWORD dwCookie, DWORD *pdwUin, void **ppvExtra)
+{
+ int i;
+ int nFound = 0;
+
+
+ EnterCriticalSection(&cookieMutex);
+
+ i = FindCookieIndex(dwCookie);
+
+ if (i != INVALID_COOKIE_INDEX)
+ {
+ if (pdwUin)
+ *pdwUin = cookie[i].dwUin;
+ if (ppvExtra)
+ *ppvExtra = cookie[i].pvExtra;
+
+ // Cookie found
+ nFound = 1;
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+
+ return nFound;
+}
+
+
+
+int FindCookieByData(void *pvExtra,DWORD *pdwCookie, DWORD *pdwUin)
+{
+ int i;
+ int nFound = 0;
+
+
+ EnterCriticalSection(&cookieMutex);
+
+ for (i = 0; i < cookieCount; i++)
+ {
+ if (pvExtra == cookie[i].pvExtra)
+ {
+ if (pdwUin)
+ *pdwUin = cookie[i].dwUin;
+ if (pdwCookie)
+ *pdwCookie = cookie[i].dwCookie;
+
+ // Cookie found, exit loop
+ nFound = 1;
+ break;
+
+ }
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+
+ return nFound;
+}
+
+
+
+int FindMessageCookie(DWORD dwMsgID1, DWORD dwMsgID2, DWORD *pdwCookie, DWORD *pdwUin, message_cookie_data **ppvExtra)
+{
+ int i;
+ int nFound = 0;
+
+
+ EnterCriticalSection(&cookieMutex);
+
+ for (i = 0; i < cookieCount; i++)
+ {
+ if (cookie[i].bType == CKT_MESSAGE || cookie[i].bType == CKT_FILE || cookie[i].bType == CKT_REVERSEDIRECT)
+ { // message cookie found
+ message_cookie_data *pCookie = (message_cookie_data*)cookie[i].pvExtra;
+
+ if (pCookie->dwMsgID1 == dwMsgID1 && pCookie->dwMsgID2 == dwMsgID2)
+ {
+ if (pdwUin)
+ *pdwUin = cookie[i].dwUin;
+ if (pdwCookie)
+ *pdwCookie = cookie[i].dwCookie;
+ if (ppvExtra)
+ *ppvExtra = pCookie;
+
+ // Cookie found, exit loop
+ nFound = 1;
+ break;
+ }
+ }
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+
+ return nFound;
+}
+
+
+
+void FreeCookie(DWORD dwCookie)
+{
+ int i;
+
+ EnterCriticalSection(&cookieMutex);
+
+ i = FindCookieIndex(dwCookie);
+
+ if (i != INVALID_COOKIE_INDEX)
+ { // Cookie found, remove from list
+ RemoveCookieIndex(i);
+ }
+ RemoveExpiredCookies();
+
+ LeaveCriticalSection(&cookieMutex);
+}
+
+
+
+void ReleaseCookie(DWORD dwCookie)
+{
+ int i;
+
+ EnterCriticalSection(&cookieMutex);
+
+ i = FindCookieIndex(dwCookie);
+
+ if (i != INVALID_COOKIE_INDEX)
+ { // Cookie found, remove from list
+ SAFE_FREE(&cookie[i].pvExtra);
+ RemoveCookieIndex(i);
+ }
+ RemoveExpiredCookies();
+
+ LeaveCriticalSection(&cookieMutex);
+}
+
+
+
+message_cookie_data *CreateMessageCookie(WORD bMsgType, BYTE bAckType)
+{
+ message_cookie_data *pCookie;
+ DWORD dwMsgID1;
+ DWORD dwMsgID2;
+
+ do
+ { // ensure that message ids are unique
+ dwMsgID1 = time(NULL);
+ dwMsgID2 = RandRange(0, 0x0FFFF);
+ } while (FindMessageCookie(dwMsgID1, dwMsgID2, NULL, NULL, NULL));
+
+ pCookie = (message_cookie_data*)SAFE_MALLOC(sizeof(message_cookie_data));
+ if (pCookie)
+ {
+ pCookie->bMessageType = bMsgType;
+ pCookie->nAckType = bAckType;
+ pCookie->dwMsgID1 = dwMsgID1;
+ pCookie->dwMsgID2 = dwMsgID2;
+ }
+ return pCookie;
+}
\ No newline at end of file diff --git a/icqj_mod/cookies.h b/icqj_mod/cookies.h new file mode 100644 index 0000000..1b7c097 --- /dev/null +++ b/icqj_mod/cookies.h @@ -0,0 +1,140 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/cookies.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __COOKIES_H
+#define __COOKIES_H
+
+
+#define CKT_MESSAGE 0x01
+#define CKT_FILE 0x02
+#define CKT_SEARCH 0x04
+#define CKT_SERVERLIST 0x08
+#define CKT_SERVICEREQUEST 0x0A
+#define CKT_REVERSEDIRECT 0x0C
+#define CKT_FAMILYSPECIAL 0x10
+#define CKT_AVATAR 0x20
+
+typedef struct icq_cookie_info_s
+{
+ DWORD dwCookie;
+ DWORD dwUin;
+ void *pvExtra;
+ DWORD dwTime;
+ BYTE bType;
+} icq_cookie_info;
+
+typedef struct familyrequest_rec_s
+{
+ WORD wFamily;
+ void (*familyhandler)(HANDLE hConn, char* cookie, WORD cookieLen);
+} familyrequest_rec;
+
+
+typedef struct message_cookie_data_s
+{
+ DWORD dwMsgID1;
+ DWORD dwMsgID2;
+ WORD bMessageType;
+ BYTE nAckType;
+} message_cookie_data;
+
+#define ACKTYPE_NONE 0
+#define ACKTYPE_SERVER 1
+#define ACKTYPE_CLIENT 2
+
+
+typedef struct fam15_cookie_data_s
+{
+ BYTE bRequestType;
+ HANDLE hContact;
+} fam15_cookie_data;
+
+#define REQUESTTYPE_OWNER 0
+#define REQUESTTYPE_USERAUTO 1
+#define REQUESTTYPE_USERMINIMAL 2
+#define REQUESTTYPE_USERDETAILED 3
+#define REQUESTTYPE_PROFILE 4
+
+
+typedef struct search_cookie_s
+{
+ BYTE bSearchType;
+ char* szObject;
+ DWORD dwMainId;
+ DWORD dwStatus;
+} search_cookie;
+
+#define SEARCHTYPE_UID 0
+#define SEARCHTYPE_EMAIL 1
+#define SEARCHTYPE_NAMES 2
+#define SEARCHTYPE_DETAILS 4
+
+typedef struct avatarcookie_t
+{
+ DWORD dwUin;
+ HANDLE hContact;
+ unsigned int hashlen;
+ char *hash;
+ unsigned int cbData;
+ char *szFile;
+} avatarcookie;
+
+typedef struct {
+ message_cookie_data pMessage;
+ HANDLE hContact;
+ DWORD dwUin;
+ int type;
+ void *ft;
+} reverse_cookie;
+
+
+void InitCookies(void);
+void UninitCookies(void);
+
+DWORD AllocateCookie(BYTE bType, WORD wIdent, DWORD dwUin, void *pvExtra);
+void FreeCookie(DWORD dwCookie);
+void ReleaseCookie(DWORD dwCookie);
+DWORD GenerateCookie(WORD wIdent);
+
+int GetCookieType(DWORD dwCookie);
+
+int FindCookie(DWORD wCookie, DWORD *pdwUin, void **ppvExtra);
+int FindCookieByData(void *pvExtra, DWORD *pdwCookie, DWORD *pdwUin);
+int FindMessageCookie(DWORD dwMsgID1, DWORD dwMsgID2, DWORD *pdwCookie, DWORD *pdwUin, message_cookie_data **ppvExtra);
+
+message_cookie_data *CreateMessageCookie(WORD bMsgType, BYTE bAckType);
+
+#endif /* __COOKIES_H */
diff --git a/icqj_mod/directpackets.c b/icqj_mod/directpackets.c new file mode 100644 index 0000000..cb1d249 --- /dev/null +++ b/icqj_mod/directpackets.c @@ -0,0 +1,303 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/directpackets.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+extern HANDLE hsmsgrequest;
+extern CRITICAL_SECTION modeMsgsMutex;
+extern WORD wListenPort;
+
+extern packEmptyMsg(icq_packet *packet);
+
+
+void packDirectMsgHeader(icq_packet* packet, WORD wDataLen, WORD wCommand, DWORD dwCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wX1, WORD wX2)
+{
+ directPacketInit(packet, 29 + wDataLen);
+ packByte(packet, 2); /* channel */
+ packLEDWord(packet, 0); /* space for crypto */
+ packLEWord(packet, wCommand);
+ packLEWord(packet, 14); /* unknown */
+ packLEWord(packet, (WORD)dwCookie);
+ packLEDWord(packet, 0); /* unknown */
+ packLEDWord(packet, 0); /* unknown */
+ packLEDWord(packet, 0); /* unknown */
+ packByte(packet, bMsgType);
+ packByte(packet, bMsgFlags);
+ packLEWord(packet, wX1); /* unknown. Is 1 for getawaymsg, 0 otherwise */
+ packLEWord(packet, wX2); // this is probably priority
+}
+
+
+
+void icq_sendDirectMsgAck(directconnect* dc, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags, char* szCap)
+{
+ icq_packet packet;
+
+ packDirectMsgHeader(&packet, (WORD)(bMsgType==MTYPE_PLAIN ? (szCap ? 53 : 11) : 3), DIRECT_ACK, wCookie, bMsgType, bMsgFlags, 0, 0);
+ packEmptyMsg(&packet); /* empty message */
+
+ if (bMsgType == MTYPE_PLAIN)
+ {
+ packMsgColorInfo(&packet);
+
+ if (szCap)
+ {
+ packLEDWord(&packet, 0x26); /* CLSID length */
+ packBuffer(&packet, szCap, 0x26); /* GUID */
+ }
+ }
+ EncryptDirectPacket(dc, &packet);
+ sendDirectPacket(dc, &packet);
+
+ NetLog_Direct("Sent acknowledgement thru direct connection");
+}
+
+
+
+DWORD icq_sendGetAwayMsgDirect(HANDLE hContact, int type)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ message_cookie_data *pCookieData;
+
+ if (ICQGetContactSettingWord(hContact, "Version", 0) == 9)
+ return 0; // v9 DC protocol does not support this message
+
+ pCookieData = CreateMessageCookie(MTYPE_AUTOAWAY, (BYTE)type);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, ICQGetContactSettingUIN(hContact), (void*)pCookieData);
+
+ packDirectMsgHeader(&packet, 3, DIRECT_MESSAGE, dwCookie, (BYTE)type, 3, 1, 0);
+ packEmptyMsg(&packet); // message
+
+ if (SendDirectMessage(hContact, &packet))
+ return dwCookie; // Success
+ else
+ return 0;
+}
+
+
+
+void icq_sendAwayMsgReplyDirect(directconnect* dc, WORD wCookie, BYTE msgType, const char** szMsg)
+{
+ icq_packet packet;
+ WORD wMsgLen;
+
+
+ if (validateStatusMessageRequest(dc->hContact, msgType))
+ {
+ NotifyEventHooks(hsmsgrequest, (WPARAM)msgType, (LPARAM)dc->dwRemoteUin);
+
+ EnterCriticalSection(&modeMsgsMutex);
+
+ if (szMsg && *szMsg)
+ {
+ char* szAnsiMsg;
+
+ // prepare Ansi message - only Ansi supported
+ wMsgLen = strlennull(*szMsg) + 1;
+ szAnsiMsg = (char*)_alloca(wMsgLen);
+ utf8_decode_static(*szMsg, szAnsiMsg, wMsgLen);
+ wMsgLen = strlennull(szAnsiMsg);
+ packDirectMsgHeader(&packet, (WORD)(3 + wMsgLen), DIRECT_ACK, wCookie, msgType, 3, 0, 0);
+ packLEWord(&packet, (WORD)(wMsgLen + 1));
+ packBuffer(&packet, szAnsiMsg, (WORD)(wMsgLen + 1));
+ EncryptDirectPacket(dc, &packet);
+
+ sendDirectPacket(dc, &packet);
+ }
+
+ LeaveCriticalSection(&modeMsgsMutex);
+ }
+}
+
+
+
+void icq_sendFileAcceptDirect(HANDLE hContact, filetransfer* ft)
+{ // v7 packet
+ icq_packet packet;
+
+ packDirectMsgHeader(&packet, 18, DIRECT_ACK, ft->dwCookie, MTYPE_FILEREQ, 0, 0, 0);
+ packLEWord(&packet, 1); // description
+ packByte(&packet, 0);
+ packWord(&packet, wListenPort);
+ packLEWord(&packet, 0);
+ packLEWord(&packet, 1); // filename
+ packByte(&packet, 0); // TODO: really send filename
+ packLEDWord(&packet, ft->dwTotalSize); // file size
+ packLEDWord(&packet, wListenPort); // FIXME: ideally we want to open a new port for this
+
+ SendDirectMessage(hContact, &packet);
+
+ NetLog_Direct("Sent file accept direct, port %u", wListenPort);
+}
+
+
+
+void icq_sendFileDenyDirect(HANDLE hContact, filetransfer* ft, char *szReason)
+{ // v7 packet
+ icq_packet packet;
+
+ packDirectMsgHeader(&packet, (WORD)(18+strlennull(szReason)), DIRECT_ACK, ft->dwCookie, MTYPE_FILEREQ, 0, 1, 0);
+ packLEWord(&packet, (WORD)(1+strlennull(szReason))); // description
+ if (szReason) packBuffer(&packet, szReason, (WORD)strlennull(szReason));
+ packByte(&packet, 0);
+ packWord(&packet, 0);
+ packLEWord(&packet, 0);
+ packLEWord(&packet, 1); // filename
+ packByte(&packet, 0); // TODO: really send filename
+ packLEDWord(&packet, 0); // file size
+ packLEDWord(&packet, 0);
+
+ SendDirectMessage(hContact, &packet);
+
+ NetLog_Direct("Sent file deny direct.");
+}
+
+
+
+int icq_sendFileSendDirectv7(filetransfer *ft, const char* pszFiles)
+{
+ icq_packet packet;
+ WORD wDescrLen = strlennull(ft->szDescription), wFilesLen = strlennull(pszFiles);
+
+ packDirectMsgHeader(&packet, (WORD)(18 + wDescrLen + wFilesLen), DIRECT_MESSAGE, (WORD)ft->dwCookie, MTYPE_FILEREQ, 0, 0, 0);
+ packLEWord(&packet, (WORD)(wDescrLen + 1));
+ packBuffer(&packet, ft->szDescription, (WORD)(wDescrLen + 1));
+ packLEDWord(&packet, 0); // listen port
+ packLEWord(&packet, (WORD)(wFilesLen + 1));
+ packBuffer(&packet, pszFiles, (WORD)(wFilesLen + 1));
+ packLEDWord(&packet, ft->dwTotalSize);
+ packLEDWord(&packet, 0); // listen port (again)
+
+ NetLog_Direct("Sending v%u file transfer request direct", 7);
+
+ return SendDirectMessage(ft->hContact, &packet);
+}
+
+
+
+int icq_sendFileSendDirectv8(filetransfer *ft, const char *pszFiles)
+{
+ icq_packet packet;
+ WORD wDescrLen = strlennull(ft->szDescription), wFilesLen = strlennull(pszFiles);
+
+ packDirectMsgHeader(&packet, (WORD)(0x2E + 22 + wDescrLen + wFilesLen + 1), DIRECT_MESSAGE, (WORD)ft->dwCookie, MTYPE_PLUGIN, 0, 0, 0);
+ packEmptyMsg(&packet); // message
+ packPluginTypeId(&packet, MTYPE_FILEREQ);
+
+ packLEDWord(&packet, (WORD)(18 + wDescrLen + wFilesLen + 1)); // Remaining length
+ packLEDWord(&packet, wDescrLen); // Description
+ packBuffer(&packet, ft->szDescription, wDescrLen);
+ packWord(&packet, 0x8c82); // Unknown (port?), seen 0x80F6
+ packWord(&packet, 0x0222); // Unknown, seen 0x2e01
+ packLEWord(&packet, (WORD)(wFilesLen + 1));
+ packBuffer(&packet, pszFiles, (WORD)(wFilesLen + 1));
+ packLEDWord(&packet, ft->dwTotalSize);
+ packLEDWord(&packet, 0x0008c82); // Unknown, (seen 0xf680 ~33000)
+
+ NetLog_Direct("Sending v%u file transfer request direct", 8);
+
+ return SendDirectMessage(ft->hContact, &packet);
+}
+
+
+
+DWORD icq_SendDirectMessage(DWORD dwUin, HANDLE hContact, const char *szMessage, int nBodyLength, WORD wPriority, message_cookie_data *pCookieData, char *szCap)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+
+
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, dwUin, (void*)pCookieData);
+
+ // Pack the standard header
+ packDirectMsgHeader(&packet, (WORD)(nBodyLength + (szCap ? 53:11)), DIRECT_MESSAGE, dwCookie, (BYTE)pCookieData->bMessageType, 0, 0, 0);
+
+ packLEWord(&packet, (WORD)(nBodyLength+1)); // Length of message
+ packBuffer(&packet, szMessage, (WORD)(nBodyLength+1)); // Message
+ packMsgColorInfo(&packet);
+ if (szCap)
+ {
+ packLEDWord(&packet, 0x00000026); // length of GUID
+ packBuffer(&packet, szCap, 0x26); // UTF-8 GUID
+ }
+
+ if (SendDirectMessage(hContact, &packet))
+ return dwCookie; // Success
+ else
+ {
+ FreeCookie(dwCookie); // release cookie
+
+ return 0; // Failure
+ }
+}
+
+
+
+void icq_sendXtrazRequestDirect(DWORD dwUin, HANDLE hContact, DWORD dwCookie, char* szBody, int nBodyLen, WORD wType)
+{
+ icq_packet packet;
+
+ packDirectMsgHeader(&packet, (WORD)(11 + getPluginTypeIdLen(wType) + nBodyLen), DIRECT_MESSAGE, dwCookie, MTYPE_PLUGIN, 0, 0, 1);
+ packEmptyMsg(&packet); // message (unused)
+ packPluginTypeId(&packet, wType);
+
+ packLEDWord(&packet, nBodyLen + 4);
+ packLEDWord(&packet, nBodyLen);
+ packBuffer(&packet, szBody, (WORD)nBodyLen);
+
+ SendDirectMessage(hContact, &packet);
+}
+
+
+
+void icq_sendXtrazResponseDirect(DWORD dwUin, HANDLE hContact, WORD wCookie, char* szBody, int nBodyLen, WORD wType)
+{
+ icq_packet packet;
+
+ packDirectMsgHeader(&packet, (WORD)(getPluginTypeIdLen(wType) + 11 + nBodyLen), DIRECT_ACK, wCookie, MTYPE_PLUGIN, 0, 0, 0);
+ //
+ packEmptyMsg(&packet); // Message (unused)
+
+ packPluginTypeId(&packet, wType);
+
+ packLEDWord(&packet, nBodyLen + 4);
+ packLEDWord(&packet, nBodyLen);
+ packBuffer(&packet, szBody, (WORD)nBodyLen);
+
+ SendDirectMessage(hContact, &packet);
+}
diff --git a/icqj_mod/directpackets.h b/icqj_mod/directpackets.h new file mode 100644 index 0000000..54513a2 --- /dev/null +++ b/icqj_mod/directpackets.h @@ -0,0 +1,55 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/directpackets.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_DIRECTPACKETS_H
+#define __ICQ_DIRECTPACKETS_H
+
+// Direct packet senders
+void packDirectMsgHeader(icq_packet *packet, WORD wDataLen, WORD wCommand, DWORD dwCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wX1, WORD wX2);
+
+void icq_sendDirectMsgAck(directconnect* dc, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags, char* szCap);
+
+DWORD icq_sendGetAwayMsgDirect(HANDLE hContact, int type);
+int icq_sendFileSendDirectv7(filetransfer *ft, const char *pszFiles);
+int icq_sendFileSendDirectv8(filetransfer *ft, const char *pszFiles);
+void icq_sendFileAcceptDirect(HANDLE hContact, filetransfer *ft);
+void icq_sendFileDenyDirect(HANDLE hContact, filetransfer* ft, char *szReason);
+DWORD icq_SendDirectMessage(DWORD dwUin, HANDLE hContact, const char *szMessage, int nBodyLength, WORD wPriority, message_cookie_data *pCookieData, char *szCap);
+
+void icq_sendXtrazRequestDirect(DWORD dwUin, HANDLE hContact, DWORD dwCookie, char* szBody, int nBodyLen, WORD wType);
+void icq_sendXtrazResponseDirect(DWORD dwUin, HANDLE hContact, WORD wCookie, char* szBody, int nBodyLen, WORD wType);
+
+#endif /* __ICQ_DIRECTPACKETS_H */
diff --git a/icqj_mod/docs/IcqOscarJ-db settings.txt b/icqj_mod/docs/IcqOscarJ-db settings.txt new file mode 100644 index 0000000..3bfa96e --- /dev/null +++ b/icqj_mod/docs/IcqOscarJ-db settings.txt @@ -0,0 +1,142 @@ +"Server" +Type=string +Default="icq.mirabilis.com" +Contacts: NULL only +Written by: +The server name passed to icqlib to log on to + +
+"Port" +Type=word +Default=4000 +Contacts: NULL and normal +Written by: protocols/icq (normal) +for NULL: The port for the above server +for normal: The port on which to do direct communication with that contact. +Only valid if the contact is currently online. +
+
+"UIN" +Type=dword +Contacts: NULL and normal +Written by: random/firstrun (NULL), protocols/icq (normal), random/icqimport (normal), random/auth (normal), ui/findadd (normal) +For the user contact, this stores the UIN that is used for this profile +For other contacts, it is the UIN of the contact. This setting is often used +to detect if a contact is an ICQ contact, as opposed to any other sort. +If you create a new contact and just set this value, other modules will pick +up on the fact and do everything that needs to be done for a new ICQ contact. +
+ +"Enable" +Type=byte +Default=1 +Contacts: NULL only +Written by: random/firstrun +Whether to use the ICQ protocol for this profile. At startup, protocols/icq +does not load and returns with no error if this setting is true. +
+
+"Status" +Type=word +Contacts: normal only +Written by: protocols/icq +The status mode of the contact, using the numbers defined by ui/contactlist +(see m_clist.h) +
+
+"Password" +Type=string +Contacts: NULL only +Written by: random/firstrun +The password to use when this profile logs into the ICQ server +
+
+"UseProxy" +Type=byte +Default=0 +Contacts: NULL only +Written by: +Whether to use a proxy server when logging in to the ICQ server +
+
+"ProxyHost" +Type=string +Contacts: NULL only +Written by: +The name of the proxy server to use when logging in to the ICQ server + +
+"ProxyPort" +Type=word +Default=1080 +Contacts: NULL only +Written by: +The port to access the above server on + +
+"ProxyAuth" +Type=byte +Default=0 +Contacts: NULL only +Written by: +Whether the ICQ proxy requires a user name and password to access it +
+
+"ProxyUser" +Type=string +Contacts: NULL only +Written by: +The user name to use to log in to the above proxy +
+
+"ProxyPassword" +Type=string +Contacts: NULL only +Written by: +The password to use to log in to the above proxy + +
+"IP" +Type=dword +Contacts: normal only +Written by: protocols/icq +The current or last IP address of a contact that has at one time been online +at the same time as the user. +
+ +"RealIP" +Type=dword +Contacts: normal only +Written by: protocols/icq +The IP of a contact who is behind a proxy. If this is equal to "IP" then the +user probably isn't behind a proxy. +
+ +"Auth" +Type=byte +Contacts: NULL and normal +Written by: protocols/icq (normal) +True if the contact requires an authorisation request before they can be added +to your contact list +
+
+"FirstName","LastName","e-mail","Nick","City","Country","State","Phone","Homepage","About" +Type=string +Contacts: NULL and normal +Written by: protocols/icq (normal) +As stored in the ICQ server's database + +
+"Age" +Type=word +Contacts: NULL and normal +Written by: protocols/icq (normal) +As stored in the ICQ server's database +
+
+"Gender" +Type=byte +Contacts: NULL and normal +Written by: protocols/icq (normal) +As stored in the ICQ server's database. Values are 'M', 'F' or '?' for +unspecified diff --git a/icqj_mod/docs/IcqOscarJ-translation.txt b/icqj_mod/docs/IcqOscarJ-translation.txt new file mode 100644 index 0000000..7632a3a --- /dev/null +++ b/icqj_mod/docs/IcqOscarJ-translation.txt @@ -0,0 +1,215 @@ +Miranda Language Pack Version 1
+Locale: 0809
+Authors: Martin Öberg, Richard Hughes, Jon Keating, Joe Kucera
+Author-email: info@miranda-im.org
+Last-Modified-Using: Miranda IM 0.4
+Plugins-included:
+
+; Generated by lpgen on Mon May 16 15:18:49 2005
+; Translations: 175
+
+; chan_04close.c
+;[You could not sign on because the server returned invalid data. Try again.]
+;[You have been disconnected from the ICQ network because the current server shut down.]
+;[Connection failed.\nYour ICQ number or password was rejected (%d).]
+;[Connection failed.\nThe server is temporally unavailable (%d).]
+;[Connection failed.\nServer has too many connections from your IP (%d).]
+;[Connection failed.\nYou have connected too quickly,\nplease wait and retry 10 to 20 minutes later (%d).]
+;[Connection failed.\nThe server did not accept this client version.]
+;[The server sent warning, this version is getting old.\nTry to look for a new one.]
+;[Connection failed.\nYou were rejected by the server for an unknown reason.\nThis can happen if the UIN is already connected.]
+;[Connection failed.\nUnknown error during sign on: 0x%02x]
+;[You have been disconnected from the ICQ network because you logged on from another location using the same ICQ number.]
+;[Unknown runtime error: 0x%02x]
+
+; fam_01service.c
+;[A server migration has failed because the server returned invalid data. You must reconnect manually.]
+
+; fam_04message.c
+;[You are sending too fast. Wait a while and try again.\nSNAC(4.1) Error x02]
+;[You are sending too fast. Wait a while and try again.\nSNAC(4.1) Error x03]
+;[The user has logged off. Select 'Retry' to send an offline message.\nSNAC(4.1) Error x04]
+;[The receiving client does not support this type of message.\nSNAC(4.1) Error x09]
+;[You sent too long message. The receiving client does not support it.\nSNAC(4.1) Error x0A]
+;[The SNAC format was rejected by the server.\nSNAC(4.1) Error x0E]
+;[The user is temporarily unavailable. Wait a while and try again.\nSNAC(4.1) Error x13]
+;[SNAC(4.1) SENDMSG Error (x%02x)]
+;[** This message was blocked by the ICQ server ** The message was invalid.]
+;[** This message was blocked by the ICQ server ** The message was too long.]
+;[** This message was blocked by the ICQ server ** The sender has flooded the server.]
+;[** This message was blocked by the ICQ server ** You are too evil.]
+
+; fam_13servclist.c
+;[Server contact list is unavailable, Miranda will use local contact list.]
+;[Renaming of server contact failed.]
+;[Update of server contact's comment failed.]
+;[Adding of privacy item to server list failed.]
+;[Removing of privacy item from server list failed.]
+;[Adding of contact to server list failed.]
+;[Adding of group to server list failed.]
+;[Removing of contact from server list failed.]
+;[Updating of group on server list failed.]
+;[Removing of group from server list failed.]
+;[Moving of user to another group on server list failed.]
+;[Renaming of server group failed.]
+
+; icq_filerequests.c
+;[No description given]
+
+; icq_filetransfer.c
+;[Your file transfer has been aborted because one of the files that you selected to send is no longer readable from the disk. You may have deleted or moved it.]
+;[Your file receive has been aborted because Miranda could not open the destination file in order to write to it. You may be trying to save to a read-only folder.]
+
+; icq_opts.c
+;[Network]
+;[Contacts]
+;[Privacy]
+
+; icq_uploadui.c
+;[Select contacts you want to store on server.]
+;[Ready...]
+;[Adding group \"%s\"...]
+;[Uploading %s...]
+;[Uploading %u...]
+;[FAILED]
+;[No upload group available]
+;[Deleting %s...]
+;[Deleting %u...]
+;[Moving %s to group \"%s\"...]
+;[Moving %u to group \"%s\"...]
+;[Adding %u to visible list...]
+;[Adding %u to invisible list...]
+;[Deleting %u from visible list...]
+;[Deleting %u from invisible list...]
+;[Cleaning groups]
+;[Updating group \"%s\"...]
+;[Deleting group \"%s\"...]
+;[All operations complete]
+;[Close]
+;[You have to be online to sychronize the server-list !]
+;[** All contacts **]
+
+; icqosc_svcs.c
+;[User ID]
+;[You have not entered a ICQ number.\nConfigure this in Options->Network->ICQ and try again.]
+;[The receiver has an invalid user ID.]
+;[You cannot send messages when you are offline.]
+;[Messages to offline contacts must be shorter than 450 characters.]
+;[Bad data (internal error #1)]
+;[Bad data (internal error #2)]
+
+; init.c
+;[Request authorization]
+;[Grant authorization]
+;[%s server connection]
+;[%s client-to-client connections]
+
+; log.c
+;[error]
+
+; askauthentication.c
+;[Please authorize me to add you to my contact list.]
+
+; loginpassword.c
+;[Enter a password for UIN %u:]
+
+; userinfotab.c
+;[Avatar]
+;[%s Avatar]
+;[Member since:]
+;[Male]
+;[Female]
+;[<not specified>]
+
+; resources.rc
+;[Create new account]
+;[Allow direct connections with any user]
+;[Allow direct connections with users on my contact list]
+;[Allow direct connections only for file transfers and chats]
+;[All users may add me to their Contact List]
+;[I want to be asked when someone wants to add me to their Contact List]
+;[Allow others to view my Online / Offline status from the web (Web Aware)]
+;[Allow others to view my primary e-mail address]
+;[Only reply to status message requests from users on my contact list]
+;[Only reply to status message request from visible contacts]
+;[Change my details using the ICQ website]
+;[Search online users only]
+;[Retrieve a lost password or ICQ number]
+;[Create a new ICQ account using the ICQ website]
+;[Use HTTP Gateway mode for HTTP proxy]
+;[Send 'Keep-alives' (enable this if you use a proxy server and frequently get disconnected)]
+;[Notify me when a message delivery has failed]
+;[Slider1]
+;[Enable server-side contact lists *]
+;[Add contacts to the server's list when I add them to mine]
+;[Update my contacts' details from the server *]
+;[Update contacts' details on the server's list when I change them in mine]
+;[Enable avatar support]
+;[Load avatars automatically (like ICQ Lite)]
+;[Link avatars as contact photos (mToolTip photos)]
+;[OK]
+;[&Send]
+;[Synchronize]
+;[Cancel]
+;[&Cancel]
+;[Set]
+;[Delete]
+;[Default]
+;[Manage server's list...]
+;[Please enter your ICQ account details to continue:]
+;[ICQ number:]
+;[Password:]
+;[Enter a password for UIN %d:]
+;[Allowing direct connections will expose your IP address but may be necessary for some ICQ features to work properly.]
+;[UIN:]
+;[External IP:]
+;[Internal IP:]
+;[Port:]
+;[Protocol Version:]
+;[User Client:]
+;[Online since:]
+;[System up since:]
+;[Idle since:]
+;[First name:]
+;[Last name:]
+;[Nickname:]
+;[E-mail:]
+;[Gender:]
+;[Age:]
+;[Field:]
+;[Company:]
+;[Department:]
+;[Position:]
+;[Organisation:]
+;[Keywords:]
+;[Language:]
+;[Country:]
+;[State:]
+;[City:]
+;[Interests]
+;[Category:]
+;[Past]
+;[Homepage]
+;[Login Server:]
+;[Show connection error messages:]
+;[Hint: Use port 0 to connect on a random port. Try port 80 or port 443 if you are having problems connecting through a http proxy server.]
+;[Hint: If you don't enter your password here, Miranda will ask for the password everytime you try to go online.]
+;[You will need to reconnect to the ICQ network for the changes you have made on this page to take effect.]
+;[You cannot enable/disable the server-side contact list while you are connected to the ICQ network.]
+;[Select contacts to store:]
+;[Direct connections]
+;[Contact List Authorization]
+;[Misc Settings]
+;[Summary]
+;[Work]
+;[Location]
+;[Background]
+;[ICQ]
+;[Connection settings]
+;[ICQ contacts stored on server]
+;[ICQ avatars]
+;[ICQ Account Setup]
+;[Enter an authorization request]
+;[Enter ICQ Password]
+;[Manage ICQ Server Contacts]
+
diff --git a/icqj_mod/docs/icq-license.txt b/icqj_mod/docs/icq-license.txt new file mode 100644 index 0000000..7f11610 --- /dev/null +++ b/icqj_mod/docs/icq-license.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/icqj_mod/docs/icq-readme.txt b/icqj_mod/docs/icq-readme.txt new file mode 100644 index 0000000..48888bd --- /dev/null +++ b/icqj_mod/docs/icq-readme.txt @@ -0,0 +1,344 @@ +
+ ICQ protocol plugin for Miranda IM (Joe)
+ ________________________________________
+
+
+About
+_____
+
+This Miranda IM plugin makes it possible to connect to the ICQ
+instant messenger network and communicate with other ICQ users.
+
+
+Known Problems
+______________
+
+- In Invisible mode, when other side is not in visible list messages are sometimes
+ received twice from some clients (it is a problem of that clients, they do send them
+ twice)
+
+- In Invisible mode, when other side is not in visible list messages are not unicode
+ aware. This is because ICQ protocol does not support unicode offline messages.
+ You can partly solve this by setting proper codepage for the contact - database setting
+ WORD "CodePage" in ICQ scope
+
+- When synchronising server-list, users get added with await auth flag or receive added
+ message. The way which ICQ servers handle authorizations, we cannot do it better - when
+ uploading contacts to server account has to be a new one, then contacts can be added
+ and uploaded without auth... If the account is an old one they cannot be added without
+ auth if they require one. So they are added with flag awaiting auth. With the new
+ Manage server list contacts added contacts should never receive auth requests, but
+ if you have an old account they can receive added notification.
+
+- Some wicked firewall software can cause HTML tags (e.g. <font> </font>) to be added to
+ incoming messages.
+
+TO-DO List
+__________
+
+0.3.9
+ Manage server-list dialog now groups requests - much faster
+ Full support for sub-groups in Manage server-list dialog
+ Real Level 1 rate management (will solve multi-recipient message problems)
+ AIM file transfers (OFT) - like icq5 (including transfer thru server)
+
+0.5
+ Account management (together with Miranda core changes)
+ Multi-user chat (Xtraz based)
+
+
+
+Changes
+_______
+
+0.3.7
+
+Bugfixes:
+ Our own contact in list now correctly handles events
+ Proxy Gateway mode is working again
+ File receiving from Trillian clients work again
+ Incorporated some bugfixes from ISee (thx Bio)
+ Message errors are now really displayed
+ Fixed memory leak in avatar code
+ File transfers with GnomeICU works now
+ Fixed changing password in ICQ Details will not save it to DB if not there
+ Fixed PING channel handling (caused connection drop)
+ Fixed bug in changeinfo with translated listbox values (thx Bio)
+ Fixed error handling in avatar code for uploading avatar
+ Fixed bug in Manage-Server list dialog, caused hang
+ Fixed occasional losing of messages (message parsing was incomplete)
+ Server-list management now stores all info - solves problems
+ Fixed unknown errors during login were not reported sometimes
+
+New Features:
+ Messaging support enhanced (P2P messaging supported)
+ Direct Connection support rewritten (with P2P messaging and reverse file-transfers)
+ Temporary Visible List support
+ New Features page in options to configure extra features
+ Custom statuses just like icq5 - needs clist_mw derivative (thx Big Muscle)
+ New custom status icons (thx Angeli-ka)
+ Enhanced Unicode & Ansi charsets support (each contact can have its own codepage)
+ AIM cross-compatability (add/remove, search by mail, status, messaging, away messages)
+ Secure MD5 login authentification
+ Revoke authorization (Advanced Feature - see further) - removes you from contact's server-list
+
+Improvements:
+ Advanced search now can use newer method (thx Bio)
+ Better protocol error handling
+ Slightly better avatar handling
+ Detects some spam bots & ability to block known spam bots
+ Merged with ChangeInfo (thx Bio)
+ Added possibility to remember password for session
+ Added possibility to retrieve away message from libgaim clients
+ Added status to UserInfo page
+ Small improvements to client detection
+ Uses newer capabilities format (cuts incoming traffic)
+ Display error messages using PopUp Plugin
+ Support for Iconlib Plugin
+ Support for unicode database module (clist data)
+ Level 2 Rate management for Status & Xtraz replies, Xtraz requests (useful with many contacts in list)
+ Full unicode/ansi support (2in1)
+ Support for Updater Plugin
+ Added support for Flash Avatars Service Plugin
+ Added ability to upload own flash avatar - XML file (thx Big Muscle)
+
+
+0.3.5.3
+
+Bugfixes:
+ Fixed losing of almost all messages (protocol change)
+
+
+0.3.5.2
+
+Bugfixes:
+ Error checking on offline messages was not working
+ Now correctly handles "import time" item (should solve some auth issues)
+
+
+0.3.5.1
+
+Bugfixes:
+ Renaming of server groups was not working properly - caused errors
+ Avatar could not be deleted (the delete button did not work)
+ File Transfers were not working properly in some cases (wrong cookie handling)
+ Avatar formats were not recognized correctly
+ Method of determining target dir in file receive was not solid enough
+ Manage server-list dialog leaked memory
+ Synchronize visibility items was not working properly
+ Our avatar image was not linked to our ContactPhoto
+ Added workaround for DB Blob caching issues
+ Fixed occasional crash on login (missing TLV validity checks)
+ Fixed slow update of nicks when users imported from server-list
+ Fixed auto info update mechanism, do not progress too fast, do not drop processing
+ Fixed empty groups are always hidden in Manage Server List, cannot be used either
+ Fixed occasional crash on avatar retrieval - limit size of image to the size of packet
+ If our rate is high, ignore user requests for status msgs & user details (prevents disconnection)
+ Added temporary solution for roughly translated ICQ 2003b russian
+ Manage server-list dialog could display other contacts and could crash
+ Basic search could search for bad uin - garbage can be in the string
+ Added workaround for select() malfunction - caused high CPU load
+
+Improvements:
+ If Update details from server is on, user groups are also updated
+ Changed System Uptime to Member since in my details
+ Auth system recognizes & sends UTF-8 messages
+ Miranda version signature improved (preparing for old signature removal in the future)
+ Added better error detection for offline msgs receival process
+ Made avatar handling more resilient to server errors
+
+
+0.3.5
+
+Bugfixes:
+ Server-list operations is now scheduled correctly
+ Newly added contact with privacy setting is not hidden anymore
+ Fixed unicode message receiving from Icq2Go! (messages were corrupted)
+ Fixed Grant authorization - not showed correctly and crashing randomly
+ Move to group was not working properly
+ On accept/decline filetransfer miranda was sometimes disconnected
+ Group with subgroups was deleted if empty, that messed up subgroups
+ Newly added contacts from server sometimes missed their group
+ Offline messages are no longer received older than existing ones
+ Now will not try to add contacts to server, which are not ours
+ Divided server ids to groups - caused strange behaviour if id and group id were same
+ Other small fixes
+
+New features:
+ Added avatar tab to user-details dialog to show avatar even without mToolTip
+ Linking avatar to mToolTip is now optional
+ My user-details now show more informations & added idle since to ICQ tab
+ Added support for uploading your own avatar image
+
+Improvements:
+ Rewritten Manage Server List dialog - now works perfectly (without sub-groups support)
+ Added partial support for subgroups (supported: rename, move, parial: add)
+ Added optional linking to mToolTip, link only if no image set
+ Added workaround for QNext client (it is not capable of type2 msgs)
+ Added option to turn off HTTP gateway on HTTP proxy
+
+
+0.3.4.2 (not published)
+
+Bugfixes:
+ Fixed authorization reply
+ Fixed contact transfer ack
+ Now parses URL send ack correctly, no more timeout
+ Now sending ack on contacts receive
+ Now correctly add contact without auth if they does not require it
+ Fixed crash on receiving long message through P2P (very old bug)
+ Many other fixes (see CVS changelog for details)
+
+New features:
+ Added full unicode message support (requires SRMM Unicode)
+ Added support for sending and receiving Idle time.
+ Added reliable client identification (if not identified, gives appropriate ICQ client)
+ Added support for avatar images (downloading only).
+ Added Grant authorization option (send & recognize)
+
+Improvements:
+ Server-side list support rewritten, now uses acking, partly supports groups (without sub-groups for now).
+ Most cookies standardised to imitate icq5 behaviour
+ Basic search now automatically removes garbage from text, e.g. it can search by 123-456-789
+
+
+0.3.3.1
+
+Bugfixes:
+ Could crash when receiving unicode messages.
+
+
+0.3.3
+
+Bugfixes:
+ Failed to send or receive files from ICQ 2003b.
+ Fixed a number of smaller memory leaks.
+ Contact e-mail info was not displayed correctly.
+ Failed to retrieve user details during certain circumstances.
+ URL messages could disappear when sent through a Direct Connection.
+ Nick name was not deleted from server list when local nick name was deleted.
+ Server side contacts could reappear after being deleted if they were on the
+ visible/invisible lists.
+ Changing status while connecting had no effect.
+ A bunch of other fixes that are too boring to list here, have a look at
+ the CVS changelog if you want the big list.
+
+New features:
+ Added support for sending and receiving Typing Notifications.
+ Now accepts messages formatted in unicode (note: this wont solve the problem
+ with displaying messages with multiple charsets).
+
+Improvements:
+ Uses plugin DLL name in various menus to make it easier to have several ICQ
+ plugins loaded.
+ More robust packet parsing reduces the risk of any future stability problems.
+
+
+0.3.2
+
+Bugfixes:
+ Prevent your status messages being read when you are invisible.
+ Small memory leak when sending an SMS.
+ Fixed a dumb bug that caused random disconnections from the ICQ server.
+ Cleaned up the code for searches and user info updates, should work better now.
+ AIM users in your server contact list would get added locally with uin 0.
+
+New features:
+ Added "missed message" notification.
+
+Improvements:
+ Added better error messages for message send failures.
+ Messages now default to the most reliable delivery method available for a given contact.
+
+
+0.3.1
+
+Bugfixes:
+ Fixed crash when incoming file transfer was cancelled before the transfer started
+ Failed to receive SMS messages sent while offline
+ Fixed some problems with accepting file transfers from Mirabilis clients
+ Increased thread safety to reduce some reported connection/disconnection problems
+ Fixed compability problems with sending messages to some jabber clients
+ Fixed some message compability problems with Trillian
+ Corrected some ack sending
+ Added a lot of safety checks to increase general stability
+ Plugin didnt load unless winsocks2 was installed
+
+New features:
+ Removed restrictions on UIN length for better compability with iserverd
+ The password can now be left empty in options, it will be asked for during login
+ Server port can now be left empty in options, a random port will be selected during login
+ Show logged on since and system uptime info in ICQ tab
+
+Improvements:
+ Reduced file size
+ Message sending now uses a more reliable delivery method
+
+
+
+Support and bug reporting
+_________________________
+
+We cannot give support on e-mail or ICQ. Please visit the Miranda IM help page at
+http://www.miranda-im.org/help/ if you need help with this plugin.
+
+If the help page does answer your question, visit the Miranda support forum at:
+http://forums.miranda-im.org/ and we will try to assist you.
+
+If you want to report a bug, please do so in the official bugtracker at:
+http://bugs.miranda-im.org/
+
+
+
+Contact
+_______
+
+Current maintainer is Joe @ Whale, jokusoftware at miranda-im.org
+
+
+
+Advanced Features
+_________________
+
+There are some features that are not widely used so there is no UI for them, if
+you want to use them you need to do manual setup using DBE++.
+
+Database items (usually at Contact\ICQ):
+(BYTE)UnicodeSend = 0 - to Disable unicode support (useful as a workaround for Trillian's bug)
+
+(WORD)CodePage - codepage for plain text encoding/decoding to/from unicode
+
+(WORD)InfoCodePage - codepage for interpreting user details
+
+Database items for Main Contact (usually at Settings\ICQ):
+(BYTE)InfoUpdate - Threshold in DAYS for updating user info (restart is needed) - default is 14 days
+
+(BYTE)PrivacyItems = 1 - adds more privacy tools to contact menu (e.g. Revoke Authorization)
+
+
+
+Credits and Thanks
+__________________
+
+Thanks to Angeli-Ka for nice custom status icons.
+
+
+
+License and Copyright
+_____________________
+
+Copyright (C) 2000-2006 Joe Kucera, Martin Öberg, Richard Hughes, Jon Keating
+
+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.
\ No newline at end of file diff --git a/icqj_mod/docs/icq-readme.txt.bak b/icqj_mod/docs/icq-readme.txt.bak new file mode 100644 index 0000000..6da3c39 --- /dev/null +++ b/icqj_mod/docs/icq-readme.txt.bak @@ -0,0 +1,334 @@ +
+ ICQ protocol plugin for Miranda IM (Joe)
+ ________________________________________
+
+
+About
+_____
+
+This Miranda IM plugin makes it possible to connect to the ICQ
+instant messenger network and communicate with other ICQ users.
+
+
+Known Problems
+______________
+
+- In Invisible mode, when other side is not in visible list messages are sometimes
+ received twice from some clients (it is a problem of that clients, they do send them
+ twice)
+
+- In Invisible mode, when other side is not in visible list messages are not unicode
+ aware. This is because ICQ protocol does not support unicode offline messages.
+ You can partly solve this by setting proper codepage for the contact - database setting
+ WORD "CodePage" in ICQ scope
+
+- When synchronising server-list, users get added with await auth flag or receive added
+ message. The way which ICQ servers handle authorisations, we cannot do it better - when
+ uploading contacts to server account has to be a new one, then contacts can be added
+ and uploaded without auth... If the account is an old one they cannot be added without
+ auth if they require one. So they are added with flag awaiting auth. With the new
+ Manage server list contacts added contacts should never receive auth requests, but
+ if you have an old account they can receive added notification.
+
+
+TO-DO List
+__________
+
+0.3.9
+ Manage server-list dialog now groups requests - much faster
+ Full support for sub-groups in Manage server-list dialog
+ Real Level 1 rate management (will solve multi-recipient message problems)
+ AIM file transfers (OFT) - like icq5 (including transfer thru server)
+
+0.5
+ Account management (together with Miranda core changes)
+ Multi-user chat (Xtraz based)
+
+
+
+Changes
+_______
+
+0.3.6
+
+Bugfixes:
+ Our own contact in list now correctly handles events
+ Proxy Gateway mode is working again
+ File receiving from Trillian clients work again
+ Incorporated some bugfixes from ISee (thx Bio)
+ Message errors are now really displayed
+ Fixed memory leak in avatar code
+ File transfers with GnomeICU works now
+ Fixed changing password in ICQ Details will not save it to DB if not there
+ Fixed PING channel handling (caused connection drop)
+ Fixed bug in changeinfo with translated listbox values (thx Bio)
+ Fixed error handling in avatar code for uploading avatar
+ Fixed bug in Manage-Server list dialog, caused hang
+ Fixed occasional losing of messages (message parsing was incomplete)
+ Server-list management now stores all info - solves problems
+
+New Features:
+ Messaging support enhanced (P2P messaging supported)
+ Direct Connection support rewritten (with P2P messaging and reverse file-transfers)
+ Temporary Visible List support
+ New Features page in options to configure extra features
+ Custom statuses just like icq5 - needs clist_mw derivative (thx Big Muscle)
+ New custom status icons (thx Angeli-ka)
+ Enhanced Unicode & Ansi charsets support (each contact can have its own codepage)
+ AIM cross-compatability (add/remove, search by mail, status, messaging, away messages)
+ Secure MD5 login authentification
+ Revoke authorization (Advanced Feature - see further) - removes you from contact's server-list
+
+Improvements:
+ Advanced search now can use newer method (thx Bio)
+ Better protocol error handling
+ Slightly better avatar handling
+ Detects some spam bots & ability to block known spam bots
+ Merged with ChangeInfo (thx Bio)
+ Added possibility to remember password for session
+ Added possibility to retrieve away message from libgaim clients
+ Added status to UserInfo page
+ Small improvements to client detection
+ Uses newer capabilities format (cuts incoming traffic)
+ Display error messages using PopUp Plugin
+ Support for Iconlib Plugin
+ Support for unicode database module (clist data)
+ Level 2 Rate management for Status & Xtraz replies, Xtraz requests (useful with many contaccts in list)
+ Full unicode/ansi support (2in1)
+ Support for Updater Plugin
+
+
+0.3.5.2
+
+Bugfixes:
+ Error checking on offline messages was not working
+ Now correctly handles "import time" item (should solve some auth issues)
+
+
+0.3.5.1
+
+Bugfixes:
+ Renaming of server groups was not working properly - caused errors
+ Avatar could not be deleted (the delete button did not work)
+ File Transfers were not working properly in some cases (wrong cookie handling)
+ Avatar formats were not recognized correctly
+ Method of determining target dir in file receive was not solid enough
+ Manage server-list dialog leaked memory
+ Synchronize visibility items was not working properly
+ Our avatar image was not linked to our ContactPhoto
+ Added workaround for DB Blob caching issues
+ Fixed occasional crash on login (missing TLV validity checks)
+ Fixed slow update of nicks when users imported from server-list
+ Fixed auto info update mechanism, do not progress too fast, do not drop processing
+ Fixed empty groups are always hidden in Manage Server List, cannot be used either
+ Fixed occasional crash on avatar retrieval - limit size of image to the size of packet
+ If our rate is high, ignore user requests for status msgs & user details (prevents disconnection)
+ Added temporary solution for roughly translated ICQ 2003b russian
+ Manage server-list dialog could display other contacts and could crash
+ Basic search could search for bad uin - garbage can be in the string
+ Added workaround for select() malfunction - caused high CPU load
+
+Improvements:
+ If Update details from server is on, user groups are also updated
+ Changed System Uptime to Member since in my details
+ Auth system recognizes & sends UTF-8 messages
+ Miranda version signature improved (preparing for old signature removal in the future)
+ Added better error detection for offline msgs receival process
+ Made avatar handling more resilient to server errors
+
+
+0.3.5
+
+Bugfixes:
+ Server-list operations is now scheduled correctly
+ Newly added contact with privacy setting is not hidden anymore
+ Fixed unicode message receiving from Icq2Go! (messages were corrupted)
+ Fixed Grant authorisation - not showed correctly and crashing randomly
+ Move to group was not working properly
+ On accept/decline filetransfer miranda was sometimes disconnected
+ Group with subgroups was deleted if empty, that messed up subgroups
+ Newly added contacts from server sometimes missed their group
+ Offline messages are no longer received older than existing ones
+ Now will not try to add contacts to server, which are not ours
+ Divided server ids to groups - caused strange behaviour if id and group id were same
+ Other small fixes
+
+New features:
+ Added avatar tab to user-details dialog to show avatar even without mToolTip
+ Linking avatar to mToolTip is now optional
+ My user-details now show more informations & added idle since to ICQ tab
+ Added support for uploading your own avatar image
+
+Improvements:
+ Rewritten Manage Server List dialog - now works perfectly (without sub-groups support)
+ Added partial support for subgroups (supported: rename, move, parial: add)
+ Added optional linking to mToolTip, link only if no image set
+ Added workaround for QNext client (it is not capable of type2 msgs)
+ Added option to turn off HTTP gateway on HTTP proxy
+
+
+0.3.4.2 (not published)
+
+Bugfixes:
+ Fixed authorisation reply
+ Fixed contact transfer ack
+ Now parses URL send ack correctly, no more timeout
+ Now sending ack on contacts receive
+ Now correctly add contact without auth if they does not require it
+ Fixed crash on receiving long message through P2P (very old bug)
+ Many other fixes (see CVS changelog for details)
+
+New features:
+ Added full unicode message support (requires SRMM Unicode)
+ Added support for sending and receiving Idle time.
+ Added reliable client identification (if not identified, gives appropriate ICQ client)
+ Added support for avatar images (downloading only).
+ Added Grant authorisation option (send & recognize)
+
+Improvements:
+ Server-side list support rewritten, now uses acking, partly supports groups (without sub-groups for now).
+ Most cookies standardised to imitate icq5 behaviour
+ Basic search now automatically removes garbage from text, e.g. it can search by 123-456-789
+
+
+0.3.3.1
+
+Bugfixes:
+ Could crash when receiving unicode messages.
+
+
+0.3.3
+
+Bugfixes:
+ Failed to send or receive files from ICQ 2003b.
+ Fixed a number of smaller memory leaks.
+ Contact e-mail info was not displayed correctly.
+ Failed to retrieve user details during certain circumstances.
+ URL messages could disappear when sent through a Direct Connection.
+ Nick name was not deleted from server list when local nick name was deleted.
+ Server side contacts could reappear after being deleted if they were on the
+ visible/invisible lists.
+ Changing status while connecting had no effect.
+ A bunch of other fixes that are too boring to list here, have a look at
+ the CVS changelog if you want the big list.
+
+New features:
+ Added support for sending and receiving Typing Notifications.
+ Now accepts messages formatted in unicode (note: this wont solve the problem
+ with displaying messages with multiple charsets).
+
+Improvements:
+ Uses plugin DLL name in various menus to make it easier to have several ICQ
+ plugins loaded.
+ More robust packet parsing reduces the risk of any future stability problems.
+
+
+0.3.2
+
+Bugfixes:
+ Prevent your status messages being read when you are invisible.
+ Small memory leak when sending an SMS.
+ Fixed a dumb bug that caused random disconnections from the ICQ server.
+ Cleaned up the code for searches and user info updates, should work better now.
+ AIM users in your server contact list would get added locally with uin 0.
+
+New features:
+ Added "missed message" notification.
+
+Improvements:
+ Added better error messages for message send failures.
+ Messages now default to the most reliable delivery method available for a given contact.
+
+
+0.3.1
+
+Bugfixes:
+ Fixed crash when incoming file transfer was cancelled before the transfer started
+ Failed to receive SMS messages sent while offline
+ Fixed some problems with accepting file transfers from Mirabilis clients
+ Increased thread safety to reduce some reported connection/disconnection problems
+ Fixed compability problems with sending messages to some jabber clients
+ Fixed some message compability problems with Trillian
+ Corrected some ack sending
+ Added a lot of safety checks to increase general stability
+ Plugin didnt load unless winsocks2 was installed
+
+New features:
+ Removed restrictions on UIN length for better compability with iserverd
+ The password can now be left empty in options, it will be asked for during login
+ Server port can now be left empty in options, a random port will be selected during login
+ Show logged on since and system uptime info in ICQ tab
+
+Improvements:
+ Reduced file size
+ Message sending now uses a more reliable delivery method
+
+
+
+Support and bug reporting
+_________________________
+
+We cannot give support on e-mail or ICQ. Please visit the Miranda IM help page at
+http://www.miranda-im.org/help/ if you need help with this plugin.
+
+If the help page does answer your question, visit the Miranda support forum at:
+http://forums.miranda-im.org/ and we will try to assist you.
+
+If you want to report a bug, please do so in the official bugtracker at:
+http://bugs.miranda-im.org/
+
+
+
+Contact
+_______
+
+Current maintainer is Joe @ Whale, jokusoftware at users.sourceforge.net
+ Martin Öberg, strickz at miranda-im.org
+
+
+
+Advanced Features
+_________________
+
+There are some features that are not widely used so there is no UI for them, if
+you want to use them you need to do manual setup using DBE++.
+
+Database items (usually at Contact\ICQ):
+(BYTE)UnicodeSend = 0 - to Disable unicode support (useful as a workaround for Trillian's bug)
+
+(WORD)CodePage - codepage for plain text encoding/decoding to/from unicode
+
+(WORD)InfoCodePage - codepage for interpreting user details
+
+Database items for Main Contact (usually at Settings\ICQ):
+(BYTE)InfoUpdate - Threshold in DAYS for updating user info (restart is needed) - default is 14 days
+
+(BYTE)PrivacyItems = 1 - adds more privacy tools to contact menu
+
+
+
+Credits and Thanks
+__________________
+
+Thanks to Angeli-Ka for nice custom status icons.
+
+
+
+License and Copyright
+_____________________
+
+Copyright (C) 2000-2006 Joe Kucera, Martin Öberg, Richard Hughes, Jon Keating
+
+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.
\ No newline at end of file diff --git a/icqj_mod/fam_01service.c b/icqj_mod/fam_01service.c new file mode 100644 index 0000000..2356f68 --- /dev/null +++ b/icqj_mod/fam_01service.c @@ -0,0 +1,1017 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_01service.c,v $
+// Revision : $Revision: 3316 $
+// Last change on : $Date: 2006-07-12 20:26:25 +0400 (Ср, 12 июл 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+extern int gbIdleAllow;
+extern int icqGoingOnlineStatus;
+extern BYTE gbOverRate;
+extern int pendingAvatarsStart;
+extern DWORD dwLocalInternalIP;
+extern WORD wListenPort;
+extern DWORD dwLocalDirectConnCookie;
+extern CRITICAL_SECTION modeMsgsMutex;
+
+extern const capstr capXStatus[];
+
+void setUserInfo();
+
+char* calcMD5Hash(char* szFile);
+
+
+void handleServiceFam(unsigned char* pBuffer, WORD wBufferLength, snac_header* pSnacHeader, serverthread_info *info)
+{
+ icq_packet packet;
+
+ switch (pSnacHeader->wSubtype)
+ {
+
+ case ICQ_SERVER_READY:
+#ifdef _DEBUG
+ NetLog_Server("Server is ready and is requesting my Family versions");
+ NetLog_Server("Sending my Families");
+#endif
+
+ // This packet is a response to SRV_FAMILIES SNAC(1,3).
+ // This tells the server which SNAC families and their corresponding
+ // versions which the client understands. This also seems to identify
+ // the client as an ICQ vice AIM client to the server.
+ // Miranda mimics the behaviour of icq5 (haven't changed since at least 2002a)
+ serverPacketInit(&packet, 50);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_FAMILIES);
+ packDWord(&packet, 0x00010004);
+ packDWord(&packet, 0x00130004);
+ packDWord(&packet, 0x00020001);
+ packDWord(&packet, 0x00030001);
+ packDWord(&packet, 0x00150001);
+ packDWord(&packet, 0x00040001);
+ packDWord(&packet, 0x00060001);
+ packDWord(&packet, 0x00090001);
+ packDWord(&packet, 0x000a0001);
+ packDWord(&packet, 0x000b0001);
+ sendServPacket(&packet);
+ break;
+
+ case ICQ_SERVER_FAMILIES2:
+ /* This is a reply to CLI_FAMILIES and it tells the client which families and their versions that this server understands.
+ * We send a rate request packet */
+#ifdef _DEBUG
+ NetLog_Server("Server told me his Family versions");
+ NetLog_Server("Requesting Rate Information");
+#endif
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_REQ_RATE_INFO);
+ sendServPacket(&packet);
+ break;
+
+ case ICQ_SERVER_RATE_INFO:
+#ifdef _DEBUG
+ NetLog_Server("Server sent Rate Info");
+ NetLog_Server("Sending Rate Info Ack");
+#endif
+ /* Don't really care about this now, just send the ack */
+ serverPacketInit(&packet, 20);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_RATE_ACK);
+ packDWord(&packet, 0x00010002);
+ packDWord(&packet, 0x00030004);
+ packWord(&packet, 0x0005);
+ sendServPacket(&packet);
+
+ /* CLI_REQINFO - This command requests from the server certain information about the client that is stored on the server. */
+#ifdef _DEBUG
+ NetLog_Server("Sending CLI_REQINFO");
+#endif
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_REQINFO);
+ sendServPacket(&packet);
+
+ if (gbSsiEnabled)
+ {
+ DWORD dwLastUpdate;
+ WORD wRecordCount;
+ servlistcookie* ack;
+ DWORD dwCookie;
+
+ dwLastUpdate = ICQGetContactSettingDword(NULL, "SrvLastUpdate", 0);
+ wRecordCount = ICQGetContactSettingWord(NULL, "SrvRecordCount", 0);
+
+ // CLI_REQLISTS - we want to use SSI
+#ifdef _DEBUG
+ NetLog_Server("Requesting roster rights");
+#endif
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_CLI_REQLISTS);
+ sendServPacket(&packet);
+
+ if (!wRecordCount) // CLI_REQROSTER
+ { // we do not have any data - request full list
+#ifdef _DEBUG
+ NetLog_Server("Requesting full roster");
+#endif
+ serverPacketInit(&packet, 10);
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (ack)
+ { // we try to use standalone cookie if available
+ ack->dwAction = SSA_CHECK_ROSTER; // loading list
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_CLI_REQUEST, 0, ack);
+ }
+ else // if not use that old fake
+ dwCookie = ICQ_LISTS_CLI_REQUEST<<0x10;
+
+ packFNACHeaderFull(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_CLI_REQUEST, 0, dwCookie);
+ sendServPacket(&packet);
+ }
+ else // CLI_CHECKROSTER
+ {
+#ifdef _DEBUG
+ NetLog_Server("Requesting roster check");
+#endif
+ serverPacketInit(&packet, 16);
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (ack) // TODO: rewrite - use get list service for empty list
+ { // we try to use standalone cookie if available
+ ack->dwAction = SSA_CHECK_ROSTER; // loading list
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_CLI_CHECK, 0, ack);
+ }
+ else // if not use that old fake
+ dwCookie = ICQ_LISTS_CLI_CHECK<<0x10;
+
+ packFNACHeaderFull(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_CLI_CHECK, 0, dwCookie);
+ // check if it was not changed elsewhere (force reload, set that setting to zero)
+ if (IsServerGroupsDefined())
+ {
+ packDWord(&packet, dwLastUpdate); // last saved time
+ packWord(&packet, wRecordCount); // number of records saved
+ }
+ else
+ { // we need to get groups info into DB, force receive list
+ packDWord(&packet, 0); // last saved time
+ packWord(&packet, 0); // number of records saved
+ }
+ sendServPacket(&packet);
+ }
+ }
+
+ // CLI_REQLOCATION
+#ifdef _DEBUG
+ NetLog_Server("Requesting Location rights");
+#endif
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_CLI_REQ_RIGHTS);
+ sendServPacket(&packet);
+
+ // CLI_REQBUDDY
+#ifdef _DEBUG
+ NetLog_Server("Requesting Client-side contactlist rights");
+#endif
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_BUDDY_FAMILY, ICQ_USER_CLI_REQBUDDY);
+ sendServPacket(&packet);
+
+ // CLI_REQICBM
+#ifdef _DEBUG
+ NetLog_Server("Sending CLI_REQICBM");
+#endif
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_MSG_FAMILY, ICQ_MSG_CLI_REQICBM);
+ sendServPacket(&packet);
+
+ // CLI_REQBOS
+#ifdef _DEBUG
+ NetLog_Server("Sending CLI_REQBOS");
+#endif
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_BOS_FAMILY, ICQ_PRIVACY_REQ_RIGHTS);
+ sendServPacket(&packet);
+ break;
+
+ case ICQ_SERVER_PAUSE:
+ NetLog_Server("Server is going down in a few seconds... (Flags: %u)", pSnacHeader->wFlags);
+ // This is the list of groups that we want to have on the next server
+ serverPacketInit(&packet, 30);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_PAUSE_ACK);
+ packWord(&packet,ICQ_SERVICE_FAMILY);
+ packWord(&packet,ICQ_LISTS_FAMILY);
+ packWord(&packet,ICQ_LOCATION_FAMILY);
+ packWord(&packet,ICQ_BUDDY_FAMILY);
+ packWord(&packet,ICQ_EXTENSIONS_FAMILY);
+ packWord(&packet,ICQ_MSG_FAMILY);
+ packWord(&packet,0x06);
+ packWord(&packet,ICQ_BOS_FAMILY);
+ packWord(&packet,ICQ_LOOKUP_FAMILY);
+ packWord(&packet,ICQ_STATS_FAMILY);
+ sendServPacket(&packet);
+#ifdef _DEBUG
+ NetLog_Server("Sent server pause ack");
+#endif
+ break;
+
+ case ICQ_SERVER_MIGRATIONREQ:
+ {
+ oscar_tlv_chain *chain = NULL;
+
+#ifdef _DEBUG
+ NetLog_Server("Server migration requested (Flags: %u)", pSnacHeader->wFlags);
+#endif
+ pBuffer += 2; // Unknown, seen: 0
+ wBufferLength -= 2;
+ chain = readIntoTLVChain(&pBuffer, wBufferLength, 0);
+
+ if (info->cookieDataLen > 0)
+ SAFE_FREE(&info->cookieData);
+
+ info->newServer = getStrFromChain(chain, 0x05, 1);
+ info->cookieData = getStrFromChain(chain, 0x06, 1);
+ info->cookieDataLen = getLenFromChain(chain, 0x06, 1);
+
+ if (!info->newServer || !info->cookieData)
+ {
+ icq_LogMessage(LOG_FATAL, "A server migration has failed because the server returned invalid data. You must reconnect manually.");
+ SAFE_FREE(&info->newServer);
+ SAFE_FREE(&info->cookieData);
+ info->cookieDataLen = 0;
+ info->newServerReady = 0;
+ return;
+ }
+
+ disposeChain(&chain);
+ NetLog_Server("Migration has started. New server will be %s", info->newServer);
+
+ icqGoingOnlineStatus = gnCurrentStatus;
+ SetCurrentStatus(ID_STATUS_CONNECTING); // revert to connecting state
+
+ info->newServerReady = 1;
+ info->isMigrating = 1;
+ }
+ break;
+
+ case ICQ_SERVER_NAME_INFO: // This is the reply to CLI_REQINFO
+ {
+ BYTE bUinLen;
+ oscar_tlv_chain *chain;
+
+ unpackByte(&pBuffer, &bUinLen);
+ pBuffer += bUinLen;
+ pBuffer += 4; /* warning level & user class */
+ wBufferLength -= 5 + bUinLen;
+
+ if (pSnacHeader->dwRef == ICQ_CLIENT_REQINFO<<0x10)
+ { // This is during the login sequence
+ DWORD dwValue;
+
+ // TLV(x01) User type?
+ // TLV(x0C) Empty CLI2CLI Direct connection info
+ // TLV(x0A) External IP
+ // TLV(x0F) Number of seconds that user has been online
+ // TLV(x03) The online since time.
+ // TLV(x0A) External IP again
+ // TLV(x22) Unknown
+ // TLV(x1E) Unknown: empty.
+ // TLV(x05) Member of ICQ since.
+ // TLV(x14) Unknown
+ chain = readIntoTLVChain(&pBuffer, wBufferLength, 0);
+
+ // Save external IP
+ dwValue = getDWordFromChain(chain, 10, 1);
+ ICQWriteContactSettingDword(NULL, "IP", dwValue);
+ ICQWriteContactSettingDword(NULL, "OldIP", dwValue);
+
+ // Save member since timestamp
+ dwValue = getDWordFromChain(chain, 5, 1);
+ if (dwValue) ICQWriteContactSettingDword(NULL, "MemberTS", dwValue);
+
+ ICQWriteContactSettingDword(NULL, "LogonTS", time(NULL));
+
+ disposeChain(&chain);
+
+ // If we are in SSI mode, this is sent after the list is acked instead
+ // to make sure that we don't set status before seing the visibility code
+ if (!gbSsiEnabled || info->isMigrating)
+ handleServUINSettings(wListenPort, info);
+ }
+ }
+ break;
+
+ case ICQ_SERVER_RATE_CHANGE:
+
+ if (wBufferLength >= 2)
+ {
+ WORD wStatus;
+ WORD wClass;
+ // This is a horrible simplification, but the only
+ // area where we have rate control is in the user info
+ // auto request part.
+ unpackWord(&pBuffer, &wStatus);
+ unpackWord(&pBuffer, &wClass);
+
+ if (wStatus == 2 || wStatus == 3)
+ { // this is only the simplest solution, needs rate management to every section
+ ICQBroadcastAck(NULL, ICQACKTYPE_RATEWARNING, ACKRESULT_STATUS, (HANDLE)wClass, wStatus);
+ gbOverRate = 1; // block user requests (user info, status messages, etc.)
+ icq_PauseUserLookup(); // pause auto-info update thread
+ }
+ else if (wStatus == 4)
+ {
+ ICQBroadcastAck(NULL, ICQACKTYPE_RATEWARNING, ACKRESULT_STATUS, (HANDLE)wClass, wStatus);
+ gbOverRate = 0; // enable user requests
+ icq_EnableUserLookup(TRUE);
+ }
+ }
+
+ break;
+
+ case ICQ_SERVER_REDIRECT_SERVICE: // reply to family request, got new connection point
+ {
+ oscar_tlv_chain* pChain = NULL;
+ WORD wFamily;
+ familyrequest_rec* reqdata;
+
+ if (!(pChain = readIntoTLVChain(&pBuffer, wBufferLength, 0)))
+ {
+ NetLog_Server("Received Broken Redirect Service SNAC(1,5).");
+ break;
+ }
+ wFamily = getWordFromChain(pChain, 0x0D, 1);
+
+ // pick request data
+ if ((!FindCookie(pSnacHeader->dwRef, NULL, &reqdata)) || (reqdata->wFamily != wFamily))
+ {
+ disposeChain(&pChain);
+ NetLog_Server("Received unexpected SNAC(1,5), skipping.");
+ break;
+ }
+
+ FreeCookie(pSnacHeader->dwRef);
+
+ { // new family entry point received
+ char* pServer;
+ WORD wPort;
+ char* pCookie;
+ WORD wCookieLen;
+ NETLIBOPENCONNECTION nloc = {0};
+ HANDLE hConnection;
+
+ pServer = getStrFromChain(pChain, 0x05, 1);
+ pCookie = getStrFromChain(pChain, 0x06, 1);
+ wCookieLen = getLenFromChain(pChain, 0x06, 1);
+
+ if (!pServer || !pCookie)
+ {
+ NetLog_Server("Server returned invalid data, family unavailable.");
+
+ SAFE_FREE(&pServer);
+ SAFE_FREE(&pCookie);
+ break;
+ }
+
+ // Get new family server ip and port
+ parseServerAddress(pServer, &wPort);
+
+ nloc.cbSize = sizeof(nloc); // establish connection
+ nloc.flags = 0;
+ nloc.szHost = pServer;
+ nloc.wPort = wPort;
+
+ hConnection = NetLib_OpenConnection(ghServerNetlibUser, &nloc);
+
+ if (hConnection == NULL)
+ {
+ NetLog_Server("Unable to connect to ICQ new family server.");
+ } // we want the handler to be called even if the connecting failed
+ reqdata->familyhandler(hConnection, pCookie, wCookieLen);
+
+ // Free allocated memory
+ // NOTE: "cookie" will get freed when we have connected to the avatar server.
+ disposeChain(&pChain);
+ SAFE_FREE(&pServer);
+ SAFE_FREE(&reqdata);
+ }
+
+ break;
+ }
+
+ case ICQ_SERVER_EXTSTATUS: // our avatar
+ {
+ NetLog_Server("Received our avatar hash & status.");
+
+ if ((wBufferLength >= 0x14) && gbAvatarsEnabled)
+ {
+ switch (pBuffer[2])
+ {
+ case 1: // our avatar is on the server
+ {
+ char* file;
+ char* hash;
+
+ ICQWriteContactSettingBlob(NULL, "AvatarHash", pBuffer, 0x14);
+
+ setUserInfo();
+ // here we need to find a file, check its hash, if invalid get avatar from server
+ file = loadMyAvatarFileName();
+ if (!file)
+ { // we have no avatar file, download from server
+ char szFile[MAX_PATH + 4];
+#ifdef _DEBUG
+ NetLog_Server("We have no avatar, requesting from server.");
+#endif
+ GetAvatarFileName(0, NULL, szFile, MAX_PATH);
+ GetAvatarData(NULL, dwLocalUIN, NULL, pBuffer, 0x14, szFile);
+ }
+ else
+ { // we know avatar filename
+ hash = calcMD5Hash(file);
+ if (!hash)
+ { // hash could not be calculated - probably missing file, get avatar from server
+ char szFile[MAX_PATH + 4];
+#ifdef _DEBUG
+ NetLog_Server("We have no avatar, requesting from server.");
+#endif
+ GetAvatarFileName(0, NULL, szFile, MAX_PATH);
+ GetAvatarData(NULL, dwLocalUIN, NULL, pBuffer, 0x14, szFile);
+ } // check if we had set any avatar if yes set our, if not download from server
+ else if (memcmp(hash, pBuffer+4, 0x10))
+ { // we have different avatar, sync that
+ if (ICQGetContactSettingByte(NULL, "ForceOurAvatar", 1))
+ { // we want our avatar, update hash
+ DWORD dwPaFormat = DetectAvatarFormat(file);
+ char* pHash = _alloca(0x14);
+
+ NetLog_Server("Our avatar is different, set our new hash.");
+
+ pHash[0] = 0;
+ pHash[1] = dwPaFormat == PA_FORMAT_XML ? 8 : 1;
+ pHash[2] = 1; // state of the hash
+ pHash[3] = 0x10; // len of the hash
+ memcpy(pHash + 4, hash, 0x10);
+ updateServAvatarHash(pHash, 0x14);
+ }
+ else
+ { // get avatar from server
+ char szFile[MAX_PATH + 4];
+#ifdef _DEBUG
+ NetLog_Server("We have different avatar, requesting new from server.");
+#endif
+ GetAvatarFileName(0, NULL, szFile, MAX_PATH);
+ GetAvatarData(NULL, dwLocalUIN, NULL, pBuffer, 0x14, szFile);
+ }
+ }
+ SAFE_FREE(&hash);
+ SAFE_FREE(&file);
+ }
+ break;
+ }
+ case 0x41: // request to upload avatar data
+ case 0x81:
+ { // request to re-upload avatar data
+ char* file;
+ char* hash;
+ DWORD dwPaFormat;
+
+ if (!gbSsiEnabled) break; // we could not change serv-list if it is disabled...
+
+ file = loadMyAvatarFileName();
+ if (!file)
+ { // we have no file to upload, remove hash from server
+ NetLog_Server("We do not have avatar, removing hash.");
+ IcqSetMyAvatar(0, 0);
+ LinkContactPhotoToFile(NULL, NULL);
+ break;
+ }
+ dwPaFormat = DetectAvatarFormat(file);
+ hash = calcMD5Hash(file);
+ if (!hash)
+ { // the hash could not be calculated, remove from server
+ NetLog_Server("We could not obtain hash, removing hash.");
+ IcqSetMyAvatar(0, 0);
+ LinkContactPhotoToFile(NULL, NULL);
+ }
+ else if (!memcmp(hash, pBuffer+4, 0x10))
+ { // we have the right file
+ HANDLE hFile = NULL, hMap = NULL;
+ BYTE* ppMap = NULL;
+ long cbFileSize = 0;
+
+ NetLog_Server("Uploading our avatar data.");
+
+ if ((hFile = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL )) != INVALID_HANDLE_VALUE)
+ if ((hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL)
+ if ((ppMap = (BYTE*)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
+ cbFileSize = GetFileSize( hFile, NULL );
+
+ if (cbFileSize != 0)
+ {
+ SetAvatarData(NULL, (WORD)(dwPaFormat == PA_FORMAT_XML ? 8 : 1), ppMap, cbFileSize);
+ LinkContactPhotoToFile(NULL, file);
+ }
+
+ if (ppMap != NULL) UnmapViewOfFile(ppMap);
+ if (hMap != NULL) CloseHandle(hMap);
+ if (hFile != NULL) CloseHandle(hFile);
+ SAFE_FREE(&hash);
+ }
+ else
+ {
+ char* pHash = _alloca(0x14);
+
+ NetLog_Server("Our file is different, set our new hash.");
+
+ pHash[0] = 0;
+ pHash[1] = dwPaFormat == PA_FORMAT_XML ? 8 : 1;
+ pHash[2] = 1; // state of the hash
+ pHash[3] = 0x10; // len of the hash
+ memcpy(pHash + 4, hash, 0x10);
+ updateServAvatarHash(pHash, 0x14);
+
+ SAFE_FREE(&hash);
+ }
+
+ SAFE_FREE(&file);
+ break;
+ default:
+ NetLog_Server("Reiceived UNKNOWN Avatar Status.");
+ }
+ }
+ }
+ break;
+ }
+
+ case ICQ_ERROR:
+ { // Something went wrong, probably the request for avatar family failed
+ WORD wError;
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ LogFamilyError(ICQ_SERVICE_FAMILY, wError);
+ break;
+ }
+
+ // Stuff we don't care about
+ case ICQ_SERVER_MOTD:
+#ifdef _DEBUG
+ NetLog_Server("Server message of the day");
+#endif
+ break;
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_SERVICE_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+
+ }
+}
+
+
+
+char* calcMD5Hash(char* szFile)
+{
+ md5_state_t state;
+ md5_byte_t digest[16];
+
+ if (szFile)
+ {
+ HANDLE hFile = NULL, hMap = NULL;
+ BYTE* ppMap = NULL;
+ long cbFileSize = 0;
+ char* res;
+
+ if ((hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL )) != INVALID_HANDLE_VALUE)
+ if ((hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL)
+ if ((ppMap = (BYTE*)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
+ cbFileSize = GetFileSize( hFile, NULL );
+
+ res = (char*)SAFE_MALLOC(16*sizeof(char));
+ if (cbFileSize != 0 && res)
+ {
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)ppMap, cbFileSize);
+ md5_finish(&state, digest);
+ memcpy(res, digest, 16);
+ }
+
+ if (ppMap != NULL) UnmapViewOfFile(ppMap);
+ if (hMap != NULL) CloseHandle(hMap);
+ if (hFile != NULL) CloseHandle(hFile);
+
+ if (res) return res;
+ }
+
+ return NULL;
+}
+
+
+
+static char* buildUinList(int subtype, WORD wMaxLen, HANDLE* hContactResume)
+{
+ char* szList;
+ HANDLE hContact;
+ WORD wCurrentLen = 0;
+ DWORD dwUIN;
+ uid_str szUID;
+ char szLen[2];
+ int add;
+
+
+ szList = (char*)SAFE_MALLOC(CallService(MS_DB_CONTACT_GETCOUNT, 0, 0) * UINMAXLEN);
+ szLen[1] = '\0';
+
+ if (*hContactResume)
+ hContact = *hContactResume;
+ else
+ hContact = ICQFindFirstContact();
+
+ while (hContact != NULL)
+ {
+ if (!ICQGetContactSettingUID(hContact, &dwUIN, &szUID))
+ {
+ szLen[0] = strlennull(strUID(dwUIN, szUID));
+
+ switch (subtype)
+ {
+
+ case BUL_VISIBLE:
+ add = ID_STATUS_ONLINE == ICQGetContactSettingWord(hContact, "ApparentMode", 0);
+ break;
+
+ case BUL_INVISIBLE:
+ add = ID_STATUS_OFFLINE == ICQGetContactSettingWord(hContact, "ApparentMode", 0);
+ break;
+
+ case BUL_TEMPVISIBLE:
+ add = ICQGetContactSettingByte(hContact, "TemporaryVisible", 0);
+ // clear temporary flag
+ // Here we assume that all temporary contacts will be in one packet
+ ICQDeleteContactSetting(hContact, "TemporaryVisible");
+ break;
+
+ default:
+ add = 1;
+
+ // If we are in SS mode, we only add those contacts that are
+ // not in our SS list, or are awaiting authorization, to our
+ // client side list
+ if (gbSsiEnabled && ICQGetContactSettingWord(hContact, "ServerId", 0) &&
+ !ICQGetContactSettingByte(hContact, "Auth", 0))
+ add = 0;
+
+ // Never add hidden contacts to CS list
+ if (DBGetContactSettingByte(hContact, "CList", "Hidden", 0))
+ add = 0;
+
+ break;
+ }
+
+ if (add)
+ {
+ wCurrentLen += szLen[0] + 1;
+ if (wCurrentLen > wMaxLen)
+ {
+ *hContactResume = hContact;
+ return szList;
+ }
+
+ strcat(szList, szLen);
+ strcat(szList, szUID);
+ }
+ }
+
+ hContact = ICQFindNextContact(hContact);
+ }
+ *hContactResume = NULL;
+
+
+ return szList;
+}
+
+
+
+void sendEntireListServ(WORD wFamily, WORD wSubtype, int listType)
+{
+ HANDLE hResumeContact;
+ char* szList;
+ int nListLen;
+ icq_packet packet;
+
+
+ hResumeContact = NULL;
+
+ do
+ { // server doesn't seem to be able to cope with packets larger than 8k
+ // send only about 100contacts per packet
+ szList = buildUinList(listType, 0x3E8, &hResumeContact);
+ nListLen = strlennull(szList);
+
+ if (nListLen)
+ {
+ serverPacketInit(&packet, (WORD)(nListLen + 10));
+ packFNACHeader(&packet, wFamily, wSubtype);
+ packBuffer(&packet, szList, (WORD)nListLen);
+ sendServPacket(&packet);
+ }
+
+ SAFE_FREE(&szList);
+ }
+ while (hResumeContact);
+}
+
+
+
+static void packNewCap(icq_packet* packet, WORD wNewCap)
+{ // pack standard capability
+ DWORD dwQ1 = 0x09460000 | wNewCap;
+
+ packDWord(packet, dwQ1);
+ packDWord(packet, 0x4c7f11d1);
+ packDWord(packet, 0x82224445);
+ packDWord(packet, 0x53540000);
+}
+
+
+
+void setUserInfo()
+{ // CLI_SETUSERINFO
+ icq_packet packet;
+ WORD wAdditionalData = 0;
+ BYTE bXStatus = gbXStatusEnabled?ICQGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0):0;
+
+ if (gbAimEnabled)
+ wAdditionalData += 16;
+#ifdef DBG_CAPMTN
+ wAdditionalData += 16;
+#endif
+#ifdef DBG_CAPCH2
+ wAdditionalData += 16;
+#endif
+#ifdef DBG_CAPRTF
+ wAdditionalData += 16;
+#endif
+ if (gbUtfEnabled)
+ wAdditionalData += 16;
+#ifdef DBG_NEWCAPS
+ wAdditionalData += 16;
+#endif
+#ifdef DBG_CAPXTRAZ
+ wAdditionalData += 16;
+#endif
+#ifdef DBG_XTRAZ_MUC
+ wAdditionalData += 16;
+#endif
+ if (bXStatus)
+ wAdditionalData += 16;
+ if (gbAvatarsEnabled)
+ wAdditionalData += 16;
+
+ serverPacketInit(&packet, (WORD)(46 + wAdditionalData));
+ packFNACHeader(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_SET_USER_INFO);
+
+ /* TLV(5): capability data */
+ packWord(&packet, 0x0005);
+ packWord(&packet, (WORD)(32 + wAdditionalData));
+
+
+#ifdef DBG_CAPMTN
+ {
+ packDWord(&packet, 0x563FC809); // CAP_TYPING
+ packDWord(&packet, 0x0B6F41BD);
+ packDWord(&packet, 0x9F794226);
+ packDWord(&packet, 0x09DFA2F3);
+ }
+#endif
+#ifdef DBG_CAPCH2
+ {
+ packNewCap(&packet, 0x1349); // AIM_CAPS_ICQSERVERRELAY
+ }
+#endif
+#ifdef DBG_CAPRTF
+ {
+ packDWord(&packet, 0x97B12751); // AIM_CAPS_ICQRTF
+ packDWord(&packet, 0x243C4334); // Broadcasts the capability to receive
+ packDWord(&packet, 0xAD22D6AB); // RTF messages
+ packDWord(&packet, 0xF73F1492);
+ }
+#endif
+ if (gbUtfEnabled)
+ {
+ packNewCap(&packet, 0x134E); // CAP_UTF8MSGS
+ } // Broadcasts the capability to receive UTF8 encoded messages
+#ifdef DBG_NEWCAPS
+ {
+ packNewCap(&packet, 0x0000); // CAP_NEWCAPS
+ } // Tells server we understand to new format of caps
+#endif
+#ifdef DBG_CAPXTRAZ
+ {
+ packDWord(&packet, 0x1a093c6c); // CAP_XTRAZ
+ packDWord(&packet, 0xd7fd4ec5); // Broadcasts the capability to handle
+ packDWord(&packet, 0x9d51a647); // Xtraz
+ packDWord(&packet, 0x4e34f5a0);
+ }
+#endif
+#ifdef DBG_CAPXTRAZ_MUC
+ {
+ packNewCap(&packet, 0x134C); // CAP_XTRAZ_MUC
+ } // Broadcasts the capability handle Xtraz multi-user chat
+#endif
+ if (gbAimEnabled)
+ {
+ packNewCap(&packet, 0x134D); // Tells the server we can speak to AIM
+ }
+ if (bXStatus)
+ {
+ packBuffer(&packet, capXStatus[bXStatus-1], 0x10);
+ }
+ if (gbAvatarsEnabled)
+ {
+ BYTE Cap[16] = {CAP_ICQ_DEVIL};
+ packBuffer(&packet, Cap, 0x10); // ICQ Devils
+ }
+
+ packNewCap(&packet, 0x1344); // AIM_CAPS_ICQ
+
+ packDWord(&packet, 0x4D697261); // Miranda Signature
+ packDWord(&packet, 0x6E64614D);
+ packDWord(&packet, MIRANDA_VERSION);
+ packDWord(&packet, ICQ_PLUG_VERSION);
+
+ sendServPacket(&packet);
+}
+
+
+
+void handleServUINSettings(int nPort, serverthread_info *info)
+{
+ icq_packet packet;
+
+ setUserInfo();
+
+ /* SNAC 3,4: Tell server who's on our list */
+ sendEntireListServ(ICQ_BUDDY_FAMILY, ICQ_USER_ADDTOLIST, BUL_ALLCONTACTS);
+
+ if (icqGoingOnlineStatus == ID_STATUS_INVISIBLE)
+ {
+ /* Tell server who's on our visible list */
+ if (!gbSsiEnabled)
+ sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_ADDVISIBLE, BUL_VISIBLE);
+ else
+ updateServVisibilityCode(3);
+ }
+
+ if (icqGoingOnlineStatus != ID_STATUS_INVISIBLE)
+ {
+ /* Tell server who's on our invisible list */
+ if (!gbSsiEnabled)
+ sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_ADDINVISIBLE, BUL_INVISIBLE);
+ else
+ updateServVisibilityCode(4);
+ }
+
+
+ // SNAC 1,1E: Set status
+ {
+ WORD wStatus;
+
+ // Get status
+ wStatus = MirandaStatusToIcq(icqGoingOnlineStatus);
+ //icq_setstatus_ex(wStatus, ICQGetContactSettingDword(NULL, "RealIP", 0), nPort);
+
+
+ serverPacketInit(&packet, 71);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_STATUS);
+ packDWord(&packet, 0x00060004); // TLV 6: Status mode and security flags
+ packWord(&packet, GetMyStatusFlags()); // Status flags
+ packWord(&packet, wStatus); // Status
+ packTLVWord(&packet, 0x0008, 0x0000); // TLV 8: Error code
+ packDWord(&packet, 0x000c0025); // TLV C: Direct connection info
+ packDWord(&packet, ICQGetContactSettingDword(NULL, "RealIP", 0));
+ packDWord(&packet, nPort);
+ packByte(&packet, DC_TYPE); // TCP/FLAG firewall settings
+ packWord(&packet, ICQ_VERSION);
+ packDWord(&packet, dwLocalDirectConnCookie);// DC Cookie
+ packDWord(&packet, WEBFRONTPORT); // Web front port
+ packDWord(&packet, CLIENTFEATURES); // Client features
+ packDWord(&packet, gdwFP1); // Abused timestamp
+ packDWord(&packet, gdwFP2); // Abused timestamp
+ packDWord(&packet, gdwFP3); // Timestamp
+ packWord(&packet, 0x0000); // Unknown
+ packTLVWord(&packet, 0x001F, 0x0000);
+
+ sendServPacket(&packet);
+ }
+
+ /* SNAC 1,11 */
+ serverPacketInit(&packet, 14);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_IDLE);
+ packDWord(&packet, 0x00000000);
+
+ sendServPacket(&packet);
+ gbIdleAllow = 0;
+
+ // Change status
+ SetCurrentStatus(icqGoingOnlineStatus);
+
+ // Finish Login sequence
+ serverPacketInit(&packet, 90);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_READY);
+ packDWord(&packet, 0x00010004); // imitate icq5 behaviour
+ packDWord(&packet, 0x011008E4);
+ packDWord(&packet, 0x00130004);
+ packDWord(&packet, 0x011008E4);
+ packDWord(&packet, 0x00020001);
+ packDWord(&packet, 0x011008E4);
+ packDWord(&packet, 0x00030001);
+ packDWord(&packet, 0x011008E4);
+ packDWord(&packet, 0x00150001);
+ packDWord(&packet, 0x011008E4);
+ packDWord(&packet, 0x00040001);
+ packDWord(&packet, 0x011008E4);
+ packDWord(&packet, 0x00060001);
+ packDWord(&packet, 0x011008E4);
+ packDWord(&packet, 0x00090001);
+ packDWord(&packet, 0x011008E4);
+ packDWord(&packet, 0x000A0001);
+ packDWord(&packet, 0x011008E4);
+ packDWord(&packet, 0x000B0001);
+ packDWord(&packet, 0x011008E4);
+
+ sendServPacket(&packet);
+
+ NetLog_Server(" *** Yeehah, login sequence complete");
+
+ // login sequence is complete enter logged-in mode
+ info->bLoggedIn = 1;
+
+ if (!info->isMigrating)
+ { /* Get Offline Messages Reqeust */
+ serverPacketInit(&packet, 24);
+ packFNACHeaderFull(&packet, ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQ, 0, 0x00020001);
+ packDWord(&packet, 0x0001000a); /* TLV */
+ packLEWord(&packet, 8); /* bytes remaining */
+ packLEDWord(&packet, dwLocalUIN);
+ packDWord(&packet, 0x3c000200); /* get offline msgs */
+
+ sendServPacket(&packet);
+
+ // Update our information from the server
+ sendOwnerInfoRequest();
+
+ // Request info updates on all contacts
+ icq_RescanInfoUpdate();
+
+ // Start sending Keep-Alive packets
+ StartKeepAlive();
+
+ if (gbAvatarsEnabled)
+ { // Send SNAC 1,4 - request avatar family 0x10 connection
+ icq_requestnewfamily(ICQ_AVATAR_FAMILY, StartAvatarThread);
+
+ pendingAvatarsStart = 1;
+ NetLog_Server("Requesting Avatar family entry point.");
+ }
+ }
+ info->isMigrating = 0;
+
+ if (gbAimEnabled)
+ {
+ char** szMsg = MirandaStatusToAwayMsg(gnCurrentStatus);
+
+ EnterCriticalSection(&modeMsgsMutex);
+ if (szMsg)
+ icq_sendSetAimAwayMsgServ(*szMsg);
+ LeaveCriticalSection(&modeMsgsMutex);
+ }
+}
diff --git a/icqj_mod/fam_02location.c b/icqj_mod/fam_02location.c new file mode 100644 index 0000000..066f9ea --- /dev/null +++ b/icqj_mod/fam_02location.c @@ -0,0 +1,478 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_02location.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static void handleLocationAwayReply(BYTE* buf, WORD wLen, DWORD dwCookie);
+
+
+void handleLocationFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+
+ case ICQ_LOCATION_RIGHTS_REPLY: // Reply to CLI_REQLOCATION
+ NetLog_Server("Server sent SNAC(x02,x03) - SRV_LOCATION_RIGHTS_REPLY");
+ break;
+
+ case ICQ_LOCATION_USR_INFO_REPLY: // AIM user info reply
+ handleLocationAwayReply(pBuffer, wBufferLength, pSnacHeader->dwRef);
+ break;
+
+ case ICQ_ERROR:
+ {
+ WORD wError;
+ DWORD dwCookieUin;
+ fam15_cookie_data *pCookieData;
+
+
+ if (wBufferLength >= 2) {
+ unpackWord(&pBuffer, &wError);
+
+ LogFamilyError(ICQ_LOCATION_FAMILY, wError);
+ if (pSnacHeader->dwRef >= 2 && pSnacHeader->dwRef <= 0xFFFF)
+ icq_SetUserStatus(0, (WORD)(pSnacHeader->dwRef), -5);
+ }
+ else
+ wError = 0;
+
+ if (wError == 4)
+ {
+ if (FindCookie(pSnacHeader->dwRef, &dwCookieUin, &pCookieData) && !dwCookieUin && pCookieData->bRequestType == REQUESTTYPE_PROFILE)
+ {
+ ICQBroadcastAck(pCookieData->hContact, ACKTYPE_GETINFO, ACKRESULT_FAILED, (HANDLE)1 ,0);
+
+ ReleaseCookie(pSnacHeader->dwRef);
+ }
+ }
+
+ LogFamilyError(ICQ_LOCATION_FAMILY, wError);
+ break;
+ }
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_LOCATION_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+ }
+}
+
+static void handleLocationUserOnlineInfo(HANDLE hContact, BYTE *buf, WORD wLen, DWORD dwCookie)
+{
+
+ oscar_tlv_chain *pChain;
+ oscar_tlv* pTLV;
+
+ DWORD dwPort;
+ DWORD dwRealIP;
+ DWORD dwIP;
+ DWORD dwDirectConnCookie;
+ WORD wVersion;
+ WORD wStatusFlags;
+ WORD wStatus;
+ BYTE nTCPFlag;
+ DWORD dwOnlineSince = 0;
+ WORD wIdleTimer = 0;
+ DWORD dwFP1 = 0;
+ DWORD dwFP2 = 0;
+ DWORD dwFP3 = 0;
+ DWORD dwBuild = 0;
+ WORD wOldStatus, wNewStatus;
+ BOOL Hidden = 0;
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Server sent SNAC(x02,x06) - SRV_USER_ONLINE_INFO");
+#endif
+
+ // Get chain
+ if (!(pChain = readIntoTLVChain(&buf, wLen, 0)))
+ return;
+
+ // Get DC info TLV
+ pTLV = getTLV(pChain, 0x0C, 1);
+ if (pTLV && (pTLV->wLen >= 15))
+ {
+ unsigned char* pBuffer;
+
+ pBuffer = pTLV->pData;
+ unpackDWord(&pBuffer, &dwRealIP);
+ unpackDWord(&pBuffer, &dwPort);
+ unpackByte(&pBuffer, &nTCPFlag);
+ unpackWord(&pBuffer, &wVersion);
+ unpackDWord(&pBuffer, &dwDirectConnCookie);
+ pBuffer += 4; // Web front port
+ pBuffer += 4; // Client features
+
+ unpackDWord(&pBuffer, &dwFP1);
+ unpackDWord(&pBuffer, &dwFP2);
+ unpackDWord(&pBuffer, &dwFP3);
+ }
+ else
+ {
+ // This client doesnt want DCs
+ dwRealIP = 0;
+ dwPort = 0;
+ nTCPFlag = 0;
+ wVersion = 0;
+ dwDirectConnCookie = 0;
+ }
+
+ // Get Status info TLV
+ pTLV = getTLV(pChain, 0x06, 1);
+ if (pTLV && (pTLV->wLen >= 4))
+ {
+ unsigned char* pBuffer;
+
+ pBuffer = pTLV->pData;
+ unpackWord(&pBuffer, &wStatusFlags);
+ unpackWord(&pBuffer, &wStatus);
+ }
+ else
+ {
+ // Huh? No status TLV? Lets guess then...
+ wStatusFlags = 0;
+ wStatus = ICQ_STATUS_ONLINE;
+ }
+
+
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Flags are %x", wStatusFlags);
+ Netlib_Logf(ghServerNetlibUser, "Status is %x", wStatus);
+#endif
+
+ // Get IP TLV
+ dwIP = getDWordFromChain(pChain, 0x0a, 1);
+
+ // Get Online Since TLV
+ {
+ int len;
+ int i = 1;
+
+ while(len = getLenFromChain(pChain, 0x03, i))
+ {
+ if (len == 4)
+ {
+ dwOnlineSince = getDWordFromChain(pChain, 0x03, i);
+ break;
+ }
+ else
+ i++;
+ }
+ }
+
+ // Get Idle timer TLV
+ wIdleTimer = getWordFromChain(pChain, 0x04, 1);
+
+#ifdef _DEBUG
+ if (wIdleTimer)
+ Netlib_Logf(ghServerNetlibUser, "Idle timer is %u.", wIdleTimer);
+// Netlib_Logf(ghServerNetlibUser, "Online since %s", asctime(localtime(&dwOnlineSince)));
+#endif
+
+ wOldStatus = DBGetContactSettingWord(hContact, gpszICQProtoName, "Status", ID_STATUS_OFFLINE);
+ wNewStatus = IcqStatusToMiranda(wStatus);
+
+ if (wOldStatus != ID_STATUS_OFFLINE && CheckContactCapabilities(hContact, WAS_FOUND))
+ Hidden = 1;
+
+ if (dwIP)
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "IP", dwIP);
+ if (dwRealIP)
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "RealIP", dwRealIP);
+ if (dwPort)
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "UserPort", (WORD)(dwPort & 0xffff));
+
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "LogonTS", dwOnlineSince);
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "DirectCookie", dwDirectConnCookie);
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "Version", wVersion);
+
+ if (!wIdleTimer)
+ {
+ DWORD dw = DBGetContactSettingDword(hContact, gpszICQProtoName, "IdleTS", 0);
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "OldIdleTS", dw);
+ }
+
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "IdleTS", (wIdleTimer)?((DWORD)time(NULL) - wIdleTimer * 60):0);
+
+ // Free TLV chain
+ disposeChain(&pChain);
+
+ // make some checks
+ if (dwCookie >= 2 && dwCookie <= 0xFFFF)
+ icq_SetUserStatus(0, (WORD)dwCookie, 5);
+
+ // hack: restore hidden stuff here
+ if (Hidden)
+ {
+ ClearContactCapabilities(hContact, CAPF_SRV_RELAY); // for compability
+ SetContactCapabilities(hContact, WAS_FOUND);
+ // dim icon
+ if (!DBGetContactSettingDword(hContact, gpszICQProtoName, "IdleTS", 0))
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "IdleTS", (DWORD)time(NULL));
+ }
+
+ // write new status after all other info
+ if (wOldStatus != wNewStatus)
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "Status", wNewStatus);
+}
+
+static char* AimApplyEncoding(char* pszStr, const char* pszEncoding)
+{ // decode encoding to ANSI only
+ if (pszStr && pszEncoding)
+ {
+ char *szEnc = strstr(pszEncoding, "charset=");
+
+ if (szEnc)
+ {
+ szEnc = szEnc + 9; // get charset string
+
+ if (!strnicmp(szEnc, "utf-8", 5))
+ { // it is utf-8 encoded
+ char *szRes = NULL;
+
+ utf8_decode(pszStr, &szRes);
+ SAFE_FREE(&pszStr);
+
+ return szRes;
+ }
+ if (!strnicmp(szEnc, "unicode-2-0", 11))
+ { // it is UCS-2 encoded
+ int wLen = wcslen((wchar_t*)pszStr) + 1;
+ wchar_t *szStr = (wchar_t*)_alloca(wLen*2);
+ char *szRes = (char*)SAFE_MALLOC(wLen);
+ char *tmp = pszStr;
+
+ unpackWideString(&tmp, szStr, (WORD)(wLen*2));
+ WideCharToMultiByte(CP_ACP, 0, szStr, -1, szRes, wLen, NULL, NULL);
+ SAFE_FREE(&pszStr);
+
+ return szRes;
+ }
+ }
+ }
+ return pszStr;
+}
+
+
+
+void handleLocationAwayReply(BYTE* buf, WORD wLen, DWORD dwCookie)
+{
+ HANDLE hContact;
+ DWORD dwUIN;
+ uid_str szUID;
+ WORD wTLVCount;
+ WORD wWarningLevel;
+ DWORD dwCookieUin;
+ WORD status;
+ message_cookie_data *pCookieData;
+
+ // Unpack the sender's user ID
+ if (!unpackUID(&buf, &wLen, &dwUIN, &szUID)) return;
+
+ // Syntax check
+ if (wLen < 4)
+ return;
+
+ // Warning level?
+ unpackWord(&buf, &wWarningLevel);
+ wLen -= 2;
+
+ // TLV count
+ unpackWord(&buf, &wTLVCount);
+ wLen -= 2;
+
+ // Determine contact
+ hContact = HContactFromUID(dwUIN, szUID, NULL);
+
+ // Ignore away status if the user is not already on our list
+ if (hContact == INVALID_HANDLE_VALUE)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Ignoring away reply (%s)", strUID(dwUIN, szUID));
+#endif
+ return;
+ }
+
+ if (!FindCookie(dwCookie, &dwCookieUin, &pCookieData))
+ {
+ NetLog_Server("Error: Received unexpected away reply from %s", strUID(dwUIN, szUID));
+ //handleLocationUserOnlineInfo(hContact, buf, wLen, dwCookie);
+ return;
+ }
+
+ if (dwUIN != dwCookieUin)
+ {
+ NetLog_Server("Error: Away reply UIN does not match Cookie UIN(%u != %u)", dwUIN, dwCookieUin);
+
+ ReleaseCookie(dwCookie); // This could be a bad idea, but I think it is safe
+ return;
+ }
+
+ if (GetCookieType(dwCookie) == CKT_FAMILYSPECIAL)
+ {
+ ReleaseCookie(dwCookie);
+
+ // Read user info TLVs
+ {
+ oscar_tlv_chain* pChain;
+ oscar_tlv* pTLV;
+ BYTE *tmp;
+ char *szMsg = NULL;
+
+ // Syntax check
+ if (wLen < 4)
+ return;
+
+ tmp = buf;
+ // Get general chain
+ if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
+ return;
+
+ disposeChain(&pChain);
+
+ wLen -= (buf - tmp);
+
+ // Get extra chain
+ if (pChain = readIntoTLVChain(&buf, wLen, 2))
+ {
+ char* szEncoding = NULL;
+
+ // Get Profile encoding TLV
+ pTLV = getTLV(pChain, 0x01, 1);
+ if (pTLV && (pTLV->wLen >= 1))
+ {
+ szEncoding = (char*)_alloca(pTLV->wLen + 1);
+ memcpy(szEncoding, pTLV->pData, pTLV->wLen);
+ szEncoding[pTLV->wLen] = '\0';
+ }
+ // Get Profile info TLV
+ pTLV = getTLV(pChain, 0x02, 1);
+ if (pTLV && (pTLV->wLen >= 1))
+ {
+ szMsg = (char*)SAFE_MALLOC(pTLV->wLen + 2);
+ memcpy(szMsg, pTLV->pData, pTLV->wLen);
+ szMsg[pTLV->wLen] = '\0';
+ szMsg[pTLV->wLen + 1] = '\0';
+ szMsg = AimApplyEncoding(szMsg, szEncoding);
+ szMsg = EliminateHtml(szMsg, pTLV->wLen);
+ }
+ // Free TLV chain
+ disposeChain(&pChain);
+ }
+
+ ICQWriteContactSettingString(hContact, "About", szMsg);
+ ICQBroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1 ,0);
+
+ SAFE_FREE(&szMsg);
+ }
+ }
+ else
+ {
+ status = AwayMsgTypeToStatus(pCookieData->nAckType);
+ if (status == ID_STATUS_OFFLINE)
+ {
+ NetLog_Server("SNAC(2.6) Ignoring unknown status message from %s", strUID(dwUIN, szUID));
+
+ ReleaseCookie(dwCookie);
+ return;
+ }
+
+ ReleaseCookie(dwCookie);
+
+ // Read user info TLVs
+ {
+ oscar_tlv_chain* pChain;
+ oscar_tlv* pTLV;
+ BYTE *tmp;
+ char *szMsg = NULL;
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+
+ // Syntax check
+ if (wLen < 4)
+ return;
+
+ tmp = buf;
+ // Get general chain
+ if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
+ return;
+
+ disposeChain(&pChain);
+
+ wLen -= (buf - tmp);
+
+ // Get extra chain
+ if (pChain = readIntoTLVChain(&buf, wLen, 2))
+ {
+ char* szEncoding = NULL;
+
+ // Get Away encoding TLV
+ pTLV = getTLV(pChain, 0x03, 1);
+ if (pTLV && (pTLV->wLen >= 1))
+ {
+ szEncoding = (char*)_alloca(pTLV->wLen + 1);
+ memcpy(szEncoding, pTLV->pData, pTLV->wLen);
+ szEncoding[pTLV->wLen] = '\0';
+ }
+ // Get Away info TLV
+ pTLV = getTLV(pChain, 0x04, 1);
+ if (pTLV && (pTLV->wLen >= 1))
+ {
+ szMsg = (char*)SAFE_MALLOC(pTLV->wLen + 2);
+ memcpy(szMsg, pTLV->pData, pTLV->wLen);
+ szMsg[pTLV->wLen] = '\0';
+ szMsg[pTLV->wLen + 1] = '\0';
+ szMsg = AimApplyEncoding(szMsg, szEncoding);
+ szMsg = EliminateHtml(szMsg, pTLV->wLen);
+ }
+ // Free TLV chain
+ disposeChain(&pChain);
+ }
+
+ ccs.szProtoService = PSR_AWAYMSG;
+ ccs.hContact = hContact;
+ ccs.wParam = status;
+ ccs.lParam = (LPARAM)⪯
+ pre.flags = 0;
+ pre.szMessage = szMsg?szMsg:"";
+ pre.timestamp = time(NULL);
+ pre.lParam = dwCookie;
+
+ CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
+
+ SAFE_FREE(&szMsg);
+ }
+ }
+}
diff --git a/icqj_mod/fam_03buddy.c b/icqj_mod/fam_03buddy.c new file mode 100644 index 0000000..a81929f --- /dev/null +++ b/icqj_mod/fam_03buddy.c @@ -0,0 +1,505 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_03buddy.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Handles packets from Buddy family
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+static void handleUserOffline(BYTE* buf, WORD wPackLen);
+static void handleUserOnline(BYTE* buf, WORD wPackLen);
+static void handleReplyBuddy(BYTE* buf, WORD wPackLen);
+static void handleNotifyRejected(BYTE* buf, WORD wPackLen);
+
+extern DWORD dwLocalDirectConnCookie;
+
+extern const capstr capAimIcon;
+extern const char* cliSpamBot;
+extern char* detectUserClient(HANDLE hContact, DWORD dwUin, WORD wVersion, DWORD dwFT1, DWORD dwFT2, DWORD dwFT3, DWORD dwOnlineSince, DWORD dwDirectCookie, DWORD dwWebPort, BYTE* caps, WORD wLen, BYTE* bClientId, char* szClientBuf);
+
+
+void handleBuddyFam(unsigned char* pBuffer, WORD wBufferLength, snac_header* pSnacHeader)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+ case ICQ_USER_ONLINE:
+ handleUserOnline(pBuffer, wBufferLength);
+ break;
+
+ case ICQ_USER_OFFLINE:
+ handleUserOffline(pBuffer, wBufferLength);
+ break;
+
+ case ICQ_USER_SRV_REPLYBUDDY:
+ handleReplyBuddy(pBuffer, wBufferLength);
+ break;
+
+ case ICQ_USER_NOTIFY_REJECTED:
+ handleNotifyRejected(pBuffer, wBufferLength);
+ break;
+
+ case ICQ_ERROR:
+ {
+ WORD wError;
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ LogFamilyError(ICQ_BUDDY_FAMILY, wError);
+ break;
+ }
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_BUDDY_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+ }
+}
+
+
+// TLV(1) Unknown (x50)
+// TLV(2) Member since (not sent)
+// TLV(3) Online since
+// TLV(4) Idle time (not sent)
+// TLV(6) New status
+// TLV(A) External IP
+// TLV(C) DC Info
+// TLV(D) Capabilities
+// TLV(F) Session timer (in seconds)
+// TLV(1D) Avatar Hash (20 bytes)
+static void handleUserOnline(BYTE* buf, WORD wLen)
+{
+ HANDLE hContact;
+ DWORD dwPort;
+ DWORD dwRealIP;
+ DWORD dwIP;
+ DWORD dwUIN;
+ uid_str szUID;
+ DWORD dwDirectConnCookie;
+ DWORD dwWebPort;
+ DWORD dwFT1, dwFT2, dwFT3;
+ LPSTR szClient = 0;
+ BYTE bClientId = 0;
+ WORD wVersion = 0;
+ WORD wTLVCount;
+ WORD wWarningLevel;
+ WORD wStatusFlags;
+ WORD wStatus;
+ BYTE nTCPFlag;
+ DWORD dwOnlineSince;
+ WORD wIdleTimer = 0;
+ time_t tIdleTS = 0;
+ char szStrBuf[MAX_PATH];
+
+ // Unpack the sender's user ID
+ if (!unpackUID(&buf, &wLen, &dwUIN, &szUID)) return;
+
+ // Syntax check
+ if (wLen < 4)
+ return;
+
+ // Warning level?
+ unpackWord(&buf, &wWarningLevel);
+ wLen -= 2;
+
+ // TLV count
+ unpackWord(&buf, &wTLVCount);
+ wLen -= 2;
+
+ // Determine contact
+ hContact = HContactFromUID(dwUIN, szUID, NULL);
+
+ // Ignore status notification if the user is not already on our list
+ if (hContact == INVALID_HANDLE_VALUE)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Ignoring user online (%s)", strUID(dwUIN, szUID));
+#endif
+ return;
+ }
+
+ // Read user info TLVs
+ {
+ oscar_tlv_chain* pChain;
+ oscar_tlv* pTLV;
+
+ // Syntax check
+ if (wLen < 4)
+ return;
+
+ // Get chain
+ if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
+ return;
+
+ if (dwUIN)
+ {
+ // Get DC info TLV
+ pTLV = getTLV(pChain, 0x0C, 1);
+ if (pTLV && (pTLV->wLen >= 15))
+ {
+ unsigned char* pBuffer;
+
+ pBuffer = pTLV->pData;
+ unpackDWord(&pBuffer, &dwRealIP);
+ unpackDWord(&pBuffer, &dwPort);
+ unpackByte(&pBuffer, &nTCPFlag);
+ unpackWord(&pBuffer, &wVersion);
+ unpackDWord(&pBuffer, &dwDirectConnCookie);
+ unpackDWord(&pBuffer, &dwWebPort); // Web front port
+ pBuffer += 4; // Client features
+
+ // Get faked time signatures, used to identify clients
+ if (pTLV->wLen >= 0x23)
+ {
+ unpackDWord(&pBuffer, &dwFT1);
+ unpackDWord(&pBuffer, &dwFT2);
+ unpackDWord(&pBuffer, &dwFT3);
+ }
+ else
+ { // just for the case the timestamps are not there
+ dwFT1 = dwFT2 = dwFT3 = 0;
+ }
+ }
+ else
+ {
+ // This client doesnt want DCs
+ dwRealIP = 0;
+ dwPort = 0;
+ nTCPFlag = 0;
+ dwDirectConnCookie = 0;
+ dwWebPort = 0;
+ dwFT1 = dwFT2 = dwFT3 = 0;
+ }
+
+ // Get Status info TLV
+ pTLV = getTLV(pChain, 0x06, 1);
+ if (pTLV && (pTLV->wLen >= 4))
+ {
+ unsigned char* pBuffer;
+
+ pBuffer = pTLV->pData;
+ unpackWord(&pBuffer, &wStatusFlags);
+ unpackWord(&pBuffer, &wStatus);
+ }
+ else
+ {
+ // Huh? No status TLV? Lets guess then...
+ wStatusFlags = 0;
+ wStatus = ICQ_STATUS_ONLINE;
+ }
+ }
+ else
+ {
+ // Get Class word
+ WORD wClass = getWordFromChain(pChain, 0x01, 1);
+
+ if (wClass & CLASS_AWAY)
+ wStatus = ID_STATUS_AWAY;
+ else
+ wStatus = ID_STATUS_ONLINE;
+
+ wStatusFlags = 0;
+ dwRealIP = 0;
+ dwPort = 0;
+ nTCPFlag = 0;
+ dwDirectConnCookie = 0;
+ dwFT1 = dwFT2 = dwFT3 = 0;
+ }
+
+#ifdef _DEBUG
+ NetLog_Server("Flags are %x", wStatusFlags);
+ NetLog_Server("Status is %x", wStatus);
+#endif
+
+ // Get IP TLV
+ dwIP = getDWordFromChain(pChain, 0x0a, 1);
+
+ // Get Online Since TLV
+ dwOnlineSince = getDWordFromChain(pChain, 0x03, 1);
+
+ // Get Idle timer TLV
+ wIdleTimer = getWordFromChain(pChain, 0x04, 1);
+ if (wIdleTimer)
+ {
+ time(&tIdleTS);
+ tIdleTS -= (wIdleTimer*60);
+ };
+
+#ifdef _DEBUG
+ if (wIdleTimer)
+ NetLog_Server("Idle timer is %u.", wIdleTimer);
+ NetLog_Server("Online since %s", asctime(localtime(&dwOnlineSince)));
+#endif
+
+ // Check client capabilities
+ if (hContact != NULL)
+ {
+ WORD wOldStatus;
+
+ wOldStatus = ICQGetContactStatus(hContact);
+
+ // Get Avatar Hash TLV
+ pTLV = getTLV(pChain, 0x1D, 1);
+ if (pTLV)
+ handleAvatarContactHash(dwUIN, szUID, hContact, pTLV->pData, pTLV->wLen, wOldStatus);
+ else
+ handleAvatarContactHash(dwUIN, szUID, hContact, NULL, 0, wOldStatus);
+
+ // Update the contact's capabilities
+ if (wOldStatus == ID_STATUS_OFFLINE || CheckContactCapabilities(hContact, WAS_FOUND))
+ {
+ // Delete the capabilities we saved the last time this contact came online
+ ClearAllContactCapabilities(hContact);
+
+ {
+ BYTE capBufDat[0x200]; // max 0x20 caps, currently used max 0x12
+ BYTE* capBuf = NULL;
+ WORD capLen = 0;
+ oscar_tlv* pNewTLV;
+
+ // Get Location Capability Info TLVs
+ pTLV = getTLV(pChain, 0x0D, 1);
+ pNewTLV = getTLV(pChain, 0x19, 1);
+
+ if (pTLV && (pTLV->wLen >= 16))
+ capLen = pTLV->wLen;
+
+ if (pNewTLV && (pNewTLV->wLen >= 2))
+ capLen += (pNewTLV->wLen * 8);
+
+ if (capLen)
+ {
+ int i;
+ BYTE* pCap;
+
+ capBuf = pCap = capBufDat;
+
+ if (pTLV && (pTLV->wLen >= 16))
+ { // copy classic Capabilities
+ pCap += pTLV->wLen;
+ memcpy(capBuf, pTLV->pData, pTLV->wLen);
+ }
+
+ if (pNewTLV && (pNewTLV->wLen >= 2))
+ { // get new Capabilities
+ capstr tmp;
+ BYTE* capNew = pNewTLV->pData;
+
+ memcpy(tmp, capAimIcon, 0x10);
+
+ for (i = 0; i<pNewTLV->wLen; i+=2)
+ {
+ BYTE capVal;
+
+ capVal = capNew[0];
+ tmp[2] = capVal;
+ capVal = capNew[1];
+ tmp[3] = capVal;
+
+ capNew += 2;
+
+ memcpy(pCap, tmp, 0x10);
+ pCap += 0x10;
+ }
+ }
+ AddCapabilitiesFromBuffer(hContact, capBuf, capLen);
+ }
+ else
+ { // no capability
+ NetLog_Server("No capability info TLVs");
+ }
+
+ // handle Xtraz status
+ handleXStatusCaps(hContact, capBuf, capLen);
+
+ szClient = detectUserClient(hContact, dwUIN, wVersion, dwFT1, dwFT2, dwFT3, dwOnlineSince, dwDirectConnCookie, dwWebPort, capBuf, capLen, &bClientId, szStrBuf);
+ }
+
+#ifdef _DEBUG
+ if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY))
+ NetLog_Server("Supports advanced messages");
+ else
+ NetLog_Server("Does NOT support advanced messages");
+#endif
+
+ if (dwUIN && wVersion < 8)
+ {
+ ClearContactCapabilities(hContact, CAPF_SRV_RELAY);
+ NetLog_Server("Forcing simple messages due to compability issues");
+ }
+ }
+ else
+ {
+ szClient = (char*)-1; // we don't want to client be overwritten if no capabilities received
+
+ // Get Capability Info TLV
+ pTLV = getTLV(pChain, 0x0D, 1);
+
+ if (pTLV && (pTLV->wLen >= 16))
+ {
+ // handle Xtraz status
+ handleXStatusCaps(hContact, pTLV->pData, pTLV->wLen);
+ }
+ }
+ }
+
+ // Free TLV chain
+ disposeChain(&pChain);
+ }
+
+ // Save contacts details in database
+ if (hContact != NULL)
+ {
+ if (szClient == 0) szClient = ICQTranslateUtfStatic("Unknown", szStrBuf); // if no detection, set uknown
+
+ ICQWriteContactSettingDword(hContact, "LogonTS", dwOnlineSince);
+ if (dwUIN)
+ { // on AIM these are not used
+ ICQWriteContactSettingDword(hContact, "IP", dwIP);
+ ICQWriteContactSettingDword(hContact, "RealIP", dwRealIP);
+ ICQWriteContactSettingDword(hContact, "DirectCookie", dwDirectConnCookie);
+ ICQWriteContactSettingByte(hContact, "DCType", (BYTE)nTCPFlag);
+ ICQWriteContactSettingWord(hContact, "UserPort", (WORD)(dwPort & 0xffff));
+ ICQWriteContactSettingWord(hContact, "Version", wVersion);
+ }
+ if (szClient != (char*)-1)
+ {
+ ICQWriteContactSettingUtf(hContact, "MirVer", szClient);
+ ICQWriteContactSettingByte(hContact, "ClientID", bClientId);
+ }
+ ICQWriteContactSettingWord(hContact, "Status", (WORD)IcqStatusToMiranda(wStatus));
+ if (!wIdleTimer)
+ {
+ DWORD dw = ICQGetContactSettingDword(hContact, "IdleTS", 0);
+ ICQWriteContactSettingDword(hContact, "OldIdleTS", dw);
+ }
+ ICQWriteContactSettingDword(hContact, "IdleTS", tIdleTS);
+
+ // Update info?
+ if (dwUIN && ((time(NULL) - ICQGetContactSettingDword(hContact, "InfoTS", 0)) > UPDATE_THRESHOLD))
+ icq_QueueUser(hContact);
+ }
+ else
+ {
+ dwLocalDirectConnCookie = dwDirectConnCookie;
+ }
+
+ // And a small log notice...
+ NetLog_Server("%s changed status to %s (v%d).", strUID(dwUIN, szUID),
+ MirandaStatusToString(IcqStatusToMiranda(wStatus)), wVersion);
+
+ if (szClient == cliSpamBot)
+ {
+ if (ICQGetContactSettingByte(NULL, "KillSpambots", DEFAULT_KILLSPAM_ENABLED) && DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ { // kill spammer
+ icq_DequeueUser(dwUIN);
+ AddToSpammerList(dwUIN);
+ icq_sendRemoveContact(dwUIN, NULL);
+ if (ICQGetContactSettingByte(NULL, "PopupsSpamEnabled", DEFAULT_SPAM_POPUPS_ENABLED))
+ ShowPopUpMsg(hContact, "Spambot Detected", "Contact deleted & further events blocked.", POPTYPE_SPAM);
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+
+ NetLog_Server("Contact %u deleted", dwUIN);
+ }
+ }
+}
+
+
+
+static void handleUserOffline(BYTE *buf, WORD wLen)
+{
+ HANDLE hContact;
+ DWORD dwUIN;
+ uid_str szUID;
+
+ // Unpack the sender's user ID
+ if (!unpackUID(&buf, &wLen, &dwUIN, &szUID)) return;
+
+ hContact = HContactFromUID(dwUIN, szUID, NULL);
+
+ // Skip contacts that are not already on our list
+ if (hContact != INVALID_HANDLE_VALUE)
+ {
+ NetLog_Server("%s went offline.", strUID(dwUIN, szUID));
+
+ ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+ ICQWriteContactSettingDword(hContact, "IdleTS", 0);
+ // close Direct Connections to that user
+ CloseContactDirectConns(hContact);
+ // clear Xtraz status
+ handleXStatusCaps(hContact, NULL, 0);
+
+ icq_GetUserStatus(hContact,2);
+ }
+}
+
+
+
+static void handleReplyBuddy(BYTE *buf, WORD wPackLen)
+{
+ oscar_tlv_chain *pChain;
+
+ pChain = readIntoTLVChain(&buf, wPackLen, 0);
+
+ if (pChain)
+ {
+ DWORD wMaxUins;
+ DWORD wMaxWatchers;
+
+ wMaxUins = getWordFromChain(pChain, 1, 1);
+ wMaxWatchers = getWordFromChain(pChain, 2, 1);
+
+ NetLog_Server("MaxUINs %u", wMaxUins);
+ NetLog_Server("MaxWatchers %u", wMaxWatchers);
+
+ disposeChain(&pChain);
+ }
+ else
+ {
+ NetLog_Server("Error: Malformed BuddyReply");
+ }
+}
+
+
+
+static void handleNotifyRejected(BYTE *buf, WORD wPackLen)
+{
+ DWORD dwUIN;
+ uid_str szUID;
+
+ if (!unpackUID(&buf, &wPackLen, &dwUIN, &szUID))
+ return;
+
+ NetLog_Server("SNAC(x03,x0a) - SRV_NOTIFICATION_REJECTED for %s", strUID(dwUIN, szUID));
+}
diff --git a/icqj_mod/fam_04message.c b/icqj_mod/fam_04message.c new file mode 100644 index 0000000..52e2a1a --- /dev/null +++ b/icqj_mod/fam_04message.c @@ -0,0 +1,2519 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_04message.c,v $
+// Revision : $Revision: 3001 $
+// Last change on : $Date: 2006-06-02 11:05:11 +0200 (Fri, 02 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Handlers for Family 4 ICBM Messages
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static void handleReplyICBM(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+static void handleRecvServMsg(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+static void handleRecvServMsgType1(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwTS1, DWORD dwTS2);
+static void handleRecvServMsgType2(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwTS1, DWORD dwTS2);
+static void handleRecvServMsgType4(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwTS1, DWORD dwTS2);
+static void handleRecvServMsgError(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+static void handleRecvMsgResponse(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+static void handleServerAck(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+static void handleTypingNotification(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+static void handleMissedMsg(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+static void parseTLV2711(DWORD dwUin, HANDLE hContact, DWORD dwID1, DWORD dwID2, WORD wAckType, oscar_tlv* tlv);
+static void parseServerGreeting(BYTE* pDataBuf, WORD wLen, WORD wMsgLen, DWORD dwUin, BYTE bFlags, WORD wStatus, WORD wCookie, WORD wAckType, DWORD dwID1, DWORD dwID2, WORD wVersion);
+
+
+
+void handleMsgFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+
+ case ICQ_MSG_SRV_ERROR: // SNAC(4, 0x01)
+ handleRecvServMsgError(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+
+ case ICQ_MSG_SRV_RECV: // SNAC(4, 0x07)
+ handleRecvServMsg(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+
+ case ICQ_MSG_SRV_MISSED_MESSAGE: // SNAC(4, 0x0A)
+ handleMissedMsg(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+
+ case ICQ_MSG_RESPONSE: // SNAC(4, 0x0B)
+ handleRecvMsgResponse(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+
+ case ICQ_MSG_SRV_ACK: // SNAC(4, 0x0C) Server acknowledgements
+ handleServerAck(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+
+ case ICQ_MSG_MTN: // SNAC(4, 0x14) Typing notifications
+ handleTypingNotification(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+
+ case ICQ_MSG_SRV_REPLYICBM: // SNAC(4, 0x05) SRV_REPLYICBM
+ handleReplyICBM(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_MSG_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+ }
+}
+
+
+
+static void handleReplyICBM(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{ // we don't care about the stuff, just change the params
+ icq_packet packet;
+
+ // Set message parameters for channel 1 (CLI_SET_ICBM_PARAMS)
+ serverPacketInit(&packet, 26);
+ packFNACHeader(&packet, ICQ_MSG_FAMILY, ICQ_MSG_CLI_SETPARAMS);
+ packWord(&packet, 0x0001); // Channel
+#ifdef DBG_CAPMTN
+ packDWord(&packet, 0x0000000B); // Flags
+#else
+ packDWord(&packet, 0x00000003); // Flags
+#endif
+ packWord(&packet, MAX_MESSAGESNACSIZE); // Max message snac size
+ packWord(&packet, 0x03E7); // Max sender warning level
+ packWord(&packet, 0x03E7); // Max receiver warning level
+ packWord(&packet, CLIENTRATELIMIT); // Minimum message interval in seconds
+ packWord(&packet, 0x0000); // Unknown
+ sendServPacket(&packet);
+
+ // Set message parameters for channel 2 (CLI_SET_ICBM_PARAMS)
+ serverPacketInit(&packet, 26);
+ packFNACHeader(&packet, ICQ_MSG_FAMILY, ICQ_MSG_CLI_SETPARAMS);
+ packWord(&packet, 0x0002); // Channel
+ packDWord(&packet, 0x00000003); // Flags
+ packWord(&packet, MAX_MESSAGESNACSIZE); // Max message snac size
+ packWord(&packet, 0x03E7); // Max sender warning level
+ packWord(&packet, 0x03E7); // Max receiver warning level
+ packWord(&packet, CLIENTRATELIMIT); // Minimum message interval in seconds
+ packWord(&packet, 0x0000); // Unknown
+ sendServPacket(&packet);
+
+ // Set message parameters for channel 4 (CLI_SET_ICBM_PARAMS)
+ serverPacketInit(&packet, 26);
+ packFNACHeader(&packet, ICQ_MSG_FAMILY, ICQ_MSG_CLI_SETPARAMS);
+ packWord(&packet, 0x0004); // Channel
+ packDWord(&packet, 0x00000003); // Flags
+ packWord(&packet, MAX_MESSAGESNACSIZE); // Max message snac size
+ packWord(&packet, 0x03E7); // Max sender warning level
+ packWord(&packet, 0x03E7); // Max receiver warning level
+ packWord(&packet, CLIENTRATELIMIT); // Minimum message interval in seconds
+ packWord(&packet, 0x0000); // Unknown
+ sendServPacket(&packet);
+}
+
+
+
+static void handleRecvServMsg(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{
+ DWORD dwUin;
+ DWORD dwID1;
+ DWORD dwID2;
+ WORD wTLVCount;
+ WORD wMessageFormat;
+ uid_str szUID;
+
+
+ // These two values are some kind of reference, we need to save
+ // them to send file request responses for example
+ unpackLEDWord(&buf, &dwID1); // TODO: msg cookies should be main
+ wLen -= 4;
+ unpackLEDWord(&buf, &dwID2);
+ wLen -= 4;
+
+ // The message type used:
+ unpackWord(&buf, &wMessageFormat); // 0x0001: Simple message format
+ wLen -= 2; // 0x0002: Advanced message format
+ // 0x0004: 'New' message format
+ // Sender UIN
+ if (wMessageFormat == 1)
+ {
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUID)) return;
+ }
+ else
+ {
+ szUID[0] = '\0';
+ if (!unpackUID(&buf, &wLen, &dwUin, NULL)) return;
+ }
+
+ if (dwUin && IsOnSpammerList(dwUin))
+ {
+ NetLog_Server("Ignored Message from known Spammer");
+ return;
+ }
+
+ // Warning level?
+ buf += 2;
+ wLen -= 2;
+
+ // Number of following TLVs, until msg-format dependant TLVs
+ unpackWord(&buf, &wTLVCount);
+ wLen -= 2;
+ if (wTLVCount > 0)
+ {
+ // Save current buffer pointer so we can calculate
+ // how much data we have left after the chain read.
+ oscar_tlv_chain* chain = NULL;
+ unsigned char* pBufStart = buf;
+
+ chain = readIntoTLVChain(&buf, wLen, wTLVCount);
+
+ // This chain contains info that is filled in by the server.
+ // TLV(1): unknown
+ // TLV(2): date: on since
+ // TLV(3): date: on since
+ // TLV(4): unknown, usually 0000. Not in file-req or auto-msg-req
+ // TLV(6): sender's status
+ // TLV(F): a time in seconds, unknown
+
+ disposeChain(&chain);
+
+ // Update wLen
+ wLen = wLen - (buf - pBufStart);
+ }
+
+
+ // This is where the format specific data begins
+
+ switch (wMessageFormat)
+ {
+
+ case 1: // Simple message format
+ handleRecvServMsgType1(buf, wLen, dwUin, szUID, dwID1, dwID2);
+ break;
+
+ case 2: // Encapsulated messages
+ handleRecvServMsgType2(buf, wLen, dwUin, szUID, dwID1, dwID2);
+ break;
+
+ case 4: // Typed messages
+ handleRecvServMsgType4(buf, wLen, dwUin, szUID, dwID1, dwID2);
+ break;
+
+ default:
+ NetLog_Server("Unknown format message thru server - Flags %u, Ref %u, Type: %u, UID: %s", wFlags, dwRef, wMessageFormat, strUID(dwUin, szUID));
+ break;
+
+ }
+}
+
+
+
+static char* convertMsgToUserSpecificUtf(HANDLE hContact, const char* szMsg)
+{
+ WORD wCP = ICQGetContactSettingWord(hContact, "CodePage", gwAnsiCodepage);
+ wchar_t* usMsg = NULL;
+
+ if (wCP != CP_ACP)
+ {
+ int nMsgLen = strlennull(szMsg);
+
+ usMsg = (wchar_t*)SAFE_MALLOC((nMsgLen + 2)*(sizeof(wchar_t) + 1));
+ memcpy((char*)usMsg, szMsg, nMsgLen + 1);
+ MultiByteToWideChar(wCP, 0, szMsg, nMsgLen, (wchar_t*)((char*)usMsg + nMsgLen + 1), nMsgLen);
+ *(wchar_t*)((char*)usMsg + 1 + nMsgLen*(1 + sizeof(wchar_t))) = '\0'; // trailing zeros
+ }
+ return (char*)usMsg;
+}
+
+
+
+static void handleRecvServMsgType1(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwTS1, DWORD dwTS2)
+{
+ WORD wTLVType;
+ WORD wTLVLen;
+ BYTE* pDataBuf;
+ BYTE* pBuf;
+
+ // Unpack the first TLV(2)
+ unpackTypedTLV(&buf, wLen, 2, &wTLVType, &wTLVLen, &pDataBuf);
+ NetLog_Server("Message (format %u) - UID: %s", 1, strUID(dwUin, szUID));
+ pBuf = pDataBuf;
+
+ // It must be TLV(2)
+ if (wTLVType == 2)
+ {
+ oscar_tlv_chain* pChain;
+
+ pChain = readIntoTLVChain(&pDataBuf, wTLVLen, 0);
+
+ // TLV(2) contains yet another TLV chain with the following TLVs:
+ // TLV(1281): Capability
+ // TLV(257): This TLV contains the actual message
+
+ if (pChain)
+ {
+ oscar_tlv* pMessageTLV;
+ oscar_tlv* pCapabilityTLV;
+
+ // Find the capability TLV
+ pCapabilityTLV = getTLV(pChain, 0x0501, 1);
+ if (pCapabilityTLV && (pCapabilityTLV->wLen > 0))
+ {
+ WORD wDataLen;
+ BYTE *pDataBuf;
+
+ wDataLen = pCapabilityTLV->wLen;
+ pDataBuf = pCapabilityTLV->pData;
+
+ if (wDataLen > 0)
+ {
+ NetLog_Server("Message (format 1) - Message has %d caps.", wDataLen);
+ }
+ }
+ else
+ {
+ NetLog_Server("Message (format 1) - No message cap.");
+ }
+
+ // Find the message TLV
+ pMessageTLV = getTLV(pChain, 0x0101, 1);
+ if (pMessageTLV)
+ {
+ if (pMessageTLV->wLen > 4)
+ {
+ WORD wMsgLen;
+ BYTE* pMsgBuf;
+ WORD wEncoding;
+ WORD wCodePage;
+ char* szMsg = NULL;
+ HANDLE hContact;
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ int bAdded;
+
+ // The message begins with a encoding specification
+ // The first WORD is believed to have the following meaning:
+ // 0x00: US-ASCII
+ // 0x02: Unicode UCS-2 Big Endian encoding
+ // 0x03: local 8bit encoding
+ pMsgBuf = pMessageTLV->pData;
+ unpackWord(&pMsgBuf, &wEncoding);
+ unpackWord(&pMsgBuf, &wCodePage);
+
+ wMsgLen = pMessageTLV->wLen - 4;
+ NetLog_Server("Message (format 1) - Encoding is 0x%X, page is 0x%X", wEncoding, wCodePage);
+
+ pre.flags = 0;
+
+ hContact = HContactFromUID(dwUin, szUID, &bAdded);
+
+ switch (wEncoding)
+ {
+
+ case 2:
+ {
+ WCHAR* usMsg;
+ int nStrSize;
+
+ usMsg = (WCHAR*)SAFE_MALLOC(wMsgLen + 2);
+ unpackWideString(&pMsgBuf, usMsg, wMsgLen);
+ usMsg[wMsgLen/2] = 0;
+
+ if (!dwUin)
+ {
+ char *utf = make_utf8_string(usMsg);
+ int nUtfLen = strlennull(utf);
+
+ SAFE_FREE(&usMsg);
+ utf = EliminateHtml(utf, nUtfLen);
+
+ usMsg = make_unicode_string(utf);
+ SAFE_FREE(&utf);
+ SetContactCapabilities(hContact, CAPF_UTF);
+ }
+
+ nStrSize = WideCharToMultiByte(CP_ACP, 0, usMsg, wMsgLen / sizeof(WCHAR), szMsg, 0, NULL, NULL);
+ szMsg = (char*)SAFE_MALLOC((nStrSize+1)*(sizeof(wchar_t)+1));
+ WideCharToMultiByte(CP_ACP, 0, usMsg, wMsgLen / sizeof(WCHAR), szMsg, nStrSize, NULL, NULL);
+ nStrSize = strlennull(szMsg); // this is necessary, sometimes it was bad
+ memcpy(szMsg+nStrSize+1, usMsg, wMsgLen);
+
+ pre.flags = PREF_UNICODE;
+
+ SAFE_FREE(&usMsg);
+
+ break;
+ }
+
+ case 0:
+ case 3:
+ default:
+ {
+ // Copy the message text into a new proper string.
+ szMsg = (char *)SAFE_MALLOC(wMsgLen + 1);
+ memcpy(szMsg, pMsgBuf, wMsgLen);
+ szMsg[wMsgLen] = '\0';
+ if (!dwUin)
+ {
+ szMsg = EliminateHtml(szMsg, wMsgLen);
+ }
+
+ break;
+ }
+ }
+
+ if (!pre.flags && !IsUSASCII(szMsg, strlennull(szMsg)))
+ { // message is Ansi and contains national characters, create Unicode part by codepage
+ char* usMsg = convertMsgToUserSpecificUtf(hContact, szMsg);
+
+ if (usMsg)
+ {
+ SAFE_FREE(&szMsg);
+ szMsg = (char*)usMsg;
+ pre.flags = PREF_UNICODE;
+ }
+ }
+ // Create and send the message event
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.timestamp = time(NULL);
+ pre.szMessage = (char *)szMsg;
+ pre.lParam = 0;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+
+ SAFE_FREE(&szMsg);
+
+ NetLog_Server("Message (format 1) received");
+
+ // Save tick value
+ ICQWriteContactSettingDword(ccs.hContact, "TickTS", time(NULL) - (dwTS1/1000));
+ }
+ else
+ {
+ NetLog_Server("Ignoring empty message (format 1)");
+ }
+ }
+ else
+ {
+ NetLog_Server("Failed to find TLV(1281) message (format 1)");
+ }
+
+ // Free the chain memory
+ disposeChain(&pChain);
+ }
+ else
+ {
+ NetLog_Server("Failed to read TLV chain in message (format 1)");
+ }
+ }
+ else
+ {
+ NetLog_Server("Unsupported TLV (%u) in message (format %u)", wTLVType, 1);
+ }
+ icq_SetUserStatus(dwUin,0,21);
+ SAFE_FREE(&pBuf);
+}
+
+
+
+static void handleRecvServMsgType2(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwID1, DWORD dwID2)
+{
+ WORD wTLVType;
+ WORD wTLVLen;
+ char* pDataBuf = NULL;
+ char* pBuf;
+
+ // Unpack the first TLV(5)
+ unpackTypedTLV(&buf, wLen, 5, &wTLVType, &wTLVLen, &pDataBuf);
+ NetLog_Server("Message (format %u) through server - UID: %s", 2, strUID(dwUin, szUID));
+ pBuf = pDataBuf;
+
+ // It must be TLV(5)
+ if (wTLVType == 5)
+ {
+ WORD wCommand;
+ oscar_tlv_chain* chain;
+ oscar_tlv* tlv;
+ DWORD dwIP;
+ DWORD dwExternalIP;
+ WORD wPort;
+ WORD wAckType;
+ DWORD q1,q2,q3,q4;
+
+ unpackWord(&pDataBuf, &wCommand);
+ wTLVLen -= 2; // Command 0x0000 - Normal message/file send request
+#ifdef _DEBUG // 0x0001 - Abort request
+ NetLog_Server("Command is %u", wCommand); // 0x0002 - Acknowledge request
+#endif
+
+ if (wCommand == 1)
+ {
+ NetLog_Server("Cannot handle abort messages yet... :(");
+ icq_SetUserStatus(dwUin,0,22);
+ SAFE_FREE(&pBuf);
+ return;
+ }
+
+ // Some stuff we don't use
+ pDataBuf += 8; // dwID1 and dwID2 again
+ wTLVLen -= 8;
+ unpackDWord(&pDataBuf, &q1);
+ unpackDWord(&pDataBuf, &q2);
+ unpackDWord(&pDataBuf, &q3);
+ unpackDWord(&pDataBuf, &q4); // Capability (CAP_SRV_RELAY)
+ wTLVLen -= 16;
+
+ if (CompareGUIDs(q1,q2,q3,q4, MCAP_TLV2711_FMT))
+ {
+ // We need at least 4 bytes to read a chain
+ if (wTLVLen > 4)
+ {
+ HANDLE hContact = HContactFromUIN(dwUin, NULL);
+
+ // This TLV chain may contain the following TLVs:
+ // TLV(A): Acktype 0x0000 - normal message
+ // 0x0001 - file request / abort request
+ // 0x0002 - file ack
+ // TLV(F): Unknown
+ // TLV(3): External IP
+ // TLV(5): DC port (not to use for filetransfers)
+ // TLV(0x2711): The next message level
+
+ chain = readIntoTLVChain(&pDataBuf, wTLVLen, 0);
+
+ wAckType = getWordFromChain(chain, 0x0A, 1);
+
+ // Update the saved DC info (if contact already exists)
+ if (hContact != INVALID_HANDLE_VALUE)
+ {
+ if (dwExternalIP = getDWordFromChain(chain, 0x03, 1))
+ ICQWriteContactSettingDword(hContact, "RealIP", dwExternalIP);
+ if (dwIP = getDWordFromChain(chain, 0x04, 1))
+ ICQWriteContactSettingDword(hContact, "IP", dwIP);
+ if (wPort = getWordFromChain(chain, 0x05, 1))
+ ICQWriteContactSettingWord(hContact, "UserPort", wPort);
+
+ // Save tick value
+ ICQWriteContactSettingDword(hContact, "TickTS", time(NULL) - (dwID1/1000));
+ }
+
+ // Parse the next message level
+ if (tlv = getTLV(chain, 0x2711, 1))
+ {
+ parseTLV2711(dwUin, hContact, dwID1, dwID2, wAckType, tlv);
+ }
+ else
+ {
+ NetLog_Server("Warning, no 0x2711 TLV in message (format 2)");
+ }
+ // Clean up
+ disposeChain(&chain);
+ }
+ else
+ {
+ NetLog_Server("Warning, empty message (format 2)");
+ }
+ }
+ else if (CompareGUIDs(q1,q2,q3,q4,MCAP_REVERSE_REQ))
+ { // Handle reverse DC request
+ // We need at least 4 bytes to read a chain
+ if (wTLVLen > 4)
+ {
+ chain = readIntoTLVChain(&pDataBuf, wTLVLen, 0);
+
+ wAckType = getWordFromChain(chain, 0x0A, 1);
+ // Parse the next message level
+ if (tlv = getTLV(chain, 0x2711, 1))
+ {
+ if (tlv->wLen == 0x1B)
+ {
+ char* buf=tlv->pData;
+ DWORD dwUin, dwIp, dwPort, dwId;
+ WORD wVersion;
+ BYTE bMode;
+ HANDLE hContact;
+
+ unpackLEDWord(&buf, &dwUin);
+
+ hContact = HContactFromUIN(dwUin, NULL);
+ if (hContact == INVALID_HANDLE_VALUE)
+ {
+ NetLog_Server("Error: %s from unknown contact %u", "Reverse Connect Request", dwUin);
+ }
+ else
+ {
+ unpackDWord(&buf, &dwIp);
+ unpackLEDWord(&buf, &dwPort);
+ unpackByte(&buf, &bMode);
+ buf += 4; // unknown
+ if (dwPort)
+ buf += 4; // port, again?
+ else
+ unpackLEDWord(&buf, &dwPort);
+ unpackLEWord(&buf, &wVersion);
+
+ ICQWriteContactSettingDword(hContact, "IP", dwIp);
+ ICQWriteContactSettingWord(hContact, "UserPort", (WORD)dwPort);
+ ICQWriteContactSettingByte(hContact, "DCType", bMode);
+ ICQWriteContactSettingWord(hContact, "Version", wVersion);
+ if (wVersion>6)
+ {
+ unpackLEDWord(&buf, &dwId);
+
+ OpenDirectConnection(hContact, DIRECTCONN_REVERSE, (void*)dwId);
+ }
+ else
+ NetLog_Server("Warning: Unsupported direct protocol version in %s", "Reverse Connect Request");
+ }
+ }
+ else
+ {
+ NetLog_Server("Malformed %s", "Reverse Connect Request");
+ }
+ }
+ else
+ {
+ NetLog_Server("Warning, no 0x2711 TLV in message (format 2)");
+ }
+ // Clean up
+ disposeChain(&chain);
+ }
+ else
+ {
+ NetLog_Server("Warning, empty message (format 2)");
+ }
+ }
+ else
+ {
+ NetLog_Server("Unknown Message Format Capability");
+ }
+ }
+ else
+ {
+ NetLog_Server("Unsupported TLV (%u) in message (format %u)", wTLVType, 2);
+ }
+
+ icq_SetUserStatus(dwUin,0,22);
+ SAFE_FREE(&pBuf);
+}
+
+
+
+static void parseTLV2711(DWORD dwUin, HANDLE hContact, DWORD dwID1, DWORD dwID2, WORD wAckType, oscar_tlv* tlv)
+{
+ BYTE* pDataBuf;
+ WORD wId;
+ WORD wLen;
+
+ pDataBuf = tlv->pData;
+ wLen = tlv->wLen;
+
+ unpackLEWord(&pDataBuf, &wId); // Incorrect identification, but working
+ wLen -= 2;
+
+ // Only 0x1B are real messages
+ if (wId == 0x001B)
+ {
+ WORD wVersion;
+ WORD wCookie;
+ WORD wMsgLen;
+ BYTE bMsgType;
+ BYTE bFlags;
+ DWORD dwGuid1,dwGuid2,dwGuid3,dwGuid4;
+
+ unpackLEWord(&pDataBuf, &wVersion);
+ wLen -= 2;
+
+ if (hContact != INVALID_HANDLE_VALUE)
+ ICQWriteContactSettingWord(hContact, "Version", wVersion);
+
+ unpackDWord(&pDataBuf, &dwGuid1); // plugin type GUID
+ unpackDWord(&pDataBuf, &dwGuid2);
+ unpackDWord(&pDataBuf, &dwGuid3);
+ unpackDWord(&pDataBuf, &dwGuid4);
+ wLen -= 16;
+
+ // Skip lots of unused stuff
+ pDataBuf += 9;
+ wLen -= 9;
+
+ unpackLEWord(&pDataBuf, &wId);
+ wLen -= 2;
+
+ unpackLEWord(&pDataBuf, &wCookie);
+ wLen -= 2;
+
+ if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PSIG_MESSAGE))
+ { // is this a normal message ?
+ WORD wPritority;
+ WORD wStatus;
+
+ pDataBuf += 12; /* all zeroes */
+ wLen -= 12;
+ unpackByte(&pDataBuf, &bMsgType);
+ wLen -= 1;
+ unpackByte(&pDataBuf, &bFlags);
+ wLen -= 1;
+
+ // Status
+ unpackLEWord(&pDataBuf, &wStatus);
+ wLen -= 2;
+
+ // Priority
+ unpackLEWord(&pDataBuf, &wPritority);
+ wLen -= 2;
+ NetLog_Server("Priority: %u", wPritority);
+
+ // Message
+ unpackLEWord(&pDataBuf, &wMsgLen);
+ wLen -= 2;
+
+ // HANDLERS
+ switch (bMsgType)
+ {
+ // File messages, handled by the file module
+ case MTYPE_FILEREQ:
+ {
+ char* szMsg;
+
+ szMsg = (char *)_alloca(wMsgLen + 1);
+ memcpy(szMsg, pDataBuf, wMsgLen);
+ szMsg[wMsgLen] = '\0';
+ pDataBuf += wMsgLen;
+ wLen -= wMsgLen;
+
+ if (wAckType == 0 || wAckType == 1)
+ {
+ // File requests 7
+ handleFileRequest(pDataBuf, wLen, dwUin, wCookie, dwID1, dwID2, szMsg, 7, FALSE);
+ }
+ else if (wAckType == 2)
+ {
+ // File reply 7
+ handleFileAck(pDataBuf, wLen, dwUin, wCookie, wStatus, szMsg);
+ }
+ else
+ {
+ NetLog_Server("Ignored strange file message");
+ }
+
+ break;
+ }
+
+ // Chat messages, handled by the chat module
+ case MTYPE_CHAT:
+ {
+ break;
+ }
+
+ // Plugin messages, need further parsing
+ case MTYPE_PLUGIN:
+ {
+ parseServerGreeting(pDataBuf, wLen, wMsgLen, dwUin, bFlags, wStatus, wCookie, wAckType, dwID1, dwID2, wVersion);
+ break;
+ }
+
+ // Everything else
+ default:
+ {
+ // Only ack non-status message requests
+ // The other will be acked later
+ if (bMsgType < 0x80)
+ icq_sendAdvancedMsgAck(dwUin, dwID1, dwID2, wCookie, bMsgType, bFlags);
+ handleMessageTypes(dwUin, time(NULL), dwID1, dwID2, wCookie, wVersion, bMsgType, bFlags, wAckType, tlv->wLen - 53, wMsgLen, pDataBuf, FALSE);
+ break;
+ }
+ }
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PSIG_INFO_PLUGIN))
+ { // info manager plugin - obsolete
+ BYTE bLevel;
+
+ pDataBuf += 16; /* unused stuff */
+ wLen -= 16;
+ unpackByte(&pDataBuf, &bMsgType);
+ wLen -= 1;
+
+ pDataBuf += 3; // unknown
+ wLen -= 3;
+ unpackByte(&pDataBuf, &bLevel);
+ if (bLevel != 0 || wLen < 16)
+ {
+ NetLog_Server("Invalid %s Manager Plugin message from %u", "Info", dwUin);
+ return;
+ }
+ unpackDWord(&pDataBuf, &dwGuid1); // plugin request GUID
+ unpackDWord(&pDataBuf, &dwGuid2);
+ unpackDWord(&pDataBuf, &dwGuid3);
+ unpackDWord(&pDataBuf, &dwGuid4);
+ wLen -= 16;
+
+ if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PMSG_QUERY_INFO))
+ {
+ NetLog_Server("User %u requests our %s plugin list. NOT SUPPORTED", dwUin, "info");
+ }
+ else
+ NetLog_Server("Unknown %s Manager message from %u", "Info", dwUin);
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PSIG_STATUS_PLUGIN))
+ { // status manager plugin - obsolete
+ BYTE bLevel;
+
+ pDataBuf += 16; /* unused stuff */
+ wLen -= 16;
+ unpackByte(&pDataBuf, &bMsgType);
+ wLen -= 1;
+
+ pDataBuf += 3; // unknown
+ wLen -= 3;
+ unpackByte(&pDataBuf, &bLevel);
+ if (bLevel != 0 || wLen < 16)
+ {
+ NetLog_Server("Invalid %s Manager Plugin message from %u", "Status", dwUin);
+ return;
+ }
+ unpackDWord(&pDataBuf, &dwGuid1); // plugin request GUID
+ unpackDWord(&pDataBuf, &dwGuid2);
+ unpackDWord(&pDataBuf, &dwGuid3);
+ unpackDWord(&pDataBuf, &dwGuid4);
+ wLen -= 16;
+
+ if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PMSG_QUERY_STATUS))
+ {
+ NetLog_Server("User %u requests our %s plugin list. NOT SUPPORTED", dwUin, "status");
+ }
+ else
+ NetLog_Server("Unknown %s Manager message from %u", "Status", dwUin);
+ }
+ else
+ NetLog_Server("Unknown signature (%08x-%08x-%08x-%08x) in message (format 2)", dwGuid1, dwGuid2, dwGuid3, dwGuid4);
+ }
+ else
+ {
+ NetLog_Server("Unknown wId1 (%u) in message (format 2)", wId);
+ }
+}
+
+
+
+void parseServerGreeting(BYTE* pDataBuf, WORD wLen, WORD wMsgLen, DWORD dwUin, BYTE bFlags, WORD wStatus, WORD wCookie, WORD wAckType, DWORD dwID1, DWORD dwID2, WORD wVersion)
+{
+ WORD wInfoLen;
+ DWORD dwPluginNameLen;
+ DWORD dwLengthToEnd;
+ DWORD dwDataLen;
+ DWORD q1,q2,q3,q4;
+ WORD qt;
+ char* szPluginName;
+ int typeId;
+
+ NetLog_Server("Parsing Greeting message through server");
+
+ pDataBuf += wMsgLen; // Message
+ wLen -= wMsgLen;
+
+ //
+ unpackLEWord(&pDataBuf, &wInfoLen);
+
+ unpackDWord(&pDataBuf, &q1); // get data GUID & function id
+ unpackDWord(&pDataBuf, &q2);
+ unpackDWord(&pDataBuf, &q3);
+ unpackDWord(&pDataBuf, &q4);
+ unpackLEWord(&pDataBuf, &qt);
+ wLen -= 20;
+
+ unpackLEDWord(&pDataBuf, &dwPluginNameLen);
+ wLen -= 4;
+
+ if (dwPluginNameLen > wLen)
+ { // check for malformed plugin name
+ dwPluginNameLen = wLen;
+ NetLog_Server("Warning: malformed size of plugin name.");
+ }
+ szPluginName = (char *)_alloca(dwPluginNameLen + 1);
+ memcpy(szPluginName, pDataBuf, dwPluginNameLen);
+ szPluginName[dwPluginNameLen] = '\0';
+ wLen -= (WORD)dwPluginNameLen;
+
+ pDataBuf += dwPluginNameLen + 15;
+
+ typeId = TypeGUIDToTypeId(q1, q2, q3, q4, qt);
+ if (!typeId)
+ NetLog_Server("Error: Unknown type {%08x-%08x-%08x-%08x:%04x}: %s", q1,q2,q3,q4,qt, szPluginName);
+
+ if (wLen > 8)
+ {
+ // Length of remaining data
+ unpackLEDWord(&pDataBuf, &dwLengthToEnd);
+
+ // Length of message
+ unpackLEDWord(&pDataBuf, &dwDataLen);
+ wLen -= 8;
+
+ if (dwDataLen > wLen)
+ dwDataLen = wLen;
+
+ if (typeId == MTYPE_FILEREQ && wAckType == 2)
+ {
+ char* szMsg;
+
+
+ NetLog_Server("This is file ack");
+ szMsg = (char *)_alloca(dwDataLen + 1);
+ memcpy(szMsg, pDataBuf, dwDataLen);
+ szMsg[dwDataLen] = '\0';
+ pDataBuf += dwDataLen;
+ wLen -= (WORD)dwDataLen;
+
+ handleFileAck(pDataBuf, wLen, dwUin, wCookie, wStatus, szMsg);
+ }
+ else if (typeId == MTYPE_FILEREQ && wAckType == 1)
+ {
+ char* szMsg;
+
+
+ NetLog_Server("This is a file request");
+ szMsg = (char *)_alloca(dwDataLen + 1);
+ memcpy(szMsg, pDataBuf, dwDataLen);
+ szMsg[dwDataLen] = '\0';
+ pDataBuf += dwDataLen;
+ wLen -= (WORD)dwDataLen;
+
+ handleFileRequest(pDataBuf, wLen, dwUin, wCookie, dwID1, dwID2, szMsg, 8, FALSE);
+ }
+ else if (typeId == MTYPE_CHAT && wAckType == 1)
+ {
+ char* szMsg;
+
+ NetLog_Server("This is a chat request");
+ szMsg = (char *)_alloca(dwDataLen + 1);
+ memcpy(szMsg, pDataBuf, dwDataLen);
+ szMsg[dwDataLen] = '\0';
+ pDataBuf += dwDataLen;
+ wLen -= (WORD)dwDataLen;
+
+ // handleChatRequest(pDataBuf, wLen, dwUin, wCookie, dwID1, dwID2, szMsg, 8);
+ }
+ else if (typeId)
+ {
+ if (typeId == MTYPE_URL || typeId == MTYPE_CONTACTS)
+ icq_sendAdvancedMsgAck(dwUin, dwID1, dwID2, wCookie, (BYTE)typeId, bFlags);
+
+ handleMessageTypes(dwUin, time(NULL), dwID1, dwID2, wCookie, wVersion, typeId, bFlags, wAckType, dwLengthToEnd, (WORD)dwDataLen, pDataBuf, FALSE);
+ }
+ else
+ {
+ NetLog_Server("Unsupported plugin message type '%s'", szPluginName);
+ }
+ }
+}
+
+
+
+static void handleRecvServMsgType4(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwTS1, DWORD dwTS2)
+{
+ WORD wTLVType;
+ WORD wTLVLen;
+ BYTE* pDataBuf;
+ DWORD dwUin2;
+
+ // Unpack the first TLV(5)
+ unpackTypedTLV(&buf, wLen, 5, &wTLVType, &wTLVLen, &pDataBuf);
+ NetLog_Server("Message (format %u) through server - UID: %u", 4, strUID(dwUin, szUID));
+
+ // It must be TLV(5)
+ if (wTLVType == 5)
+ {
+ BYTE bMsgType;
+ BYTE bFlags;
+ unsigned char* pmsg = pDataBuf;
+ WORD wMsgLen;
+
+
+ unpackLEDWord(&pmsg, &dwUin2);
+
+ if (dwUin2 == dwUin)
+ {
+ unpackByte(&pmsg, &bMsgType);
+ unpackByte(&pmsg, &bFlags);
+ unpackLEWord(&pmsg, &wMsgLen);
+
+ if (bMsgType == 0 && wMsgLen == 1)
+ {
+ NetLog_Server("User %u probably checks his ignore state.", dwUin);
+ }
+ else
+ {
+ handleMessageTypes(dwUin, time(NULL), dwTS1, dwTS2, 0, 0, bMsgType, bFlags, 0, wTLVLen - 8, wMsgLen, pmsg, FALSE);
+
+ NetLog_Server("TYPE4 message thru server from %d, message type %d", dwUin, bMsgType);
+ }
+ }
+ else
+ {
+ NetLog_Server("Ignoring spoofed TYPE4 message thru server from %d", dwUin);
+ }
+ }
+ else
+ {
+ NetLog_Server("Unsupported TLV in Type 4 message (%u)", wTLVType);
+ }
+
+ SAFE_FREE(&pDataBuf);
+ icq_SetUserStatus(dwUin,0,24);
+}
+
+
+
+//
+// Helper functions
+//
+
+int TypeGUIDToTypeId(DWORD dwGuid1, DWORD dwGuid2, DWORD dwGuid3, DWORD dwGuid4, WORD wType)
+{
+ int nTypeID = MTYPE_UNKNOWN;
+
+ if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_STATUSMSGEXT))
+ {
+ nTypeID = MTYPE_STATUSMSGEXT;
+ }
+ else if (wType==MGTYPE_STANDARD_SEND)
+ {
+ if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_WEBURL))
+ {
+ nTypeID = MTYPE_URL;
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_CONTACTS))
+ {
+ nTypeID = MTYPE_CONTACTS;
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_CHAT))
+ {
+ nTypeID = MTYPE_CHAT;
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_FILE))
+ {
+ nTypeID = MTYPE_FILEREQ;
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_GREETING_CARD))
+ {
+ nTypeID = MTYPE_GREETINGCARD;
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_MESSAGE))
+ {
+ nTypeID = MTYPE_MESSAGE;
+ }
+ }
+ else if (wType==MGTYPE_CONTACTS_REQUEST)
+ {
+ if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_CONTACTS))
+ {
+ nTypeID = MTYPE_REQUESTCONTACTS;
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_XTRAZ_SCRIPT))
+ {
+ nTypeID = MTYPE_SCRIPT_DATA;
+ }
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_XTRAZ_SCRIPT))
+ {
+ if (wType==MGTYPE_SCRIPT_INVITATION)
+ {
+ nTypeID = MTYPE_SCRIPT_INVITATION;
+ }
+ else if (wType==MGTYPE_SCRIPT_NOTIFY)
+ {
+ nTypeID = MTYPE_SCRIPT_NOTIFY;
+ }
+ }
+
+ return nTypeID;
+}
+
+
+
+int getPluginTypeIdLen(int nTypeID)
+{
+ switch (nTypeID)
+ {
+ case MTYPE_SCRIPT_NOTIFY:
+ return 0x51;
+
+ case MTYPE_FILEREQ:
+ return 0x2B;
+
+ default:
+ return 0;
+ }
+}
+
+
+
+void packPluginTypeId(icq_packet *packet, int nTypeID)
+{
+ switch (nTypeID)
+ {
+ case MTYPE_SCRIPT_NOTIFY:
+ packLEWord(packet, 0x04f); // Length
+
+ packGUID(packet, MGTYPE_XTRAZ_SCRIPT); // Message Type GUID
+ packLEWord(packet, MGTYPE_SCRIPT_NOTIFY); // Function ID
+ packLEDWord(packet, 0x002a); // Request type string
+ packBuffer(packet, "Script Plug-in: Remote Notification Arrive", 0x002a);
+
+ packDWord(packet, 0x00000100); // Unknown binary stuff
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packWord(packet, 0x0000);
+ packByte(packet, 0x00);
+
+ break;
+
+ case MTYPE_FILEREQ:
+ packLEWord(packet, 0x029); // Length
+
+ packGUID(packet, MGTYPE_FILE); // Message Type GUID
+ packWord(packet, 0x0000); // Unknown
+ packLEDWord(packet, 0x0004); // Request type string
+ packBuffer(packet, "File", 0x0004);
+
+ packDWord(packet, 0x00000100); // More unknown binary stuff
+ packDWord(packet, 0x00010000);
+ packDWord(packet, 0x00000000);
+ packWord(packet, 0x0000);
+ packByte(packet, 0x00);
+
+ break;
+
+ default:
+ return;
+ }
+}
+
+
+
+static void handleSmsReceipt(unsigned char *buf, DWORD dwDataLen)
+{
+ DWORD dwLen;
+ DWORD dwTextLen;
+ char* szInfo;
+
+
+ if (dwDataLen < 36)
+ return;
+
+ buf += 20; // Unknown byte sequence
+ dwDataLen -= 20;
+
+ unpackLEDWord(&buf, &dwLen); // Length of message description
+ dwDataLen -= 4;
+ if (dwLen > dwDataLen)
+ {
+ NetLog_Server("SMS failed syntax check %d (%d, %d)", 1, dwDataLen, dwLen);
+ return;
+ }
+ buf += dwLen; // Skip message description (usually "ICQSMS\0")
+ dwDataLen -= dwLen;
+
+ // Unknown (0,0,0)
+ buf += 3;
+ dwDataLen -= 3;
+
+ // Remaining bytes
+ unpackLEDWord(&buf, &dwLen);
+ dwDataLen -= 4;
+ if (dwLen > dwDataLen)
+ {
+ NetLog_Server("SMS failed syntax check %d (%d, %d)", 2, dwDataLen, dwLen);
+ return;
+ }
+
+ // Length of message
+ unpackLEDWord(&buf, &dwTextLen);
+ dwDataLen -= 4;
+ if ((dwTextLen > dwDataLen) || (dwTextLen+4 != dwLen))
+ {
+ NetLog_Server("SMS failed syntax check %d (%d, %d, %d)", 3, dwDataLen, dwLen, dwTextLen);
+ return;
+ }
+
+ // Unpack message
+ szInfo = (char *)_alloca(dwTextLen + 1);
+ memcpy(szInfo, buf, dwTextLen);
+ szInfo[dwTextLen] = 0;
+
+ ICQBroadcastAck(NULL, ICQACKTYPE_SMS, ACKRESULT_SUCCESS, NULL, (LPARAM)szInfo);
+}
+
+
+
+static void handleStatusMsgReply(const char* szPrefix, HANDLE hContact, DWORD dwUin, WORD wVersion, int bMsgType, WORD wCookie, const char* szMsg)
+{
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ int status;
+ char* pszMsg;
+
+
+ if (hContact == INVALID_HANDLE_VALUE)
+ {
+ NetLog_Server("%sIgnoring status message from unknown contact %u", szPrefix, dwUin);
+ return;
+ }
+
+ status = AwayMsgTypeToStatus(bMsgType);
+ if (status == ID_STATUS_OFFLINE)
+ {
+ NetLog_Server("%sIgnoring unknown status message from %u", szPrefix, dwUin);
+ return;
+ }
+
+ pszMsg = null_strdup((char*)szMsg);
+
+ if (wVersion == 9)
+ { // it is probably UTF-8 status reply
+ pszMsg = detect_decode_utf8(pszMsg);
+ }
+
+ ccs.szProtoService = PSR_AWAYMSG;
+ ccs.hContact = hContact;
+ ccs.wParam = status;
+ ccs.lParam = (LPARAM)⪯
+ pre.flags = 0;
+ pre.szMessage = pszMsg;
+ pre.timestamp = time(NULL);
+ pre.lParam = wCookie;
+
+ CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
+
+ SAFE_FREE(&pszMsg);
+}
+
+
+
+static HANDLE handleMessageAck(DWORD dwUin, WORD wCookie, WORD wVersion, int type, WORD wMsgLen, PBYTE buf, BYTE bFlags)
+{
+ if (bFlags == 3)
+ {
+ HANDLE hContact;
+ DWORD dwCookieUin;
+ message_cookie_data* pCookieData = NULL;
+
+ hContact = HContactFromUIN(dwUin, NULL);
+
+
+ // Added by BM
+ icq_SetUserStatus(dwUin,0,2);
+
+ if (!FindCookie(wCookie, &dwCookieUin, &pCookieData))
+ {
+ NetLog_Server("Ignoring unrequested status message from %u", "handleMessageAck: ", dwUin);
+
+ ReleaseCookie(wCookie);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (dwUin != dwCookieUin)
+ {
+ NetLog_Server("%sAck UIN does not match Cookie UIN(%u != %u)", "handleMessageAck: ", dwUin, dwCookieUin);
+
+ ReleaseCookie(wCookie);
+ return INVALID_HANDLE_VALUE;
+ }
+ ReleaseCookie(wCookie);
+
+ handleStatusMsgReply("handleMessageAck: ", hContact, dwUin, wVersion, type, wCookie, (char*)buf);
+ }
+ else
+ {
+ // Should not happen
+ NetLog_Server("%sIgnored type %u ack message (this should not happen)", "handleMessageAck: ", type);
+ }
+
+ return INVALID_HANDLE_VALUE;
+}
+
+
+
+/* this function also processes direct packets, so it should be bulletproof */
+/* pMsg points to the beginning of the message */
+void handleMessageTypes(DWORD dwUin, DWORD dwTimestamp, DWORD dwMsgID, DWORD dwMsgID2, WORD wCookie, WORD wVersion, int type, int flags, WORD wAckType, DWORD dwDataLen, WORD wMsgLen, char *pMsg, BOOL bThruDC)
+{
+ char* szMsg;
+ char* pszMsgField[2*MAX_CONTACTSSEND+1];
+ char* pszMsg;
+ int nMsgFields;
+ HANDLE hContact = INVALID_HANDLE_VALUE;
+ int bAdded;
+
+
+ if (dwDataLen < wMsgLen)
+ {
+ NetLog_Uni(bThruDC, "Ignoring overflowed message");
+ return;
+ }
+
+ if (wAckType == 2)
+ {
+ handleMessageAck(dwUin, wCookie, wVersion, type, wMsgLen, pMsg, (BYTE)flags);
+ return;
+ }
+
+ szMsg = (char *)SAFE_MALLOC(wMsgLen + 1);
+ if (wMsgLen > 0)
+ {
+ memcpy(szMsg, pMsg, wMsgLen);
+ pMsg += wMsgLen;
+ dwDataLen -= wMsgLen;
+ }
+ szMsg[wMsgLen] = '\0';
+
+
+ pszMsgField[0] = szMsg;
+ nMsgFields = 0;
+ if (type == MTYPE_URL || type == MTYPE_AUTHREQ || type == MTYPE_ADDED || type == MTYPE_CONTACTS || type == MTYPE_EEXPRESS || type == MTYPE_WWP)
+ {
+ for (pszMsg=szMsg, nMsgFields=1; *pszMsg; pszMsg++)
+ {
+ if ((unsigned char)*pszMsg == 0xFE)
+ {
+ *pszMsg = '\0';
+ pszMsgField[nMsgFields++] = pszMsg + 1;
+ if (nMsgFields >= sizeof(pszMsgField)/sizeof(pszMsgField[0]))
+ break;
+ }
+ }
+ }
+
+
+ switch (type)
+ {
+
+ case MTYPE_PLAIN: /* plain message */
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+
+ pre.flags = 0;
+
+ // Check if this message is marked as UTF8 encoded
+ if (dwDataLen > 12)
+ {
+ DWORD dwGuidLen;
+
+ wchar_t* usMsg;
+ wchar_t* usMsgW;
+
+ if (bThruDC)
+ {
+ DWORD dwExtraLen = *(DWORD*)pMsg;
+
+ if (dwExtraLen < dwDataLen && !strncmp(szMsg, "{\\rtf", 5))
+ { // it is icq5 sending us crap, get real message from it
+ int nStrSize;
+
+ usMsg = (wchar_t*)(pMsg + 4);
+ nStrSize = WideCharToMultiByte(CP_ACP, 0, usMsg, dwExtraLen, szMsg, 0, NULL, NULL);
+ SAFE_FREE(&szMsg);
+ szMsg = (char*)SAFE_MALLOC((nStrSize+1)*(sizeof(wchar_t)+1));
+ WideCharToMultiByte(CP_ACP, 0, usMsg, dwExtraLen, szMsg, nStrSize, NULL, NULL);
+ nStrSize = strlennull(szMsg); // this is necessary, sometimes it was bad
+ memcpy(szMsg+nStrSize+1, usMsg, dwExtraLen*sizeof(wchar_t));
+
+ pre.flags = PREF_UNICODE;
+
+ dwGuidLen = 0;
+ }
+ }
+
+ if (!pre.flags)
+ {
+ dwGuidLen = *(DWORD*)(pMsg+8);
+ dwDataLen -= 12;
+ pMsg += 12;
+ }
+
+ while ((dwGuidLen >= 38) && (dwDataLen >= dwGuidLen))
+ {
+ if (!strncmp(pMsg, CAP_UTF8MSGS, 38))
+ { // Found UTF8 cap, convert message to ansi
+ char *szAnsiMessage = NULL;
+
+ if (utf8_decode(szMsg, &szAnsiMessage))
+ {
+ if (!strcmpnull(szMsg, szAnsiMessage))
+ {
+ SAFE_FREE(&szMsg);
+ szMsg = szAnsiMessage;
+ }
+ else
+ {
+ int nMsgLen = strlennull(szAnsiMessage) + 1;
+ int nMsgWLen;
+
+ usMsg = SAFE_MALLOC((nMsgLen)*(sizeof(wchar_t) + 1));
+ memcpy((char*)usMsg, szAnsiMessage, nMsgLen);
+ usMsgW = make_unicode_string(szMsg);
+ nMsgWLen = wcslen(usMsgW);
+ memcpy((char*)usMsg + nMsgLen, (char*)usMsgW, ((nMsgWLen>nMsgLen)?nMsgLen:nMsgWLen)*sizeof(wchar_t));
+ SAFE_FREE(&usMsgW);
+ SAFE_FREE(&szAnsiMessage);
+ SAFE_FREE(&szMsg);
+ szMsg = (char*)usMsg;
+ pre.flags = PREF_UNICODE;
+ }
+ }
+ else
+ {
+ NetLog_Uni(bThruDC, "Failed to translate UTF-8 message.");
+ }
+ break;
+ }
+ else if (!strncmp(pMsg, CAP_RTFMSGS, 38))
+ { // Found RichText cap
+ NetLog_Uni(bThruDC, "Warning: User %u sends us RichText.", dwUin);
+ break;
+ }
+
+ dwGuidLen -= 38;
+ dwDataLen -= 38;
+ pMsg += 38;
+ }
+ }
+
+ hContact = HContactFromUIN(dwUin, &bAdded);
+
+ if (!pre.flags && !IsUSASCII(szMsg, strlennull(szMsg)))
+ { // message is Ansi and contains national characters, create Unicode part by codepage
+ char* usMsg = convertMsgToUserSpecificUtf(hContact, szMsg);
+
+ if (usMsg)
+ {
+ SAFE_FREE(&szMsg);
+ szMsg = (char*)usMsg;
+ pre.flags = PREF_UNICODE;
+ }
+ }
+
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.timestamp = dwTimestamp;
+ pre.szMessage = (char *)szMsg;
+ pre.lParam = 0;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+ break;
+
+ case MTYPE_URL:
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ char* szBlob;
+
+
+ if (nMsgFields < 2)
+ {
+ NetLog_Uni(bThruDC, "Malformed '%s' message", "URL");
+ break;
+ }
+
+ szBlob = (char *)_alloca(strlennull(pszMsgField[0]) + strlennull(pszMsgField[1]) + 2);
+ strcpy(szBlob, pszMsgField[1]);
+ strcpy(szBlob + strlennull(szBlob) + 1, pszMsgField[0]);
+
+ ccs.szProtoService = PSR_URL;
+ ccs.hContact = hContact = HContactFromUIN(dwUin, &bAdded);
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.flags = 0;
+ pre.timestamp = dwTimestamp;
+ pre.szMessage = (char *)szBlob;
+ pre.lParam = 0;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+ break;
+
+ case MTYPE_AUTHREQ: /* auth request */
+ /* format: nick FE first FE last FE email FE unk-char FE msg 00 */
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ char* szBlob;
+ char* pCurBlob;
+
+
+ if (nMsgFields < 6)
+ {
+ NetLog_Server("Malformed '%s' message", "auth req");
+ break;
+ }
+
+ ccs.szProtoService=PSR_AUTH;
+ ccs.hContact=hContact=HContactFromUIN(dwUin, &bAdded);
+ ccs.wParam=0;
+ ccs.lParam=(LPARAM)⪯
+ pre.flags=0;
+ pre.timestamp=dwTimestamp;
+ pre.lParam=sizeof(DWORD)+sizeof(HANDLE)+strlennull(pszMsgField[0])+strlennull(pszMsgField[1])+strlennull(pszMsgField[2])+strlennull(pszMsgField[3])+strlennull(pszMsgField[5])+5;
+
+ /*blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ), reason(ASCIIZ)*/
+ pCurBlob=szBlob=(char *)_alloca(pre.lParam);
+ memcpy(pCurBlob,&dwUin,sizeof(DWORD)); pCurBlob+=sizeof(DWORD);
+ memcpy(pCurBlob,&hContact,sizeof(HANDLE)); pCurBlob+=sizeof(HANDLE);
+ strcpy((char *)pCurBlob,pszMsgField[0]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[1]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[2]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[3]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[5]);
+ pre.szMessage=(char *)szBlob;
+
+ CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
+ }
+ break;
+
+ case MTYPE_ADDED: /* 'you were added' */
+ /* format: nick FE first FE last FE email 00 */
+ {
+ DBEVENTINFO dbei;
+ PBYTE pCurBlob;
+
+ if (nMsgFields < 4)
+ {
+ NetLog_Server("Malformed '%s' message", "you were added");
+ break;
+ }
+
+ hContact = HContactFromUIN(dwUin, &bAdded);
+
+ /*blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ) */
+ ZeroMemory(&dbei,sizeof(dbei));
+ dbei.cbSize=sizeof(dbei);
+ dbei.szModule=gpszICQProtoName;
+ dbei.timestamp=dwTimestamp;
+ dbei.flags=0;
+ dbei.eventType=EVENTTYPE_ADDED;
+ dbei.cbBlob=sizeof(DWORD)+sizeof(HANDLE)+strlennull(pszMsgField[0])+strlennull(pszMsgField[1])+strlennull(pszMsgField[2])+strlennull(pszMsgField[3])+4;
+ pCurBlob=dbei.pBlob=(PBYTE)_alloca(dbei.cbBlob);
+ memcpy(pCurBlob,&dwUin,sizeof(DWORD)); pCurBlob+=sizeof(DWORD);
+ memcpy(pCurBlob,&hContact,sizeof(HANDLE)); pCurBlob+=sizeof(HANDLE);
+ strcpy((char *)pCurBlob,pszMsgField[0]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[1]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[2]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[3]);
+
+ CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&dbei);
+ }
+ break;
+
+ case MTYPE_CONTACTS:
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ ICQSEARCHRESULT** isrList;
+ char* pszNContactsEnd;
+ int nContacts;
+ int i;
+ int valid;
+
+
+ if (nMsgFields < 3
+ || (nContacts = strtol(pszMsgField[0], &pszNContactsEnd, 10)) == 0
+ || pszNContactsEnd - pszMsgField[0] != (int)strlennull(pszMsgField[0])
+ || nMsgFields < nContacts * 2 + 1)
+ {
+ NetLog_Uni(bThruDC, "Malformed '%s' message", "contacts");
+ break;
+ }
+
+ valid = 1;
+ isrList = (ICQSEARCHRESULT**)_alloca(nContacts * sizeof(ICQSEARCHRESULT*));
+ for (i = 0; i < nContacts; i++)
+ {
+ isrList[i] = (ICQSEARCHRESULT*)SAFE_MALLOC(sizeof(ICQSEARCHRESULT));
+ isrList[i]->hdr.cbSize = sizeof(ICQSEARCHRESULT);
+ if (IsStringUIN(pszMsgField[1 + i * 2]))
+ { // icq contact
+ isrList[i]->uin = atoi(pszMsgField[1 + i * 2]);
+ if (isrList[i]->uin == 0)
+ valid = 0;
+ }
+ else
+ { // aim contact
+ isrList[i]->uid = pszMsgField[1 + i * 2];
+ if (!strlennull(isrList[i]->uid))
+ valid = 0;
+ }
+ isrList[i]->hdr.nick = pszMsgField[2 + i * 2];
+ }
+
+ if (!valid)
+ {
+ NetLog_Uni(bThruDC, "Malformed '%s' message", "contacts");
+ }
+ else
+ {
+ ccs.szProtoService = PSR_CONTACTS;
+ ccs.hContact = hContact = HContactFromUIN(dwUin, &bAdded);
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.flags = 0;
+ pre.timestamp = dwTimestamp;
+ pre.szMessage = (char *)isrList;
+ pre.lParam = nContacts;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+
+ for (i = 0; i < nContacts; i++)
+ SAFE_FREE(&isrList[i]);
+ }
+ break;
+
+ case MTYPE_PLUGIN:
+ hContact = NULL;
+
+ switch(dwUin)
+ {
+ case 1002: /* SMS receipt */
+ handleSmsReceipt(pMsg, dwDataLen);
+ break;
+
+ case 1111: /* icqmail 'you've got mail' - not processed */
+ break;
+ }
+ break;
+
+ case MTYPE_WWP:
+ /* format: fromname FE FE FE fromemail FE unknownbyte FE 'Sender IP: xxx.xxx.xxx.xxx' 0D 0A body */
+ {
+ DBEVENTINFO dbei;
+ PBYTE pCurBlob;
+
+
+ if (nMsgFields < 6)
+ {
+ NetLog_Server("Malformed '%s' message", "web pager");
+ break;
+ }
+
+ /*blob is: body(ASCIIZ), name(ASCIIZ), email(ASCIIZ) */
+ ZeroMemory(&dbei,sizeof(dbei));
+ dbei.cbSize=sizeof(dbei);
+ dbei.szModule=gpszICQProtoName;
+ dbei.timestamp=dwTimestamp;
+ dbei.flags=0;
+ dbei.eventType=ICQEVENTTYPE_WEBPAGER;
+ dbei.cbBlob=strlennull(pszMsgField[0])+strlennull(pszMsgField[3])+strlennull(pszMsgField[5])+3;
+ pCurBlob=dbei.pBlob=(PBYTE)_alloca(dbei.cbBlob);
+ strcpy((char *)pCurBlob,pszMsgField[5]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[0]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[3]);
+
+ CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&dbei);
+ }
+ break;
+
+ case MTYPE_EEXPRESS:
+ /* format: fromname FE FE FE fromemail FE unknownbyte FE body */
+ {
+ DBEVENTINFO dbei;
+ PBYTE pCurBlob;
+
+
+ if (nMsgFields < 6)
+ {
+ NetLog_Server("Malformed '%s' message", "e-mail express");
+ break;
+ }
+
+ /*blob is: body(ASCIIZ), name(ASCIIZ), email(ASCIIZ) */
+ ZeroMemory(&dbei,sizeof(dbei));
+ dbei.cbSize=sizeof(dbei);
+ dbei.szModule=gpszICQProtoName;
+ dbei.timestamp=dwTimestamp;
+ dbei.flags=0;
+ dbei.eventType=ICQEVENTTYPE_EMAILEXPRESS;
+ dbei.cbBlob=strlennull(pszMsgField[0])+strlennull(pszMsgField[3])+strlennull(pszMsgField[5])+3;
+ pCurBlob=dbei.pBlob=(PBYTE)_alloca(dbei.cbBlob);
+ strcpy((char *)pCurBlob,pszMsgField[5]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[0]); pCurBlob+=strlennull((char *)pCurBlob)+1;
+ strcpy((char *)pCurBlob,pszMsgField[3]);
+
+ CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&dbei);
+ }
+ break;
+
+ case MTYPE_REQUESTCONTACTS:
+ /* it's a contacts-request */
+ NetLog_Uni(bThruDC, "Received %s from %u", "Request for Contacts", dwUin);
+ break;
+
+ case MTYPE_GREETINGCARD:
+ /* it's a greeting card */
+ NetLog_Uni(bThruDC, "Received %s from %u", "Greeting Card", dwUin);
+ break;
+
+ case MTYPE_SCRIPT_NOTIFY:
+ /* it's a xtraz notify request */
+ NetLog_Uni(bThruDC, "Received %s from %u", "Xtraz Notify Request", dwUin);
+ handleXtrazNotify(dwUin, dwMsgID, dwMsgID2, wCookie, szMsg, wMsgLen, bThruDC);
+ break;
+
+ case MTYPE_SCRIPT_INVITATION:
+ /* it's a xtraz invitation to session */
+ NetLog_Uni(bThruDC, "Received %s from %u", "Xtraz Invitation", dwUin);
+ handleXtrazInvitation(dwUin, dwMsgID, dwMsgID2, wCookie, szMsg, wMsgLen, bThruDC);
+ break;
+
+ case MTYPE_SCRIPT_DATA:
+ /* it's a xtraz data packet */
+ NetLog_Uni(bThruDC, "Received %s from %u", "Xtraz data packet", dwUin);
+ handleXtrazData(dwUin, dwMsgID, dwMsgID2, wCookie, szMsg, wMsgLen, bThruDC);
+ break;
+
+ case MTYPE_AUTOAWAY:
+ case MTYPE_AUTOBUSY:
+ case MTYPE_AUTONA:
+ case MTYPE_AUTODND:
+ case MTYPE_AUTOFFC:
+ {
+ char** szMsg = MirandaStatusToAwayMsg(AwayMsgTypeToStatus(type));
+
+ if (szMsg)
+ {
+ rate_record rr = {0};
+
+ rr.bType = RIT_AWAYMSG_RESPONSE;
+ rr.dwUin = dwUin;
+ rr.dwMid1 = dwMsgID;
+ rr.dwMid2 = dwMsgID2;
+ rr.wCookie = wCookie;
+ rr.wVersion = wVersion;
+ rr.msgType = type;
+ rr.rate_group = 0x102;
+ if (!handleRateItem(&rr, TRUE))
+ icq_sendAwayMsgReplyServ(dwUin, dwMsgID, dwMsgID2, wCookie, wVersion, (BYTE)type, szMsg);
+ }
+
+ break;
+ }
+
+ case MTYPE_FILEREQ: // Never happens
+ default:
+ if(wMsgLen == 0) {
+ int iAdded;
+ hContact = HContactFromUIN(dwUin, &iAdded);
+ ShowPopUpMsg(hContact, NickFromHandleUtf(hContact), ICQTranslateUtf("... is checking your ignore list"), LOG_NOTE);
+ }
+ NetLog_Uni(bThruDC, "Unprocessed message type %d", type);
+ break;
+
+ }
+
+ SAFE_FREE(&szMsg);
+}
+
+
+
+static void handleRecvMsgResponse(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{
+ DWORD dwUin;
+ DWORD dwCookie;
+ WORD wMessageFormat;
+ WORD wStatus;
+ WORD bMsgType = 0;
+ BYTE bFlags;
+ WORD wLength;
+ HANDLE hContact;
+ DWORD dwCookieUin;
+ DWORD dwMsgID1, dwMsgID2;
+ WORD wVersion = 0;
+ message_cookie_data* pCookieData = NULL;
+
+
+ unpackLEDWord(&buf, &dwMsgID1); // Message ID
+ unpackLEDWord(&buf, &dwMsgID2);
+ wLen -= 8;
+
+ unpackWord(&buf, &wMessageFormat);
+ wLen -= 2;
+ if (wMessageFormat != 2)
+ {
+ NetLog_Server("SNAC(4.B) Unknown type");
+ return;
+ }
+
+ if (!unpackUID(&buf, &wLen, &dwUin, NULL)) return;
+
+ hContact = HContactFromUIN(dwUin, NULL);
+
+ buf += 2; // 3. unknown
+ wLen -= 2;
+
+ if (!FindMessageCookie(dwMsgID1, dwMsgID2, &dwCookie, &dwCookieUin, &pCookieData))
+ {
+ icq_SetUserStatus(dwUin, 0, 2);
+ NetLog_Server("SNAC(4.B) Received an ack that I did not ask for from (%u)", dwUin);
+ return;
+ }
+
+ // Length of sub chunk?
+ if (wLen >= 2)
+ {
+ unpackLEWord(&buf, &wLength);
+ wLen -= 2;
+ }
+ else
+ wLength = 0;
+
+ if (wLength == 0x1b && pCookieData->bMessageType != MTYPE_REVERSE_REQUEST)
+ { // this can be v8 greeting message reply
+ WORD wCookie;
+
+ unpackLEWord(&buf, &wVersion);
+ buf += 27; /* unknowns from the msg we sent */
+ wLen -= 29;
+
+ // Message sequence (SEQ2)
+ unpackLEWord(&buf, &wCookie);
+ wLen -= 2;
+
+ // Unknown (12 bytes)
+ buf += 12;
+ wLen -= 12;
+
+ // Message type
+ unpackByte(&buf, (BYTE*)&bMsgType);
+ unpackByte(&buf, &bFlags);
+ wLen -= 2;
+
+ // Status
+ unpackLEWord(&buf, &wStatus);
+ wLen -= 2;
+
+ // Priority?
+ buf += 2;
+ wLen -= 2;
+
+ dwCookie = wCookie;
+
+ if (!FindCookie(dwCookie, &dwCookieUin, &pCookieData))
+ { // use old reliable method
+ NetLog_Server("Warning: Invalid cookie in %s from (%u)", "message response", dwUin);
+ }
+ }
+ else
+ {
+ bMsgType = pCookieData->bMessageType;
+ bFlags = 0;
+ }
+
+ if (dwCookieUin != dwUin)
+ {
+ NetLog_Server("SNAC(4.B) Ack UIN does not match Cookie UIN(%u != %u)", dwUin, dwCookieUin);
+
+ ReleaseCookie(dwCookie); // This could be a bad idea, but I think it is safe
+ return;
+ }
+
+ if (bFlags == 3) // A status message reply
+ {
+ // Added by BM
+ icq_SetUserStatus(dwUin,0,2);
+
+ handleStatusMsgReply("SNAC(4.B) ", hContact, dwUin, wVersion, bMsgType, (WORD)dwCookie, (char*)(buf + 2));
+ }
+ else
+ { // An ack of some kind
+ int ackType;
+
+
+ if (hContact == NULL || hContact == INVALID_HANDLE_VALUE)
+ {
+ NetLog_Server("SNAC(4.B) Message from unknown contact (%u)", dwUin);
+
+ ReleaseCookie(dwCookie); // This could be a bad idea, but I think it is safe
+ return;
+ }
+
+ switch (bMsgType)
+ {
+
+ case MTYPE_FILEREQ:
+ {
+ char* szMsg;
+ WORD wMsgLen;
+
+ // Message length
+ unpackLEWord(&buf, &wMsgLen);
+ wLen -= 2;
+ szMsg = (char *)_alloca(wMsgLen + 1);
+ szMsg[wMsgLen] = '\0';
+ if (wMsgLen > 0)
+ {
+ memcpy(szMsg, buf, wMsgLen);
+ buf += wMsgLen;
+ wLen -= wMsgLen;
+ }
+ handleFileAck(buf, wLen, dwUin, dwCookie, wStatus, szMsg);
+ // No success protoack will be sent here, since all file requests
+ // will have been 'sent' when the server returns its ack
+ return;
+ }
+
+ case MTYPE_PLUGIN:
+ {
+ DWORD dwLengthToEnd;
+ DWORD dwDataLen;
+ DWORD dwPluginNameLen;
+ int typeId;
+ WORD wInfoLen;
+ char* szPluginName;
+ DWORD q1,q2,q3,q4;
+ WORD qt;
+
+ if (wLength != 0x1B)
+ {
+ NetLog_Server("Invalid Greeting %s", "message response");
+
+ ReleaseCookie(dwCookie);
+ return;
+ }
+
+ NetLog_Server("Parsing Greeting %s", "message response");
+
+ // Message
+ unpackLEWord(&buf, &wInfoLen);
+ wLen -= 2;
+ buf += wInfoLen;
+ wLen -= wInfoLen;
+
+ // This packet is malformed. Possibly a file accept from Miranda IM 0.1.2.1
+ if (wLen < 20) return;
+
+ unpackLEWord(&buf, &wInfoLen);
+
+ unpackDWord(&buf, &q1); // get data GUID & function id
+ unpackDWord(&buf, &q2);
+ unpackDWord(&buf, &q3);
+ unpackDWord(&buf, &q4);
+ unpackLEWord(&buf, &qt);
+ wLen -= 20;
+
+ unpackLEDWord(&buf, &dwPluginNameLen);
+ wLen -= 4;
+ if (dwPluginNameLen > wLen)
+ { // check for malformed plugin name
+ dwPluginNameLen = wLen;
+ NetLog_Server("Warning: malformed size of plugin name.");
+ }
+ szPluginName = (char *)_alloca(dwPluginNameLen + 1);
+ memcpy(szPluginName, buf, dwPluginNameLen);
+ szPluginName[dwPluginNameLen] = '\0';
+
+ buf += dwPluginNameLen + 15;
+ if (dwPluginNameLen == wLen)
+ wLen = 0;
+ else
+ wLen -= ((WORD)dwPluginNameLen + 15);
+
+ typeId = TypeGUIDToTypeId(q1, q2, q3, q4, qt);
+ if (!typeId)
+ NetLog_Server("Error: Unknown type {%04x%04x%04x%04x-%02x}: %s", q1,q2,q3,q4,qt,szPluginName);
+
+ if (wLen < 4)
+ {
+ NetLog_Server("Error: Invalid greeting %s", "message response");
+
+ ReleaseCookie(dwCookie);
+ return;
+ }
+
+ // Length of remaining data
+ unpackLEDWord(&buf, &dwLengthToEnd);
+ wLen -= 4;
+
+ if (wLen >= 4 && dwLengthToEnd > 0)
+ unpackLEDWord(&buf, &dwDataLen); // Length of message
+ else
+ dwDataLen = 0;
+
+
+ switch (typeId)
+ {
+
+ case MTYPE_URL:
+ ackType = ACKTYPE_URL;
+ break;
+
+ case MTYPE_CONTACTS:
+ ackType = ACKTYPE_CONTACTS;
+ break;
+
+ case MTYPE_FILEREQ:
+ {
+ char* szMsg;
+
+ NetLog_Server("This is file ack");
+ szMsg = (char *)_alloca(dwDataLen + 1);
+ if (dwDataLen > 0)
+ memcpy(szMsg, buf, dwDataLen);
+ szMsg[dwDataLen] = '\0';
+ buf += dwDataLen;
+ wLen -= (WORD)dwDataLen;
+
+ handleFileAck(buf, wLen, dwUin, dwCookie, wStatus, szMsg);
+ // No success protoack will be sent here, since all file requests
+ // will have been 'sent' when the server returns its ack
+ }
+ return;
+
+ case MTYPE_SCRIPT_NOTIFY:
+ {
+ char *szMsg;
+
+ szMsg = (char*)_alloca(dwDataLen + 1);
+ if (dwDataLen > 0)
+ memcpy(szMsg, buf, dwDataLen);
+ szMsg[dwDataLen] = '\0';
+
+ handleXtrazNotifyResponse(dwUin, hContact, (WORD)dwCookie, szMsg, dwDataLen);
+
+ ReleaseCookie(dwCookie);
+ }
+ return;
+
+ default:
+ NetLog_Server("Error: Unknown greeting %s, type \"%s\".", "message response", szPluginName);
+ return;
+ }
+ }
+ break;
+
+ case MTYPE_PLAIN:
+ ackType = ACKTYPE_MESSAGE;
+ break;
+
+ case MTYPE_URL:
+ ackType = ACKTYPE_URL;
+ break;
+
+ case MTYPE_AUTHOK:
+ case MTYPE_AUTHDENY:
+ ackType = ACKTYPE_AUTHREQ;
+ break;
+
+ case MTYPE_ADDED:
+ ackType = ACKTYPE_ADDED;
+ break;
+
+ case MTYPE_CONTACTS:
+ ackType = ACKTYPE_CONTACTS;
+ break;
+
+ case MTYPE_REVERSE_REQUEST:
+ {
+ reverse_cookie *pReverse = (reverse_cookie*)pCookieData;
+
+ if (pReverse->ft)
+ {
+ filetransfer *ft = (filetransfer*)pReverse->ft;
+
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ }
+ NetLog_Server("Reverse Connect request failed");
+ }
+ break;
+
+ case MTYPE_CHAT:
+ default:
+ NetLog_Server("SNAC(4.B) Unknown message type (%u) in switch", bMsgType);
+ return;
+ }
+
+ if (bMsgType != MTYPE_REVERSE_REQUEST && ((ackType == MTYPE_PLAIN && pCookieData && (pCookieData->nAckType == ACKTYPE_CLIENT)) ||
+ ackType != MTYPE_PLAIN))
+ {
+ ICQBroadcastAck(hContact, ackType, ACKRESULT_SUCCESS, (HANDLE)(WORD)dwCookie, 0);
+ }
+ }
+
+ ReleaseCookie(dwCookie);
+}
+
+
+// A response to a CLI_SENDMSG
+static void handleRecvServMsgError(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwSequence)
+{
+ WORD wError;
+ char* pszErrorMessage;
+ DWORD dwUin;
+ HANDLE hContact;
+ message_cookie_data* pCookieData = NULL;
+ int nMessageType;
+ BOOL isHidden;
+
+ if (wLen < 2)
+ return;
+
+ if (FindCookie((WORD)dwSequence, &dwUin, &pCookieData))
+ { // all packet cookies from msg family has command 0 in the queue
+ hContact = HContactFromUIN(dwUin, NULL);
+
+ // Error code
+ unpackWord(&buf, &wError);
+
+ if ((hContact == NULL) || (hContact == INVALID_HANDLE_VALUE))
+ {
+ NetLog_Server("SNAC(4.1) Received a SENDMSG Error (%u) from invalid contact %u", wError, dwUin);
+
+ ReleaseCookie((WORD)dwSequence);
+ return;
+ }
+ if (wError == 9 && pCookieData->bMessageType == MTYPE_AUTOAWAY)
+ { // we failed to request away message the normal way, try it AIM way
+ icq_packet packet;
+
+ serverPacketInit(&packet, (WORD)(13 + getUINLen(dwUin)));
+ packFNACHeaderFull(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, 0, (WORD)dwSequence);
+ packWord(&packet, 0x03);
+ packUIN(&packet, dwUin);
+
+ sendServPacket(&packet);
+
+ return;
+ }
+
+ isHidden = CheckContactCapabilities(hContact, WAS_FOUND);
+
+ // Not all of these are actually used in family 4
+ // This will be moved into a special error handling function later
+ switch (wError)
+ {
+
+ case 0x0002: // Server rate limit exceeded
+ pszErrorMessage = ICQTranslate("You are sending too fast. Wait a while and try again.\r\nSNAC(4.1) Error x02");
+ break;
+
+ case 0x0003: // Client rate limit exceeded
+ pszErrorMessage = ICQTranslate("You are sending too fast. Wait a while and try again.\r\nSNAC(4.1) Error x03");
+ break;
+
+ case 0x0004: // Recipient is not logged in (resend in a offline message)
+ if (isHidden || pCookieData->bMessageType == MTYPE_PLAIN) // TODO: this needs better solution
+ ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+ pszErrorMessage = ICQTranslate("The user has logged off. Select 'Retry' to send an offline message.\r\nSNAC(4.1) Error x04");
+ break;
+
+ case 0x0009: // Not supported by client (resend in a simpler format)
+ pszErrorMessage = ICQTranslate("The receiving client does not support this type of message.\r\nSNAC(4.1) Error x09");
+ makeUserOffline(hContact);
+ break;
+
+ case 0x000A: // Refused by client
+ pszErrorMessage = ICQTranslate("You sent too long message. The receiving client does not support it.\r\nSNAC(4.1) Error x0A");
+ break;
+
+ case 0x000E: // Incorrect SNAC format
+ pszErrorMessage = ICQTranslate("The SNAC format was rejected by the server.\nSNAC(4.1) Error x0E");
+ break;
+
+ case 0x0013: // User temporarily unavailable
+ pszErrorMessage = ICQTranslate("The user is temporarily unavailable. Wait a while and try again.\r\nSNAC(4.1) Error x13");
+ break;
+
+ case 0x0001: // Invalid SNAC header
+ case 0x0005: // Requested service unavailable
+ case 0x0006: // Requested service not defined
+ case 0x0007: // You sent obsolete SNAC
+ case 0x0008: // Not supported by server
+ case 0x000B: // Reply too big
+ case 0x000C: // Responses lost
+ case 0x000D: // Request denied
+ case 0x000F: // Insufficient rights
+ case 0x0010: // In local permit/deny (recipient blocked)
+ case 0x0011: // Sender too evil
+ case 0x0012: // Receiver too evil
+ case 0x0014: // No match
+ case 0x0015: // List overflow
+ case 0x0016: // Request ambiguous
+ case 0x0017: // Server queue full
+ case 0x0018: // Not while on AOL
+ default:
+ if (pszErrorMessage = _alloca(256))
+ null_snprintf(pszErrorMessage, 256, ICQTranslate("SNAC(4.1) SENDMSG Error (x%02x)"), wError);
+ break;
+ }
+
+
+ switch (pCookieData->bMessageType)
+ {
+
+ case MTYPE_PLAIN:
+ nMessageType = ACKTYPE_MESSAGE;
+ break;
+
+ case MTYPE_CHAT:
+ nMessageType = ACKTYPE_CHAT;
+ break;
+
+ case MTYPE_FILEREQ:
+ nMessageType = ACKTYPE_FILE;
+ break;
+
+ case MTYPE_URL:
+ nMessageType = ACKTYPE_URL;
+ break;
+
+ case MTYPE_CONTACTS:
+ nMessageType = ACKTYPE_CONTACTS;
+ break;
+
+ default:
+ nMessageType = -1;
+ break;
+ }
+
+ if (nMessageType != -1)
+ {
+ ICQBroadcastAck(hContact, nMessageType, ACKRESULT_FAILED, (HANDLE)(WORD)dwSequence, (LPARAM)pszErrorMessage);
+ }
+ else
+ {
+ NetLog_Server("Error: Message delivery to %u failed: %s", dwUin, pszErrorMessage);
+ }
+
+ FreeCookie((WORD)dwSequence);
+
+ if (pCookieData->bMessageType != MTYPE_FILEREQ)
+ SAFE_FREE(&pCookieData);
+ }
+ else
+ {
+ WORD wError;
+
+ unpackWord(&buf, &wError);
+ switch (wError)
+ {
+ case 0x0004: icq_SetUserStatus(0,(WORD)dwSequence,-4); break;
+ case 0x0009: icq_SetUserStatus(0,(WORD)dwSequence, 3); break;
+ case 0x000E: icq_SetUserStatus(0,(WORD)dwSequence, 4); break;
+ case 0x000C: icq_SetUserStatus(0,(WORD)dwSequence,-2); break;
+ default: LogFamilyError(ICQ_MSG_FAMILY, wError); break;
+ }}
+}
+
+
+
+static void handleServerAck(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwSequence)
+{
+ DWORD dwUin;
+ uid_str szUID;
+ WORD wChannel;
+ HANDLE hContact;
+ message_cookie_data* pCookieData;
+
+
+ if (wLen < 13)
+ {
+ NetLog_Server("Ignoring SNAC(4,C) Packet to short");
+ return;
+ }
+
+ buf += 8; // Skip first 8 bytes
+ wLen -= 8;
+
+ // Message channel
+ unpackWord(&buf, &wChannel);
+ wLen -= 2;
+
+ // Sender
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUID)) return;
+
+ hContact = HContactFromUID(dwUin, szUID, NULL);
+
+ if (FindCookie((WORD)dwSequence, &dwUin, &pCookieData))
+ {
+ // If the user requested a full ack, the
+ // server ack should be ignored here.
+ if (pCookieData && (pCookieData->nAckType == ACKTYPE_SERVER))
+ {
+ if ((hContact != NULL) && (hContact != INVALID_HANDLE_VALUE))
+ {
+ int ackType;
+ int ackRes = ACKRESULT_SUCCESS;
+
+ switch (pCookieData->bMessageType)
+ {
+ case MTYPE_PLAIN:
+ ackType = ACKTYPE_MESSAGE;
+ break;
+
+ case MTYPE_CONTACTS:
+ ackType = ACKTYPE_CONTACTS;
+ break;
+
+ case MTYPE_URL:
+ ackType = ACKTYPE_URL;
+ break;
+
+ case MTYPE_FILEREQ:
+ ackType = ACKTYPE_FILE;
+ ackRes = ACKRESULT_SENTREQUEST;
+ // Note 1: We are not allowed to free the cookie here because it
+ // contains the filetransfer struct that we will need later
+ // Note 2: The cookiedata is NOT a message_cookie_data*, it is a
+ // filetransfer*. IMPORTANT! (it's one of those silly things)
+ break;
+
+ default:
+ ackType = -1;
+ NetLog_Server("Error: Unknown message type %d in ack", pCookieData->bMessageType);
+ break;
+ }
+ if (ackType != -1)
+ ICQBroadcastAck(hContact, ackType, ackRes, (HANDLE)(WORD)dwSequence, 0);
+
+ if (pCookieData->bMessageType != MTYPE_FILEREQ)
+ SAFE_FREE(&pCookieData); // this could be a bad idea, but I think it is safe
+ }
+ FreeCookie((WORD)dwSequence);
+ }
+ else if (pCookieData && (pCookieData->nAckType == ACKTYPE_CLIENT))
+ {
+ NetLog_Server("Received a server ack, waiting for client ack.");
+ }
+ else
+ {
+ NetLog_Server("Ignored a server ack I did not ask for");
+ }
+ } //else
+ icq_SetUserStatus(0,(WORD)dwSequence, -1);
+
+ return;
+}
+
+
+
+static void handleMissedMsg(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{
+ DWORD dwUin;
+ WORD wChannel;
+ WORD wWarningLevel;
+ WORD wCount;
+ WORD wError;
+ WORD wTLVCount;
+ char* pszErrorMsg;
+ oscar_tlv_chain* pChain;
+
+
+ if (wLen < 14)
+ return; // Too short
+
+ // Message channel?
+ unpackWord(&buf, &wChannel);
+ wLen -= 2;
+
+ // Sender
+ if (!unpackUID(&buf, &wLen, &dwUin, NULL)) return;
+
+ if (wLen < 8)
+ return; // Too short
+
+ // Warning level?
+ unpackWord(&buf, &wWarningLevel);
+ wLen -= 2;
+
+ // TLV count
+ unpackWord(&buf, &wTLVCount);
+ wLen -= 2;
+
+ // Read past user info TLVs
+ pChain = readIntoTLVChain(&buf, (WORD)(wLen-4), wTLVCount);
+
+ if (pChain)
+ disposeChain(&pChain);
+
+ if (wLen < 4)
+ return; // Too short
+
+
+ // Number of missed messages
+ unpackWord(&buf, &wCount);
+ wLen -= 2;
+
+ // Error code
+ unpackWord(&buf, &wError);
+ wLen -= 2;
+
+ switch (wError)
+ {
+
+ case 0:
+ pszErrorMsg = ICQTranslate("** This message was blocked by the ICQ server ** The message was invalid.");
+ break;
+
+ case 1:
+ pszErrorMsg = ICQTranslate("** This message was blocked by the ICQ server ** The message was too long.");
+ break;
+
+ case 2:
+ pszErrorMsg = ICQTranslate("** This message was blocked by the ICQ server ** The sender has flooded the server.");
+ break;
+
+ case 4:
+ pszErrorMsg = ICQTranslate("** This message was blocked by the ICQ server ** You are too evil.");
+ break;
+
+ default:
+ // 3 = Sender too evil (sender warn level > your max_msg_sevil)
+ return;
+ break;
+ }
+
+
+ // Create message to notify user
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ int bAdded;
+
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = HContactFromUIN(dwUin, &bAdded);
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.flags = 0;
+ pre.timestamp = time(NULL);
+ pre.szMessage = pszErrorMsg;
+ pre.lParam = 0;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+}
+
+
+
+static void handleTypingNotification(unsigned char* buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{
+ DWORD dwUin;
+ uid_str szUID;
+ WORD wChannel;
+ WORD wNotification;
+ HANDLE hContact;
+
+ if (wLen < 14)
+ {
+ NetLog_Server("Ignoring SNAC(4.x11) Packet to short");
+ return;
+ }
+
+#ifndef DBG_CAPMTN
+ {
+ NetLog_Server("Ignoring unexpected typing notification");
+ return;
+ }
+#endif
+
+ // The message ID, unused?
+ buf += 8;
+ wLen -= 8;
+
+ // Message channel, unused?
+ unpackWord(&buf, &wChannel);
+ wLen -= 2;
+
+ // Sender
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUID)) return;
+
+ hContact = HContactFromUID(dwUin, szUID, NULL);
+
+ if (hContact == INVALID_HANDLE_VALUE) return;
+
+ // Typing notification code
+ unpackWord(&buf, &wNotification);
+ wLen -= 2;
+
+ icq_SetUserStatus(dwUin,0,25);
+ SetContactCapabilities(hContact, CAPF_TYPING);
+
+ // Notify user
+ switch (wNotification)
+ {
+
+ case MTN_FINISHED:
+ case MTN_TYPED:
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, (LPARAM)PROTOTYPE_CONTACTTYPING_OFF);
+ NetLog_Server("%s has stopped typing (ch %u).", strUID(dwUin, szUID), wChannel);
+ break;
+
+ case MTN_BEGUN:
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, (LPARAM)60);
+ NetLog_Server("%s is typing a message (ch %u).", strUID(dwUin, szUID), wChannel);
+ break;
+
+ default:
+ NetLog_Server("Unknown typing notification from %s, type %u (ch %u)", strUID(dwUin, szUID), wNotification, wChannel);
+ break;
+ }
+
+ return;
+}
+
+
+
+void sendTypingNotification(HANDLE hContact, WORD wMTNCode)
+{
+ icq_packet p;
+ BYTE byUinlen;
+ DWORD dwUin;
+ uid_str szUID;
+
+ _ASSERTE((wMTNCode == MTN_FINISHED) || (wMTNCode == MTN_TYPED) || (wMTNCode == MTN_BEGUN));
+
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUID))
+ return; // Invalid contact
+
+ byUinlen = getUIDLen(dwUin, szUID);
+
+ serverPacketInit(&p, (WORD)(23 + byUinlen));
+ packFNACHeader(&p, ICQ_MSG_FAMILY, ICQ_MSG_MTN);
+ packLEDWord(&p, 0x0000); // Msg ID
+ packLEDWord(&p, 0x0000); // Msg ID
+ packWord(&p, 0x01); // Channel
+ packUID(&p, dwUin, szUID); // User ID
+ packWord(&p, wMTNCode); // Notification type
+
+ sendServPacket(&p);
+}
diff --git a/icqj_mod/fam_09bos.c b/icqj_mod/fam_09bos.c new file mode 100644 index 0000000..b45d6a7 --- /dev/null +++ b/icqj_mod/fam_09bos.c @@ -0,0 +1,132 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_09bos.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+static void handlePrivacyRightsReply(unsigned char *pBuffer, WORD wBufferLength);
+
+void handleBosFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+
+ case ICQ_PRIVACY_RIGHTS_REPLY: // Reply to CLI_REQBOS
+ handlePrivacyRightsReply(pBuffer, wBufferLength);
+ break;
+
+ case ICQ_ERROR:
+ {
+ WORD wError;
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ LogFamilyError(ICQ_BOS_FAMILY, wError);
+ break;
+ }
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_BOS_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+
+ }
+}
+
+
+
+static void handlePrivacyRightsReply(unsigned char *pBuffer, WORD wBufferLength)
+{
+ if (wBufferLength >= 12)
+ {
+ oscar_tlv_chain* pChain;
+
+
+ pChain = readIntoTLVChain(&pBuffer, wBufferLength, 0);
+
+ if (pChain)
+ {
+ WORD wMaxVisibleContacts;
+ WORD wMaxInvisibleContacts;
+
+
+ wMaxVisibleContacts = getWordFromChain(pChain, 0x0001, 1);
+ wMaxInvisibleContacts = getWordFromChain(pChain, 0x0001, 1);
+
+ disposeChain(&pChain);
+
+ NetLog_Server("PRIVACY: Max visible %u, max invisible %u items.", wMaxVisibleContacts, wMaxInvisibleContacts);
+
+ // Success
+ return;
+ }
+ }
+
+ // Failure
+ NetLog_Server("Warning: Malformed SRV_PRIVACY_RIGHTS_REPLY");
+}
+
+
+
+void makeContactTemporaryVisible(HANDLE hContact)
+{
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (ICQGetContactSettingByte(hContact, "TemporaryVisible", 0))
+ return; // already there
+
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ return; // Invalid contact
+
+ icq_sendGenericContact(dwUin, szUid, ICQ_BOS_FAMILY, ICQ_CLI_ADDTEMPVISIBLE);
+
+ ICQWriteContactSettingByte(hContact, "TemporaryVisible", 1);
+
+#ifdef _DEBUG
+ NetLog_Server("Added contact %s to temporary visible list", strUID(dwUin, szUid));
+#endif
+}
+
+
+
+void clearTemporaryVisibleList()
+{ // remove all temporary visible contacts
+ sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_REMOVETEMPVISIBLE, BUL_TEMPVISIBLE);
+}
diff --git a/icqj_mod/fam_0alookup.c b/icqj_mod/fam_0alookup.c new file mode 100644 index 0000000..7a2e944 --- /dev/null +++ b/icqj_mod/fam_0alookup.c @@ -0,0 +1,144 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_0alookup.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static void handleLookupEmailReply(BYTE* buf, WORD wLen, DWORD dwCookie);
+static void ReleaseLookupCookie(DWORD dwCookie, search_cookie* pCookie);
+
+
+void handleLookupFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+
+ case ICQ_LOOKUP_EMAIL_REPLY: // AIM search reply
+ handleLookupEmailReply(pBuffer, wBufferLength, pSnacHeader->dwRef);
+ break;
+
+ case ICQ_ERROR:
+ {
+ WORD wError;
+ search_cookie* pCookie;
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, &pCookie))
+ {
+ if (wError == 0x14)
+ NetLog_Server("Lookup: No results");
+
+ ReleaseLookupCookie(pSnacHeader->dwRef, pCookie);
+
+ if (wError == 0x14) return;
+ }
+
+ LogFamilyError(ICQ_LOOKUP_FAMILY, wError);
+ break;
+ }
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_LOOKUP_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+ }
+}
+
+
+
+static void ReleaseLookupCookie(DWORD dwCookie, search_cookie* pCookie)
+{
+ FreeCookie(dwCookie);
+ SAFE_FREE(&pCookie->szObject);
+
+ if (pCookie->dwMainId && !pCookie->dwStatus)
+ { // we need to wait for main search
+ pCookie->dwStatus = 1;
+ }
+ else
+ { // finish everything
+ if (pCookie->dwMainId)
+ ICQBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)pCookie->dwMainId, 0);
+ else // we are single
+ ICQBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+
+ SAFE_FREE(&pCookie);
+ }
+}
+
+
+
+void handleLookupEmailReply(BYTE* buf, WORD wLen, DWORD dwCookie)
+{
+ ICQSEARCHRESULT sr = {0};
+ oscar_tlv_chain* pChain;
+ search_cookie* pCookie;
+ int i;
+
+ if (!FindCookie(dwCookie, NULL, &pCookie))
+ {
+ NetLog_Server("Error: Received unexpected lookup reply");
+ return;
+ }
+ else
+ NetLog_Server("SNAC(0x0A,0x3): Lookup reply");
+
+ sr.hdr.cbSize = sizeof(sr);
+ sr.hdr.email = pCookie->szObject;
+
+ // Syntax check, read chain
+ if (wLen >= 4 && (pChain = readIntoTLVChain(&buf, wLen, 0)))
+ {
+ for (i = 1; TRUE; i++)
+ { // collect the results
+ sr.hdr.nick = getStrFromChain(pChain, 1, (WORD)i);
+ if (!sr.hdr.nick) break;
+ sr.uid = sr.hdr.nick;
+ // broadcast the result
+ if (pCookie->dwMainId)
+ ICQBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)pCookie->dwMainId, (LPARAM)&sr);
+ else
+ ICQBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)dwCookie, (LPARAM)&sr);
+ SAFE_FREE(&sr.hdr.nick);
+ }
+ disposeChain(&pChain);
+ }
+
+ ReleaseLookupCookie(dwCookie, pCookie);
+}
diff --git a/icqj_mod/fam_0bstatus.c b/icqj_mod/fam_0bstatus.c new file mode 100644 index 0000000..fc35f46 --- /dev/null +++ b/icqj_mod/fam_0bstatus.c @@ -0,0 +1,70 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_0bstatus.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void handleStatusFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+
+ case ICQ_STATS_MINREPORTINTERVAL:
+ {
+ WORD wInterval;
+ unpackWord(&pBuffer, &wInterval);
+ NetLog_Server("Server sent SNAC(x0B,x02) - SRV_SET_MINREPORTINTERVAL (Value: %u hours)", wInterval);
+ }
+ break;
+
+ case ICQ_ERROR:
+ {
+ WORD wError;
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ LogFamilyError(ICQ_STATS_FAMILY, wError);
+ break;
+ }
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_STATS_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+ }
+}
diff --git a/icqj_mod/fam_13servclist.c b/icqj_mod/fam_13servclist.c new file mode 100644 index 0000000..ab30af7 --- /dev/null +++ b/icqj_mod/fam_13servclist.c @@ -0,0 +1,1900 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_13servclist.c,v $
+// Revision : $Revision: 3074 $
+// Last change on : $Date: 2006-06-07 21:21:32 +0200 (Wed, 07 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+extern WORD wListenPort;
+
+extern void setUserInfo();
+extern int GroupNameExistsUtf(const char *name,int skipGroup);
+
+BOOL bIsSyncingCL = FALSE;
+
+static HANDLE HContactFromRecordName(char* szRecordName, int *bAdded);
+
+static int getServerDataFromItemTLV(oscar_tlv_chain* pChain, unsigned char *buf);
+
+static int unpackServerListItem(unsigned char** pbuf, WORD* pwLen, char* pszRecordName, WORD* pwGroupId, WORD* pwItemId, WORD* pwItemType, WORD* pwTlvLength);
+
+static void handleServerCListAck(servlistcookie* sc, WORD wError);
+static void handleServerCList(unsigned char *buf, WORD wLen, WORD wFlags, serverthread_info *info);
+static void handleRecvAuthRequest(unsigned char *buf, WORD wLen);
+static void handleRecvAuthResponse(unsigned char *buf, WORD wLen);
+static void handleRecvAdded(unsigned char *buf, WORD wLen);
+void sendRosterAck(void);
+
+
+static WORD swapWord(WORD val)
+{
+ return (val & 0xFF)<<8 | (val>>8);
+}
+
+
+
+void handleServClistFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader, serverthread_info *info)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+
+ case ICQ_LISTS_ACK: // UPDATE_ACK
+ if (wBufferLength >= 2)
+ {
+ WORD wError;
+ DWORD dwActUin;
+ servlistcookie* sc;
+
+ unpackWord(&pBuffer, &wError);
+
+ if (FindCookie(pSnacHeader->dwRef, &dwActUin, &sc))
+ { // look for action cookie
+#ifdef _DEBUG
+ NetLog_Server("Received expected server list ack, action: %d, result: %d", sc->dwAction, wError);
+#endif
+ FreeCookie(pSnacHeader->dwRef); // release cookie
+
+ handleServerCListAck(sc, wError);
+ }
+ else
+ {
+ NetLog_Server("Received unexpected server list ack %u", wError);
+ }
+ }
+ break;
+
+ case ICQ_LISTS_SRV_REPLYLISTS:
+ {
+ /* received list rights, we just skip them */
+
+ oscar_tlv_chain* chain;
+
+ if (chain = readIntoTLVChain(&pBuffer, wBufferLength, 0))
+ {
+ oscar_tlv* pTLV;
+
+ if ((pTLV = getTLV(chain, 0x04, 1)) && pTLV->wLen>=30)
+ { // limits for item types
+ WORD* pMax = (WORD*)pTLV->pData;
+
+ NetLog_Server("SSI: Max %d contacts, %d groups, %d permit, %d deny, %d ignore items.", swapWord(pMax[0]), swapWord(pMax[1]), swapWord(pMax[2]), swapWord(pMax[3]), swapWord(pMax[14]));
+ }
+
+ disposeChain(&chain);
+ }
+#ifdef _DEBUG
+ NetLog_Server("Server sent SNAC(x13,x03) - SRV_REPLYLISTS");
+#endif
+ }
+ break;
+
+ case ICQ_LISTS_LIST: // SRV_REPLYROSTER
+ {
+ servlistcookie* sc;
+ BOOL blWork;
+
+ blWork = bIsSyncingCL;
+ bIsSyncingCL = TRUE; // this is not used if cookie takes place
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, &sc))
+ { // we do it by reliable cookie
+ if (!sc->dwUin)
+ { // is this first packet ?
+ ResetSettingsOnListReload();
+ sc->dwUin = 1;
+ }
+ handleServerCList(pBuffer, wBufferLength, pSnacHeader->wFlags, info);
+ if (!(pSnacHeader->wFlags & 0x0001))
+ { // was that last packet ?
+ ReleaseCookie(pSnacHeader->dwRef); // yes, release cookie
+ }
+ }
+ else
+ { // use old fake
+ if (!blWork)
+ { // this can fail on some crazy situations
+ ResetSettingsOnListReload();
+ }
+ handleServerCList(pBuffer, wBufferLength, pSnacHeader->wFlags, info);
+ }
+ break;
+ }
+
+ case ICQ_LISTS_UPTODATE: // SRV_REPLYROSTEROK
+ {
+ servlistcookie* sc;
+
+ bIsSyncingCL = FALSE;
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, &sc))
+ { // we requested servlist check
+#ifdef _DEBUG
+ NetLog_Server("Server stated roster is ok.");
+#endif
+ ReleaseCookie(pSnacHeader->dwRef);
+ LoadServerIDs();
+ }
+ else
+ NetLog_Server("Server sent unexpected SNAC(x13,x0F) - SRV_REPLYROSTEROK");
+
+ // This will activate the server side list
+ sendRosterAck(); // this must be here, cause of failures during cookie alloc
+ handleServUINSettings(wListenPort, info);
+ break;
+ }
+
+ case ICQ_LISTS_CLI_MODIFYSTART:
+ NetLog_Server("Server sent SNAC(x13,x%02x) - %s", 0x11, "Server is modifying contact list");
+ break;
+
+ case ICQ_LISTS_CLI_MODIFYEND:
+ NetLog_Server("Server sent SNAC(x13,x%02x) - %s", 0x12, "End of server modification");
+ break;
+
+ case ICQ_LISTS_UPDATEGROUP:
+ if (wBufferLength >= 10)
+ {
+ WORD wGroupId, wItemId, wItemType, wTlvLen;
+ uid_str szUID;
+
+ if (unpackServerListItem(&pBuffer, &wBufferLength, szUID, &wGroupId, &wItemId, &wItemType, &wTlvLen))
+ {
+ HANDLE hContact = HContactFromRecordName(szUID, NULL);
+
+ if (wBufferLength >= wTlvLen && hContact != INVALID_HANDLE_VALUE && wItemType == SSI_ITEM_BUDDY)
+ { // a contact was updated on server
+ if (wTlvLen > 0)
+ { // parse details
+ oscar_tlv_chain *pChain = readIntoTLVChain(&pBuffer, (WORD)(wTlvLen), 0);
+
+ if (pChain)
+ {
+ oscar_tlv* pAuth = getTLV(pChain, SSI_TLV_AWAITING_AUTH, 1);
+ BYTE bAuth = ICQGetContactSettingByte(hContact, "Auth", 0);
+
+ if (bAuth && !pAuth)
+ { // server authorised our contact
+ char str[MAX_PATH];
+ char msg[MAX_PATH];
+ char *nick = NickFromHandleUtf(hContact);
+
+ ICQWriteContactSettingByte(hContact, "Auth", 0);
+ null_snprintf(str, MAX_PATH, ICQTranslateUtfStatic("User \"%s\" was authorised in the server list.", msg), nick);
+ icq_LogMessage(LOG_WARNING, str);
+ SAFE_FREE(&nick);
+ }
+
+ { // update server's data - otherwise consequent operations can fail with 0x0E
+ unsigned char* data = (unsigned char*)_alloca(wTlvLen);
+ int datalen = getServerDataFromItemTLV(pChain, data);
+
+ if (datalen > 0)
+ ICQWriteContactSettingBlob(hContact, "ServerData", data, datalen);
+ else
+ ICQDeleteContactSetting(hContact, "ServerData");
+ }
+
+ disposeChain(&pChain);
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ NetLog_Server("Server sent SNAC(x13,x%02x) - %s", 0x09, "Server updated our contact on list");
+ break;
+
+ case ICQ_LISTS_REMOVEFROMLIST:
+ if (wBufferLength >= 10)
+ {
+ WORD wGroupId, wItemId, wItemType;
+ uid_str szUID;
+
+ if (unpackServerListItem(&pBuffer, &wBufferLength, szUID, &wGroupId, &wItemId, &wItemType, NULL))
+ {
+ HANDLE hContact = HContactFromRecordName(szUID, NULL);
+
+ if (hContact != INVALID_HANDLE_VALUE && wItemType == SSI_ITEM_BUDDY)
+ { // a contact was removed from our list
+ ICQDeleteContactSetting(hContact, "ServerId");
+ ICQDeleteContactSetting(hContact, "SrvGroupId");
+ ICQDeleteContactSetting(hContact, "Auth");
+ icq_sendNewContact(0, szUID); // add to CS to see him
+ {
+ char str[MAX_PATH];
+ char msg[MAX_PATH];
+ char *nick = NickFromHandleUtf(hContact);
+
+ null_snprintf(str, MAX_PATH, ICQTranslateUtfStatic("User \"%s\" was removed from server list.", msg), nick);
+ icq_LogMessage(LOG_WARNING, str);
+ SkinPlaySound("ContactRemovedSelf");
+
+ icq_SetUserStatus(atoi(szUID), 0, 29);
+ SAFE_FREE(&nick);
+ }
+ }
+ }
+ }
+ NetLog_Server("Server sent SNAC(x13,x%02x) - %s", 0x0A, "Server removed something from our list");
+ break;
+
+ case ICQ_LISTS_ADDTOLIST:
+ if (wBufferLength >= 10)
+ {
+ WORD wGroupId, wItemId, wItemType, wTlvLen;
+
+ if (unpackServerListItem(&pBuffer, &wBufferLength, NULL, &wGroupId, &wItemId, &wItemType, &wTlvLen))
+ {
+ if (wBufferLength >= wTlvLen && wItemType == SSI_ITEM_IMPORTTIME)
+ {
+ if (wTlvLen > 0)
+ { // parse timestamp
+ oscar_tlv_chain *pChain = readIntoTLVChain(&pBuffer, (WORD)(wTlvLen), 0);
+
+ if (pChain)
+ {
+ ICQWriteContactSettingDword(NULL, "ImportTS", getDWordFromChain(pChain, SSI_TLV_TIMESTAMP, 1));
+ ICQWriteContactSettingWord(NULL, "SrvImportID", wItemId);
+ disposeChain(&pChain);
+
+ NetLog_Server("Server added Import timestamp to list");
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ NetLog_Server("Server sent SNAC(x13,x%02x) - %s", 0x08, "Server added something to our list");
+ break;
+
+ case ICQ_LISTS_AUTHREQUEST:
+ handleRecvAuthRequest(pBuffer, wBufferLength);
+ break;
+
+ case ICQ_LISTS_SRV_AUTHRESPONSE:
+ handleRecvAuthResponse(pBuffer, wBufferLength);
+ break;
+
+ case ICQ_LISTS_AUTHGRANTED:
+ NetLog_Server("Server sent SNAC(x13,x%02x) - %s", 0x15, "User granted us future authorization");
+ break;
+
+ case ICQ_LISTS_YOUWEREADDED:
+ handleRecvAdded(pBuffer, wBufferLength);
+ break;
+
+ case ICQ_LISTS_ERROR:
+ if (wBufferLength >= 2)
+ {
+ WORD wError;
+ DWORD dwActUin;
+ servlistcookie* sc;
+
+ unpackWord(&pBuffer, &wError);
+
+ if (FindCookie(pSnacHeader->dwRef, &dwActUin, &sc))
+ { // look for action cookie
+#ifdef _DEBUG
+ NetLog_Server("Received server list error, action: %d, result: %d", sc->dwAction, wError);
+#endif
+ FreeCookie(pSnacHeader->dwRef); // release cookie
+
+ if (sc->dwAction==SSA_CHECK_ROSTER)
+ { // the serv-list is unavailable turn it off
+ icq_LogMessage(LOG_ERROR, "Server contact list is unavailable, Miranda will use local contact list.");
+ gbSsiEnabled = 0;
+ handleServUINSettings(wListenPort, info);
+ }
+ SAFE_FREE(&sc);
+ }
+ else
+ {
+ LogFamilyError(ICQ_LISTS_FAMILY, wError);
+ }
+ }
+ break;
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_LISTS_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+ }
+}
+
+
+
+static int unpackServerListItem(unsigned char** pbuf, WORD* pwLen, char* pszRecordName, WORD* pwGroupId, WORD* pwItemId, WORD* pwItemType, WORD* pwTlvLength)
+{
+ WORD wRecordNameLen;
+
+ // The name of the entry. If this is a group header, then this
+ // is the name of the group. If it is a plain contact list entry,
+ // then it's the UIN of the contact.
+ unpackWord(pbuf, &wRecordNameLen);
+ if (*pwLen < 10 + wRecordNameLen || wRecordNameLen >= MAX_PATH)
+ return 0; // Failure
+
+ unpackString(pbuf, pszRecordName, wRecordNameLen);
+ if (pszRecordName)
+ pszRecordName[wRecordNameLen] = '\0';
+
+ // The group identifier this entry belongs to. If 0, this is meta information or
+ // a contact without a group
+ unpackWord(pbuf, pwGroupId);
+
+ // The ID of this entry. Group headers have ID 0. Otherwise, this
+ // is a random number generated when the user is added to the
+ // contact list, or when the user is ignored. See CLI_ADDBUDDY.
+ unpackWord(pbuf, pwItemId);
+
+ // This field indicates what type of entry this is
+ unpackWord(pbuf, pwItemType);
+
+ // The length in bytes of the following TLV chain
+ unpackWord(pbuf, pwTlvLength);
+
+ *pwLen -= wRecordNameLen + 10;
+
+ return 1; // Success
+}
+
+
+
+static DWORD updateServerGroupData(WORD wGroupId, void *groupData, int groupSize)
+{
+ DWORD dwCookie;
+ servlistcookie* ack;
+
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (!ack)
+ {
+ NetLog_Server("Updating of group on server list failed (malloc error)");
+ return 0;
+ }
+ ack->dwAction = SSA_GROUP_UPDATE;
+ ack->szGroupName = getServerGroupNameUtf(wGroupId);
+ ack->wGroupId = wGroupId;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+
+ return icq_sendGroupUtf(dwCookie, ICQ_LISTS_UPDATEGROUP, ack->wGroupId, ack->szGroupName, groupData, groupSize);
+}
+
+
+
+static void handleServerCListAck(servlistcookie* sc, WORD wError)
+{
+ switch (sc->dwAction)
+ {
+ case SSA_VISIBILITY:
+ {
+ if (wError)
+ NetLog_Server("Server visibility update failed, error %d", wError);
+ break;
+ }
+ case SSA_CONTACT_UPDATE:
+ {
+ RemovePendingOperation(sc->hContact, 1);
+ if (wError)
+ {
+ NetLog_Server("Updating of server contact failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, "Updating of server contact failed.");
+ }
+ break;
+ }
+ case SSA_PRIVACY_ADD:
+ {
+ if (wError)
+ {
+ NetLog_Server("Adding of privacy item to server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, "Adding of privacy item to server list failed.");
+ }
+ break;
+ }
+ case SSA_PRIVACY_REMOVE:
+ {
+ if (wError)
+ {
+ NetLog_Server("Removing of privacy item from server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, "Removing of privacy item from server list failed.");
+ }
+ FreeServerID(sc->wContactId, SSIT_ITEM); // release server id
+ break;
+ }
+ case SSA_CONTACT_ADD:
+ {
+ if (wError)
+ {
+ if (wError == 0xE) // server refused to add contact w/o auth, add with
+ {
+ DWORD dwCookie;
+
+ NetLog_Server("Contact could not be added without authorization, add with await auth flag.");
+
+ ICQWriteContactSettingByte(sc->hContact, "Auth", 1); // we need auth
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, sc->dwUin, sc);
+ icq_sendServerContact(sc->hContact, dwCookie, ICQ_LISTS_ADDTOLIST, sc->wGroupId, sc->wContactId);
+
+ sc = NULL; // we do not want it to be freed now
+ break;
+ }
+ FreeServerID(sc->wContactId, SSIT_ITEM);
+ sendAddEnd(); // end server modifications here
+ RemovePendingOperation(sc->hContact, 0);
+
+ NetLog_Server("Adding of contact to server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, "Adding of contact to server list failed.");
+ }
+ else
+ {
+ void* groupData;
+ int groupSize;
+ HANDLE hPend = sc->hContact;
+
+ ICQWriteContactSettingWord(sc->hContact, "ServerId", sc->wContactId);
+ ICQWriteContactSettingWord(sc->hContact, "SrvGroupId", sc->wGroupId);
+
+ if (groupData = collectBuddyGroup(sc->wGroupId, &groupSize))
+ { // the group is not empty, just update it
+ updateServerGroupData(sc->wGroupId, groupData, groupSize);
+ SAFE_FREE(&groupData);
+ }
+ else
+ { // this should never happen
+ NetLog_Server("Group update failed.");
+ }
+ sendAddEnd(); // end server modifications here
+
+ if (hPend) RemovePendingOperation(hPend, 1);
+ }
+ break;
+ }
+ case SSA_GROUP_ADD:
+ {
+ if (wError)
+ {
+ FreeServerID(sc->wGroupId, SSIT_GROUP);
+ NetLog_Server("Adding of group to server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, "Adding of group to server list failed.");
+ }
+ else // group added, we need to update master group
+ {
+ void* groupData;
+ int groupSize;
+ servlistcookie* ack;
+ DWORD dwCookie;
+
+ setServerGroupNameUtf(sc->wGroupId, sc->szGroupName); // add group to namelist
+ setServerGroupIDUtf(makeGroupPathUtf(sc->wGroupId), sc->wGroupId); // add group to known
+
+ groupData = collectGroups(&groupSize);
+ groupData = realloc(groupData, groupSize+2);
+ *(((WORD*)groupData)+(groupSize>>1)) = sc->wGroupId; // add this new group id
+ groupSize += 2;
+
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (ack)
+ {
+ ack->dwAction = SSA_GROUP_UPDATE;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+
+ icq_sendGroupUtf(dwCookie, ICQ_LISTS_UPDATEGROUP, 0, ack->szGroupName, groupData, groupSize);
+ }
+ sendAddEnd(); // end server modifications here
+
+ SAFE_FREE(&groupData);
+
+ if (sc->ofCallback) // is add contact pending
+ {
+ sc->ofCallback(sc->wGroupId, (LPARAM)sc->lParam);
+ // sc = NULL; // we do not want to be freed here
+ }
+ }
+ SAFE_FREE(&sc->szGroupName);
+ break;
+ }
+ case SSA_CONTACT_REMOVE:
+ {
+ if (!wError)
+ {
+ void* groupData;
+ int groupSize;
+
+ ICQWriteContactSettingWord(sc->hContact, "ServerId", 0); // clear the values
+ ICQWriteContactSettingWord(sc->hContact, "SrvGroupId", 0);
+
+ FreeServerID(sc->wContactId, SSIT_ITEM);
+
+ if (groupData = collectBuddyGroup(sc->wGroupId, &groupSize))
+ { // the group is still not empty, just update it
+ updateServerGroupData(sc->wGroupId, groupData, groupSize);
+
+ sendAddEnd(); // end server modifications here
+ }
+ else // the group is empty, delete it if it does not have sub-groups
+ {
+ DWORD dwCookie;
+
+ if (!CheckServerID((WORD)(sc->wGroupId+1), 0) || countGroupLevel((WORD)(sc->wGroupId+1)) == 0)
+ { // is next id an sub-group, if yes, we cannot delete this group
+ sc->dwAction = SSA_GROUP_REMOVE;
+ sc->wContactId = 0;
+ sc->hContact = NULL;
+ sc->szGroupName = getServerGroupNameUtf(sc->wGroupId);
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, 0, sc);
+
+ icq_sendGroupUtf(dwCookie, ICQ_LISTS_REMOVEFROMLIST, sc->wGroupId, sc->szGroupName, NULL, 0);
+ // here the modifications go on
+ sc = NULL; // we do not want it to be freed now
+ }
+ }
+ SAFE_FREE(&groupData); // free the memory
+ }
+ else
+ {
+ NetLog_Server("Removing of contact from server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, "Removing of contact from server list failed.");
+ sendAddEnd(); // end server modifications here
+ }
+ break;
+ }
+ case SSA_GROUP_UPDATE:
+ {
+ if (wError)
+ {
+ NetLog_Server("Updating of group on server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, "Updating of group on server list failed.");
+ }
+ SAFE_FREE(&sc->szGroupName);
+ break;
+ }
+ case SSA_GROUP_REMOVE:
+ {
+ SAFE_FREE(&sc->szGroupName);
+ if (wError)
+ {
+ NetLog_Server("Removing of group from server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, "Removing of group from server list failed.");
+ }
+ else // group removed, we need to update master group
+ {
+ void* groupData;
+ int groupSize;
+ DWORD dwCookie;
+
+ setServerGroupNameUtf(sc->wGroupId, NULL); // clear group from namelist
+ FreeServerID(sc->wGroupId, SSIT_GROUP);
+ removeGroupPathLinks(sc->wGroupId);
+
+ groupData = collectGroups(&groupSize);
+ sc->wGroupId = 0;
+ sc->dwAction = SSA_GROUP_UPDATE;
+ sc->szGroupName = NULL;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, sc);
+
+ icq_sendGroupUtf(dwCookie, ICQ_LISTS_UPDATEGROUP, 0, sc->szGroupName, groupData, groupSize);
+ sendAddEnd(); // end server modifications here
+
+ sc = NULL; // we do not want to be freed here
+
+ SAFE_FREE(&groupData);
+ }
+ break;
+ }
+ case SSA_CONTACT_SET_GROUP:
+ { // we moved contact to another group
+ if (sc->lParam == -1)
+ { // the first was an error
+ break;
+ }
+ if (wError)
+ {
+ RemovePendingOperation(sc->hContact, 0);
+ NetLog_Server("Moving of user to another group on server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, "Moving of user to another group on server list failed.");
+ if (!sc->lParam) // is this first ack ?
+ {
+ sc->lParam = -1;
+ sc = NULL; // this can't be freed here
+ }
+ break;
+ }
+ if (sc->lParam) // is this the second ack ?
+ {
+ void* groupData;
+ int groupSize;
+ int bEnd = 1; // shall we end the sever modifications
+
+ ICQWriteContactSettingWord(sc->hContact, "ServerId", sc->wNewContactId);
+ ICQWriteContactSettingWord(sc->hContact, "SrvGroupId", sc->wNewGroupId);
+ FreeServerID(sc->wContactId, SSIT_ITEM); // release old contact id
+
+ if (groupData = collectBuddyGroup(sc->wGroupId, &groupSize)) // update the group we moved from
+ { // the group is still not empty, just update it
+ updateServerGroupData(sc->wGroupId, groupData, groupSize);
+ SAFE_FREE(&groupData); // free the memory
+ }
+ else if (!CheckServerID((WORD)(sc->wGroupId+1), 0) || countGroupLevel((WORD)(sc->wGroupId+1)) == 0)
+ { // the group is empty and is not followed by sub-groups, delete it
+ DWORD dwCookie;
+ servlistcookie* ack;
+
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (!ack)
+ {
+ NetLog_Server("Updating of group on server list failed (malloc error)");
+ break;
+ }
+ ack->dwAction = SSA_GROUP_REMOVE;
+ ack->szGroupName = getServerGroupNameUtf(sc->wGroupId);
+ ack->wGroupId = sc->wGroupId;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, 0, ack);
+
+ icq_sendGroupUtf(dwCookie, ICQ_LISTS_REMOVEFROMLIST, ack->wGroupId, ack->szGroupName, NULL, 0);
+ bEnd = 0; // here the modifications go on
+ }
+
+ groupData = collectBuddyGroup(sc->wNewGroupId, &groupSize); // update the group we moved to
+ updateServerGroupData(sc->wNewGroupId, groupData, groupSize);
+ SAFE_FREE(&groupData);
+
+ if (bEnd) sendAddEnd();
+ if (sc->hContact) RemovePendingOperation(sc->hContact, 1);
+ }
+ else // contact was deleted from server-list
+ {
+ ICQDeleteContactSetting(sc->hContact, "ServerId");
+ ICQDeleteContactSetting(sc->hContact, "SrvGroupId");
+ sc->lParam = 1;
+ sc = NULL; // wait for second ack
+ }
+ break;
+ }
+ case SSA_GROUP_RENAME:
+ {
+ if (wError)
+ {
+ NetLog_Server("Renaming of server group failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, "Renaming of server group failed.");
+ }
+ else
+ {
+ setServerGroupNameUtf(sc->wGroupId, sc->szGroupName);
+ removeGroupPathLinks(sc->wGroupId);
+ setServerGroupIDUtf(makeGroupPathUtf(sc->wGroupId), sc->wGroupId);
+ }
+ RemoveGroupRename(sc->wGroupId);
+ SAFE_FREE(&sc->szGroupName);
+ break;
+ }
+ case SSA_SETAVATAR:
+ {
+ if (wError)
+ {
+ NetLog_Server("Uploading of avatar hash failed.");
+ if (sc->wGroupId) // is avatar added or updated?
+ {
+ FreeServerID(sc->wContactId, SSIT_ITEM);
+ ICQDeleteContactSetting(NULL, "SrvAvatarID"); // to fix old versions
+ }
+ }
+ else
+ {
+ ICQWriteContactSettingWord(NULL, "SrvAvatarID", sc->wContactId);
+ }
+ break;
+ }
+ case SSA_REMOVEAVATAR:
+ {
+ if (wError)
+ NetLog_Server("Removing of avatar hash failed.");
+ else
+ {
+ ICQDeleteContactSetting(NULL, "SrvAvatarID");
+ FreeServerID(sc->wContactId, SSIT_ITEM);
+ }
+ break;
+ }
+ case SSA_SERVLIST_ACK:
+ {
+ ICQBroadcastAck(sc->hContact, ICQACKTYPE_SERVERCLIST, wError?ACKRESULT_FAILED:ACKRESULT_SUCCESS, (HANDLE)sc->lParam, wError);
+ break;
+ }
+ case SSA_IMPORT:
+ {
+ if (wError)
+ NetLog_Server("Re-starting import sequence failed, error %d", wError);
+ else
+ {
+ ICQWriteContactSettingWord(NULL, "SrvImportID", 0);
+ ICQDeleteContactSetting(NULL, "ImportTS");
+ }
+ break;
+ }
+ default:
+ NetLog_Server("Server ack cookie type (%d) not recognized.", sc->dwAction);
+ }
+ SAFE_FREE(&sc); // free the memory
+
+ return;
+}
+
+
+
+static HANDLE HContactFromRecordName(char* szRecordName, int *bAdded)
+{
+ HANDLE hContact = INVALID_HANDLE_VALUE;
+
+ if (!IsStringUIN(szRecordName))
+ { // probably AIM contact
+ hContact = HContactFromUID(0, szRecordName, bAdded);
+ }
+ else
+ { // this should be ICQ number
+ DWORD dwUin;
+
+ dwUin = atoi(szRecordName);
+ hContact = HContactFromUIN(dwUin, bAdded);
+ }
+ return hContact;
+}
+
+
+
+static int getServerDataFromItemTLV(oscar_tlv_chain* pChain, unsigned char *buf)
+{ // get server-list item's TLV data
+ oscar_tlv_chain* list = pChain;
+ int datalen = 0;
+ icq_packet pBuf;
+
+ // Initialize our handy data buffer
+ pBuf.wPlace = 0;
+ pBuf.pData = buf;
+
+ while (list)
+ { // collect non-standard TLVs and save them to DB
+ if (list->tlv.wType != SSI_TLV_AWAITING_AUTH &&
+ list->tlv.wType != SSI_TLV_NAME &&
+ list->tlv.wType != SSI_TLV_COMMENT)
+ { // only TLVs which we do not handle on our own
+ packTLV(&pBuf, list->tlv.wType, list->tlv.wLen, list->tlv.pData);
+
+ datalen += list->tlv.wLen + 4;
+ }
+ list = list->next;
+ }
+ return datalen;
+}
+
+
+static void handleServerCList(unsigned char *buf, WORD wLen, WORD wFlags, serverthread_info *info)
+{
+ BYTE bySSIVersion;
+ WORD wRecordCount;
+ WORD wRecord;
+ WORD wGroupId;
+ WORD wItemId;
+ WORD wTlvType;
+ WORD wTlvLength;
+ BOOL bIsLastPacket;
+ uid_str szRecordName;
+ oscar_tlv_chain* pChain = NULL;
+ oscar_tlv* pTLV = NULL;
+
+
+ // If flag bit 1 is set, this is not the last
+ // packet. If it is 0, this is the last packet
+ // and there will be a timestamp at the end.
+ if (wFlags & 0x0001)
+ bIsLastPacket = FALSE;
+ else
+ bIsLastPacket = TRUE;
+
+ if (wLen < 3)
+ return;
+
+ // Version number of SSI protocol?
+ unpackByte(&buf, &bySSIVersion);
+ wLen -= 1;
+
+ // Total count of following entries. This is the size of the server
+ // side contact list and should be saved and sent with CLI_CHECKROSTER.
+ // NOTE: When the entries are split up in several packets, each packet
+ // has it's own count and they must be added to get the total size of
+ // server list.
+ unpackWord(&buf, &wRecordCount);
+ wLen -= 2;
+ NetLog_Server("SSI: number of entries is %u, version is %u", wRecordCount, bySSIVersion);
+
+
+ // Loop over all items in the packet
+ for (wRecord = 0; wRecord < wRecordCount; wRecord++)
+ {
+ NetLog_Server("SSI: parsing record %u", wRecord + 1);
+
+ if (wLen < 10)
+ { // minimum: name length (zero), group ID, item ID, empty TLV
+ NetLog_Server("Warning: SSI parsing error (%d)", 0);
+ break;
+ }
+
+ if (!unpackServerListItem(&buf, &wLen, szRecordName, &wGroupId, &wItemId, &wTlvType, &wTlvLength))
+ { // unpack basic structure
+ NetLog_Server("Warning: SSI parsing error (%d)", 1);
+ break;
+ }
+
+ NetLog_Server("Name: '%s', GroupID: %u, EntryID: %u, EntryType: %u, TLVlength: %u",
+ szRecordName, wGroupId, wItemId, wTlvType, wTlvLength);
+
+ if (wLen < wTlvLength)
+ {
+ NetLog_Server("Warning: SSI parsing error (%d)", 2);
+ break;
+ }
+
+ // Initialize the tlv chain
+ if (wTlvLength > 0)
+ {
+ pChain = readIntoTLVChain(&buf, wTlvLength, 0);
+ wLen -= wTlvLength;
+ }
+ else
+ {
+ pChain = NULL;
+ }
+
+
+ switch (wTlvType)
+ {
+
+ case SSI_ITEM_BUDDY:
+ {
+ /* this is a contact */
+ HANDLE hContact;
+ int bAdded;
+
+ hContact = HContactFromRecordName(szRecordName, &bAdded);
+
+ if (hContact != INVALID_HANDLE_VALUE)
+ {
+ int bRegroup = 0;
+ int bNicked = 0;
+ WORD wOldGroupId;
+
+ if (bAdded)
+ { // Not already on list: added
+ char* szGroup;
+
+ NetLog_Server("SSI added new %s contact '%s'", "ICQ", szRecordName);
+
+ if (szGroup = makeGroupPathUtf(wGroupId))
+ { // try to get Miranda Group path from groupid, if succeeded save to db
+ UniWriteContactSettingUtf(hContact, "CList", "Group", szGroup);
+
+ SAFE_FREE(&szGroup);
+ }
+ AddJustAddedContact(hContact);
+ }
+ else
+ { // we should add new contacts and this contact was just added, show it
+ if (IsContactJustAdded(hContact))
+ {
+ SetContactHidden(hContact, 0);
+ bAdded = 1; // we want details for new contacts
+ }
+ else
+ NetLog_Server("SSI ignoring existing contact '%s'", szRecordName);
+ // Contact on server is always on list
+ DBWriteContactSettingByte(hContact, "CList", "NotOnList", 0);
+ }
+
+ wOldGroupId = ICQGetContactSettingWord(hContact, "SrvGroupId", 0);
+ // Save group and item ID
+ ICQWriteContactSettingWord(hContact, "ServerId", wItemId);
+ ICQWriteContactSettingWord(hContact, "SrvGroupId", wGroupId);
+ ReserveServerID(wItemId, SSIT_ITEM);
+
+ if (!bAdded && (wOldGroupId != wGroupId) && ICQGetContactSettingByte(NULL, "LoadServerDetails", DEFAULT_SS_LOAD))
+ { // contact has been moved on the server
+ char* szOldGroup = getServerGroupNameUtf(wOldGroupId);
+ char* szGroup = getServerGroupNameUtf(wGroupId);
+
+ if (!szOldGroup)
+ { // old group is not known, most probably not created subgroup
+ char* szTmp = UniGetContactSettingUtf(hContact, "CList", "Group", "");
+
+ if (strlennull(szTmp))
+ { // got group from CList
+ SAFE_FREE(&szOldGroup);
+ szOldGroup = szTmp;
+ }
+ else
+ SAFE_FREE(&szTmp);
+
+ if (!szOldGroup) szOldGroup = null_strdup(DEFAULT_SS_GROUP);
+ }
+
+ if (!szGroup || strlennull(szGroup)>=strlennull(szOldGroup) || strnicmp(szGroup, szOldGroup, strlennull(szGroup)))
+ { // contact moved to new group or sub-group or not to master group
+ bRegroup = 1;
+ }
+ if (bRegroup && !stricmp(DEFAULT_SS_GROUP, szGroup) && !GroupNameExistsUtf(szGroup, -1))
+ { // is it the default "General" group ? yes, does it exists in CL ?
+ bRegroup = 0; // if no, do not move to it - cause it would hide the contact
+ }
+ SAFE_FREE(&szGroup);
+ SAFE_FREE(&szOldGroup);
+ }
+
+ if (bRegroup || bAdded)
+ { // if we should load server details or contact was just added, update its group
+ char* szGroup;
+
+ if (szGroup = makeGroupPathUtf(wGroupId))
+ { // try to get Miranda Group path from groupid, if succeeded save to db
+ UniWriteContactSettingUtf(hContact, "CList", "Group", szGroup);
+
+ SAFE_FREE(&szGroup);
+ }
+ }
+
+ if (pChain)
+ { // Look for nickname TLV and copy it to the db if necessary
+ if (pTLV = getTLV(pChain, SSI_TLV_NAME, 1))
+ {
+ if (pTLV->pData && (pTLV->wLen > 0))
+ {
+ char* pszNick;
+ WORD wNickLength;
+
+ wNickLength = pTLV->wLen;
+
+ pszNick = (char*)SAFE_MALLOC(wNickLength + 1);
+ // Copy buffer to utf-8 buffer
+ memcpy(pszNick, pTLV->pData, wNickLength);
+ pszNick[wNickLength] = 0; // Terminate string
+
+ NetLog_Server("Nickname is '%s'", pszNick);
+
+ bNicked = 1;
+
+ // Write nickname to database
+ if (ICQGetContactSettingByte(NULL, "LoadServerDetails", DEFAULT_SS_LOAD) || bAdded)
+ { // if just added contact, save details always - does no harm
+ char *szOldNick;
+
+ if (szOldNick = UniGetContactSettingUtf(hContact,"CList","MyHandle",""))
+ {
+ if ((strcmpnull(szOldNick, pszNick)) && (strlennull(pszNick) > 0))
+ {
+ // Yes, we really do need to delete it first. Otherwise the CLUI nick
+ // cache isn't updated (I'll look into it)
+ DBDeleteContactSetting(hContact,"CList","MyHandle");
+ UniWriteContactSettingUtf(hContact, "CList", "MyHandle", pszNick);
+ }
+ SAFE_FREE(&szOldNick);
+ }
+ else if (strlennull(pszNick) > 0)
+ {
+ DBDeleteContactSetting(hContact,"CList","MyHandle");
+ UniWriteContactSettingUtf(hContact, "CList", "MyHandle", pszNick);
+ }
+ }
+ SAFE_FREE(&pszNick);
+ }
+ else
+ {
+ NetLog_Server("Invalid nickname");
+ }
+ }
+ if (bAdded && !bNicked)
+ icq_QueueUser(hContact); // queue user without nick for fast auto info update
+
+ // Look for comment TLV and copy it to the db if necessary
+ if (pTLV = getTLV(pChain, SSI_TLV_COMMENT, 1))
+ {
+ if (pTLV->pData && (pTLV->wLen > 0))
+ {
+ char* pszComment;
+ WORD wCommentLength;
+
+
+ wCommentLength = pTLV->wLen;
+
+ pszComment = (char*)SAFE_MALLOC(wCommentLength + 1);
+ // Copy buffer to utf-8 buffer
+ memcpy(pszComment, pTLV->pData, wCommentLength);
+ pszComment[wCommentLength] = 0; // Terminate string
+
+ NetLog_Server("Comment is '%s'", pszComment);
+
+ // Write comment to database
+ if (ICQGetContactSettingByte(NULL, "LoadServerDetails", DEFAULT_SS_LOAD) || bAdded)
+ { // if just added contact, save details always - does no harm
+ char *szOldComment;
+
+ if (szOldComment = UniGetContactSettingUtf(hContact,"UserInfo","MyNotes",""))
+ {
+ if ((strcmpnull(szOldComment, pszComment)) && (strlennull(pszComment) > 0))
+ {
+ UniWriteContactSettingUtf(hContact, "UserInfo", "MyNotes", pszComment);
+ }
+ SAFE_FREE(&szOldComment);
+ }
+ else if (strlennull(pszComment) > 0)
+ {
+ UniWriteContactSettingUtf(hContact, "UserInfo", "MyNotes", pszComment);
+ }
+ }
+ SAFE_FREE(&pszComment);
+ }
+ else
+ {
+ NetLog_Server("Invalid comment");
+ }
+ }
+
+ // Look for need-authorization TLV
+ if (getTLV(pChain, SSI_TLV_AWAITING_AUTH, 1))
+ {
+ ICQWriteContactSettingByte(hContact, "Auth", 1);
+ NetLog_Server("SSI contact need authorization");
+ }
+ else
+ {
+ ICQWriteContactSettingByte(hContact, "Auth", 0);
+ }
+
+ { // store server-list item's TLV data
+ unsigned char* data = (unsigned char*)SAFE_MALLOC(wTlvLength);
+ int datalen = getServerDataFromItemTLV(pChain, data);
+
+ if (datalen > 0)
+ ICQWriteContactSettingBlob(hContact, "ServerData", data, datalen);
+ else
+ ICQDeleteContactSetting(hContact, "ServerData");
+
+ SAFE_FREE(&data);
+ }
+ }
+ }
+ else
+ { // failed to add or other error
+ NetLog_Server("SSI failed to handle %s Item '%s'", "Buddy", szRecordName);
+ }
+ }
+ break;
+
+ case SSI_ITEM_GROUP:
+ if ((wGroupId == 0) && (wItemId == 0))
+ {
+ /* list of groups. wTlvType=1, data is TLV(C8) containing list of WORDs which */
+ /* is the group ids
+ /* we don't need to use this. Our processing is on-the-fly */
+ /* this record is always sent first in the first packet only, */
+ }
+ else if (wGroupId != 0)
+ {
+ /* wGroupId != 0: a group record */
+ if (wItemId == 0)
+ { /* no item ID: this is a group */
+ /* pszRecordName is the name of the group */
+ char* pszName = NULL;
+
+ ReserveServerID(wGroupId, SSIT_GROUP);
+
+ setServerGroupNameUtf(wGroupId, szRecordName);
+
+ NetLog_Server("Group %s added to known groups.", szRecordName);
+
+ /* demangle full grouppath, create groups, set it to known */
+ pszName = makeGroupPathUtf(wGroupId);
+ SAFE_FREE(&pszName);
+
+ /* TLV contains a TLV(C8) with a list of WORDs of contained contact IDs */
+ /* our processing is good enough that we don't need this duplication */
+ }
+ else
+ {
+ NetLog_Server("Unhandled type 0x01, wItemID != 0");
+ }
+ }
+ else
+ {
+ NetLog_Server("Unhandled type 0x01");
+ }
+ break;
+
+ case SSI_ITEM_PERMIT:
+ {
+ /* item on visible list */
+ /* wItemId not related to contact ID */
+ /* pszRecordName is the UIN */
+ HANDLE hContact;
+ int bAdded;
+
+ hContact = HContactFromRecordName(szRecordName, &bAdded);
+
+ if (hContact != INVALID_HANDLE_VALUE)
+ {
+ if (bAdded)
+ {
+ NetLog_Server("SSI added new %s contact '%s'", "Permit", szRecordName);
+ // It wasn't previously in the list, we hide it so it only appears in the visible list
+ SetContactHidden(hContact, 1);
+ // Add it to the list, so it can be added properly if proper contact
+ AddJustAddedContact(hContact);
+ }
+ else
+ NetLog_Server("SSI %s contact already exists '%s'", "Permit", szRecordName);
+
+ // Save permit ID
+ ICQWriteContactSettingWord(hContact, "SrvPermitId", wItemId);
+ ReserveServerID(wItemId, SSIT_ITEM);
+ // Set apparent mode
+ ICQWriteContactSettingWord(hContact, "ApparentMode", ID_STATUS_ONLINE);
+ NetLog_Server("Visible-contact (%s)", szRecordName);
+ }
+ else
+ { // failed to add or other error
+ NetLog_Server("SSI failed to handle %s Item '%s'", "Permit", szRecordName);
+ }
+ }
+ break;
+
+ case SSI_ITEM_DENY:
+ {
+ /* Item on invisible list */
+ /* wItemId not related to contact ID */
+ /* pszRecordName is the UIN */
+ HANDLE hContact;
+ int bAdded;
+
+ hContact = HContactFromRecordName(szRecordName, &bAdded);
+
+ if (hContact != INVALID_HANDLE_VALUE)
+ {
+ if (bAdded)
+ {
+ /* not already on list: added */
+ NetLog_Server("SSI added new %s contact '%s'", "Deny", szRecordName);
+ // It wasn't previously in the list, we hide it so it only appears in the visible list
+ SetContactHidden(hContact, 1);
+ // Add it to the list, so it can be added properly if proper contact
+ AddJustAddedContact(hContact);
+ }
+ else
+ NetLog_Server("SSI %s contact already exists '%s'", "Deny", szRecordName);
+
+ // Save Deny ID
+ ICQWriteContactSettingWord(hContact, "SrvDenyId", wItemId);
+ ReserveServerID(wItemId, SSIT_ITEM);
+
+ // Set apparent mode
+ ICQWriteContactSettingWord(hContact, "ApparentMode", ID_STATUS_OFFLINE);
+ NetLog_Server("Invisible-contact (%s)", szRecordName);
+ }
+ else
+ { // failed to add or other error
+ NetLog_Server("SSI failed to handle %s Item '%s'", "Deny", szRecordName);
+ }
+ }
+ break;
+
+ case SSI_ITEM_VISIBILITY: /* My visibility settings */
+ {
+ BYTE bVisibility;
+
+ ReserveServerID(wItemId, SSIT_ITEM);
+
+ // Look for visibility TLV
+ if (bVisibility = getByteFromChain(pChain, SSI_TLV_VISIBILITY, 1))
+ { // found it, store the id, we do not need current visibility - we do not rely on it
+ ICQWriteContactSettingWord(NULL, "SrvVisibilityID", wItemId);
+ NetLog_Server("Visibility is %u", bVisibility);
+ }
+ }
+ break;
+
+ case SSI_ITEM_IGNORE:
+ {
+ /* item on ignore list */
+ /* wItemId not related to contact ID */
+ /* pszRecordName is the UIN */
+ HANDLE hContact;
+ int bAdded;
+
+ hContact = HContactFromRecordName(szRecordName, &bAdded);
+
+ if (hContact != INVALID_HANDLE_VALUE)
+ {
+ if (bAdded)
+ {
+ /* not already on list: add */
+ NetLog_Server("SSI added new %s contact '%s'", "Ignore", szRecordName);
+ // It wasn't previously in the list, we hide it
+ SetContactHidden(hContact, 1);
+ // Add it to the list, so it can be added properly if proper contact
+ AddJustAddedContact(hContact);
+ }
+ else
+ NetLog_Server("SSI %s contact already exists '%s'", "Ignore", szRecordName);
+
+ // Save Ignore ID
+ ICQWriteContactSettingWord(hContact, "SrvIgnoreId", wItemId);
+ ReserveServerID(wItemId, SSIT_ITEM);
+
+ // Set apparent mode & ignore
+ ICQWriteContactSettingWord(hContact, "ApparentMode", ID_STATUS_OFFLINE);
+ // set ignore all events
+ DBWriteContactSettingDword(hContact, "Ignore", "Mask1", 0xFFFF);
+ NetLog_Server("Ignore-contact (%s)", szRecordName);
+ }
+ else
+ { // failed to add or other error
+ NetLog_Server("SSI failed to handle %s Item '%s'", "Ignore", szRecordName);
+ }
+ }
+ break;
+
+ case SSI_ITEM_UNKNOWN2:
+ NetLog_Server("SSI unknown type 0x11");
+ break;
+
+ case SSI_ITEM_IMPORTTIME:
+ if (wGroupId == 0)
+ {
+ /* time our list was first imported */
+ /* pszRecordName is "Import Time" */
+ /* data is TLV(13) {TLV(D4) {time_t importTime}} */
+ ICQWriteContactSettingDword(NULL, "ImportTS", getDWordFromChain(pChain, SSI_TLV_TIMESTAMP, 1));
+ ICQWriteContactSettingWord(NULL, "SrvImportID", wItemId);
+ NetLog_Server("SSI first import recognized");
+ }
+ break;
+
+ case SSI_ITEM_BUDDYICON:
+ if (wGroupId == 0)
+ {
+ /* our avatar MD5-hash */
+ /* pszRecordName is "1" */
+ /* data is TLV(D5) hash */
+ /* we ignore this, just save the id */
+ /* cause we get the hash again after login */
+ ReserveServerID(wItemId, SSIT_ITEM);
+ ICQWriteContactSettingWord(NULL, "SrvAvatarID", wItemId);
+ NetLog_Server("SSI Avatar item recognized");
+ }
+ break;
+
+ case SSI_ITEM_UNKNOWN1:
+ if (wGroupId == 0)
+ {
+ /* ICQ2k ShortcutBar Items */
+ /* data is TLV(CD) text */
+ }
+
+ default:
+ NetLog_Server("SSI unhandled item %2x", wTlvType);
+ break;
+ }
+
+ if (pChain)
+ disposeChain(&pChain);
+
+ } // end for
+
+ NetLog_Server("Bytes left: %u", wLen);
+
+ ICQWriteContactSettingWord(NULL, "SrvRecordCount", (WORD)(wRecord + ICQGetContactSettingWord(NULL, "SrvRecordCount", 0)));
+
+ if (bIsLastPacket)
+ {
+ // No contacts left to sync
+ bIsSyncingCL = FALSE;
+
+ icq_RescanInfoUpdate();
+
+ if (wLen >= 4)
+ {
+ DWORD dwLastUpdateTime;
+
+ /* finally we get a time_t of the last update time */
+ unpackDWord(&buf, &dwLastUpdateTime);
+ ICQWriteContactSettingDword(NULL, "SrvLastUpdate", dwLastUpdateTime);
+ NetLog_Server("Last update of server list was (%u) %s", dwLastUpdateTime, asctime(localtime(&dwLastUpdateTime)));
+
+ sendRosterAck();
+ handleServUINSettings(wListenPort, info);
+ }
+ else
+ {
+ NetLog_Server("Last packet missed update time...");
+ }
+ if (ICQGetContactSettingWord(NULL, "SrvRecordCount", 0) == 0)
+ { // we got empty serv-list, create master group
+ servlistcookie* ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (ack)
+ {
+ DWORD seq;
+
+ ack->dwAction = SSA_GROUP_UPDATE;
+ ack->szGroupName = "";
+ seq = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, 0, ack);
+ icq_sendGroupUtf(seq, ICQ_LISTS_ADDTOLIST, 0, ack->szGroupName, NULL, 0);
+ }
+ }
+ // serv-list sync finished, clear just added contacts
+ FlushJustAddedContacts();
+ }
+ else
+ {
+ NetLog_Server("Waiting for more packets");
+ }
+}
+
+
+
+static void handleRecvAuthRequest(unsigned char *buf, WORD wLen)
+{
+ WORD wReasonLen;
+ DWORD dwUin;
+ uid_str szUid;
+ HANDLE hcontact;
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ char* szReason;
+ int nReasonLen;
+ char* szNick;
+ int nNickLen;
+ char* szBlob;
+ char* pCurBlob;
+ DBVARIANT dbv;
+ int bAdded;
+
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) return;
+
+ if (dwUin && IsOnSpammerList(dwUin))
+ {
+ NetLog_Server("Ignored Message from known Spammer");
+ return;
+ }
+
+ unpackWord(&buf, &wReasonLen);
+ wLen -= 2;
+ if (wReasonLen > wLen)
+ return;
+
+ hcontact = HContactFromUID(dwUin, szUid, &bAdded);
+
+ ccs.szProtoService=PSR_AUTH;
+ ccs.hContact=hcontact;
+ ccs.wParam=0;
+ ccs.lParam=(LPARAM)⪯
+ pre.flags=0;
+ pre.timestamp=time(NULL);
+ pre.lParam=sizeof(DWORD)+sizeof(HANDLE)+wReasonLen+5;
+ szReason = (char*)SAFE_MALLOC(wReasonLen+1);
+ if (szReason)
+ {
+ memcpy(szReason, buf, wReasonLen);
+ szReason[wReasonLen] = '\0';
+ szReason = detect_decode_utf8(szReason); // detect & decode UTF-8
+ }
+ nReasonLen = strlennull(szReason);
+ // Read nick name from DB
+ if (dwUin)
+ {
+ if (ICQGetContactSetting(hcontact, "Nick", &dbv))
+ nNickLen = 0;
+ else
+ {
+ szNick = dbv.pszVal;
+ nNickLen = strlennull(szNick);
+ }
+ }
+ else
+ nNickLen = strlennull(szUid);
+ pre.lParam += nNickLen + nReasonLen;
+
+ ICQWriteContactSettingByte(ccs.hContact, "Grant", 1);
+
+ /*blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ), reason(ASCIIZ)*/
+ pCurBlob=szBlob=(char *)_alloca(pre.lParam);
+ memcpy(pCurBlob,&dwUin,sizeof(DWORD)); pCurBlob+=sizeof(DWORD);
+ memcpy(pCurBlob,&hcontact,sizeof(HANDLE)); pCurBlob+=sizeof(HANDLE);
+ if (nNickLen && dwUin)
+ { // if we have nick we add it, otherwise keep trailing zero
+ memcpy(pCurBlob, szNick, nNickLen);
+ pCurBlob+=nNickLen;
+ }
+ else
+ {
+ memcpy(pCurBlob, szUid, nNickLen);
+ pCurBlob+=nNickLen;
+ }
+ *(char *)pCurBlob = 0; pCurBlob++;
+ *(char *)pCurBlob = 0; pCurBlob++;
+ *(char *)pCurBlob = 0; pCurBlob++;
+ *(char *)pCurBlob = 0; pCurBlob++;
+ if (nReasonLen)
+ {
+ memcpy(pCurBlob, szReason, nReasonLen);
+ pCurBlob += nReasonLen;
+ }
+ else
+ {
+ memcpy(pCurBlob, buf, wReasonLen);
+ pCurBlob += wReasonLen;
+ }
+ *(char *)pCurBlob = 0;
+ pre.szMessage=(char *)szBlob;
+
+// TODO: Change for new auth system, include all known informations
+ CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
+
+ SAFE_FREE(&szReason);
+ ICQFreeVariant(&dbv);
+
+ SkinPlaySound("AuthRequest"); // Added by BM
+ icq_SetUserStatus(dwUin, 0, 26);
+
+ return;
+}
+
+
+
+static void handleRecvAdded(unsigned char *buf, WORD wLen)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ DBEVENTINFO dbei;
+ PBYTE pCurBlob;
+ HANDLE hContact;
+ int bAdded;
+ char* szNick;
+ int nNickLen;
+ DBVARIANT dbv;
+
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) return;
+
+ if (dwUin && IsOnSpammerList(dwUin))
+ {
+ NetLog_Server("Ignored Message from known Spammer");
+ return;
+ }
+
+ hContact=HContactFromUID(dwUin, szUid, &bAdded);
+
+ ICQDeleteContactSetting(hContact, "Grant");
+
+ ZeroMemory(&dbei,sizeof(dbei));
+ dbei.cbSize=sizeof(dbei);
+ dbei.szModule=gpszICQProtoName;
+ dbei.timestamp=time(NULL);
+ dbei.flags=0;
+ dbei.eventType=EVENTTYPE_ADDED;
+ dbei.cbBlob=sizeof(DWORD)+sizeof(HANDLE)+4;
+
+ if (dwUin)
+ {
+ if (ICQGetContactSetting(hContact, "Nick", &dbv))
+ nNickLen = 0;
+ else
+ {
+ szNick = dbv.pszVal;
+ nNickLen = strlennull(szNick);
+ }
+ }
+ else
+ nNickLen = strlennull(szUid);
+
+ dbei.cbBlob += nNickLen;
+
+ pCurBlob=dbei.pBlob=(PBYTE)_alloca(dbei.cbBlob);
+ /*blob is: uin(DWORD), hContact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ) */
+ memcpy(pCurBlob,&dwUin,sizeof(DWORD)); pCurBlob+=sizeof(DWORD);
+ memcpy(pCurBlob,&hContact,sizeof(HANDLE)); pCurBlob+=sizeof(HANDLE);
+ if (nNickLen && dwUin)
+ { // if we have nick we add it, otherwise keep trailing zero
+ memcpy(pCurBlob, szNick, nNickLen);
+ pCurBlob+=nNickLen;
+ }
+ else
+ {
+ memcpy(pCurBlob, szUid, nNickLen);
+ pCurBlob+=nNickLen;
+ }
+ *(char *)pCurBlob = 0; pCurBlob++;
+ *(char *)pCurBlob = 0; pCurBlob++;
+ *(char *)pCurBlob = 0; pCurBlob++;
+ *(char *)pCurBlob = 0;
+// TODO: Change for new auth system
+
+ CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&dbei);
+
+ SkinPlaySound("YouWereAdded"); // Added by BM
+}
+
+
+
+static void handleRecvAuthResponse(unsigned char *buf, WORD wLen)
+{
+ BYTE bResponse;
+ DWORD dwUin;
+ uid_str szUid;
+ HANDLE hContact;
+ char* szNick;
+ WORD nReasonLen;
+ char* szReason;
+ int bAdded;
+
+ bResponse = 0xFF;
+
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) return;
+
+ if (dwUin && IsOnSpammerList(dwUin))
+ {
+ NetLog_Server("Ignored Message from known Spammer");
+ return;
+ }
+
+ hContact = HContactFromUID(dwUin, szUid, &bAdded);
+
+ if (hContact != INVALID_HANDLE_VALUE) szNick = NickFromHandle(hContact);
+
+ if (wLen > 0)
+ {
+ unpackByte(&buf, &bResponse);
+ wLen -= 1;
+ }
+ if (wLen >= 2)
+ {
+ unpackWord(&buf, &nReasonLen);
+ wLen -= 2;
+ if (wLen >= nReasonLen)
+ {
+ szReason = (char*)_alloca(nReasonLen+1);
+ unpackString(&buf, szReason, nReasonLen);
+ szReason[nReasonLen] = '\0';
+ }
+ }
+
+ switch (bResponse)
+ {
+
+ case 0:
+ NetLog_Server("Authorization request %s by %s", "denied", strUID(dwUin, szUid));
+ // TODO: Add to system history as soon as new auth system is ready
+ break;
+
+ case 1:
+ ICQWriteContactSettingByte(hContact, "Auth", 0);
+ NetLog_Server("Authorization request %s by %s", "granted", strUID(dwUin, szUid));
+ // TODO: Add to system history as soon as new auth system is ready
+ break;
+
+ default:
+ NetLog_Server("Unknown Authorization request response (%u) from %s", bResponse, strUID(dwUin, szUid));
+ break;
+
+ }
+ SAFE_FREE(&szNick);
+}
+
+
+
+// Updates the visibility code used while in SSI mode. If a server ID is
+// not stored in the local DB, a new ID will be added to the server list.
+//
+// Possible values are:
+// 01 - Allow all users to see you
+// 02 - Block all users from seeing you
+// 03 - Allow only users in the permit list to see you
+// 04 - Block only users in the invisible list from seeing you
+// 05 - Allow only users in the buddy list to see you
+//
+void updateServVisibilityCode(BYTE bCode)
+{
+ icq_packet packet;
+ WORD wVisibilityID;
+ WORD wCommand;
+ int special = 0;
+
+
+ servlistcookie* ack;
+ DWORD dwCookie;
+ BYTE bVisibility = ICQGetContactSettingByte(NULL, "SrvVisibility", 0);
+
+ if (gbVisibility)
+ bCode = gbVisibility;
+
+ // add by Se7ven
+ if (bCode == 6)
+ {
+ bCode = 3;
+ special = 1;
+ }
+
+//
+ if ((bCode > 0) && (bCode < 6))
+ {
+// add by Se7ven
+ if (special)
+ sendVisListServ(1);
+//
+ if (bVisibility == bCode) // if no change was made, not necescary to update that
+ return;
+ ICQWriteContactSettingByte(NULL, "SrvVisibility", bCode);
+
+ // Do we have a known server visibility ID? We should, unless we just subscribed to the serv-list for the first time
+ if ((wVisibilityID = ICQGetContactSettingWord(NULL, "SrvVisibilityID", 0)) == 0)
+ {
+ // No, create a new random ID
+ wVisibilityID = GenerateServerId(SSIT_ITEM);
+ ICQWriteContactSettingWord(NULL, "SrvVisibilityID", wVisibilityID);
+ wCommand = ICQ_LISTS_ADDTOLIST;
+ NetLog_Server("Made new srvVisibilityID, id is %u, code is %u", wVisibilityID, bCode);
+ }
+ else
+ {
+ NetLog_Server("Reused srvVisibilityID, id is %u, code is %u", wVisibilityID, bCode);
+ wCommand = ICQ_LISTS_UPDATEGROUP;
+ }
+
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (!ack)
+ {
+ NetLog_Server("Cookie alloc failure.");
+ return; // out of memory, go away
+ }
+ ack->dwAction = SSA_VISIBILITY; // update visibility
+ dwCookie = AllocateCookie(CKT_SERVERLIST, wCommand, 0, ack); // take cookie
+
+ // Build and send packet
+ serverPacketInit(&packet, 25);
+ packFNACHeaderFull(&packet, ICQ_LISTS_FAMILY, wCommand, 0, dwCookie);
+
+ packWord(&packet, 0); // Name (null)
+ packWord(&packet, 0); // GroupID (0 if not relevant)
+ packWord(&packet, wVisibilityID); // EntryID
+ packWord(&packet, SSI_ITEM_VISIBILITY); // EntryType
+ packWord(&packet, 5); // Length in bytes of following TLV
+ packTLV(&packet, SSI_TLV_VISIBILITY, 1, &bCode); // TLV (Visibility)
+ sendServPacket(&packet);
+ // There is no need to send ICQ_LISTS_CLI_MODIFYSTART or
+ // ICQ_LISTS_CLI_MODIFYEND when modifying the visibility code
+//
+ if (!special)
+ sendVisListServ(0);
+//
+ }
+}
+
+
+
+// Updates the avatar hash used while in SSI mode. If a server ID is
+// not stored in the local DB, a new ID will be added to the server list.
+void updateServAvatarHash(char* pHash, int size)
+{
+ icq_packet packet;
+ WORD wAvatarID;
+ WORD wCommand;
+ DBVARIANT dbvHash;
+ int bResetHash = 0;
+ BYTE bName = 0;
+
+ if (!ICQGetContactSetting(NULL, "AvatarHash", &dbvHash))
+ {
+ bName = 0x30 + dbvHash.pbVal[1];
+
+ if (memcmp(pHash, dbvHash.pbVal, 2) != 0)
+ {
+ /** add code to remove old hash from server */
+ bResetHash = 1;
+ }
+ ICQFreeVariant(&dbvHash);
+ }
+
+ if (bResetHash) // start update session
+ sendAddStart(FALSE);
+
+ if (bResetHash || !pHash)
+ {
+ servlistcookie* ack;
+ DWORD dwCookie;
+
+ // Do we have a known server avatar ID?
+ if (wAvatarID = ICQGetContactSettingWord(NULL, "SrvAvatarID", 0))
+ {
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (!ack)
+ {
+ NetLog_Server("Cookie alloc failure.");
+ return; // out of memory, go away
+ }
+ ack->dwAction = SSA_REMOVEAVATAR; // update avatar hash
+ ack->wContactId = wAvatarID;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, 0, ack); // take cookie
+
+ // Build and send packet
+ serverPacketInit(&packet, (WORD)(20 + (bName ? 1 : 0)));
+ packFNACHeaderFull(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_REMOVEFROMLIST, 0, dwCookie);
+ if (bName)
+ { // name
+ packWord(&packet, 1);
+ packByte(&packet, bName); // Name
+ }
+ else
+ packWord(&packet, 0); // Name (null)
+ packWord(&packet, 0); // GroupID (0 if not relevant)
+ packWord(&packet, wAvatarID); // EntryID
+ packWord(&packet, SSI_ITEM_BUDDYICON); // EntryType
+ packWord(&packet, 0); // Length in bytes of following TLV
+ sendServPacket(&packet);
+ }
+ }
+
+ if (pHash)
+ {
+ servlistcookie* ack;
+ DWORD dwCookie;
+ WORD hashsize = size - 2;
+
+ // Do we have a known server avatar ID? We should, unless we just subscribed to the serv-list for the first time
+ if (bResetHash || (wAvatarID = ICQGetContactSettingWord(NULL, "SrvAvatarID", 0)) == 0)
+ {
+ // No, create a new random ID
+ wAvatarID = GenerateServerId(SSIT_ITEM);
+ wCommand = ICQ_LISTS_ADDTOLIST;
+ NetLog_Server("Made new srvAvatarID, id is %u", wAvatarID);
+ }
+ else
+ {
+ NetLog_Server("Reused srvAvatarID, id is %u", wAvatarID);
+ wCommand = ICQ_LISTS_UPDATEGROUP;
+ }
+
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (!ack)
+ {
+ NetLog_Server("Cookie alloc failure.");
+ return; // out of memory, go away
+ }
+ ack->dwAction = SSA_SETAVATAR; // update avatar hash
+ ack->wContactId = wAvatarID;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, wCommand, 0, ack); // take cookie
+
+ // Build and send packet
+ serverPacketInit(&packet, (WORD)(29 + hashsize));
+ packFNACHeaderFull(&packet, ICQ_LISTS_FAMILY, wCommand, 0, dwCookie);
+ packWord(&packet, 1); // Name length
+ packByte(&packet, (BYTE)(0x30 + pHash[1])); // Name
+ packWord(&packet, 0); // GroupID (0 if not relevant)
+ packWord(&packet, wAvatarID); // EntryID
+ packWord(&packet, SSI_ITEM_BUDDYICON); // EntryType
+ packWord(&packet, (WORD)(0x8 + hashsize)); // Length in bytes of following TLV
+ packTLV(&packet, SSI_TLV_NAME, 0, NULL); // TLV (Name)
+ packTLV(&packet, SSI_TLV_AVATARHASH, hashsize, pHash + 2); // TLV (Hash)
+ sendServPacket(&packet);
+ // There is no need to send ICQ_LISTS_CLI_MODIFYSTART or
+ // ICQ_LISTS_CLI_MODIFYEND when modifying the avatar hash
+ }
+
+ if (bResetHash) // finish update session
+ sendAddEnd();
+}
+
+
+
+// Should be called before the server list is modified. When all
+// modifications are done, call sendAddEnd().
+void sendAddStart(int bImport)
+{
+ icq_packet packet;
+ WORD wImportID = ICQGetContactSettingWord(NULL, "SrvImportID", 0);
+
+ if (bImport && wImportID)
+ { // we should be importing, check if already have import item
+ if (ICQGetContactSettingDword(NULL, "ImportTS", 0) + 604800 < ICQGetContactSettingDword(NULL, "LogonTS", 0))
+ { // is the timestamp week older, clear it and begin new import
+ DWORD dwCookie;
+ servlistcookie* ack;
+
+ if (ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie)))
+ { // we have cookie good, go on
+ ack->dwAction = SSA_IMPORT;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, 0, ack);
+
+ icq_sendSimpleItem(dwCookie, ICQ_LISTS_REMOVEFROMLIST, 0, "ImportTime", 0, wImportID, SSI_ITEM_IMPORTTIME);
+ }
+ }
+ }
+
+ serverPacketInit(&packet, (WORD)(bImport?14:10));
+ packFNACHeader(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_CLI_MODIFYSTART);
+ if (bImport) packDWord(&packet, 1<<0x10);
+ sendServPacket(&packet);
+}
+
+
+
+// Should be called after the server list has been modified to inform
+// the server that we are done.
+void sendAddEnd(void)
+{
+ icq_packet packet;
+
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_CLI_MODIFYEND);
+ sendServPacket(&packet);
+}
+
+
+
+// Sent when the last roster packet has been received
+void sendRosterAck(void)
+{
+ icq_packet packet;
+
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_GOTLIST);
+ sendServPacket(&packet);
+
+#ifdef _DEBUG
+ NetLog_Server("Sent SNAC(x13,x07) - CLI_ROSTERACK");
+#endif
+}
diff --git a/icqj_mod/fam_15icqserver.c b/icqj_mod/fam_15icqserver.c new file mode 100644 index 0000000..1a93212 --- /dev/null +++ b/icqj_mod/fam_15icqserver.c @@ -0,0 +1,1109 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_15icqserver.c,v $
+// Revision : $Revision: 2991 $
+// Last change on : $Date: 2006-05-30 19:55:48 +0200 (Tue, 30 May 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+static void handleExtensionError(unsigned char *buf, WORD wPackLen);
+static void handleExtensionServerInfo(unsigned char *buf, WORD wPackLen, WORD wFlags);
+static void parseOfflineMessage(unsigned char *databuf, WORD wPacketLen);
+static void parseEndOfOfflineMessages(unsigned char *databuf, WORD wPacketLen);
+static void handleExtensionMetaResponse(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wFlags);
+static void parseSearchReplies(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype, BYTE bResultCode);
+static void parseUserInfoRequestReplies(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wFlags, WORD wReplySubtype, BYTE bResultCode);
+static void parseUserInfoUpdateAck(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype, BYTE bResultCode);
+
+
+
+void handleIcqExtensionsFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+
+ case ICQ_META_ERROR:
+ handleExtensionError(pBuffer, wBufferLength);
+ break;
+
+ case ICQ_META_SRV_REPLY:
+ handleExtensionServerInfo(pBuffer, wBufferLength, pSnacHeader->wFlags);
+ break;
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_EXTENSIONS_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+ }
+}
+
+
+
+static void handleExtensionError(unsigned char *buf, WORD wPackLen)
+{
+ WORD wErrorCode;
+
+ if (wPackLen < 2)
+ {
+ wErrorCode = 0;
+ }
+ if (wPackLen >= 2 && wPackLen <= 6)
+ {
+ unpackWord(&buf, &wErrorCode);
+ }
+ else
+ { // TODO: cookies need to be handled and freed here on error
+ oscar_tlv_chain *chain = NULL;
+
+ unpackWord(&buf, &wErrorCode);
+ wPackLen -= 2;
+ chain = readIntoTLVChain(&buf, wPackLen, 0);
+ if (chain)
+ {
+ oscar_tlv* pTLV;
+
+ pTLV = getTLV(chain, 0x21, 1); // get meta error data
+ if (pTLV && pTLV->wLen >= 8)
+ {
+ unsigned char* pBuffer = pTLV->pData;
+ WORD wData;
+ pBuffer += 6;
+ unpackLEWord(&pBuffer, &wData); // get request type
+ switch (wData)
+ {
+ case CLI_OFFLINE_MESSAGE_REQ:
+ NetLog_Server("Offline messages request failed with error 0x%02x", wData, wErrorCode);
+ break;
+
+ case CLI_DELETE_OFFLINE_MSGS_REQ:
+ NetLog_Server("Deleting offline messages from server failed with error 0x%02x", wErrorCode);
+ icq_LogMessage(LOG_WARNING, "Deleting Offline Messages from server failed.\nYou will probably receive them again.");
+ break;
+
+ case CLI_META_INFO_REQ:
+ if (pTLV->wLen >= 12)
+ {
+ WORD wSubType;
+ WORD wCookie;
+
+ unpackWord(&pBuffer, &wCookie);
+ unpackLEWord(&pBuffer, &wSubType);
+ // more sofisticated detection, send ack
+ if (wSubType == META_REQUEST_FULL_INFO)
+ {
+ DWORD dwCookieUin;
+ fam15_cookie_data* pCookieData = NULL;
+ int foundCookie;
+
+ foundCookie = FindCookie(wCookie, &dwCookieUin, (void**)&pCookieData);
+ if (foundCookie && pCookieData)
+ {
+ HANDLE hContact = HContactFromUIN(dwCookieUin, NULL);
+ ICQBroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_FAILED, (HANDLE)1 ,0);
+
+ ReleaseCookie(wCookie); // we do not leak cookie and memory
+ }
+
+ NetLog_Server("Full info request error 0x%02x received", wErrorCode);
+ }
+ }
+ else
+ NetLog_Server("Meta request error 0x%02x received", wErrorCode);
+
+ break;
+
+ default:
+ NetLog_Server("Unknown request 0x%02x error 0x%02x received", wData, wErrorCode);
+ }
+ disposeChain(&chain);
+ return;
+ }
+ disposeChain(&chain);
+ }
+ }
+ LogFamilyError(ICQ_EXTENSIONS_FAMILY, wErrorCode);
+}
+
+
+
+static void handleExtensionServerInfo(unsigned char *buf, WORD wPackLen, WORD wFlags)
+{
+ WORD wBytesRemaining;
+ WORD wRequestType;
+ WORD wCookie;
+ DWORD dwMyUin;
+ oscar_tlv_chain* chain;
+ oscar_tlv* dataTlv;
+ unsigned char* databuf;
+
+
+ // The entire packet is encapsulated in a TLV type 1
+ chain = readIntoTLVChain(&buf, wPackLen, 0);
+ if (chain == NULL)
+ {
+ NetLog_Server("Error: Broken snac 15/3 %d", 1);
+ return;
+ }
+
+ dataTlv = getTLV(chain, 0x0001, 1);
+ if (dataTlv == NULL)
+ {
+ disposeChain(&chain);
+ NetLog_Server("Error: Broken snac 15/3 %d", 2);
+ return;
+ }
+ databuf = dataTlv->pData;
+ wPackLen -= 4;
+
+ _ASSERTE(dataTlv->wLen == wPackLen);
+ _ASSERTE(wPackLen >= 10);
+
+ if ((dataTlv->wLen == wPackLen) && (wPackLen >= 10))
+ {
+ unpackLEWord(&databuf, &wBytesRemaining);
+ unpackLEDWord(&databuf, &dwMyUin);
+ unpackLEWord(&databuf, &wRequestType);
+ unpackWord(&databuf, &wCookie);
+
+ _ASSERTE(wBytesRemaining == (wPackLen - 2));
+ if (wBytesRemaining == (wPackLen - 2))
+ {
+ wPackLen -= 10;
+ switch (wRequestType)
+ {
+ case SRV_OFFLINE_MESSAGE: // This is an offline message
+ parseOfflineMessage(databuf, wPackLen);
+ break;
+
+ case SRV_END_OF_OFFLINE_MSGS: // This packets marks the end of offline messages
+ parseEndOfOfflineMessages(databuf, wPackLen);
+ break;
+
+ case SRV_META_INFO_REPLY: // SRV_META request replies
+ handleExtensionMetaResponse(databuf, wPackLen, wCookie, wFlags);
+ break;
+ }
+ }
+ }
+ else
+ {
+ NetLog_Server("Error: Broken snac 15/3 %d", 3);
+ }
+
+ if (chain)
+ disposeChain(&chain);
+}
+
+
+
+static void parseOfflineMessage(unsigned char *databuf, WORD wPacketLen)
+{
+ _ASSERTE(wPacketLen >= 14);
+ if (wPacketLen >= 14)
+ {
+ DWORD dwUin;
+ DWORD dwTimestamp;
+ WORD wYear;
+ WORD wMsgLen;
+ BYTE nMonth;
+ BYTE nDay;
+ BYTE nHour;
+ BYTE nMinute;
+ BYTE bType;
+ BYTE bFlags;
+
+
+ unpackLEDWord(&databuf, &dwUin);
+ unpackLEWord(&databuf, &wYear);
+ unpackByte(&databuf, &nMonth);
+ unpackByte(&databuf, &nDay);
+ unpackByte(&databuf, &nHour);
+ unpackByte(&databuf, &nMinute);
+ unpackByte(&databuf, &bType);
+ unpackByte(&databuf, &bFlags);
+ unpackLEWord(&databuf, &wMsgLen);
+ wPacketLen -=14;
+
+
+ NetLog_Server("Offline message time: %u-%u-%u %u:%u", wYear, nMonth, nDay, nHour, nMinute);
+ NetLog_Server("Offline message type %u from %u", bType, dwUin);
+
+ _ASSERTE(wMsgLen == wPacketLen);
+ if (wMsgLen == wPacketLen)
+ {
+ struct tm *sentTm;
+
+ // Hack around the timezone problem
+ // This is probably broken in some countries
+ // but I'll leave it like this for now (todo)
+ time(&dwTimestamp);
+ sentTm = gmtime(&dwTimestamp);
+ sentTm->tm_sec = 28800;
+ sentTm->tm_min = nMinute;
+ sentTm->tm_hour = nHour;
+ sentTm->tm_mday = nDay;
+ sentTm->tm_mon = nMonth - 1;
+ sentTm->tm_year = wYear - 1900;
+ mktime(sentTm);
+
+ // I *guess* server runs in US time-8 hours.
+ // It might be UK time or something.
+ // More observations reqd at changeover.
+ if ((sentTm->tm_mon > 3 && sentTm->tm_mon < 9)
+ || (sentTm->tm_mon == 3
+ && (sentTm->tm_mday > 7
+ || (sentTm->tm_wday != 0 && sentTm->tm_mday > sentTm->tm_wday)
+ || (sentTm->tm_wday == 0 && sentTm->tm_hour >= 2)))
+ || (sentTm->tm_mon == 9
+ && (sentTm->tm_mday < 25
+ || (sentTm->tm_wday != 0 && sentTm->tm_mday < 25 + sentTm->tm_wday)
+ || (sentTm->tm_wday == 0 && sentTm->tm_hour <= 2))))
+ sentTm->tm_hour--;
+
+ sentTm->tm_sec -= 28800 + _timezone;
+ { // _daylight global variable is reversed in southern hemisphere. Silly.
+ TIME_ZONE_INFORMATION tzinfo;
+ if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT)
+ sentTm->tm_hour++;
+ }
+ dwTimestamp = mktime(sentTm);
+
+ // :NOTE:
+ // This is a check for the problem with offline messages being marked
+ // with the wrong year by the server. It can cause other problems when
+ // the internal system clock is incorrect but I think this is the most
+ // generic fix.
+ if (dwTimestamp > (unsigned long)time(NULL))
+ dwTimestamp = time(NULL);
+
+ { // Check if the time is not behind last user event, if yes, get current time
+ HANDLE hContact = HContactFromUIN(dwUin, NULL);
+
+ if (hContact)
+ { // we have contact
+ HANDLE hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0);
+
+ if (hEvent)
+ { // contact has events
+ DBEVENTINFO dbei;
+ DWORD dummy;
+
+ dbei.cbSize = sizeof (DBEVENTINFO);
+ dbei.pBlob = (char*)&dummy;
+ dbei.cbBlob = 2;
+ if (!CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbei))
+ { // got that event, if newer than ts then reset to current time
+ if (dwTimestamp<dbei.timestamp) dwTimestamp = time(NULL);
+ }
+ }
+ }
+ }
+
+ // Handle the actual message
+ handleMessageTypes(dwUin, dwTimestamp, 0, 0, 0, 0, bType, bFlags,
+ 0, wPacketLen, wMsgLen, databuf, FALSE);
+
+ // Success
+ return;
+ }
+ }
+
+ // Failure
+ NetLog_Server("Error: Broken offline message");
+}
+
+
+
+static void parseEndOfOfflineMessages(unsigned char *databuf, WORD wPacketLen)
+{
+ BYTE bMissedMessages = 0;
+ icq_packet packet;
+
+ if (wPacketLen == 1)
+ {
+ unpackByte(&databuf, &bMissedMessages);
+ NetLog_Server("End of offline msgs, %u dropped", bMissedMessages);
+ }
+ else
+ {
+ NetLog_Server("Error: Malformed end of offline msgs");
+ }
+
+ // Send 'got offline msgs'
+ // This will delete the messages stored on server
+ serverPacketInit(&packet, 24);
+ packFNACHeader(&packet, ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQ);
+ packWord(&packet, 1); // TLV Type
+ packWord(&packet, 10); // TLV Length
+ packLEWord(&packet, 8); // Data length
+ packLEDWord(&packet, dwLocalUIN); // My UIN
+ packLEWord(&packet, CLI_DELETE_OFFLINE_MSGS_REQ); // Ack offline msgs
+ packLEWord(&packet, 0x0000); // Request sequence number (we dont use this for now)
+
+ // Send it
+ sendServPacket(&packet);
+}
+
+
+
+static void handleExtensionMetaResponse(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wFlags)
+{
+ WORD wReplySubtype;
+ BYTE bResultCode;
+
+ _ASSERTE(wPacketLen >= 3);
+ if (wPacketLen >= 3)
+ {
+ // Reply subtype
+ unpackLEWord(&databuf, &wReplySubtype);
+ wPacketLen -= 2;
+
+ // Success byte
+ unpackByte(&databuf, &bResultCode);
+ wPacketLen -= 1;
+
+ switch (wReplySubtype)
+ {
+ case META_SET_PASSWORD_ACK:
+ case META_SET_FULLINFO_ACK:
+ parseUserInfoUpdateAck(databuf, wPacketLen, wCookie, wReplySubtype, bResultCode);
+ break;
+
+ case SRV_RANDOM_FOUND:
+ case SRV_USER_FOUND:
+ case SRV_LAST_USER_FOUND:
+ parseSearchReplies(databuf, wPacketLen, wCookie, wReplySubtype, bResultCode);
+ break;
+
+ case META_SHORT_USERINFO:
+ case META_BASIC_USERINFO:
+ case META_WORK_USERINFO:
+ case META_MORE_USERINFO:
+ case META_NOTES_USERINFO:
+ case META_EMAIL_USERINFO:
+ case META_INTERESTS_USERINFO:
+ case META_AFFILATIONS_USERINFO:
+ case META_HPAGECAT_USERINFO:
+ parseUserInfoRequestReplies(databuf, wPacketLen, wCookie, wFlags, wReplySubtype, bResultCode);
+ break;
+
+ case META_PROCESSING_ERROR: // Meta processing error server reply
+ // Todo: We only use this as an SMS ack, that will have to change
+ {
+ char *pszInfo;
+
+ // Terminate buffer
+ pszInfo = (char *)_alloca(wPacketLen + 1);
+ if (wPacketLen > 0)
+ memcpy(pszInfo, databuf, wPacketLen);
+ pszInfo[wPacketLen] = 0;
+
+ ICQBroadcastAck(NULL, ICQACKTYPE_SMS, ACKRESULT_FAILED, (HANDLE)wCookie, (LPARAM)pszInfo);
+ FreeCookie(wCookie);
+ break;
+ }
+ break;
+
+ case META_SMS_DELIVERY_RECEIPT:
+ // Todo: This overlaps with META_SET_AFFINFO_ACK.
+ // Todo: Check what happens if result != A
+ if (wPacketLen > 8)
+ {
+ WORD wNetworkNameLen;
+ WORD wAckLen;
+ char *pszInfo;
+
+
+ databuf += 6; // Some unknowns
+ wPacketLen -= 6;
+
+ unpackWord(&databuf, &wNetworkNameLen);
+ if (wPacketLen >= (wNetworkNameLen + 2))
+ {
+ databuf += wNetworkNameLen;
+ wPacketLen -= wNetworkNameLen;
+
+ unpackWord(&databuf, &wAckLen);
+ if (pszInfo = (char *)_alloca(wAckLen + 1))
+ {
+ // Terminate buffer
+ if (wAckLen > 0)
+ memcpy(pszInfo, databuf, wAckLen);
+ pszInfo[wAckLen] = 0;
+
+ ICQBroadcastAck(NULL, ICQACKTYPE_SMS, ACKRESULT_SENTREQUEST, (HANDLE)wCookie, (LPARAM)pszInfo);
+ FreeCookie(wCookie);
+
+ // Parsing success
+ break;
+ }
+ }
+ }
+
+ // Parsing failure
+ NetLog_Server("Error: Failure parsing META_SMS_DELIVERY_RECEIPT");
+ break;
+
+ default:
+ NetLog_Server("Warning: Ignored 15/03 replysubtype x%x", wReplySubtype);
+// _ASSERTE(0);
+ break;
+ }
+
+ // Success
+ return;
+ }
+
+ // Failure
+ NetLog_Server("Warning: Broken 15/03 ExtensionMetaResponse");
+}
+
+
+
+static void ReleaseSearchCookie(DWORD dwCookie, search_cookie *pCookie)
+{
+ if (pCookie)
+ {
+ FreeCookie(dwCookie);
+ if (pCookie->dwMainId)
+ {
+ if (pCookie->dwStatus)
+ {
+ SAFE_FREE(&pCookie);
+ ICQBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+ }
+ else
+ pCookie->dwStatus = 1;
+ }
+ else
+ {
+ SAFE_FREE(&pCookie);
+ ICQBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+ }
+ }
+ else
+ ICQBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+}
+
+
+
+static void parseSearchReplies(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype, BYTE bResultCode)
+{
+ BYTE bParsingOK = FALSE; // For debugging purposes only
+ BOOL bLastUser = FALSE;
+ search_cookie* pCookie;
+
+ if (!FindCookie(wCookie, NULL, &pCookie))
+ {
+ NetLog_Server("Warning: Received unexpected search reply");
+ pCookie = NULL;
+ }
+
+ switch (wReplySubtype)
+ {
+
+ case SRV_LAST_USER_FOUND: // Search: last user found reply
+ bLastUser = TRUE;
+
+ case SRV_USER_FOUND: // Search: user found reply
+ if (bLastUser)
+ NetLog_Server("SNAC(0x15,0x3): Last search reply");
+ else
+ NetLog_Server("SNAC(0x15,0x3): Search reply");
+
+ if (bResultCode == 0xA)
+ {
+ ICQSEARCHRESULT sr = {0};
+ DWORD dwUin;
+ WORD wLen;
+
+ sr.hdr.cbSize = sizeof(sr);
+
+ // Remaining bytes
+ if (wPacketLen < 2)
+ break;
+ unpackLEWord(&databuf, &wLen);
+ wPacketLen -= 2;
+
+ _ASSERTE(wLen <= wPacketLen);
+ if (wLen > wPacketLen)
+ break;
+
+ // Uin
+ if (wPacketLen < 4)
+ break;
+ unpackLEDWord(&databuf, &dwUin); // Uin
+ wPacketLen -= 4;
+ sr.uin = dwUin;
+
+ // Nick
+ if (wPacketLen < 2)
+ break;
+ unpackLEWord(&databuf, &wLen);
+ wPacketLen -= 2;
+ if (wLen > 0)
+ {
+ if (wPacketLen < wLen || (databuf[wLen-1] != 0))
+ break;
+ sr.hdr.nick = databuf;
+ databuf += wLen;
+ }
+ else
+ {
+ sr.hdr.nick = NULL;
+ }
+
+ // First name
+ if (wPacketLen < 2)
+ break;
+ unpackLEWord(&databuf, &wLen);
+ wPacketLen -= 2;
+ if (wLen > 0)
+ {
+ if (wPacketLen < wLen || (databuf[wLen-1] != 0))
+ break;
+ sr.hdr.firstName = databuf;
+ databuf += wLen;
+ }
+ else
+ {
+ sr.hdr.firstName = NULL;
+ }
+
+ // Last name
+ if (wPacketLen < 2)
+ break;
+ unpackLEWord(&databuf, &wLen);
+ wPacketLen -= 2;
+ if (wLen > 0)
+ {
+ if (wPacketLen < wLen || (databuf[wLen-1] != 0))
+ break;
+ sr.hdr.lastName = databuf;
+ databuf += wLen;
+ }
+ else
+ {
+ sr.hdr.lastName = NULL;
+ }
+
+ // E-mail name
+ if (wPacketLen < 2)
+ break;
+ unpackLEWord(&databuf, &wLen);
+ wPacketLen -= 2;
+ if (wLen > 0)
+ {
+ if (wPacketLen < wLen || (databuf[wLen-1] != 0))
+ break;
+ sr.hdr.email = databuf;
+ databuf += wLen;
+ }
+ else
+ {
+ sr.hdr.email = NULL;
+ }
+
+ // Authentication needed flag
+ if (wPacketLen < 1)
+ break;
+ unpackByte(&databuf, &sr.auth);
+
+ sr.uid = NULL; // icq contact
+ // Finally, broadcast the result
+ ICQBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)wCookie, (LPARAM)&sr);
+
+ // Broadcast "Last result" ack if this was the last user found
+ if (wReplySubtype == SRV_LAST_USER_FOUND)
+ {
+ if (wPacketLen>=10)
+ {
+ DWORD dwLeft;
+
+ databuf += 5;
+ unpackLEDWord(&databuf, &dwLeft);
+ if (dwLeft)
+ NetLog_Server("Warning: %d search results omitted", dwLeft);
+ }
+ ReleaseSearchCookie(wCookie, pCookie);
+ }
+
+ bParsingOK = TRUE;
+ }
+ else
+ {
+ // Failed search
+ NetLog_Server("SNAC(0x15,0x3): Search error %u", bResultCode);
+
+ ReleaseSearchCookie(wCookie, pCookie);
+
+ bParsingOK = TRUE;
+ }
+ break;
+
+ case SRV_RANDOM_FOUND: // Random search server reply
+ default:
+ if (pCookie)
+ {
+ ReleaseCookie(wCookie);
+ }
+ break;
+
+ }
+
+ // For debugging purposes only
+ if (!bParsingOK)
+ {
+ NetLog_Server("Warning: Parsing error in 15/03 search reply type x%x", wReplySubtype);
+ _ASSERTE(!bParsingOK);
+ }
+}
+
+
+
+static void parseUserInfoRequestReplies(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wFlags, WORD wReplySubtype, BYTE bResultCode)
+{
+ BOOL bMoreDataFollows;
+ DWORD dwCookieUin;
+ fam15_cookie_data* pCookieData = NULL;
+ HANDLE hContact = INVALID_HANDLE_VALUE;
+ int foundCookie;
+ BOOL bOK = TRUE;
+
+
+ foundCookie = FindCookie(wCookie, &dwCookieUin, (void**)&pCookieData);
+ if (foundCookie && pCookieData)
+ {
+ if (pCookieData->bRequestType == REQUESTTYPE_OWNER)
+ hContact = NULL; // this is here for situation when we have own uin in clist
+ else
+ hContact = HContactFromUIN(dwCookieUin, NULL);
+ }
+ else
+ {
+ NetLog_Server("Warning: Ignoring unrequested 15/03 user info reply type 0x%x", wReplySubtype);
+
+ return;
+ }
+
+ if (bResultCode != 0x0A)
+ {
+ NetLog_Server("Warning: Got 15/03 user info failure reply type 0x%x", wReplySubtype);
+ }
+
+ // Check if this is the last packet for this request
+ bMoreDataFollows = wFlags&0x0001;
+
+
+ switch (wReplySubtype)
+ {
+
+ case META_BASIC_USERINFO:
+ NetLog_Server("SNAC(0x15,0x3): META_%s_USERINFO for %u", "BASIC", dwCookieUin);
+ if (bResultCode == 0x0A)
+ {
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "Nick", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "FirstName", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "LastName", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "e-mail", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "City", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "State", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "Phone", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "Fax", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "Street", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "Cellular", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "ZIP", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingWord(hContact, "Country", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingByte(hContact, "Timezone", &databuf, &wPacketLen);
+
+ if (bOK && (wPacketLen >= 3))
+ {
+ if (hContact == NULL)
+ {
+ ICQWriteContactSettingByte(hContact, "Auth", (BYTE)!(*databuf));
+ databuf += 1;
+
+ ICQWriteContactSettingByte(hContact, "WebAware", (*databuf));
+ databuf += 1;
+
+ ICQWriteContactSettingByte(hContact, "PublishPrimaryEmail", (BYTE)!(*databuf));
+ databuf += 1;
+ }
+ else
+ databuf += 3;
+
+ wPacketLen -= 3;
+ }
+ if (bOK && (wPacketLen >= 1))
+ {
+ databuf++;
+ wPacketLen--;
+ }
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "ZIP", &databuf, &wPacketLen);
+ }
+ break;
+
+ case META_WORK_USERINFO:
+ NetLog_Server("SNAC(0x15,0x3): META_%s_USERINFO for %u", "WORK", dwCookieUin);
+ if (bResultCode == 0x0A)
+ {
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "CompanyCity", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "CompanyState", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "CompanyPhone", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "CompanyFax", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "CompanyStreet", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "CompanyZIP", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingWord(hContact, "CompanyCountry", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "Company", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "CompanyDepartment",&databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "CompanyPosition", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingWord(hContact, "CompanyOccupation",&databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "CompanyHomepage", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "CompanyZIP", &databuf, &wPacketLen);
+ }
+ break;
+
+ case META_MORE_USERINFO:
+ NetLog_Server("SNAC(0x15,0x3): META_%s_USERINFO for %u", "MORE", dwCookieUin);
+ if (bResultCode == 0x0A)
+ {
+ if (bOK) bOK = writeDbInfoSettingWord(hContact, "Age", &databuf, &wPacketLen);
+ if (bOK && (wPacketLen >= 1))
+ {
+ if (*databuf)
+ ICQWriteContactSettingByte(hContact, "Gender", (BYTE)(*databuf == 1 ? 'F' : 'M'));
+ else
+ // Undefined gender
+ ICQDeleteContactSetting(hContact, "Gender");
+ databuf += 1;
+ wPacketLen -= 1;
+ }
+ else
+ bOK = FALSE;
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "Homepage", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingWord(hContact, "BirthYear", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingByte(hContact, "BirthMonth", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingByte(hContact, "BirthDay", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingByteWithTable(hContact, "Language1", languageField, &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingByteWithTable(hContact, "Language2", languageField, &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingByteWithTable(hContact, "Language3", languageField, &databuf, &wPacketLen);
+
+ if (bOK && (wPacketLen >= 2))
+ {
+ databuf += 2;
+ wPacketLen -= 2;
+ }
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "OriginCity", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "OriginState", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingWord(hContact, "OriginCountry", &databuf, &wPacketLen);
+
+ if (bOK) bOK = writeDbInfoSettingByte(hContact, "MaritalStatus", &databuf, &wPacketLen);
+
+ if (bOK)
+ {
+ if (hContact == NULL)
+ bOK = writeDbInfoSettingByte(hContact, "AllowSpam", &databuf, &wPacketLen);
+ else
+ {
+ databuf++;
+ wPacketLen--;
+ }
+ }
+ if (bOK) bOK = writeDbInfoSettingWord(hContact, "InfoCP", &databuf, &wPacketLen);
+
+ }
+ break;
+
+ case META_NOTES_USERINFO:
+ NetLog_Server("SNAC(0x15,0x3): META_%s_USERINFO for %u", "NOTES", dwCookieUin);
+ if (bResultCode == 0x0A)
+ {
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "About", &databuf, &wPacketLen);
+ }
+ break;
+
+ case META_EMAIL_USERINFO:
+ NetLog_Server("SNAC(0x15,0x3): META_%s_USERINFO for %u", "EMAIL", dwCookieUin);
+ if (bResultCode == 0x0A)
+ {
+ int nCount = 0;
+ char pszDatabaseKey[33];
+ WORD wEmailLength;
+
+
+ // This value used to be a e-mail counter. Either that was wrong or
+ // Mirabilis changed the behaviour again. It usually says NULL now so
+ // I use the packet byte count to extract the e-mails instead.
+ databuf++;
+ wPacketLen--;
+
+ while (wPacketLen > 4)
+ {
+
+ // Don't publish flag
+ databuf += 1;
+ wPacketLen -= 1;
+
+ // E-mail length
+ unpackLEWord(&databuf, &wEmailLength);
+ wPacketLen -= 2;
+
+ // Check for buffer overflows
+ if ((wEmailLength > wPacketLen) || (databuf[wEmailLength-1] != 0))
+ break;
+
+ // Rewind buffer pointer for writeDbInfoSettingString().
+ databuf -= 2;
+ wPacketLen += 2;
+
+ if (wEmailLength > 1)
+ {
+ null_snprintf(pszDatabaseKey, 33, "e-mail%d", nCount);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, pszDatabaseKey, &databuf, &wPacketLen);
+
+ // Stop on parsing errors
+ if (!bOK)
+ break;
+
+ // Increase counter
+ nCount++;
+ }
+ else
+ {
+ databuf += wEmailLength;
+ wPacketLen -= wEmailLength;
+ }
+ }
+
+ // Delete the next key (this may not exist but that is OK)
+ // :TODO:
+ // We should probably continue to enumerate some keys here just in case
+ // many e-mails were deleted. But it is not that important.
+ if (bOK)
+ {
+ // We only delete e-mails when the parsing was successful since nCount
+ // may be incorrect otherwise
+ null_snprintf(pszDatabaseKey, 33, "e-mail%d", nCount);
+ ICQDeleteContactSetting(hContact, pszDatabaseKey);
+ }
+ }
+ break;
+
+ case META_INTERESTS_USERINFO:
+ NetLog_Server("SNAC(0x15,0x3): META_%s_USERINFO for %u", "INTERESTS", dwCookieUin);
+ if (bResultCode == 0x0A)
+ {
+ int i, count;
+ char idstr[33];
+
+ wPacketLen--;
+ count = *databuf++;
+ // 4 is the maximum allowed personal interests, if count is
+ // higher it's likely a parsing error
+ _ASSERTE(count <= 4);
+ for (i = 0; i < 4; i++)
+ {
+ if (i < count)
+ {
+ null_snprintf(idstr, 33, "Interest%dCat", i);
+ if (bOK) bOK = writeDbInfoSettingWordWithTable(hContact, idstr, interestsField, &databuf, &wPacketLen);
+
+ null_snprintf(idstr, 33, "Interest%dText", i);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, idstr, &databuf, &wPacketLen);
+
+ if (!bOK)
+ break;
+ }
+ else
+ {
+ // Delete older entries if the count has decreased since last update
+ null_snprintf(idstr, 33, "Interest%dCat", i);
+ ICQDeleteContactSetting(hContact, idstr);
+
+ null_snprintf(idstr, 33, "Interest%dText", i);
+ ICQDeleteContactSetting(hContact, idstr);
+ }
+ }
+ }
+ break;
+
+ case META_AFFILATIONS_USERINFO:
+ NetLog_Server("SNAC(0x15,0x3): META_%s_USERINFO for %u", "AFFILATIONS", dwCookieUin);
+ if (bResultCode == 0x0A)
+ {
+ int i;
+ int count;
+ char idstr[33];
+
+ wPacketLen--;
+ count = *databuf++;
+ // 3 is the maximum allowed backgrounds, if count is
+ // higher it's likely a parsing error
+ _ASSERTE(count <= 3);
+ for (i = 0; i < 3; i++)
+ {
+ if (i < count)
+ {
+ null_snprintf(idstr, 33, "Past%d", i);
+ if (bOK) bOK = writeDbInfoSettingWordWithTable(hContact, idstr, pastField, &databuf, &wPacketLen);
+
+ null_snprintf(idstr, 33, "Past%dText", i);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, idstr, &databuf, &wPacketLen);
+
+ if (!bOK)
+ break;
+ }
+ else
+ {
+ // Delete older entries if the count has decreased since last update
+ null_snprintf(idstr, 33, "Past%d", i);
+ ICQDeleteContactSetting(hContact, idstr);
+
+ null_snprintf(idstr, 33, "Past%dText", i);
+ ICQDeleteContactSetting(hContact, idstr);
+ }
+ }
+
+ wPacketLen--;
+ count = *databuf++;
+ // 3 is the maximum allowed affiliations, if count is
+ // higher it's likely a parsing error
+ _ASSERTE(count <= 3);
+ for (i = 0; i < 3; i++)
+ {
+ if (i < count)
+ {
+ null_snprintf(idstr, 33, "Affiliation%d", i);
+ if (bOK) bOK = writeDbInfoSettingWordWithTable(hContact, idstr, affiliationField, &databuf, &wPacketLen);
+
+ null_snprintf(idstr, 33, "Affiliation%dText", i);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, idstr, &databuf, &wPacketLen);
+
+ if (!bOK)
+ break;
+ }
+ else
+ {
+ // Delete older entries if the count has decreased since last update
+ null_snprintf(idstr, 33, "Affiliation%d", i);
+ ICQDeleteContactSetting(hContact, idstr);
+
+ null_snprintf(idstr, 33, "Affiliation%dText", i);
+ ICQDeleteContactSetting(hContact, idstr);
+ }
+ }
+
+ }
+ break;
+
+ // This is either a auto update reply or a GetInfo Minimal reply
+ case META_SHORT_USERINFO:
+ NetLog_Server("SNAC(0x15,0x3): META_%s_USERINFO for %u", "SHORT", dwCookieUin);
+ if (bResultCode == 0xA)
+ {
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "Nick", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "FirstName", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "LastName", &databuf, &wPacketLen);
+ if (bOK) bOK = writeDbInfoSettingString(hContact, "e-mail", &databuf, &wPacketLen);
+ }
+ break;
+
+ case META_HPAGECAT_USERINFO:
+ NetLog_Server("SNAC(0x15,0x3): META_%s_USERINFO for %u", "HPAGECAT", dwCookieUin);
+ break;
+
+ default:
+ NetLog_Server("Warning: Ignored 15/03 user info reply type x%x", wReplySubtype);
+// _ASSERTE(0);
+ break;
+ }
+
+ if (!bOK)
+ {
+ NetLog_Server("Error: Failed parsing 15/03 user info reply type x%x", wReplySubtype);
+ }
+
+ // :TRICKY: * Dont change the following section unless you really understand it *
+ // I have now switched to only send one GETINFO ack instead of 8. The multiple ack
+ // sending originated in a incorrect assumption in the old code and that is long
+ // gone now. The ack will be sent when the last packet has arrived
+ // or when an error has occured. I'm not sure if a error packet will be marked
+ // as the last one but it probably is. Doesn't matter anyway.
+ // The cookie will be freed for all "last packets" but the ack will only be sent if the
+ // request originated from a PS_GETINFO call
+ if (((pCookieData->bRequestType == REQUESTTYPE_USERDETAILED) ||
+ (pCookieData->bRequestType == REQUESTTYPE_USERMINIMAL))
+ &&
+ ((bResultCode != 0x0A) || !bMoreDataFollows))
+ {
+ ICQBroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1 ,0);
+ }
+
+ // Free cookie
+ if (!bMoreDataFollows || bResultCode != 0x0A)
+ {
+ ReleaseCookie(wCookie);
+
+ // Remove user from info update queue. Removing is fast so we always call this
+ // even if it is likely that the user is not queued at all.
+ ICQWriteContactSettingDword(hContact, "InfoTS", time(NULL));
+ icq_DequeueUser(dwCookieUin);
+ }
+
+ // :NOTE:
+ // bResultcode can be xA (success), x14 or x32 (failure). I dont know the difference
+ // between the two failures.
+}
+
+
+static void parseUserInfoUpdateAck(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype, BYTE bResultCode)
+{
+ switch (wReplySubtype)
+ {
+ case META_SET_PASSWORD_ACK: // Set user password server ack
+ case META_SET_FULLINFO_ACK: // Server ack for set fullinfo command
+
+ if (bResultCode == 0xA)
+ ICQBroadcastAck(NULL, ACKTYPE_SETINFO, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
+ else
+ ICQBroadcastAck(NULL, ACKTYPE_SETINFO, ACKRESULT_FAILED, (HANDLE)wCookie, 0);
+
+ FreeCookie(wCookie);
+ break;
+
+ default:
+ NetLog_Server("Warning: Ignored 15/03 user info update ack type x%x", wReplySubtype);
+ break;
+ }
+}
diff --git a/icqj_mod/fam_17signon.c b/icqj_mod/fam_17signon.c new file mode 100644 index 0000000..3919694 --- /dev/null +++ b/icqj_mod/fam_17signon.c @@ -0,0 +1,198 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_17signon.c,v $
+// Revision : $Revision: 3316 $
+// Last change on : $Date: 2006-07-12 20:26:25 +0400 (Ср, 12 июл 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+static void handleAuthKeyResponse(BYTE *buf, WORD wPacketLen, serverthread_info *info);
+
+
+void handleAuthorizationFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader, serverthread_info *info)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+
+ case ICQ_SIGNON_ERROR:
+ {
+ WORD wError;
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ LogFamilyError(ICQ_AUTHORIZATION_FAMILY, wError);
+ break;
+ }
+
+ case ICQ_SIGNON_AUTH_KEY:
+ handleAuthKeyResponse(pBuffer, wBufferLength, info);
+ break;
+
+ case ICQ_SIGNON_LOGIN_REPLY:
+ handleLoginReply(pBuffer, wBufferLength, info);
+ break;
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_AUTHORIZATION_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+ }
+}
+
+
+
+static void icq_encryptPassword(const char* szPassword, unsigned char* encrypted)
+{
+ unsigned int i;
+ unsigned char table[] =
+ {
+ 0xf3, 0x26, 0x81, 0xc4,
+ 0x39, 0x86, 0xdb, 0x92,
+ 0x71, 0xa3, 0xb9, 0xe6,
+ 0x53, 0x7a, 0x95, 0x7c
+ };
+
+ for (i = 0; szPassword[i]; i++)
+ {
+ encrypted[i] = (szPassword[i] ^ table[i % 16]);
+ }
+}
+
+
+
+void sendClientAuth(const char* szKey, WORD wKeyLen, BOOL bSecure)
+{
+ char szUin[UINMAXLEN];
+ WORD wUinLen;
+ icq_packet packet;
+
+ wUinLen = strlennull(strUID(dwLocalUIN, szUin));
+
+ packet.wLen = 65 + sizeof(CLIENT_ID_STRING) + wUinLen + wKeyLen;
+
+ if (bSecure)
+ {
+ serverPacketInit(&packet, (WORD)(packet.wLen + 10));
+ packFNACHeaderFull(&packet, ICQ_AUTHORIZATION_FAMILY, ICQ_SIGNON_LOGIN_REQUEST, 0, 0);
+ }
+ else
+ {
+ write_flap(&packet, ICQ_LOGIN_CHAN);
+ packDWord(&packet, 0x00000001);
+ }
+ packTLV(&packet, 0x0001, wUinLen, szUin);
+
+ if (bSecure)
+ { // Pack MD5 auth digest
+ packTLV(&packet, 0x0025, wKeyLen, (BYTE*)szKey);
+ packDWord(&packet, 0x004C0000); // empty TLV(0x4C): unknown
+ }
+ else
+ { // Pack old style password hash
+ char hash[20];
+
+ icq_encryptPassword(szKey, hash);
+ packTLV(&packet, 0x0002, wKeyLen, hash);
+ }
+
+ // Pack client identification details. We identify ourselves as icq5.1 english
+ packTLV(&packet, 0x0003, (WORD)sizeof(CLIENT_ID_STRING)-1, CLIENT_ID_STRING); // Client ID string
+ packTLVWord(&packet, 0x0016, 0x010a); // Client ID
+ packTLVWord(&packet, 0x0017, 0x0014); // Client major version
+ packTLVWord(&packet, 0x0018, 0x0034); // Client minor version
+ packTLVWord(&packet, 0x0019, 0x0000); // Client lesser version
+ packTLVWord(&packet, 0x001a, 0x0bb8); // Client build number
+ packTLVDWord(&packet, 0x0014, 0x0000043d); // Client distribution number
+ packTLV(&packet, 0x000f, 0x0002, "en"); // Client language
+ packTLV(&packet, 0x000e, 0x0002, "us"); // Client country
+
+ sendServPacket(&packet);
+}
+
+
+
+static void handleAuthKeyResponse(BYTE *buf, WORD wPacketLen, serverthread_info *info)
+{
+ WORD wKeyLen;
+ char szKey[64] = {0};
+ md5_state_t state;
+ md5_byte_t digest[16];
+
+#ifdef _DEBUG
+ NetLog_Server("Received %s", "ICQ_SIGNON_AUTH_KEY");
+#endif
+
+ if (wPacketLen < 2)
+ {
+ NetLog_Server("Malformed %s", "ICQ_SIGNON_AUTH_KEY");
+ icq_LogMessage(LOG_FATAL, "Secure login failed.\nInvalid server response.");
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ unpackWord(&buf, &wKeyLen);
+ wPacketLen -= 2;
+
+ if (!wKeyLen || wKeyLen > wPacketLen || wKeyLen > sizeof(szKey))
+ {
+ NetLog_Server("Invalid length in %s: %u", "ICQ_SIGNON_AUTH_KEY", wKeyLen);
+ icq_LogMessage(LOG_FATAL, "Secure login failed.\nInvalid key length.");
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ unpackString(&buf, szKey, wKeyLen);
+
+ {
+ char *pwd = info->szAuthKey;
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t*)pwd, info->wAuthKeyLen);
+ md5_finish(&state, digest);
+ }
+
+ md5_init(&state);
+ md5_append(&state, szKey, wKeyLen);
+ md5_append(&state, digest, 16);
+ md5_append(&state, CLIENT_MD5_STRING, sizeof(CLIENT_MD5_STRING)-1);
+ md5_finish(&state, digest);
+
+#ifdef _DEBUG
+ NetLog_Server("Sending ICQ_SIGNON_LOGIN_REQUEST to login server");
+#endif
+ sendClientAuth(digest, 0x10, TRUE);
+}
diff --git a/icqj_mod/families.h b/icqj_mod/families.h new file mode 100644 index 0000000..838fe45 --- /dev/null +++ b/icqj_mod/families.h @@ -0,0 +1,90 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/families.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Declaration for handlers of Channel 2 SNAC Families
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __FAMILIES_H
+#define __FAMILIES_H
+
+
+typedef struct snac_header_s
+{
+ BOOL bValid;
+ WORD wFamily;
+ WORD wSubtype;
+ WORD wFlags;
+ DWORD dwRef;
+ WORD wVersion;
+} snac_header;
+
+
+/*---------* Functions *---------------*/
+
+void handleServiceFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader, serverthread_info *info);
+void handleLocationFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+void handleBuddyFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+void handleMsgFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+void handleBosFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+void handleLookupFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+void handleStatusFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+void handleServClistFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader, serverthread_info *info);
+void handleIcqExtensionsFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+void handleAuthorizationFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader, serverthread_info *info);
+
+void sendClientAuth(const char* szKey, WORD wKeyLen, BOOL bSecure);
+void handleLoginReply(unsigned char *buf, WORD datalen, serverthread_info *info);
+
+void handleServUINSettings(int nPort, serverthread_info *info);
+int TypeGUIDToTypeId(DWORD dwGuid1, DWORD dwGuid2, DWORD dwGuid3, DWORD dwGuid4, WORD wType);
+int getPluginTypeIdLen(int nTypeID);
+void packPluginTypeId(icq_packet *packet, int nTypeID);
+
+void handleMessageTypes(DWORD dwUin, DWORD dwTimestamp, DWORD dwMsgID, DWORD dwMsgID2, WORD wCookie, WORD wVersion, int type, int flags, WORD wAckType, DWORD dwDataLen, WORD wMsgLen, char *pMsg, BOOL bThruDC);
+
+#define BUL_ALLCONTACTS 0
+#define BUL_VISIBLE 1
+#define BUL_INVISIBLE 2
+#define BUL_TEMPVISIBLE 4
+void sendEntireListServ(WORD wFamily, WORD wSubtype, int listType);
+void updateServVisibilityCode(BYTE bCode);
+void updateServAvatarHash(char* pHash, int size);
+void sendAddStart(int bImport);
+void sendAddEnd(void);
+void sendTypingNotification(HANDLE hContact, WORD wMTNCode);
+
+void makeContactTemporaryVisible(HANDLE hContact);
+void clearTemporaryVisibleList();
+
+
+#endif /* __FAMILIES_H */
diff --git a/icqj_mod/forkthread.c b/icqj_mod/forkthread.c new file mode 100644 index 0000000..9e0d2f4 --- /dev/null +++ b/icqj_mod/forkthread.c @@ -0,0 +1,121 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/forkthread.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Miranda Friendly thread wrapper
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+struct FORK_ARG {
+ HANDLE hEvent;
+ void (__cdecl *threadcode)(void*);
+ unsigned (__stdcall *threadcodeex)(void*);
+ void *arg;
+};
+
+
+void __cdecl forkthread_r(struct FORK_ARG *fa)
+{
+ void (*callercode)(void*) = fa->threadcode;
+ void *arg = fa->arg;
+
+ CallService(MS_SYSTEM_THREAD_PUSH,0,0);
+ SetEvent(fa->hEvent);
+
+ callercode(arg);
+
+ CallService(MS_SYSTEM_THREAD_POP,0,0);
+
+ return;
+}
+
+
+unsigned long forkthread(void (__cdecl *threadcode)(void*), unsigned long stacksize, void *arg)
+{
+ unsigned long rc;
+ struct FORK_ARG fa;
+
+ fa.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
+ fa.threadcode = threadcode;
+ fa.arg = arg;
+
+ rc = _beginthread(forkthread_r, stacksize, &fa);
+
+ if ((unsigned long)-1L != rc)
+ {
+ WaitForSingleObject(fa.hEvent, INFINITE);
+ }
+ CloseHandle(fa.hEvent);
+
+ return rc;
+}
+
+
+unsigned long __stdcall forkthreadex_r(struct FORK_ARG *fa)
+{
+ unsigned (__stdcall * threadcode) (void *) = fa->threadcodeex;
+ void *arg = fa->arg;
+ unsigned long rc;
+
+ CallService(MS_SYSTEM_THREAD_PUSH,0,0);
+ SetEvent(fa->hEvent);
+
+ rc = threadcode(arg);
+
+ CallService(MS_SYSTEM_THREAD_POP,0,0);
+
+ return rc;
+}
+
+
+unsigned long forkthreadex(void *sec, unsigned stacksize, unsigned (__stdcall *threadcode)(void*),
+ void *arg, unsigned cf, unsigned *thraddr)
+{
+ unsigned long rc;
+ struct FORK_ARG fa;
+
+ fa.threadcodeex = threadcode;
+ fa.arg = arg;
+ fa.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
+
+ rc = _beginthreadex(sec,stacksize,forkthreadex_r,&fa,0,thraddr);
+ if (rc)
+ {
+ WaitForSingleObject(fa.hEvent,INFINITE);
+ }
+ CloseHandle(fa.hEvent);
+
+ return rc;
+}
diff --git a/icqj_mod/forkthread.h b/icqj_mod/forkthread.h new file mode 100644 index 0000000..78689f3 --- /dev/null +++ b/icqj_mod/forkthread.h @@ -0,0 +1,73 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/forkthread.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// A safe version of _beginthread()
+//
+// A new thread is created and the source thread is paused until
+// internal code to call MS_SYSTEM_THREAD_PUSH is made in the context
+// if the new thread.
+//
+// The source thread is then released and then the user supplied
+// code is called, when that function returns -- MS_SYSTEM_THREAD_POP
+// is called and then the thread returns.
+//
+// This insures that Miranda will not exit whilst new threads
+// are trying to be born; and the unwind wait stack will ensure
+// that Miranda will wait for all created threads to return as well.
+//
+// Caveats:
+//
+// The function must be reimplemented across MT plugins, since thread
+// creation depends on CRT which can not be shared.
+// -----------------------------------------------------------------------------
+
+
+
+typedef struct {
+ HANDLE hThread;
+ DWORD dwThreadId;
+} pthread_t;
+
+unsigned long forkthread (
+ void (__cdecl *threadcode)(void*),
+ unsigned long stacksize,
+ void *arg
+);
+
+unsigned long forkthreadex(
+ void *sec,
+ unsigned stacksize,
+ unsigned (__stdcall *threadcode)(void*),
+ void *arg,
+ unsigned cf,
+ unsigned *thraddr
+);
diff --git a/icqj_mod/globals.h b/icqj_mod/globals.h new file mode 100644 index 0000000..ebcbd90 --- /dev/null +++ b/icqj_mod/globals.h @@ -0,0 +1,138 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/globals.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Contains global variables declarations.
+//
+// -----------------------------------------------------------------------------
+
+
+#ifndef __GLOBALS_H
+#define __GLOBALS_H
+
+typedef char uid_str[MAX_PATH];
+
+// Defaults
+#define DEFAULT_SECURE_LOGIN 0
+#define DEFAULT_QUICK_LOGIN 1
+#define DEFAULT_DCTYPE 2 //auth req
+#define DEFAULT_VISIBILITY 0
+#define DEFAULT_OEM_CONV 0
+#define DEFAULT_RENAME_SERVER_NICKS 1
+#define DEFAULT_UPLOAD_DELAY 2
+#define DEFAULT_PRIVACY_ENABLED 1
+#define DEFAULT_SHOW_IDLE_TIME 1
+#define DEFAULT_EXTSEARCH_ENABLED 1
+#define DEFAULT_TOOLS 0
+#define DEFAULT_VISIBILITY_TOOLS 0
+#define DEFAULT_EXT_STATUS 0
+#define DEFAULT_VISIBLEMODE 4
+#define DEFAULT_INVISIBLEMODE 3
+
+// from init.c
+HINSTANCE hInst;
+char gpszICQProtoName[MAX_PATH];
+
+HANDLE ghServerNetlibUser;
+HANDLE ghDirectNetlibUser;
+
+// from init.h
+BYTE gbSecureLogin;
+BYTE gbAimEnabled;
+BYTE gbUtfEnabled;
+WORD gwAnsiCodepage;
+BYTE gbDCMsgEnabled;
+BYTE gbTempVisListEnabled;
+BYTE gbSsiEnabled;
+BYTE gbAvatarsEnabled;
+BYTE gbXStatusEnabled;
+BYTE gbOverRate;
+DWORD gtLastRequest;
+DWORD MIRANDA_VERSION;
+
+
+// from icqosc_svcs.c
+int gnCurrentStatus;
+DWORD dwLocalUIN;
+
+char gpszPassword[16];
+BYTE gbRememberPwd;
+
+BYTE gbUnicodeAPI;
+BYTE gbUnicodeCore;
+BYTE gbUtfLangpack;
+
+// Globals
+BYTE gbAimEnabled;
+BYTE gbSsiEnabled;
+BYTE gbShowIdle;
+BYTE gbVisibility;
+BYTE gbMtnEnabled;
+BYTE gbAdvSearch;
+BYTE gbWebAware;
+BYTE gbTools;
+BYTE gbVTools;
+BYTE gbExtStatus;
+BYTE gbRcvUnicode;
+BYTE gbSendUnicode;
+BYTE gbUnicodeDecode;
+BYTE gbVisibleMode;
+BYTE gwVersion;
+BYTE gbQuickLogin;
+BYTE gbSecureLogin;
+BYTE gbSavePass;
+BYTE gbUseServerNicks;
+BYTE gbRenameServerNicks;
+BYTE gbServerAddRemove;
+BYTE gbSlowSend;
+BYTE gbSetStatus;
+
+DWORD gdwFP1;
+DWORD gdwFP2;
+DWORD gdwFP3;
+
+DWORD gdwUpdateThreshold;
+
+// from fam_04message.c
+typedef struct icq_mode_messages_s
+{
+ char* szAway;
+ char* szNa;
+ char* szDnd;
+ char* szOccupied;
+ char* szFfc;
+} icq_mode_messages;
+
+icq_mode_messages modeMsgs;
+CRITICAL_SECTION modeMsgsMutex;
+
+
+#endif /* __GLOBALS_H */
diff --git a/icqj_mod/guids.h b/icqj_mod/guids.h new file mode 100644 index 0000000..f28d4b1 --- /dev/null +++ b/icqj_mod/guids.h @@ -0,0 +1,91 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/guids.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Contains helper functions to handle oscar message GUIDs.
+//
+// -----------------------------------------------------------------------------
+
+
+#ifndef __GUIDS_H
+#define __GUIDS_H
+
+
+typedef DWORD plugin_guid[4];
+
+// Message Capability GUIDs
+static plugin_guid MCAP_TLV2711_FMT = {MCAP_TLV2711_FMT_s};
+static plugin_guid MCAP_REVERSE_REQ = {MCAP_REVERSE_REQ_s};
+
+// Plugin GUIDs
+static plugin_guid PSIG_MESSAGE = {PSIG_MESSAGE_s};
+static plugin_guid PSIG_INFO_PLUGIN = {PSIG_INFO_PLUGIN_s};
+static plugin_guid PSIG_STATUS_PLUGIN = {PSIG_STATUS_PLUGIN_s};
+
+// Plugin Message GUIDs
+static plugin_guid PMSG_QUERY_INFO = {PMSG_QUERY_INFO_s};
+static plugin_guid PMSG_QUERY_STATUS = {PMSG_QUERY_STATUS_s};
+
+// Message GUIDs
+static plugin_guid MGTYPE_MESSAGE = {MGTYPE_MESSAGE_s};
+static plugin_guid MGTYPE_STATUSMSGEXT = {MGTYPE_STATUSMSGEXT_s};
+static plugin_guid MGTYPE_FILE = {MGTYPE_FILE_s};
+static plugin_guid MGTYPE_WEBURL = {MGTYPE_WEBURL_s};
+static plugin_guid MGTYPE_CONTACTS = {MGTYPE_CONTACTS_s};
+static plugin_guid MGTYPE_GREETING_CARD = {MGTYPE_GREETING_CARD_s};
+static plugin_guid MGTYPE_CHAT = {MGTYPE_CHAT_s};
+static plugin_guid MGTYPE_XTRAZ_SCRIPT = {MGTYPE_XTRAZ_SCRIPT_s};
+
+
+// make GUID checks easy
+static BOOL CompareGUIDs(DWORD q1,DWORD q2,DWORD q3,DWORD q4, plugin_guid guid)
+{
+ return ((q1 == guid[0]) && (q2 == guid[1]) && (q3 == guid[2]) && (q4 == guid[3]))?TRUE:FALSE;
+}
+
+
+// pack entire GUID into icq packet
+static __inline void packGUID(icq_packet* packet, plugin_guid guid)
+{
+ packDWord(packet, guid[0]);
+ packDWord(packet, guid[1]);
+ packDWord(packet, guid[2]);
+ packDWord(packet, guid[3]);
+}
+
+
+// capabilities
+typedef unsigned char capstr[0x10];
+
+capstr* MatchCap(char* buf, int bufsize, const capstr* cap, int capsize);
+
+
+#endif /* __GUIDS_H */
diff --git a/icqj_mod/i18n.c b/icqj_mod/i18n.c new file mode 100644 index 0000000..f29f686 --- /dev/null +++ b/icqj_mod/i18n.c @@ -0,0 +1,477 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/i18n.c,v $
+// Revision : $Revision: 3184 $
+// Last change on : $Date: 2006-06-20 12:40:26 +0200 (Tue, 20 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Contains helper functions to convert text messages between different
+// character sets.
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static BOOL bHasCP_UTF8 = FALSE;
+
+
+void InitI18N(void)
+{
+ CPINFO CPInfo;
+
+
+ bHasCP_UTF8 = GetCPInfo(CP_UTF8, &CPInfo);
+}
+
+
+
+// Returns true if the buffer only contains 7-bit characters.
+BOOL IsUSASCII(const unsigned char* pBuffer, int nSize)
+{
+ BOOL bResult = TRUE;
+ int nIndex;
+
+ for (nIndex = 0; nIndex < nSize; nIndex++)
+ {
+ if (pBuffer[nIndex] > 0x7F)
+ {
+ bResult = FALSE;
+ break;
+ }
+ }
+
+ return bResult;
+}
+
+// Returns true if the unicode buffer only contains 7-bit characters.
+BOOL IsUnicodeAscii(const wchar_t* pBuffer, int nSize)
+{
+ BOOL bResult = TRUE;
+ int nIndex;
+
+
+ for (nIndex = 0; nIndex < nSize; nIndex++)
+ {
+ if (pBuffer[nIndex] > 0x7F)
+ {
+ bResult = FALSE;
+ break;
+ }
+ }
+
+ return bResult;
+}
+
+
+// Scans a string encoded in UTF-8 to verify that it contains
+// only valid sequences. It will return 1 if the string contains
+// only legitimate encoding sequences; otherwise it will return 0;
+// From 'Secure Programming Cookbook', John Viega & Matt Messier, 2003
+int UTF8_IsValid(const unsigned char* pszInput)
+{
+ int nb, i;
+ const unsigned char* c = pszInput;
+
+
+ for (c = pszInput; *c; c += (nb + 1))
+ {
+ if (!(*c & 0x80))
+ nb = 0;
+ else if ((*c & 0xc0) == 0x80) return 0;
+ else if ((*c & 0xe0) == 0xc0) nb = 1;
+ else if ((*c & 0xf0) == 0xe0) nb = 2;
+ else if ((*c & 0xf8) == 0xf0) nb = 3;
+ else if ((*c & 0xfc) == 0xf8) nb = 4;
+ else if ((*c & 0xfe) == 0xfc) nb = 5;
+
+ for (i = 1; i<=nb; i++) // we this forward, do not cross end of string
+ if ((*(c + i) & 0xc0) != 0x80)
+ return 0;
+ }
+
+ return 1;
+}
+
+
+// returns ansi string in all cases
+char* detect_decode_utf8(const char *from)
+{
+ char* temp = NULL;
+
+ if (IsUSASCII(from, strlennull(from)) || !UTF8_IsValid(from) || !utf8_decode(from, &temp)) return (char*)from;
+ SAFE_FREE((char**)&from);
+
+ return temp;
+}
+
+
+/*
+ * The following UTF8 routines are
+ *
+ * Copyright (C) 2001 Peter Harris <peter.harris@hummingbird.com>
+ * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
+ *
+ * under a GPL license
+ *
+ * --------------------------------------------------------------
+ * Convert a string between UTF-8 and the locale's charset.
+ * Invalid bytes are replaced by '#', and characters that are
+ * not available in the target encoding are replaced by '?'.
+ *
+ * If the locale's charset is not set explicitly then it is
+ * obtained using nl_langinfo(CODESET), where available, the
+ * environment variable CHARSET, or assumed to be US-ASCII.
+ *
+ * Return value of conversion functions:
+ *
+ * -1 : memory allocation failed
+ * 0 : data was converted exactly
+ * 1 : valid data was converted approximately (using '?')
+ * 2 : input was invalid (but still converted, using '#')
+ * 3 : unknown encoding (but still converted, using '?')
+ */
+
+
+
+/*
+ * Convert a string between UTF-8 and the locale's charset.
+ */
+unsigned char *make_utf8_string(const wchar_t *unicode)
+{
+ int size = 0;
+ int index = 0;
+ int out_index = 0;
+ unsigned char* out;
+ unsigned short c;
+
+
+ /* first calculate the size of the target string */
+ c = unicode[index++];
+ while (c)
+ {
+ if (c < 0x0080)
+ size += 1;
+ else if (c < 0x0800)
+ size += 2;
+ else
+ size += 3;
+ c = unicode[index++];
+ }
+
+ out = (unsigned char*)SAFE_MALLOC(size + 1);
+ if (out == NULL)
+ return NULL;
+ index = 0;
+
+ c = unicode[index++];
+ while (c)
+ {
+ if (c < 0x080)
+ {
+ out[out_index++] = (unsigned char)c;
+ }
+ else if (c < 0x800)
+ {
+ out[out_index++] = 0xc0 | (c >> 6);
+ out[out_index++] = 0x80 | (c & 0x3f);
+ }
+ else
+ {
+ out[out_index++] = 0xe0 | (c >> 12);
+ out[out_index++] = 0x80 | ((c >> 6) & 0x3f);
+ out[out_index++] = 0x80 | (c & 0x3f);
+ }
+ c = unicode[index++];
+ }
+ out[out_index] = 0x00;
+
+ return out;
+}
+
+
+
+wchar_t *make_unicode_string(const unsigned char *utf8)
+{
+ int size = 0, index = 0, out_index = 0;
+ wchar_t *out;
+ unsigned char c;
+
+ /* first calculate the size of the target string */
+ c = utf8[index++];
+ while (c)
+ {
+ if ((c & 0x80) == 0)
+ {
+ index += 0;
+ }
+ else if ((c & 0xe0) == 0xe0)
+ {
+ index += 2;
+ }
+ else
+ {
+ index += 1;
+ }
+ size += 1;
+ c = utf8[index++];
+ }
+
+ out = (wchar_t*)SAFE_MALLOC((size + 1) * sizeof(wchar_t));
+ if (out == NULL)
+ return NULL;
+ index = 0;
+
+ c = utf8[index++];
+ while (c)
+ {
+ if((c & 0x80) == 0)
+ {
+ out[out_index++] = c;
+ }
+ else if((c & 0xe0) == 0xe0)
+ {
+ out[out_index] = (c & 0x1F) << 12;
+ c = utf8[index++];
+ out[out_index] |= (c & 0x3F) << 6;
+ c = utf8[index++];
+ out[out_index++] |= (c & 0x3F);
+ }
+ else
+ {
+ out[out_index] = (c & 0x3F) << 6;
+ c = utf8[index++];
+ out[out_index++] |= (c & 0x3F);
+ }
+ c = utf8[index++];
+ }
+ out[out_index] = 0;
+
+ return out;
+}
+
+
+
+int utf8_encode(const char *from, char **to)
+{
+ wchar_t *unicode;
+ int wchars, err;
+
+
+ wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
+ strlennull(from), NULL, 0);
+
+ if (wchars == 0)
+ {
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+ return -1;
+ }
+
+ unicode = (wchar_t*)_alloca((wchars + 1) * sizeof(unsigned short));
+ unicode[wchars] = 0;
+
+ err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
+ strlennull(from), unicode, wchars);
+ if(err != wchars)
+ {
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+ return -1;
+ }
+
+ /* On NT-based windows systems, we could use WideCharToMultiByte(), but
+ * MS doesn't actually have a consistent API across win32.
+ */
+ *to = make_utf8_string(unicode);
+
+ return 0;
+}
+
+
+
+char *ansi_to_utf8(const char *szAnsi)
+{
+ char *szUtf;
+
+ if (strlennull(szAnsi))
+ {
+ utf8_encode(szAnsi, &szUtf);
+
+ return szUtf;
+ }
+ else
+ return null_strdup("");
+}
+
+
+
+char *ansi_to_utf8_codepage(const char *szAnsi, WORD wCp)
+{
+ wchar_t *unicode;
+ int wchars = strlennull(szAnsi);
+
+ unicode = (wchar_t*)_alloca((wchars + 1) * sizeof(wchar_t));
+ ZeroMemory(unicode, (wchars + 1)*sizeof(wchar_t));
+
+ MultiByteToWideChar(wCp, MB_PRECOMPOSED, szAnsi, wchars, unicode, wchars);
+
+ return make_utf8_string(unicode);
+}
+
+
+
+// Returns 0 on error, 1 on success
+int utf8_decode(const char *from, char **to)
+{
+ int nResult = 0;
+
+ _ASSERTE(!(*to)); // You passed a non-zero pointer, make sure it doesnt point to unfreed memory
+
+ // Validate the string
+ if (!UTF8_IsValid(from))
+ return 0;
+
+ // Use the native conversion routines when available
+ if (bHasCP_UTF8)
+ {
+ WCHAR *wszTemp = NULL;
+ int inlen = strlennull(from);
+
+ wszTemp = (WCHAR *)_alloca(sizeof(WCHAR) * (inlen + 1));
+
+ // Convert the UTF-8 string to UCS
+ if (MultiByteToWideChar(CP_UTF8, 0, from, -1, wszTemp, inlen + 1))
+ {
+ // Convert the UCS string to local ANSI codepage
+ *to = (char*)SAFE_MALLOC(inlen+1);
+ if (WideCharToMultiByte(CP_ACP, 0, wszTemp, -1, *to, inlen+1, NULL, NULL))
+ {
+ nResult = 1;
+ }
+ else
+ {
+ SAFE_FREE(&(*to));
+ }
+ }
+ }
+ else
+ {
+ wchar_t *unicode;
+ int chars;
+ int err;
+
+ unicode = make_unicode_string(from);
+ if(unicode == NULL)
+ {
+ fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n");
+ return 0;
+ }
+
+ chars = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL);
+
+ if(chars == 0)
+ {
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+ SAFE_FREE(&unicode);
+ return 0;
+ }
+
+ *to = (char*)SAFE_MALLOC((chars + 1)*sizeof(unsigned char));
+ if(*to == NULL)
+ {
+ fprintf(stderr, "Out of memory processing string to local charset\n");
+ SAFE_FREE(&unicode);
+ return 0;
+ }
+
+ err = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL);
+ if (err != chars)
+ {
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+ SAFE_FREE(&unicode);
+ SAFE_FREE(to);
+ return 0;
+ }
+
+ SAFE_FREE(&unicode);
+
+ nResult = 1;
+ }
+
+ return nResult;
+}
+
+
+
+// Returns 0 on error, 1 on success
+int utf8_decode_static(const char *from, char *to, int to_size)
+{
+ int nResult = 0;
+
+ _ASSERTE(to); // You passed a zero pointer
+
+ // Validate the string
+ if (!UTF8_IsValid(from))
+ return 0;
+
+ // Use the native conversion routines when available
+ if (bHasCP_UTF8)
+ {
+ WCHAR *wszTemp = NULL;
+ int inlen = strlennull(from);
+
+ wszTemp = (WCHAR *)_alloca(sizeof(WCHAR) * (inlen + 1));
+
+ // Convert the UTF-8 string to UCS
+ if (MultiByteToWideChar(CP_UTF8, 0, from, -1, wszTemp, inlen + 1))
+ {
+ // Convert the UCS string to local ANSI codepage
+ if (WideCharToMultiByte(CP_ACP, 0, wszTemp, -1, to, to_size, NULL, NULL))
+ {
+ nResult = 1;
+ }
+ }
+ }
+ else
+ {
+ wchar_t *unicode = make_unicode_string(from);
+
+ if (unicode == NULL)
+ {
+ fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n");
+ return 0;
+ }
+
+ WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, to, to_size, NULL, NULL);
+
+ SAFE_FREE(&unicode);
+
+ nResult = 1;
+ }
+
+ return nResult;
+}
diff --git a/icqj_mod/i18n.h b/icqj_mod/i18n.h new file mode 100644 index 0000000..76f885c --- /dev/null +++ b/icqj_mod/i18n.h @@ -0,0 +1,55 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/i18n.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Helper functions to convert text messages between different character sets.
+//
+// -----------------------------------------------------------------------------
+
+
+
+BOOL IsUSASCII(const unsigned char *pBuffer, int nSize);
+BOOL IsUnicodeAscii(const wchar_t *pBuffer, int nSize);
+int UTF8_IsValid(const unsigned char* pszInput);
+
+char* detect_decode_utf8(const char *from);
+
+wchar_t *make_unicode_string(const unsigned char *utf8);
+
+unsigned char *make_utf8_string(const wchar_t *unicode);
+
+int utf8_encode(const char *from, char **to);
+char *ansi_to_utf8(const char *szAnsi);
+char *ansi_to_utf8_codepage(const char *szAnsi, WORD wCp);
+int utf8_decode(const char *from, char **to);
+int utf8_decode_static(const char *from, char *to, int to_size);
+
+void InitI18N(void);
diff --git a/icqj_mod/iconlib.c b/icqj_mod/iconlib.c new file mode 100644 index 0000000..243e634 --- /dev/null +++ b/icqj_mod/iconlib.c @@ -0,0 +1,126 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/iconlib.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Support for IcoLib plug-in
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_icolib.h"
+
+
+static int bIcoReady = 0;
+static int bIcoUtf = 0;
+
+
+void InitIconLib()
+{ // check plugin presence, init variables
+ bIcoReady = ServiceExists(MS_SKIN2_GETICON);
+ if (bIcoReady)
+ {
+ SKINICONDESC sid = {0};
+
+ if (CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid) >= PLUGIN_MAKE_VERSION(0,0,1,0))
+ bIcoUtf = 1;
+ }
+}
+
+
+
+int IconLibInstalled()
+{
+ return bIcoReady;
+}
+
+
+
+void IconLibDefine(const char* desc, const char* section, const char* ident, HICON icon, const char* def_file, int def_idx)
+{
+ if (bIcoReady)
+ {
+ SKINICONDESC sid = {0};
+ char szTemp[MAX_PATH + 128];
+
+ if (bIcoUtf)
+ {
+ sid.cbSize = SKINICONDESC_SIZE;
+ sid.pwszSection = make_unicode_string(section);
+ sid.pwszDescription = make_unicode_string(desc);
+ sid.flags = SIDF_UNICODE;
+ }
+ else
+ {
+ sid.cbSize = SKINICONDESC_SIZE_V3;
+ utf8_decode(section, &sid.pszSection);
+ utf8_decode(desc, &sid.pszDescription);
+ }
+ null_snprintf(szTemp, sizeof(szTemp), "%s_%s", gpszICQProtoName, ident);
+ sid.pszName = szTemp;
+ sid.pszDefaultFile = (char*)def_file;
+ sid.iDefaultIndex = def_idx;
+ sid.hDefaultIcon = icon;
+ sid.cx = sid.cy = 16;
+
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ SAFE_FREE(&sid.pwszSection);
+ SAFE_FREE(&sid.pwszDescription);
+ }
+}
+
+
+
+HICON IconLibProcess(HICON icon, const char* ident)
+{
+ if (bIcoReady)
+ {
+ char szTemp[MAX_PATH + 128];
+ HICON hNew;
+
+ null_snprintf(szTemp, sizeof(szTemp), "%s_%s", gpszICQProtoName, ident);
+ hNew = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szTemp);
+ if (hNew) return hNew;
+ }
+
+ return icon;
+}
+
+
+
+HANDLE IconLibHookIconsChanged(MIRANDAHOOK hook)
+{
+ if (bIcoReady)
+ {
+ return HookEvent(ME_SKIN2_ICONSCHANGED, hook);
+ }
+ return NULL;
+}
diff --git a/icqj_mod/iconlib.h b/icqj_mod/iconlib.h new file mode 100644 index 0000000..9b7c187 --- /dev/null +++ b/icqj_mod/iconlib.h @@ -0,0 +1,50 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/iconlib.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Headers for IconLib Plugin support
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICONLIB_H
+#define __ICONLIB_H
+
+
+void InitIconLib();
+
+int IconLibInstalled();
+
+void IconLibDefine(const char* desc, const char* section, const char* ident, HICON icon, const char* def_file, int def_idx);
+HICON IconLibProcess(HICON icon, const char* ident);
+HANDLE IconLibHookIconsChanged(MIRANDAHOOK hook);
+
+
+#endif /* __ICONLIB_H */
diff --git a/icqj_mod/icons_pack/ICONS.dep b/icqj_mod/icons_pack/ICONS.dep new file mode 100644 index 0000000..743fff5 --- /dev/null +++ b/icqj_mod/icons_pack/ICONS.dep @@ -0,0 +1,36 @@ +# Microsoft Developer Studio Generated Dependency File, included by ICONS.mak
+
+.\ICONS.rc : \
+ "..\icos\xstatus01.ico"\
+ "..\icos\xstatus02.ico"\
+ "..\icos\xstatus03.ico"\
+ "..\icos\xstatus04.ico"\
+ "..\icos\xstatus05.ico"\
+ "..\icos\xstatus06.ico"\
+ "..\icos\xstatus07.ico"\
+ "..\icos\xstatus08.ico"\
+ "..\icos\xstatus09.ico"\
+ "..\icos\xstatus10.ico"\
+ "..\icos\xstatus11.ico"\
+ "..\icos\xstatus12.ico"\
+ "..\icos\xstatus13.ico"\
+ "..\icos\xstatus14.ico"\
+ "..\icos\xstatus15.ico"\
+ "..\icos\xstatus16.ico"\
+ "..\icos\xstatus17.ico"\
+ "..\icos\xstatus18.ico"\
+ "..\icos\xstatus19.ico"\
+ "..\icos\xstatus20.ico"\
+ "..\icos\xstatus21.ico"\
+ "..\icos\xstatus22.ico"\
+ "..\icos\xstatus23.ico"\
+ "..\icos\xstatus24.ico"\
+ "..\icos\xstatus25.ico"\
+ "..\icos\xstatus26.ico"\
+ "..\icos\xstatus27.ico"\
+ "..\icos\xstatus28.ico"\
+ "..\icos\xstatus29.ico"\
+ "..\icos\xstatus30.ico"\
+ "..\icos\xstatus31.ico"\
+ "..\icos\xstatus32.ico"\
+
diff --git a/icqj_mod/icons_pack/ICONS.dsp b/icqj_mod/icons_pack/ICONS.dsp new file mode 100644 index 0000000..baa6dc2 --- /dev/null +++ b/icqj_mod/icons_pack/ICONS.dsp @@ -0,0 +1,194 @@ +# Microsoft Developer Studio Project File - Name="ICONS" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=ICONS - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ICONS.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ICONS.mak" CFG="ICONS - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ICONS - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "ICONS_EXPORTS" /D "_MBCS" /Yu"stdafx.h" /c
+# ADD CPP /nologo /MT /W3 /GX /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "ICONS_EXPORTS" /D "_MBCS" /Yu"stdafx.h" /c
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /dll /debug /machine:I386
+# ADD LINK32 /nologo /dll /debug /machine:I386 /out:"..\..\..\bin\release\plugins\ICQ_icons.dll" /noentry /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /pdb:none
+# Begin Target
+
+# Name "ICONS - Win32 Release"
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+# Begin Source File
+
+SOURCE=.\ICONS.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus01.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus02.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus03.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus04.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus05.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus06.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus07.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus08.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus09.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus10.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus11.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus12.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus13.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus14.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus15.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus16.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus17.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus18.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus19.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus20.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus21.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus22.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus23.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus24.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus25.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus26.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus27.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus28.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus29.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus30.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus31.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\icos\xstatus32.ico
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/icqj_mod/icons_pack/ICONS.dsw b/icqj_mod/icons_pack/ICONS.dsw new file mode 100644 index 0000000..17255a8 --- /dev/null +++ b/icqj_mod/icons_pack/ICONS.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "ICONS"=".\ICONS.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/icqj_mod/icons_pack/ICONS.mak b/icqj_mod/icons_pack/ICONS.mak new file mode 100644 index 0000000..31b7af9 --- /dev/null +++ b/icqj_mod/icons_pack/ICONS.mak @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ICONS.dsp
+!IF "$(CFG)" == ""
+CFG=ICONS - Win32 Release
+!MESSAGE No configuration specified. Defaulting to ICONS - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "ICONS - Win32 Release"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ICONS.mak" CFG="ICONS - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ICONS - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\bin\release\plugins\xstatus_icons.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ICONS.res"
+ -@erase "$(OUTDIR)\xstatus_icons.exp"
+ -@erase "$(OUTDIR)\xstatus_icons.lib"
+ -@erase "$(OUTDIR)\xstatus_icons.pdb"
+ -@erase "..\..\..\bin\release\plugins\xstatus_icons.dll"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ICONS.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /dll /incremental:no /pdb:"$(OUTDIR)\xstatus_icons.pdb" /debug /machine:I386 /out:"..\..\..\bin\release\plugins\xstatus_icons.dll" /implib:"$(OUTDIR)\xstatus_icons.lib" /noentry /ALIGN:4096 /ignore:4108
+LINK32_OBJS= \
+ "$(INTDIR)\ICONS.res"
+
+"..\..\..\bin\release\plugins\xstatus_icons.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+CPP_PROJ=/nologo /MT /W3 /GX /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "ICONS_EXPORTS" /D "_MBCS" /Fp"$(INTDIR)\ICONS.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL_PROJ=/nologo /win32
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\ICONS.res"
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("ICONS.dep")
+!INCLUDE "ICONS.dep"
+!ELSE
+!MESSAGE Warning: cannot find "ICONS.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "ICONS - Win32 Release"
+SOURCE=.\ICONS.rc
+
+"$(INTDIR)\ICONS.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/icqj_mod/icons_pack/ICONS.rc b/icqj_mod/icons_pack/ICONS.rc new file mode 100644 index 0000000..7a4d080 --- /dev/null +++ b/icqj_mod/icons_pack/ICONS.rc @@ -0,0 +1,120 @@ +// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+#ifdef _WIN32
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Russian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_XSTATUS1 ICON "..\\icos\\xstatus01.ico"
+IDI_XSTATUS2 ICON "..\\icos\\xstatus02.ico"
+IDI_XSTATUS3 ICON "..\\icos\\xstatus03.ico"
+IDI_XSTATUS4 ICON "..\\icos\\xstatus04.ico"
+IDI_XSTATUS5 ICON "..\\icos\\xstatus05.ico"
+IDI_XSTATUS6 ICON "..\\icos\\xstatus06.ico"
+IDI_XSTATUS7 ICON "..\\icos\\xstatus07.ico"
+IDI_XSTATUS8 ICON "..\\icos\\xstatus08.ico"
+IDI_XSTATUS9 ICON "..\\icos\\xstatus09.ico"
+IDI_XSTATUS10 ICON "..\\icos\\xstatus10.ico"
+IDI_XSTATUS11 ICON "..\\icos\\xstatus11.ico"
+IDI_XSTATUS12 ICON "..\\icos\\xstatus12.ico"
+IDI_XSTATUS13 ICON "..\\icos\\xstatus13.ico"
+IDI_XSTATUS14 ICON "..\\icos\\xstatus14.ico"
+IDI_XSTATUS15 ICON "..\\icos\\xstatus15.ico"
+IDI_XSTATUS16 ICON "..\\icos\\xstatus16.ico"
+IDI_XSTATUS17 ICON "..\\icos\\xstatus17.ico"
+IDI_XSTATUS18 ICON "..\\icos\\xstatus18.ico"
+IDI_XSTATUS19 ICON "..\\icos\\xstatus19.ico"
+IDI_XSTATUS20 ICON "..\\icos\\xstatus20.ico"
+IDI_XSTATUS21 ICON "..\\icos\\xstatus21.ico"
+IDI_XSTATUS22 ICON "..\\icos\\xstatus22.ico"
+IDI_XSTATUS23 ICON "..\\icos\\xstatus23.ico"
+IDI_XSTATUS24 ICON "..\\icos\\xstatus24.ico"
+IDI_XSTATUS25 ICON "..\\icos\\xstatus25.ico"
+IDI_XSTATUS26 ICON "..\\icos\\xstatus26.ico"
+IDI_XSTATUS27 ICON "..\\icos\\xstatus27.ico"
+IDI_XSTATUS28 ICON "..\\icos\\xstatus28.ico"
+IDI_XSTATUS29 ICON "..\\icos\\xstatus29.ico"
+IDI_XSTATUS30 ICON "..\\icos\\xstatus30.ico"
+IDI_XSTATUS31 ICON "..\\icos\\xstatus31.ico"
+IDI_XSTATUS32 ICON "..\\icos\\xstatus32.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_IDENTIFY "# Custom Status Icons #"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/icqj_mod/icons_pack/ICONS.vcproj b/icqj_mod/icons_pack/ICONS.vcproj new file mode 100644 index 0000000..85a918e --- /dev/null +++ b/icqj_mod/icons_pack/ICONS.vcproj @@ -0,0 +1,318 @@ +<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="xstatus_icons"
+ ProjectGUID="{47204E10-B438-4DFD-B115-E0F5A3F8A05E}"
+ RootNamespace="ICONS"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../../bin8/release/Plugins"
+ IntermediateDirectory="../../../bin8/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/ICONS.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="4"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ICONS_EXPORTS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="stdafx.h"
+ PrecompiledHeaderFile=".\Release/ICONS.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="odbc32.lib odbccp32.lib"
+ OutputFile="..\..\..\bin8\release\plugins\$(ProjectName).dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(IntDir)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(IntDir)\$(ProjectName).map"
+ ResourceOnlyDLL="true"
+ ImportLibrary="$(IntDir)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Release/ICONS.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ >
+ <File
+ RelativePath="..\icos\arrow.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\auth_ask.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\auth_grant.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\auth_revoke.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\check.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\dot.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\hidden.ico"
+ >
+ </File>
+ <File
+ RelativePath="ICONS.rc"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\icq.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\list.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\pause.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\privacy.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\scan.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\start.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\stop.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus01.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus02.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus03.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus04.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus05.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus06.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus07.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus08.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus09.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus10.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus11.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus12.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus13.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus14.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus15.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus16.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus17.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus18.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus19.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus20.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus21.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus22.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus23.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus24.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus25.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus26.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus27.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus28.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus29.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus30.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus31.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus32.ico"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/icqj_mod/icons_pack/resource.h b/icqj_mod/icons_pack/resource.h new file mode 100644 index 0000000..e7ffd17 --- /dev/null +++ b/icqj_mod/icons_pack/resource.h @@ -0,0 +1,234 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by ICONS.rc
+//
+#define ID_FIRSTICON 1
+#define IDI_ICQ 101
+#define IDD_ICQACCOUNT 102
+#define IDS_IDENTIFY 102
+#define IDD_ASKAUTH 103
+#define IDS_IDENTIFY1 103
+#define IDD_LOGINPW 104
+#define IDD_INFO_AVATAR 105
+#define IDD_OPT_ICQMAIN 106
+#define IDD_OPT_ICQFEATURES 107
+#define IDD_OPT_ICQPRIVACY 111
+#define IDI_PRIVACY 111
+#define IDI_DOT 112
+#define IDI_CHECK 113
+#define IDI_LIST 114
+#define IDI_SCAN 121
+#define IDI_START 122
+#define IDI_PAUSE 123
+#define IDI_STOP 124
+#define IDI_HIDDEN 125
+#define IDI_AUTH 131
+#define IDI_GRANT 132
+#define IDI_REMOVE 133
+#define IDI_ICON2 141
+#define IDI_AUTH_ASK 150
+#define IDD_CONFIRM 151
+#define IDI_AUTH_GRANT 151
+#define IDD_OPT_ICQ 152
+#define IDI_AUTH_REVOKE 152
+//#define IDI_SET_VIS 153
+//#define IDI_SET_INVIS 154
+#define ID_LASTICON 199
+#define IDI_XSTATUS1 201
+#define IDI_XSTATUS2 202
+#define IDI_XSTATUS3 203
+#define IDI_XSTATUS4 204
+#define IDI_XSTATUS5 205
+#define IDI_XSTATUS6 206
+#define IDI_XSTATUS7 207
+#define IDI_XSTATUS8 208
+#define IDI_XSTATUS9 209
+#define IDI_XSTATUS10 210
+#define IDI_XSTATUS11 211
+#define IDI_XSTATUS12 212
+#define IDI_XSTATUS13 213
+#define IDI_XSTATUS14 214
+#define IDI_XSTATUS15 215
+#define IDI_XSTATUS16 216
+#define IDI_XSTATUS17 217
+#define IDI_XSTATUS18 218
+#define IDI_XSTATUS19 219
+#define IDI_XSTATUS20 220
+#define IDI_XSTATUS21 221
+#define IDI_XSTATUS22 222
+#define IDI_XSTATUS23 223
+#define IDI_XSTATUS24 224
+#define IDI_XSTATUS25 225
+#define IDI_XSTATUS26 226
+#define IDI_XSTATUS27 227
+#define IDI_XSTATUS28 228
+#define IDI_XSTATUS29 229
+#define IDI_XSTATUS30 230
+#define IDI_XSTATUS31 231
+#define IDI_XSTATUS32 232
+#define IDD_INFO_ICQ 240
+#define IDD_ICQADVANCEDSEARCH 242
+#define IDD_OPT_ICQCONTACTS 252
+#define IDD_ICQUPLOADLIST 253
+#define IDD_SETXSTATUS 256
+#define IDD_PWCONFIRM 300
+#define IDD_INFO_CHANGEINFO 301
+#define IDD_OPT_POPUPS 400
+#define IDC_POPUPS_ENABLED 410
+#define IDC_POPUPS_LOG_ENABLED 411
+#define IDC_POPUPS_SPAM_ENABLED 412
+#define IDC_POPUP_LOG0_TEXTCOLOR 420
+#define IDC_POPUP_LOG1_TEXTCOLOR 421
+#define IDC_POPUP_LOG2_TEXTCOLOR 422
+#define IDC_POPUP_LOG3_TEXTCOLOR 423
+#define IDC_POPUP_SPAM_TEXTCOLOR 425
+#define IDC_POPUP_LOG0_BACKCOLOR 430
+#define IDC_POPUP_LOG1_BACKCOLOR 431
+#define IDC_POPUP_LOG2_BACKCOLOR 432
+#define IDC_POPUP_LOG3_BACKCOLOR 433
+#define IDC_POPUP_SPAM_BACKCOLOR 435
+#define IDC_POPUP_LOG0_TIMEOUT 440
+#define IDC_POPUP_LOG1_TIMEOUT 441
+#define IDC_POPUP_LOG2_TIMEOUT 442
+#define IDC_POPUP_LOG3_TIMEOUT 443
+#define IDC_POPUP_SPAM_TIMEOUT 444
+#define IDC_USEWINCOLORS 450
+#define IDC_USESYSICONS 451
+#define IDC_PREVIEW 455
+#define IDC_OPTIONSTAB 500
+#define IDC_LOG 1001
+#define IDI_EXPANDSTRINGEDIT 1001
+#define IDC_SAVEPASS 1004
+#define IDC_RETRXSTATUS 1005
+#define IDC_FLAGSTEXT 1008
+#define IDC_SECURE 1009
+#define IDC_USEGATEWAY 1010
+#define IDC_UTFENABLE 1010
+#define IDC_XTITLE 1010
+#define IDC_FLAGS 1010
+#define IDC_KEEPALIVE 1011
+#define IDC_XMSG 1011
+#define IDC_UTFALL 1012
+#define IDC_UTFSTATIC 1013
+#define IDC_UTFCODEPAGE 1014
+#define IDC_PW 1015
+#define IDC_TEMPVISIBLE 1015
+#define IDC_REGISTER 1016
+#define IDC_EDITAUTH 1017
+#define IDC_LOGINPW 1018
+#define IDC_INSTRUCTION 1019
+#define IDC_PASSWORD 1020
+#define IDC_SUPTIME 1020
+#define IDC_DCENABLE 1020
+#define IDC_DCPASSIVE 1021
+#define IDC_OLDPASS 1021
+#define IDC_ICQNUM 1022
+#define IDC_AVATAR 1023
+#define IDC_SETAVATAR 1024
+#define IDC_RETRIEVE 1024
+#define IDC_DELETEAVATAR 1025
+#define IDC_AIMENABLE 1030
+#define IDC_GETSTATUS 1030
+#define IDC_CLIST 1035
+#define IDC_XSTATUSENABLE 1040
+#define IDC_XSTATUSAUTO 1041
+#define IDC_XSTATUSRESET 1042
+#define IDC_KILLSPAMBOTS 1045
+#define IDC_EMAIL 1048
+#define IDC_NICK 1053
+#define IDC_GENDER 1060
+#define IDC_CITY 1061
+#define IDC_STATE 1062
+#define IDC_COUNTRY 1063
+#define IDC_COMPANY 1066
+#define IDC_DEPARTMENT 1067
+#define IDC_POSITION 1069
+#define IDC_IP 1094
+#define IDC_UINSTATIC 1122
+#define IDC_UIN 1123
+#define IDC_STATIC11 1154
+#define IDC_STATIC12 1155
+#define IDC_ICQSERVER 1171
+#define IDC_ICQPORT 1172
+#define IDC_VERSION 1179
+#define IDC_FIRSTNAME 1224
+#define IDC_LASTNAME 1225
+#define IDC_REALIP 1230
+#define IDC_RECONNECTREQD 1239
+#define IDC_OFFLINETOENABLE 1240
+#define IDC_PORT 1249
+#define IDC_MIRVER 1251
+#define IDC_ONLINESINCE 1252
+#define IDC_SYSTEMUPTIME 1253
+#define IDC_IDLETIME 1254
+#define IDC_STATUS 1255
+#define IDC_SLOWSEND 1301
+#define IDC_ONLYSERVERACKS 1302
+#define IDC_LOGLEVEL 1331
+#define IDC_LEVELDESCR 1332
+#define IDC_NOERRMULTI 1333
+#define IDC_STICQGROUP 1374
+#define IDC_ASD 1380
+#define IDC_AGERANGE 1410
+#define IDC_MARITALSTATUS 1411
+#define IDC_KEYWORDS 1412
+#define IDC_LANGUAGE 1414
+#define IDC_WORKFIELD 1421
+#define IDC_PASTCAT 1422
+#define IDC_PASTKEY 1423
+#define IDC_INTERESTSCAT 1424
+#define IDC_INTERESTSKEY 1425
+#define IDC_ORGANISATION 1426
+#define IDC_ORGKEYWORDS 1427
+#define IDC_OTHERGROUP 1429
+#define IDC_ONLINEONLY 1430
+#define IDC_HOMEPAGECAT 1431
+#define IDC_HOMEPAGEKEY 1432
+#define IDC_SUMMARYGROUP 1434
+#define IDC_WORKGROUP 1435
+#define IDC_LOCATIONGROUP 1436
+#define IDC_BACKGROUNDGROUP 1437
+#define IDC_NEWUINLINK 1438
+#define IDC_LOOKUPLINK 1439
+#define IDC_RESETSERVER 1472
+#define IDC_UPLOADNOW 1521
+#define IDC_GROUPS 1522
+#define IDC_ALLGROUPS 1526
+#define IDC_VISIBILITY 1527
+#define IDC_IGNORE 1528
+#define IDC_ENABLE 1529
+#define IDC_LOADFROMSERVER 1530
+#define IDC_LINKAVATARS 1531
+#define IDC_ADDSERVER 1532
+#define IDC_SAVETOSERVER 1533
+#define IDC_ENABLEAVATARS 1536
+#define IDC_AUTOLOADAVATARS 1537
+#define IDC_IGNORECHECK 1537
+#define IDC_WEBAWARE 1546
+#define IDC_DCALLOW_ANY 1547
+#define IDC_DCALLOW_CLIST 1548
+#define IDC_DCALLOW_AUTH 1549
+#define IDC_PUBLISHPRIMARY 1550
+#define IDC_ADD_ANY 1551
+#define IDC_ADD_AUTH 1552
+#define IDC_STATUSMSG_CLIST 1553
+#define IDC_STATUSMSG_VISIBLE 1554
+#define IDC_STATIC_NOTONLINE 1555
+#define IDC_STATIC_DC2 1556
+#define IDC_STATIC_DC1 1557
+#define IDC_STATIC_CLIST 1558
+#define IDC_CONFIRMATION 1560
+#define IDC_SAVE 1600
+#define IDC_LIST 1601
+#define IDC_UPLOADING 1602
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 120
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1026
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/icqj_mod/icos/arrow.ico b/icqj_mod/icos/arrow.ico Binary files differnew file mode 100644 index 0000000..aefec22 --- /dev/null +++ b/icqj_mod/icos/arrow.ico diff --git a/icqj_mod/icos/auth_ask.ico b/icqj_mod/icos/auth_ask.ico Binary files differnew file mode 100644 index 0000000..54c4601 --- /dev/null +++ b/icqj_mod/icos/auth_ask.ico diff --git a/icqj_mod/icos/auth_grant.ico b/icqj_mod/icos/auth_grant.ico Binary files differnew file mode 100644 index 0000000..08b6710 --- /dev/null +++ b/icqj_mod/icos/auth_grant.ico diff --git a/icqj_mod/icos/auth_revoke.ico b/icqj_mod/icos/auth_revoke.ico Binary files differnew file mode 100644 index 0000000..386e234 --- /dev/null +++ b/icqj_mod/icos/auth_revoke.ico diff --git a/icqj_mod/icos/check.ico b/icqj_mod/icos/check.ico Binary files differnew file mode 100644 index 0000000..6e3b4d9 --- /dev/null +++ b/icqj_mod/icos/check.ico diff --git a/icqj_mod/icos/dot.ico b/icqj_mod/icos/dot.ico Binary files differnew file mode 100644 index 0000000..82423a6 --- /dev/null +++ b/icqj_mod/icos/dot.ico diff --git a/icqj_mod/icos/hidden.ico b/icqj_mod/icos/hidden.ico Binary files differnew file mode 100644 index 0000000..51c84c5 --- /dev/null +++ b/icqj_mod/icos/hidden.ico diff --git a/icqj_mod/icos/icq.ico b/icqj_mod/icos/icq.ico Binary files differnew file mode 100644 index 0000000..bb1b781 --- /dev/null +++ b/icqj_mod/icos/icq.ico diff --git a/icqj_mod/icos/list.ico b/icqj_mod/icos/list.ico Binary files differnew file mode 100644 index 0000000..af93fd2 --- /dev/null +++ b/icqj_mod/icos/list.ico diff --git a/icqj_mod/icos/pause.ico b/icqj_mod/icos/pause.ico Binary files differnew file mode 100644 index 0000000..60536a1 --- /dev/null +++ b/icqj_mod/icos/pause.ico diff --git a/icqj_mod/icos/privacy.ico b/icqj_mod/icos/privacy.ico Binary files differnew file mode 100644 index 0000000..d8b1182 --- /dev/null +++ b/icqj_mod/icos/privacy.ico diff --git a/icqj_mod/icos/scan.ico b/icqj_mod/icos/scan.ico Binary files differnew file mode 100644 index 0000000..d0abef5 --- /dev/null +++ b/icqj_mod/icos/scan.ico diff --git a/icqj_mod/icos/set_invis.ico b/icqj_mod/icos/set_invis.ico Binary files differnew file mode 100644 index 0000000..cf29bdb --- /dev/null +++ b/icqj_mod/icos/set_invis.ico diff --git a/icqj_mod/icos/set_vis.ico b/icqj_mod/icos/set_vis.ico Binary files differnew file mode 100644 index 0000000..9789c71 --- /dev/null +++ b/icqj_mod/icos/set_vis.ico diff --git a/icqj_mod/icos/start.ico b/icqj_mod/icos/start.ico Binary files differnew file mode 100644 index 0000000..f3f1b0a --- /dev/null +++ b/icqj_mod/icos/start.ico diff --git a/icqj_mod/icos/stop.ico b/icqj_mod/icos/stop.ico Binary files differnew file mode 100644 index 0000000..757350d --- /dev/null +++ b/icqj_mod/icos/stop.ico diff --git a/icqj_mod/icos/xstatus01.ico b/icqj_mod/icos/xstatus01.ico Binary files differnew file mode 100644 index 0000000..6bc9d77 --- /dev/null +++ b/icqj_mod/icos/xstatus01.ico diff --git a/icqj_mod/icos/xstatus02.ico b/icqj_mod/icos/xstatus02.ico Binary files differnew file mode 100644 index 0000000..6de8459 --- /dev/null +++ b/icqj_mod/icos/xstatus02.ico diff --git a/icqj_mod/icos/xstatus03.ico b/icqj_mod/icos/xstatus03.ico Binary files differnew file mode 100644 index 0000000..bdd63a8 --- /dev/null +++ b/icqj_mod/icos/xstatus03.ico diff --git a/icqj_mod/icos/xstatus04.ico b/icqj_mod/icos/xstatus04.ico Binary files differnew file mode 100644 index 0000000..9fe9392 --- /dev/null +++ b/icqj_mod/icos/xstatus04.ico diff --git a/icqj_mod/icos/xstatus05.ico b/icqj_mod/icos/xstatus05.ico Binary files differnew file mode 100644 index 0000000..7d17bdd --- /dev/null +++ b/icqj_mod/icos/xstatus05.ico diff --git a/icqj_mod/icos/xstatus06.ico b/icqj_mod/icos/xstatus06.ico Binary files differnew file mode 100644 index 0000000..9bad185 --- /dev/null +++ b/icqj_mod/icos/xstatus06.ico diff --git a/icqj_mod/icos/xstatus07.ico b/icqj_mod/icos/xstatus07.ico Binary files differnew file mode 100644 index 0000000..16dbc21 --- /dev/null +++ b/icqj_mod/icos/xstatus07.ico diff --git a/icqj_mod/icos/xstatus08.ico b/icqj_mod/icos/xstatus08.ico Binary files differnew file mode 100644 index 0000000..d818ff0 --- /dev/null +++ b/icqj_mod/icos/xstatus08.ico diff --git a/icqj_mod/icos/xstatus09.ico b/icqj_mod/icos/xstatus09.ico Binary files differnew file mode 100644 index 0000000..49d68e9 --- /dev/null +++ b/icqj_mod/icos/xstatus09.ico diff --git a/icqj_mod/icos/xstatus10.ico b/icqj_mod/icos/xstatus10.ico Binary files differnew file mode 100644 index 0000000..188119e --- /dev/null +++ b/icqj_mod/icos/xstatus10.ico diff --git a/icqj_mod/icos/xstatus11.ico b/icqj_mod/icos/xstatus11.ico Binary files differnew file mode 100644 index 0000000..abe2e4b --- /dev/null +++ b/icqj_mod/icos/xstatus11.ico diff --git a/icqj_mod/icos/xstatus12.ico b/icqj_mod/icos/xstatus12.ico Binary files differnew file mode 100644 index 0000000..051f117 --- /dev/null +++ b/icqj_mod/icos/xstatus12.ico diff --git a/icqj_mod/icos/xstatus13.ico b/icqj_mod/icos/xstatus13.ico Binary files differnew file mode 100644 index 0000000..6784045 --- /dev/null +++ b/icqj_mod/icos/xstatus13.ico diff --git a/icqj_mod/icos/xstatus14.ico b/icqj_mod/icos/xstatus14.ico Binary files differnew file mode 100644 index 0000000..d34b9fe --- /dev/null +++ b/icqj_mod/icos/xstatus14.ico diff --git a/icqj_mod/icos/xstatus15.ico b/icqj_mod/icos/xstatus15.ico Binary files differnew file mode 100644 index 0000000..5942549 --- /dev/null +++ b/icqj_mod/icos/xstatus15.ico diff --git a/icqj_mod/icos/xstatus16.ico b/icqj_mod/icos/xstatus16.ico Binary files differnew file mode 100644 index 0000000..96e2545 --- /dev/null +++ b/icqj_mod/icos/xstatus16.ico diff --git a/icqj_mod/icos/xstatus17.ico b/icqj_mod/icos/xstatus17.ico Binary files differnew file mode 100644 index 0000000..d73be87 --- /dev/null +++ b/icqj_mod/icos/xstatus17.ico diff --git a/icqj_mod/icos/xstatus18.ico b/icqj_mod/icos/xstatus18.ico Binary files differnew file mode 100644 index 0000000..b4257ce --- /dev/null +++ b/icqj_mod/icos/xstatus18.ico diff --git a/icqj_mod/icos/xstatus19.ico b/icqj_mod/icos/xstatus19.ico Binary files differnew file mode 100644 index 0000000..b45a166 --- /dev/null +++ b/icqj_mod/icos/xstatus19.ico diff --git a/icqj_mod/icos/xstatus20.ico b/icqj_mod/icos/xstatus20.ico Binary files differnew file mode 100644 index 0000000..99094f8 --- /dev/null +++ b/icqj_mod/icos/xstatus20.ico diff --git a/icqj_mod/icos/xstatus21.ico b/icqj_mod/icos/xstatus21.ico Binary files differnew file mode 100644 index 0000000..f9510f1 --- /dev/null +++ b/icqj_mod/icos/xstatus21.ico diff --git a/icqj_mod/icos/xstatus22.ico b/icqj_mod/icos/xstatus22.ico Binary files differnew file mode 100644 index 0000000..fffe979 --- /dev/null +++ b/icqj_mod/icos/xstatus22.ico diff --git a/icqj_mod/icos/xstatus23.ico b/icqj_mod/icos/xstatus23.ico Binary files differnew file mode 100644 index 0000000..66db1ef --- /dev/null +++ b/icqj_mod/icos/xstatus23.ico diff --git a/icqj_mod/icos/xstatus24.ico b/icqj_mod/icos/xstatus24.ico Binary files differnew file mode 100644 index 0000000..df468f9 --- /dev/null +++ b/icqj_mod/icos/xstatus24.ico diff --git a/icqj_mod/icos/xstatus25.ico b/icqj_mod/icos/xstatus25.ico Binary files differnew file mode 100644 index 0000000..2cbb2ad --- /dev/null +++ b/icqj_mod/icos/xstatus25.ico diff --git a/icqj_mod/icos/xstatus26.ico b/icqj_mod/icos/xstatus26.ico Binary files differnew file mode 100644 index 0000000..7b3d89f --- /dev/null +++ b/icqj_mod/icos/xstatus26.ico diff --git a/icqj_mod/icos/xstatus27.ico b/icqj_mod/icos/xstatus27.ico Binary files differnew file mode 100644 index 0000000..1ae5ac5 --- /dev/null +++ b/icqj_mod/icos/xstatus27.ico diff --git a/icqj_mod/icos/xstatus28.ico b/icqj_mod/icos/xstatus28.ico Binary files differnew file mode 100644 index 0000000..c8ca9ff --- /dev/null +++ b/icqj_mod/icos/xstatus28.ico diff --git a/icqj_mod/icos/xstatus29.ico b/icqj_mod/icos/xstatus29.ico Binary files differnew file mode 100644 index 0000000..f8be002 --- /dev/null +++ b/icqj_mod/icos/xstatus29.ico diff --git a/icqj_mod/icos/xstatus30.ico b/icqj_mod/icos/xstatus30.ico Binary files differnew file mode 100644 index 0000000..02f6f28 --- /dev/null +++ b/icqj_mod/icos/xstatus30.ico diff --git a/icqj_mod/icos/xstatus31.ico b/icqj_mod/icos/xstatus31.ico Binary files differnew file mode 100644 index 0000000..da441df --- /dev/null +++ b/icqj_mod/icos/xstatus31.ico diff --git a/icqj_mod/icos/xstatus32.ico b/icqj_mod/icos/xstatus32.ico Binary files differnew file mode 100644 index 0000000..ac91a82 --- /dev/null +++ b/icqj_mod/icos/xstatus32.ico diff --git a/icqj_mod/icq_advsearch.c b/icqj_mod/icq_advsearch.c new file mode 100644 index 0000000..9284b26 --- /dev/null +++ b/icqj_mod/icq_advsearch.c @@ -0,0 +1,211 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_advsearch.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+static void InitComboBox(HWND hwndCombo,struct fieldnames_t *names)
+{
+ int iItem;
+ int i;
+
+ iItem = ComboBoxAddStringUtf(hwndCombo, "", 0);
+ SendMessage(hwndCombo, CB_SETCURSEL, iItem, 0);
+
+ for (i = 0; ; i++)
+ {
+ if (names[i].text == NULL)
+ break;
+
+ iItem = ComboBoxAddStringUtf(hwndCombo, names[i].text, names[i].code);
+ }
+}
+
+
+
+BOOL CALLBACK AdvancedSearchDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_GENDER), genderField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_AGERANGE), agesField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_MARITALSTATUS), maritalField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_WORKFIELD), workField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_ORGANISATION), affiliationField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_LANGUAGE), languageField);
+
+ {
+ struct CountryListEntry *countries;
+ int countryCount;
+ int i;
+ int iItem;
+ HWND hCombo;
+
+ CallService(MS_UTILS_GETCOUNTRYLIST, (WPARAM)&countryCount, (LPARAM)&countries);
+
+ hCombo = GetDlgItem(hwndDlg, IDC_COUNTRY);
+ iItem = ComboBoxAddStringUtf(hCombo, "", 0);
+ SendMessage(hCombo, CB_SETCURSEL, iItem, 0);
+ for (i = 0; i < countryCount; i++)
+ {
+ if (countries[i].id == 0 || countries[i].id == 0xFFFF)
+ continue;
+ iItem = ComboBoxAddStringUtf(hCombo, countries[i].szName, countries[i].id);
+ }
+ }
+
+ InitComboBox(GetDlgItem(hwndDlg, IDC_INTERESTSCAT), interestsField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_PASTCAT), pastField);
+
+ return TRUE;
+
+ case WM_COMMAND:
+ {
+ switch(LOWORD(wParam))
+ {
+
+ case IDOK:
+ SendMessage(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), (LPARAM)GetDlgItem(GetParent(hwndDlg), IDOK));
+ break;
+
+ case IDCANCEL:
+ // CheckDlgButton(GetParent(hwndDlg),IDC_ADVANCED,BST_UNCHECKED);
+ // SendMessage(GetParent(hwndDlg),WM_COMMAND,MAKEWPARAM(IDC_ADVANCED,BN_CLICKED),(LPARAM)GetDlgItem(GetParent(hwndDlg),IDC_ADVANCED));
+ break;
+
+ default:
+ break;
+
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+
+
+static DWORD getCurItemData(HWND hwndDlg, UINT iCtrl)
+{
+ return SendDlgItemMessage(hwndDlg, iCtrl, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, iCtrl, CB_GETCURSEL, 0, 0), 0);
+}
+
+
+
+static void searchPackTLVLNTS(PBYTE *buf, int *buflen, HWND hwndDlg, UINT idControl, WORD wType)
+{
+ char str[512];
+
+ GetDlgItemText(hwndDlg, idControl, str, sizeof(str));
+
+ ppackTLVLNTS(buf, buflen, str, wType, 0);
+}
+
+
+
+static void searchPackTLVWordLNTS(PBYTE *buf, int *buflen, HWND hwndDlg, UINT idControl, WORD w, WORD wType)
+{
+ char str[512];
+
+ GetDlgItemText(hwndDlg, idControl, str, sizeof(str));
+
+ ppackTLVWordLNTS(buf, buflen, w, str, wType, 0);
+}
+
+
+
+static PBYTE createAdvancedSearchStructureTLV(HWND hwndDlg, int *length)
+{
+ PBYTE buf = NULL;
+ int buflen = 0;
+ WORD w;
+
+ ppackLEWord(&buf, &buflen, META_SEARCH_GENERIC); /* subtype: full search */
+
+ searchPackTLVLNTS(&buf, &buflen, hwndDlg, IDC_FIRSTNAME, TLV_FIRSTNAME);
+ searchPackTLVLNTS(&buf, &buflen, hwndDlg, IDC_LASTNAME, TLV_LASTNAME);
+ searchPackTLVLNTS(&buf, &buflen, hwndDlg, IDC_NICK, TLV_NICKNAME);
+ searchPackTLVLNTS(&buf, &buflen, hwndDlg, IDC_EMAIL, TLV_EMAIL);
+ searchPackTLVLNTS(&buf, &buflen, hwndDlg, IDC_CITY, TLV_CITY);
+ searchPackTLVLNTS(&buf, &buflen, hwndDlg, IDC_STATE, TLV_STATE);
+ searchPackTLVLNTS(&buf, &buflen, hwndDlg, IDC_COMPANY, TLV_COMPANY);
+ searchPackTLVLNTS(&buf, &buflen, hwndDlg, IDC_DEPARTMENT, TLV_DEPARTMENT);
+ searchPackTLVLNTS(&buf, &buflen, hwndDlg, IDC_POSITION, TLV_POSITION);
+ searchPackTLVLNTS(&buf, &buflen, hwndDlg, IDC_KEYWORDS, TLV_KEYWORDS);
+
+ ppackTLVDWord(&buf, &buflen, (DWORD)getCurItemData(hwndDlg, IDC_AGERANGE), TLV_AGERANGE, 0);
+ ppackTLVByte(&buf, &buflen, (BYTE)getCurItemData(hwndDlg, IDC_GENDER), TLV_GENDER, 0);
+ ppackTLVByte(&buf, &buflen, (BYTE)getCurItemData(hwndDlg, IDC_MARITALSTATUS), TLV_MARITAL, 0);
+ ppackTLVWord(&buf, &buflen, (WORD)getCurItemData(hwndDlg, IDC_LANGUAGE), TLV_LANGUAGE, 0);
+ ppackTLVWord(&buf, &buflen, (WORD)getCurItemData(hwndDlg, IDC_COUNTRY), TLV_COUNTRY, 0);
+ ppackTLVWord(&buf, &buflen, (WORD)getCurItemData(hwndDlg, IDC_WORKFIELD), TLV_OCUPATION, 0);
+
+ w = (WORD)getCurItemData(hwndDlg, IDC_PASTCAT);
+ searchPackTLVWordLNTS(&buf, &buflen, hwndDlg, IDC_PASTKEY, w, TLV_PASTINFO);
+
+ w = (WORD)getCurItemData(hwndDlg, IDC_INTERESTSCAT);
+ searchPackTLVWordLNTS(&buf, &buflen, hwndDlg, IDC_INTERESTSKEY, w, TLV_INTERESTS);
+
+ w = (WORD)getCurItemData(hwndDlg, IDC_ORGANISATION);
+ searchPackTLVWordLNTS(&buf, &buflen, hwndDlg, IDC_ORGKEYWORDS, w, TLV_AFFILATIONS);
+
+ w = (WORD)getCurItemData(hwndDlg, IDC_HOMEPAGECAT);;
+ searchPackTLVWordLNTS(&buf, &buflen, hwndDlg, IDC_HOMEPAGEKEY, w, TLV_HOMEPAGE);
+
+ ppackTLVByte(&buf, &buflen, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_ONLINEONLY), TLV_ONLINEONLY, 1);
+
+ if (length)
+ *length = buflen;
+
+ return buf;
+}
+
+
+
+PBYTE createAdvancedSearchStructure(HWND hwndDlg, int *length)
+{
+ if (!hwndDlg)
+ return NULL;
+
+ return createAdvancedSearchStructureTLV(hwndDlg, length);
+}
diff --git a/icqj_mod/icq_advsearch.h b/icqj_mod/icq_advsearch.h new file mode 100644 index 0000000..d677c40 --- /dev/null +++ b/icqj_mod/icq_advsearch.h @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_advsearch.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+BOOL CALLBACK AdvancedSearchDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam);
+PBYTE createAdvancedSearchStructure(HWND hwndDlg,int *length);
diff --git a/icqj_mod/icq_avatar.c b/icqj_mod/icq_avatar.c new file mode 100644 index 0000000..81c6bc0 --- /dev/null +++ b/icqj_mod/icq_avatar.c @@ -0,0 +1,1275 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_avatar.c,v $
+// Revision : $Revision: 2940 $
+// Last change on : $Date: 2006-05-23 20:46:36 +0200 (Tue, 23 May 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Manages Avatar connection, provides internal service for handling avatars
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+BOOL AvatarsReady = FALSE; // states if avatar connection established and ready for requests
+
+
+typedef struct avatarthreadstartinfo_t
+{
+ HANDLE hConnection; // handle to the connection
+ char* pCookie;
+ WORD wCookieLen;
+ HANDLE hAvatarPacketRecver;
+ int stopThread; // horrible, but simple - signal for thread to stop
+ WORD wLocalSequence;
+ CRITICAL_SECTION localSeqMutex;
+ int pendingLogin;
+ int paused;
+ HANDLE runContact[4];
+ DWORD runTime[4];
+ int runCount;
+} avatarthreadstartinfo;
+
+typedef struct avatarrequest_t
+{
+ int type;
+ DWORD dwUin;
+ char *szUid;
+ HANDLE hContact;
+ char *hash;
+ unsigned int hashlen;
+ char *szFile;
+ char *pData;
+ unsigned int cbData;
+ WORD wRef;
+ void *pNext; // invalid, but reused - spare realloc
+} avatarrequest;
+
+avatarthreadstartinfo* currentAvatarThread;
+int pendingAvatarsStart = 1;
+static avatarrequest* pendingRequests = NULL;
+
+extern CRITICAL_SECTION cookieMutex;
+
+static int sendAvatarPacket(icq_packet* pPacket, avatarthreadstartinfo* atsi /*= currentAvatarThread*/);
+
+static DWORD __stdcall icq_avatarThread(avatarthreadstartinfo *atsi);
+int handleAvatarPackets(unsigned char* buf, int buflen, avatarthreadstartinfo* atsi);
+
+void handleAvatarLogin(unsigned char *buf, WORD datalen, avatarthreadstartinfo *atsi);
+void handleAvatarData(unsigned char *pBuffer, WORD wBufferLength, avatarthreadstartinfo *atsi);
+
+void handleAvatarServiceFam(unsigned char* pBuffer, WORD wBufferLength, snac_header* pSnacHeader, avatarthreadstartinfo *atsi);
+void handleAvatarFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader, avatarthreadstartinfo *atsi);
+
+
+char* loadMyAvatarFileName()
+{
+ DBVARIANT dbvFile = {0};
+
+ if (!ICQGetContactSetting(NULL, "AvatarFile", &dbvFile))
+ {
+ char tmp[MAX_PATH];;
+
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)dbvFile.pszVal, (LPARAM)tmp);
+ ICQFreeVariant(&dbvFile);
+ return null_strdup(tmp);
+ }
+ return NULL;
+}
+
+
+
+void storeMyAvatarFileName(char* szFile)
+{
+ char tmp[MAX_PATH];
+
+ CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)szFile, (LPARAM)tmp);
+ ICQWriteContactSettingString(NULL, "AvatarFile", tmp);
+}
+
+
+
+void GetFullAvatarFileName(int dwUin, char* szUid, int dwFormat, char* pszDest, int cbLen)
+{
+ GetAvatarFileName(dwUin, szUid, pszDest, cbLen);
+ AddAvatarExt(dwFormat, pszDest);
+}
+
+
+
+void GetAvatarFileName(int dwUin, char* szUid, char* pszDest, int cbLen)
+{
+ int tPathLen;
+
+ CallService(MS_DB_GETPROFILEPATH, cbLen, (LPARAM)pszDest);
+
+ tPathLen = strlennull(pszDest);
+ tPathLen += null_snprintf(pszDest + tPathLen, MAX_PATH-tPathLen, "\\%s\\", gpszICQProtoName);
+ CreateDirectory(pszDest, NULL);
+
+ if (dwUin != 0)
+ {
+ ltoa(dwUin, pszDest + tPathLen, 10);
+ }
+ else if (szUid)
+ {
+ strcpy(pszDest + tPathLen, szUid);
+ }
+ else
+ {
+ char szBuf[MAX_PATH];
+
+ if (CallService(MS_DB_GETPROFILENAME, 250 - tPathLen, (LPARAM)szBuf))
+ strcpy(pszDest + tPathLen, "avatar" );
+ else
+ {
+ char* szLastDot = strstr(szBuf, ".");
+ if (szLastDot) while (strstr(szLastDot+1, ".")) szLastDot = strstr(szLastDot+1, ".");
+ if (szLastDot) szLastDot[0] = '\0';
+ strcpy(pszDest + tPathLen, szBuf);
+ strcat(pszDest + tPathLen, "_avt");
+ }
+ }
+}
+
+
+
+void AddAvatarExt(int dwFormat, char* pszDest)
+{
+ if (dwFormat == PA_FORMAT_JPEG)
+ strcat(pszDest, ".jpg");
+ else if (dwFormat == PA_FORMAT_GIF)
+ strcat(pszDest, ".gif");
+ else if (dwFormat == PA_FORMAT_PNG)
+ strcat(pszDest, ".png");
+ else if (dwFormat == PA_FORMAT_BMP)
+ strcat(pszDest, ".bmp");
+ else if (dwFormat == PA_FORMAT_XML)
+ strcat(pszDest, ".xml");
+ else if (dwFormat == PA_FORMAT_SWF)
+ strcat(pszDest, ".swf");
+ else
+ strcat(pszDest, ".dat");
+}
+
+
+
+int DetectAvatarFormatBuffer(char* pBuffer)
+{
+ if (!strncmp(pBuffer, "%PNG", 4))
+ {
+ return PA_FORMAT_PNG;
+ }
+ if (!strncmp(pBuffer, "GIF8", 4))
+ {
+ return PA_FORMAT_GIF;
+ }
+ if (!strnicmp(pBuffer, "<?xml", 5))
+ {
+ return PA_FORMAT_XML;
+ }
+ if ((((DWORD*)pBuffer)[0] == 0xE0FFD8FFul) || (((DWORD*)pBuffer)[0] == 0xE1FFD8FFul))
+ {
+ return PA_FORMAT_JPEG;
+ }
+ if (!strncmp(pBuffer, "BM", 2))
+ {
+ return PA_FORMAT_BMP;
+ }
+ return PA_FORMAT_UNKNOWN;
+}
+
+
+
+int DetectAvatarFormat(char* szFile)
+{
+ char pBuf[32];
+
+ int src = _open(szFile, _O_BINARY | _O_RDONLY);
+
+ if (src != -1)
+ {
+ _read(src, pBuf, 32);
+ _close(src);
+
+ return DetectAvatarFormatBuffer(pBuf);
+ }
+ else
+ return PA_FORMAT_UNKNOWN;
+}
+
+
+
+int IsAvatarSaved(HANDLE hContact, char* pHash)
+{
+ DBVARIANT dbvSaved = {0};
+
+ if (!ICQGetContactSetting(hContact, "AvatarSaved", &dbvSaved))
+ {
+ if ((dbvSaved.cpbVal != 0x14) || memcmp(dbvSaved.pbVal, pHash, 0x14))
+ { // the hashes is different
+ ICQFreeVariant(&dbvSaved);
+
+ return 2;
+ }
+ ICQFreeVariant(&dbvSaved);
+
+ return 0; // hash is there and is the same - Success
+ }
+ return 1; // saved Avatar hash is missing
+}
+
+
+
+void StartAvatarThread(HANDLE hConn, char* cookie, WORD cookieLen) // called from event
+{
+ avatarthreadstartinfo* atsi = NULL;
+ pthread_t tid;
+
+ if (!hConn)
+ {
+ atsi = currentAvatarThread;
+ if (atsi && atsi->pendingLogin) // this is not safe...
+ {
+ NetLog_Server("Avatar, Multiple start thread attempt, ignored.");
+ SAFE_FREE(&cookie);
+ return;
+ }
+ pendingAvatarsStart = 0;
+ NetLog_Server("Avatar: Connect failed");
+
+ EnterCriticalSection(&cookieMutex); // wait for ready queue, reused cs
+ { // check if any upload request is not in the queue
+ avatarrequest* ar;
+ void** par = &pendingRequests;
+ int bYet = 0;
+ ar = pendingRequests;
+ while (ar)
+ {
+ if (ar->type == 2)
+ { // we found it, return error
+ void *tmp;
+
+ if (!bYet)
+ {
+ icq_LogMessage(LOG_WARNING, "Error uploading avatar to server, server temporarily unavailable.");
+ }
+ bYet = 1;
+ SAFE_FREE(&ar->pData); // remove upload request from queue
+ tmp = ar;
+ ar = ar->pNext;
+ *par = ar;
+ SAFE_FREE(&tmp);
+ continue;
+ }
+ par = &ar->pNext;
+ ar = ar->pNext;
+ }
+ }
+ LeaveCriticalSection(&cookieMutex);
+
+ SAFE_FREE(&cookie);
+
+ return;
+ }
+ atsi = currentAvatarThread;
+ if (atsi && atsi->pendingLogin) // this is not safe...
+ {
+ NetLog_Server("Avatar, Multiple start thread attempt, ignored.");
+ Netlib_CloseHandle(hConn);
+ SAFE_FREE(&cookie);
+ return;
+ }
+
+ AvatarsReady = FALSE; // the old connection should not be used anymore
+
+ atsi = (avatarthreadstartinfo*)SAFE_MALLOC(sizeof(avatarthreadstartinfo));
+ atsi->pendingLogin = 1;
+ // Randomize sequence
+ atsi->wLocalSequence = (WORD)RandRange(0, 0x7fff);
+ atsi->hConnection = hConn;
+ atsi->pCookie = cookie;
+ atsi->wCookieLen = cookieLen;
+ currentAvatarThread = atsi; // we store only current thread
+ tid.hThread = (HANDLE)forkthreadex(NULL, 0, icq_avatarThread, atsi, 0, &tid.dwThreadId);
+ CloseHandle(tid.hThread);
+
+ return;
+}
+
+
+
+void StopAvatarThread()
+{
+ AvatarsReady = FALSE; // the connection are about to close
+
+ if (currentAvatarThread)
+ {
+ currentAvatarThread->stopThread = 1; // make the thread stop
+ currentAvatarThread = NULL; // the thread will finish in background
+ }
+ return;
+}
+
+
+
+static void NetLog_Hash(const char* pszIdent, unsigned char* pHash)
+{
+ NetLog_Server("%s Hash: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", pszIdent, pHash[0], pHash[1], pHash[2], pHash[3], pHash[4], pHash[5], pHash[6], pHash[7], pHash[8], pHash[9], pHash[10], pHash[11], pHash[12], pHash[13], pHash[14], pHash[15], pHash[16], pHash[17], pHash[18], pHash[19]);
+}
+
+
+
+// handle Contact's avatar hash
+void handleAvatarContactHash(DWORD dwUIN, char* szUID, HANDLE hContact, unsigned char* pHash, unsigned int nHashLen, WORD wOldStatus)
+{
+ DBVARIANT dbv;
+ BOOL bJob = FALSE;
+ char szAvatar[MAX_PATH];
+ int dwPaFormat;
+
+ if (nHashLen >= 0x14)
+ {
+ // check if it is really avatar (it can be also AIM's online message)
+ if (pHash[0] != 0 || (pHash[1] != 1 && pHash[1] != 8)) return;
+
+ if (nHashLen == 0x18 && pHash[3] == 0)
+ { // icq probably set two avatars, get something from that
+ memcpy(pHash, pHash+4, 0x14);
+ }
+
+ if (gbAvatarsEnabled)
+ { // check settings, should we request avatar immediatelly
+ BYTE bAutoLoad = ICQGetContactSettingByte(NULL, "AvatarsAutoLoad", DEFAULT_LOAD_AVATARS);
+
+ if (ICQGetContactSetting(hContact, "AvatarHash", &dbv))
+ { // we not found old hash, i.e. get new avatar
+ int fileState = IsAvatarSaved(hContact, pHash);
+
+ // check saved hash and file, if equal only store hash
+ if (!fileState)
+ { // hashes are the same
+ dwPaFormat = ICQGetContactSettingByte(hContact, "AvatarType", PA_FORMAT_UNKNOWN);
+
+ GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, szAvatar, MAX_PATH);
+ if (access(szAvatar, 0) == 0)
+ { // the file is there, link to contactphoto, save hash
+ NetLog_Server("Avatar is known, hash stored, linked to file.");
+
+ ICQWriteContactSettingBlob(hContact, "AvatarHash", pHash, 0x14);
+
+ if (dwPaFormat != PA_FORMAT_UNKNOWN && dwPaFormat != PA_FORMAT_XML)
+ LinkContactPhotoToFile(hContact, szAvatar);
+ else // the format is not supported unlink
+ LinkContactPhotoToFile(hContact, NULL);
+
+ ICQBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, (LPARAM)NULL);
+ }
+ else // the file is lost, request avatar again
+ bJob = TRUE;
+ }
+ else
+ { // the hash is not the one we want, request avatar
+ if (fileState == 2)
+ { // the hash is different, unlink contactphoto
+ LinkContactPhotoToFile(hContact, NULL);
+ }
+ bJob = TRUE;
+ }
+ }
+ else
+ { // we found hash check if it changed or not
+ NetLog_Hash("Old", dbv.pbVal);
+ if ((dbv.cpbVal != 0x14) || memcmp(dbv.pbVal, pHash, 0x14))
+ { // the hash is different, request new avatar
+ LinkContactPhotoToFile(hContact, NULL); // unlink photo
+ bJob = TRUE;
+ }
+ else
+ { // the hash does not changed, check if we have correct file
+ int fileState = IsAvatarSaved(hContact, pHash);
+
+ // we should have file, check if the file really exists
+ if (!fileState)
+ {
+ dwPaFormat = ICQGetContactSettingByte(hContact, "AvatarType", PA_FORMAT_UNKNOWN);
+ if (dwPaFormat == PA_FORMAT_UNKNOWN)
+ { // we do not know the format, get avatar again
+ bJob = TRUE;
+ }
+ else
+ {
+ GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, szAvatar, MAX_PATH);
+ if (access(szAvatar, 0) == 0)
+ { // the file exists, so try to update photo setting
+ if (dwPaFormat != PA_FORMAT_XML && dwPaFormat != PA_FORMAT_UNKNOWN)
+ {
+ LinkContactPhotoToFile(hContact, szAvatar);
+ }
+ }
+ else // the file was lost, get it again
+ bJob = TRUE;
+ }
+ }
+ else
+ { // the hash is not the one we want, request avatar
+ if (fileState == 2)
+ { // the hash is different, unlink contactphoto
+ LinkContactPhotoToFile(hContact, NULL);
+ }
+ bJob = TRUE;
+ }
+ }
+ ICQFreeVariant(&dbv);
+ }
+
+ if (bJob)
+ {
+ NetLog_Hash("New", pHash);
+ NetLog_Server("User has Avatar, new hash stored.");
+
+ ICQWriteContactSettingBlob(hContact, "AvatarHash", pHash, 0x14);
+
+ ICQBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, (LPARAM)NULL);
+
+ if (bAutoLoad)
+ { // auto-load is on, so request the avatar now, otherwise we are done
+ GetAvatarFileName(dwUIN, szUID, szAvatar, MAX_PATH);
+ GetAvatarData(hContact, dwUIN, szUID, pHash, 0x14 /*nHashLen*/, szAvatar);
+ } // avatar request sent or added to queue
+ }
+ else
+ {
+ NetLog_Server("User has Avatar.");
+ }
+ }
+ }
+ else if (wOldStatus == ID_STATUS_OFFLINE)
+ { // if user were offline, and now hash not found, clear the hash
+ ICQDeleteContactSetting(hContact, "AvatarHash"); // TODO: need more testing
+ }
+}
+
+
+
+static avatarrequest* CreateAvatarRequest(int type)
+{
+ avatarrequest *ar;
+
+ ar = (avatarrequest*)SAFE_MALLOC(sizeof(avatarrequest));
+ if (ar)
+ ar->type = type;
+
+ return ar;
+}
+
+
+
+// request avatar data from server
+int GetAvatarData(HANDLE hContact, DWORD dwUin, char* szUid, char* hash, unsigned int hashlen, char* file)
+{
+ avatarthreadstartinfo* atsi;
+
+ atsi = currentAvatarThread; // we take avatar thread - horrible, but realiable
+ if (AvatarsReady && !atsi->paused) // check if we are ready
+ {
+ icq_packet packet;
+ BYTE nUinLen;
+ DWORD dwCookie;
+ avatarcookie* ack;
+ int i;
+ DWORD dwNow = GetTickCount();
+
+ EnterCriticalSection(&cookieMutex); // reused...
+ for(i = 0; i < atsi->runCount;)
+ { // look for timeouted requests
+ if (atsi->runTime[i] < dwNow)
+ { // found outdated, remove
+ atsi->runContact[i] = atsi->runContact[atsi->runCount - 1];
+ atsi->runTime[i] = atsi->runTime[atsi->runCount - 1];
+ atsi->runCount--;
+ }
+ else
+ i++;
+ }
+
+ for(i = 0; i < atsi->runCount; i++)
+ {
+ if (atsi->runContact[i] == hContact)
+ {
+ LeaveCriticalSection(&cookieMutex);
+ NetLog_Server("Ignoring duplicate get %d avatar request.", dwUin);
+
+ return 0;
+ }
+ }
+
+ if (atsi->runCount < 4)
+ { // 4 concurent requests at most
+ atsi->runContact[atsi->runCount] = hContact;
+ atsi->runTime[atsi->runCount] = GetTickCount() + 30000; // 30sec to complete request
+ atsi->runCount++;
+ LeaveCriticalSection(&cookieMutex);
+
+ nUinLen = getUIDLen(dwUin, szUid);
+
+ ack = (avatarcookie*)SAFE_MALLOC(sizeof(avatarcookie));
+ if (!ack) return 0; // out of memory, go away
+ ack->dwUin = 1; //dwUin; // I should be damned for this - only to identify get request
+ ack->hContact = hContact;
+ ack->hash = (char*)SAFE_MALLOC(hashlen);
+ memcpy(ack->hash, hash, hashlen); // copy the data
+ ack->hashlen = hashlen;
+ ack->szFile = null_strdup(file); // we duplicate the string
+ dwCookie = AllocateCookie(CKT_AVATAR, ICQ_AVATAR_GET_REQUEST, dwUin, ack);
+
+ serverPacketInit(&packet, (WORD)(12 + nUinLen + hashlen));
+ packFNACHeaderFull(&packet, ICQ_AVATAR_FAMILY, ICQ_AVATAR_GET_REQUEST, 0, dwCookie);
+ packUID(&packet, dwUin, szUid);
+ packByte(&packet, 1); // unknown, probably type of request: 1 = get icon :)
+ packBuffer(&packet, hash, (unsigned short)hashlen);
+
+ if (sendAvatarPacket(&packet, atsi))
+ {
+ NetLog_Server("Request to get %d avatar image sent.", dwUin);
+
+ return dwCookie;
+ }
+ FreeCookie(dwCookie); // sending failed, free resources
+ SAFE_FREE(&ack->szFile);
+ SAFE_FREE(&ack->hash);
+ SAFE_FREE(&ack);
+ }
+ else
+ LeaveCriticalSection(&cookieMutex);
+ }
+ // we failed to send request, or avatar thread not ready
+ EnterCriticalSection(&cookieMutex); // wait for ready queue, reused cs
+ { // check if any request for this user is not already in the queue
+ avatarrequest* ar;
+ int bYet = 0;
+ ar = pendingRequests;
+ while (ar)
+ {
+ if (ar->hContact == hContact)
+ { // we found it, return error
+ LeaveCriticalSection(&cookieMutex);
+ NetLog_Server("Ignoring duplicate get %d avatar request.", dwUin);
+
+ if (!AvatarsReady && !pendingAvatarsStart)
+ {
+ icq_requestnewfamily(ICQ_AVATAR_FAMILY, StartAvatarThread);
+ pendingAvatarsStart = 1;
+ }
+ return 0;
+ }
+ ar = ar->pNext;
+ }
+ // add request to queue, processed after successful login
+ ar = CreateAvatarRequest(1); // get avatar
+ if (!ar)
+ { // out of memory, go away
+ LeaveCriticalSection(&cookieMutex);
+ return 0;
+ }
+ ar->dwUin = dwUin;
+ ar->szUid = null_strdup(szUid);
+ ar->hContact = hContact;
+ ar->hash = (char*)SAFE_MALLOC(hashlen);
+ memcpy(ar->hash, hash, hashlen); // copy the data
+ ar->hashlen = hashlen;
+ ar->szFile = null_strdup(file); // duplicate the string
+ ar->pNext = pendingRequests;
+ pendingRequests = ar;
+ }
+ LeaveCriticalSection(&cookieMutex);
+
+ NetLog_Server("Request to get %d avatar image added to queue.", dwUin);
+
+ if (!AvatarsReady && !pendingAvatarsStart)
+ {
+ icq_requestnewfamily(0x10, StartAvatarThread);
+ pendingAvatarsStart = 1;
+ }
+
+ return -1; // we added to queue
+}
+
+
+
+// upload avatar data to server
+int SetAvatarData(HANDLE hContact, WORD wRef, char* data, unsigned int datalen)
+{
+ avatarthreadstartinfo* atsi;
+
+ atsi = currentAvatarThread; // we take avatar thread - horrible, but realiable
+ if (AvatarsReady && !atsi->paused) // check if we are ready
+ {
+ icq_packet packet;
+ DWORD dwCookie;
+ avatarcookie* ack;
+
+ ack = (avatarcookie*)SAFE_MALLOC(sizeof(avatarcookie));
+ if (!ack) return 0; // out of memory, go away
+ ack->hContact = hContact;
+ ack->cbData = datalen;
+
+ dwCookie = AllocateCookie(CKT_AVATAR, ICQ_AVATAR_UPLOAD_REQUEST, 0, ack);
+
+ serverPacketInit(&packet, (WORD)(14 + datalen));
+ packFNACHeaderFull(&packet, ICQ_AVATAR_FAMILY, ICQ_AVATAR_UPLOAD_REQUEST, 0, dwCookie);
+ packWord(&packet, wRef); // unknown, probably reference
+ packWord(&packet, (WORD)datalen);
+ packBuffer(&packet, data, (unsigned short)datalen);
+
+ if (sendAvatarPacket(&packet, atsi))
+ {
+ NetLog_Server("Upload avatar packet sent.");
+
+ return dwCookie;
+ }
+ ReleaseCookie(dwCookie); // failed to send, free resources
+ }
+ // we failed to send request, or avatar thread not ready
+ EnterCriticalSection(&cookieMutex); // wait for ready queue, reused cs
+ { // check if any request for this user is not already in the queue
+ avatarrequest* ar;
+ int bYet = 0;
+ ar = pendingRequests;
+ while (ar)
+ {
+ if (ar->hContact == hContact)
+ { // we found it, return error
+ LeaveCriticalSection(&cookieMutex);
+ NetLog_Server("Ignoring duplicate upload avatar request.");
+
+ if (!AvatarsReady && !pendingAvatarsStart)
+ {
+ icq_requestnewfamily(0x10, StartAvatarThread);
+ pendingAvatarsStart = 1;
+ }
+ return 0;
+ }
+ ar = ar->pNext;
+ }
+ // add request to queue, processed after successful login
+ ar = CreateAvatarRequest(2); // upload avatar
+ if (!ar)
+ { // out of memory, go away
+ LeaveCriticalSection(&cookieMutex);
+ return 0;
+ }
+ ar->hContact = hContact;
+ ar->pData = (char*)SAFE_MALLOC(datalen);
+ if (!ar->pData)
+ { // alloc failed
+ LeaveCriticalSection(&cookieMutex);
+ SAFE_FREE(&ar);
+ return 0;
+ }
+ memcpy(ar->pData, data, datalen); // copy the data
+ ar->cbData = datalen;
+ ar->wRef = wRef;
+ ar->pNext = pendingRequests;
+ pendingRequests = ar;
+ }
+ LeaveCriticalSection(&cookieMutex);
+
+ NetLog_Server("Request to upload avatar image added to queue.");
+
+ if (!AvatarsReady && !pendingAvatarsStart)
+ {
+ pendingAvatarsStart = 1;
+ icq_requestnewfamily(0x10, StartAvatarThread);
+ }
+
+ return -1; // we added to queue
+}
+
+
+
+static DWORD __stdcall icq_avatarThread(avatarthreadstartinfo *atsi)
+{
+ // This is the "infinite" loop that receives the packets from the ICQ avatar server
+ {
+ int recvResult;
+ NETLIBPACKETRECVER packetRecv = {0};
+ DWORD wLastKeepAlive = 0; // we send keep-alive at most one per 30secs
+
+ InitializeCriticalSection(&atsi->localSeqMutex);
+
+ atsi->hAvatarPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)atsi->hConnection, 8192);
+ packetRecv.cbSize = sizeof(packetRecv);
+ packetRecv.dwTimeout = 60000; // timeout every minute - for stopThread to work
+ while(!atsi->stopThread)
+ {
+ recvResult = CallService(MS_NETLIB_GETMOREPACKETS,(WPARAM)atsi->hAvatarPacketRecver, (LPARAM)&packetRecv);
+
+ if (recvResult == 0)
+ {
+ NetLog_Server("Clean closure of avatar socket");
+ break;
+ }
+
+ if (recvResult == SOCKET_ERROR)
+ {
+ if (GetLastError() == ERROR_TIMEOUT)
+ { // timeout, check if we should be still running
+ if (Miranda_Terminated())
+ atsi->stopThread = 1; // we must stop here, cause due to a hack in netlib, we always get timeout, even if the connection is already dead
+#ifdef _DEBUG
+ else
+ NetLog_Server("Avatar Thread is Idle.");
+#endif
+ if (GetTickCount() > wLastKeepAlive)
+ { // limit frequency (HACK: on some systems select() does not work well)
+ if (ICQGetContactSettingByte(NULL, "KeepAlive", 0))
+ { // send keep-alive packet
+ icq_packet packet;
+
+ packet.wLen = 0;
+ write_flap(&packet, ICQ_PING_CHAN);
+ sendAvatarPacket(&packet, atsi);
+ }
+ wLastKeepAlive = GetTickCount() + 57000;
+ }
+ else
+ { // this is bad, the system does not handle select() properly
+#ifdef _DEBUG
+ NetLog_Server("Avatar Thread is Forcing Idle.");
+#endif
+ SleepEx(500, TRUE); // wait some time, can we do anything else ??
+ }
+ continue;
+ }
+ NetLog_Server("Abortive closure of avatar socket");
+ break;
+ }
+
+ // Deal with the packet
+ packetRecv.bytesUsed = handleAvatarPackets(packetRecv.buffer, packetRecv.bytesAvailable, atsi);
+
+ if ((AvatarsReady == TRUE) && (packetRecv.bytesAvailable == packetRecv.bytesUsed) && !atsi->paused) // no packets pending
+ { // process request queue
+ EnterCriticalSection(&cookieMutex);
+
+ while (pendingRequests && atsi->runCount < 3) // pick up an request and send it - happens immediatelly after login
+ { // do not fill queue to top, leave one place free
+ avatarrequest* reqdata = pendingRequests;
+ pendingRequests = reqdata->pNext;
+
+#ifdef _DEBUG
+ NetLog_Server("Picked up the %d request from queue.", reqdata->dwUin);
+#endif
+ switch (reqdata->type)
+ {
+ case 1: // get avatar
+ GetAvatarData(reqdata->hContact, reqdata->dwUin, reqdata->szUid, reqdata->hash, reqdata->hashlen, reqdata->szFile);
+
+ SAFE_FREE(&reqdata->szUid);
+ SAFE_FREE(&reqdata->szFile);
+ SAFE_FREE(&reqdata->hash); // as soon as it will be copied
+ break;
+ case 2: // set avatar
+ SetAvatarData(reqdata->hContact, reqdata->wRef, reqdata->pData, reqdata->cbData);
+
+ SAFE_FREE(&reqdata->pData);
+ break;
+ }
+ SAFE_FREE(&reqdata);
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+ }
+ }
+ Netlib_CloseHandle(atsi->hAvatarPacketRecver); // Close the packet receiver
+ }
+ Netlib_CloseHandle(atsi->hConnection); // Close the connection
+
+ DeleteCriticalSection(&atsi->localSeqMutex);
+
+ SAFE_FREE(&atsi->pCookie);
+ if (currentAvatarThread == atsi) // if we stoped by error or unexpectedly, clear global variable
+ {
+ AvatarsReady = FALSE; // we are not ready
+ pendingAvatarsStart = 0;
+ currentAvatarThread = NULL; // this is horrible, rewrite
+ }
+ SAFE_FREE(&atsi);
+
+ NetLog_Server("%s thread ended.", "Avatar");
+
+ return 0;
+}
+
+
+
+int handleAvatarPackets(unsigned char* buf, int buflen, avatarthreadstartinfo* atsi)
+{
+ BYTE channel;
+ WORD sequence;
+ WORD datalen;
+ int bytesUsed = 0;
+
+ while (buflen > 0)
+ {
+ // All FLAPS begin with 0x2a
+ if (*buf++ != FLAP_MARKER)
+ break;
+
+ if (buflen < 6)
+ break;
+
+ unpackByte(&buf, &channel);
+ unpackWord(&buf, &sequence);
+ unpackWord(&buf, &datalen);
+
+ if (buflen < 6 + datalen)
+ break;
+
+#ifdef _DEBUG
+ NetLog_Server("Avatar FLAP: Channel %u, Seq %u, Length %u bytes", channel, sequence, datalen);
+#endif
+
+ switch (channel)
+ {
+ case ICQ_LOGIN_CHAN:
+ handleAvatarLogin(buf, datalen, atsi);
+ break;
+
+ case ICQ_DATA_CHAN:
+ handleAvatarData(buf, datalen, atsi);
+ break;
+
+ default:
+ NetLog_Server("Warning: Unhandled %s FLAP Channel: Channel %u, Seq %u, Length %u bytes", "Avatar", channel, sequence, datalen);
+ break;
+ }
+
+ /* Increase pointers so we can check for more FLAPs */
+ buf += datalen;
+ buflen -= (datalen + 6);
+ bytesUsed += (datalen + 6);
+ }
+
+ return bytesUsed;
+}
+
+
+
+static int sendAvatarPacket(icq_packet* pPacket, avatarthreadstartinfo* atsi)
+{
+ int lResult = 0;
+
+ // This critsec makes sure that the sequence order doesn't get screwed up
+ EnterCriticalSection(&atsi->localSeqMutex);
+
+ if (atsi->hConnection)
+ {
+ int nRetries;
+ int nSendResult;
+
+ // :IMPORTANT:
+ // The FLAP sequence must be a WORD. When it reaches 0xFFFF it should wrap to
+ // 0x0000, otherwise we'll get kicked by server.
+ atsi->wLocalSequence++;
+
+ // Pack sequence number
+ pPacket->pData[2] = ((atsi->wLocalSequence & 0xff00) >> 8);
+ pPacket->pData[3] = (atsi->wLocalSequence & 0x00ff);
+
+ for (nRetries = 3; nRetries >= 0; nRetries--)
+ {
+ nSendResult = Netlib_Send(atsi->hConnection, (const char *)pPacket->pData, pPacket->wLen, 0);
+
+ if (nSendResult != SOCKET_ERROR)
+ break;
+
+ Sleep(1000);
+ }
+
+ // Send error
+ if (nSendResult == SOCKET_ERROR)
+ { // thread stops automatically
+ NetLog_Server("Your connection with the ICQ avatar server was abortively closed");
+ }
+ else
+ {
+ lResult = 1; // packet sent successfully
+ }
+ }
+ else
+ {
+ NetLog_Server("Error: Failed to send packet (no connection)");
+ }
+
+ LeaveCriticalSection(&atsi->localSeqMutex);
+
+ SAFE_FREE(&pPacket->pData);
+
+ return lResult;
+}
+
+
+
+void handleAvatarLogin(unsigned char *buf, WORD datalen, avatarthreadstartinfo *atsi)
+{
+ icq_packet packet;
+
+ if (*(DWORD*)buf == 0x1000000)
+ { // here check if we received SRV_HELLO
+ atsi->wLocalSequence = (WORD)RandRange(0, 0xffff);
+
+ serverCookieInit(&packet, atsi->pCookie, atsi->wCookieLen);
+ sendAvatarPacket(&packet, atsi);
+
+#ifdef _DEBUG
+ NetLog_Server("Sent CLI_IDENT to %s server", "avatar");
+#endif
+
+ SAFE_FREE(&atsi->pCookie);
+ atsi->wCookieLen = 0;
+ }
+ else
+ {
+ NetLog_Server("Invalid Avatar Server response, Ch1.");
+ }
+}
+
+
+
+void handleAvatarData(unsigned char *pBuffer, WORD wBufferLength, avatarthreadstartinfo *atsi)
+{
+ snac_header snacHeader = {0};
+
+ if (!unpackSnacHeader(&snacHeader, &pBuffer, &wBufferLength) || !snacHeader.bValid)
+ {
+ NetLog_Server("Error: Failed to parse SNAC header");
+ }
+ else
+ {
+#ifdef _DEBUG
+ NetLog_Server(" Received SNAC(x%02X,x%02X)", snacHeader.wFamily, snacHeader.wSubtype);
+#endif
+
+ switch (snacHeader.wFamily)
+ {
+
+ case ICQ_SERVICE_FAMILY:
+ handleAvatarServiceFam(pBuffer, wBufferLength, &snacHeader, atsi);
+ break;
+
+ case ICQ_AVATAR_FAMILY:
+ handleAvatarFam(pBuffer, wBufferLength, &snacHeader, atsi);
+ break;
+
+ default:
+ NetLog_Server("Ignoring SNAC(x%02X,x%02X) - FAMILYx%02X not implemented", snacHeader.wFamily, snacHeader.wSubtype, snacHeader.wFamily);
+ break;
+ }
+ }
+}
+
+
+
+void handleAvatarServiceFam(unsigned char* pBuffer, WORD wBufferLength, snac_header* pSnacHeader, avatarthreadstartinfo *atsi)
+{
+ icq_packet packet;
+
+ switch (pSnacHeader->wSubtype)
+ {
+
+ case ICQ_SERVER_READY:
+#ifdef _DEBUG
+ NetLog_Server("Avatar server is ready and is requesting my Family versions");
+ NetLog_Server("Sending my Families");
+#endif
+
+ // Miranda mimics the behaviour of Icq5
+ serverPacketInit(&packet, 18);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_FAMILIES);
+ packDWord(&packet, 0x00010004);
+ packDWord(&packet, 0x00100001);
+ sendAvatarPacket(&packet, atsi);
+ break;
+
+ case ICQ_SERVER_FAMILIES2:
+ /* This is a reply to CLI_FAMILIES and it tells the client which families and their versions that this server understands.
+ * We send a rate request packet */
+#ifdef _DEBUG
+ NetLog_Server("Server told me his Family versions");
+ NetLog_Server("Requesting Rate Information");
+#endif
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_REQ_RATE_INFO);
+ sendAvatarPacket(&packet, atsi);
+ break;
+
+ case ICQ_SERVER_RATE_INFO:
+#ifdef _DEBUG
+ NetLog_Server("Server sent Rate Info");
+ NetLog_Server("Sending Rate Info Ack");
+#endif
+ /* Don't really care about this now, just send the ack */
+ serverPacketInit(&packet, 20); // TODO: add rate management to request queue (0.5+)
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_RATE_ACK);
+ packDWord(&packet, 0x00010002);
+ packDWord(&packet, 0x00030004);
+ packWord(&packet, 0x0005);
+ sendAvatarPacket(&packet, atsi);
+
+ // send cli_ready
+ serverPacketInit(&packet, 26);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_READY);
+ packDWord(&packet, 0x00010004);
+ packDWord(&packet, 0x001008E4);
+ packDWord(&packet, 0x00100001);
+ packDWord(&packet, 0x001008E4);
+ sendAvatarPacket(&packet, atsi);
+
+ AvatarsReady = TRUE; // we are ready to process requests
+ pendingAvatarsStart = 0;
+ atsi->pendingLogin = 0;
+
+ NetLog_Server(" *** Yeehah, avatar login sequence complete");
+ break;
+
+/* case ICQ_SERVER_PAUSE:
+ NetLog_Server("Avatar server is going down in a few seconds... (Flags: %u, Ref: %u)", pSnacHeader->wFlags, pSnacHeader->dwRef);
+ // This is the list of groups that we want to have on the next server
+ serverPacketInit(&packet, 14);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_PAUSE_ACK);
+ packWord(&packet,ICQ_SERVICE_FAMILY);
+ packWord(&packet,ICQ_AVATAR_FAMILY);
+ sendAvatarPacket(&packet, atsi);
+#ifdef _DEBUG
+ NetLog_Server("Sent server pause ack");
+#endif
+ break; // TODO: avatar migration is not working, should be ?*/
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_SERVICE_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+ }
+}
+
+
+
+void handleAvatarFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader, avatarthreadstartinfo *atsi)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+ case ICQ_AVATAR_GET_REPLY: // received avatar data, store to file
+ { // handle new avatar, notify
+ avatarcookie* ac;
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, &ac))
+ {
+ BYTE len;
+ WORD datalen;
+ int out;
+ char* szMyFile = (char*)_alloca(strlennull(ac->szFile)+10);
+ PROTO_AVATAR_INFORMATION ai;
+ int i;
+
+ EnterCriticalSection(&cookieMutex);
+ for(i = 0; i < atsi->runCount; i++)
+ { // look for our record
+ if (atsi->runContact[i] == ac->hContact)
+ { // found remove
+ atsi->runContact[i] = atsi->runContact[atsi->runCount - 1];
+ atsi->runTime[i] = atsi->runTime[atsi->runCount - 1];
+ atsi->runCount--;
+ break;
+ }
+ }
+ LeaveCriticalSection(&cookieMutex);
+
+ strcpy(szMyFile, ac->szFile);
+
+ ai.cbSize = sizeof ai;
+ ai.format = PA_FORMAT_JPEG; // this is for error only
+ ai.hContact = ac->hContact;
+ strcpy(ai.filename, ac->szFile);
+ AddAvatarExt(PA_FORMAT_JPEG, ai.filename);
+
+ FreeCookie(pSnacHeader->dwRef);
+ unpackByte(&pBuffer, &len);
+ if (wBufferLength < ((ac->hashlen)<<1)+4+len)
+ {
+ NetLog_Server("Received invalid avatar reply.");
+
+ ICQBroadcastAck(ac->hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, (HANDLE)&ai, 0);
+
+ SAFE_FREE(&ac->szFile);
+ SAFE_FREE(&ac->hash);
+ SAFE_FREE(&ac);
+
+ break;
+ }
+
+ pBuffer += len;
+ pBuffer += (ac->hashlen<<1) + 1;
+ unpackWord(&pBuffer, &datalen);
+
+ wBufferLength -= 4 + len + (ac->hashlen<<1);
+ if (datalen > wBufferLength)
+ {
+ datalen = wBufferLength;
+ NetLog_Server("Avatar reply broken, trying to do my best.");
+ }
+
+ if (datalen > 4)
+ { // store to file...
+ int dwPaFormat;
+
+ NetLog_Server("Received user avatar, storing (%d bytes).", datalen);
+
+ dwPaFormat = DetectAvatarFormatBuffer(pBuffer);
+ ICQWriteContactSettingByte(ac->hContact, "AvatarType", (BYTE)dwPaFormat);
+ ai.format = dwPaFormat; // set the format
+ AddAvatarExt(dwPaFormat, szMyFile);
+ strcpy(ai.filename, szMyFile);
+
+ out = _open(szMyFile, _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY, _S_IREAD | _S_IWRITE);
+ if (out)
+ {
+ DBVARIANT dbv;
+
+ _write(out, pBuffer, datalen);
+ _close(out);
+
+ if (dwPaFormat != PA_FORMAT_XML && dwPaFormat != PA_FORMAT_UNKNOWN)
+ LinkContactPhotoToFile(ac->hContact, szMyFile); // this should not be here, but no other simple solution available
+
+ if (!ac->hContact) // our avatar, set filename
+ storeMyAvatarFileName(szMyFile);
+ else
+ { // contact's avatar set hash
+ if (!ICQGetContactSetting(ac->hContact, "AvatarHash", &dbv))
+ {
+ if (ICQWriteContactSettingBlob(ac->hContact, "AvatarSaved", dbv.pbVal, dbv.cpbVal))
+ NetLog_Server("Failed to set file hash.");
+
+ ICQFreeVariant(&dbv);
+ }
+ else
+ {
+ NetLog_Server("Warning: DB error (no hash in DB).");
+ // the hash was lost, try to fix that
+ if (ICQWriteContactSettingBlob(ac->hContact, "AvatarSaved", ac->hash, ac->hashlen) ||
+ ICQWriteContactSettingBlob(ac->hContact, "AvatarHash", ac->hash, ac->hashlen))
+ {
+ NetLog_Server("Failed to save avatar hash to DB");
+ }
+ }
+ }
+
+ ICQBroadcastAck(ac->hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&ai, 0);
+ }
+ }
+ else
+ { // the avatar is empty
+ NetLog_Server("Received empty avatar, nothing written.", datalen);
+
+ ICQBroadcastAck(ac->hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, (HANDLE)&ai, 0);
+ }
+ SAFE_FREE(&ac->szFile);
+ SAFE_FREE(&ac->hash);
+ SAFE_FREE(&ac);
+ }
+ else
+ {
+ NetLog_Server("Warning: Received unexpected Avatar Reply SNAC(x10,x07).");
+ }
+
+ break;
+ }
+ case ICQ_AVATAR_UPLOAD_ACK:
+ {
+ // upload completed, notify
+ BYTE res;
+ unpackByte(&pBuffer, &res);
+ if (!res && (wBufferLength == 0x15))
+ {
+ avatarcookie* ac;
+ if (FindCookie(pSnacHeader->dwRef, NULL, &ac))
+ {
+ // here we store the local hash
+ ReleaseCookie(pSnacHeader->dwRef);
+ }
+ else
+ {
+ NetLog_Server("Warning: Received unexpected Upload Avatar Reply SNAC(x10,x03).");
+ }
+ }
+ else if (res)
+ {
+ NetLog_Server("Error uploading avatar to server, #%d", res);
+ icq_LogMessage(LOG_WARNING, "Error uploading avatar to server, server refused to accept the image.");
+ }
+ else
+ NetLog_Server("Received invalid upload avatar ack.");
+
+ break;
+ }
+ case ICQ_ERROR:
+ {
+ WORD wError;
+ avatarcookie *ack;
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, &ack))
+ {
+ if (ack->dwUin)
+ {
+ NetLog_Server("Error: Avatar request failed");
+ SAFE_FREE(&ack->szFile);
+ SAFE_FREE(&ack->hash);
+ }
+ else
+ {
+ NetLog_Server("Error: Avatar upload failed");
+ }
+ ReleaseCookie(pSnacHeader->dwRef);
+ }
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ LogFamilyError(ICQ_AVATAR_FAMILY, wError);
+ break;
+ }
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_AVATAR_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+
+ }
+}
diff --git a/icqj_mod/icq_avatar.h b/icqj_mod/icq_avatar.h new file mode 100644 index 0000000..bb8bebd --- /dev/null +++ b/icqj_mod/icq_avatar.h @@ -0,0 +1,62 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_avatar.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_AVATAR_H
+#define __ICQ_AVATAR_H
+
+extern BOOL AvatarsReady;
+
+void handleAvatarContactHash(DWORD dwUIN, char* szUID, HANDLE hContact, unsigned char* pHash, unsigned int nHashLen, WORD wOldStatus);
+
+char* loadMyAvatarFileName();
+void storeMyAvatarFileName(char* szFile);
+
+void GetFullAvatarFileName(int dwUin, char* szUid, int dwFormat, char* pszDest, int cbLen);
+void GetAvatarFileName(int dwUin, char* szUid, char* pszDest, int cbLen);
+void AddAvatarExt(int dwFormat, char* pszDest);
+
+int DetectAvatarFormat(char* szFile);
+
+int IsAvatarSaved(HANDLE hContact, char* pHash);
+
+int GetAvatarData(HANDLE hContact, DWORD dwUin, char* szUid, char* hash, unsigned int hashlen, char* file);
+int SetAvatarData(HANDLE hContact, WORD wRef, char* data, unsigned int datalen);
+
+void StartAvatarThread(HANDLE hConn, char* cookie, WORD cookieLen);
+void StopAvatarThread();
+
+
+#endif /* __ICQ_AVATAR_H */
diff --git a/icqj_mod/icq_clients.c b/icqj_mod/icq_clients.c new file mode 100644 index 0000000..af976ee --- /dev/null +++ b/icqj_mod/icq_clients.c @@ -0,0 +1,687 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_clients.c,v $
+// Revision : $Revision: 3259 $
+// Last change on : $Date: 2006-06-30 18:17:33 +0200 (pá, 30 VI 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Provides capability & signature based client detection
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+capstr* MatchCap(char* buf, int bufsize, const capstr* cap, int capsize)
+{
+ while (bufsize>0) // search the buffer for a capability
+ {
+ if (!memcmp(buf, cap, capsize))
+ {
+ return (capstr*)buf; // give found capability for version info
+ }
+ else
+ {
+ buf += 0x10;
+ bufsize -= 0x10;
+ }
+ }
+ return 0;
+}
+
+
+
+static void makeClientVersion(char *szBuf, const char* szClient, unsigned v1, unsigned v2, unsigned v3, unsigned v4)
+{
+ if (v4)
+ null_snprintf(szBuf, 64, "%s%u.%u.%u.%u", szClient, v1, v2, v3, v4);
+ else if (v3)
+ null_snprintf(szBuf, 64, "%s%u.%u.%u", szClient, v1, v2, v3);
+ else
+ null_snprintf(szBuf, 64, "%s%u.%u", szClient, v1, v2);
+}
+
+
+
+static void verToStr(char* szStr, int v)
+{
+ char szVer[64];
+
+ if (v&0x1000000) {
+ strcat(szStr, "BM ");
+ v &= ~0x1000000;
+ }
+ if (v&0x2000000) {
+ strcat(szStr, "S7 ");
+ v &= ~0x2000000;
+ }
+ makeClientVersion(szVer, "v", (v>>24)&0x7F, (v>>16)&0xFF, (v>>8)&0xFF, v&0xFF);
+ strcat(szStr, szVer);
+ if (v&0x80000000) strcat(szStr, " alpha");
+}
+
+
+static char* MirandaVersionToStringEx(char* szStr, char* szPlug, int v, int m)
+{
+ if (!v) // this is not Miranda
+ return NULL;
+ else
+ {
+ strcpy(szStr, "Miranda IM ");
+
+ if (!m && v == 1)
+ verToStr(szStr, 0x80010200);
+ else if (!m && (v&0x7FFFFFFF) <= 0x030301)
+ verToStr(szStr, v);
+ else
+ {
+ if (m)
+ {
+ verToStr(szStr, m);
+ strcat(szStr, " ");
+ }
+ strcat(szStr, "(");
+ strcat(szStr, szPlug);
+ strcat(szStr, " ");
+ verToStr(szStr, v);
+ strcat(szStr, ")");
+ }
+ }
+
+ return szStr;
+}
+
+
+
+char* MirandaVersionToString(char* szStr, int v, int m)
+{
+ return MirandaVersionToStringEx(szStr, "ICQ", v, m);
+}
+
+
+const capstr capMirandaIm = {'M', 'i', 'r', 'a', 'n', 'd', 'a', 'M', 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capAimOscar = {'M', 'i', 'r', 'a', 'n', 'd', 'a', 'A', 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capTrillian = {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x09};
+const capstr capTrilCrypt = {0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb, 0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00};
+const capstr capSim = {'S', 'I', 'M', ' ', 'c', 'l', 'i', 'e', 'n', 't', ' ', ' ', 0, 0, 0, 0};
+const capstr capSimOld = {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x00};
+const capstr capLicq = {'L', 'i', 'c', 'q', ' ', 'c', 'l', 'i', 'e', 'n', 't', ' ', 0, 0, 0, 0};
+const capstr capKopete = {'K', 'o', 'p', 'e', 't', 'e', ' ', 'I', 'C', 'Q', ' ', ' ', 0, 0, 0, 0};
+const capstr capmIcq = {'m', 'I', 'C', 'Q', ' ', 0xA9, ' ', 'R', '.', 'K', '.', ' ', 0, 0, 0, 0};
+const capstr capAndRQ = {'&', 'R', 'Q', 'i', 'n', 's', 'i', 'd', 'e', 0, 0, 0, 0, 0, 0, 0};
+const capstr capRAndQ = {'R', '&', 'Q', 'i', 'n', 's', 'i', 'd', 'e', 0, 0, 0, 0, 0, 0, 0};
+const capstr capmChat = {'m', 'C', 'h', 'a', 't', ' ', 'i', 'c', 'q', ' ', 0, 0, 0, 0, 0, 0};
+const capstr capJimm = {'J', 'i', 'm', 'm', ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capQip = {0x56, 0x3F, 0xC8, 0x09, 0x0B, 0x6F, 0x41, 'Q', 'I', 'P', ' ', '2', '0', '0', '5', 'a'};
+const capstr capIm2 = {0x74, 0xED, 0xC3, 0x36, 0x44, 0xDF, 0x48, 0x5B, 0x8B, 0x1C, 0x67, 0x1A, 0x1F, 0x86, 0x09, 0x9F}; // IM2 Ext Msg
+const capstr capMacIcq = {0xdd, 0x16, 0xf2, 0x02, 0x84, 0xe6, 0x11, 0xd4, 0x90, 0xdb, 0x00, 0x10, 0x4b, 0x9b, 0x4b, 0x7d};
+const capstr capRichText = {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92};
+const capstr capIs2001 = {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8, 0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf};
+const capstr capIs2002 = {0x10, 0xcf, 0x40, 0xd1, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capComm20012 = {0xa0, 0xe9, 0x3f, 0x37, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capStrIcq = {0xa0, 0xe9, 0x3f, 0x37, 0x4f, 0xe9, 0xd3, 0x11, 0xbc, 0xd2, 0x00, 0x04, 0xac, 0x96, 0xdd, 0x96};
+const capstr capAimIcon = {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}; // CAP_AIM_BUDDYICON
+const capstr capAimDirect = {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}; // CAP_AIM_DIRECTIM
+const capstr capIsIcq = {0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capIcqLite = {0x17, 0x8C, 0x2D, 0x9B, 0xDA, 0xA5, 0x45, 0xBB, 0x8D, 0xDB, 0xF3, 0xBD, 0xBD, 0x53, 0xA1, 0x0A};
+const capstr capAimChat = {0x74, 0x8F, 0x24, 0x20, 0x62, 0x87, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capUim = {0xA7, 0xE4, 0x0A, 0x96, 0xB3, 0xA0, 0x47, 0x9A, 0xB8, 0x45, 0xC9, 0xE4, 0x67, 0xC5, 0x6B, 0x1F};
+const capstr capRambler = {0x7E, 0x11, 0xB7, 0x78, 0xA3, 0x53, 0x49, 0x26, 0xA8, 0x02, 0x44, 0x73, 0x52, 0x08, 0xC4, 0x2A};
+const capstr capAbv = {0x00, 0xE7, 0xE0, 0xDF, 0xA9, 0xD0, 0x4F, 0xe1, 0x91, 0x62, 0xC8, 0x90, 0x9A, 0x13, 0x2A, 0x1B};
+const capstr capNetvigator= {0x4C, 0x6B, 0x90, 0xA3, 0x3D, 0x2D, 0x48, 0x0E, 0x89, 0xD6, 0x2E, 0x4B, 0x2C, 0x10, 0xD9, 0x9F};
+const capstr captZers = {0xb2, 0xec, 0x8f, 0x16, 0x7c, 0x6f, 0x45, 0x1b, 0xbd, 0x79, 0xdc, 0x58, 0x49, 0x78, 0x88, 0xb9}; // CAP_TZERS
+const capstr capSimpLite = {0x53, 0x49, 0x4D, 0x50, 0x53, 0x49, 0x4D, 0x50, 0x53, 0x49, 0x4D, 0x50, 0x53, 0x49, 0x4D, 0x50};
+const capstr capSimpPro = {0x53, 0x49, 0x4D, 0x50, 0x5F, 0x50, 0x52, 0x4F, 0x53, 0x49, 0x4D, 0x50, 0x5F, 0x50, 0x52, 0x4F};
+
+
+static BOOL hasRichText, hasRichChecked;
+
+static BOOL hasCapRichText(BYTE* caps, WORD wLen)
+{
+ if (!hasRichChecked)
+ {
+ hasRichText = MatchCap(caps, wLen, &capRichText, 0x10)?TRUE:FALSE;
+ hasRichChecked = TRUE;
+ }
+ return hasRichText;
+}
+
+
+char* cliLibicq2k = "libicq2000";
+char* cliLicqVer = "Licq ";
+char* cliCentericq = "Centericq";
+char* cliLibicqUTF = "libicq2000 (Unicode)";
+char* cliTrillian = "Trillian";
+char* cliQip = "QIP 200%c%c";
+char* cliIM2 = "IM2";
+char* cliSpamBot = "Spam Bot";
+
+
+char* detectUserClient(HANDLE hContact, DWORD dwUin, WORD wVersion, DWORD dwFT1, DWORD dwFT2, DWORD dwFT3, DWORD dwOnlineSince, DWORD dwDirectCookie, DWORD dwWebPort, BYTE* caps, WORD wLen, BYTE* bClientId, char* szClientBuf)
+{
+ LPSTR szClient = NULL;
+
+ *bClientId = 1; // Most clients does not tick as MsgIDs
+ hasRichChecked = FALSE; // init fast rich text detection
+
+ // Is this a Miranda IM client?
+ if (dwFT1 == 0xffffffff)
+ {
+ if (dwFT2 == 0xffffffff)
+ { // This is Gaim not Miranda
+ szClient = "Gaim";
+ }
+ else if (!dwFT2 && wVersion == 7)
+ { // This is WebICQ not Miranda
+ szClient = "WebICQ";
+ }
+ else if (!dwFT2 && dwFT3 == 0x3B7248ED)
+ { // And this is most probably Spam Bot
+ szClient = cliSpamBot;
+ }
+ else
+ { // Yes this is most probably Miranda, get the version info
+ szClient = MirandaVersionToString(szClientBuf, dwFT2, 0);
+ *bClientId = 2;
+ }
+ }
+ else if ((dwFT1 & 0xFF7F0000) == 0x7D000000)
+ { // This is probably an Licq client
+ DWORD ver = dwFT1 & 0xFFFF;
+
+ makeClientVersion(szClientBuf, cliLicqVer, ver / 1000, (ver / 10) % 100, ver % 10, 0);
+ if (dwFT1 & 0x00800000)
+ strcat(szClientBuf, "/SSL");
+
+ szClient = szClientBuf;
+ }
+ else if (dwFT1 == 0xffffff8f)
+ {
+ szClient = "StrICQ";
+ }
+ else if (dwFT1 == 0xffffff42)
+ {
+ szClient = "mICQ";
+ }
+ else if (dwFT1 == 0xffffffbe)
+ {
+ unsigned ver1 = (dwFT2>>24)&0xFF;
+ unsigned ver2 = (dwFT2>>16)&0xFF;
+ unsigned ver3 = (dwFT2>>8)&0xFF;
+
+ makeClientVersion(szClientBuf, "Alicq ", ver1, ver2, ver3, 0);
+
+ szClient = szClientBuf;
+ }
+ else if (dwFT1 == 0xFFFFFF7F)
+ {
+ szClient = "&RQ";
+ }
+ else if (dwFT1 == 0xFFFFFFAB)
+ {
+ szClient = "YSM";
+ }
+ else if (dwFT1 == 0x04031980)
+ {
+ szClient = "vICQ";
+ }
+ else if ((dwFT1 == 0x3AA773EE) && (dwFT2 == 0x3AA66380))
+ {
+ szClient = cliLibicq2k;
+ }
+ else if (dwFT1 == 0x3B75AC09)
+ {
+ szClient = cliTrillian;
+ }
+ else if (dwFT1 == 0x3BA8DBAF) // FT2: 0x3BEB5373; FT3: 0x3BEB5262;
+ {
+ if (wVersion == 2)
+ szClient = "stICQ";
+ }
+ else if (dwFT1 == 0xFFFFFFFE && dwFT3 == 0xFFFFFFFE)
+ {
+ szClient = "Jimm";
+ }
+ else if (dwFT1 == 0x3FF19BEB && dwFT3 == 0x3FF19BEB)
+ {
+ szClient = cliIM2;
+ }
+ else if (dwFT1 == 0xDDDDEEFF && !dwFT2 && !dwFT3)
+ {
+ szClient = "SmartICQ";
+ }
+ else if ((dwFT1 & 0xFFFFFFF0) == 0x494D2B00 && !dwFT2 && !dwFT3)
+ { // last byte of FT1: (5 = Win32, 3 = SmartPhone, Pocket PC)
+ szClient = "IM+";
+ }
+ else if (dwFT1 == 0x3B4C4C0C && !dwFT2 && dwFT3 == 0x3B7248ed)
+ {
+ szClient = "KXicq2";
+ }
+ else if (dwFT1 == 0xFFFFF666 && !dwFT3)
+ { // this is R&Q (Rapid Edition)
+ null_snprintf(szClientBuf, 64, "R&Q %u", (unsigned)dwFT2);
+ szClient = szClientBuf;
+ }
+ else if (dwFT1 == dwFT2 && dwFT2 == dwFT3 && wVersion == 8)
+ {
+ if ((dwFT1 < dwOnlineSince + 3600) && (dwFT1 > (dwOnlineSince - 3600)))
+ {
+ szClient = cliSpamBot;
+ }
+ }
+ else if (!dwFT1 && !dwFT2 && !dwFT3 && !wVersion && !wLen && dwWebPort == 0x75BB)
+ {
+ szClient = cliSpamBot;
+ }
+
+ { // capabilities based detection
+ capstr* capId;
+
+ if (dwUin && caps)
+ {
+ // check capabilities for client identification
+ if (capId = MatchCap(caps, wLen, &capMirandaIm, 8))
+ { // new Miranda Signature
+ DWORD iver = (*capId)[0xC] << 0x18 | (*capId)[0xD] << 0x10 | (*capId)[0xE] << 8 | (*capId)[0xF];
+ DWORD mver = (*capId)[0x8] << 0x18 | (*capId)[0x9] << 0x10 | (*capId)[0xA] << 8 | (*capId)[0xB];
+
+ szClient = MirandaVersionToString(szClientBuf, iver, mver);
+
+ *bClientId = 2;
+ }
+ else if (MatchCap(caps, wLen, &capTrillian, 0x10) || MatchCap(caps, wLen, &capTrilCrypt, 0x10))
+ { // this is Trillian, check for new version
+ if (hasCapRichText(caps, wLen))
+ szClient = "Trillian v3";
+ else
+ szClient = cliTrillian;
+ }
+ else if ((capId = MatchCap(caps, wLen, &capSimOld, 0xF)) && ((*capId)[0xF] != 0x92 && (*capId)[0xF] >= 0x20 || (*capId)[0xF] == 0))
+ {
+ int hiVer = (((*capId)[0xF]) >> 6) - 1;
+ unsigned loVer = (*capId)[0xF] & 0x1F;
+
+ if ((hiVer < 0) || ((hiVer == 0) && (loVer == 0)))
+ szClient = "Kopete";
+ else
+ {
+ null_snprintf(szClientBuf, 64, "SIM %u.%u", (unsigned)hiVer, loVer);
+ szClient = szClientBuf;
+ }
+ }
+ else if (capId = MatchCap(caps, wLen, &capSim, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+
+ makeClientVersion(szClientBuf, "SIM ", ver1, ver2, ver3, 0);
+ if ((*capId)[0xF] & 0x80)
+ strcat(szClientBuf,"/Win32");
+ else if ((*capId)[0xF] & 0x40)
+ strcat(szClientBuf,"/MacOS X");
+
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capLicq, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD] % 100;
+ unsigned ver3 = (*capId)[0xE];
+
+ makeClientVersion(szClientBuf, cliLicqVer, ver1, ver2, ver3, 0);
+ if ((*capId)[0xF])
+ strcat(szClientBuf,"/SSL");
+
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capKopete, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ makeClientVersion(szClientBuf, "Kopete ", ver1, ver2, ver3, ver4);
+
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capmIcq, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ makeClientVersion(szClientBuf, "mICQ ", ver1, ver2, ver3, ver4);
+
+ szClient = szClientBuf;
+ }
+ else if (MatchCap(caps, wLen, &capIm2, 0x10))
+ { // IM2 v2 provides also Aim Icon cap
+ szClient = cliIM2;
+ }
+ else if (capId = MatchCap(caps, wLen, &capAndRQ, 9))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xB];
+ unsigned ver3 = (*capId)[0xA];
+ unsigned ver4 = (*capId)[9];
+
+ makeClientVersion(szClientBuf, "&RQ ", ver1, ver2, ver3, ver4);
+
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capRAndQ, 9))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xB];
+ unsigned ver3 = (*capId)[0xA];
+ unsigned ver4 = (*capId)[9];
+
+ makeClientVersion(szClientBuf, "R&Q ", ver1, ver2, ver3, ver4);
+
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capQip, 0xE))
+ {
+ char v1 = (*capId)[0xE];
+ char v2 = (*capId)[0xF];
+
+ null_snprintf(szClientBuf, 64, cliQip, v1, v2);
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capmChat, 0xA))
+ {
+ strcpy(szClientBuf, "mChat ");
+ strncat(szClientBuf, (*capId) + 0xA, 6);
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capJimm, 5))
+ {
+ strcpy(szClientBuf, "Jimm ");
+ strncat(szClientBuf, (*capId) + 5, 11);
+ szClient = szClientBuf;
+ }
+ else if (MatchCap(caps, wLen, &capMacIcq, 0x10))
+ {
+ szClient = "ICQ for Mac";
+ }
+ else if (MatchCap(caps, wLen, &capUim, 0x10))
+ {
+ szClient = "uIM";
+ }
+ else if (szClient == cliLibicq2k)
+ { // try to determine which client is behind libicq2000
+ if (hasCapRichText(caps, wLen))
+ szClient = cliCentericq; // centericq added rtf capability to libicq2000
+ else if (CheckContactCapabilities(hContact, CAPF_UTF))
+ szClient = cliLibicqUTF; // IcyJuice added unicode capability to libicq2000
+ // others - like jabber transport uses unmodified library, thus cannot be detected
+ }
+ else if (szClient == NULL) // HERE ENDS THE SIGNATURE DETECTION, after this only feature default will be detected
+ {
+ if (wVersion == 8 && (MatchCap(caps, wLen, &capComm20012, 0x10) || CheckContactCapabilities(hContact, CAPF_SRV_RELAY)))
+ { // try to determine 2001-2003 versions
+ if (MatchCap(caps, wLen, &capIs2001, 0x10))
+ {
+ if (!dwFT1 && !dwFT2 && !dwFT3)
+ if (hasCapRichText(caps, wLen))
+ szClient = "TICQClient"; // possibly also older GnomeICU
+ else
+ szClient = "ICQ for Pocket PC";
+ else
+ {
+ *bClientId = 0;
+ szClient = "ICQ 2001";
+ }
+ }
+ else if (MatchCap(caps, wLen, &capIs2002, 0x10))
+ {
+ *bClientId = 0;
+ szClient = "ICQ 2002";
+ }
+ else if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY | CAPF_UTF) && hasCapRichText(caps, wLen))
+ {
+ if (!dwFT1 && !dwFT2 && !dwFT3)
+ {
+ if (!dwWebPort)
+ szClient = "GnomeICU 0.99.5+"; // no other way
+ else
+ szClient = "IC@";
+ }
+ else
+ {
+ *bClientId = 0;
+ szClient = "ICQ 2002/2003a";
+ }
+ }
+ else if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY | CAPF_UTF | CAPF_TYPING))
+ {
+ if (!dwFT1 && !dwFT2 && !dwFT3)
+ {
+ szClient = "PreludeICQ";
+ }
+ }
+ }
+ else if (wVersion == 9)
+ { // try to determine lite versions
+ if (CheckContactCapabilities(hContact, CAPF_XTRAZ))
+ {
+ *bClientId = 0;
+ if (CheckContactCapabilities(hContact, CAPF_AIM_FILE))
+ {
+ if (MatchCap(caps, wLen, &captZers, 0x10))
+ { // capable of tZers ?
+ strcpy(szClientBuf, "icq5.1");
+ }
+ else
+ {
+ strcpy(szClientBuf, "icq5");
+ }
+ if (MatchCap(caps, wLen, &capRambler, 0x10))
+ {
+ strcat(szClientBuf, " (Rambler)");
+ }
+ else if (MatchCap(caps, wLen, &capAbv, 0x10))
+ {
+ strcat(szClientBuf, " (Abv)");
+ }
+ else if (MatchCap(caps, wLen, &capNetvigator, 0x10))
+ {
+ strcat(szClientBuf, " (Netvigator)");
+ }
+ szClient = szClientBuf;
+ }
+ else if (!MatchCap(caps, wLen, &capIsIcq, 0x10))
+ szClient = "pyICQ";
+ else
+ szClient = "ICQ Lite v4";
+ }
+ }
+ else if (wVersion == 7)
+ {
+ if (hasCapRichText(caps, wLen))
+ szClient = "GnomeICU"; // this is an exception
+ else if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY))
+ {
+ if (!dwFT1 && !dwFT2 && !dwFT3)
+ szClient = "&RQ";
+ else
+ {
+ *bClientId = 0;
+ szClient = "ICQ 2000";
+ }
+ }
+ else if (CheckContactCapabilities(hContact, CAPF_TYPING))
+ szClient = "Icq2Go! (Java)";
+ else
+ szClient = "Icq2Go!";
+ }
+ else if (wVersion == 0xA)
+ {
+ if (!hasCapRichText(caps, wLen) && !CheckContactCapabilities(hContact, CAPF_UTF))
+ { // this is bad, but we must do it - try to detect QNext
+ ClearContactCapabilities(hContact, CAPF_SRV_RELAY);
+ NetLog_Server("Forcing simple messages (QNext client).");
+ szClient = "QNext";
+ }
+ else if (!hasCapRichText(caps, wLen) && CheckContactCapabilities(hContact, CAPF_UTF) && !dwFT1 && !dwFT2 && !dwFT3)
+ { // not really good, but no other option
+ szClient = "NanoICQ";
+ }
+ }
+ else if (wVersion == 0)
+ { // capability footprint based detection - not really reliable
+ if (!dwFT1 && !dwFT2 && !dwFT3 && !dwWebPort && !dwDirectCookie)
+ { // DC info is empty
+ if (CheckContactCapabilities(hContact, CAPF_TYPING) && MatchCap(caps, wLen, &capIs2001, 0x10) &&
+ MatchCap(caps, wLen, &capIs2002, 0x10) && MatchCap(caps, wLen, &capComm20012, 0x10))
+ szClient = cliSpamBot;
+ else if (MatchCap(caps, wLen, &capAimIcon, 0x10) && MatchCap(caps, wLen, &capAimDirect, 0x10) &&
+ CheckContactCapabilities(hContact, CAPF_AIM_FILE | CAPF_UTF))
+ { // detect libgaim
+ if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY))
+ szClient = "Adium X"; // yeah, AFAIK only Adium has this fixed
+ else
+ szClient = "libgaim";
+ }
+ else if (MatchCap(caps, wLen, &capAimIcon, 0x10) && MatchCap(caps, wLen, &capAimDirect, 0x10) &&
+ MatchCap(caps, wLen, &capAimChat, 0x10) && CheckContactCapabilities(hContact, CAPF_AIM_FILE) && wLen == 0x40)
+ szClient = "libgaim"; // Gaim 1.5.1 most probably
+ else if (MatchCap(caps, wLen, &capAimChat, 0x10) && CheckContactCapabilities(hContact, CAPF_AIM_FILE) && wLen == 0x20)
+ szClient = "Easy Message";
+ else if (MatchCap(caps, wLen, &capAimIcon, 0x10) && CheckContactCapabilities(hContact, CAPF_UTF) && wLen == 0x20)
+ szClient = "Meebo";
+ else if (MatchCap(caps, wLen, &capAimIcon, 0x10) && MatchCap(caps, wLen, &capIcqLite, 0x10) && CheckContactCapabilities(hContact, CAPF_UTF | CAPF_XTRAZ))
+ szClient = "PyICQ-t Jabber Transport";
+ else if (MatchCap(caps, wLen, &capIsIcq, 0x10) && CheckContactCapabilities(hContact, CAPF_UTF | CAPF_SRV_RELAY | CAPF_TYPING) && wLen == 0x40)
+ szClient = "Agile Messenger"; // Smartphone 2002
+ }
+ }
+ }
+ }
+ else if (!dwUin)
+ { // detect AIM clients
+ if (caps)
+ {
+ if (capId = MatchCap(caps, wLen, &capAimOscar, 8))
+ { // AimOscar Signature
+ DWORD aver = (*capId)[0xC] << 0x18 | (*capId)[0xD] << 0x10 | (*capId)[0xE] << 8 | (*capId)[0xF];
+ DWORD mver = (*capId)[0x8] << 0x18 | (*capId)[0x9] << 0x10 | (*capId)[0xA] << 8 | (*capId)[0xB];
+
+ szClient = MirandaVersionToStringEx(szClientBuf, "AimOscar", aver, mver);
+ }
+ else if (capId = MatchCap(caps, wLen, &capSim, 0xC))
+ { // Sim is universal
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+
+ makeClientVersion(szClientBuf, "SIM ", ver1, ver2, ver3, 0);
+ if ((*capId)[0xF] & 0x80)
+ strcat(szClientBuf,"/Win32");
+ else if ((*capId)[0xF] & 0x40)
+ strcat(szClientBuf,"/MacOS X");
+
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capKopete, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ makeClientVersion(szClientBuf, "Kopete ", ver1, ver2, ver3, ver4);
+
+ szClient = szClientBuf;
+ }
+ else if (MatchCap(caps, wLen, &capIm2, 0x10))
+ { // IM2 extensions
+ szClient = cliIM2;
+ }
+ else
+ szClient = "AIM";
+ }
+ else
+ szClient = "AIM";
+ }
+ }
+
+ if (!szClient)
+ {
+ NetLog_Server("No client identification, put default ICQ client for protocol.");
+
+ *bClientId = 0;
+
+ switch (wVersion)
+ { // client detection failed, provide default clients
+ case 6:
+ szClient = "ICQ99";
+ break;
+ case 7:
+ szClient = "ICQ 2000/Icq2Go";
+ break;
+ case 8:
+ szClient = "ICQ 2001-2003a";
+ break;
+ case 9:
+ szClient = "ICQ Lite";
+ break;
+ case 0xA:
+ szClient = "ICQ 2003b";
+ }
+ }
+ else
+ {
+ NetLog_Server("Client identified as %s", szClient);
+ }
+
+ if (szClient)
+ {
+ char* szExtra = NULL;
+
+ if (MatchCap(caps, wLen, &capSimpLite, 0x10))
+ szExtra = " + SimpLite";
+ else if (MatchCap(caps, wLen, &capSimpPro, 0x10))
+ szExtra = " + SimpPro";
+
+ if (szExtra)
+ {
+ if (szClient != szClientBuf)
+ {
+ strcpy(szClientBuf, szClient);
+ szClient = szClientBuf;
+ }
+ strcat(szClient, szExtra);
+ }
+ }
+ return szClient;
+}
diff --git a/icqj_mod/icq_constants.h b/icqj_mod/icq_constants.h new file mode 100644 index 0000000..55c8214 --- /dev/null +++ b/icqj_mod/icq_constants.h @@ -0,0 +1,572 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_constants.h,v $
+// Revision : $Revision: 3069 $
+// Last change on : $Date: 2006-06-07 20:05:39 +0200 (Wed, 07 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Global constants and default settings are defined here
+//
+// -----------------------------------------------------------------------------
+
+// Most of the protocol constants follow the naming conventions of the
+// Oscar documentation at http://iserverd.khstu.ru/oscar/index.html
+// BIG THANKS to Alexandr for maintaining this site and to everyone
+// in the ICQ devel community who have helped to collect the data.
+
+#ifndef __ICQ_CONSTANTS_H
+#define __ICQ_CONSTANTS_H
+
+#define DEF_FP1 0xffffffff
+#define DEF_FP2 ICQ_PLUG_VERSION
+#define DEF_FP3 0x00000000
+
+/* Some default settings */
+#define DEFAULT_SERVER_PORT 5190
+#define DEFAULT_SERVER_HOST "login.icq.com"
+#define DEFAULT_SS_ENABLED 1
+#define DEFAULT_SS_ADDSERVER 1
+#define DEFAULT_SS_LOAD 0
+#define DEFAULT_SS_STORE 1
+#define DEFAULT_SS_GROUP "General"
+
+#define DEFAULT_SECURE_LOGIN 1
+#define DEFAULT_AIM_ENABLED 0
+#define DEFAULT_UTF_ENABLED 2 // everything unicode is default
+#define DEFAULT_ANSI_CODEPAGE CP_ACP
+#define DEFAULT_DCMSG_ENABLED 1 // passive dc messaging is default
+#define DEFAULT_TEMPVIS_ENABLED 1 // temporary visible is enabled by default
+#define DEFAULT_MTN_ENABLED 1
+#define DEFAULT_CAPS 0
+#define DEFAULT_AVATARS_ENABLED 1
+#define DEFAULT_LOAD_AVATARS 1
+#define DEFAULT_LINK_AVATARS 1
+#define DEFAULT_XSTATUS_ENABLED 1
+#define DEFAULT_XSTATUS_AUTO 1
+#define DEFAULT_XSTATUS_RESET 0
+#define DEFAULT_KILLSPAM_ENABLED 1
+
+#define DEFAULT_SLOWSEND 1
+#define DEFAULT_ONLYSERVERACKS 0
+
+#define DEFAULT_POPUPS_ENABLED 1
+#define DEFAULT_SPAM_POPUPS_ENABLED 1
+#define DEFAULT_LOG_POPUPS_ENABLED 1
+#define DEFAULT_POPUPS_SYS_ICONS 1
+#define DEFAULT_LOG0_TEXT_COLORS RGB(0,0,0) // LOG_NOTE
+#define DEFAULT_LOG0_BACK_COLORS RGB(255,255,255)
+#define DEFAULT_LOG0_TIMEOUT 0
+#define DEFAULT_LOG1_TEXT_COLORS RGB(0,0,0) // LOG_WARNING
+#define DEFAULT_LOG1_BACK_COLORS RGB(255,255,255)
+#define DEFAULT_LOG1_TIMEOUT 0
+#define DEFAULT_LOG2_TEXT_COLORS RGB(0,0,0) // LOG_ERROR
+#define DEFAULT_LOG2_BACK_COLORS RGB(255,255,255)
+#define DEFAULT_LOG2_TIMEOUT 0
+#define DEFAULT_LOG3_TEXT_COLORS RGB(0,0,0) // LOG_FATAL
+#define DEFAULT_LOG3_BACK_COLORS RGB(255,255,255)
+#define DEFAULT_LOG3_TIMEOUT 0
+#define DEFAULT_LOG4_TEXT_COLORS RGB(0,0,0) // LOG_FOUND
+#define DEFAULT_LOG4_BACK_COLORS RGB(255,255,255)
+#define DEFAULT_LOG4_TIMEOUT 0
+#define DEFAULT_LOG5_TEXT_COLORS RGB(0,0,0) // LOG_FINISHED
+#define DEFAULT_LOG5_BACK_COLORS RGB(255,255,255)
+#define DEFAULT_LOG5_TIMEOUT 0
+#define DEFAULT_SPAM_TEXT_COLORS RGB(193,0,38)
+#define DEFAULT_SPAM_BACK_COLORS RGB(213,209,208)
+#define DEFAULT_SPAM_TIMEOUT 0
+#define DEFAULT_POPUPS_WIN_COLORS 0
+
+// Database setting names
+#define DBSETTING_CAPABILITIES "caps"
+#define DBSETTING_XSTATUSID "XStatusId"
+#define DBSETTING_XSTATUSNAME "XStatusName"
+#define DBSETTING_XSTATUSMSG "XStatusMsg"
+
+
+// Status FLAGS (used to determine status of other users)
+#define ICQ_STATUSF_ONLINE 0x0000
+#define ICQ_STATUSF_AWAY 0x0001
+#define ICQ_STATUSF_DND 0x0002
+#define ICQ_STATUSF_NA 0x0004
+#define ICQ_STATUSF_OCCUPIED 0x0010
+#define ICQ_STATUSF_FFC 0x0020
+#define ICQ_STATUSF_INVISIBLE 0x0100
+
+// Status values (used to set own status)
+#define ICQ_STATUS_ONLINE 0x0000
+#define ICQ_STATUS_AWAY 0x0001
+#define ICQ_STATUS_NA 0x0005
+#define ICQ_STATUS_OCCUPIED 0x0011
+#define ICQ_STATUS_DND 0x0013
+#define ICQ_STATUS_FFC 0x0020
+#define ICQ_STATUS_INVISIBLE 0x0100
+
+#define STATUS_WEBAWARE 0x0001 // Status webaware flag
+#define STATUS_SHOWIP 0x0002 // Status show ip flag
+#define STATUS_BIRTHDAY 0x0008 // User birthday flag
+#define STATUS_WEBFRONT 0x0020 // User active webfront flag
+#define STATUS_DCDISABLED 0x0100 // Direct connection not supported
+#define STATUS_DCAUTH 0x1000 // Direct connection upon authorization
+#define STATUS_DCCONT 0x2000 // DC only with contact users
+
+
+
+// Typing notification statuses
+#define MTN_FINISHED 0x0000
+#define MTN_TYPED 0x0001
+#define MTN_BEGUN 0x0002
+
+
+
+// Ascii Capability IDs
+#define CAP_RTFMSGS "{97B12751-243C-4334-AD22-D6ABF73F1492}"
+#define CAP_UTF8MSGS "{0946134E-4C7F-11D1-8222-444553540000}"
+
+// Binary Capability IDs
+#define BINARY_CAP_SIZE 16
+#define CAP_SRV_RELAY 0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
+#define CAP_UTF 0x09, 0x46, 0x13, 0x4e, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
+#define CAP_TYPING 0x56, 0x3f, 0xc8, 0x09, 0x0b, 0x6f, 0x41, 0xbd, 0x9f, 0x79, 0x42, 0x26, 0x09, 0xdf, 0xa2, 0xf3
+#define CAP_XTRAZ 0x1A, 0x09, 0x3C, 0x6C, 0xD7, 0xFD, 0x4E, 0xC5, 0x9D, 0x51, 0xA6, 0x47, 0x4E, 0x34, 0xF5, 0xA0
+#define CAP_AIM_FILE 0x09, 0x46, 0x13, 0x43, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
+
+#define CAP_PUSH2TALK 0xE3, 0x62, 0xC1, 0xE9, 0x12, 0x1A, 0x4B, 0x94, 0xA6, 0x26, 0x7A, 0x74, 0xDE, 0x24, 0x27, 0x0D
+#define CAP_ICQ_LITE 0x17, 0x8C, 0x2D, 0x9B, 0xDA, 0xA5, 0x45, 0xBB, 0x8D, 0xDB, 0xF3, 0xBD, 0xBD, 0x53, 0xA1, 0x0A
+#define CAP_RTF 0x97, 0xB1, 0x27, 0x51, 0x24, 0x3C, 0x43, 0x34, 0xAD, 0x22, 0xD6, 0xAB, 0xF7, 0x3F, 0x14, 0x92
+#define CAP_XTRAZ_CHAT 0x67, 0x36, 0x15, 0x15, 0x61, 0x2D, 0x4C, 0x07, 0x8F, 0x3D, 0xBD, 0xE6, 0x40, 0x8E, 0xA0, 0x41
+#define CAP_VOICE_CHAT 0xB9, 0x97, 0x08, 0xB5, 0x3A, 0x92, 0x42, 0x02, 0xB0, 0x69, 0xF1, 0xE7, 0x57, 0xBB, 0x2E, 0x17
+#define CAP_ICQ_DEVIL 0x09, 0x46, 0x13, 0x4C, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
+#define CAP_DIRECT 0x09, 0x46, 0x13, 0x44, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
+
+// Miranda IM Capability bitmask
+#define CAPF_SRV_RELAY 0x00000001
+#define CAPF_UTF 0x00000002
+#define CAPF_TYPING 0x00000004
+#define CAPF_XTRAZ 0x00000010
+#define CAPF_AIM_FILE 0x00000040
+
+#define CAPF_PUSH2TALK 0x00000080
+#define CAPF_ICQ_LITE 0x00000100
+#define CAPF_RTF 0x00000200
+#define CAPF_XTRAZ_CHAT 0x00000400
+#define CAPF_VOICE_CHAT 0x00000800
+#define CAPF_ICQ_DEVIL 0x00001000
+#define CAPF_DIRECT 0x00002000
+
+// Message Capability IDs
+#define MCAP_TLV2711_FMT_s 0x09461349, 0x4c7f11d1, 0x82224445, 0x53540000
+#define MCAP_REVERSE_REQ_s 0x09461344, 0x4c7f11d1, 0x82224445, 0x53540000
+
+// Plugin Type GUIDs
+#define PSIG_MESSAGE_s 0x00000000, 0x00000000, 0x00000000, 0x00000000
+#define PSIG_INFO_PLUGIN_s 0xa0e93f37, 0x4fe9d311, 0xbcd20004, 0xac96dd96
+#define PSIG_STATUS_PLUGIN_s 0x10cf40d1, 0x4fe9d311, 0xbcd20004, 0xac96dd96
+
+// Plugin Message GUIDs
+#define PMSG_QUERY_INFO_s 0xF002BF71, 0x4371D311, 0x8DD20010, 0x4B06462E
+#define PMSG_QUERY_STATUS_s 0x10180670, 0x5471D311, 0x8DD20010, 0x4B06462E
+
+
+
+// Message types
+#define MTYPE_PLAIN 0x01 // Plain text (simple) message
+#define MTYPE_CHAT 0x02 // Chat request message
+#define MTYPE_FILEREQ 0x03 // File request / file ok message
+#define MTYPE_URL 0x04 // URL message (0xFE formatted)
+#define MTYPE_AUTHREQ 0x06 // Authorization request message (0xFE formatted)
+#define MTYPE_AUTHDENY 0x07 // Authorization denied message (0xFE formatted)
+#define MTYPE_AUTHOK 0x08 // Authorization given message (empty)
+#define MTYPE_SERVER 0x09 // Message from OSCAR server (0xFE formatted)
+#define MTYPE_ADDED 0x0C // "You-were-added" message (0xFE formatted)
+#define MTYPE_WWP 0x0D // Web pager message (0xFE formatted)
+#define MTYPE_EEXPRESS 0x0E // Email express message (0xFE formatted)
+#define MTYPE_CONTACTS 0x13 // Contact list message
+#define MTYPE_PLUGIN 0x1A // Plugin message described by text string
+#define MTYPE_AUTOAWAY 0xE8 // Auto away message
+#define MTYPE_AUTOBUSY 0xE9 // Auto occupied message
+#define MTYPE_AUTONA 0xEA // Auto not available message
+#define MTYPE_AUTODND 0xEB // Auto do not disturb message
+#define MTYPE_AUTOFFC 0xEC // Auto free for chat message
+// Internal Message types
+#define MTYPE_UNKNOWN 0x00 // Unknown message
+
+#define MTYPE_GREETINGCARD 0x101 // Greeting Card
+#define MTYPE_REQUESTCONTACTS 0x102 // Request for Contacts
+#define MTYPE_MESSAGE 0x103 // Message+
+#define MTYPE_STATUSMSGEXT 0x104 // StatusMsgExt (2003b)
+#define MTYPE_SCRIPT_INVITATION 0x201 // Xtraz Invitation
+#define MTYPE_SCRIPT_DATA 0x202 // Xtraz Message
+#define MTYPE_SCRIPT_NOTIFY 0x208 // Xtraz Response
+#define MTYPE_REVERSE_REQUEST 0x401 // Reverse DC request
+
+// Message Plugin Type GUIDs
+#define MGTYPE_MESSAGE_s 0xBE6B7305, 0x0FC2104F, 0xA6DE4DB1, 0xE3564B0E
+#define MGTYPE_STATUSMSGEXT_s 0x811a18bc, 0x0e6c1847, 0xa5916f18, 0xdcc76f1a
+#define MGTYPE_FILE_s 0xF02D12D9, 0x3091D311, 0x8DD70010, 0x4B06462E
+#define MGTYPE_WEBURL_s 0x371C5872, 0xE987D411, 0xA4C100D0, 0xB759B1D9
+#define MGTYPE_CONTACTS_s 0x2A0E7D46, 0x7676D411, 0xBCE60004, 0xAC961EA6
+#define MGTYPE_GREETING_CARD_s 0x01E53B48, 0x2AE4D111, 0xB6790060, 0x97E1E294
+#define MGTYPE_CHAT_s 0xBFF720B2, 0x378ED411, 0xBD280004, 0xAC96D905
+#define MGTYPE_XTRAZ_SCRIPT_s 0x3b60b3ef, 0xd82a6c45, 0xa4e09c5a, 0x5e67e865
+
+// Message Plugin Sub-Type IDs
+#define MGTYPE_STANDARD_SEND 0x00
+#define MGTYPE_CONTACTS_REQUEST 0x02
+#define MGTYPE_SCRIPT_INVITATION 0x01
+#define MGTYPE_SCRIPT_DATA 0x02
+#define MGTYPE_SCRIPT_USER_REMOVE 0x04
+#define MGTYPE_SCRIPT_NOTIFY 0x08
+
+
+
+/* Channels */
+#define ICQ_LOGIN_CHAN 0x01
+#define ICQ_DATA_CHAN 0x02
+#define ICQ_ERROR_CHAN 0x03
+#define ICQ_CLOSE_CHAN 0x04
+#define ICQ_PING_CHAN 0x05
+
+/* Families */
+#define ICQ_SERVICE_FAMILY 0x0001
+#define ICQ_LOCATION_FAMILY 0x0002
+#define ICQ_BUDDY_FAMILY 0x0003
+#define ICQ_MSG_FAMILY 0x0004
+#define ICQ_BOS_FAMILY 0x0009
+#define ICQ_LOOKUP_FAMILY 0x000a
+#define ICQ_STATS_FAMILY 0x000b
+#define ICQ_AVATAR_FAMILY 0x0010
+#define ICQ_LISTS_FAMILY 0x0013
+#define ICQ_EXTENSIONS_FAMILY 0x0015
+#define ICQ_AUTHORIZATION_FAMILY 0x0017
+
+/* Subtypes for Service Family 0x0001 */
+#define ICQ_ERROR 0x0001
+#define ICQ_CLIENT_READY 0x0002
+#define ICQ_SERVER_READY 0x0003
+#define ICQ_CLIENT_NEW_SERVICE 0x0004
+#define ICQ_SERVER_REDIRECT_SERVICE 0x0005
+#define ICQ_CLIENT_REQ_RATE_INFO 0x0006
+#define ICQ_SERVER_RATE_INFO 0x0007
+#define ICQ_CLIENT_RATE_ACK 0x0008
+#define ICQ_SERVER_RATE_CHANGE 0x000a
+#define ICQ_SERVER_PAUSE 0x000b
+#define ICQ_CLIENT_PAUSE_ACK 0x000c
+#define ICQ_SERVER_RESUME 0x000d
+#define ICQ_CLIENT_REQINFO 0x000e
+#define ICQ_SERVER_NAME_INFO 0x000f
+#define ICQ_SERVER_EVIL_NOTICE 0x0010
+#define ICQ_CLIENT_SET_IDLE 0x0011
+#define ICQ_SERVER_MIGRATIONREQ 0x0012
+#define ICQ_SERVER_MOTD 0x0013
+#define ICQ_CLIENT_FAMILIES 0x0017
+#define ICQ_SERVER_FAMILIES2 0x0018
+#define ICQ_CLIENT_SET_STATUS 0x001e
+#define ICQ_SERVER_EXTSTATUS 0x0021
+
+/* Subtypes for Location Family 0x0002 */
+#define ICQ_LOCATION_CLI_REQ_RIGHTS 0x0002
+#define ICQ_LOCATION_RIGHTS_REPLY 0x0003
+#define ICQ_LOCATION_SET_USER_INFO 0x0004
+#define ICQ_LOCATION_REQ_USER_INFO 0x0005
+#define ICQ_LOCATION_USR_INFO_REPLY 0x0006
+
+/* Subtypes for Buddy Family 0x0003 */
+#define ICQ_USER_CLI_REQBUDDY 0x0002
+#define ICQ_USER_SRV_REPLYBUDDY 0x0003
+#define ICQ_USER_ADDTOLIST 0x0004
+#define ICQ_USER_REMOVEFROMLIST 0x0005
+#define ICQ_USER_NOTIFY_REJECTED 0x000a
+#define ICQ_USER_ONLINE 0x000b
+#define ICQ_USER_OFFLINE 0x000c
+
+/* Subtypes for Message Family 0x0004 */
+#define ICQ_MSG_SRV_ERROR 0x0001
+#define ICQ_MSG_CLI_SETPARAMS 0x0002
+#define ICQ_MSG_CLI_RESETPARAMS 0x0003
+#define ICQ_MSG_CLI_REQICBM 0x0004
+#define ICQ_MSG_SRV_REPLYICBM 0x0005
+#define ICQ_MSG_SRV_SEND 0x0006
+#define ICQ_MSG_SRV_RECV 0x0007
+#define ICQ_MSG_SRV_MISSED_MESSAGE 0x000A
+#define ICQ_MSG_RESPONSE 0x000B
+#define ICQ_MSG_SRV_ACK 0x000C
+#define ICQ_MSG_MTN 0x0014
+
+/* Subtypes for Privacy Family 0x0009 */
+#define ICQ_PRIVACY_REQ_RIGHTS 0x0002
+#define ICQ_PRIVACY_RIGHTS_REPLY 0x0003
+#define ICQ_CLI_ADDVISIBLE 0x0005
+#define ICQ_CLI_REMOVEVISIBLE 0x0006
+#define ICQ_CLI_ADDINVISIBLE 0x0007
+#define ICQ_CLI_REMOVEINVISIBLE 0x0008
+#define ICQ_PRIVACY_SERVICE_ERROR 0x0009
+#define ICQ_CLI_ADDTEMPVISIBLE 0x000A
+#define ICQ_CLI_REMOVETEMPVISIBLE 0x000B
+
+/* Subtypes for Lookup Family 0x000a */
+#define ICQ_LOOKUP_REQUEST 0x0002
+#define ICQ_LOOKUP_EMAIL_REPLY 0x0003
+
+/* Subtypes for Stats Family 0x000b */
+#define ICQ_STATS_MINREPORTINTERVAL 0x0002
+
+/* Subtypes for Avatar Family 0x0010 */
+#define ICQ_AVATAR_ERROR 0x0001
+#define ICQ_AVATAR_UPLOAD_REQUEST 0x0002
+#define ICQ_AVATAR_UPLOAD_ACK 0x0003
+#define ICQ_AVATAR_GET_REQUEST 0x0006
+#define ICQ_AVATAR_GET_REPLY 0x0007
+
+/* Subtypes for Server Lists Family 0x0013 */
+#define ICQ_LISTS_ERROR 0x0001
+#define ICQ_LISTS_CLI_REQLISTS 0x0002
+#define ICQ_LISTS_SRV_REPLYLISTS 0x0003
+#define ICQ_LISTS_CLI_REQUEST 0x0004
+#define ICQ_LISTS_CLI_CHECK 0x0005
+#define ICQ_LISTS_LIST 0x0006
+#define ICQ_LISTS_GOTLIST 0x0007
+#define ICQ_LISTS_ADDTOLIST 0x0008
+#define ICQ_LISTS_UPDATEGROUP 0x0009
+#define ICQ_LISTS_REMOVEFROMLIST 0x000A
+#define ICQ_LISTS_ACK 0x000E
+#define ICQ_LISTS_UPTODATE 0x000F
+#define ICQ_LISTS_CLI_MODIFYSTART 0x0011
+#define ICQ_LISTS_CLI_MODIFYEND 0x0012
+#define ICQ_LISTS_GRANTAUTH 0x0014
+#define ICQ_LISTS_AUTHGRANTED 0x0015
+#define ICQ_LISTS_REVOKEAUTH 0x0016
+#define ICQ_LISTS_REQUESTAUTH 0x0018
+#define ICQ_LISTS_AUTHREQUEST 0x0019
+#define ICQ_LISTS_CLI_AUTHRESPONSE 0x001A
+#define ICQ_LISTS_SRV_AUTHRESPONSE 0x001B
+#define ICQ_LISTS_YOUWEREADDED 0x001C
+
+/* Subtypes for ICQ Extensions Family 0x0015 */
+#define ICQ_META_ERROR 0x0001
+#define ICQ_META_CLI_REQ 0x0002
+#define ICQ_META_SRV_REPLY 0x0003
+
+/* Subtypes for Authorization Family 0x0017 */
+#define ICQ_SIGNON_ERROR 0x0001
+#define ICQ_SIGNON_LOGIN_REQUEST 0x0002
+#define ICQ_SIGNON_LOGIN_REPLY 0x0003
+#define ICQ_SIGNON_REGISTRATION_REQ 0x0004
+#define ICQ_SIGNON_NEW_UIN 0x0005
+#define ICQ_SIGNON_AUTH_REQUEST 0x0006
+#define ICQ_SIGNON_AUTH_KEY 0x0007
+#define ICQ_SIGNON_REQUEST_IMAGE 0x000C
+#define ICQ_SIGNON_REG_AUTH_IMAGE 0x000D
+
+// Class constants
+#define CLASS_UNCONFIRMED 0x0001
+#define CLASS_ADMINISTRATOR 0x0002
+#define CLASS_AOL 0x0004
+#define CLASS_COMMERCIAL 0x0008
+#define CLASS_FREE 0x0010
+#define CLASS_AWAY 0x0020
+#define CLASS_ICQ 0x0040
+#define CLASS_WIRELESS 0x0080
+
+// Reply types for SNAC 15/02 & 15/03
+#define CLI_OFFLINE_MESSAGE_REQ 0x003C
+#define CLI_DELETE_OFFLINE_MSGS_REQ 0x003E
+#define SRV_OFFLINE_MESSAGE 0x0041
+#define SRV_END_OF_OFFLINE_MSGS 0x0042
+#define CLI_META_INFO_REQ 0x07D0
+#define SRV_META_INFO_REPLY 0x07DA
+
+// Reply subtypes for SNAC 15/02 & 15/03
+#define META_PROCESSING_ERROR 0x0001 // Meta processing error server reply
+#define META_SMS_DELIVERY_RECEIPT 0x0096 // Server SMS response (delivery receipt)
+#define META_SET_PASSWORD_ACK 0x00AA // Set user password server ack
+#define META_UNREGISTER_ACK 0x00B4 // Unregister account server ack
+#define META_BASIC_USERINFO 0x00C8 // User basic info reply
+#define META_WORK_USERINFO 0x00D2 // User work info reply
+#define META_MORE_USERINFO 0x00DC // User more info reply
+#define META_NOTES_USERINFO 0x00E6 // User notes (about) info reply
+#define META_EMAIL_USERINFO 0x00EB // User extended email info reply
+#define META_INTERESTS_USERINFO 0x00F0 // User interests info reply
+#define META_AFFILATIONS_USERINFO 0x00FA // User past/affilations info reply
+#define META_SHORT_USERINFO 0x0104 // Short user information reply
+#define META_HPAGECAT_USERINFO 0x010E // User homepage category information reply
+#define SRV_USER_FOUND 0x01A4 // Search: user found reply
+#define SRV_LAST_USER_FOUND 0x01AE // Search: last user found reply
+#define META_REGISTRATION_STATS_ACK 0x0302 // Registration stats ack
+#define SRV_RANDOM_FOUND 0x0366 // Random search server reply
+#define META_SET_PASSWORD_REQ 0x042E // Set user password request
+#define META_REQUEST_FULL_INFO 0x04B2 // Request full user info
+#define META_REQUEST_SHORT_INFO 0x04BA // Request short user info
+#define META_REQUEST_SELF_INFO 0x04D0 // Request full self user info
+#define META_SEARCH_GENERIC 0x055F // Search user by details (TLV)
+#define META_SEARCH_UIN 0x0569 // Search user by UIN (TLV)
+#define META_SEARCH_EMAIL 0x0573 // Search user by E-mail (TLV)
+
+#define META_XML_INFO 0x08A2 // Server variable requested via xml
+#define META_SET_FULLINFO_REQ 0x0C3A // Set full user info request
+#define META_SET_FULLINFO_ACK 0x0C3F // Server ack for set fullinfo command
+#define META_SPAM_REPORT_ACK 0x2012 // Server ack for user spam report
+
+// TLV types
+
+// SECURITY flags
+#define TLV_AUTH 0x02F8 // uint8 User authorization permissions
+#define TLV_WEBAWARE 0x030C // uint8 User 'show web status' permissions
+
+
+// SEARCH only TLVs
+#define TLV_AGERANGE 0x0168 // acombo Age range to search
+#define TLV_KEYWORDS 0x0226 // sstring Whitepages search keywords string
+#define TLV_ONLINEONLY 0x0230 // uint8 Search only online users flag
+#define TLV_UIN 0x0136 // uint32 User uin
+
+// common
+#define TLV_FIRSTNAME 0x0140 // sstring User firstname
+#define TLV_LASTNAME 0x014A // sstring User lastname
+#define TLV_NICKNAME 0x0154 // sstring User nickname
+#define TLV_EMAIL 0x015E // ecombo User email
+#define TLV_GENDER 0x017C // uint8 User gender
+#define TLV_MARITAL 0x033E // uint8 User marital status
+#define TLV_LANGUAGE 0x0186 // uint16 User spoken language
+#define TLV_CITY 0x0190 // sstring User home city name
+#define TLV_STATE 0x019A // sstring User home state abbr
+#define TLV_COUNTRY 0x01A4 // uint16 User home country code
+#define TLV_COMPANY 0x01AE // sstring User work company name
+#define TLV_DEPARTMENT 0x01B8 // sstring User work department name
+#define TLV_POSITION 0x01C2 // sstring User work position (title)
+#define TLV_OCUPATION 0x01CC // uint16 User work ocupation code
+#define TLV_PASTINFO 0x01D6 // icombo User affilations node
+#define TLV_AFFILATIONS 0x01FE // icombo User past info node
+#define TLV_INTERESTS 0x01EA // icombo User interests node
+#define TLV_HOMEPAGE 0x0212 // sstring User homepage category/keywords
+
+// changeinfo
+#define TLV_AGE 0x0172 // uint16 User age
+#define TLV_URL 0x0213 // sstring User homepage url
+#define TLV_BIRTH 0x023A // bcombo User birthday info (year, month, day)
+#define TLV_ABOUT 0x0258 // sstring User notes (about) text
+#define TLV_STREET 0x0262 // sstring User home street address
+#define TLV_ZIPCODE 0x026D // sstring User home zip code
+#define TLV_PHONE 0x0276 // sstring User home phone number
+#define TLV_FAX 0x0280 // sstring User home fax number
+#define TLV_MOBILE 0x028A // sstring User home cellular phone number
+#define TLV_WORKSTREET 0x0294 // sstring User work street address
+#define TLV_WORKCITY 0x029E // sstring User work city name
+#define TLV_WORKSTATE 0x02A8 // sstring User work state name
+#define TLV_WORKCOUNTRY 0x02B2 // uint16 User work country code
+#define TLV_WORKZIPCODE 0x02BD // sstring User work zip code
+#define TLV_WORKPHONE 0x02C6 // sstring User work phone number
+#define TLV_WORKFAX 0x02D0 // sstring User work fax number
+#define TLV_WORKURL 0x02DA // sstring User work webpage url
+#define TLV_TIMEZONE 0x0316 // uint8 User GMT offset
+#define TLV_ORGCITY 0x0320 // sstring User originally from city
+#define TLV_ORGSTATE 0x032A // sstring User originally from state
+#define TLV_ORGCOUNTRY 0x0334 // uint16 User originally from country (code)
+#define TLV_ALLOWSPAM 0x0348 // uint8
+#define TLV_CODEPAGE 0x0352 // uint16 Codepage used for details
+
+
+/* Direct packet types */
+#define PEER_INIT 0xFF
+#define PEER_INIT_ACK 0x01
+#define PEER_MSG_INIT 0x03
+#define PEER_MSG 0x02
+#define PEER_FILE_INIT 0x00
+#define PEER_FILE_INIT_ACK 0x01
+#define PEER_FILE_NEXTFILE 0x02
+#define PEER_FILE_RESUME 0x03
+#define PEER_FILE_STOP 0x04
+#define PEER_FILE_SPEED 0x05
+#define PEER_FILE_DATA 0x06
+
+/* Direct command types */
+#define DIRECT_CANCEL 0x07D0 /* 2000 TCP cancel previous file/chat request */
+#define DIRECT_ACK 0x07DA /* 2010 TCP acknowledge message packet */
+#define DIRECT_MESSAGE 0x07EE /* 2030 TCP message */
+
+// DC types
+#define DC_DISABLED 0x0000 // Direct connection disabled / auth required
+#define DC_HTTPS 0x0001 // Direct connection thru firewall or https proxy
+#define DC_SOCKS 0x0002 // Direct connection thru socks4/5 proxy server
+#define DC_NORMAL 0x0004 // Normal direct connection (without proxy/firewall)
+#define DC_WEB 0x0006 // Web client - no direct connection
+
+// Message flags
+#define MFLAG_NORMAL 0x01 // Normal message
+#define MFLAG_AUTO 0x03 // Auto-message flag
+#define MFLAG_MULTI 0x80 // This is multiple recipients message
+
+// Some SSI constants
+#define SSI_ITEM_BUDDY 0x0000 // Buddy record (name: uin for ICQ and screenname for AIM)
+#define SSI_ITEM_GROUP 0x0001 // Group record
+#define SSI_ITEM_PERMIT 0x0002 // Permit record ("Allow" list in AIM, and "Visible" list in ICQ)
+#define SSI_ITEM_DENY 0x0003 // Deny record ("Block" list in AIM, and "Invisible" list in ICQ)
+#define SSI_ITEM_VISIBILITY 0x0004 // Permit/deny settings or/and bitmask of the AIM classes
+#define SSI_ITEM_PRESENCE 0x0005 // Presence info (if others can see your idle status, etc)
+#define SSI_ITEM_UNKNOWN1 0x0009 // Unknown. ICQ2k shortcut bar items ?
+#define SSI_ITEM_IGNORE 0x000e // Ignore list record.
+#define SSI_ITEM_LASTUPDATE 0x000f // Item that contain roster update time (name: "LastUpdateDate")
+#define SSI_ITEM_NONICQ 0x0010 // Non-ICQ contact (to send SMS). Name: 1#EXT, 2#EXT, etc
+#define SSI_ITEM_UNKNOWN2 0x0011 // Unknown.
+#define SSI_ITEM_IMPORTTIME 0x0013 // Item that contain roster import time (name: "Import time")
+#define SSI_ITEM_BUDDYICON 0x0014 // Buddy icon info. (names: from "0" and incrementing by one)
+
+#define SSI_TLV_AWAITING_AUTH 0x0066 // Contact not authorised in list
+#define SSI_TLV_UNKNOWN 0x006D // WTF ?
+#define SSI_TLV_SUBITEMS 0x00C8 // List of sub-items IDs
+#define SSI_TLV_VISIBILITY 0x00CA
+#define SSI_TLV_SHORTCUT 0x00CD
+#define SSI_TLV_TIMESTAMP 0x00D4 // Import Timestamp
+#define SSI_TLV_AVATARHASH 0x00D5
+#define SSI_TLV_NAME 0x0131 // Custom contact nickname
+#define SSI_TLV_EMAIL 0x0137 // Custom contact email
+#define SSI_TLV_PHONE 0x013A // Custom contact SMS number
+#define SSI_TLV_COMMENT 0x013C // User comment
+
+
+
+// Internal Constants
+#define ICQ_PLUG_VERSION 0x82030700
+#define ICQ_VERSION 8
+#define DC_TYPE DC_NORMAL // Used for DC settings
+#define MAX_NICK_SIZE 32
+#define MAX_CONTACTSSEND 15
+#define MAX_MESSAGESNACSIZE 8000
+#define CLIENTRATELIMIT 0
+#define UPDATE_THRESHOLD 1209600 // Two weeks
+#define COOKIE_TIMEOUT 3600 // One hour
+#define WEBFRONTPORT 0x50
+#define CLIENTFEATURES 0x3
+#define URL_FORGOT_PASSWORD "https://www.icq.com/password/"
+#define URL_REGISTER "http://lite.icq.com/register"
+#define FLAP_MARKER 0x2a
+#define CLIENT_ID_STRING "ICQBasic"
+#define CLIENT_MD5_STRING "AOL Instant Messenger (SM)"
+#define UNIQUEIDSETTING "UIN"
+#define UINMAXLEN 11 // DWORD string max len + 1
+
+#endif /* __ICQ_CONSTANTS_H */
diff --git a/icqj_mod/icq_db.c b/icqj_mod/icq_db.c new file mode 100644 index 0000000..9f4e5fb --- /dev/null +++ b/icqj_mod/icq_db.c @@ -0,0 +1,342 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_db.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Internal Database API
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static BOOL bUtfReadyDB = FALSE;
+
+void InitDB()
+{
+ bUtfReadyDB = ServiceExists(MS_DB_CONTACT_GETSETTING_STR);
+ if (!bUtfReadyDB)
+ NetLog_Server("Warning: DB module does not support Unicode.");
+}
+
+
+BYTE ICQGetContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bDef)
+{
+ return DBGetContactSettingByte(hContact, gpszICQProtoName, szSetting, bDef);
+}
+
+
+WORD ICQGetContactSettingWord(HANDLE hContact, const char* szSetting, WORD wDef)
+{
+ return DBGetContactSettingWord(hContact, gpszICQProtoName, szSetting, wDef);
+}
+
+
+DWORD ICQGetContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwDef)
+{
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING cgs;
+ DWORD dwRes;
+
+ cgs.szModule = gpszICQProtoName;
+ cgs.szSetting = szSetting;
+ cgs.pValue = &dbv;
+ if (CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs))
+ return dwDef; // not found, give default
+
+ if (dbv.type != DBVT_DWORD)
+ dwRes = dwDef; // invalid type, give default
+ else // found and valid, give result
+ dwRes = dbv.dVal;
+
+ ICQFreeVariant(&dbv);
+ return dwRes;
+}
+
+
+
+DWORD ICQGetContactSettingUIN(HANDLE hContact)
+{
+ return ICQGetContactSettingDword(hContact, UNIQUEIDSETTING, 0);
+}
+
+
+
+int ICQGetContactSettingUID(HANDLE hContact, DWORD *pdwUin, uid_str* ppszUid)
+{
+ DBVARIANT dbv;
+ int iRes = 1;
+
+ *pdwUin = 0;
+ if (ppszUid) *ppszUid[0] = '\0';
+
+ if (!ICQGetContactSetting(hContact, UNIQUEIDSETTING, &dbv))
+ {
+ if (dbv.type == DBVT_DWORD)
+ {
+ *pdwUin = dbv.dVal;
+ iRes = 0;
+ }
+ else if (dbv.type == DBVT_ASCIIZ)
+ {
+ if (ppszUid && gbAimEnabled)
+ {
+ strcpy(*ppszUid, dbv.pszVal);
+ iRes = 0;
+ }
+ else
+ NetLog_Server("AOL screennames not accepted");
+ }
+ ICQFreeVariant(&dbv);
+ }
+ return iRes;
+}
+
+
+
+int ICQGetContactSetting(HANDLE hContact, const char* szSetting, DBVARIANT *dbv)
+{
+ return DBGetContactSetting(hContact, gpszICQProtoName, szSetting, dbv);
+}
+
+
+
+char* UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szDef)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ char* szRes;
+
+ if (bUtfReadyDB)
+ {
+ if (DBGetContactSettingStringUtf(hContact, szModule, szSetting, &dbv))
+ return null_strdup(szDef);
+
+ szRes = null_strdup(dbv.pszVal);
+ ICQFreeVariant(&dbv);
+ }
+ else
+ { // old DB, we need to convert the string to UTF-8
+ if (DBGetContactSetting(hContact, szModule, szSetting, &dbv))
+ return null_strdup(szDef);
+
+ szRes = ansi_to_utf8(dbv.pszVal);
+
+ ICQFreeVariant(&dbv);
+ }
+ return szRes;
+}
+
+
+
+char* ICQGetContactSettingUtf(HANDLE hContact, const char* szSetting, char* szDef)
+{
+ return UniGetContactSettingUtf(hContact, gpszICQProtoName, szSetting, szDef);
+}
+
+
+
+WORD ICQGetContactStatus(HANDLE hContact)
+{
+ return ICQGetContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+}
+
+
+
+// (c) by George Hazan
+int ICQGetContactStaticString(HANDLE hContact, const char* valueName, char* dest, int dest_len)
+{
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING sVal;
+
+ dbv.pszVal = dest;
+ dbv.cchVal = dest_len;
+ dbv.type = DBVT_ASCIIZ;
+
+ sVal.pValue = &dbv;
+ sVal.szModule = gpszICQProtoName;
+ sVal.szSetting = valueName;
+
+ if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&sVal) != 0)
+ {
+ dbv.pszVal = dest;
+ dbv.cchVal = dest_len;
+ dbv.type = DBVT_UTF8;
+
+ if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&sVal) != 0)
+ return 1; // this is here due to DB module bug...
+ }
+
+ return (dbv.type != DBVT_ASCIIZ);
+}
+
+
+int ICQDeleteContactSetting(HANDLE hContact, const char* szSetting)
+{
+ return DBDeleteContactSetting(hContact, gpszICQProtoName, szSetting);
+}
+
+
+int ICQWriteContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bValue)
+{
+ return DBWriteContactSettingByte(hContact, gpszICQProtoName, szSetting, bValue);
+}
+
+
+int ICQWriteContactSettingWord(HANDLE hContact, const char* szSetting, WORD wValue)
+{
+ return DBWriteContactSettingWord(hContact, gpszICQProtoName, szSetting, wValue);
+}
+
+
+int ICQWriteContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwValue)
+{
+ return DBWriteContactSettingDword(hContact, gpszICQProtoName, szSetting, dwValue);
+}
+
+
+int ICQWriteContactSettingString(HANDLE hContact, const char* szSetting, char* szValue)
+{
+ return DBWriteContactSettingString(hContact, gpszICQProtoName, szSetting, szValue);
+}
+
+
+int UniWriteContactSettingUtf(HANDLE hContact, const char *szModule, const char* szSetting, char* szValue)
+{
+ if (bUtfReadyDB)
+ return DBWriteContactSettingStringUtf(hContact, szModule, szSetting, szValue);
+ else
+ { // old DB, we need to convert the string to Ansi
+ int size = strlennull(szValue) + 2;
+ char* szAnsi = (char*)_alloca(size);
+
+ if (utf8_decode_static(szValue, szAnsi, size))
+ return DBWriteContactSettingString(hContact, szModule, szSetting, szAnsi);
+ // failed to convert - give error
+
+ return 1;
+ }
+}
+
+
+int ICQWriteContactSettingUtf(HANDLE hContact, const char* szSetting, char* szValue)
+{
+ return UniWriteContactSettingUtf(hContact, gpszICQProtoName, szSetting, szValue);
+}
+
+
+/*static int bdCacheTested = 0;
+static int bdWorkaroundRequired = 0;
+
+void TestDBBlobIssue()
+{
+ DBVARIANT dbv = {0};
+
+ bdCacheTested = 1;
+ DBDeleteContactSetting(NULL, gpszICQProtoName, "BlobTestItem"); // delete setting
+ DBGetContactSetting(NULL, gpszICQProtoName, "BlobTestItem", &dbv); // create crap cache item
+ DBWriteContactSettingBlob(NULL, gpszICQProtoName, "BlobTestItem", "Test", 4); // write blob
+ if (!DBGetContactSetting(NULL, gpszICQProtoName, "BlobTestItem", &dbv)) // try to read it back
+ { // we were able to read it, the DB finally work correctly, hurrah
+ ICQFreeVariant(&dbv);
+ }
+ else // the crap is still in the cache, we need to use workaround for avatars to work properly
+ {
+ NetLog_Server("DB Module contains bug #0001177, using workaround");
+ bdWorkaroundRequired = 1;
+ }
+ DBDeleteContactSetting(NULL, gpszICQProtoName, "BlobTestItem");
+}*/
+
+
+int ICQWriteContactSettingBlob(HANDLE hContact,const char *szSetting,const char *val, const int cbVal)
+{
+ DBCONTACTWRITESETTING cws;
+
+/* if (!bdCacheTested) TestDBBlobIssue();
+
+ if (bdWorkaroundRequired)
+ { // this is workaround for DB blob caching problems - nasty isn't it
+ DBWriteContactSettingByte(hContact, gpszICQProtoName, szSetting, 1);
+ DBDeleteContactSetting(hContact, gpszICQProtoName, szSetting);
+ }*/
+
+ cws.szModule=gpszICQProtoName;
+ cws.szSetting=szSetting;
+ cws.value.type=DBVT_BLOB;
+ cws.value.pbVal=(char*)val;
+ cws.value.cpbVal = cbVal;
+ return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws);
+}
+
+
+
+int ICQFreeVariant(DBVARIANT* dbv)
+{
+ return DBFreeVariant(dbv);
+}
+
+
+
+int IsICQContact(HANDLE hContact)
+{
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ return !strcmpnull(szProto, gpszICQProtoName);
+}
+
+
+
+HANDLE ICQFindFirstContact()
+{
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+
+ if (IsICQContact(hContact))
+ {
+ return hContact;
+ }
+ return ICQFindNextContact(hContact);
+}
+
+
+
+HANDLE ICQFindNextContact(HANDLE hContact)
+{
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+
+ while (hContact != NULL)
+ {
+ if (IsICQContact(hContact))
+ {
+ return hContact;
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ }
+ return hContact;
+}
diff --git a/icqj_mod/icq_db.h b/icqj_mod/icq_db.h new file mode 100644 index 0000000..706ee34 --- /dev/null +++ b/icqj_mod/icq_db.h @@ -0,0 +1,73 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_db.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_DB_H
+#define __ICQ_DB_H
+
+void InitDB();
+
+BYTE ICQGetContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bDef);
+WORD ICQGetContactSettingWord(HANDLE hContact, const char* szSetting, WORD wDef);
+DWORD ICQGetContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwDef);
+DWORD ICQGetContactSettingUIN(HANDLE hContact);
+int ICQGetContactSettingUID(HANDLE hContact, DWORD *pdwUin, uid_str* ppszUid);
+int ICQGetContactSetting(HANDLE hContact, const char* szSetting, DBVARIANT *dbv);
+char* ICQGetContactSettingUtf(HANDLE hContact, const char* szSetting, char* szDef);
+
+WORD ICQGetContactStatus(HANDLE hContact);
+
+int ICQGetContactStaticString(HANDLE hContact, const char* valueName, char* dest, int dest_len);
+
+int ICQDeleteContactSetting(HANDLE hContact, const char* szSetting);
+
+int ICQWriteContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bValue);
+int ICQWriteContactSettingWord(HANDLE hContact, const char* szSetting, WORD wValue);
+int ICQWriteContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwValue);
+int ICQWriteContactSettingString(HANDLE hContact, const char* szSetting, char* szValue);
+int ICQWriteContactSettingUtf(HANDLE hContact, const char* szSetting, char* szValue);
+
+int ICQWriteContactSettingBlob(HANDLE hContact,const char *szSetting,const char *val, const int cbVal);
+
+char* UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szDef);
+int UniWriteContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szValue);
+
+int ICQFreeVariant(DBVARIANT* dbv);
+
+int IsICQContact(HANDLE hContact);
+HANDLE ICQFindFirstContact();
+HANDLE ICQFindNextContact(HANDLE hContact);
+
+#endif /* __ICQ_DB_H */
diff --git a/icqj_mod/icq_direct.c b/icqj_mod/icq_direct.c new file mode 100644 index 0000000..1adce2a --- /dev/null +++ b/icqj_mod/icq_direct.c @@ -0,0 +1,1367 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_direct.c,v $
+// Revision : $Revision: 2955 $
+// Last change on : $Date: 2006-05-24 23:04:25 +0200 (Wed, 24 May 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+typedef struct directthreadstartinfo_t
+{
+ int type; // Only valid for outgoing connections
+ int incoming; // 1=incoming, 0=outgoing
+ HANDLE hConnection; // only valid for incoming connections, handle to the connection
+ HANDLE hContact; // Only valid for outgoing connections
+ void* pvExtra; // Only valid for outgoing connections
+} directthreadstartinfo;
+
+static unsigned char client_check_data[] = {
+ "As part of this software beta version Mirabilis is "
+ "granting a limited access to the ICQ network, "
+ "servers, directories, listings, information and databases (\""
+ "ICQ Services and Information\"). The "
+ "ICQ Service and Information may databases (\""
+ "ICQ Services and Information\"). The "
+ "ICQ Service and Information may\0"
+};
+
+static directconnect** directConnList = NULL;
+static int directConnSize = 0;
+static int directConnCount = 0;
+static int mutexesInited = 0;
+static CRITICAL_SECTION directConnListMutex;
+static CRITICAL_SECTION expectedFileRecvMutex;
+static int expectedFileRecvCount = 0;
+static filetransfer** expectedFileRecv = NULL;
+
+extern WORD wListenPort;
+extern DWORD dwLocalDirectConnCookie;
+
+static void handleDirectPacket(directconnect* dc, PBYTE buf, WORD wLen);
+static DWORD __stdcall icq_directThread(directthreadstartinfo* dtsi);
+static void sendPeerInit_v78(directconnect* dc);
+static int DecryptDirectPacket(directconnect* dc, PBYTE buf, WORD wLen);
+static void sendPeerInitAck(directconnect* dc);
+static void sendPeerMsgInit(directconnect* dc, DWORD dwSeq);
+static void sendPeerFileInit(directconnect* dc);
+
+
+void InitDirectConns(void)
+{
+ if (!mutexesInited)
+ {
+ mutexesInited = 1;
+ InitializeCriticalSection(&directConnListMutex);
+ InitializeCriticalSection(&expectedFileRecvMutex);
+ }
+ directConnCount = 0;
+ directConnSize = 0;
+}
+
+
+
+void UninitDirectConns(void)
+{
+ CloseContactDirectConns(NULL);
+
+ for(;;)
+ {
+ if (!directConnCount)
+ break;
+
+ Sleep(10); /* yeah, ugly */
+ }
+
+ DeleteCriticalSection(&directConnListMutex);
+ DeleteCriticalSection(&expectedFileRecvMutex);
+
+ SAFE_FREE((void**)&directConnList);
+}
+
+
+
+void CloseContactDirectConns(HANDLE hContact)
+{
+ int i;
+
+ EnterCriticalSection(&directConnListMutex);
+
+ for (i = 0; i < directConnCount; i++)
+ {
+ if (!hContact || directConnList[i]->hContact == hContact)
+ {
+ HANDLE hConnection = directConnList[i]->hConnection;
+ int sck = CallService(MS_NETLIB_GETSOCKET, (WPARAM)hConnection, 0);
+
+ directConnList[i]->hConnection = NULL; // do not allow reuse
+ if (sck!=INVALID_SOCKET) shutdown(sck, 2); // close gracefully
+ Netlib_CloseHandle(hConnection);
+ }
+ }
+
+ LeaveCriticalSection(&directConnListMutex);
+}
+
+
+
+static void ResizeDirectList(int nSize)
+{
+ if ((directConnSize < nSize) || ((directConnSize > nSize + 6) && nSize))
+ {
+ if (directConnSize < nSize)
+ directConnSize += 4;
+ else
+ directConnSize -= 4;
+
+ directConnList = (directconnect**)realloc(directConnList, sizeof(directconnect*) * directConnSize);
+ }
+}
+
+
+
+static void AddDirectConnToList(directconnect* dc)
+{
+ EnterCriticalSection(&directConnListMutex);
+
+ ResizeDirectList(directConnCount + 1);
+ directConnList[directConnCount] = dc;
+ directConnCount++;
+
+ LeaveCriticalSection(&directConnListMutex);
+}
+
+
+
+static RemoveDirectConnFromList(directconnect* dc)
+{
+ int i;
+
+ EnterCriticalSection(&directConnListMutex);
+
+ for (i = 0; i < directConnCount; i++)
+ {
+ if (directConnList[i] == dc)
+ {
+ directConnCount--;
+ directConnList[i] = directConnList[directConnCount];
+ ResizeDirectList(directConnCount);
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&directConnListMutex);
+}
+
+
+
+directconnect* FindFileTransferDC(filetransfer* ft)
+{
+ int i;
+ directconnect* dc = NULL;
+
+ EnterCriticalSection(&directConnListMutex);
+
+ for (i = 0; i < directConnCount; i++)
+ {
+ if (directConnList[i] && directConnList[i]->ft == ft)
+ {
+ dc = directConnList[i];
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&directConnListMutex);
+ return dc;
+}
+
+
+
+void AddExpectedFileRecv(filetransfer* ft)
+{
+ EnterCriticalSection(&expectedFileRecvMutex);
+
+ expectedFileRecv = (filetransfer** )realloc(expectedFileRecv, sizeof(filetransfer *) * (expectedFileRecvCount + 1));
+ expectedFileRecv[expectedFileRecvCount++] = ft;
+
+ LeaveCriticalSection(&expectedFileRecvMutex);
+}
+
+
+
+filetransfer *FindExpectedFileRecv(DWORD dwUin, DWORD dwTotalSize)
+{
+ int i;
+ filetransfer* pFt = NULL;
+
+
+ EnterCriticalSection(&expectedFileRecvMutex);
+
+ for (i = 0; i < expectedFileRecvCount; i++)
+ {
+ if (expectedFileRecv[i]->dwUin == dwUin && expectedFileRecv[i]->dwTotalSize == dwTotalSize)
+ {
+ pFt = expectedFileRecv[i];
+ expectedFileRecvCount--;
+ memmove(expectedFileRecv + i, expectedFileRecv + i + 1, sizeof(filetransfer*) * (expectedFileRecvCount - i));
+ expectedFileRecv = (filetransfer**)realloc(expectedFileRecv, sizeof(filetransfer*) * expectedFileRecvCount);
+
+ // Filereceive found, exit loop
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&expectedFileRecvMutex);
+
+ return pFt;
+}
+
+
+
+int sendDirectPacket(directconnect* dc, icq_packet* pkt)
+{
+ int nResult;
+
+ nResult = Netlib_Send(dc->hConnection, (const char*)pkt->pData, pkt->wLen + 2, 0);
+
+ if (nResult == SOCKET_ERROR)
+ {
+ NetLog_Direct("Direct %p socket error: %d, closing", dc->hConnection, GetLastError());
+ CloseDirectConnection(dc);
+ }
+
+ SAFE_FREE(&pkt->pData);
+
+ return nResult;
+}
+
+
+
+directthreadstartinfo* CreateDTSI(HANDLE hContact, HANDLE hConnection, int type)
+{
+ directthreadstartinfo* dtsi;
+
+ dtsi = (directthreadstartinfo*)SAFE_MALLOC(sizeof(directthreadstartinfo));
+ dtsi->hContact = hContact;
+ dtsi->hConnection = hConnection;
+ if (type == -1)
+ {
+ dtsi->incoming = 1;
+ }
+ else
+ {
+ dtsi->type = type;
+ }
+
+ return dtsi;
+}
+
+
+
+// Check if we have an open and initialized DC with type
+// 'type' to the specified contact
+BOOL IsDirectConnectionOpen(HANDLE hContact, int type)
+{
+ int i;
+ BOOL bIsOpen = FALSE, bIsCreated = FALSE;
+
+
+ EnterCriticalSection(&directConnListMutex);
+
+ for (i = 0; i < directConnCount; i++)
+ {
+ if (directConnList[i] && (directConnList[i]->type == type))
+ {
+ if (directConnList[i]->hContact == hContact)
+ if (directConnList[i]->initialised)
+ {
+ // Connection is OK
+ bIsOpen = TRUE;
+ // we are going to use the conn, so prevent timeout
+ directConnList[i]->packetPending = 1;
+ break;
+ }
+ else
+ bIsCreated = TRUE; // we found pending connection
+ }
+ }
+
+ LeaveCriticalSection(&directConnListMutex);
+
+ if (!bIsCreated && !bIsOpen && type == DIRECTCONN_STANDARD && gbDCMsgEnabled == 2)
+ { // do not try to open DC to offline contact
+ if (ICQGetContactStatus(hContact) == ID_STATUS_OFFLINE) return FALSE;
+
+ // Create a new connection
+ OpenDirectConnection(hContact, DIRECTCONN_STANDARD, NULL);
+ }
+
+ return bIsOpen;
+}
+
+
+
+// This function is called from the Netlib when someone is connecting to
+// one of our incomming DC ports
+void icq_newConnectionReceived(HANDLE hNewConnection, DWORD dwRemoteIP)
+{
+ pthread_t tid;
+
+ // Start a new thread for the incomming connection
+ tid.hThread = (HANDLE)forkthreadex(NULL, 0, icq_directThread, CreateDTSI(NULL, hNewConnection, -1), 0, &tid.dwThreadId);
+ CloseHandle(tid.hThread);
+}
+
+
+
+// Opens direct connection of specified type to specified contact
+void OpenDirectConnection(HANDLE hContact, int type, void* pvExtra)
+{
+ pthread_t tid;
+ directthreadstartinfo* dtsi;
+
+ // Create a new connection
+ dtsi = CreateDTSI(hContact, NULL, type);
+ dtsi->pvExtra = pvExtra;
+
+ tid.hThread = (HANDLE)forkthreadex(NULL, 0, icq_directThread, dtsi, 0, &tid.dwThreadId);
+ CloseHandle(tid.hThread);
+}
+
+
+
+// Safely close NetLib connection - do not corrupt direct connection list
+void CloseDirectConnection(directconnect *dc)
+{
+ EnterCriticalSection(&directConnListMutex);
+
+ if (dc->hConnection)
+ {
+ Netlib_CloseHandle(dc->hConnection);
+#ifdef _DEBUG
+ NetLog_Direct("Direct conn closed (%p)", dc->hConnection);
+#endif
+ dc->hConnection = NULL;
+ }
+
+ LeaveCriticalSection(&directConnListMutex);
+}
+
+
+
+// This should be called only if connection already exists
+int SendDirectMessage(HANDLE hContact, icq_packet *pkt)
+{
+ int i;
+
+ EnterCriticalSection(&directConnListMutex);
+
+ for (i = 0; i < directConnCount; i++)
+ {
+ if (directConnList[i] == NULL)
+ continue;
+
+ if (directConnList[i]->hContact == hContact)
+ {
+ if (directConnList[i]->initialised)
+ {
+ // This connection can be reused, send packet and exit
+ NetLog_Direct("Sending direct message");
+
+ if (pkt->pData[2] == 2)
+ EncryptDirectPacket(directConnList[i], pkt);
+
+ sendDirectPacket(directConnList[i], pkt);
+ directConnList[i]->packetPending = 0; // packet done
+
+ LeaveCriticalSection(&directConnListMutex);
+
+ return TRUE; // Success
+ }
+ break; // connection not ready, use server instead
+ }
+ }
+
+ LeaveCriticalSection(&directConnListMutex);
+
+ return FALSE; // connection pending, we failed, use server instead
+}
+
+
+// Called from icq_newConnectionReceived when a new incomming dc is done
+// Called from OpenDirectConnection when a new outgoing dc is done
+// Called from SendDirectMessage when a new outgoing dc is done
+static DWORD __stdcall icq_directThread(directthreadstartinfo *dtsi)
+{
+ directconnect dc = {0};
+ NETLIBPACKETRECVER packetRecv={0};
+ HANDLE hPacketRecver;
+ BOOL bFirstPacket = TRUE;
+
+
+ srand(time(NULL));
+ AddDirectConnToList(&dc);
+
+ // Initialize DC struct
+ dc.hContact = dtsi->hContact;
+ dc.dwThreadId = GetCurrentThreadId();
+ dc.incoming = dtsi->incoming;
+ dc.hConnection = dtsi->hConnection;
+ dc.ft = NULL;
+
+ if (!dc.incoming)
+ {
+ dc.type = dtsi->type;
+ dc.dwRemoteExternalIP = ICQGetContactSettingDword(dtsi->hContact, "IP", 0);
+ dc.dwRemoteInternalIP = ICQGetContactSettingDword(dtsi->hContact, "RealIP", 0);
+ dc.dwRemotePort = ICQGetContactSettingWord(dtsi->hContact, "UserPort", 0);
+ dc.dwRemoteUin = ICQGetContactSettingUIN(dtsi->hContact);
+ dc.wVersion = ICQGetContactSettingWord(dtsi->hContact, "Version", 0);
+ dc.dwConnCookie = ICQGetContactSettingDword(dtsi->hContact, "DirectCookie", 0);
+
+ if (!dc.wVersion)
+ dc.wVersion = ICQGetContactSettingWord(dtsi->hContact, "OldVersion", 0);
+
+ if (!dc.dwRemoteExternalIP && !dc.dwRemoteInternalIP)
+ { // we do not have any ip, do not try to connect
+ RemoveDirectConnFromList(&dc);
+ SAFE_FREE(&dtsi);
+ return 0;
+ }
+
+ dc.dwReqId = 0;
+
+ if (dc.type == DIRECTCONN_STANDARD)
+ {
+ // do nothing - some specific init for msg sessions
+ }
+ else if (dc.type == DIRECTCONN_FILE)
+ {
+ dc.ft = (filetransfer*)dtsi->pvExtra;
+ dc.dwRemotePort = dc.ft->dwRemotePort;
+ }
+ else if (dc.type == DIRECTCONN_REVERSE)
+ {
+ dc.dwReqId = (DWORD)dtsi->pvExtra;
+ }
+ }
+ else
+ {
+ dc.type = DIRECTCONN_STANDARD;
+ }
+
+ SAFE_FREE(&dtsi);
+
+ // Load local IP information
+ dc.dwLocalExternalIP = ICQGetContactSettingDword(NULL, "IP", 0);
+ dc.dwLocalInternalIP = ICQGetContactSettingDword(NULL, "RealIP", 0);
+
+ // Create outgoing DC
+ if (!dc.incoming)
+ {
+ NETLIBOPENCONNECTION nloc = {0};
+ IN_ADDR addr;
+
+
+ nloc.cbSize = sizeof(nloc);
+ nloc.flags = 0;
+ if (dc.dwRemoteExternalIP == dc.dwLocalExternalIP)
+ addr.S_un.S_addr = htonl(dc.dwRemoteInternalIP);
+ else
+ addr.S_un.S_addr = htonl(dc.dwRemoteExternalIP);
+
+ if (!addr.S_un.S_addr)
+ { // IP to connect to is empty, go away
+ RemoveDirectConnFromList(&dc);
+ return 0;
+ }
+ nloc.szHost = inet_ntoa(addr);
+ nloc.wPort = (WORD)dc.dwRemotePort;
+ NetLog_Direct("%sConnecting to %s:%u", dc.type==DIRECTCONN_REVERSE?"Reverse ":"", nloc.szHost, nloc.wPort);
+
+ dc.hConnection = NetLib_OpenConnection(ghDirectNetlibUser, &nloc);
+ if (dc.hConnection == NULL)
+ {
+ if (dc.type != DIRECTCONN_REVERSE)
+ { // try reverse connect
+ reverse_cookie *pCookie = (reverse_cookie*)SAFE_MALLOC(sizeof(reverse_cookie));
+ DWORD dwCookie;
+
+ NetLog_Direct("connect() failed (%d), trying reverse.", GetLastError());
+
+ if (pCookie)
+ { // ini cookie
+ pCookie->pMessage.bMessageType = MTYPE_REVERSE_REQUEST;
+ pCookie->pMessage.dwMsgID1 = time(NULL);
+ pCookie->pMessage.dwMsgID2 = RandRange(0, 0x00FF);
+ pCookie->hContact = dc.hContact;
+ pCookie->dwUin = dc.dwRemoteUin;
+ pCookie->type = dc.type;
+ pCookie->ft = dc.ft;
+ dwCookie = AllocateCookie(CKT_REVERSEDIRECT, 0, dc.dwRemoteUin, pCookie);
+ icq_sendReverseReq(&dc, dwCookie, (message_cookie_data*)pCookie);
+ RemoveDirectConnFromList(&dc);
+
+ return 0;
+ }
+ else
+ NetLog_Direct("Reverse failed (%s)", "malloc failed");
+ }
+ else // we failed reverse connection
+ {
+ reverse_cookie *pCookie;
+ DWORD dwUin;
+
+ if (FindCookie(dc.dwReqId, &dwUin, &pCookie))
+ { // release cookie
+ icq_sendReverseFailed(&dc, pCookie->pMessage.dwMsgID1, pCookie->pMessage.dwMsgID2, dc.dwReqId);
+ ReleaseCookie(dc.dwReqId);
+ }
+ }
+ NetLog_Direct("connect() failed (%d)", GetLastError());
+ RemoveDirectConnFromList(&dc);
+ if (dc.type == DIRECTCONN_FILE)
+ ICQBroadcastAck(dc.ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, dc.ft, 0);
+
+ return 0;
+ }
+
+ if (dc.type == DIRECTCONN_FILE)
+ dc.ft->hConnection = dc.hConnection;
+
+ if (dc.wVersion > 6)
+ {
+ sendPeerInit_v78(&dc);
+ }
+ else
+ {
+ NetLog_Direct("Error: Unsupported direct protocol: %d, closing.", dc.wVersion);
+ CloseDirectConnection(&dc);
+ RemoveDirectConnFromList(&dc);
+
+ return 0;
+ }
+ }
+
+ hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)dc.hConnection, 8192);
+ packetRecv.cbSize = sizeof(packetRecv);
+ packetRecv.bytesUsed = 0;
+
+ // Packet receiving loop
+
+ while (dc.hConnection)
+ {
+ int recvResult;
+
+ packetRecv.dwTimeout = dc.wantIdleTime ? 0 : 600000;
+
+ recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPacketRecver, (LPARAM)&packetRecv);
+ if (recvResult == 0)
+ {
+ NetLog_Direct("Clean closure of direct socket (%p)", dc.hConnection);
+ break;
+ }
+
+ if (recvResult == SOCKET_ERROR)
+ {
+ if (GetLastError() == ERROR_TIMEOUT)
+ { // TODO: this will not work on some systems
+ if (dc.wantIdleTime)
+ {
+ switch (dc.type)
+ {
+ case DIRECTCONN_FILE:
+ handleFileTransferIdle(&dc);
+ break;
+ }
+ }
+ else if (dc.packetPending)
+ { // do we expect packet soon?
+ NetLog_Direct("Keeping connection, packet pending.");
+ }
+ else
+ {
+ NetLog_Direct("Connection inactive for 10 minutes, closing.");
+ break;
+ }
+ }
+ else
+ {
+ NetLog_Direct("Abortive closure of direct socket (%p) (%d)", dc.hConnection, GetLastError());
+ break;
+ }
+ }
+
+ if (dc.type == DIRECTCONN_CLOSING)
+ packetRecv.bytesUsed = packetRecv.bytesAvailable;
+ else
+ {
+ int i;
+
+ for (i = 0; i + 2 <= packetRecv.bytesAvailable;)
+ {
+ WORD wLen = *(WORD*)(packetRecv.buffer + i);
+
+ if (bFirstPacket)
+ {
+ if (wLen > 64)
+ { // roughly check first packet size
+ NetLog_Direct("Error: Overflowed packet, closing connection.");
+ CloseDirectConnection(&dc);
+ break;
+ }
+ bFirstPacket = FALSE;
+ }
+
+ if (wLen + 2 + i > packetRecv.bytesAvailable)
+ break;
+
+ if (dc.type == DIRECTCONN_STANDARD && wLen && packetRecv.buffer[i + 2] == 2)
+ {
+ if (!DecryptDirectPacket(&dc, packetRecv.buffer + i + 3, (WORD)(wLen - 1)))
+ {
+ NetLog_Direct("Error: Corrupted packet encryption, ignoring packet");
+ i += wLen + 2;
+ continue;
+ }
+ }
+#ifdef _DEBUG
+ NetLog_Direct("New direct package");
+#endif
+ if (dc.type == DIRECTCONN_FILE && dc.initialised)
+ handleFileTransferPacket(&dc, packetRecv.buffer + i + 2, wLen);
+ else
+ handleDirectPacket(&dc, packetRecv.buffer + i + 2, wLen);
+
+ i += wLen + 2;
+ }
+ packetRecv.bytesUsed = i;
+ }
+ }
+
+ // End of packet receiving loop
+
+ Netlib_CloseHandle(hPacketRecver);
+ CloseDirectConnection(&dc);
+
+ if (dc.ft)
+ {
+ if (dc.ft->fileId != -1)
+ {
+ _close(dc.ft->fileId);
+ ICQBroadcastAck(dc.ft->hContact, ACKTYPE_FILE, dc.ft->dwBytesDone==dc.ft->dwTotalSize ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, dc.ft, 0);
+ }
+ else if (dc.ft->hConnection)
+ ICQBroadcastAck(dc.ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, dc.ft, 0);
+
+ SAFE_FREE(&dc.ft->szFilename);
+ SAFE_FREE(&dc.ft->szDescription);
+ SAFE_FREE(&dc.ft->szSavePath);
+ SAFE_FREE(&dc.ft->szThisFile);
+ SAFE_FREE(&dc.ft->szThisSubdir);
+ if (dc.ft->files)
+ {
+ int i;
+
+ for (i = 0; i < (int)dc.ft->dwFileCount; i++)
+ SAFE_FREE(&dc.ft->files[i]);
+ SAFE_FREE((char**)&dc.ft->files);
+ }
+ SAFE_FREE(&dc.ft);
+ _chdir("\\"); /* so we don't leave a subdir handle open so it can't be deleted */
+ }
+
+ RemoveDirectConnFromList(&dc);
+
+ return 0;
+}
+
+
+
+static void handleDirectPacket(directconnect* dc, PBYTE buf, WORD wLen)
+{
+ if (wLen < 1)
+ return;
+
+ switch (buf[0])
+ {
+ case PEER_FILE_INIT: // first packet of a file transfer
+#ifdef _DEBUG
+ NetLog_Direct("Received PEER_FILE_INIT from %u",dc->dwRemoteUin);
+#endif
+ if (dc->handshake)
+ handleFileTransferPacket(dc, buf, wLen);
+ else
+ NetLog_Direct("Received %s on uninitialised DC, ignoring.", "PEER_FILE_INIT");
+
+ break;
+
+ case PEER_INIT_ACK: // This is sent as a response to our PEER_INIT packet
+ if (wLen != 4)
+ {
+ NetLog_Direct("Error: Received malformed PEER_INITACK from %u", dc->dwRemoteUin);
+ break;
+ }
+#ifdef _DEBUG
+ NetLog_Direct("Received PEER_INITACK from %u on %s DC", dc->dwRemoteUin, dc->incoming?"incoming":"outgoing");
+#endif
+ if (dc->incoming) dc->handshake = 1;
+
+ if (dc->incoming && dc->type == DIRECTCONN_REVERSE)
+ {
+ reverse_cookie* pCookie;
+ DWORD dwCookieUin;
+
+ dc->incoming = 0;
+
+ if (FindCookie(dc->dwReqId, &dwCookieUin, &pCookie) && pCookie)
+ { // valid reverse DC, check and init session
+ FreeCookie(dc->dwReqId);
+ if (pCookie->dwUin == dc->dwRemoteUin)
+ { // valid connection
+ dc->type = pCookie->type;
+ dc->ft = pCookie->ft;
+ dc->hContact = pCookie->hContact;
+ if (dc->type == DIRECTCONN_STANDARD)
+ { // init message session
+ sendPeerMsgInit(dc, 0);
+ }
+ else if (dc->type == DIRECTCONN_FILE)
+ { // init file session
+ sendPeerFileInit(dc);
+ dc->initialised = 1;
+ }
+ SAFE_FREE(&pCookie);
+ break;
+ }
+ else
+ {
+ SAFE_FREE(&pCookie);
+ NetLog_Direct("Error: Invalid connection (UINs does not match).");
+ CloseDirectConnection(dc);
+ return;
+ }
+ }
+ else
+ {
+ NetLog_Direct("Error: Received unexpected reverse DC, closing.");
+ CloseDirectConnection(dc);
+ return;
+ }
+ }
+ break;
+
+ case PEER_INIT: /* connect packet */
+#ifdef _DEBUG
+ NetLog_Direct("Received PEER_INIT");
+#endif
+ buf++;
+
+ if (wLen < 3)
+ return;
+
+ unpackLEWord(&buf, &dc->wVersion);
+
+ if (dc->wVersion > 6)
+ { // we support only versions 7 and up
+ WORD wSecondLen;
+ DWORD dwUin;
+ DWORD dwPort;
+ DWORD dwCookie;
+ HANDLE hContact;
+
+ if (wLen != 0x30)
+ {
+ NetLog_Direct("Error: Received malformed PEER_INIT");
+ return;
+ }
+
+ unpackLEWord(&buf, &wSecondLen);
+ if (wSecondLen && wSecondLen != 0x2b)
+ { // OMG? GnomeICU sets this to zero
+ NetLog_Direct("Error: Received malformed PEER_INIT");
+ return;
+ }
+
+ unpackLEDWord(&buf, &dwUin);
+ if (dwUin != dwLocalUIN)
+ {
+ NetLog_Direct("Error: Received PEER_INIT targeted to %u", dwUin);
+ CloseDirectConnection(dc);
+ return;
+ }
+
+ buf += 2; /* 00 00 */
+ unpackLEDWord(&buf, &dc->dwRemotePort);
+ unpackLEDWord(&buf, &dc->dwRemoteUin);
+ unpackDWord(&buf, &dc->dwRemoteExternalIP);
+ unpackDWord(&buf, &dc->dwRemoteInternalIP);
+ buf ++; /* 04: accept direct connections */
+ unpackLEDWord(&buf, &dwPort);
+ if (dwPort != dc->dwRemotePort)
+ {
+ NetLog_Direct("Error: Received malformed PEER_INIT (invalid port)");
+ return;
+ }
+ unpackLEDWord(&buf, &dwCookie);
+
+ buf += 8; // Unknown stuff
+ unpackLEDWord(&buf, &dc->dwReqId);
+
+ if (dc->dwRemoteUin || !dc->dwReqId)
+ { // OMG! Licq sends on reverse connection empty uin
+ hContact = HContactFromUIN(dc->dwRemoteUin, NULL);
+ if (hContact == INVALID_HANDLE_VALUE)
+ {
+ NetLog_Direct("Error: Received PEER_INIT from %u not on my list", dwUin);
+ CloseDirectConnection(dc);
+ return; /* don't allow direct connection with people not on my clist */
+ }
+
+ if (dwCookie != ICQGetContactSettingDword(hContact, "DirectCookie", 0))
+ {
+ NetLog_Direct("Error: Received PEER_INIT with broken cookie");
+ CloseDirectConnection(dc);
+ return;
+ }
+ }
+
+ if (dc->incoming && dc->dwReqId)
+ { // this is reverse connection
+ dc->type = DIRECTCONN_REVERSE;
+ if (!dc->dwRemoteUin)
+ { // we need to load cookie (licq)
+ reverse_cookie* pCookie;
+ DWORD dwCookieUin;
+
+ if (FindCookie(dc->dwReqId, &dwCookieUin, &pCookie) && pCookie)
+ { // valid reverse DC, check and init session
+ dc->dwRemoteUin = pCookie->dwUin;
+ dc->hContact = pCookie->hContact;
+ }
+ else
+ {
+ NetLog_Direct("Error: Received unexpected reverse DC, closing.");
+ CloseDirectConnection(dc);
+ return;
+ }
+ }
+ }
+
+ sendPeerInitAck(dc); // ack good PEER_INIT packet
+
+ if (dc->incoming)
+ { // store good IP info
+ dc->hContact = hContact;
+ dc->dwConnCookie = dwCookie;
+ ICQWriteContactSettingDword(dc->hContact, "IP", dc->dwRemoteExternalIP);
+ ICQWriteContactSettingDword(dc->hContact, "RealIP", dc->dwRemoteInternalIP);
+ sendPeerInit_v78(dc); // reply with our PEER_INIT
+ }
+ else // outgoing
+ {
+ dc->handshake = 1;
+
+ if (dc->type == DIRECTCONN_REVERSE)
+ {
+ dc->incoming = 1; // this is incoming reverse connection
+ dc->type = DIRECTCONN_STANDARD; // we still do not know type
+ }
+ else if (dc->type == DIRECTCONN_STANDARD)
+ { // send PEER_MSGINIT
+ sendPeerMsgInit(dc, 0);
+ }
+ else if (dc->type == DIRECTCONN_FILE)
+ {
+ sendPeerFileInit(dc);
+ dc->initialised = 1;
+ }
+ }
+ }
+ else
+ {
+ NetLog_Direct("Unsupported direct protocol: %d, closing connection", dc->wVersion);
+ CloseDirectConnection(dc);
+ }
+ break;
+
+ case PEER_MSG: /* messaging packets */
+#ifdef _DEBUG
+ NetLog_Direct("Received PEER_MSG from %u", dc->dwRemoteUin);
+#endif
+ if (dc->initialised)
+ handleDirectMessage(dc, buf + 1, (WORD)(wLen - 1));
+ else
+ NetLog_Direct("Received %s on uninitialised DC, ignoring.", "PEER_MSG");
+
+ break;
+
+ case PEER_MSG_INIT: /* init message connection */
+ { // it is sent by both contains GUID of message channel
+ DWORD q1,q2,q3,q4;
+
+ if (!gbDCMsgEnabled)
+ { // DC messaging disabled, close connection
+ NetLog_Direct("Messaging DC requested, denied");
+ CloseDirectConnection(dc);
+ break;
+ }
+
+#ifdef _DEBUG
+ NetLog_Direct("Received PEER_MSG_INIT from %u",dc->dwRemoteUin);
+#endif
+ buf++;
+ if (wLen != 0x21)
+ break;
+
+ if (!dc->handshake)
+ {
+ NetLog_Direct("Received %s on unitialised DC, ignoring.", "PEER_MSG_INIT");
+ break;
+ }
+
+ buf += 4; /* always 10 */
+ buf += 4; /* some id */
+ buf += 4; /* sequence - always 0 on incoming */
+ unpackDWord(&buf, &q1); // session type GUID
+ unpackDWord(&buf, &q2);
+ if (!dc->incoming)
+ { // skip marker on sequence 1
+ buf += 4;
+ }
+ unpackDWord(&buf, &q3);
+ unpackDWord(&buf, &q4);
+ if (!CompareGUIDs(q1,q2,q3,q4,PSIG_MESSAGE))
+ { // This is not for normal messages, useless so kill.
+ if (CompareGUIDs(q1,q2,q3,q4,PSIG_STATUS_PLUGIN))
+ {
+ NetLog_Direct("Status Manager Plugin connections not supported, closing.");
+ }
+ else if (CompareGUIDs(q1,q2,q3,q4,PSIG_INFO_PLUGIN))
+ {
+ NetLog_Direct("Info Manager Plugin connection not supported, closing.");
+ }
+ else
+ {
+ NetLog_Direct("Unknown connection type init, closing.");
+ }
+ CloseDirectConnection(dc);
+ break;
+ }
+
+ if (dc->incoming)
+ { // reply with our PEER_MSG_INIT
+ sendPeerMsgInit(dc, 1);
+ }
+ else
+ { // connection initialized, ready to send message packet
+ }
+ NetLog_Direct("Direct message session ready.");
+ dc->initialised = 1;
+ }
+ break;
+
+ default:
+ NetLog_Direct("Unknown direct packet ignored.");
+ break;
+ }
+}
+
+
+
+void EncryptDirectPacket(directconnect* dc, icq_packet* p)
+{
+ unsigned long B1;
+ unsigned long M1;
+ unsigned long check;
+ unsigned int i;
+ unsigned char X1;
+ unsigned char X2;
+ unsigned char X3;
+ unsigned char* buf = (unsigned char*)(p->pData + 3);
+ unsigned char bak[6];
+ unsigned long offset;
+ unsigned long key;
+ unsigned long hex;
+ unsigned long size = p->wLen - 1;
+
+
+ if (dc->wVersion < 4)
+ return; // no encryption necessary.
+
+
+ switch (dc->wVersion)
+ {
+ case 4:
+ case 5:
+ offset = 6;
+ break;
+
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ default:
+ offset = 0;
+ }
+
+ // calculate verification data
+ M1 = (rand() % ((size < 255 ? size : 255)-10))+10;
+ X1 = buf[M1] ^ 0xFF;
+ X2 = rand() % 220;
+ X3 = client_check_data[X2] ^ 0xFF;
+ if (offset)
+ {
+ memcpy(bak, buf, sizeof(bak));
+ B1 = (buf[offset+4]<<24) | (buf[offset+6]<<16) | (buf[2]<<8) | buf[0];
+ }
+ else
+ {
+ B1 = (buf[4]<<24) | (buf[6]<<16) | (buf[4]<<8) | (buf[6]);
+ }
+
+ // calculate checkcode
+ check = (M1<<24) | (X1<<16) | (X2<<8) | X3;
+ check ^= B1;
+
+ // main XOR key
+ key = 0x67657268 * size + check;
+
+ // XORing the actual data
+ for (i = 0; i<(size+3)/4; i+=4)
+ {
+ hex = key + client_check_data[i&0xFF];
+ *(PDWORD)(buf + i) ^= hex;
+ }
+
+ // in TCPv4 are the first 6 bytes unencrypted
+ // so restore them
+ if (offset)
+ memcpy(buf, bak, sizeof(bak));
+
+ // storing the checkcode
+ *(PDWORD)(buf + offset) = check;
+}
+
+
+
+static int DecryptDirectPacket(directconnect* dc, PBYTE buf, WORD wLen)
+{
+ unsigned long hex;
+ unsigned long key;
+ unsigned long B1;
+ unsigned long M1;
+ unsigned long check;
+ unsigned int i;
+ unsigned char X1;
+ unsigned char X2;
+ unsigned char X3;
+ unsigned char bak[6];
+ unsigned long size = wLen;
+ unsigned long offset;
+
+
+ if (dc->wVersion < 4)
+ return 1; // no decryption necessary.
+
+ if (size < 4)
+ return 1;
+
+ if (dc->wVersion < 4)
+ return 1;
+
+ if (dc->wVersion == 4 || dc->wVersion == 5)
+ {
+ offset = 6;
+ }
+ else
+ {
+ offset = 0;
+ }
+
+ // backup the first 6 bytes
+ if (offset)
+ memcpy(bak, buf, sizeof(bak));
+
+ // retrieve checkcode
+ check = *(PDWORD)(buf+offset);
+
+ // main XOR key
+ key = 0x67657268 * size + check;
+
+ for (i=4; i<(size+3)/4; i+=4)
+ {
+ hex = key + client_check_data[i&0xFF];
+ *(PDWORD)(buf + i) ^= hex;
+ }
+
+ // retrive validate data
+ if (offset)
+ {
+ // in TCPv4 are the first 6 bytes unencrypted
+ // so restore them
+ memcpy(buf, bak, sizeof(bak));
+ B1 = (buf[offset+4]<<24) | (buf[offset+6]<<16) | (buf[2]<<8) | buf[0];
+ }
+ else
+ {
+ B1 = (buf[4]<<24) | (buf[6]<<16) | (buf[4]<<8) | (buf[6]<<0);
+ }
+
+ // special decryption
+ B1 ^= check;
+
+ // validate packet
+ M1 = (B1>>24) & 0xFF;
+ if (M1 < 10 || M1 >= size)
+ {
+ return 0;
+ }
+
+ X1 = buf[M1] ^ 0xFF;
+ if(((B1 >> 16) & 0xFF) != X1)
+ {
+ return 0;
+ }
+
+ X2 = (BYTE)((B1 >> 8) & 0xFF);
+ if (X2 < 220)
+ {
+ X3 = client_check_data[X2] ^ 0xFF;
+ if ((B1 & 0xFF) != X3)
+ {
+ return 0;
+ }
+ }
+#ifdef _DEBUG
+ { // log decrypted data
+ char szTitleLine[128];
+ char* szBuf;
+ int titleLineLen;
+ int line;
+ int col;
+ int colsInLine;
+ char* pszBuf;
+
+
+ titleLineLen = null_snprintf(szTitleLine, 128, "DECRYPTED\n");
+ szBuf = (char*)_alloca(titleLineLen + ((wLen+15)>>4) * 76 + 1);
+ CopyMemory(szBuf, szTitleLine, titleLineLen);
+ pszBuf = szBuf + titleLineLen;
+
+ for (line = 0; ; line += 16)
+ {
+ colsInLine = min(16, wLen - line);
+ pszBuf += wsprintf(pszBuf, "%08X: ", line);
+
+ for (col = 0; col<colsInLine; col++)
+ pszBuf += wsprintf(pszBuf, "%02X%c", buf[line+col], (col&3)==3 && col!=15?'-':' ');
+
+ for (; col<16; col++)
+ {
+ lstrcpy(pszBuf," ");
+ pszBuf+=3;
+ }
+
+ *pszBuf++ = ' ';
+ for (col = 0; col<colsInLine; col++)
+ *pszBuf++ = buf[line+col]<' ' ? '.' : (char)buf[line+col];
+ if(wLen-line<=16) break;
+ *pszBuf++='\n';
+ }
+ *pszBuf='\0';
+
+ CallService(MS_NETLIB_LOG,(WPARAM)ghDirectNetlibUser, (LPARAM)szBuf);
+ }
+#endif
+
+ return 1;
+}
+
+
+
+/*
+void startHandshake_v6(const char *szHost, DWORD dwPort, DWORD dwUin)
+{
+ icq_packet packet;
+ DWORD dwSessionId;
+
+ dwSessionId = rand();
+
+ directPacketInit(&packet, 44);
+ packByte(&packet, 0xff); // Ident
+ packLEDWord(&packet, ICQ_VERSION); // Our version
+ packLEDWord(&packet, dwUin);
+
+ packWord(&packet, 0);
+
+ packLEDWord(&packet, dwListenPort);
+ packLEDWord(&packet, dwLocalUin);
+ packDWord(&packet, dwExternalIP);
+ packDWord(&packet, dwInteralIP);
+ packByte(&packet, nTCPFlag);
+ packLEDWord(&packet, dwSessionId);
+ packLEDWord(&packet, dwListenPort);
+ packLEDWord(&packet, dwSessionId);
+ packLEDWord(&packet, WEBFRONTPORT);
+ packLEDWord(&packet, 0x00000003);
+}
+*/
+
+
+
+// Sends a PEER_INIT packet through a DC
+// -----------------------------------------------------------------------
+// This packet is sent during direct connection initialization between two
+// ICQ clients. It is sent by the originator of the connection to start
+// the handshake and by the receiver directly after it has sent the
+// PEER_ACK packet as a reply to the originator's PEER_INIT. The values
+// after the COOKIE field have been added for v7.
+static void sendPeerInit_v78(directconnect* dc)
+{
+ icq_packet packet;
+
+ directPacketInit(&packet, 48); // Full packet length
+ packByte(&packet, PEER_INIT); // Command
+ packLEWord(&packet, dc->wVersion); // Version
+ packLEWord(&packet, 43); // Data length
+ packLEDWord(&packet, dc->dwRemoteUin); // UIN of remote user
+ packWord(&packet, 0); // Unknown
+ packLEDWord(&packet, wListenPort); // Our port
+ packLEDWord(&packet, dwLocalUIN); // Our UIN
+ packDWord(&packet, dc->dwLocalExternalIP); // Our external IP
+ packDWord(&packet, dc->dwLocalInternalIP); // Our internal IP
+ packByte(&packet, DC_TYPE); // TCP connection flags
+ packLEDWord(&packet, wListenPort); // Our port
+ packLEDWord(&packet, dc->dwConnCookie); // DC cookie
+ packLEDWord(&packet, WEBFRONTPORT); // Unknown
+ packLEDWord(&packet, CLIENTFEATURES); // Unknown
+ if (dc->type == DIRECTCONN_REVERSE)
+ packLEDWord(&packet, dc->dwReqId); // Reverse Request Cookie
+ else
+ packDWord(&packet, 0); // Unknown
+
+ sendDirectPacket(dc, &packet);
+#ifdef _DEBUG
+ NetLog_Direct("Sent PEER_INIT to %u on %s DC", dc->dwRemoteUin, dc->incoming?"incoming":"outgoing");
+#endif
+}
+
+
+
+// Sends a PEER_INIT packet through a DC
+// -----------------------------------------------------------------------
+// This is sent to acknowledge a PEER_INIT packet.
+static void sendPeerInitAck(directconnect* dc)
+{
+ icq_packet packet;
+
+ directPacketInit(&packet, 4); // Packet length
+ packLEDWord(&packet, PEER_INIT_ACK); //
+
+ sendDirectPacket(dc, &packet);
+#ifdef _DEBUG
+ NetLog_Direct("Sent PEER_INIT_ACK to %u on %s DC", dc->dwRemoteUin, dc->incoming?"incoming":"outgoing");
+#endif
+}
+
+
+
+// Sends a PEER_MSG_INIT packet through a DC
+// -----------------------------------------------------------------------
+// This packet starts message session.
+static void sendPeerMsgInit(directconnect* dc, DWORD dwSeq)
+{
+ icq_packet packet;
+
+ directPacketInit(&packet, 33);
+ packByte(&packet, PEER_MSG_INIT);
+ packLEDWord(&packet, 10); // unknown
+ packLEDWord(&packet, 1); // message connection
+ packLEDWord(&packet, dwSeq); // sequence is 0,1
+ if (!dwSeq)
+ {
+ packGUID(&packet, PSIG_MESSAGE); // message type GUID
+ packLEWord(&packet, 1); // delimiter
+ packLEWord(&packet, 4);
+ }
+ else
+ {
+ packDWord(&packet, 0); // first part of Message GUID
+ packDWord(&packet, 0);
+ packLEWord(&packet, 1); // delimiter
+ packLEWord(&packet, 4);
+ packDWord(&packet, 0); // second part of Message GUID
+ packDWord(&packet, 0);
+ }
+ sendDirectPacket(dc, &packet);
+#ifdef _DEBUG
+ NetLog_Direct("Sent PEER_MSG_INIT to %u on %s DC", dc->dwRemoteUin, dc->incoming?"incoming":"outgoing");
+#endif
+}
+
+
+
+// Sends a PEER_FILE_INIT packet through a DC
+// -----------------------------------------------------------------------
+// This packet configures file-transfer session.
+static void sendPeerFileInit(directconnect* dc)
+{
+ icq_packet packet;
+ DBVARIANT dbv;
+ char* szNick;
+ int nNickLen;
+
+ dbv.type = DBVT_DELETED;
+ if (ICQGetContactSetting(NULL, "Nick", &dbv))
+ szNick = "";
+ else
+ szNick = dbv.pszVal;
+ nNickLen = strlennull(szNick);
+
+ directPacketInit(&packet, (WORD)(20 + nNickLen));
+ packByte(&packet, PEER_FILE_INIT); /* packet type */
+ packLEDWord(&packet, 0); /* unknown */
+ packLEDWord(&packet, dc->ft->dwFileCount);
+ packLEDWord(&packet, dc->ft->dwTotalSize);
+ packLEDWord(&packet, dc->ft->dwTransferSpeed);
+ packLEWord(&packet, (WORD)(nNickLen + 1));
+ packBuffer(&packet, szNick, (WORD)(nNickLen + 1));
+ sendDirectPacket(dc, &packet);
+#ifdef _DEBUG
+ NetLog_Direct("Sent PEER_FILE_INIT to %u on %s DC", dc->dwRemoteUin, dc->incoming?"incoming":"outgoing");
+#endif
+ ICQFreeVariant(&dbv);
+}
diff --git a/icqj_mod/icq_direct.h b/icqj_mod/icq_direct.h new file mode 100644 index 0000000..156196c --- /dev/null +++ b/icqj_mod/icq_direct.h @@ -0,0 +1,129 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_direct.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_DIRECT_H
+#define __ICQ_DIRECT_H
+
+typedef struct {
+ message_cookie_data pMessage;
+ int status;
+ int sending;
+ int iCurrentFile;
+ int currentIsDir;
+ DWORD dwCookie;
+ DWORD dwUin;
+ DWORD dwRemotePort;
+ HANDLE hContact;
+ char *szFilename;
+ char *szDescription;
+ char *szSavePath;
+ char *szThisFile;
+ char *szThisSubdir;
+ char **files;
+ DWORD dwThisFileSize;
+ DWORD dwThisFileDate;
+ DWORD dwTotalSize;
+ DWORD dwFileCount;
+ DWORD dwTransferSpeed;
+ DWORD dwBytesDone, dwFileBytesDone;
+ int fileId;
+ HANDLE hConnection;
+ DWORD dwLastNotify;
+ int nVersion; // Was this sent with a v7 or a v8 packet?
+ BOOL bDC; // Was this received over a DC or through server?
+ BOOL bEmptyDesc; // Was the description empty ?
+} filetransfer;
+
+#define DIRECTCONN_STANDARD 0
+#define DIRECTCONN_FILE 1
+#define DIRECTCONN_CHAT 2
+#define DIRECTCONN_REVERSE 10
+#define DIRECTCONN_CLOSING 15
+
+typedef struct {
+ HANDLE hContact;
+ HANDLE hConnection;
+ int type;
+ WORD wVersion;
+ int incoming;
+ int wantIdleTime;
+ int packetPending;
+ DWORD dwRemotePort;
+ DWORD dwRemoteUin;
+ DWORD dwRemoteExternalIP;
+ DWORD dwRemoteInternalIP;
+ DWORD dwLocalExternalIP;
+ DWORD dwLocalInternalIP;
+ DWORD dwConnCookie;
+ int initialised;
+ int handshake;
+ DWORD dwThreadId;
+ filetransfer *ft;
+ DWORD dwReqId; // Reverse Connect request cookie
+} directconnect;
+
+void OpenDirectConnection(HANDLE hContact, int type, void *pvExtra);
+int IsDirectConnectionOpen(HANDLE hContact, int type);
+void CloseDirectConnection(directconnect *dc);
+void CloseContactDirectConns(HANDLE hContact);
+int SendDirectMessage(HANDLE hContact, icq_packet *pkt);
+int sendDirectPacket(directconnect *dc, icq_packet *pkt);
+void icq_newConnectionReceived(HANDLE hNewConnection, DWORD dwRemoteIP);
+void InitDirectConns(void);
+void UninitDirectConns(void);
+directconnect* FindFileTransferDC(filetransfer* ft);
+void handleDirectMessage(directconnect *dc, PBYTE buf, WORD wLen);
+void EncryptDirectPacket(directconnect *dc, icq_packet *p);
+void icq_AcceptFileTransfer(HANDLE hContact, filetransfer *ft);
+void icq_CancelFileTransfer(HANDLE hContact, filetransfer *ft);
+void icq_sendFileResume(filetransfer *ft, int action, const char *szFilename);
+void icq_InitFileSend(filetransfer *ft);
+void AddExpectedFileRecv(filetransfer *ft);
+filetransfer *FindExpectedFileRecv(DWORD dwUin, DWORD dwTotalSize);
+void handleFileTransferPacket(directconnect *dc, PBYTE buf, WORD wLen);
+void handleFileTransferIdle(directconnect *dc);
+
+
+void handleDirectCancel(directconnect *dc, PBYTE buf, WORD wLen, WORD wCommand, DWORD dwCookie, WORD wMessageType, WORD wStatus, WORD wFlags, char* pszText);
+
+// Handles all types of file transfer replies
+void handleFileAck(PBYTE buf, WORD wLen, DWORD dwUin, DWORD dwCookie, WORD wStatus, char* pszText);
+
+// Handle a received file transfer request (direct & server)
+void handleFileRequest(PBYTE buf, WORD wLen, DWORD dwUin, DWORD dwCookie, DWORD dwID1, DWORD dwID2, char* pszDescription, int nVersion, BOOL bDC);
+
+
+#endif /* __ICQ_DIRECT_H */
diff --git a/icqj_mod/icq_directmsg.c b/icqj_mod/icq_directmsg.c new file mode 100644 index 0000000..6ae9fc5 --- /dev/null +++ b/icqj_mod/icq_directmsg.c @@ -0,0 +1,418 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_directmsg.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern WORD wListenPort;
+
+void icq_sendAwayMsgReplyDirect(directconnect *dc, WORD wCookie, BYTE msgType, const char **szMsg);
+
+void handleDirectGreetingMessage(directconnect *dc, PBYTE buf, WORD wLen, WORD wCommand, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wStatus, WORD wFlags, char* pszText);
+
+
+
+void handleDirectMessage(directconnect* dc, PBYTE buf, WORD wLen)
+{
+ WORD wCommand;
+ WORD wCookie;
+ BYTE bMsgType,bMsgFlags;
+ WORD wStatus;
+ WORD wFlags;
+ WORD wTextLen;
+ char* pszText = NULL;
+
+
+ // The first part of the packet should always be at least 31 bytes
+ if (wLen < 31)
+ {
+ NetLog_Direct("Error during parsing of DC packet 2 PEER_MSG (too short)");
+ return;
+ }
+
+ // Skip packet checksum
+ buf += 4;
+ wLen -= 4;
+
+ // Command:
+ // 0x07d0 = 2000 - cancel given message.
+ // 0x07da = 2010 - acknowledge message.
+ // 0x07ee = 2030 - normal message/request.
+ unpackLEWord(&buf, &wCommand);
+ wLen -= 2;
+
+ // Unknown, always 0xe (14)
+ buf += 2;
+ wLen -= 2;
+
+ // Sequence number
+ unpackLEWord(&buf, &wCookie);
+ wLen -=2;
+
+ // Unknown, always zeroes
+ buf += 12;
+ wLen -= 12;
+
+ // Peer message type
+ unpackByte(&buf, &bMsgType);
+ // Peer message flags
+ unpackByte(&buf, &bMsgFlags);
+ wLen -= 2;
+
+ // The current status of the user, or whether the message was accepted or not.
+ // 0x00 - user is online, or message was receipt, or file transfer accepted
+ // 0x01 - refused
+ // 0x04 - auto-refused, because of away
+ // 0x09 - auto-refused, because of occupied
+ // 0x0a - auto-refused, because of dnd
+ // 0x0e - auto-refused, because of na
+ unpackLEWord(&buf, &wStatus);
+ wLen -= 2;
+
+ // Flags, or priority
+ // Seen: 1 - Chat request
+ // 0 - File auto accept (type 3)
+ // 33 - priority ?
+ unpackLEWord(&buf, &wFlags);
+ wLen -= 2;
+
+ // Messagetext. This is either the status message or the actual message
+ // when this is a PEER_MSG_MSG packet
+ unpackLEWord(&buf, &wTextLen);
+ if (wTextLen > 0)
+ {
+ pszText = _alloca(wTextLen+1);
+ unpackString(&buf, pszText, wTextLen);
+ pszText[wTextLen] = '\0';
+ }
+ wLen = (wLen - 2) - wTextLen;
+
+#ifdef _DEBUG
+ NetLog_Direct("Handling PEER_MSG '%s', command %u, cookie %u, messagetype %u, messageflags %u, status %u, flags %u", pszText, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags);
+#else
+ NetLog_Direct("Message through direct - UID: %u", dc->dwRemoteUin);
+#endif
+
+ // The remaining actual message is handled either as a status message request,
+ // a greeting message, a acknowledge or a normal (text, url, file) message
+ if (wCommand == DIRECT_MESSAGE)
+ switch (bMsgType)
+ {
+ case MTYPE_FILEREQ: // File inits
+ handleFileRequest(buf, wLen, dc->dwRemoteUin, wCookie, 0, 0, pszText, 7, TRUE);
+ break;
+
+ case MTYPE_AUTOAWAY:
+ case MTYPE_AUTOBUSY:
+ case MTYPE_AUTONA:
+ case MTYPE_AUTODND:
+ case MTYPE_AUTOFFC:
+ {
+ char** szMsg = MirandaStatusToAwayMsg(AwayMsgTypeToStatus(bMsgType));
+
+ if (szMsg)
+ icq_sendAwayMsgReplyDirect(dc, wCookie, bMsgType, szMsg);
+ }
+ break;
+
+ case MTYPE_PLUGIN: // Greeting
+ handleDirectGreetingMessage(dc, buf, wLen, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags, pszText);
+ break;
+
+ default:
+ {
+ buf -= wTextLen;
+ wLen += wTextLen;
+
+ handleMessageTypes(dc->dwRemoteUin, time(NULL), 0, 0, wCookie, dc->wVersion, (int)bMsgType, (int)bMsgFlags, 0, (DWORD)wLen, wTextLen, buf, TRUE);
+
+ // Send acknowledgement
+ if (bMsgType == MTYPE_PLAIN || bMsgType == MTYPE_URL || bMsgType == MTYPE_CONTACTS)
+ {
+ icq_sendDirectMsgAck(dc, wCookie, bMsgType, bMsgFlags, CAP_RTFMSGS);
+ }
+ break;
+ }
+ }
+ else if (wCommand == DIRECT_ACK)
+ {
+ if (bMsgFlags == 3)
+ { // this is status reply
+ buf -= wTextLen;
+ wLen += wTextLen;
+
+ handleMessageTypes(dc->dwRemoteUin, time(NULL), 0, 0, wCookie, dc->wVersion, (int)bMsgType, (int)bMsgFlags, 2, (DWORD)wLen, wTextLen, buf, TRUE);
+ }
+ else
+ {
+ DWORD dwCookieUin;
+ message_cookie_data* pCookieData = NULL;
+
+ if (!FindCookie(wCookie, &dwCookieUin, &pCookieData))
+ {
+ NetLog_Direct("Received an unexpected direct ack");
+ }
+ else if (dwCookieUin != dc->dwRemoteUin)
+ {
+ NetLog_Direct("Direct UIN does not match Cookie UIN(%u != %u)", dc->dwRemoteUin, dwCookieUin);
+ ReleaseCookie(wCookie); // This could be a bad idea, but I think it is safe
+ }
+ else
+ { // the ack is correct
+ int ackType = -1;
+
+ switch (bMsgType)
+ {
+ case MTYPE_PLAIN:
+ ackType = ACKTYPE_MESSAGE;
+ break;
+ case MTYPE_URL:
+ ackType = ACKTYPE_URL;
+ break;
+ case MTYPE_CONTACTS:
+ ackType = ACKTYPE_CONTACTS;
+ break;
+
+ case MTYPE_FILEREQ: // File acks
+ handleFileAck(buf, wLen, dc->dwRemoteUin, wCookie, wStatus, pszText);
+ break;
+
+ case MTYPE_PLUGIN: // Greeting
+ handleDirectGreetingMessage(dc, buf, wLen, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags, pszText);
+ break;
+
+ default:
+ NetLog_Direct("Skipped packet from direct connection");
+ break;
+ }
+ if (ackType != -1)
+ { // was a good ack to broadcast ?
+ ICQBroadcastAck(dc->hContact, ackType, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
+ ReleaseCookie(wCookie);
+ }
+ }
+ }
+ }
+ else if (wCommand == DIRECT_CANCEL)
+ {
+ NetLog_Direct("Cannot handle abort messages yet... :(");
+ }
+ else
+ NetLog_Direct("Unknown wCommand, packet skipped");
+}
+
+
+
+void handleDirectGreetingMessage(directconnect* dc, PBYTE buf, WORD wLen, WORD wCommand, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wStatus, WORD wFlags, char* pszText)
+{
+ DWORD dwMsgTypeLen;
+ DWORD dwLengthToEnd;
+ DWORD dwDataLength;
+ char* szMsgType = NULL;
+ char* pszFileName = NULL;
+ int typeId;
+ WORD wPacketCommand;
+ DWORD q1,q2,q3,q4;
+ WORD qt;
+
+#ifdef _DEBUG
+ NetLog_Direct("Handling PEER_MSG_GREETING, command %u, cookie %u, messagetype %u, messageflags %u, status %u, flags %u", wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags);
+#endif
+
+ // The command in this packet.
+ unpackLEWord(&buf, &wPacketCommand); // TODO: this is most probably length...
+ wLen -= 2;
+
+ // Data type GUID
+ unpackDWord(&buf, &q1);
+ unpackDWord(&buf, &q2);
+ unpackDWord(&buf, &q3);
+ unpackDWord(&buf, &q4);
+ wLen -= 16;
+
+ // Data type function id
+ unpackLEWord(&buf, &qt);
+ wLen -= 2;
+
+ // A text string
+ // "ICQ Chat" for chat request, "File" for file request,
+ // "File Transfer" for file request grant/refusal. This text is
+ // displayed in the requester opened by Windows.
+ unpackLEDWord(&buf, &dwMsgTypeLen);
+ wLen -= 4;
+ if (dwMsgTypeLen == 0 || dwMsgTypeLen>256)
+ {
+ NetLog_Direct("Error: Sanity checking failed (%d) in handleDirectGreetingMessage, len is %u", 1, dwMsgTypeLen);
+ return;
+ }
+ szMsgType = (char *)_alloca(dwMsgTypeLen + 1);
+ memcpy(szMsgType, buf, dwMsgTypeLen);
+ szMsgType[dwMsgTypeLen] = '\0';
+ typeId = TypeGUIDToTypeId(q1,q2,q3,q4,qt);
+ if (!typeId)
+ NetLog_Direct("Error: Unknown type {%04x%04x%04x%04x-%02x}: %s", q1,q2,q3,q4,qt,szMsgType);
+
+ buf += dwMsgTypeLen;
+ wLen -= (WORD)dwMsgTypeLen;
+
+ NetLog_Direct("PEER_MSG_GREETING, command: %u, type: %s, typeID: %u", typeId, szMsgType, typeId);
+
+ // Unknown
+ buf += 15;
+ wLen -= 15;
+
+ // Length of remaining data
+ unpackLEDWord(&buf, &dwLengthToEnd);
+ if (dwLengthToEnd < 4 || dwLengthToEnd > wLen)
+ {
+ NetLog_Direct("Error: Sanity checking failed (%d) in handleDirectGreetingMessage, datalen %u wLen %u", 2, dwLengthToEnd, wLen);
+ return;
+ }
+
+ // Length of message/reason
+ unpackLEDWord(&buf, &dwDataLength);
+ wLen -= 4;
+ if (dwDataLength > wLen)
+ {
+ NetLog_Direct("Error: Sanity checking failed (%d) in handleDirectGreetingMessage, datalen %u wLen %u", 3, dwDataLength, wLen);
+ return;
+ }
+
+ if (typeId == MTYPE_FILEREQ && wCommand == DIRECT_MESSAGE)
+ {
+ char* szMsg;
+
+ NetLog_Direct("This is file request");
+ szMsg = _alloca(dwDataLength+1);
+ unpackString(&buf, szMsg, (WORD)dwDataLength);
+ szMsg[dwDataLength] = '\0';
+ wLen = wLen - (WORD)dwDataLength;
+
+ handleFileRequest(buf, wLen, dc->dwRemoteUin, wCookie, 0, 0, szMsg, 8, TRUE);
+ }
+ else if (typeId == MTYPE_FILEREQ && wCommand == DIRECT_ACK)
+ {
+ char* szMsg;
+
+ NetLog_Direct("This is file ack");
+ szMsg = _alloca(dwDataLength+1);
+ unpackString(&buf, szMsg, (WORD)dwDataLength);
+ szMsg[dwDataLength] = '\0';
+ wLen = wLen - (WORD)dwDataLength;
+
+ // 50 - file request granted/refused
+ handleFileAck(buf, wLen, dc->dwRemoteUin, wCookie, wStatus, szMsg);
+ }
+ else if (typeId && wCommand == DIRECT_MESSAGE)
+ {
+ if (typeId == MTYPE_URL || typeId == MTYPE_CONTACTS)
+ {
+ icq_sendDirectMsgAck(dc, wCookie, (BYTE)typeId, 0, CAP_RTFMSGS);
+ }
+ handleMessageTypes(dc->dwRemoteUin, time(NULL), 0, 0, wCookie, dc->wVersion, typeId, 0, 0, dwLengthToEnd, (WORD)dwDataLength, buf, TRUE);
+ }
+ else if (typeId == MTYPE_STATUSMSGEXT && wCommand == DIRECT_ACK)
+ { // especially for icq2003b
+ char* szMsg;
+
+ NetLog_Direct("This is extended status reply");
+ szMsg = _alloca(dwDataLength+1);
+ unpackString(&buf, szMsg, (WORD)dwDataLength);
+ szMsg[dwDataLength] = '\0';
+
+ handleMessageTypes(dc->dwRemoteUin, time(NULL), 0, 0, wCookie, dc->wVersion, (int)(qt + 0xE7), 3, 2, (DWORD)wLen, (WORD)dwDataLength, szMsg, TRUE);
+ }
+ else if (typeId && wCommand == DIRECT_ACK)
+ {
+ DWORD dwCookieUin;
+ message_cookie_data* pCookieData = NULL;
+
+ if (!FindCookie(wCookie, &dwCookieUin, &pCookieData))
+ {
+ NetLog_Direct("Received an unexpected direct ack");
+ }
+ else if (dwCookieUin != dc->dwRemoteUin)
+ {
+ NetLog_Direct("Direct UIN does not match Cookie UIN(%u != %u)", dc->dwRemoteUin, dwCookieUin);
+ ReleaseCookie(wCookie); // This could be a bad idea, but I think it is safe
+ }
+ else
+ {
+ int ackType = -1;
+
+ switch (typeId)
+ {
+ case MTYPE_MESSAGE:
+ ackType = ACKTYPE_MESSAGE;
+ break;
+ case MTYPE_URL:
+ ackType = ACKTYPE_URL;
+ break;
+ case MTYPE_CONTACTS:
+ ackType = ACKTYPE_CONTACTS;
+ break;
+ case MTYPE_SCRIPT_NOTIFY:
+ {
+ char *szMsg;
+
+ szMsg = (char*)_alloca(dwDataLength + 1);
+ if (dwDataLength > 0)
+ memcpy(szMsg, buf, dwDataLength);
+ szMsg[dwDataLength] = '\0';
+
+ handleXtrazNotifyResponse(dwCookieUin, dc->hContact, wCookie, szMsg, dwDataLength);
+ }
+ break;
+
+ default:
+ NetLog_Direct("Skipped packet from direct connection");
+ break;
+ }
+
+ if (ackType != -1)
+ { // was a good ack to broadcast ?
+ ICQBroadcastAck(dc->hContact, ackType, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
+ }
+ // Release cookie
+ ReleaseCookie(wCookie);
+ }
+ }
+ else
+ {
+ NetLog_Direct("Unsupported plugin message type '%s'", szMsgType);
+ }
+}
diff --git a/icqj_mod/icq_fieldnames.c b/icqj_mod/icq_fieldnames.c new file mode 100644 index 0000000..a497175 --- /dev/null +++ b/icqj_mod/icq_fieldnames.c @@ -0,0 +1,280 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_fieldnames.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+struct fieldnames_t interestsField[]={
+ {100, "Art"},
+ {101, "Cars"},
+ {102, "Celebrity Fans"},
+ {103, "Collections"},
+ {104, "Computers"},
+ {105, "Culture & Literature"},
+ {106, "Fitness"},
+ {107, "Games"},
+ {108, "Hobbies"},
+ {109, "ICQ - Providing Help"},
+ {110, "Internet"},
+ {111, "Lifestyle"},
+ {112, "Movies/TV"},
+ {113, "Music"},
+ {114, "Outdoor Activities"},
+ {115, "Parenting"},
+ {116, "Pets/Animals"},
+ {117, "Religion"},
+ {118, "Science/Technology"},
+ {119, "Skills"},
+ {120, "Sports"},
+ {121, "Web Design"},
+ {122, "Nature and Environment"},
+ {123, "News & Media"},
+ {124, "Government"},
+ {125, "Business & Economy"},
+ {126, "Mystics"},
+ {127, "Travel"},
+ {128, "Astronomy"},
+ {129, "Space"},
+ {130, "Clothing"},
+ {131, "Parties"},
+ {132, "Women"},
+ {133, "Social science"},
+ {134, "60's"},
+ {135, "70's"},
+ {136, "80's"},
+ {137, "50's"},
+ {138, "Finance and corporate"},
+ {139, "Entertainment"},
+ {140, "Consumer electronics"},
+ {141, "Retail stores"},
+ {142, "Health and beauty"},
+ {143, "Media"},
+ {144, "Household products"},
+ {145, "Mail order catalog"},
+ {146, "Business services"},
+ {147, "Audio and visual"},
+ {148, "Sporting and athletic"},
+ {149, "Publishing"},
+ {150, "Home automation"},
+ {-1, NULL}};
+
+struct fieldnames_t languageField[]={
+ {1, "Arabic"},
+ {2, "Bhojpuri"},
+ {3, "Bulgarian"},
+ {4, "Burmese"},
+ {5, "Cantonese"},
+ {6, "Catalan"},
+ {7, "Chinese"},
+ {8, "Croatian"},
+ {9, "Czech"},
+ {10, "Danish"},
+ {11, "Dutch"},
+ {12, "English"},
+ {13, "Esperanto"},
+ {14, "Estonian"},
+ {15, "Farci"},
+ {16, "Finnish"},
+ {17, "French"},
+ {18, "Gaelic"},
+ {19, "German"},
+ {20, "Greek"},
+ {21, "Hebrew"},
+ {22, "Hindi"},
+ {23, "Hungarian"},
+ {24, "Icelandic"},
+ {25, "Indonesian"},
+ {26, "Italian"},
+ {27, "Japanese"},
+ {28, "Khmer"},
+ {29, "Korean"},
+ {30, "Lao"},
+ {31, "Latvian"},
+ {32, "Lithuanian"},
+ {33, "Malay"},
+ {34, "Norwegian"},
+ {35, "Polish"},
+ {36, "Portuguese"},
+ {37, "Romanian"},
+ {38, "Russian"},
+ {39, "Serbo-Croatian"},
+ {40, "Slovak"},
+ {41, "Slovenian"},
+ {42, "Somali"},
+ {43, "Spanish"},
+ {44, "Swahili"},
+ {45, "Swedish"},
+ {46, "Tagalog"},
+ {47, "Tatar"},
+ {48, "Thai"},
+ {49, "Turkish"},
+ {50, "Ukrainian"},
+ {51, "Urdu"},
+ {52, "Vietnamese"},
+ {53, "Yiddish"},
+ {54, "Yoruba"},
+ {55, "Afrikaans"},
+ {56, "Bosnian"},
+ {57, "Persian"},
+ {58, "Albanian"},
+ {59, "Armenian"},
+ {60, "Punjabi"},
+ {61, "Chamorro"},
+ {62, "Mongolian"},
+ {63, "Mandarin"},
+ {64, "Taiwaness"},
+ {65, "Macedonian"},
+ {66, "Sindhi"},
+ {67, "Welsh"},
+ {68, "Azerbaijani"},
+ {69, "Kurdish"},
+ {70, "Gujarati"},
+ {71, "Tamil"},
+ {72, "Belorussian"},
+ {-1, NULL}};
+
+struct fieldnames_t pastField[]={
+ {300, "Elementary School"},
+ {301, "High School"},
+ {302, "College"},
+ {303, "University"},
+ {304, "Military"},
+ {305, "Past Work Place"},
+ {306, "Past Organization"},
+ {399, "Other"},
+ {-1, NULL}};
+
+struct fieldnames_t genderField[]={
+ {1, "Female"},
+ {2, "Male"},
+ {-1, NULL}};
+
+struct fieldnames_t workField[]={
+ {1, "Academic"},
+ {2, "Administrative"},
+ {3, "Art/Entertainment"},
+ {4, "College Student"},
+ {5, "Computers"},
+ {6, "Community & Social"},
+ {7, "Education"},
+ {8, "Engineering"},
+ {9, "Financial Services"},
+ {10, "Government"},
+ {11, "High School Student"},
+ {12, "Home"},
+ {13, "ICQ - Providing Help"},
+ {14, "Law"},
+ {15, "Managerial"},
+ {16, "Manufacturing"},
+ {17, "Medical/Health"},
+ {18, "Military"},
+ {19, "Non-Government Organization"},
+ {20, "Professional"},
+ {21, "Retail"},
+ {22, "Retired"},
+ {23, "Science & Research"},
+ {24, "Sports"},
+ {25, "Technical"},
+ {26, "University Student"},
+ {27, "Web building"},
+ {99, "Other services"},
+ {-1, NULL}};
+
+struct fieldnames_t affiliationField[]={
+ {200, "Alumni Org."},
+ {201, "Charity Org."},
+ {202, "Club/Social Org."},
+ {203, "Community Org."},
+ {204, "Cultural Org."},
+ {205, "Fan Clubs"},
+ {206, "Fraternity/Sorority"},
+ {207, "Hobbyists Org."},
+ {208, "International Org."},
+ {209, "Nature and Environment Org."},
+ {210, "Professional Org."},
+ {211, "Scientific/Technical Org."},
+ {212, "Self Improvement Group"},
+ {213, "Spiritual/Religious Org."},
+ {214, "Sports Org."},
+ {215, "Support Org."},
+ {216, "Trade and Business Org."},
+ {217, "Union"},
+ {218, "Volunteer Org."},
+ {299, "Other"},
+ {-1, NULL}};
+
+struct fieldnames_t agesField[]={
+ {0x0011000D, "13-17"},
+ {0x00160012, "18-22"},
+ {0x001D0017, "23-29"},
+ {0x0027001E, "30-39"},
+ {0x00310028, "40-49"},
+ {0x003B0032, "50-59"},
+ {0x2710003C, "60-above"},
+ {-1, NULL}};
+
+struct fieldnames_t maritalField[]={
+ {10, "Single"},
+ {11, "Close relationships"},
+ {12, "Engaged"},
+ {20, "Married"},
+ {30, "Divorced"},
+ {31, "Separated"},
+ {40, "Widowed"},
+ {-1, NULL}};
+
+
+
+char *LookupFieldNameUtf(struct fieldnames_t *table, int code, char *str)
+{
+ int i;
+
+ if (code != 0)
+ {
+ for(i = 0; table[i].code != -1 && table[i].text; i++)
+ {
+ if (table[i].code == code)
+ return ICQTranslateUtfStatic(table[i].text, str);
+ }
+
+ // Tried to get unexisting field name, you have an
+ // error in the data or in the table
+ _ASSERT(FALSE);
+ }
+
+ return NULL;
+}
diff --git a/icqj_mod/icq_fieldnames.h b/icqj_mod/icq_fieldnames.h new file mode 100644 index 0000000..0d36ec3 --- /dev/null +++ b/icqj_mod/icq_fieldnames.h @@ -0,0 +1,51 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_fieldnames.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+struct fieldnames_t {
+ int code;
+ char *text;
+};
+
+extern struct fieldnames_t interestsField[];
+extern struct fieldnames_t languageField[];
+extern struct fieldnames_t pastField[];
+extern struct fieldnames_t genderField[];
+extern struct fieldnames_t agesField[];
+extern struct fieldnames_t workField[];
+extern struct fieldnames_t affiliationField[];
+extern struct fieldnames_t maritalField[];
+
+char *LookupFieldNameUtf(struct fieldnames_t *table, int code, char *str);
diff --git a/icqj_mod/icq_filerequests.c b/icqj_mod/icq_filerequests.c new file mode 100644 index 0000000..5b323da --- /dev/null +++ b/icqj_mod/icq_filerequests.c @@ -0,0 +1,237 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_filerequests.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern WORD wListenPort;
+
+void handleFileAck(PBYTE buf, WORD wLen, DWORD dwUin, DWORD dwCookie, WORD wStatus, char* pszText)
+{
+ char* pszFileName = NULL;
+ DWORD dwFileSize;
+ DWORD dwCookieUin;
+ WORD wPort;
+ WORD wFilenameLength;
+ filetransfer* ft;
+
+
+ // Find the filetransfer that belongs to this response
+ if (!FindCookie(dwCookie, &dwCookieUin, &ft))
+ {
+ NetLog_Direct("Error: Received unexpected file transfer request response");
+ return;
+ }
+
+ FreeCookie(dwCookie);
+
+ if (dwCookieUin != dwUin)
+ {
+ NetLog_Direct("Error: UINs do not match in file transfer request response");
+ return;
+ }
+
+ // If status != 0, a request has been denied
+ if (wStatus != 0)
+ {
+ NetLog_Direct("File transfer denied by %u,", dwUin);
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)ft, 0);
+
+ FreeCookie(dwCookie);
+
+ return;
+ }
+
+ // Port to connect to
+ unpackWord(&buf, &wPort);
+ ft->dwRemotePort = wPort;
+ wLen -= 2;
+
+ // Unknown
+ buf += 2;
+ wLen -= 2;
+
+ // Filename
+ unpackLEWord(&buf, &wFilenameLength);
+ if (wFilenameLength > 0)
+ {
+ pszFileName = _alloca(wFilenameLength+1);
+ unpackString(&buf, pszFileName, wFilenameLength);
+ pszFileName[wFilenameLength] = '\0';
+ }
+ wLen = wLen - 2 - wFilenameLength;
+
+ // Total filesize
+ unpackLEDWord(&buf, &dwFileSize);
+ wLen -= 4;
+
+ NetLog_Direct("File transfer ack from %u, port %u, name %s, size %u", dwUin, ft->dwRemotePort, pszFileName, dwFileSize);
+
+ OpenDirectConnection(ft->hContact, DIRECTCONN_FILE, ft);
+}
+
+
+
+filetransfer *CreateFileTransfer(HANDLE hContact, DWORD dwUin, int nVersion)
+{
+ filetransfer *ft;
+
+ ft = (filetransfer*)SAFE_MALLOC(sizeof(filetransfer));
+ if (ft)
+ {
+ ZeroMemory(ft, sizeof(filetransfer));
+ ft->dwUin = dwUin;
+ ft->hContact = hContact;
+ ft->nVersion = nVersion;
+ ft->pMessage.bMessageType = MTYPE_FILEREQ;
+ ft->pMessage.dwMsgID1 = time(NULL);
+ ft->pMessage.dwMsgID2 = RandRange(0, 0x00FF);
+ }
+ return ft;
+}
+
+// pszDescription points to a string with the reason
+// buf points to the first data after the string
+void handleFileRequest(PBYTE buf, WORD wLen, DWORD dwUin, DWORD dwCookie, DWORD dwID1, DWORD dwID2, char* pszDescription, int nVersion, BOOL bDC)
+{
+ char* pszFileName = NULL;
+ DWORD dwFileSize;
+ WORD wFilenameLength;
+ BOOL bEmptyDesc = FALSE;
+
+
+ if (strlennull(pszDescription) == 0)
+ {
+ pszDescription = ICQTranslate("No description given");
+ bEmptyDesc = TRUE;
+ }
+
+ // Empty port+pad
+ buf += 4;
+ wLen -= 4;
+
+
+ // Filename
+ unpackLEWord(&buf, &wFilenameLength);
+ if (wFilenameLength > 0)
+ {
+ pszFileName = _alloca(wFilenameLength + 1);
+ unpackString(&buf, pszFileName, wFilenameLength);
+ pszFileName[wFilenameLength] = '\0';
+ }
+ else
+ {
+ NetLog_Direct("Ignoring malformed file send request");
+ return;
+ }
+
+ wLen = wLen - 2 - wFilenameLength;
+
+ // Total filesize
+ unpackLEDWord(&buf, &dwFileSize);
+ wLen -= 4;
+
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ char* szBlob;
+ filetransfer* ft;
+ int bAdded;
+ HANDLE hContact = HContactFromUIN(dwUin, &bAdded);
+
+ // Initialize a filetransfer struct
+ ft = CreateFileTransfer(hContact, dwUin, nVersion);
+ ft->dwCookie = dwCookie;
+ ft->szFilename = null_strdup(pszFileName);
+ ft->szDescription = null_strdup(pszDescription);
+ ft->fileId = -1;
+ ft->dwTotalSize = dwFileSize;
+ ft->pMessage.dwMsgID1 = dwID1;
+ ft->pMessage.dwMsgID2 = dwID2;
+ ft->bDC = bDC;
+ ft->bEmptyDesc = bEmptyDesc;
+
+
+ // Send chain event
+ szBlob = (char*)_alloca(sizeof(DWORD) + strlennull(pszFileName) + strlennull(pszDescription) + 2);
+ *(PDWORD)szBlob = (DWORD)ft;
+ strcpy(szBlob + sizeof(DWORD), pszFileName);
+ strcpy(szBlob + sizeof(DWORD) + strlennull(pszFileName) + 1, pszDescription);
+ ccs.szProtoService = PSR_FILE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.flags = 0;
+ pre.timestamp = time(NULL);
+ pre.szMessage = szBlob;
+ pre.lParam = 0;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+}
+
+
+
+void handleDirectCancel(directconnect *dc, PBYTE buf, WORD wLen, WORD wCommand, DWORD dwCookie, WORD wMessageType, WORD wStatus, WORD wFlags, char* pszText)
+{
+ NetLog_Direct("handleDirectCancel: Unhandled cancel");
+}
+
+
+
+// *******************************************************************************
+
+
+
+void icq_CancelFileTransfer(HANDLE hContact, filetransfer* ft)
+{
+ DWORD dwCookie;
+
+ if (FindCookieByData(ft, &dwCookie, NULL))
+ FreeCookie(dwCookie); /* this bit stops a send that's waiting for acceptance */
+
+ if (ft->hConnection)
+ {
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ Netlib_CloseHandle(ft->hConnection);
+ ft->hConnection = NULL;
+ }
+ /* FIXME: Do not free ft, or anything therein, it is freed inside DC thread ! */
+ #ifdef _DEBUG
+ NetLog_Direct("icq_CancelFileTransfer: OK");
+ #endif
+}
diff --git a/icqj_mod/icq_filetransfer.c b/icqj_mod/icq_filetransfer.c new file mode 100644 index 0000000..576d65e --- /dev/null +++ b/icqj_mod/icq_filetransfer.c @@ -0,0 +1,576 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_filetransfer.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static void file_buildProtoFileTransferStatus(filetransfer* ft, PROTOFILETRANSFERSTATUS* pfts)
+{
+ ZeroMemory(pfts, sizeof(PROTOFILETRANSFERSTATUS));
+ pfts->cbSize = sizeof(PROTOFILETRANSFERSTATUS);
+ pfts->hContact = ft->hContact;
+ pfts->sending = ft->sending;
+ if (ft->sending)
+ pfts->files = ft->files;
+ else
+ pfts->files = NULL; /* FIXME */
+ pfts->totalFiles = ft->dwFileCount;
+ pfts->currentFileNumber = ft->iCurrentFile;
+ pfts->totalBytes = ft->dwTotalSize;
+ pfts->totalProgress = ft->dwBytesDone;
+ pfts->workingDir = ft->szSavePath;
+ pfts->currentFile = ft->szThisFile;
+ pfts->currentFileSize = ft->dwThisFileSize;
+ pfts->currentFileTime = ft->dwThisFileDate;
+ pfts->currentFileProgress = ft->dwFileBytesDone;
+}
+
+
+
+static void file_sendTransferSpeed(directconnect* dc)
+{
+ icq_packet packet;
+
+ directPacketInit(&packet, 5);
+ packByte(&packet, PEER_FILE_SPEED); /* Ident */
+ packLEDWord(&packet, dc->ft->dwTransferSpeed);
+ sendDirectPacket(dc, &packet);
+}
+
+
+
+static void file_sendNick(directconnect* dc)
+{
+ icq_packet packet;
+ char* szNick;
+ WORD wNickLen;
+ DBVARIANT dbv;
+
+
+ dbv.type = DBVT_DELETED;
+ if (ICQGetContactSetting(NULL, "Nick", &dbv))
+ szNick = "";
+ else
+ szNick = dbv.pszVal;
+
+ wNickLen = strlennull(szNick);
+
+ directPacketInit(&packet, (WORD)(8 + wNickLen));
+ packByte(&packet, PEER_FILE_INIT_ACK); /* Ident */
+ packLEDWord(&packet, dc->ft->dwTransferSpeed);
+ packLEWord(&packet, (WORD)(wNickLen + 1));
+ packBuffer(&packet, szNick, (WORD)(wNickLen + 1));
+ sendDirectPacket(dc, &packet);
+ ICQFreeVariant(&dbv);
+}
+
+
+
+static void file_sendNextFile(directconnect* dc)
+{
+ icq_packet packet;
+ struct _stat statbuf;
+ char *pszThisFileName;
+ char szThisSubDir[MAX_PATH];
+ WORD wThisFileNameLen, wThisSubDirLen;
+
+
+ if (dc->ft->iCurrentFile >= (int)dc->ft->dwFileCount)
+ {
+ ICQBroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, dc->ft, 0);
+ CloseDirectConnection(dc);
+ dc->ft->hConnection = NULL;
+ return;
+ }
+
+ dc->ft->szThisFile = null_strdup(dc->ft->files[dc->ft->iCurrentFile]);
+ if (_stat(dc->ft->szThisFile, &statbuf))
+ {
+ icq_LogMessage(LOG_ERROR, "Your file transfer has been aborted because one of the files that you selected to send is no longer readable from the disk. You may have deleted or moved it.");
+ CloseDirectConnection(dc);
+ dc->ft->hConnection = NULL;
+ return;
+ }
+
+ szThisSubDir[0] = '\0';
+
+ if (((pszThisFileName = strrchr(dc->ft->szThisFile, '\\')) == NULL) &&
+ ((pszThisFileName = strrchr(dc->ft->szThisFile, '/')) == NULL))
+ {
+ pszThisFileName = dc->ft->szThisFile;
+ }
+ else
+ {
+ int i;
+ int len;
+
+
+ /* find an earlier subdirectory to be used as a container */
+ for (i = dc->ft->iCurrentFile - 1; i >= 0; i--)
+ {
+ len = strlennull(dc->ft->files[i]);
+ if (!_strnicmp(dc->ft->files[i], dc->ft->szThisFile, len) &&
+ (dc->ft->szThisFile[len] == '\\' || dc->ft->szThisFile[len] == '/'))
+ {
+ char* pszLastBackslash;
+
+ if (((pszLastBackslash = strrchr(dc->ft->files[i], '\\')) == NULL) &&
+ ((pszLastBackslash = strrchr(dc->ft->files[i], '/')) == NULL))
+ {
+ strcpy(szThisSubDir, dc->ft->files[i]);
+ }
+ else
+ {
+ len = pszLastBackslash - dc->ft->files[i] + 1;
+ strncpy(szThisSubDir, dc->ft->szThisFile + len,
+ pszThisFileName - dc->ft->szThisFile - len);
+ szThisSubDir[pszThisFileName - dc->ft->szThisFile - len] = '\0';
+ }
+ }
+ }
+ pszThisFileName++; // skip backslash
+ }
+
+ if (statbuf.st_mode&_S_IFDIR)
+ {
+ dc->ft->currentIsDir = 1;
+ }
+ else
+ {
+ dc->ft->currentIsDir = 0;
+ dc->ft->fileId = _open(dc->ft->szThisFile, _O_BINARY | _O_RDONLY);
+ if (dc->ft->fileId == -1)
+ {
+ icq_LogMessage(LOG_ERROR, "Your file transfer has been aborted because one of the files that you selected to send is no longer readable from the disk. You may have deleted or moved it.");
+ CloseDirectConnection(dc);
+ dc->ft->hConnection = NULL;
+ return;
+ }
+
+ }
+ dc->ft->dwThisFileSize = statbuf.st_size;
+ dc->ft->dwThisFileDate = statbuf.st_mtime;
+ dc->ft->dwFileBytesDone = 0;
+
+ wThisFileNameLen = strlennull(pszThisFileName);
+ wThisSubDirLen = strlennull(szThisSubDir);
+
+ directPacketInit(&packet, (WORD)(20 + wThisFileNameLen + wThisSubDirLen));
+ packByte(&packet, PEER_FILE_NEXTFILE); /* Ident */
+ packByte(&packet, (BYTE)((statbuf.st_mode & _S_IFDIR) != 0)); // Is subdir
+ packLEWord(&packet, (WORD)(wThisFileNameLen + 1));
+ packBuffer(&packet, pszThisFileName, (WORD)(wThisFileNameLen + 1));
+ packLEWord(&packet, (WORD)(wThisSubDirLen + 1));
+ packBuffer(&packet, szThisSubDir, (WORD)(wThisSubDirLen + 1));
+ packLEDWord(&packet, dc->ft->dwThisFileSize);
+ packLEDWord(&packet, statbuf.st_mtime);
+ packLEDWord(&packet, dc->ft->dwTransferSpeed);
+
+ sendDirectPacket(dc, &packet);
+
+ ICQBroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, dc->ft, 0);
+}
+
+
+
+static void file_sendResume(directconnect* dc)
+{
+ icq_packet packet;
+
+ directPacketInit(&packet, 17);
+ packByte(&packet, PEER_FILE_RESUME); /* Ident */
+ packLEDWord(&packet, dc->ft->dwFileBytesDone); /* file resume */
+ packLEDWord(&packet, 0); /* unknown */
+ packLEDWord(&packet, dc->ft->dwTransferSpeed);
+ packLEDWord(&packet, dc->ft->iCurrentFile + 1); /* file number */
+ sendDirectPacket(dc, &packet);
+}
+
+
+
+static void file_sendData(directconnect* dc)
+{
+ BYTE buf[2048];
+ int bytesRead = 0;
+
+ if (!dc->ft->currentIsDir)
+ {
+ icq_packet packet;
+
+ if (dc->ft->fileId == -1)
+ return;
+ bytesRead = _read(dc->ft->fileId, buf, sizeof(buf));
+ if (bytesRead == -1)
+ return;
+
+ directPacketInit(&packet, (WORD)(1 + bytesRead));
+ packByte(&packet, PEER_FILE_DATA); /* Ident */
+ packBuffer(&packet, buf, (WORD)bytesRead);
+ sendDirectPacket(dc, &packet);
+ }
+
+ dc->ft->dwBytesDone += bytesRead;
+ dc->ft->dwFileBytesDone += bytesRead;
+
+ if (GetTickCount() > dc->ft->dwLastNotify + 500 || bytesRead == 0)
+ {
+ PROTOFILETRANSFERSTATUS pfts;
+
+ file_buildProtoFileTransferStatus(dc->ft, &pfts);
+ ICQBroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, dc->ft, (LPARAM)&pfts);
+ dc->ft->dwLastNotify = GetTickCount();
+ }
+
+ if (bytesRead == 0)
+ {
+ if (!dc->ft->currentIsDir) _close(dc->ft->fileId);
+ dc->ft->fileId = -1;
+ dc->wantIdleTime = 0;
+ dc->ft->iCurrentFile++;
+ file_sendNextFile(dc); /* this will close the socket if no more files */
+ }
+}
+
+
+
+void handleFileTransferIdle(directconnect* dc)
+{
+ file_sendData(dc);
+}
+
+
+
+void icq_sendFileResume(filetransfer* ft, int action, const char* szFilename)
+{
+ int openFlags;
+ directconnect *dc;
+
+
+ if (ft->hConnection == NULL)
+ return;
+
+ dc = FindFileTransferDC(ft);
+ if (!dc) return; // something is broken...
+
+ switch (action)
+ {
+ case FILERESUME_RESUME:
+ openFlags = _O_BINARY | _O_WRONLY;
+ break;
+
+ case FILERESUME_OVERWRITE:
+ openFlags = _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY;
+ ft->dwFileBytesDone = 0;
+ break;
+
+ case FILERESUME_SKIP:
+ openFlags = _O_BINARY | _O_WRONLY;
+ ft->dwFileBytesDone = ft->dwThisFileSize;
+ break;
+
+ case FILERESUME_RENAME:
+ openFlags = _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY;
+ SAFE_FREE(&ft->szThisFile);
+ ft->szThisFile = null_strdup(szFilename);
+ ft->dwFileBytesDone = 0;
+ break;
+ }
+
+ ft->fileId = _open(ft->szThisFile, openFlags, _S_IREAD | _S_IWRITE);
+ if (ft->fileId == -1)
+ {
+ icq_LogMessage(LOG_ERROR, "Your file receive has been aborted because Miranda could not open the destination file in order to write to it. You may be trying to save to a read-only folder.");
+ Netlib_CloseHandle(ft->hConnection);
+ ft->hConnection = NULL;
+ return;
+ }
+
+ if (action == FILERESUME_RESUME)
+ ft->dwFileBytesDone = _lseek(ft->fileId, 0, SEEK_END);
+ else
+ _lseek(ft->fileId, ft->dwFileBytesDone, SEEK_SET);
+
+ ft->dwBytesDone += ft->dwFileBytesDone;
+
+ file_sendResume(dc);
+
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
+}
+
+
+
+// small utility function
+static void NormalizeBackslash(char* path)
+{
+ int len = strlennull(path);
+
+ if (len && path[len-1] != '\\') strcat(path, "\\");
+}
+
+
+
+/* a file transfer looks like this:
+S: 0
+R: 5
+R: 1
+S: 2
+R: 3
+S: 6 * many
+(for more files, send 2, 3, 6*many)
+*/
+void handleFileTransferPacket(directconnect* dc, PBYTE buf, WORD wLen)
+{
+ if (wLen < 1)
+ return;
+
+ NetLog_Direct("Handling file packet");
+
+ switch (buf[0])
+ {
+ case PEER_FILE_INIT: /* first packet of a file transfer */
+ if (dc->initialised)
+ return;
+ if (wLen < 19)
+ return;
+ buf += 5; /* id, and unknown 0 */
+ dc->type = DIRECTCONN_FILE;
+ {
+ DWORD dwFileCount;
+ DWORD dwTotalSize;
+ DWORD dwTransferSpeed;
+ WORD wNickLength;
+ int bAdded;
+
+ unpackLEDWord(&buf, &dwFileCount);
+ unpackLEDWord(&buf, &dwTotalSize);
+ unpackLEDWord(&buf, &dwTransferSpeed);
+ unpackLEWord(&buf, &wNickLength);
+
+ dc->ft = FindExpectedFileRecv(dc->dwRemoteUin, dwTotalSize);
+ if (dc->ft == NULL)
+ {
+ NetLog_Direct("Unexpected file receive");
+ CloseDirectConnection(dc);
+ return;
+ }
+ dc->ft->dwFileCount = dwFileCount;
+ dc->ft->dwTransferSpeed = dwTransferSpeed;
+ dc->ft->hContact = HContactFromUIN(dc->ft->dwUin, &bAdded);
+ dc->ft->dwBytesDone = 0;
+ dc->ft->iCurrentFile = -1;
+ dc->ft->fileId = -1;
+ dc->ft->hConnection = dc->hConnection;
+ dc->ft->dwLastNotify = GetTickCount();
+
+ dc->initialised = 1;
+
+ file_sendTransferSpeed(dc);
+ file_sendNick(dc);
+ }
+ ICQBroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, dc->ft, 0);
+ break;
+
+ case PEER_FILE_INIT_ACK:
+ if (wLen < 8)
+ return;
+ buf++;
+ unpackLEDWord(&buf, &dc->ft->dwTransferSpeed);
+ /* followed by nick */
+ file_sendNextFile(dc);
+ break;
+
+ case PEER_FILE_NEXTFILE:
+ if (wLen < 20)
+ return;
+ buf++; /* id */
+ {
+ WORD wThisFilenameLen, wSubdirLen;
+ BYTE isDirectory;
+ char *szFullPath;
+
+ unpackByte(&buf, &isDirectory);
+ unpackLEWord(&buf, &wThisFilenameLen);
+ if (wLen < 19 + wThisFilenameLen)
+ return;
+ SAFE_FREE(&dc->ft->szThisFile);
+ dc->ft->szThisFile = (char *)SAFE_MALLOC(wThisFilenameLen + 1);
+ memcpy(dc->ft->szThisFile, buf, wThisFilenameLen);
+ dc->ft->szThisFile[wThisFilenameLen] = '\0';
+ buf += wThisFilenameLen;
+
+ unpackLEWord(&buf, &wSubdirLen);
+ if (wLen < 18 + wThisFilenameLen + wSubdirLen)
+ return;
+ SAFE_FREE(&dc->ft->szThisSubdir);
+ dc->ft->szThisSubdir = (char *)SAFE_MALLOC(wSubdirLen + 1);
+ memcpy(dc->ft->szThisSubdir, buf, wSubdirLen);
+ dc->ft->szThisSubdir[wSubdirLen] = '\0';
+ buf += wSubdirLen;
+
+ unpackLEDWord(&buf, &dc->ft->dwThisFileSize);
+ unpackLEDWord(&buf, &dc->ft->dwThisFileDate);
+ unpackLEDWord(&buf, &dc->ft->dwTransferSpeed);
+
+ /* no cheating with paths */
+ if (strstr(dc->ft->szThisFile, "..\\") || strstr(dc->ft->szThisFile, "../") ||
+ strstr(dc->ft->szThisFile, ":\\") || strstr(dc->ft->szThisFile, ":/") ||
+ dc->ft->szThisFile[0] == '\\' || dc->ft->szThisFile[0] == '/')
+ {
+ NetLog_Direct("Invalid path information");
+ break;
+ }
+ if (strstr(dc->ft->szThisSubdir, "..\\") || strstr(dc->ft->szThisSubdir, "../") ||
+ strstr(dc->ft->szThisSubdir, ":\\") || strstr(dc->ft->szThisSubdir, ":/") ||
+ dc->ft->szThisSubdir[0] == '\\' || dc->ft->szThisSubdir[0] == '/')
+ {
+ NetLog_Direct("Invalid path information");
+ break;
+ }
+
+ szFullPath = (char*)SAFE_MALLOC(strlennull(dc->ft->szSavePath)+strlennull(dc->ft->szThisSubdir)+strlennull(dc->ft->szThisFile)+3);
+ strcpy(szFullPath, dc->ft->szSavePath);
+ NormalizeBackslash(szFullPath);
+ strcat(szFullPath, dc->ft->szThisSubdir);
+ NormalizeBackslash(szFullPath);
+ _chdir(szFullPath); // set current dir - not very useful
+ strcat(szFullPath, dc->ft->szThisFile);
+ // we joined the full path to dest file
+ SAFE_FREE(&dc->ft->szThisFile);
+ dc->ft->szThisFile = szFullPath;
+
+ dc->ft->dwFileBytesDone = 0;
+ dc->ft->iCurrentFile++;
+
+ if (isDirectory)
+ {
+ _mkdir(dc->ft->szThisFile);
+ dc->ft->fileId = -1;
+ }
+ else
+ {
+ /* file resume */
+ PROTOFILETRANSFERSTATUS pfts = {0};
+
+ file_buildProtoFileTransferStatus(dc->ft, &pfts);
+ if (ICQBroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, dc->ft, (LPARAM)&pfts))
+ break; /* UI supports resume: it will call PS_FILERESUME */
+
+ dc->ft->fileId = _open(dc->ft->szThisFile, _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY, _S_IREAD | _S_IWRITE);
+ if (dc->ft->fileId == -1)
+ {
+ icq_LogMessage(LOG_ERROR, "Your file receive has been aborted because Miranda could not open the destination file in order to write to it. You may be trying to save to a read-only folder.");
+ CloseDirectConnection(dc);
+ dc->ft->hConnection = NULL;
+ break;
+ }
+ }
+ }
+ file_sendResume(dc);
+ ICQBroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, dc->ft, 0);
+ break;
+
+ case PEER_FILE_RESUME:
+ if (dc->ft->fileId == -1 && !dc->ft->currentIsDir)
+ return;
+ if (wLen < 13)
+ return;
+ if (wLen < 17)
+ NetLog_Direct("Warning: Received short PEER_FILE_RESUME");
+ buf++;
+ {
+ DWORD dwRestartFrom;
+
+ unpackLEDWord(&buf, &dwRestartFrom);
+ if (dwRestartFrom > dc->ft->dwThisFileSize)
+ return;
+ buf += 4; /* unknown. 0 */
+ unpackLEDWord(&buf, &dc->ft->dwTransferSpeed);
+ buf += 4; /* unknown. 1 */
+ if (!dc->ft->currentIsDir)
+ _lseek(dc->ft->fileId, dwRestartFrom, 0);
+ dc->wantIdleTime = 1;
+ dc->ft->dwBytesDone += dwRestartFrom;
+ dc->ft->dwFileBytesDone += dwRestartFrom;
+ }
+ break;
+
+ case PEER_FILE_SPEED:
+ if (wLen < 5)
+ return;
+ buf++;
+ unpackLEDWord(&buf, &dc->ft->dwTransferSpeed);
+ dc->ft->dwLastNotify = GetTickCount();
+ break;
+
+ case PEER_FILE_DATA:
+ if (!dc->ft->currentIsDir)
+ {
+ if (dc->ft->fileId == -1)
+ break;
+ buf++; wLen--;
+ _write(dc->ft->fileId, buf, wLen);
+ }
+ else
+ wLen = 0;
+ dc->ft->dwBytesDone += wLen;
+ dc->ft->dwFileBytesDone += wLen;
+ if (GetTickCount() > dc->ft->dwLastNotify + 500 || wLen < 2048)
+ {
+ PROTOFILETRANSFERSTATUS pfts;
+
+ file_buildProtoFileTransferStatus(dc->ft, &pfts);
+ ICQBroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, dc->ft, (LPARAM)&pfts);
+ dc->ft->dwLastNotify = GetTickCount();
+ }
+ if (wLen < 2048)
+ {
+ /* EOF */
+ if (!dc->ft->currentIsDir)
+ _close(dc->ft->fileId);
+ dc->ft->fileId = -1;
+ if ((DWORD)dc->ft->iCurrentFile == dc->ft->dwFileCount - 1)
+ {
+ dc->type = DIRECTCONN_CLOSING; /* this guarantees that we won't accept any more data but that the sender is still free to closesocket() neatly */
+ ICQBroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, dc->ft, 0);
+ }
+ }
+ break;
+
+ default:
+ NetLog_Direct("Unknown file transfer packet ignored.");
+ break;
+ }
+}
diff --git a/icqj_mod/icq_firstrun.c b/icqj_mod/icq_firstrun.c new file mode 100644 index 0000000..86f0f29 --- /dev/null +++ b/icqj_mod/icq_firstrun.c @@ -0,0 +1,129 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_firstrun.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+BOOL CALLBACK icq_FirstRunDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+void icq_FirstRunCheck()
+{
+ if (ICQGetContactSettingByte(NULL, "FirstRun", 0))
+ return;
+
+ DialogBox(hInst, MAKEINTRESOURCE(IDD_ICQACCOUNT), NULL, icq_FirstRunDlgProc);
+}
+
+
+
+BOOL CALLBACK icq_FirstRunDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ char* pszPwd;
+ DWORD dwUIN;
+ char pszUIN[20];
+
+
+ ICQTranslateDialog(hwndDlg);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICQ)));
+
+ dwUIN = ICQGetContactSettingUIN(NULL);
+
+ if (dwUIN)
+ {
+ null_snprintf(pszUIN, 20, "%u", dwUIN);
+ SetDlgItemText(hwndDlg, IDC_UIN, pszUIN);
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_PW, EM_LIMITTEXT, 10, 0);
+ pszPwd = GetUserPassword(FALSE);
+ if (pszPwd)
+ {
+ SetDlgItemText(hwndDlg, IDC_PW, pszPwd);
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+
+ case IDC_REGISTER:
+ {
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM)URL_REGISTER);
+ break;
+ }
+
+ case IDOK:
+ {
+ char str[128];
+ DWORD dwUIN;
+
+ GetDlgItemText(hwndDlg, IDC_UIN, str, sizeof(str));
+ dwUIN = atoi(str);
+ ICQWriteContactSettingDword(NULL, UNIQUEIDSETTING, dwUIN);
+ GetDlgItemText(hwndDlg, IDC_PW, str, sizeof(str));
+ strcpy(gpszPassword, str);
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(str), (LPARAM) str);
+ ICQWriteContactSettingString(NULL, "Password", str);
+ }
+ // fall through
+
+ case IDCANCEL:
+ {
+ // Mark first run as completed
+ ICQWriteContactSettingByte(NULL, "FirstRun", 1);
+ EndDialog(hwndDlg, IDCANCEL);
+ }
+ break;
+
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/icqj_mod/icq_http.c b/icqj_mod/icq_http.c new file mode 100644 index 0000000..8afe50b --- /dev/null +++ b/icqj_mod/icq_http.c @@ -0,0 +1,213 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_http.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+int icq_httpGatewayInit(HANDLE hConn, NETLIBOPENCONNECTION *nloc, NETLIBHTTPREQUEST *nlhr)
+{
+ WORD wLen, wVersion, wType;
+ WORD wIpLen;
+ DWORD dwSid1, dwSid2, dwSid3, dwSid4;
+ BYTE response[300], *buf;
+ int responseBytes, recvResult;
+ char szSid[33], szHttpServer[256], szHttpGetUrl[300], szHttpPostUrl[300];
+ NETLIBHTTPPROXYINFO nlhpi = {0};
+
+
+ for (responseBytes = 0; ; )
+ {
+ recvResult = Netlib_Recv(hConn, response + responseBytes, sizeof(response) - responseBytes, MSG_DUMPPROXY);
+ if(recvResult<=0) break;
+ responseBytes += recvResult;
+ if(responseBytes == sizeof(response))
+ break;
+ }
+
+ if (responseBytes < 31)
+ {
+ SetLastError(ERROR_INVALID_DATA);
+ return 0;
+ }
+
+ buf = response;
+ unpackWord(&buf, &wLen);
+ unpackWord(&buf, &wVersion); /* always 0x0443 */
+ unpackWord(&buf, &wType); /* hello reply */
+ buf += 6; /* dunno */
+ unpackDWord(&buf, &dwSid1);
+ unpackDWord(&buf, &dwSid2);
+ unpackDWord(&buf, &dwSid3);
+ unpackDWord(&buf, &dwSid4);
+ null_snprintf(szSid, 33, "%08x%08x%08x%08x", dwSid1, dwSid2, dwSid3, dwSid4);
+ unpackWord(&buf, &wIpLen);
+
+ if(responseBytes < 30 + wIpLen || wIpLen == 0 || wIpLen > sizeof(szHttpServer) - 1)
+ {
+ SetLastError(ERROR_INVALID_DATA);
+ return 0;
+ }
+
+ SetGatewayIndex(hConn, 1); // new master connection begins here
+
+ memcpy(szHttpServer, buf, wIpLen);
+ szHttpServer[wIpLen] = '\0';
+
+ nlhpi.cbSize = sizeof(nlhpi);
+ nlhpi.flags = NLHPIF_USEPOSTSEQUENCE;
+ nlhpi.szHttpGetUrl = szHttpGetUrl;
+ nlhpi.szHttpPostUrl = szHttpPostUrl;
+ nlhpi.firstPostSequence = 1;
+ null_snprintf(szHttpGetUrl, 300, "http://%s/monitor?sid=%s", szHttpServer, szSid);
+ null_snprintf(szHttpPostUrl, 300, "http://%s/data?sid=%s&seq=", szHttpServer, szSid);
+
+ return CallService(MS_NETLIB_SETHTTPPROXYINFO, (WPARAM)hConn, (LPARAM)&nlhpi);
+}
+
+
+
+int icq_httpGatewayBegin(HANDLE hConn, NETLIBOPENCONNECTION* nloc)
+{
+ icq_packet packet;
+ int serverNameLen;
+
+ serverNameLen = strlennull(nloc->szHost);
+
+ packet.wLen = (WORD)(serverNameLen + 4);
+ write_httphdr(&packet, HTTP_PACKETTYPE_LOGIN, GetGatewayIndex(hConn));
+ packWord(&packet, (WORD)serverNameLen);
+ packBuffer(&packet, nloc->szHost, (WORD)serverNameLen);
+ packWord(&packet, nloc->wPort);
+ Netlib_Send(hConn, packet.pData, packet.wLen, MSG_DUMPPROXY|MSG_NOHTTPGATEWAYWRAP);
+ SAFE_FREE(&packet.pData);
+
+ return 1;
+}
+
+
+
+int icq_httpGatewayWrapSend(HANDLE hConn, PBYTE buf, int len, int flags, MIRANDASERVICE pfnNetlibSend)
+{
+ icq_packet packet;
+ int sendResult;
+
+ packet.wLen = len;
+ write_httphdr(&packet, HTTP_PACKETTYPE_FLAP, GetGatewayIndex(hConn));
+ packBuffer(&packet, buf, (WORD)len);
+ sendResult = Netlib_Send(hConn, packet.pData, packet.wLen, flags);
+ SAFE_FREE(&packet.pData);
+
+ if(sendResult <= 0)
+ return sendResult;
+
+ if(sendResult < 14)
+ return 0;
+
+ return sendResult - 14;
+}
+
+
+
+PBYTE icq_httpGatewayUnwrapRecv(NETLIBHTTPREQUEST* nlhr, PBYTE buf, int len, int* outBufLen, void *(*NetlibRealloc)(void *, size_t))
+{
+ WORD wLen, wType;
+ DWORD dwPackSeq;
+ PBYTE tbuf;
+ int i, copyBytes;
+
+
+ tbuf = buf;
+ for(i = 0;;)
+ {
+ if (tbuf - buf + 2 > len)
+ break;
+ unpackWord(&tbuf, &wLen);
+ if (wLen < 12)
+ break;
+ if (tbuf - buf + wLen > len)
+ break;
+ tbuf += 2; /* version */
+ unpackWord(&tbuf, &wType);
+ tbuf += 4; /* flags */
+ unpackDWord(&tbuf, &dwPackSeq);
+ if (wType == HTTP_PACKETTYPE_FLAP)
+ {
+ copyBytes = wLen - 12;
+ if (copyBytes > len - i)
+ {
+ /* invalid data - do our best to get something out of it */
+ copyBytes = len - i;
+ }
+ memcpy(buf + i, tbuf, copyBytes);
+ i += copyBytes;
+ }
+ else if (wType == HTTP_PACKETTYPE_LOGINREPLY)
+ {
+ BYTE bRes;
+
+ unpackByte(&tbuf, &bRes);
+ wLen -= 1;
+ if (!bRes)
+ NetLog_Server("Gateway Connection #%d Established.", dwPackSeq);
+ else
+ NetLog_Server("Gateway Connection #%d Failed, error: %d", dwPackSeq, bRes);
+ }
+ else if (wType == HTTP_PACKETTYPE_CLOSEREPLY)
+ {
+ NetLog_Server("Gateway Connection #%d Closed.", dwPackSeq);
+ }
+ tbuf += wLen - 12;
+ }
+ *outBufLen = i;
+
+ return buf;
+}
+
+
+int icq_httpGatewayWalkTo(HANDLE hConn, NETLIBOPENCONNECTION* nloc)
+{
+ icq_packet packet;
+ DWORD dwGatewaySeq = GetGatewayIndex(hConn);
+
+ packet.wLen = 0;
+ write_httphdr(&packet, HTTP_PACKETTYPE_CLOSE, dwGatewaySeq);
+ Netlib_Send(hConn, packet.pData, packet.wLen, MSG_DUMPPROXY|MSG_NOHTTPGATEWAYWRAP);
+ // we closed virtual connection, open new one
+ dwGatewaySeq++;
+ SetGatewayIndex(hConn, dwGatewaySeq);
+ return icq_httpGatewayBegin(hConn, nloc);
+}
diff --git a/icqj_mod/icq_http.h b/icqj_mod/icq_http.h new file mode 100644 index 0000000..12c8ab3 --- /dev/null +++ b/icqj_mod/icq_http.h @@ -0,0 +1,55 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_http.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_HTTP_H
+#define __ICQ_HTTP_H
+
+#define HTTP_PROXY_VERSION 0x0443
+
+#define HTTP_PACKETTYPE_HELLOREPLY 2
+#define HTTP_PACKETTYPE_LOGIN 3
+#define HTTP_PACKETTYPE_LOGINREPLY 4 /* contains 1 byte: 0 */
+#define HTTP_PACKETTYPE_FLAP 5
+#define HTTP_PACKETTYPE_CLOSE 6 /* contains no data */
+#define HTTP_PACKETTYPE_CLOSEREPLY 7 /* contains 1 byte: 0 */
+
+int icq_httpGatewayInit(HANDLE hConn, NETLIBOPENCONNECTION *nloc, NETLIBHTTPREQUEST *nlhr);
+int icq_httpGatewayBegin(HANDLE hConn, NETLIBOPENCONNECTION *nloc);
+int icq_httpGatewayWrapSend(HANDLE hConn, PBYTE buf, int len, int flags, MIRANDASERVICE pfnNetlibSend);
+PBYTE icq_httpGatewayUnwrapRecv(NETLIBHTTPREQUEST *nlhr, PBYTE buf, int bufLen, int *outBufLen, void *(*NetlibRealloc)(void *, size_t));
+int icq_httpGatewayWalkTo(HANDLE hConn, NETLIBOPENCONNECTION* nloc);
+
+#endif /* __ICQ_HTTP_H */
diff --git a/icqj_mod/icq_infoupdate.c b/icqj_mod/icq_infoupdate.c new file mode 100644 index 0000000..a9a80d3 --- /dev/null +++ b/icqj_mod/icq_infoupdate.c @@ -0,0 +1,355 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_infoupdate.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+#define LISTSIZE 100
+static CRITICAL_SECTION listmutex;
+static HANDLE hQueueEvent = NULL;
+static HANDLE hDummyEvent = NULL;
+static int nUserCount = 0;
+static int bPendingUsers = 0;
+static BOOL bEnabled = TRUE;
+static BOOL bPaused = FALSE;
+static BOOL bRunning = FALSE;
+static DWORD tLast;
+static HANDLE hInfoThread = NULL;
+static DWORD dwUpdateThreshold;
+typedef struct s_userinfo {
+ DWORD dwUin;
+ HANDLE hContact;
+} userinfo;
+static userinfo userList[LISTSIZE];
+
+
+// Retrieve users' info
+unsigned __stdcall icq_InfoUpdateThread(void* arg);
+
+
+
+void icq_InitInfoUpdate(void)
+{
+ int i;
+
+ // Create wait objects
+ hQueueEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ hDummyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ if (hQueueEvent && hDummyEvent)
+ {
+ // Init mutexes
+ InitializeCriticalSection(&listmutex);
+
+ // Init list
+ for (i = 0; i<LISTSIZE; i++)
+ {
+ userList[i].dwUin = 0;
+ userList[i].hContact = NULL;
+ }
+
+ dwUpdateThreshold = ICQGetContactSettingByte(NULL, "InfoUpdate", UPDATE_THRESHOLD/(3600*24))*3600*24;
+
+ hInfoThread = (HANDLE)forkthreadex(NULL, 0, icq_InfoUpdateThread, 0, 0, (DWORD*)&hInfoThread);
+ }
+
+ bPendingUsers = 0;
+}
+
+// Returns TRUE if user was queued
+// Returns FALSE if the list was full
+BOOL icq_QueueUser(HANDLE hContact)
+{
+ if (nUserCount < LISTSIZE)
+ {
+ int i, nChecked = 0, nFirstFree = -1;
+ BOOL bFound = FALSE;
+
+ EnterCriticalSection(&listmutex);
+
+ // Check if in list
+ for (i = 0; (i<LISTSIZE && nChecked<nUserCount); i++)
+ {
+ if (userList[i].hContact)
+ {
+ nChecked++;
+ if (userList[i].hContact == hContact)
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+ else if (nFirstFree == -1)
+ {
+ nFirstFree = i;
+ }
+ }
+ if (nFirstFree == -1)
+ nFirstFree = i;
+
+ // Add to list
+ if (!bFound)
+ {
+ DWORD dwUin = ICQGetContactSettingUIN(hContact);
+
+ if (dwUin)
+ {
+ userList[nFirstFree].dwUin = dwUin;
+ userList[nFirstFree].hContact = hContact;
+ nUserCount++;
+#ifdef _DEBUG
+ NetLog_Server("Queued user %u, place %u, count %u", userList[nFirstFree].dwUin, nFirstFree, nUserCount);
+#endif
+ // Notify worker thread
+ if (hQueueEvent)
+ SetEvent(hQueueEvent);
+ }
+ }
+
+ LeaveCriticalSection(&listmutex);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+void icq_DequeueUser(DWORD dwUin)
+{
+ if (nUserCount > 0)
+ {
+ int i, nChecked = 0;
+ // Check if in list
+ EnterCriticalSection(&listmutex);
+ for (i = 0; (i<LISTSIZE && nChecked<nUserCount); i++)
+ {
+ if (userList[i].dwUin)
+ {
+ nChecked++;
+ // Remove from list
+ if (userList[i].dwUin == dwUin)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Dequeued user %u", userList[i].dwUin);
+#endif
+ userList[i].dwUin = 0;
+ userList[i].hContact = NULL;
+ nUserCount--;
+ break;
+ }
+ }
+ }
+ LeaveCriticalSection(&listmutex);
+ }
+}
+
+
+
+void icq_RescanInfoUpdate()
+{
+ HANDLE hContact = NULL;
+ DWORD dwCurrentTime = 0;
+ BOOL bOldEnable = bEnabled;
+
+ bPendingUsers = 0;
+ /* This is here, cause we do not want to emit large number of reuqest at once,
+ fill queue, and let thread deal with it */
+ bEnabled = 0; // freeze thread
+ // Queue all outdated users
+ dwCurrentTime = time(NULL);
+ hContact = ICQFindFirstContact();
+
+ while (hContact != NULL)
+ {
+ if ((dwCurrentTime - ICQGetContactSettingDword(hContact, "InfoTS", 0)) > dwUpdateThreshold)
+ {
+ // Queue user
+ if (!icq_QueueUser(hContact))
+ { // The queue is full, pause queuing contacts
+ bPendingUsers = 1;
+ break;
+ }
+ }
+ hContact = ICQFindNextContact(hContact);
+ }
+ icq_EnableUserLookup(bOldEnable); // wake up thread
+}
+
+
+
+void icq_EnableUserLookup(BOOL bEnable)
+{
+ bEnabled = bEnable;
+
+ if (bEnabled) bPaused = FALSE;
+
+ // Notify worker thread
+ if (bEnabled && hQueueEvent)
+ SetEvent(hQueueEvent);
+}
+
+
+
+void icq_PauseUserLookup()
+{
+ bPaused = TRUE;
+ tLast = GetTickCount();
+
+#ifdef _DEBUG
+ NetLog_Server("Pausing Auto-info update thread...");
+#endif
+}
+
+
+
+unsigned __stdcall icq_InfoUpdateThread(void* arg)
+{
+ int i;
+ DWORD dwWait;
+
+ bRunning = TRUE;
+
+ while (bRunning)
+ {
+ // Wait for a while
+ ResetEvent(hQueueEvent);
+
+ if (!nUserCount && bPendingUsers) // whole queue processed, check if more users needs updating
+ icq_RescanInfoUpdate();
+
+ if ((nUserCount > 0) && bEnabled && icqOnline)
+ dwWait = WaitForSingleObjectEx(hDummyEvent, 3000, TRUE);
+ else
+ { // we need to slow down the process or icq will kick us
+ dwWait = WaitForSingleObjectEx(hDummyEvent, 1000, TRUE);
+ while (bRunning && dwWait == WAIT_TIMEOUT)
+ { // wait for new work or until we should end
+ dwWait = WaitForSingleObjectEx(hQueueEvent, 10000, TRUE);
+ }
+ }
+ if (!bRunning) break;
+
+ switch (dwWait)
+ {
+ case WAIT_IO_COMPLETION:
+ // Possible shutdown in progress
+ break;
+
+ case WAIT_OBJECT_0:
+ case WAIT_TIMEOUT:
+ // Time to check for new users
+ if (!bEnabled) continue; // we can't send requests now
+
+ if (bPaused)
+ { // pause for 30sec
+ if (GetTickCount()-tLast>30000)
+ {
+ bPaused = FALSE;
+#ifdef _DEBUG
+ NetLog_Server("Resuming auto-info update thread...");
+#endif
+ }
+ continue;
+ }
+ tLast = GetTickCount();
+
+#ifdef _DEBUG
+ NetLog_Server("Users %u", nUserCount);
+#endif
+ if (nUserCount && icqOnline)
+ {
+ EnterCriticalSection(&listmutex);
+ for (i = 0; i<LISTSIZE; i++)
+ {
+ if (userList[i].hContact)
+ {
+ // Check TS again, maybe it has been updated while we slept
+ if ((time(NULL) - ICQGetContactSettingDword(userList[i].hContact, "InfoTS", 0)) > dwUpdateThreshold) {
+#ifdef _DEBUG
+ NetLog_Server("Request info for user %u", userList[i].dwUin);
+#endif
+ sendUserInfoAutoRequest(userList[i].dwUin);
+
+ // Dequeue user and go back to sleep
+ userList[i].dwUin = 0;
+ userList[i].hContact = NULL;
+ nUserCount--;
+ break;
+ }
+ else
+ {
+#ifdef _DEBUG
+ NetLog_Server("Dequeued absolete user %u", userList[i].dwUin);
+#endif
+ // Dequeue user and find another one
+ userList[i].dwUin = 0;
+ userList[i].hContact = NULL;
+ nUserCount--;
+ // continue for loop
+ }
+ }
+ }
+ LeaveCriticalSection(&listmutex);
+ }
+ break;
+
+ default:
+ // Something strange happened. Exit
+ bRunning = FALSE;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+
+// Clean up before exit
+void icq_InfoUpdateCleanup(void)
+{
+ bRunning = FALSE;
+ SetEvent(hDummyEvent); // break timeout
+ SetEvent(hQueueEvent); // break queue loop
+ if (hInfoThread) WaitForSingleObjectEx(hInfoThread, INFINITE, TRUE);
+ // Uninit mutex
+ DeleteCriticalSection(&listmutex);
+ CloseHandle(hQueueEvent);
+ CloseHandle(hDummyEvent);
+ CloseHandle(hInfoThread);
+}
diff --git a/icqj_mod/icq_infoupdate.h b/icqj_mod/icq_infoupdate.h new file mode 100644 index 0000000..99d307c --- /dev/null +++ b/icqj_mod/icq_infoupdate.h @@ -0,0 +1,58 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_infoupdate.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+// Queues all outdated users
+void icq_InitInfoUpdate(void);
+
+// Queue one UIN to the list for updating
+BOOL icq_QueueUser(HANDLE hContact);
+
+// Remove one UIN from the list
+void icq_DequeueUser(DWORD dwUin);
+
+// Add all outdated contacts to the list
+void icq_RescanInfoUpdate();
+
+// Clean up on exit
+void icq_InfoUpdateCleanup(void);
+
+// Enable/disable user info lookups
+void icq_EnableUserLookup(BOOL bEnable);
+
+// Pause user info lookup for 30sec
+void icq_PauseUserLookup();
diff --git a/icqj_mod/icq_opts.c b/icqj_mod/icq_opts.c new file mode 100644 index 0000000..b70f14e --- /dev/null +++ b/icqj_mod/icq_opts.c @@ -0,0 +1,870 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_opts.c,v $
+// Revision : $Revision: 3251 $
+// Last change on : $Date: 2006-06-30 00:12:33 +0200 (Fri, 30 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#include <win2k.h>
+#include <uxtheme.h>
+
+
+static BOOL CALLBACK DlgProcIcqMain(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqContactsOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqFeaturesOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqPrivacyOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+static const char* szLogLevelDescr[] = {"Display all problems", "Display problems causing possible loss of data", "Display explanations for disconnection", "Display problems requiring user intervention"};
+
+static BOOL (WINAPI *pfnEnableThemeDialogTexture)(HANDLE, DWORD) = 0;
+
+
+static void AddUniPageUtf(const char* szService, OPTIONSDIALOGPAGE *op, WPARAM wParam, const char *szGroup, const char *szTitle)
+{
+ char str[MAX_PATH];
+ char *pszTitle;
+
+ if (strstr(szTitle, "%s"))
+ {
+ char *lTitle = ICQTranslateUtfStatic(szTitle, str);
+ int size = strlennull(lTitle) + strlennull(gpszICQProtoName);
+
+ pszTitle = (char*)_alloca(size);
+ null_snprintf(pszTitle, size, lTitle, gpszICQProtoName);
+ }
+ else
+ pszTitle = (char*)ICQTranslateUtfStatic(szTitle, str);
+
+ if (gbUnicodeCore)
+ {
+ wchar_t *utitle, *ugroup;
+
+ utitle = make_unicode_string(pszTitle);
+ if (szGroup)
+ ugroup = make_unicode_string(ICQTranslateUtfStatic(szGroup, str));
+ else
+ ugroup = NULL;
+ op->pszTitle = (char*)utitle; // this is union with ptszTitle
+ op->pszGroup = (char*)ugroup;
+ op->flags |= ODPF_UNICODE;
+ CallService(szService, wParam, (LPARAM)op);
+ SAFE_FREE(&utitle);
+ SAFE_FREE(&ugroup);
+ }
+ else
+ {
+ char *title, *group, *tmp;
+ int size;
+
+ size = strlennull(pszTitle) + 2;
+ title = (char*)_alloca(size);
+ utf8_decode_static(pszTitle, title, size);
+ if (szGroup)
+ {
+ tmp = ICQTranslateUtfStatic(szGroup, str);
+ size = strlennull(tmp) + 2;
+ group = (char*)_alloca(size);
+ utf8_decode_static(tmp, group, size);
+ }
+ else
+ group = NULL;
+ op->pszTitle = title;
+ op->pszGroup = group;
+ CallService(szService, wParam, (LPARAM)op);
+ }
+}
+
+
+
+void AddOptionsPageUtf(OPTIONSDIALOGPAGE *op, WPARAM wParam, const char *szGroup, const char *szTitle)
+{
+ AddUniPageUtf(MS_OPT_ADDPAGE, op, wParam, szGroup, szTitle);
+}
+
+
+
+void AddUserInfoPageUtf(OPTIONSDIALOGPAGE *op, WPARAM wParam, const char *szTitle)
+{
+ AddUniPageUtf(MS_USERINFO_ADDPAGE, op, wParam, NULL, szTitle);
+}
+
+
+HWND hOptBasic = 0, hOptContacts = 0, hOptFeatures = 0, hOptPrivacy = 0;
+
+static void TabOptions_AddItemUtf(HWND hTabCtrl, const char* szTitle, HWND hPage)
+{
+ TCITEM tci = {0};
+ RECT rcClient;
+ char* szTitleUtf;
+ int iTotal;
+
+ GetClientRect(GetParent(hTabCtrl), &rcClient);
+
+ szTitleUtf = ICQTranslateUtf(szTitle);
+
+ iTotal = TabCtrl_GetItemCount(hTabCtrl);
+
+ tci.mask = TCIF_PARAM|TCIF_TEXT;
+ tci.lParam = (LPARAM)hPage;
+ if (gbUnicodeAPI)
+ {
+ tci.pszText = (char*)make_unicode_string(szTitleUtf);
+ SendMessageW(hTabCtrl, TCM_INSERTITEMW, iTotal, (WPARAM)&tci);
+ }
+ else
+ {
+ utf8_decode(szTitleUtf, &tci.pszText);
+ SendMessageA(hTabCtrl, TCM_INSERTITEMA, iTotal, (WPARAM)&tci);
+ }
+ SAFE_FREE(&tci.pszText);
+ SAFE_FREE(&szTitleUtf);
+
+ MoveWindow(hPage, 3, 24, rcClient.right - 6, rcClient.bottom - 28, 1);
+}
+
+static void SetOptionsDlgToType(HWND hwnd, int iExpert)
+{
+ HWND hwndTab = GetDlgItem(hwnd, IDC_OPTIONSTAB), hwndEnum;
+
+ if (!hOptBasic)
+ {
+ hOptBasic = CreateDialogUtf(hInst, MAKEINTRESOURCE(IDD_OPT_ICQ), hwnd, DlgProcIcqOpts);
+ if (pfnEnableThemeDialogTexture)
+ pfnEnableThemeDialogTexture(hOptBasic, ETDT_ENABLETAB);
+ }
+
+ hwndEnum = GetWindow(hOptBasic, GW_CHILD);
+
+ while (hwndEnum)
+ { // too bad
+ ShowWindow(hwndEnum, iExpert ? SW_SHOW : SW_HIDE);
+ hwndEnum = GetWindow(hwndEnum, GW_HWNDNEXT);
+ }
+
+ if (!iExpert)
+ {
+ hwndEnum = GetDlgItem(hOptBasic, IDC_STICQGROUP);
+ ShowWindow(hwndEnum, SW_SHOW);
+ hwndEnum = GetWindow(hwndEnum, GW_HWNDNEXT);
+ do {
+ ShowWindow(hwndEnum, SW_SHOW);
+ hwndEnum = GetWindow(hwndEnum, GW_HWNDNEXT);
+ } while(hwndEnum && hwndEnum != GetDlgItem(hOptBasic, IDC_NEWUINLINK));
+ }
+ ShowWindow(hwndEnum, SW_SHOW);
+ TabCtrl_DeleteAllItems(hwndTab);
+
+ TabOptions_AddItemUtf(hwndTab, "Account", hOptBasic);
+
+ if (!hOptContacts)
+ {
+ hOptContacts = CreateDialogUtf(hInst, MAKEINTRESOURCE(IDD_OPT_ICQCONTACTS), hwnd, DlgProcIcqContactsOpts);
+ if (pfnEnableThemeDialogTexture)
+ pfnEnableThemeDialogTexture(hOptContacts, ETDT_ENABLETAB);
+ }
+
+ if (!hOptFeatures)
+ {
+ hOptFeatures = CreateDialogUtf(hInst, MAKEINTRESOURCE(IDD_OPT_ICQFEATURES), hwnd, DlgProcIcqFeaturesOpts);
+ if (pfnEnableThemeDialogTexture)
+ pfnEnableThemeDialogTexture(hOptFeatures, ETDT_ENABLETAB);
+ }
+
+ if (!hOptPrivacy)
+ {
+ hOptPrivacy = CreateDialogUtf(hInst, MAKEINTRESOURCE(IDI_PRIVACY), hwnd, DlgProcIcqPrivacyOpts);
+ if (pfnEnableThemeDialogTexture)
+ pfnEnableThemeDialogTexture(hOptPrivacy, ETDT_ENABLETAB);
+ }
+
+ ShowWindow(hOptContacts, SW_HIDE);
+ ShowWindow(hOptPrivacy, SW_HIDE);
+ if (hOptFeatures)
+ ShowWindow(hOptFeatures, SW_HIDE);
+ ShowWindow(hOptBasic, SW_SHOW);
+
+ TabOptions_AddItemUtf(hwndTab, "Contacts", hOptContacts);
+ if (iExpert)
+ TabOptions_AddItemUtf(hwndTab, "Features", hOptFeatures);
+ TabOptions_AddItemUtf(hwndTab, "Privacy", hOptPrivacy);
+
+ TabCtrl_SetCurSel(hwndTab, 0);
+}
+
+
+int IcqOptInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+ HMODULE hUxTheme = 0;
+
+ if (IsWinVerXPPlus())
+ {
+ hUxTheme = GetModuleHandle("uxtheme.dll");
+
+ if (hUxTheme)
+ pfnEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
+ }
+
+ odp.cbSize = sizeof(odp);
+ odp.position = -800000000;
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_ICQMAIN);
+ odp.pfnDlgProc = DlgProcIcqMain;
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.nIDBottomSimpleControl = 0;
+ AddOptionsPageUtf(&odp, wParam, "Network", gpszICQProtoName);
+
+ InitPopupOpts(wParam);
+
+ return 0;
+}
+
+
+
+static void LoadDBCheckState(HWND hwndDlg, int idCtrl, const char* szSetting, BYTE bDef)
+{
+ CheckDlgButton(hwndDlg, idCtrl, ICQGetContactSettingByte(NULL, szSetting, bDef));
+}
+
+
+
+static void StoreDBCheckState(HWND hwndDlg, int idCtrl, const char* szSetting)
+{
+ ICQWriteContactSettingByte(NULL, szSetting, (BYTE)IsDlgButtonChecked(hwndDlg, idCtrl));
+}
+
+
+
+static void OptDlgChanged(HWND hwndDlg)
+{
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+}
+
+
+// tabbed options page wrapper
+
+static BOOL CALLBACK DlgProcIcqMain(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int iInit = TRUE;
+
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ int iExpert;
+
+ iInit = TRUE;
+ iExpert = SendMessage(GetParent(hwnd), PSM_ISEXPERT, 0, 0);
+ SetOptionsDlgToType(hwnd, iExpert);
+ iInit = FALSE;
+ return FALSE;
+ }
+
+ case WM_DESTROY:
+ hOptBasic = hOptContacts = hOptFeatures = hOptPrivacy = 0;
+ break;
+
+ case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0);
+ if (!iInit) OptDlgChanged(hwnd);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ TCITEM tci;
+ int i,count;
+
+ tci.mask = TCIF_PARAM;
+ count = TabCtrl_GetItemCount(GetDlgItem(hwnd,IDC_OPTIONSTAB));
+ for (i=0; i<count; i++)
+ {
+ TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),i,&tci);
+ SendMessage((HWND)tci.lParam,WM_NOTIFY,0,lParam);
+ }
+ break;
+ }
+
+ case PSN_EXPERTCHANGED:
+ {
+ int iExpert = SendMessage(GetParent(hwnd), PSM_ISEXPERT, 0, 0);
+
+ SetOptionsDlgToType(hwnd, iExpert);
+ break;
+ }
+ }
+ break;
+
+ case IDC_OPTIONSTAB:
+ {
+ HWND hTabCtrl = GetDlgItem(hwnd, IDC_OPTIONSTAB);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case TCN_SELCHANGING:
+ {
+ TCITEM tci;
+
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hTabCtrl, TabCtrl_GetCurSel(hTabCtrl), &tci);
+ ShowWindow((HWND)tci.lParam, SW_HIDE);
+ }
+ break;
+
+ case TCN_SELCHANGE:
+ {
+ TCITEM tci;
+
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hTabCtrl, TabCtrl_GetCurSel(hTabCtrl), &tci);
+ ShowWindow((HWND)tci.lParam,SW_SHOW);
+ }
+ break;
+ }
+ break;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+// standalone option pages
+
+static BOOL CALLBACK DlgProcIcqOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ char pszPwd[16];
+ char szServer[MAX_PATH];
+
+ ICQTranslateDialog(hwndDlg);
+
+ SetDlgItemInt(hwndDlg, IDC_ICQNUM, ICQGetContactSettingUIN(NULL), FALSE);
+
+ if (!ICQGetContactStaticString(NULL, "Password", pszPwd, sizeof(pszPwd)))
+ {
+ CallService(MS_DB_CRYPT_DECODESTRING, strlennull(pszPwd) + 1, (LPARAM)pszPwd);
+
+ //bit of a security hole here, since it's easy to extract a password from an edit box
+ SetDlgItemText(hwndDlg, IDC_PASSWORD, pszPwd);
+ }
+
+ if (!ICQGetContactStaticString(NULL, "OscarServer", szServer, MAX_PATH))
+ {
+ SetDlgItemText(hwndDlg, IDC_ICQSERVER, szServer);
+ }
+ else
+ {
+ SetDlgItemText(hwndDlg, IDC_ICQSERVER, DEFAULT_SERVER_HOST);
+ }
+
+ SetDlgItemInt(hwndDlg, IDC_ICQPORT, ICQGetContactSettingWord(NULL, "OscarPort", DEFAULT_SERVER_PORT), FALSE);
+ LoadDBCheckState(hwndDlg, IDC_KEEPALIVE, "KeepAlive", 1);
+ LoadDBCheckState(hwndDlg, IDC_USEGATEWAY, "UseGateway", 0);
+ LoadDBCheckState(hwndDlg, IDC_SECURE, "SecureLogin", DEFAULT_SECURE_LOGIN);
+ SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_SETRANGE, FALSE, MAKELONG(0, 3));
+ SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_SETPOS, TRUE, 3-ICQGetContactSettingByte(NULL, "ShowLogLevel", LOG_WARNING));
+ SetDlgItemTextUtf(hwndDlg, IDC_LEVELDESCR, ICQTranslateUtfStatic(szLogLevelDescr[3-SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_GETPOS, 0, 0)], szServer));
+ ShowWindow(GetDlgItem(hwndDlg, IDC_RECONNECTREQD), SW_HIDE);
+ LoadDBCheckState(hwndDlg, IDC_NOERRMULTI, "IgnoreMultiErrorBox", 0);
+
+ return TRUE;
+ }
+
+ case WM_HSCROLL:
+ {
+ char str[MAX_PATH];
+
+ SetDlgItemTextUtf(hwndDlg, IDC_LEVELDESCR, ICQTranslateUtfStatic(szLogLevelDescr[3-SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL,TBM_GETPOS, 0, 0)], str));
+ OptDlgChanged(hwndDlg);
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+
+ case IDC_LOOKUPLINK:
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM)URL_FORGOT_PASSWORD);
+ return TRUE;
+
+ case IDC_NEWUINLINK:
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM)URL_REGISTER);
+ return TRUE;
+
+ case IDC_RESETSERVER:
+ SetDlgItemText(hwndDlg, IDC_ICQSERVER, DEFAULT_SERVER_HOST);
+ SetDlgItemInt(hwndDlg, IDC_ICQPORT, DEFAULT_SERVER_PORT, FALSE);
+ OptDlgChanged(hwndDlg);
+ return TRUE;
+ }
+
+ if (icqOnline && LOWORD(wParam) != IDC_NOERRMULTI)
+ {
+ char szClass[80];
+
+
+ GetClassName((HWND)lParam, szClass, sizeof(szClass));
+
+ if (lstrcmpi(szClass, "EDIT") || HIWORD(wParam) == EN_CHANGE)
+ ShowWindow(GetDlgItem(hwndDlg, IDC_RECONNECTREQD), SW_SHOW);
+ }
+
+ if ((LOWORD(wParam)==IDC_ICQNUM || LOWORD(wParam)==IDC_PASSWORD || LOWORD(wParam)==IDC_ICQSERVER || LOWORD(wParam)==IDC_ICQPORT) &&
+ (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus()))
+ {
+ return 0;
+ }
+
+ OptDlgChanged(hwndDlg);
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ case PSN_APPLY:
+ {
+ char str[128];
+
+ ICQWriteContactSettingDword(NULL, UNIQUEIDSETTING, (DWORD)GetDlgItemInt(hwndDlg, IDC_ICQNUM, NULL, FALSE));
+ GetDlgItemText(hwndDlg, IDC_PASSWORD, str, sizeof(str));
+ if (strlennull(str))
+ {
+ strcpy(gpszPassword, str);
+ gbRememberPwd = TRUE;
+ }
+ else
+ {
+ gbRememberPwd = ICQGetContactSettingByte(NULL, "RememberPass", 0);
+ }
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(str), (LPARAM)str);
+ ICQWriteContactSettingString(NULL, "Password", str);
+ GetDlgItemText(hwndDlg,IDC_ICQSERVER, str, sizeof(str));
+ ICQWriteContactSettingString(NULL, "OscarServer", str);
+ ICQWriteContactSettingWord(NULL, "OscarPort", (WORD)GetDlgItemInt(hwndDlg, IDC_ICQPORT, NULL, FALSE));
+ StoreDBCheckState(hwndDlg, IDC_KEEPALIVE, "KeepAlive");
+ StoreDBCheckState(hwndDlg, IDC_USEGATEWAY, "UseGateway");
+ StoreDBCheckState(hwndDlg, IDC_SECURE, "SecureLogin");
+ StoreDBCheckState(hwndDlg, IDC_NOERRMULTI, "IgnoreMultiErrorBox");
+ ICQWriteContactSettingByte(NULL, "ShowLogLevel", (BYTE)(3-SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_GETPOS, 0, 0)));
+
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+
+static const UINT icqPrivacyControls[]={IDC_DCALLOW_ANY, IDC_DCALLOW_CLIST, IDC_DCALLOW_AUTH, IDC_ADD_ANY, IDC_ADD_AUTH, IDC_WEBAWARE, IDC_PUBLISHPRIMARY, IDC_STATIC_DC1, IDC_STATIC_DC2, IDC_STATIC_CLIST};
+static BOOL CALLBACK DlgProcIcqPrivacyOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ int nDcType;
+ int nAddAuth;
+
+ nDcType = ICQGetContactSettingByte(NULL, "DCType", 0);
+ nAddAuth = ICQGetContactSettingByte(NULL, "Auth", 1);
+
+ ICQTranslateDialog(hwndDlg);
+ if (!icqOnline)
+ {
+ icq_EnableMultipleControls(hwndDlg, icqPrivacyControls, sizeof(icqPrivacyControls)/sizeof(icqPrivacyControls[0]), FALSE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_STATIC_NOTONLINE), SW_SHOW);
+ }
+ else
+ {
+ ShowWindow(GetDlgItem(hwndDlg, IDC_STATIC_NOTONLINE), SW_HIDE);
+ }
+ CheckDlgButton(hwndDlg, IDC_DCALLOW_ANY, (nDcType == 0));
+ CheckDlgButton(hwndDlg, IDC_DCALLOW_CLIST, (nDcType == 1));
+ CheckDlgButton(hwndDlg, IDC_DCALLOW_AUTH, (nDcType == 2));
+ CheckDlgButton(hwndDlg, IDC_ADD_ANY, (nAddAuth == 0));
+ CheckDlgButton(hwndDlg, IDC_ADD_AUTH, (nAddAuth == 1));
+ LoadDBCheckState(hwndDlg, IDC_WEBAWARE, "WebAware", 0);
+ LoadDBCheckState(hwndDlg, IDC_PUBLISHPRIMARY, "PublishPrimaryEmail", 0);
+ LoadDBCheckState(hwndDlg, IDC_STATUSMSG_CLIST, "StatusMsgReplyCList", 0);
+ LoadDBCheckState(hwndDlg, IDC_STATUSMSG_VISIBLE, "StatusMsgReplyVisible", 0);
+ if (!ICQGetContactSettingByte(NULL, "StatusMsgReplyCList", 0))
+ EnableDlgItem(hwndDlg, IDC_STATUSMSG_VISIBLE, FALSE);
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_DCALLOW_ANY:
+ case IDC_DCALLOW_CLIST:
+ case IDC_DCALLOW_AUTH:
+ case IDC_ADD_ANY:
+ case IDC_ADD_AUTH:
+ case IDC_WEBAWARE:
+ case IDC_PUBLISHPRIMARY:
+ case IDC_STATUSMSG_VISIBLE:
+ if ((HWND)lParam != GetFocus()) return 0;
+ break;
+ case IDC_STATUSMSG_CLIST:
+ if (IsDlgButtonChecked(hwndDlg, IDC_STATUSMSG_CLIST))
+ {
+ EnableDlgItem(hwndDlg, IDC_STATUSMSG_VISIBLE, TRUE);
+ LoadDBCheckState(hwndDlg, IDC_STATUSMSG_VISIBLE, "StatusMsgReplyVisible", 0);
+ }
+ else
+ {
+ EnableDlgItem(hwndDlg, IDC_STATUSMSG_VISIBLE, FALSE);
+ CheckDlgButton(hwndDlg, IDC_STATUSMSG_VISIBLE, FALSE);
+ }
+ break;
+ default:
+ return 0;
+ }
+ OptDlgChanged(hwndDlg);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ StoreDBCheckState(hwndDlg, IDC_WEBAWARE, "WebAware");
+ StoreDBCheckState(hwndDlg, IDC_PUBLISHPRIMARY, "PublishPrimaryEmail");
+ StoreDBCheckState(hwndDlg, IDC_STATUSMSG_CLIST, "StatusMsgReplyCList");
+ StoreDBCheckState(hwndDlg, IDC_STATUSMSG_VISIBLE, "StatusMsgReplyVisible");
+ if (IsDlgButtonChecked(hwndDlg, IDC_DCALLOW_AUTH))
+ ICQWriteContactSettingByte(NULL, "DCType", 2);
+ else if (IsDlgButtonChecked(hwndDlg, IDC_DCALLOW_CLIST))
+ ICQWriteContactSettingByte(NULL, "DCType", 1);
+ else
+ ICQWriteContactSettingByte(NULL, "DCType", 0);
+ StoreDBCheckState(hwndDlg, IDC_ADD_AUTH, "Auth");
+
+ if (icqOnline)
+ {
+ PBYTE buf=NULL;
+ int buflen=0;
+
+ ppackTLVLNTSBytefromDB(&buf, &buflen, "e-mail", (BYTE)!ICQGetContactSettingByte(NULL, "PublishPrimaryEmail", 0), TLV_EMAIL);
+ ppackTLVLNTSBytefromDB(&buf, &buflen, "e-mail0", 0, TLV_EMAIL);
+ ppackTLVLNTSBytefromDB(&buf, &buflen, "e-mail1", 0, TLV_EMAIL);
+
+ ppackTLVByte(&buf, &buflen, (BYTE)!ICQGetContactSettingByte(NULL, "Auth", 1), TLV_AUTH, 1);
+
+ ppackTLVByte(&buf, &buflen, (BYTE)ICQGetContactSettingByte(NULL, "WebAware", 0), TLV_WEBAWARE, 1);
+
+ icq_changeUserDetailsServ(META_SET_FULLINFO_REQ, buf, (WORD)buflen);
+
+ SAFE_FREE(&buf);
+
+ // Send a status packet to notify the server about the webaware setting
+ {
+ WORD wStatus;
+
+ wStatus = MirandaStatusToIcq(gnCurrentStatus);
+
+ if (gnCurrentStatus == ID_STATUS_INVISIBLE)
+ {
+
+
+ if (gbSsiEnabled)
+ updateServVisibilityCode(3);
+ icq_setstatus(wStatus);
+ // Tell who is on our visible list
+ icq_sendEntireVisInvisList(0);
+ }
+ else
+ {
+ icq_setstatus(wStatus);
+ if (gbSsiEnabled)
+ updateServVisibilityCode(4);
+ // Tell who is on our invisible list
+ icq_sendEntireVisInvisList(1);
+ }
+ }
+ }
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+static HWND hCpCombo;
+
+struct CPTABLE {
+ WORD cpId;
+ char *cpName;
+};
+
+struct CPTABLE cpTable[] = {
+ { 874, "Thai" },
+ { 932, "Japanese" },
+ { 936, "Simplified Chinese" },
+ { 949, "Korean" },
+ { 950, "Traditional Chinese" },
+ { 1250, "Central European" },
+ { 1251, "Cyrillic" },
+ { 1252, "Latin I" },
+ { 1253, "Greek" },
+ { 1254, "Turkish" },
+ { 1255, "Hebrew" },
+ { 1256, "Arabic" },
+ { 1257, "Baltic" },
+ { 1258, "Vietnamese" },
+ { 1361, "Korean (Johab)" },
+ { -1, NULL}
+};
+
+static BOOL CALLBACK FillCpCombo(LPCSTR str)
+{
+ int i;
+ UINT cp;
+
+ cp = atoi(str);
+ for (i=0; cpTable[i].cpName != NULL && cpTable[i].cpId!=cp; i++);
+ if (cpTable[i].cpName != NULL)
+ {
+ ComboBoxAddStringUtf(hCpCombo, cpTable[i].cpName, cpTable[i].cpId);
+ }
+ return TRUE;
+}
+
+
+static const UINT icqUnicodeControls[] = {IDC_UTFALL,IDC_UTFSTATIC,IDC_UTFCODEPAGE};
+static const UINT icqDCMsgControls[] = {IDC_DCPASSIVE};
+static const UINT icqXStatusControls[] = {IDC_XSTATUSAUTO,IDC_XSTATUSRESET};
+static const UINT icqAimControls[] = {IDC_AIMENABLE};
+static BOOL CALLBACK DlgProcIcqFeaturesOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ BYTE bData;
+ int sCodePage;
+ int i;
+
+ ICQTranslateDialog(hwndDlg);
+ bData = ICQGetContactSettingByte(NULL, "UtfEnabled", DEFAULT_UTF_ENABLED);
+ CheckDlgButton(hwndDlg, IDC_UTFENABLE, bData?TRUE:FALSE);
+ CheckDlgButton(hwndDlg, IDC_UTFALL, bData==2?TRUE:FALSE);
+ icq_EnableMultipleControls(hwndDlg, icqUnicodeControls, sizeof(icqUnicodeControls)/sizeof(icqUnicodeControls[0]), bData?TRUE:FALSE);
+ LoadDBCheckState(hwndDlg, IDC_TEMPVISIBLE, "TempVisListEnabled",DEFAULT_TEMPVIS_ENABLED);
+ LoadDBCheckState(hwndDlg, IDC_SLOWSEND, "SlowSend", DEFAULT_SLOWSEND);
+ LoadDBCheckState(hwndDlg, IDC_ONLYSERVERACKS, "OnlyServerAcks", DEFAULT_ONLYSERVERACKS);
+ bData = ICQGetContactSettingByte(NULL, "DirectMessaging", DEFAULT_DCMSG_ENABLED);
+ CheckDlgButton(hwndDlg, IDC_DCENABLE, bData?TRUE:FALSE);
+ CheckDlgButton(hwndDlg, IDC_DCPASSIVE, bData==1?TRUE:FALSE);
+ icq_EnableMultipleControls(hwndDlg, icqDCMsgControls, sizeof(icqDCMsgControls)/sizeof(icqDCMsgControls[0]), bData?TRUE:FALSE);
+ bData = DBGetContactSettingByte(NULL,gpszICQProtoName,"ASD", 0);
+ CheckDlgButton(hwndDlg, IDC_ASD, bData);
+ bData = ICQGetContactSettingByte(NULL, "XStatusEnabled", DEFAULT_XSTATUS_ENABLED);
+ CheckDlgButton(hwndDlg, IDC_XSTATUSENABLE, bData);
+ icq_EnableMultipleControls(hwndDlg, icqXStatusControls, sizeof(icqXStatusControls)/sizeof(icqXStatusControls[0]), bData);
+ LoadDBCheckState(hwndDlg, IDC_XSTATUSAUTO, "XStatusAuto", DEFAULT_XSTATUS_AUTO);
+ LoadDBCheckState(hwndDlg, IDC_XSTATUSRESET, "XStatusReset", DEFAULT_XSTATUS_RESET);
+ LoadDBCheckState(hwndDlg, IDC_KILLSPAMBOTS, "KillSpambots", DEFAULT_KILLSPAM_ENABLED);
+ LoadDBCheckState(hwndDlg, IDC_AIMENABLE, "AimEnabled", DEFAULT_AIM_ENABLED);
+ icq_EnableMultipleControls(hwndDlg, icqAimControls, sizeof(icqAimControls)/sizeof(icqAimControls[0]), icqOnline?FALSE:TRUE);
+
+ hCpCombo = GetDlgItem(hwndDlg, IDC_UTFCODEPAGE);
+ sCodePage = ICQGetContactSettingWord(NULL, "AnsiCodePage", CP_ACP);
+ ComboBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_UTFCODEPAGE), "System default codepage", 0);
+ EnumSystemCodePagesA(FillCpCombo, CP_INSTALLED);
+ if(sCodePage == 0)
+ SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_SETCURSEL, (WPARAM)0, 0);
+ else
+ {
+ for (i = 0; i < SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_GETCOUNT, 0, 0); i++)
+ {
+ if (SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_GETITEMDATA, (WPARAM)i, 0) == sCodePage)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_SETCURSEL, (WPARAM)i, 0);
+ break;
+ }
+ }
+ }
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_UTFENABLE:
+ icq_EnableMultipleControls(hwndDlg, icqUnicodeControls, sizeof(icqUnicodeControls)/sizeof(icqUnicodeControls[0]), IsDlgButtonChecked(hwndDlg, IDC_UTFENABLE));
+ break;
+ case IDC_DCENABLE:
+ icq_EnableMultipleControls(hwndDlg, icqDCMsgControls, sizeof(icqDCMsgControls)/sizeof(icqDCMsgControls[0]), IsDlgButtonChecked(hwndDlg, IDC_DCENABLE));
+ break;
+ case IDC_XSTATUSENABLE:
+ icq_EnableMultipleControls(hwndDlg, icqXStatusControls, sizeof(icqXStatusControls)/sizeof(icqXStatusControls[0]), IsDlgButtonChecked(hwndDlg, IDC_XSTATUSENABLE));
+ break;
+ }
+ OptDlgChanged(hwndDlg);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ ICQWriteContactSettingByte(NULL,"ASD",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ASD));
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_UTFENABLE))
+ gbUtfEnabled = IsDlgButtonChecked(hwndDlg, IDC_UTFALL)?2:1;
+ else
+ gbUtfEnabled = 0;
+ {
+ int i = SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_GETCURSEL, 0, 0);
+ gwAnsiCodepage = (WORD)SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_GETITEMDATA, (WPARAM)i, 0);
+ ICQWriteContactSettingWord(NULL, "AnsiCodePage", gwAnsiCodepage);
+ }
+ ICQWriteContactSettingByte(NULL, "UtfEnabled", gbUtfEnabled);
+ gbTempVisListEnabled = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_TEMPVISIBLE);
+ ICQWriteContactSettingByte(NULL, "TempVisListEnabled", gbTempVisListEnabled);
+ StoreDBCheckState(hwndDlg, IDC_SLOWSEND, "SlowSend");
+ StoreDBCheckState(hwndDlg, IDC_ONLYSERVERACKS, "OnlyServerAcks");
+ if (IsDlgButtonChecked(hwndDlg, IDC_DCENABLE))
+ gbDCMsgEnabled = IsDlgButtonChecked(hwndDlg, IDC_DCPASSIVE)?1:2;
+ else
+ gbDCMsgEnabled = 0;
+ ICQWriteContactSettingByte(NULL, "DirectMessaging", gbDCMsgEnabled);
+ gbXStatusEnabled = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_XSTATUSENABLE);
+ ICQWriteContactSettingByte(NULL, "XStatusEnabled", gbXStatusEnabled);
+ StoreDBCheckState(hwndDlg, IDC_XSTATUSAUTO, "XStatusAuto");
+ StoreDBCheckState(hwndDlg, IDC_XSTATUSRESET, "XStatusReset");
+ StoreDBCheckState(hwndDlg, IDC_KILLSPAMBOTS , "KillSpambots");
+ StoreDBCheckState(hwndDlg, IDC_AIMENABLE, "AimEnabled");
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+
+static const UINT icqContactsControls[] = {IDC_ADDSERVER,IDC_LOADFROMSERVER,IDC_SAVETOSERVER,IDC_UPLOADNOW};
+static const UINT icqAvatarControls[] = {IDC_AUTOLOADAVATARS,IDC_LINKAVATARS};
+static BOOL CALLBACK DlgProcIcqContactsOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ LoadDBCheckState(hwndDlg, IDC_ENABLE, "UseServerCList", DEFAULT_SS_ENABLED);
+ LoadDBCheckState(hwndDlg, IDC_ADDSERVER, "ServerAddRemove", DEFAULT_SS_ADDSERVER);
+ LoadDBCheckState(hwndDlg, IDC_LOADFROMSERVER, "LoadServerDetails", DEFAULT_SS_LOAD);
+ LoadDBCheckState(hwndDlg, IDC_SAVETOSERVER, "StoreServerDetails", DEFAULT_SS_STORE);
+ LoadDBCheckState(hwndDlg, IDC_ENABLEAVATARS, "AvatarsEnabled", DEFAULT_AVATARS_ENABLED);
+ LoadDBCheckState(hwndDlg, IDC_AUTOLOADAVATARS, "AvatarsAutoLoad", DEFAULT_LOAD_AVATARS);
+ LoadDBCheckState(hwndDlg, IDC_LINKAVATARS, "AvatarsAutoLink", DEFAULT_LINK_AVATARS);
+
+ icq_EnableMultipleControls(hwndDlg, icqContactsControls, sizeof(icqContactsControls)/sizeof(icqContactsControls[0]),
+ ICQGetContactSettingByte(NULL, "UseServerCList", DEFAULT_SS_ENABLED)?TRUE:FALSE);
+ icq_EnableMultipleControls(hwndDlg, icqAvatarControls, sizeof(icqAvatarControls)/sizeof(icqAvatarControls[0]),
+ ICQGetContactSettingByte(NULL, "AvatarsEnabled", DEFAULT_AVATARS_ENABLED)?TRUE:FALSE);
+
+ if (icqOnline)
+ {
+ ShowWindow(GetDlgItem(hwndDlg, IDC_OFFLINETOENABLE), SW_SHOW);
+ EnableDlgItem(hwndDlg, IDC_ENABLE, FALSE);
+ EnableDlgItem(hwndDlg, IDC_ENABLEAVATARS, FALSE);
+ }
+ else
+ {
+ EnableDlgItem(hwndDlg, IDC_UPLOADNOW, FALSE);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_UPLOADNOW:
+ ShowUploadContactsDialog();
+ return TRUE;
+ case IDC_ENABLE:
+ icq_EnableMultipleControls(hwndDlg, icqContactsControls, sizeof(icqContactsControls)/sizeof(icqContactsControls[0]), IsDlgButtonChecked(hwndDlg, IDC_ENABLE));
+ if (icqOnline)
+ ShowWindow(GetDlgItem(hwndDlg, IDC_RECONNECTREQD), SW_SHOW);
+ else
+ EnableDlgItem(hwndDlg, IDC_UPLOADNOW, FALSE);
+ break;
+ case IDC_ENABLEAVATARS:
+ icq_EnableMultipleControls(hwndDlg, icqAvatarControls, sizeof(icqAvatarControls)/sizeof(icqAvatarControls[0]), IsDlgButtonChecked(hwndDlg, IDC_ENABLEAVATARS));
+ break;
+ }
+ OptDlgChanged(hwndDlg);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ StoreDBCheckState(hwndDlg, IDC_ENABLE, "UseServerCList");
+ StoreDBCheckState(hwndDlg, IDC_ADDSERVER, "ServerAddRemove");
+ StoreDBCheckState(hwndDlg, IDC_LOADFROMSERVER, "LoadServerDetails");
+ StoreDBCheckState(hwndDlg, IDC_SAVETOSERVER, "StoreServerDetails");
+ StoreDBCheckState(hwndDlg, IDC_ENABLEAVATARS, "AvatarsEnabled");
+ StoreDBCheckState(hwndDlg, IDC_AUTOLOADAVATARS, "AvatarsAutoLoad");
+ StoreDBCheckState(hwndDlg, IDC_LINKAVATARS, "AvatarsAutoLink");
+
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
diff --git a/icqj_mod/icq_opts.h b/icqj_mod/icq_opts.h new file mode 100644 index 0000000..e8c25d5 --- /dev/null +++ b/icqj_mod/icq_opts.h @@ -0,0 +1,42 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_opts.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+int IcqOptInit(WPARAM, LPARAM);
+
+void AddUserInfoPageUtf(OPTIONSDIALOGPAGE *op, WPARAM wParam, const char *szTitle);
+void AddOptionsPageUtf(OPTIONSDIALOGPAGE *op, WPARAM wParam, const char *szGroup, const char *szTitle);
diff --git a/icqj_mod/icq_packet.c b/icqj_mod/icq_packet.c new file mode 100644 index 0000000..a0b628b --- /dev/null +++ b/icqj_mod/icq_packet.c @@ -0,0 +1,706 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_packet.c,v $
+// Revision : $Revision: 2991 $
+// Last change on : $Date: 2006-05-30 19:55:48 +0200 (Tue, 30 May 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+void write_httphdr(icq_packet* pPacket, WORD wType, DWORD dwSeq)
+{
+ pPacket->wPlace = 0;
+ pPacket->wLen += 14;
+ pPacket->pData = (BYTE*)SAFE_MALLOC(pPacket->wLen);
+
+ packWord(pPacket, (WORD)(pPacket->wLen - 2));
+ packWord(pPacket, HTTP_PROXY_VERSION);
+ packWord(pPacket, wType);
+ packDWord(pPacket, 0); // Flags?
+ packDWord(pPacket, dwSeq); // Connection sequence ?
+}
+
+
+
+void __fastcall write_flap(icq_packet* pPacket, BYTE byFlapChannel)
+{
+ pPacket->wPlace = 0;
+ pPacket->wLen += 6;
+ pPacket->pData = (BYTE*)SAFE_MALLOC(pPacket->wLen);
+
+ packByte(pPacket, FLAP_MARKER);
+ packByte(pPacket, byFlapChannel);
+ packWord(pPacket, 0); // This is the sequence ID, it is filled in during the actual sending
+ packWord(pPacket, (WORD)(pPacket->wLen - 6)); // This counter should not include the flap header (thus the -6)
+}
+
+
+
+void __fastcall serverPacketInit(icq_packet* pPacket, WORD wSize)
+{
+ pPacket->wLen = wSize;
+ write_flap(pPacket, ICQ_DATA_CHAN);
+}
+
+
+
+void __fastcall directPacketInit(icq_packet* pPacket, DWORD dwSize)
+{
+ pPacket->wPlace = 0;
+ pPacket->wLen = (WORD)dwSize;
+ pPacket->pData = (BYTE *)SAFE_MALLOC(dwSize + 2);
+
+ packLEWord(pPacket, pPacket->wLen);
+}
+
+
+
+void __fastcall serverCookieInit(icq_packet* pPacket, BYTE* pCookie, WORD wCookieSize)
+{
+ pPacket->wLen = (WORD)(wCookieSize + 8);
+
+ write_flap(pPacket, ICQ_LOGIN_CHAN);
+ packDWord(pPacket, 0x00000001);
+ packTLV(pPacket, 0x06, wCookieSize, pCookie);
+}
+
+
+
+void __fastcall packByte(icq_packet* pPacket, BYTE byValue)
+{
+ pPacket->pData[pPacket->wPlace++] = byValue;
+}
+
+
+
+void __fastcall packWord(icq_packet* pPacket, WORD wValue)
+{
+ pPacket->pData[pPacket->wPlace++] = ((wValue & 0xff00) >> 8);
+ pPacket->pData[pPacket->wPlace++] = (wValue & 0x00ff);
+}
+
+
+
+void __fastcall packDWord(icq_packet* pPacket, DWORD dwValue)
+{
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0xff000000) >> 24);
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0x00ff0000) >> 16);
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0x0000ff00) >> 8);
+ pPacket->pData[pPacket->wPlace++] = (BYTE) (dwValue & 0x000000ff);
+}
+
+
+
+void packTLV(icq_packet* pPacket, WORD wType, WORD wLength, BYTE* pbyValue)
+{
+ packWord(pPacket, wType);
+ packWord(pPacket, wLength);
+ packBuffer(pPacket, pbyValue, wLength);
+}
+
+
+
+void packTLVWord(icq_packet* pPacket, WORD wType, WORD wValue)
+{
+ packWord(pPacket, wType);
+ packWord(pPacket, 0x02);
+ packWord(pPacket, wValue);
+}
+
+
+
+void packTLVDWord(icq_packet* pPacket, WORD wType, DWORD dwValue)
+{
+ packWord(pPacket, wType);
+ packWord(pPacket, 0x04);
+ packDWord(pPacket, dwValue);
+}
+
+
+
+// Pack a preformatted buffer.
+// This can be used to pack strings or any type of raw data.
+void packBuffer(icq_packet* pPacket, const BYTE* pbyBuffer, WORD wLength)
+{
+
+ while (wLength)
+ {
+ pPacket->pData[pPacket->wPlace++] = *pbyBuffer++;
+ wLength--;
+ }
+
+}
+
+
+
+// Pack a buffer and prepend it with the size as a LE WORD.
+// Commented out since its not actually used anywhere right now.
+//void packLEWordSizedBuffer(icq_packet* pPacket, const BYTE* pbyBuffer, WORD wLength)
+//{
+//
+// packLEWord(pPacket, wLength);
+// packBuffer(pPacket, pbyBuffer, wLength);
+//
+//}
+
+
+int __fastcall getUINLen(DWORD dwUin)
+{ // TODO: invent something more clever
+ if (dwUin >= 1000000000) return 10;
+ if (dwUin >= 100000000) return 9;
+ if (dwUin >= 10000000) return 8;
+ if (dwUin >= 1000000) return 7;
+ if (dwUin >= 100000) return 6;
+ if (dwUin >= 10000) return 5;
+ if (dwUin >= 1000) return 4;
+ if (dwUin >= 100) return 3;
+ if (dwUin >= 10) return 2;
+ return 1;
+}
+
+
+
+int __fastcall getUIDLen(DWORD dwUin, char* szUid)
+{
+ if (dwUin)
+ return getUINLen(dwUin);
+ else
+ return strlennull(szUid);
+}
+
+
+
+void __fastcall packUIN(icq_packet* pPacket, DWORD dwUin)
+{
+ unsigned char pszUin[UINMAXLEN];
+ BYTE nUinLen = getUINLen(dwUin);
+
+ ltoa(dwUin, pszUin, 10);
+
+ packByte(pPacket, nUinLen); // Length of user id
+ packBuffer(pPacket, pszUin, nUinLen); // Receiving user's id
+}
+
+
+
+void __fastcall packUID(icq_packet* pPacket, DWORD dwUin, char* szUid)
+{
+ if (dwUin)
+ packUIN(pPacket, dwUin);
+ else
+ {
+ BYTE nLen = strlennull(szUid);
+ packByte(pPacket, nLen);
+ packBuffer(pPacket, szUid, nLen);
+ }
+}
+
+
+
+void packFNACHeader(icq_packet* pPacket, WORD wFamily, WORD wSubtype)
+{
+ packWord(pPacket, wFamily); // Family type
+ packWord(pPacket, wSubtype); // Family subtype
+ packDWord(pPacket, 0); // SNAC flags // SNAC request id (sequence)
+ packWord(pPacket, wSubtype); // SNAC request id (command)
+}
+
+
+
+void packFNACHeaderFull(icq_packet* pPacket, WORD wFamily, WORD wSubtype, WORD wFlags, DWORD dwSeq)
+{
+ WORD wSeq = (WORD)dwSeq & 0x7FFF; // this is necessary, if that bit is there we get disconnected
+
+ packWord(pPacket, wFamily); // Family type
+ packWord(pPacket, wSubtype); // Family subtype
+ packWord(pPacket, wFlags); // SNAC flags
+ packWord(pPacket, wSeq); // SNAC request id (sequence)
+ packWord(pPacket, (WORD)(dwSeq>>0x10)); // SNAC request id (command)
+}
+
+
+
+void __fastcall packLEWord(icq_packet* pPacket, WORD wValue)
+{
+ pPacket->pData[pPacket->wPlace++] = (wValue & 0x00ff);
+ pPacket->pData[pPacket->wPlace++] = ((wValue & 0xff00) >> 8);
+}
+
+
+
+void __fastcall packLEDWord(icq_packet* pPacket, DWORD dwValue)
+{
+ pPacket->pData[pPacket->wPlace++] = (BYTE) (dwValue & 0x000000ff);
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0x0000ff00) >> 8);
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0x00ff0000) >> 16);
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0xff000000) >> 24);
+}
+
+
+
+void ppackByte(PBYTE *buf,int *buflen,BYTE b)
+{
+ *buf=(PBYTE)realloc(*buf,1+*buflen);
+ *(*buf+*buflen)=b;
+ ++*buflen;
+}
+
+
+
+void ppackLEWord(PBYTE *buf,int *buflen,WORD w)
+{
+ *buf=(PBYTE)realloc(*buf,2+*buflen);
+ *(PWORD)(*buf+*buflen)=w;
+ *buflen+=2;
+}
+
+
+
+void ppackLEDWord(PBYTE *buf, int *buflen, DWORD d)
+{
+ *buf = (PBYTE)realloc(*buf, 4 + *buflen);
+ *(PDWORD)(*buf + *buflen) = d;
+ *buflen += 4;
+}
+
+
+
+/*void ppackLNTS(PBYTE *buf, int *buflen, const char *str)
+{
+ WORD len = strlennull(str);
+ ppackWord(buf, buflen, len);
+ *buf = (PBYTE)realloc(*buf, *buflen + len);
+ memcpy(*buf + *buflen, str, len);
+ *buflen += len;
+}*/
+
+
+
+void ppackLELNTS(PBYTE *buf, int *buflen, const char *str)
+{
+ WORD len = strlennull(str);
+ ppackLEWord(buf, buflen, len);
+ *buf = (PBYTE)realloc(*buf, *buflen + len);
+ memcpy(*buf + *buflen, str, len);
+ *buflen += len;
+}
+
+
+
+void ppackLELNTSfromDB(PBYTE *buf, int *buflen, const char *szSetting)
+{
+ DBVARIANT dbv;
+
+ if (ICQGetContactSetting(NULL, szSetting, &dbv))
+ {
+ ppackLEWord(buf, buflen, 0);
+ }
+ else
+ {
+ ppackLELNTS(buf, buflen, dbv.pszVal);
+ ICQFreeVariant(&dbv);
+ }
+}
+
+
+
+// *** TLV based (!!! WORDs and DWORDs are LE !!!)
+void ppackTLVByte(PBYTE *buf, int *buflen, BYTE b, WORD wType, BYTE always)
+{
+ if (!always && !b) return;
+
+ *buf = (PBYTE)realloc(*buf, 5 + *buflen);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = 1;
+ *(*buf + *buflen + 4) = b;
+ *buflen += 5;
+}
+
+
+
+void ppackTLVWord(PBYTE *buf, int *buflen, WORD w, WORD wType, BYTE always)
+{
+ if (!always && !w) return;
+
+ *buf = (PBYTE)realloc(*buf, 6 + *buflen);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = 2;
+ *(PWORD)(*buf + *buflen + 4) = w;
+ *buflen += 6;
+}
+
+
+
+void ppackTLVDWord(PBYTE *buf, int *buflen, DWORD d, WORD wType, BYTE always)
+{
+ if (!always && !d) return;
+
+ *buf = (PBYTE)realloc(*buf, 8 + *buflen);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = 4;
+ *(PDWORD)(*buf + *buflen + 4) = d;
+ *buflen += 8;
+}
+
+
+
+void packTLVLNTS(PBYTE *buf, int *bufpos, const char *str, WORD wType)
+{
+ int len = strlennull(str) + 1;
+
+ *(PWORD)(*buf + *bufpos) = wType;
+ *(PWORD)(*buf + *bufpos + 2) = len + 2;
+ *(PWORD)(*buf + *bufpos + 4) = len;
+ memcpy(*buf + *bufpos + 6, str, len);
+ *bufpos += len + 6;
+}
+
+
+
+void ppackTLVLNTS(PBYTE *buf, int *buflen, const char *str, WORD wType, BYTE always)
+{
+ int len = strlennull(str) + 1;
+
+ if (!always && len < 2) return;
+
+ *buf = (PBYTE)realloc(*buf, 6 + *buflen + len);
+ packTLVLNTS(buf, buflen, str, wType);
+}
+
+
+
+void ppackTLVWordLNTS(PBYTE *buf, int *buflen, WORD w, const char *str, WORD wType, BYTE always)
+{
+ int len = strlennull(str) + 1;
+
+ if (!always && len < 2 && !w) return;
+
+ *buf = (PBYTE)realloc(*buf, 8 + *buflen + len);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = len + 4;
+ *(PWORD)(*buf + *buflen + 4) = w;
+ *(PWORD)(*buf + *buflen + 6) = len;
+ memcpy(*buf + *buflen + 8, str, len);
+ *buflen += len + 8;
+}
+
+
+
+void ppackTLVLNTSByte(PBYTE *buf, int *buflen, const char *str, BYTE b, WORD wType)
+{
+ int len = strlennull(str) + 1;
+
+ *buf = (PBYTE)realloc(*buf, 7 + *buflen + len);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = len + 3;
+ *(PWORD)(*buf + *buflen + 4) = len;
+ memcpy(*buf + *buflen + 6, str, len);
+ *(*buf + *buflen + 6 + len) = b;
+ *buflen += len + 7;
+}
+
+
+
+void ppackTLVLNTSfromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!ICQGetContactStaticString(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackTLVLNTS(buf, buflen, str, wType, 1);
+}
+
+
+
+void ppackTLVWordLNTSfromDB(PBYTE *buf, int *buflen, WORD w, const char *szSetting, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!ICQGetContactStaticString(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackTLVWordLNTS(buf, buflen, w, str, wType, 1);
+}
+
+
+
+void ppackTLVLNTSBytefromDB(PBYTE *buf, int *buflen, const char *szSetting, BYTE b, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!ICQGetContactStaticString(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackTLVLNTSByte(buf, buflen, str, b, wType);
+}
+
+
+
+void __fastcall unpackByte(BYTE** pSource, BYTE* byDestination)
+{
+ if (byDestination)
+ {
+ *byDestination = *(*pSource)++;
+ }
+ else
+ {
+ *pSource += 1;
+ }
+}
+
+
+
+void __fastcall unpackWord(BYTE** pSource, WORD* wDestination)
+{
+ unsigned char *tmp = *pSource;
+
+ if (wDestination)
+ {
+ *wDestination = *tmp++ << 8;
+ *wDestination |= *tmp++;
+
+ *pSource = tmp;
+ }
+ else
+ {
+ *pSource += 2;
+ }
+}
+
+
+
+void __fastcall unpackDWord(BYTE** pSource, DWORD* dwDestination)
+{
+ unsigned char *tmp = *pSource;
+
+ if (dwDestination)
+ {
+ *dwDestination = *tmp++ << 24;
+ *dwDestination |= *tmp++ << 16;
+ *dwDestination |= *tmp++ << 8;
+ *dwDestination |= *tmp++;
+
+ *pSource = tmp;
+ }
+ else
+ {
+ *pSource += 4;
+ }
+}
+
+
+
+void __fastcall unpackLEWord(unsigned char **buf, WORD *w)
+{
+ unsigned char *tmp = *buf;
+
+ if (w)
+ {
+ *w = (*tmp++);
+ *w |= ((*tmp++) << 8);
+ }
+ else
+ tmp += 2;
+
+ *buf = tmp;
+}
+
+
+
+void __fastcall unpackLEDWord(unsigned char **buf, DWORD *dw)
+{
+ unsigned char *tmp = *buf;
+
+ if (dw)
+ {
+ *dw = (*tmp++);
+ *dw |= ((*tmp++) << 8);
+ *dw |= ((*tmp++) << 16);
+ *dw |= ((*tmp++) << 24);
+ }
+ else
+ tmp += 4;
+
+ *buf = tmp;
+}
+
+
+
+void unpackString(unsigned char **buf, char *string, WORD len)
+{
+ unsigned char *tmp = *buf;
+
+ if (string)
+ {
+ while (len) /* Can have 0x00 so go by len */
+ {
+ *string++ = *tmp++;
+ len--;
+ }
+ }
+ else
+ tmp += len;
+
+ *buf = tmp;
+}
+
+
+
+void unpackWideString(unsigned char **buf, WCHAR *string, WORD len)
+{
+ unsigned char *tmp = *buf;
+
+ while (len > 1)
+ {
+ *string = (*tmp++ << 8);
+ *string |= *tmp++;
+
+ string++;
+ len -= 2;
+ }
+
+ // We have a stray byte at the end, this means that the buffer had an odd length
+ // which indicates an error.
+ _ASSERTE(len == 0);
+ if (len != 0)
+ {
+ // We dont copy the last byte but we still need to increase the buffer pointer
+ // (we assume that 'len' was correct) since the calling function expects
+ // that it is increased 'len' bytes.
+ *tmp += len;
+ }
+
+ *buf = tmp;
+}
+
+
+
+void unpackTypedTLV(unsigned char **buf, int buflen, WORD type, WORD *ttype, WORD *tlen, char **tlv)
+{
+ WORD wType, wLen;
+ unsigned char *tmp = *buf;
+
+NextTLV:
+ // Unpack type and length
+ unpackWord(&tmp, &wType);
+ unpackWord(&tmp, &wLen);
+ buflen -= 4;
+
+ if (wType != type && buflen >= wLen + 4)
+ { // Not the right TLV, try next
+ buflen -= wLen;
+ tmp += wLen;
+ goto NextTLV;
+ }
+ // Check buffer size
+ if (wLen > buflen) wLen = buflen;
+
+ // Make sure we have a good pointer
+ if (tlv)
+ {
+ // Unpack and save value
+ *tlv = (char *)SAFE_MALLOC(wLen + 1); // Add 1 for \0
+ unpackString(&tmp, *tlv, wLen);
+ *(*tlv + wLen) = '\0';
+ }
+ else
+ {
+ *tmp += wLen;
+ }
+
+ // Save type and length
+ if (ttype)
+ *ttype = wType;
+ if (tlen)
+ *tlen = wLen;
+
+ // Increase source pointer
+ *buf = tmp;
+}
+
+
+
+BOOL unpackUID(unsigned char** ppBuf, WORD* pwLen, DWORD *pdwUIN, uid_str* ppszUID)
+{
+ BYTE nUIDLen;
+ char szUIN[UINMAXLEN+1];
+
+ // Sender UIN
+ unpackByte(ppBuf, &nUIDLen);
+ *pwLen -= 1;
+
+ if ((nUIDLen > *pwLen) || (nUIDLen == 0))
+ return FALSE;
+
+ if (nUIDLen <= UINMAXLEN)
+ { // it can be uin, check
+ unpackString(ppBuf, szUIN, nUIDLen);
+ szUIN[nUIDLen] = '\0';
+ *pwLen -= nUIDLen;
+
+ if (IsStringUIN(szUIN))
+ {
+ *pdwUIN = atoi(szUIN);
+ return TRUE;
+ }
+ else if (!ppszUID || !gbAimEnabled)
+ {
+ NetLog_Server("Malformed UIN in packet");
+ return FALSE;
+ }
+ else
+ { // go back
+ *ppBuf -= nUIDLen;
+ *pwLen += nUIDLen;
+ }
+ }
+ else if (!ppszUID || ! gbAimEnabled)
+ {
+ NetLog_Server("Malformed UIN in packet");
+ return FALSE;
+ }
+ if (!(*ppszUID)) return FALSE;
+
+ unpackString(ppBuf, *ppszUID, nUIDLen);
+ *pwLen -= nUIDLen;
+ (*ppszUID)[nUIDLen] = '\0';
+
+ *pdwUIN = 0; // this is how we determine aim contacts internally
+
+ return TRUE;
+}
diff --git a/icqj_mod/icq_packet.h b/icqj_mod/icq_packet.h new file mode 100644 index 0000000..b87d251 --- /dev/null +++ b/icqj_mod/icq_packet.h @@ -0,0 +1,113 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_packet.h,v $
+// Revision : $Revision: 2991 $
+// Last change on : $Date: 2006-05-30 19:55:48 +0200 (Tue, 30 May 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_PACKET_H
+#define __ICQ_PACKET_H
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+
+/*---------* Structures *--------------*/
+
+typedef struct icq_packet_s
+{
+ WORD wPlace;
+ BYTE nChannel;
+ WORD wSequence;
+ WORD wLen;
+ BYTE *pData;
+} icq_packet;
+
+/*---------* Functions *---------------*/
+
+void write_httphdr(icq_packet *d, WORD wType, DWORD dwSeq);
+void __fastcall write_flap(icq_packet *, BYTE);
+void __fastcall serverPacketInit(icq_packet *, WORD);
+void __fastcall directPacketInit(icq_packet *, DWORD);
+
+void __fastcall serverCookieInit(icq_packet *, BYTE *, WORD);
+
+void __fastcall packByte(icq_packet *, BYTE);
+void __fastcall packWord(icq_packet *, WORD);
+void __fastcall packDWord(icq_packet *, DWORD);
+void packTLV(icq_packet* pPacket, WORD wType, WORD wLength, BYTE* pbyValue);
+void packTLVWord(icq_packet *d, unsigned short nType, WORD wData);
+void packTLVDWord(icq_packet *d, unsigned short nType, DWORD dwData);
+
+void packBuffer(icq_packet* pPacket, const BYTE* pbyBuffer, WORD wLength);
+//void packLEWordSizedBuffer(icq_packet* pPacket, const BYTE* pbyBuffer, WORD wLength);
+int __fastcall getUINLen(DWORD dwUin);
+int __fastcall getUIDLen(DWORD dwUin, char* szUid);
+void __fastcall packUIN(icq_packet *pPacket, DWORD dwUin);
+void __fastcall packUID(icq_packet *pPacket, DWORD dwUin, char* szUid);
+void packFNACHeader(icq_packet *d, WORD wFamily, WORD wSubtype);
+void packFNACHeaderFull(icq_packet *d, WORD wFamily, WORD wSubtype, WORD wFlags, DWORD wSeq);
+
+void __fastcall packLEWord(icq_packet *, WORD);
+void __fastcall packLEDWord(icq_packet *, DWORD);
+
+void packTLVLNTS(PBYTE *buf, int *bufpos, const char *str, WORD wType);
+
+void ppackByte(PBYTE *buf,int *buflen,BYTE b);
+void ppackLEWord(PBYTE *buf,int *buflen,WORD w);
+void ppackLEDWord(PBYTE *buf,int *buflen,DWORD d);
+void ppackLELNTS(PBYTE *buf, int *buflen, const char *str);
+void ppackLELNTSfromDB(PBYTE *buf, int *buflen, const char *szSetting);
+
+void ppackTLVByte(PBYTE *buf, int *buflen, BYTE b, WORD wType, BYTE always);
+void ppackTLVWord(PBYTE *buf, int *buflen, WORD w, WORD wType, BYTE always);
+void ppackTLVDWord(PBYTE *buf, int *buflen, DWORD d, WORD wType, BYTE always);
+void ppackTLVLNTS(PBYTE *buf, int *buflen, const char *str, WORD wType, BYTE always);
+void ppackTLVWordLNTS(PBYTE *buf, int *buflen, WORD w, const char *str, WORD wType, BYTE always);
+void ppackTLVLNTSByte(PBYTE *buf, int *buflen, const char *str, BYTE b, WORD wType);
+
+void ppackTLVLNTSfromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType);
+void ppackTLVWordLNTSfromDB(PBYTE *buf, int *buflen, WORD w, const char *szSetting, WORD wType);
+void ppackTLVLNTSBytefromDB(PBYTE *buf, int *buflen, const char *szSetting, BYTE b, WORD wType);
+
+void __fastcall unpackByte(unsigned char **, BYTE *);
+void __fastcall unpackWord(unsigned char **, WORD *);
+void __fastcall unpackDWord(unsigned char **, DWORD *);
+void unpackString(unsigned char **buf, char *string, WORD len);
+void unpackWideString(unsigned char **buf, WCHAR *string, WORD len);
+void unpackTypedTLV(unsigned char **, int, WORD, WORD *, WORD *, char **);
+BOOL unpackUID(unsigned char** ppBuf, WORD* pwLen, DWORD *pdwUIN, uid_str* ppszUID);
+
+void __fastcall unpackLEWord(unsigned char **, WORD *);
+void __fastcall unpackLEDWord(unsigned char **, DWORD *);
+
+#endif /* __ICQ_PACKET_H */
diff --git a/icqj_mod/icq_popups.c b/icqj_mod/icq_popups.c new file mode 100644 index 0000000..8995c6d --- /dev/null +++ b/icqj_mod/icq_popups.c @@ -0,0 +1,310 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_popups.c,v $
+// Revision : $Revision: 2960 $
+// Last change on : $Date: 2006-05-26 09:19:42 +0200 (Fri, 26 May 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// PopUp Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_popupw.h"
+
+
+static BOOL bPopUpService = FALSE;
+
+static BOOL CALLBACK DlgProcIcqPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+void InitPopUps()
+{
+ if (ServiceExists(MS_POPUP_ADDPOPUPEX))
+ {
+ bPopUpService = TRUE;
+ }
+}
+
+
+
+void InitPopupOpts(WPARAM wParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+
+ if (bPopUpService)
+ {
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_POPUPS);
+ odp.groupPosition = 900000000;
+ odp.pfnDlgProc = DlgProcIcqPopupOpts;
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.nIDBottomSimpleControl = 0;
+ AddOptionsPageUtf(&odp, wParam, "Popups", gpszICQProtoName);
+ }
+}
+
+
+static const UINT icqPopupsControls[] = {IDC_POPUPS_LOG_ENABLED,IDC_POPUPS_SPAM_ENABLED,IDC_PREVIEW,IDC_USEWINCOLORS,IDC_USESYSICONS,IDC_POPUP_LOG0_TIMEOUT,IDC_POPUP_LOG1_TIMEOUT,IDC_POPUP_LOG2_TIMEOUT,IDC_POPUP_LOG3_TIMEOUT,IDC_POPUP_LOG4_TIMEOUT,IDC_POPUP_LOG5_TIMEOUT,IDC_POPUP_SPAM_TIMEOUT};
+static const UINT icqPopupColorControls[] = {IDC_POPUP_LOG0_TEXTCOLOR,IDC_POPUP_LOG1_TEXTCOLOR,IDC_POPUP_LOG2_TEXTCOLOR,IDC_POPUP_LOG3_TEXTCOLOR,IDC_POPUP_LOG4_TEXTCOLOR,IDC_POPUP_LOG5_TEXTCOLOR,IDC_POPUP_SPAM_TEXTCOLOR,
+ IDC_POPUP_LOG0_BACKCOLOR,IDC_POPUP_LOG1_BACKCOLOR,IDC_POPUP_LOG2_BACKCOLOR,IDC_POPUP_LOG3_BACKCOLOR,IDC_POPUP_LOG4_BACKCOLOR,IDC_POPUP_LOG5_BACKCOLOR,IDC_POPUP_SPAM_BACKCOLOR};
+static BOOL CALLBACK DlgProcIcqPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BYTE bEnabled;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_POPUPS_LOG_ENABLED, ICQGetContactSettingByte(NULL,"PopupsLogEnabled",DEFAULT_LOG_POPUPS_ENABLED));
+ CheckDlgButton(hwndDlg, IDC_POPUPS_SPAM_ENABLED, ICQGetContactSettingByte(NULL,"PopupsSpamEnabled",DEFAULT_SPAM_POPUPS_ENABLED));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG0_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups0TextColor",DEFAULT_LOG0_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG0_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups0BackColor",DEFAULT_LOG0_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG0_TIMEOUT, ICQGetContactSettingDword(NULL,"Popups0Timeout",DEFAULT_LOG0_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG1_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups1TextColor",DEFAULT_LOG1_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG1_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups1BackColor",DEFAULT_LOG1_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG1_TIMEOUT, ICQGetContactSettingDword(NULL,"Popups1Timeout",DEFAULT_LOG1_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG2_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups2TextColor",DEFAULT_LOG2_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG2_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups2BackColor",DEFAULT_LOG2_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG2_TIMEOUT, ICQGetContactSettingDword(NULL,"Popups2Timeout",DEFAULT_LOG2_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG3_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups3TextColor",DEFAULT_LOG3_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG3_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups3BackColor",DEFAULT_LOG3_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG3_TIMEOUT, ICQGetContactSettingDword(NULL,"Popups3Timeout",DEFAULT_LOG3_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG4_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsFoundTextColor",DEFAULT_LOG4_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG4_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsFoundBackColor",DEFAULT_LOG4_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG4_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsFoundTimeout",DEFAULT_LOG4_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG5_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsFinishedTextColor",DEFAULT_LOG5_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG5_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsFinishedBackColor",DEFAULT_LOG5_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG5_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsFinishedTimeout",DEFAULT_LOG5_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_SPAM_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsSpamTextColor",DEFAULT_SPAM_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_SPAM_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsSpamBackColor",DEFAULT_SPAM_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_SPAM_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsSpamTimeout",DEFAULT_SPAM_TIMEOUT),FALSE);
+ bEnabled = ICQGetContactSettingByte(NULL,"PopupsWinColors",DEFAULT_POPUPS_WIN_COLORS);
+ CheckDlgButton(hwndDlg, IDC_USEWINCOLORS, bEnabled);
+ icq_EnableMultipleControls(hwndDlg, icqPopupColorControls, sizeof(icqPopupColorControls)/sizeof(icqPopupColorControls[0]), bEnabled);
+ CheckDlgButton(hwndDlg, IDC_USESYSICONS, ICQGetContactSettingByte(NULL,"PopupsSysIcons",DEFAULT_POPUPS_SYS_ICONS));
+ bEnabled = ICQGetContactSettingByte(NULL,"PopupsEnabled",DEFAULT_POPUPS_ENABLED);
+ CheckDlgButton(hwndDlg, IDC_POPUPS_ENABLED, bEnabled);
+ icq_EnableMultipleControls(hwndDlg, icqPopupsControls, sizeof(icqPopupsControls)/sizeof(icqPopupsControls[0]), bEnabled);
+ icq_EnableMultipleControls(hwndDlg, icqPopupColorControls, sizeof(icqPopupColorControls)/sizeof(icqPopupColorControls[0]), bEnabled);
+
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_PREVIEW:
+ {
+ ShowPopUpMsg(NULL, "Popup Title", "Sample Note", LOG_NOTE);
+ ShowPopUpMsg(NULL, "Popup Title", "Sample Warning", LOG_WARNING);
+ ShowPopUpMsg(NULL, "Popup Title", "Sample Error", LOG_ERROR);
+ ShowPopUpMsg(NULL, "Popup Title", "Sample Fatal", LOG_FATAL);
+ ShowPopUpMsg(NULL, "Popup Title", "Sample Warning", LOG_WARNING);
+ ShowPopUpMsg(NULL, "Contact", "...was found!", LOG_FOUND);
+ ShowPopUpMsg(NULL, "Active Status Scan", "Users Status Scan Complete", LOG_FINISHED);
+ ShowPopUpMsg(NULL, "Popup Title", "Sample Spambot", POPTYPE_SPAM);
+ }
+ return FALSE;
+
+ case IDC_POPUPS_ENABLED:
+ bEnabled = IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED);
+ icq_EnableMultipleControls(hwndDlg, icqPopupsControls, sizeof(icqPopupsControls)/sizeof(icqPopupsControls[0]), bEnabled);
+ icq_EnableMultipleControls(hwndDlg, icqPopupColorControls, sizeof(icqPopupColorControls)/sizeof(icqPopupColorControls[0]), bEnabled & IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED));
+ break;
+
+ case IDC_USEWINCOLORS:
+ bEnabled = IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED);
+ icq_EnableMultipleControls(hwndDlg, icqPopupColorControls, sizeof(icqPopupColorControls)/sizeof(icqPopupColorControls[0]), bEnabled);
+ break;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ ICQWriteContactSettingByte(NULL,"PopupsEnabled",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED));
+ ICQWriteContactSettingByte(NULL,"PopupsLogEnabled",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_POPUPS_LOG_ENABLED));
+ ICQWriteContactSettingByte(NULL,"PopupsSpamEnabled",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_POPUPS_SPAM_ENABLED));
+ ICQWriteContactSettingDword(NULL,"Popups0TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG0_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"Popups0BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG0_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"Popups0Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG0_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"Popups1TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG1_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"Popups1BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG1_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"Popups1Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG1_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"Popups2TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG2_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"Popups2BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG2_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"Popups2Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG2_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"Popups3TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG3_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"Popups3BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG3_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"Popups3Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG3_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"PopupsFoundTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG4_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsFoundBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG4_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsFoundTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG4_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"PopupsFinishedTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG5_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsFinishedBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG5_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsFinishedTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG5_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"PopupsSpamTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_SPAM_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsSpamBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_SPAM_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsSpamTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_SPAM_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingByte(NULL,"PopupsWinColors",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_USEWINCOLORS));
+ ICQWriteContactSettingByte(NULL,"PopupsSysIcons",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_USESYSICONS));
+
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+
+int ShowPopUpMsg(HANDLE hContact, const char* szTitle, const char* szMsg, BYTE bType)
+{
+ if (bPopUpService && ICQGetContactSettingByte(NULL, "PopupsEnabled", DEFAULT_POPUPS_ENABLED))
+ {
+ POPUPDATAEX ppd = {0};
+ POPUPDATAW ppdw = {0};
+ LPCTSTR rsIcon;
+ HINSTANCE hIcons = NULL;
+ char szPrefix[32], szSetting[32];
+
+ strcpy(szPrefix, "Popups");
+ ppd.iSeconds = 0;
+
+ switch(bType)
+ {
+ case LOG_NOTE:
+ rsIcon = MAKEINTRESOURCE(IDI_INFORMATION);
+ ppd.colorBack = DEFAULT_LOG0_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG0_TEXT_COLORS;
+ strcat(szPrefix, "0");
+ break;
+
+ case LOG_WARNING:
+ rsIcon = MAKEINTRESOURCE(IDI_WARNING);
+ ppd.colorBack = DEFAULT_LOG1_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG1_TEXT_COLORS;
+ strcat(szPrefix, "1");
+ break;
+
+ case LOG_ERROR:
+ rsIcon = MAKEINTRESOURCE(IDI_ERROR);
+ ppd.colorBack = DEFAULT_LOG2_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG2_TEXT_COLORS;
+ strcat(szPrefix, "2");
+ break;
+
+ case LOG_FATAL:
+ rsIcon = MAKEINTRESOURCE(IDI_ERROR);
+ ppd.colorBack = DEFAULT_LOG3_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG3_TEXT_COLORS;
+ strcat(szPrefix, "3");
+ break;
+
+ case POPTYPE_SPAM:
+ rsIcon = MAKEINTRESOURCE(IDI_WARNING);
+ ppd.colorBack = DEFAULT_SPAM_BACK_COLORS;
+ ppd.colorText = DEFAULT_SPAM_TEXT_COLORS;
+ strcat(szPrefix, "Spam");
+ break;
+
+ case LOG_FOUND:
+ hIcons = hInst;
+ rsIcon = MAKEINTRESOURCE(IDI_HIDDEN);
+ ppd.colorBack = DEFAULT_LOG4_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG4_TEXT_COLORS;
+ strcat(szPrefix, "Found");
+ break;
+
+ case LOG_FINISHED:
+ hIcons = hInst;
+ rsIcon = MAKEINTRESOURCE(IDI_STOP);
+ ppd.colorBack = DEFAULT_LOG5_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG5_TEXT_COLORS;
+ strcat(szPrefix, "Finished");
+ break;
+
+ default:
+ return -1;
+ }
+ if (!ICQGetContactSettingByte(NULL, "PopupsSysIcons", DEFAULT_POPUPS_SYS_ICONS))
+ {
+ hIcons = hInst;
+ rsIcon = MAKEINTRESOURCE(IDI_ICQ);
+ }
+ ppd.lchIcon = (HICON)LoadImage(hIcons, rsIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ strcpy(szSetting, szPrefix);
+ strcat(szSetting, "TextColor");
+ ppd.colorText = ICQGetContactSettingDword(NULL, szSetting, ppd.colorText);
+ strcpy(szSetting, szPrefix);
+ strcat(szSetting, "BackColor");
+ ppd.colorBack = ICQGetContactSettingDword(NULL, szSetting, ppd.colorBack);
+ strcpy(szSetting, szPrefix);
+ strcat(szSetting, "Timeout");
+ ppd.iSeconds = ICQGetContactSettingDword(NULL, szSetting, ppd.iSeconds);
+
+ if (ServiceExists(MS_POPUP_ADDPOPUPW))
+ { // call unicode popup module
+ wchar_t *tmp;
+ char str[MAX_SECONDLINE];
+
+ tmp = make_unicode_string(ICQTranslateUtfStatic(szTitle, str));
+ memmove(ppdw.lpwzContactName, tmp, wcslen(tmp)*sizeof(wchar_t));
+ SAFE_FREE(&tmp);
+ tmp = make_unicode_string(ICQTranslateUtfStatic(szMsg, str));
+ memmove(ppdw.lpwzText, tmp, wcslen(tmp)*sizeof(wchar_t));
+ SAFE_FREE(&tmp);
+ ppdw.lchContact = hContact;
+ ppdw.lchIcon = ppd.lchIcon;
+ ppdw.colorBack = ppd.colorBack;
+ ppdw.colorText = ppd.colorText;
+ ppdw.PluginWindowProc = NULL;
+ ppdw.PluginData = NULL;
+ ppdw.iSeconds = ppd.iSeconds;
+
+ return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&ppdw, 0);
+ }
+ else
+ {
+ char str[MAX_SECONDLINE];
+
+ utf8_decode_static(ICQTranslateUtfStatic(szTitle, str), ppd.lpzContactName, MAX_CONTACTNAME);
+ utf8_decode_static(ICQTranslateUtfStatic(szMsg, str), ppd.lpzText, MAX_SECONDLINE);
+ ppd.lchContact = hContact;
+ ppd.PluginWindowProc = NULL;
+ ppd.PluginData = NULL;
+
+ return CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+ }
+ }
+ return -1; // Failure
+}
diff --git a/icqj_mod/icq_popups.h b/icqj_mod/icq_popups.h new file mode 100644 index 0000000..d7d77ca --- /dev/null +++ b/icqj_mod/icq_popups.h @@ -0,0 +1,50 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_popups.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Headers for PopUp Plugin support
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_POPUPS_H
+#define __ICQ_POPUPS_H
+
+
+#define POPTYPE_SPAM 254 // this is for spambots
+
+
+void InitPopUps();
+void InitPopupOpts(WPARAM wParam);
+
+int ShowPopUpMsg(HANDLE hContact, const char* szTitle, const char* szMsg, BYTE bType);
+
+
+#endif /* __ICQ_POPUPS_H */
diff --git a/icqj_mod/icq_rates.c b/icqj_mod/icq_rates.c new file mode 100644 index 0000000..fa84c4c --- /dev/null +++ b/icqj_mod/icq_rates.c @@ -0,0 +1,330 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_rates.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Ăşt, 16 V 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Rate Management stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+// links to functions that are under Rate Control
+extern DWORD sendXStatusDetailsRequest(HANDLE hContact, int bForced);
+
+static int rGroupXtrazRequest = 4500; // represents higher limits for ICQ Rate Group #3
+static int tGroupXtrazRequest;
+static int rGroupMsgResponse = 6000; // dtto #1
+static int tGroupMsgResponse;
+
+static CRITICAL_SECTION ratesMutex; // we need to be thread safe
+
+static rate_record **pendingList1; // rate queue for xtraz requests
+static int pendingListSize1;
+
+static rate_record **pendingList2; // rate queue for msg responses
+static int pendingListSize2;
+
+
+
+typedef struct rate_delay_args_s
+{
+ int nDelay;
+ void (*delaycode)();
+} rate_delay_args;
+
+void __cdecl rateDelayThread(rate_delay_args* pArgs)
+{
+ SleepEx(pArgs->nDelay, TRUE);
+ pArgs->delaycode();
+
+ SAFE_FREE(&pArgs);
+ return;
+}
+
+
+
+void InitDelay(int nDelay, void (*delaycode)())
+{
+ rate_delay_args* pArgs;
+
+//#ifdef _DEBUG
+ NetLog_Server("Delay %dms", nDelay);
+//#endif
+
+ pArgs = (rate_delay_args*)SAFE_MALLOC(sizeof(rate_delay_args)); // This will be freed in the new thread
+
+ pArgs->nDelay = nDelay;
+ pArgs->delaycode = delaycode;
+
+ forkthread(rateDelayThread, 0, pArgs);
+}
+
+
+
+static void RatesTimer1()
+{
+ rate_record *item;
+ int nLev;
+
+ if (!pendingList1) return;
+
+ EnterCriticalSection(&ratesMutex);
+ // take from queue, execute
+ item = pendingList1[0];
+ if (pendingListSize1 > 1)
+ { // we need to keep order
+ memmove(&pendingList1[0], &pendingList1[1], (pendingListSize1 - 1)*sizeof(rate_record*));
+ }
+ else
+ SAFE_FREE((void**)&pendingList1);
+ pendingListSize1--;
+ nLev = rGroupXtrazRequest*19/20 + (GetTickCount() - tGroupXtrazRequest)/20;
+ rGroupXtrazRequest = nLev < 4500 ? nLev : 4500;
+ tGroupXtrazRequest = GetTickCount();
+ if (pendingListSize1 && icqOnline)
+ { // in queue remains some items, setup timer
+ int nDelay = (3800 - rGroupXtrazRequest)*20;
+
+ if (nDelay < 10) nDelay = 10;
+ InitDelay(nDelay, RatesTimer1);
+ }
+ if (!icqOnline)
+ {
+ int i;
+
+ for (i=0; i<pendingListSize1; i++) SAFE_FREE(&pendingList1[i]);
+ SAFE_FREE((void**)&pendingList1);
+ pendingListSize1 = 0;
+ }
+ LeaveCriticalSection(&ratesMutex);
+
+ if (icqOnline)
+ {
+ NetLog_Server("Rates: Resuming Xtraz request.");
+ if (item->bType = RIT_XSTATUS_REQUEST)
+ sendXStatusDetailsRequest(item->hContact, FALSE);
+ }
+ else
+ NetLog_Server("Rates: Discarding request.");
+ SAFE_FREE(&item);
+}
+
+
+
+static void putItemToQueue1(rate_record *item, int nLev)
+{
+ int nDelay = (3800 - nLev)*20;
+
+ if (!icqOnline) return;
+
+ NetLog_Server("Rates: Delaying operation.");
+
+ if (pendingListSize1)
+ { // something already in queue, check duplicity
+ rate_record *tmp;
+ int i;
+
+ for (i = 0; i < pendingListSize1; i++)
+ { // TODO: make this more universal - for more xtraz msg types
+ if (pendingList1[i]->hContact == item->hContact)
+ return; // request xstatus from same contact, do it only once
+ }
+ pendingListSize1++;
+ pendingList1 = (rate_record**)realloc(pendingList1, pendingListSize1*sizeof(rate_record*));
+ tmp = (rate_record*)SAFE_MALLOC(sizeof(rate_record));
+ memcpy(tmp, item, sizeof(rate_record));
+ pendingList1[pendingListSize1 - 1] = tmp;
+ }
+ else
+ {
+ rate_record *tmp;
+
+ pendingListSize1++;
+ pendingList1 = (rate_record**)SAFE_MALLOC(sizeof(rate_record*));
+ tmp = (rate_record*)SAFE_MALLOC(sizeof(rate_record));
+ memcpy(tmp, item, sizeof(rate_record));
+ pendingList1[0] = tmp;
+
+ if (nDelay < 10) nDelay = 10;
+ if (nDelay < item->nMinDelay) nDelay = item->nMinDelay;
+ InitDelay(nDelay, RatesTimer1);
+ }
+}
+
+
+
+static void RatesTimer2()
+{
+ rate_record *item;
+ int nLev;
+
+ if (!pendingList2) return;
+
+ EnterCriticalSection(&ratesMutex);
+ // take from queue, execute
+ item = pendingList2[0];
+ if (pendingListSize2 > 1)
+ { // we need to keep order
+ memmove(&pendingList2[0], &pendingList2[1], (pendingListSize2 - 1)*sizeof(rate_record*));
+ }
+ else
+ SAFE_FREE((void**)&pendingList2);
+ pendingListSize2--;
+ nLev = rGroupMsgResponse*79/80 + (GetTickCount() - tGroupMsgResponse)/80;
+ rGroupMsgResponse = nLev < 6000 ? nLev : 6000;
+ tGroupMsgResponse = GetTickCount();
+ if (pendingListSize2 && icqOnline)
+ { // in queue remains some items, setup timer
+ int nDelay = (4500 - rGroupMsgResponse)*80;
+
+ if (nDelay < 10) nDelay = 10;
+ InitDelay(nDelay, RatesTimer2);
+ }
+ if (!icqOnline)
+ {
+ int i;
+
+ for (i=0; i<pendingListSize2; i++) SAFE_FREE(&pendingList2[i]);
+ SAFE_FREE((void**)&pendingList2);
+ pendingListSize2 = 0;
+ }
+ LeaveCriticalSection(&ratesMutex);
+
+ if (icqOnline)
+ {
+ NetLog_Server("Rates: Resuming message response.");
+ if (item->bType == RIT_AWAYMSG_RESPONSE)
+ {
+ icq_sendAwayMsgReplyServ(item->dwUin, item->dwMid1, item->dwMid2, item->wCookie, item->wVersion, item->msgType, MirandaStatusToAwayMsg(AwayMsgTypeToStatus(item->msgType)));
+ }
+ else if (item->bType == RIT_XSTATUS_RESPONSE)
+ {
+ SendXtrazNotifyResponse(item->dwUin, item->dwMid1, item->dwMid2, item->wCookie, item->szData, strlennull(item->szData), item->bThruDC);
+ }
+ }
+ else
+ NetLog_Server("Rates: Discarding response.");
+ SAFE_FREE(&item->szData);
+ SAFE_FREE(&item);
+}
+
+
+
+static void putItemToQueue2(rate_record *item, int nLev)
+{
+ int nDelay = (4500 - nLev)*80;
+ rate_record *tmp;
+
+ if (!icqOnline) return;
+
+ NetLog_Server("Rates: Delaying operation.");
+
+ pendingListSize2++;
+ pendingList2 = (rate_record**)realloc(pendingList2, pendingListSize2*sizeof(rate_record*));
+ tmp = (rate_record*)SAFE_MALLOC(sizeof(rate_record));
+ memcpy(tmp, item, sizeof(rate_record));
+ tmp->szData = null_strdup(item->szData);
+ pendingList2[pendingListSize2 - 1] = tmp;
+
+ if (pendingListSize2 == 1)
+ { // queue was empty setup timer
+ if (nDelay < 10) nDelay = 10;
+ InitDelay(nDelay, RatesTimer2);
+ }
+}
+
+
+
+int handleRateItem(rate_record *item, BOOL bAllowDelay)
+{
+ int tNow = GetTickCount();
+
+ EnterCriticalSection(&ratesMutex);
+
+ if (item->rate_group == 0x101)
+ { // xtraz request
+ int nLev = rGroupXtrazRequest*19/20 + (tNow - tGroupXtrazRequest)/20;
+
+ if ((nLev < 3800 || item->nMinDelay) && bAllowDelay)
+ { // limit reached or min delay configured, add to queue
+ putItemToQueue1(item, nLev);
+ LeaveCriticalSection(&ratesMutex);
+ return 1;
+ }
+ else
+ {
+ rGroupXtrazRequest = nLev < 4500 ? nLev : 4500;
+ tGroupXtrazRequest = tNow;
+ }
+ }
+ else if (item->rate_group == 0x102)
+ { // msg response
+ int nLev = rGroupMsgResponse*79/80 + (tNow - tGroupMsgResponse)/80;
+
+ if (nLev < 4500)
+ { // limit reached or min delay configured, add to queue
+ putItemToQueue2(item, nLev);
+ LeaveCriticalSection(&ratesMutex);
+ return 1;
+ }
+ else
+ {
+ rGroupMsgResponse = nLev < 6000 ? nLev : 6000;
+ tGroupMsgResponse = tNow;
+ }
+ }
+ LeaveCriticalSection(&ratesMutex);
+
+ return 0;
+}
+
+
+
+void InitRates()
+{
+ InitializeCriticalSection(&ratesMutex);
+
+ pendingListSize1 = 0;
+ pendingList1 = NULL;
+ pendingListSize2 = 0;
+ pendingList2 = NULL;
+
+ tGroupXtrazRequest = tGroupMsgResponse = GetTickCount();
+}
+
+
+
+void UninitRates()
+{
+ SAFE_FREE((void**)&pendingList1);
+ SAFE_FREE((void**)&pendingList2);
+ DeleteCriticalSection(&ratesMutex);
+}
diff --git a/icqj_mod/icq_rates.h b/icqj_mod/icq_rates.h new file mode 100644 index 0000000..88fdc2e --- /dev/null +++ b/icqj_mod/icq_rates.h @@ -0,0 +1,68 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_rates.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_RATES_H
+#define __ICQ_RATES_H
+
+
+#define RIT_AWAYMSG_RESPONSE 0x01 // response to status msg request
+
+#define RIT_XSTATUS_REQUEST 0x10 // schedule xstatus details requests
+#define RIT_XSTATUS_RESPONSE 0x11 // response to xstatus details request
+
+typedef struct rate_record_s
+{
+ BYTE bType; // type of request
+ int rate_group;
+ int nMinDelay;
+ HANDLE hContact;
+ DWORD dwUin;
+ DWORD dwMid1;
+ DWORD dwMid2;
+ WORD wCookie;
+ WORD wVersion;
+ BOOL bThruDC;
+ char *szData;
+ BYTE msgType;
+} rate_record;
+
+// Level 2 of rate management
+int handleRateItem(rate_record *item, BOOL bAllowDelay);
+
+void InitRates();
+void UninitRates();
+
+#endif /* __ICQ_RATES_H */
diff --git a/icqj_mod/icq_server.c b/icqj_mod/icq_server.c new file mode 100644 index 0000000..d275fc3 --- /dev/null +++ b/icqj_mod/icq_server.c @@ -0,0 +1,411 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_server.c,v $
+// Revision : $Revision: 3316 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Manages main server connection, low-level communication
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern void handleXStatusCaps(HANDLE hContact, char* caps, int capsize);
+
+extern CRITICAL_SECTION connectionHandleMutex;
+extern WORD wLocalSequence;
+extern CRITICAL_SECTION localSeqMutex;
+HANDLE hServerConn;
+WORD wListenPort;
+WORD wLocalSequence;
+DWORD dwLocalDirectConnCookie;
+HANDLE hServerPacketRecver;
+static pthread_t serverThreadId;
+HANDLE hDirectBoundPort;
+
+static int handleServerPackets(unsigned char* buf, int len, serverthread_info* info);
+
+
+static DWORD __stdcall icq_serverThread(serverthread_start_info* infoParam)
+{
+ serverthread_info info = {0};
+
+ info.isLoginServer = 1;
+ info.wAuthKeyLen = infoParam->wPassLen;
+ strncpy(info.szAuthKey, infoParam->szPass, info.wAuthKeyLen);
+
+ srand(time(NULL));
+
+ dwLocalDirectConnCookie = rand() ^ (rand() << 16);
+
+ ResetSettingsOnConnect();
+
+ // Connect to the login server
+ NetLog_Server("Authenticating to server");
+ {
+ NETLIBOPENCONNECTION nloc = infoParam->nloc;
+
+ hServerConn = NetLib_OpenConnection(ghServerNetlibUser, &nloc);
+
+ SAFE_FREE((void**)&nloc.szHost);
+ }
+ SAFE_FREE(&infoParam);
+
+
+ // Login error
+ if (hServerConn == NULL)
+ {
+ DWORD dwError = GetLastError();
+
+ hServerConn = NULL;
+
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+
+ icq_LogUsingErrorCode(LOG_ERROR, dwError, "Unable to connect to ICQ login server");
+
+ return 0;
+ }
+
+
+ // Initialize direct connection ports
+ {
+ NETLIBBIND nlb = {0};
+
+ nlb.cbSize = sizeof(nlb);
+ nlb.pfnNewConnection = icq_newConnectionReceived;
+ hDirectBoundPort = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)ghDirectNetlibUser, (LPARAM)&nlb);
+ if (!hDirectBoundPort && (GetLastError() == 87))
+ { // this ensures old Miranda also can bind a port for a dc
+ nlb.cbSize = NETLIBBIND_SIZEOF_V1;
+ hDirectBoundPort = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)ghDirectNetlibUser, (LPARAM)&nlb);
+ }
+ if (hDirectBoundPort == NULL)
+ {
+ icq_LogUsingErrorCode(LOG_WARNING, GetLastError(), "Miranda was unable to allocate a port to listen for direct peer-to-peer connections between clients. You will be able to use most of the ICQ network without problems but you may be unable to send or receive files.\n\nIf you have a firewall this may be blocking Miranda, in which case you should configure your firewall to leave some ports open and tell Miranda which ports to use in M->Options->ICQ->Network.");
+ wListenPort = 0;
+ }
+ wListenPort = nlb.wPort;
+ if (!ICQGetContactSettingByte(NULL, "ConstRealIP", 0))
+ ICQWriteContactSettingDword(NULL, "RealIP", nlb.dwInternalIP);
+
+ ICQWriteContactSettingDword(NULL, "OldRealIP", nlb.dwInternalIP);
+ ICQWriteContactSettingWord(NULL, "UserPort", wListenPort);
+ ICQWriteContactSettingWord(NULL, "OldUserPort", wListenPort);
+ }
+
+
+ // This is the "infinite" loop that receives the packets from the ICQ server
+ {
+ int recvResult;
+ NETLIBPACKETRECVER packetRecv = {0};
+
+ hServerPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 8192);
+ packetRecv.cbSize = sizeof(packetRecv);
+ packetRecv.dwTimeout = INFINITE;
+ while(hServerConn)
+ {
+ if (info.bReinitRecver)
+ { // we reconnected, reinit struct
+ info.bReinitRecver = 0;
+ ZeroMemory(&packetRecv, sizeof(packetRecv));
+ packetRecv.cbSize = sizeof(packetRecv);
+ packetRecv.dwTimeout = INFINITE;
+ }
+
+ recvResult = CallService(MS_NETLIB_GETMOREPACKETS,(WPARAM)hServerPacketRecver, (LPARAM)&packetRecv);
+
+ if (recvResult == 0)
+ {
+ NetLog_Server("Clean closure of server socket");
+ break;
+ }
+
+ if (recvResult == SOCKET_ERROR)
+ {
+ NetLog_Server("Abortive closure of server socket, error: %d", GetLastError());
+ break;
+ }
+
+ // Deal with the packet
+ packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable, &info);
+ }
+
+ // Close the packet receiver (connection may still be open)
+ Netlib_CloseHandle(hServerPacketRecver);
+ hServerPacketRecver = 0;
+
+ // Close DC port
+ Netlib_CloseHandle(hDirectBoundPort);
+ hDirectBoundPort = 0;
+ }
+
+ // Time to shutdown
+ icq_serverDisconnect(FALSE);
+ if (gnCurrentStatus != ID_STATUS_OFFLINE)
+ {
+ if (!info.bLoggedIn)
+ {
+ icq_LogMessage(LOG_FATAL, "Connection failed.\nLogin sequence failed for unknown reason.\nTry again later.");
+ }
+
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ }
+
+ // Close all open DC connections
+ CloseContactDirectConns(NULL);
+
+ // Offline all contacts
+ {
+ HANDLE hContact;
+
+ hContact= ICQFindFirstContact();
+
+ while (hContact)
+ {
+ DWORD dwUIN;
+ uid_str szUID;
+
+ if (!ICQGetContactSettingUID(hContact, &dwUIN, &szUID))
+ {
+ if (ICQGetContactStatus(hContact) != ID_STATUS_OFFLINE)
+ {
+ ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+
+ handleXStatusCaps(hContact, NULL, 0);
+ }
+ }
+
+ hContact = ICQFindNextContact(hContact);
+ }
+ }
+ ICQWriteContactSettingDword(NULL, "LogonTS", 0); // clear logon time
+
+ FlushServerIDs(); // clear server IDs list
+ FlushPendingOperations(); // clear pending operations list
+ FlushGroupRenames(); // clear group rename in progress list
+
+ NetLog_Server("%s thread ended.", "Server");
+
+ return 0;
+}
+
+
+
+void icq_serverDisconnect(BOOL bBlock)
+{
+ EnterCriticalSection(&connectionHandleMutex);
+
+ if (hServerConn)
+ {
+ int sck = CallService(MS_NETLIB_GETSOCKET, (WPARAM)hServerConn, (LPARAM)0);
+ if (sck!=INVALID_SOCKET) shutdown(sck, 2); // close gracefully
+ Netlib_CloseHandle(hServerConn);
+ FreeGatewayIndex(hServerConn);
+ hServerConn = NULL;
+ LeaveCriticalSection(&connectionHandleMutex);
+
+ // Not called from network thread?
+ if (bBlock && GetCurrentThreadId() != serverThreadId.dwThreadId)
+ {
+ while (WaitForSingleObjectEx(serverThreadId.hThread, INFINITE, TRUE) != WAIT_OBJECT_0);
+ CloseHandle(serverThreadId.hThread);
+ }
+ else
+ CloseHandle(serverThreadId.hThread);
+ }
+ else
+ LeaveCriticalSection(&connectionHandleMutex);
+
+ StopKeepAlive(); // signal keep-alive thread to stop
+}
+
+
+
+static int handleServerPackets(unsigned char* buf, int len, serverthread_info* info)
+{
+ BYTE channel;
+ WORD sequence;
+ WORD datalen;
+ int bytesUsed = 0;
+
+ while (len > 0)
+ {
+ if (info->bReinitRecver)
+ break;
+
+ // All FLAPS begin with 0x2a
+ if (*buf++ != FLAP_MARKER)
+ break;
+
+ if (len < 6)
+ break;
+
+ unpackByte(&buf, &channel);
+ unpackWord(&buf, &sequence);
+ unpackWord(&buf, &datalen);
+
+ if (len < 6 + datalen)
+ break;
+
+
+#ifdef _DEBUG
+ NetLog_Server("Server FLAP: Channel %u, Seq %u, Length %u bytes", channel, sequence, datalen);
+#endif
+
+ switch (channel)
+ {
+ case ICQ_LOGIN_CHAN:
+ handleLoginChannel(buf, datalen, info);
+ break;
+
+ case ICQ_DATA_CHAN:
+ handleDataChannel(buf, datalen, info);
+ break;
+
+ case ICQ_ERROR_CHAN:
+ handleErrorChannel(buf, datalen);
+ break;
+
+ case ICQ_CLOSE_CHAN:
+ handleCloseChannel(buf, datalen, info);
+ break; // we need this for walking thru proxy
+
+ case ICQ_PING_CHAN:
+ handlePingChannel(buf, datalen);
+ break;
+
+ default:
+ NetLog_Server("Warning: Unhandled %s FLAP Channel: Channel %u, Seq %u, Length %u bytes", "Server", channel, sequence, datalen);
+ break;
+ }
+
+ /* Increase pointers so we can check for more FLAPs */
+ buf += datalen;
+ len -= (datalen + 6);
+ bytesUsed += (datalen + 6);
+ }
+
+ return bytesUsed;
+}
+
+
+
+void sendServPacket(icq_packet* pPacket)
+{
+ // This critsec makes sure that the sequence order doesn't get screwed up
+ EnterCriticalSection(&localSeqMutex);
+
+ if (hServerConn)
+ {
+ int nRetries;
+ int nSendResult;
+
+
+ // :IMPORTANT:
+ // The FLAP sequence must be a WORD. When it reaches 0xFFFF it should wrap to
+ // 0x0000, otherwise we'll get kicked by server.
+ wLocalSequence++;
+
+ // Pack sequence number
+ pPacket->pData[2] = ((wLocalSequence & 0xff00) >> 8);
+ pPacket->pData[3] = (wLocalSequence & 0x00ff);
+
+ for (nRetries = 3; nRetries >= 0; nRetries--)
+ {
+ nSendResult = Netlib_Send(hServerConn, (const char *)pPacket->pData, pPacket->wLen, 0);
+
+ if (nSendResult != SOCKET_ERROR)
+ break;
+
+ Sleep(1000);
+ }
+
+
+ // Send error
+ if (nSendResult == SOCKET_ERROR)
+ {
+ icq_LogUsingErrorCode(LOG_ERROR, GetLastError(), "Your connection with the ICQ server was abortively closed");
+ icq_serverDisconnect(FALSE);
+
+ if (gnCurrentStatus != ID_STATUS_OFFLINE)
+ {
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ }
+ }
+ }
+ else
+ {
+ NetLog_Server("Error: Failed to send packet (no connection)");
+ }
+
+ LeaveCriticalSection(&localSeqMutex);
+
+ SAFE_FREE(&pPacket->pData);
+}
+
+
+
+void icq_login(const char* szPassword)
+{
+ DBVARIANT dbvServer = {DBVT_DELETED};
+ char szServer[MAX_PATH];
+ serverthread_start_info* stsi;
+ DWORD dwUin;
+
+
+ dwUin = ICQGetContactSettingUIN(NULL);
+ stsi = (serverthread_start_info*)SAFE_MALLOC(sizeof(serverthread_start_info));
+ stsi->nloc.cbSize = sizeof(NETLIBOPENCONNECTION);
+
+ // Server host name
+ if (ICQGetContactStaticString(NULL, "OscarServer", szServer, MAX_PATH))
+ stsi->nloc.szHost = null_strdup(DEFAULT_SERVER_HOST);
+ else
+ stsi->nloc.szHost = null_strdup(szServer);
+
+ // Server port
+ stsi->nloc.wPort = (WORD)ICQGetContactSettingWord(NULL, "OscarPort", DEFAULT_SERVER_PORT);
+ if (stsi->nloc.wPort == 0)
+ stsi->nloc.wPort = RandRange(1024, 65535);
+
+ // User password
+ stsi->wPassLen = strlennull(szPassword);
+ if (stsi->wPassLen > 9) stsi->wPassLen = 9;
+ strncpy(stsi->szPass, szPassword, stsi->wPassLen);
+ stsi->szPass[stsi->wPassLen] = '\0';
+
+ // Randomize sequence
+ wLocalSequence = (WORD)RandRange(0, 0x7fff);
+
+ dwLocalUIN = dwUin;
+
+ serverThreadId.hThread = (HANDLE)forkthreadex(NULL, 0, icq_serverThread, stsi, 0, &serverThreadId.dwThreadId);
+}
diff --git a/icqj_mod/icq_server.h b/icqj_mod/icq_server.h new file mode 100644 index 0000000..d573b82 --- /dev/null +++ b/icqj_mod/icq_server.h @@ -0,0 +1,66 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_server.h,v $
+// Revision : $Revision: 3316 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Declarations for server thread
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_SERVER_H
+#define __ICQ_SERVER_H
+
+typedef struct serverthread_start_info_s {
+ NETLIBOPENCONNECTION nloc;
+ WORD wPassLen;
+ char szPass[20];
+} serverthread_start_info;
+
+typedef struct serverthread_info_s {
+ int bLoggedIn;
+ int isLoginServer;
+ BYTE szAuthKey[20];
+ WORD wAuthKeyLen;
+ char *newServer;
+ BYTE* cookieData;
+ int cookieDataLen;
+ int newServerReady;
+ int isMigrating;
+ int bReinitRecver;
+} serverthread_info;
+
+/*---------* Functions *---------------*/
+
+void icq_serverDisconnect(BOOL bBlock);
+void sendServPacket(icq_packet *);
+void icq_login(const char *szPassword);
+
+
+#endif /* __ICQ_SERVER_H */
diff --git a/icqj_mod/icq_servlist.c b/icqj_mod/icq_servlist.c new file mode 100644 index 0000000..1c532d1 --- /dev/null +++ b/icqj_mod/icq_servlist.c @@ -0,0 +1,1925 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_servlist.c,v $
+// Revision : $Revision: 3119 $
+// Last change on : $Date: 2006-06-11 23:24:04 +0200 (Sun, 11 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Functions that handles list of used server IDs, sends low-level packets for SSI information
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern BOOL bIsSyncingCL;
+
+static HANDLE hHookSettingChanged = NULL;
+static HANDLE hHookContactDeleted = NULL;
+static DWORD* pwIDList = NULL;
+static int nIDListCount = 0;
+static int nIDListSize = 0;
+
+
+
+// cookie struct for pending records
+typedef struct ssipendingitem_t
+{
+ HANDLE hContact;
+ char* szGroupPath;
+ GROUPADDCALLBACK ofCallback;
+ servlistcookie* pCookie;
+} ssipendingitem;
+
+static CRITICAL_SECTION servlistMutex;
+static int nPendingCount = 0;
+static int nPendingSize = 0;
+static ssipendingitem** pdwPendingList = NULL;
+static int nJustAddedCount = 0;
+static int nJustAddedSize = 0;
+static HANDLE* pdwJustAddedList = NULL;
+static WORD* pwGroupRenameList = NULL;
+static int nGroupRenameCount = 0;
+static int nGroupRenameSize = 0;
+
+static DWORD updateServContact(HANDLE hContact);
+
+
+// Add running group rename operation
+void AddGroupRename(WORD wGroupID)
+{
+ EnterCriticalSection(&servlistMutex);
+ if (nGroupRenameCount >= nGroupRenameSize)
+ {
+ nGroupRenameSize += 10;
+ pwGroupRenameList = (WORD*)realloc(pwGroupRenameList, nGroupRenameSize * sizeof(WORD));
+ }
+
+ pwGroupRenameList[nGroupRenameCount] = wGroupID;
+ nGroupRenameCount++;
+ LeaveCriticalSection(&servlistMutex);
+}
+
+
+// Remove running group rename operation
+void RemoveGroupRename(WORD wGroupID)
+{
+ int i, j;
+
+ EnterCriticalSection(&servlistMutex);
+ if (pwGroupRenameList)
+ {
+ for (i = 0; i<nGroupRenameCount; i++)
+ {
+ if (pwGroupRenameList[i] == wGroupID)
+ { // we found it, so remove
+ for (j = i+1; j<nGroupRenameCount; j++)
+ {
+ pwGroupRenameList[j-1] = pwGroupRenameList[j];
+ }
+ nGroupRenameCount--;
+ }
+ }
+ }
+ LeaveCriticalSection(&servlistMutex);
+}
+
+
+// Returns true if dwID is reserved
+BOOL IsGroupRenamed(WORD wGroupID)
+{
+ int i;
+
+ EnterCriticalSection(&servlistMutex);
+ if (pwGroupRenameList)
+ {
+ for (i = 0; i<nGroupRenameCount; i++)
+ {
+ if (pwGroupRenameList[i] == wGroupID)
+ {
+ LeaveCriticalSection(&servlistMutex);
+ return TRUE;
+ }
+ }
+ }
+ LeaveCriticalSection(&servlistMutex);
+
+ return FALSE;
+}
+
+
+void FlushGroupRenames()
+{
+ EnterCriticalSection(&servlistMutex);
+ SAFE_FREE(&pwGroupRenameList);
+ nGroupRenameCount = 0;
+ nGroupRenameSize = 0;
+ LeaveCriticalSection(&servlistMutex);
+}
+
+
+// used for adding new contacts to list - sync with visible items
+void AddJustAddedContact(HANDLE hContact)
+{
+ EnterCriticalSection(&servlistMutex);
+ if (nJustAddedCount >= nJustAddedSize)
+ {
+ nJustAddedSize += 10;
+ pdwJustAddedList = (HANDLE*)realloc(pdwJustAddedList, nJustAddedSize * sizeof(HANDLE));
+ }
+
+ pdwJustAddedList[nJustAddedCount] = hContact;
+ nJustAddedCount++;
+ LeaveCriticalSection(&servlistMutex);
+}
+
+
+// was the contact added during this serv-list load
+BOOL IsContactJustAdded(HANDLE hContact)
+{
+ int i;
+
+ EnterCriticalSection(&servlistMutex);
+ if (pdwJustAddedList)
+ {
+ for (i = 0; i<nJustAddedCount; i++)
+ {
+ if (pdwJustAddedList[i] == hContact)
+ {
+ LeaveCriticalSection(&servlistMutex);
+ return TRUE;
+ }
+ }
+ }
+ LeaveCriticalSection(&servlistMutex);
+
+ return FALSE;
+}
+
+
+void FlushJustAddedContacts()
+{
+ EnterCriticalSection(&servlistMutex);
+ SAFE_FREE((void**)&pdwJustAddedList);
+ nJustAddedSize = 0;
+ nJustAddedCount = 0;
+ LeaveCriticalSection(&servlistMutex);
+}
+
+
+
+// Used for event-driven adding of contacts, before it is completed this is used
+static BOOL AddPendingOperation(HANDLE hContact, const char* szGroup, servlistcookie* cookie, GROUPADDCALLBACK ofEvent)
+{
+ BOOL bRes = TRUE;
+ ssipendingitem* pItem = NULL;
+ int i;
+
+ EnterCriticalSection(&servlistMutex);
+ if (pdwPendingList)
+ {
+ for (i = 0; i<nPendingCount; i++)
+ {
+ if (pdwPendingList[i]->hContact == hContact)
+ { // we need the last item for this contact
+ pItem = pdwPendingList[i];
+ }
+ }
+ }
+
+ if (pItem) // we found a pending operation, so link our data
+ {
+ pItem->ofCallback = ofEvent;
+ pItem->pCookie = cookie;
+ pItem->szGroupPath = null_strdup(szGroup); // we need to duplicate the string
+ bRes = FALSE;
+
+ NetLog_Server("Operation postponed.");
+ }
+
+ if (nPendingCount >= nPendingSize) // add new
+ {
+ nPendingSize += 10;
+ pdwPendingList = (ssipendingitem**)realloc(pdwPendingList, nPendingSize * sizeof(ssipendingitem*));
+ }
+
+ pdwPendingList[nPendingCount] = (ssipendingitem*)SAFE_MALLOC(sizeof(ssipendingitem));
+ pdwPendingList[nPendingCount]->hContact = hContact;
+
+ nPendingCount++;
+ LeaveCriticalSection(&servlistMutex);
+
+ return bRes;
+}
+
+
+
+// Check if any pending operation is in progress
+// If yes, get its data and remove it from queue
+void RemovePendingOperation(HANDLE hContact, int nResult)
+{
+ int i, j;
+ ssipendingitem* pItem = NULL;
+
+ EnterCriticalSection(&servlistMutex);
+ if (pdwPendingList)
+ {
+ for (i = 0; i<nPendingCount; i++)
+ {
+ if (pdwPendingList[i]->hContact == hContact)
+ {
+ pItem = pdwPendingList[i];
+ for (j = i+1; j<nPendingCount; j++)
+ {
+ pdwPendingList[j-1] = pdwPendingList[j];
+ }
+ nPendingCount--;
+ if (nResult) // we succeded, go on, resume operation
+ {
+ LeaveCriticalSection(&servlistMutex);
+
+ if (pItem->ofCallback)
+ {
+ NetLog_Server("Resuming postponed operation.");
+
+ makeGroupId(pItem->szGroupPath, pItem->ofCallback, pItem->pCookie);
+ }
+ else if ((int)pItem->pCookie == 1)
+ {
+ NetLog_Server("Resuming postponed update.");
+
+ updateServContact(hContact);
+ }
+
+ SAFE_FREE(&pItem->szGroupPath); // free the string
+ SAFE_FREE(&pItem);
+ return;
+ } // else remove all pending operations for this contact
+ NetLog_Server("Purging postponed operation.");
+ if ((pItem->pCookie) && ((int)pItem->pCookie != 1))
+ SAFE_FREE(&pItem->pCookie->szGroupName); // do not leak nick name on error
+ SAFE_FREE(&pItem->szGroupPath);
+ SAFE_FREE(&pItem);
+ }
+ }
+ }
+ LeaveCriticalSection(&servlistMutex);
+ return;
+}
+
+
+
+// Remove All pending operations
+void FlushPendingOperations()
+{
+ int i;
+
+ EnterCriticalSection(&servlistMutex);
+
+ for (i = 0; i<nPendingCount; i++)
+ {
+ SAFE_FREE((void**)&pdwPendingList[i]);
+ }
+ SAFE_FREE((void**)&pdwPendingList);
+ nPendingCount = 0;
+ nPendingSize = 0;
+
+ LeaveCriticalSection(&servlistMutex);
+}
+
+
+
+// Add a server ID to the list of reserved IDs.
+// To speed up the process, no checks is done, if
+// you try to reserve an ID twice, it will be added again.
+// You should call CheckServerID before reserving an ID.
+void ReserveServerID(WORD wID, int bGroupId)
+{
+ EnterCriticalSection(&servlistMutex);
+ if (nIDListCount >= nIDListSize)
+ {
+ nIDListSize += 100;
+ pwIDList = (DWORD*)realloc(pwIDList, nIDListSize * sizeof(DWORD));
+ }
+
+ pwIDList[nIDListCount] = wID | bGroupId << 0x18;
+ nIDListCount++;
+ LeaveCriticalSection(&servlistMutex);
+}
+
+
+
+// Remove a server ID from the list of reserved IDs.
+// Used for deleting contacts and other modifications.
+void FreeServerID(WORD wID, int bGroupId)
+{
+ int i, j;
+ DWORD dwId = wID | bGroupId << 0x18;
+
+ EnterCriticalSection(&servlistMutex);
+ if (pwIDList)
+ {
+ for (i = 0; i<nIDListCount; i++)
+ {
+ if (pwIDList[i] == dwId)
+ { // we found it, so remove
+ for (j = i+1; j<nIDListCount; j++)
+ {
+ pwIDList[j-1] = pwIDList[j];
+ }
+ nIDListCount--;
+ }
+ }
+ }
+ LeaveCriticalSection(&servlistMutex);
+}
+
+
+// Returns true if dwID is reserved
+BOOL CheckServerID(WORD wID, unsigned int wCount)
+{
+ int i;
+
+ EnterCriticalSection(&servlistMutex);
+ if (pwIDList)
+ {
+ for (i = 0; i<nIDListCount; i++)
+ {
+ if (((pwIDList[i] & 0xFFFF) >= wID) && ((pwIDList[i] & 0xFFFF) <= wID + wCount))
+ {
+ LeaveCriticalSection(&servlistMutex);
+ return TRUE;
+ }
+ }
+ }
+ LeaveCriticalSection(&servlistMutex);
+
+ return FALSE;
+}
+
+
+
+void FlushServerIDs()
+{
+ EnterCriticalSection(&servlistMutex);
+ SAFE_FREE(&pwIDList);
+ nIDListCount = 0;
+ nIDListSize = 0;
+ LeaveCriticalSection(&servlistMutex);
+}
+
+
+
+static int GroupReserveIdsEnumProc(const char *szSetting,LPARAM lParam)
+{
+ if (szSetting && strlennull(szSetting)<5)
+ { // it is probably server group
+ char val[MAX_PATH+2]; // dummy
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING cgs;
+
+ dbv.type = DBVT_ASCIIZ;
+ dbv.pszVal = val;
+ dbv.cchVal = MAX_PATH;
+
+ cgs.szModule=(char*)lParam;
+ cgs.szSetting=szSetting;
+ cgs.pValue=&dbv;
+ if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC,(WPARAM)NULL,(LPARAM)&cgs))
+ { // we failed to read setting, try also utf8 - DB bug
+ dbv.type = DBVT_UTF8;
+ dbv.pszVal = val;
+ dbv.cchVal = MAX_PATH;
+ if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC,(WPARAM)NULL,(LPARAM)&cgs))
+ return 0; // we failed also, invalid setting
+ }
+ if (dbv.type!=DBVT_ASCIIZ)
+ { // it is not a cached server-group name
+ return 0;
+ }
+ ReserveServerID((WORD)strtoul(szSetting, NULL, 0x10), SSIT_GROUP);
+#ifdef _DEBUG
+ NetLog_Server("Loaded group %u:'%s'", strtoul(szSetting, NULL, 0x10), val);
+#endif
+ }
+ return 0;
+}
+
+
+
+int ReserveServerGroups()
+{
+ DBCONTACTENUMSETTINGS dbces;
+ int nStart = nIDListCount;
+
+ char szModule[MAX_PATH+9];
+
+ strcpy(szModule, gpszICQProtoName);
+ strcat(szModule, "SrvGroups");
+
+ dbces.pfnEnumProc = &GroupReserveIdsEnumProc;
+ dbces.szModule = szModule;
+ dbces.lParam = (LPARAM)szModule;
+
+ CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces);
+
+ return nIDListCount - nStart;
+}
+
+
+
+// Load all known server IDs from DB to list
+void LoadServerIDs()
+{
+ HANDLE hContact;
+ WORD wSrvID;
+ int nGroups = 0, nContacts = 0, nPermits = 0, nDenys = 0, nIgnores = 0;
+
+ EnterCriticalSection(&servlistMutex);
+ if (wSrvID = ICQGetContactSettingWord(NULL, "SrvAvatarID", 0))
+ ReserveServerID(wSrvID, SSIT_ITEM);
+ if (wSrvID = ICQGetContactSettingWord(NULL, "SrvVisibilityID", 0))
+ ReserveServerID(wSrvID, SSIT_ITEM);
+
+ nGroups = ReserveServerGroups();
+
+ hContact = ICQFindFirstContact();
+
+ while (hContact)
+ { // search all our contacts, reserve their server IDs
+ if (wSrvID = ICQGetContactSettingWord(hContact, "ServerId", 0))
+ {
+ ReserveServerID(wSrvID, SSIT_ITEM);
+ nContacts++;
+ }
+ if (wSrvID = ICQGetContactSettingWord(hContact, "SrvDenyId", 0))
+ {
+ ReserveServerID(wSrvID, SSIT_ITEM);
+ nDenys++;
+ }
+ if (wSrvID = ICQGetContactSettingWord(hContact, "SrvPermitId", 0))
+ {
+ ReserveServerID(wSrvID, SSIT_ITEM);
+ nPermits++;
+ }
+ if (wSrvID = ICQGetContactSettingWord(hContact, "SrvIgnoreId", 0))
+ {
+ ReserveServerID(wSrvID, SSIT_ITEM);
+ nIgnores++;
+ }
+
+ hContact = ICQFindNextContact(hContact);
+ }
+ LeaveCriticalSection(&servlistMutex);
+
+ NetLog_Server("Loaded SSI: %d contacts, %d groups, %d permit, %d deny, %d ignore items.", nContacts, nGroups, nPermits, nDenys, nIgnores);
+
+ return;
+}
+
+
+
+WORD GenerateServerId(int bGroupId)
+{
+ WORD wId;
+
+ while (TRUE)
+ {
+ // Randomize a new ID
+ // Max value is probably 0x7FFF, lowest value is probably 0x0001 (generated by Icq2Go)
+ // We use range 0x1000-0x7FFF.
+ wId = (WORD)RandRange(0x1000, 0x7FFF);
+
+ if (!CheckServerID(wId, 0))
+ break;
+ }
+
+ ReserveServerID(wId, bGroupId);
+
+ return wId;
+}
+
+
+
+// Generate server ID with wCount IDs free after it, for sub-groups.
+WORD GenerateServerIdPair(int bGroupId, int wCount)
+{
+ WORD wId;
+
+ while (TRUE)
+ {
+ // Randomize a new ID
+ // Max value is probably 0x7FFF, lowest value is probably 0x0001 (generated by Icq2Go)
+ // We use range 0x1000-0x7FFF.
+ wId = (WORD)RandRange(0x1000, 0x7FFF);
+
+ if (!CheckServerID(wId, wCount))
+ break;
+ }
+
+ ReserveServerID(wId, bGroupId);
+
+ return wId;
+}
+
+
+/***********************************************
+ *
+ * --- Low-level packet sending functions ---
+ *
+ */
+
+
+static DWORD icq_sendServerItem(DWORD dwCookie, WORD wAction, WORD wGroupId, WORD wItemId, const char *szName, BYTE *pTLVs, int nTlvLength, WORD wItemType)
+{ // generic packet
+ icq_packet packet;
+ int nNameLen;
+ WORD wTLVlen = (WORD)nTlvLength;
+
+ // Prepare item name length
+ nNameLen = strlennull(szName);
+
+ // Build the packet
+ serverPacketInit(&packet, (WORD)(nNameLen + 20 + wTLVlen));
+ packFNACHeaderFull(&packet, ICQ_LISTS_FAMILY, wAction, 0, dwCookie);
+ packWord(&packet, (WORD)nNameLen);
+ if (nNameLen)
+ packBuffer(&packet, szName, (WORD)nNameLen);
+ packWord(&packet, wGroupId);
+ packWord(&packet, wItemId);
+ packWord(&packet, wItemType);
+ packWord(&packet, wTLVlen);
+ if (wTLVlen)
+ packBuffer(&packet, pTLVs, wTLVlen);
+
+ // Send the packet and return the cookie
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_sendServerContact(HANDLE hContact, DWORD dwCookie, WORD wAction, WORD wGroupId, WORD wContactId)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ icq_packet pBuffer;
+ char *szNick = NULL, *szNote = NULL;
+ BYTE *pData = NULL;
+ int nNickLen, nNoteLen, nDataLen;
+ WORD wTLVlen;
+ BYTE bAuth;
+
+ // Prepare UID
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ {
+ NetLog_Server("Buddy upload failed (UID missing).");
+ return 0;
+ }
+
+ bAuth = ICQGetContactSettingByte(hContact, "Auth", 0);
+ szNick = UniGetContactSettingUtf(hContact, "CList", "MyHandle", NULL);
+ szNote = UniGetContactSettingUtf(hContact, "UserInfo", "MyNotes", NULL);
+
+ {
+ DBVARIANT dbv;
+
+ if (!DBGetContactSetting(hContact, gpszICQProtoName, "ServerData", &dbv))
+ { // read additional server item data
+ nDataLen = dbv.cpbVal;
+ pData = (BYTE*)_alloca(nDataLen);
+ memcpy(pData, dbv.pbVal, nDataLen);
+
+ ICQFreeVariant(&dbv);
+ }
+ else
+ {
+ pData = NULL;
+ nDataLen = 0;
+ }
+ }
+
+ nNickLen = strlennull(szNick);
+ nNoteLen = strlennull(szNote);
+
+ // Build the packet
+ wTLVlen = (nNickLen?4+nNickLen:0) + (nNoteLen?4+nNoteLen:0) + (bAuth?4:0) + nDataLen;
+
+ // Initialize our handy data buffer
+ pBuffer.wPlace = 0;
+ pBuffer.pData = (BYTE *)_alloca(wTLVlen);
+ pBuffer.wLen = wTLVlen;
+
+ if (nNickLen)
+ packTLV(&pBuffer, SSI_TLV_NAME, (WORD)nNickLen, szNick); // Nickname TLV
+
+ if (nNoteLen)
+ packTLV(&pBuffer, SSI_TLV_COMMENT, (WORD)nNoteLen, szNote); // Comment TLV
+
+ if (pData)
+ packBuffer(&pBuffer, pData, (WORD)nDataLen);
+
+ if (bAuth) // icq5 gives this as last TLV
+ packDWord(&pBuffer, 0x00660000); // "Still waiting for auth" TLV
+
+ return icq_sendServerItem(dwCookie, wAction, wGroupId, wContactId, strUID(dwUin, szUid), pBuffer.pData, wTLVlen, SSI_ITEM_BUDDY);
+}
+
+
+
+DWORD icq_sendSimpleItem(DWORD dwCookie, WORD wAction, DWORD dwUin, char* szUID, WORD wGroupId, WORD wItemId, WORD wItemType)
+{ // for privacy items
+ return icq_sendServerItem(dwCookie, wAction, wGroupId, wItemId, strUID(dwUin, szUID), NULL, 0, wItemType);
+}
+
+
+
+DWORD icq_sendGroupUtf(DWORD dwCookie, WORD wAction, WORD wGroupId, const char *szName, void *pContent, int cbContent)
+{
+ WORD wTLVlen;
+ icq_packet pBuffer; // I reuse the ICQ packet type as a generic buffer
+ // I should be ashamed! ;)
+
+ if (strlennull(szName) == 0 && wGroupId != 0)
+ {
+ NetLog_Server("Group upload failed (GroupName missing).");
+ return 0; // without name we could not change the group
+ }
+
+ // Calculate buffer size
+ wTLVlen = (cbContent?4+cbContent:0);
+
+ // Initialize our handy data buffer
+ pBuffer.wPlace = 0;
+ pBuffer.pData = (BYTE *)_alloca(wTLVlen);
+ pBuffer.wLen = wTLVlen;
+
+ if (wTLVlen)
+ packTLV(&pBuffer, SSI_TLV_SUBITEMS, (WORD)cbContent, pContent); // Groups TLV
+
+ return icq_sendServerItem(dwCookie, wAction, wGroupId, 0, szName, pBuffer.pData, wTLVlen, SSI_ITEM_GROUP);
+}
+
+
+
+DWORD icq_modifyServerPrivacyItem(HANDLE hContact, DWORD dwUin, char* szUid, WORD wAction, DWORD dwOperation, WORD wItemId, WORD wType)
+{
+ servlistcookie* ack;
+ DWORD dwCookie;
+
+ if (!(ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie))))
+ { // cookie failed, use old fake
+ dwCookie = GenerateCookie(wAction);
+ }
+ else
+ {
+ ack->dwAction = dwOperation; // remove privacy item
+ ack->dwUin = dwUin;
+ ack->hContact = hContact;
+ ack->wContactId = wItemId;
+
+ dwCookie = AllocateCookie(CKT_SERVERLIST, wAction, dwUin, ack);
+ }
+ return icq_sendSimpleItem(dwCookie, wAction, dwUin, szUid, 0, wItemId, wType);
+}
+
+
+
+DWORD icq_removeServerPrivacyItem(HANDLE hContact, DWORD dwUin, char* szUid, WORD wItemId, WORD wType)
+{
+ return icq_modifyServerPrivacyItem(hContact, dwUin, szUid, ICQ_LISTS_REMOVEFROMLIST, SSA_PRIVACY_REMOVE, wItemId, wType);
+}
+
+
+
+DWORD icq_addServerPrivacyItem(HANDLE hContact, DWORD dwUin, char* szUid, WORD wItemId, WORD wType)
+{
+ return icq_modifyServerPrivacyItem(hContact, dwUin, szUid, ICQ_LISTS_ADDTOLIST, SSA_PRIVACY_ADD, wItemId, wType);
+}
+
+
+/*****************************************
+ *
+ * --- Contact DB Utilities ---
+ *
+ */
+
+static int GroupNamesEnumProc(const char *szSetting,LPARAM lParam)
+{ // if we got pointer, store setting name, return zero
+ if (lParam)
+ {
+ char** block = (char**)SAFE_MALLOC(2*sizeof(char*));
+ block[1] = null_strdup(szSetting);
+ block[0] = ((char**)lParam)[0];
+ ((char**)lParam)[0] = (char*)block;
+ }
+ return 0;
+}
+
+
+
+void DeleteModuleEntries(const char* szModule)
+{
+ DBCONTACTENUMSETTINGS dbces;
+ char** list = NULL;
+
+ dbces.pfnEnumProc = &GroupNamesEnumProc;
+ dbces.szModule = szModule;
+ dbces.lParam = (LPARAM)&list;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces);
+ while (list)
+ {
+ void* bet;
+
+ DBDeleteContactSetting(NULL, szModule, list[1]);
+ SAFE_FREE(&list[1]);
+ bet = list;
+ list = (char**)list[0];
+ SAFE_FREE(&bet);
+ }
+}
+
+
+
+int IsServerGroupsDefined()
+{
+ int iRes = 1;
+
+ if (ICQGetContactSettingDword(NULL, "Version", 0) < 0x00030608)
+ { // group cache & linking data too old, flush, reload from server
+ char szModule[MAX_PATH+9];
+
+ strcpy(szModule, gpszICQProtoName);
+ strcat(szModule, "Groups"); // flush obsolete linking data
+ DeleteModuleEntries(szModule);
+
+ iRes = 0; // no groups defined, or older version
+ }
+ // store our current version
+ ICQWriteContactSettingDword(NULL, "Version", ICQ_PLUG_VERSION & 0x00FFFFFF);
+
+ return iRes;
+}
+
+
+
+void FlushSrvGroupsCache()
+{
+ char szModule[MAX_PATH+9];
+
+ strcpy(szModule, gpszICQProtoName);
+ strcat(szModule, "SrvGroups");
+ DeleteModuleEntries(szModule);
+}
+
+
+
+// Look thru DB and collect all ContactIDs from a group
+void* collectBuddyGroup(WORD wGroupID, int *count)
+{
+ WORD* buf = NULL;
+ int cnt = 0;
+ HANDLE hContact;
+ WORD wItemID;
+
+ hContact = ICQFindFirstContact();
+
+ while (hContact)
+ { // search all contacts
+ if (wGroupID == ICQGetContactSettingWord(hContact, "SrvGroupId", 0))
+ { // add only buddys from specified group
+ wItemID = ICQGetContactSettingWord(hContact, "ServerId", 0);
+
+ if (wItemID)
+ { // valid ID, add
+ cnt++;
+ buf = (WORD*)realloc(buf, cnt*sizeof(WORD));
+ buf[cnt-1] = wItemID;
+ }
+ }
+
+ hContact = ICQFindNextContact(hContact);
+ }
+
+ *count = cnt<<1; // we return size in bytes
+ return buf;
+}
+
+
+
+// Look thru DB and collect all GroupIDs
+void* collectGroups(int *count)
+{
+ WORD* buf = NULL;
+ int cnt = 0;
+ int i;
+ HANDLE hContact;
+ WORD wGroupID;
+
+ hContact = ICQFindFirstContact();
+
+ while (hContact)
+ { // search all contacts
+ if (wGroupID = ICQGetContactSettingWord(hContact, "SrvGroupId", 0))
+ { // add only valid IDs
+ for (i = 0; i<cnt; i++)
+ { // check for already added ids
+ if (buf[i] == wGroupID) break;
+ }
+
+ if (i == cnt)
+ { // not preset, add
+ cnt++;
+ buf = (WORD*)realloc(buf, cnt*sizeof(WORD));
+ buf[i] = wGroupID;
+ }
+ }
+
+ hContact = ICQFindNextContact(hContact);
+ }
+
+ *count = cnt<<1;
+ return buf;
+}
+
+
+
+static int GroupLinksEnumProc(const char *szSetting,LPARAM lParam)
+{ // check link target, add if match
+ if (DBGetContactSettingWord(NULL, ((char**)lParam)[2], szSetting, 0) == (WORD)((char**)lParam)[1])
+ {
+ char** block = (char**)SAFE_MALLOC(2*sizeof(char*));
+ block[1] = null_strdup(szSetting);
+ block[0] = ((char**)lParam)[0];
+ ((char**)lParam)[0] = (char*)block;
+ }
+ return 0;
+}
+
+
+
+void removeGroupPathLinks(WORD wGroupID)
+{ // remove miranda grouppath links targeting to this groupid
+ DBCONTACTENUMSETTINGS dbces;
+ char szModule[MAX_PATH+6];
+ char* pars[3];
+
+ strcpy(szModule, gpszICQProtoName);
+ strcat(szModule, "Groups");
+
+ pars[0] = NULL;
+ pars[1] = (char*)wGroupID;
+ pars[2] = szModule;
+
+ dbces.pfnEnumProc = &GroupLinksEnumProc;
+ dbces.szModule = szModule;
+ dbces.lParam = (LPARAM)pars;
+
+ if (!CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces))
+ { // we found some links, remove them
+ char** list = (char**)pars[0];
+ while (list)
+ {
+ void* bet;
+
+ DBDeleteContactSetting(NULL, szModule, list[1]);
+ SAFE_FREE(&list[1]);
+ bet = list;
+ list = (char**)list[0];
+ SAFE_FREE(&bet);
+ }
+ }
+ return;
+}
+
+
+
+char* getServerGroupNameUtf(WORD wGroupID)
+{
+ char szModule[MAX_PATH+9];
+ char szGroup[16];
+
+ strcpy(szModule, gpszICQProtoName);
+ strcat(szModule, "SrvGroups");
+ _itoa(wGroupID, szGroup, 0x10);
+
+ if (!CheckServerID(wGroupID, 0))
+ { // check if valid id, if not give empty and remove
+ NetLog_Server("Removing group %u from cache...", wGroupID);
+ DBDeleteContactSetting(NULL, szModule, szGroup);
+ return NULL;
+ }
+
+ return UniGetContactSettingUtf(NULL, szModule, szGroup, NULL);
+}
+
+
+
+void setServerGroupNameUtf(WORD wGroupID, const char* szGroupNameUtf)
+{
+ char szModule[MAX_PATH+9];
+ char szGroup[16];
+
+ strcpy(szModule, gpszICQProtoName);
+ strcat(szModule, "SrvGroups");
+ _itoa(wGroupID, szGroup, 0x10);
+
+ if (szGroupNameUtf)
+ UniWriteContactSettingUtf(NULL, szModule, szGroup, (char*)szGroupNameUtf);
+ else
+ {
+ DBDeleteContactSetting(NULL, szModule, szGroup);
+ removeGroupPathLinks(wGroupID);
+ }
+ return;
+}
+
+
+
+WORD getServerGroupIDUtf(const char* szPath)
+{
+ char szModule[MAX_PATH+6];
+ WORD wGroupId;
+
+ strcpy(szModule, gpszICQProtoName);
+ strcat(szModule, "Groups");
+
+ wGroupId = DBGetContactSettingWord(NULL, szModule, szPath, 0);
+
+ if (wGroupId && !CheckServerID(wGroupId, 0))
+ { // known, check if still valid, if not remove
+ NetLog_Server("Removing group \"%s\" from cache...", szPath);
+ DBDeleteContactSetting(NULL, szModule, szPath);
+ wGroupId = 0;
+ }
+
+ return wGroupId;
+}
+
+
+
+void setServerGroupIDUtf(const char* szPath, WORD wGroupID)
+{
+ char szModule[MAX_PATH+6];
+
+ strcpy(szModule, gpszICQProtoName);
+ strcat(szModule, "Groups");
+
+ if (wGroupID)
+ DBWriteContactSettingWord(NULL, szModule, szPath, wGroupID);
+ else
+ DBDeleteContactSetting(NULL, szModule, szPath);
+
+ return;
+}
+
+
+
+// copied from groups.c - horrible, but only possible as this is not available as service
+int GroupNameExistsUtf(const char *name,int skipGroup)
+{
+ char idstr[33];
+ char* szGroup = NULL;
+ int i;
+
+ if (name == NULL) return 1; // no group always exists
+ for(i=0;;i++)
+ {
+ if(i==skipGroup) continue;
+ itoa(i,idstr,10);
+ szGroup = UniGetContactSettingUtf(NULL, "CListGroups", idstr, "");
+ if (!strlennull(szGroup)) break;
+ if (!strcmpnull(szGroup+1, name))
+ { // caution, this can be false - with ansi clist
+ SAFE_FREE(&szGroup);
+ return 1;
+ }
+ SAFE_FREE(&szGroup);
+ }
+ SAFE_FREE(&szGroup);
+ return 0;
+}
+
+
+
+// utility function which counts > on start of a server group name
+static int countGroupNameLevel(const char *szGroupName)
+{
+ int nNameLen = strlennull(szGroupName);
+ int i = 0;
+
+ while (i<nNameLen)
+ {
+ if (szGroupName[i] != '>')
+ return i;
+
+ i++;
+ }
+ return -1;
+}
+
+
+
+int countGroupLevel(WORD wGroupId)
+{
+ char* szGroupName = getServerGroupNameUtf(wGroupId);
+ int cnt = -1;
+
+ if (szGroupName)
+ cnt = countGroupNameLevel(szGroupName);
+
+ return cnt;
+}
+
+
+
+static int countClistGroupLevel(const char *szClistName)
+{
+ int nNameLen = strlennull(szClistName);
+ int i, level = 0;
+
+ for (i = 0; i < nNameLen; i++)
+ if (szClistName[i] == '\\') level++;
+
+ return level;
+}
+
+
+
+int CreateCListGroup(const char* szGroupName)
+{
+ int hGroup;
+ CLIST_INTERFACE *clint = NULL;
+
+ if (ServiceExists(MS_CLIST_RETRIEVE_INTERFACE))
+ clint = (CLIST_INTERFACE*)CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, 0);
+
+ hGroup = CallService(MS_CLIST_GROUPCREATE, 0, 0);
+
+ if (gbUnicodeCore && clint && clint->version >= 1)
+ { // we've got unicode interface, use it
+ wchar_t* usTmp = make_unicode_string(szGroupName);
+
+ clint->pfnRenameGroup(hGroup, (TCHAR*)usTmp);
+ SAFE_FREE(&usTmp);
+ }
+ else
+ { // old ansi version - no other way
+ int size = strlennull(szGroupName) + 2;
+ char* szTmp = (char*)_alloca(size);
+
+ utf8_decode_static(szGroupName, szTmp, size);
+ CallService(MS_CLIST_GROUPRENAME, hGroup, (LPARAM)szTmp);
+ }
+
+ return hGroup;
+}
+
+
+
+// demangle group path
+char* makeGroupPathUtf(WORD wGroupId)
+{
+ char* szGroup = NULL;
+
+ if (szGroup = getServerGroupNameUtf(wGroupId))
+ { // this groupid is not valid
+ while (strstr(szGroup, "\\")!=NULL) *strstr(szGroup, "\\") = '_'; // remove invalid char
+ if (getServerGroupIDUtf(szGroup) == wGroupId)
+ { // this grouppath is known and is for this group, set user group
+ return szGroup;
+ }
+ else
+ {
+ if (strlennull(szGroup) && (szGroup[0] == '>'))
+ { // it is probably a sub-group
+ WORD wId = wGroupId-1;
+ int level = countGroupLevel(wGroupId);
+ int levnew = countGroupLevel(wId);
+ char* szTempGroup;
+
+ if (level == -1)
+ { // this is just an ordinary group
+ int hGroup;
+
+ if (!GroupNameExistsUtf(szGroup, -1))
+ { // if the group does not exist, create it
+ hGroup = CreateCListGroup(szGroup);
+ }
+ setServerGroupIDUtf(szGroup, wGroupId); // set grouppath id
+ return szGroup;
+ }
+ while ((levnew >= level) && (levnew != -1))
+ { // we look for parent group
+ wId--;
+ levnew = countGroupLevel(wId);
+ }
+ if (levnew == -1)
+ { // that was not a sub-group, it was just a group starting with >
+ if (!GroupNameExistsUtf(szGroup, -1))
+ { // if the group does not exist, create it
+ int hGroup = CreateCListGroup(szGroup);
+ }
+ setServerGroupIDUtf(szGroup, wGroupId); // set grouppath id
+ return szGroup;
+ }
+
+ szTempGroup = makeGroupPathUtf(wId);
+
+ szTempGroup = realloc(szTempGroup, strlennull(szGroup)+strlennull(szTempGroup)+2);
+ strcat(szTempGroup, "\\");
+ strcat(szTempGroup, szGroup+level);
+ SAFE_FREE(&szGroup);
+ szGroup = szTempGroup;
+
+ if (getServerGroupIDUtf(szGroup) == wGroupId)
+ { // known path, give
+ return szGroup;
+ }
+ else
+ { // unknown path, create
+ if (!GroupNameExistsUtf(szGroup, -1))
+ { // if the group does not exist, create it
+ int hGroup = CreateCListGroup(szGroup);
+ }
+ setServerGroupIDUtf(szGroup, wGroupId); // set grouppath id
+ return szGroup;
+ }
+ }
+ else
+ { // create that group
+ int hGroup;
+
+ if (!GroupNameExistsUtf(szGroup, -1))
+ { // if the group does not exist, create it
+ hGroup = CreateCListGroup(szGroup);
+ }
+ setServerGroupIDUtf(szGroup, wGroupId); // set grouppath id
+ return szGroup;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+
+// this is the second pard of recursive event-driven procedure
+void madeMasterGroupId(WORD wGroupID, LPARAM lParam)
+{
+ servlistcookie* clue = (servlistcookie*)lParam;
+ char* szGroup = clue->szGroupName;
+ GROUPADDCALLBACK ofCallback = clue->ofCallback;
+ servlistcookie* param = (servlistcookie*)clue->lParam;
+ int level;
+
+ if (wGroupID) // if we got an id count level
+ level = countGroupLevel(wGroupID);
+ else
+ level = -1;
+
+ SAFE_FREE(&clue);
+
+ if (level == -1)
+ { // something went wrong, give the id and go away
+ if (ofCallback) ofCallback(wGroupID, (LPARAM)param);
+
+ SAFE_FREE(&szGroup);
+ return;
+ }
+ level++; // we are a sub
+
+ // check if on that id is not group of the same or greater level, if yes, try next
+ while (CheckServerID((WORD)(wGroupID+1),0) && (countGroupLevel((WORD)(wGroupID+1)) >= level))
+ {
+ wGroupID++;
+ }
+
+ if (!CheckServerID((WORD)(wGroupID+1), 0))
+ { // the next id is free, so create our group with that id
+ servlistcookie* ack;
+ DWORD dwCookie;
+ char* szSubGroup = (char*)SAFE_MALLOC(strlennull(szGroup)+level+1);
+
+ if (szSubGroup)
+ {
+ int i;
+
+ for (i=0; i<level; i++)
+ {
+ szSubGroup[i] = '>';
+ }
+ strcpy(szSubGroup+level, szGroup);
+ szSubGroup[strlennull(szGroup)+level] = '\0';
+
+ if (ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie)))
+ { // we have cookie good, go on
+ ReserveServerID((WORD)(wGroupID+1), SSIT_GROUP);
+
+ ack->wGroupId = wGroupID+1;
+ ack->szGroupName = szSubGroup; // we need that name
+ ack->dwAction = SSA_GROUP_ADD;
+ ack->ofCallback = ofCallback;
+ ack->lParam = (LPARAM)param;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, 0, ack);
+
+ sendAddStart(0);
+ icq_sendGroupUtf(dwCookie, ICQ_LISTS_ADDTOLIST, ack->wGroupId, szSubGroup, NULL, 0);
+
+ SAFE_FREE(&szGroup);
+ return;
+ }
+ SAFE_FREE(&szSubGroup);
+ }
+ }
+ // we failed to create sub-group give parent groupid
+ if (ofCallback) ofCallback(wGroupID, (LPARAM)param);
+
+ SAFE_FREE(&szGroup);
+ return;
+}
+
+
+
+// create group with this path, a bit complex task
+// this supposes that all server groups are known
+WORD makeGroupId(const char* szGroupPath, GROUPADDCALLBACK ofCallback, servlistcookie* lParam)
+{
+ WORD wGroupID = 0;
+ char* szGroup = (char*)szGroupPath;
+
+ if (!szGroup || szGroup[0]=='\0') szGroup = DEFAULT_SS_GROUP;
+
+ if (wGroupID = getServerGroupIDUtf(szGroup))
+ {
+ if (ofCallback) ofCallback(wGroupID, (LPARAM)lParam);
+ return wGroupID; // if the path is known give the id
+ }
+
+ if (!strstr(szGroup, "\\"))
+ { // a root group can be simply created without problems
+ servlistcookie* ack;
+ DWORD dwCookie;
+
+ if (ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie)))
+ { // we have cookie good, go on
+ ack->wGroupId = GenerateServerId(SSIT_GROUP);
+ ack->szGroupName = null_strdup(szGroup); // we need that name
+ ack->dwAction = SSA_GROUP_ADD;
+ ack->ofCallback = ofCallback;
+ ack->lParam = (LPARAM)lParam;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, 0, ack);
+
+ sendAddStart(0);
+ icq_sendGroupUtf(dwCookie, ICQ_LISTS_ADDTOLIST, ack->wGroupId, szGroup, NULL, 0);
+
+ return 0;
+ }
+ }
+ else
+ { // this is a sub-group
+ char* szSub = null_strdup(szGroup); // create subgroup, recursive, event-driven, possibly relocate
+ servlistcookie* ack;
+ char *szLast;
+
+ if (strstr(szSub, "\\") != NULL)
+ { // determine parent group
+ szLast = strstr(szSub, "\\")+1;
+
+ while (strstr(szLast, "\\") != NULL)
+ szLast = strstr(szLast, "\\")+1; // look for last backslash
+ szLast[-1] = '\0';
+ }
+ // make parent group id
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (ack)
+ {
+ WORD wRes;
+ ack->lParam = (LPARAM)lParam;
+ ack->ofCallback = ofCallback;
+ ack->szGroupName = null_strdup(szLast); // groupname
+ wRes = makeGroupId(szSub, madeMasterGroupId, ack);
+ SAFE_FREE(&szSub);
+
+ return wRes;
+ }
+
+ SAFE_FREE(&szSub);
+ }
+
+ if (strstr(szGroup, "\\") != NULL)
+ { // we failed to get grouppath, trim it by one group
+ WORD wRes;
+ char *szLast = null_strdup(szGroup);
+ char *szLess = szLast;
+
+ while (strstr(szLast, "\\") != NULL)
+ szLast = strstr(szLast, "\\")+1; // look for last backslash
+ szLast[-1] = '\0';
+ wRes = makeGroupId(szLess, ofCallback, lParam);
+ SAFE_FREE(&szLess);
+
+ return wRes;
+ }
+
+ wGroupID = 0; // everything failed, let callback handle error
+ if (ofCallback) ofCallback(wGroupID, (LPARAM)lParam);
+
+ return wGroupID;
+}
+
+
+/*****************************************
+ *
+ * --- Server-List Operations ---
+ *
+ */
+
+void addServContactReady(WORD wGroupID, LPARAM lParam)
+{
+ WORD wItemID;
+ DWORD dwUin;
+ uid_str szUid;
+ servlistcookie* ack;
+ DWORD dwCookie;
+
+ ack = (servlistcookie*)lParam;
+
+ if (!ack || !wGroupID) // something went wrong
+ {
+ if (ack) RemovePendingOperation(ack->hContact, 0);
+ return;
+ }
+
+ wItemID = ICQGetContactSettingWord(ack->hContact, "ServerId", 0);
+
+ if (wItemID)
+ { // Only add the contact if it doesnt already have an ID
+ RemovePendingOperation(ack->hContact, 0);
+ NetLog_Server("Failed to add contact to server side list (%s)", "already there");
+ return;
+ }
+
+ // Get UID
+ if (ICQGetContactSettingUID(ack->hContact, &dwUin, &szUid))
+ { // Could not do anything without uid
+ RemovePendingOperation(ack->hContact, 0);
+ NetLog_Server("Failed to add contact to server side list (%s)", "no UID");
+ return;
+ }
+
+ wItemID = GenerateServerId(SSIT_ITEM);
+
+ ack->dwAction = SSA_CONTACT_ADD;
+ ack->dwUin = dwUin;
+ ack->wGroupId = wGroupID;
+ ack->wContactId = wItemID;
+
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, dwUin, ack);
+
+ sendAddStart(0);
+ icq_sendServerContact(ack->hContact, dwCookie, ICQ_LISTS_ADDTOLIST, wGroupID, wItemID);
+}
+
+
+
+// Called when contact should be added to server list, if group does not exist, create one
+DWORD addServContact(HANDLE hContact, const char *pszNick, const char *pszGroup)
+{
+ servlistcookie* ack;
+
+ if (!(ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie))))
+ { // Could not do anything without cookie
+ NetLog_Server("Failed to add contact to server side list (%s)", "malloc failed");
+ return 0;
+ }
+ else
+ {
+ ack->hContact = hContact;
+
+ if (AddPendingOperation(hContact, pszGroup, ack, addServContactReady))
+ makeGroupId(pszGroup, addServContactReady, ack);
+
+ return 1;
+ }
+}
+
+
+
+// Called when contact should be removed from server list, remove group if it remain empty
+DWORD removeServContact(HANDLE hContact)
+{
+ WORD wGroupID;
+ WORD wItemID;
+ DWORD dwUin;
+ uid_str szUid;
+ servlistcookie* ack;
+ DWORD dwCookie;
+
+ // Get the contact's group ID
+ if (!(wGroupID = ICQGetContactSettingWord(hContact, "SrvGroupId", 0)))
+ {
+ // Could not find a usable group ID
+ NetLog_Server("Failed to remove contact from server side list (%s)", "no group ID");
+ return 0;
+ }
+
+ // Get the contact's item ID
+ if (!(wItemID = ICQGetContactSettingWord(hContact, "ServerId", 0)))
+ {
+ // Could not find usable item ID
+ NetLog_Server("Failed to remove contact from server side list (%s)", "no item ID");
+ return 0;
+ }
+
+ // Get UID
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ {
+ // Could not do anything without uid
+ NetLog_Server("Failed to remove contact from server side list (%s)", "no UID");
+ return 0;
+ }
+
+ if (!(ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie))))
+ { // Could not do anything without cookie
+ NetLog_Server("Failed to remove contact from server side list (%s)", "malloc failed");
+ return 0;
+ }
+ else
+ {
+ ack->dwAction = SSA_CONTACT_REMOVE;
+ ack->dwUin = dwUin;
+ ack->hContact = hContact;
+ ack->wGroupId = wGroupID;
+ ack->wContactId = wItemID;
+
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, dwUin, ack);
+ }
+
+ sendAddStart(0);
+ icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_REMOVEFROMLIST, wGroupID, wItemID);
+
+ return 0;
+}
+
+
+
+void moveServContactReady(WORD wNewGroupID, LPARAM lParam)
+{
+ WORD wItemID;
+ WORD wGroupID;
+ DWORD dwUin;
+ uid_str szUid;
+ servlistcookie* ack;
+ DWORD dwCookie, dwCookie2;
+
+ ack = (servlistcookie*)lParam;
+
+ if (!ack || !wNewGroupID) // something went wrong
+ {
+ if (ack) RemovePendingOperation(ack->hContact, 0);
+ return;
+ }
+
+ if (!ack->hContact) return; // we do not move us, caused our uin was wrongly added to list
+
+ wItemID = ICQGetContactSettingWord(ack->hContact, "ServerId", 0);
+ wGroupID = ICQGetContactSettingWord(ack->hContact, "SrvGroupId", 0);
+
+ if (!wItemID)
+ { // We have no ID, so try to simply add the contact to serv-list
+ NetLog_Server("Unable to move contact (no ItemID) -> trying to add");
+ // we know the GroupID, so directly call add
+ addServContactReady(wNewGroupID, lParam);
+ return;
+ }
+
+ if (!wGroupID)
+ { // Only move the contact if it had an GroupID
+ RemovePendingOperation(ack->hContact, 0);
+ NetLog_Server("Failed to move contact to group on server side list (%s)", "no Group");
+ return;
+ }
+
+ if (wGroupID == wNewGroupID)
+ { // Only move the contact if it had different GroupID
+ RemovePendingOperation(ack->hContact, 1);
+ NetLog_Server("Contact not moved to group on server side list (same Group)");
+ return;
+ }
+
+ // Get UID
+ if (ICQGetContactSettingUID(ack->hContact, &dwUin, &szUid))
+ { // Could not do anything without uin
+ RemovePendingOperation(ack->hContact, 0);
+ NetLog_Server("Failed to move contact to group on server side list (%s)", "no UID");
+ return;
+ }
+
+ ack->szGroupName = NULL;
+ ack->dwAction = SSA_CONTACT_SET_GROUP;
+ ack->dwUin = dwUin;
+ ack->wGroupId = wGroupID;
+ ack->wContactId = wItemID;
+ ack->wNewContactId = GenerateServerId(SSIT_ITEM); // icq5 recreates also this, imitate
+ ack->wNewGroupId = wNewGroupID;
+ ack->lParam = 0; // we use this as a sign
+
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, dwUin, ack);
+ dwCookie2 = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, dwUin, ack);
+
+ sendAddStart(0);
+ // imitate icq5, previously here was different order, but AOL changed and it ceased to work
+ icq_sendServerContact(ack->hContact, dwCookie, ICQ_LISTS_REMOVEFROMLIST, wGroupID, wItemID);
+ icq_sendServerContact(ack->hContact, dwCookie2, ICQ_LISTS_ADDTOLIST, wNewGroupID, ack->wNewContactId);
+}
+
+
+
+// Called when contact should be moved from one group to another, create new, remove empty
+DWORD moveServContactGroup(HANDLE hContact, const char *pszNewGroup)
+{
+ servlistcookie* ack;
+
+ if (!GroupNameExistsUtf(pszNewGroup, -1) && (pszNewGroup != NULL) && (pszNewGroup[0]!='\0'))
+ { // the contact moved to non existing group, do not do anything: MetaContact hack
+ NetLog_Server("Contact not moved - probably hiding by MetaContacts.");
+ return 0;
+ }
+
+ if (!ICQGetContactSettingWord(hContact, "ServerId", 0))
+ { // the contact is not stored on the server, check if we should try to add
+ if (!ICQGetContactSettingByte(NULL, "ServerAddRemove", DEFAULT_SS_ADDSERVER) ||
+ DBGetContactSettingByte(hContact, "CList", "Hidden", 0))
+ return 0;
+ }
+
+ if (!(ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie))))
+ { // Could not do anything without cookie
+ NetLog_Server("Failed to add contact to server side list (%s)", "malloc failed");
+ return 0;
+ }
+ else
+ {
+ ack->hContact = hContact;
+
+ if (AddPendingOperation(hContact, pszNewGroup, ack, moveServContactReady))
+ makeGroupId(pszNewGroup, moveServContactReady, ack);
+ return 1;
+ }
+}
+
+
+
+// Is called when a contact' details has been changed locally to update
+// the server side details.
+static DWORD updateServContact(HANDLE hContact)
+{
+ WORD wGroupID;
+ WORD wItemID;
+ DWORD dwUin;
+ uid_str szUid;
+ servlistcookie* ack;
+ DWORD dwCookie;
+
+ // Get the contact's group ID
+ if (!(wGroupID = ICQGetContactSettingWord(hContact, "SrvGroupId", 0)))
+ {
+ // Could not find a usable group ID
+ NetLog_Server("Failed to update contact's details on server side list (%s)", "no group ID");
+ RemovePendingOperation(hContact, 0);
+ return 0;
+ }
+
+ // Get the contact's item ID
+ if (!(wItemID = ICQGetContactSettingWord(hContact, "ServerId", 0)))
+ {
+ // Could not find usable item ID
+ NetLog_Server("Failed to update contact's details on server side list (%s)", "no item ID");
+ RemovePendingOperation(hContact, 0);
+ return 0;
+ }
+
+ // Get UID
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ {
+ // Could not set nickname on server without uid
+ NetLog_Server("Failed to update contact's details on server side list (%s)", "no UID");
+ RemovePendingOperation(hContact, 0);
+ return 0;
+ }
+
+ if (!(ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie))))
+ {
+ // Could not allocate cookie - use old fake
+ NetLog_Server("Failed to allocate cookie");
+ dwCookie = GenerateCookie(ICQ_LISTS_UPDATEGROUP);
+ }
+ else
+ {
+ ack->dwAction = SSA_CONTACT_UPDATE;
+ ack->wContactId = wItemID;
+ ack->wGroupId = wGroupID;
+ ack->dwUin = dwUin;
+ ack->hContact = hContact;
+
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, dwUin, ack);
+ }
+
+ // There is no need to send ICQ_LISTS_CLI_MODIFYSTART or
+ // ICQ_LISTS_CLI_MODIFYEND when just changing nick name
+ icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_UPDATEGROUP, wGroupID, wItemID);
+
+ return dwCookie;
+}
+
+
+
+void renameServGroup(WORD wGroupId, char* szGroupName)
+{
+ servlistcookie* ack;
+ DWORD dwCookie;
+ char* szGroup, *szLast;
+ int level = countGroupLevel(wGroupId);
+ int i;
+ void* groupData;
+ DWORD groupSize;
+
+ if (IsGroupRenamed(wGroupId)) return; // the group was already renamed
+
+ if (level == -1) return; // we failed to prepare group
+
+ szLast = szGroupName;
+ i = level;
+ while (i)
+ { // find correct part of grouppath
+ szLast = strstr(szLast, "\\")+1;
+ i--;
+ }
+ szGroup = (char*)SAFE_MALLOC(strlennull(szLast)+1+level);
+ if (!szGroup) return;
+
+ for (i=0;i<level;i++)
+ { // create level prefix
+ szGroup[i] = '>';
+ }
+ strcat(szGroup, szLast);
+ // truncate other possible sub-groups
+ szLast = strstr(szGroup, "\\");
+ if (szLast)
+ szLast[0] = '\0';
+
+ if (!(ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie))))
+ { // cookie failed, use old fake
+ dwCookie = GenerateCookie(ICQ_LISTS_UPDATEGROUP);
+ }
+ if (groupData = collectBuddyGroup(wGroupId, &groupSize))
+ {
+ ack->dwAction = SSA_GROUP_RENAME;
+ ack->wGroupId = wGroupId;
+ ack->szGroupName = szGroup; // we need this name
+
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+
+ AddGroupRename(wGroupId);
+
+ icq_sendGroupUtf(dwCookie, ICQ_LISTS_UPDATEGROUP, wGroupId, szGroup, groupData, groupSize);
+ SAFE_FREE(&groupData);
+ }
+}
+
+
+/*****************************************
+ *
+ * --- Miranda Contactlist Hooks ---
+ *
+ */
+
+
+
+static int ServListDbSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING* cws = (DBCONTACTWRITESETTING*)lParam;
+
+ // We can't upload changes to NULL contact
+ if ((HANDLE)wParam == NULL)
+ return 0;
+
+ if (!strcmpnull(cws->szModule, "ContactPhoto"))
+ { // contact photo changed ?
+ ContactPhotoSettingChanged((HANDLE)wParam);
+ }
+
+ // TODO: Queue changes that occur while offline
+ if (!icqOnline || !gbSsiEnabled || bIsSyncingCL)
+ return 0;
+
+ { // only our contacts will be handled
+ if (IsICQContact((HANDLE)wParam))
+ ;// our contact, fine; otherwise return
+ else
+ return 0;
+ }
+
+ if (!strcmpnull(cws->szModule, "CList"))
+ {
+ // Has a temporary contact just been added permanently?
+ if (!strcmpnull(cws->szSetting, "NotOnList") &&
+ (cws->value.type == DBVT_DELETED || (cws->value.type == DBVT_BYTE && cws->value.bVal == 0)) &&
+ ICQGetContactSettingByte(NULL, "ServerAddRemove", DEFAULT_SS_ADDSERVER) &&
+ !DBGetContactSettingByte((HANDLE)wParam, "CList", "Hidden", 0))
+ {
+ DWORD dwUin;
+ uid_str szUid;
+
+ // Does this contact have a UID?
+ if (!ICQGetContactSettingUID((HANDLE)wParam, &dwUin, &szUid))
+ {
+ char *pszNick;
+ char *pszGroup;
+// sendVisContactServ(dwUin, 1);
+ // Read nick name from DB
+ pszNick = UniGetContactSettingUtf((HANDLE)wParam, "CList", "MyHandle", NULL);
+
+ // Read group from DB
+ pszGroup = UniGetContactSettingUtf((HANDLE)wParam, "CList", "Group", NULL);
+
+ addServContact((HANDLE)wParam, pszNick, pszGroup);
+
+ SAFE_FREE(&pszNick);
+ SAFE_FREE(&pszGroup);
+ }
+ }
+
+ // Has contact been renamed?
+ if (!strcmpnull(cws->szSetting, "MyHandle") &&
+ ICQGetContactSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
+ {
+ if (AddPendingOperation((HANDLE)wParam, NULL, (servlistcookie*)1, NULL))
+ updateServContact((HANDLE)wParam);
+ }
+
+ // Has contact been moved to another group?
+ if (!strcmpnull(cws->szSetting, "Group") &&
+ ICQGetContactSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
+ { // Test if group was not renamed...
+ WORD wGroupId = ICQGetContactSettingWord((HANDLE)wParam, "SrvGroupId", 0);
+ char* szGroup = makeGroupPathUtf(wGroupId);
+ char* szNewGroup;
+ int bRenamed = 0;
+ int bMoved = 1;
+
+ // Read group from DB
+ szNewGroup = UniGetContactSettingUtf((HANDLE)wParam, "CList", "Group", NULL);
+
+ if (szNewGroup && wGroupId && !GroupNameExistsUtf(szGroup, -1))
+ { // if we moved from non-existing group, it can be rename
+ if (!getServerGroupIDUtf(szNewGroup))
+ { // the target group is not known - it is probably rename
+ if (getServerGroupIDUtf(szGroup))
+ { // source group not known -> already renamed
+ if (countClistGroupLevel(szNewGroup) == countGroupLevel(wGroupId))
+ { // renamed groups can be only in the same level, if not it is move
+ if (!IsGroupRenamed(wGroupId))
+ { // is rename in progress ?
+ bRenamed = 1; // TODO: we should really check if group was not moved to sub-group
+ NetLog_Server("Group %x renamed to ""%s"".", wGroupId, szNewGroup);
+ }
+ else // if rename in progress do not move contacts
+ bMoved = 0;
+ }
+ }
+ }
+ }
+ SAFE_FREE(&szGroup);
+
+ if (bRenamed)
+ renameServGroup(wGroupId, szNewGroup);
+ else if (bMoved) // TODO: this is bad, we badly need rate management
+ moveServContactGroup((HANDLE)wParam, szNewGroup);
+
+ SAFE_FREE(&szNewGroup);
+ }
+ }
+
+ if (!strcmpnull(cws->szModule, "UserInfo"))
+ {
+ if (!strcmpnull(cws->szSetting, "MyNotes") &&
+ ICQGetContactSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
+ {
+ if (AddPendingOperation((HANDLE)wParam, NULL, (servlistcookie*)1, NULL))
+ updateServContact((HANDLE)wParam);
+ }
+ }
+
+ return 0;
+}
+
+
+
+static int ServListDbContactDeleted(WPARAM wParam, LPARAM lParam)
+{
+ DeleteFromCache((HANDLE)wParam);
+
+ if (!icqOnline || !gbSsiEnabled)
+ return 0;
+
+ { // we need all server contacts on local buddy list
+ WORD wContactID;
+ WORD wGroupID;
+ WORD wVisibleID;
+ WORD wInvisibleID;
+ WORD wIgnoreID;
+ DWORD dwUIN;
+ uid_str szUID;
+// sendVisContactServ(dwUIN, 0);
+ wContactID = ICQGetContactSettingWord((HANDLE)wParam, "ServerId", 0);
+ wGroupID = ICQGetContactSettingWord((HANDLE)wParam, "SrvGroupId", 0);
+ wVisibleID = ICQGetContactSettingWord((HANDLE)wParam, "SrvPermitId", 0);
+ wInvisibleID = ICQGetContactSettingWord((HANDLE)wParam, "SrvDenyId", 0);
+ wIgnoreID = ICQGetContactSettingWord((HANDLE)wParam, "SrvIgnoreId", 0);
+ if (ICQGetContactSettingUID((HANDLE)wParam, &dwUIN, &szUID))
+ return 0;
+
+ // Close all opened peer connections
+ CloseContactDirectConns((HANDLE)wParam);
+
+ if ((wGroupID && wContactID) || wVisibleID || wInvisibleID || wIgnoreID)
+ {
+ if (wContactID)
+ { // delete contact from server
+ removeServContact((HANDLE)wParam);
+ }
+
+ if (wVisibleID)
+ { // detete permit record
+ icq_removeServerPrivacyItem((HANDLE)wParam, dwUIN, szUID, wVisibleID, SSI_ITEM_PERMIT);
+ }
+
+ if (wInvisibleID)
+ { // delete deny record
+ icq_removeServerPrivacyItem((HANDLE)wParam, dwUIN, szUID, wInvisibleID, SSI_ITEM_DENY);
+ }
+
+ if (wIgnoreID)
+ { // delete ignore record
+ icq_removeServerPrivacyItem((HANDLE)wParam, dwUIN, szUID, wIgnoreID, SSI_ITEM_IGNORE);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+void InitServerLists(void)
+{
+ InitializeCriticalSection(&servlistMutex);
+
+ hHookSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ServListDbSettingChanged);
+ hHookContactDeleted = HookEvent(ME_DB_CONTACT_DELETED, ServListDbContactDeleted);
+}
+
+
+
+void UninitServerLists(void)
+{
+ if (hHookSettingChanged)
+ UnhookEvent(hHookSettingChanged);
+
+ if (hHookContactDeleted)
+ UnhookEvent(hHookContactDeleted);
+
+ FlushServerIDs();
+ FlushPendingOperations();
+
+ DeleteCriticalSection(&servlistMutex);
+}
diff --git a/icqj_mod/icq_servlist.h b/icqj_mod/icq_servlist.h new file mode 100644 index 0000000..eae1950 --- /dev/null +++ b/icqj_mod/icq_servlist.h @@ -0,0 +1,124 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_servlist.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_SERVLIST_H
+#define __ICQ_SERVLIST_H
+
+// actions:
+#define SSA_CHECK_ROSTER 0 // request serv-list
+#define SSA_VISIBILITY 1 // update visibility
+#define SSA_CONTACT_UPDATE 2 // update contact's details
+#define SSA_GROUP_RENAME 5 // rename group
+#define SSA_PRIVACY_ADD 0xA // add privacy item
+#define SSA_PRIVACY_REMOVE 0xB // remove privacy item
+#define SSA_CONTACT_PRE_ADD 0x14 // add contact to new group, group added
+#define SSA_CONTACT_ADD 0x10 // add contact w/o auth
+#define SSA_CONTACT_ADD_AUTH 0x11 // add contact with auth
+#define SSA_CONTACT_SET_GROUP 0x12 // move to group
+#define SSA_CONTACT_REMOVE 0x13 // delete contact
+#define SSA_GROUP_ADD 0x15 // create group
+#define SSA_GROUP_REMOVE 0x16 // delete group
+#define SSA_GROUP_UPDATE 0x17 // update group
+#define SSA_SERVLIST_ACK 0x20 // send proto ack only (UploadUI)
+#define SSA_SETAVATAR 0x30
+#define SSA_REMOVEAVATAR 0x31
+#define SSA_IMPORT 7
+
+typedef void (*GROUPADDCALLBACK)(WORD wGroupId, LPARAM lParam);
+
+// cookie struct for SSI actions
+typedef struct servlistcookie_t
+{
+ DWORD dwUin;
+ HANDLE hContact;
+ WORD wContactId;
+ WORD wGroupId;
+ char* szGroupName;
+ WORD wNewContactId;
+ WORD wNewGroupId;
+ int dwAction;
+ GROUPADDCALLBACK ofCallback;
+ LPARAM lParam;
+} servlistcookie;
+
+
+void InitServerLists(void);
+void UninitServerLists(void);
+
+void* collectGroups(int *count);
+void* collectBuddyGroup(WORD wGroupID, int *count);
+char* getServerGroupNameUtf(WORD wGroupID);
+void setServerGroupNameUtf(WORD wGroupID, const char* szGroupNameUtf);
+WORD getServerGroupIDUtf(const char* szPath);
+void setServerGroupIDUtf(const char* szPath, WORD wGroupID);
+int IsServerGroupsDefined();
+char* makeGroupPathUtf(WORD wGroupId);
+WORD makeGroupId(const char* szGroupPath, GROUPADDCALLBACK ofCallback, servlistcookie* lParam);
+void removeGroupPathLinks(WORD wGroupID);
+int countGroupLevel(WORD wGroupId);
+
+void FlushSrvGroupsCache();
+
+DWORD icq_sendServerContact(HANDLE hContact, DWORD dwCookie, WORD wAction, WORD wGroupId, WORD wContactId);
+DWORD icq_sendSimpleItem(DWORD dwCookie, WORD wAction, DWORD dwUin, char* szUID, WORD wGroupId, WORD wItemId, WORD wItemType);
+DWORD icq_sendGroupUtf(DWORD dwCookie, WORD wAction, WORD wGroupId, const char *szName, void *pContent, int cbContent);
+
+DWORD icq_removeServerPrivacyItem(HANDLE hContact, DWORD dwUin, char* szUid, WORD wItemId, WORD wType);
+DWORD icq_addServerPrivacyItem(HANDLE hContact, DWORD dwUin, char* szUid, WORD wItemId, WORD wType);
+
+// id type groups
+#define SSIT_ITEM 0
+#define SSIT_GROUP 1
+
+WORD GenerateServerId(int bGroupId);
+WORD GenerateServerIdPair(int bGroupId, int wCount);
+void ReserveServerID(WORD wID, int bGroupId);
+void FreeServerID(WORD wID, int bGroupId);
+BOOL CheckServerID(WORD wID, unsigned int wCount);
+void FlushServerIDs();
+void LoadServerIDs();
+
+void FlushPendingOperations();
+void RemovePendingOperation(HANDLE hContact, int nResult);
+void AddGroupRename(WORD wGroupID);
+void RemoveGroupRename(WORD wGroupID);
+void FlushGroupRenames();
+
+void AddJustAddedContact(HANDLE hContact);
+BOOL IsContactJustAdded(HANDLE hContact);
+void FlushJustAddedContacts();
+
+#endif /* __ICQ_SERVLIST_H */
diff --git a/icqj_mod/icq_uploadui.c b/icqj_mod/icq_uploadui.c new file mode 100644 index 0000000..02d1f5a --- /dev/null +++ b/icqj_mod/icq_uploadui.c @@ -0,0 +1,1075 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_uploadui.c,v $
+// Revision : $Revision: 3250 $
+// Last change on : $Date: 2006-06-30 00:08:42 +0200 (Fri, 30 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Implements Manage Server List dialog
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static int bListInit = 0;
+static HANDLE hItemAll;
+static int dwUploadDelay = 1000; // initial setting, it is too low for icq server but good for short updates
+
+static HWND hwndUploadContacts=NULL;
+static const UINT settingsControls[]={IDOK};
+
+static WORD* pwGroupIds = NULL;
+static int cbGroupIds = 0;
+
+// Selects the "All contacts" checkbox if all other list entries
+// are selected, deselects it if not.
+static void UpdateAllContactsCheckmark(HWND hwndList, HANDLE phItemAll)
+{
+ int check = 1;
+ HANDLE hContact;
+ HANDLE hItem;
+
+ hContact = ICQFindFirstContact();
+
+ while (hContact)
+ {
+ hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ {
+ if (!SendMessage(hwndList, CLM_GETCHECKMARK, (WPARAM)hItem, 0))
+ { // if any of our contacts is unchecked, uncheck all contacts as well
+ check = 0;
+ break;
+ }
+ }
+ hContact = ICQFindNextContact(hContact);
+ }
+
+ SendMessage(hwndList, CLM_SETCHECKMARK, (WPARAM)phItemAll, check);
+}
+
+
+
+// Loop over all contacts and update the checkmark
+// that indicates wether or not they are already uploaded
+static int UpdateCheckmarks(HWND hwndList, HANDLE phItemAll)
+{
+ int bAll = 1;
+ HANDLE hContact;
+ HANDLE hItem;
+
+ bListInit = 1; // lock CLC events
+
+ hContact = ICQFindFirstContact();
+ while (hContact)
+ {
+ hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ {
+ if (ICQGetContactSettingWord(hContact, "ServerId", 0))
+ SendMessage(hwndList, CLM_SETCHECKMARK, (WPARAM)hItem, 1);
+ else
+ bAll = 0;
+ }
+ hContact = ICQFindNextContact(hContact);
+ }
+
+ // Update the "All contacts" checkmark
+ if (phItemAll)
+ SendMessage(hwndList, CLM_SETCHECKMARK, (WPARAM)phItemAll, bAll);
+
+ bListInit = 0;
+
+ return bAll;
+}
+
+
+
+static void DeleteOtherContactsFromControl(HWND hCtrl)
+{
+ HANDLE hContact;
+ HANDLE hItem;
+
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ hItem = (HANDLE)SendMessage(hCtrl, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ {
+ if (!IsICQContact(hContact))
+ SendMessage(hCtrl, CLM_DELETEITEM, (WPARAM)hItem, 0);
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+}
+
+
+
+static void AppendToUploadLog(HWND hwndDlg, const char *fmt, ...)
+{
+ va_list va;
+ char szText[1024];
+ char*pszText = NULL;
+ int iItem;
+
+ va_start(va, fmt);
+ mir_vsnprintf(szText, sizeof(szText), fmt, va);
+ va_end(va);
+
+ iItem = ListBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_LOG), szText);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, LB_SETTOPINDEX, iItem, 0);
+}
+
+
+
+static void DeleteLastUploadLogLine(HWND hwndDlg)
+{
+ SendDlgItemMessage(hwndDlg, IDC_LOG, LB_DELETESTRING, SendDlgItemMessage(hwndDlg, IDC_LOG, LB_GETCOUNT, 0, 0)-1, 0);
+}
+
+
+
+static void GetLastUploadLogLine(HWND hwndDlg, char *szBuf)
+{
+ if (gbUnicodeAPI)
+ {
+ wchar_t str[MAX_PATH];
+ char *ustr;
+
+ SendDlgItemMessageW(hwndDlg, IDC_LOG, LB_GETTEXT, SendDlgItemMessage(hwndDlg, IDC_LOG, LB_GETCOUNT, 0, 0)-1, (LPARAM)str);
+ ustr = make_utf8_string(str);
+ strcpy(szBuf, ustr);
+ SAFE_FREE(&ustr);
+ }
+ else
+ {
+ char str[MAX_PATH];
+ char *ustr=NULL;
+
+ SendDlgItemMessageA(hwndDlg, IDC_LOG, LB_GETTEXT, SendDlgItemMessage(hwndDlg, IDC_LOG, LB_GETCOUNT, 0, 0)-1, (LPARAM)str);
+ utf8_encode(str, &ustr);
+ strcpy(szBuf, ustr);
+ SAFE_FREE(&ustr);
+ }
+}
+
+
+
+static int GroupEnumIdsEnumProc(const char *szSetting,LPARAM lParam)
+{
+ if (szSetting && strlennull(szSetting)<5)
+ { // it is probably server group
+ char val[MAX_PATH+2]; // dummy
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING cgs;
+
+ dbv.type = DBVT_ASCIIZ;
+ dbv.pszVal = val;
+ dbv.cchVal = MAX_PATH;
+
+ cgs.szModule=(char*)lParam;
+ cgs.szSetting=szSetting;
+ cgs.pValue=&dbv;
+ if(CallService(MS_DB_CONTACT_GETSETTINGSTATIC,(WPARAM)NULL,(LPARAM)&cgs))
+ return 0; // this converts all string types to DBVT_ASCIIZ
+ if(dbv.type!=DBVT_ASCIIZ)
+ { // it is not a cached server-group name
+ return 0;
+ }
+ pwGroupIds = (WORD*)realloc(pwGroupIds, (cbGroupIds+1)*sizeof(WORD));
+ pwGroupIds[cbGroupIds] = (WORD)strtoul(szSetting, NULL, 0x10);
+ cbGroupIds++;
+ }
+ return 0;
+}
+
+
+
+static void enumServerGroups()
+{
+ DBCONTACTENUMSETTINGS dbces;
+
+ char szModule[MAX_PATH+9];
+
+ strcpy(szModule, gpszICQProtoName);
+ strcat(szModule, "SrvGroups");
+
+ dbces.pfnEnumProc = &GroupEnumIdsEnumProc;
+ dbces.szModule = szModule;
+ dbces.lParam = (LPARAM)szModule;
+
+ CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces);
+}
+
+
+
+static DWORD sendUploadGroup(WORD wAction, WORD wGroupId, char* szItemName)
+{
+ DWORD dwCookie;
+ servlistcookie* ack;
+
+ if (ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie)))
+ { // we have cookie good, go on
+ ack->wGroupId = wGroupId;
+ ack->dwAction = SSA_SERVLIST_ACK;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, wAction, 0, ack);
+ ack->lParam = dwCookie;
+
+ icq_sendGroupUtf(dwCookie, wAction, ack->wGroupId, szItemName, NULL, 0);
+
+ return dwCookie;
+ }
+ return 0;
+}
+
+static DWORD sendUploadBuddy(HANDLE hContact, WORD wAction, DWORD dwUin, char *szUID, WORD wContactId, WORD wGroupId, WORD wItemType)
+{
+ DWORD dwCookie;
+ servlistcookie* ack;
+
+ if (ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie)))
+ { // we have cookie good, go on
+ ack->hContact = hContact;
+ ack->wContactId = wContactId;
+ ack->wGroupId = wGroupId;
+ ack->dwAction = SSA_SERVLIST_ACK;
+ ack->dwUin = dwUin;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, wAction, dwUin, ack);
+ ack->lParam = dwCookie;
+
+ if (wItemType == SSI_ITEM_BUDDY)
+ icq_sendServerContact(hContact, dwCookie, wAction, ack->wGroupId, ack->wContactId);
+ else
+ icq_sendSimpleItem(dwCookie, wAction, dwUin, szUID, ack->wGroupId, ack->wContactId, wItemType);
+
+ return dwCookie;
+ }
+ return 0;
+}
+
+static char* getServerResultDesc(int wCode)
+{
+ switch (wCode)
+ {
+ case 0: return "OK";
+ case 2: return "NOT FOUND";
+ case 3: return "ALREADY EXISTS";
+ case 0xA: return "INVALID DATA";
+ case 0xC: return "LIST FULL";
+ default: return "FAILED";
+ }
+}
+
+#define ACTION_NONE 0
+#define ACTION_ADDBUDDY 1
+#define ACTION_ADDBUDDYAUTH 2
+#define ACTION_REMOVEBUDDY 3
+#define ACTION_ADDGROUP 4
+#define ACTION_REMOVEGROUP 5
+#define ACTION_UPDATESTATE 6
+#define ACTION_MOVECONTACT 7
+#define ACTION_ADDVISIBLE 8
+#define ACTION_REMOVEVISIBLE 9
+#define ACTION_ADDINVISIBLE 10
+#define ACTION_REMOVEINVISIBLE 11
+
+#define STATE_READY 1
+#define STATE_REGROUP 2
+#define STATE_ITEMS 3
+#define STATE_VISIBILITY 5
+#define STATE_CONSOLIDATE 4
+
+#define M_PROTOACK (WM_USER+100)
+#define M_UPLOADMORE (WM_USER+101)
+#define M_INITCLIST (WM_USER+102)
+static BOOL CALLBACK DlgProcUploadList(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam)
+{
+ static int working;
+ static HANDLE hProtoAckHook;
+ static int currentSequence;
+ static int currentAction;
+ static int currentState;
+ static HANDLE hCurrentContact;
+ static int lastAckResult = 0;
+ static WORD wNewContactId;
+ static WORD wNewGroupId;
+ static char* szNewGroupName;
+ static WORD wNewVisibilityId;
+
+ switch(message)
+ {
+
+ case WM_INITDIALOG:
+ {
+ char str[MAX_PATH];
+
+ ICQTranslateDialog(hwndDlg);
+ working = 0;
+ hProtoAckHook = NULL;
+ currentState = STATE_READY;
+
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Select contacts you want to store on server.", str));
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Ready...", str));
+ }
+ return TRUE;
+
+ // The M_PROTOACK message is received when the
+ // server has responded to our last update packet
+ case M_PROTOACK:
+ {
+ int bMulti = 0;
+ ACKDATA *ack = (ACKDATA*)lParam;
+ char szLastLogLine[MAX_PATH];
+ char str[MAX_PATH];
+
+ // Is this an ack we are waiting for?
+ if (strcmpnull(ack->szModule, gpszICQProtoName))
+ break;
+
+ if (ack->type == ICQACKTYPE_RATEWARNING)
+ { // we are sending tooo fast, slow down the process
+ if (ack->hProcess != (HANDLE)1) break; // check class
+ if (ack->lParam == 2 || ack->lParam == 3) // check status
+ {
+ GetLastUploadLogLine(hwndDlg, szLastLogLine);
+ DeleteLastUploadLogLine(hwndDlg);
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Server rate warning -> slowing down the process.", str));
+ AppendToUploadLog(hwndDlg, szLastLogLine);
+
+ dwUploadDelay *= 2;
+
+ break;
+ }
+ if (ack->lParam == 4) dwUploadDelay /= 2; // the rate is ok, turn up
+ }
+
+ if (ack->type != ICQACKTYPE_SERVERCLIST)
+ break;
+
+ if ((int)ack->hProcess != currentSequence)
+ break;
+
+ lastAckResult = ack->result == ACKRESULT_SUCCESS ? 0 : 1;
+
+ switch (currentAction)
+ {
+ case ACTION_ADDBUDDY:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ ICQWriteContactSettingByte(hCurrentContact, "Auth", 0);
+ ICQWriteContactSettingWord(hCurrentContact, "ServerId", wNewContactId);
+ ICQWriteContactSettingWord(hCurrentContact, "SrvGroupId", wNewGroupId);
+ break;
+ }
+ else
+ { // If the server refused to add the contact without authorization,
+ // we try again _with_ authorization TLV
+ DWORD dwUIN;
+ uid_str szUID;
+
+ ICQWriteContactSettingByte(hCurrentContact, "Auth", 1);
+
+ if (!ICQGetContactSettingUID(hCurrentContact, &dwUIN, &szUID))
+ {
+ currentAction = ACTION_ADDBUDDYAUTH;
+ currentSequence = sendUploadBuddy(hCurrentContact, ICQ_LISTS_ADDTOLIST, dwUIN, szUID, wNewContactId, wNewGroupId, SSI_ITEM_BUDDY);
+ }
+
+ return FALSE;
+ }
+
+ case ACTION_ADDBUDDYAUTH:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ ICQWriteContactSettingWord(hCurrentContact, "ServerId", wNewContactId);
+ ICQWriteContactSettingWord(hCurrentContact, "SrvGroupId", wNewGroupId);
+ }
+ else
+ {
+ ICQDeleteContactSetting(hCurrentContact, "Auth");
+ FreeServerID(wNewContactId, SSIT_ITEM);
+ }
+
+ break;
+
+ case ACTION_REMOVEBUDDY:
+ if (ack->result == ACKRESULT_SUCCESS)
+ { // clear obsolete settings
+ FreeServerID(wNewContactId, SSIT_ITEM);
+ ICQDeleteContactSetting(hCurrentContact, "ServerId");
+ ICQDeleteContactSetting(hCurrentContact, "SrvGroupId");
+ ICQDeleteContactSetting(hCurrentContact, "Auth");
+ }
+ break;
+
+ case ACTION_ADDGROUP:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ void* groupData;
+ int groupSize;
+ servlistcookie* ack;
+
+ setServerGroupNameUtf(wNewGroupId, szNewGroupName); // add group to list
+ setServerGroupIDUtf(szNewGroupName, wNewGroupId); // grouppath is known
+
+ groupData = collectGroups(&groupSize);
+ groupData = realloc(groupData, groupSize+2);
+ *(((WORD*)groupData)+(groupSize>>1)) = wNewGroupId; // add this new group id
+ groupSize += 2;
+
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (ack)
+ {
+ DWORD dwCookie; // we do not use this
+
+ ack->dwAction = SSA_SERVLIST_ACK;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+
+ icq_sendGroupUtf(dwCookie, ICQ_LISTS_UPDATEGROUP, 0, ack->szGroupName, groupData, groupSize);
+ }
+ SAFE_FREE(&groupData);
+ }
+ else
+ FreeServerID(wNewGroupId, SSIT_GROUP);
+
+ SAFE_FREE(&szNewGroupName);
+ break;
+
+ case ACTION_REMOVEGROUP:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ void* groupData;
+ int groupSize;
+ servlistcookie* ack;
+
+ FreeServerID(wNewGroupId, SSIT_GROUP);
+ setServerGroupNameUtf(wNewGroupId, NULL); // remove group from list
+ removeGroupPathLinks(wNewGroupId); // grouppath is known
+
+ groupData = collectGroups(&groupSize);
+
+ ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+ if (ack)
+ {
+ DWORD dwCookie; // we do not use this
+
+ ack->dwAction = SSA_SERVLIST_ACK;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+
+ icq_sendGroupUtf(dwCookie, ICQ_LISTS_UPDATEGROUP, 0, ack->szGroupName, groupData, groupSize);
+ }
+ SAFE_FREE(&groupData);
+ }
+ break;
+
+ case ACTION_UPDATESTATE:
+ // do nothing
+ break;
+
+ case ACTION_MOVECONTACT:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ FreeServerID(ICQGetContactSettingWord(hCurrentContact, "ServerId", 0), SSIT_ITEM);
+ ICQWriteContactSettingWord(hCurrentContact, "ServerId", wNewContactId);
+ ICQWriteContactSettingWord(hCurrentContact, "SrvGroupId", wNewGroupId);
+ dwUploadDelay *= 2; // we double the delay here (2 packets)
+ }
+ break;
+
+ case ACTION_ADDVISIBLE:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ ICQWriteContactSettingWord(hCurrentContact, "SrvPermitId", wNewContactId);
+ }
+ else
+ FreeServerID(wNewContactId, SSIT_ITEM);
+ break;
+
+ case ACTION_ADDINVISIBLE:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ ICQWriteContactSettingWord(hCurrentContact, "SrvDenyId", wNewContactId);
+ }
+ else
+ FreeServerID(wNewContactId, SSIT_ITEM);
+ break;
+
+ case ACTION_REMOVEVISIBLE:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ FreeServerID(wNewContactId, SSIT_ITEM);
+ ICQWriteContactSettingWord(hCurrentContact, "SrvPermitId", 0);
+ }
+ break;
+
+ case ACTION_REMOVEINVISIBLE:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ FreeServerID(wNewContactId, SSIT_ITEM);
+ ICQWriteContactSettingWord(hCurrentContact, "SrvDenyId", 0);
+ }
+ break;
+ }
+
+ // Update the log window
+ GetLastUploadLogLine(hwndDlg, szLastLogLine);
+ DeleteLastUploadLogLine(hwndDlg);
+ AppendToUploadLog(hwndDlg, "%s%s", szLastLogLine,
+ ICQTranslateUtfStatic(getServerResultDesc(ack->lParam), str));
+
+ if (!bMulti)
+ {
+ SetTimer(hwndDlg, M_UPLOADMORE, dwUploadDelay, 0); // delay
+ }
+ }
+ break;
+
+ case WM_TIMER:
+ {
+ switch (wParam)
+ {
+ case M_UPLOADMORE:
+ KillTimer(hwndDlg, M_UPLOADMORE);
+ if (currentAction == ACTION_MOVECONTACT)
+ dwUploadDelay /= 2; // turn it back
+
+ PostMessage(hwndDlg, M_UPLOADMORE, 0, 0);
+
+ return 0;
+ }
+ }
+
+ // The M_UPLOADMORE window message is received when the user presses 'Update'
+ // and every time an ack from the server has been taken care of.
+ case M_UPLOADMORE:
+ {
+ HANDLE hContact;
+ HANDLE hItem;
+ DWORD dwUin;
+ uid_str szUid;
+ char* pszNick;
+ char* pszGroup;
+ int isChecked;
+ int isOnServer;
+ BOOL bUidOk;
+ char str[MAX_PATH];
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_CLIST);
+
+ switch (currentState)
+ {
+ case STATE_REGROUP:
+
+ // TODO: iterate over all checked groups and create if needed
+ // if creation requires reallocation of groups do it here
+
+ currentState = STATE_ITEMS;
+ hCurrentContact = NULL;
+ PostMessage(hwndDlg, M_UPLOADMORE, 0, 0);
+ break;
+
+ case STATE_ITEMS:
+ // Iterate over all contacts until one is found that
+ // needs to be updated on the server
+ if (hCurrentContact == NULL)
+ hContact = ICQFindFirstContact();
+ else // we do not want to go thru all contacts over and over again
+ {
+ hContact = hCurrentContact;
+ if (lastAckResult) // if the last operation on this contact fail, do not do it again, go to next
+ hContact = ICQFindNextContact(hContact);
+ }
+
+ while (hContact)
+ {
+ hCurrentContact = hContact;
+
+ hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ {
+ isChecked = SendMessage(hwndList, CLM_GETCHECKMARK, (WPARAM)hItem, 0) != 0;
+ isOnServer = ICQGetContactSettingWord(hContact, "ServerId", 0) != 0;
+
+ bUidOk = !ICQGetContactSettingUID(hContact, &dwUin, &szUid);
+
+ // Is this one out of sync?
+ if (bUidOk && (isChecked != isOnServer))
+ {
+ // Only upload custom nicks
+ pszNick = UniGetContactSettingUtf(hContact, "CList", "MyHandle", NULL);
+
+ if (isChecked)
+ { // Queue for uploading
+ pszGroup = UniGetContactSettingUtf(hContact, "CList", "Group", NULL);
+ if (!strlennull(pszGroup)) pszGroup = null_strdup(DEFAULT_SS_GROUP);
+
+ // Get group ID from cache, if not ready use parent group, if still not ready create one
+ wNewGroupId = getServerGroupIDUtf(pszGroup);
+ if (!wNewGroupId && strstr(pszGroup, "\\") != NULL)
+ { // if it is sub-group, take master parent
+ strstr(pszGroup, "\\")[0] = '\0';
+ wNewGroupId = getServerGroupIDUtf(pszGroup);
+ }
+ if (!wNewGroupId && currentAction != ACTION_ADDGROUP)
+ { // if the group still does not exist and there was no try before, try to add group
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Adding group \"%s\"...", str), pszGroup);
+
+ wNewGroupId = GenerateServerId(SSIT_GROUP);
+ szNewGroupName = pszGroup;
+ currentAction = ACTION_ADDGROUP;
+ currentSequence = sendUploadGroup(ICQ_LISTS_ADDTOLIST, wNewGroupId, pszGroup);
+ SAFE_FREE(&pszNick);
+
+ return FALSE;
+ }
+
+ SAFE_FREE(&pszGroup);
+
+ if (pszNick)
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Uploading %s...", str), pszNick);
+ else
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Uploading %s...", str), strUID(dwUin, szUid));
+
+ currentAction = ACTION_ADDBUDDY;
+
+ if (wNewGroupId)
+ {
+ wNewContactId = GenerateServerId(SSIT_ITEM);
+
+ currentSequence = sendUploadBuddy(hCurrentContact, ICQ_LISTS_ADDTOLIST, dwUin, szUid,
+ wNewContactId, wNewGroupId, SSI_ITEM_BUDDY);
+ SAFE_FREE(&pszNick);
+
+ return FALSE;
+ }
+ else
+ {
+ char szLastLogLine[256];
+ // Update the log window with the failure and continue with next contact
+ GetLastUploadLogLine(hwndDlg, szLastLogLine);
+ DeleteLastUploadLogLine(hwndDlg);
+ AppendToUploadLog(hwndDlg, "%s%s", szLastLogLine, ICQTranslateUtfStatic("FAILED", str));
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("No upload group available", str));
+ NetLog_Server("Upload failed, no group");
+ currentState = STATE_READY;
+ }
+ }
+ else
+ { // Queue for deletion
+ if (pszNick)
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Deleting %s...", str), pszNick);
+ else
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Deleting %s...", str), strUID(dwUin, szUid));
+
+ wNewGroupId = ICQGetContactSettingWord(hContact, "SrvGroupId", 0);
+ wNewContactId = ICQGetContactSettingWord(hContact, "ServerId", 0);
+ currentAction = ACTION_REMOVEBUDDY;
+ currentSequence = sendUploadBuddy(hContact, ICQ_LISTS_REMOVEFROMLIST, dwUin, szUid,
+ wNewContactId, wNewGroupId, SSI_ITEM_BUDDY);
+ }
+ SAFE_FREE(&pszNick);
+
+ break;
+ }
+ else if (bUidOk && isChecked)
+ { // the contact is and should be on server, check if it is in correct group, move otherwise
+ WORD wCurrentGroupId = ICQGetContactSettingWord(hContact, "SrvGroupId", 0);
+
+ pszGroup = UniGetContactSettingUtf(hContact, "CList", "Group", NULL);
+ if (!strlennull(pszGroup)) pszGroup = null_strdup(DEFAULT_SS_GROUP);
+ wNewGroupId = getServerGroupIDUtf(pszGroup);
+ if (!wNewGroupId && strstr(pszGroup, "\\") != NULL)
+ { // if it is sub-group, take master parent
+ strstr(pszGroup, "\\")[0] = '\0';
+ wNewGroupId = getServerGroupIDUtf(pszGroup);
+ }
+ if (!wNewGroupId && currentAction != ACTION_ADDGROUP)
+ { // if the group still does not exist and there was no try before, try to add group
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Adding group \"%s\"...", str), pszGroup);
+
+ wNewGroupId = GenerateServerId(SSIT_GROUP);
+ szNewGroupName = pszGroup;
+ currentAction = ACTION_ADDGROUP;
+ currentSequence = sendUploadGroup(ICQ_LISTS_ADDTOLIST, wNewGroupId, pszGroup);
+
+ return FALSE;
+ }
+ if (wNewGroupId && (wNewGroupId != wCurrentGroupId))
+ { // we have a group the contact should be in, move it
+ WORD wCurrentContactId = ICQGetContactSettingWord(hContact, "ServerId", 0);
+ BYTE bAuth = ICQGetContactSettingByte(hContact, "Auth", 0);
+
+ pszNick = UniGetContactSettingUtf(hContact, "CList", "MyHandle", NULL);
+
+ if (pszNick)
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Moving %s to group \"%s\"...", str), pszNick, pszGroup);
+ else
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Moving %s to group \"%s\"...", str), strUID(dwUin, szUid), pszGroup);
+
+ currentAction = ACTION_MOVECONTACT;
+ wNewContactId = GenerateServerId(SSIT_ITEM);
+ sendUploadBuddy(hContact, ICQ_LISTS_REMOVEFROMLIST, dwUin, szUid, wCurrentContactId, wCurrentGroupId, SSI_ITEM_BUDDY);
+ currentSequence = sendUploadBuddy(hContact, ICQ_LISTS_ADDTOLIST, dwUin, szUid, wNewContactId, wNewGroupId, SSI_ITEM_BUDDY);
+ SAFE_FREE(&pszNick);
+ SAFE_FREE(&pszGroup);
+
+ break;
+ }
+ SAFE_FREE(&pszGroup);
+ }
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ if (!hContact)
+ {
+ currentState = STATE_VISIBILITY;
+ hCurrentContact = NULL;
+ PostMessage(hwndDlg, M_UPLOADMORE, 0, 0);
+ }
+ break;
+
+ case STATE_VISIBILITY:
+ // Iterate over all contacts until one is found that
+ // needs to be updated on the server
+ if (hCurrentContact == NULL)
+ hContact = ICQFindFirstContact();
+ else // we do not want to go thru all contacts over and over again
+ {
+ hContact = hCurrentContact;
+ if (lastAckResult) // if the last operation on this contact fail, do not do it again, go to next
+ hContact = ICQFindNextContact(hContact);
+ }
+
+ while (hContact)
+ {
+ WORD wApparentMode = ICQGetContactSettingWord(hContact, "ApparentMode", 0);
+ WORD wDenyId = ICQGetContactSettingWord(hContact, "SrvDenyId", 0);
+ WORD wPermitId = ICQGetContactSettingWord(hContact, "SrvPermitId", 0);
+ WORD wIgnoreId = ICQGetContactSettingWord(hContact, "SrvIgnoreId", 0);
+
+ hCurrentContact = hContact;
+ ICQGetContactSettingUID(hContact, &dwUin, &szUid);
+
+ if (wApparentMode == ID_STATUS_ONLINE)
+ { // contact is on the visible list
+ if (wPermitId == 0)
+ {
+ currentAction = ACTION_ADDVISIBLE;
+ wNewContactId = GenerateServerId(SSIT_ITEM);
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Adding %s to visible list...", str), strUID(dwUin, szUid));
+ currentSequence = sendUploadBuddy(hContact, ICQ_LISTS_ADDTOLIST, dwUin, szUid, wNewContactId, 0, SSI_ITEM_PERMIT);
+ break;
+ }
+ }
+ if (wApparentMode == ID_STATUS_OFFLINE)
+ { // contact is on the invisible list
+ if (wDenyId == 0 && wIgnoreId == 0)
+ {
+ currentAction = ACTION_ADDINVISIBLE;
+ wNewContactId = GenerateServerId(SSIT_ITEM);
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Adding %s to invisible list...", str), strUID(dwUin, szUid));
+ currentSequence = sendUploadBuddy(hContact, ICQ_LISTS_ADDTOLIST, dwUin, szUid, wNewContactId, 0, SSI_ITEM_DENY);
+ break;
+ }
+ }
+ if (wApparentMode != ID_STATUS_ONLINE)
+ { // contact is not on visible list
+ if (wPermitId != 0)
+ {
+ currentAction = ACTION_REMOVEVISIBLE;
+ wNewContactId = wPermitId;
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Deleting %s from visible list...", str), strUID(dwUin, szUid));
+ currentSequence = sendUploadBuddy(hContact, ICQ_LISTS_REMOVEFROMLIST, dwUin, szUid, wNewContactId, 0, SSI_ITEM_PERMIT);
+ break;
+ }
+ }
+ if (wApparentMode != ID_STATUS_OFFLINE)
+ { // contact is not on invisible list
+ if (wDenyId != 0)
+ {
+ currentAction = ACTION_REMOVEINVISIBLE;
+ wNewContactId = wDenyId;
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Deleting %s from invisible list...", str), strUID(dwUin, szUid));
+ currentSequence = sendUploadBuddy(hContact, ICQ_LISTS_REMOVEFROMLIST, dwUin, szUid, wNewContactId, 0, SSI_ITEM_DENY);
+ break;
+ }
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ if (!hContact)
+ {
+ currentState = STATE_CONSOLIDATE;
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Cleaning groups", str));
+ EnableDlgItem(hwndDlg, IDCANCEL, FALSE);
+ enumServerGroups();
+ PostMessage(hwndDlg, M_UPLOADMORE, 0, 0);
+ }
+ break;
+
+ case STATE_CONSOLIDATE: // updage group data, remove redundant groups
+ if (currentAction == ACTION_UPDATESTATE)
+ DeleteLastUploadLogLine(hwndDlg);
+
+ if (cbGroupIds) // some groups in the list
+ {
+ void* groupData;
+ int groupSize;
+
+ cbGroupIds--;
+ wNewGroupId = pwGroupIds[cbGroupIds];
+
+ if (groupData = collectBuddyGroup(wNewGroupId, &groupSize))
+ { // the group is still not empty, just update it
+ char* pszGroup = getServerGroupNameUtf(wNewGroupId);
+ servlistcookie* ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+
+ ack->dwAction = SSA_SERVLIST_ACK;
+ ack->wGroupId = wNewGroupId;
+ currentSequence = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+ ack->lParam = currentSequence;
+ currentAction = ACTION_UPDATESTATE;
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Updating group \"%s\"...", str), pszGroup);
+
+ icq_sendGroupUtf(currentSequence, ICQ_LISTS_UPDATEGROUP, wNewGroupId, pszGroup, groupData, groupSize);
+
+ SAFE_FREE(&pszGroup);
+ }
+ else // the group is empty, delete it if it does not have sub-groups
+ {
+ if (!CheckServerID((WORD)(wNewGroupId+1), 0) || countGroupLevel((WORD)(wNewGroupId+1)) == 0)
+ { // is next id an sub-group, if yes, we cannot delete this group
+ char* pszGroup = getServerGroupNameUtf(wNewGroupId);
+ currentAction = ACTION_REMOVEGROUP;
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Deleting group \"%s\"...", str), pszGroup);
+ currentSequence = sendUploadGroup(ICQ_LISTS_REMOVEFROMLIST, wNewGroupId, pszGroup);
+ SAFE_FREE(&pszGroup);
+ }
+ else // update empty group
+ {
+ char* pszGroup = getServerGroupNameUtf(wNewGroupId);
+ servlistcookie* ack = (servlistcookie*)SAFE_MALLOC(sizeof(servlistcookie));
+
+ ack->dwAction = SSA_SERVLIST_ACK;
+ ack->wGroupId = wNewGroupId;
+ currentSequence = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+ ack->lParam = currentSequence;
+ currentAction = ACTION_UPDATESTATE;
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Updating group \"%s\"...", str), pszGroup);
+
+ icq_sendGroupUtf(currentSequence, ICQ_LISTS_UPDATEGROUP, wNewGroupId, pszGroup, 0, 0);
+
+ SAFE_FREE(&pszGroup);
+ }
+ }
+ SAFE_FREE(&groupData); // free the memory
+ }
+ else
+ { // all groups processed
+ SAFE_FREE(&pwGroupIds);
+ currentState = STATE_READY;
+ }
+ break;
+ }
+
+ if (currentState == STATE_READY)
+ {
+ // All contacts are in sync
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("All operations complete", str));
+ EnableDlgItem(hwndDlg, IDCANCEL, TRUE);
+ SetDlgItemTextUtf(hwndDlg, IDCANCEL, ICQTranslateUtfStatic("Close", str));
+ sendAddEnd();
+ working = 0;
+// SendMessage(hwndList, CLM_SETGREYOUTFLAGS,0,0);
+ UpdateCheckmarks(hwndList, hItemAll);
+// EnableWindow(hwndList, FALSE);
+ if (hProtoAckHook)
+ UnhookEvent(hProtoAckHook);
+ }
+ break;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ SendDlgItemMessage(hwndDlg, IDC_LOG, LB_RESETCONTENT, 0, 0);
+ if (gnCurrentStatus == ID_STATUS_OFFLINE || gnCurrentStatus == ID_STATUS_CONNECTING)
+ {
+ char str[MAX_PATH];
+
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("You have to be online to sychronize the server-list !", str));
+ break;
+ }
+ working = 1;
+ hCurrentContact = NULL;
+ currentState = STATE_REGROUP;
+ currentAction = ACTION_NONE;
+ icq_ShowMultipleControls(hwndDlg, settingsControls, sizeof(settingsControls)/sizeof(settingsControls[0]), SW_HIDE);
+// SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETGREYOUTFLAGS, 0xFFFFFFFF, 0);
+// InvalidateRect(GetDlgItem(hwndDlg, IDC_CLIST), NULL, FALSE);
+ EnableDlgItem(hwndDlg, IDC_CLIST, FALSE);
+ hProtoAckHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, M_PROTOACK);
+ sendAddStart(1);
+ PostMessage(hwndDlg, M_UPLOADMORE, 0, 0);
+ break;
+
+ case IDCANCEL: // TODO: this must be clean
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ switch(((NMHDR*)lParam)->idFrom)
+ {
+
+ case IDC_CLIST:
+ {
+ HWND hClist = GetDlgItem(hwndDlg, IDC_CLIST);
+
+ switch(((NMHDR*)lParam)->code)
+ {
+
+ case CLN_OPTIONSCHANGED:
+ {
+ int i;
+
+ SendMessage(hClist, CLM_SETLEFTMARGIN, 2, 0);
+ SendMessage(hClist, CLM_SETBKBITMAP, 0, (LPARAM)(HBITMAP)NULL);
+ SendMessage(hClist, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0);
+ SendMessage(hClist, CLM_SETGREYOUTFLAGS, working?0xFFFFFFFF:0, 0);
+ for (i=0; i<=FONTID_MAX; i++)
+ SendMessage(hClist, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+ if (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_HIDEEMPTYGROUPS) // hide empty groups
+ SendMessage(hClist, CLM_SETHIDEEMPTYGROUPS, (WPARAM) TRUE, 0);
+ }
+ break;
+
+ case CLN_NEWCONTACT:
+ case CLN_CONTACTMOVED:
+ {
+ // Delete non-icq contacts
+ DeleteOtherContactsFromControl(hClist);
+ if (hItemAll)
+ UpdateAllContactsCheckmark(hClist, hItemAll);
+ }
+ break;
+
+ case CLN_LISTREBUILT:
+ {
+ int bCheck;
+
+ // Delete non-icq contacts
+ DeleteOtherContactsFromControl(hClist);
+
+ if (!bListInit) // do not enter twice
+ bCheck = UpdateCheckmarks(hClist, NULL);
+
+ if (!hItemAll) // Add the "All contacts" item
+ {
+ CLCINFOITEM cii = {0};
+
+ cii.cbSize = sizeof(cii);
+ cii.flags = CLCIIF_GROUPFONT | CLCIIF_CHECKBOX;
+ cii.pszText = ICQTranslate("** All contacts **");
+ hItemAll = (HANDLE)SendMessage(hClist, CLM_ADDINFOITEM, 0, (LPARAM)&cii);
+ }
+
+ SendMessage(hClist, CLM_SETCHECKMARK, (WPARAM)hItemAll, bCheck);
+ }
+ break;
+
+ case CLN_CHECKCHANGED:
+ {
+ NMCLISTCONTROL *nm = (NMCLISTCONTROL*)lParam;
+ HANDLE hContact;
+ HANDLE hItem;
+
+ if (bListInit) break;
+
+ if (nm->flags&CLNF_ISINFO)
+ {
+ int check;
+
+ check = SendMessage(hClist, CLM_GETCHECKMARK, (WPARAM)hItemAll, 0);
+
+ hContact = ICQFindFirstContact();
+ while (hContact)
+ {
+ hItem = (HANDLE)SendMessage(hClist, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ SendMessage(hClist, CLM_SETCHECKMARK, (WPARAM)hItem, check);
+ hContact = ICQFindNextContact(hContact);
+ }
+ }
+ else
+ {
+ UpdateAllContactsCheckmark(hClist, hItemAll);
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ if (hProtoAckHook)
+ UnhookEvent(hProtoAckHook);
+ if (working)
+ sendAddEnd();
+ hwndUploadContacts = NULL;
+ working = 0;
+ break;
+ }
+
+ return FALSE;
+}
+
+
+
+void ShowUploadContactsDialog(void)
+{
+ if (hwndUploadContacts == NULL)
+ {
+ hItemAll = NULL;
+ hwndUploadContacts = CreateDialogUtf(hInst, MAKEINTRESOURCE(IDD_ICQUPLOADLIST), NULL, DlgProcUploadList);
+ }
+
+ SetForegroundWindow(hwndUploadContacts);
+}
diff --git a/icqj_mod/icq_uploadui.h b/icqj_mod/icq_uploadui.h new file mode 100644 index 0000000..dfa6086 --- /dev/null +++ b/icqj_mod/icq_uploadui.h @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_uploadui.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+void ShowUploadContactsDialog(void);
diff --git a/icqj_mod/icq_xstatus.c b/icqj_mod/icq_xstatus.c new file mode 100644 index 0000000..4346fac --- /dev/null +++ b/icqj_mod/icq_xstatus.c @@ -0,0 +1,1249 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Angeli-Ka, Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_xstatus.c,v $
+// Revision : $Revision: 3075 $
+// Last change on : $Date: 2006-06-07 21:47:37 +0200 (st, 07 VI 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Support for Custom Statuses
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_cluiframes.h"
+
+
+extern void setUserInfo();
+
+extern HANDLE hxstatusiconchanged;
+
+int bHideXStatusUI = 0;
+static int bStatusMenu = 0;
+static int bXStatusMenuBuilt = 0;
+static HANDLE hHookExtraIconsRebuild = NULL;
+static HANDLE hHookStatusBuild = NULL;
+static HANDLE hHookExtraIconsApply = NULL;
+static HMODULE hXStatusIconsDLL = NULL;
+static HANDLE hXStatusIcons[32];
+static HANDLE hXStatusItems[33];
+
+void CListShowMenuItem(HANDLE hMenuItem, BYTE bShow);
+void CListSetMenuItemIcon(HANDLE hMenuItem, HICON hIcon);
+
+
+DWORD sendXStatusDetailsRequest(HANDLE hContact, int bForced)
+{
+ char *szNotify;
+ int nNotifyLen;
+ DWORD dwCookie;
+
+ nNotifyLen = 94 + UINMAXLEN;
+ szNotify = (char*)_alloca(nNotifyLen);
+ nNotifyLen = null_snprintf(szNotify, nNotifyLen, "<srv><id>cAwaySrv</id><req><id>AwayStat</id><trans>1</trans><senderId>%d</senderId></req></srv>", dwLocalUIN);
+
+ dwCookie = SendXtrazNotifyRequest(hContact, "<Q><PluginID>srvMng</PluginID></Q>", szNotify, bForced);
+
+ return dwCookie;
+}
+
+
+
+static DWORD requestXStatusDetails(HANDLE hContact, BOOL bAllowDelay)
+{
+ rate_record rr = {0};
+
+ if (!validateStatusMessageRequest(hContact, MTYPE_SCRIPT_NOTIFY))
+ return 0; // apply privacy rules
+
+ // delay is disabled only if fired from dialog
+ if (!CheckContactCapabilities(hContact, CAPF_XTRAZ) && bAllowDelay)
+ return 0; // Contact does not support xtraz, do not request details
+
+ rr.hContact = hContact;
+ rr.bType = RIT_XSTATUS_REQUEST;
+ rr.rate_group = 0x101; // request
+ rr.nMinDelay = 1000; // delay at least 1s
+
+ if (!handleRateItem(&rr, bAllowDelay))
+ return sendXStatusDetailsRequest(hContact, !bAllowDelay);
+
+ return -1; // delayed
+}
+
+
+
+static char* InitXStatusIconLibrary(char* buf)
+{
+ char path[2*MAX_PATH];
+ char* p;
+
+ // get miranda's exe path
+ GetModuleFileNameA(NULL, path, MAX_PATH);
+ // find the last \ and null it out, this leaves no trailing slash
+ p = strrchr(path, '\\');
+ strcpy(p, "\\Plugins");
+ strcat(p, "\\xstatus_icons.dll");
+ hXStatusIconsDLL = LoadLibrary(path);
+
+ if (!hXStatusIconsDLL)
+ {
+ strcpy(p, "\\Icons");
+ strcat(p, "\\xstatus_icons.dll");
+ hXStatusIconsDLL = LoadLibrary(path);
+ }
+ if (hXStatusIconsDLL)
+ {
+ strcpy(buf, path);
+ }
+
+ return buf;
+}
+
+
+
+HICON LoadDefaultXStatusIcon(int bStatus)
+{
+ if (hXStatusIconsDLL)
+ return LoadImage(hXStatusIconsDLL, MAKEINTRESOURCE(IDI_XSTATUS1 + bStatus - 1), IMAGE_ICON, 0, 0, 0);
+ else
+ return NULL;
+}
+
+
+
+HICON GetXStatusIcon(int bStatus)
+{
+ char szTemp[64];
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", bStatus - 1);
+
+ if (IconLibInstalled())
+ return IconLibProcess(NULL, szTemp);
+
+ return LoadDefaultXStatusIcon(bStatus);
+}
+
+
+
+static void setContactExtraIcon(HANDLE hContact, HANDLE hIcon)
+{
+ IconExtraColumn iec;
+
+ iec.cbSize = sizeof(iec);
+ iec.hImage = hIcon;
+ iec.ColumnType = EXTRA_ICON_ADV1;
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)&iec);
+
+ NotifyEventHooks(hxstatusiconchanged, (WPARAM)hContact, (LPARAM)hIcon);
+}
+
+
+
+static int CListMW_ExtraIconsRebuild(WPARAM wParam, LPARAM lParam)
+{
+ int i;
+
+ if (gbXStatusEnabled && ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+ for (i = 0; i < 32; i++)
+ {
+ HICON hXIcon = LoadDefaultXStatusIcon(i + 1);
+ char szTemp[64];
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", i);
+ hXStatusIcons[i] = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)IconLibProcess(hXIcon, szTemp), 0);
+ DestroyIcon(hXIcon);
+ }
+ }
+
+ return 0;
+}
+
+
+
+static int CListMW_ExtraIconsApply(WPARAM wParam, LPARAM lParam)
+{
+ if (gbXStatusEnabled && ServiceExists(MS_CLIST_EXTRA_SET_ICON))
+ {
+ if (IsICQContact((HANDLE)wParam))
+ { // only apply icons to our contacts, do not mess others
+ DWORD bXStatus = ICQGetContactSettingByte((HANDLE)wParam, DBSETTING_XSTATUSID, 0);
+
+ if (bXStatus > 0 && bXStatus < 33)
+ {
+ setContactExtraIcon((HANDLE)wParam, hXStatusIcons[bXStatus-1]);
+ }
+ else
+ {
+ setContactExtraIcon((HANDLE)wParam, (HANDLE)-1);
+ }
+ }
+ }
+ return 0;
+}
+
+
+
+static int CListMW_BuildStatusItems(WPARAM wParam, LPARAM lParam)
+{
+ InitXStatusItems(TRUE);
+ return 0;
+}
+
+
+
+void InitXStatusEvents()
+{
+ if (!hHookStatusBuild)
+ if (bStatusMenu = ServiceExists(MS_CLIST_ADDSTATUSMENUITEM))
+ hHookStatusBuild = HookEvent(ME_CLIST_PREBUILDSTATUSMENU, CListMW_BuildStatusItems);
+
+ if (!hHookExtraIconsRebuild)
+ hHookExtraIconsRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, CListMW_ExtraIconsRebuild);
+
+ if (!hHookExtraIconsApply)
+ hHookExtraIconsApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, CListMW_ExtraIconsApply);
+}
+
+
+
+void UninitXStatusEvents()
+{
+ if (hHookStatusBuild)
+ UnhookEvent(hHookStatusBuild);
+
+ if (hHookExtraIconsRebuild)
+ UnhookEvent(hHookExtraIconsRebuild);
+
+ if (hHookExtraIconsApply)
+ UnhookEvent(hHookExtraIconsApply);
+}
+
+
+
+const capstr capXStatus[32] = {
+ {0x01, 0xD8, 0xD7, 0xEE, 0xAC, 0x3B, 0x49, 0x2A, 0xA5, 0x8D, 0xD3, 0xD8, 0x77, 0xE6, 0x6B, 0x92},
+ {0x5A, 0x58, 0x1E, 0xA1, 0xE5, 0x80, 0x43, 0x0C, 0xA0, 0x6F, 0x61, 0x22, 0x98, 0xB7, 0xE4, 0xC7},
+ {0x83, 0xC9, 0xB7, 0x8E, 0x77, 0xE7, 0x43, 0x78, 0xB2, 0xC5, 0xFB, 0x6C, 0xFC, 0xC3, 0x5B, 0xEC},
+ {0xE6, 0x01, 0xE4, 0x1C, 0x33, 0x73, 0x4B, 0xD1, 0xBC, 0x06, 0x81, 0x1D, 0x6C, 0x32, 0x3D, 0x81},
+ {0x8C, 0x50, 0xDB, 0xAE, 0x81, 0xED, 0x47, 0x86, 0xAC, 0xCA, 0x16, 0xCC, 0x32, 0x13, 0xC7, 0xB7},
+ {0x3F, 0xB0, 0xBD, 0x36, 0xAF, 0x3B, 0x4A, 0x60, 0x9E, 0xEF, 0xCF, 0x19, 0x0F, 0x6A, 0x5A, 0x7F},
+ {0xF8, 0xE8, 0xD7, 0xB2, 0x82, 0xC4, 0x41, 0x42, 0x90, 0xF8, 0x10, 0xC6, 0xCE, 0x0A, 0x89, 0xA6},
+ {0x80, 0x53, 0x7D, 0xE2, 0xA4, 0x67, 0x4A, 0x76, 0xB3, 0x54, 0x6D, 0xFD, 0x07, 0x5F, 0x5E, 0xC6},
+ {0xF1, 0x8A, 0xB5, 0x2E, 0xDC, 0x57, 0x49, 0x1D, 0x99, 0xDC, 0x64, 0x44, 0x50, 0x24, 0x57, 0xAF},
+ {0x1B, 0x78, 0xAE, 0x31, 0xFA, 0x0B, 0x4D, 0x38, 0x93, 0xD1, 0x99, 0x7E, 0xEE, 0xAF, 0xB2, 0x18},
+ {0x61, 0xBE, 0xE0, 0xDD, 0x8B, 0xDD, 0x47, 0x5D, 0x8D, 0xEE, 0x5F, 0x4B, 0xAA, 0xCF, 0x19, 0xA7},
+ {0x48, 0x8E, 0x14, 0x89, 0x8A, 0xCA, 0x4A, 0x08, 0x82, 0xAA, 0x77, 0xCE, 0x7A, 0x16, 0x52, 0x08},
+ {0x10, 0x7A, 0x9A, 0x18, 0x12, 0x32, 0x4D, 0xA4, 0xB6, 0xCD, 0x08, 0x79, 0xDB, 0x78, 0x0F, 0x09},
+ {0x6F, 0x49, 0x30, 0x98, 0x4F, 0x7C, 0x4A, 0xFF, 0xA2, 0x76, 0x34, 0xA0, 0x3B, 0xCE, 0xAE, 0xA7},
+ {0x12, 0x92, 0xE5, 0x50, 0x1B, 0x64, 0x4F, 0x66, 0xB2, 0x06, 0xB2, 0x9A, 0xF3, 0x78, 0xE4, 0x8D},
+ {0xD4, 0xA6, 0x11, 0xD0, 0x8F, 0x01, 0x4E, 0xC0, 0x92, 0x23, 0xC5, 0xB6, 0xBE, 0xC6, 0xCC, 0xF0},
+ {0x60, 0x9D, 0x52, 0xF8, 0xA2, 0x9A, 0x49, 0xA6, 0xB2, 0xA0, 0x25, 0x24, 0xC5, 0xE9, 0xD2, 0x60},
+ {0x63, 0x62, 0x73, 0x37, 0xA0, 0x3F, 0x49, 0xFF, 0x80, 0xE5, 0xF7, 0x09, 0xCD, 0xE0, 0xA4, 0xEE},
+ {0x1F, 0x7A, 0x40, 0x71, 0xBF, 0x3B, 0x4E, 0x60, 0xBC, 0x32, 0x4C, 0x57, 0x87, 0xB0, 0x4C, 0xF1},
+ {0x78, 0x5E, 0x8C, 0x48, 0x40, 0xD3, 0x4C, 0x65, 0x88, 0x6F, 0x04, 0xCF, 0x3F, 0x3F, 0x43, 0xDF},
+ {0xA6, 0xED, 0x55, 0x7E, 0x6B, 0xF7, 0x44, 0xD4, 0xA5, 0xD4, 0xD2, 0xE7, 0xD9, 0x5C, 0xE8, 0x1F},
+ {0x12, 0xD0, 0x7E, 0x3E, 0xF8, 0x85, 0x48, 0x9E, 0x8E, 0x97, 0xA7, 0x2A, 0x65, 0x51, 0xE5, 0x8D},
+ {0xBA, 0x74, 0xDB, 0x3E, 0x9E, 0x24, 0x43, 0x4B, 0x87, 0xB6, 0x2F, 0x6B, 0x8D, 0xFE, 0xE5, 0x0F},
+ {0x63, 0x4F, 0x6B, 0xD8, 0xAD, 0xD2, 0x4A, 0xA1, 0xAA, 0xB9, 0x11, 0x5B, 0xC2, 0x6D, 0x05, 0xA1},
+ {0x2C, 0xE0, 0xE4, 0xE5, 0x7C, 0x64, 0x43, 0x70, 0x9C, 0x3A, 0x7A, 0x1C, 0xE8, 0x78, 0xA7, 0xDC},
+ {0x10, 0x11, 0x17, 0xC9, 0xA3, 0xB0, 0x40, 0xF9, 0x81, 0xAC, 0x49, 0xE1, 0x59, 0xFB, 0xD5, 0xD4},
+ {0x16, 0x0C, 0x60, 0xBB, 0xDD, 0x44, 0x43, 0xF3, 0x91, 0x40, 0x05, 0x0F, 0x00, 0xE6, 0xC0, 0x09},
+ {0x64, 0x43, 0xC6, 0xAF, 0x22, 0x60, 0x45, 0x17, 0xB5, 0x8C, 0xD7, 0xDF, 0x8E, 0x29, 0x03, 0x52},
+ {0x16, 0xF5, 0xB7, 0x6F, 0xA9, 0xD2, 0x40, 0x35, 0x8C, 0xC5, 0xC0, 0x84, 0x70, 0x3C, 0x98, 0xFA},
+ {0x63, 0x14, 0x36, 0xff, 0x3f, 0x8a, 0x40, 0xd0, 0xa5, 0xcb, 0x7b, 0x66, 0xe0, 0x51, 0xb3, 0x64},
+ {0xb7, 0x08, 0x67, 0xf5, 0x38, 0x25, 0x43, 0x27, 0xa1, 0xff, 0xcf, 0x4c, 0xc1, 0x93, 0x97, 0x97},
+ {0xdd, 0xcf, 0x0e, 0xa9, 0x71, 0x95, 0x40, 0x48, 0xa9, 0xc6, 0x41, 0x32, 0x06, 0xd6, 0xf2, 0x80}};
+
+const char* nameXStatus[32] = {
+ "Angry",
+ "Taking a bath",
+ "Tired",
+ "Party",
+ "Drinking beer",
+ "Thinking",
+ "Eating",
+ "Watching TV",
+ "Meeting",
+ "Coffee",
+ "Listening to music",
+ "Business",
+ "Shooting",
+ "Having fun",
+ "On the phone",
+ "Gaming",
+ "Studying",
+ "Shopping",
+ "Feeling sick",
+ "Sleeping",
+ "Surfing",
+ "Browsing",
+ "Working",
+ "Typing",
+ "Picnic",
+ "Cooking",
+ "Smoking",
+ "I'm high",
+ "On WC",
+ "To be or not to be",
+ "Watching pro7 on TV",
+ "Love"};
+
+
+void handleXStatusCaps(HANDLE hContact, char* caps, int capsize)
+{
+ HANDLE hIcon = (HANDLE)-1;
+
+ if (!gbXStatusEnabled) return;
+
+ if (caps)
+ {
+ int i;
+
+ for (i = 0; i<32; i++)
+ {
+ if (MatchCap(caps, capsize, (const capstr*)capXStatus[i], 0x10))
+ {
+ char str[MAX_PATH];
+
+ ICQWriteContactSettingByte(hContact, DBSETTING_XSTATUSID, (BYTE)(i+1));
+ ICQWriteContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, ICQTranslateUtfStatic(nameXStatus[i], str));
+
+ if (ICQGetContactSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO))
+ requestXStatusDetails(hContact, TRUE);
+
+ hIcon = hXStatusIcons[i];
+
+ break;
+ }
+ }
+ }
+ if (hIcon == (HANDLE)-1)
+ {
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSID);
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSNAME);
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSMSG);
+ }
+
+ if (gbXStatusEnabled != 10)
+ {
+ setContactExtraIcon(hContact, hIcon);
+ }
+}
+
+
+static WNDPROC OldMessageEditProc;
+
+static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_CHAR:
+ if(wParam=='\n' && GetKeyState(VK_CONTROL)&0x8000)
+ {
+ PostMessage(GetParent(hwnd),WM_COMMAND,IDOK,0);
+ return 0;
+ }
+ if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000)
+ { // ctrl-a
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ return 0;
+ }
+ if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000)
+ { // ctrl-w
+ SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0);
+ return 0;
+ }
+ if (wParam == 127 && GetKeyState(VK_CONTROL) & 0x8000)
+ { // ctrl-backspace
+ DWORD start, end;
+ wchar_t *text;
+
+ SendMessage(hwnd, EM_GETSEL, (WPARAM) & end, (LPARAM) (PDWORD) NULL);
+ SendMessage(hwnd, WM_KEYDOWN, VK_LEFT, 0);
+ SendMessage(hwnd, EM_GETSEL, (WPARAM) & start, (LPARAM) (PDWORD) NULL);
+ text = GetWindowTextUcs(hwnd);
+ MoveMemory(text + start, text + end, sizeof(wchar_t) * (wcslen(text) + 1 - end));
+ SetWindowTextUcs(hwnd, text);
+ SAFE_FREE(&text);
+ SendMessage(hwnd, EM_SETSEL, start, start);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM) hwnd);
+ return 0;
+ }
+ break;
+ }
+ return CallWindowProcUtf(OldMessageEditProc,hwnd,msg,wParam,lParam);
+}
+
+
+typedef struct SetXStatusData_s {
+ BYTE bAction;
+ BYTE bXStatus;
+ HANDLE hContact;
+ HANDLE hEvent;
+ DWORD iEvent;
+ int countdown;
+ char *okButtonFormat;
+ HICON hDlgIcon;
+} SetXStatusData;
+
+typedef struct InitXStatusData_s {
+ BYTE bAction;
+ BYTE bXStatus;
+ HANDLE hContact;
+} InitXStatusData;
+
+#define HM_PROTOACK (WM_USER+10)
+static BOOL CALLBACK SetXStatusDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam)
+{
+ SetXStatusData *dat = (SetXStatusData*)GetWindowLong(hwndDlg,GWL_USERDATA);
+ char str[MAX_PATH];
+
+ switch(message)
+ {
+ case HM_PROTOACK:
+ {
+ ACKDATA *ack = (ACKDATA*)lParam;
+ char *szText;
+
+ if (ack->type != ICQACKTYPE_XSTATUS_RESPONSE) break;
+ if (ack->hContact != dat->hContact) break;
+ if ((DWORD)ack->hProcess != dat->iEvent) break;
+
+ ShowWindow(GetDlgItem(hwndDlg, IDC_RETRXSTATUS), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_XMSG), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_XTITLE), SW_SHOW);
+ SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic("Close", str));
+ UnhookEvent(dat->hEvent); dat->hEvent = NULL;
+ szText = ICQGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSNAME, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, szText);
+ SAFE_FREE(&szText);
+ szText = ICQGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSMSG, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XMSG, szText);
+ SAFE_FREE(&szText);
+
+ break;
+ }
+ case WM_INITDIALOG:
+ {
+ InitXStatusData *init = (InitXStatusData*)lParam;
+
+ ICQTranslateDialog(hwndDlg);
+ dat = (SetXStatusData*)SAFE_MALLOC(sizeof(SetXStatusData));
+ SetWindowLong(hwndDlg,GWL_USERDATA,(LONG)dat);
+ dat->bAction = init->bAction;
+
+ if (!init->bAction)
+ { // set our xStatus
+ char szSetting[64];
+ char* szValue;
+
+ dat->bXStatus = init->bXStatus;
+ SendDlgItemMessage(hwndDlg, IDC_XTITLE, EM_LIMITTEXT, 256, 0);
+ SendDlgItemMessage(hwndDlg, IDC_XMSG, EM_LIMITTEXT, 1024, 0);
+ OldMessageEditProc = (WNDPROC)SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XTITLE),GWL_WNDPROC,(LONG)MessageEditSubclassProc);
+ OldMessageEditProc = (WNDPROC)SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XMSG),GWL_WNDPROC,(LONG)MessageEditSubclassProc);
+ dat->okButtonFormat = GetDlgItemTextUtf(hwndDlg,IDOK);
+
+ dat->countdown=5;
+ SendMessage(hwndDlg, WM_TIMER, 0, 0);
+ SetTimer(hwndDlg,1,1000,0);
+
+ sprintf(szSetting, "XStatus%dName", dat->bXStatus);
+ szValue = ICQGetContactSettingUtf(NULL, szSetting, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, szValue);
+ SAFE_FREE(&szValue);
+
+ sprintf(szSetting, "XStatus%dMsg", dat->bXStatus);
+ szValue = ICQGetContactSettingUtf(NULL, szSetting, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XMSG, szValue);
+ SAFE_FREE(&szValue);
+ }
+ else
+ { // retrieve contact's xStatus
+ dat->hContact = init->hContact;
+ dat->bXStatus = ICQGetContactSettingByte(dat->hContact, DBSETTING_XSTATUSID, 0);
+ dat->okButtonFormat = NULL;
+ SendMessage(GetDlgItem(hwndDlg, IDC_XTITLE), EM_SETREADONLY, 1, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_XMSG), EM_SETREADONLY, 1, 0);
+ if (!ICQGetContactSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO))
+ {
+ SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic("Cancel", str));
+ dat->hEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_PROTOACK);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_RETRXSTATUS), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_XMSG), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_XTITLE), SW_HIDE);
+ dat->iEvent = requestXStatusDetails(dat->hContact, FALSE);
+ }
+ else
+ {
+ char *szText;
+
+ SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic("Close", str));
+ dat->hEvent = NULL;
+ szText = ICQGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSNAME, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, szText);
+ SAFE_FREE(&szText);
+ szText = ICQGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSMSG, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XMSG, szText);
+ SAFE_FREE(&szText);
+ }
+ }
+
+ if (dat->bXStatus)
+ {
+ HICON iXStatus = GetXStatusIcon(dat->bXStatus);
+
+ dat->hDlgIcon = iXStatus;
+ }
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)dat->hDlgIcon);
+
+ {
+ char *format;
+ char buf[MAX_PATH];
+
+ format = GetWindowTextUtf(hwndDlg);
+ null_snprintf(str, sizeof(str), format, dat->bXStatus?ICQTranslateUtfStatic(nameXStatus[dat->bXStatus-1], buf):"");
+ SetWindowTextUtf(hwndDlg, str);
+ SAFE_FREE(&format);
+ }
+ return TRUE;
+ }
+ case WM_TIMER:
+ if(dat->countdown==-1)
+ {
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ {
+ null_snprintf(str,sizeof(str),dat->okButtonFormat,dat->countdown);
+ SetDlgItemTextUtf(hwndDlg,IDOK,str);
+ }
+ dat->countdown--;
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDOK:
+ DestroyWindow(hwndDlg);
+ break;
+ case IDC_XTITLE:
+ case IDC_XMSG:
+ if (!dat->bAction)
+ { // set our xStatus
+ KillTimer(hwndDlg,1);
+ SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic("OK", str));
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ if (!dat->bAction)
+ { // set our xStatus
+ char szSetting[64];
+ char* szValue;
+ char *ansi = NULL;
+ CLISTMENUITEM mi = {0};
+ szValue = GetDlgItemTextUtf(hwndDlg,IDC_XMSG);
+ sprintf(szSetting, "XStatus%dMsg", dat->bXStatus);
+ ICQWriteContactSettingUtf(NULL, szSetting, szValue);
+ ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, szValue);
+ SAFE_FREE(&szValue);
+ szValue = GetDlgItemTextUtf(hwndDlg,IDC_XTITLE);
+ sprintf(szSetting, "XStatus%dName", dat->bXStatus);
+ ICQWriteContactSettingUtf(NULL, szSetting, szValue);
+ ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, szValue);
+ mi.cbSize = sizeof(mi);
+ utf8_decode(szValue, &ansi);
+ mi.pszName = strlen(ansi) > 0 ? ansi : ICQTranslate(nameXStatus[dat->bXStatus-1]);
+ mi.flags = CMIM_NAME;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[dat->bXStatus], (LPARAM)&mi);
+
+ SAFE_FREE(&szValue);
+ SAFE_FREE(&ansi);
+
+
+ setUserInfo();
+
+ SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XMSG),GWL_WNDPROC,(LONG)OldMessageEditProc);
+ SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XTITLE),GWL_WNDPROC,(LONG)OldMessageEditProc);
+ }
+ if (dat->hEvent) UnhookEvent(dat->hEvent);
+ SAFE_FREE(&dat->okButtonFormat);
+ if (dat->hDlgIcon && !IconLibInstalled())
+ DestroyIcon(dat->hDlgIcon); // release dialog icon
+ SAFE_FREE(&dat);
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ return FALSE;
+}
+
+
+
+static void setXStatusEx(BYTE bXStatus, BYTE bQuiet)
+{
+
+ CLISTMENUITEM mi = {0};
+ BYTE bOldXStatus = ICQGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+
+ mi.cbSize = sizeof(mi);
+
+ if (bOldXStatus <= 32)
+ {
+ mi.flags = CMIM_FLAGS;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[bOldXStatus], (LPARAM)&mi);
+ }
+
+
+ ICQWriteContactSettingByte(NULL, DBSETTING_XSTATUSID, bXStatus);
+ mi.flags = CMIM_FLAGS | (bXStatus?CMIF_CHECKED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[bXStatus], (LPARAM)&mi);
+
+ if (bXStatus)
+ {
+ char szSetting[64];
+ char str[MAX_PATH];
+ char* szUtf;
+
+ sprintf(szSetting, "XStatus%dName", bXStatus);
+ szUtf = ICQGetContactSettingUtf(NULL, szSetting, ICQTranslateUtfStatic(nameXStatus[bXStatus-1], str));
+ ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, szUtf);
+ SAFE_FREE(&szUtf);
+
+ sprintf(szSetting, "XStatus%dMsg", bXStatus);
+ szUtf = ICQGetContactSettingUtf(NULL, szSetting, "");
+ ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, szUtf);
+ SAFE_FREE(&szUtf);
+
+ sprintf(szSetting, "XStatus%dStat", bXStatus);
+ if (!bQuiet && !ICQGetContactSettingByte(NULL, szSetting, 0))
+ {
+ InitXStatusData init;
+
+ init.bAction = 0; // set
+ init.bXStatus = bXStatus;
+ DialogBoxUtf(FALSE, hInst, MAKEINTRESOURCEA(IDD_SETXSTATUS),NULL,SetXStatusDlgProc,(LPARAM)&init);
+ }
+ else
+ setUserInfo();
+ }
+ else
+ {
+ ICQDeleteContactSetting(NULL, DBSETTING_XSTATUSNAME);
+ ICQDeleteContactSetting(NULL, DBSETTING_XSTATUSMSG);
+
+ setUserInfo();
+ }
+}
+
+
+
+static void __fastcall setXStatus(BYTE bXStatus)
+{ // for menu commands
+ setXStatusEx(bXStatus, 0);
+}
+
+static int menuXStatus0(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(0); return 0;
+}
+
+static int menuXStatus1(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(1); return 0;
+}
+
+static int menuXStatus2(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(2); return 0;
+}
+
+static int menuXStatus3(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(3); return 0;
+}
+
+static int menuXStatus4(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(4); return 0;
+}
+
+static int menuXStatus5(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(5); return 0;
+}
+
+static int menuXStatus6(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(6); return 0;
+}
+
+static int menuXStatus7(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(7); return 0;
+}
+
+static int menuXStatus8(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(8); return 0;
+}
+
+static int menuXStatus9(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(9); return 0;
+}
+
+static int menuXStatus10(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(10); return 0;
+}
+
+static int menuXStatus11(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(11); return 0;
+}
+
+static int menuXStatus12(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(12); return 0;
+}
+
+static int menuXStatus13(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(13); return 0;
+}
+
+static int menuXStatus14(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(14); return 0;
+}
+
+static int menuXStatus15(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(15); return 0;
+}
+
+static int menuXStatus16(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(16); return 0;
+}
+
+static int menuXStatus17(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(17); return 0;
+}
+
+static int menuXStatus18(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(18); return 0;
+}
+
+static int menuXStatus19(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(19); return 0;
+}
+
+static int menuXStatus20(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(20); return 0;
+}
+
+static int menuXStatus21(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(21); return 0;
+}
+
+static int menuXStatus22(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(22); return 0;
+}
+
+static int menuXStatus23(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(23); return 0;
+}
+
+static int menuXStatus24(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(24); return 0;
+}
+
+static int menuXStatus25(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(25); return 0;
+}
+
+static int menuXStatus26(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(26); return 0;
+}
+
+static int menuXStatus27(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(27); return 0;
+}
+
+static int menuXStatus28(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(28); return 0;
+}
+
+static int menuXStatus29(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(29); return 0;
+}
+
+static int menuXStatus30(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(30); return 0;
+}
+static int menuXStatus31(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(31); return 0;
+}
+static int menuXStatus32(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(32); return 0;
+}
+
+
+void InitXStatusItems(BOOL bAllowStatus)
+{
+ CLISTMENUITEM mi;
+
+ int i = 0;
+ char srvFce[MAX_PATH + 64];
+ char szItem[MAX_PATH + 64];
+ HANDLE hXStatusRoot;
+
+ BYTE bXStatus = ICQGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+
+ if (!gbXStatusEnabled) return;
+
+ if (bStatusMenu && !bAllowStatus) return;
+
+ null_snprintf(szItem, sizeof(szItem), ICQTranslate("%s Custom Status"), gpszICQProtoName);
+ mi.cbSize = sizeof(mi);
+ mi.pszPopupName = szItem;
+ mi.popupPosition= 500084000;
+ mi.position = 2000040000;
+
+ for(i = 0; i <= 32; i++)
+ {
+ char szTemp[64];
+ char* szValue;
+ char* ansi = NULL;
+ HICON hIIcon = (i > 0) ? LoadDefaultXStatusIcon(i) : NULL;
+
+ null_snprintf(srvFce, sizeof(srvFce), "%s/menuXStatus%d", gpszICQProtoName, i);
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", i-1);
+ mi.hIcon = IconLibProcess(hIIcon, szTemp);
+ mi.position++;
+
+ if (!bXStatusMenuBuilt)
+ {
+ switch(i)
+ {
+ case 0: CreateServiceFunction(srvFce, menuXStatus0); break;
+ case 1: CreateServiceFunction(srvFce, menuXStatus1); break;
+ case 2: CreateServiceFunction(srvFce, menuXStatus2); break;
+ case 3: CreateServiceFunction(srvFce, menuXStatus3); break;
+ case 4: CreateServiceFunction(srvFce, menuXStatus4); break;
+ case 5: CreateServiceFunction(srvFce, menuXStatus5); break;
+ case 6: CreateServiceFunction(srvFce, menuXStatus6); break;
+ case 7: CreateServiceFunction(srvFce, menuXStatus7); break;
+ case 8: CreateServiceFunction(srvFce, menuXStatus8); break;
+ case 9: CreateServiceFunction(srvFce, menuXStatus9); break;
+ case 10: CreateServiceFunction(srvFce, menuXStatus10); break;
+ case 11: CreateServiceFunction(srvFce, menuXStatus11); break;
+ case 12: CreateServiceFunction(srvFce, menuXStatus12); break;
+ case 13: CreateServiceFunction(srvFce, menuXStatus13); break;
+ case 14: CreateServiceFunction(srvFce, menuXStatus14); break;
+ case 15: CreateServiceFunction(srvFce, menuXStatus15); break;
+ case 16: CreateServiceFunction(srvFce, menuXStatus16); break;
+ case 17: CreateServiceFunction(srvFce, menuXStatus17); break;
+ case 18: CreateServiceFunction(srvFce, menuXStatus18); break;
+ case 19: CreateServiceFunction(srvFce, menuXStatus19); break;
+ case 20: CreateServiceFunction(srvFce, menuXStatus20); break;
+ case 21: CreateServiceFunction(srvFce, menuXStatus21); break;
+ case 22: CreateServiceFunction(srvFce, menuXStatus22); break;
+ case 23: CreateServiceFunction(srvFce, menuXStatus23); break;
+ case 24: CreateServiceFunction(srvFce, menuXStatus24); break;
+ case 25: CreateServiceFunction(srvFce, menuXStatus25); break;
+ case 26: CreateServiceFunction(srvFce, menuXStatus26); break;
+ case 27: CreateServiceFunction(srvFce, menuXStatus27); break;
+ case 28: CreateServiceFunction(srvFce, menuXStatus28); break;
+ case 29: CreateServiceFunction(srvFce, menuXStatus29); break;
+ case 30: CreateServiceFunction(srvFce, menuXStatus30); break;
+ case 31: CreateServiceFunction(srvFce, menuXStatus31); break;
+ case 32: CreateServiceFunction(srvFce, menuXStatus32); break;
+ }
+ }
+
+ mi.flags = bXStatus == i?CMIF_CHECKED:0;
+
+ sprintf(szTemp, "XStatus%dName", i);
+ szValue = ICQGetContactSettingUtf(NULL, szTemp, "");
+
+ utf8_decode(szValue, &ansi);
+ mi.pszName = (strlen(ansi) == 0) ? ICQTranslate(i?nameXStatus[i-1]:"None") : ansi;
+ mi.pszService = srvFce;
+ mi.pszContactOwner = gpszICQProtoName;
+
+ if (bStatusMenu)
+ hXStatusItems[i] = (HANDLE)CallService(MS_CLIST_ADDSTATUSMENUITEM, (WPARAM)&hXStatusRoot, (LPARAM)&mi);
+ else
+ hXStatusItems[i] = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi);
+ if (i) DestroyIcon(hIIcon);
+ SAFE_FREE(&szValue);
+ SAFE_FREE(&ansi);
+
+ }
+
+ bXStatusMenuBuilt = 1;
+}
+
+
+
+void InitXStatusIcons()
+{
+ char szSection[MAX_PATH + 64];
+ char str[MAX_PATH], prt[MAX_PATH];
+ char lib[2*MAX_PATH] = {0};
+ char* icon_lib;
+ int i;
+
+ if (!gbXStatusEnabled) return;
+
+ icon_lib = InitXStatusIconLibrary(lib);
+
+ null_snprintf(szSection, sizeof(szSection), ICQTranslateUtfStatic("%s/Custom Status", str), ICQTranslateUtfStatic(gpszICQProtoName, prt));
+
+ for (i = 0; i < 32; i++)
+ {
+ char szTemp[64];
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", i);
+ IconLibDefine(ICQTranslateUtfStatic(nameXStatus[i], str), szSection, szTemp, NULL, icon_lib, -(IDI_XSTATUS1+i));
+ }
+
+ if (bXStatusMenuBuilt)
+ ChangedIconsXStatus();
+}
+
+
+
+void ChangedIconsXStatus()
+{ // reload icons
+ int i;
+
+ if (!gbXStatusEnabled) return;
+
+ for (i = 1; i < 33; i++)
+ {
+ HICON hIcon = GetXStatusIcon(i);
+
+ CListSetMenuItemIcon(hXStatusItems[i], hIcon);
+ if (!IconLibInstalled())
+ DestroyIcon(hIcon); // if not IconLib resource release
+ }
+}
+
+
+
+int IcqShowXStatusDetails(WPARAM wParam, LPARAM lParam)
+{
+ InitXStatusData init;
+
+ init.bAction = 1; // retrieve
+ init.hContact = (HANDLE)wParam;
+ DialogBoxUtf(FALSE, hInst, MAKEINTRESOURCEA(IDD_SETXSTATUS), NULL, SetXStatusDlgProc, (LPARAM)&init);
+
+ return 0;
+}
+
+
+
+int IcqSetXStatus(WPARAM wParam, LPARAM lParam)
+{ // obsolete (TODO: remove in next version)
+ if (!gbXStatusEnabled) return 0;
+
+ if (wParam >= 0 && wParam <= 32)
+ {
+ setXStatusEx((BYTE)wParam, 1);
+
+ return wParam;
+ }
+ return 0;
+}
+
+
+
+int IcqGetXStatus(WPARAM wParam, LPARAM lParam)
+{ // obsolete (TODO: remove in next version)
+ BYTE status = ICQGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+
+ if (!gbXStatusEnabled) return 0;
+
+ if (!icqOnline) return 0;
+
+ if (status < 1 || status > 32) status = 0;
+
+ if (wParam) *((char**)wParam) = DBSETTING_XSTATUSNAME;
+ if (lParam) *((char**)lParam) = DBSETTING_XSTATUSMSG;
+
+ return status;
+}
+
+
+
+int IcqSetXStatusEx(WPARAM wParam, LPARAM lParam)
+{
+ ICQ_CUSTOM_STATUS *pData = (ICQ_CUSTOM_STATUS*)lParam;
+
+ if (!gbXStatusEnabled) return 1;
+
+ if (pData->cbSize < sizeof(ICQ_CUSTOM_STATUS)) return 1; // Failure
+
+ if (pData->flags & CSSF_MASK_STATUS)
+ { // set custom status
+ int status = *pData->status;
+
+ if (status >= 0 && status <= 32)
+ {
+ setXStatusEx((BYTE)status, 1);
+ }
+ else
+ return 1; // Failure
+ }
+
+ if (pData->flags & (CSSF_MASK_NAME | CSSF_MASK_MESSAGE))
+ {
+ BYTE status = ICQGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+
+ if (status < 1 || status > 32) return 1; // Failure
+
+ if (pData->flags & CSSF_MASK_NAME)
+ { // set custom status name
+ if (pData->flags & CSSF_UNICODE)
+ {
+ char* utf = make_utf8_string(pData->pwszName);
+
+ ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, utf);
+ SAFE_FREE(&utf);
+ }
+ else
+ ICQWriteContactSettingString(NULL, DBSETTING_XSTATUSNAME, pData->pszName);
+ }
+ if (pData->flags & CSSF_MASK_MESSAGE)
+ { // set custom status message
+ if (pData->flags & CSSF_UNICODE)
+ {
+ char* utf = make_utf8_string(pData->pwszMessage);
+
+ ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, utf);
+ SAFE_FREE(&utf);
+ }
+ else
+ ICQWriteContactSettingString(NULL, DBSETTING_XSTATUSMSG, pData->pszMessage);
+ }
+ }
+
+ if (pData->flags & CSSF_DISABLE_UI)
+ { // hide menu items
+ int n;
+
+ bHideXStatusUI = (*pData->wParam) ? 0 : 1;
+
+ for (n = 0; n<=32; n++)
+ CListShowMenuItem(hXStatusItems[n], (BYTE)!bHideXStatusUI);
+ }
+
+ return 0; // Success
+}
+
+
+
+int IcqGetXStatusEx(WPARAM wParam, LPARAM lParam)
+{
+ ICQ_CUSTOM_STATUS *pData = (ICQ_CUSTOM_STATUS*)lParam;
+ HANDLE hContact = (HANDLE)wParam;
+
+ if (!gbXStatusEnabled) return 1;
+
+ if (pData->cbSize < sizeof(ICQ_CUSTOM_STATUS)) return 1; // Failure
+
+ if (pData->flags & CSSF_MASK_STATUS)
+ { // fill status member
+ *pData->status = ICQGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+ }
+
+ if (pData->flags & CSSF_MASK_NAME)
+ { // fill status name member
+ if (pData->flags & CSSF_DEFAULT_NAME)
+ {
+ int status = *pData->wParam;
+
+ if (status < 1 || status > 32) return 1; // Failure
+
+ if (pData->flags & CSSF_UNICODE)
+ {
+ char *text = (char*)nameXStatus[status -1];
+
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text, strlennull(text), pData->pwszName, MAX_PATH);
+ }
+ else
+ strcpy(pData->pszName, nameXStatus[status - 1]);
+ }
+ else
+ {
+ if (pData->flags & CSSF_UNICODE)
+ {
+ char* str = ICQGetContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, "");
+ wchar_t* wstr = make_unicode_string(str);
+
+ wcscpy(pData->pwszName, wstr);
+ SAFE_FREE(&str);
+ SAFE_FREE(&wstr);
+ }
+ else
+ {
+ DBVARIANT dbv = {0};
+
+ ICQGetContactSetting(hContact, DBSETTING_XSTATUSNAME, &dbv);
+ strcpy(pData->pszName, dbv.pszVal);
+
+ ICQFreeVariant(&dbv);
+ }
+ }
+ }
+
+ if (pData->flags & CSSF_MASK_MESSAGE)
+ { // fill status message member
+ if (pData->flags & CSSF_UNICODE)
+ {
+ char* str = ICQGetContactSettingUtf(hContact, DBSETTING_XSTATUSMSG, "");
+ wchar_t* wstr = make_unicode_string(str);
+
+ wcscpy(pData->pwszMessage, wstr);
+ SAFE_FREE(&str);
+ SAFE_FREE(&wstr);
+ }
+ else
+ {
+ DBVARIANT dbv = {0};
+
+ ICQGetContactSetting(hContact, DBSETTING_XSTATUSMSG, &dbv);
+ strcpy(pData->pszMessage, dbv.pszVal);
+
+ ICQFreeVariant(&dbv);
+ }
+ }
+
+ if (pData->flags & CSSF_DISABLE_UI)
+ {
+ if (pData->wParam) *pData->wParam = !bHideXStatusUI;
+ }
+
+ if (pData->flags & CSSF_STATUSES_COUNT)
+ {
+ if (pData->wParam) *pData->wParam = 32;
+ }
+
+ if (pData->flags & CSSF_STR_SIZES)
+ {
+ DBVARIANT dbv = {0};
+
+ if (pData->wParam)
+ {
+ if (!ICQGetContactSetting(hContact, DBSETTING_XSTATUSNAME, &dbv))
+ {
+ *pData->wParam = strlennull(dbv.pszVal);
+ ICQFreeVariant(&dbv);
+ }
+ else
+ *pData->wParam = 0;
+ }
+ if (pData->lParam)
+ {
+ if (!ICQGetContactSetting(hContact, DBSETTING_XSTATUSMSG, &dbv))
+ {
+ *pData->lParam = strlennull(dbv.pszVal);
+ ICQFreeVariant(&dbv);
+ }
+ else
+ *pData->lParam = 0;
+ }
+ }
+
+ return 0; // Success
+}
+
+
+
+int IcqGetXStatusIcon(WPARAM wParam, LPARAM lParam)
+{
+ if (!gbXStatusEnabled) return 0;
+
+ if (!wParam)
+ wParam = ICQGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+
+ if (wParam >= 1 && wParam <= 32)
+ {
+ HICON icon = GetXStatusIcon((BYTE)wParam);
+
+ if (IconLibInstalled())
+ icon = CopyIcon(icon);
+
+ return (int)icon;
+ }
+ return 0;
+}
+
+
+
+int IcqRequestXStatusDetails(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+
+ if (!gbXStatusEnabled) return 0;
+
+ if (hContact && !ICQGetContactSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO) &&
+ ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, 0))
+ { // user has xstatus, no auto-retrieve details, valid contact, request details
+ return requestXStatusDetails(hContact, TRUE);
+ }
+ return 0;
+}
diff --git a/icqj_mod/icq_xtraz.c b/icqj_mod/icq_xtraz.c new file mode 100644 index 0000000..6c70bdc --- /dev/null +++ b/icqj_mod/icq_xtraz.c @@ -0,0 +1,454 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_xtraz.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Ăşt, 16 V 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Internal Xtraz API
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+extern HANDLE hsmsgrequest;
+
+
+void handleXtrazNotify(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC)
+{
+ char *szWork, *szEnd, *szNotify, *szQuery;
+ int nNotifyLen, nQueryLen;
+ HANDLE hContact;
+
+ szNotify = strstr(szMsg, "<NOTIFY>");
+ szQuery = strstr(szMsg, "<QUERY>");
+
+ hContact = HContactFromUIN(dwUin, NULL);
+ if (hContact) // user sent us xtraz, he supports it
+ SetContactCapabilities(hContact, CAPF_XTRAZ);
+
+ if (szNotify && szQuery)
+ { // valid request
+ szNotify += 8;
+ szQuery += 7;
+ szEnd = strstr(szMsg, "</NOTIFY>");
+ if (!szEnd) szEnd = szMsg + nMsgLen;
+ nNotifyLen = (szEnd - szNotify);
+ szEnd = strstr(szMsg, "</QUERY>");
+ if (!szEnd) szEnd = szNotify;
+ szNotify = DemangleXml(szNotify, nNotifyLen);
+ nQueryLen = (szEnd - szQuery);
+ szQuery = DemangleXml(szQuery, nQueryLen);
+ szWork = strstr(szQuery, "<PluginID>");
+ szEnd = strstr(szQuery, "</PluginID>");
+#ifdef _DEBUG
+ NetLog_Server("Query: %s", szQuery);
+ NetLog_Server("Notify: %s", szNotify);
+#endif
+ if (szWork && szEnd)
+ { // this is our plugin
+ szWork += 10;
+ *szEnd = '\0';
+
+ if (!stricmp(szWork, "srvMng") && strstr(szNotify, "AwayStat"))
+ {
+ char* szSender = strstr(szNotify, "<senderId>");
+ char* szEndSend = strstr(szNotify, "</senderId>");
+
+ if (szSender && szEndSend)
+ {
+ szSender += 10;
+ *szEndSend = '\0';
+
+ if ((DWORD)atoi(szSender) == dwUin)
+ {
+ char *szResponse;
+ int nResponseLen;
+ char *szXName, *szXMsg;
+ BYTE dwXId = ICQGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+
+ if (dwXId && validateStatusMessageRequest(hContact, MTYPE_SCRIPT_NOTIFY))
+ { // apply privacy rules
+ NotifyEventHooks(hsmsgrequest, (WPARAM)MTYPE_SCRIPT_NOTIFY, (LPARAM)dwUin);
+
+ szXName = ICQGetContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, "");
+ szXMsg = ICQGetContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, "");
+
+ nResponseLen = 212 + strlennull(szXName) + strlennull(szXMsg) + UINMAXLEN + 2;
+ szResponse = (char*)_alloca(nResponseLen + 1);
+ // send response
+ nResponseLen = null_snprintf(szResponse, nResponseLen,
+ "<ret event='OnRemoteNotification'>"
+ "<srv><id>cAwaySrv</id>"
+ "<val srv_id='cAwaySrv'><Root>"
+ "<CASXtraSetAwayMessage></CASXtraSetAwayMessage>"
+ "<uin>%d</uin>"
+ "<index>%d</index>"
+ "<title>%s</title>"
+ "<desc>%s</desc></Root></val></srv></ret>",
+ dwLocalUIN, dwXId, szXName, szXMsg);
+
+ SAFE_FREE(&szXName);
+ SAFE_FREE(&szXMsg);
+
+ if (gbXStatusEnabled)
+ {
+ rate_record rr = {0};
+
+ rr.bType = RIT_XSTATUS_RESPONSE;
+ rr.dwUin = dwUin;
+ rr.dwMid1 = dwMID;
+ rr.dwMid2 = dwMID2;
+ rr.wCookie = wCookie;
+ rr.szData = szResponse;
+ rr.bThruDC = bThruDC;
+ rr.rate_group = 0x102;
+ if (bThruDC || !handleRateItem(&rr, TRUE))
+ SendXtrazNotifyResponse(dwUin, dwMID, dwMID2, wCookie, szResponse, nResponseLen, bThruDC);
+ }
+ else
+ NetLog_Server("Error: XStatus Disabled");
+ }
+ else if (dwXId)
+ NetLog_Server("Privacy: Ignoring XStatus request");
+ else
+ NetLog_Server("Error: We are not in XStatus, skipping");
+ }
+ else
+ NetLog_Server("Error: Invalid sender information");
+ }
+ else
+ NetLog_Server("Error: Missing sender information");
+ }
+ else
+ NetLog_Server("Error: Unknown plugin \"%s\" in Xtraz message", szWork);
+ }
+ else
+ NetLog_Server("Error: Missing PluginID in Xtraz message");
+
+ SAFE_FREE(&szNotify);
+ SAFE_FREE(&szQuery);
+ }
+ else
+ NetLog_Server("Error: Invalid Xtraz Notify message");
+}
+
+
+
+void handleXtrazNotifyResponse(DWORD dwUin, HANDLE hContact, WORD wCookie, char* szMsg, int nMsgLen)
+{
+ char *szMem, *szRes, *szEnd;
+ int nResLen;
+
+#ifdef _DEBUG
+ NetLog_Server("Received Xtraz Notify Response");
+#endif
+
+ szRes = strstr(szMsg, "<RES>");
+ szEnd = strstr(szMsg, "</RES>");
+
+ if (szRes && szEnd)
+ { // valid response
+ char *szNode, *szWork;
+
+ szRes += 5;
+ nResLen = szEnd - szRes;
+
+ szMem = szRes = DemangleXml(szRes, nResLen);
+
+#ifdef _DEBUG
+ NetLog_Server("Response: %s", szRes);
+#endif
+
+ ICQBroadcastAck(hContact, ICQACKTYPE_XTRAZNOTIFY_RESPONSE, ACKRESULT_SUCCESS, (HANDLE)wCookie, (LPARAM)szRes);
+
+NextVal:
+ szNode = strstr(szRes, "<val srv_id='");
+ if (szNode) szEnd = strstr(szNode, ">"); else szEnd = NULL;
+
+ if (szNode && szEnd)
+ {
+ *(szEnd-1) = '\0';
+ szNode += 13;
+ szWork = szEnd + 1;
+
+ if (!stricmp(szNode, "cAwaySrv"))
+ {
+ szNode = strstr(szWork, "<uin>");
+ szEnd = strstr(szWork, "</uin>");
+
+ if (szNode && szEnd)
+ {
+ szNode += 5;
+ *szEnd = '\0';
+
+ if ((DWORD)atoi(szNode) == dwUin)
+ {
+ *szEnd = ' ';
+ szNode = strstr(szWork, "<index>");
+ szEnd = strstr(szWork, "</index>");
+
+ if (szNode && szEnd)
+ {
+ szNode += 7;
+ *szEnd = '\0';
+ if (atoi(szNode) != ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, 0))
+ { // this is strange - but go on
+ NetLog_Server("Warning: XStatusIds do not match!");
+ }
+ *szEnd = ' ';
+ }
+ szNode = strstr(szWork, "<title>");
+ szEnd = strstr(szWork, "</title>");
+
+ if (szNode && szEnd)
+ { // we got XStatus title, save it
+ szNode += 7;
+ *szEnd = '\0';
+ ICQWriteContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, szNode);
+ *szEnd = ' ';
+ }
+ szNode = strstr(szWork, "<desc>");
+ szEnd = strstr(szWork, "</desc>");
+
+ if (szNode && szEnd)
+ { // we got XStatus mode msg, save it
+ szNode += 6;
+ *szEnd = '\0';
+ ICQWriteContactSettingUtf(hContact, DBSETTING_XSTATUSMSG, szNode);
+ }
+ ICQBroadcastAck(hContact, ICQACKTYPE_XSTATUS_RESPONSE, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
+ }
+ else
+ NetLog_Server("Error: Invalid sender information");
+ }
+ else
+ NetLog_Server("Error: Missing sender information");
+ }
+ else
+ {
+ char *szSrvEnd = strstr(szEnd, "</srv>");
+
+ if (szSrvEnd && strstr(szSrvEnd, "<val srv_id='"))
+ { // check all values !
+ szRes = szSrvEnd + 6; // after first value
+ goto NextVal;
+ }
+ // no next val, we were unable to handle packet, write error
+ NetLog_Server("Error: Unknown serverId \"%s\" in Xtraz response", szNode);
+ }
+ }
+ else
+ NetLog_Server("Error: Missing serverId in Xtraz response");
+
+ SAFE_FREE(&szMem);
+ }
+ else
+ NetLog_Server("Error: Invalid Xtraz Notify response");
+}
+
+
+
+static char* getXmlPidItem(const char* szData, int nLen)
+{
+ char *szPid, *szEnd;
+
+ szPid = strstr(szData, "<PID>");
+ szEnd = strstr(szData, "</PID>");
+
+ if (szPid && szEnd)
+ {
+ szPid += 5;
+
+ return DemangleXml(szPid, szEnd - szPid);
+ }
+ return NULL;
+}
+
+
+
+void handleXtrazInvitation(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC)
+{
+ HANDLE hContact;
+ char* szPluginID;
+
+ hContact = HContactFromUIN(dwUin, NULL);
+ if (hContact) // user sent us xtraz, he supports it
+ SetContactCapabilities(hContact, CAPF_XTRAZ);
+
+ szPluginID = getXmlPidItem(szMsg, nMsgLen);
+ if (!strcmpnull(szPluginID, "ICQChatRecv"))
+ { // it is a invitation to multi-user chat
+ }
+ else
+ {
+ NetLog_Uni(bThruDC, "Error: Unknown plugin \"%s\" in Xtraz message", szPluginID);
+ }
+ SAFE_FREE(&szPluginID);
+}
+
+
+
+void handleXtrazData(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC)
+{
+ HANDLE hContact;
+ char* szPluginID;
+
+ hContact = HContactFromUIN(dwUin, NULL);
+ if (hContact) // user sent us xtraz, he supports it
+ SetContactCapabilities(hContact, CAPF_XTRAZ);
+
+ szPluginID = getXmlPidItem(szMsg, nMsgLen);
+ if (!strcmpnull(szPluginID, "viewCard"))
+ { // it is a greeting card
+ char *szWork, *szEnd, *szUrl, *szNum;
+
+ szWork = strstr(szMsg, "<InD>");
+ szEnd = strstr(szMsg, "</InD>");
+ if (szWork && szEnd)
+ {
+ int nDataLen = szEnd - szWork;
+
+ szUrl = (char*)_alloca(nDataLen);
+ memcpy(szUrl, szWork+5, nDataLen);
+ szUrl[nDataLen - 5] = '\0';
+
+ if (!strnicmp(szUrl, "view_", 5))
+ {
+ szNum = szUrl + 5;
+ szWork = strstr(szUrl, ".html");
+ if (szWork)
+ {
+ strcpy(szWork, ".php");
+ strcat(szWork, szWork+5);
+ }
+ while (szWork = strstr(szUrl, "&"))
+ { // unescape & code
+ strcpy(szWork+1, szWork+5);
+ }
+ szWork = (char*)_alloca(nDataLen + MAX_PATH);
+ ICQTranslateUtfStatic("Greeting card:", szWork);
+ strcat(szWork, "\r\nhttp://www.icq.com/friendship/pages/view_page_");
+ strcat(szWork, szNum);
+
+ // Create message to notify user
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ int bAdded;
+
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = HContactFromUIN(dwUin, &bAdded);
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.flags = 0;
+ pre.timestamp = time(NULL);
+ pre.szMessage = szWork;
+ pre.lParam = 0;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+ }
+ else
+ NetLog_Uni(bThruDC, "Error: Non-standard greeting card message");
+ }
+ else
+ NetLog_Uni(bThruDC, "Error: Malformed greeting card message");
+ }
+ else
+ {
+ NetLog_Uni(bThruDC, "Error: Unknown plugin \"%s\" in Xtraz message", szPluginID);
+ }
+ SAFE_FREE(&szPluginID);
+}
+
+
+
+// Functions really sending Xtraz stuff
+DWORD SendXtrazNotifyRequest(HANDLE hContact, char* szQuery, char* szNotify, int bForced)
+{
+ char *szQueryBody;
+ char *szNotifyBody;
+ DWORD dwUin;
+ int nBodyLen;
+ char *szBody;
+ DWORD dwCookie;
+ message_cookie_data* pCookieData;
+
+ if (ICQGetContactSettingUID(hContact, &dwUin, NULL))
+ return 0; // Invalid contact
+
+ if (!CheckContactCapabilities(hContact, CAPF_XTRAZ) && !bForced)
+ return 0; // Contact does not support xtraz, do not send anything
+
+ szQueryBody = MangleXml(szQuery, strlennull(szQuery));
+ szNotifyBody = MangleXml(szNotify, strlennull(szNotify));
+ nBodyLen = strlennull(szQueryBody) + strlennull(szNotifyBody) + 41;
+ szBody = (char*)_alloca(nBodyLen);
+ nBodyLen = null_snprintf(szBody, nBodyLen, "<N><QUERY>%s</QUERY><NOTIFY>%s</NOTIFY></N>", szQueryBody, szNotifyBody);
+ SAFE_FREE(&szQueryBody);
+ SAFE_FREE(&szNotifyBody);
+
+ // Set up the ack type
+ pCookieData = CreateMessageCookie(MTYPE_SCRIPT_NOTIFY, ACKTYPE_CLIENT);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, dwUin, (void*)pCookieData);
+
+ // have we a open DC, send through that
+ if (gbDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD))
+ icq_sendXtrazRequestDirect(dwUin, hContact, dwCookie, szBody, nBodyLen, MTYPE_SCRIPT_NOTIFY);
+ else
+ icq_sendXtrazRequestServ(dwUin, dwCookie, szBody, nBodyLen, pCookieData);
+
+ return dwCookie;
+}
+
+
+
+void SendXtrazNotifyResponse(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szResponse, int nResponseLen, BOOL bThruDC)
+{
+ char *szResBody = MangleXml(szResponse, nResponseLen);
+ int nBodyLen = strlennull(szResBody) + 21;
+ char *szBody = (char*)_alloca(nBodyLen);
+ HANDLE hContact = HContactFromUIN(dwUin, NULL);
+
+ if (hContact != INVALID_HANDLE_VALUE && !CheckContactCapabilities(hContact, CAPF_XTRAZ))
+ {
+ SAFE_FREE(&szResBody);
+ return; // Contact does not support xtraz, do not send anything
+ }
+
+ nBodyLen = null_snprintf(szBody, nBodyLen, "<NR><RES>%s</RES></NR>", szResBody);
+ SAFE_FREE(&szResBody);
+
+ // Was request received thru DC and have we a open DC, send through that
+ if (bThruDC && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD))
+ icq_sendXtrazResponseDirect(dwUin, hContact, wCookie, szBody, nBodyLen, MTYPE_SCRIPT_NOTIFY);
+ else
+ icq_sendXtrazResponseServ(dwUin, dwMID, dwMID2, wCookie, szBody, nBodyLen, MTYPE_SCRIPT_NOTIFY);
+}
diff --git a/icqj_mod/icq_xtraz.h b/icqj_mod/icq_xtraz.h new file mode 100644 index 0000000..84a387a --- /dev/null +++ b/icqj_mod/icq_xtraz.h @@ -0,0 +1,70 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_xtraz.h,v $
+// Revision : $Revision: 3069 $
+// Last change on : $Date: 2006-06-07 20:05:39 +0200 (st, 07 VI 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_XTRAZ_H
+#define __ICQ_XTRAZ_H
+
+void handleXtrazNotify(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC);
+void handleXtrazNotifyResponse(DWORD dwUin, HANDLE hContact, WORD wCookie, char* szMsg, int nMsgLen);
+
+void handleXtrazInvitation(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC);
+void handleXtrazData(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC);
+
+DWORD SendXtrazNotifyRequest(HANDLE hContact, char* szQuery, char* szNotify, int bForced);
+void SendXtrazNotifyResponse(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szResponse, int nResponseLen, BOOL bThruDC);
+
+// custom status support
+void InitXStatusItems(BOOL bAllowStatus);
+void InitXStatusEvents();
+void UninitXStatusEvents();
+
+void InitXStatusIcons();
+void ChangedIconsXStatus();
+HICON GetXStatusIcon(int bStatus);
+
+void handleXStatusCaps(HANDLE hContact, char* caps, int capsize);
+
+int IcqShowXStatusDetails(WPARAM wParam, LPARAM lParam);
+
+// custom status public services
+int IcqSetXStatus(WPARAM wParam, LPARAM lParam);
+int IcqGetXStatus(WPARAM wParam, LPARAM lParam);
+int IcqSetXStatusEx(WPARAM wParam, LPARAM lParam);
+int IcqGetXStatusEx(WPARAM wParam, LPARAM lParam);
+int IcqGetXStatusIcon(WPARAM wParam, LPARAM lParam);
+int IcqRequestXStatusDetails(WPARAM wParam, LPARAM lParam);
+
+#endif /* __ICQ_XTRAZ_H */
diff --git a/icqj_mod/icqosc_proto.h b/icqj_mod/icqosc_proto.h new file mode 100644 index 0000000..27b37ac --- /dev/null +++ b/icqj_mod/icqosc_proto.h @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icqosc_proto.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQOSC_PROTO_H
+#define __ICQOSC_PROTO_H
+
+
+#endif /* __ICQOSC_PROTO_H */
\ No newline at end of file diff --git a/icqj_mod/icqosc_svcs.c b/icqj_mod/icqosc_svcs.c new file mode 100644 index 0000000..9cd7b9f --- /dev/null +++ b/icqj_mod/icqosc_svcs.c @@ -0,0 +1,2306 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icqosc_svcs.c,v $
+// Revision : $Revision: 3237 $
+// Last change on : $Date: 2006-06-27 19:57:56 +0200 (Tue, 27 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// High-level code for exported API services
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+int gbIdleAllow;
+int icqGoingOnlineStatus;
+
+extern WORD wListenPort;
+
+extern char* calcMD5Hash(char* szFile);
+extern filetransfer *CreateFileTransfer(HANDLE hContact, DWORD dwUin, int nVersion);
+
+
+int IcqGetCaps(WPARAM wParam, LPARAM lParam)
+{
+ int nReturn = 0;
+
+
+ switch (wParam)
+ {
+
+ case PFLAGNUM_1:
+ nReturn = PF1_IM | PF1_URL | PF1_AUTHREQ | PF1_BASICSEARCH | PF1_ADDSEARCHRES |
+ PF1_VISLIST | PF1_INVISLIST | PF1_MODEMSG | PF1_FILE | PF1_EXTSEARCH |
+ PF1_EXTSEARCHUI | PF1_SEARCHBYEMAIL | PF1_SEARCHBYNAME |
+ PF1_ADDED | PF1_CONTACT;
+ if (!gbAimEnabled)
+ nReturn |= PF1_NUMERICUSERID;
+ if (gbSsiEnabled && ICQGetContactSettingByte(NULL, "ServerAddRemove", DEFAULT_SS_ADDSERVER))
+ nReturn |= PF1_SERVERCLIST;
+ break;
+
+ case PFLAGNUM_2:
+ nReturn = PF2_ONLINE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND |
+ PF2_FREECHAT | PF2_INVISIBLE;
+ break;
+
+ case PFLAGNUM_3:
+ nReturn = PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND |
+ PF2_FREECHAT;
+ break;
+
+ case PFLAGNUM_4:
+ nReturn = PF4_SUPPORTIDLE;
+ if (gbAvatarsEnabled)
+ nReturn |= PF4_AVATARS;
+#ifdef DBG_CAPMTN
+ nReturn |= PF4_SUPPORTTYPING;
+#endif
+ break;
+
+ case PFLAG_UNIQUEIDTEXT:
+ nReturn = (int)ICQTranslate("User ID");
+ break;
+
+ case PFLAG_UNIQUEIDSETTING:
+ nReturn = (int)UNIQUEIDSETTING;
+ break;
+
+ case PFLAG_MAXCONTACTSPERPACKET:
+ nReturn = MAX_CONTACTSSEND;
+ break;
+
+ case PFLAG_MAXLENOFMESSAGE:
+ nReturn = MAX_MESSAGESNACSIZE-102;
+ }
+
+ return nReturn;
+}
+
+
+
+int IcqGetName(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam)
+ {
+ strncpy((char *)lParam, ICQTranslate(gpszICQProtoName), wParam);
+
+ return 0; // Success
+ }
+
+ return 1; // Failure
+}
+
+
+
+int IcqLoadIcon(WPARAM wParam, LPARAM lParam)
+{
+ UINT id;
+
+
+ switch (wParam & 0xFFFF)
+ {
+ case PLI_PROTOCOL:
+ id = IDI_ICQ;
+ break;
+
+ default:
+ return 0; // Failure
+ }
+
+ return (int)LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON, GetSystemMetrics(wParam&PLIF_SMALL?SM_CXSMICON:SM_CXICON), GetSystemMetrics(wParam&PLIF_SMALL?SM_CYSMICON:SM_CYICON), 0);
+}
+
+
+
+int IcqIdleChanged(WPARAM wParam, LPARAM lParam)
+{
+ int bIdle = (lParam&IDF_ISIDLE);
+ int bPrivacy = (lParam&IDF_PRIVACY);
+
+ if (bPrivacy) return 0;
+
+ ICQWriteContactSettingDword(NULL, "IdleTS", bIdle ? time(0) : 0);
+
+ if (gbTempVisListEnabled) // remove temporary visible users
+ clearTemporaryVisibleList();
+
+ icq_setidle(bIdle ? 1 : 0);
+
+ return 0;
+}
+
+
+
+int IcqGetAvatarInfo(WPARAM wParam, LPARAM lParam)
+{
+ PROTO_AVATAR_INFORMATION* pai = (PROTO_AVATAR_INFORMATION*)lParam;
+ DWORD dwUIN;
+ uid_str szUID;
+ DBVARIANT dbv;
+ int dwPaFormat;
+
+ if (!gbAvatarsEnabled) return GAIR_NOAVATAR;
+
+ if (ICQGetContactSetting(pai->hContact, "AvatarHash", &dbv) || dbv.cpbVal != 0x14)
+ return GAIR_NOAVATAR; // we did not found avatar hash or hash invalid - no avatar available
+
+ if (ICQGetContactSettingUID(pai->hContact, &dwUIN, &szUID))
+ {
+ ICQFreeVariant(&dbv);
+
+ return GAIR_NOAVATAR; // we do not support avatars for invalid contacts
+ }
+
+ dwPaFormat = ICQGetContactSettingByte(pai->hContact, "AvatarType", PA_FORMAT_UNKNOWN);
+ if (dwPaFormat != PA_FORMAT_UNKNOWN)
+ { // we know the format, test file
+ GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, pai->filename, MAX_PATH);
+
+ pai->format = dwPaFormat;
+
+ if (!IsAvatarSaved(pai->hContact, dbv.pbVal))
+ { // hashes are the same
+ if (access(pai->filename, 0) == 0)
+ {
+ ICQFreeVariant(&dbv);
+
+ return GAIR_SUCCESS; // we have found the avatar file, whoala
+ }
+ }
+ }
+
+ if (IsAvatarSaved(pai->hContact, dbv.pbVal))
+ { // we didn't received the avatar before - this ensures we will not request avatar again and again
+ if ((wParam & GAIF_FORCE) != 0 && pai->hContact != 0)
+ { // request avatar data
+ GetAvatarFileName(dwUIN, szUID, pai->filename, MAX_PATH);
+ GetAvatarData(pai->hContact, dwUIN, szUID, dbv.pbVal, dbv.cpbVal, pai->filename);
+ ICQFreeVariant(&dbv);
+
+ return GAIR_WAITFOR;
+ }
+ }
+ ICQFreeVariant(&dbv);
+
+ return GAIR_NOAVATAR;
+}
+
+
+
+int IcqGetMaxAvatarSize(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam) *((int*)wParam) = 64;
+ if (lParam) *((int*)lParam) = 64;
+
+ return 0;
+}
+
+
+
+int IcqAvatarFormatSupported(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam == PA_FORMAT_JPEG || lParam == PA_FORMAT_GIF)
+ return -2;
+ else
+ return 0;
+}
+
+
+
+int IcqGetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+ char* file;
+
+ if (!gbAvatarsEnabled) return -2;
+
+ if (!wParam) return -3;
+
+ file = loadMyAvatarFileName();
+ if (file) strncpy((char*)wParam, file, (int)lParam);
+ SAFE_FREE(&file);
+ if (!access((char*)wParam, 0)) return 0;
+ return -1;
+}
+
+
+
+int IcqSetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+ char* szFile = (char*)lParam;
+ int iRet = -1;
+
+ if (!gbAvatarsEnabled || !gbSsiEnabled) return -2;
+
+ if (szFile)
+ { // set file for avatar
+ char szMyFile[MAX_PATH+1];
+ int dwPaFormat = DetectAvatarFormat(szFile);
+ char* hash;
+ HBITMAP avt;
+
+ if (dwPaFormat != PA_FORMAT_XML)
+ { // if it should be image, check if it is valid
+ avt = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szFile);
+ if (!avt) return iRet;
+ DeleteObject(avt);
+ }
+ GetFullAvatarFileName(0, NULL, dwPaFormat, szMyFile, MAX_PATH);
+ if (!CopyFile(szFile, szMyFile, FALSE))
+ {
+ NetLog_Server("Failed to copy our avatar to local storage.");
+ return iRet;
+ }
+
+ hash = calcMD5Hash(szMyFile);
+ if (hash)
+ {
+ char* ihash = (char*)_alloca(0x14);
+ // upload hash to server
+ ihash[0] = 0; //unknown
+ ihash[1] = dwPaFormat == PA_FORMAT_XML ? 8 : 1; //hash type
+ ihash[2] = 1; //hash status
+ ihash[3] = 0x10; //hash len
+ memcpy(ihash+4, hash, 0x10);
+ updateServAvatarHash(ihash, 0x14);
+
+ if (ICQWriteContactSettingBlob(NULL, "AvatarHash", ihash, 0x14))
+ {
+ NetLog_Server("Failed to save avatar hash.");
+ }
+
+ storeMyAvatarFileName(szMyFile);
+ iRet = 0;
+
+ SAFE_FREE(&hash);
+ }
+ }
+ else
+ { // delete user avatar
+ BYTE bEmptyAvatar[9] = {0x00, 0x01, 0x00,0x05,0x02,0x01,0xD2,0x04,0x72};
+
+ ICQDeleteContactSetting(NULL, "AvatarFile");
+ ICQDeleteContactSetting(NULL, "AvatarHash");
+ updateServAvatarHash(bEmptyAvatar, 9); // clear hash on server
+ iRet = 0;
+ }
+
+ return iRet;
+}
+
+
+
+void updateAimAwayMsg()
+{
+ char** szMsg = MirandaStatusToAwayMsg(gnCurrentStatus);
+
+ EnterCriticalSection(&modeMsgsMutex);
+ if (szMsg)
+ icq_sendSetAimAwayMsgServ(*szMsg);
+ LeaveCriticalSection(&modeMsgsMutex);
+}
+
+
+
+int IcqSetStatus(WPARAM wParam, LPARAM lParam)
+{
+ int nNewStatus = MirandaStatusToSupported(wParam);
+
+ // check if netlib handles are ready
+ if (!ghServerNetlibUser)
+ return 0;
+
+ if (gbTempVisListEnabled) // remove temporary visible users
+ clearTemporaryVisibleList();
+
+ if (nNewStatus != gnCurrentStatus)
+ {
+ if (ICQGetContactSettingByte(NULL, "XStatusReset", DEFAULT_XSTATUS_RESET))
+ { // clear custom status on status change
+ IcqSetXStatus(0, 0);
+ }
+
+ // New status is OFFLINE
+ if (nNewStatus == ID_STATUS_OFFLINE)
+ {
+ // for quick logoff
+ icqGoingOnlineStatus = nNewStatus;
+
+ // Send disconnect packet
+ icq_sendCloseConnection();
+
+ icq_serverDisconnect(FALSE);
+
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+
+ NetLog_Server("Logged off.");
+ }
+ else
+ {
+ switch (gnCurrentStatus)
+ {
+
+ // We are offline and need to connect
+ case ID_STATUS_OFFLINE:
+ {
+ char *pszPwd;
+
+ // Update user connection settings
+ UpdateGlobalSettings();
+
+ // Read UIN from database
+ dwLocalUIN = ICQGetContactSettingUIN(NULL);
+ if (dwLocalUIN == 0)
+ {
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+
+ icq_LogMessage(LOG_FATAL, "You have not entered a ICQ number.\nConfigure this in Options->Network->ICQ and try again.");
+ return 0;
+ }
+
+ // Set status to 'Connecting'
+ icqGoingOnlineStatus = nNewStatus;
+ SetCurrentStatus(ID_STATUS_CONNECTING);
+
+ // Read password from database
+ pszPwd = GetUserPassword(FALSE);
+
+ if (pszPwd)
+ icq_login(pszPwd);
+ else
+ RequestPassword();
+
+ break;
+ }
+
+ // We are connecting... We only need to change the going online status
+ case ID_STATUS_CONNECTING:
+ {
+ icqGoingOnlineStatus = nNewStatus;
+ break;
+ }
+
+ // We are already connected so we should just change status
+ default:
+ {
+
+ SetCurrentStatus(nNewStatus);
+
+ if (gnCurrentStatus == ID_STATUS_INVISIBLE)
+ {
+ if (gbSsiEnabled)
+ updateServVisibilityCode(3);
+ icq_setstatus(MirandaStatusToIcq(gnCurrentStatus));
+ // Tell whos on our visible list
+ icq_sendEntireVisInvisList(0);
+ if (gbAimEnabled)
+ updateAimAwayMsg();
+ }
+ else
+ {
+ icq_setstatus(MirandaStatusToIcq(gnCurrentStatus));
+ if (gbSsiEnabled)
+ updateServVisibilityCode(4);
+ // Tell whos on our invisible list
+
+ icq_sendEntireVisInvisList(1);
+ if (gbAimEnabled)
+ updateAimAwayMsg();
+ }
+ }
+
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+int IcqGetStatus(WPARAM wParam, LPARAM lParam)
+{
+ return gnCurrentStatus;
+}
+
+
+
+int IcqSetAwayMsg(WPARAM wParam, LPARAM lParam)
+{
+ char** ppszMsg = NULL;
+ char* szNewUtf = NULL;
+
+
+ EnterCriticalSection(&modeMsgsMutex);
+
+ ppszMsg = MirandaStatusToAwayMsg(wParam);
+ if (!ppszMsg)
+ {
+ LeaveCriticalSection(&modeMsgsMutex);
+ return 1; // Failure
+ }
+
+ // Prepare UTF-8 status message
+ szNewUtf = ansi_to_utf8((char*)lParam);
+
+ if (strcmpnull(szNewUtf, *ppszMsg))
+ {
+ // Free old message
+ SAFE_FREE(ppszMsg);
+
+ // Set new message
+ *ppszMsg = szNewUtf;
+ szNewUtf = NULL;
+
+ if (gbAimEnabled && (gnCurrentStatus == (int)wParam))
+ icq_sendSetAimAwayMsgServ(*ppszMsg);
+ }
+ SAFE_FREE(&szNewUtf);
+
+ LeaveCriticalSection(&modeMsgsMutex);
+
+ return 0; // Success
+}
+
+
+
+static HANDLE HContactFromAuthEvent(WPARAM hEvent)
+{
+ DBEVENTINFO dbei;
+ DWORD body[2];
+
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = sizeof(DWORD)*2;
+ dbei.pBlob = (PBYTE)&body;
+
+ if (CallService(MS_DB_EVENT_GET, hEvent, (LPARAM)&dbei))
+ return INVALID_HANDLE_VALUE;
+
+ if (dbei.eventType != EVENTTYPE_AUTHREQUEST)
+ return INVALID_HANDLE_VALUE;
+
+ if (strcmpnull(dbei.szModule, gpszICQProtoName))
+ return INVALID_HANDLE_VALUE;
+
+ return (HANDLE)body[1]; // this is bad - needs new auth system
+}
+
+
+
+int IcqAuthAllow(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline && wParam)
+ {
+ DWORD uin;
+ uid_str uid;
+ HANDLE hContact;
+
+ hContact = HContactFromAuthEvent(wParam);
+ if (hContact == INVALID_HANDLE_VALUE)
+ return 1;
+
+ if (ICQGetContactSettingUID(hContact, &uin, &uid))
+ return 1;
+
+ icq_sendAuthResponseServ(uin, uid, 1, "");
+
+ return 0; // Success
+ }
+
+ return 1; // Failure
+}
+
+
+
+int IcqAuthDeny(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline && wParam)
+ {
+ DWORD uin;
+ uid_str uid;
+ HANDLE hContact;
+
+
+ hContact = HContactFromAuthEvent(wParam);
+ if (hContact == INVALID_HANDLE_VALUE)
+ return 1;
+
+ if (ICQGetContactSettingUID(hContact, &uin, &uid))
+ return 1;
+
+ icq_sendAuthResponseServ(uin, uid, 0, (char *)lParam);
+
+ return 0; // Success
+ }
+
+ return 1; // Failure
+}
+
+
+
+static int cheekySearchId = -1;
+static DWORD cheekySearchUin;
+static char* cheekySearchUid;
+static VOID CALLBACK CheekySearchTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
+{
+ ICQSEARCHRESULT isr = {0};
+
+ KillTimer(hwnd, idEvent);
+
+ isr.hdr.cbSize = sizeof(isr);
+ if (cheekySearchUin)
+ {
+ isr.hdr.nick = "";
+ isr.uid = NULL;
+ }
+ else
+ {
+ isr.hdr.nick = cheekySearchUid;
+ isr.uid = cheekySearchUid;
+ }
+ isr.hdr.firstName = "";
+ isr.hdr.lastName = "";
+ isr.hdr.email = "";
+ isr.uin = cheekySearchUin;
+
+ ICQBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)cheekySearchId, (LPARAM)&isr);
+ ICQBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)cheekySearchId, 0);
+
+ cheekySearchId = -1;
+}
+
+
+int IcqBasicSearch(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam)
+ {
+ char* pszSearch = (char*)lParam;
+ DWORD dwUin;
+
+ if (strlennull(pszSearch))
+ {
+ char pszUIN[255];
+ int nHandle = 0;
+ unsigned int i, j;
+
+ if (!gbAimEnabled)
+ {
+ for (i=j=0; (i<strlennull(pszSearch)) && (j<255); i++)
+ { // we take only numbers
+ if ((pszSearch[i]>=0x30) && (pszSearch[i]<=0x39))
+ {
+ pszUIN[j] = pszSearch[i];
+ j++;
+ }
+ }
+ }
+ else
+ {
+ for (i=j=0; (i<strlennull(pszSearch)) && (j<255); i++)
+ { // we remove spaces and slashes
+ if ((pszSearch[i]!=0x20) && (pszSearch[i]!='-'))
+ {
+ pszUIN[j] = pszSearch[i];
+ j++;
+ }
+ }
+ }
+ pszUIN[j] = 0;
+
+ if (strlennull(pszUIN))
+ {
+ if (IsStringUIN(pszUIN))
+ dwUin = atoi(pszUIN);
+ else
+ dwUin = 0;
+
+ // Cheeky instant UIN search
+ if (!dwUin || GetKeyState(VK_CONTROL)&0x8000)
+ {
+ cheekySearchId = GenerateCookie(0);
+ cheekySearchUin = dwUin;
+ cheekySearchUid = null_strdup(pszUIN);
+ SetTimer(NULL, 0, 10, CheekySearchTimerProc); // The caller needs to get this return value before the results
+ nHandle = cheekySearchId;
+ }
+ else if (icqOnline)
+ {
+ nHandle = SearchByUin(dwUin);
+ }
+
+ // Success
+ return nHandle;
+ }
+ }
+ }
+
+ // Failure
+ return 0;
+}
+
+
+int IcqSearchByEmail(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam && icqOnline && (strlennull((char*)lParam) > 0))
+ {
+ DWORD dwSearchId, dwSecId;
+
+ // Success
+ dwSearchId = SearchByEmail((char *)lParam);
+ if (gbAimEnabled)
+ dwSecId = icq_searchAimByEmail((char *)lParam, dwSearchId);
+ else
+ dwSecId = 0;
+ if (dwSearchId)
+ return dwSearchId;
+ else
+ return dwSecId;
+ }
+
+ return 0; // Failure
+}
+
+
+int IcqSearchByDetails(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam && icqOnline)
+ {
+ PROTOSEARCHBYNAME *psbn=(PROTOSEARCHBYNAME*)lParam;
+
+
+ if (psbn->pszNick || psbn->pszFirstName || psbn->pszLastName)
+ {
+ // Success
+ return SearchByNames(psbn->pszNick, psbn->pszFirstName, psbn->pszLastName);
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+int IcqCreateAdvSearchUI(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam && hInst)
+ {
+ // Success
+ return (int)CreateDialogUtf(hInst, MAKEINTRESOURCE(IDD_ICQADVANCEDSEARCH), (HWND)lParam, AdvancedSearchDlgProc);
+ }
+
+ return 0; // Failure
+}
+
+
+int IcqSearchByAdvanced(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline && IsWindow((HWND)lParam))
+ {
+ int nDataLen;
+ BYTE* bySearchData;
+
+ if (bySearchData = createAdvancedSearchStructure((HWND)lParam, &nDataLen))
+ {
+ int result;
+
+ result = icq_sendAdvancedSearchServ(bySearchData, nDataLen);
+ SAFE_FREE(&bySearchData);
+
+ return result; // Success
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+
+// TODO: Adding needs some more work in general
+static HANDLE AddToListByUIN(DWORD dwUin, DWORD dwFlags)
+{
+ HANDLE hContact;
+ int bAdded;
+
+ hContact = HContactFromUIN(dwUin, &bAdded);
+
+ if (hContact)
+ {
+ if ((!dwFlags & PALF_TEMPORARY) && DBGetContactSettingByte(hContact, "CList", "NotOnList", 1))
+ {
+ DBDeleteContactSetting(hContact, "CList", "NotOnList");
+ SetContactHidden(hContact, 0);
+ }
+
+ return hContact; // Success
+ }
+
+ return NULL; // Failure
+}
+
+
+static HANDLE AddToListByUID(char *szUID, DWORD dwFlags)
+{
+ HANDLE hContact;
+ int bAdded;
+
+ hContact = HContactFromUID(0, szUID, &bAdded);
+
+ if (hContact)
+ {
+ if ((!dwFlags & PALF_TEMPORARY) && DBGetContactSettingByte(hContact, "CList", "NotOnList", 1))
+ {
+ DBDeleteContactSetting(hContact, "CList", "NotOnList");
+ SetContactHidden(hContact, 0);
+ }
+
+ return hContact; // Success
+ }
+
+ return NULL; // Failure
+}
+
+
+
+int IcqAddToList(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam)
+ { // this should be only from search
+ ICQSEARCHRESULT *isr = (ICQSEARCHRESULT*)lParam;
+
+ if (isr->hdr.cbSize == sizeof(ICQSEARCHRESULT))
+ {
+ if (!isr->uin)
+ return (int)AddToListByUID(isr->hdr.nick, wParam);
+ else
+ return (int)AddToListByUIN(isr->uin, wParam);
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+
+int IcqAddToListByEvent(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei = {0};
+ DWORD uin = 0;
+ uid_str uid = {0};
+
+
+ dbei.cbSize = sizeof(dbei);
+
+ if ((dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, lParam, 0)) == -1)
+ return 0;
+
+ dbei.pBlob = (PBYTE)_alloca(dbei.cbBlob + 1);
+ dbei.pBlob[dbei.cbBlob] = '\0';
+
+ if (CallService(MS_DB_EVENT_GET, lParam, (LPARAM)&dbei))
+ return 0; // failed to get event
+
+ if (strcmpnull(dbei.szModule, gpszICQProtoName))
+ return 0; // this event is not ours
+
+ if (dbei.eventType == EVENTTYPE_CONTACTS)
+ {
+ int i, ci = HIWORD(wParam);
+ char* pbOffset, *pbEnd;
+
+ for (i = 0, pbOffset = (char*)dbei.pBlob, pbEnd = pbOffset + dbei.cbBlob; i <= ci; i++)
+ {
+ pbOffset += strlennull((char*)pbOffset) + 1; // Nick
+ if (pbOffset >= pbEnd) break;
+ if (i == ci)
+ { // we found the contact, get uid
+ if (IsStringUIN((char*)pbOffset))
+ uin = atoi((char*)pbOffset);
+ else
+ {
+ uin = 0;
+ strcpy(uid, (char*)pbOffset);
+ }
+ }
+ pbOffset += strlennull((char*)pbOffset) + 1; // Uin
+ if (pbOffset >= pbEnd) break;
+ }
+ }
+ else if (dbei.eventType != EVENTTYPE_AUTHREQUEST && dbei.eventType != EVENTTYPE_ADDED)
+ {
+ return 0;
+ }
+ else // auth req or added event
+ {
+ HANDLE hContact = ((HANDLE*)dbei.pBlob)[1]; // this sucks - awaiting new auth system
+
+ if (ICQGetContactSettingUID(hContact, &uin, &uid))
+ return 0;
+ }
+
+ if (uin != 0)
+ {
+ return (int)AddToListByUIN(uin, LOWORD(wParam)); // Success
+ }
+ else if (strlennull(uid))
+ { // add aim contact
+ return (int)AddToListByUID(uid, LOWORD(wParam)); // Success
+ }
+
+ return 0; // Failure
+}
+
+
+
+int IcqSetNickName(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline)
+ {
+ ICQWriteContactSettingString(NULL, "Nick", (char*)lParam);
+
+ return IcqChangeInfoEx(CIXT_BASIC, 0);
+ }
+
+ return 0; // Failure
+}
+
+
+
+int IcqChangeInfoEx(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline && wParam)
+ {
+ PBYTE buf = NULL;
+ int buflen = 0;
+ BYTE b;
+
+ // userinfo
+ ppackTLVWord(&buf, &buflen, (WORD)GetACP(), TLV_CODEPAGE, 0);
+
+ if (wParam & CIXT_CONTACT)
+ { // contact information
+ b = !ICQGetContactSettingByte(NULL, "PublishPrimaryEmail", 0);
+ ppackTLVLNTSBytefromDB(&buf, &buflen, "e-mail", b, TLV_EMAIL);
+ ppackTLVLNTSBytefromDB(&buf, &buflen, "e-mail0", 0, TLV_EMAIL);
+ ppackTLVLNTSBytefromDB(&buf, &buflen, "e-mail1", 0, TLV_EMAIL);
+
+ ppackTLVByte(&buf, &buflen, ICQGetContactSettingByte(NULL, "AllowSpam", 0), TLV_ALLOWSPAM, 1);
+
+ ppackTLVLNTSfromDB(&buf, &buflen, "Phone", TLV_PHONE);
+ ppackTLVLNTSfromDB(&buf, &buflen, "Fax", TLV_FAX);
+ ppackTLVLNTSfromDB(&buf, &buflen, "Cellular", TLV_MOBILE);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyPhone", TLV_WORKPHONE);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyFax", TLV_WORKFAX);
+ }
+
+ if (wParam & CIXT_BASIC)
+ { // upload basic user info
+ ppackTLVLNTSfromDB(&buf, &buflen, "Nick", TLV_NICKNAME);
+ ppackTLVLNTSfromDB(&buf, &buflen, "FirstName", TLV_FIRSTNAME);
+ ppackTLVLNTSfromDB(&buf, &buflen, "LastName", TLV_LASTNAME);
+ ppackTLVLNTSfromDB(&buf, &buflen, "About", TLV_ABOUT);
+ }
+
+ if (wParam & CIXT_MORE)
+ {
+ ppackTLVWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "Age", 0), TLV_AGE, 1);
+ b = ICQGetContactSettingByte(NULL, "Gender", 0);
+ ppackTLVByte(&buf, &buflen, (BYTE)(b ? (b == 'M' ? 2 : 1) : 0), TLV_GENDER, 1);
+ ppackLEWord(&buf, &buflen, TLV_BIRTH);
+ ppackLEWord(&buf, &buflen, 0x06);
+ ppackLEWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "BirthYear", 0));
+ ppackLEWord(&buf, &buflen, (WORD)ICQGetContactSettingByte(NULL, "BirthMonth", 0));
+ ppackLEWord(&buf, &buflen, (WORD)ICQGetContactSettingByte(NULL, "BirthDay", 0));
+
+ ppackTLVWord(&buf, &buflen, (WORD)StringToListItemId("Language1", 0), TLV_LANGUAGE, 1);
+ ppackTLVWord(&buf, &buflen, (WORD)StringToListItemId("Language2", 0), TLV_LANGUAGE, 1);
+ ppackTLVWord(&buf, &buflen, (WORD)StringToListItemId("Language3", 0), TLV_LANGUAGE, 1);
+
+ ppackTLVByte(&buf, &buflen, ICQGetContactSettingByte(NULL, "MaritalStatus", 0), TLV_MARITAL, 1);
+ }
+
+ if (wParam & CIXT_WORK)
+ {
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyDepartment", TLV_DEPARTMENT);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyPosition", TLV_POSITION);
+ ppackTLVLNTSfromDB(&buf, &buflen, "Company", TLV_COMPANY);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyStreet", TLV_WORKSTREET);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyState", TLV_WORKSTATE);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyCity", TLV_WORKCITY);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyHomepage", TLV_WORKURL);
+ ppackTLVLNTSfromDB(&buf, &buflen, "CompanyZIP", TLV_WORKZIPCODE);
+ ppackTLVWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "CompanyCountry", 0), TLV_WORKCOUNTRY, 1);
+ ppackTLVWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "CompanyOccupation", 0), TLV_OCUPATION, 1);
+ }
+
+ if (wParam & CIXT_LOCATION)
+ {
+ ppackTLVLNTSfromDB(&buf, &buflen, "City", TLV_CITY);
+ ppackTLVLNTSfromDB(&buf, &buflen, "State", TLV_STATE);
+ ppackTLVWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "Country", 0), TLV_COUNTRY, 1);
+ ppackTLVLNTSfromDB(&buf, &buflen, "OriginCity", TLV_ORGCITY);
+ ppackTLVLNTSfromDB(&buf, &buflen, "OriginState", TLV_ORGSTATE);
+ ppackTLVWord(&buf, &buflen, ICQGetContactSettingWord(NULL, "OriginCountry", 0), TLV_ORGCOUNTRY, 1);
+ ppackTLVLNTSfromDB(&buf, &buflen, "Street", TLV_STREET);
+ ppackTLVLNTSfromDB(&buf, &buflen, "ZIP", TLV_ZIPCODE);
+
+ ppackTLVLNTSfromDB(&buf, &buflen, "Homepage", TLV_URL);
+
+ ppackTLVByte(&buf, &buflen, ICQGetContactSettingByte(NULL, "Timezone", 0), TLV_TIMEZONE, 1);
+ }
+
+ if (wParam & CIXT_BACKGROUND)
+ {
+ WORD w;
+
+ w = StringToListItemId("Interest0Cat", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Interest0Text", TLV_INTERESTS);
+ w = StringToListItemId("Interest1Cat", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Interest1Text", TLV_INTERESTS);
+ w = StringToListItemId("Interest2Cat", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Interest2Text", TLV_INTERESTS);
+ w = StringToListItemId("Interest3Cat", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Interest3Text", TLV_INTERESTS);
+
+ w = StringToListItemId("Past0", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Past0Text", TLV_PASTINFO);
+ w = StringToListItemId("Past1", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Past1Text", TLV_PASTINFO);
+ w = StringToListItemId("Past2", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Past2Text", TLV_PASTINFO);
+
+ w = StringToListItemId("Affiliation0", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Affiliation0Text", TLV_AFFILATIONS);
+ w = StringToListItemId("Affiliation1", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Affiliation1Text", TLV_AFFILATIONS);
+ w = StringToListItemId("Affiliation2", 0);
+ ppackTLVWordLNTSfromDB(&buf, &buflen, w, "Affiliation2Text", TLV_AFFILATIONS);
+ }
+
+ return icq_changeUserDetailsServ(META_SET_FULLINFO_REQ, buf, (WORD)buflen);
+ }
+
+ return 0; // Failure
+}
+
+
+
+static int messageRate = 0;
+static DWORD lastMessageTick = 0;
+int IcqGetInfo(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam && icqOnline)
+ { // TODO: add checking for SGIF_ONOPEN, otherwise max one per 10sec
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUid))
+ {
+ return 0; // Invalid contact
+ }
+
+ messageRate -= (GetTickCount() - lastMessageTick)/10;
+ if (messageRate<0) // TODO: this is bad, needs centralising
+ messageRate = 0;
+ lastMessageTick = GetTickCount();
+ messageRate += 67; // max 1.5 msgs/sec when rate is high
+
+ // server kicks if 100 msgs sent instantly, so send max 50 instantly
+ if (messageRate < 67*50)
+ {
+ if (dwUin)
+ icq_sendGetInfoServ(dwUin, (ccs->wParam & SGIF_MINIMAL) != 0);
+ else
+ icq_sendGetAimProfileServ(ccs->hContact, szUid);
+
+ return 0; // Success
+ }
+ }
+
+ return 1; // Failure
+}
+
+
+
+int IcqFileAllow(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ DWORD dwUin;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, NULL))
+ return 0; // Invalid contact
+
+ if (dwUin && icqOnline && ccs->hContact && ccs->lParam && ccs->wParam)
+ {
+ filetransfer* ft = ((filetransfer *)ccs->wParam);
+
+ ft->szSavePath = null_strdup((char *)ccs->lParam);
+ AddExpectedFileRecv(ft);
+
+ // Was request received thru DC and have we a open DC, send through that
+ if (ft->bDC && IsDirectConnectionOpen(ccs->hContact, DIRECTCONN_STANDARD))
+ icq_sendFileAcceptDirect(ccs->hContact, ft);
+ else
+ icq_sendFileAcceptServ(dwUin, ft, 0);
+
+ return ccs->wParam; // Success
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+
+int IcqFileDeny(WPARAM wParam, LPARAM lParam)
+{
+ int nReturnValue = 1;
+
+ if (lParam)
+ {
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ filetransfer *ft = (filetransfer*)ccs->wParam;
+ DWORD dwUin;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, NULL))
+ return 1; // Invalid contact
+
+ if (icqOnline && dwUin && ccs->wParam && ccs->hContact)
+ {
+ // Was request received thru DC and have we a open DC, send through that
+ if (ft->bDC && IsDirectConnectionOpen(ccs->hContact, DIRECTCONN_STANDARD))
+ icq_sendFileDenyDirect(ccs->hContact, ft, (char*)ccs->lParam);
+ else
+ icq_sendFileDenyServ(dwUin, ft, (char*)ccs->lParam, 0);
+
+ nReturnValue = 0; // Success
+ }
+ /* FIXME: ft leaks (but can get double freed?) */
+ }
+
+ return nReturnValue;
+}
+
+
+
+int IcqFileCancel(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam /*&& icqOnline*/)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ DWORD dwUin;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, NULL))
+ return 1; // Invalid contact
+
+ if (ccs->hContact && dwUin && ccs->wParam)
+ {
+ filetransfer * ft = (filetransfer * ) ccs->wParam;
+
+ icq_CancelFileTransfer(ccs->hContact, ft);
+
+ return 0; // Success
+ }
+ }
+
+ return 1; // Failure
+}
+
+
+
+int IcqFileResume(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline && wParam)
+ {
+ PROTOFILERESUME *pfr = (PROTOFILERESUME*)lParam;
+
+ icq_sendFileResume((filetransfer *)wParam, pfr->action, pfr->szFilename);
+
+ return 0; // Success
+ }
+
+ return 1; // Failure
+}
+
+
+
+int IcqSendSms(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline && wParam && lParam)
+ return icq_sendSMSServ((const char *)wParam, (const char *)lParam);
+
+ return 0; // Failure
+}
+
+
+
+// Maybe we should be saving these up for batch changing, but I can't be bothered yet
+int IcqSetApparentMode(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ DWORD uin;
+ uid_str uid;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &uin, &uid))
+ return 1; // Invalid contact
+
+ if (ccs->hContact)
+ {
+ // Only 3 modes are supported
+ if (ccs->wParam == 0 || ccs->wParam == ID_STATUS_ONLINE || ccs->wParam == ID_STATUS_OFFLINE)
+ {
+ int oldMode = ICQGetContactSettingWord(ccs->hContact, "ApparentMode", 0);
+
+ // Don't send redundant updates
+ if ((int)ccs->wParam != oldMode)
+ {
+ ICQWriteContactSettingWord(ccs->hContact, "ApparentMode", (WORD)ccs->wParam);
+
+ // Not being online is only an error when in SS mode. This is not handled
+ // yet so we just ignore this for now.
+ if (icqOnline)
+ {
+ if (oldMode != 0) // Remove from old list
+ icq_sendChangeVisInvis(ccs->hContact, uin, uid, oldMode==ID_STATUS_OFFLINE, 0);
+ if (ccs->wParam != 0) // Add to new list
+ icq_sendChangeVisInvis(ccs->hContact, uin, uid, ccs->wParam==ID_STATUS_OFFLINE, 1);
+ if (oldMode==ID_STATUS_OFFLINE)
+ sendVisContactServ(uin, 1);
+ else
+ if (ccs->wParam==ID_STATUS_OFFLINE)
+ sendVisContactServ(uin, 0);
+ }
+
+ return 0; // Success
+ }
+ }
+ }
+ }
+
+ return 1; // Failure
+}
+
+
+
+int IcqGetAwayMsg(WPARAM wParam,LPARAM lParam)
+{
+ if (lParam && icqOnline)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ DWORD dwUin;
+ uid_str szUID;
+ WORD wStatus;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUID))
+ return 0; // Invalid contact
+
+ wStatus = ICQGetContactStatus(ccs->hContact);
+
+ if (dwUin)
+ {
+ int wMessageType = 0;
+
+ switch(wStatus)
+ {
+
+ case ID_STATUS_AWAY:
+ wMessageType = MTYPE_AUTOAWAY;
+ break;
+
+ case ID_STATUS_NA:
+ wMessageType = MTYPE_AUTONA;
+ break;
+
+ case ID_STATUS_OCCUPIED:
+ wMessageType = MTYPE_AUTOBUSY;
+ break;
+
+ case ID_STATUS_DND:
+ wMessageType = MTYPE_AUTODND;
+ break;
+
+ case ID_STATUS_FREECHAT:
+ wMessageType = MTYPE_AUTOFFC;
+ break;
+
+ default:
+ break;
+ }
+
+ if (wMessageType)
+ {
+ if (gbDCMsgEnabled && IsDirectConnectionOpen(ccs->hContact, DIRECTCONN_STANDARD))
+ {
+ int iRes = icq_sendGetAwayMsgDirect(ccs->hContact, wMessageType);
+ if (iRes) return iRes; // we succeded, return
+ }
+ return icq_sendGetAwayMsgServ(dwUin, wMessageType,
+ (WORD)(ICQGetContactSettingWord(ccs->hContact, "Version", 0)==9?9:ICQ_VERSION)); // Success
+ }
+ }
+ else
+ {
+ if (wStatus == ID_STATUS_AWAY)
+ {
+ return icq_sendGetAimAwayMsgServ(szUID, MTYPE_AUTOAWAY);
+ }
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+
+static message_cookie_data* CreateMsgCookieData(BYTE bMsgType, HANDLE hContact, DWORD dwUin)
+{
+ BYTE bAckType;
+ WORD wStatus = ICQGetContactStatus(hContact);
+
+ if (!ICQGetContactSettingByte(NULL, "SlowSend", DEFAULT_SLOWSEND))
+ bAckType = ACKTYPE_NONE;
+ else if ((!dwUin) || (!CheckContactCapabilities(hContact, CAPF_SRV_RELAY)) ||
+ (wStatus == ID_STATUS_OFFLINE) || ICQGetContactSettingByte(NULL, "OnlyServerAcks", DEFAULT_ONLYSERVERACKS))
+ bAckType = ACKTYPE_SERVER;
+ else
+ bAckType = ACKTYPE_CLIENT;
+
+ return CreateMessageCookie(bMsgType, bAckType);
+}
+
+
+
+int IcqSendMessage(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+
+ if (ccs->hContact && ccs->lParam)
+ {
+ WORD wRecipientStatus;
+ DWORD dwCookie;
+ DWORD dwUin;
+ uid_str szUID;
+ char* pszText;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUID))
+ { // Invalid contact
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_MESSAGE, ICQTranslate("The receiver has an invalid user ID."));
+ return dwCookie;
+ }
+
+ if (dwUin && gbTempVisListEnabled && gnCurrentStatus == ID_STATUS_INVISIBLE)
+ makeContactTemporaryVisible(ccs->hContact); // make us temporarily visible to contact
+
+ pszText = (char*)ccs->lParam;
+
+ wRecipientStatus = ICQGetContactStatus(ccs->hContact);
+
+ // Failure scenarios
+ if (!icqOnline)
+ {
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_MESSAGE, ICQTranslate("You cannot send messages when you are offline."));
+ }
+ else if ((wRecipientStatus == ID_STATUS_OFFLINE) && (strlennull(pszText) > 450))
+ {
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_MESSAGE, ICQTranslate("Messages to offline contacts must be shorter than 450 characters."));
+ }
+ // Looks OK
+ else
+ {
+ message_cookie_data* pCookieData;
+
+ if (wRecipientStatus != ID_STATUS_OFFLINE && gbUtfEnabled==2 && !IsUSASCII(pszText, strlennull(pszText))
+ && CheckContactCapabilities(ccs->hContact, CAPF_UTF) && ICQGetContactSettingByte(ccs->hContact, "UnicodeSend", 1))
+ { // text contains national chars and we should send all this as Unicode, so do it
+ char* pszUtf = NULL;
+ int nStrSize = MultiByteToWideChar(CP_ACP, 0, pszText, strlennull(pszText), (wchar_t*)pszUtf, 0);
+ int nRes;
+
+ pszUtf = (char*)SAFE_MALLOC((nStrSize + 2)*sizeof(wchar_t));
+ // we omit ansi string - not used...
+ MultiByteToWideChar(CP_ACP, 0, pszText, strlennull(pszText), (wchar_t*)(pszUtf+1), nStrSize);
+ *(WORD*)(pszUtf + 1 + nStrSize*sizeof(wchar_t)) = '\0'; // trailing zeros
+
+ ccs->lParam = (LPARAM)pszUtf; // yeah, this is quite a hack, BE AWARE OF THAT !!!
+ ccs->wParam |= PREF_UNICODE;
+
+ nRes = IcqSendMessageW(wParam, lParam);
+ ccs->lParam = (LPARAM)pszText;
+
+ SAFE_FREE(&pszUtf); // release memory
+
+ return nRes;
+ }
+
+ if (!dwUin)
+ { // prepare AIM Html message
+ char *mng = MangleXml(pszText, strlennull(pszText));
+ char *tmp = (char*)SAFE_MALLOC(strlennull(mng) + 28);
+
+ strcpy(tmp, "<HTML><BODY>");
+ strcat(tmp, mng);
+ SAFE_FREE(&mng);
+ strcat(tmp, "</BODY></HTML>");
+ pszText = tmp;
+ }
+
+ // Set up the ack type
+ pCookieData = CreateMsgCookieData(MTYPE_PLAIN, ccs->hContact, dwUin);
+
+#ifdef _DEBUG
+ NetLog_Server("Send message - Message cap is %u", CheckContactCapabilities(ccs->hContact, CAPF_SRV_RELAY));
+ NetLog_Server("Send message - Contact status is %u", wRecipientStatus);
+#endif
+ if (dwUin && gbDCMsgEnabled && IsDirectConnectionOpen(ccs->hContact, DIRECTCONN_STANDARD))
+ {
+ int iRes = icq_SendDirectMessage(dwUin, ccs->hContact, pszText, strlennull(pszText), 1, pCookieData, NULL);
+ if (iRes) return iRes; // we succeded, return
+ }
+
+ if ((!dwUin || !CheckContactCapabilities(ccs->hContact, CAPF_SRV_RELAY)) || (wRecipientStatus == ID_STATUS_OFFLINE))
+ {
+ dwCookie = icq_SendChannel1Message(dwUin, szUID, ccs->hContact, pszText, pCookieData);
+ }
+ else
+ {
+ WORD wPriority;
+
+ if (wRecipientStatus == ID_STATUS_ONLINE || wRecipientStatus == ID_STATUS_FREECHAT)
+ wPriority = 0x0001;
+ else
+ wPriority = 0x0021;
+
+ dwCookie = icq_SendChannel2Message(dwUin, pszText, strlennull(pszText), wPriority, pCookieData, NULL);
+ }
+
+ // This will stop the message dialog from waiting for the real message delivery ack
+ if (pCookieData->nAckType == ACKTYPE_NONE)
+ {
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_SUCCESS, ACKTYPE_MESSAGE, NULL);
+ // We need to free this here since we will never see the real ack
+ // The actual cookie value will still have to be returned to the message dialog though
+ ReleaseCookie(dwCookie);
+ }
+ if (!dwUin) SAFE_FREE(&pszText);
+ }
+
+ return dwCookie; // Success
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+
+static char* convertMsgToUserSpecificAnsi(HANDLE hContact, const char* szMsg)
+{ // this needs valid "Unicode" buffer from SRMM !!!
+ WORD wCP = ICQGetContactSettingWord(hContact, "CodePage", gwAnsiCodepage);
+ int nMsgLen = strlennull(szMsg);
+ wchar_t* usMsg = (wchar_t*)(szMsg + nMsgLen + 1);
+ char* szAnsi = NULL;
+
+ if (wCP != CP_ACP)
+ {
+ int nStrSize = WideCharToMultiByte(wCP, 0, usMsg, nMsgLen, szAnsi, 0, NULL, NULL);
+
+ szAnsi = (char*)SAFE_MALLOC(nStrSize + 1);
+ WideCharToMultiByte(wCP, 0, usMsg, nMsgLen, szAnsi, nStrSize, NULL, NULL);
+ szAnsi[nStrSize] = '\0';
+ }
+ return szAnsi;
+}
+
+
+
+int IcqSendMessageW(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+
+ if (ccs->hContact && ccs->lParam)
+ {
+ WORD wRecipientStatus;
+ DWORD dwCookie;
+ DWORD dwUin;
+ uid_str szUID;
+ wchar_t* pszText;
+ // TODO: this was not working, removed check
+ if (!gbUtfEnabled || /*(ccs->wParam & PREF_UNICODE == PREF_UNICODE) ||*/
+ (!CheckContactCapabilities(ccs->hContact, CAPF_UTF)) || (!ICQGetContactSettingByte(ccs->hContact, "UnicodeSend", 1)))
+ { // send as unicode only if marked as unicode & unicode enabled
+ char* szAnsi = convertMsgToUserSpecificAnsi(ccs->hContact, (char*)ccs->lParam);
+ int nRes;
+
+ if (szAnsi) ccs->lParam = (LPARAM)szAnsi;
+ nRes = IcqSendMessage(wParam, lParam);
+ SAFE_FREE(&szAnsi);
+
+ return nRes;
+ }
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUID))
+ { // Invalid contact
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_MESSAGE, ICQTranslate("The receiver has an invalid user ID."));
+ return dwCookie;
+ }
+
+ if (dwUin && gbTempVisListEnabled && gnCurrentStatus == ID_STATUS_INVISIBLE)
+ makeContactTemporaryVisible(ccs->hContact); // make us temporarily visible to contact
+
+ pszText = (wchar_t*)((char*)ccs->lParam+strlennull((char*)ccs->lParam)+1); // get the UTF-16 part
+
+ wRecipientStatus = ICQGetContactStatus(ccs->hContact);
+
+ // Failure scenarios
+ if (!icqOnline)
+ {
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_MESSAGE, ICQTranslate("You cannot send messages when you are offline."));
+ }
+ // Looks OK
+ else
+ {
+ message_cookie_data* pCookieData;
+ BOOL plain_ascii = IsUnicodeAscii(pszText, wcslen(pszText));
+
+ if ((wRecipientStatus == ID_STATUS_OFFLINE) || plain_ascii)
+ { // send as plain if no special char or user offline
+ char* szAnsi;
+ int nRes;
+
+ if (!plain_ascii)
+ {
+ szAnsi = convertMsgToUserSpecificAnsi(ccs->hContact, (char*)ccs->lParam);
+ if (szAnsi) ccs->lParam = (LPARAM)szAnsi;
+ }
+ nRes = IcqSendMessage(wParam, lParam);
+ if (!plain_ascii)
+ SAFE_FREE(&szAnsi);
+
+ return nRes;
+ };
+
+ // Set up the ack type
+ pCookieData = CreateMsgCookieData(MTYPE_PLAIN, ccs->hContact, dwUin);
+
+#ifdef _DEBUG
+ NetLog_Server("Send unicode message - Message cap is %u", CheckContactCapabilities(ccs->hContact, CAPF_SRV_RELAY));
+ NetLog_Server("Send unicode message - Contact status is %u", wRecipientStatus);
+#endif
+ if (dwUin && gbDCMsgEnabled && IsDirectConnectionOpen(ccs->hContact, DIRECTCONN_STANDARD))
+ {
+ char* utf8msg = make_utf8_string(pszText);
+ int iRes;
+
+ iRes = icq_SendDirectMessage(dwUin, ccs->hContact, utf8msg, strlennull(utf8msg), 1, pCookieData, CAP_UTF8MSGS);
+ SAFE_FREE(&utf8msg);
+
+ if (iRes) return iRes; // we succeded, return
+ }
+
+ if (!dwUin || !CheckContactCapabilities(ccs->hContact, CAPF_SRV_RELAY))
+ {
+ char* utmp;
+ char* mng;
+ char* tmp;
+
+ if (!dwUin)
+ {
+ utmp = make_utf8_string(pszText);
+ mng = MangleXml(utmp, strlennull(utmp));
+ SAFE_FREE(&utmp);
+ tmp = (char*)SAFE_MALLOC(strlennull(mng) + 28);
+ strcpy(tmp, "<HTML><BODY>");
+ strcat(tmp, mng);
+ SAFE_FREE(&mng);
+ strcat(tmp, "</BODY></HTML>");
+ pszText = make_unicode_string(tmp);
+ SAFE_FREE(&tmp);
+ }
+
+ dwCookie = icq_SendChannel1MessageW(dwUin, szUID, ccs->hContact, pszText, pCookieData);
+
+ if (!dwUin) SAFE_FREE(&pszText);
+ }
+ else
+ {
+ WORD wPriority;
+ char* utf8msg;
+
+ if (wRecipientStatus == ID_STATUS_ONLINE || wRecipientStatus == ID_STATUS_FREECHAT)
+ wPriority = 0x0001;
+ else
+ wPriority = 0x0021;
+
+ utf8msg = make_utf8_string(pszText);
+ dwCookie = icq_SendChannel2Message(dwUin, utf8msg, strlennull(utf8msg), wPriority, pCookieData, CAP_UTF8MSGS);
+
+ SAFE_FREE(&utf8msg);
+ }
+
+ // This will stop the message dialog from waiting for the real message delivery ack
+ if (pCookieData->nAckType == ACKTYPE_NONE)
+ {
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_SUCCESS, ACKTYPE_MESSAGE, NULL);
+ // We need to free this here since we will never see the real ack
+ // The actual cookie value will still have to be returned to the message dialog though
+ ReleaseCookie(dwCookie);
+ }
+
+ }
+ return dwCookie; // Success
+ }
+ }
+ return 0; // Failure
+}
+
+
+
+int IcqSendUrl(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+
+ if (ccs->hContact && ccs->lParam)
+ {
+ DWORD dwCookie;
+ WORD wRecipientStatus;
+ DWORD dwUin;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, NULL))
+ { // Invalid contact
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_URL, ICQTranslate("The receiver has an invalid user ID."));
+ return dwCookie;
+ }
+
+ wRecipientStatus = ICQGetContactStatus(ccs->hContact);
+
+ // Failure
+ if (!icqOnline)
+ {
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_URL, ICQTranslate("You cannot send messages when you are offline."));
+ }
+ // Looks OK
+ else
+ {
+ message_cookie_data* pCookieData;
+ char* szDesc;
+ char* szUrl;
+ char* szBody;
+ int nBodyLen;
+ int nDescLen;
+ int nUrlLen;
+
+
+ // Set up the ack type
+ pCookieData = CreateMsgCookieData(MTYPE_URL, ccs->hContact, dwUin);
+
+ // Format the body
+ szUrl = (char*)ccs->lParam;
+ nUrlLen = strlennull(szUrl);
+ szDesc = (char *)ccs->lParam + nUrlLen + 1;
+ nDescLen = strlennull(szDesc);
+ nBodyLen = nUrlLen + nDescLen + 2;
+ szBody = (char *)_alloca(nBodyLen);
+ strcpy(szBody, szDesc);
+ szBody[nDescLen] = (char)0xFE; // Separator
+ strcpy(szBody + nDescLen + 1, szUrl);
+
+
+ if (gbDCMsgEnabled && IsDirectConnectionOpen(ccs->hContact, DIRECTCONN_STANDARD))
+ {
+ int iRes = icq_SendDirectMessage(dwUin, ccs->hContact, szBody, nBodyLen, 1, pCookieData, NULL);
+ if (iRes) return iRes; // we succeded, return
+ }
+
+ // Select channel and send
+ if (!CheckContactCapabilities(ccs->hContact, CAPF_SRV_RELAY) ||
+ wRecipientStatus == ID_STATUS_OFFLINE)
+ {
+ dwCookie = icq_SendChannel4Message(dwUin, MTYPE_URL,
+ (WORD)nBodyLen, szBody, pCookieData);
+ }
+ else
+ {
+ WORD wPriority;
+
+ if (wRecipientStatus == ID_STATUS_ONLINE || wRecipientStatus == ID_STATUS_FREECHAT)
+ wPriority = 0x0001;
+ else
+ wPriority = 0x0021;
+
+ dwCookie = icq_SendChannel2Message(dwUin, szBody, nBodyLen, wPriority, pCookieData, NULL);
+ }
+
+ // This will stop the message dialog from waiting for the real message delivery ack
+ if (pCookieData->nAckType == ACKTYPE_NONE)
+ {
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_SUCCESS, ACKTYPE_URL, NULL);
+ // We need to free this here since we will never see the real ack
+ // The actual cookie value will still have to be returned to the message dialog though
+ ReleaseCookie(dwCookie);
+ }
+ }
+
+ return dwCookie; // Success
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+
+int IcqSendContacts(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+
+ if (ccs->hContact && ccs->lParam)
+ {
+ int nContacts;
+ int i;
+ HANDLE* hContactsList = (HANDLE*)ccs->lParam;
+ DWORD dwUin;
+ WORD wRecipientStatus;
+ DWORD dwCookie;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, NULL))
+ { // Invalid contact
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_CONTACTS, ICQTranslate("The receiver has an invalid user ID."));
+ return dwCookie;
+ }
+
+ wRecipientStatus = ICQGetContactStatus(ccs->hContact);
+ nContacts = HIWORD(ccs->wParam);
+
+ // Failures
+ if (!icqOnline)
+ {
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_CONTACTS, ICQTranslate("You cannot send messages when you are offline."));
+ }
+ else if (!hContactsList || (nContacts < 1) || (nContacts > MAX_CONTACTSSEND))
+ {
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_CONTACTS, ICQTranslate("Bad data (internal error #1)"));
+ }
+ // OK
+ else
+ {
+ int nBodyLength;
+ char szUin[UINMAXLEN];
+ char szCount[17];
+ struct icq_contactsend_s* contacts = NULL;
+ uid_str szUid;
+
+
+ // Format the body
+ // This is kinda messy, but there is no simple way to do it. First
+ // we need to calculate the length of the packet.
+ if (contacts = (struct icq_contactsend_s*)SAFE_MALLOC(sizeof(struct icq_contactsend_s)*nContacts))
+ {
+ nBodyLength = 0;
+ for (i = 0; i < nContacts; i++)
+ {
+ if (!IsICQContact(hContactsList[i]))
+ break; // Abort if a non icq contact is found
+ if (ICQGetContactSettingUID(hContactsList[i], &contacts[i].uin, &szUid))
+ break; // Abort if invalid contact
+ contacts[i].uid = contacts[i].uin?NULL:null_strdup(szUid);
+ contacts[i].szNick = NickFromHandle(hContactsList[i]);
+ // Compute this contact's length
+ nBodyLength += getUIDLen(contacts[i].uin, contacts[i].uid) + 1;
+ nBodyLength += strlennull(contacts[i].szNick) + 1;
+ }
+
+ if (i == nContacts)
+ {
+ message_cookie_data* pCookieData;
+ char* pBody;
+ char* pBuffer;
+
+#ifdef _DEBUG
+ NetLog_Server("Sending contacts to %d.", dwUin);
+#endif
+ // Compute count record's length
+ _itoa(nContacts, szCount, 10);
+ nBodyLength += strlennull(szCount) + 1;
+
+ // Finally we need to copy the contact data into the packet body
+ pBuffer = pBody = (char *)SAFE_MALLOC(nBodyLength);
+ strncpy(pBuffer, szCount, nBodyLength);
+ pBuffer += strlennull(pBuffer);
+ *pBuffer++ = (char)0xFE;
+ for (i = 0; i < nContacts; i++)
+ {
+ if (contacts[i].uin)
+ {
+ _itoa(contacts[i].uin, szUin, 10);
+ strcpy(pBuffer, szUin);
+ }
+ else
+ strcpy(pBuffer, contacts[i].uid);
+ pBuffer += strlennull(pBuffer);
+ *pBuffer++ = (char)0xFE;
+ strcpy(pBuffer, contacts[i].szNick);
+ pBuffer += strlennull(pBuffer);
+ *pBuffer++ = (char)0xFE;
+ }
+
+ // Set up the ack type
+ pCookieData = CreateMsgCookieData(MTYPE_CONTACTS, ccs->hContact, dwUin);
+
+ if (gbDCMsgEnabled && IsDirectConnectionOpen(ccs->hContact, DIRECTCONN_STANDARD))
+ {
+ int iRes = icq_SendDirectMessage(dwUin, ccs->hContact, pBody, nBodyLength, 1, pCookieData, NULL);
+
+ if (iRes)
+ {
+ SAFE_FREE(&pBody);
+
+ for(i = 0; i < nContacts; i++)
+ { // release memory
+ SAFE_FREE(&contacts[i].szNick);
+ SAFE_FREE(&contacts[i].uid);
+ }
+
+ SAFE_FREE(&contacts);
+
+ return iRes; // we succeded, return
+ }
+ }
+
+ // Select channel and send
+ if (!CheckContactCapabilities(ccs->hContact, CAPF_SRV_RELAY) ||
+ wRecipientStatus == ID_STATUS_OFFLINE)
+ {
+ dwCookie = icq_SendChannel4Message(dwUin, MTYPE_CONTACTS,
+ (WORD)nBodyLength, pBody, pCookieData);
+ }
+ else
+ {
+ WORD wPriority;
+
+ if (wRecipientStatus == ID_STATUS_ONLINE || wRecipientStatus == ID_STATUS_FREECHAT)
+ wPriority = 0x0001;
+ else
+ wPriority = 0x0021;
+
+ dwCookie = icq_SendChannel2Message(dwUin, pBody, nBodyLength, wPriority, pCookieData, NULL);
+ }
+
+ // This will stop the message dialog from waiting for the real message delivery ack
+ if (pCookieData->nAckType == ACKTYPE_NONE)
+ {
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_SUCCESS, ACKTYPE_CONTACTS, NULL);
+ // We need to free this here since we will never see the real ack
+ // The actual cookie value will still have to be returned to the message dialog though
+ ReleaseCookie(dwCookie);
+ }
+ SAFE_FREE(&pBody);
+ }
+ else
+ {
+ dwCookie = GenerateCookie(0);
+ icq_SendProtoAck(ccs->hContact, dwCookie, ACKRESULT_FAILED, ACKTYPE_CONTACTS, ICQTranslate("Bad data (internal error #2)"));
+ }
+
+ for(i = 0; i < nContacts; i++)
+ {
+ SAFE_FREE(&contacts[i].szNick);
+ SAFE_FREE(&contacts[i].uid);
+ }
+
+ SAFE_FREE(&contacts);
+ }
+ else
+ {
+ dwCookie = 0;
+ }
+ }
+
+ return dwCookie;
+ }
+ }
+
+ // Exit with Failure
+ return 0;
+}
+
+
+
+int IcqSendFile(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam && icqOnline)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+
+ if (ccs->hContact && ccs->lParam && ccs->wParam)
+ {
+ HANDLE hContact = ccs->hContact;
+ char** files = (char**)ccs->lParam;
+ char* pszDesc = (char*)ccs->wParam;
+ DWORD dwUin;
+
+ if (ICQGetContactSettingUID(hContact, &dwUin, NULL))
+ return 0; // Invalid contact
+
+ if (dwUin)
+ {
+ if (ICQGetContactStatus(hContact) != ID_STATUS_OFFLINE)
+ {
+ WORD wClientVersion;
+
+ wClientVersion = ICQGetContactSettingWord(ccs->hContact, "Version", 7);
+ if (wClientVersion < 7)
+ {
+ NetLog_Server("IcqSendFile() can't send to version %u", wClientVersion);
+ }
+ else
+ {
+ int i;
+ filetransfer* ft;
+ struct _stat statbuf;
+
+ // Initialize filetransfer struct
+ ft = CreateFileTransfer(hContact, dwUin, (wClientVersion == 7) ? 7: 8);
+
+ for (ft->dwFileCount = 0; files[ft->dwFileCount]; ft->dwFileCount++);
+ ft->files = (char **)SAFE_MALLOC(sizeof(char *) * ft->dwFileCount);
+ ft->dwTotalSize = 0;
+ for (i = 0; i < (int)ft->dwFileCount; i++)
+ {
+ ft->files[i] = null_strdup(files[i]);
+
+ if (_stat(files[i], &statbuf))
+ NetLog_Server("IcqSendFile() was passed invalid filename(s)");
+ else
+ ft->dwTotalSize += statbuf.st_size;
+ }
+ ft->szDescription = null_strdup(pszDesc);
+ ft->dwTransferSpeed = 100;
+ ft->sending = 1;
+ ft->fileId = -1;
+ ft->iCurrentFile = 0;
+ ft->dwCookie = AllocateCookie(CKT_FILE, 0, dwUin, ft);
+ ft->hConnection = NULL;
+
+ // Send file transfer request
+ {
+ char szFiles[64];
+ char* pszFiles;
+
+
+ NetLog_Server("Init file send");
+
+ if (ft->dwFileCount == 1)
+ {
+ pszFiles = strrchr(ft->files[0], '\\');
+ if (pszFiles)
+ pszFiles++;
+ else
+ pszFiles = ft->files[0];
+ }
+ else
+ {
+ null_snprintf(szFiles, 64, ICQTranslate("%d Files"), ft->dwFileCount);
+ pszFiles = szFiles;
+ }
+
+ // Send packet
+ {
+ if (ft->nVersion == 7)
+ {
+ if (gbDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD))
+ {
+ int iRes = icq_sendFileSendDirectv7(ft, pszFiles);
+ if (iRes) return (int)(HANDLE)ft; // Success
+ }
+ NetLog_Server("Sending v%u file transfer request through server", 7);
+ icq_sendFileSendServv7(ft, pszFiles);
+ }
+ else
+ {
+ if (gbDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD))
+ {
+ int iRes = icq_sendFileSendDirectv8(ft, pszFiles);
+ if (iRes) return (int)(HANDLE)ft; // Success
+ }
+ NetLog_Server("Sending v%u file transfer request through server", 8);
+ icq_sendFileSendServv8(ft, pszFiles, ACKTYPE_NONE);
+ }
+ }
+ }
+
+ return (int)(HANDLE)ft; // Success
+ }
+ }
+ }
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+int IcqSendAuthRequest(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam && icqOnline)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (ccs->hContact)
+ {
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+ if (dwUin && ccs->lParam)
+ {
+ char *text = (char *)ccs->lParam;
+ char *utf;
+
+ utf = ansi_to_utf8(text); // Miranda is ANSI only here
+
+ icq_sendAuthReqServ(dwUin, szUid, utf);
+
+ SAFE_FREE(&utf);
+
+ return 0; // Success
+ }
+ }
+ }
+
+ return 1; // Failure
+}
+
+
+
+int IcqSendYouWereAdded(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam && icqOnline)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+
+ if (ccs->hContact)
+ {
+ DWORD dwUin, dwMyUin;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, NULL))
+ return 1; // Invalid contact
+
+ dwMyUin = ICQGetContactSettingUIN(NULL);
+
+ if (dwUin)
+ {
+ icq_sendYouWereAddedServ(dwUin, dwMyUin);
+
+ return 0; // Success
+ }
+ }
+ }
+
+ return 1; // Failure
+}
+
+
+
+int IcqGrantAuthorization(WPARAM wParam, LPARAM lParam)
+{
+ if (gnCurrentStatus != ID_STATUS_OFFLINE && gnCurrentStatus != ID_STATUS_CONNECTING && wParam != 0)
+ {
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (ICQGetContactSettingUID((HANDLE)wParam, &dwUin, &szUid))
+ return 0; // Invalid contact
+
+ // send without reason, do we need any ?
+ icq_sendGrantAuthServ(dwUin, szUid, NULL);
+ }
+
+ return 0;
+}
+
+
+
+int IcqRevokeAuthorization(WPARAM wParam, LPARAM lParam)
+{
+ if (gnCurrentStatus != ID_STATUS_OFFLINE && gnCurrentStatus != ID_STATUS_CONNECTING && wParam != 0)
+ {
+ DWORD dwUin;
+ uid_str szUid;
+ char str[MAX_PATH], cap[MAX_PATH];
+
+ if (ICQGetContactSettingUID((HANDLE)wParam, &dwUin, &szUid))
+ return 0; // Invalid contact
+
+ if (MessageBoxUtf(NULL, ICQTranslateUtfStatic("Are you sure you want to revoke user's autorisation (this will remove you from his/her list on some clients) ?", str), ICQTranslateUtfStatic("Confirmation", cap), MB_ICONQUESTION | MB_YESNO) != IDYES)
+ return 0;
+
+ icq_sendRevokeAuthServ(dwUin, szUid);
+ }
+
+ return 0;
+}
+
+
+
+int IcqSendUserIsTyping(WPARAM wParam, LPARAM lParam)
+{
+ int nResult = 1;
+ HANDLE hContact = (HANDLE)wParam;
+
+
+ if (hContact && icqOnline)
+ {
+ if (CheckContactCapabilities(hContact, CAPF_TYPING))
+ {
+ switch (lParam)
+ {
+ case PROTOTYPE_SELFTYPING_ON:
+ sendTypingNotification(hContact, MTN_BEGUN);
+ nResult = 0;
+ break;
+
+ case PROTOTYPE_SELFTYPING_OFF:
+ sendTypingNotification(hContact, MTN_FINISHED);
+ nResult = 0;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ return nResult;
+}
+
+
+
+/*
+ ---------------------------------
+ | Receiving |
+ ---------------------------------
+*/
+
+int IcqRecvAwayMsg(WPARAM wParam,LPARAM lParam)
+{
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam;
+
+
+ ICQBroadcastAck(ccs->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS,
+ (HANDLE)pre->lParam, (LPARAM)pre->szMessage);
+
+ return 0;
+}
+
+
+
+int IcqRecvMessage(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam;
+
+
+ SetContactHidden(ccs->hContact, 0);
+
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = gpszICQProtoName;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0;
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.cbBlob = strlennull(pre->szMessage) + 1;
+ if ( pre->flags & PREF_UNICODE )
+ dbei.cbBlob *= ( sizeof( wchar_t )+1 );
+ dbei.pBlob = (PBYTE)pre->szMessage;
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM)ccs->hContact, (LPARAM)&dbei);
+
+ // stop contact from typing - some clients do not sent stop notify
+ if (CheckContactCapabilities(ccs->hContact, CAPF_TYPING))
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)ccs->hContact, PROTOTYPE_CONTACTTYPING_OFF);
+
+ return 0;
+}
+
+
+
+int IcqRecvUrl(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam;
+ char* szDesc;
+
+
+ SetContactHidden(ccs->hContact, 0);
+
+ szDesc = pre->szMessage + strlennull(pre->szMessage) + 1;
+
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = gpszICQProtoName;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0;
+ dbei.eventType = EVENTTYPE_URL;
+ dbei.cbBlob = strlennull(pre->szMessage) + strlennull(szDesc) + 2;
+ dbei.pBlob = (PBYTE)pre->szMessage;
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM)ccs->hContact, (LPARAM)&dbei);
+
+ return 0;
+}
+
+
+
+int IcqRecvContacts(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei = {0};
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam;
+ ICQSEARCHRESULT** isrList = (ICQSEARCHRESULT**)pre->szMessage;
+ int i;
+ char szUin[UINMAXLEN];
+ PBYTE pBlob;
+
+
+ SetContactHidden(ccs->hContact, 0);
+
+ for (i = 0; i < pre->lParam; i++)
+ {
+ dbei.cbBlob += strlennull(isrList[i]->hdr.nick) + 2; // both trailing zeros
+ if (isrList[i]->uin)
+ dbei.cbBlob += getUINLen(isrList[i]->uin);
+ else
+ dbei.cbBlob += strlennull(isrList[i]->uid);
+ }
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = gpszICQProtoName;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0;
+ dbei.eventType = EVENTTYPE_CONTACTS;
+ dbei.pBlob = (PBYTE)_alloca(dbei.cbBlob);
+ for (i = 0, pBlob = dbei.pBlob; i < pre->lParam; i++)
+ {
+ strcpy(pBlob, isrList[i]->hdr.nick);
+ pBlob += strlennull(pBlob) + 1;
+ if (isrList[i]->uin)
+ {
+ _itoa(isrList[i]->uin, szUin, 10);
+ strcpy(pBlob, szUin);
+ }
+ else // aim contact
+ strcpy(pBlob, isrList[i]->uid);
+ pBlob += strlennull(pBlob) + 1;
+ }
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM)ccs->hContact, (LPARAM)&dbei);
+
+ return 0;
+}
+
+
+
+int IcqRecvFile(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam;
+ char* szDesc;
+ char* szFile;
+
+
+ SetContactHidden(ccs->hContact, 0);
+
+ szFile = pre->szMessage + sizeof(DWORD);
+ szDesc = szFile + strlennull(szFile) + 1;
+
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = gpszICQProtoName;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0;
+ dbei.eventType = EVENTTYPE_FILE;
+ dbei.cbBlob = sizeof(DWORD) + strlennull(szFile) + strlennull(szDesc) + 2;
+ dbei.pBlob = (PBYTE)pre->szMessage;
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM)ccs->hContact, (LPARAM)&dbei);
+
+ return 0;
+}
+
+
+
+int IcqRecvAuth(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam;
+
+
+ SetContactHidden(ccs->hContact, 0);
+
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = gpszICQProtoName;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags=(pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0;
+ dbei.eventType = EVENTTYPE_AUTHREQUEST;
+ dbei.cbBlob = pre->lParam;
+ dbei.pBlob = (PBYTE)pre->szMessage;
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM)NULL, (LPARAM)&dbei);
+
+ return 0;
+}
diff --git a/icqj_mod/icqosc_svcs.h b/icqj_mod/icqosc_svcs.h new file mode 100644 index 0000000..5a04ebc --- /dev/null +++ b/icqj_mod/icqosc_svcs.h @@ -0,0 +1,96 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icqosc_svcs.h,v $
+// Revision : $Revision: 2991 $
+// Last change on : $Date: 2006-05-30 19:55:48 +0200 (Tue, 30 May 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQOSC_SVCS_H
+#define __ICQOSC_SVCS_H
+
+/*---------* Functions *---------------*/
+
+int IcqGetCaps(WPARAM wParam, LPARAM lParam);
+int IcqGetName(WPARAM wParam, LPARAM lParam);
+int IcqLoadIcon(WPARAM wParam, LPARAM lParam);
+int IcqSetStatus(WPARAM wParam, LPARAM lParam);
+int IcqGetStatus(WPARAM wParam, LPARAM lParam);
+int IcqSetAwayMsg(WPARAM wParam, LPARAM lParam);
+int IcqGetAwayMsg(WPARAM wParam, LPARAM lParam);
+int IcqRecvAwayMsg(WPARAM wParam,LPARAM lParam);
+int IcqAuthAllow(WPARAM wParam, LPARAM lParam);
+int IcqAuthDeny(WPARAM wParam, LPARAM lParam);
+int IcqBasicSearch(WPARAM wParam, LPARAM lParam);
+int IcqSearchByEmail(WPARAM wParam, LPARAM lParam);
+int IcqSearchByDetails(WPARAM wParam, LPARAM lParam);
+int IcqCreateAdvSearchUI(WPARAM wParam, LPARAM lParam);
+int IcqSearchByAdvanced(WPARAM wParam, LPARAM lParam);
+int IcqAddToList(WPARAM wParam, LPARAM lParam);
+int IcqAddToListByEvent(WPARAM wParam, LPARAM lParam);
+int IcqSetNickName(WPARAM wParam, LPARAM lParam);
+int IcqChangeInfo(WPARAM wParam, LPARAM lParam);
+int _IcqChangeInfo(WPARAM wParam, LPARAM lParam);
+int IcqChangeInfoEx(WPARAM wParam, LPARAM lParam);
+int IcqGetInfo(WPARAM wParam, LPARAM lParam);
+int IcqSendSms(WPARAM wParam, LPARAM lParam);
+int IcqSetApparentMode(WPARAM wParam, LPARAM lParam);
+int IcqSendMessage(WPARAM wParam, LPARAM lParam);
+int IcqSendMessageW(WPARAM wParam, LPARAM lParam);
+int IcqSendUrl(WPARAM wParam, LPARAM lParam);
+int IcqSendContacts(WPARAM wParam, LPARAM lParam);
+int IcqSendFile(WPARAM wParam, LPARAM lParam);
+int IcqFileAllow(WPARAM wParam, LPARAM lParam);
+int IcqFileDeny(WPARAM wParam, LPARAM lParam);
+int IcqFileCancel(WPARAM wParam, LPARAM lParam);
+int IcqFileResume(WPARAM wParam, LPARAM lParam);
+int IcqGrantAuthorization(WPARAM wParam, LPARAM lParam);
+int IcqRevokeAuthorization(WPARAM wParam, LPARAM lParam);
+int IcqSendAuthRequest(WPARAM,LPARAM);
+int IcqSendYouWereAdded(WPARAM,LPARAM);
+int IcqSendUserIsTyping(WPARAM wParam, LPARAM lParam);
+
+int IcqRecvMessage(WPARAM wParam, LPARAM lParam);
+int IcqRecvUrl(WPARAM wParam, LPARAM lParam);
+int IcqRecvContacts(WPARAM wParam, LPARAM lParam);
+int IcqRecvFile(WPARAM wParam, LPARAM lParam);
+int IcqRecvAuth(WPARAM wParam, LPARAM lParam);
+
+int IcqIdleChanged(WPARAM wParam, LPARAM lParam);
+
+int IcqGetAvatarInfo(WPARAM wParam, LPARAM lParam);
+int IcqGetMaxAvatarSize(WPARAM wParam, LPARAM lParam);
+int IcqAvatarFormatSupported(WPARAM wParam, LPARAM lParam);
+int IcqGetMyAvatar(WPARAM wParam, LPARAM lParam);
+int IcqSetMyAvatar(WPARAM wParam, LPARAM lParam);
+
+
+#endif /* __ICQOSC_SVCS_H */
diff --git a/icqj_mod/icqoscar.c b/icqj_mod/icqoscar.c new file mode 100644 index 0000000..7526c72 --- /dev/null +++ b/icqj_mod/icqoscar.c @@ -0,0 +1,42 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icqoscar.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// The only purpose of this file is to make sure that the precompiled headers
+// are included and compiled. The Visual Studio settings for this file must be
+// 'Create precompiled header file' and all the other .c files must be set to
+// 'User precompiled header file'. Remember to check this when adding new
+// files to the project...
+//
+// -----------------------------------------------------------------------------
+
+
+
+#include "icqoscar.h"
diff --git a/icqj_mod/icqoscar.h b/icqj_mod/icqoscar.h new file mode 100644 index 0000000..75d2762 --- /dev/null +++ b/icqj_mod/icqoscar.h @@ -0,0 +1,129 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icqoscar.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Includes all header files that should be precompiled to speed up compilation.
+//
+// -----------------------------------------------------------------------------
+
+#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
+//disable the deperecated warnings for the crt functions.
+#pragma warning(disable: 4996)
+
+// Windows includes
+#include <windows.h>
+#include <commctrl.h>
+
+// Standard includes
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <direct.h>
+#include <fcntl.h>
+#include <crtdbg.h>
+#include <process.h>
+#include <malloc.h>
+
+// Miranda IM SDK includes
+#include <newpluginapi.h> // This must be included first
+#include <m_clc.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_message.h>
+#include <m_netlib.h>
+#include <m_protocols.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_options.h>
+#include <m_system.h>
+#include <m_userinfo.h>
+#include <m_utils.h>
+#include <m_idle.h>
+#include <m_popup.h>
+#include <m_clistint.h>
+#include <m_skin.h>
+
+// Project resources
+#include "resource.h"
+
+// ICQ plugin includes
+#include "isee.h"
+#include "globals.h"
+#include "icq_db.h"
+#include "i18n.h"
+#include "cookies.h"
+#include "capabilities.h"
+#include "icq_packet.h"
+#include "icq_direct.h"
+#include "icq_server.h"
+#include "icqosc_svcs.h"
+#include "icq_xtraz.h"
+#include "icq_opts.h"
+#include "icq_servlist.h"
+#include "icq_http.h"
+#include "icq_fieldnames.h"
+#include "icq_constants.h"
+#include "guids.h"
+#include "icq_infoupdate.h"
+#include "icq_avatar.h"
+#include "init.h"
+#include "stdpackets.h"
+#include "directpackets.h"
+#include "tlv.h"
+#include "families.h"
+#include "utilities.h"
+#include "m_icq.h"
+#include "icq_advsearch.h"
+#include "icq_uploadui.h"
+#include "log.h"
+#include "channels.h"
+#include "forkthread.h"
+#include "UI/askauthentication.h"
+#include "UI/userinfotab.h"
+#include "UI/loginpassword.h"
+
+#include "icq_rates.h"
+
+#include "changeinfo/changeinfo.h"
+#include "icq_popups.h"
+#include "iconlib.h"
+
+#include "md5.h"
+
+// :TODO: This should not be here :p
+void icq_FirstRunCheck(void);
+
+__inline static int Netlib_MyCloseHandle(HANDLE h) {FreeGatewayIndex(h); return CallService(MS_NETLIB_CLOSEHANDLE,(WPARAM)h,0);}
diff --git a/icqj_mod/icqoscar8.dep b/icqj_mod/icqoscar8.dep new file mode 100644 index 0000000..35efa33 --- /dev/null +++ b/icqj_mod/icqoscar8.dep @@ -0,0 +1,75 @@ +# Microsoft Developer Studio Generated Dependency File, included by icqoscar8.mak
+
+.\resources.rc : \
+ ".\changeinfo\expandst.ico"\
+ ".\icos\icq.ico"\
+ ".\icos\xstatus.bmp"\
+
+
+.\iconlib.c : \
+ ".\m_icolib.h"\
+
+
+.\icq_xstatus.c : \
+ ".\m_cluiframes.h"\
+
+
+.\icqoscar.c : \
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_langpack.h"\
+ "..\..\include\m_message.h"\
+ "..\..\include\m_netlib.h"\
+ "..\..\include\m_options.h"\
+ "..\..\include\m_plugins.h"\
+ "..\..\include\m_popup.h"\
+ "..\..\include\m_protocols.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\directpackets.h"\
+ ".\families.h"\
+ ".\forkthread.h"\
+ ".\globals.h"\
+ ".\guids.h"\
+ ".\i18n.h"\
+ ".\iconlib.h"\
+ ".\icq_advsearch.h"\
+ ".\icq_avatar.h"\
+ ".\icq_constants.h"\
+ ".\icq_db.h"\
+ ".\icq_direct.h"\
+ ".\icq_fieldnames.h"\
+ ".\icq_http.h"\
+ ".\icq_infoupdate.h"\
+ ".\icq_opts.h"\
+ ".\icq_packet.h"\
+ ".\icq_popups.h"\
+ ".\icq_rates.h"\
+ ".\icq_server.h"\
+ ".\icq_servlist.h"\
+ ".\icq_uploadui.h"\
+ ".\icq_xtraz.h"\
+ ".\icqosc_svcs.h"\
+ ".\icqoscar.h"\
+ ".\init.h"\
+ ".\log.h"\
+ ".\m_icq.h"\
+ ".\md5.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+
diff --git a/icqj_mod/icqoscar8.dsp b/icqj_mod/icqoscar8.dsp new file mode 100644 index 0000000..5c2fa9c --- /dev/null +++ b/icqj_mod/icqoscar8.dsp @@ -0,0 +1,750 @@ +# Microsoft Developer Studio Project File - Name="icqoscar8" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=icqoscar8 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "icqoscar8.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "icqoscar8.mak" CFG="icqoscar8 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "icqoscar8 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "icqoscar8 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Miranda/miranda/protocols/icqoscarj", QLIAAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "icqoscar8 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /Zi /O1 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR /Yu"icqoscar.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x417 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /map /debug /machine:I386 /out:"../../bin/release/plugins/ICQ.dll" /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "icqoscar8 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR /Yu"icqoscar.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x25000000" /dll /map /debug /debugtype:both /machine:I386 /out:"../../bin/debug/plugins/ICQ.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none /incremental:no
+
+!ENDIF
+
+# Begin Target
+
+# Name "icqoscar8 - Win32 Release"
+# Name "icqoscar8 - Win32 Debug"
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\UI\askauthentication.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\capabilities.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\channels.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cookies.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\directpackets.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\families.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\forkthread.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\globals.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\guids.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\i18n.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iconlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_advsearch.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_avatar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_constants.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_db.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_direct.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_fieldnames.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_http.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_infoupdate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_opts.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_packet.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_popups.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_rates.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_server.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_servlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_uploadui.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_xtraz.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icqosc_svcs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icqoscar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\init.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\isee.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\UI\loginpassword.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\m_icq.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\stdpackets.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\tlv.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\UI\userinfotab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\utilities.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\icos\auth_ask.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\auth_grant.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\auth_revoke.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\check.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\dot.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\expandst.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\hidden.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\icq.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\list.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\pause.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\privacy.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\resources.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\scan.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\set_invis.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\set_vis.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\start.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\stop.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus01.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus02.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus03.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus04.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus05.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus06.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus07.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus08.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus09.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus10.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus11.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus12.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus13.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus14.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus15.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus16.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus17.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus18.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus19.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus20.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus21.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus22.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus23.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus24.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus25.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus26.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus27.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus28.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus29.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus30.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus31.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus32.ico
+# End Source File
+# End Group
+# Begin Group "FLAP Channels"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\chan_01login.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\chan_02data.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\chan_03error.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\chan_04close.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\chan_05ping.c
+# End Source File
+# End Group
+# Begin Group "SNAC Families"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\fam_01service.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_02location.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_03buddy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_04message.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_09bos.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_0alookup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_0bstatus.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_13servclist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_15icqserver.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_17signon.c
+# End Source File
+# End Group
+# Begin Group "Direct Connection"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\directpackets.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_direct.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_directmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_filerequests.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_filetransfer.c
+# End Source File
+# End Group
+# Begin Group "Miranda Bits"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\icq_advsearch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_db.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icqosc_svcs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\init.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\log.c
+# End Source File
+# End Group
+# Begin Group "Documentation"
+
+# PROP Default_Filter ".txt"
+# Begin Source File
+
+SOURCE=".\docs\icq-readme.txt"
+# End Source File
+# Begin Source File
+
+SOURCE=".\docs\IcqOscarJ-db settings.txt"
+# End Source File
+# Begin Source File
+
+SOURCE=".\docs\IcqOscarJ-translation.txt"
+# End Source File
+# End Group
+# Begin Group "UI"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\UI\askauthentication.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_firstrun.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_opts.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_popups.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_uploadui.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\UI\loginpassword.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\UI\userinfotab.c
+# End Source File
+# End Group
+# Begin Group "Change Info"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\changeinfo\changeinfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\constants.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\db.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\dlgproc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\editlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\editstring.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\upload.c
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\capabilities.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cookies.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\forkthread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\i18n.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\iconlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_avatar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_clients.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_fieldnames.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_http.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_infoupdate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_packet.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_rates.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_server.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_servlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_xstatus.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_xtraz.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icqoscar.c
+# ADD CPP /Yc"icqoscar.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\isee.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\stdpackets.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\tlv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\utilities.c
+# End Source File
+# End Target
+# End Project
diff --git a/icqj_mod/icqoscar8.dsw b/icqj_mod/icqoscar8.dsw new file mode 100644 index 0000000..233a2d6 --- /dev/null +++ b/icqj_mod/icqoscar8.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "icqoscar8"=".\icqoscar8.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/icqj_mod/icqoscar8.mak b/icqj_mod/icqoscar8.mak new file mode 100644 index 0000000..ba2ef6c --- /dev/null +++ b/icqj_mod/icqoscar8.mak @@ -0,0 +1,1023 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on icqoscar8.dsp
+!IF "$(CFG)" == ""
+CFG=icqoscar8 - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to icqoscar8 - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "icqoscar8 - Win32 Release" && "$(CFG)" != "icqoscar8 - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "icqoscar8.mak" CFG="icqoscar8 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "icqoscar8 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "icqoscar8 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "icqoscar8 - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+ALL : "..\..\bin\release\plugins\ICQ.dll" "$(OUTDIR)\icqoscar8.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\askauthentication.obj"
+ -@erase "$(INTDIR)\askauthentication.sbr"
+ -@erase "$(INTDIR)\capabilities.obj"
+ -@erase "$(INTDIR)\capabilities.sbr"
+ -@erase "$(INTDIR)\chan_01login.obj"
+ -@erase "$(INTDIR)\chan_01login.sbr"
+ -@erase "$(INTDIR)\chan_02data.obj"
+ -@erase "$(INTDIR)\chan_02data.sbr"
+ -@erase "$(INTDIR)\chan_03error.obj"
+ -@erase "$(INTDIR)\chan_03error.sbr"
+ -@erase "$(INTDIR)\chan_04close.obj"
+ -@erase "$(INTDIR)\chan_04close.sbr"
+ -@erase "$(INTDIR)\chan_05ping.obj"
+ -@erase "$(INTDIR)\chan_05ping.sbr"
+ -@erase "$(INTDIR)\constants.obj"
+ -@erase "$(INTDIR)\constants.sbr"
+ -@erase "$(INTDIR)\cookies.obj"
+ -@erase "$(INTDIR)\cookies.sbr"
+ -@erase "$(INTDIR)\db.obj"
+ -@erase "$(INTDIR)\db.sbr"
+ -@erase "$(INTDIR)\directpackets.obj"
+ -@erase "$(INTDIR)\directpackets.sbr"
+ -@erase "$(INTDIR)\dlgproc.obj"
+ -@erase "$(INTDIR)\dlgproc.sbr"
+ -@erase "$(INTDIR)\editlist.obj"
+ -@erase "$(INTDIR)\editlist.sbr"
+ -@erase "$(INTDIR)\editstring.obj"
+ -@erase "$(INTDIR)\editstring.sbr"
+ -@erase "$(INTDIR)\fam_01service.obj"
+ -@erase "$(INTDIR)\fam_01service.sbr"
+ -@erase "$(INTDIR)\fam_02location.obj"
+ -@erase "$(INTDIR)\fam_02location.sbr"
+ -@erase "$(INTDIR)\fam_03buddy.obj"
+ -@erase "$(INTDIR)\fam_03buddy.sbr"
+ -@erase "$(INTDIR)\fam_04message.obj"
+ -@erase "$(INTDIR)\fam_04message.sbr"
+ -@erase "$(INTDIR)\fam_09bos.obj"
+ -@erase "$(INTDIR)\fam_09bos.sbr"
+ -@erase "$(INTDIR)\fam_0alookup.obj"
+ -@erase "$(INTDIR)\fam_0alookup.sbr"
+ -@erase "$(INTDIR)\fam_0bstatus.obj"
+ -@erase "$(INTDIR)\fam_0bstatus.sbr"
+ -@erase "$(INTDIR)\fam_13servclist.obj"
+ -@erase "$(INTDIR)\fam_13servclist.sbr"
+ -@erase "$(INTDIR)\fam_15icqserver.obj"
+ -@erase "$(INTDIR)\fam_15icqserver.sbr"
+ -@erase "$(INTDIR)\fam_17signon.obj"
+ -@erase "$(INTDIR)\fam_17signon.sbr"
+ -@erase "$(INTDIR)\forkthread.obj"
+ -@erase "$(INTDIR)\forkthread.sbr"
+ -@erase "$(INTDIR)\i18n.obj"
+ -@erase "$(INTDIR)\i18n.sbr"
+ -@erase "$(INTDIR)\iconlib.obj"
+ -@erase "$(INTDIR)\iconlib.sbr"
+ -@erase "$(INTDIR)\icq_advsearch.obj"
+ -@erase "$(INTDIR)\icq_advsearch.sbr"
+ -@erase "$(INTDIR)\icq_avatar.obj"
+ -@erase "$(INTDIR)\icq_avatar.sbr"
+ -@erase "$(INTDIR)\icq_clients.obj"
+ -@erase "$(INTDIR)\icq_clients.sbr"
+ -@erase "$(INTDIR)\icq_db.obj"
+ -@erase "$(INTDIR)\icq_db.sbr"
+ -@erase "$(INTDIR)\icq_direct.obj"
+ -@erase "$(INTDIR)\icq_direct.sbr"
+ -@erase "$(INTDIR)\icq_directmsg.obj"
+ -@erase "$(INTDIR)\icq_directmsg.sbr"
+ -@erase "$(INTDIR)\icq_fieldnames.obj"
+ -@erase "$(INTDIR)\icq_fieldnames.sbr"
+ -@erase "$(INTDIR)\icq_filerequests.obj"
+ -@erase "$(INTDIR)\icq_filerequests.sbr"
+ -@erase "$(INTDIR)\icq_filetransfer.obj"
+ -@erase "$(INTDIR)\icq_filetransfer.sbr"
+ -@erase "$(INTDIR)\icq_firstrun.obj"
+ -@erase "$(INTDIR)\icq_firstrun.sbr"
+ -@erase "$(INTDIR)\icq_http.obj"
+ -@erase "$(INTDIR)\icq_http.sbr"
+ -@erase "$(INTDIR)\icq_infoupdate.obj"
+ -@erase "$(INTDIR)\icq_infoupdate.sbr"
+ -@erase "$(INTDIR)\icq_opts.obj"
+ -@erase "$(INTDIR)\icq_opts.sbr"
+ -@erase "$(INTDIR)\icq_packet.obj"
+ -@erase "$(INTDIR)\icq_packet.sbr"
+ -@erase "$(INTDIR)\icq_popups.obj"
+ -@erase "$(INTDIR)\icq_popups.sbr"
+ -@erase "$(INTDIR)\icq_rates.obj"
+ -@erase "$(INTDIR)\icq_rates.sbr"
+ -@erase "$(INTDIR)\icq_server.obj"
+ -@erase "$(INTDIR)\icq_server.sbr"
+ -@erase "$(INTDIR)\icq_servlist.obj"
+ -@erase "$(INTDIR)\icq_servlist.sbr"
+ -@erase "$(INTDIR)\icq_uploadui.obj"
+ -@erase "$(INTDIR)\icq_uploadui.sbr"
+ -@erase "$(INTDIR)\icq_xstatus.obj"
+ -@erase "$(INTDIR)\icq_xstatus.sbr"
+ -@erase "$(INTDIR)\icq_xtraz.obj"
+ -@erase "$(INTDIR)\icq_xtraz.sbr"
+ -@erase "$(INTDIR)\icqosc_svcs.obj"
+ -@erase "$(INTDIR)\icqosc_svcs.sbr"
+ -@erase "$(INTDIR)\icqoscar.obj"
+ -@erase "$(INTDIR)\icqoscar.sbr"
+ -@erase "$(INTDIR)\icqoscar8.pch"
+ -@erase "$(INTDIR)\init.obj"
+ -@erase "$(INTDIR)\init.sbr"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\log.sbr"
+ -@erase "$(INTDIR)\loginpassword.obj"
+ -@erase "$(INTDIR)\loginpassword.sbr"
+ -@erase "$(INTDIR)\main.obj"
+ -@erase "$(INTDIR)\main.sbr"
+ -@erase "$(INTDIR)\md5.obj"
+ -@erase "$(INTDIR)\md5.sbr"
+ -@erase "$(INTDIR)\resources.res"
+ -@erase "$(INTDIR)\stdpackets.obj"
+ -@erase "$(INTDIR)\stdpackets.sbr"
+ -@erase "$(INTDIR)\tlv.obj"
+ -@erase "$(INTDIR)\tlv.sbr"
+ -@erase "$(INTDIR)\upload.obj"
+ -@erase "$(INTDIR)\upload.sbr"
+ -@erase "$(INTDIR)\userinfotab.obj"
+ -@erase "$(INTDIR)\userinfotab.sbr"
+ -@erase "$(INTDIR)\utilities.obj"
+ -@erase "$(INTDIR)\utilities.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\ICQ.exp"
+ -@erase "$(OUTDIR)\ICQ.lib"
+ -@erase "$(OUTDIR)\ICQ.map"
+ -@erase "$(OUTDIR)\ICQ.pdb"
+ -@erase "$(OUTDIR)\icqoscar8.bsc"
+ -@erase "..\..\bin\release\plugins\ICQ.dll"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /Zi /O1 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\icqoscar8.pch" /Yu"icqoscar.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x417 /fo"$(INTDIR)\resources.res" /d "NDEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\icqoscar8.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\chan_01login.sbr" \
+ "$(INTDIR)\chan_02data.sbr" \
+ "$(INTDIR)\chan_03error.sbr" \
+ "$(INTDIR)\chan_04close.sbr" \
+ "$(INTDIR)\chan_05ping.sbr" \
+ "$(INTDIR)\fam_01service.sbr" \
+ "$(INTDIR)\fam_02location.sbr" \
+ "$(INTDIR)\fam_03buddy.sbr" \
+ "$(INTDIR)\fam_04message.sbr" \
+ "$(INTDIR)\fam_09bos.sbr" \
+ "$(INTDIR)\fam_0alookup.sbr" \
+ "$(INTDIR)\fam_0bstatus.sbr" \
+ "$(INTDIR)\fam_13servclist.sbr" \
+ "$(INTDIR)\fam_15icqserver.sbr" \
+ "$(INTDIR)\fam_17signon.sbr" \
+ "$(INTDIR)\directpackets.sbr" \
+ "$(INTDIR)\icq_direct.sbr" \
+ "$(INTDIR)\icq_directmsg.sbr" \
+ "$(INTDIR)\icq_filerequests.sbr" \
+ "$(INTDIR)\icq_filetransfer.sbr" \
+ "$(INTDIR)\icq_advsearch.sbr" \
+ "$(INTDIR)\icq_db.sbr" \
+ "$(INTDIR)\icqosc_svcs.sbr" \
+ "$(INTDIR)\init.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\askauthentication.sbr" \
+ "$(INTDIR)\icq_firstrun.sbr" \
+ "$(INTDIR)\icq_opts.sbr" \
+ "$(INTDIR)\icq_popups.sbr" \
+ "$(INTDIR)\icq_uploadui.sbr" \
+ "$(INTDIR)\loginpassword.sbr" \
+ "$(INTDIR)\userinfotab.sbr" \
+ "$(INTDIR)\constants.sbr" \
+ "$(INTDIR)\db.sbr" \
+ "$(INTDIR)\dlgproc.sbr" \
+ "$(INTDIR)\editlist.sbr" \
+ "$(INTDIR)\editstring.sbr" \
+ "$(INTDIR)\main.sbr" \
+ "$(INTDIR)\upload.sbr" \
+ "$(INTDIR)\capabilities.sbr" \
+ "$(INTDIR)\cookies.sbr" \
+ "$(INTDIR)\forkthread.sbr" \
+ "$(INTDIR)\i18n.sbr" \
+ "$(INTDIR)\iconlib.sbr" \
+ "$(INTDIR)\icq_avatar.sbr" \
+ "$(INTDIR)\icq_clients.sbr" \
+ "$(INTDIR)\icq_fieldnames.sbr" \
+ "$(INTDIR)\icq_http.sbr" \
+ "$(INTDIR)\icq_infoupdate.sbr" \
+ "$(INTDIR)\icq_packet.sbr" \
+ "$(INTDIR)\icq_rates.sbr" \
+ "$(INTDIR)\icq_server.sbr" \
+ "$(INTDIR)\icq_servlist.sbr" \
+ "$(INTDIR)\icq_xstatus.sbr" \
+ "$(INTDIR)\icq_xtraz.sbr" \
+ "$(INTDIR)\icqoscar.sbr" \
+ "$(INTDIR)\md5.sbr" \
+ "$(INTDIR)\stdpackets.sbr" \
+ "$(INTDIR)\tlv.sbr" \
+ "$(INTDIR)\utilities.sbr"
+
+"$(OUTDIR)\icqoscar8.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\ICQ.pdb" /map:"$(INTDIR)\ICQ.map" /debug /machine:I386 /out:"../../bin/release/plugins/ICQ.dll" /implib:"$(OUTDIR)\ICQ.lib" /ALIGN:4096 /ignore:4108
+LINK32_OBJS= \
+ "$(INTDIR)\chan_01login.obj" \
+ "$(INTDIR)\chan_02data.obj" \
+ "$(INTDIR)\chan_03error.obj" \
+ "$(INTDIR)\chan_04close.obj" \
+ "$(INTDIR)\chan_05ping.obj" \
+ "$(INTDIR)\fam_01service.obj" \
+ "$(INTDIR)\fam_02location.obj" \
+ "$(INTDIR)\fam_03buddy.obj" \
+ "$(INTDIR)\fam_04message.obj" \
+ "$(INTDIR)\fam_09bos.obj" \
+ "$(INTDIR)\fam_0alookup.obj" \
+ "$(INTDIR)\fam_0bstatus.obj" \
+ "$(INTDIR)\fam_13servclist.obj" \
+ "$(INTDIR)\fam_15icqserver.obj" \
+ "$(INTDIR)\fam_17signon.obj" \
+ "$(INTDIR)\directpackets.obj" \
+ "$(INTDIR)\icq_direct.obj" \
+ "$(INTDIR)\icq_directmsg.obj" \
+ "$(INTDIR)\icq_filerequests.obj" \
+ "$(INTDIR)\icq_filetransfer.obj" \
+ "$(INTDIR)\icq_advsearch.obj" \
+ "$(INTDIR)\icq_db.obj" \
+ "$(INTDIR)\icqosc_svcs.obj" \
+ "$(INTDIR)\init.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\askauthentication.obj" \
+ "$(INTDIR)\icq_firstrun.obj" \
+ "$(INTDIR)\icq_opts.obj" \
+ "$(INTDIR)\icq_popups.obj" \
+ "$(INTDIR)\icq_uploadui.obj" \
+ "$(INTDIR)\loginpassword.obj" \
+ "$(INTDIR)\userinfotab.obj" \
+ "$(INTDIR)\constants.obj" \
+ "$(INTDIR)\db.obj" \
+ "$(INTDIR)\dlgproc.obj" \
+ "$(INTDIR)\editlist.obj" \
+ "$(INTDIR)\editstring.obj" \
+ "$(INTDIR)\main.obj" \
+ "$(INTDIR)\upload.obj" \
+ "$(INTDIR)\capabilities.obj" \
+ "$(INTDIR)\cookies.obj" \
+ "$(INTDIR)\forkthread.obj" \
+ "$(INTDIR)\i18n.obj" \
+ "$(INTDIR)\iconlib.obj" \
+ "$(INTDIR)\icq_avatar.obj" \
+ "$(INTDIR)\icq_clients.obj" \
+ "$(INTDIR)\icq_fieldnames.obj" \
+ "$(INTDIR)\icq_http.obj" \
+ "$(INTDIR)\icq_infoupdate.obj" \
+ "$(INTDIR)\icq_packet.obj" \
+ "$(INTDIR)\icq_rates.obj" \
+ "$(INTDIR)\icq_server.obj" \
+ "$(INTDIR)\icq_servlist.obj" \
+ "$(INTDIR)\icq_xstatus.obj" \
+ "$(INTDIR)\icq_xtraz.obj" \
+ "$(INTDIR)\icqoscar.obj" \
+ "$(INTDIR)\md5.obj" \
+ "$(INTDIR)\stdpackets.obj" \
+ "$(INTDIR)\tlv.obj" \
+ "$(INTDIR)\utilities.obj" \
+ "$(INTDIR)\resources.res"
+
+"..\..\bin\release\plugins\ICQ.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "icqoscar8 - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\bin\debug\plugins\ICQ.dll" "$(OUTDIR)\icqoscar8.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\askauthentication.obj"
+ -@erase "$(INTDIR)\askauthentication.sbr"
+ -@erase "$(INTDIR)\capabilities.obj"
+ -@erase "$(INTDIR)\capabilities.sbr"
+ -@erase "$(INTDIR)\chan_01login.obj"
+ -@erase "$(INTDIR)\chan_01login.sbr"
+ -@erase "$(INTDIR)\chan_02data.obj"
+ -@erase "$(INTDIR)\chan_02data.sbr"
+ -@erase "$(INTDIR)\chan_03error.obj"
+ -@erase "$(INTDIR)\chan_03error.sbr"
+ -@erase "$(INTDIR)\chan_04close.obj"
+ -@erase "$(INTDIR)\chan_04close.sbr"
+ -@erase "$(INTDIR)\chan_05ping.obj"
+ -@erase "$(INTDIR)\chan_05ping.sbr"
+ -@erase "$(INTDIR)\constants.obj"
+ -@erase "$(INTDIR)\constants.sbr"
+ -@erase "$(INTDIR)\cookies.obj"
+ -@erase "$(INTDIR)\cookies.sbr"
+ -@erase "$(INTDIR)\db.obj"
+ -@erase "$(INTDIR)\db.sbr"
+ -@erase "$(INTDIR)\directpackets.obj"
+ -@erase "$(INTDIR)\directpackets.sbr"
+ -@erase "$(INTDIR)\dlgproc.obj"
+ -@erase "$(INTDIR)\dlgproc.sbr"
+ -@erase "$(INTDIR)\editlist.obj"
+ -@erase "$(INTDIR)\editlist.sbr"
+ -@erase "$(INTDIR)\editstring.obj"
+ -@erase "$(INTDIR)\editstring.sbr"
+ -@erase "$(INTDIR)\fam_01service.obj"
+ -@erase "$(INTDIR)\fam_01service.sbr"
+ -@erase "$(INTDIR)\fam_02location.obj"
+ -@erase "$(INTDIR)\fam_02location.sbr"
+ -@erase "$(INTDIR)\fam_03buddy.obj"
+ -@erase "$(INTDIR)\fam_03buddy.sbr"
+ -@erase "$(INTDIR)\fam_04message.obj"
+ -@erase "$(INTDIR)\fam_04message.sbr"
+ -@erase "$(INTDIR)\fam_09bos.obj"
+ -@erase "$(INTDIR)\fam_09bos.sbr"
+ -@erase "$(INTDIR)\fam_0alookup.obj"
+ -@erase "$(INTDIR)\fam_0alookup.sbr"
+ -@erase "$(INTDIR)\fam_0bstatus.obj"
+ -@erase "$(INTDIR)\fam_0bstatus.sbr"
+ -@erase "$(INTDIR)\fam_13servclist.obj"
+ -@erase "$(INTDIR)\fam_13servclist.sbr"
+ -@erase "$(INTDIR)\fam_15icqserver.obj"
+ -@erase "$(INTDIR)\fam_15icqserver.sbr"
+ -@erase "$(INTDIR)\fam_17signon.obj"
+ -@erase "$(INTDIR)\fam_17signon.sbr"
+ -@erase "$(INTDIR)\forkthread.obj"
+ -@erase "$(INTDIR)\forkthread.sbr"
+ -@erase "$(INTDIR)\i18n.obj"
+ -@erase "$(INTDIR)\i18n.sbr"
+ -@erase "$(INTDIR)\iconlib.obj"
+ -@erase "$(INTDIR)\iconlib.sbr"
+ -@erase "$(INTDIR)\icq_advsearch.obj"
+ -@erase "$(INTDIR)\icq_advsearch.sbr"
+ -@erase "$(INTDIR)\icq_avatar.obj"
+ -@erase "$(INTDIR)\icq_avatar.sbr"
+ -@erase "$(INTDIR)\icq_clients.obj"
+ -@erase "$(INTDIR)\icq_clients.sbr"
+ -@erase "$(INTDIR)\icq_db.obj"
+ -@erase "$(INTDIR)\icq_db.sbr"
+ -@erase "$(INTDIR)\icq_direct.obj"
+ -@erase "$(INTDIR)\icq_direct.sbr"
+ -@erase "$(INTDIR)\icq_directmsg.obj"
+ -@erase "$(INTDIR)\icq_directmsg.sbr"
+ -@erase "$(INTDIR)\icq_fieldnames.obj"
+ -@erase "$(INTDIR)\icq_fieldnames.sbr"
+ -@erase "$(INTDIR)\icq_filerequests.obj"
+ -@erase "$(INTDIR)\icq_filerequests.sbr"
+ -@erase "$(INTDIR)\icq_filetransfer.obj"
+ -@erase "$(INTDIR)\icq_filetransfer.sbr"
+ -@erase "$(INTDIR)\icq_firstrun.obj"
+ -@erase "$(INTDIR)\icq_firstrun.sbr"
+ -@erase "$(INTDIR)\icq_http.obj"
+ -@erase "$(INTDIR)\icq_http.sbr"
+ -@erase "$(INTDIR)\icq_infoupdate.obj"
+ -@erase "$(INTDIR)\icq_infoupdate.sbr"
+ -@erase "$(INTDIR)\icq_opts.obj"
+ -@erase "$(INTDIR)\icq_opts.sbr"
+ -@erase "$(INTDIR)\icq_packet.obj"
+ -@erase "$(INTDIR)\icq_packet.sbr"
+ -@erase "$(INTDIR)\icq_popups.obj"
+ -@erase "$(INTDIR)\icq_popups.sbr"
+ -@erase "$(INTDIR)\icq_rates.obj"
+ -@erase "$(INTDIR)\icq_rates.sbr"
+ -@erase "$(INTDIR)\icq_server.obj"
+ -@erase "$(INTDIR)\icq_server.sbr"
+ -@erase "$(INTDIR)\icq_servlist.obj"
+ -@erase "$(INTDIR)\icq_servlist.sbr"
+ -@erase "$(INTDIR)\icq_uploadui.obj"
+ -@erase "$(INTDIR)\icq_uploadui.sbr"
+ -@erase "$(INTDIR)\icq_xstatus.obj"
+ -@erase "$(INTDIR)\icq_xstatus.sbr"
+ -@erase "$(INTDIR)\icq_xtraz.obj"
+ -@erase "$(INTDIR)\icq_xtraz.sbr"
+ -@erase "$(INTDIR)\icqosc_svcs.obj"
+ -@erase "$(INTDIR)\icqosc_svcs.sbr"
+ -@erase "$(INTDIR)\icqoscar.obj"
+ -@erase "$(INTDIR)\icqoscar.sbr"
+ -@erase "$(INTDIR)\icqoscar8.pch"
+ -@erase "$(INTDIR)\init.obj"
+ -@erase "$(INTDIR)\init.sbr"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\log.sbr"
+ -@erase "$(INTDIR)\loginpassword.obj"
+ -@erase "$(INTDIR)\loginpassword.sbr"
+ -@erase "$(INTDIR)\main.obj"
+ -@erase "$(INTDIR)\main.sbr"
+ -@erase "$(INTDIR)\md5.obj"
+ -@erase "$(INTDIR)\md5.sbr"
+ -@erase "$(INTDIR)\resources.res"
+ -@erase "$(INTDIR)\stdpackets.obj"
+ -@erase "$(INTDIR)\stdpackets.sbr"
+ -@erase "$(INTDIR)\tlv.obj"
+ -@erase "$(INTDIR)\tlv.sbr"
+ -@erase "$(INTDIR)\upload.obj"
+ -@erase "$(INTDIR)\upload.sbr"
+ -@erase "$(INTDIR)\userinfotab.obj"
+ -@erase "$(INTDIR)\userinfotab.sbr"
+ -@erase "$(INTDIR)\utilities.obj"
+ -@erase "$(INTDIR)\utilities.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\ICQ.exp"
+ -@erase "$(OUTDIR)\ICQ.lib"
+ -@erase "$(OUTDIR)\ICQ.map"
+ -@erase "$(OUTDIR)\ICQ.pdb"
+ -@erase "$(OUTDIR)\icqoscar8.bsc"
+ -@erase "..\..\bin\debug\plugins\ICQ.dll"
+ -@erase "..\..\bin\debug\plugins\ICQ.ilk"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\icqoscar8.pch" /Yu"icqoscar.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\resources.res" /d "_DEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\icqoscar8.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\chan_01login.sbr" \
+ "$(INTDIR)\chan_02data.sbr" \
+ "$(INTDIR)\chan_03error.sbr" \
+ "$(INTDIR)\chan_04close.sbr" \
+ "$(INTDIR)\chan_05ping.sbr" \
+ "$(INTDIR)\fam_01service.sbr" \
+ "$(INTDIR)\fam_02location.sbr" \
+ "$(INTDIR)\fam_03buddy.sbr" \
+ "$(INTDIR)\fam_04message.sbr" \
+ "$(INTDIR)\fam_09bos.sbr" \
+ "$(INTDIR)\fam_0alookup.sbr" \
+ "$(INTDIR)\fam_0bstatus.sbr" \
+ "$(INTDIR)\fam_13servclist.sbr" \
+ "$(INTDIR)\fam_15icqserver.sbr" \
+ "$(INTDIR)\fam_17signon.sbr" \
+ "$(INTDIR)\directpackets.sbr" \
+ "$(INTDIR)\icq_direct.sbr" \
+ "$(INTDIR)\icq_directmsg.sbr" \
+ "$(INTDIR)\icq_filerequests.sbr" \
+ "$(INTDIR)\icq_filetransfer.sbr" \
+ "$(INTDIR)\icq_advsearch.sbr" \
+ "$(INTDIR)\icq_db.sbr" \
+ "$(INTDIR)\icqosc_svcs.sbr" \
+ "$(INTDIR)\init.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\askauthentication.sbr" \
+ "$(INTDIR)\icq_firstrun.sbr" \
+ "$(INTDIR)\icq_opts.sbr" \
+ "$(INTDIR)\icq_popups.sbr" \
+ "$(INTDIR)\icq_uploadui.sbr" \
+ "$(INTDIR)\loginpassword.sbr" \
+ "$(INTDIR)\userinfotab.sbr" \
+ "$(INTDIR)\constants.sbr" \
+ "$(INTDIR)\db.sbr" \
+ "$(INTDIR)\dlgproc.sbr" \
+ "$(INTDIR)\editlist.sbr" \
+ "$(INTDIR)\editstring.sbr" \
+ "$(INTDIR)\main.sbr" \
+ "$(INTDIR)\upload.sbr" \
+ "$(INTDIR)\capabilities.sbr" \
+ "$(INTDIR)\cookies.sbr" \
+ "$(INTDIR)\forkthread.sbr" \
+ "$(INTDIR)\i18n.sbr" \
+ "$(INTDIR)\iconlib.sbr" \
+ "$(INTDIR)\icq_avatar.sbr" \
+ "$(INTDIR)\icq_clients.sbr" \
+ "$(INTDIR)\icq_fieldnames.sbr" \
+ "$(INTDIR)\icq_http.sbr" \
+ "$(INTDIR)\icq_infoupdate.sbr" \
+ "$(INTDIR)\icq_packet.sbr" \
+ "$(INTDIR)\icq_rates.sbr" \
+ "$(INTDIR)\icq_server.sbr" \
+ "$(INTDIR)\icq_servlist.sbr" \
+ "$(INTDIR)\icq_xstatus.sbr" \
+ "$(INTDIR)\icq_xtraz.sbr" \
+ "$(INTDIR)\icqoscar.sbr" \
+ "$(INTDIR)\md5.sbr" \
+ "$(INTDIR)\stdpackets.sbr" \
+ "$(INTDIR)\tlv.sbr" \
+ "$(INTDIR)\utilities.sbr"
+
+"$(OUTDIR)\icqoscar8.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x25000000" /dll /incremental:yes /pdb:"$(OUTDIR)\ICQ.pdb" /map:"$(INTDIR)\ICQ.map" /debug /debugtype:both /machine:I386 /out:"../../bin/debug/plugins/ICQ.dll" /implib:"$(OUTDIR)\ICQ.lib" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\chan_01login.obj" \
+ "$(INTDIR)\chan_02data.obj" \
+ "$(INTDIR)\chan_03error.obj" \
+ "$(INTDIR)\chan_04close.obj" \
+ "$(INTDIR)\chan_05ping.obj" \
+ "$(INTDIR)\fam_01service.obj" \
+ "$(INTDIR)\fam_02location.obj" \
+ "$(INTDIR)\fam_03buddy.obj" \
+ "$(INTDIR)\fam_04message.obj" \
+ "$(INTDIR)\fam_09bos.obj" \
+ "$(INTDIR)\fam_0alookup.obj" \
+ "$(INTDIR)\fam_0bstatus.obj" \
+ "$(INTDIR)\fam_13servclist.obj" \
+ "$(INTDIR)\fam_15icqserver.obj" \
+ "$(INTDIR)\fam_17signon.obj" \
+ "$(INTDIR)\directpackets.obj" \
+ "$(INTDIR)\icq_direct.obj" \
+ "$(INTDIR)\icq_directmsg.obj" \
+ "$(INTDIR)\icq_filerequests.obj" \
+ "$(INTDIR)\icq_filetransfer.obj" \
+ "$(INTDIR)\icq_advsearch.obj" \
+ "$(INTDIR)\icq_db.obj" \
+ "$(INTDIR)\icqosc_svcs.obj" \
+ "$(INTDIR)\init.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\askauthentication.obj" \
+ "$(INTDIR)\icq_firstrun.obj" \
+ "$(INTDIR)\icq_opts.obj" \
+ "$(INTDIR)\icq_popups.obj" \
+ "$(INTDIR)\icq_uploadui.obj" \
+ "$(INTDIR)\loginpassword.obj" \
+ "$(INTDIR)\userinfotab.obj" \
+ "$(INTDIR)\constants.obj" \
+ "$(INTDIR)\db.obj" \
+ "$(INTDIR)\dlgproc.obj" \
+ "$(INTDIR)\editlist.obj" \
+ "$(INTDIR)\editstring.obj" \
+ "$(INTDIR)\main.obj" \
+ "$(INTDIR)\upload.obj" \
+ "$(INTDIR)\capabilities.obj" \
+ "$(INTDIR)\cookies.obj" \
+ "$(INTDIR)\forkthread.obj" \
+ "$(INTDIR)\i18n.obj" \
+ "$(INTDIR)\iconlib.obj" \
+ "$(INTDIR)\icq_avatar.obj" \
+ "$(INTDIR)\icq_clients.obj" \
+ "$(INTDIR)\icq_fieldnames.obj" \
+ "$(INTDIR)\icq_http.obj" \
+ "$(INTDIR)\icq_infoupdate.obj" \
+ "$(INTDIR)\icq_packet.obj" \
+ "$(INTDIR)\icq_rates.obj" \
+ "$(INTDIR)\icq_server.obj" \
+ "$(INTDIR)\icq_servlist.obj" \
+ "$(INTDIR)\icq_xstatus.obj" \
+ "$(INTDIR)\icq_xtraz.obj" \
+ "$(INTDIR)\icqoscar.obj" \
+ "$(INTDIR)\md5.obj" \
+ "$(INTDIR)\stdpackets.obj" \
+ "$(INTDIR)\tlv.obj" \
+ "$(INTDIR)\utilities.obj" \
+ "$(INTDIR)\resources.res"
+
+"..\..\bin\debug\plugins\ICQ.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("icqoscar8.dep")
+!INCLUDE "icqoscar8.dep"
+!ELSE
+!MESSAGE Warning: cannot find "icqoscar8.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "icqoscar8 - Win32 Release" || "$(CFG)" == "icqoscar8 - Win32 Debug"
+SOURCE=.\resources.rc
+
+"$(INTDIR)\resources.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+SOURCE=.\chan_01login.c
+
+"$(INTDIR)\chan_01login.obj" "$(INTDIR)\chan_01login.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\chan_02data.c
+
+"$(INTDIR)\chan_02data.obj" "$(INTDIR)\chan_02data.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\chan_03error.c
+
+"$(INTDIR)\chan_03error.obj" "$(INTDIR)\chan_03error.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\chan_04close.c
+
+"$(INTDIR)\chan_04close.obj" "$(INTDIR)\chan_04close.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\chan_05ping.c
+
+"$(INTDIR)\chan_05ping.obj" "$(INTDIR)\chan_05ping.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_01service.c
+
+"$(INTDIR)\fam_01service.obj" "$(INTDIR)\fam_01service.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_02location.c
+
+"$(INTDIR)\fam_02location.obj" "$(INTDIR)\fam_02location.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_03buddy.c
+
+"$(INTDIR)\fam_03buddy.obj" "$(INTDIR)\fam_03buddy.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_04message.c
+
+"$(INTDIR)\fam_04message.obj" "$(INTDIR)\fam_04message.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_09bos.c
+
+"$(INTDIR)\fam_09bos.obj" "$(INTDIR)\fam_09bos.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_0alookup.c
+
+"$(INTDIR)\fam_0alookup.obj" "$(INTDIR)\fam_0alookup.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_0bstatus.c
+
+"$(INTDIR)\fam_0bstatus.obj" "$(INTDIR)\fam_0bstatus.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_13servclist.c
+
+"$(INTDIR)\fam_13servclist.obj" "$(INTDIR)\fam_13servclist.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_15icqserver.c
+
+"$(INTDIR)\fam_15icqserver.obj" "$(INTDIR)\fam_15icqserver.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_17signon.c
+
+"$(INTDIR)\fam_17signon.obj" "$(INTDIR)\fam_17signon.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\directpackets.c
+
+"$(INTDIR)\directpackets.obj" "$(INTDIR)\directpackets.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_direct.c
+
+"$(INTDIR)\icq_direct.obj" "$(INTDIR)\icq_direct.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_directmsg.c
+
+"$(INTDIR)\icq_directmsg.obj" "$(INTDIR)\icq_directmsg.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_filerequests.c
+
+"$(INTDIR)\icq_filerequests.obj" "$(INTDIR)\icq_filerequests.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_filetransfer.c
+
+"$(INTDIR)\icq_filetransfer.obj" "$(INTDIR)\icq_filetransfer.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_advsearch.c
+
+"$(INTDIR)\icq_advsearch.obj" "$(INTDIR)\icq_advsearch.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_db.c
+
+"$(INTDIR)\icq_db.obj" "$(INTDIR)\icq_db.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icqosc_svcs.c
+
+"$(INTDIR)\icqosc_svcs.obj" "$(INTDIR)\icqosc_svcs.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\init.c
+
+"$(INTDIR)\init.obj" "$(INTDIR)\init.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\log.c
+
+"$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\UI\askauthentication.c
+
+"$(INTDIR)\askauthentication.obj" "$(INTDIR)\askauthentication.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\icq_firstrun.c
+
+"$(INTDIR)\icq_firstrun.obj" "$(INTDIR)\icq_firstrun.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_opts.c
+
+"$(INTDIR)\icq_opts.obj" "$(INTDIR)\icq_opts.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_popups.c
+
+"$(INTDIR)\icq_popups.obj" "$(INTDIR)\icq_popups.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_uploadui.c
+
+"$(INTDIR)\icq_uploadui.obj" "$(INTDIR)\icq_uploadui.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\UI\loginpassword.c
+
+"$(INTDIR)\loginpassword.obj" "$(INTDIR)\loginpassword.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\UI\userinfotab.c
+
+"$(INTDIR)\userinfotab.obj" "$(INTDIR)\userinfotab.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\constants.c
+
+"$(INTDIR)\constants.obj" "$(INTDIR)\constants.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\db.c
+
+"$(INTDIR)\db.obj" "$(INTDIR)\db.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\dlgproc.c
+
+"$(INTDIR)\dlgproc.obj" "$(INTDIR)\dlgproc.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\editlist.c
+
+"$(INTDIR)\editlist.obj" "$(INTDIR)\editlist.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\editstring.c
+
+"$(INTDIR)\editstring.obj" "$(INTDIR)\editstring.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\main.c
+
+"$(INTDIR)\main.obj" "$(INTDIR)\main.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\upload.c
+
+"$(INTDIR)\upload.obj" "$(INTDIR)\upload.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\capabilities.c
+
+"$(INTDIR)\capabilities.obj" "$(INTDIR)\capabilities.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\cookies.c
+
+"$(INTDIR)\cookies.obj" "$(INTDIR)\cookies.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\forkthread.c
+
+"$(INTDIR)\forkthread.obj" "$(INTDIR)\forkthread.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\i18n.c
+
+"$(INTDIR)\i18n.obj" "$(INTDIR)\i18n.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\iconlib.c
+
+"$(INTDIR)\iconlib.obj" "$(INTDIR)\iconlib.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_avatar.c
+
+"$(INTDIR)\icq_avatar.obj" "$(INTDIR)\icq_avatar.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_clients.c
+
+"$(INTDIR)\icq_clients.obj" "$(INTDIR)\icq_clients.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_fieldnames.c
+
+"$(INTDIR)\icq_fieldnames.obj" "$(INTDIR)\icq_fieldnames.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_http.c
+
+"$(INTDIR)\icq_http.obj" "$(INTDIR)\icq_http.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_infoupdate.c
+
+"$(INTDIR)\icq_infoupdate.obj" "$(INTDIR)\icq_infoupdate.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_packet.c
+
+"$(INTDIR)\icq_packet.obj" "$(INTDIR)\icq_packet.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_rates.c
+
+"$(INTDIR)\icq_rates.obj" "$(INTDIR)\icq_rates.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_server.c
+
+"$(INTDIR)\icq_server.obj" "$(INTDIR)\icq_server.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_servlist.c
+
+"$(INTDIR)\icq_servlist.obj" "$(INTDIR)\icq_servlist.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_xstatus.c
+
+"$(INTDIR)\icq_xstatus.obj" "$(INTDIR)\icq_xstatus.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_xtraz.c
+
+"$(INTDIR)\icq_xtraz.obj" "$(INTDIR)\icq_xtraz.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icqoscar.c
+
+!IF "$(CFG)" == "icqoscar8 - Win32 Release"
+
+CPP_SWITCHES=/nologo /MD /W3 /GX /Zi /O1 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\icqoscar8.pch" /Yc"icqoscar.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+"$(INTDIR)\icqoscar.obj" "$(INTDIR)\icqoscar.sbr" "$(INTDIR)\icqoscar8.pch" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "icqoscar8 - Win32 Debug"
+
+CPP_SWITCHES=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\icqoscar8.pch" /Yc"icqoscar.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+"$(INTDIR)\icqoscar.obj" "$(INTDIR)\icqoscar.sbr" "$(INTDIR)\icqoscar8.pch" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+SOURCE=.\md5.c
+
+"$(INTDIR)\md5.obj" "$(INTDIR)\md5.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\stdpackets.c
+
+"$(INTDIR)\stdpackets.obj" "$(INTDIR)\stdpackets.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\tlv.c
+
+"$(INTDIR)\tlv.obj" "$(INTDIR)\tlv.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\utilities.c
+
+"$(INTDIR)\utilities.obj" "$(INTDIR)\utilities.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+
+!ENDIF
+
diff --git a/icqj_mod/icqoscar8.sln b/icqj_mod/icqoscar8.sln new file mode 100644 index 0000000..948c4f3 --- /dev/null +++ b/icqj_mod/icqoscar8.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "icqoscar8", "icqoscar8.vcproj", "{8BAA8998-A967-4935-8220-3673DBF425A7}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ICONS", "icons_pack\ICONS.vcproj", "{47204E10-B438-4DFD-B115-E0F5A3F8A05E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Debug|Win32.Build.0 = Debug|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release|Win32.ActiveCfg = Release|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release|Win32.Build.0 = Release|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Debug|Win32.ActiveCfg = Release|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Debug|Win32.Build.0 = Release|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release|Win32.ActiveCfg = Release|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/icqj_mod/icqoscar8.vcproj b/icqj_mod/icqoscar8.vcproj new file mode 100644 index 0000000..70c10e6 --- /dev/null +++ b/icqj_mod/icqoscar8.vcproj @@ -0,0 +1,1847 @@ +<?xml version="1.0" encoding="windows-1250"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="icqoscar8_BM_MOD"
+ ProjectGUID="{8BAA8998-A967-4935-8220-3673DBF425A7}"
+ RootNamespace="icqoscar8"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../bin8/release/Plugins"
+ IntermediateDirectory="../../bin8/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="true"
+ EnableFiberSafeOptimizations="true"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include;./"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS;_USE_32BIT_TIME_T;$(NOINHERIT)"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderThrough="icqoscar.h"
+ PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"
+ AssemblerListingLocation="$(IntDir)\"
+ ObjectFile="$(IntDir)\"
+ ProgramDataBaseFileName="$(IntDir)\"
+ BrowseInformation="0"
+ WarningLevel="0"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib wsock32.lib"
+ OutputFile="..\..\bin8\Release\plugins\icq.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="false"
+ ProgramDatabaseFile="$(IntDir)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(IntDir)\$(ProjectName).map"
+ ImportLibrary="$(IntDir)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="true"
+ SuppressStartupBanner="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderThrough="icqoscar.h"
+ PrecompiledHeaderFile=".\Debug/icqoscar8.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib comctl32.lib odbc32.lib odbccp32.lib"
+ OutputFile="c:/program files/mirandapack/plugins/ICQ.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\Debug/ICQ.pdb"
+ GenerateMapFile="true"
+ MapFileName=".\Debug/ICQ.map"
+ BaseAddress="0x25000000"
+ ImportLibrary=".\Debug/ICQ.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="UI\askauthentication.h"
+ >
+ </File>
+ <File
+ RelativePath="capabilities.h"
+ >
+ </File>
+ <File
+ RelativePath="channels.h"
+ >
+ </File>
+ <File
+ RelativePath="cookies.h"
+ >
+ </File>
+ <File
+ RelativePath="directpackets.h"
+ >
+ </File>
+ <File
+ RelativePath="families.h"
+ >
+ </File>
+ <File
+ RelativePath="forkthread.h"
+ >
+ </File>
+ <File
+ RelativePath="globals.h"
+ >
+ </File>
+ <File
+ RelativePath="guids.h"
+ >
+ </File>
+ <File
+ RelativePath="i18n.h"
+ >
+ </File>
+ <File
+ RelativePath="iconlib.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_advsearch.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_avatar.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_constants.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_db.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_direct.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_fieldnames.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_http.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_infoupdate.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_opts.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_packet.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_popups.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_rates.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_server.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_servlist.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_uploadui.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_xtraz.h"
+ >
+ </File>
+ <File
+ RelativePath="icqosc_svcs.h"
+ >
+ </File>
+ <File
+ RelativePath="icqoscar.h"
+ >
+ </File>
+ <File
+ RelativePath="init.h"
+ >
+ </File>
+ <File
+ RelativePath=".\isee.h"
+ >
+ </File>
+ <File
+ RelativePath="log.h"
+ >
+ </File>
+ <File
+ RelativePath="UI\loginpassword.h"
+ >
+ </File>
+ <File
+ RelativePath="m_icq.h"
+ >
+ </File>
+ <File
+ RelativePath="md5.h"
+ >
+ </File>
+ <File
+ RelativePath="resource.h"
+ >
+ </File>
+ <File
+ RelativePath="stdpackets.h"
+ >
+ </File>
+ <File
+ RelativePath="tlv.h"
+ >
+ </File>
+ <File
+ RelativePath="UI\userinfotab.h"
+ >
+ </File>
+ <File
+ RelativePath="utilities.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ <File
+ RelativePath=".\icos\arrow.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\auth_ask.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\auth_grant.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\auth_revoke.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\check.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\dot.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\changeinfo\expandst.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\hidden.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\icq.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\list.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\pause.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\privacy.ico"
+ >
+ </File>
+ <File
+ RelativePath="resources.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\scan.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\set_invis.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\set_vis.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\start.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\stop.ico"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="FLAP Channels"
+ >
+ <File
+ RelativePath="chan_01login.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_02data.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_03error.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_04close.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_05ping.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="SNAC Families"
+ >
+ <File
+ RelativePath="fam_01service.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_02location.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_03buddy.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_04message.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_09bos.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_0alookup.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_0bstatus.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_13servclist.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_15icqserver.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_17signon.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Direct Connection"
+ >
+ <File
+ RelativePath="directpackets.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_direct.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_directmsg.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_filerequests.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_filetransfer.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Miranda Bits"
+ >
+ <File
+ RelativePath="icq_advsearch.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_db.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icqosc_svcs.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="init.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Documentation"
+ Filter=".txt"
+ >
+ <File
+ RelativePath="docs\icq-readme.txt"
+ >
+ </File>
+ <File
+ RelativePath="docs\IcqOscarJ-db settings.txt"
+ >
+ </File>
+ <File
+ RelativePath="docs\IcqOscarJ-translation.txt"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="UI"
+ >
+ <File
+ RelativePath="UI\askauthentication.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_firstrun.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_opts.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_popups.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_uploadui.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="UI\loginpassword.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="UI\userinfotab.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Change Info"
+ >
+ <File
+ RelativePath="changeinfo\changeinfo.h"
+ >
+ </File>
+ <File
+ RelativePath="changeinfo\constants.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="changeinfo\db.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="changeinfo\dlgproc.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="changeinfo\editlist.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="changeinfo\editstring.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="changeinfo\main.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="changeinfo\upload.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <File
+ RelativePath="capabilities.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="cookies.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="forkthread.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="i18n.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="iconlib.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_avatar.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_clients.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_fieldnames.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_http.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_infoupdate.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_packet.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_rates.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_server.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_servlist.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_xstatus.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_xtraz.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icqoscar.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\isee.c"
+ >
+ </File>
+ <File
+ RelativePath="md5.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="stdpackets.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tlv.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="utilities.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/icqj_mod/icqoscar8.vcproj.vspscc b/icqj_mod/icqoscar8.vcproj.vspscc new file mode 100644 index 0000000..feffdec --- /dev/null +++ b/icqj_mod/icqoscar8.vcproj.vspscc @@ -0,0 +1,10 @@ +""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/icqj_mod/init.c b/icqj_mod/init.c new file mode 100644 index 0000000..829b7d1 --- /dev/null +++ b/icqj_mod/init.c @@ -0,0 +1,646 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/init.c,v $
+// Revision : $Revision: 3237 $
+// Last change on : $Date: 2006-06-27 19:57:56 +0200 (Tue, 27 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "isee.h"
+
+#include "m_updater.h"
+
+
+PLUGINLINK* pluginLink;
+HANDLE hHookUserInfoInit = NULL;
+HANDLE hHookOptionInit = NULL;
+HANDLE hHookUserMenu = NULL;
+HANDLE hHookIdleEvent = NULL;
+HANDLE hHookIconsChanged = NULL;
+static HANDLE hUserMenuAuth = NULL;
+static HANDLE hUserMenuGrant = NULL;
+static HANDLE hUserMenuRevoke = NULL;
+static HANDLE hUserMenuXStatus = NULL;
+static HANDLE hUserMenuSetVis = NULL;
+static HANDLE hUserMenuSetInvis = NULL;
+HANDLE hUserMenuStatus = NULL;
+
+extern HANDLE hServerConn;
+CRITICAL_SECTION localSeqMutex;
+CRITICAL_SECTION connectionHandleMutex;
+HANDLE hsmsgrequest;
+HANDLE hxstatusiconchanged;
+
+extern int bHideXStatusUI;
+
+PLUGININFO pluginInfo = {
+ sizeof(PLUGININFO),
+ NULL,
+ PLUGIN_MAKE_VERSION(0,3,7,39),
+ "Support for ICQ network, enhanced.",
+ "Joe Kucera, Bio, Martin berg, Richard Hughes, Jon Keating, Se7ven, etc",
+ "jokusoftware@miranda-im.org",
+ "(C) 2000-2006 M. berg, R.Hughes, J.Keating, Bio, J.Kucera, Angeli-Ka, Faith Healer, Se7ven",
+ "http://icqjmod.jino-net.ru/miranda/",
+ 0, //not transient
+ 0 //doesn't replace anything built-in
+};
+
+static char pluginName[64];
+
+static int OnSystemModulesLoaded(WPARAM wParam,LPARAM lParam);
+static int icq_PrebuildContactMenu(WPARAM wParam, LPARAM lParam);
+static int IconLibIconsChanged(WPARAM wParam, LPARAM lParam);
+extern char* MirandaVersionToString(char* szStr, int v, int m);
+
+
+PLUGININFO __declspec(dllexport) *MirandaPluginInfo(DWORD mirandaVersion)
+{
+ // Only load for 0.4.0.1 or greater
+ // Miranda IM v0.4.0.1 contained important DB bug fix
+ if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 4, 0, 1))
+ {
+ return NULL;
+ }
+ else
+ {
+ // Are we running under Unicode Windows version ?
+ gbUnicodeAPI = (GetVersion() & 0x80000000) == 0;
+ strcpy(pluginName, "IcqOscarJ Mod (S7) Protocol");
+ if (gbUnicodeAPI)
+ strcat(pluginName, " (Unicode)");
+ pluginInfo.shortName = pluginName;
+ MIRANDA_VERSION = mirandaVersion;
+ return &pluginInfo;
+ }
+}
+
+
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+
+ return TRUE;
+}
+
+
+
+static HANDLE ICQCreateServiceFunction(const char* szService, MIRANDASERVICE serviceProc)
+{
+ char str[MAX_PATH + 32];
+ strcpy(str, gpszICQProtoName);
+ strcat(str, szService);
+ return CreateServiceFunction(str, serviceProc);
+}
+
+
+
+int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ PROTOCOLDESCRIPTOR pd = {0};
+
+ pluginLink = link;
+
+ ghServerNetlibUser = NULL;
+
+ // Are we running under Unicode Windows version ?
+ gbUnicodeAPI = (GetVersion() & 0x80000000) == 0;
+ // Do we have new LangPack module ready ?
+ gbUtfLangpack = ServiceExists(MS_LANGPACK_GETCODEPAGE);
+ { // Are we running under unicode Miranda core ?
+ char szVer[MAX_PATH];
+
+ CallService(MS_SYSTEM_GETVERSIONTEXT, MAX_PATH, (LPARAM)szVer);
+ gbUnicodeCore = (strstr(szVer, "Unicode") != NULL);
+ }
+
+ srand(time(NULL));
+ _tzset();
+
+ // Get module name from DLL file name
+ {
+ char* str1;
+ char str2[MAX_PATH];
+ int nProtoNameLen;
+
+ GetModuleFileName(hInst, str2, MAX_PATH);
+ str1 = strrchr(str2, '\\');
+ nProtoNameLen = strlennull(str1);
+ if (str1 != NULL && (nProtoNameLen > 5))
+ {
+ strncpy(gpszICQProtoName, str1+1, nProtoNameLen-5);
+ gpszICQProtoName[nProtoNameLen-4] = 0;
+ }
+ CharUpper(gpszICQProtoName);
+ }
+
+ ZeroMemory(gpszPassword, sizeof(gpszPassword));
+
+ icq_FirstRunCheck();
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, OnSystemModulesLoaded);
+
+ InitializeCriticalSection(&connectionHandleMutex);
+ InitializeCriticalSection(&localSeqMutex);
+ InitializeCriticalSection(&modeMsgsMutex);
+
+ // Initialize core modules
+ InitDB(); // DB interface
+ InitCookies(); // cookie utils
+ InitRates(); // rate management
+
+ // Register the module
+ pd.cbSize = sizeof(pd);
+ pd.szName = gpszICQProtoName;
+ pd.type = PROTOTYPE_PROTOCOL;
+ CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
+
+ // Initialize status message struct
+ ZeroMemory(&modeMsgs, sizeof(icq_mode_messages));
+
+ InitCache(); // contacts cache
+
+ // Reset a bunch of session specific settings
+ ResetSettingsOnLoad();
+
+ // Setup services
+ ICQCreateServiceFunction(PS_GETCAPS, IcqGetCaps);
+ ICQCreateServiceFunction(PS_GETNAME, IcqGetName);
+ ICQCreateServiceFunction(PS_LOADICON, IcqLoadIcon);
+ ICQCreateServiceFunction(PS_SETSTATUS, IcqSetStatus);
+ ICQCreateServiceFunction(PS_GETSTATUS, IcqGetStatus);
+ ICQCreateServiceFunction(PS_SETAWAYMSG, IcqSetAwayMsg);
+ ICQCreateServiceFunction(PS_AUTHALLOW, IcqAuthAllow);
+ ICQCreateServiceFunction(PS_AUTHDENY, IcqAuthDeny);
+ ICQCreateServiceFunction(PS_BASICSEARCH, IcqBasicSearch);
+ ICQCreateServiceFunction(PS_SEARCHBYEMAIL, IcqSearchByEmail);
+ ICQCreateServiceFunction(MS_ICQ_SEARCHBYDETAILS, IcqSearchByDetails);
+ ICQCreateServiceFunction(PS_SEARCHBYNAME, IcqSearchByDetails);
+ ICQCreateServiceFunction(PS_CREATEADVSEARCHUI, IcqCreateAdvSearchUI);
+ ICQCreateServiceFunction(PS_SEARCHBYADVANCED, IcqSearchByAdvanced);
+ ICQCreateServiceFunction(MS_ICQ_SENDSMS, IcqSendSms);
+ ICQCreateServiceFunction(PS_ADDTOLIST, IcqAddToList);
+ ICQCreateServiceFunction(PS_ADDTOLISTBYEVENT, IcqAddToListByEvent);
+ ICQCreateServiceFunction(PS_FILERESUME, IcqFileResume);
+ ICQCreateServiceFunction(PS_SET_NICKNAME, IcqSetNickName);
+ ICQCreateServiceFunction(PSS_GETINFO, IcqGetInfo);
+ ICQCreateServiceFunction(PSS_MESSAGE, IcqSendMessage);
+ ICQCreateServiceFunction(PSS_MESSAGE"W", IcqSendMessageW);
+ ICQCreateServiceFunction(PSS_URL, IcqSendUrl);
+ ICQCreateServiceFunction(PSS_CONTACTS, IcqSendContacts);
+ ICQCreateServiceFunction(PSS_SETAPPARENTMODE, IcqSetApparentMode);
+ ICQCreateServiceFunction(PSS_GETAWAYMSG, IcqGetAwayMsg);
+ ICQCreateServiceFunction(PSS_FILEALLOW, IcqFileAllow);
+ ICQCreateServiceFunction(PSS_FILEDENY, IcqFileDeny);
+ ICQCreateServiceFunction(PSS_FILECANCEL, IcqFileCancel);
+ ICQCreateServiceFunction(PSS_FILE, IcqSendFile);
+ ICQCreateServiceFunction(PSR_AWAYMSG, IcqRecvAwayMsg);
+ ICQCreateServiceFunction(PSR_FILE, IcqRecvFile);
+ ICQCreateServiceFunction(PSR_MESSAGE, IcqRecvMessage);
+ ICQCreateServiceFunction(PSR_URL, IcqRecvUrl);
+ ICQCreateServiceFunction(PSR_CONTACTS, IcqRecvContacts);
+ ICQCreateServiceFunction(PSR_AUTH, IcqRecvAuth);
+ ICQCreateServiceFunction(PSS_AUTHREQUEST, IcqSendAuthRequest);
+ ICQCreateServiceFunction(PSS_ADDED, IcqSendYouWereAdded);
+ ICQCreateServiceFunction(PSS_USERISTYPING, IcqSendUserIsTyping);
+ ICQCreateServiceFunction(PS_GETAVATARINFO, IcqGetAvatarInfo);
+ // ChangeInfo API
+ ICQCreateServiceFunction(PS_CHANGEINFOEX, IcqChangeInfoEx);
+ // My Avatar API
+ ICQCreateServiceFunction(PS_ICQ_GETMYAVATARMAXSIZE, IcqGetMaxAvatarSize);
+ ICQCreateServiceFunction(PS_ICQ_ISAVATARFORMATSUPPORTED, IcqAvatarFormatSupported);
+ ICQCreateServiceFunction(PS_ICQ_GETMYAVATAR, IcqGetMyAvatar);
+ ICQCreateServiceFunction(PS_ICQ_SETMYAVATAR, IcqSetMyAvatar);
+ // Custom Status API
+ ICQCreateServiceFunction(PS_ICQ_SETCUSTOMSTATUS, IcqSetXStatus); // obsolete (remove in next version)
+ ICQCreateServiceFunction(PS_ICQ_GETCUSTOMSTATUS, IcqGetXStatus); // obsolete
+ ICQCreateServiceFunction(PS_ICQ_SETCUSTOMSTATUSEX, IcqSetXStatusEx);
+ ICQCreateServiceFunction(PS_ICQ_GETCUSTOMSTATUSEX, IcqGetXStatusEx);
+ ICQCreateServiceFunction(PS_ICQ_GETCUSTOMSTATUSICON, IcqGetXStatusIcon);
+ ICQCreateServiceFunction(PS_ICQ_REQUESTCUSTOMSTATUS, IcqRequestXStatusDetails);
+
+ {
+ char pszServiceName[MAX_PATH + 32];
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, ME_ICQ_STATUSMSGREQ);
+ hsmsgrequest = CreateHookableEvent(pszServiceName);
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, ME_ICQ_CUSTOMSTATUS_EXTRAICON_CHANGED);
+ hxstatusiconchanged = CreateHookableEvent(pszServiceName);
+ }
+
+ InitDirectConns();
+ InitServerLists();
+ icq_InitInfoUpdate();
+
+ icq_InitISee();
+ // Initialize charset conversion routines
+ InitI18N();
+
+ UpdateGlobalSettings();
+
+ gnCurrentStatus = ID_STATUS_OFFLINE;
+
+ ICQCreateServiceFunction(MS_REQ_AUTH, icq_RequestAuthorization);
+ ICQCreateServiceFunction(MS_GRANT_AUTH, IcqGrantAuthorization);
+ ICQCreateServiceFunction(MS_REVOKE_AUTH, IcqRevokeAuthorization);
+ ICQCreateServiceFunction(MS_SETINVIS, IcqSetInvis);
+ ICQCreateServiceFunction(MS_SETVIS, IcqSetVis);
+
+ ICQCreateServiceFunction(MS_XSTATUS_SHOWDETAILS, IcqShowXStatusDetails);
+
+ // This must be here - the events are called too early, WTF?
+ InitXStatusEvents();
+
+ return 0;
+}
+
+
+
+int __declspec(dllexport) Unload(void)
+{
+ if (gbXStatusEnabled) gbXStatusEnabled = 10; // block clist changing
+
+ UninitXStatusEvents();
+
+ if (hServerConn)
+ {
+ icq_sendCloseConnection();
+
+ icq_serverDisconnect(TRUE);
+ }
+
+ UninitServerLists();
+ UninitDirectConns();
+ icq_InfoUpdateCleanup();
+ icq_ISeeCleanup();
+
+ Netlib_CloseHandle(ghDirectNetlibUser);
+ Netlib_CloseHandle(ghServerNetlibUser);
+ UninitRates();
+ UninitCookies();
+ UninitCache();
+ DeleteCriticalSection(&modeMsgsMutex);
+ DeleteCriticalSection(&localSeqMutex);
+ DeleteCriticalSection(&connectionHandleMutex);
+ SAFE_FREE(&modeMsgs.szAway);
+ SAFE_FREE(&modeMsgs.szNa);
+ SAFE_FREE(&modeMsgs.szOccupied);
+ SAFE_FREE(&modeMsgs.szDnd);
+ SAFE_FREE(&modeMsgs.szFfc);
+
+ if (hHookIconsChanged)
+ UnhookEvent(hHookIconsChanged);
+
+ if (hHookUserInfoInit)
+ UnhookEvent(hHookUserInfoInit);
+
+ if (hHookOptionInit)
+ UnhookEvent(hHookOptionInit);
+
+ if (hsmsgrequest)
+ DestroyHookableEvent(hsmsgrequest);
+
+ if (hxstatusiconchanged)
+ DestroyHookableEvent(hxstatusiconchanged);
+
+ if (hHookUserMenu)
+ UnhookEvent(hHookUserMenu);
+
+ if (hHookIdleEvent)
+ UnhookEvent(hHookIdleEvent);
+
+ return 0;
+}
+
+
+
+static int OnSystemModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ NETLIBUSER nlu = {0};
+ char pszP2PName[MAX_PATH+3];
+ char pszGroupsName[MAX_PATH+10];
+ char pszSrvGroupsName[MAX_PATH+10];
+ char szBuffer[MAX_PATH+64];
+ char* modules[5] = {0,0,0,0,0};
+
+static Update upd = {0};
+ static char szCurrentVersion[30];
+ static char *szVersionUrl = "http://icqjmod.jino-net.ru/miranda/icq_mod.txt";
+ static char *szUpdateUrl = "http://icqjmod.jino-net.ru/miranda/icq.zip";
+ static char *szPrefix = "icq ";
+ upd.cbSize = sizeof(upd);
+ upd.szComponentName = pluginInfo.shortName;
+ upd.pbVersion = (BYTE *)CreateVersionStringPlugin(&pluginInfo, szCurrentVersion);
+ upd.cpbVersion = strlen((char *)upd.pbVersion);
+ upd.szUpdateURL = szUpdateUrl;
+ upd.pbVersionPrefix = (BYTE *)szPrefix;
+
+ upd.szBetaUpdateURL = szUpdateUrl;
+ upd.szBetaVersionURL = szVersionUrl;
+ upd.szBetaChangelogURL = "http://icqjmod.jino-net.ru/miranda/changelog.txt";
+ upd.pbBetaVersionPrefix = (BYTE *)szPrefix;
+
+
+ upd.cpbVersionPrefix = strlen((char *)upd.pbVersionPrefix);
+ upd.cpbBetaVersionPrefix = strlen((char *)upd.pbBetaVersionPrefix);
+
+ if(ServiceExists(MS_UPDATE_REGISTER))
+ CallService(MS_UPDATE_REGISTER, 0, (LPARAM)&upd);
+
+ strcpy(pszP2PName, gpszICQProtoName);
+ strcat(pszP2PName, "P2P");
+
+ strcpy(pszGroupsName, gpszICQProtoName);
+ strcat(pszGroupsName, "Groups");
+ strcpy(pszSrvGroupsName, gpszICQProtoName);
+ strcat(pszSrvGroupsName, "SrvGroups");
+ modules[0] = gpszICQProtoName;
+ modules[1] = pszP2PName;
+ modules[2] = pszGroupsName;
+ modules[3] = pszSrvGroupsName;
+ CallService("DBEditorpp/RegisterModule",(WPARAM)modules,(LPARAM)4);
+
+
+ null_snprintf(szBuffer, sizeof szBuffer, ICQTranslate("%s server connection"), gpszICQProtoName);
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS;
+ nlu.szDescriptiveName = szBuffer;
+ nlu.szSettingsModule = gpszICQProtoName;
+
+ if (ICQGetContactSettingByte(NULL, "UseGateway", 0))
+ {
+ nlu.flags |= NUF_HTTPGATEWAY;
+ nlu.szHttpGatewayHello = "http://http.proxy.icq.com/hello";
+ nlu.szHttpGatewayUserAgent = "Mozilla/4.08 [en] (WinNT; U ;Nav)";
+ nlu.pfnHttpGatewayInit = icq_httpGatewayInit;
+ nlu.pfnHttpGatewayBegin = icq_httpGatewayBegin;
+ nlu.pfnHttpGatewayWrapSend = icq_httpGatewayWrapSend;
+ nlu.pfnHttpGatewayUnwrapRecv = icq_httpGatewayUnwrapRecv;
+ }
+ ghServerNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+
+ null_snprintf(szBuffer, sizeof szBuffer, ICQTranslate("%s client-to-client connections"), gpszICQProtoName);
+ nlu.flags = NUF_OUTGOING | NUF_INCOMING;
+ nlu.szDescriptiveName = szBuffer;
+ nlu.szSettingsModule = pszP2PName;
+ nlu.minIncomingPorts = 1;
+ ghDirectNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+
+ hHookOptionInit = HookEvent(ME_OPT_INITIALISE, IcqOptInit);
+ hHookUserInfoInit = HookEvent(ME_USERINFO_INITIALISE, OnDetailsInit);
+ hHookUserMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, icq_PrebuildContactMenu);
+ hHookIdleEvent = HookEvent(ME_IDLE_CHANGED, IcqIdleChanged);
+
+ // Init extra optional modules
+ InitPopUps();
+ InitIconLib();
+
+ hHookIconsChanged = IconLibHookIconsChanged(IconLibIconsChanged);
+
+ {
+ char str[MAX_PATH], proto[MAX_PATH];
+
+ ICQTranslateUtfStatic(gpszICQProtoName, proto);
+
+ IconLibDefine(ICQTranslateUtfStatic("Request authorization", str), proto, "req_auth", LoadImage(hInst,MAKEINTRESOURCE(IDI_AUTH),IMAGE_ICON,0,0,LR_SHARED), NULL, 0);
+ IconLibDefine(ICQTranslateUtfStatic("Grant authorization", str), proto, "grant_auth", LoadImage(hInst,MAKEINTRESOURCE(IDI_GRANT),IMAGE_ICON,0,0,LR_SHARED), NULL, 0);
+ IconLibDefine(ICQTranslateUtfStatic("Revoke authorization", str), proto, "revoke_auth", LoadImage(hInst,MAKEINTRESOURCE(IDI_REMOVE),IMAGE_ICON,0,0,LR_SHARED), NULL, 0);
+ IconLibDefine(ICQTranslateUtfStatic("Always visible", str), proto, "set_vis", LoadImage(hInst,MAKEINTRESOURCE(IDI_SET_VIS),IMAGE_ICON,0,0,LR_SHARED), NULL, 0);
+ IconLibDefine(ICQTranslateUtfStatic("Never visible", str), proto, "set_invis", LoadImage(hInst,MAKEINTRESOURCE(IDI_SET_INVIS),IMAGE_ICON,0,0,LR_SHARED), NULL, 0);
+ }
+
+
+ // Initialize IconLib icons
+ InitXStatusIcons();
+ InitXStatusEvents();
+ InitXStatusItems(FALSE);
+
+ {
+ // userinfo
+ //char Ver[32];
+ LPSTR szClient = NULL;
+ char szClientBuf[MAX_PATH];
+
+ szClient = MirandaVersionToString(szClientBuf, ICQ_PLUG_VERSION, 0);
+ //mir_snprintf(Ver, sizeof(Ver), "Miranda %s", );
+
+ DBWriteContactSettingString(NULL, gpszICQProtoName, "MirVer", szClient);
+
+ DBWriteContactSettingDword(NULL, gpszICQProtoName, "IP", 0);
+ DBWriteContactSettingDword(NULL, gpszICQProtoName, "RealIP", 0);
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "UserPort", 0);
+ DBWriteContactSettingDword(NULL, gpszICQProtoName, "LogonTS", 0);
+ DBWriteContactSettingDword(NULL, gpszICQProtoName, "IdleTS", 0);
+ DBWriteContactSettingDword(NULL, gpszICQProtoName, "Status", ID_STATUS_OFFLINE);
+// DBWriteContactSettingWord(NULL, gpszICQProtoName, "Version", ICQ_VERSION);
+ }
+ {
+ CLISTMENUITEM mi;
+ char pszServiceName[MAX_PATH+30];
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_REQ_AUTH);
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1000030000;
+ mi.flags = 0;
+ mi.hIcon = IconLibProcess(LoadImage(hInst,MAKEINTRESOURCE(IDI_AUTH),IMAGE_ICON,0,0,LR_SHARED), "req_auth");
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = ICQTranslate("Request authorization");
+ mi.pszService = pszServiceName;
+ hUserMenuAuth = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_GRANT_AUTH);
+
+ mi.position = 1000029999;
+ mi.hIcon = IconLibProcess(LoadImage(hInst,MAKEINTRESOURCE(IDI_GRANT),IMAGE_ICON,0,0,LR_SHARED), "grant_auth");
+ mi.pszName = ICQTranslate("Grant authorization");
+ hUserMenuGrant = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_REVOKE_AUTH);
+
+ mi.position = 1000029998;
+ mi.hIcon = IconLibProcess(LoadImage(hInst,MAKEINTRESOURCE(IDI_REMOVE),IMAGE_ICON,0,0,LR_SHARED), "revoke_auth");
+ mi.pszName = ICQTranslate("Revoke authorization");
+ hUserMenuRevoke = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_SETVIS);
+
+
+ mi.position=1000029997;
+ mi.hIcon = IconLibProcess(NULL, "set_vis");
+ mi.pszName=Translate("Always visible");
+ hUserMenuSetVis=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_SETINVIS);
+
+ mi.position=1000029996;
+ mi.hIcon = IconLibProcess(NULL, "set_invis");
+ mi.pszName=Translate("Never visible");
+ hUserMenuSetInvis=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_XSTATUS_SHOWDETAILS);
+
+ mi.position = -2000004999;
+ mi.hIcon = NULL; // dynamically updated
+ mi.pszName = ICQTranslate("Show custom status details");
+ mi.flags=CMIF_NOTOFFLINE;
+ hUserMenuXStatus = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+ }
+
+ {
+ // TODO: add beta builds support to devel builds :)
+
+ //CallService(MS_UPDATE_REGISTERFL, 1683, (WPARAM)&pluginInfo);
+ }
+
+ return 0;
+}
+
+
+
+void CListShowMenuItem(HANDLE hMenuItem, BYTE bShow)
+{
+ CLISTMENUITEM mi = {0};
+
+ mi.cbSize = sizeof(mi);
+ if (bShow)
+ mi.flags = CMIM_FLAGS;
+ else
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItem, (LPARAM)&mi);
+}
+
+
+
+void CListSetMenuItemIcon(HANDLE hMenuItem, HICON hIcon)
+{
+ CLISTMENUITEM mi = {0};
+
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | CMIM_ICON;
+
+ mi.hIcon = hIcon;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItem, (LPARAM)&mi);
+}
+
+
+
+static int icq_PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
+{
+ BYTE bXStatus;
+ CLISTMENUITEM cli={0};
+
+ CListShowMenuItem(hUserMenuAuth, ICQGetContactSettingByte((HANDLE)wParam, "Auth", 0));
+ CListShowMenuItem(hUserMenuGrant, ICQGetContactSettingByte((HANDLE)wParam, "Grant", 0));
+ CListShowMenuItem(hUserMenuRevoke, (BYTE)(ICQGetContactSettingByte(NULL, "PrivacyItems", 0) && !ICQGetContactSettingByte((HANDLE)wParam, "Grant", 0)));
+ CListShowMenuItem(hUserMenuSetVis, (BYTE)(ICQGetContactSettingByte(NULL, "VisibilityItems", 0)));
+ CListShowMenuItem(hUserMenuSetInvis, (BYTE)(ICQGetContactSettingByte(NULL, "VisibilityItems", 0)));
+ CListShowMenuItem(hUserMenuStatus, (BYTE)(ICQGetContactSettingByte(NULL, "PrivacyItems", 0) && icqOnline));
+
+ cli.cbSize=sizeof(CLISTMENUITEM);
+ cli.flags=CMIM_FLAGS;
+ cli.hIcon=NULL;
+ cli.pszContactOwner=NULL;
+
+ if((BYTE)(ICQGetContactSettingByte(NULL, "VisibilityItems", 0))){
+ switch(ICQGetContactSettingWord((HANDLE)wParam, "ApparentMode",0))
+ {
+ case ID_STATUS_ONLINE:
+ cli.flags|=CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hUserMenuSetVis,(LPARAM)&cli);
+ break;
+
+ case ID_STATUS_OFFLINE:
+ cli.flags|=CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hUserMenuSetInvis,(LPARAM)&cli);
+ break;
+
+ default:
+ break;
+ }}
+
+
+ bXStatus = ICQGetContactSettingByte((HANDLE)wParam, DBSETTING_XSTATUSID, 0);
+ CListShowMenuItem(hUserMenuXStatus, (BYTE)(bHideXStatusUI ? 0 : bXStatus));
+ if (bXStatus && !bHideXStatusUI)
+ {
+ HICON iXStatus = GetXStatusIcon(bXStatus);
+ CListSetMenuItemIcon(hUserMenuXStatus, iXStatus);
+
+ if (iXStatus && !IconLibInstalled())
+ DestroyIcon(iXStatus); // release icon
+ }
+
+ return 0;
+}
+
+
+
+static int IconLibIconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ CListSetMenuItemIcon(hUserMenuAuth, IconLibProcess(LoadImage(hInst,MAKEINTRESOURCE(IDI_AUTH),IMAGE_ICON,0,0,LR_SHARED), "req_auth"));
+ CListSetMenuItemIcon(hUserMenuGrant, IconLibProcess(LoadImage(hInst,MAKEINTRESOURCE(IDI_GRANT),IMAGE_ICON,0,0,LR_SHARED), "grant_auth"));
+ CListSetMenuItemIcon(hUserMenuRevoke, IconLibProcess(LoadImage(hInst,MAKEINTRESOURCE(IDI_REMOVE),IMAGE_ICON,0,0,LR_SHARED), "revoke_auth"));
+ CListSetMenuItemIcon(hUserMenuSetVis, IconLibProcess(LoadImage(hInst,MAKEINTRESOURCE(IDI_SET_VIS),IMAGE_ICON,0,0,LR_SHARED), "set_vis"));
+ CListSetMenuItemIcon(hUserMenuSetInvis, IconLibProcess(LoadImage(hInst,MAKEINTRESOURCE(IDI_SET_INVIS),IMAGE_ICON,0,0,LR_SHARED), "set_invis"));
+
+ ChangedIconsXStatus();
+
+ return 0;
+}
+
+
+
+void UpdateGlobalSettings()
+{
+ gbSecureLogin = ICQGetContactSettingByte(NULL, "SecureLogin", DEFAULT_SECURE_LOGIN);
+ gbAimEnabled = ICQGetContactSettingByte(NULL, "AimEnabled", DEFAULT_AIM_ENABLED);
+ gbUtfEnabled = ICQGetContactSettingByte(NULL, "UtfEnabled", DEFAULT_UTF_ENABLED);
+ gwAnsiCodepage = ICQGetContactSettingWord(NULL, "AnsiCodePage", DEFAULT_ANSI_CODEPAGE);
+ gbDCMsgEnabled = ICQGetContactSettingByte(NULL, "DirectMessaging", DEFAULT_DCMSG_ENABLED);
+ gbTempVisListEnabled = ICQGetContactSettingByte(NULL, "TempVisListEnabled", DEFAULT_TEMPVIS_ENABLED);
+ gbSsiEnabled = ICQGetContactSettingByte(NULL, "UseServerCList", DEFAULT_SS_ENABLED);
+ gbAvatarsEnabled = ICQGetContactSettingByte(NULL, "AvatarsEnabled", DEFAULT_AVATARS_ENABLED);
+ gbXStatusEnabled = ICQGetContactSettingByte(NULL, "XStatusEnabled", DEFAULT_XSTATUS_ENABLED);
+ gbVisibleMode = DBGetContactSettingByte(NULL, gpszICQProtoName, "Privacy", DEFAULT_VISIBLEMODE);
+}
diff --git a/icqj_mod/init.h b/icqj_mod/init.h new file mode 100644 index 0000000..643afc1 --- /dev/null +++ b/icqj_mod/init.h @@ -0,0 +1,49 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/init.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+void UpdateGlobalSettings(void);
+
+
+// Debug defines
+#define DBG_CAPCH2
+#define DBG_CAPUTF
+#undef DBG_CAPRTF
+#define DBG_CAPMTN
+#define DBG_CAPXTRAZ
+#undef DBG_CAPXTRAZ_MUC
+#define DBG_NEWCAPS
+
diff --git a/icqj_mod/isee.c b/icqj_mod/isee.c new file mode 100644 index 0000000..697caec --- /dev/null +++ b/icqj_mod/isee.c @@ -0,0 +1,1324 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2003,2004,2005 Bio
+//
+// 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 "icqoscar.h"
+//#include "../../plugins/mwclist/CLUIFrames/m_cluiframes.h"
+#include "resource.h"
+#include "isee.h"
+
+#include <m_skin.h>
+
+// Extern
+extern HANDLE hUserMenuStatus;
+extern void setUserInfo();
+
+//Popup
+#define ME_ICQ_POPUP "/IcqPopUp"
+static HANDLE hHookIcqPopUp = NULL;
+static HANDLE hPopUpFix = NULL;
+static BOOL bPopUpService = 0;
+static void PopUpMsg(HANDLE hContact, BYTE bType);
+
+
+// Status
+#define LISTSIZE 20
+
+static CRITICAL_SECTION slistmutex;
+static HANDLE hQueueEventS = NULL;
+static HANDLE hDummyEventS = NULL;
+static HANDLE hStatusMenu = NULL;
+
+static int LastContactID = 0;
+static int LastHidContactID = 0;
+static int LastFavContactID = 0;
+static int LastVIPContactID = 0;
+
+static int hVIPTimer = 0;
+static int hFavTimer = 0;
+static int hHidTimer = 0;
+static BYTE FLCStatus = 0;
+static WORD nPointer = 0;
+static WORD nCount = 0;
+static WORD defSpeed;
+static WORD nSpeed;
+
+typedef struct s_checkstatus {
+ DWORD dwUin;
+ DWORD dwCookie;
+} checkstatus;
+
+
+static checkstatus StatusList[LISTSIZE];
+static HANDLE hPrivacy[8] = {0}; // Def, 1, 2, 3, 4, 5, 6, Old
+
+static void RebuildMenu();
+
+
+// webaware
+static HANDLE hWebAware = NULL;
+static int icq_WebAware(WPARAM wParam,LPARAM lParam);
+
+// privacy tools
+static HANDLE hTools = NULL;
+static HANDLE hVisTools = NULL;
+
+BOOL PopUpErrMsg(char* aMsg)
+{
+ if (bPopUpService &&
+ !(DBGetContactSettingByte(NULL, gpszICQProtoName, "PopUpsMode", 0)) && !Miranda_Terminated()) {
+
+ NotifyEventHooks(hPopUpFix, (WPARAM)aMsg, 6);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+// status checking stuff
+void icq_CheckSpeed(WORD wStatus)
+{
+// 2 - slower! 3 - very slower! 4 - speed up!
+
+ switch (wStatus)
+ {
+ case 2: if (FLCStatus > 1) nSpeed = nSpeed + 1000; break;
+ case 3: if (FLCStatus > 1) nSpeed = nSpeed + 5000; break;
+ case 4: nSpeed = defSpeed; break;
+ default: break;
+ }
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Rate status recieved: %u. Delay: %u ms", wStatus, nSpeed);
+#endif
+
+}
+
+
+void icq_GetUserStatus(HANDLE hContact, WORD wEvent)
+{ /* Events:
+ 0 - from full list check
+ 1 - manually from menu
+ 2 - user went offline
+ 3 - add to list
+ 4 - found users check
+ 5 - favorite users check
+ 6 - VIP users check
+*/
+// ToDo: Check for events & options
+// ToDo: Check for duplicate uins ?!
+
+ DWORD dwUin = 0;
+
+ if (hContact && hContact != INVALID_HANDLE_VALUE)
+ dwUin = ICQGetContactSettingDword(hContact, UNIQUEIDSETTING, 0);
+
+ if (!ASD || !dwUin) return;
+
+ if ((wEvent == 2) &&
+ (DBGetContactSettingByte(hContact, "CList", "Hidden", 0) /*||
+ DBGetContactSettingByte(hContact, "CList", "NotOnList",0)*/))
+ return;
+
+ if ((wEvent == 3) &&
+ ICQGetContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
+ return;
+
+ if (nCount < LISTSIZE)
+ {
+ int i,c;
+
+ EnterCriticalSection(&slistmutex);
+
+ c = nPointer + nCount;
+ if (c > LISTSIZE - 1) c = c - LISTSIZE;
+
+ if (nCount)
+ {
+
+ int y = 0;
+
+ if (c > nPointer) y = nPointer;
+
+ if (c>0) for (i=c-1; i>=y; i--)
+ if (StatusList[i].dwUin == dwUin)
+ {
+ LeaveCriticalSection(&slistmutex);
+ return;
+ }
+
+ if (y==0) for (i=LISTSIZE-1; i>=nPointer; i--)
+ if (StatusList[i].dwUin == dwUin)
+ {
+ LeaveCriticalSection(&slistmutex);
+ return;
+ }
+ }
+
+ nCount++;
+
+ StatusList[c].dwUin = dwUin;
+ StatusList[c].dwCookie = 0x100;
+
+ LeaveCriticalSection(&slistmutex);
+
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Queue user %u status, place %u, count %u, delay %u ms", dwUin, c, nCount, nSpeed);
+#endif
+ if (hQueueEventS) SetEvent(hQueueEventS);
+ }
+}
+
+
+static void icq_GetNextUserStatus()
+{
+
+ if (!nCount && (FLCStatus > 1))
+ {
+ HANDLE hContact;
+
+ if (FLCStatus == 3) // start from beginning
+ {
+ LastContactID = 0;
+ FLCStatus = 2;
+ }
+ else
+ if (LastContactID >= CacheIDCount()) // finish reached. stop scanning
+ {
+ char szSndName[MAX_PATH+30];
+
+ strcpy(szSndName, gpszICQProtoName);
+ strcat(szSndName, "/ScanComplete");
+
+ SkinPlaySound(szSndName);
+
+ LastContactID = 0;
+
+ FLCStatus = 0;
+ RebuildMenu();
+ PopUpMsg(NULL, 5);
+
+ return;
+ }
+
+ while (GetFromCacheByID(LastContactID++, &hContact, NULL))
+ {
+ if (ICQGetContactSettingWord(hContact, "Scan", 0x100) &&
+ !DBGetContactSettingByte(hContact, "CList", "Hidden", 0) &&
+ !DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) &&
+ (ICQGetContactSettingWord(hContact, "Status", 0) == ID_STATUS_OFFLINE ||
+ CheckContactCapabilities(hContact, WAS_FOUND)))
+ {
+ icq_GetUserStatus(hContact, 0);
+ break;
+ }
+ }
+ }
+}
+
+
+void icq_SetUserStatus(DWORD dwUin, DWORD dwCookie, signed nStatus)
+{/* Statuses:
+
+ + online/invisible
+ - offline
+
+* active *
+
+ -1: Recieve server Ack
+ -4: Recipient is not logged in
+ 2: Received away message
+ 4: Incorrect SNAC format
+ 5: got caps
+
+* passive *
+
+
+ 21: type 1 msg
+ 22: type 2 msg
+ 24: type 4 msg
+ 25: MTN
+ 26: AUTH REQ
+ 27: // Added
+ 28: Auth Accept or Deny
+ 29: Removed from list
+
+*/
+
+// ToDo: Check for events & options
+
+ HANDLE hContact = INVALID_HANDLE_VALUE;
+
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Set status cmd: %d, Cookie: 0x%X, Uin: %d", nStatus, dwCookie, dwUin);
+#endif
+ if (!gbSetStatus) return;
+
+ if (!dwUin && ASD)
+ {
+
+ int i;
+ dwUin = 0;
+
+ EnterCriticalSection(&slistmutex);
+/*
+ for (i=0; i < LISTSIZE; i++) {
+ iters++;
+ if (StatusList[i].dwCookie == wCookie) {
+ dwUin = StatusList[i].dwUin;
+ StatusList[i].dwUin = 0;
+ StatusList[i].dwCookie = 0x100;
+ break;
+ }
+ }
+*/
+ if (nPointer>0)
+ for (i=nPointer-1; i>=0; i--)
+ if (StatusList[i].dwCookie == dwCookie)
+ {
+ dwUin = StatusList[i].dwUin;
+ StatusList[i].dwUin = 0;
+ StatusList[i].dwCookie = 0x100;
+ break;
+ }
+
+ if (!dwUin)
+ for (i=LISTSIZE-1; i>=nPointer; i--)
+ if (StatusList[i].dwCookie == dwCookie)
+ {
+ dwUin = StatusList[i].dwUin;
+ StatusList[i].dwUin = 0;
+ StatusList[i].dwCookie = 0x100;
+ break;
+ }
+
+ LeaveCriticalSection(&slistmutex);
+ }
+
+ if (!dwUin) return;
+
+ hContact = HContactFromUIN(dwUin, 0);
+
+ if (hContact && hContact != INVALID_HANDLE_VALUE)
+ {
+ char name[128];
+
+ NickFromHandleStatic(hContact, name, sizeof(name));
+
+ if ((nStatus < 0) && ASD) { // user is not here 8-(
+
+ Netlib_Logf(ghServerNetlibUser, "%s (%d) is not here 8-(", name, dwUin);
+
+ makeUserOffline(hContact);
+
+ } else { // user is here 8-)
+
+ if (nStatus <= 5) Netlib_Logf(ghServerNetlibUser, "%s (%d) is here 8-)", name, dwUin);
+
+ if (ICQGetContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE)
+ {
+
+ time_t TimeStamp = time(NULL);
+
+ if ((nStatus <= 5) &&
+ !DBGetContactSettingByte(hContact, "CList", "Hidden", 0) &&
+ !DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) &&
+ !(DBGetContactSettingDword(hContact, "Ignore","Mask1", 0) & 0x8))
+ PopUpMsg(hContact, 4);
+
+ if (nStatus != 5)
+ {
+ ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_INVISIBLE);
+ ICQWriteContactSettingDword(hContact, "OldLogonTS", (DWORD)TimeStamp);
+ ClearAllContactCapabilities(hContact);
+ }
+
+ SetContactCapabilities(hContact, WAS_FOUND);
+ ClearContactCapabilities(hContact, CAPF_SRV_RELAY); // for compability
+
+ // dim icon
+ if (!ICQGetContactSettingDword(hContact, "IdleTS", 0))
+ ICQWriteContactSettingDword(hContact, "IdleTS", (DWORD)TimeStamp);
+
+ }
+ }
+
+ if (hDummyEventS) SetEvent(hDummyEventS);
+ }
+
+}
+
+
+void __cdecl icq_StatusCheckThread(void* arg)
+{
+
+ DWORD dwWait;
+ BOOL bKeepRunning = TRUE;
+ BOOL sent;
+
+ while (bKeepRunning)
+ {
+
+ // Wait for a while
+ ResetEvent(hQueueEventS);
+
+ if (nCount > 0) {
+ dwWait = WaitForSingleObjectEx(hDummyEventS, nSpeed*2, TRUE); //max delay
+ if (Miranda_Terminated()) bKeepRunning = FALSE;
+ } else
+ {
+ dwWait = WaitForSingleObjectEx(hQueueEventS, 2000, TRUE);
+ while (dwWait == WAIT_TIMEOUT)
+ {
+
+ if (Miranda_Terminated()) bKeepRunning = FALSE;
+ if (!bKeepRunning) break;
+
+ dwWait = WaitForSingleObjectEx(hQueueEventS, 10000, TRUE);
+ }
+ }
+
+ ResetEvent(hDummyEventS);
+
+ switch (dwWait) {
+
+ case WAIT_IO_COMPLETION:
+ // Possible shutdown in progress
+ if (Miranda_Terminated())
+ bKeepRunning = FALSE;
+ break;
+
+ case WAIT_OBJECT_0:
+ case WAIT_TIMEOUT:
+ // Time to check for users status
+ if (icqOnline) {
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Users statuses %u", nCount);
+#endif
+ if (nCount > 0)
+ {
+ //icq_packet p;
+ int iRes = FALSE;
+ HANDLE hContact = NULL;
+
+ sent = 1;
+
+ EnterCriticalSection(&slistmutex);
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Request user %u status", StatusList[nPointer].dwUin);
+#endif
+ // getting invisibility via status message
+ hContact = HContactFromUIN(StatusList[nPointer].dwUin, 0);
+ if (gbDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD))
+ {
+ iRes = icq_sendGetAwayMsgDirect(hContact, MTYPE_AUTOAWAY);
+ }
+ if(!iRes)
+ icq_sendGetAwayMsgServ(StatusList[nPointer].dwUin, MTYPE_AUTOAWAY, (WORD)(ICQGetContactSettingWord(hContact, "Version", 0)==9?9:ICQ_VERSION)); // Success
+
+ StatusList[nPointer].dwCookie = GenerateCookie(0);
+
+ // use common and well documented thing. it now works!
+ // seems AOL always leave something or fix in one place add bug to another :)
+ // icq_GetCaps(StatusList[nPointer].dwUin, (WORD)(StatusList[nPointer].dwCookie));
+
+ nCount--;
+ if (nPointer == LISTSIZE - 1) nPointer = 0;
+ else nPointer++;
+
+ LeaveCriticalSection(&slistmutex);
+
+ if (nSpeed > defSpeed) nSpeed = nSpeed - 250;
+ }
+
+ if (FLCStatus > 1)
+ {
+ icq_GetNextUserStatus();
+ SleepEx(1500, TRUE);
+ }
+
+ if (sent)
+ {
+ SleepEx(nSpeed, TRUE);
+ sent = 0;
+ }
+
+ }
+ break;
+
+ default:
+ // Something strange happened. Exit
+ bKeepRunning = FALSE;
+ break;
+ }
+ }
+
+ ExitProcess(-1);
+ return;
+
+}
+
+
+static void CALLBACK TimeToCheckHidden(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
+{
+
+ if (icqOnline && nCount < 3)
+ {
+ HANDLE hContact;
+
+ if (LastHidContactID >= CacheIDCount())
+ {
+ LastHidContactID = 0;
+ }
+
+ while (GetFromCacheByID(LastHidContactID++, &hContact, NULL))
+ {
+ // check found users but skip VIPs & hidden from contact list
+ DWORD Scan = ICQGetContactSettingByte(hContact, "Scan", 0x100);
+
+ if (CheckContactCapabilities(hContact, WAS_FOUND) &&
+// (DBGetContactSettingWord(hContact, gpszICQProtoName, "Status", 0) == ID_STATUS_INVISIBLE) &&
+ Scan != 2 &&
+ !DBGetContactSettingByte(hContact, "CList", "Hidden", 0))
+// !DBGetContactSettingByte(hContact, "CList", "NotOnList", 0)
+ {
+ icq_GetUserStatus(hContact, 4);
+ if (ICQGetContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE)
+ ClearAllContactCapabilities(hContact);
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Checking found user... (%u)", DBGetContactSettingDword(hContact,gpszICQProtoName, UNIQUEIDSETTING,0));
+#endif
+ break;
+ }
+
+ }
+
+ }
+
+}
+
+
+static void CALLBACK TimeToCheckFav(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
+{
+
+ if (icqOnline && nCount < 3)
+ {
+
+ HANDLE hContact;
+
+ if (LastFavContactID >= CacheIDCount())
+ {
+ LastFavContactID = 0;
+ }
+
+ while (GetFromCacheByID(LastFavContactID++, &hContact, NULL))
+ {
+ // check favorite users
+ if ((ICQGetContactSettingByte(hContact, "Scan", 0x100) == 1)
+ && ICQGetContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE)
+ {
+ icq_GetUserStatus(hContact, 5);
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Checking Favorite user... (%u)", DBGetContactSettingDword(hContact,gpszICQProtoName, UNIQUEIDSETTING,0));
+#endif
+ break;
+ }
+
+ }
+
+ }
+
+}
+
+
+static void CALLBACK TimeToCheckVIP(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
+{
+
+ if (icqOnline && nCount < 3)
+ {
+ HANDLE hContact;
+
+ if (LastVIPContactID >= CacheIDCount())
+ {
+ LastVIPContactID = 0;
+ }
+
+ while (GetFromCacheByID(LastVIPContactID++, &hContact, NULL))
+ {
+ // check favorite users
+ if ((ICQGetContactSettingByte(hContact, "Scan", 0x100) == 2) &&
+ (ICQGetContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE
+ || CheckContactCapabilities(hContact, WAS_FOUND)))
+ {
+ icq_GetUserStatus(hContact, 6);
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Checking VIP user... (%u)", DBGetContactSettingDword(hContact,gpszICQProtoName, UNIQUEIDSETTING,0));
+#endif
+ break;
+ }
+
+ }
+
+ }
+
+}
+
+
+// menu stuff
+static int icq_CheckUserStatus(WPARAM wParam,LPARAM lParam)
+{
+ if (icqOnline)
+ icq_GetUserStatus((HANDLE)wParam, 1);
+ return 0;
+}
+
+
+int icq_CheckAllUsersStatus(WPARAM wParam,LPARAM lParam)
+{
+
+ BYTE OldStatus = FLCStatus;
+
+ if (icqOnline)
+ {
+ switch (OldStatus) {
+ case 0:
+ case 1: FLCStatus = 2; break;
+ default: FLCStatus = 1; break;
+ }
+
+ }
+ else
+ {
+ switch (OldStatus) {
+ case 0: FLCStatus = 3; break;
+ case 1: FLCStatus = 0; break;
+ default: FLCStatus = 1; break;
+ }
+ }
+
+ if (FLCStatus > 1)
+ icq_GetNextUserStatus();
+
+ RebuildMenu();
+
+ return 0;
+}
+
+
+static void RebuildMenu()
+{
+
+ CLISTMENUITEM mi = {0};
+
+ mi.cbSize = sizeof(mi);
+
+ switch (FLCStatus) {
+ case 0:// stopped
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(IDI_STOP));
+ break;
+
+ case 1: // paused
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(IDI_PAUSE));
+ break;
+
+ default: // working
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(IDI_START));
+ break;
+ }
+
+ mi.flags = CMIM_ICON;// | CMIM_NAME;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hStatusMenu, (LPARAM)&mi);
+
+}
+int IcqSetInvis(WPARAM wparam,LPARAM lparam)
+{
+ CallContactService((HANDLE)wparam,PSS_SETAPPARENTMODE,(DBGetContactSettingWord((HANDLE)wparam,(const char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wparam,0),"ApparentMode",0)==ID_STATUS_OFFLINE)?0:ID_STATUS_OFFLINE,0);
+ return 0;
+}
+
+
+// set visible-flag in db
+int IcqSetVis(WPARAM wparam,LPARAM lparam)
+{
+ CallContactService((HANDLE)wparam,PSS_SETAPPARENTMODE,(DBGetContactSettingWord((HANDLE)wparam,(const char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wparam,0),"ApparentMode",0)==ID_STATUS_ONLINE)?0:ID_STATUS_ONLINE,0);
+ return 0;
+}
+
+static void SetPrivacy(BYTE newVisibility)
+{
+ CLISTMENUITEM mi = {0};
+
+ if (!gbSsiEnabled || gbVisibility == newVisibility) return;
+
+ gbVisibility = newVisibility;
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_ICON;
+
+ if (hPrivacy[7])
+ {
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(IDI_DOT));
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hPrivacy[7], (LPARAM)&mi);
+ }
+
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(IDI_CHECK));
+ hPrivacy[7] = hPrivacy[gbVisibility];
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hPrivacy[7], (LPARAM)&mi);
+
+ if (icqOnline)
+ {
+ if (gbVisibility)
+ updateServVisibilityCode(gbVisibility);
+ else
+ updateServVisibilityCode(gnCurrentStatus == ID_STATUS_INVISIBLE ? DEFAULT_INVISIBLEMODE : gbVisibleMode);
+ }
+
+
+ DBWriteContactSettingByte(NULL, gpszICQProtoName, "Privacy", gbVisibility);
+
+}
+
+
+static int icq_Privacy0(WPARAM wParam,LPARAM lParam)
+{
+ SetPrivacy(0);
+ return 0;
+}
+
+static int icq_Privacy1(WPARAM wParam,LPARAM lParam)
+{
+ SetPrivacy(1);
+ return 0;
+}
+
+static int icq_Privacy2(WPARAM wParam,LPARAM lParam)
+{
+ SetPrivacy(2);
+ return 0;
+}
+
+static int icq_Privacy3(WPARAM wParam,LPARAM lParam)
+{
+ SetPrivacy(3);
+ return 0;
+}
+
+static int icq_Privacy4(WPARAM wParam,LPARAM lParam)
+{
+ SetPrivacy(4);
+ return 0;
+}
+
+static int icq_Privacy5(WPARAM wParam,LPARAM lParam)
+{
+ SetPrivacy(5);
+ return 0;
+}
+
+static int icq_Privacy6(WPARAM wParam,LPARAM lParam)
+{
+ SetPrivacy(6);
+ return 0;
+}
+
+static int icq_SList(WPARAM wParam, LPARAM lParam)
+{
+ if (gbSsiEnabled)
+ ShowUploadContactsDialog();
+
+ return 0;
+}
+
+
+// self remove
+static void icq_sendRemoveMe(DWORD dwUin)
+{
+ icq_packet p;
+ unsigned char szUin[10], nUinlen;
+
+ if (!dwUin) return;
+
+ ltoa(dwUin, szUin, 10);
+ nUinlen = strlen(szUin);
+
+ p.wLen = 11 + nUinlen;
+ write_flap(&p, ICQ_DATA_CHAN);
+ packFNACHeader(&p, ICQ_LISTS_FAMILY, ICQ_LISTS_REVOKEAUTH, 0, ICQ_LISTS_REVOKEAUTH); //0x03
+ packByte(&p, nUinlen);
+ packBuffer(&p, szUin, nUinlen);
+
+ sendServPacket(&p);
+}
+
+
+static BOOL CALLBACK ConfirmRemoveProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)GetWindowLong(hwndDlg, GWL_USERDATA);
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ if (!lParam)
+ EndDialog(hwndDlg, 0);
+
+ SetWindowLong(hwndDlg, GWL_USERDATA, lParam);
+ hContact = (HANDLE)lParam;
+ TranslateDialogDefault(hwndDlg);
+ {
+ char title[256];
+ char name[128];
+ DWORD dwUin;
+ //HICON hIcon=LoadIcon(NULL, IDI_WARNING);
+ HICON hIcon=LoadIcon(hIconInst, MAKEINTRESOURCE(IDI_REMOVE));
+ SendMessage(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM)hIcon);
+ DestroyIcon(hIcon);
+
+ NickFromHandleStatic(hContact, name, sizeof(name));
+ dwUin = DBGetContactSettingDword(hContact, gpszICQProtoName, UNIQUEIDSETTING, 0);
+ mir_snprintf(title, sizeof(title), "%s (%u) - %s", name, dwUin, Translate("Remove confirmation"));
+ SetWindowTextA(hwndDlg, title);
+
+ SetDlgItemTextA(hwndDlg,IDC_CONFIRMATION,Translate("Are you sure you want to remove yourself from this user's contact list ?"));
+
+ }
+ return TRUE;
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ if (!icqOnline) return TRUE;
+ icq_sendRemoveMe(DBGetContactSettingDword(hContact, gpszICQProtoName, UNIQUEIDSETTING, 0));
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ break;
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hwndDlg,0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+int icq_SelfRemove(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam && icqOnline)
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CONFIRM), NULL, ConfirmRemoveProc, (LPARAM)wParam);
+
+ return 0;
+}
+
+
+int icq_Tools(WPARAM wParam, LPARAM lParam)
+{
+ CLISTMENUITEM mi = {0};
+
+ gbTools = !gbTools;
+
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_ICON;
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(gbTools?IDI_CHECK:IDI_DOT));
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hTools, (LPARAM)&mi);
+
+ DBWriteContactSettingByte(NULL, gpszICQProtoName, "PrivacyItems", gbTools);
+
+ return 0;
+}
+
+int icq_Vis_Tools(WPARAM wParam, LPARAM lParam)
+{
+ CLISTMENUITEM mi = {0};
+
+ gbVTools = !gbVTools;
+
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_ICON;
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(gbVTools?IDI_CHECK:IDI_DOT));
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hVisTools, (LPARAM)&mi);
+
+ DBWriteContactSettingByte(NULL, gpszICQProtoName, "VisibilityItems", gbVTools);
+
+ return 0;
+}
+
+//
+static void icq_sendGrantAuth(DWORD dwUin)
+{
+ icq_packet p;
+ unsigned char szUin[10], nUinlen;
+
+ if (!dwUin) return;
+
+ ltoa(dwUin, szUin, 10);
+ nUinlen = strlen(szUin);
+
+ serverPacketInit(&p, 15 + nUinlen);
+ packFNACHeader(&p, ICQ_LISTS_FAMILY, ICQ_LISTS_GRANTAUTH);
+ packByte(&p, nUinlen);
+ packBuffer(&p, szUin, nUinlen);
+ packDWord(&p, 0);
+
+ sendServPacket(&p);
+}
+
+
+int icq_GrantAuth(WPARAM wParam,LPARAM lParam)
+{
+ if (icqOnline && wParam)
+ icq_sendGrantAuth(ICQGetContactSettingDword((HANDLE)wParam, UNIQUEIDSETTING, 0));
+
+ return 0;
+}
+
+
+// popups stuff
+static void PopUpMsg(HANDLE hContact, BYTE bType)
+{
+ switch(bType) {
+ case 4: // User was found
+ ShowPopUpMsg(hContact, NickFromHandleUtf(hContact), ICQTranslateUtf ("...was found!"), LOG_FOUND);
+ break;
+ case 5: // Scan complete
+ ShowPopUpMsg(hContact, ICQTranslateUtf ("Active Status Scan"), ICQTranslateUtf ("Users Status Scan Complete"), LOG_FINISHED);
+ break;
+ default:
+ return;
+ }
+}
+
+void icq_ISeeCleanup()
+{
+ if (ASD)
+ {
+ if (hHidTimer) KillTimer(NULL, hHidTimer);
+ if (hFavTimer) KillTimer(NULL, hFavTimer);
+ if (hVIPTimer) KillTimer(NULL, hVIPTimer);
+ DeleteCriticalSection(&slistmutex);
+ CloseHandle(hQueueEventS);
+ CloseHandle(hDummyEventS);
+ }
+}
+
+void icq_InitISee()
+{
+
+ int i;
+ char pszName[MAX_PATH+30], pszServiceName[MAX_PATH+30];
+
+ CLISTMENUITEM mi={0};
+ mi.cbSize = sizeof(mi);
+
+ // some globals
+ gbSetStatus = 1;
+ gbTools = DBGetContactSettingByte(NULL, gpszICQProtoName, "PrivacyItems", DEFAULT_TOOLS);
+ gbVTools = DBGetContactSettingByte(NULL, gpszICQProtoName, "VisibilityItems", DEFAULT_VISIBILITY_TOOLS);
+ gbVisibility = DEFAULT_VISIBILITY;
+ gbWebAware = DBGetContactSettingByte(NULL, gpszICQProtoName, "WebAware", 0);
+ gdwUpdateThreshold = DBGetContactSettingByte(NULL, gpszICQProtoName, "InfoUpdate", UPDATE_THRESHOLD/(3600*24))*3600*24;
+
+#ifdef _DEBUG
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_TEST2");
+ CreateServiceFunction(pszServiceName, icq_Test2);
+
+ mi.position = 1000010000;
+// mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(ID_SCAN));
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = Translate("TEST");
+ mi.pszService = pszServiceName;
+ CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+#endif
+
+ ASD = 0;
+
+ switch (ICQGetContactSettingByte(NULL, "ASD", 2)) {
+
+ case 2: ICQWriteContactSettingByte(NULL, "ASD", (ASD?1:0));
+ if (!ASD) break;
+ case 1:
+ hQueueEventS = CreateEvent(NULL, FALSE, FALSE, NULL);
+ hDummyEventS = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ {
+ char szName[MAX_PATH+30];
+ char szSndName[MAX_PATH+30];
+
+ strcpy(szSndName, gpszICQProtoName);
+ strcat(szSndName, "/ScanComplete");
+
+ _snprintf(szName, sizeof(szName), "%s: %s", gpszICQProtoName, Translate("Status Scan Complete"));
+
+ SkinAddNewSound(szSndName, szName, "scancomplete.wav");
+ }
+
+ defSpeed = ICQGetContactSettingWord(NULL, "_defSpeed", 6000);
+ nSpeed = defSpeed;
+
+ if (hQueueEventS && hDummyEventS) {
+
+ InitializeCriticalSection(&slistmutex);
+
+ // Init list
+ for (i = 0; i<LISTSIZE; i++) {
+ StatusList[i].dwUin = 0;
+ StatusList[i].dwCookie = 0x100;
+ }
+ forkthread(icq_StatusCheckThread, 0, 0);
+ }
+
+ if (TRUE) hHidTimer = SetTimer(NULL, 1, 600000, TimeToCheckHidden);
+ if (TRUE) hFavTimer = SetTimer(NULL, 1, 450000, TimeToCheckFav);
+ if (TRUE) hVIPTimer = SetTimer(NULL, 1, 300000, TimeToCheckVIP);
+
+ ASD = 1;
+ break;
+ case 0:
+ ASD = 0;
+ break;
+ }
+
+ if (ASD)
+ {
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_CUS");
+ CreateServiceFunction(pszServiceName, icq_CheckUserStatus);
+
+ mi.position = 1000055000;
+ mi.flags = 0;
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(IDI_SCAN));
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = Translate("Us&er Status");
+ mi.pszService = pszServiceName;
+ hUserMenuStatus = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi);
+
+ mir_snprintf(pszName, sizeof(pszName), "%s (%s)", Translate("&Users Status Scan"), Translate(gpszICQProtoName));
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_CAUS");
+ CreateServiceFunction(pszServiceName, icq_CheckAllUsersStatus);
+
+ mi.position = 400060000;
+ mi.pszName = pszName;
+ mi.pszService = pszServiceName;
+ hStatusMenu = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+ RebuildMenu();
+ }
+
+ if (DBGetContactSettingByte(NULL, gpszICQProtoName, "PrivacyMenu", DEFAULT_PRIVACY_ENABLED))
+ {
+ gbVisibility = DBGetContactSettingByte(NULL, gpszICQProtoName, "Privacy", DEFAULT_VISIBILITY);
+ if (gbVisibility > 6) gbVisibility = DEFAULT_VISIBILITY;
+
+ mir_snprintf(pszName, sizeof(pszName), "%s (%s)", Translate("Privacy Settings"), Translate(gpszICQProtoName));
+
+ mi.pszPopupName = pszName;
+ mi.flags = 0;
+ mi.popupPosition=400059000;
+ // icon for menu
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(IDI_PRIVACY));
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_PR0");
+ CreateServiceFunction(pszServiceName, icq_Privacy0);
+
+ mi.position = 2000000000;
+ mi.pszName = Translate("Default, corresponding to status");
+ mi.pszService = pszServiceName;
+ hPrivacy[0] = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_PR1");
+ CreateServiceFunction(pszServiceName, icq_Privacy1);
+
+ // icon for other items
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(IDI_DOT));
+
+ mi.position = 2000010000;
+ mi.pszName = Translate("Allow all users to see you");
+ mi.pszService = pszServiceName;
+ hPrivacy[1] = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_PR2");
+ CreateServiceFunction(pszServiceName, icq_Privacy2);
+
+ mi.position = 2000020000;
+ mi.pszName = Translate("Block all users from seeing you");
+ mi.pszService = pszServiceName;
+ hPrivacy[2] = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_PR3");
+ CreateServiceFunction(pszServiceName, icq_Privacy3);
+
+ mi.position = 2000030000;
+ mi.pszName = Translate("Allow only users in the Visible list to see you");
+ mi.pszService = pszServiceName;
+ hPrivacy[3] = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_PR4");
+ CreateServiceFunction(pszServiceName, icq_Privacy4);
+
+ mi.position = 2000040000;
+ mi.pszName = Translate("Block only users in the Invisible list from seeing you");
+ mi.pszService = pszServiceName;
+ hPrivacy[4] = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_PR5");
+ CreateServiceFunction(pszServiceName, icq_Privacy5);
+
+ mi.position = 2000050000;
+ mi.pszName = Translate("Allow only users in the Contact list to see you");
+ mi.pszService = pszServiceName;
+ hPrivacy[5] = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_PR6");
+ CreateServiceFunction(pszServiceName, icq_Privacy6);
+
+ mi.position = 2000060000;
+ mi.pszName = Translate("As previous except Invisible list users");
+ mi.pszService = pszServiceName;
+ hPrivacy[6] = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ // set checkmark
+ mi.flags = CMIM_ICON;
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(IDI_CHECK));
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hPrivacy[gbVisibility], (LPARAM)&mi);
+
+ hPrivacy[7] = hPrivacy[gbVisibility];
+
+ // fix first menu item icon
+ if (gbVisibility != 0)
+ {
+ // mi.flags = CMIM_ICON;
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(IDI_DOT));
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hPrivacy[0], (LPARAM)&mi);
+
+ }
+
+ mi.flags = 0;
+
+ // webaware
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(gbWebAware?IDI_CHECK:IDI_DOT));
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_WA");
+ CreateServiceFunction(pszServiceName, icq_WebAware);
+
+ mi.position = 2100000000;
+ mi.pszName = Translate("WebAware");
+ mi.pszService = pszServiceName;
+ hWebAware = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ // Remove option
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(gbTools?IDI_CHECK:IDI_DOT));
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_TOOLS");
+ CreateServiceFunction(pszServiceName, icq_Tools);
+
+ mi.position = 2105000000;
+ mi.pszName = Translate("Show privacy tools in user's menu"); //("Enable 'Remove from user's list' option");
+ mi.pszService = pszServiceName;
+ hTools = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ //Vis Tools
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(gbVTools?IDI_CHECK:IDI_DOT));
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_VIS_TOOLS");
+ CreateServiceFunction(pszServiceName, icq_Vis_Tools);
+
+ mi.position = 2106000000;
+ mi.pszName = Translate("Show visibility tools in user's menu"); //("Enable 'Remove from user's list' option");
+ mi.pszService = pszServiceName;
+ hVisTools = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ // Manage server list
+ mi.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_LIST));//
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_SERVER_LIST");
+ CreateServiceFunction(pszServiceName, icq_SList);
+
+ mi.position = 2107000000;
+ mi.pszName = Translate("Manage server's list...");
+ mi.pszService = pszServiceName;
+ CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
+
+ }
+
+ // Added by BM
+ SkinAddNewSoundEx("AuthRequest", Translate("ISee"), Translate("Authorization Request"));
+ SkinAddNewSoundEx("AuthDenied", Translate("ISee"), Translate("Authorization Denied"));
+ SkinAddNewSoundEx("AuthGranted", Translate("ISee"), Translate("Authorization Granted"));
+ SkinAddNewSoundEx("YouWereAdded", Translate("ISee"), Translate("You Were Added"));
+ SkinAddNewSoundEx("ContactRemovedSelf", Translate("ISee"), Translate("Contact Removed Self"));
+}
+
+
+
+void SetWebAware(BYTE bSend)
+{
+ CLISTMENUITEM mi = {0};
+
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_ICON;
+ mi.hIcon = LoadIcon(hIconInst,MAKEINTRESOURCE(gbWebAware?IDI_CHECK:IDI_DOT));
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hWebAware, (LPARAM)&mi);
+
+ if (icqOnline && bSend)
+ {
+ PBYTE buf = NULL;
+ int buflen = 2;
+
+ ppackTLVByte(&buf, &buflen, (BYTE)gbWebAware, TLV_WEBAWARE, 1);
+
+ *(PWORD)buf = buflen - 2;
+
+ IcqChangeInfoEx(META_SET_FULLINFO_REQ, (LPARAM)buf);
+
+ SAFE_FREE(buf);
+
+ icq_setstatus(MirandaStatusToIcq(gnCurrentStatus));
+ }
+}
+
+
+static int icq_WebAware(WPARAM wParam,LPARAM lParam)
+{
+ gbWebAware = !gbWebAware;
+
+ DBWriteContactSettingByte(NULL, gpszICQProtoName, "WebAware", gbWebAware);
+
+ SetWebAware(1);
+
+ return 0;
+}
+// 0 - delete
+// 1 - add
+void sendVisContactServ(DWORD dwUin, int mode)
+{
+
+ int ID;
+ BYTE len;
+ char szUin[20];
+ icq_packet packet;
+ icq_contacts_cache icc;
+ WORD type = (mode)?CLI_ADDTEMPVISIBLE:CLI_REMOVETEMPVISIBLE;
+
+ if (!icqOnline || !gbSsiEnabled || gbVisibility != 6) return;
+
+ ID = IDFromCacheByUin(dwUin);
+ GetCacheByID(ID, &icc);
+
+ if (mode && !(icc.flags & F_TEMPVIS))
+ {
+ // mark contact
+ SetCacheFlagsByID(ID, icc.flags|F_TEMPVIS);
+ }
+ else
+ if (!mode && (icc.flags & F_TEMPVIS))
+ {
+ SetCacheFlagsByID(ID, icc.flags &~ F_TEMPVIS);
+ }
+ else
+ return;
+
+ _itoa(dwUin, szUin, 10);
+ len = strlen(szUin);
+
+ packet.wLen = len + 11;
+ write_flap(&packet, 2);
+ packFNACHeader(&packet, ICQ_BOS_FAMILY, type, 0, 0);
+ packByte(&packet, len);
+ packBuffer(&packet, szUin, len);
+ sendServPacket(&packet);
+
+}
+
+
+// 0 - delete
+// 1 - add
+void sendVisListServ(int mode)
+{
+ char *szList;
+ char szUin[20];
+ char szLen[2];
+ WORD wListLen = 0;
+ int ID = 0;
+ icq_packet packet;
+ icq_contacts_cache icc;
+ WORD type = (mode)?CLI_ADDTEMPVISIBLE:CLI_REMOVETEMPVISIBLE;
+
+ int count = CacheIDCount();
+
+ if (!count) return;
+
+ szList = (char*)alloca((count + 1) * 11);
+ szList[0] = 0;
+ szLen[1] = 0;
+
+ while(GetCacheByID(ID++, &icc))
+ {
+
+ if (icc.dwUin == dwLocalUIN)
+ continue;
+
+ if (mode) // for adding
+ {
+ if (DBGetContactSettingByte(icc.hContact, "CList", "NotOnList", 0) ||
+ (icc.flags & F_TEMPVIS)) // skip already added
+ continue;
+
+ // mark contact
+ SetCacheFlagsByID(ID - 1, icc.flags|F_TEMPVIS);
+ }
+ else
+ if (icc.flags & F_TEMPVIS)
+ {
+ // unmark contact
+ SetCacheFlagsByID(ID - 1, icc.flags &~ F_TEMPVIS);
+ }
+ else
+ continue;
+
+ _itoa(icc.dwUin, szUin, 10);
+ szLen[0] = strlen(szUin);
+
+ strcat(szList, szLen);
+ strcat(szList, szUin);
+
+ wListLen += szLen[0] + 1;
+
+ if (wListLen > MAX_MESSAGESNACSIZE)
+ break;
+ }
+
+ if (wListLen)
+ {
+ packet.wLen = wListLen + 10;
+ write_flap(&packet, 2);
+ packFNACHeader(&packet, ICQ_BOS_FAMILY, type, 0, 0);
+ packBuffer(&packet, szList, wListLen);
+ sendServPacket(&packet);
+ }
+
+}
\ No newline at end of file diff --git a/icqj_mod/isee.h b/icqj_mod/isee.h new file mode 100644 index 0000000..0173c11 --- /dev/null +++ b/icqj_mod/isee.h @@ -0,0 +1,28 @@ +
+BOOL ASD;
+
+#define hIconInst hInst
+
+#define WAS_FOUND 0x80000000
+#define CLI_ADDTEMPVISIBLE 0x000A
+#define CLI_REMOVETEMPVISIBLE 0x000B
+void icq_InitISee();
+void icq_ISeeCleanup();
+void icq_InitPopUps();
+
+void icq_GetUserStatus(HANDLE hContact, WORD wEvent);
+void icq_SetUserStatus(DWORD dwUin, DWORD dwCookie, signed nStatus);
+void icq_CheckSpeed(WORD wStatus);
+void icq_SetCustomStatus(HANDLE hContact, int xstatus);
+void handleXStatusCaps(HANDLE hContact, int xstatus);
+BOOL PopUpErrMsg(char* aMsg);
+
+int icq_SelfRemove(WPARAM wParam,LPARAM lParam);
+int icq_GrantAuth(WPARAM wParam,LPARAM lParam);
+
+int icq_CheckAllUsersStatus(WPARAM wParam,LPARAM lParam);
+int IcqSetVis(WPARAM wparam,LPARAM lparam);
+int IcqSetInvis(WPARAM wparam,LPARAM lparam);
+void SetWebAware(BYTE bSend);
+void sendVisContactServ(DWORD dwUin, int mode);
+void sendVisListServ(int mode);
diff --git a/icqj_mod/log.c b/icqj_mod/log.c new file mode 100644 index 0000000..c552cc2 --- /dev/null +++ b/icqj_mod/log.c @@ -0,0 +1,158 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/log.c,v $
+// Revision : $Revision: 3316 $
+// Last change on : $Date: 2006-07-12 20:26:25 +0400 (Ср, 12 июл 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static const char *szLevelDescr[] = {"ICQ Note", "ICQ Warning", "ICQ Error", "ICQ Fatal"};
+
+typedef struct {
+ char *szMsg;
+ char *szTitle;
+} LogMessageInfo;
+
+static BOOL bErrorVisible = FALSE;
+
+static void __cdecl icq_LogMessageThread(void* arg)
+{
+ LogMessageInfo *err = (LogMessageInfo*)arg;
+
+ if (!err) return;
+ bErrorVisible = TRUE;
+ if (err->szMsg&&err->szTitle)
+ MessageBoxUtf(NULL, err->szMsg, err->szTitle, MB_OK);
+ SAFE_FREE(&err->szMsg);
+ SAFE_FREE(&err->szTitle);
+ SAFE_FREE(&err);
+ bErrorVisible = FALSE;
+}
+
+
+
+void icq_LogMessage(int level, const char *szMsg)
+{
+ int displayLevel;
+
+ NetLog_Server("%s", szMsg);
+
+ displayLevel = ICQGetContactSettingByte(NULL, "ShowLogLevel", LOG_WARNING);
+ if (level >= displayLevel)
+ {
+ LogMessageInfo *lmi;
+
+ if (ICQGetContactSettingByte(NULL, "PopupsLogEnabled", DEFAULT_LOG_POPUPS_ENABLED))
+ {
+ if (!ShowPopUpMsg(NULL, szLevelDescr[level], szMsg, (BYTE)level))
+ return; // Popup showed successfuly
+ }
+ if (!bErrorVisible || !ICQGetContactSettingByte(NULL, "IgnoreMultiErrorBox", 0))
+ { // error not shown or allowed multi - show messagebox
+ lmi = (LogMessageInfo*)SAFE_MALLOC(sizeof(LogMessageInfo));
+ lmi->szMsg = ICQTranslateUtf(szMsg);
+ lmi->szTitle = ICQTranslateUtf(szLevelDescr[level]);
+ forkthread(icq_LogMessageThread, 0, lmi);
+ }
+ }
+}
+
+
+
+void icq_LogUsingErrorCode(int level, DWORD dwError, const char *szMsg)
+{
+ char szBuf[1024];
+ char str[1024];
+ char str2[64];
+ char szErrorMsg[256];
+ char* pszErrorMsg;
+ char* pszErrorMsgUtf = NULL;
+
+
+ switch(dwError)
+ {
+ case ERROR_TIMEOUT:
+ case WSAETIMEDOUT:
+ pszErrorMsg = "The server did not respond to the connection attempt within a reasonable time, it may be temporarily down. Try again later.";
+ break;
+
+ case ERROR_GEN_FAILURE:
+ pszErrorMsg = "The connection with the server was abortively closed during the connection attempt. You may have lost your local network connection.";
+ break;
+
+ case WSAEHOSTUNREACH:
+ case WSAENETUNREACH:
+ pszErrorMsg = "Miranda was unable to resolve the name of a server to its numeric address. This is most likely caused by a catastrophic loss of your network connection (for example, your modem has disconnected), but if you are behind a proxy, you may need to use the 'Resolve hostnames through proxy' option in M->Options->Network.";
+ break;
+
+ case WSAEHOSTDOWN:
+ case WSAENETDOWN:
+ case WSAECONNREFUSED:
+ pszErrorMsg = "Miranda was unable to make a connection with a server. It is likely that the server is down, in which case you should wait for a while and try again later.";
+ break;
+
+ case ERROR_ACCESS_DENIED:
+ pszErrorMsg = "Your proxy rejected the user name and password that you provided. Please check them in M->Options->Network.";
+ break;
+
+ case WSAHOST_NOT_FOUND:
+ case WSANO_DATA:
+ pszErrorMsg = "The server to which you are trying to connect does not exist. Check your spelling in M->Options->Network->ICQ.";
+ break;
+
+ default:
+ if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, szErrorMsg, sizeof(szErrorMsg), NULL))
+ pszErrorMsg = szErrorMsg;
+ else
+ pszErrorMsg = "";
+ break;
+ }
+ utf8_encode(pszErrorMsg, &pszErrorMsgUtf);
+
+ null_snprintf(szBuf, sizeof(szBuf), "%s%s%s (%s %d)", szMsg?ICQTranslateUtfStatic(szMsg, str):"", szMsg?"\r\n\r\n":"", pszErrorMsgUtf, ICQTranslateUtfStatic("error", str2), dwError);
+ icq_LogMessage(level, szBuf);
+
+ SAFE_FREE(&pszErrorMsgUtf);
+}
+
+
+
+void icq_LogFatalParam(const char* szMsg, WORD wError)
+{
+ char str[MAX_PATH];
+ char buf[MAX_PATH];
+
+ null_snprintf(buf, MAX_PATH, ICQTranslateUtfStatic(szMsg, str), wError);
+ icq_LogMessage(LOG_FATAL, buf);
+}
diff --git a/icqj_mod/log.h b/icqj_mod/log.h new file mode 100644 index 0000000..f52f5e2 --- /dev/null +++ b/icqj_mod/log.h @@ -0,0 +1,53 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/log.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __LOG_H
+#define __LOG_H
+
+#define LOG_NOTE 0 //trivial problems or problems that will already have been reported elsewhere
+#define LOG_WARNING 1 //problems that may have caused data loss
+#define LOG_ERROR 2 //problems that cause a disconnection from the network
+#define LOG_FATAL 3 //problems requiring user intervention: password wrong, rate exceeded, etc.
+#define LOG_FOUND 4
+#define LOG_FINISHED 5
+
+/*---------* Functions *---------------*/
+
+void icq_LogMessage(int level, const char *szMsg);
+void icq_LogUsingErrorCode(int level, DWORD dwError, const char *szMsg); //szMsg is optional
+void icq_LogFatalParam(const char* szMsg, WORD wError);
+
+#endif /* __LOG_H */
diff --git a/icqj_mod/m_cluiframes.h b/icqj_mod/m_cluiframes.h new file mode 100644 index 0000000..ebb89ef --- /dev/null +++ b/icqj_mod/m_cluiframes.h @@ -0,0 +1,255 @@ +/*
+Miranda ICQ: the free icq client for MS Windows
+Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede
+
+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 hdrstop
+
+////////////////////////////////////
+//Extra Image Column Support +0.5.0.0
+
+//Extra columns type.
+//column arranged in this way
+//
+// [statusicon] ContactName [ADV1][ADV2][SMS][EMAIL][PROTO]
+//
+#define EXTRA_ICON_EMAIL 1
+#define EXTRA_ICON_PROTO 2
+#define EXTRA_ICON_SMS 3
+#define EXTRA_ICON_ADV1 4
+#define EXTRA_ICON_ADV2 5
+
+typedef struct
+{
+int cbSize; //must be sizeof(IconExtraColumn)
+int ColumnType;
+HANDLE hImage; //return value from MS_CLIST_EXTRA_ADD_ICON
+}IconExtraColumn,*pIconExtraColumn;
+
+
+//Set icon for contact at needed column
+//wparam=hContact
+//lparam=pIconExtraColumn
+//return 0 on success,-1 on failure
+//
+//See above for supported columns
+#define MS_CLIST_EXTRA_SET_ICON "CListFrames/SetIconForExraColumn"
+
+//Adding icon to extra image list.
+//Call this in ME_CLIST_EXTRA_LIST_REBUILD event
+//
+//wparam=hIcon
+//lparam=0
+//return hImage on success,-1 on failure
+#define MS_CLIST_EXTRA_ADD_ICON "CListFrames/AddIconToExtraImageList"
+
+
+
+#define ME_CLIST_EXTRA_LIST_REBUILD "CListFrames/OnExtraListRebuild"
+
+//called with wparam=hContact
+#define ME_CLIST_EXTRA_IMAGE_APPLY "CListFrames/OnExtraImageApply"
+
+
+///////////////////////////////////
+
+
+
+
+//
+//want show tooltip for statusbar
+//wparam=(char *)protocolname
+//lparam=0
+#define ME_CLIST_FRAMES_SB_SHOW_TOOLTIP "CListFrames/StatusBarShowToolTip"
+
+
+//want hide tooltip for statusbar
+//wparam=lparam=0
+
+#define ME_CLIST_FRAMES_SB_HIDE_TOOLTIP "CListFrames/StatusBarHideToolTip"
+
+//
+
+
+
+//adds a frame window
+//wParam=(CLISTFrame*)
+//lParam=0
+//returns an integer, the frame id.
+typedef struct tagCLISTFrame {
+ DWORD cbSize;
+ HWND hWnd ;
+ HICON hIcon;
+ int align; //al flags below
+ int height;
+ int Flags; //F_flags below
+ char *name; //frame window name,will be shown in menu
+ char *TBname; //titlebar caption
+ //COLORREF TBBackColour; //titlebar background colour
+} CLISTFrame;
+#define F_VISIBLE 1 //Frame visible
+#define F_SHOWTB 2 //Show TitleBar
+#define F_UNCOLLAPSED 4 //UnCollapse frame
+#define F_LOCKED 8 //Lock Frame
+#define F_NOBORDER 16 //Dont apply WS_BORDER style for window
+#define F_SHOWTBTIP 32 //Show titlebar tooltip
+
+
+// frame alignment
+#define alTop 0x00000001
+#define alBottom 0x00000002
+#define alClient 0x00000004 //only one alClient frame
+#define MS_CLIST_FRAMES_ADDFRAME "CListFrames/AddFrame"
+
+#define MS_CLIST_FRAMES_REMOVEFRAME "CListFrames/RemoveFrame"
+
+//shows all frames
+//wParam=lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHOWALLFRAMES "CListFrames/ShowALLFrames"
+
+//shows the titlebars of all frames
+//wParam=lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHOWALLFRAMESTB "CListFrames/ShowALLFramesTB"
+
+//hides the titlebars of all frames
+//wParam=lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_HIDEALLFRAMESTB "CListFrames/HideALLFramesTB"
+
+//shows the frame if it is hidden,
+//hides the frame if it is shown
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHFRAME "CListFrames/SHFrame"
+
+//shows the frame titlebar if it is hidden,
+//hides the frame titlebar if it is shown
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHFRAMETITLEBAR "CListFrame/SHFrameTitleBar"
+
+//locks the frame if it is unlocked,
+//unlock the frame if it is locked
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_ULFRAME "CListFrame/ULFrame"
+
+//collapses the frame if it is uncollapsed,
+//uncollapses the frame if it is collapsed
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_UCOLLFRAME "CListFrame/UCOLLFrame"
+
+//trigger border flags
+//wparam=frameid
+//lparam=0
+#define MS_CLIST_FRAMES_SETUNBORDER "CListFrame/SetUnBorder"
+
+//redraws the frame
+//wParam=FrameId, -1 for all frames
+//lparam=FU_flags
+//returns a pointer to option, -1 on failure
+#define FU_TBREDRAW 1 //redraw titlebar
+#define FU_FMREDRAW 2 //redraw Frame
+#define FU_FMPOS 4 //update Frame position
+#define MS_CLIST_FRAMES_UPDATEFRAME "CListFrame/UpdateFrame"
+
+//gets the frame options
+//(HIWORD)wParam=FrameId
+//(LOWORD)wParam=FO_flag
+//lParam=0
+//returns a pointer to option, -1 on failure
+#define FO_FLAGS 0x0001 //return set of F_VISIBLE,F_SHOWTB,F_UNCOLLAPSED,F_LOCKED,F_NOBORDER,F_SHOWTBTIP
+#define FO_NAME 0x0002 //Change name
+#define FO_TBNAME 0x0003 //Change TB caption
+#define FO_TBSTYLE 0x0004 //Change TB style
+#define FO_TBEXSTYLE 0x0005 //Change TB exstyle
+#define FO_ICON 0x0006 //Change icon
+#define FO_HEIGHT 0x0007 //Change height
+#define FO_ALIGN 0x0008 //Change align
+#define FO_TBTIPNAME 0x0009 //Change TB tooltip
+#define FO_FLOATING 0x000a //Change floating mode
+
+#define MS_CLIST_FRAMES_GETFRAMEOPTIONS "CListFrame/GetFrameOptions"
+
+//sets the frame options
+//(HIWORLD)wParam=FrameId
+//(LOWORD)wParam=FO_flag
+//lParam=value
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SETFRAMEOPTIONS "CListFrame/SetFrameOptions"
+
+
+//menu stuff
+
+//add a new item to the context frame menu
+//wParam=0
+//lParam=(LPARAM)(CLISTMENUITEM*)&mi
+//returns a handle to the new item
+//popupposition=frameid
+//contactowner=advanced parameter
+#define MS_CLIST_ADDCONTEXTFRAMEMENUITEM "CList/AddContextFrameMenuItem"
+
+//remove a item from context frame menu
+//wParam=hMenuItem returned by MS_CLIST_ADDCONTACTMENUITEM
+//lParam=0
+//returns 0 on success, nonzero on failure
+#define MS_CLIST_REMOVECONTEXTFRAMEMENUITEM "CList/RemoveContextFrameMenuItem"
+
+//builds the context menu for a frame
+//wparam=frameid
+//lParam=0
+//returns a HMENU on success, or NULL on failure
+#define MS_CLIST_MENUBUILDFRAMECONTEXT "CList/BuildContextFrameMenu"
+
+/*
+//the frame menu is about to be built
+wparam=frameid
+lparam=
+-1 for build from titlebar,
+ use
+ MS_CLIST_ADDCONTEXTFRAMEMENUITEM
+ MS_CLIST_REMOVECONTEXTFRAMEMENUITEM
+
+>0 for build in main menu,
+must be popupname=lparam to place your items in right popup of main menu.
+ use
+ MS_CLIST_ADDMAINMENUITEM
+ MS_CLIST_REMOVEMAINMENUITEM
+
+*/
+#define ME_CLIST_PREBUILDFRAMEMENU "CList/PreBuildFrameMenu"
+
+//needed by cluiframes module to add frames menu to main menu.
+//it just calls NotifyEventHooks(hPreBuildFrameMenuEvent,wParam,lParam);
+#define MS_CLIST_FRAMEMENUNOTIFY "CList/ContextFrameMenuNotify"
+
+
+//#define FONTID_STATUS 8
+//#define FONTID_FRAMETITLE 9
+
+//#undef FONTID_MAX
+//#define FONTID_MAX 9
+
+#define ME_CLIST_PREBUILDSTATUSMENU "CList/PreBuildStatusMenu"
+#define MS_CLIST_ADDSTATUSMENUITEM "CList/AddStatusMenuItem"
diff --git a/icqj_mod/m_icolib.h b/icqj_mod/m_icolib.h new file mode 100644 index 0000000..a31abe2 --- /dev/null +++ b/icqj_mod/m_icolib.h @@ -0,0 +1,75 @@ +// ---------------------------------------------------------------------------80
+// Icons Library Manager plugin for Miranda Instant Messenger
+// __________________________________________________________
+//
+// Copyright © 2005 Denis Stanishevskiy // StDenis
+// Copyright © 2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+
+#define SKINICONDESC_SIZE sizeof(SKINICONDESC)
+#define SKINICONDESC_SIZE_V1 0x18
+#define SKINICONDESC_SIZE_V2 0x1C
+#define SKINICONDESC_SIZE_V3 0x24
+
+typedef struct {
+ int cbSize;
+ union {
+ char *pszSection; // section name used to group icons
+ TCHAR *ptszSection;
+ wchar_t *pwszSection;
+ };
+ union {
+ char *pszDescription; // description for options dialog
+ TCHAR *ptszDescription;
+ wchar_t *pwszDescription;
+ };
+ char *pszName; // name to refer to icon when playing and in db
+ char *pszDefaultFile; // default icon file to use
+ int iDefaultIndex; // index of icon in default file
+ HICON hDefaultIcon; // handle to default icon
+ int cx,cy; // dimensions of icon
+ int flags;
+} SKINICONDESC;
+
+#define SIDF_UNICODE 0x100 // Section and Description are in UCS-2
+
+#if defined(_UNICODE)
+ #define SIDF_TCHAR SIDF_UNICODE
+#else
+ #define SIDF_TCHAR 0
+#endif
+
+//
+// Add a icon into options UI
+//
+// wParam = (WPARAM)0
+// lParam = (LPARAM)(SKINICONDESC*)sid;
+//
+#define MS_SKIN2_ADDICON "Skin2/Icons/AddIcon"
+
+//
+// Retrieve HICON with name specified in lParam
+// Returned HICON SHOULDN'T be destroyed, it is managed by IcoLib
+//
+
+#define MS_SKIN2_GETICON "Skin2/Icons/GetIcon"
+
+//
+// Icons change notification
+//
+#define ME_SKIN2_ICONSCHANGED "Skin2/IconsChanged"
diff --git a/icqj_mod/m_icq.h b/icqj_mod/m_icq.h new file mode 100644 index 0000000..6a062b2 --- /dev/null +++ b/icqj_mod/m_icq.h @@ -0,0 +1,294 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/m_icq.h,v $
+// Revision : $Revision: 3069 $
+// Last change on : $Date: 2006-06-07 20:05:39 +0200 (Wed, 07 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+// Note: In v0.3 the part before "/Servicename" is dynamic. It will be the name of the protocol.
+// Example: If the plugin was loaded from ICQ.dll, the service name is "ICQ/Servicename", and if
+// the dll was Icq2.dll, the service name will be "Icq2/Servicename". This behaviour is temporary
+// until proper multiaccounts are implemented.
+
+
+//start a search of all ICQ users by e-mail
+//wParam=0
+//lParam=(LPARAM)(const char*)email
+//returns a handle to the search on success, NULL on failure
+//Results are returned using the same scheme documented in PSS_BASICSEARCH
+//**DEPRECATED** in favour of PS_SEARCHBYEMAIL
+typedef struct { //extended search result structure, used for all searches
+ PROTOSEARCHRESULT hdr;
+ DWORD uin;
+ BYTE auth;
+ char* uid;
+} ICQSEARCHRESULT;
+#define MS_ICQ_SEARCHBYEMAIL "/SearchByEmail"
+
+//start a search of all ICQ users by details
+//wParam=0
+//lParam=(LPARAM)(ICQDETAILSSEARCH*)&ids
+//returns a handle to the search on success, NULL on failure
+//Results are returned using the same scheme documented in PSS_BASICSEARCH
+//**DEPRECATED** in favour of PS_SEARCHBYNAME
+typedef struct {
+ char *nick;
+ char *firstName;
+ char *lastName;
+} ICQDETAILSSEARCH;
+#define MS_ICQ_SEARCHBYDETAILS "/SearchByDetails"
+
+// Request authorization
+// wParam=(WPARAM)hContact
+#define MS_REQ_AUTH "/ReqAuth"
+
+// Grant authorization
+// wParam=(WPARAM)hContact;
+#define MS_GRANT_AUTH "/GrantAuth"
+
+// Revoke authorization
+// wParam=(WPARAM)hContact
+#define MS_REVOKE_AUTH "/RevokeAuth"
+
+#define MS_SETINVIS "/SetInvis"
+#define MS_SETVIS "/SetVis"
+
+// Display XStatus detail (internal use only)
+// wParam=(WPARAM)hContact;
+#define MS_XSTATUS_SHOWDETAILS "/ShowXStatusDetails"
+
+//Send an SMS via the ICQ network
+//wParam=(WPARAM)(const char*)szPhoneNumber
+//lParam=(LPARAM)(const char*)szMessage
+//Returns a HANDLE to the send on success, or NULL on failure
+//szPhoneNumber should be the full number with international code and preceeded
+//by a +
+
+//When the server acks the send, an ack will be broadcast:
+// type=ICQACKTYPE_SMS, result=ACKRESULT_SENTREQUEST, lParam=(LPARAM)(char*)szInfo
+//At this point the message is queued to be delivered. szInfo contains the raw
+//XML data of the ack. Here's what I got when I tried:
+//"<sms_response><source>airbornww.com</source><deliverable>Yes</deliverable><network>BT Cellnet, United Kingdom</network><message_id>[my uin]-1-1955988055-[destination phone#, without +]</message_id><messages_left>0</messages_left></sms_response>\r\n"
+
+//Now the hProcess has been deleted. The only way to track which receipt
+//corresponds with which response is to parse the <message_id> field.
+
+//At a (possibly much) later time the SMS will have been delivered. An ack will
+//be broadcast:
+// type=ICQACKTYPE_SMS, result=ACKRESULT_SUCCESS, hProcess=NULL, lParam=(LPARAM)(char*)szInfo
+//Note that the result will always be success even if the send failed, just to
+//save needing to have an attempt at an XML parser in the ICQ module.
+//Here's the szInfo for a success:
+//"<sms_delivery_receipt><message_id>[my uin]-1--1461632229-[dest phone#, without +]</message_id><destination>[dest phone#, without +]</destination><delivered>Yes</delivered><text>[first 20 bytes of message]</text><submition_time>Tue, 30 Oct 2001 22:35:16 GMT</submition_time><delivery_time>Tue, 30 Oct 2001 22:34:00 GMT</delivery_time></sms_delivery_receipt>"
+//And here's a failure:
+//"<sms_delivery_receipt><message_id>[my uin]-1-1955988055-[destination phone#, without leading +]</message_id><destination>[destination phone#, without leading +]</destination><delivered>No</delivered><submition_time>Tue, 23 Oct 2001 23:17:02 GMT</submition_time><error_code>999999</error_code><error><id>15</id><params><param>0</param><param>Multiple message submittion failed</param></params></error></sms_delivery_receipt>"
+
+//SMSes received from phones come through this same ack, again to avoid having
+//an XML parser in the protocol module. Here's one I got:
+//"<sms_message><source>MTN</source><destination_UIN>[UIN of recipient, ie this account]</destination_UIN><sender>[sending phone number, without +]</sender><senders_network>[contains one space, because I sent from ICQ]</senders_network><text>[body of the message]</text><time>Fri, 16 Nov 2001 03:12:33 GMT</time></sms_message>"
+#define ICQACKTYPE_SMS 1001
+#define ICQEVENTTYPE_SMS 2001 //database event type
+#define MS_ICQ_SENDSMS "/SendSMS"
+
+//e-mail express
+//db event added to NULL contact
+//blob format is:
+//ASCIIZ text, usually of the form "Subject: %s\r\n%s"
+//ASCIIZ from name
+//ASCIIZ from e-mail
+#define ICQEVENTTYPE_EMAILEXPRESS 2002 //database event type
+
+//www pager
+//db event added to NULL contact
+//blob format is:
+//ASCIIZ text, usually "Sender IP: xxx.xxx.xxx.xxx\r\n%s"
+//ASCIIZ from name
+//ASCIIZ from e-mail
+#define ICQEVENTTYPE_WEBPAGER 2003 //database event type
+
+//for server-side lists, used internally only
+//hProcess=dwSequence
+//lParam=server's error code, 0 for success
+#define ICQACKTYPE_SERVERCLIST 1003
+
+//for rate warning distribution (mainly upload dlg)
+//hProcess=Rate class ID
+//lParam=server's status code
+#define ICQACKTYPE_RATEWARNING 1004
+
+//received Xtraz Notify response
+//hProcess=dwSequence
+//lParam=contents of RES node
+#define ICQACKTYPE_XTRAZNOTIFY_RESPONSE 1005
+
+//received Custom Status details response
+//hProcess=dwSequence
+//lParam=0
+#define ICQACKTYPE_XSTATUS_RESPONSE 1006
+
+
+//Update user details on server
+//Permited operation types:
+#define CIXT_BASIC 0x0001
+#define CIXT_MORE 0x0002
+#define CIXT_WORK 0x0004
+#define CIXT_CONTACT 0x0008
+#define CIXT_LOCATION 0x0010
+#define CIXT_BACKGROUND 0x0020
+#define CIXT_FULL 0x003F
+//wParam=operationType
+#define PS_CHANGEINFOEX "/ChangeInfoEx"
+
+//Change nickname in White pages
+//lParam=(LPARAM)(const char*)szNewNickName
+#define PS_SET_NICKNAME "/SetNickname"
+
+
+//miranda/icqoscar/statusmsgreq event
+//called when our status message is requested
+//wParam=(BYTE)msgType
+//lParam=(DWORD)uin
+//msgType is one of the ICQ_MSGTYPE_GET###MSG constants in icq_constants.h
+//uin is the UIN of the contact requesting our status message
+#define ME_ICQ_STATUSMSGREQ "/StatusMsgReq"
+
+
+//set owner avatar
+//wParam=0
+//lParam=(const char *)Avatar file name
+//return=0 for success
+#define PS_ICQ_SETMYAVATAR "/SetMyAvatar"
+
+//get current owner avatar
+//wParam=(char *)Buffer to file name
+//lParam=(int)Buffer size
+//return=0 for success
+#define PS_ICQ_GETMYAVATAR "/GetMyAvatar"
+
+//get size limit for avatar image
+//wParam=(int *)max width of avatar - will be set
+//lParam=(int *)max height of avatar - will be set
+//return=0 for success
+#define PS_ICQ_GETMYAVATARMAXSIZE "/GetMyAvatarMaxSize"
+
+//check if image format supported for avatars
+//wParam = 0
+//lParam = PA_FORMAT_* // avatar format
+//return = 1 (supported) or 0 (not supported)
+#define PS_ICQ_ISAVATARFORMATSUPPORTED "/IsAvatarFormatSupported"
+
+
+/* Custom Status helper API *
+ - to set custom status message & title use PS_ICQ_GETCUSTOMSTATUS to obtain
+ DB settings and write values to them (UTF-8 strings best). (obsolete)
+ - use PS_ICQ_GETCUSTOMSTATUSEX and PS_ICQ_SETCUSTOMSTATUSEX for controling Custom Status
+ - custom messages for each user supported - ME_ICQ_STATUSMSGREQ with type MTYPE_SCRIPT_NOTIFY
+ */
+#define CSSF_MASK_STATUS 0x0001 // status member valid for set/get
+#define CSSF_MASK_NAME 0x0002 // pszName member valid for set/get
+#define CSSF_MASK_MESSAGE 0x0004 // pszMessage member valid for set/get
+#define CSSF_DISABLE_UI 0x0040 // disable default custom status UI, wParam = bEnable
+#define CSSF_DEFAULT_NAME 0x0080 // only with CSSF_MASK_NAME and get API to get default custom status name (wParam = status)
+#define CSSF_STATUSES_COUNT 0x0100 // returns number of custom statuses in wParam, only get API
+#define CSSF_STR_SIZES 0x0200 // returns sizes of custom status name & message (wParam & lParam members) in chars
+#define CSSF_UNICODE 0x1000 // strings are in UCS-2
+
+#if defined(_UNICODE)
+ #define CSSF_TCHAR CSSF_UNICODE
+#else
+ #define CSSF_TCHAR 0
+#endif
+
+
+typedef struct {
+ int cbSize; // size of the structure
+ int flags; // combination of CSSF_*
+ int *status; // custom status id
+ union {
+ char *pszName; // buffer for custom status name
+ TCHAR *ptszName;
+ WCHAR *pwszName;
+ };
+ union {
+ char *pszMessage; // buffer for custom status message
+ TCHAR *ptszMessage;
+ WCHAR *pwszMessage;
+ };
+ WPARAM *wParam; // extra params, see flags
+ LPARAM *lParam;
+} ICQ_CUSTOM_STATUS;
+
+
+// Sets owner current custom status (obsolete)
+//wParam = (int)N // custom status id (1-32)
+//lParam = 0
+//return = N (id of status set) or 0 (failed - probably bad params)
+#define PS_ICQ_SETCUSTOMSTATUS "/SetXStatus"
+
+// Sets owner current custom status
+//wParam = 0 // reserved
+//lParam = (ICQ_CUSTOM_STATUS*)pData // contains what to set and new values
+//return = 0 (for success)
+#define PS_ICQ_SETCUSTOMSTATUSEX "/SetXStatusEx"
+
+// Retrieves custom status details for specified hContact
+//wParam = (HANDLE)hContact
+//lParam = (ICQ_CUSTOM_STATUS*)pData // receives details (members must be prepared)
+//return = 0 (for success)
+#define PS_ICQ_GETCUSTOMSTATUSEX "/GetXStatusEx"
+
+// Retrieves specified custom status icon
+//wParam = (int)N // custom status id (1-32), 0 = my current custom status
+//lParam = 0
+//return = HICON // custom status icon (use DestroyIcon to release resources)
+#define PS_ICQ_GETCUSTOMSTATUSICON "/GetXStatusIcon"
+
+// Get Custom status DB field names & current owner custom status (obsolete)
+//wParam = (char**)szDBTitle // will receive title DB setting name (do not free)
+//lParam = (char**)szDBMsg // will receive message DB setting name
+//return = N // current custom status id if successful, 0 otherwise
+#define PS_ICQ_GETCUSTOMSTATUS "/GetXStatus"
+
+// Request Custom status details (messages) for specified contact
+//wParam = hContact // request custom status details for this contact
+//lParam = 0
+//return = (int)dwSequence // if successful it is sequence for ICQACKTYPE_XSTATUS_RESPONSE
+ // 0 failed to request (e.g. auto-request enabled)
+ // -1 delayed (rate control) - sequence unknown
+#define PS_ICQ_REQUESTCUSTOMSTATUS "/RequestXStatusDetails"
+
+// Called when contact changes custom status and extra icon is set to clist_mw
+//wParam = hContact // contact changing status
+//lParam = hIcon // HANDLE to clist extra icon set as custom status
+#define ME_ICQ_CUSTOMSTATUS_EXTRAICON_CHANGED "/XStatusExtraIconChanged"
diff --git a/icqj_mod/m_popupw.h b/icqj_mod/m_popupw.h new file mode 100644 index 0000000..c0cac41 --- /dev/null +++ b/icqj_mod/m_popupw.h @@ -0,0 +1,56 @@ +/*
+===============================================================================
+ PopUp plugin
+Plugin Name: PopUp
+Plugin authors: Luca Santarelli aka hrk (hrk@users.sourceforge.net)
+ Victor Pavlychko aka zazoo (nullbie@gmail.com)
+===============================================================================
+The purpose of this plugin is to give developers a common "platform/interface"
+to show PopUps. It is born from the source code of NewStatusNotify, another
+plugin I've made.
+
+Remember that users *must* have this plugin enabled, or they won't get any
+popup. Write this in the requirements, do whatever you wish ;-)... but tell
+them!
+===============================================================================
+*/
+#ifndef M_POPUPW_H
+#define M_POPUPW_H
+
+#ifndef MAX_CONTACTNAME
+ #define MAX_CONTACTNAME 2048
+#endif
+
+#ifndef MAX_SECONDLINE
+ #define MAX_SECONDLINE 2048
+#endif
+
+// Unicode Popup Info
+typedef struct {
+ HANDLE lchContact;
+ HICON lchIcon;
+ WCHAR lpwzContactName[MAX_CONTACTNAME];
+ WCHAR lpwzText[MAX_SECONDLINE];
+ COLORREF colorBack;
+ COLORREF colorText;
+ WNDPROC PluginWindowProc;
+ void * PluginData;
+ int iSeconds; //Custom delay time in seconds. -1 means "forever", 0 means "default time".
+ char cZero[16]; //some unused bytes which may come useful in the future.
+} POPUPDATAW, *LPPOPUPDATAW;
+
+// Create Popup
+#define MS_POPUP_ADDPOPUPW "PopUp/AddPopUpW"
+
+static int __inline PUAddPopUpW(POPUPDATAW* ppdp) {
+ return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)ppdp,0);
+}
+
+// Change Text
+#define MS_POPUP_CHANGETEXTW "PopUp/ChangetextW"
+
+static int __inline PUChangeTextW(HWND hWndPopUp, LPCWSTR lpwzNewText) {
+ return (int)CallService(MS_POPUP_CHANGETEXTW, (WPARAM)hWndPopUp, (LPARAM)lpwzNewText);
+}
+
+#endif
diff --git a/icqj_mod/m_updater.h b/icqj_mod/m_updater.h new file mode 100644 index 0000000..c83b8a4 --- /dev/null +++ b/icqj_mod/m_updater.h @@ -0,0 +1,117 @@ +#ifndef _M_UPDATER_H
+#define _M_UPDATER_H
+
+// if you set Update::szUpdateURL to the following value when registering, as well as setting your beta site and version data,
+// updater will ignore szVersionURL and pbVersionPrefix, and attempt to find the file listing URL's from the backend XML data.
+// for this to work, the plugin name in pluginInfo.shortName must match the file listing exactly (except for case)
+#define UPDATER_AUTOREGISTER "UpdaterAUTOREGISTER"
+
+typedef struct Update_tag {
+ int cbSize;
+ char *szComponentName; // component name as it will appear in the UI (will be translated before displaying)
+
+ char *szVersionURL; // URL where the current version can be found (NULL to disable)
+ BYTE *pbVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data
+ // (not that this URL could point at a binary file - dunno why, but it could :)
+ int cpbVersionPrefix; // number of bytes pionted to by pbVersionPrefix
+ char *szUpdateURL; // URL where dll/zip is located
+ // set to UPDATER_AUTOREGISTER if you want updater to find the file listing URLs (ensure plugin shortName matches file listing!)
+
+ char *szBetaVersionURL; // URL where the beta version can be found (NULL to disable betas)
+ BYTE *pbBetaVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data
+ int cpbBetaVersionPrefix; // number of bytes pionted to by pbVersionPrefix
+ char *szBetaUpdateURL; // URL where dll/zip is located
+
+ BYTE *pbVersion; // bytes of current version, used for comparison with those in VersionURL
+ int cpbVersion; // number of bytes pionted to by pbVersion
+
+ char *szBetaChangelogURL; // url for displaying changelog for beta versions
+} Update;
+
+// register a comonent with the updater
+//
+// wparam = 0
+// lparam = (LPARAM)&Update
+#define MS_UPDATE_REGISTER "Update/Register"
+
+// utility functions to create a version string from a DWORD or from pluginInfo
+// point buf at a buffer at least 16 chars wide - but note the version string returned may be shorter
+//
+__inline static char *CreateVersionString(DWORD version, char *buf) {
+ mir_snprintf(buf, 16, "%d.%d.%d.%d", (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF);
+ return buf;
+}
+
+__inline static char *CreateVersionStringPlugin(PLUGININFO *pluginInfo, char *buf) {
+ return CreateVersionString(pluginInfo->version, buf);
+}
+
+
+// register the 'easy' way - use this method if you have no beta URL and the plugin is on the miranda file listing
+// NOTE: the plugin 'short name' in pluginInfo must match the name of the plugin on the file listing, exactly (not including case)
+// AND the plugin version string on the file listing must be the string version of the version in pluginInfo (i.e. 0.0.0.1,
+// so no letters, brackets, etc.)
+//
+// wParam = (int)fileID - this is the file ID from the file listing (i.e. the number at the end of the download link)
+// lParam = (PLUGININFO*)&pluginInfo
+#define MS_UPDATE_REGISTERFL "Update/RegisterFL"
+
+// this event is fired when the startup process is complete, but NOT if a restart is imminent
+// it is designed for status managment plugins to use as a trigger for beggining their own startup process
+// wParam = lParam = 0 (unused)
+// (added in version 0.1.6.0)
+#define ME_UPDATE_STARTUPDONE "Update/StartupDone"
+
+// this service can be used to enable/disable Updater's global status control
+// it can be called from the StartupDone event handler
+// wParam = (BOOL)enable
+// lParam = 0
+// (added in version 0.1.6.0)
+#define MS_UPDATE_ENABLESTATUSCONTROL "Update/EnableStatusControl"
+
+// An description of usage of the above service and event:
+// Say you are a status control plugin that normally sets protocol or global statuses in your ModulesLoaded event handler.
+// In order to make yourself 'updater compatible', you would move the status control code from ModulesLoaded to another function,
+// say DoStartup. Then, in ModulesLoaded you would check for the existence of the MS_UPDATE_ENABLESTATUSCONTROL service.
+// If it does not exist, call DoStartup. If it does exist, hook the ME_UPDATE_STARTUPDONE event and call DoStartup from there. You may
+// also wish to call MS_UPDATE_ENABLESTATUSCONTROL with wParam == FALSE at this time, to disable Updater's own status control feature.
+
+#endif
+
+
+/////////////// Usage Example ///////////////
+
+#ifdef EXAMPLE_CODE
+
+// you need to #include "m_updater.h" and HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded) in your Load function...
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam) {
+
+ Update update = {0}; // for c you'd use memset or ZeroMemory...
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionString(&pluginInfo, szVersion);
+ update.cpbVersion = strlen((char *)update.pbVersion);
+
+ // these are the three lines that matter - the archive, the page containing the version string, and the text (or data)
+ // before the version that we use to locate it on the page
+ // (note that if the update URL and the version URL point to standard file listing entries, the backend xml
+ // data will be used to check for updates rather than the actual web page - this is not true for beta urls)
+ update.szUpdateURL = "http://scottellis.com.au:81/test/updater.zip";
+ update.szVersionURL = "http://scottellis.com.au:81/test/updater_test.html";
+ update.pbVersionPrefix = (BYTE *)"Updater version ";
+
+ update.cpbVersionPrefix = strlen((char *)update.pbVersionPrefix);
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+
+ // Alternatively, to register a plugin with e.g. file ID 2254 on the file listing...
+ // CallService(MS_UPDATE_REGISTERFL, (WPARAM)2254, (LPARAM)&pluginInfo);
+
+ return 0;
+}
+
+#endif
diff --git a/icqj_mod/md5.c b/icqj_mod/md5.c new file mode 100644 index 0000000..fb2fc84 --- /dev/null +++ b/icqj_mod/md5.c @@ -0,0 +1,352 @@ +/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.c 2874 2006-05-16 21:38:00Z ghazan $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+ either statically or dynamically; added missing #include <string.h>
+ in library.
+ 2002-03-11 lpd Corrected argument list for main(), and added int return
+ type, in test program and T value program.
+ 2002-02-21 lpd Added missing #include <stdio.h> in test program.
+ 2000-07-03 lpd Patched to eliminate warnings about "constant is
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+// (C) 2005 Joe @ Whale - changed to compile with Miranda
+
+#include "icqoscar.h"
+
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+//gfd*
+static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+
+ {
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+ else /* dynamic big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
+
+ X = xbuf; /* (dynamic only) */
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+ }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET1(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET1(a, b, c, d, 0, 7, T1);
+ SET1(d, a, b, c, 1, 12, T2);
+ SET1(c, d, a, b, 2, 17, T3);
+ SET1(b, c, d, a, 3, 22, T4);
+ SET1(a, b, c, d, 4, 7, T5);
+ SET1(d, a, b, c, 5, 12, T6);
+ SET1(c, d, a, b, 6, 17, T7);
+ SET1(b, c, d, a, 7, 22, T8);
+ SET1(a, b, c, d, 8, 7, T9);
+ SET1(d, a, b, c, 9, 12, T10);
+ SET1(c, d, a, b, 10, 17, T11);
+ SET1(b, c, d, a, 11, 22, T12);
+ SET1(a, b, c, d, 12, 7, T13);
+ SET1(d, a, b, c, 13, 12, T14);
+ SET1(c, d, a, b, 14, 17, T15);
+ SET1(b, c, d, a, 15, 22, T16);
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET2(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET2(a, b, c, d, 1, 5, T17);
+ SET2(d, a, b, c, 6, 9, T18);
+ SET2(c, d, a, b, 11, 14, T19);
+ SET2(b, c, d, a, 0, 20, T20);
+ SET2(a, b, c, d, 5, 5, T21);
+ SET2(d, a, b, c, 10, 9, T22);
+ SET2(c, d, a, b, 15, 14, T23);
+ SET2(b, c, d, a, 4, 20, T24);
+ SET2(a, b, c, d, 9, 5, T25);
+ SET2(d, a, b, c, 14, 9, T26);
+ SET2(c, d, a, b, 3, 14, T27);
+ SET2(b, c, d, a, 8, 20, T28);
+ SET2(a, b, c, d, 13, 5, T29);
+ SET2(d, a, b, c, 2, 9, T30);
+ SET2(c, d, a, b, 7, 14, T31);
+ SET2(b, c, d, a, 12, 20, T32);
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET3(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET3(a, b, c, d, 5, 4, T33);
+ SET3(d, a, b, c, 8, 11, T34);
+ SET3(c, d, a, b, 11, 16, T35);
+ SET3(b, c, d, a, 14, 23, T36);
+ SET3(a, b, c, d, 1, 4, T37);
+ SET3(d, a, b, c, 4, 11, T38);
+ SET3(c, d, a, b, 7, 16, T39);
+ SET3(b, c, d, a, 10, 23, T40);
+ SET3(a, b, c, d, 13, 4, T41);
+ SET3(d, a, b, c, 0, 11, T42);
+ SET3(c, d, a, b, 3, 16, T43);
+ SET3(b, c, d, a, 6, 23, T44);
+ SET3(a, b, c, d, 9, 4, T45);
+ SET3(d, a, b, c, 12, 11, T46);
+ SET3(c, d, a, b, 15, 16, T47);
+ SET3(b, c, d, a, 2, 23, T48);
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET4(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET4(a, b, c, d, 0, 6, T49);
+ SET4(d, a, b, c, 7, 10, T50);
+ SET4(c, d, a, b, 14, 15, T51);
+ SET4(b, c, d, a, 5, 21, T52);
+ SET4(a, b, c, d, 12, 6, T53);
+ SET4(d, a, b, c, 3, 10, T54);
+ SET4(c, d, a, b, 10, 15, T55);
+ SET4(b, c, d, a, 1, 21, T56);
+ SET4(a, b, c, d, 8, 6, T57);
+ SET4(d, a, b, c, 15, 10, T58);
+ SET4(c, d, a, b, 6, 15, T59);
+ SET4(b, c, d, a, 13, 21, T60);
+ SET4(a, b, c, d, 4, 6, T61);
+ SET4(d, a, b, c, 11, 10, T62);
+ SET4(c, d, a, b, 2, 15, T63);
+ SET4(b, c, d, a, 9, 21, T64);
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset)
+ {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/icqj_mod/md5.h b/icqj_mod/md5.h new file mode 100644 index 0000000..d3fd8bb --- /dev/null +++ b/icqj_mod/md5.h @@ -0,0 +1,82 @@ +/*
+ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.h 2874 2006-05-16 21:38:00Z ghazan $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Removed support for non-ANSI compilers; removed
+ references to Ghostscript; clarified derivation from RFC 1321;
+ now handles byte order either statically or dynamically.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#endif /* md5_INCLUDED */
diff --git a/icqj_mod/resource.h b/icqj_mod/resource.h new file mode 100644 index 0000000..ffc6051 --- /dev/null +++ b/icqj_mod/resource.h @@ -0,0 +1,236 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resources.rc
+//
+#define ID_FIRSTICON 1
+#define IDI_ICQ 101
+#define IDD_ICQACCOUNT 102
+#define IDD_ASKAUTH 103
+#define IDD_LOGINPW 104
+#define IDD_INFO_AVATAR 105
+#define IDD_OPT_ICQMAIN 106
+#define IDD_OPT_ICQFEATURES 107
+#define IDS_IDENTIFY 108
+#define IDI_PRIVACY 111
+#define IDD_OPT_ICQPRIVACY 111
+#define IDI_DOT 112
+#define IDI_CHECK 113
+#define IDI_LIST 114
+#define IDI_SCAN 121
+#define IDI_START 122
+#define IDI_PAUSE 123
+#define IDI_STOP 124
+#define IDI_HIDDEN 125
+#define IDI_AUTH 131
+#define IDI_GRANT 132
+#define IDI_REMOVE 133
+#define IDI_SET_VIS 134
+#define IDI_SET_INVIS 135
+#define IDI_ICON2 141
+#define IDD_CONFIRM 151
+#define IDD_OPT_ICQ 152
+#define ID_LASTICON 199
+#define IDI_XSTATUS1 201
+#define IDI_XSTATUS2 202
+#define IDI_XSTATUS3 203
+#define IDI_XSTATUS4 204
+#define IDI_XSTATUS5 205
+#define IDI_XSTATUS6 206
+#define IDI_XSTATUS7 207
+#define IDI_XSTATUS8 208
+#define IDI_XSTATUS9 209
+#define IDI_XSTATUS10 210
+#define IDI_XSTATUS11 211
+#define IDI_XSTATUS12 212
+#define IDI_XSTATUS13 213
+#define IDI_XSTATUS14 214
+#define IDI_XSTATUS15 215
+#define IDI_XSTATUS16 216
+#define IDI_XSTATUS17 217
+#define IDI_XSTATUS18 218
+#define IDI_XSTATUS19 219
+#define IDI_XSTATUS20 220
+#define IDI_XSTATUS21 221
+#define IDI_XSTATUS22 222
+#define IDI_XSTATUS23 223
+#define IDI_XSTATUS24 224
+#define IDI_XSTATUS25 225
+#define IDI_XSTATUS26 226
+#define IDI_XSTATUS27 227
+#define IDI_XSTATUS28 228
+#define IDI_XSTATUS29 229
+#define IDI_XSTATUS30 230
+#define IDI_XSTATUS31 231
+#define IDI_XSTATUS32 232
+#define IDD_INFO_ICQ 240
+#define IDD_ICQADVANCEDSEARCH 242
+#define IDD_OPT_ICQCONTACTS 252
+#define IDD_ICQUPLOADLIST 253
+#define IDD_SETXSTATUS 256
+#define IDD_PWCONFIRM 300
+#define IDD_INFO_CHANGEINFO 301
+#define IDD_OPT_POPUPS 400
+#define IDC_POPUPS_ENABLED 410
+#define IDC_POPUPS_LOG_ENABLED 411
+#define IDC_POPUPS_SPAM_ENABLED 412
+#define IDC_POPUP_LOG0_TEXTCOLOR 420
+#define IDC_POPUP_LOG1_TEXTCOLOR 421
+#define IDC_POPUP_LOG2_TEXTCOLOR 422
+#define IDC_POPUP_LOG3_TEXTCOLOR 423
+#define IDC_POPUP_SPAM_TEXTCOLOR 425
+#define IDC_POPUP_LOG0_BACKCOLOR 430
+#define IDC_POPUP_LOG1_BACKCOLOR 431
+#define IDC_POPUP_LOG2_BACKCOLOR 432
+#define IDC_POPUP_LOG3_BACKCOLOR 433
+#define IDC_POPUP_SPAM_BACKCOLOR 435
+#define IDC_POPUP_LOG0_TIMEOUT 440
+#define IDC_POPUP_LOG1_TIMEOUT 441
+#define IDC_POPUP_LOG2_TIMEOUT 442
+#define IDC_POPUP_LOG3_TIMEOUT 443
+#define IDC_POPUP_SPAM_TIMEOUT 444
+#define IDC_USEWINCOLORS 450
+#define IDC_USESYSICONS 451
+#define IDC_PREVIEW 455
+#define IDC_POPUP_LOG4_TEXTCOLOR 456
+#define IDC_POPUP_LOG5_TEXTCOLOR 457
+#define IDC_POPUP_LOG4_BACKCOLOR 458
+#define IDC_POPUP_LOG5_BACKCOLOR 459
+#define IDC_POPUP_LOG4_TIMEOUT 460
+#define IDC_POPUP_LOG5_TIMEOUT 461
+#define IDC_OPTIONSTAB 500
+#define IDC_LOG 1001
+#define IDI_EXPANDSTRINGEDIT 1001
+#define IDC_SAVEPASS 1004
+#define IDC_RETRXSTATUS 1005
+#define IDC_FLAGSTEXT 1008
+#define IDC_SECURE 1009
+#define IDC_USEGATEWAY 1010
+#define IDC_UTFENABLE 1010
+#define IDC_XTITLE 1010
+#define IDC_FLAGS 1010
+#define IDC_KEEPALIVE 1011
+#define IDC_XMSG 1011
+#define IDC_UTFALL 1012
+#define IDC_UTFSTATIC 1013
+#define IDC_UTFCODEPAGE 1014
+#define IDC_PW 1015
+#define IDC_TEMPVISIBLE 1015
+#define IDC_REGISTER 1016
+#define IDC_EDITAUTH 1017
+#define IDC_LOGINPW 1018
+#define IDC_INSTRUCTION 1019
+#define IDC_PASSWORD 1020
+#define IDC_SUPTIME 1020
+#define IDC_DCENABLE 1020
+#define IDC_DCPASSIVE 1021
+#define IDC_OLDPASS 1021
+#define IDC_ICQNUM 1022
+#define IDC_AVATAR 1023
+#define IDC_SETAVATAR 1024
+#define IDC_RETRIEVE 1024
+#define IDC_DELETEAVATAR 1025
+#define IDC_AIMENABLE 1030
+#define IDC_GETSTATUS 1030
+#define IDC_CLIST 1035
+#define IDC_XSTATUSENABLE 1040
+#define IDC_XSTATUSAUTO 1041
+#define IDC_XSTATUSRESET 1042
+#define IDC_KILLSPAMBOTS 1045
+#define IDC_EMAIL 1048
+#define IDC_NICK 1053
+#define IDC_GENDER 1060
+#define IDC_CITY 1061
+#define IDC_STATE 1062
+#define IDC_COUNTRY 1063
+#define IDC_COMPANY 1066
+#define IDC_DEPARTMENT 1067
+#define IDC_POSITION 1069
+#define IDC_IP 1094
+#define IDC_UINSTATIC 1122
+#define IDC_UIN 1123
+#define IDC_STATIC11 1154
+#define IDC_STATIC12 1155
+#define IDC_ICQSERVER 1171
+#define IDC_ICQPORT 1172
+#define IDC_VERSION 1179
+#define IDC_FIRSTNAME 1224
+#define IDC_LASTNAME 1225
+#define IDC_REALIP 1230
+#define IDC_RECONNECTREQD 1239
+#define IDC_OFFLINETOENABLE 1240
+#define IDC_PORT 1249
+#define IDC_MIRVER 1251
+#define IDC_ONLINESINCE 1252
+#define IDC_SYSTEMUPTIME 1253
+#define IDC_IDLETIME 1254
+#define IDC_STATUS 1255
+#define IDC_SLOWSEND 1301
+#define IDC_ONLYSERVERACKS 1302
+#define IDC_LOGLEVEL 1331
+#define IDC_LEVELDESCR 1332
+#define IDC_NOERRMULTI 1333
+#define IDC_STICQGROUP 1374
+#define IDC_ASD 1380
+#define IDC_AGERANGE 1410
+#define IDC_MARITALSTATUS 1411
+#define IDC_KEYWORDS 1412
+#define IDC_LANGUAGE 1414
+#define IDC_WORKFIELD 1421
+#define IDC_PASTCAT 1422
+#define IDC_PASTKEY 1423
+#define IDC_INTERESTSCAT 1424
+#define IDC_INTERESTSKEY 1425
+#define IDC_ORGANISATION 1426
+#define IDC_ORGKEYWORDS 1427
+#define IDC_OTHERGROUP 1429
+#define IDC_ONLINEONLY 1430
+#define IDC_HOMEPAGECAT 1431
+#define IDC_HOMEPAGEKEY 1432
+#define IDC_SUMMARYGROUP 1434
+#define IDC_WORKGROUP 1435
+#define IDC_LOCATIONGROUP 1436
+#define IDC_BACKGROUNDGROUP 1437
+#define IDC_NEWUINLINK 1438
+#define IDC_LOOKUPLINK 1439
+#define IDC_RESETSERVER 1472
+#define IDC_UPLOADNOW 1521
+#define IDC_GROUPS 1522
+#define IDC_ALLGROUPS 1526
+#define IDC_VISIBILITY 1527
+#define IDC_IGNORE 1528
+#define IDC_ENABLE 1529
+#define IDC_LOADFROMSERVER 1530
+#define IDC_LINKAVATARS 1531
+#define IDC_ADDSERVER 1532
+#define IDC_SAVETOSERVER 1533
+#define IDC_ENABLEAVATARS 1536
+#define IDC_AUTOLOADAVATARS 1537
+#define IDC_IGNORECHECK 1537
+#define IDC_WEBAWARE 1546
+#define IDC_DCALLOW_ANY 1547
+#define IDC_DCALLOW_CLIST 1548
+#define IDC_DCALLOW_AUTH 1549
+#define IDC_PUBLISHPRIMARY 1550
+#define IDC_ADD_ANY 1551
+#define IDC_ADD_AUTH 1552
+#define IDC_STATUSMSG_CLIST 1553
+#define IDC_STATUSMSG_VISIBLE 1554
+#define IDC_STATIC_NOTONLINE 1555
+#define IDC_STATIC_DC2 1556
+#define IDC_STATIC_DC1 1557
+#define IDC_STATIC_CLIST 1558
+#define IDC_CONFIRMATION 1560
+#define IDC_SAVE 1600
+#define IDC_LIST 1601
+#define IDC_UPLOADING 1602
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 120
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1026
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/icqj_mod/resources.rc b/icqj_mod/resources.rc new file mode 100644 index 0000000..3e7bc6f --- /dev/null +++ b/icqj_mod/resources.rc @@ -0,0 +1,531 @@ +// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICQ ICON "icos\\icq.ico"
+IDI_AUTH ICON "icos\\auth_ask.ico"
+IDI_GRANT ICON "icos\\auth_grant.ico"
+IDI_REMOVE ICON "icos\\auth_revoke.ico"
+IDI_SET_VIS ICON "icos\\set_vis.ico"
+IDI_SET_INVIS ICON "icos\\set_invis.ico"
+IDI_CHECK ICON "icos\\check.ico"
+IDI_DOT ICON "icos\\dot.ico"
+IDI_PRIVACY ICON "icos\\privacy.ico"
+IDI_START ICON "icos\\start.ico"
+IDI_STOP ICON "icos\\stop.ico"
+IDI_PAUSE ICON "icos\\pause.ico"
+IDI_HIDDEN ICON "icos\\hidden.ico"
+IDI_SCAN ICON "icos\\scan.ico"
+IDI_LIST ICON "icos\\list.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ICQACCOUNT DIALOGEX 0, 0, 200, 101
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "ICQ Account Setup"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_UIN,91,34,102,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_PW,91,54,102,13,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,87,80,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,143,80,50,14
+ CONTROL "Create new account",IDC_REGISTER,"Hyperlink",WS_TABSTOP,7,82,74,10
+ LTEXT "Please enter your ICQ account details to continue:",IDC_STATIC,7,9,186,20
+ LTEXT "ICQ number:",IDC_STATIC,21,37,65,8
+ LTEXT "Password:",IDC_STATIC,21,57,66,8
+END
+
+IDD_ASKAUTH DIALOGEX 0, 0, 186, 95
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Enter an authorization request"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "&Send",IDOK,34,74,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,98,74,50,14
+ EDITTEXT IDC_EDITAUTH,7,7,172,59,ES_AUTOHSCROLL
+END
+
+IDD_CONFIRM DIALOGEX 0, 0, 166, 60
+STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Confirmation"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CTEXT "Are you sure?",IDC_CONFIRMATION,10,9,146,25
+ DEFPUSHBUTTON "&No",IDCANCEL,94,41,50,15
+ PUSHBUTTON "&Yes",IDOK,22,41,50,15
+END
+
+IDD_LOGINPW DIALOGEX 0, 0, 157, 68
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Enter ICQ Password"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_LOGINPW,17,16,122,14,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "Remember this session password",IDC_SAVEPASS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,33,120,10
+ DEFPUSHBUTTON "OK",IDOK,25,48,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,82,48,50,14
+ LTEXT "Enter a password for UIN %d:",IDC_INSTRUCTION,7,7,142,8
+END
+
+IDD_OPT_ICQMAIN DIALOGEX 0, 0, 318, 252
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_OPTIONSTAB,"SysTabControl32",0x0,1,1,316,250
+END
+
+IDD_OPT_ICQ DIALOGEX 0, 0, 314, 236
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "ICQ",IDC_STICQGROUP,4,0,306,95
+ RTEXT "ICQ number:",IDC_STATIC11,12,14,51,8
+ EDITTEXT IDC_ICQNUM,68,12,106,12,ES_AUTOHSCROLL | ES_NUMBER
+ RTEXT "Password:",IDC_STATIC12,12,28,51,8
+ EDITTEXT IDC_PASSWORD,68,26,106,12,ES_PASSWORD | ES_AUTOHSCROLL
+ LTEXT "Hint: If you don't enter your password here, Miranda will ask for the password everytime you try to go online.",IDC_STATIC,12,43,290,19
+ CONTROL "Retrieve a lost password or ICQ number",IDC_LOOKUPLINK,
+ "Hyperlink",WS_TABSTOP,12,78,290,8
+ CONTROL "Create a new ICQ account using the ICQ website",IDC_NEWUINLINK,
+ "Hyperlink",WS_TABSTOP,12,66,290,8
+ GROUPBOX "Connection settings",IDC_STATIC,4,96,306,136
+ LTEXT "Login Server:",IDC_STATIC,12,110,55,8
+ EDITTEXT IDC_ICQSERVER,68,108,106,12,ES_AUTOHSCROLL
+ LTEXT "Port:",IDC_STATIC,182,110,25,8
+ EDITTEXT IDC_ICQPORT,208,108,29,12,ES_AUTOHSCROLL
+ PUSHBUTTON "Default",IDC_RESETSERVER,244,108,50,12
+ LTEXT "Hint: Use port 0 to connect on a random port. Try port 80 or port 443 if you are having problems connecting through a http proxy server.",IDC_STATIC,12,125,290,19
+ CONTROL "Secure (MD5) login",IDC_SECURE,"Button",BS_AUTOCHECKBOX | BS_TOP | WS_TABSTOP,12,148,290,10
+ CONTROL "Use HTTP Gateway mode for HTTP proxy",IDC_USEGATEWAY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,160,290,10
+ CONTROL "Send 'Keep-alives' (enable this if you use a proxy server and frequently get disconnected)",IDC_KEEPALIVE,
+ "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,12,172,290,18
+ CONTROL "Ignore concurrent error messages",IDC_NOERRMULTI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,192,290,10
+ LTEXT "Show connection error messages:",IDC_STATIC,12,206,238,8
+ CONTROL "Slider1",IDC_LOGLEVEL,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,18,216,52,10
+ LTEXT "",IDC_LEVELDESCR,72,216,230,8,SS_NOPREFIX
+END
+
+IDD_OPT_ICQCONTACTS DIALOGEX 0, 0, 314, 228
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "ICQ contacts stored on server",IDC_STICQGROUP,4,0,306,99
+ PUSHBUTTON "Manage server's list...",IDC_UPLOADNOW,12,77,97,14
+ CONTROL "Enable server-side contact lists *",IDC_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,15,290,10
+ CONTROL "Add contacts to the server's list when I add them to mine",IDC_ADDSERVER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,33,290,10
+ CONTROL "Update my contacts' details from the server *",IDC_LOADFROMSERVER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,46,290,10
+ CONTROL "Update contacts' details on the server's list when I change them in mine",IDC_SAVETOSERVER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,59,290,10
+ GROUPBOX "ICQ avatars",IDC_STATIC,4,100,306,53
+ CONTROL "Enable avatar support",IDC_ENABLEAVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,112,290,10
+ CONTROL "Load avatars automatically (like ICQ Lite)",IDC_AUTOLOADAVATARS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,124,290,10
+ CONTROL "Link avatars as contact photos (mToolTip photos)",IDC_LINKAVATARS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,138,290,10
+ LTEXT "You will need to reconnect to the ICQ network for the changes you have made on this page to take effect.",IDC_RECONNECTREQD,12,161,290,16,NOT WS_VISIBLE
+ LTEXT "You cannot enable/disable the server-side contact list while you are connected to the ICQ network.",IDC_OFFLINETOENABLE,12,182,290,16,NOT WS_VISIBLE
+ CTEXT "Note: The options marked with an asterisk have important side-effects or caveats that may not be initially apparent documented in the help.",IDC_STATIC,12,203,290,16
+END
+
+IDD_OPT_ICQFEATURES DIALOGEX 0, 0, 314, 236
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Messaging",IDC_STATIC,4,0,306,94
+ CONTROL "Enable unicode messaging support",IDC_UTFENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,14,290,10
+ CONTROL "Send all messages in unicode if possible",IDC_UTFALL,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,26,290,10
+ RTEXT "Use this codepage for Ansi <-> Unicode translation :",IDC_UTFSTATIC,12,40,174,10
+ COMBOBOX IDC_UTFCODEPAGE,190,38,107,51,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Make me temporarily visible to contacts I send message to",IDC_TEMPVISIBLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,53,290,10
+ CONTROL "Notify me when a message delivery has failed (recommended)",IDC_SLOWSEND,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,65,290,10
+ CONTROL "Use only server's acknowledgement (faster)",IDC_ONLYSERVERACKS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,77,290,10
+ GROUPBOX "Peer-to-peer Messaging",IDC_STATIC,4,95,306,43
+ CONTROL "Enable peer-to-peer message connections",IDC_DCENABLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,109,290,10
+ CONTROL "Passive mode, i.e. do not initiate new connections",IDC_DCPASSIVE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,121,290,10
+ GROUPBOX "Extra Features",IDC_STATIC,4,139,306,93
+ CONTROL "Enable Custom status support",IDC_XSTATUSENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,153,145,10
+ CONTROL "Reset Custom status on status change",IDC_XSTATUSRESET,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,165,290,10
+ CONTROL "Auto-retrieve Custom status details",IDC_XSTATUSAUTO,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,177,290,10
+ CONTROL "Block known Spam Bots",IDC_KILLSPAMBOTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,191,290,10
+ CONTROL "Enable AIM support",IDC_AIMENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,12,205,290,10
+ LTEXT "Note: The support is VERY limited, only messaging and status supported.",IDC_STATIC,12,217,290,10,WS_DISABLED
+ CONTROL "Enable Active Status Discovery",IDC_ASD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,153,142,10
+END
+
+IDD_OPT_ICQPRIVACY DIALOGEX 0, 0, 314, 240
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Direct connections",IDC_STATIC_DC1,7,7,300,78
+ LTEXT "Allowing direct connections will expose your IP address but may be necessary for some ICQ features to work properly.",IDC_STATIC_DC2,13,19,292,17
+ CONTROL "Allow direct connections with any user",IDC_DCALLOW_ANY,
+ "Button",BS_AUTORADIOBUTTON,24,41,281,10
+ CONTROL "Allow direct connections with users on my contact list",IDC_DCALLOW_CLIST,
+ "Button",BS_AUTORADIOBUTTON,24,54,281,10
+ CONTROL "Allow direct connections only when I authorize or initiate them",IDC_DCALLOW_AUTH,
+ "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,24,67,281,10
+ GROUPBOX "Contact List Authorization",IDC_STATIC_CLIST,7,90,300,45,WS_GROUP
+ CONTROL "All users may add me to their Contact List",IDC_ADD_ANY,
+ "Button",BS_AUTORADIOBUTTON,24,104,281,10
+ CONTROL "I want to be asked when someone wants to add me to their Contact List",IDC_ADD_AUTH,
+ "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,24,118,281,10
+ CONTROL "Allow others to view my Online / Offline status from the web (Web Aware)",IDC_WEBAWARE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,151,281,10
+ CONTROL "Allow others to view my primary e-mail address",IDC_PUBLISHPRIMARY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,167,281,10
+ CONTROL "Only reply to status message requests from users on my contact list",IDC_STATUSMSG_CLIST,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,183,281,10
+ CONTROL "Only reply to status message request from visible contacts",IDC_STATUSMSG_VISIBLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,36,199,269,10
+ GROUPBOX "Misc Settings",IDC_STATIC,7,138,300,78
+ CTEXT "Some options are greyed out because they can only be changed when you are online.",IDC_STATIC_NOTONLINE,7,222,300,8
+END
+
+IDD_OPT_POPUPS DIALOGEX 0, 0, 314, 251
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Options",IDC_STATIC,4,4,305,61
+ CONTROL "Enable popup support",IDC_POPUPS_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,19,216,10
+ CONTROL "Display errors using popups",IDC_POPUPS_LOG_ENABLED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,37,216,10
+ CONTROL "Display popup when spambot is detected",IDC_POPUPS_SPAM_ENABLED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,50,216,10
+ GROUPBOX "Look && Feel",IDC_STATIC,4,71,305,163
+ LTEXT "Back Color",IDC_STATIC,80,79,42,8
+ LTEXT "Text Color",IDC_STATIC,130,79,40,8
+ LTEXT "Timeout (*)",IDC_STATIC,182,79,60,8
+ LTEXT "Note",IDC_STATIC,12,91,60,8
+ CONTROL "",IDC_POPUP_LOG0_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,90,39,10
+ CONTROL "",IDC_POPUP_LOG0_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,90,39,10
+ EDITTEXT IDC_POPUP_LOG0_TIMEOUT,182,89,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Warning",IDC_STATIC,12,106,60,8
+ CONTROL "",IDC_POPUP_LOG1_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,105,39,10
+ CONTROL "",IDC_POPUP_LOG1_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,105,39,10
+ EDITTEXT IDC_POPUP_LOG1_TIMEOUT,182,104,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Error",IDC_STATIC,12,121,60,8
+ CONTROL "",IDC_POPUP_LOG2_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,120,39,10
+ CONTROL "",IDC_POPUP_LOG2_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,120,39,10
+ EDITTEXT IDC_POPUP_LOG2_TIMEOUT,182,119,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Fatal",IDC_STATIC,12,136,60,8
+ CONTROL "",IDC_POPUP_LOG3_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,135,39,10
+ CONTROL "",IDC_POPUP_LOG3_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,135,39,10
+ EDITTEXT IDC_POPUP_LOG3_TIMEOUT,182,134,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Spam detected",IDC_STATIC,12,151,60,8
+ CONTROL "",IDC_POPUP_SPAM_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,150,39,10
+ CONTROL "",IDC_POPUP_SPAM_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,150,39,10
+ EDITTEXT IDC_POPUP_SPAM_TIMEOUT,182,149,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "&Use Windows colors",IDC_USEWINCOLORS,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,12,194,220,8
+ CONTROL "Use system &icons",IDC_USESYSICONS,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,12,207,220,8
+ DEFPUSHBUTTON "Previe&w",IDC_PREVIEW,247,203,52,12
+ LTEXT "(*) Timeouts require Popup v. 1.0.1.9 or later",IDC_STATIC,12,221,232,8
+ LTEXT "User Found",IDC_STATIC,12,167,60,8
+ CONTROL "",IDC_POPUP_LOG4_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,165,39,10
+ CONTROL "",IDC_POPUP_LOG4_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,165,39,10
+ EDITTEXT IDC_POPUP_LOG4_TIMEOUT,182,165,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Active Status Scan",IDC_STATIC,12,182,60,8
+ CONTROL "",IDC_POPUP_LOG5_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,180,39,10
+ CONTROL "",IDC_POPUP_LOG5_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,180,39,10
+ EDITTEXT IDC_POPUP_LOG5_TIMEOUT,182,180,34,12,ES_AUTOHSCROLL | ES_NUMBER
+END
+
+IDD_INFO_ICQ DIALOGEX 0, 0, 223, 146
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "UIN:",IDC_UINSTATIC,5,5,71,8
+ EDITTEXT IDC_UIN,74,5,63,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "External IP:",IDC_STATIC,5,16,71,8
+ EDITTEXT IDC_IP,74,16,62,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Internal IP:",IDC_STATIC,5,27,71,8
+ EDITTEXT IDC_REALIP,74,27,62,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Port:",IDC_STATIC,5,39,71,8
+ EDITTEXT IDC_PORT,74,39,62,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Protocol Version:",IDC_STATIC,5,50,71,8
+ EDITTEXT IDC_VERSION,74,50,61,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "User Client:",IDC_STATIC,5,61,71,8
+ EDITTEXT IDC_MIRVER,74,61,141,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Online since:",IDC_STATIC,5,72,71,8
+ EDITTEXT IDC_ONLINESINCE,74,72,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "System up since:",IDC_SUPTIME,5,83,71,8
+ EDITTEXT IDC_SYSTEMUPTIME,74,83,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Idle since:",IDC_STATIC,5,94,71,8
+ EDITTEXT IDC_IDLETIME,74,94,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Status:",IDC_STATIC,5,105,71,8
+ EDITTEXT IDC_STATUS,74,105,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ PUSHBUTTON "&Check Status",IDC_GETSTATUS,137,4,80,12,NOT WS_VISIBLE
+ PUSHBUTTON "&Retrieve IP",IDC_RETRIEVE,137,17,80,12,NOT WS_VISIBLE
+ PUSHBUTTON "&Ignore Check",IDC_IGNORECHECK,137,30,80,12,NOT WS_VISIBLE
+ LTEXT "Flags:",IDC_FLAGS,5,116,65,8
+ EDITTEXT IDC_FLAGSTEXT,74,116,143,29,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ CTEXT "",IDC_IGNORE,140,44,77,8
+ LTEXT "Status:",IDC_STATIC,5,105,70,8
+END
+
+IDD_ICQADVANCEDSEARCH DIALOGEX 0, 0, 335, 247
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_BORDER
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Summary",IDC_SUMMARYGROUP,8,3,156,131
+ LTEXT "Nickname:",IDC_STATIC,15,14,50,8
+ EDITTEXT IDC_NICK,65,12,91,12,ES_AUTOHSCROLL
+ LTEXT "First name:",IDC_STATIC,15,29,50,8
+ EDITTEXT IDC_FIRSTNAME,65,27,91,12,ES_AUTOHSCROLL
+ LTEXT "Last name:",IDC_STATIC,15,44,50,8
+ EDITTEXT IDC_LASTNAME,65,42,91,12,ES_AUTOHSCROLL
+ LTEXT "E-mail:",IDC_STATIC,15,59,50,8
+ EDITTEXT IDC_EMAIL,65,57,91,12,ES_AUTOHSCROLL
+ LTEXT "Gender:",IDC_STATIC,15,74,50,8
+ COMBOBOX IDC_GENDER,65,72,91,51,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Age:",IDC_STATIC,15,89,50,8
+ COMBOBOX IDC_AGERANGE,65,87,91,90,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Marital status:",IDC_STATIC,15,104,50,8
+ COMBOBOX IDC_MARITALSTATUS,65,102,91,90,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Keywords:",IDC_STATIC,15,119,50,8
+ EDITTEXT IDC_KEYWORDS,65,117,91,12,ES_AUTOHSCROLL
+ GROUPBOX "Work",IDC_WORKGROUP,8,138,156,102
+ LTEXT "Occupation:",IDC_STATIC,15,149,50,8
+ COMBOBOX IDC_WORKFIELD,65,147,91,93,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Company:",IDC_STATIC,15,164,50,8
+ EDITTEXT IDC_COMPANY,65,162,91,12,ES_AUTOHSCROLL
+ LTEXT "Department:",IDC_STATIC,15,179,50,8
+ EDITTEXT IDC_DEPARTMENT,65,177,91,12,ES_AUTOHSCROLL
+ LTEXT "Position:",IDC_STATIC,15,194,50,8
+ EDITTEXT IDC_POSITION,65,192,91,12,ES_AUTOHSCROLL
+ LTEXT "Organisation:",IDC_STATIC,15,209,50,8
+ COMBOBOX IDC_ORGANISATION,65,207,91,99,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Keywords:",IDC_STATIC,24,224,41,8
+ EDITTEXT IDC_ORGKEYWORDS,65,222,91,12,ES_AUTOHSCROLL
+ GROUPBOX "Location",IDC_LOCATIONGROUP,171,3,156,72
+ LTEXT "Language:",IDC_STATIC,178,14,50,8
+ COMBOBOX IDC_LANGUAGE,228,12,91,113,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Country:",IDC_STATIC,178,29,50,8
+ COMBOBOX IDC_COUNTRY,228,27,91,172,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "State:",IDC_STATIC,178,44,50,8
+ EDITTEXT IDC_STATE,228,42,91,12,ES_AUTOHSCROLL
+ LTEXT "City:",IDC_STATIC,178,59,50,8
+ EDITTEXT IDC_CITY,228,57,91,12,ES_AUTOHSCROLL
+ GROUPBOX "Background",IDC_BACKGROUNDGROUP,171,79,156,116
+ LTEXT "Interests",IDC_STATIC,178,90,50,8
+ LTEXT "Category:",IDC_STATIC,188,101,40,8
+ COMBOBOX IDC_INTERESTSCAT,228,99,91,95,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Keywords:",IDC_STATIC,188,116,40,8
+ EDITTEXT IDC_INTERESTSKEY,228,114,91,12,ES_AUTOHSCROLL
+ LTEXT "Past",IDC_STATIC,178,129,50,8
+ LTEXT "Category:",IDC_STATIC,188,140,40,8
+ COMBOBOX IDC_PASTCAT,228,138,91,97,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Keywords:",IDC_STATIC,188,155,40,8
+ EDITTEXT IDC_PASTKEY,228,153,91,12,ES_AUTOHSCROLL
+ LTEXT "Homepage",IDC_STATIC,178,168,50,8
+ LTEXT "Category:",IDC_STATIC,188,179,40,8,NOT WS_VISIBLE
+ COMBOBOX IDC_HOMEPAGECAT,228,177,91,56,CBS_DROPDOWNLIST | CBS_SORT | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Keywords:",IDC_STATIC,188,179,40,8
+ EDITTEXT IDC_HOMEPAGEKEY,228,177,91,12,ES_AUTOHSCROLL
+ GROUPBOX "Other",IDC_OTHERGROUP,171,199,156,41
+ CONTROL "Search online users only",IDC_ONLINEONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,217,140,10
+END
+
+IDD_INFO_AVATAR DIALOGEX 0, 0, 222, 131
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_AVATAR,"Static",SS_BITMAP | SS_CENTERIMAGE | SS_SUNKEN,9,11,96,96
+ PUSHBUTTON "Set",IDC_SETAVATAR,9,112,45,13,NOT WS_VISIBLE
+ PUSHBUTTON "Delete",IDC_DELETEAVATAR,61,112,45,13,NOT WS_VISIBLE
+ LTEXT "Note: Only JPGs and GIFs\nImage size max 64x64\nFile size max 6kB",IDC_STATIC,112,54,106,34,NOT WS_VISIBLE
+END
+
+IDD_ICQUPLOADLIST DIALOGEX 0, 0, 358, 241
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Manage ICQ Server Contacts"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Select contacts to store:",IDC_STATIC11,5,5,91,8
+ CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x2c8,5,14,155,222,WS_EX_CLIENTEDGE
+ DEFPUSHBUTTON "Synchronize",IDOK,238,222,56,14
+ PUSHBUTTON "Cancel",IDCANCEL,298,222,55,14
+ LISTBOX IDC_LOG,169,5,184,213,NOT LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_SETXSTATUS DIALOGEX 0, 0, 189, 98
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Custom Status ""%s"" Details"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "Closing in %d",IDOK,62,79,65,14
+ LTEXT "Title:",IDC_STATIC,5,0,179,8
+ EDITTEXT IDC_XTITLE,5,9,179,13
+ LTEXT "Message:",IDC_STATIC,5,22,179,8
+ EDITTEXT IDC_XMSG,5,31,179,43,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ CTEXT "Retrieving custom status details...",IDC_RETRXSTATUS,5,0,179,75,SS_CENTERIMAGE | NOT WS_VISIBLE
+END
+
+IDD_INFO_CHANGEINFO DIALOGEX 0, 0, 222, 132
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,2,2,218,113
+ PUSHBUTTON "&Save changes",IDC_SAVE,140,117,80,13,WS_DISABLED
+ EDITTEXT IDC_UPLOADING,2,118,127,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_VISIBLE | NOT WS_BORDER
+END
+
+IDD_PWCONFIRM DIALOGEX 0, 0, 167, 78
+STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Confirm Password Change"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Please re-type your new password:",IDC_STATIC,5,5,157,9
+ EDITTEXT IDC_PASSWORD,5,15,157,12,ES_PASSWORD | ES_AUTOHSCROLL
+ LTEXT "Enter your current password:",IDC_STATIC,5,32,157,9
+ EDITTEXT IDC_OLDPASS,5,42,157,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,26,59,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,91,59,50,14
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,3,7,39
+ PRODUCTVERSION 0,6,0,7
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004e4"
+ BEGIN
+ VALUE "Comments", "Licensed under the terms of the GNU General Public License"
+ VALUE "FileDescription", "ICQ protocol plugin for Miranda IM, enhanced"
+ VALUE "FileVersion", "0, 3, 7, 39"
+ VALUE "InternalName", "ICQJ protocol plugin for Miranda IM"
+ VALUE "LegalCopyright", "Copyright (C) 2000-2006 Joe Kucera, Angeli-Ka, Bio, Martin Öberg, Richard Hughes, Jon Keating"
+ VALUE "OriginalFilename", "ICQ.dll"
+ VALUE "ProductName", "ICQ Protocol Support"
+ VALUE "ProductVersion", "0, 6, 0, 7"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1252
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_INFO_ICQ, DIALOG
+ BEGIN
+ RIGHTMARGIN, 222
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/icqj_mod/stdpackets.c b/icqj_mod/stdpackets.c new file mode 100644 index 0000000..adef009 --- /dev/null +++ b/icqj_mod/stdpackets.c @@ -0,0 +1,1569 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/stdpackets.c,v $
+// Revision : $Revision: 2991 $
+// Last change on : $Date: 2006-05-30 19:55:48 +0200 (Tue, 30 May 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern int gbIdleAllow;
+extern WORD wListenPort;
+extern HANDLE hsmsgrequest;
+extern DWORD dwLocalDirectConnCookie;
+static DWORD sendTLVSearchPacket(BYTE bType, char *pSearchDataBuf, WORD wSearchType, WORD wInfoLen, BOOL bOnlineUsersOnly);
+
+
+
+/*****************************************************************************
+ *
+ * Some handy extra pack functions for basic message type headers
+ *
+ */
+
+
+
+// This is the part of the message header that is common for all message channels
+static void packServMsgSendHeader(icq_packet *p, DWORD dwSequence, DWORD dwID1, DWORD dwID2, DWORD dwUin, char *szUID, WORD wFmt, WORD wLen)
+{
+ unsigned char nUinLen;
+
+ nUinLen = getUIDLen(dwUin, szUID);
+
+ serverPacketInit(p, (WORD)(21 + nUinLen + wLen));
+ packFNACHeaderFull(p, ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, 0, dwSequence | ICQ_MSG_SRV_SEND<<0x10);
+ packLEDWord(p, dwID1); // Msg ID part 1
+ packLEDWord(p, dwID2); // Msg ID part 2
+ packWord(p, wFmt); // Message channel
+ packUID(p, dwUin, szUID); // User ID
+}
+
+
+
+static void packServIcqExtensionHeader(icq_packet *p, WORD wLen, WORD wType, WORD wSeq)
+{
+ serverPacketInit(p, (WORD)(24 + wLen));
+ packFNACHeaderFull(p, ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQ, 0, wSeq | ICQ_META_CLI_REQ<<0x10);
+ packWord(p, 0x01); // TLV type 1
+ packWord(p, (WORD)(10 + wLen)); // TLV len
+ packLEWord(p, (WORD)(8 + wLen)); // Data chunk size (TLV.Length-2)
+ packLEDWord(p, dwLocalUIN); // My UIN
+ packLEWord(p, wType); // Request type
+ packWord(p, wSeq);
+}
+
+
+
+static void packServTLV5Header(icq_packet *p, WORD wLen, DWORD TS1, DWORD TS2, WORD wAckType)
+{
+ // TLV(5) header
+ packWord(p, 0x05); // Type
+ packWord(p, (WORD)(36 + wLen)); // Len
+ // TLV(5) data
+ packWord(p, 0); // Command
+ packLEDWord(p, TS1); // msgid1
+ packLEDWord(p, TS2); // msgid2
+ packGUID(p, MCAP_TLV2711_FMT); // capabilities (4 dwords)
+ packDWord(p, 0x000A0002); // TLV: 0x0A Acktype: 1 for normal, 2 for ack
+ packWord(p, wAckType);
+ packDWord(p, 0x000F0000); // TLV: 0x0F empty
+}
+
+
+
+static void packServTLV2711Header(icq_packet *packet, WORD wCookie, WORD wVersion, BYTE bMsgType, BYTE bMsgFlags, WORD X1, WORD X2, int nLen)
+{
+ packWord(packet, 0x2711); // Type
+ packWord(packet, (WORD)(51 + nLen)); // Len
+ // TLV(0x2711) data
+ packLEWord(packet, 0x1B); // Unknown
+ packByte(packet, (BYTE)wVersion); // Client (message) version
+ packGUID(packet, PSIG_MESSAGE);
+ packDWord(packet, CLIENTFEATURES);
+ packDWord(packet, DC_TYPE);
+ packLEWord(packet, wCookie); // Reference cookie
+ packLEWord(packet, 0x0E); // Unknown
+ packLEWord(packet, wCookie); // Reference cookie again
+ packDWord(packet, 0); // Unknown (12 bytes)
+ packDWord(packet, 0); // -
+ packDWord(packet, 0); // -
+ packByte(packet, bMsgType); // Message type
+ packByte(packet, bMsgFlags); // Flags
+ packLEWord(packet, X1); // Accepted
+ packWord(packet, X2); // Unknown, priority?
+}
+
+
+
+static void packServDCInfo(icq_packet *p, BOOL bEmpty)
+{
+ packTLVDWord(p, 0x03, bEmpty ? 0 : ICQGetContactSettingDword(NULL, "RealIP", 0)); // TLV: 0x03 DWORD IP
+ packTLVWord(p, 0x05, (WORD)(bEmpty ? 0 : wListenPort)); // TLV: 0x05 Listen port
+}
+
+
+
+static void packServChannel2Header(icq_packet *p, DWORD dwUin, WORD wLen, DWORD dwID1, DWORD dwID2, DWORD dwCookie, WORD wVersion, BYTE bMsgType, BYTE bMsgFlags, WORD wPriority, int isAck, int includeDcInfo, BYTE bRequestServerAck)
+{
+ packServMsgSendHeader(p, dwCookie, dwID1, dwID2, dwUin, NULL, 0x0002,
+ (WORD)(wLen + 95 + (bRequestServerAck?4:0) + (includeDcInfo?14:0)));
+
+ packWord(p, 0x05); // TLV type
+ packWord(p, (WORD)(wLen + 91 + (includeDcInfo?14:0))); /* TLV len */
+ packWord(p, (WORD)(isAck ? 2: 0)); /* not aborting anything */
+ packLEDWord(p, dwID1); // Msg ID part 1
+ packLEDWord(p, dwID2); // Msg ID part 2
+ packGUID(p, MCAP_TLV2711_FMT); /* capability (4 dwords) */
+ packDWord(p, 0x000A0002); // TLV: 0x0A WORD: 1 for normal, 2 for ack
+ packWord(p, (WORD)(isAck ? 2 : 1));
+
+ if (includeDcInfo)
+ {
+ packServDCInfo(p, FALSE);
+ }
+
+ packDWord(p, 0x000F0000); // TLV: 0x0F empty
+
+ packServTLV2711Header(p, (WORD)dwCookie, wVersion, bMsgType, bMsgFlags, (WORD)MirandaStatusToIcq(gnCurrentStatus), wPriority, wLen);
+}
+
+
+
+static void packServAdvancedMsgReply(icq_packet *p, DWORD dwUin, DWORD dwTimestamp, DWORD dwTimestamp2, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wLen)
+{
+ unsigned char nUinLen;
+
+ nUinLen = getUINLen(dwUin);
+
+ serverPacketInit(p, (WORD)(nUinLen + 74 + wLen));
+ packFNACHeaderFull(p, ICQ_MSG_FAMILY, ICQ_MSG_RESPONSE, 0, ICQ_MSG_RESPONSE<<0x10 | (wCookie & 0x7FFF));
+ packLEDWord(p, dwTimestamp); // Msg ID part 1
+ packLEDWord(p, dwTimestamp2); // Msg ID part 2
+ packWord(p, 0x02); // Channel
+ packUIN(p, dwUin); // Your UIN
+ packWord(p, 0x03); // Unknown
+ packLEWord(p, 0x1B); // Unknown
+ packByte(p, ICQ_VERSION); // Protocol version
+ packGUID(p, PSIG_MESSAGE);
+ packDWord(p, CLIENTFEATURES);
+ packDWord(p, DC_TYPE);
+ packLEWord(p, wCookie); // Reference
+ packLEWord(p, 0x0E); // Unknown
+ packLEWord(p, wCookie); // Reference
+ packDWord(p, 0); // Unknown
+ packDWord(p, 0); // Unknown
+ packDWord(p, 0); // Unknown
+ packByte(p, bMsgType); // Message type
+ packByte(p, bMsgFlags); // Message flags
+ packLEWord(p, 0); // Ack status code ( 0 = accepted, this is hardcoded because
+ // it is only used this way yet)
+ packLEWord(p, 0); // Unused priority field
+}
+
+
+
+void packMsgColorInfo(icq_packet *packet)
+{ // TODO: make configurable
+ packLEDWord(packet, 0x00000000); // Foreground colour
+ packLEDWord(packet, 0x00FFFFFF); // Background colour
+}
+
+
+
+void packEmptyMsg(icq_packet *packet)
+{
+ packLEWord(packet, 1);
+ packByte(packet, 0);
+}
+
+
+/*****************************************************************************
+ *
+ * Functions to actually send the stuff
+ *
+ */
+
+void icq_sendCloseConnection()
+{
+ icq_packet packet;
+
+ packet.wLen = 0;
+ write_flap(&packet, ICQ_CLOSE_CHAN);
+ sendServPacket(&packet);
+}
+
+
+
+void icq_requestnewfamily(WORD wFamily, void (*familyhandler)(HANDLE hConn, char* cookie, WORD cookieLen))
+{
+ icq_packet packet;
+ DWORD dwIdent;
+ familyrequest_rec* request;
+
+ request = (familyrequest_rec*)SAFE_MALLOC(sizeof(familyrequest_rec));
+ request->wFamily = wFamily;
+ request->familyhandler = familyhandler;
+
+ dwIdent = AllocateCookie(CKT_SERVICEREQUEST, ICQ_CLIENT_NEW_SERVICE, 0, request); // generate and alloc cookie
+
+ serverPacketInit(&packet, 12);
+ packFNACHeaderFull(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_NEW_SERVICE, 0, dwIdent);
+ packWord(&packet, wFamily);
+
+ sendServPacket(&packet);
+}
+
+
+
+void icq_setidle(int bAllow)
+{
+ icq_packet packet;
+
+ if (bAllow!=gbIdleAllow)
+ {
+ /* SNAC 1,11 */
+ serverPacketInit(&packet, 14);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_IDLE);
+ if (bAllow==1)
+ {
+ packDWord(&packet, 0x0000003C);
+ }
+ else
+ {
+ packDWord(&packet, 0x00000000);
+ }
+
+ sendServPacket(&packet);
+ gbIdleAllow = bAllow;
+ }
+}
+
+
+
+void icq_setstatus(WORD wStatus)
+{
+ icq_packet packet;
+
+ // Pack data in packet
+ serverPacketInit(&packet, 18);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_STATUS);
+ packWord(&packet, 0x06); // TLV 6
+ packWord(&packet, 0x04); // TLV length
+ packWord(&packet, GetMyStatusFlags()); // Status flags
+ packWord(&packet, wStatus); // Status
+
+ // Send packet
+ sendServPacket(&packet);
+}
+
+
+DWORD icq_SendChannel1Message(DWORD dwUin, char *szUID, HANDLE hContact, char *pszText, message_cookie_data *pCookieData)
+{
+ icq_packet packet;
+ WORD wMessageLen;
+ DWORD dwCookie;
+ WORD wPacketLength;
+
+
+ wMessageLen = strlennull(pszText);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, dwUin, (void*)pCookieData);
+
+ if (pCookieData->nAckType == ACKTYPE_SERVER)
+ wPacketLength = 25;
+ else
+ wPacketLength = 21;
+
+ // Pack the standard header
+ packServMsgSendHeader(&packet, dwCookie, pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwUin, szUID, 1, (WORD)(wPacketLength + wMessageLen));
+
+ // Pack first TLV
+ packWord(&packet, 0x0002); // TLV(2)
+ packWord(&packet, (WORD)(wMessageLen + 13)); // TLV len
+
+ // Pack client features
+ packWord(&packet, 0x0501); // TLV(501)
+ packWord(&packet, 0x0001); // TLV len
+ packByte(&packet, 0x1); // Features, meaning unknown, duplicated from ICQ Lite
+
+ // Pack text TLV
+ packWord(&packet, 0x0101); // TLV(2)
+ packWord(&packet, (WORD)(wMessageLen + 4)); // TLV len
+ packWord(&packet, 0x0003); // Message charset number, again copied from ICQ Lite
+ packWord(&packet, 0x0000); // Message charset subset
+ packBuffer(&packet, pszText, (WORD)(wMessageLen)); // Message text
+
+ // Pack request server ack TLV
+ if (pCookieData->nAckType == ACKTYPE_SERVER)
+ {
+ packDWord(&packet, 0x00030000); // TLV(3)
+ }
+
+ // Pack store on server TLV
+ packDWord(&packet, 0x00060000); // TLV(6)
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_SendChannel1MessageW(DWORD dwUin, char *szUID, HANDLE hContact, wchar_t *pszText, message_cookie_data *pCookieData)
+{
+ icq_packet packet;
+ WORD wMessageLen;
+ DWORD dwCookie;
+ WORD wPacketLength;
+ wchar_t* ppText;
+ int i;
+
+
+ wMessageLen = wcslen(pszText)*sizeof(wchar_t);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, dwUin, (void*)pCookieData);
+
+ if (pCookieData->nAckType == ACKTYPE_SERVER)
+ wPacketLength = 26;
+ else
+ wPacketLength = 22;
+
+ // Pack the standard header
+ packServMsgSendHeader(&packet, dwCookie, pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwUin, szUID, 1, (WORD)(wPacketLength + wMessageLen));
+
+ // Pack first TLV
+ packWord(&packet, 0x0002); // TLV(2)
+ packWord(&packet, (WORD)(wMessageLen + 14)); // TLV len
+
+ // Pack client features
+ packWord(&packet, 0x0501); // TLV(501)
+ packWord(&packet, 0x0002); // TLV len
+ packWord(&packet, 0x0106); // Features, meaning unknown, duplicated from ICQ 2003b
+
+ // Pack text TLV
+ packWord(&packet, 0x0101); // TLV(2)
+ packWord(&packet, (WORD)(wMessageLen + 4)); // TLV len
+ packWord(&packet, 0x0002); // Message charset number, again copied from ICQ 2003b
+ packWord(&packet, 0x0000); // Message charset subset
+ ppText = pszText; // we must convert the widestring
+ for (i = 0; i<wMessageLen; i+=2, ppText++)
+ {
+ packWord(&packet, *ppText);
+ }
+
+ // Pack request server ack TLV
+ if (pCookieData->nAckType == ACKTYPE_SERVER)
+ {
+ packDWord(&packet, 0x00030000); // TLV(3)
+ }
+
+ // Pack store on server TLV
+ packDWord(&packet, 0x00060000); // TLV(6)
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_SendChannel2Message(DWORD dwUin, const char *szMessage, int nBodyLen, WORD wPriority, message_cookie_data *pCookieData, char *szCap)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+
+
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, dwUin, (void*)pCookieData);
+
+ // Pack the standard header
+ packServChannel2Header(&packet, dwUin, (WORD)(nBodyLen + (szCap ? 53:11)), pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwCookie, ICQ_VERSION, (BYTE)pCookieData->bMessageType, 0,
+ wPriority, 0, 0, (BYTE)((pCookieData->nAckType == ACKTYPE_SERVER)?1:0));
+
+ packLEWord(&packet, (WORD)(nBodyLen+1)); // Length of message
+ packBuffer(&packet, szMessage, (WORD)(nBodyLen+1)); // Message
+ packMsgColorInfo(&packet);
+
+ if (szCap)
+ {
+ packLEDWord(&packet, 0x00000026); // length of GUID
+ packBuffer(&packet, szCap, 0x26); // UTF-8 GUID
+ }
+
+ // Pack request server ack TLV
+ if (pCookieData->nAckType == ACKTYPE_SERVER)
+ {
+ packDWord(&packet, 0x00030000); // TLV(3)
+ }
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_SendChannel4Message(DWORD dwUin, BYTE bMsgType, WORD wMsgLen, const char *szMsg, message_cookie_data *pCookieData)
+{
+ icq_packet packet;
+ WORD wPacketLength;
+ DWORD dwCookie;
+
+
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, dwUin, (void*)pCookieData);
+
+ if (pCookieData->nAckType == ACKTYPE_SERVER)
+ wPacketLength = 28;
+ else
+ wPacketLength = 24;
+
+ // Pack the standard header
+ packServMsgSendHeader(&packet, dwCookie, pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwUin, NULL, 4, (WORD)(wPacketLength + wMsgLen));
+
+ // Pack first TLV
+ packWord(&packet, 0x05); // TLV(5)
+ packWord(&packet, (WORD)(wMsgLen + 16)); // TLV len
+ packLEDWord(&packet, dwLocalUIN); // My UIN
+ packByte(&packet, bMsgType); // Message type
+ packByte(&packet, 0); // Message flags
+ packLEWord(&packet, wMsgLen); // Message length
+ packBuffer(&packet, szMsg, wMsgLen); // Message text
+ packMsgColorInfo(&packet);
+
+ // Pack request ack TLV
+ if (pCookieData->nAckType == ACKTYPE_SERVER)
+ {
+ packDWord(&packet, 0x00030000); // TLV(3)
+ }
+
+ // Pack store on server TLV
+ packDWord(&packet, 0x00060000); // TLV(6)
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+void sendOwnerInfoRequest(void)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ fam15_cookie_data *pCookieData = NULL;
+
+
+ pCookieData = SAFE_MALLOC(sizeof(fam15_cookie_data));
+ pCookieData->bRequestType = REQUESTTYPE_OWNER;
+ dwCookie = AllocateCookie(CKT_FAMILYSPECIAL, 0, dwLocalUIN, (void*)pCookieData);
+
+ packServIcqExtensionHeader(&packet, 6, 0x07D0, (WORD)dwCookie);
+ packLEWord(&packet, META_REQUEST_SELF_INFO);
+ packLEDWord(&packet, dwLocalUIN);
+
+ sendServPacket(&packet);
+}
+
+
+
+void sendUserInfoAutoRequest(DWORD dwUin)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ fam15_cookie_data *pCookieData = NULL;
+
+
+ pCookieData = SAFE_MALLOC(sizeof(fam15_cookie_data));
+ pCookieData->bRequestType = REQUESTTYPE_USERAUTO;
+ dwCookie = AllocateCookie(CKT_FAMILYSPECIAL, 0, dwUin, (void*)pCookieData);
+
+ packServIcqExtensionHeader(&packet, 6, 0x07D0, (WORD)dwCookie);
+ packLEWord(&packet, META_REQUEST_SHORT_INFO);
+ packLEDWord(&packet, dwUin);
+
+ sendServPacket(&packet);
+}
+
+
+
+DWORD icq_sendGetInfoServ(DWORD dwUin, int bMinimal)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ fam15_cookie_data *pCookieData = NULL;
+
+ // we request if we can or 10sec after last request
+ if (gbOverRate && (GetTickCount()-gtLastRequest)<10000) return 0;
+ gbOverRate = 0;
+ gtLastRequest = GetTickCount();
+
+ pCookieData = SAFE_MALLOC(sizeof(fam15_cookie_data));
+ dwCookie = AllocateCookie(CKT_FAMILYSPECIAL, 0, dwUin, (void*)pCookieData);
+
+ packServIcqExtensionHeader(&packet, 6, CLI_META_INFO_REQ, (WORD)dwCookie);
+ if (bMinimal)
+ {
+ pCookieData->bRequestType = REQUESTTYPE_USERMINIMAL;
+ packLEWord(&packet, META_REQUEST_SHORT_INFO);
+ }
+ else
+ {
+ pCookieData->bRequestType = REQUESTTYPE_USERDETAILED;
+ packLEWord(&packet, META_REQUEST_FULL_INFO);
+ }
+ packLEDWord(&packet, dwUin);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_sendGetAimProfileServ(HANDLE hContact, char* szUid)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ fam15_cookie_data *pCookieData = NULL;
+ BYTE bUIDlen = strlennull(szUid);
+
+ pCookieData = SAFE_MALLOC(sizeof(fam15_cookie_data));
+ dwCookie = AllocateCookie(CKT_FAMILYSPECIAL, ICQ_LOCATION_REQ_USER_INFO, 0, (void*)pCookieData);
+ pCookieData->bRequestType = REQUESTTYPE_PROFILE;
+ pCookieData->hContact = hContact;
+
+ serverPacketInit(&packet, (WORD)(13 + bUIDlen));
+ packFNACHeaderFull(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, 0, dwCookie);
+ packWord(&packet, 0x01); // request profile info
+ packByte(&packet, bUIDlen);
+ packBuffer(&packet, szUid, bUIDlen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_sendGetAwayMsgServ(DWORD dwUin, int type, WORD wVersion)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ message_cookie_data *pCookieData = NULL;
+
+ // we request if we can or 10sec after last request
+ if (gbOverRate && (GetTickCount()-gtLastRequest)<10000) return 0;
+ gbOverRate = 0;
+ gtLastRequest = GetTickCount();
+
+ pCookieData = CreateMessageCookie(MTYPE_AUTOAWAY, (BYTE)type);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, dwUin, (void*)pCookieData);
+
+ packServChannel2Header(&packet, dwUin, 3, pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwCookie, wVersion, (BYTE)type, 3, 1, 0, 0, 0);
+ packEmptyMsg(&packet); // Message
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_sendGetAimAwayMsgServ(char *szUID, int type)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ message_cookie_data *pCookieData = NULL;
+ BYTE bUIDlen = strlennull(szUID);
+
+ pCookieData = CreateMessageCookie(MTYPE_AUTOAWAY, (byte)type);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, 0, (void*)pCookieData);
+
+ serverPacketInit(&packet, (WORD)(13 + bUIDlen));
+ packFNACHeaderFull(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, 0, dwCookie);
+ packWord(&packet, 0x03);
+ packByte(&packet, bUIDlen);
+ packBuffer(&packet, szUID, bUIDlen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+void icq_sendSetAimAwayMsgServ(char *szMsg)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ WORD wMsgLen = strlennull(szMsg);
+
+ dwCookie = GenerateCookie(ICQ_LOCATION_SET_USER_INFO);
+
+ if (wMsgLen > 0x1000) wMsgLen = 0x1000; // limit length
+ serverPacketInit(&packet, (WORD)(51 + wMsgLen));
+ packFNACHeaderFull(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_SET_USER_INFO, 0, dwCookie);
+ packTLV(&packet, 0x03, 0x21, "text/x-aolrtf; charset=\"utf-8\"");
+ packTLV(&packet, 0x04, wMsgLen, szMsg);
+
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendFileSendServv7(filetransfer* ft, const char *szFiles)
+{
+ icq_packet packet;
+ WORD wDescrLen,wFilesLen;
+
+ wDescrLen = strlennull(ft->szDescription);
+ wFilesLen = strlennull(szFiles);
+
+ packServChannel2Header(&packet, ft->dwUin, (WORD)(18 + wDescrLen + wFilesLen), ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, ft->dwCookie, ICQ_VERSION, MTYPE_FILEREQ, 0, 1, 0, 1, 1);
+
+ packLEWord(&packet, (WORD)(wDescrLen + 1));
+ packBuffer(&packet, ft->szDescription, (WORD)(wDescrLen + 1));
+ packLEDWord(&packet, 0); // unknown
+ packLEWord(&packet, (WORD)(wFilesLen + 1));
+ packBuffer(&packet, szFiles, (WORD)(wFilesLen + 1));
+ packLEDWord(&packet, ft->dwTotalSize);
+ packLEDWord(&packet, 0); // unknown
+
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendFileSendServv8(filetransfer* ft, const char *szFiles, int nAckType)
+{
+ icq_packet packet;
+ WORD wFlapLen;
+ WORD wDescrLen,wFilesLen;
+
+ wDescrLen = strlennull(ft->szDescription);
+ wFilesLen = strlennull(szFiles);
+
+ // 202 + UIN len + file description (no null) + file name (null included)
+ // Packet size = Flap length + 4
+ wFlapLen = 178 + wDescrLen + wFilesLen + (nAckType == ACKTYPE_SERVER?4:0);
+ packServMsgSendHeader(&packet, ft->dwCookie, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, ft->dwUin, NULL, 2, wFlapLen);
+
+ // TLV(5) header
+ packServTLV5Header(&packet, (WORD)(138 + wDescrLen + wFilesLen), ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, 1);
+
+ // Port & IP information
+ packServDCInfo(&packet, FALSE);
+
+ // TLV(0x2711) header
+ packServTLV2711Header(&packet, (WORD)ft->dwCookie, ICQ_VERSION, MTYPE_PLUGIN, 0, (WORD)MirandaStatusToIcq(gnCurrentStatus), 0x100, 69 + wDescrLen + wFilesLen);
+
+ packEmptyMsg(&packet); // Message (unused)
+
+ packPluginTypeId(&packet, MTYPE_FILEREQ);
+
+ packLEDWord(&packet, (WORD)(18 + wDescrLen + wFilesLen + 1)); // Remaining length
+ packLEDWord(&packet, wDescrLen); // Description
+ packBuffer(&packet, ft->szDescription, wDescrLen);
+ packWord(&packet, 0x8c82); // Unknown (port?), seen 0x80F6
+ packWord(&packet, 0x0222); // Unknown, seen 0x2e01
+ packLEWord(&packet, (WORD)(wFilesLen + 1));
+ packBuffer(&packet, szFiles, (WORD)(wFilesLen + 1));
+ packLEDWord(&packet, ft->dwTotalSize);
+ packLEDWord(&packet, 0x0008c82); // Unknown, (seen 0xf680 ~33000)
+
+ // Pack request server ack TLV
+ if (nAckType == ACKTYPE_SERVER)
+ {
+ packDWord(&packet, 0x00030000); // TLV(3)
+ }
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+
+
+/* also sends rejections */
+void icq_sendFileAcceptServv8(DWORD dwUin, DWORD TS1, DWORD TS2, DWORD dwCookie, const char *szFiles, const char *szDescr, DWORD dwTotalSize, WORD wPort, BOOL accepted, int nAckType)
+{
+ icq_packet packet;
+ WORD wFlapLen;
+ WORD wDescrLen,wFilesLen;
+
+ /* if !accepted, szDescr == szReason, szFiles = "" */
+
+ if (!accepted) szFiles = "";
+
+ wDescrLen = strlennull(szDescr);
+ wFilesLen = strlennull(szFiles);
+
+ // 202 + UIN len + file description (no null) + file name (null included)
+ // Packet size = Flap length + 4
+ wFlapLen = 178 + wDescrLen + wFilesLen + (nAckType == ACKTYPE_SERVER?4:0);
+ packServMsgSendHeader(&packet, dwCookie, TS1, TS2, dwUin, NULL, 2, wFlapLen);
+
+ // TLV(5) header
+ packServTLV5Header(&packet, (WORD)(138 + wDescrLen + wFilesLen), TS1, TS2, 2);
+
+ // Port & IP information
+ packServDCInfo(&packet, !accepted);
+
+ // TLV(0x2711) header
+ packServTLV2711Header(&packet, (WORD)dwCookie, ICQ_VERSION, MTYPE_PLUGIN, 0, (WORD)(accepted ? 0:1), 0, 69 + wDescrLen + wFilesLen);
+ //
+ packEmptyMsg(&packet); // Message (unused)
+
+ packPluginTypeId(&packet, MTYPE_FILEREQ);
+
+ packLEDWord(&packet, (WORD)(18 + wDescrLen + wFilesLen + 1)); // Remaining length
+ packLEDWord(&packet, wDescrLen); // Description
+ packBuffer(&packet, szDescr, wDescrLen);
+ packWord(&packet, wPort); // Port
+ packWord(&packet, 0x00); // Unknown
+ packLEWord(&packet, (WORD)(wFilesLen + 1));
+ packBuffer(&packet, szFiles, (WORD)(wFilesLen + 1));
+ packLEDWord(&packet, dwTotalSize);
+ packLEDWord(&packet, (DWORD)wPort); // Unknown
+
+ // Pack request server ack TLV
+ if (nAckType == ACKTYPE_SERVER)
+ {
+ packDWord(&packet, 0x00030000); // TLV(3)
+ }
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendFileAcceptServv7(DWORD dwUin, DWORD TS1, DWORD TS2, DWORD dwCookie, const char* szFiles, const char* szDescr, DWORD dwTotalSize, WORD wPort, BOOL accepted, int nAckType)
+{
+ icq_packet packet;
+ WORD wFlapLen;
+ WORD wDescrLen,wFilesLen;
+
+ /* if !accepted, szDescr == szReason, szFiles = "" */
+
+ if (!accepted) szFiles = "";
+
+ wDescrLen = strlennull(szDescr);
+ wFilesLen = strlennull(szFiles);
+
+ // 150 + UIN len + file description (with null) + file name (2 nulls)
+ // Packet size = Flap length + 4
+ wFlapLen = 127 + wDescrLen + 1 + wFilesLen + (nAckType == ACKTYPE_SERVER?4:0);
+ packServMsgSendHeader(&packet, dwCookie, TS1, TS2, dwUin, NULL, 2, wFlapLen);
+
+ // TLV(5) header
+ packServTLV5Header(&packet, (WORD)(88 + wDescrLen + wFilesLen), TS1, TS2, 2);
+
+ // Port & IP information
+ packServDCInfo(&packet, !accepted);
+
+ // TLV(0x2711) header
+ packServTLV2711Header(&packet, (WORD)dwCookie, ICQ_VERSION, MTYPE_FILEREQ, 0, (WORD)(accepted ? 0:1), 0, 19 + wDescrLen + wFilesLen);
+ //
+ packLEWord(&packet, (WORD)(wDescrLen + 1)); // Description
+ packBuffer(&packet, szDescr, (WORD)(wDescrLen + 1));
+ packWord(&packet, wPort); // Port
+ packWord(&packet, 0x00); // Unknown
+ packLEWord(&packet, (WORD)(wFilesLen + 2));
+ packBuffer(&packet, szFiles, (WORD)(wFilesLen + 1));
+ packByte(&packet, 0);
+ packLEDWord(&packet, dwTotalSize);
+ packLEDWord(&packet, (DWORD)wPort); // Unknown
+
+ // Pack request server ack TLV
+ if (nAckType == ACKTYPE_SERVER)
+ {
+ packDWord(&packet, 0x00030000); // TLV(3)
+ }
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendFileAcceptServ(DWORD dwUin, filetransfer* ft, int nAckType)
+{
+ char *szDesc = ft->szDescription;
+
+ if (ft->bEmptyDesc) szDesc = ""; // keep empty if it originally was (Trillian workaround)
+
+ if (ft->nVersion >= 8)
+ {
+ icq_sendFileAcceptServv8(dwUin, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, ft->dwCookie, ft->szFilename, szDesc, ft->dwTotalSize, wListenPort, TRUE, nAckType);
+ NetLog_Server("Sent file accept v%u through server, port %u", 8, wListenPort);
+ }
+ else
+ {
+ icq_sendFileAcceptServv7(dwUin, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, ft->dwCookie, ft->szFilename, szDesc, ft->dwTotalSize, wListenPort, TRUE, nAckType);
+ NetLog_Server("Sent file accept v%u through server, port %u", 7, wListenPort);
+ }
+}
+
+
+
+void icq_sendFileDenyServ(DWORD dwUin, filetransfer* ft, char *szReason, int nAckType)
+{
+ if (ft->nVersion >= 8)
+ {
+ icq_sendFileAcceptServv8(dwUin, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, ft->dwCookie, ft->szFilename, szReason, ft->dwTotalSize, wListenPort, FALSE, nAckType);
+ NetLog_Server("Sent file deny v%u through server", 8);
+ }
+ else
+ {
+ icq_sendFileAcceptServv7(dwUin, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, ft->dwCookie, ft->szFilename, szReason, ft->dwTotalSize, wListenPort, FALSE, nAckType);
+ NetLog_Server("Sent file deny v%u through server", 7);
+ }
+}
+
+
+
+void icq_sendAwayMsgReplyServ(DWORD dwUin, DWORD dwMsgID1, DWORD dwMsgID2, WORD wCookie, WORD wVersion, BYTE msgType, const char** szMsg)
+{
+ icq_packet packet;
+ WORD wMsgLen;
+ char* pszMsg;
+ HANDLE hContact;
+
+
+ hContact = HContactFromUIN(dwUin, NULL);
+
+ if (validateStatusMessageRequest(hContact, msgType))
+ {
+ NotifyEventHooks(hsmsgrequest, (WPARAM)msgType, (LPARAM)dwUin);
+
+ EnterCriticalSection(&modeMsgsMutex);
+
+ if (szMsg && *szMsg)
+ {
+ char* szAnsiMsg = NULL;
+
+ if (wVersion == 9 && ICQ_VERSION == 9)
+ pszMsg = (char*)*szMsg;
+ else
+ { // only v9 protocol supports UTF-8 mode messagees
+ wMsgLen = strlennull(*szMsg) + 1;
+ szAnsiMsg = (char*)_alloca(wMsgLen);
+ utf8_decode_static(*szMsg, szAnsiMsg, wMsgLen);
+ pszMsg = szAnsiMsg;
+ }
+
+ wMsgLen = strlennull(pszMsg);
+
+ // limit msg len to max snac size - we get disconnected if exceeded
+ if (wMsgLen > MAX_MESSAGESNACSIZE)
+ wMsgLen = MAX_MESSAGESNACSIZE;
+
+ packServAdvancedMsgReply(&packet, dwUin, dwMsgID1, dwMsgID2, wCookie, msgType, 3, (WORD)(wMsgLen + 3));
+ packLEWord(&packet, (WORD)(wMsgLen + 1));
+ packBuffer(&packet, pszMsg, wMsgLen);
+ packByte(&packet, 0);
+
+ sendServPacket(&packet);
+ }
+
+ LeaveCriticalSection(&modeMsgsMutex);
+ }
+}
+
+
+
+void icq_sendAdvancedMsgAck(DWORD dwUin, DWORD dwTimestamp, DWORD dwTimestamp2, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags)
+{
+ icq_packet packet;
+
+ packServAdvancedMsgReply(&packet, dwUin, dwTimestamp, dwTimestamp2, wCookie, bMsgType, bMsgFlags, 11);
+ packEmptyMsg(&packet); // Status message
+ packMsgColorInfo(&packet);
+
+ sendServPacket(&packet);
+}
+
+
+
+// Searches
+
+DWORD SearchByUin(DWORD dwUin)
+{
+ DWORD dwCookie;
+ WORD wInfoLen;
+ icq_packet pBuffer; // I reuse the ICQ packet type as a generic buffer
+ // I should be ashamed! ;)
+
+ // Calculate data size
+ wInfoLen = 8;
+
+ // Initialize our handy data buffer
+ pBuffer.wPlace = 0;
+ pBuffer.pData = (BYTE *)_alloca(wInfoLen);
+ pBuffer.wLen = wInfoLen;
+
+ // Initialize our handy data buffer
+ packLEWord(&pBuffer, TLV_UIN);
+ packLEWord(&pBuffer, 0x0004);
+ packLEDWord(&pBuffer, dwUin);
+
+ // Send it off for further packing
+ dwCookie = sendTLVSearchPacket(SEARCHTYPE_UID, pBuffer.pData, META_SEARCH_UIN, wInfoLen, FALSE);
+
+ return dwCookie;
+}
+
+
+
+DWORD SearchByNames(char* pszNick, char* pszFirstName, char* pszLastName)
+{ // use generic TLV search like icq5 does
+ DWORD dwCookie;
+ WORD wInfoLen = 0;
+ WORD wNickLen,wFirstLen,wLastLen;
+ BYTE *pBuffer;
+ int pBufferPos;
+
+ wNickLen = strlennull(pszNick);
+ wFirstLen = strlennull(pszFirstName);
+ wLastLen = strlennull(pszLastName);
+
+ _ASSERTE(wFirstLen || wLastLen || wNickLen);
+
+
+ // Calculate data size
+ if (wFirstLen > 0)
+ wInfoLen = wFirstLen + 7;
+ if (wLastLen > 0)
+ wInfoLen += wLastLen + 7;
+ if (wNickLen > 0)
+ wInfoLen += wNickLen + 7;
+
+ // Initialize our handy data buffer
+ pBuffer = (BYTE*)_alloca(wInfoLen);
+ pBufferPos = 0;
+
+ // Pack the search details
+ if (wFirstLen > 0)
+ {
+ packTLVLNTS(&pBuffer, &pBufferPos, pszFirstName, TLV_FIRSTNAME);
+ }
+
+ if (wLastLen > 0)
+ {
+ packTLVLNTS(&pBuffer, &pBufferPos, pszLastName, TLV_LASTNAME);
+ }
+
+ if (wNickLen > 0)
+ {
+ packTLVLNTS(&pBuffer, &pBufferPos, pszNick, TLV_NICKNAME);
+ }
+
+ // Send it off for further packing
+ dwCookie = sendTLVSearchPacket(SEARCHTYPE_NAMES, pBuffer, META_SEARCH_GENERIC, wInfoLen, FALSE);
+
+ return dwCookie;
+}
+
+
+
+DWORD SearchByEmail(char* pszEmail)
+{
+ DWORD dwCookie;
+ WORD wInfoLen = 0;
+ WORD wEmailLen;
+ BYTE *pBuffer;
+ int pBufferPos;
+
+ wEmailLen = strlennull(pszEmail);
+
+ _ASSERTE(wEmailLen);
+
+ if (wEmailLen > 0)
+ {
+ // Calculate data size
+ wInfoLen = wEmailLen + 7;
+
+ // Initialize our handy data buffer
+ pBuffer = (BYTE *)_alloca(wInfoLen);
+ pBufferPos = 0;
+
+ // Pack the search details
+ packTLVLNTS(&pBuffer, &pBufferPos, pszEmail, TLV_EMAIL);
+
+ // Send it off for further packing
+ dwCookie = sendTLVSearchPacket(SEARCHTYPE_EMAIL, pBuffer, META_SEARCH_EMAIL, wInfoLen, FALSE);
+ }
+
+ return dwCookie;
+}
+
+
+
+DWORD sendTLVSearchPacket(BYTE bType, char* pSearchDataBuf, WORD wSearchType, WORD wInfoLen, BOOL bOnlineUsersOnly)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ search_cookie* pCookie;
+
+ _ASSERTE(pSearchDataBuf);
+ _ASSERTE(wInfoLen >= 4);
+
+ pCookie = (search_cookie*)SAFE_MALLOC(sizeof(search_cookie));
+ if (pCookie)
+ {
+ pCookie->bSearchType = bType;
+ dwCookie = AllocateCookie(CKT_SEARCH, 0, 0, pCookie);
+ }
+ else
+ return 0;
+
+ // Pack headers
+ packServIcqExtensionHeader(&packet, (WORD)(wInfoLen + (wSearchType==META_SEARCH_GENERIC?7:2)), CLI_META_INFO_REQ, (WORD)dwCookie);
+
+ // Pack search type
+ packLEWord(&packet, wSearchType);
+
+ // Pack search data
+ packBuffer(&packet, pSearchDataBuf, wInfoLen);
+
+ if (wSearchType == META_SEARCH_GENERIC && bOnlineUsersOnly)
+ { // Pack "Online users only" flag - only for generic search
+ BYTE bData = 1;
+ packTLV(&packet, TLV_ONLINEONLY, 1, &bData);
+/* packLEWord(&packet, TLV_ONLINEONLY);
+ packLEWord(&packet, 0x0001);
+ if (bOnlineUsersOnly)
+ packByte(&packet, 0x0001);
+ else
+ packByte(&packet, 0x0000);*/
+ }
+
+ // Go!
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_sendAdvancedSearchServ(BYTE* fieldsBuffer,int bufferLen)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ search_cookie* pCookie;
+
+ pCookie = (search_cookie*)SAFE_MALLOC(sizeof(search_cookie));
+ if (pCookie)
+ {
+ pCookie->bSearchType = SEARCHTYPE_DETAILS;
+ dwCookie = AllocateCookie(CKT_SEARCH, 0, 0, pCookie);
+ }
+ else
+ return 0;
+
+ packServIcqExtensionHeader(&packet, (WORD)(2 + bufferLen), CLI_META_INFO_REQ, (WORD)dwCookie);
+ packBuffer(&packet, (const char*)fieldsBuffer, (WORD)bufferLen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_searchAimByEmail(char* pszEmail, DWORD dwSearchId)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ search_cookie* pCookie;
+ search_cookie* pMainCookie = NULL;
+ WORD wEmailLen;
+
+ if (!FindCookie(dwSearchId, NULL, &pCookie))
+ {
+ dwSearchId = 0;
+ pCookie = (search_cookie*)SAFE_MALLOC(sizeof(search_cookie));
+ pCookie->bSearchType = SEARCHTYPE_EMAIL;
+ }
+
+ if (pCookie)
+ {
+ pCookie->dwMainId = dwSearchId;
+ pCookie->szObject = null_strdup(pszEmail);
+ dwCookie = AllocateCookie(CKT_SEARCH, ICQ_LOOKUP_REQUEST, 0, pCookie);
+ }
+ else
+ return 0;
+
+ wEmailLen = strlennull(pszEmail);
+ serverPacketInit(&packet, (WORD)(10 + wEmailLen));
+ packFNACHeaderFull(&packet, ICQ_LOOKUP_FAMILY, ICQ_LOOKUP_REQUEST, 0, dwCookie);
+ packBuffer(&packet, pszEmail, wEmailLen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_changeUserDetailsServ(WORD type, const unsigned char *pData, WORD wDataLen)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+
+
+ dwCookie = GenerateCookie(0);
+
+ packServIcqExtensionHeader(&packet, (WORD)(wDataLen + 2), CLI_META_INFO_REQ, (WORD)dwCookie);
+ packLEWord(&packet, type);
+ packBuffer(&packet, pData, wDataLen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_sendSMSServ(const char *szPhoneNumber, const char *szMsg)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ WORD wBufferLen;
+ char* szBuffer = NULL;
+ char* szMyNick = NULL;
+ char szTime[30];
+ time_t now;
+ int nBufferSize;
+
+
+ now = time(NULL);
+ strftime(szTime, sizeof(szTime), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
+ /* Sun, 00 Jan 0000 00:00:00 GMT */
+
+ szMyNick = null_strdup((char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)(HANDLE)NULL, 0));
+ nBufferSize = 1 + strlennull(szMyNick) + strlennull(szPhoneNumber) + strlennull(szMsg) + sizeof("<icq_sms_message><destination></destination><text></text><codepage>1252</codepage><encoding>utf8</encoding><senders_UIN>0000000000</senders_UIN><senders_name></senders_name><delivery_receipt>Yes</delivery_receipt><time>Sun, 00 Jan 0000 00:00:00 GMT</time></icq_sms_message>");
+
+ if (szBuffer = (char *)_alloca(nBufferSize))
+ {
+
+ wBufferLen = null_snprintf(szBuffer, nBufferSize,
+ "<icq_sms_message>"
+ "<destination>"
+ "%s" /* phone number */
+ "</destination>"
+ "<text>"
+ "%s" /* body */
+ "</text>"
+ "<codepage>"
+ "1252"
+ "</codepage>"
+ "<encoding>"
+ "utf8"
+ "</encoding>"
+ "<senders_UIN>"
+ "%u" /* my UIN */
+ "</senders_UIN>"
+ "<senders_name>"
+ "%s" /* my nick */
+ "</senders_name>"
+ "<delivery_receipt>"
+ "Yes"
+ "</delivery_receipt>"
+ "<time>"
+ "%s" /* time */
+ "</time>"
+ "</icq_sms_message>",
+ szPhoneNumber, szMsg, dwLocalUIN, szMyNick, szTime);
+
+ dwCookie = GenerateCookie(0);
+
+ packServIcqExtensionHeader(&packet, (WORD)(wBufferLen + 27), CLI_META_INFO_REQ, (WORD)dwCookie);
+ packWord(&packet, 0x8214); /* send sms */
+ packWord(&packet, 1);
+ packWord(&packet, 0x16);
+ packDWord(&packet, 0);
+ packDWord(&packet, 0);
+ packDWord(&packet, 0);
+ packDWord(&packet, 0);
+ packWord(&packet, 0);
+ packWord(&packet, (WORD)(wBufferLen + 1));
+ packBuffer(&packet, szBuffer, (WORD)(1 + wBufferLen));
+
+ sendServPacket(&packet);
+ }
+ else
+ {
+ dwCookie = 0;
+ }
+
+ SAFE_FREE(&szMyNick);
+
+
+ return dwCookie;
+}
+
+
+
+void icq_sendGenericContact(DWORD dwUin, char* szUid, WORD wFamily, WORD wSubType)
+{
+ icq_packet packet;
+ int nUinLen;
+
+ nUinLen = getUIDLen(dwUin, szUid);
+
+ serverPacketInit(&packet, (WORD)(nUinLen + 11));
+ packFNACHeader(&packet, wFamily, wSubType);
+ packUID(&packet, dwUin, szUid);
+
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendNewContact(DWORD dwUin, char* szUid)
+{
+ icq_sendGenericContact(dwUin, szUid, ICQ_BUDDY_FAMILY, ICQ_USER_ADDTOLIST);
+}
+
+
+
+void icq_sendRemoveContact(DWORD dwUin, char* szUid)
+{
+ icq_sendGenericContact(dwUin, szUid, ICQ_BUDDY_FAMILY, ICQ_USER_REMOVEFROMLIST);
+}
+
+
+// list==0: visible list
+// list==1: invisible list
+void icq_sendChangeVisInvis(HANDLE hContact, DWORD dwUin, char* szUID, int list, int add)
+{ // TODO: This needs grouping & rate management
+ // Tell server to change our server-side contact visbility list
+ if (gbSsiEnabled)
+ {
+ WORD wContactId;
+ char* szSetting;
+ WORD wType;
+
+ if (list == 0)
+ {
+ wType = SSI_ITEM_PERMIT;
+ szSetting = "SrvPermitId";
+ }
+ else
+ {
+ wType = SSI_ITEM_DENY;
+ szSetting = "SrvDenyId";
+ }
+
+ if (add)
+ {
+ // check if we should make the changes, this is 2nd level check
+ if (ICQGetContactSettingWord(hContact, szSetting, 0) != 0)
+ return;
+
+ // Add
+ wContactId = GenerateServerId(SSIT_ITEM);
+
+ icq_addServerPrivacyItem(hContact, dwUin, szUID, wContactId, wType);
+
+ ICQWriteContactSettingWord(hContact, szSetting, wContactId);
+ }
+ else
+ {
+ // Remove
+ wContactId = ICQGetContactSettingWord(hContact, szSetting, 0);
+
+ if (wContactId)
+ {
+ icq_removeServerPrivacyItem(hContact, dwUin, szUID, wContactId, wType);
+
+ ICQDeleteContactSetting(hContact, szSetting);
+ }
+ }
+ }
+
+ // Notify server that we have changed
+ // our client side visibility list
+ {
+ int nUinLen;
+ icq_packet packet;
+ WORD wSnac;
+
+ if (list && gnCurrentStatus == ID_STATUS_INVISIBLE)
+ return;
+
+ if (!list && gnCurrentStatus != ID_STATUS_INVISIBLE)
+ return;
+
+
+ if (list && add)
+ wSnac = ICQ_CLI_ADDINVISIBLE;
+ else if (list && !add)
+ wSnac = ICQ_CLI_REMOVEINVISIBLE;
+ else if (!list && add)
+ wSnac = ICQ_CLI_ADDVISIBLE;
+ else if (!list && !add)
+ wSnac = ICQ_CLI_REMOVEVISIBLE;
+
+ nUinLen = getUIDLen(dwUin, szUID);
+
+ serverPacketInit(&packet, (WORD)(nUinLen + 11));
+ packFNACHeader(&packet, ICQ_BOS_FAMILY, wSnac);
+ packUID(&packet, dwUin, szUID);
+
+ sendServPacket(&packet);
+ }
+}
+
+
+
+void icq_sendEntireVisInvisList(int list)
+{
+ if (list)
+ sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_ADDINVISIBLE, BUL_INVISIBLE);
+ else
+ sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_ADDVISIBLE, BUL_VISIBLE);
+}
+
+
+
+void icq_sendRevokeAuthServ(DWORD dwUin, char *szUid)
+{
+ icq_sendGenericContact(dwUin, szUid, ICQ_LISTS_FAMILY, ICQ_LISTS_REVOKEAUTH);
+}
+
+
+
+void icq_sendGrantAuthServ(DWORD dwUin, char *szUid, char *szMsg)
+{
+ icq_packet packet;
+ unsigned char nUinlen;
+ char* szUtfMsg = NULL;
+ WORD nMsglen;
+
+ nUinlen = getUIDLen(dwUin, szUid);
+
+ // Prepare custom utf-8 message
+ szUtfMsg = ansi_to_utf8(szMsg);
+ nMsglen = strlennull(szUtfMsg);
+
+ serverPacketInit(&packet, (WORD)(15 + nUinlen + nMsglen));
+ packFNACHeader(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_GRANTAUTH);
+ packUID(&packet, dwUin, szUid);
+ packWord(&packet, (WORD)nMsglen);
+ packBuffer(&packet, szUtfMsg, nMsglen);
+ packWord(&packet, 0);
+
+ SAFE_FREE(&szUtfMsg);
+
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendAuthReqServ(DWORD dwUin, char *szUid, char *szMsg)
+{
+ icq_packet packet;
+ unsigned char nUinlen;
+ WORD nMsglen;
+
+ nUinlen = getUIDLen(dwUin, szUid);
+ nMsglen = strlennull(szMsg);
+
+ serverPacketInit(&packet, (WORD)(15 + nUinlen + nMsglen));
+ packFNACHeader(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_REQUESTAUTH);
+ packUID(&packet, dwUin, szUid);
+ packWord(&packet, (WORD)nMsglen);
+ packBuffer(&packet, szMsg, nMsglen);
+ packWord(&packet, 0);
+
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendAuthResponseServ(DWORD dwUin, char* szUid, int auth, char *szReason)
+{
+ icq_packet p;
+ WORD nReasonlen;
+ unsigned char nUinlen;
+ char* szUtfReason = NULL;
+
+ nUinlen = getUIDLen(dwUin, szUid);
+
+ // Prepare custom utf-8 reason
+ szUtfReason = ansi_to_utf8(szReason);
+ nReasonlen = strlennull(szUtfReason);
+
+ serverPacketInit(&p, (WORD)(16 + nUinlen + nReasonlen));
+ packFNACHeader(&p, ICQ_LISTS_FAMILY, ICQ_LISTS_CLI_AUTHRESPONSE);
+ packUID(&p, dwUin, szUid);
+ packByte(&p, (BYTE)auth);
+ packWord(&p, nReasonlen);
+ packBuffer(&p, szUtfReason, nReasonlen);
+ packWord(&p, 0);
+
+ SAFE_FREE(&szUtfReason);
+
+ sendServPacket(&p);
+}
+
+
+
+void icq_sendYouWereAddedServ(DWORD dwUin, DWORD dwMyUin)
+{
+ icq_packet packet;
+ DWORD dwID1;
+ DWORD dwID2;
+
+ dwID1 = time(NULL);
+ dwID2 = RandRange(0, 0x00FF);
+
+ packServMsgSendHeader(&packet, 0, dwID1, dwID2, dwUin, NULL, 0x0004, 17);
+ packWord(&packet, 0x0005); // TLV(5)
+ packWord(&packet, 0x0009);
+ packLEDWord(&packet, dwMyUin);
+ packByte(&packet, MTYPE_ADDED);
+ packByte(&packet, 0); // msg-flags
+ packEmptyMsg(&packet); // NTS
+ packDWord(&packet, 0x00060000); // TLV(6)
+
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendXtrazRequestServ(DWORD dwUin, DWORD dwCookie, char* szBody, int nBodyLen, message_cookie_data *pCookieData)
+{
+ icq_packet packet;
+ WORD wCoreLen;
+
+ wCoreLen = 11 + getPluginTypeIdLen(pCookieData->bMessageType) + nBodyLen;
+ packServMsgSendHeader(&packet, dwCookie, pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwUin, NULL, 2, (WORD)(99 + wCoreLen));
+
+ // TLV(5) header
+ packServTLV5Header(&packet, (WORD)(55 + wCoreLen), pCookieData->dwMsgID1, pCookieData->dwMsgID2, 1);
+
+ // TLV(0x2711) header
+ packServTLV2711Header(&packet, (WORD)dwCookie, ICQ_VERSION, MTYPE_PLUGIN, 0, 0, 0x100, wCoreLen);
+ //
+ packEmptyMsg(&packet);
+
+ packPluginTypeId(&packet, pCookieData->bMessageType);
+
+ packLEDWord(&packet, nBodyLen + 4);
+ packLEDWord(&packet, nBodyLen);
+ packBuffer(&packet, szBody, (WORD)nBodyLen);
+
+ // Pack request server ack TLV
+ packDWord(&packet, 0x00030000); // TLV(3)
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendXtrazResponseServ(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szBody, int nBodyLen, int nType)
+{
+ icq_packet packet;
+
+ packServAdvancedMsgReply(&packet, dwUin, dwMID, dwMID2, wCookie, MTYPE_PLUGIN, 0, (WORD)(getPluginTypeIdLen(nType) + 11 + nBodyLen));
+ //
+ packEmptyMsg(&packet);
+
+ packPluginTypeId(&packet, nType);
+
+ packLEDWord(&packet, nBodyLen + 4);
+ packLEDWord(&packet, nBodyLen);
+ packBuffer(&packet, szBody, (WORD)nBodyLen);
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendReverseReq(directconnect *dc, DWORD dwCookie, message_cookie_data *pCookie)
+{
+ icq_packet packet;
+
+ packServMsgSendHeader(&packet, dwCookie, pCookie->dwMsgID1, pCookie->dwMsgID2, dc->dwRemoteUin, NULL, 2, 0x47);
+
+ // TLV(5) header
+ packWord(&packet, 0x05); // Type
+ packWord(&packet, 0x43); // Len
+ // TLV(5) data
+ packWord(&packet, 0); // Command
+ packLEDWord(&packet, pCookie->dwMsgID1); // msgid1
+ packLEDWord(&packet, pCookie->dwMsgID2); // msgid2
+ packGUID(&packet, MCAP_REVERSE_REQ); // capabilities (4 dwords)
+ packDWord(&packet, 0x000A0002); // TLV: 0x0A Acktype: 1 for normal, 2 for ack
+ packWord(&packet, 1);
+ packDWord(&packet, 0x000F0000); // TLV: 0x0F empty
+ packDWord(&packet, 0x2711001B); // TLV: 0x2711 Content
+ // TLV(0x2711) data
+ packLEDWord(&packet, dwLocalUIN); // Our UIN
+ packDWord(&packet, dc->dwLocalExternalIP);// IP to connect to
+ packLEDWord(&packet, wListenPort); // Port to connect to
+ packByte(&packet, DC_NORMAL); // generic DC type
+ packDWord(&packet, dc->dwRemotePort); // unknown
+ packDWord(&packet, wListenPort); // port again ?
+ packLEWord(&packet, ICQ_VERSION); // DC Version
+ packLEDWord(&packet, dwCookie); // Req Cookie
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendReverseFailed(directconnect* dc, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwCookie)
+{
+ icq_packet packet;
+ int nUinLen = getUINLen(dc->dwRemoteUin);
+
+ serverPacketInit(&packet, (WORD)(nUinLen + 74));
+ packFNACHeaderFull(&packet, ICQ_MSG_FAMILY, ICQ_MSG_RESPONSE, 0, ICQ_MSG_RESPONSE<<0x10 | (dwCookie & 0x7FFF));
+ packLEDWord(&packet, dwMsgID1); // Msg ID part 1
+ packLEDWord(&packet, dwMsgID2); // Msg ID part 2
+ packWord(&packet, 0x02);
+ packUIN(&packet, dc->dwRemoteUin);
+ packWord(&packet, 0x03);
+ packLEDWord(&packet, dc->dwRemoteUin);
+ packLEDWord(&packet, dc->dwRemotePort);
+ packLEDWord(&packet, wListenPort);
+ packLEWord(&packet, ICQ_VERSION);
+ packLEDWord(&packet, dwCookie);
+
+ sendServPacket(&packet);
+}
diff --git a/icqj_mod/stdpackets.h b/icqj_mod/stdpackets.h new file mode 100644 index 0000000..c3404c1 --- /dev/null +++ b/icqj_mod/stdpackets.h @@ -0,0 +1,107 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/stdpackets.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Low-level functions that really sends data to server
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __STDPACKETS_H
+#define __STDPACKETS_H
+
+struct icq_contactsend_s
+{
+ DWORD uin;
+ char *uid;
+ char *szNick;
+};
+
+
+void packMsgColorInfo(icq_packet *packet);
+
+void icq_sendCloseConnection();
+
+void icq_requestnewfamily(WORD wFamily, void (*familyhandler)(HANDLE hConn, char* cookie, WORD cookieLen));
+
+void icq_setidle(int bAllow);
+void icq_setstatus(WORD wStatus);
+DWORD icq_sendGetInfoServ(DWORD, int);
+DWORD icq_sendGetAimProfileServ(HANDLE hContact, char *szUid);
+DWORD icq_sendGetAwayMsgServ(DWORD, int, WORD);
+DWORD icq_sendGetAimAwayMsgServ(char *szUID, int type);
+void icq_sendSetAimAwayMsgServ(char *szMsg);
+void icq_sendFileSendServv7(filetransfer* ft, const char *szFiles);
+void icq_sendFileSendServv8(filetransfer* ft, const char *szFiles, int nAckType);
+
+void icq_sendFileAcceptServ(DWORD dwUin, filetransfer *ft, int nAckType);
+void icq_sendFileAcceptServv7(DWORD dwUin, DWORD TS1, DWORD TS2, DWORD dwCookie, const char *szFiles, const char *szDescr, DWORD dwTotalSize, WORD wPort, BOOL accepted, int nAckType);
+void icq_sendFileAcceptServv8(DWORD dwUin, DWORD TS1, DWORD TS2, DWORD dwCookie, const char *szFiles, const char *szDescr, DWORD dwTotalSize, WORD wPort, BOOL accepted, int nAckType);
+
+void icq_sendFileDenyServ(DWORD dwUin, filetransfer* ft, char *szReason, int nAckType);
+
+DWORD icq_sendAdvancedSearchServ(BYTE *fieldsBuffer,int bufferLen);
+DWORD icq_changeUserDetailsServ(WORD, const unsigned char *, WORD);
+void icq_sendGenericContact(DWORD dwUin, char* szUid, WORD wFamily, WORD wSubType);
+void icq_sendNewContact(DWORD dwUin, char* szUid);
+void icq_sendRemoveContact(DWORD dwUin, char* szUid);
+void icq_sendChangeVisInvis(HANDLE hContact, DWORD dwUin, char* szUID, int list, int add);
+void icq_sendEntireVisInvisList(int);
+void icq_sendAwayMsgReplyServ(DWORD, DWORD, DWORD, WORD, WORD, BYTE, const char **);
+void icq_sendAdvancedMsgAck(DWORD, DWORD, DWORD, WORD, BYTE, BYTE);
+DWORD icq_sendSMSServ(const char *szPhoneNumber, const char *szMsg);
+void icq_sendMessageCapsServ(DWORD dwUin);
+void icq_sendRevokeAuthServ(DWORD dwUin, char *szUid);
+void icq_sendGrantAuthServ(DWORD dwUin, char* szUid, char *szMsg);
+void icq_sendAuthReqServ(DWORD dwUin, char* szUid, char *szMsg);
+void icq_sendAuthResponseServ(DWORD dwUin, char* szUid,int auth,char *szReason);
+void icq_sendYouWereAddedServ(DWORD,DWORD);
+
+void sendOwnerInfoRequest(void);
+void sendUserInfoAutoRequest(DWORD dwUin);
+
+DWORD icq_SendChannel1Message(DWORD dwUin, char *szUID, HANDLE hContact, char *pszText, message_cookie_data *pCookieData);
+DWORD icq_SendChannel1MessageW(DWORD dwUin, char *szUID, HANDLE hContact, wchar_t *pszText, message_cookie_data *pCookieData); // UTF-16
+DWORD icq_SendChannel2Message(DWORD dwUin, const char *szMessage, int nBodyLength, WORD wPriority, message_cookie_data *pCookieData, char *szCap);
+DWORD icq_SendChannel4Message(DWORD dwUin, BYTE bMsgType, WORD wMsgLen, const char *szMsg, message_cookie_data *pCookieData);
+
+void icq_sendReverseReq(directconnect *dc, DWORD dwCookie, message_cookie_data *pCookie);
+void icq_sendReverseFailed(directconnect* dc, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwCookie);
+
+void icq_sendXtrazRequestServ(DWORD dwUin, DWORD dwCookie, char* szBody, int nBodyLen, message_cookie_data *pCookieData);
+void icq_sendXtrazResponseServ(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szBody, int nBodyLen, int nType);
+
+DWORD SearchByUin(DWORD dwUin);
+DWORD SearchByNames(char *pszNick, char *pszFirstName, char *pszLastName);
+DWORD SearchByEmail(char *pszEmail);
+
+DWORD icq_searchAimByEmail(char* pszEmail, DWORD dwSearchId);
+
+#endif /* __STDPACKETS_H */
diff --git a/icqj_mod/tlv.c b/icqj_mod/tlv.c new file mode 100644 index 0000000..98d6c27 --- /dev/null +++ b/icqj_mod/tlv.c @@ -0,0 +1,222 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/tlv.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Helper functions for Oscar TLV chains
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+/* set maxTlvs<=0 to get all TLVs in length, or a positive integer to get at most the first n */
+oscar_tlv_chain* readIntoTLVChain(BYTE **buf, WORD wLen, int maxTlvs)
+{
+ oscar_tlv_chain *now, *last, *chain = NULL;
+ WORD now_tlv_len;
+ int len = wLen;
+
+ if (!buf || !wLen) return NULL;
+
+ while (len > 0) /* don't use unsigned variable for this check */
+ {
+ now = (oscar_tlv_chain *)SAFE_MALLOC(sizeof(oscar_tlv_chain));
+
+ if (!now)
+ {
+ disposeChain(&chain);
+ return NULL;
+ }
+
+ unpackWord(buf, &(now->tlv.wType));
+ unpackWord(buf, &now_tlv_len);
+ now->tlv.wLen = now_tlv_len;
+ len -= 4;
+
+ if (now_tlv_len < 1)
+ {
+ now->tlv.pData = NULL;
+ }
+ else if (now_tlv_len <= len)
+ {
+ now->tlv.pData = (BYTE *)SAFE_MALLOC(now_tlv_len);
+ if (now->tlv.pData)
+ memcpy(now->tlv.pData, *buf, now_tlv_len);
+ }
+ else
+ { // the packet is shorter than it should be
+ SAFE_FREE(&now);
+ return chain; // give at least the rest of chain
+ }
+
+ if (chain) // keep the original order
+ last->next = now;
+ else
+ chain = now;
+
+ last = now;
+
+ len -= now_tlv_len;
+ *buf += now_tlv_len;
+
+ if (--maxTlvs == 0)
+ break;
+ }
+
+ return chain;
+}
+
+// Returns a pointer to the TLV with type wType and number wIndex in the chain
+// If wIndex = 1, the first matching TLV will be returned, if wIndex = 2,
+// the second matching one will be returned.
+// wIndex must be > 0
+oscar_tlv* getTLV(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ int i = 0;
+
+ while (list)
+ {
+ if (list->tlv.wType == wType)
+ i++;
+ if (i >= wIndex)
+ return &list->tlv;
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+WORD getLenFromChain(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv;
+ WORD wLen = 0;
+
+ tlv = getTLV(list, wType, wIndex);
+ if (tlv)
+ {
+ wLen = tlv->wLen;
+ }
+
+ return wLen;
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* Values are returned in MSB format */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+DWORD getDWordFromChain(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv;
+ DWORD dw = 0;
+
+ tlv = getTLV(list, wType, wIndex);
+ if (tlv && tlv->wLen >= 4)
+ {
+ dw |= (*((tlv->pData)+0) << 24);
+ dw |= (*((tlv->pData)+1) << 16);
+ dw |= (*((tlv->pData)+2) << 8);
+ dw |= (*((tlv->pData)+3));
+ }
+
+ return dw;
+}
+
+WORD getWordFromChain(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv;
+ WORD w = 0;
+
+ tlv = getTLV(list, wType, wIndex);
+ if (tlv && tlv->wLen >= 2)
+ {
+ w |= (*((tlv->pData)+0) << 8);
+ w |= (*((tlv->pData)+1));
+ }
+
+ return w;
+}
+
+BYTE getByteFromChain(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv;
+ BYTE b = 0;
+
+ tlv = getTLV(list, wType, wIndex);
+ if (tlv && tlv->wLen)
+ {
+ b = *(tlv->pData);
+ }
+
+ return b;
+}
+
+BYTE* getStrFromChain(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv;
+ BYTE *str = NULL;
+
+ tlv = getTLV(list, wType, wIndex);
+ if (tlv)
+ {
+ str = (BYTE*)SAFE_MALLOC(tlv->wLen+1); /* For \0 */
+
+ if (!str) return NULL;
+
+ memcpy(str, tlv->pData, tlv->wLen);
+ *(str+tlv->wLen) = '\0';
+ }
+
+ return str;
+}
+
+void disposeChain(oscar_tlv_chain **list)
+{
+ oscar_tlv_chain *now;
+
+ if (!list || !*list)
+ return;
+
+ now = *list;
+
+ while (now)
+ {
+ oscar_tlv_chain *temp;
+
+ SAFE_FREE(&now->tlv.pData);
+
+ temp = now->next;
+ SAFE_FREE(&now);
+ now = temp;
+ }
+
+ *list = NULL;
+}
diff --git a/icqj_mod/tlv.h b/icqj_mod/tlv.h new file mode 100644 index 0000000..1f1b281 --- /dev/null +++ b/icqj_mod/tlv.h @@ -0,0 +1,68 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/tlv.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __TLV_H
+#define __TLV_H
+
+/*---------* Structures *--------------*/
+
+typedef struct oscar_tlv_s
+{
+ WORD wType;
+ WORD wLen;
+ BYTE *pData;
+} oscar_tlv;
+
+typedef struct oscar_tlv_chain_s
+{
+ oscar_tlv tlv;
+ struct oscar_tlv_chain_s *next;
+} oscar_tlv_chain;
+
+/*---------* Functions *---------------*/
+
+oscar_tlv_chain* readIntoTLVChain(BYTE **buf, WORD wLen, int maxTlvs);
+oscar_tlv* getTLV(oscar_tlv_chain *, WORD, WORD);
+
+WORD getLenFromChain(oscar_tlv_chain* chain, WORD wType, WORD wIndex);
+DWORD getDWordFromChain(oscar_tlv_chain* chain, WORD wType, WORD wIndex);
+WORD getWordFromChain(oscar_tlv_chain* chain, WORD wType, WORD wIndex);
+BYTE getByteFromChain(oscar_tlv_chain* chain, WORD wType, WORD wIndex);
+BYTE *getStrFromChain(oscar_tlv_chain* chain, WORD wType, WORD wIndex);
+
+void disposeChain(oscar_tlv_chain** chain);
+
+#endif /* __TLV_H */
diff --git a/icqj_mod/utilities.c b/icqj_mod/utilities.c new file mode 100644 index 0000000..279874c --- /dev/null +++ b/icqj_mod/utilities.c @@ -0,0 +1,1941 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/utilities.c,v $
+// Revision : $Revision: 3130 $
+// Last change on : $Date: 2006-06-13 23:02:57 +0200 (Tue, 13 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+typedef struct gateway_index_s
+{
+ HANDLE hConn;
+ DWORD dwIndex;
+} gateway_index;
+
+extern CRITICAL_SECTION cookieMutex;
+
+static gateway_index *gateways = NULL;
+static int gatewayCount = 0;
+
+static DWORD *spammerList = NULL;
+static int spammerListCount = 0;
+
+
+static icq_contacts_cache *contacts_cache = NULL;
+static int cacheCount = 0;
+static int cacheListSize = 0;
+static CRITICAL_SECTION cacheMutex;
+
+extern BYTE gbOverRate;
+extern DWORD gtLastRequest;
+extern BOOL bIsSyncingCL;
+
+
+void EnableDlgItem(HWND hwndDlg, UINT control, int state)
+{
+ EnableWindow(GetDlgItem(hwndDlg, control), state);
+}
+
+
+
+void icq_EnableMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state)
+{
+ int i;
+
+ for (i = 0; i < cControls; i++)
+ EnableDlgItem(hwndDlg, controls[i], state);
+}
+
+
+
+void icq_ShowMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state)
+{
+ int i;
+
+ for(i = 0; i < cControls; i++)
+ ShowWindow(GetDlgItem(hwndDlg, controls[i]), state);
+}
+
+
+// Maps the ICQ status flag (as seen in the status change SNACS) and returns
+// a Miranda style status.
+int IcqStatusToMiranda(WORD nIcqStatus)
+{
+ int nMirandaStatus;
+
+ // :NOTE: The order in which the flags are compared are important!
+ // I dont like this method but it works.
+
+ if (nIcqStatus & ICQ_STATUSF_INVISIBLE)
+ nMirandaStatus = ID_STATUS_INVISIBLE;
+ else
+ if (nIcqStatus & ICQ_STATUSF_DND)
+ nMirandaStatus = ID_STATUS_DND;
+ else
+ if (nIcqStatus & ICQ_STATUSF_OCCUPIED)
+ nMirandaStatus = ID_STATUS_OCCUPIED;
+ else
+ if (nIcqStatus & ICQ_STATUSF_NA)
+ nMirandaStatus = ID_STATUS_NA;
+ else
+ if (nIcqStatus & ICQ_STATUSF_AWAY)
+ nMirandaStatus = ID_STATUS_AWAY;
+ else
+ if (nIcqStatus & ICQ_STATUSF_FFC)
+ nMirandaStatus = ID_STATUS_FREECHAT;
+ else
+ // Can be discussed, but I think 'online' is the most generic ICQ status
+ nMirandaStatus = ID_STATUS_ONLINE;
+
+ return nMirandaStatus;
+}
+
+
+
+WORD MirandaStatusToIcq(int nMirandaStatus)
+{
+ WORD nIcqStatus;
+
+
+ switch (nMirandaStatus)
+ {
+
+ case ID_STATUS_ONLINE:
+ nIcqStatus = ICQ_STATUS_ONLINE;
+ break;
+
+ case ID_STATUS_AWAY:
+ nIcqStatus = ICQ_STATUS_AWAY;
+ break;
+
+ case ID_STATUS_OUTTOLUNCH:
+ case ID_STATUS_NA:
+ nIcqStatus = ICQ_STATUS_NA;
+ break;
+
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OCCUPIED:
+ nIcqStatus = ICQ_STATUS_OCCUPIED;
+ break;
+
+ case ID_STATUS_DND:
+ nIcqStatus = ICQ_STATUS_DND;
+ break;
+
+ case ID_STATUS_INVISIBLE:
+ nIcqStatus = ICQ_STATUS_INVISIBLE;
+ break;
+
+ case ID_STATUS_FREECHAT:
+ nIcqStatus = ICQ_STATUS_FFC;
+ break;
+
+ case ID_STATUS_OFFLINE:
+ // Oscar doesnt have anything that maps to this status. This should never happen.
+ _ASSERTE(nMirandaStatus != ID_STATUS_OFFLINE);
+ nIcqStatus = 0;
+ break;
+
+ default:
+ // Online seems to be a good default.
+ // Since it cant be offline, it must be a new type of online status.
+ nIcqStatus = ICQ_STATUS_ONLINE;
+ break;
+ }
+
+ return nIcqStatus;
+}
+
+
+
+int MirandaStatusToSupported(int nMirandaStatus)
+{
+ int nSupportedStatus;
+
+ switch (nMirandaStatus)
+ {
+
+ // These status mode does not need any mapping
+ case ID_STATUS_ONLINE:
+ case ID_STATUS_AWAY:
+ case ID_STATUS_NA:
+ case ID_STATUS_OCCUPIED:
+ case ID_STATUS_DND:
+ case ID_STATUS_INVISIBLE:
+ case ID_STATUS_FREECHAT:
+ case ID_STATUS_OFFLINE:
+ nSupportedStatus = nMirandaStatus;
+ break;
+
+ // This mode is not support and must be mapped to something else
+ case ID_STATUS_OUTTOLUNCH:
+ nSupportedStatus = ID_STATUS_NA;
+ break;
+
+ // This mode is not support and must be mapped to something else
+ case ID_STATUS_ONTHEPHONE:
+ nSupportedStatus = ID_STATUS_OCCUPIED;
+ break;
+
+ // This is not supposed to happen.
+ default:
+ _ASSERTE(0);
+ // Online seems to be a good default.
+ nSupportedStatus = ID_STATUS_ONLINE;
+ break;
+ }
+
+ return nSupportedStatus;
+}
+
+
+
+char* MirandaStatusToString(int mirandaStatus)
+{
+ return (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, mirandaStatus, 0);
+}
+
+
+
+char* MirandaStatusToStringUtf(int mirandaStatus)
+{
+ char* szRes = NULL;
+
+ if (gbUnicodeCore)
+ { // we can get unicode version, request, give utf-8
+ szRes = make_utf8_string((wchar_t *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, mirandaStatus, GCMDF_UNICODE));
+ }
+ else
+ { // we are ansi only, get it, convert to utf-8
+ utf8_encode(MirandaStatusToString(mirandaStatus), &szRes);
+ }
+ return szRes;
+}
+
+
+
+char**MirandaStatusToAwayMsg(int nStatus)
+{
+ switch (nStatus)
+ {
+
+ case ID_STATUS_AWAY:
+ return &modeMsgs.szAway;
+ break;
+
+ case ID_STATUS_NA:
+ return &modeMsgs.szNa;
+
+ case ID_STATUS_OCCUPIED:
+ return &modeMsgs.szOccupied;
+
+ case ID_STATUS_DND:
+ return &modeMsgs.szDnd;
+
+ case ID_STATUS_FREECHAT:
+ return &modeMsgs.szFfc;
+
+ default:
+ return NULL;
+ }
+}
+
+
+
+int AwayMsgTypeToStatus(int nMsgType)
+{
+ switch (nMsgType)
+ {
+ case MTYPE_AUTOAWAY:
+ return ID_STATUS_AWAY;
+
+ case MTYPE_AUTOBUSY:
+ return ID_STATUS_OCCUPIED;
+
+ case MTYPE_AUTONA:
+ return ID_STATUS_NA;
+
+ case MTYPE_AUTODND:
+ return ID_STATUS_DND;
+
+ case MTYPE_AUTOFFC:
+ return ID_STATUS_FREECHAT;
+
+ default:
+ return ID_STATUS_OFFLINE;
+ }
+}
+
+
+
+void SetGatewayIndex(HANDLE hConn, DWORD dwIndex)
+{
+ int i;
+
+ EnterCriticalSection(&cookieMutex);
+
+ for (i = 0; i < gatewayCount; i++)
+ {
+ if (hConn == gateways[i].hConn)
+ {
+ gateways[i].dwIndex = dwIndex;
+
+ LeaveCriticalSection(&cookieMutex);
+
+ return;
+ }
+ }
+
+ gateways = (gateway_index *)realloc(gateways, sizeof(gateway_index) * (gatewayCount + 1));
+ gateways[gatewayCount].hConn = hConn;
+ gateways[gatewayCount].dwIndex = dwIndex;
+ gatewayCount++;
+
+ LeaveCriticalSection(&cookieMutex);
+
+ return;
+}
+
+
+
+DWORD GetGatewayIndex(HANDLE hConn)
+{
+ int i;
+
+ EnterCriticalSection(&cookieMutex);
+
+ for (i = 0; i < gatewayCount; i++)
+ {
+ if (hConn == gateways[i].hConn)
+ {
+ LeaveCriticalSection(&cookieMutex);
+
+ return gateways[i].dwIndex;
+ }
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+
+ return 1; // this is default
+}
+
+
+
+void FreeGatewayIndex(HANDLE hConn)
+{
+ int i;
+
+
+ EnterCriticalSection(&cookieMutex);
+
+ for (i = 0; i < gatewayCount; i++)
+ {
+ if (hConn == gateways[i].hConn)
+ {
+ gatewayCount--;
+ memmove(&gateways[i], &gateways[i+1], sizeof(gateway_index) * (gatewayCount - i));
+ gateways = (gateway_index*)realloc(gateways, sizeof(gateway_index) * gatewayCount);
+
+ // Gateway found, exit loop
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+}
+
+
+
+void AddToSpammerList(DWORD dwUIN)
+{
+ EnterCriticalSection(&cookieMutex);
+
+ spammerList = (DWORD *)realloc(spammerList, sizeof(DWORD) * (spammerListCount + 1));
+ spammerList[spammerListCount] = dwUIN;
+ spammerListCount++;
+
+ LeaveCriticalSection(&cookieMutex);
+}
+
+
+
+BOOL IsOnSpammerList(DWORD dwUIN)
+{
+ int i;
+
+ EnterCriticalSection(&cookieMutex);
+
+ for (i = 0; i < spammerListCount; i++)
+ {
+ if (dwUIN == spammerList[i])
+ {
+ LeaveCriticalSection(&cookieMutex);
+
+ return TRUE;
+ }
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+
+ return FALSE;
+}
+
+
+
+// ICQ contacts cache
+static void AddToCache(HANDLE hContact, DWORD dwUin)
+{
+ int i = 0;
+
+ if (!hContact || !dwUin)
+ return;
+
+ EnterCriticalSection(&cacheMutex);
+
+ if (cacheCount + 1 >= cacheListSize)
+ {
+ cacheListSize += 100;
+ contacts_cache = (icq_contacts_cache *)realloc(contacts_cache, sizeof(icq_contacts_cache) * cacheListSize);
+ }
+
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Adding contact to cache: %u, position: %u", dwUin, cacheCount);
+#endif
+
+ contacts_cache[cacheCount].hContact = hContact;
+ contacts_cache[cacheCount].dwUin = dwUin;
+
+ cacheCount++;
+
+ LeaveCriticalSection(&cacheMutex);
+}
+
+int GetFromCacheByID(int ID, HANDLE *hContact, DWORD *dwUin)
+{
+
+ DWORD uin;
+
+ if (ID < 0 || ID >= cacheCount)
+ return 0;
+
+ EnterCriticalSection(&cacheMutex);
+
+ if (hContact)
+ *hContact = contacts_cache[ID].hContact;
+
+ uin = contacts_cache[ID].dwUin;
+
+ if (dwUin)
+ *dwUin = uin;
+
+ LeaveCriticalSection(&cacheMutex);
+
+ return uin; // to be sure it is not 0
+
+}
+
+
+void InitCache(void)
+{
+ HANDLE hContact;
+
+ InitializeCriticalSection(&cacheMutex);
+ cacheCount = 0;
+ cacheListSize = 0;
+ contacts_cache = NULL;
+
+ // build cache
+ EnterCriticalSection(&cacheMutex);
+
+ hContact = ICQFindFirstContact();
+
+ while (hContact)
+ {
+ DWORD dwUin;
+
+ dwUin = ICQGetContactSettingUIN(hContact);
+ if (dwUin) AddToCache(hContact, dwUin);
+
+ hContact = ICQFindNextContact(hContact);
+ }
+
+ LeaveCriticalSection(&cacheMutex);
+}
+
+
+
+void UninitCache(void)
+{
+ SAFE_FREE(&contacts_cache);
+
+ DeleteCriticalSection(&cacheMutex);
+}
+
+
+
+void DeleteFromCache(HANDLE hContact)
+{
+ int i;
+
+ if (cacheCount == 0)
+ return;
+
+ EnterCriticalSection(&cacheMutex);
+
+ for (i = cacheCount-1; i >= 0; i--)
+ if (contacts_cache[i].hContact == hContact)
+ {
+ cacheCount--;
+
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Removing contact from cache: %u, position: %u", contacts_cache[i].dwUin, i);
+#endif
+ // move last contact to deleted position
+ if (i < cacheCount)
+ memcpy(&contacts_cache[i], &contacts_cache[cacheCount], sizeof(icq_contacts_cache));
+
+ // clear last contact position
+ ZeroMemory(&contacts_cache[cacheCount], sizeof(icq_contacts_cache));
+
+ break;
+ }
+
+ LeaveCriticalSection(&cacheMutex);
+}
+
+
+
+static HANDLE HandleFromCacheByUin(DWORD dwUin)
+{
+ int i;
+ HANDLE hContact = NULL;
+
+ if (cacheCount == 0)
+ return hContact;
+
+ EnterCriticalSection(&cacheMutex);
+
+ for (i = cacheCount-1; i >= 0; i--)
+ if (contacts_cache[i].dwUin == dwUin)
+ {
+ hContact = contacts_cache[i].hContact;
+ break;
+ }
+
+ LeaveCriticalSection(&cacheMutex);
+
+ return hContact;
+}
+
+
+
+HANDLE HContactFromUIN(DWORD uin, int *Added)
+{
+ HANDLE hContact;
+
+ if (Added) *Added = 0;
+
+ hContact = HandleFromCacheByUin(uin);
+ if (hContact) return hContact;
+
+ hContact = ICQFindFirstContact();
+ while (hContact != NULL)
+ {
+ DWORD dwUin;
+
+ dwUin = ICQGetContactSettingUIN(hContact);
+ if (dwUin == uin)
+ {
+ AddToCache(hContact, dwUin);
+ return hContact;
+ }
+
+ hContact = ICQFindNextContact(hContact);
+ }
+
+ //not present: add
+ if (Added)
+ {
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0);
+ if (!hContact)
+ {
+ NetLog_Server("Failed to create ICQ contact %u", uin);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)gpszICQProtoName) != 0)
+ {
+ // For some reason we failed to register the protocol to this contact
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+ NetLog_Server("Failed to register ICQ contact %u", uin);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ ICQWriteContactSettingDword(hContact, UNIQUEIDSETTING, uin);
+
+ if (!bIsSyncingCL)
+ {
+ DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
+ SetContactHidden(hContact, 1);
+
+ ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+
+ icq_QueueUser(hContact);
+
+ if (icqOnline)
+ {
+ icq_sendNewContact(uin, NULL);
+ // else need to wait for CList/NotOnList to be deleted
+ //icq_GetUserStatus(hContact, 3);
+ }
+ }
+ AddToCache(hContact, uin);
+ *Added = 1;
+
+ return hContact;
+ }
+
+ // not in list, check that uin do not belong to us
+ if (ICQGetContactSettingUIN(NULL) == uin)
+ return NULL;
+
+ return INVALID_HANDLE_VALUE;
+}
+
+
+
+HANDLE HContactFromUID(DWORD dwUIN, char* pszUID, int *Added)
+{
+ HANDLE hContact;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (dwUIN)
+ return HContactFromUIN(dwUIN, Added);
+
+ if (Added) *Added = 0;
+
+ if (!gbAimEnabled) return INVALID_HANDLE_VALUE;
+
+ hContact = ICQFindFirstContact();
+ while (hContact != NULL)
+ {
+ if (!ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ {
+ if (!dwUin && !stricmp(szUid, pszUID))
+ {
+ if (strcmpnull(szUid, pszUID))
+ { // fix case in SN
+ ICQWriteContactSettingString(hContact, UNIQUEIDSETTING, pszUID);
+ }
+ return hContact;
+ }
+ }
+ hContact = ICQFindNextContact(hContact);
+ }
+
+ //not present: add
+ if (Added)
+ {
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0);
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)gpszICQProtoName);
+
+ ICQWriteContactSettingString(hContact, UNIQUEIDSETTING, pszUID);
+
+ if (!bIsSyncingCL)
+ {
+ DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
+ SetContactHidden(hContact, 1);
+
+ ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+
+ if (icqOnline)
+ {
+ icq_sendNewContact(0, pszUID);
+ }
+ }
+ *Added = 1;
+
+ return hContact;
+ }
+
+ return INVALID_HANDLE_VALUE;
+}
+
+
+
+char *NickFromHandle(HANDLE hContact)
+{
+ if (hContact == INVALID_HANDLE_VALUE)
+ return null_strdup(ICQTranslate("<invalid>"));
+
+ return null_strdup((char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0));
+}
+
+void NickFromHandleStatic(HANDLE hContact, char *szNick, WORD wLen)
+{
+
+ if (!wLen || !szNick) return;
+
+ if (hContact == INVALID_HANDLE_VALUE)
+ lstrcpyn(szNick, "<invalid>", wLen);
+ else
+ lstrcpyn(szNick, (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0), wLen);
+
+}
+
+
+char *NickFromHandleUtf(HANDLE hContact)
+{
+ if (hContact == INVALID_HANDLE_VALUE)
+ return ICQTranslateUtf("<invalid>");
+
+ if (gbUnicodeCore)
+ return make_utf8_string((wchar_t*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_UNICODE));
+ else
+ {
+ unsigned char *utf = NULL;
+
+ utf8_encode((char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0), &utf);
+ return utf;
+ }
+}
+
+
+
+char *strUID(DWORD dwUIN, char *pszUID)
+{
+ if (dwUIN)
+ ltoa(dwUIN, pszUID, 10);
+
+ return pszUID;
+}
+
+
+
+void SetContactHidden(HANDLE hContact, BYTE bHidden)
+{
+ DBWriteContactSettingByte(hContact, "CList", "Hidden", bHidden);
+
+ if (!bHidden) // clear zero setting
+ DBDeleteContactSetting(hContact, "CList", "Hidden");
+}
+
+
+
+/* a strlennull() that likes NULL */
+size_t __fastcall strlennull(const char *string)
+{
+ if (string)
+ return strlen(string);
+
+ return 0;
+}
+
+
+/* a strcmp() that likes NULL */
+int __fastcall strcmpnull(const char *str1, const char *str2)
+{
+ if (str1 && str2)
+ return strcmp(str1, str2);
+
+ return 1;
+}
+
+
+
+int null_snprintf(char *buffer, size_t count, const char* fmt, ...)
+{
+ va_list va;
+ int len;
+
+ ZeroMemory(buffer, count);
+ va_start(va, fmt);
+ len = _vsnprintf(buffer, count-1, fmt, va);
+ va_end(va);
+ return len;
+}
+
+
+
+char* __fastcall null_strdup(const char *string)
+{
+ if (string)
+ return strdup(string);
+
+ return NULL;
+}
+
+
+
+void parseServerAddress(char* szServer, WORD* wPort)
+{
+ int i = 0;
+
+ while (szServer[i] && szServer[i] != ':') i++;
+ if (szServer[i] == ':')
+ { // port included
+ *wPort = atoi(&szServer[i + 1]);
+ }
+ else // port not found, use pre-configured
+ {
+ *wPort = ICQGetContactSettingWord(NULL, "OscarPort", DEFAULT_SERVER_PORT);
+ if (!*wPort) *wPort = (WORD)RandRange(1024, 65535);
+ }
+
+ szServer[i] = '\0';
+}
+
+
+
+char *DemangleXml(const char *string, int len)
+{
+ char *szWork = (char*)SAFE_MALLOC(len+1), *szChar = szWork;
+ int i;
+
+ for (i=0; i<len; i++)
+ {
+ if (!strnicmp(string+i, ">", 4))
+ {
+ *szChar = '>';
+ szChar++;
+ i += 3;
+ }
+ else if (!strnicmp(string+i, "<", 4))
+ {
+ *szChar = '<';
+ szChar++;
+ i += 3;
+ }
+ else if (!strnicmp(string+i, "&", 5))
+ {
+ *szChar = '&';
+ szChar++;
+ i += 4;
+ }
+ else if (!strnicmp(string+i, """, 6))
+ {
+ *szChar = '"';
+ szChar++;
+ i += 5;
+ }
+ else
+ {
+ *szChar = string[i];
+ szChar++;
+ }
+ }
+ *szChar = '\0';
+
+ return szWork;
+}
+
+
+
+char *MangleXml(const char *string, int len)
+{
+ int i, l = 1;
+ char *szWork, *szChar;
+
+ for (i = 0; i<len; i++)
+ {
+ if (string[i]=='<' || string[i]=='>') l += 4; else if (string[i]=='&') l += 5; else l++;
+ }
+ szChar = szWork = (char*)SAFE_MALLOC(l + 1);
+ for (i = 0; i<len; i++)
+ {
+ if (string[i]=='<')
+ {
+ *(DWORD*)szChar = ';tl&';
+ szChar += 4;
+ }
+ else if (string[i]=='>')
+ {
+ *(DWORD*)szChar = ';tg&';
+ szChar += 4;
+ }
+ else if (string[i]=='&')
+ {
+ *(DWORD*)szChar = 'pma&';
+ szChar += 4;
+ *szChar = ';';
+ szChar++;
+ }
+ else
+ {
+ *szChar = string[i];
+ szChar++;
+ }
+ }
+ *szChar = '\0';
+
+ return szWork;
+}
+
+
+
+char *EliminateHtml(const char *string, int len)
+{
+ char *tmp = (char*)SAFE_MALLOC(len + 1);
+ int i,j;
+ BOOL tag = FALSE;
+ char *res;
+
+ for (i=0,j=0;i<len;i++)
+ {
+ if (!tag && string[i] == '<')
+ {
+ if ((i + 4 <= len) && (!strnicmp(string + i, "<br>", 4) || !strnicmp(string + i, "<br/>", 5)))
+ { // insert newline
+ tmp[j] = '\r';
+ j++;
+ tmp[j] = '\n';
+ j++;
+ }
+ tag = TRUE;
+ }
+ else if (tag && string[i] == '>')
+ {
+ tag = FALSE;
+ }
+ else if (!tag)
+ {
+ tmp[j] = string[i];
+ j++;
+ }
+ tmp[j] = '\0';
+ }
+ SAFE_FREE((void**)&string);
+ res = DemangleXml(tmp, strlennull(tmp));
+ SAFE_FREE(&tmp);
+
+ return res;
+}
+
+void makeUserOffline(HANDLE hContact)
+{
+
+ WORD w;
+ DWORD dw;
+
+ if (DBGetContactSettingWord(hContact, gpszICQProtoName, "Status", 0) != ID_STATUS_OFFLINE)
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "Status", ID_STATUS_OFFLINE);
+
+ if (dw=DBGetContactSettingDword(hContact, gpszICQProtoName, "LogonTS", 0)) {
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "LogonTS", 0);
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "OldLogonTS", dw);
+ }
+
+ if (dw=DBGetContactSettingDword(hContact, gpszICQProtoName, "IdleTS", 0)) {
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "IdleTS", 0);
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "OldIdleTS", dw);
+ }
+
+ if (dw=DBGetContactSettingDword(hContact, gpszICQProtoName, "RealIP", 0)) {
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "RealIP", 0);
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "OldRealIP", dw);
+ }
+
+ if (dw=DBGetContactSettingDword(hContact, gpszICQProtoName, "IP", 0)) {
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "IP", 0);
+ DBWriteContactSettingDword(hContact, gpszICQProtoName, "OldIP", dw);
+ }
+
+ if (w=DBGetContactSettingWord(hContact, gpszICQProtoName, "UserPort", 0)) {
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "UserPort", 0);
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "OldUserPort", w);
+ }
+
+ if (w=DBGetContactSettingWord(hContact, gpszICQProtoName, "Version", 0)) {
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "Version", 0);
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "OldVersion", w);
+ }
+
+
+ // if (DBGetContactSettingDword(hContact, gpszICQProtoName, "TickTS", 0))
+ // DBWriteContactSettingDword(hContact, gpszICQProtoName, "TickTS", 0);
+
+ //DBWriteContactSettingDword(hContact, gpszICQProtoName, "DirectCookie", 0);
+}
+
+
+void ResetSettingsOnListReload()
+{
+ HANDLE hContact;
+
+ // Reset a bunch of session specific settings
+ ICQWriteContactSettingWord(NULL, "SrvVisibilityID", 0);
+ ICQWriteContactSettingWord(NULL, "SrvAvatarID", 0);
+ ICQWriteContactSettingWord(NULL, "SrvRecordCount", 0);
+
+ hContact = ICQFindFirstContact();
+
+ while (hContact)
+ {
+ // All these values will be restored during the serv-list receive
+ ICQWriteContactSettingWord(hContact, "ServerId", 0);
+ ICQWriteContactSettingWord(hContact, "SrvGroupId", 0);
+ ICQWriteContactSettingWord(hContact, "SrvPermitId", 0);
+ ICQWriteContactSettingWord(hContact, "SrvDenyId", 0);
+ ICQWriteContactSettingByte(hContact, "Auth", 0);
+
+ hContact = ICQFindNextContact(hContact);
+ }
+
+ FlushSrvGroupsCache();
+}
+
+
+
+void ResetSettingsOnConnect()
+{
+ HANDLE hContact;
+
+ gbOverRate = 0; // init
+ gtLastRequest = 0;
+
+ // Reset a bunch of session specific settings
+ ICQWriteContactSettingByte(NULL, "SrvVisibility", 0);
+ ICQWriteContactSettingDword(NULL, "IdleTS", 0);
+
+ hContact = ICQFindFirstContact();
+
+ while (hContact)
+ {
+ ICQWriteContactSettingDword(hContact, "LogonTS", 0);
+ ICQWriteContactSettingDword(hContact, "IdleTS", 0);
+ ICQWriteContactSettingDword(hContact, "TickTS", 0);
+ ICQDeleteContactSetting(hContact, "TemporaryVisible");
+
+ // All these values will be restored during the login
+ if (ICQGetContactStatus(hContact) != ID_STATUS_OFFLINE)
+ ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+
+ hContact = ICQFindNextContact(hContact);
+ }
+}
+
+
+
+void ResetSettingsOnLoad()
+{
+ HANDLE hContact;
+
+ ICQWriteContactSettingDword(NULL, "IdleTS", 0);
+ ICQWriteContactSettingDword(NULL, "LogonTS", 0);
+
+ hContact = ICQFindFirstContact();
+
+ while (hContact)
+ {
+ ICQWriteContactSettingDword(hContact, "LogonTS", 0);
+ ICQWriteContactSettingDword(hContact, "IdleTS", 0);
+ ICQWriteContactSettingDword(hContact, "TickTS", 0);
+ if (ICQGetContactStatus(hContact) != ID_STATUS_OFFLINE)
+ {
+ ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSID);
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSNAME);
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSMSG);
+ }
+ hContact = ICQFindNextContact(hContact);
+ }
+}
+
+
+
+int RandRange(int nLow, int nHigh)
+{
+ return nLow + (int)((nHigh-nLow+1)*rand()/(RAND_MAX+1.0));
+}
+
+
+
+BOOL IsStringUIN(char* pszString)
+{
+ int i;
+ int nLen = strlennull(pszString);
+
+
+ if (nLen > 0 && pszString[0] != '0')
+ {
+ for (i=0; i<nLen; i++)
+ {
+ if ((pszString[i] < '0') || (pszString[i] > '9'))
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+void __cdecl icq_ProtocolAckThread(icq_ack_args* pArguments)
+{
+ ICQBroadcastAck(pArguments->hContact, pArguments->nAckType, pArguments->nAckResult, pArguments->hSequence, pArguments->pszMessage);
+
+ if (pArguments->nAckResult == ACKRESULT_SUCCESS)
+ NetLog_Server("Sent fake message ack");
+ else if (pArguments->nAckResult == ACKRESULT_FAILED)
+ NetLog_Server("Message delivery failed");
+
+ SAFE_FREE((char **)&pArguments->pszMessage);
+ SAFE_FREE(&pArguments);
+
+ return;
+}
+
+
+
+void icq_SendProtoAck(HANDLE hContact, DWORD dwCookie, int nAckResult, int nAckType, char* pszMessage)
+{
+ icq_ack_args* pArgs;
+
+
+ pArgs = (icq_ack_args*)SAFE_MALLOC(sizeof(icq_ack_args)); // This will be freed in the new thread
+
+ pArgs->hContact = hContact;
+ pArgs->hSequence = (HANDLE)dwCookie;
+ pArgs->nAckResult = nAckResult;
+ pArgs->nAckType = nAckType;
+ pArgs->pszMessage = (LPARAM)null_strdup(pszMessage);
+
+ forkthread(icq_ProtocolAckThread, 0, pArgs);
+}
+
+
+
+void SetCurrentStatus(int nStatus)
+{
+ int nOldStatus = gnCurrentStatus;
+
+ gnCurrentStatus = nStatus;
+ ICQBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)nOldStatus, nStatus);
+}
+
+
+
+BOOL writeDbInfoSettingString(HANDLE hContact, const char* szSetting, char** buf, WORD* pwLength)
+{
+ WORD wLen;
+
+
+ if (*pwLength < 2)
+ return FALSE;
+
+ unpackLEWord(buf, &wLen);
+ *pwLength -= 2;
+
+ if (*pwLength < wLen)
+ return FALSE;
+
+ if ((wLen > 0) && (**buf) && ((*buf)[wLen-1]==0)) // Make sure we have a proper string
+ {
+ WORD wCp = ICQGetContactSettingWord(hContact, "InfoCodePage", ICQGetContactSettingWord(hContact, "InfoCP", CP_ACP));
+
+ if (wCp != CP_ACP)
+ {
+ char *szUtf = ansi_to_utf8_codepage(*buf, wCp);
+
+ if (szUtf)
+ {
+ ICQWriteContactSettingUtf(hContact, szSetting, szUtf);
+ SAFE_FREE(&szUtf);
+ }
+ else
+ ICQWriteContactSettingString(hContact, szSetting, *buf);
+ }
+ else
+ ICQWriteContactSettingString(hContact, szSetting, *buf);
+ }
+ else
+ ICQDeleteContactSetting(hContact, szSetting);
+
+ *buf += wLen;
+ *pwLength -= wLen;
+
+ return TRUE;
+}
+
+
+
+BOOL writeDbInfoSettingWord(HANDLE hContact, const char *szSetting, char **buf, WORD* pwLength)
+{
+ WORD wVal;
+
+
+ if (*pwLength < 2)
+ return FALSE;
+
+ unpackLEWord(buf, &wVal);
+ *pwLength -= 2;
+
+ if (wVal != 0)
+ ICQWriteContactSettingWord(hContact, szSetting, wVal);
+ else
+ ICQDeleteContactSetting(hContact, szSetting);
+
+ return TRUE;
+}
+
+
+
+BOOL writeDbInfoSettingWordWithTable(HANDLE hContact, const char *szSetting, struct fieldnames_t *table, char **buf, WORD* pwLength)
+{
+ WORD wVal;
+ char sbuf[MAX_PATH];
+ char *text;
+
+ if (*pwLength < 2)
+ return FALSE;
+
+ unpackLEWord(buf, &wVal);
+ *pwLength -= 2;
+
+ text = LookupFieldNameUtf(table, wVal, sbuf);
+ if (text)
+ ICQWriteContactSettingUtf(hContact, szSetting, text);
+ else
+ ICQDeleteContactSetting(hContact, szSetting);
+
+ return TRUE;
+}
+
+
+
+BOOL writeDbInfoSettingByte(HANDLE hContact, const char *pszSetting, char **buf, WORD* pwLength)
+{
+ BYTE byVal;
+
+ if (*pwLength < 1)
+ return FALSE;
+
+ unpackByte(buf, &byVal);
+ *pwLength -= 1;
+
+ if (byVal != 0)
+ ICQWriteContactSettingByte(hContact, pszSetting, byVal);
+ else
+ ICQDeleteContactSetting(hContact, pszSetting);
+
+ return TRUE;
+}
+
+
+
+BOOL writeDbInfoSettingByteWithTable(HANDLE hContact, const char *szSetting, struct fieldnames_t *table, char **buf, WORD* pwLength)
+{
+ BYTE byVal;
+ char sbuf[MAX_PATH];
+ char *text;
+
+ if (*pwLength < 1)
+ return FALSE;
+
+ unpackByte(buf, &byVal);
+ *pwLength -= 1;
+
+ text = LookupFieldNameUtf(table, byVal, sbuf);
+ if (text)
+ ICQWriteContactSettingUtf(hContact, szSetting, text);
+ else
+ ICQDeleteContactSetting(hContact, szSetting);
+
+ return TRUE;
+}
+
+
+
+// Returns the current GMT offset in seconds
+int GetGMTOffset(void)
+{
+ TIME_ZONE_INFORMATION tzinfo;
+ DWORD dwResult;
+ int nOffset = 0;
+
+
+ dwResult = GetTimeZoneInformation(&tzinfo);
+
+ switch(dwResult)
+ {
+
+ case TIME_ZONE_ID_STANDARD:
+ nOffset = -(tzinfo.Bias + tzinfo.StandardBias) * 60;
+ break;
+
+ case TIME_ZONE_ID_DAYLIGHT:
+ nOffset = -(tzinfo.Bias + tzinfo.DaylightBias) * 60;
+ break;
+
+ case TIME_ZONE_ID_UNKNOWN:
+ case TIME_ZONE_ID_INVALID:
+ default:
+ nOffset = 0;
+ break;
+
+ }
+
+ return nOffset;
+}
+
+
+
+BOOL validateStatusMessageRequest(HANDLE hContact, WORD byMessageType)
+{
+ // Privacy control
+ if (ICQGetContactSettingByte(NULL, "StatusMsgReplyCList", 0))
+ {
+ // Don't send statusmessage to unknown contacts
+ if (hContact == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ // Don't send statusmessage to temporary contacts or hidden contacts
+ if (DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) ||
+ DBGetContactSettingByte(hContact, "CList", "Hidden", 0))
+ return FALSE;
+
+ // Don't send statusmessage to invisible contacts
+ if (ICQGetContactSettingByte(NULL, "StatusMsgReplyVisible", 0))
+ {
+ WORD wStatus = ICQGetContactStatus(hContact);
+ if (wStatus == ID_STATUS_OFFLINE)
+ return FALSE;
+ }
+ }
+
+ // Dont send messages to people you are hiding from
+ if (hContact != INVALID_HANDLE_VALUE &&
+ ICQGetContactSettingWord(hContact, "ApparentMode", 0) == ID_STATUS_OFFLINE)
+ {
+ return FALSE;
+ }
+
+ // Dont respond to request for other statuses than your current one
+ if ((byMessageType == MTYPE_AUTOAWAY && gnCurrentStatus != ID_STATUS_AWAY) ||
+ (byMessageType == MTYPE_AUTOBUSY && gnCurrentStatus != ID_STATUS_OCCUPIED) ||
+ (byMessageType == MTYPE_AUTONA && gnCurrentStatus != ID_STATUS_NA) ||
+ (byMessageType == MTYPE_AUTODND && gnCurrentStatus != ID_STATUS_DND) ||
+ (byMessageType == MTYPE_AUTOFFC && gnCurrentStatus != ID_STATUS_FREECHAT))
+ {
+ return FALSE;
+ }
+
+ if (hContact != INVALID_HANDLE_VALUE && gnCurrentStatus==ID_STATUS_INVISIBLE &&
+ ICQGetContactSettingWord(hContact, "ApparentMode", 0) != ID_STATUS_ONLINE)
+ {
+ if (!ICQGetContactSettingByte(hContact, "TemporaryVisible", 0))
+ { // Allow request to temporary visible contacts
+ return FALSE;
+ }
+ }
+
+ // All OK!
+ return TRUE;
+}
+
+
+
+void __fastcall SAFE_FREE(void** p)
+{
+ if (*p)
+ {
+ free(*p);
+ *p = NULL;
+ }
+}
+
+
+
+void* __fastcall SAFE_MALLOC(size_t size)
+{
+ void* p = malloc(size);
+
+ if (p)
+ ZeroMemory(p, size);
+
+ return p;
+}
+
+
+static int bPhotoLock = 0;
+
+void LinkContactPhotoToFile(HANDLE hContact, char* szFile)
+{ // set contact photo if linked if no photo set link
+ if (ICQGetContactSettingByte(NULL, "AvatarsAutoLink", DEFAULT_LINK_AVATARS))
+ {
+ bPhotoLock = 1;
+ {
+ if (DBGetContactSettingByte(hContact, "ContactPhoto", "ICQLink", 0))
+ { // we are linked update DB
+ if (szFile)
+ {
+ DBDeleteContactSetting(hContact, "ContactPhoto", "File"); // delete that setting
+ DBDeleteContactSetting(hContact, "ContactPhoto", "Link");
+ if (DBWriteContactSettingString(hContact, "ContactPhoto", "File", szFile))
+ NetLog_Server("Avatar file could not be linked to ContactPhoto.");
+ }
+ else
+ { // no file, unlink
+ DBDeleteContactSetting(hContact, "ContactPhoto", "File");
+ DBDeleteContactSetting(hContact, "ContactPhoto", "ICQLink");
+ }
+ }
+ else if (szFile)
+ { // link only if file valid
+ DBVARIANT dbv;
+ if (DBGetContactSetting(hContact, "ContactPhoto", "File", &dbv))
+ {
+ if (DBGetContactSetting(hContact, "ContactPhoto", "Link", &dbv))
+ { // no photo defined
+ DBWriteContactSettingString(hContact, "ContactPhoto", "File", szFile);
+ DBWriteContactSettingByte(hContact, "ContactPhoto", "ICQLink", 1);
+ }
+ ICQFreeVariant(&dbv);
+ }
+ else
+ { // some file already defined, check if it is not the same, if yes, set link
+ if (!strcmpnull(dbv.pszVal, szFile))
+ {
+ DBWriteContactSettingByte(hContact, "ContactPhoto", "ICQLink", 1);
+ }
+ ICQFreeVariant(&dbv);
+ }
+ }
+ }
+ bPhotoLock = 0;
+ }
+}
+
+
+static int bNoChanging = 0;
+
+void ContactPhotoSettingChanged(HANDLE hContact)
+{ // the setting was changed - if it is done externaly unlink...
+ if (bNoChanging) return;
+ bNoChanging = 1;
+
+ if (!bPhotoLock && ICQGetContactSettingByte(NULL, "AvatarsAutoLink", DEFAULT_LINK_AVATARS))
+ DBDeleteContactSetting(hContact, "ContactPhoto", "ICQLink");
+
+ bNoChanging = 0;
+}
+
+
+
+HANDLE NetLib_OpenConnection(HANDLE hUser, NETLIBOPENCONNECTION* nloc)
+{
+ HANDLE hConnection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hUser, (LPARAM)nloc);
+ if (!hConnection && (GetLastError() == 87))
+ { // this ensures, an old Miranda will be able to connect also
+ nloc->cbSize = NETLIBOPENCONNECTION_V1_SIZE;
+ hConnection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hUser, (LPARAM)nloc);
+ }
+ return hConnection;
+}
+
+
+
+int NetLog_Server(const char *fmt,...)
+{
+ va_list va;
+ char szText[1024];
+
+ va_start(va,fmt);
+ mir_vsnprintf(szText,sizeof(szText),fmt,va);
+ va_end(va);
+ return CallService(MS_NETLIB_LOG,(WPARAM)ghServerNetlibUser,(LPARAM)szText);
+}
+
+
+
+int NetLog_Direct(const char *fmt,...)
+{
+ va_list va;
+ char szText[1024];
+
+ va_start(va,fmt);
+ mir_vsnprintf(szText,sizeof(szText),fmt,va);
+ va_end(va);
+ return CallService(MS_NETLIB_LOG,(WPARAM)ghDirectNetlibUser,(LPARAM)szText);
+}
+
+
+
+int NetLog_Uni(BOOL bDC, const char *fmt,...)
+{
+ va_list va;
+ char szText[1024];
+ HANDLE hNetlib;
+
+ va_start(va,fmt);
+ mir_vsnprintf(szText,sizeof(szText),fmt,va);
+ va_end(va);
+
+ if (bDC)
+ hNetlib = ghDirectNetlibUser;
+ else
+ hNetlib = ghServerNetlibUser;
+
+ return CallService(MS_NETLIB_LOG,(WPARAM)hNetlib,(LPARAM)szText);
+}
+
+
+
+int ICQBroadcastAck(HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam)
+{
+ ACKDATA ack={0};
+
+ ack.cbSize=sizeof(ACKDATA);
+ ack.szModule=gpszICQProtoName;
+ ack.hContact=hContact;
+ ack.type=type;
+ ack.result=result;
+ ack.hProcess=hProcess;
+ ack.lParam=lParam;
+ return CallService(MS_PROTO_BROADCASTACK,0,(LPARAM)&ack);
+}
+
+
+
+int __fastcall ICQTranslateDialog(HWND hwndDlg)
+{
+ LANGPACKTRANSLATEDIALOG lptd;
+
+ lptd.cbSize=sizeof(lptd);
+ lptd.flags=0;
+ lptd.hwndDlg=hwndDlg;
+ lptd.ignoreControls=NULL;
+ return CallService(MS_LANGPACK_TRANSLATEDIALOG,0,(LPARAM)&lptd);
+}
+
+
+
+char* __fastcall ICQTranslate(const char* src)
+{
+ return (char*)CallService(MS_LANGPACK_TRANSLATESTRING,0,(LPARAM)src);
+}
+
+
+
+char* __fastcall ICQTranslateUtf(const char* src)
+{ // this takes UTF-8 strings only!!!
+ char* szRes = NULL;
+
+ if (!strlennull(src))
+ { // for the case of empty strings
+ return null_strdup(src);
+ }
+
+ if (gbUtfLangpack)
+ { // we can use unicode translate
+ wchar_t* usrc = make_unicode_string(src);
+
+ szRes = make_utf8_string(TranslateW(usrc));
+
+ SAFE_FREE(&usrc);
+ }
+ else
+ {
+ int size = strlennull(src)+2;
+ char* asrc = (char*)_alloca(size);
+
+ utf8_decode_static(src, asrc, size);
+ utf8_encode(Translate(asrc), &szRes);
+ }
+ return szRes;
+}
+
+
+
+char* __fastcall ICQTranslateUtfStatic(const char* src, char* buf)
+{ // this takes UTF-8 strings only!!!
+ char* t;
+
+ if (strlennull(src))
+ {
+ t = ICQTranslateUtf(src);
+ strcpy(buf, t);
+ SAFE_FREE(&t);
+ }
+ else
+ buf[0] = '\0';
+
+ return buf;
+}
+
+
+
+char* GetUserPassword(BOOL bAlways)
+{
+ if (gpszPassword[0] != '\0' && (gbRememberPwd || bAlways))
+ return gpszPassword;
+
+ if (!ICQGetContactStaticString(NULL, "Password", gpszPassword, sizeof(gpszPassword)))
+ {
+ CallService(MS_DB_CRYPT_DECODESTRING, strlennull(gpszPassword) + 1, (LPARAM)gpszPassword);
+
+ if (!strlennull(gpszPassword)) return NULL;
+
+ gbRememberPwd = TRUE;
+
+ return gpszPassword;
+ }
+
+ return NULL;
+}
+
+
+
+WORD GetMyStatusFlags()
+{
+ WORD wFlags = 0;
+
+ // Webaware setting bit flag
+ if (ICQGetContactSettingByte(NULL, "WebAware", 0))
+ wFlags = STATUS_WEBAWARE;
+
+ // DC setting bit flag
+ switch (ICQGetContactSettingByte(NULL, "DCType", 0))
+ {
+ case 0:
+ break;
+
+ case 1:
+ wFlags = wFlags | STATUS_DCCONT;
+ break;
+
+ case 2:
+ wFlags = wFlags | STATUS_DCAUTH;
+ break;
+
+ default:
+ wFlags = wFlags | STATUS_DCDISABLED;
+ break;
+ }
+ return wFlags;
+}
+
+
+
+wchar_t *GetWindowTextUcs(HWND hWnd)
+{
+ wchar_t *utext;
+
+ if (gbUnicodeAPI)
+ {
+ int nLen = GetWindowTextLengthW(hWnd);
+
+ utext = (wchar_t*)SAFE_MALLOC((nLen+2)*sizeof(wchar_t));
+ GetWindowTextW(hWnd, utext, nLen + 1);
+ }
+ else
+ {
+ char *text;
+ int wchars, nLen = GetWindowTextLengthA(hWnd);
+
+ text = (char*)_alloca(nLen+2);
+ GetWindowTextA(hWnd, text, nLen + 1);
+
+ wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text,
+ strlennull(text), NULL, 0);
+
+ utext = (wchar_t*)SAFE_MALLOC((wchars + 1)*sizeof(unsigned short));
+
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text,
+ strlennull(text), utext, wchars);
+ }
+ return utext;
+}
+
+
+
+void SetWindowTextUcs(HWND hWnd, wchar_t *text)
+{
+ if (gbUnicodeAPI)
+ {
+ SetWindowTextW(hWnd, text);
+ }
+ else
+ {
+ char *tmp = (char*)SAFE_MALLOC(wcslen(text) + 1);
+
+ WideCharToMultiByte(CP_ACP, 0, text, -1, tmp, wcslen(text)+1, NULL, NULL);
+ SetWindowTextA(hWnd, tmp);
+ SAFE_FREE(&tmp);
+ }
+}
+
+
+
+char* GetWindowTextUtf(HWND hWnd)
+{
+ if (gbUnicodeAPI)
+ {
+ wchar_t* usText;
+ int nLen = GetWindowTextLengthW(hWnd);
+
+ usText = (wchar_t*)_alloca((nLen+2)*sizeof(wchar_t));
+ GetWindowTextW(hWnd, usText, nLen + 1);
+ return make_utf8_string(usText);
+ }
+ else
+ {
+ char* szAnsi;
+ int nLen = GetWindowTextLengthA(hWnd);
+
+ szAnsi = (char*)_alloca(nLen+2);
+ GetWindowTextA(hWnd, szAnsi, nLen + 1);
+ return ansi_to_utf8(szAnsi);
+ }
+}
+
+
+
+char* GetDlgItemTextUtf(HWND hwndDlg, int iItem)
+{
+ return GetWindowTextUtf(GetDlgItem(hwndDlg, iItem));
+}
+
+
+
+void SetWindowTextUtf(HWND hWnd, const char* szText)
+{
+ if (gbUnicodeAPI)
+ {
+ wchar_t* usText = make_unicode_string(szText);
+
+ SetWindowTextW(hWnd, usText);
+ SAFE_FREE(&usText);
+ }
+ else
+ {
+ int size = strlennull(szText)+2;
+ char* szAnsi = (char*)_alloca(size);
+
+ if (utf8_decode_static(szText, szAnsi, size))
+ SetWindowTextA(hWnd, szAnsi);
+ }
+}
+
+
+
+void SetDlgItemTextUtf(HWND hwndDlg, int iItem, const char* szText)
+{
+ SetWindowTextUtf(GetDlgItem(hwndDlg, iItem), szText);
+}
+
+
+
+LONG SetWindowLongUtf(HWND hWnd, int nIndex, LONG dwNewLong)
+{
+ if (gbUnicodeAPI)
+ return SetWindowLongW(hWnd, nIndex, dwNewLong);
+ else
+ return SetWindowLongA(hWnd, nIndex, dwNewLong);
+}
+
+
+
+LRESULT CallWindowProcUtf(WNDPROC OldProc, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (gbUnicodeAPI)
+ return CallWindowProcW(OldProc,hWnd,msg,wParam,lParam);
+ else
+ return CallWindowProcA(OldProc,hWnd,msg,wParam,lParam);
+}
+
+
+
+static int ControlAddStringUtf(HWND ctrl, DWORD msg, const char* szString)
+{
+ char str[MAX_PATH];
+ char *szItem = ICQTranslateUtfStatic(szString, str);
+ int item;
+
+ if (gbUnicodeAPI)
+ {
+ wchar_t *wItem = make_unicode_string(szItem);
+
+ item = SendMessageW(ctrl, msg, 0, (LPARAM)wItem);
+ SAFE_FREE(&wItem);
+ }
+ else
+ {
+ int size = strlennull(szItem) + 2;
+ char *aItem = (char*)_alloca(size);
+
+ utf8_decode_static(szItem, aItem, size);
+ item = SendMessageA(ctrl, msg, 0, (LPARAM)aItem);
+ }
+ return item;
+}
+
+
+
+int ComboBoxAddStringUtf(HWND hCombo, const char* szString, DWORD data)
+{
+ int item = ControlAddStringUtf(hCombo, CB_ADDSTRING, szString);
+ SendMessage(hCombo, CB_SETITEMDATA, item, data);
+
+ return item;
+}
+
+
+
+int ListBoxAddStringUtf(HWND hList, const char* szString)
+{
+ return ControlAddStringUtf(hList, LB_ADDSTRING, szString);
+}
+
+
+
+HWND DialogBoxUtf(BOOL bModal, HINSTANCE hInstance, const char* szTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
+{ // Unicode pump ready dialog box
+ if (gbUnicodeAPI)
+ {
+ if (bModal)
+ return (HANDLE)DialogBoxParamW(hInstance, (LPCWSTR)szTemplate, hWndParent, lpDialogFunc, dwInitParam);
+ else
+ return CreateDialogParamW(hInstance, (LPCWSTR)szTemplate, hWndParent, lpDialogFunc, dwInitParam);
+ }
+ else
+ {
+ if (bModal)
+ return (HANDLE)DialogBoxParamA(hInstance, szTemplate, hWndParent, lpDialogFunc, dwInitParam);
+ else
+ return CreateDialogParamA(hInstance, szTemplate, hWndParent, lpDialogFunc, dwInitParam);
+ }
+}
+
+
+
+HWND CreateDialogUtf(HINSTANCE hInstance, const char* lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc)
+{
+ if (gbUnicodeAPI)
+ return CreateDialogW(hInstance, (LPCWSTR)lpTemplate, hWndParent, lpDialogFunc);
+ else
+ return CreateDialogA(hInstance, lpTemplate, hWndParent, lpDialogFunc);
+}
+
+
+
+int MessageBoxUtf(HWND hWnd, const char* szText, const char* szCaption, UINT uType)
+{
+ int res;
+ char str[1024];
+ char cap[MAX_PATH];
+
+ if (gbUnicodeAPI)
+ {
+ wchar_t *text = make_unicode_string(ICQTranslateUtfStatic(szText, str));
+ wchar_t *caption = make_unicode_string(ICQTranslateUtfStatic(szCaption, cap));
+ res = MessageBoxW(hWnd, text, caption, uType);
+ SAFE_FREE(&caption);
+ SAFE_FREE(&text);
+ }
+ else
+ {
+ int size = strlennull(szText) + 2, size2 = strlennull(szCaption) + 2;
+ char *text = (char*)_alloca(size);
+ char *caption = (char*)_alloca(size2);
+
+ utf8_decode_static(ICQTranslateUtfStatic(szText, str), text, size);
+ utf8_decode_static(ICQTranslateUtfStatic(szCaption, cap), caption, size2);
+ res = MessageBoxA(hWnd, text, caption, uType);
+ }
+ return res;
+}
+
+
+int CacheIDCount(void)
+{
+
+ return cacheCount;
+
+}
+
+int IDFromCacheByUin(DWORD dwUin)
+{
+
+ int i = -1;
+
+ if (cacheCount == 0)
+ return i;
+
+ EnterCriticalSection(&cacheMutex);
+
+ for (i = cacheCount-1; i >= 0; i--)
+ if (contacts_cache[i].dwUin == dwUin)
+ break;
+
+ LeaveCriticalSection(&cacheMutex);
+
+ return i;
+
+}
+
+int SetCacheFlagsByID(int ID, DWORD flags)
+{
+
+ if (ID < 0 || ID >= cacheCount)
+ return 0;
+
+ contacts_cache[ID].flags = flags;
+
+ return 1;
+
+}
+
+int GetCacheByID(int ID, icq_contacts_cache *icc)
+{
+
+ if (!icc || ID < 0 || ID >= cacheCount)
+ return 0;
+
+ EnterCriticalSection(&cacheMutex);
+
+ icc->hContact = contacts_cache[ID].hContact;
+ icc->dwUin = contacts_cache[ID].dwUin;
+ icc->flags = contacts_cache[ID].flags;
+
+ LeaveCriticalSection(&cacheMutex);
+
+ return icc->dwUin; // to be sure it is not 0
+
+}
\ No newline at end of file diff --git a/icqj_mod/utilities.h b/icqj_mod/utilities.h new file mode 100644 index 0000000..d619c36 --- /dev/null +++ b/icqj_mod/utilities.h @@ -0,0 +1,171 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/utilities.h,v $
+// Revision : $Revision: 3130 $
+// Last change on : $Date: 2006-06-13 23:02:57 +0200 (Tue, 13 Jun 2006) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __UTILITIES_H
+#define __UTILITIES_H
+
+typedef struct icq_ack_args_s
+{
+ HANDLE hContact;
+ int nAckType;
+ int nAckResult;
+ HANDLE hSequence;
+ LPARAM pszMessage;
+} icq_ack_args;
+
+
+typedef struct icq_contacts_cache_s
+{
+ HANDLE hContact;
+ DWORD dwUin;
+ DWORD flags;
+} icq_contacts_cache;
+
+
+#define F_TEMPVIS 1
+
+/*---------* Functions *---------------*/
+
+void EnableDlgItem(HWND hwndDlg, UINT control, int state);
+void icq_EnableMultipleControls(HWND hwndDlg, const UINT* controls, int cControls, int state);
+void icq_ShowMultipleControls(HWND hwndDlg, const UINT* controls, int cControls, int state);
+int IcqStatusToMiranda(WORD wStatus);
+WORD MirandaStatusToIcq(int nStatus);
+int MirandaStatusToSupported(int nMirandaStatus);
+char *MirandaStatusToString(int);
+char *MirandaStatusToStringUtf(int);
+char**MirandaStatusToAwayMsg(int nStatus);
+int IDFromCacheByUin(DWORD dwUin);
+int CacheIDCount(void);
+int SetCacheFlagsByID(int ID, DWORD flags);
+int GetCacheByID(int ID, icq_contacts_cache *icc);
+int GetFromCacheByID(int ID, HANDLE *hContact, DWORD *dwUin);
+
+int AwayMsgTypeToStatus(int nMsgType);
+
+void SetGatewayIndex(HANDLE hConn, DWORD dwIndex);
+DWORD GetGatewayIndex(HANDLE hConn);
+void FreeGatewayIndex(HANDLE hConn);
+
+void AddToSpammerList(DWORD dwUIN);
+BOOL IsOnSpammerList(DWORD dwUIN);
+
+void InitCache();
+void UninitCache();
+void DeleteFromCache(HANDLE hContact);
+HANDLE HContactFromUIN(DWORD dwUin, int *Added);
+HANDLE HContactFromUID(DWORD dwUIN, char *pszUID, int *Added);
+char *NickFromHandle(HANDLE hContact);
+char *NickFromHandleUtf(HANDLE hContact);
+char *strUID(DWORD dwUIN, char *pszUID);
+void NickFromHandleStatic(HANDLE hContact, char *szNick, WORD wLen);
+void SetContactHidden(HANDLE hContact, BYTE bHidden);
+void makeUserOffline(HANDLE hContact);
+
+size_t __fastcall strlennull(const char *string);
+int __fastcall strcmpnull(const char *str1, const char *str2);
+int null_snprintf(char *buffer, size_t count, const char* fmt, ...);
+char* __fastcall null_strdup(const char *string);
+
+void parseServerAddress(char *szServer, WORD* wPort);
+
+char *DemangleXml(const char *string, int len);
+char *MangleXml(const char *string, int len);
+char *EliminateHtml(const char *string, int len);
+
+void ResetSettingsOnListReload(void);
+void ResetSettingsOnConnect(void);
+void ResetSettingsOnLoad(void);
+int RandRange(int nLow, int nHigh);
+
+BOOL IsStringUIN(char* pszString);
+
+void __cdecl icq_ProtocolAckThread(icq_ack_args* pArguments);
+void icq_SendProtoAck(HANDLE hContact, DWORD dwCookie, int nAckResult, int nAckType, char* pszMessage);
+
+void SetCurrentStatus(int nStatus);
+
+BOOL writeDbInfoSettingString(HANDLE hContact, const char* szSetting, char** buf, WORD* pwLength);
+BOOL writeDbInfoSettingWord(HANDLE hContact, const char *szSetting, char **buf, WORD* pwLength);
+BOOL writeDbInfoSettingWordWithTable(HANDLE hContact, const char *szSetting, struct fieldnames_t *table, char **buf, WORD* pwLength);
+BOOL writeDbInfoSettingByte(HANDLE hContact, const char *szSetting, char **buf, WORD* pwLength);
+BOOL writeDbInfoSettingByteWithTable(HANDLE hContact, const char *szSetting, struct fieldnames_t *table, char **buf, WORD* pwLength);
+
+int GetGMTOffset(void);
+
+BOOL validateStatusMessageRequest(HANDLE hContact, WORD byMessageType);
+
+#define icqOnline ((gnCurrentStatus != ID_STATUS_OFFLINE) && (gnCurrentStatus != ID_STATUS_CONNECTING))
+
+void __fastcall SAFE_FREE(void** p);
+void* __fastcall SAFE_MALLOC(size_t size);
+
+void LinkContactPhotoToFile(HANDLE hContact, char* szFile);
+void ContactPhotoSettingChanged(HANDLE hContact);
+
+HANDLE NetLib_OpenConnection(HANDLE hUser, NETLIBOPENCONNECTION* nloc);
+int NetLog_Server(const char *fmt,...);
+int NetLog_Direct(const char *fmt,...);
+int NetLog_Uni(BOOL bDC, const char *fmt,...);
+
+int ICQBroadcastAck(HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam);
+
+int __fastcall ICQTranslateDialog(HWND hwndDlg);
+char* __fastcall ICQTranslate(const char* src);
+char* __fastcall ICQTranslateUtf(const char* src);
+char* __fastcall ICQTranslateUtfStatic(const char* src, char* buf);
+
+char* GetUserPassword(BOOL bAlways);
+WORD GetMyStatusFlags();
+
+/* Unicode UI utility functions */
+wchar_t* GetWindowTextUcs(HWND hWnd);
+void SetWindowTextUcs(HWND hWnd, wchar_t *text);
+char* GetWindowTextUtf(HWND hWnd);
+char* GetDlgItemTextUtf(HWND hwndDlg, int iItem);
+void SetWindowTextUtf(HWND hWnd, const char* szText);
+void SetDlgItemTextUtf(HWND hwndDlg, int iItem, const char* szText);
+LONG SetWindowLongUtf(HWND hWnd, int nIndex, LONG dwNewLong);
+LRESULT CallWindowProcUtf(WNDPROC OldProc, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+int ComboBoxAddStringUtf(HWND hCombo, const char* szString, DWORD data);
+int ListBoxAddStringUtf(HWND hList, const char* szString);
+
+int MessageBoxUtf(HWND hWnd, const char* szText, const char* szCaption, UINT uType);
+HWND DialogBoxUtf(BOOL bModal, HINSTANCE hInstance, const char* szTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
+HWND CreateDialogUtf(HINSTANCE hInstance, const char* lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc);
+
+#endif /* __UTILITIES_H */
|