diff options
Diffstat (limited to 'icqj_s7_sss_mod')
194 files changed, 61398 insertions, 0 deletions
diff --git a/icqj_s7_sss_mod/UI/askauthentication.c b/icqj_s7_sss_mod/UI/askauthentication.c new file mode 100644 index 0000000..ab1f97d --- /dev/null +++ b/icqj_s7_sss_mod/UI/askauthentication.c @@ -0,0 +1,127 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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, MAX_PATH));
+
+ 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);
+
+ if (gbSsiEnabled && dwUin)
+ { // auth bug fix (thx Bio)
+ resetServContactAuthState(hContact, dwUin);
+ }
+
+ 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_s7_sss_mod/UI/askauthentication.h b/icqj_s7_sss_mod/UI/askauthentication.h new file mode 100644 index 0000000..7e0d6c5 --- /dev/null +++ b/icqj_s7_sss_mod/UI/askauthentication.h @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+int icq_RequestAuthorization(WPARAM wParam, LPARAM lParam);
+
diff --git a/icqj_s7_sss_mod/UI/loginpassword.c b/icqj_s7_sss_mod/UI/loginpassword.c new file mode 100644 index 0000000..1a83383 --- /dev/null +++ b/icqj_s7_sss_mod/UI/loginpassword.c @@ -0,0 +1,109 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+BOOL CALLBACK LoginPasswdDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+void RequestPassword()
+{
+ DialogBoxUtf(TRUE, hInst, MAKEINTRESOURCE(IDD_LOGINPW), NULL, LoginPasswdDlgProc, 0);
+}
+
+
+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;
+
+ InitIconLib();
+
+ ICQTranslateDialog(hwndDlg);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)IconLibGetIcon("proto"));
+ dwUin = ICQGetContactSettingUIN(NULL);
+ null_snprintf(pszUIN, 128, ICQTranslateUtfStatic("Enter a password for UIN %u:", str, MAX_PATH), 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_s7_sss_mod/UI/loginpassword.h b/icqj_s7_sss_mod/UI/loginpassword.h new file mode 100644 index 0000000..2183360 --- /dev/null +++ b/icqj_s7_sss_mod/UI/loginpassword.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
+// Copyright 2004,2005,2006,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+void RequestPassword(void);
diff --git a/icqj_s7_sss_mod/UI/m_flash.h b/icqj_s7_sss_mod/UI/m_flash.h new file mode 100644 index 0000000..299bf3f --- /dev/null +++ b/icqj_s7_sss_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_s7_sss_mod/UI/userinfotab.c b/icqj_s7_sss_mod/UI/userinfotab.c new file mode 100644 index 0000000..294bcec --- /dev/null +++ b/icqj_s7_sss_mod/UI/userinfotab.c @@ -0,0 +1,946 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Code for User details ICQ specific pages
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#include <windowsx.h>
+
+
+extern WORD wListenPort;
+
+extern char* calcMD5Hash(char* szFile);
+extern char* MirandaVersionToString(char* szStr, int v, int m);
+
+static BOOL CALLBACK IcqDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK IcqDlgProcClient(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_GENDER 1
+#define SVS_ZEROISUNSPEC 2
+#define SVS_IP 3
+#define SVS_COUNTRY 4
+#define SVS_MONTH 5
+#define SVS_SIGNED 6
+#define SVS_TIMEZONE 7
+#define SVS_ICQVERSION 8
+#define SVS_TIMESTAMP 9
+#define SVS_STATUSID 10
+
+#define SVS_FLAGS 0xFF
+#define SVSF_GRAYED 0x100
+#define SVSF_NORMAL 0x200
+#define AVATAR_HASH_FLASH 0x08
+static char szNotSpec[32];
+
+int OnDetailsInit(WPARAM wParam, LPARAM lParam)
+{
+ static char szTmp[256];
+ OPTIONSDIALOGPAGE odp = {0};
+
+ if ((!IsICQContact((HANDLE)lParam)) && lParam)
+ return 0;
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ mir_snprintf( szTmp, sizeof( szTmp ), "%s %s", gpszICQProtoName, Translate( "Contact Info" ));
+ odp.hIcon = NULL;
+ odp.hInstance = hInst;
+ odp.position = -1900000000;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_ICQ);
+ odp.pszTitle=Translate(szTmp);
+ odp.pfnDlgProc = IcqDlgProc;
+ CallService(MS_USERINFO_ADDPAGE,wParam,(LPARAM)&odp);
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ mir_snprintf( szTmp, sizeof( szTmp ), "%s %s", gpszICQProtoName, Translate( "Client Info" ));
+ odp.hIcon = NULL;
+ odp.hInstance = hInst;
+ odp.pfnDlgProc = IcqDlgProcClient;
+ odp.position = -1900000000;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_ICQ_CLIENT);
+ odp.pszTitle=Translate(szTmp);
+ CallService(MS_USERINFO_ADDPAGE,wParam,(LPARAM)&odp);
+
+
+ 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)
+ {
+ char str[MAX_PATH];
+ SetValue(hwndDlg, IDC_SYSTEMUPTIME, NULL, gpszICQProtoName, "MemberTS", (WORD)((icqOnline)?SVS_TIMESTAMP|SVSF_NORMAL:SVS_TIMESTAMP|SVSF_GRAYED));
+ SetDlgItemTextUtf(hwndDlg, IDC_SUPTIME, ICQTranslateUtfStatic("Member since:", str, MAX_PATH));
+ _snprintf(szStatus, sizeof(szStatus), MirandaStatusToString(gnCurrentStatus));
+ SetDlgItemText(hwndDlg, IDC_STATUS, szStatus);
+ // SetValue(hwndDlg, IDC_VERSION, NULL, gpszICQProtoName, "setVersion", SVS_ICQVERSION);
+
+ }
+ else
+ {
+ WORD wStatus = ICQGetContactSettingWord(hContact, "Status", 0);
+ char str[256] = {0};
+// int i;
+
+ SetValue(hwndDlg, IDC_STATUS, hContact, gpszICQProtoName, "Status", SVS_STATUSID);
+
+ ShowWindow(GetDlgItem(hwndDlg,IDC_GETSTATUS),(gbASD)?SW_SHOW:SW_HIDE);
+ //ShowWindow(GetDlgItem(hwndDlg,IDC_GETCAPS),(wStatus != ID_STATUS_OFFLINE)?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_RETRIEVE),SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_IGNORECHECK),SW_SHOW);
+
+ SetValue(hwndDlg, IDC_SYSTEMUPTIME, hContact, gpszICQProtoName, "MemberTS", (WORD)((icqOnline)?SVS_TIMESTAMP|SVSF_NORMAL:SVS_TIMESTAMP|SVSF_GRAYED));
+ SetDlgItemTextUtf(hwndDlg, IDC_SUPTIME, ICQTranslateUtfStatic("Member since:", str, MAX_PATH));
+/*
+ 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);
+*/
+ // Subnets
+ //DBGetStaticString(hContact, gpszICQProtoName, "SubNets", str, sizeof(str));
+
+ }
+
+ //SetValue(hwndDlg, IDC_UIN, hContact, gpszICQProtoName, UNIQUEIDSETTING, 0);
+ SetDlgItemText(hwndDlg, IDC_UIN, szUin);
+
+ // Client version
+ if (hContact == NULL)
+ SetValue(hwndDlg, IDC_MIRVER, hContact, gpszICQProtoName, "MirVer", (WORD)(SVS_ZEROISUNSPEC|flag));
+ else
+ SetValue(hwndDlg, IDC_MIRVER, NULL, gpszICQProtoName, "MirVer", (WORD)(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);
+
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDCANCEL:
+ SendMessage(GetParent(hwndDlg),msg,wParam,lParam);
+ break;
+
+ case IDC_GETSTATUS:
+ if (icqOnline && (!invis_for(0,dat->hContact)))
+ icq_GetUserStatus(dat->hContact, 1);
+ break;
+
+ case IDC_RETRIEVE:
+ if (icqOnline && dat->dwUin &&(!invis_for(0,dat->hContact))) //not on invisible status, we don't want to be detected
+ {
+ 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(NULL, 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) && (!invis_for(0,dat->hContact))) //we do not want to be detected
+
+ {
+ 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, NULL,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);
+ SetDlgItemText(hwndDlg, IDC_IGNORE, Translate(""));//set back
+ }
+ 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;
+}
+
+static BOOL CALLBACK IcqDlgProcClient(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;
+ return TRUE;
+
+ case WM_MEASUREITEM:
+ {
+ LPMEASUREITEMSTRUCT lpmis;
+ lpmis = (LPMEASUREITEMSTRUCT) lParam;
+ if (lpmis->itemID == -1)
+ return FALSE;
+ lpmis->itemHeight = 18;
+ return TRUE;
+ }
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
+ HWND hwndList;
+ ICQ_CAPINFO *info;
+
+ if (lpdis->itemID == -1)
+ return FALSE;
+ hwndList = GetDlgItem(hwndDlg, lpdis->CtlID);
+ info = (ICQ_CAPINFO *)ListBox_GetItemData(hwndList, lpdis->itemID);
+ if (info)
+ {
+ if (lpdis->itemState&ODS_SELECTED)
+ {
+ HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
+ FillRect(lpdis->hDC, &lpdis->rcItem, hbr);
+ SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ DeleteObject(hbr);
+ } else
+ {
+ HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
+ FillRect(lpdis->hDC, &lpdis->rcItem, hbr);
+ SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
+ DeleteObject(hbr);
+ }
+
+ {
+ SIZE sz;
+ SetBkMode(lpdis->hDC, TRANSPARENT);
+ GetTextExtentPoint32A(lpdis->hDC, info->name, lstrlenA(info->name), &sz);
+ TextOutA(lpdis->hDC, lpdis->rcItem.left+3+16+1,
+ (lpdis->rcItem.top+lpdis->rcItem.bottom-sz.cy)/2,
+ info->name, lstrlenA(info->name));
+ }
+ } else
+ {
+ char str[256];
+ HBRUSH hbr = CreateSolidBrush(RGB(0x60, 0x60, 0x60));
+ FillRect(lpdis->hDC, &lpdis->rcItem, hbr);
+ SetTextColor(lpdis->hDC, RGB(0xff, 0xff, 0xff));
+ DeleteObject(hbr);
+
+ ListBox_GetText(hwndList, lpdis->itemID, str);
+ if (!lstrcmpA(str, "01."))
+ {
+ lstrcpyA(str, Translate("Universal Protocol Features"));
+ } else
+ if (!lstrcmpA(str, "02."))
+ {
+ lstrcpyA(str, Translate("Miranda Features"));
+ } else
+ if (!lstrcmpA(str, "03."))
+ {
+ lstrcpyA(str, Translate("Miranda Features (unknown)"));
+ } else
+ if (!lstrcmpA(str, "04."))
+ {
+ lstrcpyA(str, Translate("Unknow Flags (decoded)"));
+ } else
+ if (!lstrcmpA(str, "05."))
+ {
+ lstrcpyA(str, Translate("Unknown Flags (other)"));
+ } else
+ {
+ if (lpdis->itemState&ODS_SELECTED)
+ {
+ HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
+ FillRect(lpdis->hDC, &lpdis->rcItem, hbr);
+ SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ DeleteObject(hbr);
+ } else
+ {
+ HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
+ FillRect(lpdis->hDC, &lpdis->rcItem, hbr);
+ SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
+ DeleteObject(hbr);
+ }
+ }
+
+ {
+ SIZE sz;
+ SetBkMode(lpdis->hDC, TRANSPARENT);
+ GetTextExtentPoint32A(lpdis->hDC, str, lstrlenA(str), &sz);
+ TextOutA(lpdis->hDC, lpdis->rcItem.left+3,
+ (lpdis->rcItem.top+lpdis->rcItem.bottom-sz.cy)/2,
+ str, lstrlenA(str));
+ }
+ }
+ return TRUE;
+ }
+ case WM_DELETEITEM:
+ {
+ DELETEITEMSTRUCT *lpdis = (DELETEITEMSTRUCT *)lParam;
+ ICQ_CAPINFO *info = (ICQ_CAPINFO *)ListBox_GetItemData(lpdis->hwndItem, lpdis->itemID);
+ if (info) free(info);
+ return TRUE;
+ }
+
+ case WM_VKEYTOITEM:
+ {
+ char ch = (char)LOWORD(wParam);
+ if (((ch == 'C') || (ch == VK_INSERT)) && (GetKeyState(VK_CONTROL)&0x80))
+ {
+ int i, count = ListBox_GetCount((HWND)lParam);
+ int bufsize = 1; // for the \0
+ char *buf, *bufptr;
+ HGLOBAL hMem;
+ for (i = 0; i < count; ++i)
+ {
+ ICQ_CAPINFO *info;
+ if (!ListBox_GetSel((HWND)lParam, i)) continue;
+ info = (ICQ_CAPINFO *)ListBox_GetItemData((HWND)lParam, i);
+ if (!info) continue;
+ bufsize += lstrlenA(info->caps) + 5 + lstrlenA(info->name) + 2;
+ }
+ hMem = GlobalAlloc(GMEM_MOVEABLE, bufsize);
+ bufptr = buf = (char *)GlobalLock(hMem);
+ for (i = 0; i < count; ++i)
+ {
+ ICQ_CAPINFO *info;
+ if (!ListBox_GetSel((HWND)lParam, i)) continue;
+ info = (ICQ_CAPINFO *)ListBox_GetItemData((HWND)lParam, i);
+ if (!info) continue;
+ bufptr += mir_snprintf(bufptr, bufsize-(bufptr-buf), "%s, // %s\r\n", info->caps, info->name);
+ }
+ GlobalUnlock(hMem);
+ OpenClipboard(hwndDlg);
+ EmptyClipboard();
+ SetClipboardData(CF_TEXT, hMem);
+ CloseClipboard();
+ return (BOOL)(-2);
+ } else
+ if ((ch == 'A') && (GetKeyState(VK_CONTROL)&0x80))
+ {
+ SendMessage((HANDLE)lParam, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, ListBox_GetCount((HWND)lParam)));
+ return (BOOL)(-2);
+ }
+ return (BOOL)(-1);
+ }
+
+ 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;
+// int i;
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING dbcgs;
+ dbcgs.szModule = gpszICQProtoName;
+ dbcgs.szSetting = "CapBuf";
+ dbcgs.pValue = &dbv;
+ CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs);
+
+ // Set flags
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_RESETCONTENT, 0, 0);
+
+ if ((dbv.type == DBVT_BLOB) && (dbv.cpbVal))
+ {
+ int bufsize = dbv.cpbVal;
+ int capsize = 0x10;
+ BYTE *buf = dbv.pbVal;
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_SETITEMDATA,
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_ADDSTRING, 0, (LPARAM)"01."), 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_SETITEMDATA,
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_ADDSTRING, 0, (LPARAM)"02."), 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_SETITEMDATA,
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_ADDSTRING, 0, (LPARAM)"03."), 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_SETITEMDATA,
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_ADDSTRING, 0, (LPARAM)"04."), 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_SETITEMDATA,
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_ADDSTRING, 0, (LPARAM)"05."), 0);
+ while (bufsize>0) // search the buffer for a capability
+ {
+ ICQ_CAPINFO *info = (ICQ_CAPINFO *)malloc(sizeof(ICQ_CAPINFO));
+ char *capName = GetCapabilityName(buf, info);
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_SETITEMDATA,
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_ADDSTRING, 0, (LPARAM)capName), (LPARAM)info);
+ buf += 0x10;
+ bufsize -= 0x10;
+ }
+ }/* else
+ {
+ 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)))
+ {
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_SETITEMDATA,
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTCAPS, LB_ADDSTRING, 0, (LPARAM)Translate(infoflags[i].Descr)), 0);
+ }
+ }
+ }*/
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+
+ // Gray flags if miranda offline
+// SetWindowLong(GetDlgItem(hwndDlg, IDC_FLAGSTEXT), GWL_USERDATA, (!icqOnline && str[0] != 0));
+
+ // Client version
+ SetValue(hwndDlg, IDC_MIRVER, hContact, gpszICQProtoName, "MirVer", (WORD)(SVS_ZEROISUNSPEC|flag));
+
+ if (ServiceExists(MS_FP_GETCLIENTICON))
+ {
+// DBVARIANT dbv;
+// DBCONTACTGETSETTING dbcgs;
+ dbcgs.szModule = gpszICQProtoName;
+ dbcgs.pValue = &dbv;
+ dbcgs.szSetting = "MirVer";
+ CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs);
+ if (dbv.type == DBVT_ASCIIZ)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTICON, STM_SETICON,
+ (WPARAM)CallService(MS_FP_GETCLIENTICON, (WPARAM)dbv.pszVal, 1), 0);
+ } else
+ {
+ SendDlgItemMessage(hwndDlg, IDC_CLIENTICON, STM_SETICON,
+ (WPARAM)CallService(MS_FP_GETCLIENTICON, (WPARAM)"[Undetected client]", 1), 0);
+ }
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ }
+
+
+
+
+ // Proto version.
+ if (hContact != NULL)
+ {
+ if (!SetValue(hwndDlg, IDC_VERSION, hContact, gpszICQProtoName, "Version", SVS_ZEROISUNSPEC|SVSF_NORMAL))
+ SetValue(hwndDlg, IDC_VERSION, hContact, gpszICQProtoName, "OldVersion", SVS_ZEROISUNSPEC|SVSF_GRAYED);
+ }
+ else
+ SetValue(hwndDlg, IDC_VERSION, NULL, gpszICQProtoName, "setVersion", SVS_ZEROISUNSPEC|SVSF_NORMAL);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDCANCEL:
+ SendMessage(GetParent(hwndDlg),msg,wParam,lParam);
+ 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 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);
+ }
+ break;
+
+ case WM_DESTROY:
+ if (dat->hEventDbSettingChange)
+ UnhookEvent(dat->hEventDbSettingChange);
+ if (dat->nTimer)
+ KillTimer(hwndDlg, TIMERID);
+ free(dat);
+ 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, 1))
+ {
+ ICQTranslateUtfStatic(" (DC Established)", szExtra, 80);
+ strcat(str, szExtra);
+ bUtf = 1;
+ }
+ }
+ else
+ unspecified = 1;
+ }
+ else if (special == SVS_STATUSID)
+ {
+ char* pXName;
+ char* pszStatus;
+ BYTE bXStatus = ICQGetContactXStatus(hContact);
+
+ 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:
+ case DBVT_WCHAR:
+ 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, MAX_PATH));
+ break;
+
+ default:
+ pstr = str;
+ strcpy(str,"???");
+ break;
+ }
+ }
+
+ EnableDlgItem(hwndDlg, idCtrl, !unspecified);
+ if (unspecified)
+ SetDlgItemTextUtf(hwndDlg, idCtrl, ICQTranslateUtfStatic("<not specified>", str, MAX_PATH));
+ 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_s7_sss_mod/UI/userinfotab.h b/icqj_s7_sss_mod/UI/userinfotab.h new file mode 100644 index 0000000..fbd1b36 --- /dev/null +++ b/icqj_s7_sss_mod/UI/userinfotab.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
+// Copyright 2004,2005,2006,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+int OnDetailsInit(WPARAM wParam, LPARAM lParam);
diff --git a/icqj_s7_sss_mod/capabilities.c b/icqj_s7_sss_mod/capabilities.c new file mode 100644 index 0000000..ac7b2b6 --- /dev/null +++ b/icqj_s7_sss_mod/capabilities.c @@ -0,0 +1,527 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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"
+
+
+// -----------------------------------------------------------------------------
+const capstr capSrvRelay = {CAP_SRV_RELAY};
+const capstr capNewCap = {CAP_NEWCAP};
+const capstr capUTF = {CAP_UTF};
+const capstr capTyping = {CAP_TYPING};
+const capstr capXtraz = {CAP_XTRAZ};
+const capstr capAimFile = {CAP_AIM_FILE};
+const capstr capPush2Talk = {CAP_PUSH2TALK};
+// this is defined among all clients caps
+//const capstr capIcqLite = {CAP_ICQ_LITE};
+const capstr capRTF = {CAP_RTF};
+const capstr capXtrazChat = {CAP_XTRAZ_CHAT};
+const capstr capVoiceChat = {CAP_VOICE_CHAT};
+const capstr capIcqDevil = {CAP_ICQ_DEVIL};
+const capstr capDirect = {CAP_DIRECT};
+// -----------------------------------------------------------------------------
+const capstr capMirandaIm = {'M', 'i', 'r', 'a', 'n', 'd', 'a', 'M', 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capMirandaMobile = {'M', 'i', 'r', 'a', 'n', 'd', 'a', 'M', 'o', 'b', 'i', 'l', 'e', 0, 0, 0}; //port by Nullbie
+const capstr capMimPack = {'M', 'I', 'M', '/', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capIcqJs7 = {'i', 'c', 'q', 'j', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capIcqJp = {'i', 'c', 'q', 'p', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capIcqJs7s = {'i', 'c', 'q', 'j', 0, 'S', 'e', 'c', 'u', 'r', 'e', 0, 'I', 'M', 0, 0};
+const capstr capIcqJs7old = {0x69, 0x63, 0x71, 0x6a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capIcqJSin = {'s', 'i', 'n', 'j', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Miranda ICQJ S!N
+const capstr capIcqJen = {'e', 'n', 'q', 'j', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // eternity mod (mod of mod of mod of mod of mod)
+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 capClimm = {'c', 'l', 'i', 'm', 'm', 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 capCorePager = {'C', 'O', 'R', 'E', ' ', 'P', 'a', 'g', 'e', 'r', 0, 0, 0, 0, 0, 0};
+const capstr capDiChat = {'D', '[', 'i', ']', 'C', 'h', 'a', 't', ' ', 0, 0, 0, 0, 0, 0, 0};
+const capstr capNaim = {0xFF, 0xFF, 0xFF, 0xFF, 'n', 'a', 'i', 'm', 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capAnastasia = {0x44, 0xE5, 0xBF, 0xCE, 0xB0, 0x96, 0xE5, 0x47, 0xBD, 0x65, 0xEF, 0xD6, 0xA3, 0x7E, 0x36, 0x02};
+const capstr capQip = {0x56, 0x3F, 0xC8, 0x09, 0x0B, 0x6F, 0x41, 'Q', 'I', 'P', ' ', '2', '0', '0', '5', 'a'};
+const capstr capQipPDA = {0x56, 0x3F, 0xC8, 0x09, 0x0B, 0x6F, 0x41, 'Q', 'I', 'P', ' ', ' ', ' ', ' ', ' ', '!'};
+const capstr capQipMobile = {0x56, 0x3F, 0xC8, 0x09, 0x0B, 0x6F, 0x41, 'Q', 'I', 'P', ' ', ' ', ' ', ' ', ' ', '"'};
+const capstr capQipInfium = {0x7C, 0x73, 0x75, 0x02, 0xC3, 0xBE, 0x4F, 0x3E, 0xA6, 0x9F, 0x01, 0x53, 0x13, 0x43, 0x1E, 0x1A};
+const capstr capQipPlugins ={0x7c, 0x53, 0x3f, 0xfa, 0x68, 0x00, 0x4f, 0x21, 0xbc, 0xfb, 0xc7, 0xd2, 0x43, 0x9a, 0xad, 0x31}; //QIP Plugins
+const capstr capQip_1 = {0xd3, 0xd4, 0x53, 0x19, 0x8b, 0x32, 0x40, 0x3b, 0xac, 0xc7, 0xd1, 0xa9, 0xe2, 0xb5, 0x81, 0x3e}; // QIP-ProtectMsg (now use for fake id only)
+const capstr capQipSymbian = {0x51, 0xad, 0xd1, 0x90, 0x72, 0x04, 0x47, 0x3d, 0xa1, 0xa1, 0x49, 0xf4, 0xa3, 0x97, 0xa4, 0x1f};
+const capstr capVmICQ = {0x56, 0x6d, 0x49, 0x43, 0x51, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capSmapeR = {'S', 'm', 'a', 'p', 'e', 'r', ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capIMPlus = {0x8e, 0xcd, 0x90, 0xe7, 0x4f, 0x18, 0x28, 0xf8, 0x02, 0xec, 0xd6, 0x18, 0xa4, 0xe9, 0xde, 0x68};
+const capstr capYapp = {0x59, 0x61, 0x70, 0x70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Yapp
+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 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 capAimFileShare = {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}; // CAP_AIM_FILE_SHARE
+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 capHtmlMsgs = {0x01, 0x38, 0xca, 0x7b, 0x76, 0x9a, 0x49, 0x15, 0x88, 0xf2, 0x13, 0xfc, 0x00, 0x97, 0x9e, 0xa8}; // icq6 html msgs
+const capstr capLiveVideo = {0x09, 0x46, 0x01, 0x01, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}; // icq6 live video
+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};
+const capstr capIMsecure = {'I', 'M', 's', 'e', 'c', 'u', 'r', 'e', 'C', 'p', 'h', 'r', 0x00, 0x00, 0x06, 0x01}; // ZoneLabs
+const capstr capMsgType2 = {0x09, 0x49, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capAimIcq = {0x09, 0x46, 0x13, 0x4D, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capAimVoice = {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capAimAudio = {0x09, 0x46, 0x01, 0x04, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}; //added to ICQ 6 & AIM 6
+const capstr capPalmJicq = {'J', 'I', 'C', 'Q', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capInluxMsgr = {0xA7, 0xE4, 0x0A, 0x96, 0xB3, 0xA0, 0x47, 0x9A, 0xB8, 0x45, 0xC9, 0xE4, 0x67, 0xC5, 0x6B, 0x1F};
+const capstr capMipClient = {0x4D, 0x49, 0x50, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capIMadering = {'I', 'M', 'a', 'd', 'e', 'r', 'i', 'n', 'g', ' ', 'C', 'l', 'i', 'e', 'n', 't'};
+//AIM Client version 5.9 capabilities
+const capstr capAimAddins = {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capAimContactSnd= {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capAimUnk2 = {0x09, 0x46, 0x01, 0x02, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capAimSendbuddylist = {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x13, 0x4B};
+//
+const capstr capIMSecKey1 = {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // ZoneLabs
+const capstr capIMSecKey2 = {2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // ZoneLabs
+const capstr capUnknown1 = {0x17, 0x8c, 0x2d,0x9b, 0xda, 0xa5, 0x45, 0xbb, 0x8d, 0xdb, 0xf3, 0xbd, 0xbd, 0x53, 0xa1,0x0a};
+
+// -----------------------------------------------------------------------------
+
+typedef struct icq_capability_s
+{
+ DWORD fdwMirandaID; // A bitmask, we use it in order to save database space
+ const BYTE *CapCLSID; // A binary representation of a oscar capability
+} icq_capability;
+
+static icq_capability CapabilityRecord[] =
+{
+ {CAPF_SRV_RELAY, capSrvRelay},
+ {CAPF_UTF, capUTF},
+ {CAPF_TYPING, capTyping},
+ {CAPF_XTRAZ, capXtraz},
+ {CAPF_AIM_FILE, capAimFile},
+ {CAPF_PUSH2TALK, capPush2Talk},
+ {CAPF_ICQ_LITE, capIcqLite},
+ {CAPF_RTF, capRTF},
+ {CAPF_XTRAZ_CHAT, capXtrazChat},
+ {CAPF_VOICE_CHAT, capVoiceChat},
+ {CAPF_ICQ_DEVIL, capIcqDevil},
+ {CAPF_DIRECT, capDirect},
+};
+
+// 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);
+}
+
+// Pack binary caps to output buffer
+void AddCapabilitiesToBuffer(BYTE* packet, DWORD fdwContactCaps)
+{
+ int iCapability = 0;
+ int nIndex;
+ int nRecordSize;
+
+ nRecordSize = sizeof(CapabilityRecord)/sizeof(icq_capability);
+
+ for (nIndex = 0; nIndex < nRecordSize; nIndex++)
+ {
+ if(CapabilityRecord[nIndex].fdwMirandaID & fdwContactCaps)
+ {
+ packBuffer(( icq_packet*)packet, CapabilityRecord[nIndex].CapCLSID, BINARY_CAP_SIZE);
+ }
+ }
+}
+
+
+typedef struct tagSTDCAPINFO
+{
+ const char *name;
+ int type;
+ const BYTE *caps;
+ int capSize;
+} STDCAPINFO;
+
+STDCAPINFO stdCapInfo[] = {
+ {"ServerRelay", 0, capSrvRelay, 16},
+ {"NewCaps support", 0, capNewCap, 16},
+ {"Aim support", 0, capAimIcq, 16},
+ {"UTF8 Messages", 0, capUTF, 16},
+ {"Typing Notifications", 0, capTyping, 16},
+ {"ICQ Xtraz", 0, capXtraz, 16},
+ {"File Transfer (AIMFile)", 0, capAimFile, 16},
+ {"Push2Talk", 0, capPush2Talk, 16},
+ {"ICQ Lite", 0, capIcqLite, 16},
+ {"RTF Messages", 0, capRTF, 16},
+ {"Xtraz Chat", 0, capXtrazChat, 16},
+ {"Voice Chat", 0, capVoiceChat, 16},
+ {"Avatars (ICQDevil)", 0, capIcqDevil, 16},
+ {"Direct Connections", 0, capDirect, 16},
+ {"Miranda IM", 0, capMirandaIm, 8},
+ {"Miranda IM Mobile", 0, capMirandaMobile, 13},
+ {"Miranda IM Custom Pack", 0, capMimPack, 4},
+ {"Miranda ICQJ eternity/PlusPlus++", 0, capIcqJen, 4},
+ {"Miranda ICQJ S7&SSS OLD", 0, capIcqJs7old, 16},
+ {"Miranda ICQJ S7&SSS + SecureIM", 0, capIcqJs7s, 16},
+ {"Miranda ICQJ S7&SSS", 0, capIcqJs7, 4},
+ {"Miranda ICQJ Plus", 0, capIcqJp, 4},
+ {"Miranda ICQJ S!N", 0, capIcqJSin, 4},
+ {"AIM Oscar", 0, capAimOscar, 8},
+ {"IMadering Client", 0, capIMadering, 0x10},
+ {"Trillian", 0, capTrillian, 16},
+ {"Trillian Crypt", 0, capTrilCrypt, 16},
+ {"SIM", 0, capSim, 0xC},
+ {"SIM (old)", 0, capSimOld, 0xF},
+ {"Licq", 0, capLicq, 0xC},
+ {"Kopete", 0, capKopete, 0xC},
+ {"mIcq", 0, capmIcq, 0xC},
+ {"&RQ", 0, capAndRQ, 9},
+ {"R&Q", 0, capRAndQ, 9},
+ {"mChat", 0, capmChat, 0xA},
+ {"Jimm", 0, capJimm, 5},
+ {"Yapp", 0, capYapp, 4},
+ {"Naim", 0, capNaim, 8},
+ {"Anastacia", 0, capAnastasia, 16},
+ {"JICQ", 0, capPalmJicq, 16},
+ {"Inlux Messenger", 0, capInluxMsgr, 16},
+ {"MIP Client", 0, capMipClient, 0xC},
+ {"QIP 2005", 0, capQip, 16},
+ {"QIP Infium", 0, capQipInfium, 16},
+ {"QIP Infium Plugins", 0, capQipPlugins, 16},
+ {"QIP PDA", 0, capQipPDA, 16},
+ {"QIP Mobile (Java)", 0, capQipMobile, 16},
+ {"QIP Mobile (Symbian)", 0, capQipSymbian, 16},
+ {"VmICQ (Symbian)", 0, capVmICQ, 6},
+ {"QIP-ProtectMsg", 0, capQip_1, 16},
+ {"IM2", 0, capIm2, 16},
+ {"ICQ for Mac", 0, capMacIcq, 16},
+ {"ICQ 2001", 0, capIs2001, 16},
+ {"ICQ 2002", 0, capIs2002, 16},
+ {"Comm20012", 0, capComm20012, 16},
+ {"StrICQ", 0, capStrIcq, 16},
+ {"AIM Buddy Icon", 0, capAimIcon, 16}, // CAP_AIM_BUDDYICON
+ {"AIM Direct IM", 0, capAimDirect, 16}, // CAP_AIM_DIRECTIM
+ {"AIM Send Buddy List", 0, capAimSendbuddylist, 16},
+ {"AIM Send Contact", 0, capAimContactSnd,16},
+ {"ICQ Lite", 0, capIcqLite, 16},
+ {"AIM Chat", 0, capAimChat, 16},
+ {"UIM", 0, capUim, 16},
+ {"Rambler ICQ", 0, capRambler, 16},
+ {"ABV ICQ", 0, capAbv, 16},
+ {"Netvigator ICQ", 0, capNetvigator, 16},
+ {"tZers", 0, captZers, 16}, // CAP_TZERS
+ {"ICQ 6 (HTML msgs)", 0, capHtmlMsgs, 16}, // icq6
+ {"Live Video", 0, capLiveVideo, 16},
+ {"Simp Lite", 0, capSimpLite, 16},
+ {"Simp Pro", 0, capSimpPro, 16},
+ {"IMsecure (ZoneLabs)", 0, capIMsecure, 16}, // ZoneLabs
+ {"Messages Type 2 support", 0, capMsgType2, 16},
+ {"Aim Voice Chat", 0, capAimVoice, 16},
+ {"Live Audio(new VoiceChat)", 0, capAimAudio, 16},
+ {"climm client", 0, capClimm, 0xC},
+ {"IM+ Client", 0, capIMPlus, 16},
+ {"mChct Client", 0, capmChat, 0xA},
+ {"SmapeR Client", 0, capSmapeR, 0x07},
+ {"CORE Pager Client", 0, capCorePager, 0xA},
+ {"Zone Alarm IMsecure key 1", 0, capIMSecKey1, 5},
+ {"Zone Alarm IMsecure key 2", 0, capIMSecKey2, 5}
+};
+
+char *GetCapabilityName(BYTE *cap, ICQ_CAPINFO *info)
+{
+ static char capabilityName[256];
+ int i;
+ BOOL found;
+ char *ptr;
+
+ if (info)
+ {
+ ptr = info->caps;
+ *ptr++ = '{';
+ for (i = 0; i < 0x10; ++i)
+ {
+ wsprintf(ptr, "0x%.2x%s", cap[i], ((i==0x0F)?"":", "));
+ ptr += 4;
+ ptr += ((i==0x0F)?0:2);
+ }
+ *ptr++ = '}';
+ *ptr = 0;
+ }
+
+ ptr = capabilityName;
+ found = FALSE;
+ for (i = 0; i < sizeof(stdCapInfo)/(sizeof(*stdCapInfo)); ++i)
+ if (!memcmp(stdCapInfo[i].caps, cap, stdCapInfo[i].capSize))
+ {
+ lstrcpyA(ptr, "01. "); ptr += 4;
+ lstrcpyA(ptr, stdCapInfo[i].name);
+ ptr += lstrlen(stdCapInfo[i].name);
+ if (info)
+ {
+ info->type = 1;
+ info->hIcon = NULL;
+ lstrcpyA(info->name, stdCapInfo[i].name);
+ }
+ found = TRUE;
+ break;
+ }
+ for (i = 0; i < sizeof(capXStatus)/(sizeof(*capXStatus)); ++i)
+ if (!memcmp(capXStatus[i], cap, 0x10))
+ {
+ lstrcpyA(ptr, "01. "); ptr += 4;
+ lstrcpyA(ptr, "XStatus: ");
+ ptr += lstrlen("XStatus: ");
+ lstrcpyA(ptr, nameXStatus[i]);
+ ptr += lstrlen(nameXStatus[i]);
+ if (info)
+ {
+ info->type = 1;
+ info->hIcon = NULL;
+ lstrcpyA(info->name, capabilityName+4);
+ }
+ found = TRUE;
+ break;
+ }
+ if (!found)
+ {
+ for (i = 0; i < lstCustomCaps->realCount; ++i)
+ if (!memcmp(((ICQ_CUSTOMCAP *)(lstCustomCaps->items[i]))->caps, cap, BINARY_CAP_SIZE))
+ {
+ lstrcpyA(ptr, "02. "); ptr += 4;
+ lstrcpyA(ptr, ((ICQ_CUSTOMCAP *)(lstCustomCaps->items[i]))->name);
+ ptr += lstrlen(((ICQ_CUSTOMCAP *)(lstCustomCaps->items[i]))->name);
+ if (info)
+ {
+ info->type = 2;
+ info->hIcon = NULL;
+ lstrcpyA(info->name, ((ICQ_CUSTOMCAP *)(lstCustomCaps->items[i]))->name);
+ }
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ {
+ int nAlpha = 0;
+ for (i = 0; i < 0x10; ++i)
+ if ((cap[i] >= 0x20) && (cap[i] <= 0x7e) || (cap[i] == 0x99))
+ {
+ if ((cap[i] >= '0') && (cap[i] <= '9') || (cap[i] >= 'a') && (cap[i] <= 'z') || (cap[i] >= 'A') && (cap[i] <= 'Z'))
+ ++nAlpha;
+ if (!found)
+ {
+ lstrcpyA(ptr, "00. ");
+ ptr += 4;
+ }
+ *ptr++ = cap[i];
+ found = TRUE;
+ }
+ *ptr = 0;
+ if (found)
+ {
+ if (!strncmp(capabilityName+4, "Miranda/", 8))
+ {
+ capabilityName[1] = '3';
+ if (info)
+ {
+ info->type = 3;
+ info->hIcon = NULL;
+ }
+ lstrcpyA(info->name, capabilityName+4);
+ } else
+ if (nAlpha > 4)
+ {
+ capabilityName[1] = '4';
+ if (info)
+ {
+ info->type = 4;
+ info->hIcon = NULL;
+ }
+ lstrcpyA(info->name, capabilityName+4);
+ } else
+ {
+ found = FALSE;
+ ptr = capabilityName;
+ }
+ }
+ }
+ if (!found)
+ {
+ lstrcpyA(ptr, "05. "); ptr += 4;
+ if (info)
+ {
+ info->type = 5;
+ lstrcpyA(ptr, info->caps);
+ ptr += lstrlenA(info->caps);
+ lstrcpyA(info->name, info->caps);
+ } else
+ {
+ info->type = 5;
+ *ptr++ = '{';
+ for (i = 0; i < 0x10; ++i)
+ {
+ wsprintf(ptr, "0x%.2x%s", cap[i], ((i==0x0F)?"":", "));
+ ptr += 4;
+ ptr += ((i==0x0F)?0:2);
+ }
+ *ptr++ = '}';
+ *ptr = 0;
+ }
+ }
+ *ptr = 0;
+ return capabilityName;
+}
diff --git a/icqj_s7_sss_mod/capabilities.h b/icqj_s7_sss_mod/capabilities.h new file mode 100644 index 0000000..6960534 --- /dev/null +++ b/icqj_s7_sss_mod/capabilities.h @@ -0,0 +1,156 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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);
+
+// Pack binary caps to output buffer
+void AddCapabilitiesToBuffer(BYTE* packet, DWORD fdwContactCaps);
+
+// Get capability name
+typedef struct
+{
+ HANDLE hIcon;
+ int type;
+ char name[128];
+ char caps[128];
+} ICQ_CAPINFO;
+char *GetCapabilityName(BYTE *cap, ICQ_CAPINFO *info);
+
+// -----------------------------------------------------------------------------
+extern const capstr capSrvRelay;
+extern const capstr capUTF;
+extern const capstr capTyping;
+extern const capstr capXtraz;
+extern const capstr capAimFile;
+extern const capstr capPush2Talk;
+extern const capstr capIcqLite;
+extern const capstr capRTF;
+extern const capstr capXtrazChat;
+extern const capstr capVoiceChat;
+extern const capstr capIcqDevil;
+extern const capstr capDirect;
+extern const capstr capNewCap;
+extern const capstr capAimIcq;
+// -----------------------------------------------------------------------------
+extern const capstr capMirandaIm;
+extern const capstr capMirandaMobile;
+extern const capstr capMimPack;
+extern const capstr capIcqJs7;
+extern const capstr capIcqJp;
+extern const capstr capIcqJs7s;
+extern const capstr capIcqJs7old;
+extern const capstr capIcqJSin;
+extern const capstr capIcqJen;
+extern const capstr capAimOscar;
+extern const capstr capTrillian;
+extern const capstr capTrilCrypt;
+extern const capstr capSim;
+extern const capstr capSimOld;
+extern const capstr capLicq;
+extern const capstr capKopete;
+extern const capstr capmIcq;
+extern const capstr capAndRQ;
+extern const capstr capRAndQ;
+extern const capstr capmChat;
+extern const capstr capJimm;
+extern const capstr capCorePager;
+extern const capstr capDiChat;
+extern const capstr capNaim;
+extern const capstr capAnastasia;
+extern const capstr capQip;
+extern const capstr capQip_1;
+extern const capstr capQipSymbian;
+extern const capstr capQipPDA;
+extern const capstr capQipMobile;
+extern const capstr capVmICQ;
+extern const capstr capSmapeR;
+extern const capstr capIMPlus;
+extern const capstr capYapp;
+extern const capstr capQipInfium;
+extern const capstr capQipPlugins;
+extern const capstr capIm2;
+extern const capstr capMacIcq;
+extern const capstr capIs2001;
+extern const capstr capIs2002;
+extern const capstr capComm20012;
+extern const capstr capStrIcq;
+extern const capstr capAimIcon; // CAP_AIM_BUDDYICON
+extern const capstr capAimDirect; // CAP_AIM_DIRECTIM
+extern const capstr capAimFileShare;
+extern const capstr capIcqLite;
+extern const capstr capAimChat;
+extern const capstr capUim;
+extern const capstr capRambler;
+extern const capstr capAbv;
+extern const capstr capNetvigator;
+extern const capstr captZers; // CAP_TZERS
+extern const capstr capHtmlMsgs; // icq6
+extern const capstr capLiveVideo;// icq6
+extern const capstr capSimpLite;
+extern const capstr capSimpPro;
+extern const capstr capIMsecure; // ZoneLabs
+extern const capstr capAimAudio;
+extern const capstr capAimAddins;
+extern const capstr capAimContactSnd;
+extern const capstr capAimUnk2;
+extern const capstr capPalmJicq;
+extern const capstr capInluxMsgr;
+extern const capstr capMipClient;
+extern const capstr capIMadering;
+extern const capstr capIMSecKey1;
+extern const capstr capIMSecKey2;
+extern const capstr capUnknown1;
+extern const capstr capAimSendbuddylist;
+extern const capstr capClimm;
+// -----------------------------------------------------------------------------
+extern const capstr capXStatus[37];
+extern const char* nameXStatus[37];
diff --git a/icqj_s7_sss_mod/chan_01login.c b/icqj_s7_sss_mod/chan_01login.c new file mode 100644 index 0000000..b308a51 --- /dev/null +++ b/icqj_s7_sss_mod/chan_01login.c @@ -0,0 +1,122 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern WORD wLocalSequence;
+
+
+void handleLoginChannel(unsigned char *buf, WORD datalen, serverthread_info *info)
+{
+ icq_packet packet;
+
+ if (icq_regNewUin){
+ requestImage();
+ return;
+ }
+
+
+ // 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 = 12;
+ write_flap(&packet, ICQ_LOGIN_CHAN);
+ packDWord(&packet, 0x00000001);
+ packTLVDWord(&packet, 0x8003, 0x00100000); // unknown
+ 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)(14 + wUinLen));
+ packFNACHeaderFull(&packet, ICQ_AUTHORIZATION_FAMILY, ICQ_SIGNON_AUTH_REQUEST, 0, 0);
+ packTLV(&packet, 0x0001, wUinLen, szUin);
+ 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_s7_sss_mod/chan_02data.c b/icqj_s7_sss_mod/chan_02data.c new file mode 100644 index 0000000..73529f4 --- /dev/null +++ b/icqj_s7_sss_mod/chan_02data.c @@ -0,0 +1,233 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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, info);
+ 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 -= wExtraBytes;
+ pSnacHeader->bValid = TRUE;
+ }
+ else if (wExtraBytes == 0x0E)
+ {
+ *pBuffer += 8; // TLV(2) - unknown
+ *pBuffer += 4;
+ unpackWord(pBuffer, &(pSnacHeader->wVersion));
+ *pwBufferLength -= wExtraBytes;
+ pSnacHeader->bValid = TRUE;
+ }
+ else
+ {
+ *pBuffer += wExtraBytes;
+ *pwBufferLength -= 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;
+ case 0x19: msg = "Query failed"; break;
+ case 0x1A: msg = "Timeout"; break;
+ case 0x1B: msg = "Error text"; break; // ?
+ case 0x1C: msg = "General failure"; break;
+ case 0x1D: msg = "Progress"; break;
+ case 0x1E: msg = "In free area"; break;
+ case 0x1F: msg = "Parental controls"; break;
+ case 0x20: msg = "Remote restricted"; break;
+ default: msg = ""; break;
+ }
+
+ NetLog_Server("SNAC(x%02X,x01) - Error(%u): %s", wFamily, wError, msg);
+}
diff --git a/icqj_s7_sss_mod/chan_03error.c b/icqj_s7_sss_mod/chan_03error.c new file mode 100644 index 0000000..11e71e2 --- /dev/null +++ b/icqj_s7_sss_mod/chan_03error.c @@ -0,0 +1,44 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/chan_04close.c b/icqj_s7_sss_mod/chan_04close.c new file mode 100644 index 0000000..dd7024d --- /dev/null +++ b/icqj_s7_sss_mod/chan_04close.c @@ -0,0 +1,351 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+extern HANDLE hServerConn;
+
+static void handleMigration(serverthread_info *info);
+static int connectNewServer(serverthread_info *info);
+static void handleRuntimeError(WORD wError);
+static void handleSignonError(WORD wError);
+
+
+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->isMigrating) && 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");
+
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+
+ 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_CloseConnection(&hServerConn, TRUE);
+}
+
+
+
+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_CloseConnection(&hServerConn, TRUE);
+ 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);
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ NetLib_CloseConnection(&hServerConn, TRUE);
+ 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;
+
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ NetLib_CloseConnection(&hServerConn, TRUE);
+ return; // Failure
+ }
+
+ NetLog_Server("Authenticated.");
+ info->newServerReady = 1;
+
+ return;
+}
+
+
+
+static int connectNewServer(serverthread_info *info)
+{
+ WORD servport;
+ NETLIBOPENCONNECTION nloc = {0};
+ int res = 0;
+
+ if (!gbGatewayMode)
+ { // close connection only if not in gateway mode
+ NetLib_CloseConnection(&hServerConn, TRUE);
+ }
+
+ /* Get the ip and port */
+ servport = info->wServerPort; // prepare default port
+ parseServerAddress(info->newServer, &servport);
+
+ nloc.flags = 0;
+ nloc.szHost = info->newServer;
+ nloc.wPort = servport;
+
+ if (!gbGatewayMode)
+ {
+ { /* Time to release packet receiver, connection already closed */
+ NetLib_CloseConnection(&info->hPacketRecver, FALSE);
+
+ NetLog_Server("Closed connection to login server");
+ }
+
+ hServerConn = NetLib_OpenConnection(ghServerNetlibUser, NULL, &nloc);
+ if (hServerConn)
+ { /* Time to recreate the packet receiver */
+ info->hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 0x2400);
+ if (!info->hPacketRecver)
+ {
+ 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);
+ ZeroMemory(gpszPassword, sizeof(gpszPassword));
+ 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 0x12: // Database send error
+ case 0x14: // Reservation map error
+ case 0x15: // Reservation link error
+ case 0x1A: // Reservation timeout
+ if(bServerAutoChange)
+ TryNextServer();
+ else
+ 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)
+ if(bServerAutoChange)
+ TryNextServer();
+ else
+ icq_LogFatalParam("Connection failed.\nServer has too many connections from your IP (%d).", wError);
+ break;
+
+ case 0x18: // Reservation rate limit exceeded
+ case 0x1D: // Rate limit exceeded
+ if(bServerAutoChange)
+ TryNextServer();
+ else
+ 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
+ if(bServerAutoChange)
+ TryNextServer();
+ else
+ 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
+ if(bServerAutoChange)
+ TryNextServer();
+ else
+ icq_LogMessage(LOG_FATAL, "Connection failed.\nSecure (MD5) login is not supported on this account.");
+ break;
+
+ case 0: // No error
+ 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 0x0F: // Internal error
+ case 0x11: // Suspended account
+ case 0x13: // Database link error
+ case 0x19: // User too heavily warned
+ case 0x1F: // Token server timeout
+ case 0x20: // Invalid SecureID number
+ case 0x21: // MC error
+ case 0x22: // Age restriction
+ case 0x23: // RequireRevalidation
+ case 0x24: // Link rule rejected
+ case 0x25: // Missing information or bad SNAC format
+ case 0x26: // Link broken
+ case 0x27: // Invalid client IP
+ case 0x28: // Partner rejected
+ case 0x29: // SecureID missing
+ case 0x2A: // Blocked account | Bump user
+
+ 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_s7_sss_mod/chan_05ping.c b/icqj_s7_sss_mod/chan_05ping.c new file mode 100644 index 0000000..187ff34 --- /dev/null +++ b/icqj_s7_sss_mod/chan_05ping.c @@ -0,0 +1,116 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern HANDLE hServerConn;
+
+
+void handlePingChannel(unsigned char* buf, WORD datalen)
+{
+ NetLog_Server("Warning: Ignoring server packet on PING channel");
+}
+
+
+
+static DWORD __stdcall icq_keepAliveThread(void* arg)
+{
+ serverthread_info* info = (serverthread_info*)arg;
+ icq_packet packet;
+ DWORD dwInterval = ICQGetContactSettingDword(NULL, "KeepAliveInterval", KEEPALIVE_INTERVAL);
+
+ NetLog_Server("Keep alive thread starting.");
+
+ info->hKeepAliveEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ for(;;)
+ {
+ DWORD dwWait = WaitForSingleObjectEx(info->hKeepAliveEvent, dwInterval, 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(info->hKeepAliveEvent);
+ info->hKeepAliveEvent = NULL;
+
+ return 0;
+}
+
+
+
+void StartKeepAlive(serverthread_info* info)
+{
+ if (info->hKeepAliveEvent) // start only once
+ return;
+
+ if (ICQGetContactSettingByte(NULL, "KeepAlive", 0))
+ {
+ info->hKeepAliveThread = ICQCreateThreadEx(icq_keepAliveThread, info, NULL);
+ }
+}
+
+
+
+void StopKeepAlive(serverthread_info* info)
+{ // finish keep alive thread
+ if (info->hKeepAliveEvent)
+ {
+ SetEvent(info->hKeepAliveEvent);
+
+ // wait for the thread to finish
+ WaitForSingleObjectEx(info->hKeepAliveThread, INFINITE, FALSE);
+ CloseHandle(info->hKeepAliveThread);
+ info->hKeepAliveThread = NULL;
+ }
+}
diff --git a/icqj_s7_sss_mod/changeinfo/changeinfo.h b/icqj_s7_sss_mod/changeinfo/changeinfo.h new file mode 100644 index 0000000..30a32a3 --- /dev/null +++ b/icqj_s7_sss_mod/changeinfo/changeinfo.h @@ -0,0 +1,119 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/changeinfo/constants.c b/icqj_s7_sss_mod/changeinfo/constants.c new file mode 100644 index 0000000..2857e1c --- /dev/null +++ b/icqj_s7_sss_mod/changeinfo/constants.c @@ -0,0 +1,661 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+static ListTypeDataItem countries[]={
+ {0 ,LPGEN("Unspecified")},
+ {9999,LPGEN("Other")},
+ {93 ,LPGEN("Afghanistan")},
+ {355 ,LPGEN("Albania")},
+ {213 ,LPGEN("Algeria")},
+ {684 ,LPGEN("American Samoa")},
+ {376 ,LPGEN("Andorra")},
+ {244 ,LPGEN("Angola")},
+ {101 ,LPGEN("Anguilla")},
+ {102 ,LPGEN("Antigua and Barbuda")},
+ {5902,LPGEN("Antilles")},
+ {54 ,LPGEN("Argentina")},
+ {374 ,LPGEN("Armenia")},
+ {297 ,LPGEN("Aruba")},
+ {247 ,LPGEN("Ascension Island")},
+ {61 ,LPGEN("Australia")},
+ {43 ,LPGEN("Austria")},
+ {994 ,LPGEN("Azerbaijan")},
+ {103 ,LPGEN("Bahamas")},
+ {973 ,LPGEN("Bahrain")},
+ {880 ,LPGEN("Bangladesh")},
+ {104 ,LPGEN("Barbados")},
+ {120 ,LPGEN("Barbuda")},
+ {375 ,LPGEN("Belarus")},
+ {32 ,LPGEN("Belgium")},
+ {501 ,LPGEN("Belize")},
+ {229 ,LPGEN("Benin")},
+ {105 ,LPGEN("Bermuda")},
+ {975 ,LPGEN("Bhutan")},
+ {591 ,LPGEN("Bolivia")},
+ {387 ,LPGEN("Bosnia and Herzegovina")},
+ {267 ,LPGEN("Botswana")},
+ {55 ,LPGEN("Brazil")},
+ {106 ,LPGEN("British Virgin Islands")},
+ {673 ,LPGEN("Brunei")},
+ {359 ,LPGEN("Bulgaria")},
+ {226 ,LPGEN("Burkina Faso")},
+ {257 ,LPGEN("Burundi")},
+ {855 ,LPGEN("Cambodia")},
+ {237 ,LPGEN("Cameroon")},
+ {107 ,LPGEN("Canada")},
+ {178 ,LPGEN("Canary Islands")},
+ {238 ,LPGEN("Cape Verde Islands")},
+ {108 ,LPGEN("Cayman Islands")},
+ {236 ,LPGEN("Central African Republic")},
+ {235 ,LPGEN("Chad")},
+ {56 ,LPGEN("Chile, Republic of")},
+ {86 ,LPGEN("China")},
+ {672 ,LPGEN("Christmas Island")},
+ {6101,LPGEN("Cocos-Keeling Islands")},
+ {6102,LPGEN("Cocos (Keeling) Islands")},
+ {57 ,LPGEN("Colombia")},
+ {2691,LPGEN("Comoros")},
+ {243 ,LPGEN("Congo, Democratic Republic of (Zaire)")},
+ {242 ,LPGEN("Congo, Republic of the")},
+ {682 ,LPGEN("Cook Islands")},
+ {506 ,LPGEN("Costa Rica")},
+ {225 ,LPGEN("Cote d'Ivoire (Ivory Coast)")},
+ {385 ,LPGEN("Croatia")},
+ {53 ,LPGEN("Cuba")},
+ {357 ,LPGEN("Cyprus")},
+ {420 ,LPGEN("Czech Republic")},
+ {45 ,LPGEN("Denmark")},
+ {246 ,LPGEN("Diego Garcia")},
+ {253 ,LPGEN("Djibouti")},
+ {109 ,LPGEN("Dominica")},
+ {110 ,LPGEN("Dominican Republic")},
+ {593 ,LPGEN("Ecuador")},
+ {20 ,LPGEN("Egypt")},
+ {503 ,LPGEN("El Salvador")},
+ {240 ,LPGEN("Equatorial Guinea")},
+ {291 ,LPGEN("Eritrea")},
+ {372 ,LPGEN("Estonia")},
+ {251 ,LPGEN("Ethiopia")},
+ {298 ,LPGEN("Faeroe Islands")},
+ {500 ,LPGEN("Falkland Islands")},
+ {679 ,LPGEN("Fiji")},
+ {358 ,LPGEN("Finland")},
+ {33 ,LPGEN("France")},
+ {5901,LPGEN("French Antilles")},
+ {594 ,LPGEN("French Guiana")},
+ {689 ,LPGEN("French Polynesia")},
+ {241 ,LPGEN("Gabon")},
+ {220 ,LPGEN("Gambia")},
+ {995 ,LPGEN("Georgia")},
+ {49 ,LPGEN("Germany")},
+ {233 ,LPGEN("Ghana")},
+ {350 ,LPGEN("Gibraltar")},
+ {30 ,LPGEN("Greece")},
+ {299 ,LPGEN("Greenland")},
+ {111 ,LPGEN("Grenada")},
+ {590 ,LPGEN("Guadeloupe")},
+ {671 ,LPGEN("Guam, US Territory of")},
+ {502 ,LPGEN("Guatemala")},
+ {224 ,LPGEN("Guinea")},
+ {245 ,LPGEN("Guinea-Bissau")},
+ {592 ,LPGEN("Guyana")},
+ {509 ,LPGEN("Haiti")},
+ {504 ,LPGEN("Honduras")},
+ {852 ,LPGEN("Hong Kong")},
+ {36 ,LPGEN("Hungary")},
+ {354 ,LPGEN("Iceland")},
+ {91 ,LPGEN("India")},
+ {62 ,LPGEN("Indonesia")},
+ {98 ,LPGEN("Iran (Islamic Republic of)")},
+ {964 ,LPGEN("Iraq")},
+ {353 ,LPGEN("Ireland")},
+ {972 ,LPGEN("Israel")},
+ {39 ,LPGEN("Italy")},
+ {112 ,LPGEN("Jamaica")},
+ {81 ,LPGEN("Japan")},
+ {962 ,LPGEN("Jordan")},
+ {705 ,LPGEN("Kazakhstan")},
+ {254 ,LPGEN("Kenya")},
+ {686 ,LPGEN("Kiribati")},
+ {850 ,LPGEN("Korea, North")},
+ {82 ,LPGEN("Korea, South")},
+ {965 ,LPGEN("Kuwait")},
+ {706 ,LPGEN("Kyrgyzstan")},
+ {856 ,LPGEN("Laos")},
+ {371 ,LPGEN("Latvia")},
+ {961 ,LPGEN("Lebanon")},
+ {266 ,LPGEN("Lesotho")},
+ {231 ,LPGEN("Liberia")},
+ {218 ,LPGEN("Libyan Arab Jamahiriya")},
+ {4101,LPGEN("Liechtenstein")},
+ {370 ,LPGEN("Lithuania")},
+ {352 ,LPGEN("Luxembourg")},
+ {853 ,LPGEN("Macau")},
+ {389 ,LPGEN("Macedonia (F.Y.R.O.M.)")},
+ {261 ,LPGEN("Madagascar")},
+ {265 ,LPGEN("Malawi")},
+ {60 ,LPGEN("Malaysia")},
+ {960 ,LPGEN("Maldives")},
+ {223 ,LPGEN("Mali")},
+ {356 ,LPGEN("Malta")},
+ {692 ,LPGEN("Marshall Islands")},
+ {596 ,LPGEN("Martinique")},
+ {222 ,LPGEN("Mauritania")},
+ {230 ,LPGEN("Mauritius")},
+ {269 ,LPGEN("Mayotte Island")},
+ {52 ,LPGEN("Mexico")},
+ {691 ,LPGEN("Micronesia, Federated States of")},
+ {373 ,LPGEN("Moldova, Republic of")},
+ {377 ,LPGEN("Monaco")},
+ {976 ,LPGEN("Mongolia")},
+ {113 ,LPGEN("Montserrat")},
+ {212 ,LPGEN("Morocco")},
+ {258 ,LPGEN("Mozambique")},
+ {95 ,LPGEN("Myanmar")},
+ {264 ,LPGEN("Namibia")},
+ {674 ,LPGEN("Nauru")},
+ {977 ,LPGEN("Nepal")},
+ {31 ,LPGEN("Netherlands")},
+ {599 ,LPGEN("Netherlands Antilles")},
+ {114 ,LPGEN("Nevis")},
+ {687 ,LPGEN("New Caledonia")},
+ {64 ,LPGEN("New Zealand")},
+ {505 ,LPGEN("Nicaragua")},
+ {227 ,LPGEN("Niger")},
+ {234 ,LPGEN("Nigeria")},
+ {683 ,LPGEN("Niue")},
+ {6722,LPGEN("Norfolk Island")},
+ {47 ,LPGEN("Norway")},
+ {968 ,LPGEN("Oman")},
+ {92 ,LPGEN("Pakistan")},
+ {680 ,LPGEN("Palau")},
+ {507 ,LPGEN("Panama")},
+ {675 ,LPGEN("Papua New Guinea")},
+ {595 ,LPGEN("Paraguay")},
+ {51 ,LPGEN("Peru")},
+ {63 ,LPGEN("Philippines")},
+ {48 ,LPGEN("Poland")},
+ {351 ,LPGEN("Portugal")},
+ {121 ,LPGEN("Puerto Rico")},
+ {974 ,LPGEN("Qatar")},
+ {262 ,LPGEN("Reunion Island")},
+ {40 ,LPGEN("Romania")},
+ {6701,LPGEN("Rota Island")},
+ {7 ,LPGEN("Russia")},
+ {250 ,LPGEN("Rwanda")},
+ {290 ,LPGEN("Saint Helena")},
+ {115 ,LPGEN("Saint Kitts")},
+ {1141,LPGEN("Saint Kitts and Nevis")},
+ {122 ,LPGEN("Saint Lucia")},
+ {508 ,LPGEN("Saint Pierre and Miquelon")},
+ {116 ,LPGEN("Saint Vincent and the Grenadines")},
+ {670 ,LPGEN("Saipan Island")},
+ {378 ,LPGEN("San Marino")},
+ {239 ,LPGEN("Sao Tome and Principe")},
+ {966 ,LPGEN("Saudi Arabia")},
+ {442 ,LPGEN("Scotland")},
+ {221 ,LPGEN("Senegal")},
+ {248 ,LPGEN("Seychelles")},
+ {232 ,LPGEN("Sierra Leone")},
+ {65 ,LPGEN("Singapore")},
+ {421 ,LPGEN("Slovakia")},
+ {386 ,LPGEN("Slovenia")},
+ {677 ,LPGEN("Solomon Islands")},
+ {252 ,LPGEN("Somalia")},
+ {27 ,LPGEN("South Africa")},
+ {34 ,LPGEN("Spain")},
+ {94 ,LPGEN("Sri Lanka")},
+ {249 ,LPGEN("Sudan")},
+ {597 ,LPGEN("Suriname")},
+ {268 ,LPGEN("Swaziland")},
+ {46 ,LPGEN("Sweden")},
+ {41 ,LPGEN("Switzerland")},
+ {963 ,LPGEN("Syrian Arab Republic")},
+ {886 ,LPGEN("Taiwan")},
+ {708 ,LPGEN("Tajikistan")},
+ {255 ,LPGEN("Tanzania")},
+ {66 ,LPGEN("Thailand")},
+ {6702,LPGEN("Tinian Island")},
+ {228 ,LPGEN("Togo")},
+ {690 ,LPGEN("Tokelau")},
+ {676 ,LPGEN("Tonga")},
+ {117 ,LPGEN("Trinidad and Tobago")},
+ {216 ,LPGEN("Tunisia")},
+ {90 ,LPGEN("Turkey")},
+ {709 ,LPGEN("Turkmenistan")},
+ {118 ,LPGEN("Turks and Caicos Islands")},
+ {688 ,LPGEN("Tuvalu")},
+ {256 ,LPGEN("Uganda")},
+ {380 ,LPGEN("Ukraine")},
+ {971 ,LPGEN("United Arab Emirates")},
+ {44 ,LPGEN("United Kingdom")},
+ {598 ,LPGEN("Uruguay")},
+ {1 ,LPGEN("USA")},
+ {711 ,LPGEN("Uzbekistan")},
+ {678 ,LPGEN("Vanuatu")},
+ {379 ,LPGEN("Vatican City")},
+ {58 ,LPGEN("Venezuela")},
+ {84 ,LPGEN("Vietnam")},
+ {123 ,LPGEN("Virgin Islands (USA)")},
+ {441 ,LPGEN("Wales")},
+ {681 ,LPGEN("Wallis and Futuna Islands")},
+ {685 ,LPGEN("Western Samoa")},
+ {967 ,LPGEN("Yemen")},
+ {381 ,LPGEN("Yugoslavia")},
+ {3811,LPGEN("Yugoslavia - Serbia")},
+ {382 ,LPGEN("Yugoslavia - Montenegro")},
+ {260 ,LPGEN("Zambia")},
+ {263 ,LPGEN("Zimbabwe")},
+};
+
+static ListTypeDataItem timezones[]={
+ {-100,LPGEN("Unspecified")},
+ {24 ,LPGEN("GMT-12:00 Eniwetok; Kwajalein")},
+ {23 ,LPGEN("GMT-11:30")},
+ {22 ,LPGEN("GMT-11:00 Midway Island; Samoa")},
+ {21 ,LPGEN("GMT-10:30")},
+ {20 ,LPGEN("GMT-10:00 Hawaii")},
+ {19 ,LPGEN("GMT-9:30")},
+ {18 ,LPGEN("GMT-9:00 Alaska")},
+ {17 ,LPGEN("GMT-8:30")},
+ {16 ,LPGEN("GMT-8:00 Pacific Time; Tijuana")},
+ {15 ,LPGEN("GMT-7:30")},
+ {14 ,LPGEN("GMT-7:00 Arizona; Mountain Time")},
+ {13 ,LPGEN("GMT-6:30")},
+ {12 ,LPGEN("GMT-6:00 Central Time; Central America; Saskatchewan")},
+ {11 ,LPGEN("GMT-5:30")},
+ {10 ,LPGEN("GMT-5:00 Eastern Time; Bogota; Lima; Quito")},
+ {9 ,LPGEN("GMT-4:30")},
+ {8 ,LPGEN("GMT-4:00 Atlantic Time; Santiago; Caracas; La Paz")},
+ {7 ,LPGEN("GMT-3:30 Newfoundland")},
+ {6 ,LPGEN("GMT-3:00 Greenland; Buenos Aires; Georgetown")},
+ {5 ,LPGEN("GMT-2:30")},
+ {4 ,LPGEN("GMT-2:00 Mid-Atlantic")},
+ {3 ,LPGEN("GMT-1:30")},
+ {2 ,LPGEN("GMT-1:00 Cape Verde Islands; Azores")},
+ {1 ,LPGEN("GMT-0:30")},
+ {0 ,LPGEN("GMT+0:00 London; Dublin; Edinburgh; Lisbon; Casablanca")},
+ {-1 ,LPGEN("GMT+0:30")},
+ {-2 ,LPGEN("GMT+1:00 Central European Time; West Central Africa; Warsaw")},
+ {-3 ,LPGEN("GMT+1:30")},
+ {-4 ,LPGEN("GMT+2:00 Jerusalem; Helsinki; Harare; Cairo; Bucharest; Athens")},
+ {-5 ,LPGEN("GMT+2:30")},
+ {-6 ,LPGEN("GMT+3:00 Moscow; St. Petersburg; Nairobi; Kuwait; Baghdad")},
+ {-7 ,LPGEN("GMT+3:30 Tehran")},
+ {-8 ,LPGEN("GMT+4:00 Baku; Tbilisi; Yerevan; Abu Dhabi; Muscat")},
+ {-9 ,LPGEN("GMT+4:30 Kabul")},
+ {-10 ,LPGEN("GMT+5:00 Calcutta; Chennai; Mumbai; New Delhi; Ekaterinburg")},
+ {-11 ,LPGEN("GMT+5:30")},
+ {-12 ,LPGEN("GMT+6:00 Astana; Dhaka; Almaty; Novosibirsk; Sri Jayawardenepura")},
+ {-13 ,LPGEN("GMT+6:30 Rangoon")},
+ {-14 ,LPGEN("GMT+7:00 Bankok; Hanoi; Jakarta; Krasnoyarsk")},
+ {-15 ,LPGEN("GMT+7:30")},
+ {-16 ,LPGEN("GMT+8:00 Perth; Taipei; Singapore; Hong Kong; Beijing")},
+ {-17 ,LPGEN("GMT+8:30")},
+ {-18 ,LPGEN("GMT+9:00 Tokyo; Osaka; Seoul; Sapporo; Yakutsk")},
+ {-19 ,LPGEN("GMT+9:30 Darwin; Adelaide")},
+ {-20 ,LPGEN("GMT+10:00 East Australia; Guam; Vladivostok")},
+ {-21 ,LPGEN("GMT+10:30")},
+ {-22 ,LPGEN("GMT+11:00 Magadan; Solomon Is.; New Caledonia")},
+ {-23 ,LPGEN("GMT+11:30")},
+ {-24 ,LPGEN("GMT+12:00 Auckland; Wellington; Fiji; Kamchatka; Marshall Is.")},
+};
+
+static ListTypeDataItem occupations[] = {
+ {0, LPGEN("Unspecified")},
+ {1, LPGEN("Academic")},
+ {2, LPGEN("Administrative")},
+ {3, LPGEN("Art/Entertainment")},
+ {4, LPGEN("College Student")},
+ {5, LPGEN("Computers")},
+ {6, LPGEN("Community & Social")},
+ {7, LPGEN("Education")},
+ {8, LPGEN("Engineering")},
+ {9, LPGEN("Financial Services")},
+ {10, LPGEN("Government")},
+ {11, LPGEN("High School Student")},
+ {12, LPGEN("Home")},
+ {13, LPGEN("ICQ - Providing Help")},
+ {14, LPGEN("Law")},
+ {15, LPGEN("Managerial")},
+ {16, LPGEN("Manufacturing")},
+ {17, LPGEN("Medical/Health")},
+ {18, LPGEN("Military")},
+ {19, LPGEN("Non-Government Organization")},
+ {20, LPGEN("Professional")},
+ {21, LPGEN("Retail")},
+ {22, LPGEN("Retired")},
+ {23, LPGEN("Science & Research")},
+ {24, LPGEN("Sports")},
+ {25, LPGEN("Technical")},
+ {26, LPGEN("University Student")},
+ {27, LPGEN("Web Building")},
+ {99, LPGEN("Other Services")}
+};
+
+static ListTypeDataItem genders[]={
+ {0,LPGEN("Unspecified")},
+ {'M',LPGEN("Male")},
+ {'F',LPGEN("Female")},
+};
+
+static ListTypeDataItem months[]={
+ {0, LPGEN("Unspecified")},
+ {1, LPGEN("January")},
+ {2, LPGEN("February")},
+ {3, LPGEN("March")},
+ {4, LPGEN("April")},
+ {5, LPGEN("May")},
+ {6, LPGEN("June")},
+ {7, LPGEN("July")},
+ {8, LPGEN("August")},
+ {9, LPGEN("September")},
+ {10,LPGEN("October")},
+ {11,LPGEN("November")},
+ {12,LPGEN("December")},
+};
+
+static ListTypeDataItem languages[]={
+ {0, LPGEN("None")},
+ {55,LPGEN("Afrikaans")},
+ {58,LPGEN("Albanian")},
+ {1, LPGEN("Arabic")},
+ {59,LPGEN("Armenian")},
+ {68,LPGEN("Azerbaijani")},
+ {72,LPGEN("Belorussian")},
+ {2, LPGEN("Bhojpuri")},
+ {56,LPGEN("Bosnian")},
+ {3, LPGEN("Bulgarian")},
+ {4, LPGEN("Burmese")},
+ {5, LPGEN("Cantonese")},
+ {6, LPGEN("Catalan")},
+ {61,LPGEN("Chamorro")},
+ {7, LPGEN("Chinese")},
+ {8, LPGEN("Croatian")},
+ {9, LPGEN("Czech")},
+ {10,LPGEN("Danish")},
+ {11,LPGEN("Dutch")},
+ {12,LPGEN("English")},
+ {13,LPGEN("Esperanto")},
+ {14,LPGEN("Estonian")},
+ {15,LPGEN("Farci")},
+ {16,LPGEN("Finnish")},
+ {17,LPGEN("French")},
+ {18,LPGEN("Gaelic")},
+ {19,LPGEN("German")},
+ {20,LPGEN("Greek")},
+ {70,LPGEN("Gujarati")},
+ {21,LPGEN("Hebrew")},
+ {22,LPGEN("Hindi")},
+ {23,LPGEN("Hungarian")},
+ {24,LPGEN("Icelandic")},
+ {25,LPGEN("Indonesian")},
+ {26,LPGEN("Italian")},
+ {27,LPGEN("Japanese")},
+ {28,LPGEN("Khmer")},
+ {29,LPGEN("Korean")},
+ {69,LPGEN("Kurdish")},
+ {30,LPGEN("Lao")},
+ {31,LPGEN("Latvian")},
+ {32,LPGEN("Lithuanian")},
+ {65,LPGEN("Macedonian")},
+ {33,LPGEN("Malay")},
+ {63,LPGEN("Mandarin")},
+ {62,LPGEN("Mongolian")},
+ {34,LPGEN("Norwegian")},
+ {57,LPGEN("Persian")},
+ {35,LPGEN("Polish")},
+ {36,LPGEN("Portuguese")},
+ {60,LPGEN("Punjabi")},
+ {37,LPGEN("Romanian")},
+ {38,LPGEN("Russian")},
+ {39,LPGEN("Serbo-Croatian")},
+ {66,LPGEN("Sindhi")},
+ {40,LPGEN("Slovak")},
+ {41,LPGEN("Slovenian")},
+ {42,LPGEN("Somali")},
+ {43,LPGEN("Spanish")},
+ {44,LPGEN("Swahili")},
+ {45,LPGEN("Swedish")},
+ {46,LPGEN("Tagalog")},
+ {64,LPGEN("Taiwaness")},
+ {71,LPGEN("Tamil")},
+ {47,LPGEN("Tatar")},
+ {48,LPGEN("Thai")},
+ {49,LPGEN("Turkish")},
+ {50,LPGEN("Ukrainian")},
+ {51,LPGEN("Urdu")},
+ {52,LPGEN("Vietnamese")},
+ {67,LPGEN("Welsh")},
+ {53,LPGEN("Yiddish")},
+ {54,LPGEN("Yoruba")},
+};
+
+static ListTypeDataItem interests[]={
+ {0, LPGEN("Unspecified")},
+ {100, LPGEN("Art")},
+ {101, LPGEN("Cars")},
+ {102, LPGEN("Celebrity Fans")},
+ {103, LPGEN("Collections")},
+ {104, LPGEN("Computers")},
+ {105, LPGEN("Culture & Literature")},
+ {106, LPGEN("Fitness")},
+ {107, LPGEN("Games")},
+ {108, LPGEN("Hobbies")},
+ {109, LPGEN("ICQ - Providing Help")},
+ {110, LPGEN("Internet")},
+ {111, LPGEN("Lifestyle")},
+ {112, LPGEN("Movies/TV")},
+ {113, LPGEN("Music")},
+ {114, LPGEN("Outdoor Activities")},
+ {115, LPGEN("Parenting")},
+ {116, LPGEN("Pets/Animals")},
+ {117, LPGEN("Religion")},
+ {118, LPGEN("Science/Technology")},
+ {119, LPGEN("Skills")},
+ {120, LPGEN("Sports")},
+ {121, LPGEN("Web Design")},
+ {122, LPGEN("Nature and Environment")},
+ {123, LPGEN("News & Media")},
+ {124, LPGEN("Government")},
+ {125, LPGEN("Business & Economy")},
+ {126, LPGEN("Mystics")},
+ {127, LPGEN("Travel")},
+ {128, LPGEN("Astronomy")},
+ {129, LPGEN("Space")},
+ {130, LPGEN("Clothing")},
+ {131, LPGEN("Parties")},
+ {132, LPGEN("Women")},
+ {133, LPGEN("Social science")},
+ {134, LPGEN("60's")},
+ {135, LPGEN("70's")},
+ {136, LPGEN("80's")},
+ {137, LPGEN("50's")},
+ {138, LPGEN("Finance and corporate")},
+ {139, LPGEN("Entertainment")},
+ {140, LPGEN("Consumer electronics")},
+ {141, LPGEN("Retail stores")},
+ {142, LPGEN("Health and beauty")},
+ {143, LPGEN("Media")},
+ {144, LPGEN("Household products")},
+ {145, LPGEN("Mail order catalog")},
+ {146, LPGEN("Business services")},
+ {147, LPGEN("Audio and visual")},
+ {148, LPGEN("Sporting and athletic")},
+ {149, LPGEN("Publishing")},
+ {150, LPGEN("Home automation")}
+};
+
+static ListTypeDataItem pastbackground[]={
+ {0, LPGEN("Unspecified")},
+ {300, LPGEN("Elementary School")},
+ {301, LPGEN("High School")},
+ {302, LPGEN("College")},
+ {303, LPGEN("University")},
+ {304, LPGEN("Military")},
+ {305, LPGEN("Past Work Place")},
+ {306, LPGEN("Past Organization")},
+ {399, LPGEN("Other")}
+};
+
+static ListTypeDataItem affiliation[]={
+ {0, LPGEN("Unspecified")},
+ {200, LPGEN("Alumni Org.")},
+ {201, LPGEN("Charity Org.")},
+ {202, LPGEN("Club/Social Org.")},
+ {203, LPGEN("Community Org.")},
+ {204, LPGEN("Cultural Org.")},
+ {205, LPGEN("Fan Clubs")},
+ {206, LPGEN("Fraternity/Sorority")},
+ {207, LPGEN("Hobbyists Org.")},
+ {208, LPGEN("International Org.")},
+ {209, LPGEN("Nature and Environment Org.")},
+ {210, LPGEN("Professional Org.")},
+ {211, LPGEN("Scientific/Technical Org.")},
+ {212, LPGEN("Self Improvement Group")},
+ {213, LPGEN("Spiritual/Religious Org.")},
+ {214, LPGEN("Sports Org.")},
+ {215, LPGEN("Support Org.")},
+ {216, LPGEN("Trade and Business Org.")},
+ {217, LPGEN("Union")},
+ {218, LPGEN("Volunteer Org.")},
+ {299, LPGEN("Other")},
+};
+
+static ListTypeDataItem maritalstatuses[]={
+ {0, LPGEN("Unspecified")},
+ {10, LPGEN("Single")},
+ {11, LPGEN("Close relationships")},
+ {12, LPGEN("Engaged")},
+ {20, LPGEN("Married")},
+ {30, LPGEN("Divorced")},
+ {31, LPGEN("Separated")},
+ {40, LPGEN("Widowed")}
+};
+
+
+const int ageRange[]={13,0x7FFF}; // 14, 130
+const int yearRange[]={1753,0x7FFF}; // 1880, 2000
+const int dayRange[]={1,31};
+
+
+SettingItem setting[]={
+ //personal
+ {LPGEN("Personal"), LI_DIVIDER},
+ {LPGEN("Nickname"), LI_STRING, DBVT_ASCIIZ, "Nick"},
+ {LPGEN("First name"), LI_STRING, DBVT_ASCIIZ, "FirstName"},
+ {LPGEN("Last name"), LI_STRING, DBVT_ASCIIZ, "LastName"},
+ {LPGEN("Age"), LI_NUMBER, DBVT_WORD, "Age", (void*)ageRange},
+ {LPGEN("Gender"), LI_LIST, DBVT_BYTE, "Gender", genders, sizeof(genders)/sizeof(genders[0])},
+ {LPGEN("About"), LI_LONGSTRING, DBVT_ASCIIZ, "About"},
+ //password
+ {LPGEN("Password"), LI_DIVIDER},
+ {LPGEN("Password"), LI_STRING|LIF_PASSWORD,DBVT_ASCIIZ, "Password"},
+ //contact
+ {LPGEN("Contact"), LI_DIVIDER},
+ {LPGEN("Primary e-mail"), LI_STRING, DBVT_ASCIIZ, "e-mail"},
+ {LPGEN("Secondary e-mail"), LI_STRING, DBVT_ASCIIZ, "e-mail0"},
+ {LPGEN("Tertiary e-mail"), LI_STRING, DBVT_ASCIIZ, "e-mail1"},
+ {LPGEN("Homepage"), LI_STRING, DBVT_ASCIIZ, "Homepage"},
+ {LPGEN("Street"), LI_STRING, DBVT_ASCIIZ, "Street"},
+ {LPGEN("City"), LI_STRING, DBVT_ASCIIZ, "City"},
+ {LPGEN("State"), LI_STRING, DBVT_ASCIIZ, "State"},
+ {LPGEN("ZIP/postcode"), LI_STRING, DBVT_ASCIIZ, "ZIP"},
+ {LPGEN("Country"), LI_LIST, DBVT_WORD, "Country", countries, sizeof(countries)/sizeof(countries[0])},
+ {LPGEN("Phone number"), LI_STRING, DBVT_ASCIIZ, "Phone"},
+ {LPGEN("Fax number"), LI_STRING, DBVT_ASCIIZ, "Fax"},
+ {LPGEN("Cellular number"),LI_STRING, DBVT_ASCIIZ, "Cellular"},
+ //more
+ {LPGEN("Personal Detail"),LI_DIVIDER},
+ {LPGEN("Timezone"), LI_LIST|LIF_ZEROISVALID|LIF_SIGNED,DBVT_BYTE, "Timezone", timezones, sizeof(timezones)/sizeof(timezones[0])},
+ {LPGEN("Year of birth"), LI_NUMBER, DBVT_WORD, "BirthYear", (void*)yearRange},
+ {LPGEN("Month of birth"), LI_LIST, DBVT_BYTE, "BirthMonth", months, sizeof(months)/sizeof(months[0])},
+ {LPGEN("Day of birth"), LI_NUMBER, DBVT_BYTE, "BirthDay", (void*)dayRange},
+ {LPGEN("Marital Status"), LI_LIST, DBVT_BYTE, "MaritalStatus", maritalstatuses, sizeof(maritalstatuses)/sizeof(maritalstatuses[0])},
+ {LPGEN("Spoken language 1"), LI_LIST, DBVT_ASCIIZ, "Language1", languages, sizeof(languages)/sizeof(languages[0])},
+ {LPGEN("Spoken language 2"), LI_LIST, DBVT_ASCIIZ, "Language2", languages, sizeof(languages)/sizeof(languages[0])},
+ {LPGEN("Spoken language 3"), LI_LIST, DBVT_ASCIIZ, "Language3", languages, sizeof(languages)/sizeof(languages[0])},
+ //more
+ {LPGEN("Originally from"),LI_DIVIDER},
+ {LPGEN("City"), LI_STRING, DBVT_ASCIIZ, "OriginCity"},
+ {LPGEN("State"), LI_STRING, DBVT_ASCIIZ, "OriginState"},
+ {LPGEN("Country"), LI_LIST, DBVT_WORD, "OriginCountry", countries, sizeof(countries)/sizeof(countries[0])},
+ //work
+ {LPGEN("Work"), LI_DIVIDER},
+ {LPGEN("Company name"), LI_STRING, DBVT_ASCIIZ, "Company"},
+ {LPGEN("Company homepage"),LI_STRING, DBVT_ASCIIZ, "CompanyHomepage"},
+ {LPGEN("Company street"), LI_STRING, DBVT_ASCIIZ, "CompanyStreet"},
+ {LPGEN("Company city"), LI_STRING, DBVT_ASCIIZ, "CompanyCity"},
+ {LPGEN("Company state"), LI_STRING, DBVT_ASCIIZ, "CompanyState"},
+ {LPGEN("Company phone"), LI_STRING, DBVT_ASCIIZ, "CompanyPhone"},
+ {LPGEN("Company fax"), LI_STRING, DBVT_ASCIIZ, "CompanyFax"},
+ {LPGEN("Company ZIP/postcode"),LI_STRING,DBVT_ASCIIZ, "CompanyZIP"},
+ {LPGEN("Company country"),LI_LIST, DBVT_WORD, "CompanyCountry",countries, sizeof(countries)/sizeof(countries[0])},
+ {LPGEN("Company department"),LI_STRING, DBVT_ASCIIZ, "CompanyDepartment"},
+ {LPGEN("Company position"),LI_STRING, DBVT_ASCIIZ, "CompanyPosition"},
+ {LPGEN("Company occupation"),LI_LIST, DBVT_WORD, "CompanyOccupation", occupations, sizeof(occupations)/sizeof(occupations[0])},
+ //interests
+ {LPGEN("Personal Interests"), LI_DIVIDER},
+ {LPGEN("Interest category 1"),LI_LIST, DBVT_ASCIIZ, "Interest0Cat", interests, sizeof(interests)/sizeof(interests[0])},
+ {LPGEN("Interest areas 1"),LI_STRING, DBVT_ASCIIZ, "Interest0Text"},
+ {LPGEN("Interest category 2"),LI_LIST, DBVT_ASCIIZ, "Interest1Cat", interests, sizeof(interests)/sizeof(interests[0])},
+ {LPGEN("Interest areas 2"),LI_STRING, DBVT_ASCIIZ, "Interest1Text"},
+ {LPGEN("Interest category 3"),LI_LIST, DBVT_ASCIIZ, "Interest2Cat", interests, sizeof(interests)/sizeof(interests[0])},
+ {LPGEN("Interest areas 3"),LI_STRING, DBVT_ASCIIZ, "Interest2Text"},
+ {LPGEN("Interest category 4"),LI_LIST, DBVT_ASCIIZ, "Interest3Cat", interests, sizeof(interests)/sizeof(interests[0])},
+ {LPGEN("Interest areas 4"),LI_STRING, DBVT_ASCIIZ, "Interest3Text"},
+ //pastbackground
+ {LPGEN("Past Background"), LI_DIVIDER},
+ {LPGEN("Category 1"),LI_LIST, DBVT_ASCIIZ, "Past0", pastbackground, sizeof(pastbackground)/sizeof(pastbackground[0])},
+ {LPGEN("Past Background 1"),LI_STRING, DBVT_ASCIIZ, "Past0Text"},
+ {LPGEN("Category 2"),LI_LIST, DBVT_ASCIIZ, "Past1", pastbackground, sizeof(pastbackground)/sizeof(pastbackground[0])},
+ {LPGEN("Past Background 2"),LI_STRING, DBVT_ASCIIZ, "Past1Text"},
+ {LPGEN("Category 3"),LI_LIST, DBVT_ASCIIZ, "Past2", pastbackground, sizeof(pastbackground)/sizeof(pastbackground[0])},
+ {LPGEN("Past Background 3"),LI_STRING, DBVT_ASCIIZ, "Past2Text"},
+ //affiliation
+ {LPGEN("Affiliations"), LI_DIVIDER},
+ {LPGEN("Affiliation category 1"),LI_LIST,DBVT_ASCIIZ, "Affiliation0", affiliation, sizeof(affiliation)/sizeof(affiliation[0])},
+ {LPGEN("Affiliation 1"),LI_STRING, DBVT_ASCIIZ, "Affiliation0Text"},
+ {LPGEN("Affiliation category 2"),LI_LIST,DBVT_ASCIIZ, "Affiliation1", affiliation, sizeof(affiliation)/sizeof(affiliation[0])},
+ {LPGEN("Affiliation 2"),LI_STRING, DBVT_ASCIIZ, "Affiliation1Text"},
+ {LPGEN("Affiliation category 3"),LI_LIST,DBVT_ASCIIZ, "Affiliation2", affiliation, sizeof(affiliation)/sizeof(affiliation[0])},
+ {LPGEN("Affiliation 3"),LI_STRING, DBVT_ASCIIZ, "Affiliation2Text"}
+};
+
+const int settingCount=sizeof(setting)/sizeof(setting[0]);
diff --git a/icqj_s7_sss_mod/changeinfo/db.c b/icqj_s7_sss_mod/changeinfo/db.c new file mode 100644 index 0000000..a00352b --- /dev/null +++ b/icqj_s7_sss_mod/changeinfo/db.c @@ -0,0 +1,230 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_UTF8:
+ setting[i].value=(LPARAM)null_strdup(dbv.pszVal);
+ 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];
+
+ GetDlgItemTextA(hwndDlg,IDC_OLDPASS,szTest,sizeof(szTest));
+
+ if (strcmpnull(szTest, GetUserPassword(TRUE)))
+ {
+ MessageBoxUtf(hwndDlg, LPGEN("The password does not match your current password. Check Caps Lock and try again."), LPGEN("Change ICQ Details"), 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, LPGEN("The password does not match the password you originally entered. Check Caps Lock and try again."), LPGEN("Change ICQ Details"), 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)
+ {
+ MessageBoxUtf(hwndDlg, LPGEN("The ICQ server does not support passwords longer than 8 characters. Please use a shorter password."), LPGEN("Change ICQ Details"), 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_s7_sss_mod/changeinfo/dlgproc.c b/icqj_s7_sss_mod/changeinfo/dlgproc.c new file mode 100644 index 0000000..b916568 --- /dev/null +++ b/icqj_s7_sss_mod/changeinfo/dlgproc.c @@ -0,0 +1,561 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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, MAX_PATH);
+ else
+ text = ICQTranslateUtfStatic("<empty>", str, MAX_PATH);
+ }
+ 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, MAX_PATH);
+ }
+ else
+ {
+ int j;
+
+ text = ICQTranslateUtfStatic("Unknown value", str, MAX_PATH);
+
+ 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, MAX_PATH);
+ 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())
+ {
+ if (IDYES!=MessageBoxUtf(hwndDlg, LPGEN("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?"), LPGEN("Change ICQ Details"), 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, MAX_PATH);
+ 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, MAX_PATH), &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==VK_F2) 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, MAX_PATH));
+ }
+ 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); i++)
+ if (hUpload[i] && ack->hProcess == hUpload[i]) break;
+
+ if (i == SIZEOF(hUpload)) break;
+ hUpload[i] = NULL;
+ for (done = 0, i = 0; i < SIZEOF(hUpload); i++)
+ done += hUpload[i] == NULL;
+ wsprintf(str,"%s%d%%", ICQTranslateUtfStatic("Upload in progress...", str, MAX_PATH), 100*done/(SIZEOF(hUpload)));
+ SetDlgItemTextUtf(hwndDlg, IDC_UPLOADING, str);
+ if (done < SIZEOF(hUpload)) break;
+
+ ClearChangeFlags();
+ UnhookEvent(hAckHook); hAckHook = NULL;
+ EnableDlgItem(hwndDlg, IDC_LIST, TRUE);
+ EnableDlgItem(hwndDlg, IDC_UPLOADING, FALSE);
+ SetDlgItemTextUtf(hwndDlg, IDC_UPLOADING, ICQTranslateUtfStatic("Upload complete", str, MAX_PATH));
+ 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, MAX_PATH));
+ 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_s7_sss_mod/changeinfo/editlist.c b/icqj_s7_sss_mod/changeinfo/editlist.c new file mode 100644 index 0000000..52ba4e6 --- /dev/null +++ b/icqj_s7_sss_mod/changeinfo/editlist.c @@ -0,0 +1,176 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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, MAX_PATH))))
+ || ((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_s7_sss_mod/changeinfo/editstring.c b/icqj_s7_sss_mod/changeinfo/editstring.c new file mode 100644 index 0000000..a29487e --- /dev/null +++ b/icqj_s7_sss_mod/changeinfo/editstring.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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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*)SAFE_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_s7_sss_mod/changeinfo/expandst.ico b/icqj_s7_sss_mod/changeinfo/expandst.ico Binary files differnew file mode 100644 index 0000000..17367fe --- /dev/null +++ b/icqj_s7_sss_mod/changeinfo/expandst.ico diff --git a/icqj_s7_sss_mod/changeinfo/main.c b/icqj_s7_sss_mod/changeinfo/main.c new file mode 100644 index 0000000..a55422f --- /dev/null +++ b/icqj_s7_sss_mod/changeinfo/main.c @@ -0,0 +1,61 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+int InitChangeDetails(WPARAM wParam, LPARAM lParam)
+{
+ static char szTmp[256];
+ OPTIONSDIALOGPAGE odp = {0};
+
+ if (lParam) return 0;
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ mir_snprintf( szTmp, sizeof( szTmp ), Translate("%s Details"), gpszICQProtoName);
+ odp.hIcon = NULL;
+ odp.hInstance = hInst;
+ odp.position = -1899999999;
+ odp.pszTitle=szTmp;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_CHANGEINFO);
+ odp.pfnDlgProc = ChangeInfoDlgProc;
+
+ CallService(MS_USERINFO_ADDPAGE,wParam,(LPARAM)&odp);
+
+ return 0;
+}
diff --git a/icqj_s7_sss_mod/changeinfo/upload.c b/icqj_s7_sss_mod/changeinfo/upload.c new file mode 100644 index 0000000..1f38779 --- /dev/null +++ b/icqj_s7_sss_mod/changeinfo/upload.c @@ -0,0 +1,205 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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)
+ {
+ MessageBoxUtf(hwndParent, LPGEN("You are not currently connected to the ICQ network. You must be online in order to update your information on the server."), LPGEN("Change ICQ Details"), 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_s7_sss_mod/channels.h b/icqj_s7_sss_mod/channels.h new file mode 100644 index 0000000..08a4016 --- /dev/null +++ b/icqj_s7_sss_mod/channels.h @@ -0,0 +1,54 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __CHANNELS_H
+#define __CHANNELS_H
+
+int unpackSnacHeader(snac_header* pSnacHeader, unsigned char **pBuffer, WORD* pwBufferLength);
+void handleUinChannel(unsigned char *buf, WORD datalen, serverthread_info *info);
+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(serverthread_info* info);
+void StopKeepAlive(serverthread_info* info);
+
+#endif /* __CHANNELS_H */
diff --git a/icqj_s7_sss_mod/cookies.c b/icqj_s7_sss_mod/cookies.c new file mode 100644 index 0000000..8e9d01d --- /dev/null +++ b/icqj_s7_sss_mod/cookies.c @@ -0,0 +1,379 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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 *)SAFE_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, HANDLE hContact, 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].hContact = hContact;
+ 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, HANDLE *phContact, void **ppvExtra)
+{
+ int i;
+ int nFound = 0;
+
+
+ EnterCriticalSection(&cookieMutex);
+
+ i = FindCookieIndex(dwCookie);
+
+ if (i != INVALID_COOKIE_INDEX)
+ {
+ if (phContact)
+ *phContact = cookie[i].hContact;
+ if (ppvExtra)
+ *ppvExtra = cookie[i].pvExtra;
+
+ // Cookie found
+ nFound = 1;
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+
+ return nFound;
+}
+
+
+
+int FindCookieByData(void *pvExtra,DWORD *pdwCookie, HANDLE *phContact)
+{
+ int i;
+ int nFound = 0;
+
+
+ EnterCriticalSection(&cookieMutex);
+
+ for (i = 0; i < cookieCount; i++)
+ {
+ if (pvExtra == cookie[i].pvExtra)
+ {
+ if (phContact)
+ *phContact = cookie[i].hContact;
+ 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, HANDLE *phContact, 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 (phContact)
+ *phContact = cookie[i].hContact;
+ 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);
+}
+
+
+
+void InitMessageCookie(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));
+
+ if (pCookie)
+ {
+ pCookie->dwMsgID1 = dwMsgID1;
+ pCookie->dwMsgID2 = dwMsgID2;
+ }
+}
+
+
+
+message_cookie_data *CreateMessageCookie(WORD bMsgType, BYTE bAckType)
+{
+ message_cookie_data *pCookie;
+
+ pCookie = (message_cookie_data*)SAFE_MALLOC(bMsgType == MTYPE_PLAIN ? sizeof(message_cookie_data_ex) : sizeof(message_cookie_data));
+ if (pCookie)
+ {
+ pCookie->bMessageType = bMsgType;
+ pCookie->nAckType = bAckType;
+
+ InitMessageCookie(pCookie);
+ }
+ return pCookie;
+}
+
diff --git a/icqj_s7_sss_mod/cookies.h b/icqj_s7_sss_mod/cookies.h new file mode 100644 index 0000000..c1e6d4c --- /dev/null +++ b/icqj_s7_sss_mod/cookies.h @@ -0,0 +1,153 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_OFFLINEMESSAGE 0x12
+#define CKT_AVATAR 0x20
+#define CKT_CHECKSPAMBOT 0x40
+
+typedef struct icq_cookie_info_s
+{
+ DWORD dwCookie;
+ HANDLE hContact;
+ 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 offline_message_cookie_s
+{
+ int nMessages;
+} offline_message_cookie;
+
+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 message_cookie_data_ex_s
+{
+ message_cookie_data msg;
+ BYTE isOffline;
+} message_cookie_data_ex;
+
+typedef struct fam15_cookie_data_s
+{
+ BYTE bRequestType;
+} 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, HANDLE hContact, void *pvExtra);
+void FreeCookie(DWORD dwCookie);
+void ReleaseCookie(DWORD dwCookie);
+DWORD GenerateCookie(WORD wIdent);
+
+int GetCookieType(DWORD dwCookie);
+
+int FindCookie(DWORD wCookie, HANDLE *phContact, void **ppvExtra);
+int FindCookieByData(void *pvExtra, DWORD *pdwCookie, HANDLE *phContact);
+int FindMessageCookie(DWORD dwMsgID1, DWORD dwMsgID2, DWORD *pdwCookie, HANDLE *phContact, message_cookie_data **ppvExtra);
+
+void InitMessageCookie(message_cookie_data *pCookie);
+message_cookie_data *CreateMessageCookie(WORD bMsgType, BYTE bAckType);
+
+#endif /* __COOKIES_H */
diff --git a/icqj_s7_sss_mod/directpackets.c b/icqj_s7_sss_mod/directpackets.c new file mode 100644 index 0000000..6c8f24e --- /dev/null +++ b/icqj_s7_sss_mod/directpackets.c @@ -0,0 +1,302 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+extern HANDLE hsmsgrequest;
+extern CRITICAL_SECTION modeMsgsMutex;
+extern WORD wListenPort;
+
+
+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, 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(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, hContact, (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(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(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_s7_sss_mod/directpackets.h b/icqj_s7_sss_mod/directpackets.h new file mode 100644 index 0000000..21362cc --- /dev/null +++ b/icqj_s7_sss_mod/directpackets.h @@ -0,0 +1,56 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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(HANDLE hContact, const char *szMessage, int nBodyLength, WORD wPriority, message_cookie_data *pCookieData, char *szCap);
+
+void icq_sendXtrazRequestDirect(HANDLE hContact, DWORD dwCookie, char* szBody, int nBodyLen, WORD wType);
+void icq_sendXtrazResponseDirect(HANDLE hContact, WORD wCookie, char* szBody, int nBodyLen, WORD wType);
+
+#endif /* __ICQ_DIRECTPACKETS_H */
diff --git a/icqj_s7_sss_mod/docs/IcqOscarJ-db settings.txt b/icqj_s7_sss_mod/docs/IcqOscarJ-db settings.txt new file mode 100644 index 0000000..f932e82 --- /dev/null +++ b/icqj_s7_sss_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_s7_sss_mod/docs/IcqOscarJ-translation.txt b/icqj_s7_sss_mod/docs/IcqOscarJ-translation.txt new file mode 100644 index 0000000..7632a3a --- /dev/null +++ b/icqj_s7_sss_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_s7_sss_mod/docs/gpl.txt b/icqj_s7_sss_mod/docs/gpl.txt new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/icqj_s7_sss_mod/docs/gpl.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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) <year> <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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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 Lesser General +Public License instead of this License. diff --git a/icqj_s7_sss_mod/docs/help_us.txt b/icqj_s7_sss_mod/docs/help_us.txt new file mode 100644 index 0000000..921cd88 --- /dev/null +++ b/icqj_s7_sss_mod/docs/help_us.txt @@ -0,0 +1,3 @@ +sss: webmoney: Z310665177715, R498589439318, E620435050338, U423684816414 (at this time i need to by new computer, if you have some free money, please give me some...)
+persei:
+sin:
\ No newline at end of file diff --git a/icqj_s7_sss_mod/docs/icq-license.txt b/icqj_s7_sss_mod/docs/icq-license.txt new file mode 100644 index 0000000..7f11610 --- /dev/null +++ b/icqj_s7_sss_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_s7_sss_mod/docs/icq-readme.txt b/icqj_s7_sss_mod/docs/icq-readme.txt new file mode 100644 index 0000000..7cd143c --- /dev/null +++ b/icqj_s7_sss_mod/docs/icq-readme.txt @@ -0,0 +1,378 @@ +
+ 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)
+
+
+0.5
+ Account management (together with Miranda core changes)
+ Multi-user chat (Xtraz based)
+
+
+
+Changes
+_______
+
+0.3.8.0 Devel builds
+
+Bugfixes:
+ Fixed HTTP/HTTPS proxy support (removed useless gateway option), long messages are now sent properly
+
+New Features:
+ TODO: Oscar File Transfers - like icq5 (including transfer thru server)
+
+Improvements:
+ Added avatar validity checking
+ Client detection improvements
+
+
+0.3.7.2
+
+Bugfixes:
+ Fixes possible buffer overflow with contact status change
+ Fixed migration was not working at all (should not disconnect so often on server's upgrading)
+ Fixed offline greeting cards were not processed properly
+ Fixed small protocol glitch with reverse peer-to-peer connection
+
+
+0.3.7.1
+
+Bugfixes:
+ Fixed possible hang on exit
+ Fixed avatars were not working when server port set to 0
+ Made message parser more strict (fixes bug allowing stealth invisible client detection)
+ Fixed Popup's unicode support cannot be used in ANSI mode even if available
+
+Improvements:
+ Added new session password API - allowing plugins like Secure Login to work better
+
+
+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_s7_sss_mod/docs/icq.txt b/icqj_s7_sss_mod/docs/icq.txt new file mode 100644 index 0000000..51d2979 --- /dev/null +++ b/icqj_s7_sss_mod/docs/icq.txt @@ -0,0 +1,178 @@ +icq 0.3.8.105
+
+TODO:
+
+1. keep this log .... )))
+2. fix errors, code optimisations e.t.c......
+3. invisible status optimisations (i mean dont ask status message's and other information for contacts witch you invisible for) (in progress(testing))
+4. add more events to history
+5. add basic rtf\xml parsing feature //i think it need to be in core, or srmm module, but no one do not want to do it %)
+6. create gui for convenient viewing icq network log, option for write events to file
+7. create gui for managing visible/invisible/ignore lists
+8. add muc rooms support
+9. add more privacy statusses
+10. add invisible users detection
+11. fix last item in privacy menu: "Allow only users in the Contact list to see you, except Invisible list users"
+12. add new statuses support //currently only one client support it, not needed now....
+
+>>> ??.04.2007
+fixed crash on calulating md5checksumm for big files //patch by Nullbie
+added option for show xstatus icon in clist
+added miranda invivsible detection (like isee from Bio), need optimization //path by [sin]
+other small fixes, optimizations
+merged with latest svn
+added assocmgr support (in progress)
+added unicode version send\detect
+used new core api for creating UI
+changed first run dialog
+added icqj sin mod detection
+enhanced icolib support
+added new MIP client detection
+function for automaticaly reconnect to best servers if have errors..
+>>> 20.03.2007
+merged with latest icqj svn
+added muuid, used new pugininfoex core function, require core 0.7.0.19 or higher
+invisible status optimisations (i mean dont ask status message's and other information for contacts witch you invisible for)
+added popup events when someone checking your real status //thx Bio
+fixed own userinfo tab (in progres) //thx Baloo
+added some new clients detection
+some code fixes\optimizations
+added more popup's options
+
+
+>>> 22.02.2007
+merged with latest svn
+some new options //persei
+>>> 16.02.2007
+fixed DC status icon //persei
+merged with latest svn
+
+>>> 12.02.2007
+fixed AIM detection, added some AIM versions //report by [sin]
+added some capability flag descriptions //hints by Joe
+fixed wrong userinfo packet at login siquence
+added new uin registration feature //many thx. Persei, Bio, Joe
+
+>>> 31.01.07
+modified clients detection
+
+>>> 30.01.07
+merged with icqj sources
+some changes in optins dialog
+fixed crash on exit
+some optimization for sending capabilities
+some optimization for miranda id detection //need to better realization
+
+>>> 28.01.07
+merged with icqj sources
+fixed bug in x-status slot changing
+
+>>> 27.01.07
+merged with icqj sources //thx Joe
+added some cpabilities description //thx Joe
+added change custom status and DC icon slot's option (on features tab)
+added some fake id's
+fixed miranda version detection on non miranda id //thx me :D
+version up to 0.3.8.9
+core 0.7.0.12 or higher needed, or you can use core from my site, who do not want to use nightly builds, use old version....
+
+>>> 26.01.07
+merged with icqj sources
+core 0.7.0.12 or higher needed, or you can use core from my site, who do not want to use nightly builds, use old version....
+
+>>> ??.01.07
+fixed member since detection //thx Jazzy$
+
+>>> 18.01.07
+fixed another bug in client's detection
+
+>>> 17.01.07
+added Miranda IM and ICQ version detection for not Miranda IM id, need to optimization //thx Bio
+added icon on Direct Connection //by Persei
+small fixes\optimizations
+
+>>> 12.01.07
+renamed again.... %)
+
+>>> 11.01.07
+nothing
+
+>>> 09.01.07
+added own caps dispaying... (not completed....)
+
+>>> 09.01.07
+more modifications to userinfo dialog
+modifications to capabilities processing
+some changes to services (look at m_icq.h)
+you can use ctrl+c in "ICQ client info" tab to copy one or more capabilities to buffer (HEX + string)
+now you can send custom capabilities, just create group ICQCaps and put strings in... (use DBE), you can add postfix to your client ID by adding "MIM/MyCoolPack" capabiliti to custom cap list, this add string "MyCoolPack" to end of you client id
+thx Nullbie !
+
+>>> 08.01.07
+some code optimization
+fixed small bugs
+rewriten capabilities.....
+modifed userinfo dialog
+created service witch allow to send\check cutom capabilities to other plugins (look at m_icq.h)
+many help by Nullbie
+
+>>> 31.12.2006
+fixed bug in sending capabilities....
+
+>>> 30.12.2006
+merged with icqj sources
+some changes in clients detection
+
+>>> 26.12.2006
+(again) fixed my own stupid bug (now in clients detection)
+
+>>> 25.12.2006
+maybe random crash fixed....
+aded ICQ 6 id
+
+>>> 20.12.2006
+merged with icqj sources
+
+>>> 03.12.2006
+changed headers for more compatibility with clist_modern
+
+>>> 03.12.2006
+merged with icqj sources
+
+>>> 01.12.2006
+merged with icqj sources
+(sorry to all, i have no time to moding now...)
+
+>>> 30.11.2006
+merged with icqj sources
+
+>>> 28.11.2006
+merged with icqj sources
+
+>>> 26.11.2006
+finished updater configuration and testing.
+
+>>> 25.11.2006
+fixed Miranda IM as Unknown detection (if set send real ID)
+
+>>> 21.11.2006
+merged with icqj sources
+
+>>> 19.11.2006
+finaly fixed bug in privacy menu after source merging (thanks for testing and bug report to Inko)
+changes in db settings for version change (maybe bug fix)
+
+>>> 15.11.2006
+fixed bug in privacy menu after source merging
+
+>>> 13.11.2006
+merged with icqj sources, changed version to 0.3.8.6
+
+>>> 12.11.2006
+fixed crash in Miranda666 id (my own stupid bug ))) )
+merged with official icqj sources
+
+>>> 10.11.2006
+created this file :)
+fixed crash in some client's id
+some code cleaning
\ No newline at end of file diff --git a/icqj_s7_sss_mod/fam_01service.c b/icqj_s7_sss_mod/fam_01service.c new file mode 100644 index 0000000..1cf22c6 --- /dev/null +++ b/icqj_s7_sss_mod/fam_01service.c @@ -0,0 +1,1352 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007,2008 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+// Copyright 2008 [sss], chaos.persei, nullbie, baloo, jarvis
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#define MD5_BLOCK_SIZE 1024*1024 // use 1MB blocks
+extern int gbIdleAllow;
+extern int icqGoingOnlineStatus;
+extern int pendingAvatarsStart;
+extern WORD wListenPort;
+extern CRITICAL_SECTION modeMsgsMutex;
+extern const capstr capXStatus[];
+extern const int moodXStatus[];
+
+extern char* detectUserClient(HANDLE hContact, DWORD dwUin, WORD wVersion, DWORD dwFT1, DWORD dwFT2, DWORD dwFT3, DWORD dwOnlineSince, BYTE bDirectFlag, DWORD dwDirectCookie, DWORD dwWebPort, BYTE* caps, WORD wLen, BYTE* bClientId, char* szClientBuf);
+
+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 ICQ 6
+ serverPacketInit(&packet, 54);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_FAMILIES);
+ packDWord(&packet, 0x00220001);
+ 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
+ /* init rates management */
+ gRates = ratesCreate(pBuffer, wBufferLength);
+ /* ack rate levels */
+ 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, 16);
+ packFNACHeader(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_CLI_REQLISTS);
+ packTLVWord(&packet, 0x0B, 0x000F); // mimic ICQ 6
+ 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, 16);
+ packFNACHeader(&packet, ICQ_BUDDY_FAMILY, ICQ_USER_CLI_REQBUDDY);
+ packTLVWord(&packet, 0x05, 0x0003); // mimic ICQ 6
+ 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;
+
+#ifdef _DEBUG
+ NetLog_Server("Received self info");
+#endif
+ 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);
+
+ dwValue = getDWordFromChain(chain, 3, 1);
+ ICQWriteContactSettingDword(NULL, "LogonTS", dwValue ? dwValue : 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;
+ DWORD dwLevel;
+ // We now have global rate management, although controlled are only some
+ // areas. This should not arrive in most cases. If it does, update our
+ // local rate levels & issue broadcast.
+ unpackWord(&pBuffer, &wStatus);
+ unpackWord(&pBuffer, &wClass);
+ pBuffer += 20;
+ unpackDWord(&pBuffer, &dwLevel);
+ EnterCriticalSection(&ratesMutex);
+ ratesUpdateLevel(gRates, wClass, dwLevel);
+ LeaveCriticalSection(&ratesMutex);
+
+ 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);
+ if (wStatus == 2)
+ NetLog_Server("Rates #%u: Alert", wClass);
+ else
+ NetLog_Server("Rates #%u: Limit", wClass);
+ }
+ else if (wStatus == 4)
+ {
+ ICQBroadcastAck(NULL, ICQACKTYPE_RATEWARNING, ACKRESULT_STATUS, (HANDLE)wClass, wStatus);
+ NetLog_Server("Rates #%u: Clear", wClass);
+ }
+ icq_CheckSpeed(wStatus);
+ }
+
+ 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);
+ SAFE_FREE(&reqdata);
+ break;
+ }
+
+ // Get new family server ip and port
+ wPort = info->wServerPort; // get default port
+ parseServerAddress(pServer, &wPort);
+
+ // establish connection
+ nloc.flags = 0;
+ nloc.szHost = pServer;
+ nloc.wPort = wPort;
+
+ hConnection = NetLib_OpenConnection(ghServerNetlibUser, wFamily == ICQ_AVATAR_FAMILY ? "Avatar " : NULL, &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 > 4 && pBuffer[1] == AVATAR_HASH_PHOTO)
+ { // skip photo item
+ if (wBufferLength >= pBuffer[3] + 4)
+ {
+ wBufferLength -= pBuffer[3] + 4;
+ pBuffer += pBuffer[3] + 4;
+ }
+ else
+ {
+ pBuffer += wBufferLength;
+ wBufferLength = 0;
+ }
+ }
+
+ if ((wBufferLength >= 0x14) && gbAvatarsEnabled)
+ {
+ if (!info->bMyAvatarInited) // signal the server after login
+ { // this refreshes avatar state - it used to work automatically, but now it does not
+ if (ICQGetContactSettingByte(NULL, "ForceOurAvatar", 0))
+ { // keep our avatar
+ char* file = loadMyAvatarFileName();
+
+ IcqSetMyAvatar(0, (LPARAM)file);
+ SAFE_FREE(&file);
+ }
+ else // only change avatar hash to the same one
+ {
+ char hash[0x14];
+
+ memcpy(hash, pBuffer, 0x14);
+ hash[2] = 1; // update image status
+ updateServAvatarHash(hash, 0x14);
+ }
+ info->bMyAvatarInited = TRUE;
+ break;
+ }
+
+ 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 ? AVATAR_HASH_FLASH : AVATAR_HASH_STATIC;
+ 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);
+ 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);
+ }
+ 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 ? AVATAR_HASH_FLASH : AVATAR_HASH_STATIC), ppMap, cbFileSize);
+ }
+
+ 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 ? AVATAR_HASH_FLASH : AVATAR_HASH_STATIC;
+ 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("Received 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)
+{
+ char* res = NULL;
+
+ if (szFile)
+ {
+ HANDLE hFile = NULL, hMap = NULL;
+ BYTE* ppMap = NULL;
+
+ 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)
+ {
+ long cbFileSize = GetFileSize( hFile, NULL );
+ res = (char*)SAFE_MALLOC(16*sizeof(char));
+ if (cbFileSize != 0 && res)
+ {
+ mir_md5_state_t state;
+ mir_md5_byte_t digest[16];
+ int dwOffset = 0;
+ mir_md5_init(&state);
+ while (dwOffset < cbFileSize)
+ {
+ int dwBlockSize = min(MD5_BLOCK_SIZE, cbFileSize-dwOffset);
+ if (!(ppMap = (BYTE*)MapViewOfFile(hMap, FILE_MAP_READ, 0, dwOffset, dwBlockSize)))
+ break;
+ mir_md5_append(&state, (const mir_md5_byte_t *)ppMap, dwBlockSize);
+ UnmapViewOfFile(ppMap);
+ dwOffset += dwBlockSize;
+ }
+ mir_md5_finish(&state, digest);
+ memcpy(res, digest, 16);
+ }
+ }
+ }
+
+
+ if (hMap != NULL) CloseHandle(hMap);
+ if (hFile != NULL) CloseHandle(hFile);
+ }
+
+ return res;
+}
+
+
+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
+ ICQWriteContactSettingByte(hContact, "TemporaryVisible", 0);
+ 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);
+}
+
+
+
+
+void setUserInfo()
+{ // CLI_SETUSERINFO
+ icq_packet packet;
+ WORD wAdditionalData = 0;
+ BYTE bXStatus = ICQGetContactXStatus(NULL);
+ BYTE cID = DBGetContactSettingWord(NULL, gpszICQProtoName, "CurrentID", 0);
+ BYTE cICQModID = DBGetContactSettingWord(NULL, gpszICQProtoName, "CurrentICQModID", 0); // eternity BYTE
+
+ static char wID[] ={ 4, 1, 8, 0, 4, 1, 1, 1, 1, 1, 1, 4,//12
+ 10, 10, 10, 10, 1, 1, 2, 0, 1, 0, 0, 6,//24
+ 6, 1, 12, 2, 1, 0, 0, 0, 0, 0, 1, 4,//36
+ 0, 0, 0, 0, 1, 3, 2, 2, 1, 1, 8, 0,//48
+ 0, 1, 3, 0, 0, 0,//54
+ 4}; // 55 xo) last is MirandaMobile
+
+/* commented out, possibly fixed already
+ { // fix for setting alpha build flag, dunno why it's not retaken from init.c
+ char szVer[MAX_PATH];
+ CallService(MS_SYSTEM_GETVERSIONTEXT, MAX_PATH, (LPARAM)szVer);
+ _strlwr(szVer); // make sure it is lowercase
+ if (strstr(szVer, "alpha") != NULL) // Are we running under Alpha Core
+ MIRANDA_VERSION |= 0x80000000;
+ }
+*/
+
+ if(!cID||cID==11||cID==54)
+ { // if miranda, as 'miranda' or as 'mirandamobile'
+#ifdef DBG_XTRAZ_MUC
+ wAdditionalData += 16;
+#endif
+ if(gbAimEnabled)
+ wAdditionalData += 16;
+ if(gbAvatarsEnabled)
+ wAdditionalData += 16;
+ if(gbUtfEnabled)
+ wAdditionalData += 16;
+ if(gbRTFEnabled)
+ wAdditionalData += 16;
+ if(gbXStatusEnabled)
+ wAdditionalData += 16;
+ if(gbTzerEnabled)
+ wAdditionalData += 16;
+ if(bXStatus)
+ wAdditionalData += 16;
+#ifdef DBG_AIMCONTACTSEND
+ wAdditionalData += 16;
+#endif
+ }
+ else if(gbHideIdEnabled)
+ wAdditionalData += 16;
+ wAdditionalData += wID[cID]*16;
+ if(gbCustomCapEnabled)
+ {
+ wAdditionalData += 16 * lstCustomCaps->realCount;
+ }
+ if(cID==2||cID==23||cID==24||cID==46) //qip caps
+ {
+ if(gbXStatusEnabled)
+ wAdditionalData += 16;
+ if(bXStatus)
+ wAdditionalData += 16;
+ }
+ if(cID>=12&&cID<=15||cID==26) //icq lite group caps
+ {
+ if(gbXStatusEnabled)
+ wAdditionalData += 16;
+ if(bXStatus)
+ wAdditionalData += 16;
+ }
+ serverPacketInit(&packet, (WORD)(62+wAdditionalData));
+ packFNACHeader(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_SET_USER_INFO);
+
+ /* TLV(5): capability data */
+ packWord(&packet, 0x0005);
+ packWord(&packet, (WORD)(32 + wAdditionalData));
+ packBuffer(&packet, capNewCap, 0x10);
+#ifdef DBG_CAPHTML
+ packBuffer(&packet, capHtmlMsgs, 0x10);
+#endif
+ if(gbHideIdEnabled&&cID!=11)
+ {
+ packBuffer(&packet, capIcqJp, 4);
+ packDWord(&packet, MIRANDA_VERSION);
+ packDWord(&packet, ICQ_PLUG_VERSION);
+ packDWord(&packet, gbSecureIM?0x5AFEC0DE:0x00000000);
+ }
+ switch (cID) //client change caps
+ {
+ case 11:
+ packBuffer(&packet, gbHideIdEnabled?capIcqJp:capMirandaIm, gbHideIdEnabled?4:8);
+ packBuffer(&packet, "\x06\x06\x06\x00\x06\x06\x06\x00",8);
+ gbHideIdEnabled?packDWord(&packet, gbSecureIM?0x5AFEC0DE:0x00000000):0;
+ case 0: //miranda
+ {
+ if(!cID && !gbHideIdEnabled)
+ { // Miranda Signature - added customization of various ICQ Mods
+ switch (cICQModID) {
+ case 0:
+ packBuffer(&packet, capMirandaIm, 8);
+ packDWord(&packet, MIRANDA_VERSION);
+ packDWord(&packet, ICQ_JOEWHALE_VERSION);
+ break;
+ case 1:
+ packBuffer(&packet, capMirandaIm, 8);
+ packDWord(&packet, MIRANDA_VERSION);
+ packDWord(&packet, ICQ_BM_VERSION);
+ break;
+ case 2:
+ packBuffer(&packet, capIcqJs7, 4);
+ packDWord(&packet, MIRANDA_VERSION);
+ packDWord(&packet, ICQ_S7SSS_VERSION);
+ break;
+ case 3:
+ packBuffer(&packet, capIcqJSin, 4);
+ packDWord(&packet, MIRANDA_VERSION);
+ packDWord(&packet, ICQ_SIN_VERSION);
+ break;
+ default:
+ case 4:
+ packBuffer(&packet, capIcqJp, 4);
+ packDWord(&packet, MIRANDA_VERSION);
+ packDWord(&packet, ICQ_PLUG_VERSION);
+ break;
+ case 5:
+ packBuffer(&packet, capIcqJen, 4);
+ packDWord(&packet, MIRANDA_VERSION);
+ packDWord(&packet, ICQ_ETERN_VERSION);
+ break;
+ }
+ switch (cICQModID) { // send SecureIM or not for Mods
+ case 2: // s7sss,
+ case 3: // sin,
+ case 4: // plus and
+ case 5: // eternity mods may decode SecureIM flag
+ packDWord( &packet, gbSecureIM ? 0x5AFEC0DE : 0x00000000 );
+ case 0: // icqj and bm mod
+ case 1: // packets are already full
+ default : break;
+ }
+ }
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_TYPING|CAPF_SRV_RELAY|(gbRTFEnabled?CAPF_RTF:0)|(gbXStatusEnabled?CAPF_XTRAZ:0)
+ |(gbUtfEnabled?CAPF_UTF:0)|(gbAvatarsEnabled?CAPF_ICQ_DEVIL:0)|CAPF_AIM_FILE|CAPF_DIRECT);
+ if (bXStatus)
+ packBuffer(&packet, capXStatus[bXStatus-1], 0x10);
+ if (gbAimEnabled)
+ packBuffer(&packet, capAimIcq, 0x10);
+#ifdef DBG_AIMCONTACTSEND
+ {
+ packBuffer(&packet, capAimSendbuddylist, 0x10);
+ }
+#endif
+ if (gbTzerEnabled)
+ packBuffer(&packet, captZers, 16);
+#ifdef DBG_CAPXTRAZ_MUC
+ packNewCap(&packet, 0x134C); // CAP_XTRAZ_MUC
+#endif
+ }
+ break;
+ case 2: //QIP
+ packBuffer(&packet, capQip, 0x10);
+ packBuffer(&packet, capQip_1, 0x10);
+ break;
+ case 23:
+ packBuffer(&packet, capQipPDA, 0x10);
+ break;
+ case 24:
+ packBuffer(&packet, capQipMobile, 0x10);
+ break;
+ case 46: //QIP Infium
+ packBuffer(&packet, capQipInfium, 0x10);
+ packBuffer(&packet, capQipPlugins, 0x10);
+ break;
+ case 4: //icq
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_AIM_FILE|CAPF_XTRAZ_CHAT|CAPF_PUSH2TALK|CAPF_VOICE_CHAT|CAPF_UTF);
+ break;
+ case 9:
+ packBuffer(&packet, capKopete, 0xC);
+ packDWord(&packet, 0x000C0001);
+ break;
+ case 10:
+ packBuffer(&packet, capMacIcq, 0x10);
+ break;
+ case 5:
+ packBuffer(&packet, capAndRQ, 9);
+ packBuffer(&packet, "\x04\x07\x09\x00\x00\x00\x00",7);
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_SRV_RELAY);
+ break;
+ case 6:
+ packBuffer(&packet, capJimm, 5);
+ packBuffer(&packet, "\x30\x2E\x35\x2E\x32\x62\x00\x00\x00\x00\x00",11);
+ break;
+ case 7:
+ packBuffer(&packet, capTrillian, 0x10);
+ break;
+ case 8:
+ packBuffer(&packet, capLicq, 0xC);
+ packDWord(&packet, 0x01030200);
+ break;
+ case 12:
+ packBuffer(&packet, capRambler, 0x10);
+ break;
+ case 13:
+ packBuffer(&packet, captZers, 0x10);
+ break;
+ case 14:
+ packBuffer(&packet, capAbv, 0x10);
+ break;
+ case 15:
+ packBuffer(&packet, capNetvigator, 0x10);
+ break;
+ case 20:
+ packBuffer(&packet, capmChat, 0x10);
+ break;
+ case 25:
+ packBuffer(&packet, capIs2002, 0x10);
+ break;
+ case 26:
+ packBuffer(&packet, captZers, 0x10);
+ packBuffer(&packet, capHtmlMsgs, 0x10);
+ packBuffer(&packet, capLiveVideo, 0x10);
+ break;
+ case 27:
+ packBuffer(&packet, capComm20012, 0x10);
+ packBuffer(&packet, capIs2001, 0x10);
+ break;
+ case 28:
+ packBuffer(&packet, capAnastasia, 0x10);
+ break;
+ case 16:
+ packBuffer(&packet, capSim, 0xC);
+ packDWord(&packet, 0x00090540);
+ break;
+ case 17:
+ packBuffer(&packet, capSim, 0xC);
+ packDWord(&packet, 0x00090580);
+ break;
+ case 18:
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_SRV_RELAY|CAPF_DIRECT|CAPF_RTF);
+ break;
+ case 31:
+ packBuffer(&packet, capmIcq, 0xC); //mIcq
+ packBuffer(&packet, "\x08\x02\x00\x00",4);
+ break;
+ case 34: //IM2
+ packBuffer(&packet, capIm2, 0x10);
+ break;
+ case 35: //GAIM
+ packBuffer(&packet, capAimIcon, 0x10);
+ packBuffer(&packet, capAimDirect, 0x10);
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_AIM_FILE|CAPF_UTF);
+ break;
+ case 40: //uIM
+ packBuffer(&packet, capUim, 0x10);
+ break;
+ case 41: //TICQClient
+ packBuffer(&packet, capComm20012, 0x10);
+ packBuffer(&packet, capIs2001, 0x10);
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_SRV_RELAY|CAPF_RTF);
+ break;
+ case 42: //IC@
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_SRV_RELAY|CAPF_RTF|CAPF_UTF);
+ break;
+ case 43: //PreludeICQ
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_SRV_RELAY|CAPF_UTF|CAPF_TYPING);
+ break;
+ case 44: //QNEXT
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_RTF);
+ break;
+ case 47: //JICQ
+ packBuffer(&packet, capPalmJicq, 0xC);
+ packBuffer(&packet, "\x00\x01\x00\x05",4);
+ break;
+ case 49: //MIP
+ packBuffer(&packet, capMipClient, 0xC);
+ packBuffer(&packet, "\x00\x06\x00\x00",4);
+ break;
+ case 50: //Trillian Astra
+ packBuffer(&packet, capTrillian, 0x10);
+ packBuffer(&packet, capTrilCrypt, 0x10);
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_RTF|CAPF_AIM_FILE);
+ break;
+ case 51: //R&Q
+ packBuffer(&packet, capRAndQ, 9);
+ packBuffer(&packet, "\x01\x00\x06\x01",4);
+ break;
+ case 52: //NanoICQ
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_UTF);
+ break;
+ case 53: //IMadering
+ packBuffer(&packet, capIMadering, 0x10);
+ break;
+ case 54: // eternity : MirandaMobile
+ packBuffer(&packet, capMirandaMobile, 16);
+ break;
+ default:
+ {
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_SRV_RELAY);
+ }
+ break;
+ }
+ if(cID==2||cID==23||cID==24||cID==46) //qip caps
+ {
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_TYPING|CAPF_SRV_RELAY|CAPF_DIRECT|CAPF_ICQ_DEVIL|CAPF_UTF|CAPF_RTF|(gbXStatusEnabled?CAPF_XTRAZ:0)|CAPF_AIM_FILE);
+ if (bXStatus)
+ {
+ packBuffer(&packet, capXStatus[bXStatus-1], 0x10);
+ }
+ }
+ if(cID==10||cID>=6&&cID<=10||cID==16||cID==17||cID==20||cID==25||cID>=27&&cID<=40||cID==44||cID==45||cID==47||cID>=49&&cID<=52) //default caps
+ {
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_SRV_RELAY);
+ }
+ if(cID>=12&&cID<=15||cID==26) //icq lite group caps
+ {
+ AddCapabilitiesToBuffer((BYTE*)&packet, CAPF_TYPING|CAPF_SRV_RELAY|CAPF_DIRECT|CAPF_PUSH2TALK|CAPF_ICQ_DEVIL|CAPF_UTF|CAPF_RTF|(gbXStatusEnabled?CAPF_XTRAZ:0)|CAPF_XTRAZ_CHAT|CAPF_AIM_FILE|CAPF_VOICE_CHAT);
+ if (bXStatus)
+ {
+ packBuffer(&packet, capXStatus[bXStatus-1], 0x10);
+ }
+ }
+
+ { // store own client capabilities, and detect own client
+ DBCONTACTWRITESETTING dbcws;
+ dbcws.value.type = DBVT_BLOB;
+ dbcws.value.cpbVal = wAdditionalData+46;
+ dbcws.value.pbVal = packet.pData+20;
+ dbcws.szModule = gpszICQProtoName;
+ dbcws.szSetting = "CapBuf";
+ CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)NULL, (LPARAM)&dbcws);
+ }
+ if(gbCustomCapEnabled)
+ {
+ int i;
+ for (i = 0; i < lstCustomCaps->realCount; ++i)
+ packBuffer(&packet, ((ICQ_CUSTOMCAP *)lstCustomCaps->items[i])->caps, 0x10);
+ }
+ 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;
+ DWORD dwDirectCookie = rand() ^ (rand() << 16);
+ BYTE bXStatus = ICQGetContactXStatus(NULL);
+ char szMoodId[32];
+ WORD cbMoodId = 0;
+ WORD cbMoodData = 0;
+ DWORD dwFT1, dwFT2, dwFT3;
+
+ // Get status
+ wStatus = MirandaStatusToIcq(icqGoingOnlineStatus);
+
+ if (bXStatus && moodXStatus[bXStatus-1] != -1)
+ { // prepare mood id
+ null_snprintf(szMoodId, SIZEOF(szMoodId), "icqmood%d", moodXStatus[bXStatus-1]);
+ cbMoodId = strlennull(szMoodId);
+ cbMoodData = 8;
+ }
+
+ serverPacketInit(&packet, (WORD)(71 + cbMoodId + cbMoodData));
+ 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, (WORD)GetProtoVersion());
+ packDWord(&packet, dwDirectCookie); // DC Cookie
+ packDWord(&packet, WEBFRONTPORT); // Web front port
+ packDWord(&packet, CLIENTFEATURES); // Client features
+ SetTimeStamps(&dwFT1, &dwFT2, &dwFT3);
+ packDWord(&packet, dwFT1);
+ packDWord(&packet, dwFT2);
+ packDWord(&packet, dwFT3);
+ packWord(&packet, 0x0000); // Unknown
+ packTLVWord(&packet, 0x001F, 0x0000);
+
+ if (cbMoodId)
+ { // Pack mood data
+ packWord(&packet, 0x1D); // TLV 1D
+ packWord(&packet, (WORD)(cbMoodId + 4)); // TLV length
+ packWord(&packet, 0x0E); // Item Type
+ packWord(&packet, cbMoodId); // Flags + Item Length
+ packBuffer(&packet, szMoodId, cbMoodId); // Mood
+ }
+
+ sendServPacket(&packet);
+ }
+ {
+ LPSTR szClient = {0};
+ static DWORD dwFT1, dwFT2, dwFT3;
+ char szStrBuf[MAX_PATH];
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING dbcgs;
+ dbcgs.szModule = gpszICQProtoName;
+ dbcgs.szSetting = "CapBuf";
+ dbcgs.pValue = &dbv;
+ CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&dbcgs);
+ if (dbv.type == DBVT_BLOB)
+ {
+ char bClient=0;
+ WORD bufsize = dbv.cpbVal;
+ BYTE *buf = dbv.pbVal;
+ SetTimeStamps(&dwFT1, &dwFT2, &dwFT3);
+ szClient = detectUserClient(NULL, 0, GetProtoVersion(), dwFT1, dwFT2, dwFT3, 0, 0, 0, 0, buf, bufsize, &bClient, szStrBuf);
+ if (!szClient||szClient<0)
+ szClient = "Unknown";
+ ICQWriteContactSettingUtf(NULL, "MirVer", szClient);
+ }
+ }
+
+
+ /* 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, 98);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_READY);
+ packDWord(&packet, 0x00220001); // imitate ICQ 6 behaviour
+ packDWord(&packet, 0x0110161b);
+ packDWord(&packet, 0x00010004);
+ packDWord(&packet, 0x0110161b);
+ packDWord(&packet, 0x00130004);
+ packDWord(&packet, 0x0110161b);
+ packDWord(&packet, 0x00020001);
+ packDWord(&packet, 0x0110161b);
+ packDWord(&packet, 0x00030001);
+ packDWord(&packet, 0x0110161b);
+ packDWord(&packet, 0x00150001);
+ packDWord(&packet, 0x0110161b);
+ packDWord(&packet, 0x00040001);
+ packDWord(&packet, 0x0110161b);
+ packDWord(&packet, 0x00060001);
+ packDWord(&packet, 0x0110161b);
+ packDWord(&packet, 0x00090001);
+ packDWord(&packet, 0x0110161b);
+ packDWord(&packet, 0x000A0001);
+ packDWord(&packet, 0x0110161b);
+ packDWord(&packet, 0x000B0001);
+ packDWord(&packet, 0x0110161b);
+
+ sendServPacket(&packet);
+
+ NetLog_Server(" *** Yeehah, login sequence complete");
+
+ // login sequence is complete enter logged-in mode
+ info->bLoggedIn = 1;
+
+ // enable auto info-update routine
+ icq_EnableUserLookup(TRUE);
+
+ if (!info->isMigrating)
+ { /* Get Offline Messages Reqeust */
+ offline_message_cookie *ack;
+
+ ack = (offline_message_cookie*)SAFE_MALLOC(sizeof(offline_message_cookie));
+ if (ack)
+ {
+ DWORD dwCookie = AllocateCookie(CKT_OFFLINEMESSAGE, ICQ_MSG_CLI_REQ_OFFLINE, 0, ack);
+
+ serverPacketInit(&packet, 10);
+ packFNACHeaderFull(&packet, ICQ_MSG_FAMILY, ICQ_MSG_CLI_REQ_OFFLINE, 0, dwCookie);
+
+ sendServPacket(&packet);
+ }
+ else
+ icq_LogMessage(LOG_WARNING, "Failed to request offline messages. They may be received next time you log in.");
+
+ // Update our information from the server
+ sendOwnerInfoRequest();
+
+ // Request info updates on all contacts
+ icq_RescanInfoUpdate();
+
+ // Start sending Keep-Alive packets
+ StartKeepAlive(info);
+
+ 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 && !bNoStatusReply)
+ icq_sendSetAimAwayMsgServ(*szMsg);
+ LeaveCriticalSection(&modeMsgsMutex);
+ }
+ CheckSelfRemove();
+}
diff --git a/icqj_s7_sss_mod/fam_02location.c b/icqj_s7_sss_mod/fam_02location.c new file mode 100644 index 0000000..e9b3a1e --- /dev/null +++ b/icqj_s7_sss_mod/fam_02location.c @@ -0,0 +1,508 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static void handleLocationUserInfoReply(BYTE* buf, WORD wLen, DWORD dwCookie);
+
+extern const char* cliSpamBot;
+extern char* detectUserClient(HANDLE hContact, DWORD dwUin, WORD wVersion, DWORD dwFT1, DWORD dwFT2, DWORD dwFT3, DWORD dwOnlineSince, BYTE bDirectFlag, DWORD dwDirectCookie, DWORD dwWebPort, BYTE* caps, WORD wLen, BYTE* bClientId, char* szClientBuf);
+
+
+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
+ handleLocationUserInfoReply(pBuffer, wBufferLength, pSnacHeader->dwRef);
+ break;
+
+ case ICQ_ERROR:
+ {
+ WORD wError;
+ HANDLE hCookieContact;
+ fam15_cookie_data *pCookieData;
+
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ if (wError == 4)
+ {
+ if (FindCookie(pSnacHeader->dwRef, &hCookieContact, &pCookieData) && !ICQGetContactSettingUIN(hCookieContact) && pCookieData->bRequestType == REQUESTTYPE_PROFILE)
+ {
+ ICQBroadcastAck(hCookieContact, 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 char* AimApplyEncoding(char* pszStr, const char* pszEncoding)
+{ // decode encoding to ANSI only
+ if (pszStr && pszEncoding)
+ {
+ char *szEnc = strstr(pszEncoding, "charset=");
+
+ if (szEnc)
+ { // decode custom encoding to Utf-8
+ char* szStr = ApplyEncoding(pszStr, szEnc + 9);
+ // decode utf-8 to ansi
+ char *szRes = NULL;
+
+ SAFE_FREE(&pszStr);
+ utf8_decode(szStr, &szRes);
+ SAFE_FREE(&szStr);
+
+ return szRes;
+ }
+ }
+ return pszStr;
+}
+
+extern void extractMoodData(oscar_tlv_chain* pChain, char** pMood, int* cbMood);
+
+void handleLocationUserInfoReply(BYTE* buf, WORD wLen, DWORD dwCookie)
+{
+ HANDLE hContact;
+ DWORD dwUIN;
+ uid_str szUID;
+ WORD wTLVCount;
+ WORD wWarningLevel;
+ HANDLE hCookieContact;
+ WORD status;
+ WORD wStatusFlags;
+
+ 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;
+ }
+
+ ICQWriteContactSettingWord(hContact, "AOLWarningLevel", wWarningLevel); //maybe we display it somewhere later
+
+ if (!FindCookie(dwCookie, &hCookieContact, &pCookieData))
+ {
+ NetLog_Server("Error: Received unexpected away reply from %s", strUID(dwUIN, szUID));
+ return;
+ }
+
+ if (hContact != hCookieContact)
+ {
+ NetLog_Server("Error: Away reply Contact does not match Cookie Contact(0x%x != 0x%x)", hContact, hCookieContact);
+
+ ReleaseCookie(dwCookie); // This could be a bad idea, but I think it is safe
+ return;
+ }
+
+ switch (GetCookieType(dwCookie))
+ {
+ case 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);
+ }
+ break;
+ }
+
+ case CKT_CHECKSPAMBOT:
+ {
+ ReleaseCookie(dwCookie);
+
+ // Read user info TLVs
+ {
+ oscar_tlv_chain* pChain;
+ oscar_tlv* pTLV;
+ BYTE *tmp;
+ WORD wVersion = 0;
+ DWORD dwFT1 = 0, dwFT2 = 0, dwFT3 = 0;
+ DWORD dwOnlineSince;
+ BYTE nTCPFlag = 0;
+ DWORD dwDirectConnCookie = 0;
+ DWORD dwWebPort = 0;
+ BYTE* capBuf = NULL;
+ WORD capLen = 0;
+ char szStrBuf[MAX_PATH];
+ BYTE bClientId = 0;
+ char *szClient;
+ DWORD dwMemberSince;
+ WORD wIdleTimer;
+ DWORD dwIP = 0;
+ DWORD dwRealIP = 0;
+ DWORD dwPort = 0;
+ time_t tIdleTS = 0;
+
+
+ // Syntax check
+ if (wLen < 4)
+ return;
+
+ tmp = buf;
+ // Get general chain
+ if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
+ return;
+
+ if (dwUIN)
+ { // Get DC info TLV
+ pTLV = getTLV(pChain, 0x0C, 1);
+ if (pTLV && (pTLV->wLen >= 15))
+ {
+ BYTE* 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);
+ }
+ }
+ }
+ // Get Online Since TLV
+ dwOnlineSince = getDWordFromChain(pChain, 0x03, 1);
+
+ disposeChain(&pChain);
+
+ wLen -= (buf - tmp);
+
+ // Get extra chain
+ if (pChain = readIntoTLVChain(&buf, wLen, 2))
+ {
+ pTLV = getTLV(pChain, 0x05, 1);
+ if (pTLV && (pTLV->wLen > 0))
+ {
+ capBuf = pTLV->pData;
+ capLen = pTLV->wLen;
+ }
+ }
+
+ szClient = detectUserClient(hContact, dwUIN, wVersion, dwFT1, dwFT2, dwFT3, dwOnlineSince, nTCPFlag, dwDirectConnCookie, dwWebPort, capBuf, capLen, &bClientId, szStrBuf);
+
+ if (szClient == cliSpamBot)
+ {
+ if (DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ { // kill spammer
+ icq_DequeueUser(dwUIN);
+ AddToSpammerList(dwUIN);
+ if (ICQGetContactSettingByte(NULL, "PopupsSpamEnabled", 1))
+ ShowPopUpMsg(hContact, dwUIN, "Spambot Detected", "Contact deleted & further events blocked.", POPTYPE_SPAM);
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+
+ NetLog_Server("Contact %s deleted", strUID(dwUIN, szUID));
+ }
+ disposeChain(&pChain);
+ break;
+ }
+
+ // Get IP TLV
+ dwIP = getDWordFromChain(pChain, 0x0a, 1);
+
+ // Get Member Since TLV
+ dwMemberSince = getDWordFromChain(pChain, 0x05, 1);
+
+ // Get Idle timer TLV
+ wIdleTimer = getWordFromChain(pChain, 0x04, 1);
+ if (wIdleTimer)
+ {
+ time(&tIdleTS);
+ tIdleTS -= (wIdleTimer*60);
+ };
+
+
+ if (pTLV && (pTLV->wLen >= 4))
+ {
+ unsigned char* pBuffer;
+ pBuffer = pTLV->pData;
+ unpackWord(&pBuffer, &wStatusFlags);
+ unpackWord(&pBuffer, &status);
+ }
+
+ { // handle Xtraz status
+ char* moodData = NULL;
+ int moodSize = 0;
+
+ extractMoodData(pChain, &moodData, &moodSize);
+ handleXStatusCaps(hContact, capBuf, capLen, moodData, moodSize);
+ }
+
+ if(dwFT1)
+ ICQWriteContactSettingDword(hContact, "dwFT1", dwFT1);
+ if(dwFT2)
+ ICQWriteContactSettingDword(hContact, "dwFT2", dwFT2);
+ if(dwFT3)
+ ICQWriteContactSettingDword(hContact, "dwFT3", dwFT3);
+ if(capBuf)
+ { // store client capabilities
+ DBCONTACTWRITESETTING dbcws;
+ dbcws.value.type = DBVT_BLOB;
+ dbcws.value.cpbVal = capLen;
+ dbcws.value.pbVal = capBuf;
+ dbcws.szModule = gpszICQProtoName;
+ dbcws.szSetting = "CapBuf";
+ CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)hContact, (LPARAM)&dbcws);
+ }
+ if (pTLV && (pTLV->wLen >= 16))
+ { // handle Xtraz status
+ char* moodData = NULL;
+ int moodSize = 0;
+
+ extractMoodData(pChain, &moodData, &moodSize);
+ handleXStatusCaps(hContact, pTLV->pData, pTLV->wLen, moodData, moodSize);
+ }
+ ICQWriteContactSettingDword(hContact, "LogonTS", dwOnlineSince);
+ if (dwMemberSince)
+ ICQWriteContactSettingDword(hContact, "MemberTS", dwMemberSince);
+ if(dwUIN)
+ {
+ ICQWriteContactSettingDword(hContact, "DirectCookie", dwDirectConnCookie);
+ ICQWriteContactSettingByte(hContact, "DCType", (BYTE)nTCPFlag);
+ ICQWriteContactSettingWord(hContact, "UserPort", (WORD)(dwPort & 0xffff));
+ if(wVersion)
+ ICQWriteContactSettingWord(hContact, "Version", wVersion);
+ }
+ if (szClient != (char*)-1)
+ {
+ ICQWriteContactSettingUtf(hContact, "MirVer", szClient);
+ ICQWriteContactSettingByte(hContact, "ClientID", bClientId);
+ ICQWriteContactSettingDword(hContact, "IP", dwIP);
+ ICQWriteContactSettingDword(hContact, "RealIP", dwRealIP);
+ }
+ if(status && ICQGetContactSettingWord(hContact, "Status", 0) == ID_STATUS_OFFLINE)
+ {
+ ICQWriteContactSettingWord(hContact, "Status", (WORD)IcqStatusToMiranda(status));
+ NetLog_Server("%s changed status to %s (v%d).", strUID(dwUIN, szUID),
+ MirandaStatusToString(IcqStatusToMiranda(status)), wVersion);
+ }
+ if (!wIdleTimer)
+ {
+ DWORD dw = ICQGetContactSettingDword(hContact, "IdleTS", 0);
+ ICQWriteContactSettingDword(hContact, "OldIdleTS", dw);
+ }
+ ICQWriteContactSettingDword(hContact, "IdleTS", tIdleTS);
+
+
+ // Free TLV chain
+ disposeChain(&pChain);
+
+
+ }
+ break;
+ }
+
+ default: // away message
+ {
+ 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);
+ }
+ break;
+ }
+ }
+}
diff --git a/icqj_s7_sss_mod/fam_03buddy.c b/icqj_s7_sss_mod/fam_03buddy.c new file mode 100644 index 0000000..b782bce --- /dev/null +++ b/icqj_s7_sss_mod/fam_03buddy.c @@ -0,0 +1,824 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 50 $
+// Last change on : $Date: 2007-08-28 02:57:00 +0300 (Вт, 28 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Handles packets from Buddy family
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+static void handleUserOffline(BYTE* buf, WORD wPackLen);
+static void handleUserOnline(BYTE* buf, WORD wPackLen, serverthread_info* info);
+static void handleReplyBuddy(BYTE* buf, WORD wPackLen);
+static void handleNotifyRejected(BYTE* buf, WORD wPackLen);
+
+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, BYTE bDirectFlag, DWORD dwDirectCookie, DWORD dwWebPort, BYTE* caps, WORD wLen, BYTE* bClientId, char* szClientBuf);
+
+
+void handleBuddyFam(unsigned char* pBuffer, WORD wBufferLength, snac_header* pSnacHeader, serverthread_info *info)
+{
+ switch (pSnacHeader->wSubtype)
+ {
+ case ICQ_USER_ONLINE:
+ handleUserOnline(pBuffer, wBufferLength, info);
+ 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;
+ }
+}
+
+
+
+void extractMoodData(oscar_tlv_chain* pChain, char** pMood, int* cbMood)
+{
+ oscar_tlv* tlv = getTLV(pChain, 0x1D, 1);
+ int len = 0;
+ char* data;
+
+ if (tlv)
+ {
+ len = tlv->wLen;
+ data = tlv->pData;
+ }
+
+ while (len >= 4)
+ { // parse online message items one by one
+ WORD itemType = data[0] << 8 | data[1];
+ BYTE itemLen = data[3];
+
+ // just some validity check
+ if (itemLen + 4 > len)
+ itemLen = len - 4;
+
+ if (itemType == 0x0E)
+ { // mood data
+ *pMood = data + 4;
+ *cbMood = itemLen;
+ }
+ data += itemLen + 4;
+ len -= itemLen + 4;
+ }
+}
+
+
+// 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, serverthread_info* info)
+{
+ HANDLE hContact;
+ DWORD dwPort = 0;
+ DWORD dwRealIP = 0;
+ DWORD dwIP = 0;
+ DWORD dwUIN;
+ uid_str szUID;
+ DWORD dwDirectConnCookie = 0;
+ DWORD dwWebPort = 0;
+ DWORD dwFT1 = 0, dwFT2 = 0, dwFT3 = 0;
+ LPSTR szClient = {0};
+ BYTE bClientId = 0;
+ WORD wVersion = 0;
+ WORD wTLVCount;
+ WORD wWarningLevel;
+ WORD wStatusFlags;
+ WORD wStatus;
+ BYTE nTCPFlag = 0;
+ DWORD dwOnlineSince;
+ DWORD dwMemberSince;
+ WORD wIdleTimer;
+ 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;
+
+ // Get Class word
+ wClass = getWordFromChain(pChain, 0x01, 1);
+
+ 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
+ {
+ // This client doesnt want DCs
+ }
+
+ // 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
+ {
+ if (wClass & CLASS_AWAY)
+ wStatus = ID_STATUS_AWAY;
+ else
+ wStatus = ID_STATUS_ONLINE;
+
+ wStatusFlags = 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 Member Since TLV
+ dwMemberSince = getDWordFromChain(pChain, 0x05, 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* 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 = (BYTE*)_alloca(capLen + 0x10);
+
+ capLen = 0; // we need to recount that
+
+ if (pTLV && (pTLV->wLen >= 16))
+ { // copy classic Capabilities
+ char* cData = pTLV->pData;
+ int cLen = pTLV->wLen;
+
+ while (cLen)
+ { // ohh, those damned AOL updates.... they broke it again
+ if (!MatchCap(capBuf, capLen, (capstr*)cData, 0x10))
+ { // not there, add
+ memcpy(pCap, cData, 0x10);
+ capLen += 0x10;
+ pCap += 0x10;
+ }
+ cData += 0x10;
+ cLen -= 0x10;
+ }
+ }
+
+ 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)
+ {
+ tmp[2] = capNew[0];
+ tmp[3] = capNew[1];
+
+ capNew += 2;
+
+ if (!MatchCap(capBuf, capLen, &tmp, 0x10))
+ { // not present, add
+ memcpy(pCap, tmp, 0x10);
+ pCap += 0x10;
+ capLen += 0x10;
+ }
+ }
+ }
+ AddCapabilitiesFromBuffer(hContact, capBuf, capLen);
+ }
+ else
+ { // no capability
+ NetLog_Server("No capability info TLVs");
+ }
+
+ { // handle Xtraz status
+ char* moodData = NULL;
+ int moodSize = 0;
+
+ extractMoodData(pChain, &moodData, &moodSize);
+ handleXStatusCaps(hContact, capBuf, capLen, moodData, moodSize);
+ }
+
+
+ ICQWriteContactSettingDword(hContact, "dwFT1", dwFT1);
+ ICQWriteContactSettingDword(hContact, "dwFT2", dwFT2);
+ ICQWriteContactSettingDword(hContact, "dwFT3", dwFT3);
+
+ { // store client capabilities
+ DBCONTACTWRITESETTING dbcws;
+ dbcws.value.type = DBVT_BLOB;
+ dbcws.value.cpbVal = capLen;
+ dbcws.value.pbVal = capBuf;
+ dbcws.szModule = gpszICQProtoName;
+ dbcws.szSetting = "CapBuf";
+ CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)hContact, (LPARAM)&dbcws);
+ }
+
+ szClient = detectUserClient(hContact, dwUIN, wVersion, dwFT1, dwFT2, dwFT3, dwOnlineSince, nTCPFlag, 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
+ char* moodData = NULL;
+ int moodSize = 0;
+
+ extractMoodData(pChain, &moodData, &moodSize);
+ handleXStatusCaps(hContact, pTLV->pData, pTLV->wLen, moodData, moodSize);
+ }
+ }
+ }
+
+ // Free TLV chain
+ disposeChain(&pChain);
+ }
+
+ // Save contacts details in database
+ if (hContact != NULL)
+ {
+ if (szClient == 0)
+ szClient = ICQTranslateUtfStatic("Unknown", szStrBuf, MAX_PATH); // if no detection, set uknown
+ if(szClient != (char*)-1 && (bLogClientChangeHistory || bLogClientChangeFile))
+ {
+ LPSTR oldMirVer = {0};
+ char string[256];
+ BOOL changed = FALSE;
+ oldMirVer = (LPSTR)UniGetContactSettingUtf(hContact, gpszICQProtoName, "MirVer", "");
+ if (!oldMirVer || strcmp(oldMirVer, szClient))
+ changed = TRUE;
+ if(changed)
+ {
+ if(oldMirVer)
+ {
+ strcpy(string, oldMirVer);
+ strcat(string, ICQTranslateUtf(" changed to "));
+ }
+ else
+ strcpy(string, ICQTranslateUtf("Client changed to "));
+ strcat(string, szClient);
+ {
+ CHECKCONTACT chk = {0};
+ chk.dwUin=dwUIN;
+ chk.hContact=hContact;
+ chk.PSD=-1;
+ chk.popup=chk.logtofile=chk.historyevent=chk.nottmpcontact=TRUE;
+ chk.icqeventtype=ICQEVENTTYPE_CLIENT_CHANGE;
+ chk.popuptype=POPTYPE_CLIENT_CHANGE;
+ chk.dbeventflag=DBEF_READ;
+ chk.msg=string;
+ CheckContact(chk);
+ }
+ }
+ }
+ ICQWriteContactSettingDword(hContact, "LogonTS", dwOnlineSince);
+ if (dwMemberSince)
+ ICQWriteContactSettingDword(hContact, "MemberTS", dwMemberSince);
+ if (dwUIN)
+ { // on AIM these are not used
+ 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);
+ ICQWriteContactSettingDword(hContact, "IP", dwIP);
+ ICQWriteContactSettingDword(hContact, "RealIP", dwRealIP);
+ }
+ else
+ { // if not first notification only write significant information
+ if (dwIP)
+ ICQWriteContactSettingDword(hContact, "IP", dwIP);
+ if (dwRealIP)
+ ICQWriteContactSettingDword(hContact, "RealIP", dwRealIP);
+
+ }
+ 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)
+ {
+ DWORD dwUpdateThreshold = ICQGetContactSettingByte(NULL, "InfoUpdate", UPDATE_THRESHOLD)*3600*24;
+
+ if ((time(NULL) - ICQGetContactSettingDword(hContact, "InfoTS", 0)) > dwUpdateThreshold)
+ icq_QueueUser(hContact);
+ }
+ }
+ if (hContact == NULL)
+ {
+ if (szClient != (char*)-1)
+ ICQWriteContactSettingUtf(NULL, "MirVer", szClient);
+ }
+
+ // And a small log notice...
+ NetLog_Server("%s changed status to %s (v%d).", strUID(dwUIN, szUID),
+ MirandaStatusToString(IcqStatusToMiranda(wStatus)), wVersion);
+
+
+
+ if (( int )szClient != -1 )
+ if (strcmp(szClient, "Unknown") == 0)
+ {
+ if (ICQGetContactSettingByte(NULL, "KillUnknown", 0) && DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ {
+ icq_DequeueUser(dwUIN);
+ AddToSpammerList(dwUIN);
+ if (bUnknownPopUp)
+ ShowPopUpMsg(hContact, dwUIN, "Unknown Detected", "Contact deleted & further events blocked.", POPTYPE_UNKNOWN);
+// icq_sendRemoveContact(dwUIN, NULL);
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+
+ NetLog_Server("Contact %u deleted", dwUIN);
+ }
+ }
+
+ if (szClient == cliSpamBot||szClient == "Virus")
+ {
+ if (ICQGetContactSettingByte(NULL, "KillSpambots", DEFAULT_KILLSPAM_ENABLED) && DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ { // kill spammer
+ icq_DequeueUser(dwUIN);
+ AddToSpammerList(dwUIN);
+ if (bSpamPopUp)
+ ShowPopUpMsg(hContact, dwUIN, "Spambot Detected", "Contact deleted & further events blocked.", POPTYPE_SPAM);
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+
+ NetLog_Server("Contact %u deleted", dwUIN);
+ }
+ }
+ //inv4inv(hContact, 2);//delete from invisible list
+}
+
+
+
+static void handleUserOffline(BYTE *buf, WORD wLen)
+{
+ HANDLE hContact;
+ DWORD dwUIN;
+ uid_str szUID;
+
+ do {
+ WORD wTLVCount;
+
+ // Unpack the sender's user ID
+ if (!unpackUID(&buf, &wLen, &dwUIN, &szUID)) return;
+
+ // Warning level?
+ buf += 2;
+
+ // TLV Count
+ unpackWord(&buf, &wTLVCount);
+ wLen -= 4;
+
+ // Skip the TLV chain
+ while (wTLVCount && wLen >= 4)
+ {
+ WORD wTLVType;
+ WORD wTLVLen;
+
+ unpackWord(&buf, &wTLVType);
+ unpackWord(&buf, &wTLVLen);
+ wLen -= 4;
+
+ // stop parsing overflowed packet
+ if (wTLVLen > wLen) return;
+
+ buf += wTLVLen;
+ wLen -= wTLVLen;
+ wTLVCount--;
+ }
+
+ // Determine contact
+ hContact = HContactFromUID(dwUIN, szUID, NULL);
+
+ // Skip contacts that are not already on our list or are already offline
+ if (hContact != INVALID_HANDLE_VALUE && (ICQGetContactStatus(hContact) != ID_STATUS_OFFLINE||CheckContactCapabilities(hContact, WAS_FOUND)))
+ {
+ 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);
+ // Reset DC status
+ ICQWriteContactSettingByte(hContact, "DCStatus", 0);
+ // clear Xtraz status
+ handleXStatusCaps(hContact, NULL, 0, NULL, 0);
+ icq_GetUserStatus(hContact,2);
+ }
+ } while (wLen >= 1);
+}
+
+
+
+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));
+}
+/*
+void inv4inv(HANDLE hContact, int mode)//horrible realization xD, i'll optimize it later
+{
+ if(!ICQGetContactSettingByte(NULL, "Inv4Inv", DEFAULT_INV4INV_DISABLED))
+ return;
+
+
+ if((invis_for(0,hContact))&&
+ (DBGetContactSettingWord(hContact, gpszICQProtoName, "invis4inv", 0)==0)&&
+ (DBGetContactSettingWord(hContact,gpszICQProtoName,"ApparentMode",0)==ID_STATUS_ONLINE))
+ return;
+
+ switch(mode)
+ {
+
+ case 1:
+ if((DBGetContactSettingWord(hContact, gpszICQProtoName, "Status", 0)==ID_STATUS_OFFLINE)&&
+ (DBGetContactSettingWord(hContact, gpszICQProtoName, "invis4inv", 0)==0))
+ {
+ CallContactService(hContact, PSS_SETAPPARENTMODE, (DBGetContactSettingWord(hContact, gpszICQProtoName,"ApparentMode", 0)==ID_STATUS_OFFLINE)?0:ID_STATUS_OFFLINE,0);
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "invis4inv", 1);
+ }
+ break;
+
+ case 2:
+ if((DBGetContactSettingWord(hContact, gpszICQProtoName, "invis4inv", 0)==1))
+ {
+ CallContactService(hContact, PSS_SETAPPARENTMODE, (DBGetContactSettingWord(hContact, gpszICQProtoName,"ApparentMode", 0)==ID_STATUS_OFFLINE)?0:ID_STATUS_OFFLINE,0);
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "invis4inv", 0);
+ }
+ break;
+
+ case 3: //find better way
+ {
+ HANDLE hContact;
+ int i = 0,r = 0,x = 0;
+ hContact = ICQFindFirstContact();
+
+ while(hContact)
+ {
+ if((DBGetContactSettingWord(hContact, gpszICQProtoName, "Status", 0)==ID_STATUS_OFFLINE)&&
+ DBGetContactSettingWord(hContact, gpszICQProtoName, "invis4inv", 0)==0)
+ {
+ CallContactService(hContact, PSS_SETAPPARENTMODE, (DBGetContactSettingWord(hContact, gpszICQProtoName,"ApparentMode", 0)==ID_STATUS_OFFLINE)?0:ID_STATUS_OFFLINE,0);
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "invis4inv", 1);
+
+ NetLog_Server("Set %s invisible (inv4inv startup thread)",NickFromHandle(hContact));
+ i++;
+ }
+ if(i==10||i==20||i==30||i==40||i==50)
+ {
+ Sleep(25000); //wait
+ }
+ if(i>50)
+ {
+ Sleep(50000); //wait more
+ }
+ if(i==60||i==65||i==75||i==90)
+ {
+ Sleep(25000);
+ }
+ if(i>90)
+ {
+ Sleep(4000);
+ }
+ hContact = ICQFindNextContact(hContact);
+ }
+ NetLog_Server("Finished inv4inv startup process");
+ MessageBox(0,"inv4inv startup thread finished!","Warning",MB_OK);
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+void inv4invCleanUp()
+{
+ if(!ICQGetContactSettingByte(NULL, "Inv4Inv", 0))
+ {
+ HANDLE hContact;
+ int i = 0;
+ hContact = ICQFindFirstContact();
+
+ while(hContact)
+ {
+ if(DBGetContactSettingWord(hContact, gpszICQProtoName, "invis4inv", 0))
+ {
+ CallContactService(hContact, PSS_SETAPPARENTMODE, (DBGetContactSettingWord(hContact, gpszICQProtoName,"ApparentMode", 0)==ID_STATUS_OFFLINE)?0:ID_STATUS_OFFLINE,0);
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "invis4inv", 0);
+
+ NetLog_Server("Set %s back (inv4inv CleanUp)",NickFromHandle(hContact));
+ i++;
+ }
+ if(i==10)
+ {
+ Sleep(20000);
+ i = 0;
+ }
+ hContact = ICQFindNextContact(hContact);
+ }
+ NetLog_Server("Finished inv4inv CleanUp process");
+ MessageBox(0,"inv4inv CleanUp finished!","Warning",MB_OK);
+ }
+}
+*/
+void CheckSelfRemove()
+{
+ if(!DBGetContactSettingByte(NULL,gpszICQProtoName,"PopSelfRem", 0)&&!DBGetContactSettingByte(NULL,gpszICQProtoName,"LogSelfRem", 0))
+ return;
+ {
+ HANDLE hContact;
+ DWORD uin;
+ hContact = ICQFindFirstContact();
+ uin = DBGetContactSettingDword(hContact, gpszICQProtoName,"UIN",0);
+
+ while(hContact)
+ {
+ if (gbSsiEnabled && !ICQGetContactSettingWord(hContact, "ServerId", 0) && !ICQGetContactSettingWord(hContact, "SrvIgnoreId", 0)&&
+ !DBGetContactSettingByte(hContact, gpszICQProtoName, "CheckSelfRemove", 0))
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=uin;
+ chk.dbeventflag=DBEF_READ;
+ chk.icqeventtype=ICQEVENTTYPE_SELF_REMOVE;
+ chk.logtofile=chk.popup=chk.historyevent=TRUE;
+ chk.msg="has removed himself from your Serverlist!";
+ chk.popuptype=POPTYPE_SELFREMOVE;
+ chk.PSD=-1;
+ CheckContact(chk);
+ DBWriteContactSettingByte(hContact, gpszICQProtoName, "CheckSelfRemove", 1);
+ }
+
+ hContact = ICQFindNextContact(hContact);
+ }
+ NetLog_Server("Finished CheckSelfRemove thread");
+ // MessageBox(0,"Finished CheckSelfRemove thread!","Warning",MB_OK);
+ }
+
+
+}
+
+void CheckSelfRemoveShutdown()//exclude currently added contacts (not serverside) from beeing detected
+{
+ if(!DBGetContactSettingByte(NULL,gpszICQProtoName,"PopSelfRem", 0)&&!DBGetContactSettingByte(NULL,gpszICQProtoName,"LogSelfRem", 0))
+ return;
+ {
+ HANDLE hContact;
+ hContact = ICQFindFirstContact();
+
+ while(hContact)
+ {
+ if (gbSsiEnabled && !ICQGetContactSettingWord(hContact, "ServerId", 0) && !ICQGetContactSettingWord(hContact, "SrvIgnoreId", 0)&&
+ !DBGetContactSettingByte(hContact, gpszICQProtoName, "CheckSelfRemove", 0))
+ DBWriteContactSettingByte(hContact, gpszICQProtoName, "CheckSelfRemove", 1);
+
+ hContact = ICQFindNextContact(hContact);
+ }
+ NetLog_Server("Finished CheckSelfRemoveShutdown thread");
+ // MessageBox(0,"Finished CheckSelfRemove thread!","Warning",MB_OK);
+ }
+
+
+}
\ No newline at end of file diff --git a/icqj_s7_sss_mod/fam_04message.c b/icqj_s7_sss_mod/fam_04message.c new file mode 100644 index 0000000..1ac4b7c --- /dev/null +++ b/icqj_s7_sss_mod/fam_04message.c @@ -0,0 +1,3386 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 51 $
+// Last change on : $Date: 2007-08-30 23:46:51 +0300 (Чт, 30 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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 dwMsgID1, DWORD dwMsgID2, DWORD dwRef);
+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 dwMsgID1, DWORD dwMsgID2, DWORD dwRef);
+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 handleOffineMessagesReply(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);
+static void handleRecvServMsgContacts(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwID1, DWORD dwID2, WORD wCommand);
+static BYTE OfflineMessagesReceived = 0;
+
+
+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_OFFLINE_REPLY: // SNAC(4, 0x17) Offline Messages response
+ handleOffineMessagesReply(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 setMsgChannelParams(WORD wChan, DWORD dwFlags)
+{
+ icq_packet packet;
+
+ // Set message parameters for channel wChan (CLI_SET_ICBM_PARAMS)
+ serverPacketInit(&packet, 26);
+ packFNACHeader(&packet, ICQ_MSG_FAMILY, ICQ_MSG_CLI_SETPARAMS);
+ packWord(&packet, wChan); // Channel
+ packDWord(&packet, dwFlags); // 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 handleReplyICBM(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{ // we don't care about the stuff, just change the params
+ DWORD dwFlags = 0x00000303;
+
+#ifdef DBG_CAPHTML
+ dwFlags |= 0x00000400;
+#endif
+#ifdef DBG_CAPMTN
+ dwFlags |= 0x00000008;
+#endif
+ // Set message parameters for all channels (imitate ICQ 6)
+ setMsgChannelParams(0x0000, dwFlags);
+}
+
+
+
+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;
+
+ if (wLen < 11)
+ { // just do some basic packet checking
+ NetLog_Server("Error: Malformed message thru server");
+ return;
+ }
+
+ // 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 (!unpackUID(&buf, &wLen, &dwUin, &szUID)) return;
+
+ if (dwUin && IsOnSpammerList(dwUin))
+ {
+ NetLog_Server("Ignored Message from known Spammer");
+ return;
+ }
+
+ if (wLen < 4)
+ { // just do some basic packet checking
+ NetLog_Server("Error: Malformed message thru server");
+ 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, dwRef);
+ break;
+
+ case 2: // Encapsulated messages
+ handleRecvServMsgType2(buf, wLen, dwUin, szUID, dwID1, dwID2);
+ break;
+
+ case 4: // Typed messages
+ handleRecvServMsgType4(buf, wLen, dwUin, szUID, dwID1, dwID2, dwRef);
+ break;
+
+ default:
+ NetLog_Server("Unknown format message thru server - Ref %u, Type: %u, UID: %s", dwRef, wMessageFormat, strUID(dwUin, szUID));
+ break;
+
+ }
+}
+
+
+
+static char* convertMsgToUserSpecificUtf(HANDLE hContact, const char* szMsg)
+{
+ WORD wCP = ICQGetContactSettingWord(hContact, "CodePage", gwAnsiCodepage);
+ char* usMsg = NULL;
+
+ if (wCP != CP_ACP)
+ usMsg = ansi_to_utf8_codepage(szMsg, wCP);
+
+ return usMsg;
+}
+
+
+
+static void handleRecvServMsgType1(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef)
+{
+ WORD wTLVType;
+ WORD wTLVLen;
+ BYTE* pMsgTLV;
+ HANDLE hContact;
+
+ hContact = HContactFromUID(dwUin, szUID, 0);
+ if (wLen < 4)
+ { // just perform basic structure check
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ NetLog_Server("Message (format %u) - Ignoring empty message", 1);
+ return;
+ }
+
+ // Unpack the first TLV(2)
+ unpackTypedTLV(buf, wLen, 2, &wTLVType, &wTLVLen, &pMsgTLV);
+ NetLog_Server("Message (format %u) - UID: %s", 1, strUID(dwUin, szUID));
+
+ // It must be TLV(2)
+ if (wTLVType == 2)
+ {
+ BYTE *pDataBuf = pMsgTLV;
+ 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 (can be fragmented)
+
+ if (pChain)
+ {
+ oscar_tlv* pMessageTLV;
+ oscar_tlv* pCapabilityTLV;
+ WORD wMsgPart = 1;
+
+ // 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.");
+ }
+
+ { // Parse the message parts, usually only one 0x0101 TLV containing the message,
+ // but in some cases there can be more 0x0101 TLVs containing message parts in
+ // different encodings (just like the new format of Offline Messages).
+ DWORD dwRecvTime;
+ char* szMsg = NULL;
+ HANDLE hContact;
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+ int bAdded;
+
+ hContact = HContactFromUID(dwUin, szUID, &bAdded);
+
+ while (pMessageTLV = getTLV(pChain, 0x0101, wMsgPart))
+ { // Loop thru all message parts
+ if (pMessageTLV->wLen > 4)
+ {
+ WORD wMsgLen;
+ BYTE* pMsgBuf;
+ WORD wEncoding;
+ WORD wCodePage;
+ char* szMsgPart = NULL;
+ int bMsgPartUnicode = FALSE;
+
+ // 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) - Part %d: Encoding is 0x%X, page is 0x%X", wMsgPart, wEncoding, wCodePage);
+
+ switch (wEncoding)
+ {
+
+ case 2: // UCS-2
+ {
+ WCHAR* usMsgPart = (WCHAR*)SAFE_MALLOC(wMsgLen + 2);
+
+ unpackWideString(&pMsgBuf, usMsgPart, wMsgLen);
+ usMsgPart[wMsgLen/sizeof(WCHAR)] = 0;
+
+ szMsgPart = make_utf8_string(usMsgPart);
+ if (!IsUSASCII(szMsgPart, strlennull(szMsgPart)))
+ bMsgPartUnicode = TRUE;
+ SAFE_FREE(&usMsgPart);
+
+ break;
+ }
+
+ case 0: // us-ascii
+ case 3: // ANSI
+ default:
+ {
+ // Copy the message text into a new proper string.
+ szMsgPart = (char *)SAFE_MALLOC(wMsgLen + 1);
+ memcpy(szMsgPart, pMsgBuf, wMsgLen);
+ szMsgPart[wMsgLen] = '\0';
+
+ break;
+ }
+ }
+ // Check if the new part is compatible with the message
+ if (!pre.flags && bMsgPartUnicode)
+ { // make the resulting message utf-8 encoded - need to append utf-8 encoded part
+ if (szMsg)
+ { // not necessary to convert - appending first part, only set flags
+ char* szUtfMsg = ansi_to_utf8_codepage(szMsg, ICQGetContactSettingWord(hContact, "CodePage", gwAnsiCodepage));
+
+ SAFE_FREE(&szMsg);
+ szMsg = szUtfMsg;
+ }
+ pre.flags = PREF_UTF;
+ }
+ if (!bMsgPartUnicode && pre.flags == PREF_UTF)
+ { // convert message part to utf-8 and append
+ char* szUtfPart = ansi_to_utf8_codepage(szMsgPart, ICQGetContactSettingWord(hContact, "CodePage", gwAnsiCodepage));
+
+ SAFE_FREE(&szMsgPart);
+ szMsgPart = szUtfPart;
+ }
+ // Append the new message part
+ szMsg = (char*)SAFE_REALLOC(szMsg, strlennull(szMsg) + strlennull(szMsgPart) + 1);
+
+ strcat(szMsg, szMsgPart);
+ SAFE_FREE(&szMsgPart);
+ }
+ wMsgPart++;
+ }
+ if (strlennull(szMsg))
+ { /// TODO: Add inteligent HTML detection & stripping - support for CAPF_HTML
+ if (!dwUin)
+ { // strip HTML formating from AIM message
+ szMsg = EliminateHtml(szMsg, strlennull(szMsg));
+ }
+
+ 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 = usMsg;
+ pre.flags = PREF_UTF;
+ }
+ }
+
+ dwRecvTime = (DWORD)time(NULL);
+
+ { // Check if the message was received as offline
+ offline_message_cookie *cookie;
+
+ if (!(dwRef & 0x80000000) && FindCookie(dwRef, NULL, &cookie))
+ {
+ WORD wTimeTLVType, wTimeTLVLen;
+ BYTE *pTimeTLV;
+
+ cookie->nMessages++;
+
+ unpackTypedTLV(buf, wLen, 0x16, &wTimeTLVType, &wTimeTLVLen, &pTimeTLV);
+ if (pTimeTLV && wTimeTLVType == 0x16 && wTimeTLVLen == 4)
+ { // found Offline timestamp
+ BYTE *pBuf = pTimeTLV;
+ char *szTime;
+
+ unpackDWord(&pBuf, &dwRecvTime);
+ // TODO: add some checking
+ szTime = asctime(localtime(&dwRecvTime));
+ szTime[24] = '\0'; // remove new line
+ NetLog_Server("Message (format %u) - Offline timestamp is %s", 1, szTime);
+ }
+ SAFE_FREE(&pTimeTLV);
+ }
+ }
+ // Create and send the message event
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.timestamp = dwRecvTime;
+ pre.szMessage = (char *)szMsg;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+
+ NetLog_Server("Message (format 1) received");
+
+ // Save tick value
+ ICQWriteContactSettingDword(ccs.hContact, "TickTS", time(NULL) - (dwMsgID1/1000));
+ }
+ else
+ {
+ NetLog_Server("Message (format %u) - Ignoring empty message", 1);
+ }
+ SAFE_FREE(&szMsg);
+ }
+
+ // 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);
+ }
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ if(!OfflineMessagesReceived)
+ chk.PSD=-1;
+ CheckContact(chk);
+ }
+ SAFE_FREE(&pMsgTLV);
+}
+
+
+
+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;
+ HANDLE hContact = HContactFromUIN(dwUin, 0);
+
+
+ if (wLen < 4)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+ return;
+ }
+
+ // Unpack the first TLV(5)
+ unpackTypedTLV(buf, wLen, 5, &wTLVType, &wTLVLen, &pDataBuf);
+ NetLog_Server("Message (format %u) - 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;
+
+ if (wTLVLen < 26)
+ { // just check if all basic data is there
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+
+ return;
+ }
+
+ 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
+
+ // 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); // Message Capability
+ wTLVLen -= 16;
+
+ if (CompareGUIDs(q1,q2,q3,q4, MCAP_SRV_RELAY_FMT))
+ { // we surely have at least 4 bytes for TLV chain
+
+ if (wCommand == 1)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+ NetLog_Server("Cannot handle abort messages yet... :(");
+ SAFE_FREE(&pBuf);
+ return;
+ }
+
+ if (wTLVLen < 4)
+ { // just check if at least one tlv is there
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+ SAFE_FREE(&pBuf);
+ return;
+ }
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ SAFE_FREE(&pBuf);
+ return;
+ }
+
+ // 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 if (CompareGUIDs(q1,q2,q3,q4, MCAP_REVERSE_DC_REQ))
+ { // Handle reverse DC request
+ if (wCommand == 1)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+
+ NetLog_Server("Cannot handle abort messages yet... :(");
+ SAFE_FREE(&pBuf);
+ return;
+ }
+ if (wTLVLen < 4)
+ { // just check if at least one tlv is there
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+ SAFE_FREE(&pBuf);
+ return;
+ }
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ SAFE_FREE(&pBuf);
+ return;
+ }
+ 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;
+ WORD wVersion;
+ BYTE bMode;
+ HANDLE hContact;
+
+ unpackLEDWord(&buf, &dwUin);
+
+ hContact = HContactFromUIN(dwUin, 0);
+ 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)
+ {
+ reverse_cookie *pCookie = (reverse_cookie*)SAFE_MALLOC(sizeof(reverse_cookie));
+
+ unpackLEDWord(&buf, (DWORD*)&pCookie->ft);
+ pCookie->pMessage.dwMsgID1 = dwID1;
+ pCookie->pMessage.dwMsgID2 = dwID2;
+
+ OpenDirectConnection(hContact, DIRECTCONN_REVERSE, (void*)pCookie);
+ }
+ 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 if (CompareGUIDs(q1,q2,q3,q4, MCAP_FILE_TRANSFER))
+ { // this is an OFT packet
+ handleRecvServMsgOFT(pDataBuf, wTLVLen, dwUin, szUID, dwID1, dwID2, wCommand);
+ }
+ else if (CompareGUIDs(q1,q2,q3,q4, MCAP_CONTACTS))
+ { // this is Contacts Transfer
+ handleRecvServMsgContacts(pDataBuf, wTLVLen, dwUin, szUID, dwID1, dwID2, wCommand);
+ }
+ else // here should be detection of extra data streams (Xtraz)
+ {
+ NetLog_Server("Unknown Message Format Capability");
+ }
+ }
+ else
+ {
+ NetLog_Server("Unsupported TLV (%u) in message (format %u)", wTLVType, 2);
+ }
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ }
+ 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;
+
+
+
+ if (wLen < 2)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+ return;
+ }
+
+ 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;
+
+ if (wLen < 31)
+ { // just check if we have data to work with
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+ return;
+ }
+
+ 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;
+
+ if (wLen < 20)
+ { // check if there is everything that should be there
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+ return;
+ }
+
+ 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:
+ { // TODO: this type is deprecated
+ 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:
+ {
+ message_ack_params pMsgAck = {0};
+
+ pMsgAck.bType = MAT_SERVER_ADVANCED;
+ pMsgAck.dwUin = dwUin;
+ pMsgAck.dwMsgID1 = dwID1;
+ pMsgAck.dwMsgID2 = dwID2;
+ pMsgAck.wCookie = wCookie;
+ pMsgAck.msgType = bMsgType;
+ pMsgAck.bFlags = bFlags;
+ handleMessageTypes(dwUin, time(NULL), dwID1, dwID2, wCookie, wVersion, bMsgType, bFlags, wAckType, tlv->wLen - 53, wMsgLen, pDataBuf, FALSE, &pMsgAck);
+ 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)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+ 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)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=22;
+ CheckContact(chk);
+ 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);
+ }
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ }
+}
+
+
+
+void parseServerGreeting(BYTE* pDataBuf, WORD wLen, WORD wMsgLen, DWORD dwUin, BYTE bFlags, WORD wStatus, WORD wCookie, WORD wAckType, DWORD dwID1, DWORD dwID2, WORD wVersion)
+{
+ DWORD dwLengthToEnd;
+ DWORD dwDataLen;
+ int typeId;
+ WORD wFunction;
+
+ NetLog_Server("Parsing Greeting message through server");
+
+ pDataBuf += wMsgLen; // Message
+ wLen -= wMsgLen;
+
+ // Message plugin identification
+ if (!unpackPluginTypeId(&pDataBuf, &wLen, &typeId, &wFunction, FALSE)) return;
+
+ 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)
+ { // TODO: this is deprecated
+ 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 == MTYPE_STATUSMSGEXT && wFunction >= 1 && wFunction <= 5)
+ { // handle ICQ6 status message request
+ handleMessageTypes(dwUin, time(NULL), dwID1, dwID2, wCookie, wVersion, 0xE7 + wFunction, bFlags, wAckType, dwLengthToEnd, 0, pDataBuf, FALSE, NULL);
+ }
+ else if (typeId)
+ {
+ message_ack_params pMsgAck = {0};
+
+ pMsgAck.bType = MAT_SERVER_ADVANCED;
+ pMsgAck.dwUin = dwUin;
+ pMsgAck.dwMsgID1 = dwID1;
+ pMsgAck.dwMsgID2 = dwID2;
+ pMsgAck.wCookie = wCookie;
+ pMsgAck.msgType = typeId;
+ pMsgAck.bFlags = bFlags;
+ handleMessageTypes(dwUin, time(NULL), dwID1, dwID2, wCookie, wVersion, typeId, bFlags, wAckType, dwLengthToEnd, (WORD)dwDataLen, pDataBuf, FALSE, &pMsgAck);
+ }
+ else
+ {
+ NetLog_Server("Unsupported plugin message type %d", typeId);
+ }
+ }
+}
+
+
+
+static void handleRecvServMsgContacts(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwID1, DWORD dwID2, WORD wCommand)
+{
+ HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
+
+ if (wCommand == 0)
+ { // received contacts
+ oscar_tlv_chain *chain;
+ WORD wAckType;
+
+ if (wLen < 4)
+ { // just check if at least one tlv is there
+ NetLog_Server("Message (format %u) - Ignoring empty contacts message", 2);
+ return;
+ }
+ chain = readIntoTLVChain(&buf, wLen, 0);
+
+ wAckType = getWordFromChain(chain, 0x0A, 1);
+
+ if (wAckType == 1)
+ { // it is really message containing contacts, parse them
+ oscar_tlv *tlvUins, *tlvNames;
+ ICQSEARCHRESULT **contacts;
+ int nContacts = 0x10, iContact = 0;
+ WORD wContactsGroup = 0;
+ int i, valid;
+ char* pBuffer;
+ int nLen;
+
+ tlvUins = getTLV(chain, 0x2711, 1);
+ tlvNames = getTLV(chain, 0x2712, 1);
+
+ if (!tlvUins || tlvUins->wLen < 4)
+ {
+ NetLog_Server("Malformed '%s' message", "contacts");
+ disposeChain(&chain);
+ return;
+ }
+ valid = 1;
+ contacts = (ICQSEARCHRESULT**)SAFE_MALLOC(nContacts * sizeof(ICQSEARCHRESULT*));
+ pBuffer = tlvUins->pData;
+ nLen = tlvUins->wLen;
+
+ while (nLen > 2)
+ { // parse UIDs
+ if (!wContactsGroup)
+ {
+ WORD wGroupLen;
+
+ unpackWord(&pBuffer, &wGroupLen);
+ nLen -= 2;
+ if (nLen >= wGroupLen + 2)
+ {
+ pBuffer += wGroupLen;
+ unpackWord(&pBuffer, &wContactsGroup);
+ nLen -= wGroupLen + 2;
+ }
+ else
+ break;
+ }
+ else
+ { // group parsed, UIDs waiting
+ WORD wUidLen;
+
+ unpackWord(&pBuffer, &wUidLen);
+ nLen -= 2;
+ if (nLen >= wUidLen)
+ {
+ if (iContact >= nContacts)
+ { // the list is too small, resize it
+ nContacts += 0x10;
+ contacts = (ICQSEARCHRESULT**)SAFE_REALLOC(contacts, nContacts * sizeof(ICQSEARCHRESULT*));
+ }
+ contacts[iContact] = (ICQSEARCHRESULT*)SAFE_MALLOC(sizeof(ICQSEARCHRESULT));
+ contacts[iContact]->hdr.cbSize = sizeof(ICQSEARCHRESULT);
+ contacts[iContact]->hdr.nick = null_strdup("");
+ contacts[iContact]->uid = (char*)SAFE_MALLOC(wUidLen + 1);
+ unpackString(&pBuffer, contacts[iContact]->uid, wUidLen);
+ nLen -= wUidLen;
+
+ if (IsStringUIN(contacts[iContact]->uid))
+ { // icq contact
+ contacts[iContact]->uin = atoi(contacts[iContact]->uid);
+ if (contacts[iContact]->uin == 0)
+ valid = 0;
+
+ SAFE_FREE(&contacts[iContact]->uid);
+ }
+ else
+ { // aim contact
+ if (!strlennull(contacts[iContact]->uid))
+ valid = 0;
+ }
+ iContact++;
+ }
+ else
+ {
+ if (wContactsGroup) valid = 0;
+ break;
+ }
+
+ wContactsGroup--;
+ }
+ }
+ if (!iContact || !valid)
+ {
+ NetLog_Server("Malformed '%s' message", "contacts");
+ disposeChain(&chain);
+ for (i = 0; i < iContact; i++)
+ {
+ SAFE_FREE(&contacts[i]->uid);
+ SAFE_FREE(&contacts[i]->hdr.nick);
+ SAFE_FREE(&contacts[i]);
+ }
+ SAFE_FREE((void**)&contacts);
+ return;
+ }
+ nContacts = iContact;
+ if (tlvNames && tlvNames->wLen >= 4)
+ { // parse names, if available
+ pBuffer = tlvNames->pData;
+ nLen = tlvNames->wLen;
+ iContact = 0;
+
+ while (nLen > 2)
+ { // parse Names
+ if (!wContactsGroup)
+ {
+ WORD wGroupLen;
+
+ unpackWord(&pBuffer, &wGroupLen);
+ nLen -= 2;
+ if (nLen >= wGroupLen + 2)
+ {
+ pBuffer += wGroupLen;
+ unpackWord(&pBuffer, &wContactsGroup);
+ nLen -= wGroupLen + 2;
+ }
+ else
+ break;
+ }
+ else
+ { // group parsed, Names waiting
+ WORD wNickLen;
+
+ unpackWord(&pBuffer, &wNickLen);
+ nLen -= 2;
+ if (nLen >= wNickLen)
+ {
+ WORD wNickTLV, wNickTLVLen;
+ char* pNick = NULL;
+
+ unpackTypedTLV(pBuffer, wNickLen, 0x01, &wNickTLV, &wNickTLVLen, &pNick);
+ if (wNickTLV == 0x01)
+ {
+ SAFE_FREE(&contacts[iContact]->hdr.nick);
+ contacts[iContact]->hdr.nick = pNick;
+ }
+ else
+ SAFE_FREE(&pNick);
+ pBuffer += wNickLen;
+ nLen -= wNickLen;
+
+ iContact++;
+ if (iContact >= nContacts) break;
+ }
+ else
+ break;
+
+ wContactsGroup--;
+ }
+ }
+ }
+
+ if (!valid)
+ {
+ NetLog_Server("Malformed '%s' message", "contacts");
+ }
+ else
+ {
+ int bAdded;
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+
+ hContact = HContactFromUID(dwUin, szUID, &bAdded);
+
+ // ack the message
+ icq_sendContactsAck(dwUin, szUID, dwID1, dwID2);
+
+ ccs.szProtoService = PSR_CONTACTS;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.timestamp = (DWORD)time(NULL);
+ pre.szMessage = (char *)contacts;
+ pre.lParam = nContacts;
+ pre.flags = PREF_UTF;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+
+ for (i = 0; i < iContact; i++)
+ {
+ SAFE_FREE(&contacts[i]->uid);
+ SAFE_FREE(&contacts[i]->hdr.nick);
+ SAFE_FREE(&contacts[i]);
+ }
+ SAFE_FREE((void**)&contacts);
+ }
+ else
+ NetLog_Server("Error: Received unknown contacts message, ignoring.");
+ // Clean up
+ disposeChain(&chain);
+ }
+ else if (wCommand == 1)
+ {
+ NetLog_Server("Cannot handle abort messages yet... :(");
+ return;
+ }
+ else if (wCommand == 2)
+ { // acknowledgement
+ DWORD dwCookie;
+ HANDLE hCookieContact;
+
+ if (FindMessageCookie(dwID1, dwID2, &dwCookie, &hCookieContact, NULL))
+ {
+ if (hCookieContact != hContact)
+ NetLog_Server("Warning: Ack Contact does not match Cookie Contact(0x%x != 0x%x)", hContact, hCookieContact);
+
+ ICQBroadcastAck(hContact, ACKTYPE_CONTACTS, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+
+ ReleaseCookie(dwCookie);
+ }
+ else
+ NetLog_Server("Warning: Unexpected Contact Transfer ack from %s", strUID(dwUin, szUID));
+ }
+}
+
+
+
+static void handleRecvServMsgType4(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef)
+{
+ WORD wTLVType;
+ WORD wTLVLen;
+ BYTE* pDataBuf;
+ DWORD dwUin2;
+ HANDLE hContact;
+
+ hContact = HContactFromUIN(dwUin, NULL);
+
+
+ if (wLen < 2)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=24;
+ CheckContact(chk);
+ NetLog_Server("Message (format %u) - Ignoring empty message", 4);
+ return;
+ }
+
+ // Unpack the first TLV(5)
+ unpackTypedTLV(buf, wLen, 5, &wTLVType, &wTLVLen, &pDataBuf);
+ NetLog_Server("Message (format %u) - UID: %s", 4, strUID(dwUin, szUID));
+
+ // It must be TLV(5)
+ if (wTLVType == 5)
+ {
+ BYTE bMsgType;
+ BYTE bFlags;
+ BYTE* pmsg = pDataBuf;
+ WORD wMsgLen;
+
+ unpackLEDWord(&pmsg, &dwUin2);
+
+ if (dwUin2 == dwUin)
+ {
+ unpackByte(&pmsg, &bMsgType);
+ unpackByte(&pmsg, &bFlags);
+ unpackLEWord(&pmsg, &wMsgLen);
+
+ if (bMsgType == 0 && wMsgLen == 1)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.historyevent=chk.logtofile=chk.popup=TRUE;
+ chk.msg="has checked your ignore list";
+ chk.icqeventtype=ICQEVENTTYPE_IGNORECHECK_STATUS;
+ chk.popuptype=POPTYPE_IGNORE_CHECK;
+ chk.dbeventflag=DBEF_READ;
+ CheckContact(chk);
+ NetLog_Server("User %u probably checks his ignore state.", dwUin);
+ }
+ else
+ {
+ offline_message_cookie *cookie;
+ DWORD dwRecvTime = (DWORD)time(NULL);
+
+ if (!(dwRef & 0x80000000) && FindCookie(dwRef, NULL, &cookie))
+ {
+ WORD wTimeTLVType, wTimeTLVLen;
+ BYTE *pTimeTLV;
+
+ cookie->nMessages++;
+
+ unpackTypedTLV(buf, wLen, 0x16, &wTimeTLVType, &wTimeTLVLen, &pTimeTLV);
+ if (pTimeTLV && wTimeTLVType == 0x16 && wTimeTLVLen == 4)
+ { // found Offline timestamp
+ BYTE *pBuf = pTimeTLV;
+ char *szTime;
+
+ unpackDWord(&pBuf, &dwRecvTime);
+ // TODO: add some checking
+ szTime = asctime(localtime(&dwRecvTime));
+ szTime[24] = '\0'; // remove new line
+ NetLog_Server("Message (format %u) - Offline timestamp is %s", 4, szTime);
+ }
+ SAFE_FREE(&pTimeTLV);
+ }
+
+ if (bMsgType == MTYPE_PLUGIN)
+ {
+ WORD wLen = wTLVLen - 8;
+ int typeId;
+
+ NetLog_Server("Parsing Greeting message through server");
+
+ pmsg += wMsgLen;
+ wLen -= wMsgLen;
+
+ if (unpackPluginTypeId(&pmsg, &wLen, &typeId, NULL, FALSE) && wLen > 8)
+ {
+ DWORD dwLengthToEnd;
+ DWORD dwDataLen;
+
+ // Length of remaining data
+ unpackLEDWord(&pmsg, &dwLengthToEnd);
+
+ // Length of message
+ unpackLEDWord(&pmsg, &dwDataLen);
+ wLen -= 8;
+
+ if (dwDataLen > wLen)
+ dwDataLen = wLen;
+
+ if (typeId)
+ handleMessageTypes(dwUin, dwRecvTime, dwMsgID1, dwMsgID2, 0, 0, typeId, bFlags, 0, dwLengthToEnd, (WORD)dwDataLen, pmsg, FALSE, NULL);
+ else
+ {
+ NetLog_Server("Unsupported plugin message type %d", typeId);
+ }
+ }
+ }
+ else
+ handleMessageTypes(dwUin, dwRecvTime, dwMsgID1, dwMsgID2, 0, 0, bMsgType, bFlags, 0, wTLVLen - 8, wMsgLen, pmsg, FALSE, NULL);
+ }
+ }
+ else
+ {
+ NetLog_Server("Ignoring spoofed TYPE4 message thru server from %d", dwUin);
+ }
+ }
+ else
+ {
+ NetLog_Server("Unsupported TLV (%u) in message (format %u)", wTLVType, 4);
+ }
+ SAFE_FREE(&pDataBuf);
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ if(OfflineMessagesReceived)
+ chk.PSD=22;
+ else
+ chk.PSD=-1;
+ CheckContact(chk);
+ }
+}
+
+
+
+//
+// Helper functions
+//
+
+static 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_UNDEFINED)
+ {
+ if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PSIG_MESSAGE))
+ { // icq6 message ack
+ nTypeID = MTYPE_PLAIN;
+ }
+ }
+ 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 (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_SMS_MESSAGE))
+ {
+ nTypeID = MTYPE_SMS_MESSAGE;
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_TZER_MESSAGE))
+ {
+ nTypeID = MTYPE_TZER_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 unpackPluginTypeId(BYTE** pBuffer, WORD* pwLen, int *pTypeId, WORD *pFunctionId, BOOL bThruDC)
+{
+ WORD wLen = *pwLen;
+ WORD wInfoLen;
+ DWORD dwPluginNameLen;
+ DWORD q1,q2,q3,q4;
+ WORD qt;
+ char* szPluginName;
+ int typeId;
+
+ if (wLen < 24)
+ return 0; // Failure
+
+ unpackLEWord(pBuffer, &wInfoLen);
+
+ unpackDWord(pBuffer, &q1); // get data GUID & function id
+ unpackDWord(pBuffer, &q2);
+ unpackDWord(pBuffer, &q3);
+ unpackDWord(pBuffer, &q4);
+ unpackLEWord(pBuffer, &qt);
+ wLen -= 20;
+
+ if (pFunctionId) *pFunctionId = qt;
+
+ unpackLEDWord(pBuffer, &dwPluginNameLen);
+ wLen -= 4;
+
+ if (dwPluginNameLen > wLen)
+ { // check for malformed plugin name
+ dwPluginNameLen = wLen;
+ NetLog_Uni(bThruDC, "Warning: malformed size of plugin name.");
+ }
+ szPluginName = (char *)_alloca(dwPluginNameLen + 1);
+ memcpy(szPluginName, *pBuffer, dwPluginNameLen);
+ szPluginName[dwPluginNameLen] = '\0';
+ wLen -= (WORD)dwPluginNameLen;
+
+ *pBuffer += dwPluginNameLen;
+
+ typeId = TypeGUIDToTypeId(q1, q2, q3, q4, qt);
+ if (!typeId)
+ NetLog_Uni(bThruDC, "Error: Unknown type {%08x-%08x-%08x-%08x:%04x}: %s", q1,q2,q3,q4,qt, szPluginName);
+
+ if (wInfoLen >= 22 + dwPluginNameLen)
+ { // sanity checking
+ wInfoLen -= (WORD)(22 + dwPluginNameLen);
+
+ // check if enough data is available - skip remaining bytes of info block
+ if (wLen >= wInfoLen)
+ {
+ *pBuffer += wInfoLen;
+ wLen -= wInfoLen;
+ }
+ }
+
+ *pwLen = wLen;
+ *pTypeId = typeId;
+
+ return 1; // Success
+}
+
+
+
+int getPluginTypeIdLen(int nTypeID)
+{
+ switch (nTypeID)
+ {
+ case MTYPE_SCRIPT_NOTIFY:
+ return 0x51;
+
+ case MTYPE_FILEREQ:
+ return 0x2B;
+
+ case MTYPE_TZER_MESSAGE:
+ return 0x34;
+
+ case MTYPE_AUTOAWAY:
+ case MTYPE_AUTOBUSY:
+ case MTYPE_AUTONA:
+ case MTYPE_AUTODND:
+ case MTYPE_AUTOFFC:
+ return 0x3C;
+
+ 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;
+
+ case MTYPE_TZER_MESSAGE:
+ packLEWord(packet, 0x32);
+ packGUID(packet, MGTYPE_TZER_MESSAGE );
+ packWord(packet, 0x0000);
+ packLEDWord(packet, 0x000D);
+ packBuffer(packet, "T-Zer Message", 0x000D);
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packWord(packet, 0x0000);
+ packByte(packet, 0x00);
+
+ break;
+
+ case MTYPE_AUTOAWAY:
+ case MTYPE_AUTOBUSY:
+ case MTYPE_AUTONA:
+ case MTYPE_AUTODND:
+ case MTYPE_AUTOFFC:
+ packLEWord(packet, 0x03A); // Length
+
+ packGUID(packet, MGTYPE_STATUSMSGEXT); // Message Type GUID
+ packLEWord(packet, (WORD)(nTypeID - 0xE7)); // Function ID
+ packLEDWord(packet, 0x13); // Request type string
+ packBuffer(packet, "Away Status Message", 0x13);
+
+ packDWord(packet, 0x01000000); // Unknown binary stuff
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packByte(packet, 0x00);
+
+ break;
+
+ default:
+ return;
+ }
+}
+
+
+
+static void handleStatusMsgReply(const char* szPrefix, HANDLE hContact, DWORD dwUin, WORD wVersion, int bMsgType, WORD wCookie, const char* szMsg)
+{
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+ int status;
+ char* pszMsg;
+
+
+ if (hContact == INVALID_HANDLE_VALUE)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ NetLog_Server("%sIgnoring status message from unknown contact %u", szPrefix, dwUin);
+ return;
+ }
+
+ status = AwayMsgTypeToStatus(bMsgType);
+ if (status == ID_STATUS_OFFLINE)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ 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.szMessage = pszMsg;
+ pre.timestamp = time(NULL);
+ pre.lParam = wCookie;
+
+ CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
+
+ SAFE_FREE(&pszMsg);
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ }
+}
+
+
+
+static HANDLE handleMessageAck(DWORD dwUin, WORD wCookie, WORD wVersion, int type, WORD wMsgLen, PBYTE buf, BYTE bFlags)
+{
+ if (bFlags == 3)
+ {
+ HANDLE hContact;
+ HANDLE hCookieContact;
+ message_cookie_data* pCookieData = NULL;
+
+ hContact = HContactFromUIN(dwUin, NULL);
+
+
+ // Added by BM, modifed by icqj plus team ))
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=2;
+ CheckContact(chk);
+ }
+
+ if (!FindCookie(wCookie, &hCookieContact, &pCookieData))
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ NetLog_Server("%sIgnoring unrequested status message from %u", "handleMessageAck: ", dwUin);
+
+ ReleaseCookie(wCookie);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (hContact != hCookieContact)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ NetLog_Server("%sAck Contact does not match Cookie Contact(0x%x != 0x%x)", "handleMessageAck: ", hContact, hCookieContact);
+
+ ReleaseCookie(wCookie);
+ return INVALID_HANDLE_VALUE;
+ }
+ ReleaseCookie(wCookie);
+
+ handleStatusMsgReply("handleMessageAck: ", hContact, dwUin, wVersion, type, wCookie, (char*)buf);
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ }
+ }
+ else
+ {
+ // Should not happen
+ NetLog_Server("%sIgnored type %u ack message (this should not happen)", "handleMessageAck: ", type);
+ }
+
+ return INVALID_HANDLE_VALUE;
+}
+
+
+
+/* this function send all acks from handleMessageTypes */
+static void sendMessageTypesAck(HANDLE hContact, int bUnicode, message_ack_params *pArgs)
+{
+ if (pArgs)
+ {
+ if ((pArgs->msgType == MTYPE_PLAIN && !CallService(MS_IGNORE_ISIGNORED, (WPARAM)hContact, IGNOREEVENT_MESSAGE))
+ || (pArgs->msgType == MTYPE_URL && !CallService(MS_IGNORE_ISIGNORED, (WPARAM)hContact, IGNOREEVENT_URL))
+ || pArgs->msgType == MTYPE_CONTACTS)
+ {
+ if (pArgs->bType == MAT_SERVER_ADVANCED)
+ { // Only ack message packets
+ icq_sendAdvancedMsgAck(pArgs->dwUin, pArgs->dwMsgID1, pArgs->dwMsgID2, pArgs->wCookie, (BYTE)pArgs->msgType, pArgs->bFlags);
+ }
+ else if (pArgs->bType == MAT_DIRECT)
+ { // Send acknowledgement
+ icq_sendDirectMsgAck(pArgs->pDC, pArgs->wCookie, (BYTE)pArgs->msgType, pArgs->bFlags, bUnicode ? CAP_UTF8MSGS : NULL);
+ }
+ }
+ }
+}
+
+
+
+/* this function also processes direct packets, so it should be bulletproof */
+/* pMsg points to the beginning of the message */
+BOOL 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, message_ack_params *pAckParams)
+{
+ BOOL res = TRUE;
+ char* szMsg;
+ char* pszMsgField[2*MAX_CONTACTSSEND+1];
+ char* pszMsg;
+ int nMsgFields;
+ HANDLE hContact = INVALID_HANDLE_VALUE;
+ int bAdded;
+
+ BOOL bRdName = FALSE;
+ DWORD dwNameLen = 0;
+ char * szName = 0;
+ char * szName2 = 0;
+ BOOL bRdUrl = FALSE;
+ DWORD dwUrlLen = 0;
+ char * szUrl = 0;
+ char * szUrl2 = 0;
+ char * szStr = 0;
+ int i = 0;
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+
+
+
+
+ if (dwDataLen < wMsgLen)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ NetLog_Uni(bThruDC, "Ignoring overflowed message");
+ res = FALSE;
+ return res;
+ }
+
+ if (wAckType == 2)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ handleMessageAck(dwUin, wCookie, wVersion, type, wMsgLen, pMsg, (BYTE)flags);
+ res = FALSE;
+ return res;
+ }
+
+ 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))
+ break;
+ }
+ }
+ }
+
+
+ switch (type)
+ {
+ // hContact = HContactFromUIN(dwUin, &bAdded);
+ case MTYPE_TZER_MESSAGE://szMsg dwDataLen/ need parsing
+ for (i = 0; i < wMsgLen; i++) {
+ if (bRdName == TRUE) {
+ if (szMsg[i] == '"') {
+ if (szName) {
+ szName = realloc(szName, dwNameLen + 1);
+ szName[dwNameLen] = 0;
+ }
+
+ bRdName = FALSE;
+ } else {
+ dwNameLen++;
+ if (dwNameLen == 1) {
+ szName = (char *) malloc(dwNameLen);
+ } else {
+ szName = realloc(szName, dwNameLen);
+ }
+ szName[dwNameLen - 1] = szMsg[i];
+ }
+ }
+
+ if (bRdUrl == TRUE) {
+ if (szMsg[i] == '"') {
+ if (szUrl) {
+ szUrl = realloc(szUrl, dwUrlLen + 1);
+ szUrl[dwUrlLen] = 0;
+ }
+
+ bRdUrl = FALSE;
+ } else {
+ dwUrlLen++;
+ if (dwUrlLen == 1) {
+ szUrl = (char *) malloc(dwUrlLen);
+ } else {
+ szUrl = realloc(szUrl, dwUrlLen);
+ }
+ szUrl[dwUrlLen - 1] = szMsg[i];
+ }
+ }
+
+
+ if (i > 5) {
+ if (szMsg[i] == '"' && szMsg[i - 1] == '=' && szMsg[i - 2] == 'e' && szMsg[i - 3] == 'm' && szMsg[i - 4] == 'a' && szMsg[i - 5] == 'n') {
+ bRdName = TRUE;
+ }
+ }
+
+ if (i > 4) {
+ if (szMsg[i] == '"' && szMsg[i - 1] == '=' && szMsg[i - 2] == 'l' && szMsg[i - 3] == 'r' && szMsg[i - 4] == 'u') {
+ bRdUrl = TRUE;
+ }
+ }
+ }
+
+ szName2 = DemangleXml(szName, dwNameLen);
+ free(szName);
+
+ szUrl2 = DemangleXml(szUrl, dwUrlLen);
+ free(szUrl);
+
+ szStr = (char *) malloc(17 + dwNameLen + dwUrlLen + 1);
+ sprintf(szStr, "tZer received: %s\r\n%s", szName2, szUrl2);
+
+
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = HContactFromUIN(dwUin, &bAdded);
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.flags = 0;
+ pre.timestamp = time(NULL);
+ pre.szMessage = szStr;
+ pre.lParam = 0;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+
+ free(szName2);
+ free(szUrl2);
+ free(szStr);
+ break;
+
+ case MTYPE_PLAIN: /* plain message */
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+
+ // Check if this message is marked as UTF8 encoded
+ if (dwDataLen > 12)
+ {
+ DWORD dwGuidLen = 0;
+ int bDoubleMsg = 0;
+
+ if (bThruDC)
+ {
+ DWORD dwExtraLen = *(DWORD*)pMsg;
+
+ if (dwExtraLen < dwDataLen && !strncmp(szMsg, "{\\rtf", 5))
+ { // it is icq5 sending us crap, get real message from it
+ WCHAR* usMsg = (WCHAR*)_alloca((dwExtraLen + 1)*sizeof(WCHAR));
+ // make sure it is null-terminated
+ wcsncpy(usMsg, (WCHAR*)(pMsg + 4), dwExtraLen);
+ usMsg[dwExtraLen] = '\0';
+ SAFE_FREE(&szMsg);
+ szMsg = make_utf8_string(usMsg);
+
+ if (!IsUnicodeAscii(usMsg, dwExtraLen))
+ pre.flags = PREF_UTF; // only mark real non-ascii messages as unicode
+
+ bDoubleMsg = 1;
+ }
+ }
+
+ if (!bDoubleMsg)
+ {
+ 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
+ pre.flags = PREF_UTF;
+ 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);
+ sendMessageTypesAck(hContact, pre.flags & PREF_UTF, pAckParams);
+
+ 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 = usMsg;
+ pre.flags = PREF_UTF;
+ }
+ }
+
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.timestamp = dwTimestamp;
+ pre.szMessage = (char *)szMsg;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+ break;
+
+ case MTYPE_URL:
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+ char *szBlob, *szTitle, *szDataDescr, *szDataUrl;
+
+
+ if (nMsgFields < 2)
+ {
+ HANDLE hContact = HContactFromUIN(dwUin, NULL);
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ }
+ NetLog_Uni(bThruDC, "Malformed '%s' message (maybe checking for invisible status...)", "URL");
+ res = FALSE;
+ break;
+ }
+
+ hContact = HContactFromUIN(dwUin, &bAdded);
+ sendMessageTypesAck(hContact, 0, pAckParams);
+
+ szTitle = ICQTranslateUtf("Incoming URL:");
+ szDataDescr = ansi_to_utf8(pszMsgField[0]);
+ szDataUrl = ansi_to_utf8(pszMsgField[1]);
+ szBlob = (char *)SAFE_MALLOC(strlennull(szTitle) + strlennull(szDataDescr) + strlennull(szDataUrl) + 8);
+ strcpy(szBlob, szTitle);
+ strcat(szBlob, " ");
+ strcat(szBlob, szDataDescr); // Description
+ strcat(szBlob, "\r\n");
+ strcat(szBlob, szDataUrl); // URL
+ SAFE_FREE(&szTitle);
+ SAFE_FREE(&szDataDescr);
+ SAFE_FREE(&szDataUrl);
+
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.timestamp = dwTimestamp;
+ pre.szMessage = (char *)szBlob;
+ pre.flags = PREF_UTF;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+
+ SAFE_FREE(&szBlob);
+ }
+ break;
+
+ case MTYPE_AUTHREQ: /* auth request */
+ /* format: nick FE first FE last FE email FE unk-char FE msg 00 */
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+ char* szBlob;
+ char* pCurBlob;
+
+
+ if (nMsgFields < 6)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=24;
+ CheckContact(chk);
+ NetLog_Server("Malformed '%s' message", "auth req");
+ res = FALSE;
+ break;
+ }
+
+ ccs.szProtoService=PSR_AUTH;
+ ccs.hContact=hContact=HContactFromUIN(dwUin, &bAdded);
+ ccs.wParam=0;
+ ccs.lParam=(LPARAM)⪯
+ 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 */
+ {
+ DWORD cbBlob;
+ PBYTE pBlob, pCurBlob;
+
+ if (nMsgFields < 4)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=24;
+ CheckContact(chk);
+ NetLog_Server("Malformed '%s' message", "you were added");
+ res = FALSE;
+ break;
+ }
+
+ hContact = HContactFromUIN(dwUin, &bAdded);
+
+ /*blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ) */
+ cbBlob=sizeof(DWORD)+sizeof(HANDLE)+strlennull(pszMsgField[0])+strlennull(pszMsgField[1])+strlennull(pszMsgField[2])+strlennull(pszMsgField[3])+4;
+ pCurBlob=pBlob=(PBYTE)_alloca(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]);
+
+ ICQAddEvent(NULL, EVENTTYPE_ADDED, dwTimestamp, 0, cbBlob, pBlob);
+ }
+ break;
+
+ case MTYPE_CONTACTS:
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+ 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)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ NetLog_Uni(bThruDC, "Malformed '%s' message", "contacts");
+ res = FALSE;
+ 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)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=24;
+ CheckContact(chk);
+ NetLog_Uni(bThruDC, "Malformed '%s' message", "contacts");
+ res = FALSE;
+ }
+ else
+ {
+ hContact = HContactFromUIN(dwUin, &bAdded);
+ sendMessageTypesAck(hContact, 0, pAckParams);
+
+ ccs.szProtoService = PSR_CONTACTS;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ 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: // FIXME: this should be removed - it is never called
+ hContact = NULL;
+
+ switch(dwUin)
+ {
+ case 1111: /* icqmail 'you've got mail' - not processed */
+ res = FALSE;
+ break;
+ default:
+ res = FALSE;
+ break;
+ }
+ break;
+
+ case MTYPE_SMS_MESSAGE:
+ /* it's a SMS message from a mobile - broadcast to SMS plugin */
+ if (dwUin != 1002)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=24;
+ CheckContact(chk);
+ NetLog_Uni(bThruDC, "Malformed '%s' message", "SMS Mobile");
+ break;
+ }
+ NetLog_Server("Received SMS Mobile message");
+
+ ICQBroadcastAck(NULL, ICQACKTYPE_SMS, ACKRESULT_SUCCESS, NULL, (LPARAM)szMsg);
+ break;
+
+ case MTYPE_STATUSMSGEXT:
+ /* it's either extended StatusMsg reply from icq2003b or a IcqWebMessage */
+ if (dwUin == 1003)
+ {
+ NetLog_Server("Received ICQWebMessage - NOT SUPPORTED");
+ }
+ break;
+
+ case MTYPE_WWP:
+ /* format: fromname FE FE FE fromemail FE unknownbyte FE 'Sender IP: xxx.xxx.xxx.xxx' 0D 0A body */
+ {
+ DWORD cbBlob;
+ PBYTE pBlob, pCurBlob;
+
+ if (nMsgFields < 6)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=24;
+ CheckContact(chk);
+ NetLog_Server("Malformed '%s' message", "web pager");
+ res = FALSE;
+ break;
+ }
+
+ /*blob is: body(ASCIIZ), name(ASCIIZ), email(ASCIIZ) */
+ cbBlob=strlennull(pszMsgField[0])+strlennull(pszMsgField[3])+strlennull(pszMsgField[5])+3;
+ pCurBlob=pBlob=(PBYTE)_alloca(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]);
+
+ ICQAddEvent(NULL, ICQEVENTTYPE_WEBPAGER, dwTimestamp, 0, cbBlob, pBlob);
+ }
+ break;
+
+ case MTYPE_EEXPRESS:
+ /* format: fromname FE FE FE fromemail FE unknownbyte FE body */
+ {
+ DWORD cbBlob;
+ PBYTE pBlob, pCurBlob;
+
+ if (nMsgFields < 6)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=24;
+ CheckContact(chk);
+ NetLog_Server("Malformed '%s' message", "e-mail express");
+ res = FALSE;
+ break;
+ }
+
+ /*blob is: body(ASCIIZ), name(ASCIIZ), email(ASCIIZ) */
+ cbBlob=strlennull(pszMsgField[0])+strlennull(pszMsgField[3])+strlennull(pszMsgField[5])+3;
+ pCurBlob=pBlob=(PBYTE)_alloca(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]);
+
+ ICQAddEvent(NULL, ICQEVENTTYPE_EMAILEXPRESS, dwTimestamp, 0, cbBlob, pBlob);
+ }
+ 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_AUTOONLINE:
+ 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.nRequestType = 0x102;
+ EnterCriticalSection(&ratesMutex);
+ rr.wGroup = ratesGroupFromSNAC(gRates, ICQ_MSG_FAMILY, ICQ_MSG_RESPONSE);
+ LeaveCriticalSection(&ratesMutex);
+
+ if (!handleRateItem(&rr, TRUE))
+ icq_sendAwayMsgReplyServ(dwUin, dwMsgID, dwMsgID2, wCookie, wVersion, (BYTE)type, szMsg);
+ }
+
+ break;
+ }
+
+ case MTYPE_FILEREQ: // Never happens
+ default:
+ if(wMsgLen == 0)
+ {
+ HANDLE hContact = HContactFromUIN(dwUin,NULL);
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.popup=chk.logtofile=chk.historyevent=TRUE;
+ chk.icqeventtype=ICQEVENTTYPE_IGNORECHECK_STATUS;
+ chk.dbeventflag=DBEF_READ;
+ chk.popuptype=POPTYPE_IGNORE_CHECK;
+ chk.msg="has checked your ignore list";
+ CheckContact(chk);
+ }
+ }
+
+ NetLog_Uni(bThruDC, "Unprocessed message type %d", type);
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ }
+ res = FALSE;
+ break;
+
+ }
+ if(!bExcludePSD)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ }
+
+ SAFE_FREE(&szMsg);
+
+ return res;
+}
+
+
+
+static void handleRecvMsgResponse(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ DWORD dwCookie;
+ WORD wMessageFormat;
+ WORD wStatus;
+ WORD bMsgType = 0;
+ BYTE bFlags;
+ WORD wLength;
+ HANDLE hContact;
+ HANDLE hCookieContact;
+ 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, &szUid)) return;
+
+ hContact = HContactFromUID(dwUin, szUid, NULL);
+
+ buf += 2; // 3. unknown
+ wLen -= 2;
+
+ if (!FindMessageCookie(dwMsgID1, dwMsgID2, &dwCookie, &hCookieContact, &pCookieData))
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=2;
+ CheckContact(chk);
+ NetLog_Server("SNAC(4.B) Received an ack that I did not ask for from (%u)", dwUin);
+ return;
+ }
+
+ if (IsValidOscarTransfer(pCookieData))
+ { // it is OFT response
+ handleRecvServResponseOFT(buf, wLen, dwUin, szUid, pCookieData);
+ return;
+ }
+
+ if (!dwUin)
+ { // AIM cannot send this - just sanity
+ NetLog_Server("Error: Invalid UID in message response.");
+ 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;
+
+ if (!FindCookie(wCookie, &hCookieContact, &pCookieData))
+ { // use old reliable method
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=2;
+ CheckContact(chk);
+ NetLog_Server("Warning: Invalid cookie in %s from (%u)", "message response", dwUin);
+
+ if (pCookieData->bMessageType != MTYPE_AUTOAWAY && bFlags == 3)
+ { // most probably a broken ack of some kind (e.g. from R&Q), try to fix that
+ bMsgType = pCookieData->bMessageType;
+ bFlags = 0;
+
+ NetLog_Server("Warning: Invalid message type in %s from (%u)", "message response", dwUin);
+ }
+ }
+ else if (bMsgType != MTYPE_PLUGIN && pCookieData->bMessageType != MTYPE_AUTOAWAY)
+ { // just because some clients break it...
+ CHECKCONTACT chk= {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ dwCookie = wCookie;
+
+ if (bMsgType != pCookieData->bMessageType)
+ NetLog_Server("Warning: Invalid message type in %s from (%u)", "message response", dwUin);
+
+ bMsgType = pCookieData->bMessageType;
+ }
+ else if (pCookieData->bMessageType == MTYPE_AUTOAWAY && bMsgType != MTYPE_PLUGIN)
+ {
+ if (bMsgType != pCookieData->nAckType)
+ NetLog_Server("Warning: Invalid message type in %s from (%u)", "message response", dwUin);
+ }
+ }
+ else
+ {
+ bMsgType = pCookieData->bMessageType;
+ bFlags = 0;
+ }
+
+ if (hCookieContact != hContact)
+ {
+ NetLog_Server("SNAC(4.B) Ack Contact does not match Cookie Contact(0x%x != 0x%x)", hContact, hCookieContact);
+
+ 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, modified by icqj plus team
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+
+ 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:
+ {
+ WORD wMsgLen;
+ DWORD dwLengthToEnd;
+ DWORD dwDataLen;
+ int typeId;
+ WORD wFunctionId;
+
+
+ if (wLength != 0x1B)
+ {
+ NetLog_Server("Invalid Greeting %s", "message response");
+
+ ReleaseCookie(dwCookie);
+ return;
+ }
+
+ NetLog_Server("Parsing Greeting %s", "message response");
+
+ // Message
+ unpackLEWord(&buf, &wMsgLen);
+ wLen -= 2;
+ buf += wMsgLen;
+ wLen -= wMsgLen;
+
+ // This packet is malformed. Possibly a file accept from Miranda IM 0.1.2.1
+ if (wLen < 20) return;
+
+ if (!unpackPluginTypeId(&buf, &wLen, &typeId, &wFunctionId, FALSE)) return;
+
+ 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_PLAIN:
+ if (pCookieData && pCookieData->bMessageType == MTYPE_AUTOAWAY && dwLengthToEnd >= 4)
+ { // ICQ 6 invented this
+ char *szMsg;
+
+ szMsg = (char*)_alloca(dwDataLen + 1);
+ if (dwDataLen > 0)
+ memcpy(szMsg, buf, dwDataLen);
+ szMsg[dwDataLen] = '\0';
+ handleStatusMsgReply("SNAC(4.B) ", hContact, dwUin, wVersion, pCookieData->nAckType, (WORD)dwCookie, szMsg);
+
+ break;
+ }
+ else
+ ackType = ACKTYPE_MESSAGE;
+ break;
+
+ 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;
+
+ case MTYPE_STATUSMSGEXT:
+ { // handle Away Message response (ICQ 6)
+ char *szMsg;
+
+ szMsg = (char*)SAFE_MALLOC(dwDataLen + 1);
+ if (dwDataLen > 0)
+ memcpy(szMsg, buf, dwDataLen);
+ szMsg[dwDataLen] = '\0';
+ szMsg = EliminateHtml(szMsg, dwDataLen);
+
+ handleStatusMsgReply("SNAC(4.B) ", hContact, dwUin, wVersion, pCookieData->nAckType, (WORD)dwCookie, szMsg);
+
+ SAFE_FREE(&szMsg);
+ }
+ break;
+
+ default:
+ NetLog_Server("Error: Unknown plugin message response, type %d.", typeId);
+ 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");
+ // Set DC status to failed
+ ICQWriteContactSettingByte(hContact, "DCStatus", 2);
+ }
+ 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);
+ }
+ }
+
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ CheckContact(chk);
+ }
+
+ ReleaseCookie(dwCookie);
+}
+
+
+// A response to a CLI_SENDMSG
+static void handleRecvServMsgError(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwSequence)
+{
+ WORD wError;
+ char* pszErrorMessage;
+ HANDLE hContact;
+ message_cookie_data* pCookieData = NULL;
+ int nMessageType;
+ // BOOL isHidden;
+
+ if (wLen < 2)
+ return;
+
+ if (FindCookie((WORD)dwSequence, &hContact, &pCookieData))
+ { // all packet cookies from msg family has command 0 in the queue
+ DWORD dwUin;
+ uid_str szUid;
+
+ ICQGetContactSettingUID(hContact, &dwUin, &szUid);
+
+ // Error code
+ unpackWord(&buf, &wError);
+
+ 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)
+ {
+ if (((message_cookie_data_ex*)pCookieData)->isOffline)
+ { // offline failed - most probably to AIM contact
+ pszErrorMessage = ICQTranslate("The contact does not support receiving offline messages.");
+ break;
+ }
+ // 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 0x0005: // Requested service unavailable
+ pszErrorMessage = ICQTranslate("The messaging service is temporarily unavailable. Wait a while and try again.\r\nSNAC(4.1) Error x05");
+ 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");
+ 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 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);
+ icq_SetUserStatus(0, (WORD)dwSequence, 1, 0);
+ LogFamilyError(ICQ_MSG_FAMILY, wError);
+ }
+}
+
+
+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, NULL, &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, 0); not necessary anymore
+
+ 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 = "** This message was blocked by the ICQ server ** The message was invalid.";
+ break;
+
+ case 1:
+ pszErrorMsg = "** This message was blocked by the ICQ server ** The message was too long.";
+ break;
+
+ case 2:
+ pszErrorMsg = "** This message was blocked by the ICQ server ** The sender has flooded the server.";
+ break;
+
+ case 4:
+ pszErrorMsg = "** 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;
+ }
+
+ pszErrorMsg = ICQTranslateUtf(pszErrorMsg);
+
+ // Create message to notify user
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+ int bAdded;
+
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = HContactFromUIN(dwUin, &bAdded);
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.timestamp = time(NULL);
+ pre.szMessage = pszErrorMsg;
+ pre.flags = PREF_UTF;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+ SAFE_FREE(&pszErrorMsg);
+}
+
+
+
+static void handleOffineMessagesReply(unsigned char *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{
+ offline_message_cookie *cookie;
+
+ if (FindCookie(dwRef, NULL, &cookie))
+ {
+ NetLog_Server("End of offline msgs, %u received", cookie->nMessages);
+
+ ReleaseCookie(dwRef);
+ }
+ else
+ NetLog_Server("Error: Received unexpected end of offline msgs.");
+ OfflineMessagesReceived=1;
+}
+
+
+
+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;
+
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=25;
+ CheckContact(chk);
+ }
+ 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;
+
+ case MTN_WINDOW_CLOSED:
+ {
+ char szFormat[MAX_PATH];
+ char szMsg[MAX_PATH];
+ char *nick = NickFromHandleUtf(hContact);
+
+ null_snprintf(szMsg, MAX_PATH, ICQTranslateUtfStatic("Contact \"%s\" has closed the message window.", szFormat, MAX_PATH), nick);
+ ShowPopUpMsg(hContact, dwUin, ICQTranslateUtfStatic("ICQ Note", szFormat, MAX_PATH), szMsg, LOG_NOTE);
+ SAFE_FREE(&nick);
+
+ NetLog_Server("%s has closed the message window.", strUID(dwUin, szUID));
+ }
+ 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
+
+ sendServPacketAsync(&p);
+}
diff --git a/icqj_s7_sss_mod/fam_09bos.c b/icqj_s7_sss_mod/fam_09bos.c new file mode 100644 index 0000000..f4e3afe --- /dev/null +++ b/icqj_s7_sss_mod/fam_09bos.c @@ -0,0 +1,133 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/fam_0alookup.c b/icqj_s7_sss_mod/fam_0alookup.c new file mode 100644 index 0000000..006800d --- /dev/null +++ b/icqj_s7_sss_mod/fam_0alookup.c @@ -0,0 +1,147 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007,2008 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+// Copyright 2008 [sss], chaos.persei, nullbie, baloo, jarvis
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/fam_0bstatus.c b/icqj_s7_sss_mod/fam_0bstatus.c new file mode 100644 index 0000000..c5efb35 --- /dev/null +++ b/icqj_s7_sss_mod/fam_0bstatus.c @@ -0,0 +1,71 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/fam_13servclist.c b/icqj_s7_sss_mod/fam_13servclist.c new file mode 100644 index 0000000..973b795 --- /dev/null +++ b/icqj_s7_sss_mod/fam_13servclist.c @@ -0,0 +1,2113 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007,2008 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+// Copyright 2008 [sss], chaos.persei, nullbie, baloo, jarvis
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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);
+static void handleRecvRemoved(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;
+ servlistcookie* sc;
+
+ unpackWord(&pBuffer, &wError);
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, &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 authorized our contact
+ char str[MAX_PATH];
+ char msg[MAX_PATH];
+ char *nick = NickFromHandleUtf(hContact);
+
+ ICQWriteContactSettingByte(hContact, "Auth", 0);
+ null_snprintf(str, MAX_PATH, ICQTranslateUtfStatic("Contact \"%s\" was authorized in the server list.", msg, MAX_PATH), nick);
+ icq_LogMessage(LOG_WARNING, str);
+ SAFE_FREE(&nick);
+ }
+ else if (!bAuth && pAuth)
+ { // server took away authorization of our contact
+ char str[MAX_PATH];
+ char msg[MAX_PATH];
+ char *nick = NickFromHandleUtf(hContact);
+
+ ICQWriteContactSettingByte(hContact, "Auth", 1);
+ null_snprintf(str, MAX_PATH, ICQTranslateUtfStatic("Contact \"%s\" lost its authorization in the server list.", msg, MAX_PATH), 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
+ DWORD uin = ICQGetContactSettingDword(hContact, "UIN", 0);
+ ICQDeleteContactSetting(hContact, "ServerId");
+ ICQDeleteContactSetting(hContact, "SrvGroupId");
+ ICQDeleteContactSetting(hContact, "Auth");
+ icq_sendNewContact(0, szUID); // add to CS to see him
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=uin;
+ chk.popup=chk.historyevent=chk.logtofile=TRUE;
+ chk.icqeventtype=ICQEVENTTYPE_SELF_REMOVE;
+ chk.popuptype=POPTYPE_SELFREMOVE;
+ chk.msg="removed himself from your Serverlist!";
+ chk.dbeventflag=DBEF_READ;
+ CheckContact(chk);
+ }
+ }
+ }
+ }
+ 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;
+ servlistcookie* sc;
+
+ unpackWord(&pBuffer, &wError);
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, &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->hContact, 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 = SAFE_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)
+ {
+ if (wError == 0x0E && sc->lParam == 1)
+ { // second ack - adding failed with error 0x0E, try to add with AVAIT_AUTH flag
+ DWORD dwCookie;
+
+ if (!ICQGetContactSettingByte(sc->hContact, "Auth", 0))
+ { // we tried without AWAIT_AUTH, try again with it
+ NetLog_Server("Contact could not be added without authorization, add with await auth flag.");
+
+ ICQWriteContactSettingByte(sc->hContact, "Auth", 1); // we need auth
+ }
+ else
+ { // we tried with AWAIT_AUTH, try again without
+ NetLog_Server("Contact count not be added awaiting authorization, try authorized.");
+
+ ICQWriteContactSettingByte(sc->hContact, "Auth", 0);
+ }
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, sc->hContact, sc);
+ icq_sendServerContact(sc->hContact, dwCookie, ICQ_LISTS_ADDTOLIST, sc->wNewGroupId, sc->wNewContactId);
+
+ sc->lParam = 2; // do not cycle
+ sc = NULL; // we do not want to be freed here
+ break;
+ }
+ RemovePendingOperation(sc->hContact, 0);
+ NetLog_Server("Moving of user to another group on server list failed, error %d", wError);
+ icq_LogMessage(LOG_ERROR, "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_CONTACT_FIX_AUTH:
+ {
+ if (wError)
+ { // FIXME: something failed, we should handle it properly
+ }
+ 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))
+ { // check if the truncated nick changed, i.e. do not overwrite locally stored longer nick
+ if (strlennull(szOldNick) <= strlennull(pszNick) || strncmp(szOldNick, pszNick, null_strcut(szOldNick, MAX_SSI_TLV_NAME_SIZE)))
+ {
+ // 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))
+ { // check if the truncated comment changed, i.e. do not overwrite locally stored longer comment
+ if (strlennull(szOldComment) <= strlennull(pszComment) || strncmp(szOldComment, pszComment, null_strcut(szOldComment, MAX_SSI_TLV_COMMENT_SIZE)))
+ {
+ 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
+ CallService(MS_IGNORE_IGNORE, (WPARAM)hContact, IGNOREEVENT_ALL);
+ 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 %s item recognized", "first import");
+ }
+ 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 */
+ if (!strcmpnull(szRecordName, "12"))
+ { // need to handle Photo Item separately
+ ICQWriteContactSettingWord(NULL, "SrvPhotoID", wItemId);
+ NetLog_Server("SSI %s item recognized", "Photo");
+ }
+ else
+ {
+ ICQWriteContactSettingWord(NULL, "SrvAvatarID", wItemId);
+ NetLog_Server("SSI %s item recognized", "Avatar");
+ }
+ ReserveServerID(wItemId, SSIT_ITEM);
+ }
+ 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 (ICQGetContactSettingString(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
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hcontact;
+ chk.dwUin=dwUin;
+ chk.PSD=26;
+ chk.popup=chk.historyevent=chk.logtofile=TRUE;
+ chk.popuptype=POPTYPE_AUTH;
+ chk.msg="Authorization requested";
+ chk.icqeventtype=ICQEVENTTYPE_AUTH_REQUESTED;
+ chk.dbeventflag=DBEF_READ;
+ CheckContact(chk);
+ }
+
+ return;
+}
+
+
+
+static void handleRecvAdded(unsigned char *buf, WORD wLen)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ DWORD cbBlob;
+ PBYTE pBlob,pCurBlob;
+ HANDLE hContact;
+ int bAdded;
+ char* szNick;
+ int nNickLen;
+ BOOL NotOnList = FALSE;
+ DBVARIANT dbv = {0};
+
+
+ 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 (DBGetContactSettingByte(hContact, "CList", "NotOnList", 1))
+ {
+ NotOnList = TRUE;
+ }
+
+ if (NotOnList)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.popup=chk.logtofile=chk.historyevent=TRUE;
+ chk.popuptype=POPTYPE_AUTH;
+ chk.msg="sent you 'You were added' notice";
+ chk.icqeventtype=ICQEVENTTYPE_YOU_ADDED;
+ chk.dbeventflag=DBEF_READ;
+ CheckContact(chk);
+ }
+
+
+ ICQDeleteContactSetting(hContact, "Grant");
+
+ cbBlob=sizeof(DWORD)+sizeof(HANDLE)+4;
+
+ if (dwUin)
+ {
+ if (ICQGetContactSettingString(hContact, "Nick", &dbv))
+ nNickLen = 0;
+ else
+ {
+ szNick = dbv.pszVal;
+ nNickLen = strlennull(szNick);
+ }
+ }
+ else
+ nNickLen = strlennull(szUid);
+
+ cbBlob += nNickLen;
+
+ pCurBlob=pBlob=(PBYTE)_alloca(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
+
+ ICQAddEvent(NULL, EVENTTYPE_ADDED, time(NULL), 0, cbBlob, pBlob);
+ if(bLogAuthHistory)
+ HistoryLog(hContact,dwUin, "you added",0,DBEF_READ);
+ // logtofile(hContact, DWORD dwUin, char *string, int event_type);
+ 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;
+
+// DBEVENTINFO dbei = {0};
+// PBYTE pCurBlob;
+// char szText[MAX_PATH];
+ char szPopup[MAX_PATH];
+// WORD wTextLen;
+ BOOL NotOnList = FALSE;
+
+ 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);
+
+// szNick = NickFromHandle(hContact);
+
+ if (DBGetContactSettingByte(hContact, "CList", "NotOnList", 1))
+ {
+ NotOnList = TRUE;
+ }
+
+ 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:
+ SkinPlaySound("AuthDenied"); // Added by BM
+ //DBWriteContactSettingByte(hContact, gpszICQProtoName, "Auth", 1);
+#ifdef _DEBUG
+ NetLog_Server("Authorization request %s by %s", "denied", strUID(dwUin, szUid));
+#endif
+ if (NotOnList)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.popup=chk.historyevent=chk.logtofile=chk.fornotonlist=TRUE;
+ chk.popuptype=POPTYPE_VIS;
+ chk.dbeventflag=DBEF_READ;
+ chk.icqeventtype=ICQEVENTTYPE_CHECK_STATUS;
+ chk.msg="...probably detected your invisibility (auth denied)";
+ CheckContact(chk);
+ }
+ else
+ {
+ mir_snprintf(szPopup, sizeof(szPopup), ICQTranslateUtf("User \"%s\" was denied your authorization request.(may be checking for invisible status)"), NickFromHandleUtf(hContact));
+// dbei.eventType = ICQEVENTTYPE_AUTH_DENIED;
+ if(bLogAuthHistory)
+ HistoryLog(hContact,dwUin, "was denied your authorization request", ICQEVENTTYPE_AUTH_DENIED, DBEF_READ);
+ else
+ HistoryLog(0,0, "was denied your authorization request", ICQEVENTTYPE_AUTH_DENIED, 0);
+ LogToFile(hContact, dwUin, 0, ICQEVENTTYPE_AUTH_DENIED);
+// mir_snprintf(szText, sizeof(szText), "Authorization request denied by %s (%u): %s", szNick, dwUin, nReasonLen?szReason:"");
+ }
+ break;
+
+ case 1:
+ SkinPlaySound("AuthGranted"); // Added by BM
+ ICQWriteContactSettingByte(hContact, "Auth", 0);
+#ifdef _DEBUG
+ NetLog_Server("Authorization request %s by %s", "granted", strUID(dwUin, szUid));
+#endif
+ if (NotOnList)
+ {
+ CHECKCONTACT chk = {0};
+ chk.dwUin=dwUin;
+ chk.hContact=hContact;
+ chk.popup=chk.logtofile=chk.historyevent=chk.fornotonlist=TRUE;
+ chk.popuptype=POPTYPE_VIS;
+ chk.dbeventflag=DBEF_READ;
+ chk.icqeventtype=ICQEVENTTYPE_CHECK_STATUS;
+ chk.msg="...probably detected your invisibility (auth granted)";
+ CheckContact(chk);
+ }
+ else
+ {
+ mir_snprintf(szPopup, sizeof(szPopup), ICQTranslateUtf("User \"%s\" was granted your authorization request.(may be checking for invisible status)"), NickFromHandleUtf(hContact));
+ if(bLogAuthHistory)
+ HistoryLog(hContact,dwUin, "Authorization request granted", ICQEVENTTYPE_AUTH_GRANTED, DBEF_READ);
+ else
+ HistoryLog(0,0, "Authorization request granted", ICQEVENTTYPE_AUTH_GRANTED, 0);
+ LogToFile(hContact, dwUin, 0, ICQEVENTTYPE_AUTH_GRANTED);
+ }
+ break;
+
+ default:
+ if (NotOnList)
+ {
+ CHECKCONTACT chk = {0};
+ chk.dwUin=dwUin;
+ chk.hContact=hContact;
+ chk.popup=chk.logtofile=chk.historyevent=chk.fornotonlist=TRUE;
+ chk.popuptype=POPTYPE_VIS;
+ chk.dbeventflag=DBEF_READ;
+ chk.icqeventtype=ICQEVENTTYPE_CHECK_STATUS;
+ chk.msg="Uknown authorization request response from contact not in your list";
+ CheckContact(chk);
+
+ }
+ NetLog_Server("Unknown Authorization request response (%u) from %s", bResponse, strUID(dwUin, szUid));
+ break;
+
+ }
+
+ {
+ CHECKCONTACT chk = {0};
+ chk.dwUin=dwUin;
+ chk.hContact=hContact;
+ chk.PSD=28;
+ CheckContact(chk);
+ }
+
+}
+
+
+static void handleRecvRemoved(unsigned char *buf, WORD wLen)
+{
+
+ if (wLen >= 10)
+ {
+ WORD wGroupId, wItemId, wItemType;
+ uid_str szUid;
+ DWORD dwUin;
+
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) return;
+
+ if (unpackServerListItem(&buf, &wLen, szUid, &wGroupId, &wItemId, &wItemType, NULL))
+ {
+ HANDLE hContact = HContactFromRecordName(szUid, NULL);
+
+ if (hContact != INVALID_HANDLE_VALUE && wItemType == SSI_ITEM_BUDDY)
+ ResetUserSSISettings(hContact);
+ { // 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
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.PSD=29;
+ chk.historyevent=chk.logtofile=TRUE;
+ chk.icqeventtype=ICQEVENTTYPE_SELF_REMOVE;
+ chk.dbeventflag=DBEF_READ;
+ chk.msg="User was removed from server list";
+ CheckContact(chk);
+ }
+ }
+ }
+ }
+ NetLog_Server("Server sent SNAC(x13,x%02x) - %s", 0x0A, "Server removed something from our list");
+}
+
+
+
+// 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
+// 06 - Allow only users in the Contact list to see you, except Invisible list users
+
+void updateServVisibilityCode(BYTE bCode)
+{
+ icq_packet packet;
+ WORD wVisibilityID;
+ WORD wCommand;
+ int special = 0;
+
+
+ servlistcookie* ack;
+ DWORD dwCookie;
+
+
+ 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);
+ bVisibility = 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_s7_sss_mod/fam_15icqserver.c b/icqj_s7_sss_mod/fam_15icqserver.c new file mode 100644 index 0000000..35539ba --- /dev/null +++ b/icqj_s7_sss_mod/fam_15icqserver.c @@ -0,0 +1,946 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 37 $
+// Last change on : $Date: 2007-08-07 04:37:56 +0300 (Вт, 07 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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 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_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)
+ {
+ HANDLE hContact;
+ fam15_cookie_data* pCookieData = NULL;
+ int foundCookie;
+
+ foundCookie = FindCookie(wCookie, &hContact, (void**)&pCookieData);
+ if (foundCookie && pCookieData)
+ {
+ 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_META_INFO_REPLY: // SRV_META request replies
+ handleExtensionMetaResponse(databuf, wPackLen, wCookie, wFlags);
+ break;
+
+ default:
+ NetLog_Server("Warning: Ignoring Meta response - Unknown type %d", wRequestType);
+ break;
+ }
+ }
+ }
+ else
+ {
+ NetLog_Server("Error: Broken snac 15/3 %d", 3);
+ }
+
+ if (chain)
+ disposeChain(&chain);
+}
+
+
+
+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;
+ fam15_cookie_data* pCookieData = NULL;
+ HANDLE hContact = INVALID_HANDLE_VALUE;
+ DWORD dwCookieUin;
+ int foundCookie;
+ BOOL bOK = TRUE;
+
+
+ foundCookie = FindCookie(wCookie, &hContact, (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
+ {
+ NetLog_Server("Warning: Ignoring unrequested 15/03 user info reply type 0x%x", wReplySubtype);
+
+ return;
+ }
+ // obtain contact UIN
+ dwCookieUin = ICQGetContactSettingUIN(hContact);
+
+ 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)
+ { // auth flag is the same for normal contacts also
+ ICQWriteContactSettingByte(hContact, "Auth", (BYTE)!(*databuf));
+ databuf += 1;
+
+ // webaware is also the same, but gives different values
+ ICQWriteContactSettingByte(hContact, "WebAware", (*databuf));
+ databuf += 1;
+
+ ICQWriteContactSettingByte(hContact, "PublishPrimaryEmail", (BYTE)!(*databuf));
+ databuf += 1;
+ }
+ else
+ databuf += 3;
+
+ wPacketLen -= 3;
+
+ if (wPacketLen >= 1 && (!hContact || dwCookieUin == dwLocalUIN))
+ { // owner or owner contact contains one more unknown byte value
+ databuf += 1; // OMG!
+ wPacketLen -= 1;
+ }
+ }
+ 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_s7_sss_mod/fam_17signon.c b/icqj_s7_sss_mod/fam_17signon.c new file mode 100644 index 0000000..9cfa5aa --- /dev/null +++ b/icqj_s7_sss_mod/fam_17signon.c @@ -0,0 +1,358 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+static void handleAuthKeyResponse(BYTE *buf, WORD wPacketLen, serverthread_info *info);
+static void handleRegImage(BYTE *buf, WORD wPacketLen, serverthread_info *info);
+static void handleIcqNewUin(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;
+ case ICQ_SIGNON_REG_AUTH_IMAGE:
+ handleRegImage(pBuffer, wBufferLength, info);
+ break;
+ case ICQ_SIGNON_NEW_UIN:
+ handleIcqNewUin(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.
+ packTLV(&packet, 0x0003, (WORD)sizeof(CLIENT_ID_STRING)-1, CLIENT_ID_STRING);
+ packTLVWord(&packet, 0x0016, CLIENT_ID_CODE);
+ packTLVWord(&packet, 0x0017, CLIENT_VERSION_MAJOR);
+ packTLVWord(&packet, 0x0018, CLIENT_VERSION_MINOR);
+ packTLVWord(&packet, 0x0019, CLIENT_VERSION_LESSER);
+ packTLVWord(&packet, 0x001a, CLIENT_VERSION_BUILD);
+ packTLVDWord(&packet, 0x0014, CLIENT_DISTRIBUTION);
+ packTLV(&packet, 0x000f, 0x0002, CLIENT_LANGUAGE);
+ packTLV(&packet, 0x000e, 0x0002, CLIENT_LANGUAGE);
+
+ sendServPacket(&packet);
+}
+
+void requestImage()
+{
+ icq_packet packet;
+
+ SetDlgItemText(hwndRegImageDialog, IDC_NEWUININFO, Translate("Requesting image..."));
+
+ packet.wLen = 4;
+ write_flap(&packet, ICQ_LOGIN_CHAN);
+ packDWord(&packet, 0x00000001);
+ sendServPacket(&packet); // greet login server
+
+ serverPacketInit(&packet, (WORD)(18));
+ packFNACHeaderFull(&packet, ICQ_AUTHORIZATION_FAMILY, ICQ_SIGNON_REQUEST_IMAGE, 0, 0);
+ packTLV(&packet, 0x0001, 0, 0);
+ packDWord(&packet, 0x00000000);
+ sendServPacket(&packet); // request image
+}
+
+void registerUin(char* password, char* image)
+{
+ icq_packet packet;
+ DWORD dwCookie = 0;
+ WORD wTlvLen = 48 + strlen(password) + 3;
+
+ SetDlgItemText(hwndRegImageDialog, IDC_NEWUININFO, Translate("Requesting UIN..."));
+ EnableWindow(GetDlgItem(hwndRegImageDialog, IDC_REGISTER), FALSE);
+
+ packet.wLen = (WORD)(wTlvLen + 14 + 4 + strlen(image));
+
+ //Init packet
+ serverPacketInit(&packet, (WORD)(wTlvLen + 14 + 4 + strlen(image)));
+ packFNACHeaderFull(&packet, ICQ_AUTHORIZATION_FAMILY, ICQ_SIGNON_REGISTRATION_REQ, 0, 0);
+
+
+ //Init TLV
+ packWord(&packet, 0x0001); //TLV type - 01
+ packWord(&packet, wTlvLen); //TLV length
+ //TLV data
+ packDWord(&packet, 0); //Four zeros
+ packWord(&packet, 0x2800); //Subcommand - request new uin
+ packWord(&packet, 0x0300); //Unknown
+ packDWord(&packet, 0); //Four zeros
+ packDWord(&packet, 0); //zeros...
+ packDWord(&packet, dwCookie); //registration cookie
+ packDWord(&packet, dwCookie); //same
+ packDWord(&packet, 0); //zeros
+ packDWord(&packet, 0); //hm... zeros...
+ packDWord(&packet, 0); //it cant be! zeros!
+ packDWord(&packet, 0); //You not beleive, again zeros!:)
+ //Password & ImCode
+ packLEWord(&packet, (WORD)(strlen(password) + 1)); //Password length + null termination
+ packBuffer(&packet, password, (WORD)strlen(password)); //Password
+ packBuffer(&packet, "\0", 1); //Null-terminator
+ packDWord(&packet, dwCookie); //Same cookie again
+ packDWord(&packet, 0xE3070000); //password TLV end, unknown
+
+ //TLV with image code
+ packWord(&packet, 0x0009); //TLV type, 09
+ packWord(&packet, (WORD)strlen(image)); //Packet length
+ packBuffer(&packet, image, (WORD)strlen(image)); //Image code
+
+ sendServPacket(&packet); // send packet - request uin
+}
+
+
+static void handleRegImage(BYTE *buf, WORD wPacketLen, serverthread_info *info)
+{
+ HANDLE hFile;
+ DWORD dwBytesWritten;
+
+ char szTempName[MAX_PATH];
+ char lpPathBuffer[4096];
+ char* szType;
+ WORD wLen;
+
+ //Extracting image type (added 16 may 2007 by chaos.persei only for better debuging)
+ unpackTypedTLV(buf, wPacketLen, 0x0001, NULL, &wLen, &szType);
+ NetLog_Server("Image with protection code recieved, type is %s", szType);
+
+ buf += wLen + 4;
+ wPacketLen -= wLen;
+ buf += 2;
+ wPacketLen -= 4;
+ unpackWord(&buf, &wLen);
+
+ NetLog_Server("Image size: %d bytes", wLen);
+ NetLog_Server("Packet size: %d bytes", wPacketLen);
+
+
+ // Get the temp path
+ GetTempPath(4096, // length of the buffer
+ lpPathBuffer); // buffer for path
+
+ // Create a temporary file.
+ GetTempFileName(lpPathBuffer, // directory for temp files
+ "image", // temp file name prefix
+ 0, // create unique name
+ szTempName); // buffer for name
+
+ hFile = CreateFile((LPTSTR) szTempName, // file to create
+ GENERIC_WRITE, // open for writing
+ 0, // do not share
+ NULL, // default security
+ CREATE_ALWAYS, // overwrite existing
+ FILE_ATTRIBUTE_NORMAL, // normal file
+ NULL); // no attr. template
+
+ WriteFile(hFile, buf, wLen,
+ &dwBytesWritten, NULL);
+
+ CloseHandle(hFile);
+
+ SendDlgItemMessage(hwndRegImageDialog, IDC_UIN_IMAGE, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)(HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szTempName));
+ DeleteFile((LPCSTR)szTempName);
+ icq_regNewUin = 0;
+ SetDlgItemText(hwndRegImageDialog, IDC_NEWUININFO, Translate("Image arrived!\nEnter image code and password, then press \"Register\""));
+ EnableWindow(GetDlgItem(hwndRegImageDialog, IDC_REGISTER), TRUE);
+}
+
+static void handleIcqNewUin(BYTE *buf, WORD wPacketLen, serverthread_info *info)
+{
+ DWORD dwUIN;
+ char szUin[UINMAXLEN], szInfo[1024];
+ HGLOBAL hglbUIN;
+ LPTSTR lptstrUIN;
+
+ buf += 46;
+ unpackLEDWord(&buf, &dwUIN);
+ ltoa(dwUIN, szUin, 10);
+
+ NetLog_Server("New ICQ uin registered and received: %s", szUin);
+
+ if (OpenClipboard(NULL))
+ {
+ EmptyClipboard();
+ hglbUIN = GlobalAlloc(GMEM_MOVEABLE, (strlen(szUin) + 1) * sizeof(TCHAR)) ;
+ lptstrUIN = GlobalLock(hglbUIN);
+ memcpy(lptstrUIN, szUin, strlen(szUin) * sizeof(TCHAR)) ;
+ GlobalUnlock(hglbUIN);
+ SetClipboardData(CF_TEXT, hglbUIN);
+ CloseClipboard();
+ }
+
+ sprintf(szInfo, "%s\n%s: %s\n%s: %s\n%s", Translate("New ICQ UIN registered!"), Translate("UIN"), szUin, Translate("Password"), icq_regpassword, Translate("Look for new UIN in clipboard"));
+
+ SetDlgItemText(hwndRegImageDialog, IDC_NEWUININFO, szInfo);
+
+ icq_regedUin = dwUIN;
+
+ icq_regNewUin = 0;
+ bImageRequested = 0;
+ icq_serverDisconnect(0);
+}
+
+
+static void handleAuthKeyResponse(BYTE *buf, WORD wPacketLen, serverthread_info *info)
+{
+ WORD wKeyLen;
+ char szKey[64] = {0};
+ mir_md5_state_t state;
+ mir_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;
+
+ mir_md5_init(&state);
+ mir_md5_append(&state, (const mir_md5_byte_t*)pwd, info->wAuthKeyLen);
+ mir_md5_finish(&state, digest);
+ }
+
+ mir_md5_init(&state);
+ mir_md5_append(&state, szKey, wKeyLen);
+ mir_md5_append(&state, digest, 16);
+ mir_md5_append(&state, CLIENT_MD5_STRING, sizeof(CLIENT_MD5_STRING)-1);
+ mir_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_s7_sss_mod/families.h b/icqj_s7_sss_mod/families.h new file mode 100644 index 0000000..311634b --- /dev/null +++ b/icqj_s7_sss_mod/families.h @@ -0,0 +1,117 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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;
+
+
+typedef struct message_ack_params_s
+{
+ BYTE bType;
+ DWORD dwUin;
+ DWORD dwMsgID1;
+ DWORD dwMsgID2;
+ directconnect *pDC;
+ WORD wCookie;
+ int msgType;
+ BYTE bFlags;
+} message_ack_params;
+
+extern BOOL bExcludePSD;
+
+extern WORD wClass;
+
+#define MAT_SERVER_ADVANCED 0
+#define MAT_DIRECT 1
+
+/*---------* 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, serverthread_info *info);
+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 requestImage();
+void registerUin(char* password, char* image);
+//void handleRegImage(pBuffer, wBufferLength, info);
+//void handleIcqNewUin(pBuffer, wBufferLength, info);
+void handleLoginReply(unsigned char *buf, WORD datalen, serverthread_info *info);
+
+void handleServUINSettings(int nPort, serverthread_info *info);
+int getPluginTypeIdLen(int nTypeID);
+void packPluginTypeId(icq_packet *packet, int nTypeID);
+int unpackPluginTypeId(BYTE** pBuffer, WORD* pwLen, int *pTypeId, WORD *pFunctionId, BOOL bThruDC);
+
+BOOL 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, message_ack_params *pAckParams);
+
+#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();
+//void inv4inv(HANDLE hContact, int mode);
+//void inv4invCleanUp();
+void CheckSelfRemove();
+void CheckSelfRemoveShutdown();
+
+#endif /* __FAMILIES_H */
diff --git a/icqj_s7_sss_mod/globals.h b/icqj_s7_sss_mod/globals.h new file mode 100644 index 0000000..280e4d1 --- /dev/null +++ b/icqj_s7_sss_mod/globals.h @@ -0,0 +1,147 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 48 $
+// Last change on : $Date: 2007-08-26 16:12:47 +0300 (Вс, 26 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Contains global variables declarations.
+//
+// -----------------------------------------------------------------------------
+
+
+#ifndef __GLOBALS_H
+#define __GLOBALS_H
+
+typedef char uid_str[MAX_PATH];
+
+// Defaults
+#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 gbGatewayMode;
+BYTE gbSecureLogin;
+BYTE gbAimEnabled;
+BYTE gbUtfEnabled;
+WORD gwAnsiCodepage;
+BYTE gbDCMsgEnabled;
+BYTE gbTempVisListEnabled;
+BYTE gbSsiEnabled;
+BYTE gbAvatarsEnabled;
+BYTE gbXStatusEnabled;
+BYTE gbTzerEnabled;
+DWORD MIRANDA_VERSION;
+
+// from icqosc_svcs.c
+int gnCurrentStatus;
+DWORD dwLocalUIN;
+
+char gpszPassword[16];
+BYTE gbRememberPwd;
+
+BYTE gbUnicodeAPI;
+BYTE gbUnicodeCore;
+
+// 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;
+BYTE gbCustomCapEnabled;
+BYTE gbHideIdEnabled;
+BYTE gbRTFEnabled;
+BYTE gbVerEnabled;
+BYTE gbScan;
+
+
+DWORD gdwFP1;
+DWORD gdwFP2;
+DWORD gdwFP3;
+
+DWORD gdwUpdateThreshold;
+
+// from fam_04message.c
+typedef struct icq_mode_messages_s
+{
+ char* szOnline;
+ char* szAway;
+ char* szNa;
+ char* szDnd;
+ char* szOccupied;
+ char* szFfc;
+} icq_mode_messages;
+
+icq_mode_messages modeMsgs;
+CRITICAL_SECTION modeMsgsMutex;
+
+struct LIST_INTERFACE listInterface;
+SortedList *lstCustomCaps;
+
+
+
+#endif /* __GLOBALS_H */
diff --git a/icqj_s7_sss_mod/guids.h b/icqj_s7_sss_mod/guids.h new file mode 100644 index 0000000..1053a83 --- /dev/null +++ b/icqj_s7_sss_mod/guids.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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_SRV_RELAY_FMT = {MCAP_SRV_RELAY_FMT_s};
+static plugin_guid MCAP_REVERSE_DC_REQ = {MCAP_REVERSE_DC_REQ_s};
+static plugin_guid MCAP_FILE_TRANSFER = {MCAP_FILE_TRANSFER_s};
+static plugin_guid MCAP_CONTACTS = {MCAP_CONTACTS_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_SMS_MESSAGE = {MGTYPE_SMS_MESSAGE_s};
+static plugin_guid MGTYPE_XTRAZ_SCRIPT = {MGTYPE_XTRAZ_SCRIPT_s};
+static plugin_guid MGTYPE_TZER_MESSAGE = {MGTYPE_TZER_MESSAGE_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_s7_sss_mod/i18n.c b/icqj_s7_sss_mod/i18n.c new file mode 100644 index 0000000..eefb40f --- /dev/null +++ b/icqj_s7_sss_mod/i18n.c @@ -0,0 +1,520 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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* 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;
+
+ if (!pszInput) return 0;
+
+ 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_static(const WCHAR *unicode, unsigned char *utf8, size_t utf_size)
+{
+ int index = 0;
+ unsigned int out_index = 0;
+ unsigned short c;
+
+ c = unicode[index++];
+ while (c)
+ {
+ if (c < 0x080)
+ {
+ if (out_index + 1 >= utf_size) break;
+ utf8[out_index++] = (unsigned char)c;
+ }
+ else if (c < 0x800)
+ {
+ if (out_index + 2 >= utf_size) break;
+ utf8[out_index++] = 0xc0 | (c >> 6);
+ utf8[out_index++] = 0x80 | (c & 0x3f);
+ }
+ else
+ {
+ if (out_index + 3 >= utf_size) break;
+ utf8[out_index++] = 0xe0 | (c >> 12);
+ utf8[out_index++] = 0x80 | ((c >> 6) & 0x3f);
+ utf8[out_index++] = 0x80 | (c & 0x3f);
+ }
+ c = unicode[index++];
+ }
+ utf8[out_index] = 0x00;
+
+ return utf8;
+}
+
+
+
+unsigned char *make_utf8_string(const WCHAR *unicode)
+{
+ int size = 0;
+ int index = 0;
+ unsigned char* out;
+ unsigned short c;
+
+ if (!unicode) return NULL;
+
+ /* 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;
+ else
+ return make_utf8_string_static(unicode, out, size + 1);
+}
+
+
+
+WCHAR *make_unicode_string_static(const unsigned char *utf8, WCHAR *unicode, size_t unicode_len)
+{
+ int index = 0;
+ unsigned int out_index = 0;
+ unsigned char c;
+
+ c = utf8[index++];
+ while (c)
+ {
+ if (out_index + 1 >= unicode_len) break;
+ if((c & 0x80) == 0)
+ {
+ unicode[out_index++] = c;
+ }
+ else if((c & 0xe0) == 0xe0)
+ {
+ unicode[out_index] = (c & 0x1F) << 12;
+ c = utf8[index++];
+ unicode[out_index] |= (c & 0x3F) << 6;
+ c = utf8[index++];
+ unicode[out_index++] |= (c & 0x3F);
+ }
+ else
+ {
+ unicode[out_index] = (c & 0x3F) << 6;
+ c = utf8[index++];
+ unicode[out_index++] |= (c & 0x3F);
+ }
+ c = utf8[index++];
+ }
+ unicode[out_index] = 0;
+
+ return unicode;
+}
+
+
+
+WCHAR *make_unicode_string(const unsigned char *utf8)
+{
+ int size = 0, index = 0;
+ WCHAR *out;
+ unsigned char c;
+
+ if (!utf8) return NULL;
+
+ /* 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*)SAFE_MALLOC((size + 1) * sizeof(WCHAR));
+ if (out == NULL)
+ return NULL;
+ else
+ return make_unicode_string_static(utf8, out, size + 1);
+}
+
+
+
+int utf8_encode(const char *from, char **to)
+{
+ WCHAR *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*)_alloca((wchars + 1) * sizeof(WCHAR));
+ 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 = NULL;
+
+ if (strlennull(szAnsi))
+ {
+ utf8_encode(szAnsi, &szUtf);
+
+ return szUtf;
+ }
+ else
+ return null_strdup("");
+}
+
+
+
+char *ansi_to_utf8_codepage(const char *szAnsi, WORD wCp)
+{
+ WCHAR *unicode;
+ int wchars = strlennull(szAnsi);
+
+ unicode = (WCHAR*)_alloca((wchars + 1) * sizeof(WCHAR));
+ ZeroMemory(unicode, (wchars + 1)*sizeof(WCHAR));
+
+ MultiByteToWideChar(wCp, MB_PRECOMPOSED, szAnsi, wchars, unicode, wchars);
+
+ return make_utf8_string(unicode);
+}
+
+
+
+// Returns 0 on error, 1 on success
+int utf8_decode_codepage(const char *from, char **to, WORD wCp)
+{
+ 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(wCp, 0, wszTemp, -1, *to, inlen+1, NULL, NULL))
+ {
+ nResult = 1;
+ }
+ else
+ {
+ SAFE_FREE(&(*to));
+ }
+ }
+ }
+ else
+ {
+ WCHAR *unicode;
+ int chars;
+ int err;
+
+ chars = strlennull(from) + 1;
+ unicode = (WCHAR*)_alloca(chars * sizeof(WCHAR));
+ make_unicode_string_static(from, unicode, chars);
+
+ chars = WideCharToMultiByte(wCp, WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL);
+
+ if(chars == 0)
+ {
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+ 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");
+ return 0;
+ }
+
+ err = WideCharToMultiByte(wCp, WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL);
+ if (err != chars)
+ {
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+ SAFE_FREE(to);
+ return 0;
+ }
+
+ nResult = 1;
+ }
+
+ return nResult;
+}
+
+
+
+// Standard version with current codepage
+int utf8_decode(const char *from, char **to)
+{
+ return utf8_decode_codepage(from, to, CP_ACP);
+}
+
+
+
+// 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
+ {
+ int chars = strlennull(from) + 1;
+ WCHAR *unicode = (WCHAR*)_alloca(chars * sizeof(WCHAR));
+
+ make_unicode_string_static(from, unicode, chars);
+
+ WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, to, to_size, NULL, NULL);
+
+ nResult = 1;
+ }
+
+ return nResult;
+}
+
+
+
+char *tchar_to_utf8(const TCHAR *szTxt)
+{
+ if (gbUnicodeAPI)
+ return make_utf8_string((WCHAR*)szTxt);
+ else
+ return ansi_to_utf8((char*)szTxt);
+}
+
+
+
+char *mtchar_to_utf8(const TCHAR *szTxt)
+{
+ if (gbUnicodeCore)
+ return make_utf8_string((WCHAR*)szTxt);
+ else
+ return ansi_to_utf8((char*)szTxt);
+}
diff --git a/icqj_s7_sss_mod/i18n.h b/icqj_s7_sss_mod/i18n.h new file mode 100644 index 0000000..c28735d --- /dev/null +++ b/icqj_s7_sss_mod/i18n.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,2006,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Helper functions to convert text messages between different character sets.
+//
+// -----------------------------------------------------------------------------
+
+
+
+BOOL IsUSASCII(const unsigned char *pBuffer, int nSize);
+BOOL IsUnicodeAscii(const WCHAR *pBuffer, int nSize);
+int UTF8_IsValid(const unsigned char* pszInput);
+
+char* detect_decode_utf8(const char *from);
+
+WCHAR *make_unicode_string(const unsigned char *utf8);
+WCHAR *make_unicode_string_static(const unsigned char *utf8, WCHAR *unicode, size_t unicode_len);
+
+unsigned char *make_utf8_string(const WCHAR *unicode);
+unsigned char *make_utf8_string_static(const WCHAR *unicode, unsigned char *utf8, size_t utf_size);
+
+char *ansi_to_utf8(const char *szAnsi);
+char *ansi_to_utf8_codepage(const char *szAnsi, WORD wCp);
+char *tchar_to_utf8(const TCHAR *szTxt);
+char *mtchar_to_utf8(const TCHAR *szTxt);
+
+int utf8_encode(const char *from, char **to);
+int utf8_decode(const char *from, char **to);
+int utf8_decode_codepage(const char *from, char **to, WORD wCp);
+int utf8_decode_static(const char *from, char *to, int to_size);
+
+void InitI18N(void);
diff --git a/icqj_s7_sss_mod/iconlib.c b/icqj_s7_sss_mod/iconlib.c new file mode 100644 index 0000000..36aa1d1 --- /dev/null +++ b/icqj_s7_sss_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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 51 $
+// Last change on : $Date: 2007-08-30 23:46:51 +0300 (Чт, 30 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Support for IcoLib plug-in
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_icolib.h"
+
+
+void InitIconLib()
+{
+ char str[MAX_PATH], proto[MAX_PATH], lib[MAX_PATH];
+
+ ICQTranslateUtfStatic(gpszICQProtoName, proto, MAX_PATH);
+
+ GetModuleFileName(hInst, lib, MAX_PATH);
+
+ IconLibDefine(ICQTranslateUtfStatic("Protocol icon", str, MAX_PATH), proto, "proto", NULL, lib, -IDI_ICQ);
+ IconLibDefine(ICQTranslateUtfStatic("Request authorization", str, MAX_PATH), proto, "req_auth", NULL, lib, -IDI_AUTH);
+ IconLibDefine(ICQTranslateUtfStatic("Grant authorization", str, MAX_PATH), proto, "grant_auth", NULL, lib, -IDI_GRANT);
+ IconLibDefine(ICQTranslateUtfStatic("Revoke authorization", str, MAX_PATH), proto, "revoke_auth", NULL, lib, -IDI_REMOVE);
+ IconLibDefine(ICQTranslateUtfStatic("Add to server list", str, MAX_PATH), proto, "add_to_server", NULL, lib, -IDI_SERVLIST_ADD);
+ IconLibDefine(ICQTranslateUtfStatic("Send tZer", str, MAX_PATH), proto, "send_tzer", NULL, lib, -IDI_SEND_TZER);
+ IconLibDefine(ICQTranslateUtfStatic("Always visible", str, MAX_PATH), proto, "set_vis", NULL, lib, -IDI_SET_VIS);
+ IconLibDefine(ICQTranslateUtfStatic("Never visible", str, MAX_PATH), proto, "set_invis", NULL, lib, -IDI_SET_INVIS);
+ IconLibDefine(ICQTranslateUtfStatic("Incognito Request", str, MAX_PATH), proto, "incognito", NULL, lib, -IDI_INCOGNITO_R);
+ IconLibDefine(ICQTranslateUtfStatic("Scan", str, MAX_PATH), proto, "scan", NULL, lib, -IDI_SCAN);
+ IconLibDefine(ICQTranslateUtfStatic("Scan start", str, MAX_PATH), proto, "start", NULL, lib, -IDI_START);
+ IconLibDefine(ICQTranslateUtfStatic("Scan stop", str, MAX_PATH), proto, "stop", NULL, lib, -IDI_STOP);
+ IconLibDefine(ICQTranslateUtfStatic("Scan pause", str, MAX_PATH), proto, "pause", NULL, lib, -IDI_PAUSE);
+ IconLibDefine(ICQTranslateUtfStatic("Hidden", str, MAX_PATH), proto, "was_found", NULL, lib, -IDI_HIDDEN);
+ IconLibDefine(ICQTranslateUtfStatic("Manage Server List", str, MAX_PATH), proto, "servlist", NULL, lib, -IDI_LIST);
+ IconLibDefine(ICQTranslateUtfStatic("Advanced Features Menu", str, MAX_PATH), proto, "privacy", NULL, lib, -IDI_PRIVACY);
+ IconLibDefine(ICQTranslateUtfStatic("Disable menu item", str, MAX_PATH), proto, "dot", NULL, lib, -IDI_DOT);
+ IconLibDefine(ICQTranslateUtfStatic("Enable menu item", str, MAX_PATH), proto, "check", NULL, lib, -IDI_CHECK);
+
+ // nothing
+}
+
+
+
+HANDLE IconLibDefine(const char* desc, const char* section, const char* ident, HICON icon, const char* def_file, int def_idx)
+{
+ SKINICONDESC sid = {0};
+ char szTemp[MAX_PATH + 128];
+ HANDLE hIcon;
+
+ sid.cbSize = SKINICONDESC_SIZE;
+ sid.pwszSection = make_unicode_string(section);
+ sid.pwszDescription = make_unicode_string(ICQTranslateUtfStatic(desc, szTemp, MAX_PATH));
+ sid.flags = SIDF_UNICODE;
+
+ 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;
+
+ hIcon = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ SAFE_FREE(&sid.pwszSection);
+ SAFE_FREE(&sid.pwszDescription);
+
+ return hIcon;
+}
+
+
+
+HICON IconLibGetIcon(const char* ident)
+{
+ char szTemp[MAX_PATH + 128];
+
+ null_snprintf(szTemp, sizeof(szTemp), "%s_%s", gpszICQProtoName, ident);
+
+ return (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szTemp);
+}
+
+
+
+void IconLibReleaseIcon(const char* ident)
+{
+ char szTemp[MAX_PATH + 128];
+
+ null_snprintf(szTemp, sizeof(szTemp), "%s_%s", gpszICQProtoName, ident);
+ CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)szTemp);
+}
+
+
+
+HANDLE IconLibHookIconsChanged(MIRANDAHOOK hook)
+{
+ return HookEvent(ME_SKIN2_ICONSCHANGED, hook);
+}
diff --git a/icqj_s7_sss_mod/iconlib.h b/icqj_s7_sss_mod/iconlib.h new file mode 100644 index 0000000..5928a7e --- /dev/null +++ b/icqj_s7_sss_mod/iconlib.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,2006,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Headers for IconLib Plugin / module support
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICONLIB_H
+#define __ICONLIB_H
+
+
+extern void InitIconLib();
+
+HANDLE IconLibDefine(const char* desc, const char* section, const char* ident, HICON icon, const char* def_file, int def_idx);
+HICON IconLibGetIcon(const char* ident);
+void IconLibReleaseIcon(const char* ident);
+HANDLE IconLibHookIconsChanged(MIRANDAHOOK hook);
+
+#endif /* __ICONLIB_H */
diff --git a/icqj_s7_sss_mod/icons_pack/ICONS.APS b/icqj_s7_sss_mod/icons_pack/ICONS.APS Binary files differnew file mode 100644 index 0000000..fde1daa --- /dev/null +++ b/icqj_s7_sss_mod/icons_pack/ICONS.APS diff --git a/icqj_s7_sss_mod/icons_pack/ICONS.dep b/icqj_s7_sss_mod/icons_pack/ICONS.dep new file mode 100644 index 0000000..cd8073b --- /dev/null +++ b/icqj_s7_sss_mod/icons_pack/ICONS.dep @@ -0,0 +1,41 @@ +# 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"\
+ "..\icos\xstatus33.ico"\
+ "..\icos\xstatus34.ico"\
+ "..\icos\xstatus35.ico"\
+ "..\icos\xstatus36.ico"\
+ "..\icos\xstatus37.ico"\
+
diff --git a/icqj_s7_sss_mod/icons_pack/ICONS.dsp b/icqj_s7_sss_mod/icons_pack/ICONS.dsp new file mode 100644 index 0000000..b15c478 --- /dev/null +++ b/icqj_s7_sss_mod/icons_pack/ICONS.dsp @@ -0,0 +1,211 @@ +# 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\Icons\xstatus_ICQ.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\xstatus31.ico
+# End Source File
+# Begin Source File
+SOURCE=..\icos\xstatus32.ico
+# End Source File
+# Begin Source File
+SOURCE=..\icos\xstatus33.ico
+# End Source File
+# Begin Source File
+SOURCE=..\icos\xstatus34.ico
+# End Source File
+# Begin Source File
+SOURCE=..\icos\xstatus35.ico
+# End Source File
+# Begin Source File
+SOURCE=..\icos\xstatus36.ico
+# End Source File
+# Begin Source File
+SOURCE=..\icos\xstatus37.ico
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/icqj_s7_sss_mod/icons_pack/ICONS.dsw b/icqj_s7_sss_mod/icons_pack/ICONS.dsw new file mode 100644 index 0000000..17255a8 --- /dev/null +++ b/icqj_s7_sss_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_s7_sss_mod/icons_pack/ICONS.mak b/icqj_s7_sss_mod/icons_pack/ICONS.mak new file mode 100644 index 0000000..69dfa71 --- /dev/null +++ b/icqj_s7_sss_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\Icons\xstatus_ICQ.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ICONS.res"
+ -@erase "$(OUTDIR)\xstatus_icons.exp"
+ -@erase "$(OUTDIR)\xstatus_icons.lib"
+ -@erase "$(OUTDIR)\xstatus_icons.pdb"
+ -@erase "..\..\..\bin\release\Icons\xstatus_ICQ.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\Icons\xstatus_ICQ.dll" /implib:"$(OUTDIR)\xstatus_icons.lib" /noentry /ALIGN:4096 /ignore:4108
+LINK32_OBJS= \
+ "$(INTDIR)\ICONS.res"
+
+"..\..\..\bin\release\Icons\xstatus_ICQ.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_s7_sss_mod/icons_pack/ICONS.rc b/icqj_s7_sss_mod/icons_pack/ICONS.rc new file mode 100644 index 0000000..ebcf2f7 --- /dev/null +++ b/icqj_s7_sss_mod/icons_pack/ICONS.rc @@ -0,0 +1,130 @@ +// 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
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\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"
+//Add by BeteTest
+IDI_XSTATUS33 ICON "..\\icos\\xstatus33.ico"
+IDI_XSTATUS34 ICON "..\\icos\\xstatus34.ico"
+IDI_XSTATUS35 ICON "..\\icos\\xstatus35.ico"
+IDI_XSTATUS36 ICON "..\\icos\\xstatus36.ico"
+IDI_XSTATUS37 ICON "..\\icos\\xstatus37.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_s7_sss_mod/icons_pack/ICONS.vcproj b/icqj_s7_sss_mod/icons_pack/ICONS.vcproj new file mode 100644 index 0000000..c8f224c --- /dev/null +++ b/icqj_s7_sss_mod/icons_pack/ICONS.vcproj @@ -0,0 +1,502 @@ +<?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>
+ <Configuration
+ Name="Release (static)|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ 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>
+ <Configuration
+ Name="Release(static)|Win32"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <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="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="..\icos\ico00001.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\ico00002.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>
+ <File
+ RelativePath="..\icos\xstatus33.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus34.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus35.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus36.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icos\xstatus37.ico"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/icqj_s7_sss_mod/icons_pack/resource.h b/icqj_s7_sss_mod/icons_pack/resource.h new file mode 100644 index 0000000..4e163cd --- /dev/null +++ b/icqj_s7_sss_mod/icons_pack/resource.h @@ -0,0 +1,237 @@ +//{{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 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 IDI_XSTATUS33 233//add By BeteTest
+#define IDI_XSTATUS34 234//add By BeteTest
+#define IDI_XSTATUS35 235//add By BeteTest
+#define IDI_XSTATUS36 236//add By BeteTest
+#define IDI_XSTATUS37 237//add By BeteTest
+#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 123
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1026
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/icqj_s7_sss_mod/icos/arrow.ico b/icqj_s7_sss_mod/icos/arrow.ico Binary files differnew file mode 100644 index 0000000..aefec22 --- /dev/null +++ b/icqj_s7_sss_mod/icos/arrow.ico diff --git a/icqj_s7_sss_mod/icos/auth_ask.ico b/icqj_s7_sss_mod/icos/auth_ask.ico Binary files differnew file mode 100644 index 0000000..d8879d1 --- /dev/null +++ b/icqj_s7_sss_mod/icos/auth_ask.ico diff --git a/icqj_s7_sss_mod/icos/auth_grant.ico b/icqj_s7_sss_mod/icos/auth_grant.ico Binary files differnew file mode 100644 index 0000000..d4cd35e --- /dev/null +++ b/icqj_s7_sss_mod/icos/auth_grant.ico diff --git a/icqj_s7_sss_mod/icos/auth_revoke.ico b/icqj_s7_sss_mod/icos/auth_revoke.ico Binary files differnew file mode 100644 index 0000000..9639a9c --- /dev/null +++ b/icqj_s7_sss_mod/icos/auth_revoke.ico diff --git a/icqj_s7_sss_mod/icos/check.ico b/icqj_s7_sss_mod/icos/check.ico Binary files differnew file mode 100644 index 0000000..43ed35b --- /dev/null +++ b/icqj_s7_sss_mod/icos/check.ico diff --git a/icqj_s7_sss_mod/icos/dc.ICO b/icqj_s7_sss_mod/icos/dc.ICO Binary files differnew file mode 100644 index 0000000..1bdc86e --- /dev/null +++ b/icqj_s7_sss_mod/icos/dc.ICO diff --git a/icqj_s7_sss_mod/icos/dot.ico b/icqj_s7_sss_mod/icos/dot.ico Binary files differnew file mode 100644 index 0000000..0a4b202 --- /dev/null +++ b/icqj_s7_sss_mod/icos/dot.ico diff --git a/icqj_s7_sss_mod/icos/hidden.ico b/icqj_s7_sss_mod/icos/hidden.ico Binary files differnew file mode 100644 index 0000000..fc73c3d --- /dev/null +++ b/icqj_s7_sss_mod/icos/hidden.ico diff --git a/icqj_s7_sss_mod/icos/icq.ico b/icqj_s7_sss_mod/icos/icq.ico Binary files differnew file mode 100644 index 0000000..69229d9 --- /dev/null +++ b/icqj_s7_sss_mod/icos/icq.ico diff --git a/icqj_s7_sss_mod/icos/incognito_request.ico b/icqj_s7_sss_mod/icos/incognito_request.ico Binary files differnew file mode 100644 index 0000000..c531572 --- /dev/null +++ b/icqj_s7_sss_mod/icos/incognito_request.ico diff --git a/icqj_s7_sss_mod/icos/list.ico b/icqj_s7_sss_mod/icos/list.ico Binary files differnew file mode 100644 index 0000000..6abdf55 --- /dev/null +++ b/icqj_s7_sss_mod/icos/list.ico diff --git a/icqj_s7_sss_mod/icos/pause.ico b/icqj_s7_sss_mod/icos/pause.ico Binary files differnew file mode 100644 index 0000000..ebfb7c7 --- /dev/null +++ b/icqj_s7_sss_mod/icos/pause.ico diff --git a/icqj_s7_sss_mod/icos/privacy.ico b/icqj_s7_sss_mod/icos/privacy.ico Binary files differnew file mode 100644 index 0000000..bad6f55 --- /dev/null +++ b/icqj_s7_sss_mod/icos/privacy.ico diff --git a/icqj_s7_sss_mod/icos/scan.ico b/icqj_s7_sss_mod/icos/scan.ico Binary files differnew file mode 100644 index 0000000..b326177 --- /dev/null +++ b/icqj_s7_sss_mod/icos/scan.ico diff --git a/icqj_s7_sss_mod/icos/set_invis.ico b/icqj_s7_sss_mod/icos/set_invis.ico Binary files differnew file mode 100644 index 0000000..7ecbd97 --- /dev/null +++ b/icqj_s7_sss_mod/icos/set_invis.ico diff --git a/icqj_s7_sss_mod/icos/set_vis.ico b/icqj_s7_sss_mod/icos/set_vis.ico Binary files differnew file mode 100644 index 0000000..32b1035 --- /dev/null +++ b/icqj_s7_sss_mod/icos/set_vis.ico diff --git a/icqj_s7_sss_mod/icos/srvlist_add.ico b/icqj_s7_sss_mod/icos/srvlist_add.ico Binary files differnew file mode 100644 index 0000000..9f526c7 --- /dev/null +++ b/icqj_s7_sss_mod/icos/srvlist_add.ico diff --git a/icqj_s7_sss_mod/icos/start.ico b/icqj_s7_sss_mod/icos/start.ico Binary files differnew file mode 100644 index 0000000..7ab7d11 --- /dev/null +++ b/icqj_s7_sss_mod/icos/start.ico diff --git a/icqj_s7_sss_mod/icos/stop.ico b/icqj_s7_sss_mod/icos/stop.ico Binary files differnew file mode 100644 index 0000000..4de89b1 --- /dev/null +++ b/icqj_s7_sss_mod/icos/stop.ico diff --git a/icqj_s7_sss_mod/icos/tzer.ico b/icqj_s7_sss_mod/icos/tzer.ico Binary files differnew file mode 100644 index 0000000..c4c3af6 --- /dev/null +++ b/icqj_s7_sss_mod/icos/tzer.ico diff --git a/icqj_s7_sss_mod/icos/xstatus01.ico b/icqj_s7_sss_mod/icos/xstatus01.ico Binary files differnew file mode 100644 index 0000000..6bc9d77 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus01.ico diff --git a/icqj_s7_sss_mod/icos/xstatus02.ico b/icqj_s7_sss_mod/icos/xstatus02.ico Binary files differnew file mode 100644 index 0000000..6de8459 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus02.ico diff --git a/icqj_s7_sss_mod/icos/xstatus03.ico b/icqj_s7_sss_mod/icos/xstatus03.ico Binary files differnew file mode 100644 index 0000000..bdd63a8 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus03.ico diff --git a/icqj_s7_sss_mod/icos/xstatus04.ico b/icqj_s7_sss_mod/icos/xstatus04.ico Binary files differnew file mode 100644 index 0000000..9fe9392 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus04.ico diff --git a/icqj_s7_sss_mod/icos/xstatus05.ico b/icqj_s7_sss_mod/icos/xstatus05.ico Binary files differnew file mode 100644 index 0000000..7d17bdd --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus05.ico diff --git a/icqj_s7_sss_mod/icos/xstatus06.ico b/icqj_s7_sss_mod/icos/xstatus06.ico Binary files differnew file mode 100644 index 0000000..9bad185 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus06.ico diff --git a/icqj_s7_sss_mod/icos/xstatus07.ico b/icqj_s7_sss_mod/icos/xstatus07.ico Binary files differnew file mode 100644 index 0000000..16dbc21 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus07.ico diff --git a/icqj_s7_sss_mod/icos/xstatus08.ico b/icqj_s7_sss_mod/icos/xstatus08.ico Binary files differnew file mode 100644 index 0000000..d818ff0 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus08.ico diff --git a/icqj_s7_sss_mod/icos/xstatus09.ico b/icqj_s7_sss_mod/icos/xstatus09.ico Binary files differnew file mode 100644 index 0000000..49d68e9 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus09.ico diff --git a/icqj_s7_sss_mod/icos/xstatus10.ico b/icqj_s7_sss_mod/icos/xstatus10.ico Binary files differnew file mode 100644 index 0000000..188119e --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus10.ico diff --git a/icqj_s7_sss_mod/icos/xstatus11.ico b/icqj_s7_sss_mod/icos/xstatus11.ico Binary files differnew file mode 100644 index 0000000..abe2e4b --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus11.ico diff --git a/icqj_s7_sss_mod/icos/xstatus12.ico b/icqj_s7_sss_mod/icos/xstatus12.ico Binary files differnew file mode 100644 index 0000000..051f117 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus12.ico diff --git a/icqj_s7_sss_mod/icos/xstatus13.ico b/icqj_s7_sss_mod/icos/xstatus13.ico Binary files differnew file mode 100644 index 0000000..6784045 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus13.ico diff --git a/icqj_s7_sss_mod/icos/xstatus14.ico b/icqj_s7_sss_mod/icos/xstatus14.ico Binary files differnew file mode 100644 index 0000000..d34b9fe --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus14.ico diff --git a/icqj_s7_sss_mod/icos/xstatus15.ico b/icqj_s7_sss_mod/icos/xstatus15.ico Binary files differnew file mode 100644 index 0000000..5942549 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus15.ico diff --git a/icqj_s7_sss_mod/icos/xstatus16.ico b/icqj_s7_sss_mod/icos/xstatus16.ico Binary files differnew file mode 100644 index 0000000..96e2545 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus16.ico diff --git a/icqj_s7_sss_mod/icos/xstatus17.ico b/icqj_s7_sss_mod/icos/xstatus17.ico Binary files differnew file mode 100644 index 0000000..d73be87 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus17.ico diff --git a/icqj_s7_sss_mod/icos/xstatus18.ico b/icqj_s7_sss_mod/icos/xstatus18.ico Binary files differnew file mode 100644 index 0000000..b4257ce --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus18.ico diff --git a/icqj_s7_sss_mod/icos/xstatus19.ico b/icqj_s7_sss_mod/icos/xstatus19.ico Binary files differnew file mode 100644 index 0000000..b45a166 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus19.ico diff --git a/icqj_s7_sss_mod/icos/xstatus20.ico b/icqj_s7_sss_mod/icos/xstatus20.ico Binary files differnew file mode 100644 index 0000000..99094f8 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus20.ico diff --git a/icqj_s7_sss_mod/icos/xstatus21.ico b/icqj_s7_sss_mod/icos/xstatus21.ico Binary files differnew file mode 100644 index 0000000..f9510f1 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus21.ico diff --git a/icqj_s7_sss_mod/icos/xstatus22.ico b/icqj_s7_sss_mod/icos/xstatus22.ico Binary files differnew file mode 100644 index 0000000..fffe979 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus22.ico diff --git a/icqj_s7_sss_mod/icos/xstatus23.ico b/icqj_s7_sss_mod/icos/xstatus23.ico Binary files differnew file mode 100644 index 0000000..66db1ef --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus23.ico diff --git a/icqj_s7_sss_mod/icos/xstatus24.ico b/icqj_s7_sss_mod/icos/xstatus24.ico Binary files differnew file mode 100644 index 0000000..df468f9 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus24.ico diff --git a/icqj_s7_sss_mod/icos/xstatus25.ico b/icqj_s7_sss_mod/icos/xstatus25.ico Binary files differnew file mode 100644 index 0000000..2cbb2ad --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus25.ico diff --git a/icqj_s7_sss_mod/icos/xstatus26.ico b/icqj_s7_sss_mod/icos/xstatus26.ico Binary files differnew file mode 100644 index 0000000..7b3d89f --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus26.ico diff --git a/icqj_s7_sss_mod/icos/xstatus27.ico b/icqj_s7_sss_mod/icos/xstatus27.ico Binary files differnew file mode 100644 index 0000000..1ae5ac5 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus27.ico diff --git a/icqj_s7_sss_mod/icos/xstatus28.ico b/icqj_s7_sss_mod/icos/xstatus28.ico Binary files differnew file mode 100644 index 0000000..c8ca9ff --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus28.ico diff --git a/icqj_s7_sss_mod/icos/xstatus29.ico b/icqj_s7_sss_mod/icos/xstatus29.ico Binary files differnew file mode 100644 index 0000000..f8be002 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus29.ico diff --git a/icqj_s7_sss_mod/icos/xstatus30.ico b/icqj_s7_sss_mod/icos/xstatus30.ico Binary files differnew file mode 100644 index 0000000..02f6f28 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus30.ico diff --git a/icqj_s7_sss_mod/icos/xstatus31.ico b/icqj_s7_sss_mod/icos/xstatus31.ico Binary files differnew file mode 100644 index 0000000..da441df --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus31.ico diff --git a/icqj_s7_sss_mod/icos/xstatus32.ico b/icqj_s7_sss_mod/icos/xstatus32.ico Binary files differnew file mode 100644 index 0000000..ac91a82 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus32.ico diff --git a/icqj_s7_sss_mod/icos/xstatus33.ico b/icqj_s7_sss_mod/icos/xstatus33.ico Binary files differnew file mode 100644 index 0000000..86dde10 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus33.ico diff --git a/icqj_s7_sss_mod/icos/xstatus34.ico b/icqj_s7_sss_mod/icos/xstatus34.ico Binary files differnew file mode 100644 index 0000000..943a262 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus34.ico diff --git a/icqj_s7_sss_mod/icos/xstatus35.ico b/icqj_s7_sss_mod/icos/xstatus35.ico Binary files differnew file mode 100644 index 0000000..885c6d2 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus35.ico diff --git a/icqj_s7_sss_mod/icos/xstatus36.ico b/icqj_s7_sss_mod/icos/xstatus36.ico Binary files differnew file mode 100644 index 0000000..5a2ebca --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus36.ico diff --git a/icqj_s7_sss_mod/icos/xstatus37.ico b/icqj_s7_sss_mod/icos/xstatus37.ico Binary files differnew file mode 100644 index 0000000..62ca197 --- /dev/null +++ b/icqj_s7_sss_mod/icos/xstatus37.ico diff --git a/icqj_s7_sss_mod/icq_advsearch.c b/icqj_s7_sss_mod/icq_advsearch.c new file mode 100644 index 0000000..40f49ae --- /dev/null +++ b/icqj_s7_sss_mod/icq_advsearch.c @@ -0,0 +1,212 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/icq_advsearch.h b/icqj_s7_sss_mod/icq_advsearch.h new file mode 100644 index 0000000..85997c9 --- /dev/null +++ b/icqj_s7_sss_mod/icq_advsearch.h @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/icq_avatar.c b/icqj_s7_sss_mod/icq_avatar.c new file mode 100644 index 0000000..82af06c --- /dev/null +++ b/icqj_s7_sss_mod/icq_avatar.c @@ -0,0 +1,1552 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 39 $
+// Last change on : $Date: 2007-08-10 11:01:07 +0300 (Пт, 10 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Manages Avatar connection, provides internal service for handling avatars
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_folders.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;
+ //
+ rates* rates;
+} 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;
+ DWORD timeOut;
+ void *pNext; // invalid, but reused - spare realloc
+} avatarrequest;
+
+#define ART_GET 1
+#define ART_UPLOAD 2
+#define ART_BLOCK 4
+
+
+BYTE hashEmptyAvatar[9] = {0x00, 0x01, 0x00, 0x05, 0x02, 0x01, 0xD2, 0x04, 0x72};
+
+avatarthreadstartinfo* currentAvatarThread;
+int pendingAvatarsStart = 1;
+static avatarrequest* pendingRequests = NULL;
+
+HANDLE hAvatarsFolder;
+int bAvatarsFolderInited = FALSE;
+
+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);
+
+
+static void FreeAvatarRequest(avatarrequest **request)
+{
+ avatarrequest *ar = *request;
+
+ if (ar)
+ {
+ switch (ar->type)
+ {
+ case ART_UPLOAD:
+ SAFE_FREE(&ar->pData);
+ break;
+ case ART_GET:
+ SAFE_FREE(&ar->hash);
+ SAFE_FREE(&ar->szUid);
+ SAFE_FREE(&ar->szFile);
+ break;
+ case ART_BLOCK:
+ break;
+ }
+ }
+ SAFE_FREE(request);
+}
+
+
+
+static void AddAvatarRequestToQueue(avatarrequest *request)
+{
+ request->pNext = pendingRequests;
+ pendingRequests = request;
+}
+
+
+
+static void RemoveAvatarRequestFromQueue(avatarrequest *request)
+{
+ void **par = &pendingRequests;
+ avatarrequest *ar = pendingRequests;
+
+ while (ar)
+ {
+ if (ar == request)
+ { // found it, remove
+ *par = ar->pNext;
+ break;
+ }
+ par = &ar->pNext;
+ ar = ar->pNext;
+ }
+}
+
+
+
+static avatarrequest *ReleaseAvatarRequestInQueue(avatarrequest *request)
+{
+ avatarrequest *pNext = request->pNext;
+
+ RemoveAvatarRequestFromQueue(request);
+ FreeAvatarRequest(&request);
+
+ return pNext;
+}
+
+
+
+void InitAvatars()
+{
+ if (!bAvatarsFolderInited)
+ { // do it only once
+ bAvatarsFolderInited = TRUE;
+
+ if (ServiceExists(MS_FOLDERS_REGISTER_PATH))
+ { // check if it does make sense
+ char szPath[MAX_PATH];
+
+ null_snprintf(szPath, MAX_PATH, "%s\\%s\\", PROFILE_PATH, gpszICQProtoName);
+
+ hAvatarsFolder = FoldersRegisterCustomPath(gpszICQProtoName, "Avatars Cache", szPath);
+ }
+ }
+}
+
+
+
+char* loadMyAvatarFileName()
+{
+ DBVARIANT dbvFile = {0};
+
+ if (!ICQGetContactSettingString(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;
+ FOLDERSGETDATA fgd = {0};
+
+ InitAvatars();
+
+ fgd.cbSize = sizeof(FOLDERSGETDATA);
+ fgd.nMaxPathSize = cbLen;
+ fgd.szPath = pszDest;
+ if (CallService(MS_FOLDERS_GET_PATH, (WPARAM)hAvatarsFolder, (LPARAM)&fgd))
+ {
+ CallService(MS_DB_GETPROFILEPATH, cbLen, (LPARAM)pszDest);
+
+ tPathLen = strlennull(pszDest);
+ tPathLen += null_snprintf(pszDest + tPathLen, cbLen-tPathLen, "\\%s\\", gpszICQProtoName);
+ }
+ else
+ {
+ strcat(pszDest, "\\");
+ tPathLen = strlennull(pszDest);
+ }
+ { // make sure the avatar cache directory exists
+ char* szDir = ansi_to_utf8(pszDest);
+
+ MakeDirUtf(szDir);
+ SAFE_FREE(&szDir);
+ }
+
+ 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, int nHashLen)
+{
+ DBVARIANT dbvSaved = {0};
+
+ if (!ICQGetContactSetting(hContact, "AvatarSaved", &dbvSaved))
+ {
+ if ((dbvSaved.cpbVal != nHashLen) || memcmp(dbvSaved.pbVal, pHash, nHashLen))
+ { // 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;
+
+ 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 = pendingRequests;
+ int bYet = 0;
+
+ while (ar)
+ {
+ if (ar->type == ART_UPLOAD)
+ { // we found it, return error
+ if (!bYet)
+ {
+ icq_LogMessage(LOG_WARNING, "Error uploading avatar to server, server temporarily unavailable.");
+ }
+ bYet = 1;
+ // remove upload request from queue
+ ar = ReleaseAvatarRequestInQueue(ar);
+ continue;
+ }
+ 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_CloseConnection(&hConn, FALSE);
+ 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
+ ICQCreateThread(icq_avatarThread, atsi);
+
+ 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, int nHashLen)
+{
+ if (nHashLen == 0x14)
+ 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]);
+ else if (nHashLen == 0x09)
+ NetLog_Server("%s Hash: %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]);
+ else
+ NetLog_Server("%s Hash: Unknown hash format.", pszIdent);
+}
+
+
+
+// handle Contact's avatar hash
+void handleAvatarContactHash(DWORD dwUIN, char* szUID, HANDLE hContact, unsigned char* pHash, int nHashLen, WORD wOldStatus)
+{
+ DBVARIANT dbv;
+ int bJob = FALSE;
+ char szAvatar[MAX_PATH];
+ int dwPaFormat;
+ int avatarType = -1;
+ BYTE* pAvatarHash = NULL;
+ int cbAvatarHash;
+ BYTE emptyItem[0x10] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ if (!gbAvatarsEnabled) return; // only if enabled
+
+ if (nHashLen < 4) return; // nothing to work with
+
+ while (nHashLen >= 4)
+ { // parse online message items one by one
+ WORD itemType = pHash[0] << 8 | pHash[1];
+ BYTE itemLen = pHash[3];
+ BYTE itemFlags = pHash[2];
+
+ // just some validity check
+ if (itemLen + 4 > nHashLen)
+ itemLen = nHashLen - 4;
+
+ if (memcmp(pHash+4, emptyItem, itemLen > 0x10 ? 0x10 : itemLen))
+ { // Item types
+ // 0000: AIM mini avatar
+ // 0001: AIM/ICQ avatar ID/hash (len 5 or 16 bytes)
+ // 0002: iChat online message
+ // 0008: ICQ Flash avatar hash (16 bytes)
+ // 0009: iTunes music store link
+ // 000C: ICQ contact photo (16 bytes)
+ // 000D: ?
+ // 000E: Custom Status (ICQ6)
+ if (itemType == AVATAR_HASH_STATIC && (itemLen == 0x05 || itemLen == 0x10) && avatarType == -1)
+ { // normal avatar
+ pAvatarHash = pHash;
+ cbAvatarHash = itemLen + 4;
+ avatarType = itemType;
+ }
+ else if (itemType == AVATAR_HASH_FLASH && itemLen == 0x10 && avatarType == -1)
+ { // flash avatar
+ pAvatarHash = pHash;
+ cbAvatarHash = itemLen + 4;
+ avatarType = itemType;
+ }
+ else if (itemType == AVATAR_HASH_PHOTO && itemLen == 0x10)
+ { // big avatar (ICQ 6)
+ pAvatarHash = pHash;
+ cbAvatarHash = itemLen + 4;
+ avatarType = itemType;
+ }
+ }
+ pHash += itemLen + 4;
+ nHashLen -= itemLen + 4;
+ }
+
+ if (avatarType != -1)
+ { // check settings, should we request avatar immediatelly
+ BYTE bAutoLoad = ICQGetContactSettingByte(NULL, "AvatarsAutoLoad", DEFAULT_LOAD_AVATARS);
+
+ if (avatarType == AVATAR_HASH_STATIC && cbAvatarHash == 0x09 && !memcmp(pAvatarHash + 4, hashEmptyAvatar + 4, 0x05))
+ { // empty avatar - unlink image, clear hash
+ ICQDeleteContactSetting(hContact, "AvatarHash");
+ ICQBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, (LPARAM)NULL);
+ return;
+ }
+
+ if (ICQGetContactSetting(hContact, "AvatarHash", &dbv))
+ { // we not found old hash, i.e. get new avatar
+ int fileState = IsAvatarSaved(hContact, pAvatarHash, cbAvatarHash);
+
+ // 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", pAvatarHash, cbAvatarHash);
+ 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
+ bJob = TRUE;
+ }
+ }
+ else
+ { // we found hash check if it changed or not
+ NetLog_Hash("Old", dbv.pbVal, dbv.cpbVal);
+ if ((dbv.cpbVal != cbAvatarHash) || memcmp(dbv.pbVal, pAvatarHash, cbAvatarHash))
+ { // the hash is different, request new avatar
+ bJob = TRUE;
+ }
+ else
+ { // the hash does not changed, check if we have correct file
+ int fileState = IsAvatarSaved(hContact, pAvatarHash, cbAvatarHash);
+
+ // 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 = 2;
+ }
+ else
+ {
+ GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, szAvatar, MAX_PATH);
+ if (access(szAvatar, 0) != 0)
+ { // the file was lost, get it again
+ bJob = 2;
+ }
+ }
+ }
+ else
+ { // the hash is not the one we want, request avatar
+ bJob = 2;
+ }
+ }
+ ICQFreeVariant(&dbv);
+ }
+
+ if (bJob)
+ {
+ if (bJob == TRUE)
+ {
+ NetLog_Hash("New", pAvatarHash, cbAvatarHash);
+ NetLog_Server("User has Avatar, new hash stored.");
+
+ // Remove possible block - hash changed, try again.
+ EnterCriticalSection(&cookieMutex);
+ {
+ avatarrequest *ar = pendingRequests;
+
+ while (ar)
+ {
+ if (ar->hContact == hContact && ar->type == ART_BLOCK)
+ { // found one, remove
+ ReleaseAvatarRequestInQueue(ar);
+ break;
+ }
+ ar = ar->pNext;
+ }
+ }
+ LeaveCriticalSection(&cookieMutex);
+ }
+ else
+ NetLog_Server("User has Avatar, file is missing.");
+
+ ICQWriteContactSettingBlob(hContact, "AvatarHash", pAvatarHash, cbAvatarHash);
+
+ 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, pAvatarHash, cbAvatarHash, 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");
+ }
+}
+
+
+
+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...
+ { // check if requests for this user are not blocked
+ avatarrequest* ar = pendingRequests;
+
+ while (ar)
+ {
+ if (ar->hContact == hContact && ar->type == ART_BLOCK)
+ { // found a block item
+ if (GetTickCount() > ar->timeOut)
+ { // remove timeouted block
+ ar = ReleaseAvatarRequestInQueue(ar);
+ continue;
+ }
+ LeaveCriticalSection(&cookieMutex);
+ NetLog_Server("Requests for %d avatar are blocked.", dwUin);
+
+ return 0;
+ }
+ ar = ar->pNext;
+ }
+ }
+
+ 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
+ int bSendNow = TRUE;
+
+ EnterCriticalSection(&ratesMutex);
+ { // rate management
+ WORD wGroup = ratesGroupFromSNAC(atsi->rates, ICQ_AVATAR_FAMILY, ICQ_AVATAR_GET_REQUEST);
+
+ if (ratesNextRateLevel(atsi->rates, wGroup) < ratesGetLimitLevel(atsi->rates, wGroup, RML_ALERT))
+ { // we will be over quota if we send the request now, add to queue instead
+ bSendNow = FALSE;
+#ifdef _DEBUG
+ NetLog_Server("Rates: Delay avatar request.");
+#endif
+ }
+ }
+ LeaveCriticalSection(&ratesMutex);
+
+ if (bSendNow)
+ {
+ 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, hContact, 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);
+ }
+ 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 = pendingRequests;
+ int bYet = 0;
+
+ while (ar)
+ {
+ if (ar->hContact == hContact)
+ { // we found it, return error
+ if (ar->type == ART_BLOCK && GetTickCount() > ar->timeOut)
+ { // remove timeouted block
+ ar = ReleaseAvatarRequestInQueue(ar);
+ continue;
+ }
+ 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(ART_GET); // 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
+ AddAvatarRequestToQueue(ar);
+ }
+ LeaveCriticalSection(&cookieMutex);
+
+ NetLog_Server("Request to get %d avatar image added to queue.", dwUin);
+
+ if (!AvatarsReady && !pendingAvatarsStart)
+ {
+ icq_requestnewfamily(ICQ_AVATAR_FAMILY, 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;
+
+ 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 && ar->type == ART_UPLOAD)
+ { // we found it, return error
+ LeaveCriticalSection(&cookieMutex);
+ NetLog_Server("Ignoring duplicate upload avatar request.");
+
+ 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(ART_UPLOAD); // 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;
+ AddAvatarRequestToQueue(ar);
+ }
+ LeaveCriticalSection(&cookieMutex);
+
+ NetLog_Server("Request to upload avatar image added to queue.");
+
+ if (!AvatarsReady && !pendingAvatarsStart)
+ {
+ pendingAvatarsStart = 1;
+ icq_requestnewfamily(ICQ_AVATAR_FAMILY, 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
+ DWORD dwKeepAliveInterval = ICQGetContactSettingDword(NULL, "KeepAliveInterval", KEEPALIVE_INTERVAL);
+
+ InitializeCriticalSection(&atsi->localSeqMutex);
+
+ atsi->hAvatarPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)atsi->hConnection, 16384);
+ packetRecv.cbSize = sizeof(packetRecv);
+ packetRecv.dwTimeout = dwKeepAliveInterval < KEEPALIVE_INTERVAL ? dwKeepAliveInterval: KEEPALIVE_INTERVAL; // timeout - 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() + dwKeepAliveInterval;
+ }
+ 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 ??
+ } // FIXME: we should check the avatar queue now
+ 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;
+
+ EnterCriticalSection(&ratesMutex);
+ { // rate management
+ WORD wGroup = ratesGroupFromSNAC(atsi->rates, ICQ_AVATAR_FAMILY, (WORD)(reqdata->type == ART_UPLOAD ? ICQ_AVATAR_GET_REQUEST : ICQ_AVATAR_UPLOAD_REQUEST));
+
+ if (ratesNextRateLevel(atsi->rates, wGroup) < ratesGetLimitLevel(atsi->rates, wGroup, RML_ALERT))
+ { // we are over rate, leave queue and wait
+#ifdef _DEBUG
+ NetLog_Server("Rates: Leaving avatar queue processing");
+#endif
+ LeaveCriticalSection(&ratesMutex);
+ break;
+ }
+ }
+ LeaveCriticalSection(&ratesMutex);
+
+ pendingRequests = reqdata->pNext;
+
+#ifdef _DEBUG
+ NetLog_Server("Picked up the %d request from queue.", reqdata->dwUin);
+#endif
+ switch (reqdata->type)
+ {
+ case ART_GET: // get avatar
+ GetAvatarData(reqdata->hContact, reqdata->dwUin, reqdata->szUid, reqdata->hash, reqdata->hashlen, reqdata->szFile);
+ break;
+ case ART_UPLOAD: // set avatar
+ SetAvatarData(reqdata->hContact, reqdata->wRef, reqdata->pData, reqdata->cbData);
+ break;
+ case ART_BLOCK: // block contact processing
+ if (GetTickCount() < reqdata->timeOut)
+ { // it is not time, keep request in queue
+ if (pendingRequests)
+ { // the queue contains items, jump the queue
+ reqdata->pNext = pendingRequests->pNext;
+ pendingRequests->pNext = reqdata;
+ }
+ else
+ pendingRequests = reqdata;
+ reqdata = NULL;
+ }
+ break;
+ }
+ FreeAvatarRequest(&reqdata);
+
+ if (pendingRequests && pendingRequests->type == ART_BLOCK) break; // leave the loop
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+ }
+ }
+ NetLib_SafeCloseHandle(&atsi->hAvatarPacketRecver); // Close the packet receiver
+ }
+ NetLib_CloseConnection(&atsi->hConnection, FALSE); // Close the connection
+
+ // release rates
+ ratesRelease(&atsi->rates);
+
+ 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
+
+ EnterCriticalSection(&ratesMutex); // TODO: we should have our own mutex
+ if (atsi->rates)
+ {
+ ratesPacketSent(atsi->rates, pPacket);
+ }
+ LeaveCriticalSection(&ratesMutex);
+ }
+ }
+ 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
+ /* init rates management */
+ atsi->rates = ratesCreate(pBuffer, wBufferLength);
+ /* ack rate levels */
+ serverPacketInit(&packet, 20);
+ 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); // mimic ICQ 6
+ packDWord(&packet, 0x0010157f);
+ packDWord(&packet, 0x00100001);
+ packDWord(&packet, 0x0010157f);
+ sendAvatarPacket(&packet, atsi);
+
+ AvatarsReady = TRUE; // we are ready to process requests
+ pendingAvatarsStart = 0;
+ atsi->pendingLogin = 0;
+
+ NetLog_Server(" *** Yeehah, avatar login sequence complete");
+ //inv4inv(0, 3);
+ //inv4invCleanUp();
+ 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;
+ }
+}
+
+
+
+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;
+ BYTE bResult;
+
+ 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;
+ unpackByte(&pBuffer, &bResult);
+ pBuffer += ac->hashlen;
+ 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;
+ int aValid = 1;
+
+ if (ac->hashlen == 0x14 && ac->hash[3] == 0x10 && ICQGetContactSettingByte(NULL, "StrictAvatarCheck", DEFAULT_AVATARS_CHECK))
+ { // check only standard hashes
+ mir_md5_state_t state;
+ mir_md5_byte_t digest[16];
+
+ mir_md5_init(&state);
+ mir_md5_append(&state, (const mir_md5_byte_t *)pBuffer, datalen);
+ mir_md5_finish(&state, digest);
+ // check if received data corresponds to specified hash
+ if (memcmp(ac->hash+4, digest, 0x10)) aValid = 0;
+ }
+
+ if (aValid)
+ {
+ 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 (!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
+ { // avatar is broken
+ NetLog_Server("Error: Avatar data does not match avatar hash, ignoring.");
+
+ if (ac->hContact)
+ {
+ avatarrequest *ar = CreateAvatarRequest(ART_BLOCK);
+
+ EnterCriticalSection(&cookieMutex);
+ if (ar)
+ {
+ avatarrequest *last = pendingRequests;
+
+ ar->hContact = ac->hContact;
+ ar->timeOut = GetTickCount() + 14400000; // do not allow re-request four hours
+
+ // add it to the end of queue, i.e. do not block other requests
+ while (last && last->pNext) last = last->pNext;
+ if (last)
+ last->pNext = ar;
+ else
+ pendingRequests = ar;
+ }
+ LeaveCriticalSection(&cookieMutex);
+ }
+ ICQBroadcastAck(ac->hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, (HANDLE)&ai, 0);
+ }
+ }
+ else
+ { // the avatar is empty
+ NetLog_Server("Received empty avatar, nothing written (error 0x%x).", bResult);
+
+ 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_s7_sss_mod/icq_avatar.h b/icqj_s7_sss_mod/icq_avatar.h new file mode 100644 index 0000000..1f28fa1 --- /dev/null +++ b/icqj_s7_sss_mod/icq_avatar.h @@ -0,0 +1,71 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_AVATAR_H
+#define __ICQ_AVATAR_H
+
+extern BOOL AvatarsReady;
+
+extern BYTE hashEmptyAvatar[9];
+
+#define AVATAR_HASH_STATIC 0x01
+#define AVATAR_HASH_FLASH 0x08
+#define AVATAR_HASH_PHOTO 0x0C
+
+void handleAvatarContactHash(DWORD dwUIN, char* szUID, HANDLE hContact, unsigned char* pHash, 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 nHashLen);
+
+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();
+
+void InitAvatars();
+
+
+#endif /* __ICQ_AVATAR_H */
diff --git a/icqj_s7_sss_mod/icq_caps_list.c b/icqj_s7_sss_mod/icq_caps_list.c new file mode 100644 index 0000000..8751523 --- /dev/null +++ b/icqj_s7_sss_mod/icq_caps_list.c @@ -0,0 +1,170 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007,2008 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie, jarvis
+// Copyright 2008 [sss], chaos.persei, nullbie, baloo, jarvis
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: jarvis141 $
+//
+//
+// DESCRIPTION:
+//
+// Capabilities List GUI
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+static HWND hwndCapsList = NULL;
+HWND hCaller;
+extern BOOL id;
+WORD OldCapsCount = 0;
+static BOOL CALLBACK DlgProcCapsList( HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ char DBModule[64];
+ char buf1[64];
+ char buf2[64];
+ WORD CapsCount = 0;
+ int iIndex, i, iRow;
+ LVCOLUMN col;
+ LVITEM item;
+ HWND hwndList = GetDlgItem( hwndDlg, IDC_CAPABILITIES );
+ NMLISTVIEW * hdr = ( NMLISTVIEW * )lParam;
+ mir_snprintf( DBModule, 64, "%sCaps", gpszICQProtoName );
+ switch ( message )
+ {
+ case WM_INITDIALOG:
+ {
+ id = FALSE;
+ ICQTranslateDialog( hwndDlg );
+ col.pszText = Translate( "Capability" );
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 200;
+ ListView_InsertColumn( hwndList, 0, &col );
+ ListView_SetExtendedListViewStyleEx( hwndList, 0, LVS_EX_FULLROWSELECT );
+
+ for ( i = 1; ; i++ )
+ {
+ DBVARIANT dbv = { 0 };
+ lstrcpy( dbv.pszVal, "" );
+ mir_snprintf( buf2, 64, "cap%luname", i );
+ DBGetContactSettingString( NULL, DBModule, buf2, &dbv );
+ if ( !dbv.pszVal ) break;
+ else {
+ item.mask = LVIF_TEXT;
+ item.iItem = i;
+ item.iSubItem = 0;
+ item.pszText = buf2;
+ iRow = ListView_InsertItem( hwndList, &item );
+ lstrcpy( buf2, dbv.pszVal );
+ ListView_SetItemText( hwndList, iRow, 0, buf2 );
+ }
+ }
+ OldCapsCount = ListView_GetItemCount( hwndList );
+ }
+ return TRUE;
+ case WM_COMMAND:
+ {
+ ZeroMemory( &item, sizeof( LVITEM ) );
+ switch ( LOWORD( wParam ) )
+ {
+ case IDC_CAPL_ADD:
+ CapsCount = ListView_GetItemCount( hwndList );
+ GetDlgItemText( hwndDlg, IDC_CAPL_EDIT, buf2, 64 );
+ if( buf2[0] == 0 )
+ break;
+ item.mask = LVIF_TEXT;
+ item.iItem = CapsCount;
+ item.iSubItem = 0;
+ item.pszText = NULL;
+ iRow = ListView_InsertItem( hwndList, &item );
+ ListView_SetItemText( hwndList, iRow, 0, buf2 );
+ break;
+ case IDC_CAPL_MODIFY:
+ iIndex = ListView_GetSelectionMark( hwndList );
+ if ( iIndex < 0 ) return FALSE;
+ GetDlgItemText( hwndDlg, IDC_CAPL_EDIT, buf2 , 64 );
+ ListView_SetItemText( hwndList, iIndex, 0, buf2 );
+ break;
+ case IDC_CAPL_DELETE:
+ iIndex = ListView_GetSelectionMark( hwndList );
+ if( iIndex < 0 ) return FALSE;
+ ListView_DeleteItem( hwndList, iIndex );
+ break;
+ case IDOK:
+ case IDCANCEL:
+ SendMessage( hCaller, WM_INITDIALOG, 0, 0 );
+ DestroyWindow( hwndDlg );
+ break;
+ }
+ }
+ break;
+ case WM_NOTIFY:
+ if ( hdr && hdr->hdr.code == LVN_ITEMCHANGED && IsWindowVisible( hdr->hdr.hwndFrom ) && hdr->iItem != ( -1 ) ) {
+ iIndex = hdr->iItem;
+ if( iIndex < 0 ) return FALSE;
+ ListView_GetItemText( hwndList, iIndex, 0, buf2, 64 );
+ SetDlgItemText( hwndDlg, IDC_CAPL_EDIT, buf2 );
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow( hwndDlg );
+ break;
+ case WM_DESTROY:
+ {
+ int j;
+ hwndCapsList = NULL;
+ CapsCount = ListView_GetItemCount( hwndList );
+ for ( iRow = 0; iRow < CapsCount; iRow++ ) {
+ mir_snprintf( buf2, 64, "cap%luname", iRow + 1 );
+ ListView_GetItemText( hwndList, iRow, 0, buf1, 64 )
+ DBWriteContactSettingString( NULL, DBModule, buf2, buf1 );
+ id = TRUE;
+ }
+ for ( j = CapsCount + 1; j <= OldCapsCount; j++ )
+ {
+ mir_snprintf( buf2, 64, "cap%luname", j );
+ DBDeleteContactSetting( NULL, DBModule, buf2 );
+ id = TRUE;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void ShowCapsListDialog( HWND hwndCaller )
+{
+ hCaller = hwndCaller;
+ if ( hwndCapsList == NULL )
+ {
+ hwndCapsList = CreateDialogUtf( hInst, MAKEINTRESOURCE( IDD_ICQ_CAPS_LIST ), NULL, DlgProcCapsList );
+ }
+ SetForegroundWindow( hwndCapsList );
+}
diff --git a/icqj_s7_sss_mod/icq_clients.c b/icqj_s7_sss_mod/icq_clients.c new file mode 100644 index 0000000..0be0abf --- /dev/null +++ b/icqj_s7_sss_mod/icq_clients.c @@ -0,0 +1,1030 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007,2008 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+// Copyright 2008 [sss], chaos.persei, nullbie, baloo, jarvis
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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);
+}
+
+
+
+
+char* cliLibicq2k = "libicq2000";
+char* cliLicqVer = "Licq ";
+char* cliCentericq = "Centericq";
+char* cliLibicqUTF = "libicq2000 (Unicode)";
+char* cliTrillian = "Trillian";
+char* cliQip = "QIP %s";
+char* cliIM2 = "IM2";
+char* cliSpamBot = "Spam Bot";
+
+
+char* detectUserClient(HANDLE hContact, DWORD dwUin, WORD wVersion, DWORD dwFT1, DWORD dwFT2, DWORD dwFT3, DWORD dwOnlineSince, BYTE bDirectFlag, DWORD dwDirectCookie, DWORD dwWebPort, BYTE* caps, WORD wLen, BYTE* bClientId, char* szClientBuf)
+{
+ capstr* capId;
+ LPSTR szClient = {0};
+
+ *bClientId = CLID_ALTERNATIVE; // Most clients does not tick as MsgIDs
+
+ // 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 if(!MatchCap(caps,wLen, &capIcqJs7, 4)&&!MatchCap(caps,wLen, &capIcqJSin, 4)&&!MatchCap(caps,wLen, &capIcqJp, 4)&&!MatchCap(caps,wLen, &capIcqJen, 4))
+ { // Yes this is most probably Miranda, get the version info (need better realization)
+ unsigned ver1 = (dwFT2>>24)&0xFF;
+ unsigned ver2 = (dwFT2>>16)&0xFF;
+ unsigned ver3 = (dwFT2>>8)&0xFF;
+ unsigned ver4 = (dwFT2)&0xFF;
+ if(ver1 & 0x80)
+ {
+ makeClientVersion(szClientBuf, "Miranda IM (ICQ 0.", ver2, ver3, ver4, 0);
+ lstrcatA(szClientBuf," alpha)");
+ }
+ else
+ {
+ makeClientVersion(szClientBuf, "Miranda IM (ICQ ", ver1, ver2, ver3, ver4);
+ lstrcatA(szClientBuf,")");
+ }
+ szClient = szClientBuf;
+ *bClientId = CLID_MIRANDA;
+ }
+ }
+ 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 == 0x66666666 && dwFT3 == 0x66666666)
+ { // http://darkjimm.ucoz.ru/
+ strcpy(szClientBuf, "D[i]Chat");
+ if (dwFT2 == 0x10000)
+ strcat(szClientBuf, " v.0.1a");
+ else if (dwFT2 == 0x22)
+ strcat(szClientBuf, " v.0.2b");
+
+ 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;
+ }
+ else if (dwFT1 == 0x44F523B0 && dwFT2 == 0x44F523A6 && dwFT3 == 0x44F523A6 && wVersion == 8)
+ {
+ szClient = "Virus";
+ }
+
+ { // capabilities based detection
+
+ if (dwUin && caps)
+ {
+ // check capabilities for client identification
+ if ((capId = MatchCap(caps, wLen, &capMirandaIm, 8))&&(!MatchCap(caps, wLen, &capIcqJSin, 4)&&!MatchCap(caps,wLen,&capIcqJs7, 4)&&!MatchCap(caps,wLen,&capIcqJp, 4)&&!MatchCap(caps,wLen, &capIcqJen, 4)))
+ { // new Miranda Signature
+ char sz[64];
+ static char szTmp[256];
+ BYTE mver0 = (*capId)[0x8];
+ BYTE mver1 = (*capId)[0x9];
+ BYTE mver2 = (*capId)[0xA];
+ BYTE mver3 = (*capId)[0xB];
+ BYTE iver0 = (*capId)[0xC];
+ BYTE iver1 = (*capId)[0xD];
+ BYTE iver2 = (*capId)[0xE];
+ BYTE iver3 = (*capId)[0xF];
+ strcpy(szTmp, "Miranda IM ");
+ if (MatchCap(caps,wLen,&capMirandaMobile,13))
+ lstrcatA(szTmp, "Mobile ");
+ if (mver0 == 0x80) // alpha builds directly stamped
+ {
+ if (mver2 == 0x00)
+ mir_snprintf(sz, sizeof(sz), "0.%u alpha build #%u", mver1, mver3); // 0.x alpha #x
+ else
+ mir_snprintf(sz, sizeof(sz), "0.%u.%u preview #%u", mver1, mver2,mver3); // 0.x.x preview #x
+ lstrcatA(szTmp, sz);
+ }
+ else // others, but also for those where bug caused that alpha flag was not send
+ {
+ if (mver2 == 0x00)
+ mir_snprintf(sz, sizeof(sz), "%u.%u", mver0, mver1); // 0.x final
+ else
+ mir_snprintf(sz, sizeof(sz), "%u.%u.%u", mver0, mver1, mver2); // 0.x.x final
+ lstrcatA(szTmp, sz);
+ if (mver3 != 0x00 && mver3 != 0x64) // if some build version is set, then it's probably alpha
+ {
+ mir_snprintf(sz, sizeof(sz), " alpha build #%u", mver3); // ".. alpha #x"
+ lstrcatA(szTmp, sz);
+ }
+ }
+ if (dwFT1 == 0x7fffffff ||(BYTE)((dwFT3>>24)&0xFF) == 0x80)
+ lstrcatA(szTmp, " Unicode");
+ lstrcatA(szTmp," (ICQ ");
+ if(MatchCap(caps,wLen,&capIcqJs7old, 0x10)||MatchCap(caps,wLen,&capIcqJs7s, 0x10)) //detecting sss & s7 old mod versions
+ lstrcatA(szTmp, " S7 & SSS (old)");
+ else switch (iver0) {
+ case 0x81 : lstrcatA(szTmp, " BM"); break; // detecting BM mod
+ break;
+ case 0x88 : lstrcatA(szTmp, " eternity (old)"); break; // eternity mod
+ default : break;
+ }
+ switch (iver2) {
+ case 0x58 : lstrcatA(szTmp, " eternity/PlusPlus++ Mod"); break; // detecting naturalized eternity/PlusPlus++ mod
+ default : break;
+ }
+ lstrcatA(szTmp, " ");
+ switch (iver0) {
+ case 0x88 : // eternity (old)
+ case 0x81 : // BM
+ case 0x80 : mir_snprintf(sz, sizeof(sz), "0.%u.%u.%u alpha)", iver1, iver2, iver3); // mir and bm 0.x
+ break;
+ default : mir_snprintf(sz, sizeof(sz), "%u.%u.%u.%u)",iver0, iver1, iver2, iver3); // other x.x (only for 6.6.6.0?)
+ }
+ lstrcatA(szTmp,sz);
+ if (dwFT3 == 0x5AFEC0DE||MatchCap(caps,wLen,&capIcqJs7s, 0x10))
+ lstrcatA(szTmp, " (SecureIM)");
+ szClient = szTmp;
+ *bClientId = CLID_MIRANDA;
+ }
+ else if (MatchCap(caps, wLen, &capTrillian, 0x10) || MatchCap(caps, wLen, &capTrilCrypt, 0x10))
+ { // this is Trillian, check for new versions
+ if (CheckContactCapabilities(hContact, CAPF_RTF))
+ {
+ if (CheckContactCapabilities(hContact, CAPF_AIM_FILE))
+ szClient = "Trillian Astra";
+ else
+ { // workaroud for a bug in Trillian - make it receive msgs, other features will not work!
+ ClearContactCapabilities(hContact, CAPF_SRV_RELAY);
+ 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, &capClimm, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ makeClientVersion(szClientBuf, "climm ", ver1, ver2, ver3, ver4);
+ if ((ver1 & 0x80) == 0x80)
+ strcat(szClientBuf, " alpha");
+ if (dwFT3 == 0x02000020)
+ strcat(szClientBuf, "/Win32");
+ else if (dwFT3 == 0x03000800)
+ strcat(szClientBuf, "/MacOS X");
+
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capSim, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ makeClientVersion(szClientBuf, "SIM ", ver1, ver2, ver3, ver4 & 0x0F);
+ if (ver4 & 0x80)
+ strcat(szClientBuf,"/Win32");
+ else if (ver4 & 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);
+ if ((ver1 & 0x80) == 0x80) strcat(szClientBuf, " alpha");
+
+ 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 (MatchCap(caps, wLen, &capIMadering, 0x10))
+ { // http://imadering.com
+ szClient = "IMadering";
+ }
+ else if (MatchCap(caps, wLen, &capQipPDA, 0x10))
+ {
+ szClient = "QIP PDA (Windows)";
+ }
+ else if (MatchCap(caps, wLen, &capQipMobile, 0x10))
+ {
+ szClient = "QIP Mobile (Java)";
+ }
+ else if (MatchCap(caps,wLen,&capQipSymbian,0x10))
+ {
+ szClient = "QIP Mobile (Symbian)";
+ }
+ else if (MatchCap(caps, wLen, &capQipInfium, 0x10))
+ {
+ char ver[10];
+
+ strcpy(szClientBuf, "QIP Infium");
+ if (dwFT1)
+ { // add build
+ null_snprintf(ver, 10, " (%d)", dwFT1);
+ strcat(szClientBuf, ver);
+ }
+ if (dwFT2 == 0x0000000B)
+ strcat(szClientBuf, " Beta");
+
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capQip, 0xE))
+ {
+ char ver[10];
+
+ if (dwFT3 == 0x0F)
+ strcpy(ver, "2005");
+ else
+ {
+ strncpy(ver, (*capId)+11, 5);
+ ver[5] = '\0'; // fill in missing zero
+ }
+
+ null_snprintf(szClientBuf, 64, cliQip, ver);
+ if (dwFT1 && dwFT2 == 0x0E)
+ { // add QIP build
+ null_snprintf(ver, 10, " (%d%d%d%d)", dwFT1 >> 0x18, (dwFT1 >> 0x10) & 0xFF, (dwFT1 >> 0x08) & 0xFF, dwFT1 & 0xFF);
+ strcat(szClientBuf, ver);
+ }
+ 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 (capId = MatchCap(caps, wLen, &capCorePager, 0xA))
+ { // http://corepager.net.ru/index/0-2
+ strcpy(szClientBuf, "CORE Pager");
+ if (dwFT2 == 0x0FFFF0011 && dwFT3 == 0x1100FFFF && (dwFT1 >> 0x18))
+ {
+ char ver[16];
+
+ null_snprintf(ver, 10, " %d.%d", dwFT1 >> 0x18, (dwFT1 >> 0x10) & 0xFF);
+ if ((dwFT1 & 0xFF) == 0x0B)
+ strcat(ver, " Beta");
+ strcat(szClientBuf, ver);
+ }
+ szClient = szClientBuf;
+ }
+ else if (MatchCap(caps, wLen, &capMacIcq, 0x10))
+ {
+ szClient = "ICQ for Mac";
+ }
+ else if (MatchCap(caps, wLen, &capUim, 0x10))
+ {
+ szClient = "uIM";
+ }
+ else if (MatchCap(caps, wLen, &capAnastasia, 0x10))
+ { // http://chis.nnov.ru/anastasia
+ szClient = "Anastasia";
+ }
+ else if (capId = MatchCap(caps, wLen, &capPalmJicq, 0xC))
+ { // http://www.jsoft.ru
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ makeClientVersion(szClientBuf, "JICQ ", ver1, ver2, ver3, ver4);
+
+ szClient = szClientBuf;
+ }
+ else if (MatchCap(caps, wLen, &capInluxMsgr, 0x10))
+ { // http://www.inlusoft.com
+ szClient = "Inlux Messenger";
+ }
+ else if (capId = MatchCap(caps, wLen, &capVmICQ, 5))
+ {
+ strcpy(szClientBuf, "VmICQ ");
+ strncat(szClientBuf, (*capId) + 5, 11);
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capSmapeR, 0x07))
+ { // http://www.smape.com/smaper
+ strcpy(szClientBuf, "SmapeR");
+ strncat(szClientBuf, (*capId) + 6, 10);
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCap(caps, wLen, &capMipClient, 0x04))
+ { //http://mip.rufon.net - new signature
+ strcpy(szClientBuf, "MIP ");
+ strncat(szClientBuf, (*capId) + 4, 12);
+ szClient = szClientBuf;
+ }
+ else if(capId = MatchCap(caps,wLen,&capYapp, 4))
+ {
+ strcpy(szClientBuf, "Yapp! v");
+ strncat(szClientBuf, (*capId) + 8, 5);
+ szClient = szClientBuf;
+ }
+ else if(!wVersion && CheckContactCapabilities(hContact, CAPF_DIRECT|CAPF_RTF|CAPF_TYPING|CAPF_UTF))
+ szClient = "GlICQ";
+ else if (szClient == cliLibicq2k)
+ { // try to determine which client is behind libicq2000
+ if (CheckContactCapabilities(hContact, CAPF_RTF))
+ 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 && !((capId = MatchCap(caps, wLen, &capIcqJs7, 4))||(capId = MatchCap(caps, wLen, &capIcqJSin, 4))||(capId = MatchCap(caps, wLen, &capIcqJp, 4))||(capId = MatchCap(caps, wLen, &capIcqJen, 4)))) // HERE ENDS THE SIGNATURE DETECTION, after this only feature default will be detected
+ {
+ if (wVersion == 8 && CheckContactCapabilities(hContact, CAPF_XTRAZ) && (MatchCap(caps, wLen, &capIMSecKey1, 6) || MatchCap(caps, wLen, &capIMSecKey2, 6)))
+ { // ZA mangled the version, OMG!
+ wVersion = 9;
+ }
+ 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 (CheckContactCapabilities(hContact, CAPF_RTF))
+ szClient = "TICQClient"; // possibly also older GnomeICU
+ else
+ szClient = "ICQ for Pocket PC";
+ }
+ else
+ {
+ *bClientId = CLID_GENERIC;
+ szClient = "ICQ 2001";
+ }
+ }
+ else if (MatchCap(caps, wLen, &capIs2002, 0x10))
+ {
+ *bClientId = CLID_GENERIC;
+ szClient = "ICQ 2002";
+ }
+ else if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY | CAPF_UTF | CAPF_RTF) && !MatchCap(caps, wLen, &capIcqJs7, 0x4) && !MatchCap(caps,wLen,&capIcqJSin, 0x4))
+ {
+ 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 = CLID_GENERIC;
+ if (CheckContactCapabilities(hContact, CAPF_AIM_FILE))
+ {
+ if (MatchCap(caps, wLen, &captZers, 0x10))
+ { // capable of tZers ?
+ if (MatchCap(caps, wLen, &capHtmlMsgs, 0x10))
+ {
+ strcpy(szClientBuf, "ICQ 6");
+ *bClientId = CLID_ICQ6;
+ }
+ else
+ {
+ strcpy(szClientBuf, "icq5.1");
+ }
+ SetContactCapabilities(hContact, CAPF_STATUSMSGEXT);
+ }
+ 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 (!CheckContactCapabilities(hContact, CAPF_DIRECT))
+ if (CheckContactCapabilities(hContact, CAPF_RTF))
+ { // most probably Qnext - try to make that shit at least receiving our msgs
+ ClearContactCapabilities(hContact, CAPF_SRV_RELAY);
+ NetLog_Server("Forcing simple messages (QNext client).");
+ szClient = "QNext";
+ }
+ else
+ szClient = "pyICQ";
+ else
+ szClient = "ICQ Lite v4";
+ }
+ else if (!CheckContactCapabilities(hContact, CAPF_DIRECT))
+ {
+ if (CheckContactCapabilities(hContact, CAPF_UTF) && !CheckContactCapabilities(hContact, CAPF_RTF))
+ szClient = "pyICQ";
+ }
+ }
+ else if (wVersion == 7)
+ {
+ if (CheckContactCapabilities(hContact, CAPF_RTF))
+ szClient = "GnomeICU"; // this is an exception
+ else if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY))
+ {
+ if (!dwFT1 && !dwFT2 && !dwFT3)
+ szClient = "&RQ";
+ else
+ {
+ *bClientId = CLID_GENERIC;
+ szClient = "ICQ 2000";
+ }
+ }
+ else if (CheckContactCapabilities(hContact, CAPF_UTF))
+ {
+ if (CheckContactCapabilities(hContact, CAPF_TYPING))
+ szClient = "Icq2Go! (Java)";
+ else if (wClass & CLASS_WIRELESS)
+ szClient = "Pocket Web 1&1";
+ else
+ szClient = "Icq2Go! (Flash)"; // fixing overlay in Fingerprint
+ }
+ /* else if (CheckContactCapabilities(hContact, CAPF_UTF))
+ {
+ if (CheckContactCapabilities(hContact, CAPF_TYPING))
+ szClient = "Icq2Go! (Java)";
+ else
+ szClient = "Icq2Go! (Flash)";
+ }*/
+ }
+ else if (wVersion == 0xA)
+ {
+ if (!CheckContactCapabilities(hContact, CAPF_RTF) && !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 (!CheckContactCapabilities(hContact, CAPF_RTF) && 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) && MatchCap(caps, wLen, &capAimChat, 0x10) && CheckContactCapabilities(hContact, CAPF_UTF) && wLen == 0x30)
+ szClient = "Meebo";
+ else if (MatchCap(caps, wLen, &capAimIcon, 0x10) && CheckContactCapabilities(hContact, CAPF_UTF) && wLen == 0x20)
+ szClient = "PyICQ-t Jabber Transport";
+ 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 (CheckContactCapabilities(hContact, CAPF_UTF | CAPF_SRV_RELAY | CAPF_DIRECT | CAPF_TYPING) && wLen == 0x40)
+ szClient = "Agile Messenger"; // Smartphone 2002
+ else if (CheckContactCapabilities(hContact, CAPF_UTF | CAPF_SRV_RELAY | CAPF_DIRECT | CAPF_AIM_FILE) && MatchCap(caps, wLen, &capAimFileShare, 0x10))
+ szClient = "Slick"; // http://lonelycatgames.com/?app=slick
+ }
+ }
+ }
+ }
+ else if (!dwUin)
+ { // detect AIM clients
+ if (caps)
+ {
+ if (capId = MatchCap(caps, wLen, &capAimOscar, 8))
+ { // AimOscar Signature
+ char sz[64];
+ static char szTmp[256];
+ BYTE mver0 = (*capId)[0x8];
+ BYTE mver1 = (*capId)[0x9];
+ BYTE mver2 = (*capId)[0xA];
+ BYTE mver3 = (*capId)[0xB];
+ BYTE iver0 = (*capId)[0xC];
+ BYTE iver1 = (*capId)[0xD];
+ BYTE iver2 = (*capId)[0xE];
+ BYTE iver3 = (*capId)[0xF];
+ strcpy(szTmp, "Miranda IM ");
+ if (mver0 & 0x80)
+ {
+ mir_snprintf(sz, sizeof(sz), "0.%u.%u alpha build #%u", mver1, mver2,mver3);
+ lstrcatA(szTmp, sz);
+ }
+ else
+ {
+ mir_snprintf(sz, sizeof(sz), "%u.%u.%u.%u", mver0, mver1, mver2,mver3);
+ lstrcatA(szTmp, sz);
+ }
+ lstrcatA(szTmp," (AIM v");
+ if (iver0 & 0x80)
+ {
+ mir_snprintf(sz, sizeof(sz), "0.%u.%u.%u alpha)", iver1, iver2, iver3);
+ lstrcatA(szTmp,sz);
+ }
+ else
+ {
+ mir_snprintf(sz, sizeof(sz), "%u.%u.%u.%u)",iver0, iver1, iver2, iver3);
+ lstrcatA(szTmp,sz);
+ }
+ /* if (dwFT3 == 0x5AFEC0DE) //I don't know if integratiion with SecureIM is done
+ lstrcatA(szTmp, " (with SecureIM)"); */
+ szClient = szTmp;
+ }
+ 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 if (MatchCap(caps, wLen, &capNaim, 0x8))
+ {
+ szClient = "naim";
+ }
+ else if(MatchCap(caps, wLen, &capAimIcon, 0x10))
+ {
+ if(MatchCap(caps, wLen, &capAimAddins, 0x10) && MatchCap(caps, wLen, &capAimUnk2, 0x10))
+ {
+ szClient = "AIM 5";
+ }
+ else if(MatchCap(caps, wLen, &capAimAudio, 0x10) && MatchCap(caps, wLen, &capAimContactSnd, 0x10))
+ {
+ szClient = "AIM Pro";
+ }
+ else if(MatchCap(caps, wLen, &capAimAudio, 0x10))
+ {
+ szClient = "AIM 6";
+ }
+ else
+ {
+ szClient = "AIM";
+ }
+ }
+ }
+ }
+ }
+ if (!szClient&&!MatchCap(caps, wLen, &capIcqJs7, 4)&&!MatchCap(caps, wLen, &capIcqJSin, 4)&&!MatchCap(caps, wLen, &capIcqJp, 4)&&!MatchCap(caps, wLen, &capIcqJen, 4))
+ {
+ NetLog_Server("No client identification, put default ICQ client for protocol.");
+ *bClientId = CLID_GENERIC;
+ 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";
+ break;
+ case 0xB:
+ szClient = "QIP 2005a";
+ break;
+ }
+ }
+ if (!szClient)
+ {
+ if ((capId = MatchCap(caps, wLen, &capIcqJs7, 4))||(capId = MatchCap(caps, wLen, &capIcqJSin, 4))||(capId = MatchCap(caps, wLen, &capIcqJp, 4))||(capId = MatchCap(caps, wLen, &capIcqJen, 4))) //detecting mod and core version, please fix me
+ {
+ char sz[64];
+ static char szTmp[256];
+ BYTE mver0 = (*capId)[0x4];
+ BYTE mver1 = (*capId)[0x5];
+ BYTE mver2 = (*capId)[0x6];
+ BYTE mver3 = (*capId)[0x7];
+ BYTE iver0 = (*capId)[0x8];
+ BYTE iver1 = (*capId)[0x9];
+ BYTE iver2 = (*capId)[0xA];
+ BYTE iver3 = (*capId)[0xB];
+ BYTE secure = (*capId)[0xC];
+ BYTE ModVer = (*capId)[0x3];
+ BYTE Unicode = (BYTE)(dwFT3>>24)&0xFF;
+ if (mver1 < 20 && iver1 < 20)
+ {
+ strcpy(szTmp, "Miranda IM ");
+ if (mver0 == 0x80)
+ {
+ if (mver2 == 0x00)
+ mir_snprintf(sz, sizeof(sz), "0.%u alpha build #%u", mver1, mver3);
+ else
+ mir_snprintf(sz, sizeof(sz), "0.%u.%u alpha build #%u", mver1, mver2,mver3);
+ lstrcatA(szTmp, sz);
+ }
+ else
+ {
+ if (mver2 == 0x00)
+ mir_snprintf(sz, sizeof(sz), "%u.%u", mver0, mver1);
+ else
+ mir_snprintf(sz, sizeof(sz), "%u.%u.%u", mver0, mver1, mver2);
+ lstrcatA(szTmp, sz);
+ if (mver3 != 0x00 && mver3 != 0x64)
+ {
+ mir_snprintf(sz, sizeof(sz), " alpha build #%u", mver3);
+ lstrcatA(szTmp, sz);
+ }
+ }
+ if (Unicode == 0x80||dwFT1 == 0x7fffffff)
+ lstrcatA(szTmp," Unicode");
+ if (ModVer == 'p')
+ lstrcatA(szTmp," (ICQ "ICQ_MODNAME"");
+ else if (((*capId)[0x0]) == 's')
+ lstrcatA(szTmp," (ICQ S!N");
+ else if (((*capId)[0x0]) == 'e')
+ lstrcatA(szTmp," (ICQ eternity/PlusPlus++"); //mod of mod of mod of mod of mod
+ else if(ModVer == 'j')
+ lstrcatA(szTmp," (ICQ S7 & SSS");
+ if (iver0 == 0x80)
+ {
+ mir_snprintf(sz, sizeof(sz), " 0.%u.%u.%u alpha)", iver1, iver2, iver3);
+ lstrcatA(szTmp,sz);
+ }
+ else
+ {
+ mir_snprintf(sz, sizeof(sz), " %u.%u.%u.%u)",iver0, iver1, iver2, iver3);
+ lstrcatA(szTmp,sz);
+ }
+ if (secure != 0 && secure != 20||dwFT3 == 0x5AFEC0DE)
+ lstrcatA(szTmp, " (SecureIM)");
+ }
+ else if(MatchCap(caps,wLen,&capIcqJs7s,0x10))
+ strcpy(szTmp,"Miranda IM (ICQ SSS & S7)(SecureIM)");
+ else if(MatchCap(caps,wLen,&capIcqJs7old,0x10))
+ strcpy(szTmp,"Miranda IM (ICQ SSS & S7)");
+ szClient = szTmp;
+ }
+ else if(CheckContactCapabilities(hContact, CAPF_SRV_RELAY | CAPF_DIRECT | CAPF_TYPING) && wVersion > 1000)
+ {
+ szClient = "QIP 2005a (as Unknown)";
+ }
+ else if(CheckContactCapabilities(hContact, CAPF_UTF)&&!CheckContactCapabilities(hContact, CAPF_SRV_RELAY)&&!CheckContactCapabilities(hContact, CAPF_TYPING))//i hate pocket web ;)
+ szClient = "Pocket Web 1&1";
+ }
+ if (szClient)
+ {
+ char* szExtra = NULL;
+ if (MatchCap(caps, wLen, &capSimpLite, 0x10))
+ szExtra = " + SimpLite";
+ if (MatchCap(caps, wLen, &capSimpPro, 0x10))
+ szExtra = " + SimpPro";
+ if (MatchCap(caps, wLen, &capIMsecure, 0x10) || MatchCap(caps, wLen, &capIMSecKey1, 6) || MatchCap(caps, wLen, &capIMSecKey2, 6))
+ szExtra = " + IMsecure";
+ if (!strstr(szClient, "Miranda") && ((capId = MatchCap(caps, wLen, &capIcqJs7, 4))||(capId = MatchCap(caps, wLen, &capIcqJp, 4))||(capId = MatchCap(caps, wLen, &capIcqJSin, 4))||(capId = MatchCap(caps, wLen, &capIcqJen, 4)))) //detecting mod and core version, please fix me
+ {
+ char sz[64];
+ static char szTmp[256];
+ BYTE mver0 = (*capId)[0x4];
+ BYTE mver1 = (*capId)[0x5];
+ BYTE mver2 = (*capId)[0x6];
+ BYTE mver3 = (*capId)[0x7];
+ BYTE iver0 = (*capId)[0x8];
+ BYTE iver1 = (*capId)[0x9];
+ BYTE iver2 = (*capId)[0xA];
+ BYTE iver3 = (*capId)[0xB];
+ BYTE secure = (*capId)[0xC];
+ BYTE ModVer = (*capId)[0x3];
+ BYTE Unicode = (BYTE)(dwFT3>>24)&0xFF;
+ if (mver1 < 20 && iver1 < 20)
+ {
+ strcpy(szTmp, " (Miranda IM ");
+ if (mver0 & 0x80)
+ {
+ mir_snprintf(sz, sizeof(sz), "0.%u.%u alpha build #%u", mver1, mver2,mver3);
+ lstrcatA(szTmp, sz);
+ }
+ else
+ {
+ mir_snprintf(sz, sizeof(sz), "%u.%u.%u.%u", mver0, mver1, mver2,mver3);
+ lstrcatA(szTmp, sz);
+ }
+ if (Unicode == 0x80||dwFT1 == 0x7fffffff)
+ lstrcatA(szTmp," Unicode");
+ if (ModVer == 'p')
+ lstrcatA(szTmp," (ICQ "ICQ_MODNAME"");
+ else if (((*capId)[0x0]) == 's')
+ lstrcatA(szTmp," (ICQ S!N");
+ else if (((*capId)[0x0]) == 'e')
+ lstrcatA(szTmp," (ICQ eternity/PlusPlus++"); //mod of mod of mod of mod of mod
+ else if(ModVer == 'j')
+ lstrcatA(szTmp," (ICQ S7 & SSS");
+ if (iver0 == 0x80)
+ {
+ mir_snprintf(sz, sizeof(sz), " 0.%u.%u.%u alpha)", iver1, iver2, iver3);
+ lstrcatA(szTmp,sz);
+ }
+ else
+ {
+ mir_snprintf(sz, sizeof(sz), " %u.%u.%u.%u)",iver0, iver1, iver2, iver3);
+ lstrcatA(szTmp,sz);
+ }
+ lstrcatA(szTmp,")");
+ if (secure != 0 && secure != 20||dwFT3 == 0x5AFEC0DE)
+ lstrcatA(szTmp, " (SecureIM)");
+ }
+ if (iver1 >= 20 && mver1 >= 20||MatchCap(caps, wLen, &capIcqJs7old, 0x10))
+ {
+ strcpy(sz, " (Miranda IM (ICQ S7 & SSS))");
+ strcpy(szTmp,sz);
+ if (MatchCap(caps, wLen, &capIcqJs7s, 0x10))
+ lstrcatA(sz," (SecureIM))");
+ }
+ szExtra=szTmp;
+ }
+ if (szExtra)
+ {
+ if (szClient != szClientBuf)
+ {
+ strcpy(szClientBuf, szClient);
+ szClient = szClientBuf;
+ }
+ if (szClient != szExtra)
+ lstrcatA(szClient, szExtra);
+ }
+ }
+ { // custom miranda packs
+ char *capId;
+ if (capId = (char*)MatchCap(caps, wLen, &capMimPack, 4))
+ {
+ char szPack[16];
+ mir_snprintf(szPack, 16, " [%.12s]", capId+4);
+ lstrcatA(szClient, szPack);
+ }
+ }
+ NetLog_Server("Client identified as %s", szClient);
+// ICQWriteContactSettingUtf(hContact, "MirVer", szClient); //thi already fixed in other place
+ return szClient;
+}
diff --git a/icqj_s7_sss_mod/icq_constants.h b/icqj_s7_sss_mod/icq_constants.h new file mode 100644 index 0000000..9400a00 --- /dev/null +++ b/icqj_s7_sss_mod/icq_constants.h @@ -0,0 +1,614 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007,2008 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+// Copyright 2008 [sss], chaos.persei, nullbie, baloo, jarvis
+//
+// 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$
+// Revision : $Revision: 48 $
+// Last change on : $Date: 2007-08-26 16:12:47 +0300 (Вс, 26 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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 0x7fffffff // 0x0 asci, 0x7 unicode (??)
+#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 1
+#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_BIGGER_AVATARS 1
+#define DEFAULT_AVATARS_CHECK 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
+
+
+// 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
+#define MTN_WINDOW_CLOSED 0x000F
+
+
+
+// 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
+//new caps
+#define CAP_NEWCAP 0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
+#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_AIM_FILE 0x09, 0x46, 0x13, 0x43, 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
+#define CAP_ICQ_DEVIL 0x09, 0x46, 0x13, 0x4C, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
+//other caps
+#define CAP_RTF 0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92
+#define CAP_HTML 0x01, 0x38, 0xca, 0x7b, 0x76, 0x9a, 0x49, 0x15, 0x88, 0xf2, 0x13, 0xfc, 0x00, 0x97, 0x9e, 0xa8
+#define CAP_CONTACTS 0x09, 0x46, 0x13, 0x4b, 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_ICQDIRECT 0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
+#define CAP_XTRAZ 0x1A, 0x09, 0x3C, 0x6C, 0xD7, 0xFD, 0x4E, 0xC5, 0x9D, 0x51, 0xA6, 0x47, 0x4E, 0x34, 0xF5, 0xA0
+#define CAP_OSCAR_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_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
+
+
+
+// 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_HTML 0x00000008
+#define CAPF_CONTACTS 0x00004000
+#define CAPF_XTRAZ_CHAT 0x00000400
+#define CAPF_VOICE_CHAT 0x00000800
+#define CAPF_ICQ_DEVIL 0x00001000
+#define CAPF_DIRECT 0x00002000
+#define CAPF_STATUSMSGEXT 0x01000000
+
+
+// Message Capability IDs
+#define MCAP_SRV_RELAY_FMT_s 0x09461349, 0x4c7f11d1, 0x82224445, 0x53540000
+#define MCAP_REVERSE_DC_REQ_s 0x09461344, 0x4c7f11d1, 0x82224445, 0x53540000
+#define MCAP_FILE_TRANSFER_s 0x09461343, 0x4c7f11d1, 0x82224445, 0x53540000
+#define MCAP_CONTACTS_s 0x0946134b, 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
+
+#define X_STATUS 0x40000000
+#define WAS_FOUND 0x80000000
+
+// 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_AUTOONLINE 0xE7 // Auto online message
+#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_SMS_MESSAGE 0x110 // SMS message from Mobile
+#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
+#define MTYPE_TZER_MESSAGE 0x501 // Tzer Message
+
+// 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_SMS_MESSAGE_s 0x0e28f600, 0x11e7d311, 0xbcf30004, 0xac969dc2
+#define MGTYPE_XTRAZ_SCRIPT_s 0x3b60b3ef, 0xd82a6c45, 0xa4e09c5a, 0x5e67e865
+#define MGTYPE_TZER_MESSAGE_s 0x4fa6f34c, 0x09b7fd48, 0x92087e85, 0x7ae07330
+
+// Message Plugin Sub-Type IDs
+#define MGTYPE_STANDARD_SEND 0x0000
+#define MGTYPE_CONTACTS_REQUEST 0x0002
+#define MGTYPE_SCRIPT_INVITATION 0x0001
+#define MGTYPE_SCRIPT_DATA 0x0002
+#define MGTYPE_SCRIPT_USER_REMOVE 0x0004
+#define MGTYPE_SCRIPT_NOTIFY 0x0008
+#define MGTYPE_UNDEFINED 0xFFFF
+
+
+
+/* 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
+#define ICQ_LOCATION_QRY_USER_INFO 0x0015
+
+/* 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_CLI_REQ_OFFLINE 0x0010
+#define ICQ_MSG_MTN 0x0014
+#define ICQ_MSG_SRV_OFFLINE_REPLY 0x0017
+
+/* 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_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 authorized 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
+
+#define MAX_SSI_TLV_NAME_SIZE 0x40
+#define MAX_SSI_TLV_COMMENT_SIZE 0x50
+
+// Client ID constants (internal)
+#define CLID_GENERIC 0x00 // Generic clients (eg. older official clients)
+#define CLID_ALTERNATIVE 0x01 // Clients not using tick for MsgID (most third-party clients)
+#define CLID_MIRANDA 0x02 // Hey, that's mate!
+#define CLID_ICQ6 0x10 // Mark ICQ6 as it has some non obvious limitations!
+
+
+// Internal Constants
+#define ICQ_PLUG_VERSION 0x80030869 // last icq plus
+#define ICQ_JOEWHALE_VERSION 0x80030A0A // last Joe@Whale
+#define ICQ_BM_VERSION 0x81030A09 // last BM
+#define ICQ_SIN_VERSION 0x80030A1F // last S!N
+#define ICQ_S7SSS_VERSION 0x80030869 // last S7&SSS
+#define ICQ_ETERN_VERSION 0x80035825 // last icq eternity
+#define ICQ_VERSION 8 // Protocol version
+#define DC_TYPE DC_NORMAL // Used for DC settings
+#define MAX_CONTACTSSEND 15
+#define MAX_MESSAGESNACSIZE 8000
+#define CLIENTRATELIMIT 0
+#define UPDATE_THRESHOLD 14 // Two weeks
+#define COOKIE_TIMEOUT 3600 // One hour
+#define KEEPALIVE_INTERVAL 57000 // One minute
+#define WEBFRONTPORT 0x50
+#define CLIENTFEATURES 0x3
+#define URL_FORGOT_PASSWORD "https://www.icq.com/password/"
+#define URL_REGISTER_UIN "https://www.icq.com/register/"
+#define FLAP_MARKER 0x2a
+#define CLIENT_MD5_STRING "AOL Instant Messenger (SM)"
+#define UNIQUEIDSETTING "UIN"
+#define UINMAXLEN 11 // DWORD string max len + 1
+#define OSCAR_PROXY_HOST "ars.oscar.aol.com"
+#define OSCAR_PROXY_VERSION 0x044A
+
+#define CLIENT_ID_STRING "ICQ Client" // Client identification, mimic ICQ 6
+#define CLIENT_ID_CODE 0x010a
+#define CLIENT_VERSION_MAJOR 0x0006
+#define CLIENT_VERSION_MINOR 0x0000
+#define CLIENT_VERSION_LESSER 0x0000
+#define CLIENT_VERSION_BUILD 0x1797
+#define CLIENT_DISTRIBUTION 0x00007535
+#define CLIENT_LANGUAGE "en"
+#define CLIENT_COUNTRY "us"
+
+
+
+//auth
+//db event added to NULL or hcontact
+//blob format is:
+//ASCIIZ text
+//DWORD uin
+//HANDLE hContact
+#define ICQEVENTTYPE_AUTH_GRANTED 2004 //database event type
+#define ICQEVENTTYPE_AUTH_DENIED 2005 //database event type
+#define ICQEVENTTYPE_AUTH_REQUESTED 2006 //database event type
+#define ICQEVENTTYPE_SELF_REMOVE 2007 //database event type
+#define ICQEVENTTYPE_FUTURE_AUTH 2008 //database event type
+#define ICQEVENTTYPE_CLIENT_CHANGE 2009 //database event type
+#define ICQEVENTTYPE_CHECK_STATUS 2010 //database event type
+#define ICQEVENTTYPE_IGNORECHECK_STATUS 2011 //database event type
+#define ICQEVENTTYPE_YOU_ADDED 2012 //database event type
+#define ICQEVENTTYPE_WAS_FOUND 2013 //db event )
+
+#endif /* __ICQ_CONSTANTS_H */
diff --git a/icqj_s7_sss_mod/icq_db.c b/icqj_s7_sss_mod/icq_db.c new file mode 100644 index 0000000..6a345cd --- /dev/null +++ b/icqj_s7_sss_mod/icq_db.c @@ -0,0 +1,379 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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.");
+}
+
+
+
+void __stdcall ICQCreateResidentSetting(const char* szSetting)
+{
+ char pszSetting[2*MAX_PATH];
+
+ strcpy(pszSetting, gpszICQProtoName);
+ strcat(pszSetting, "/");
+ strcat(pszSetting, szSetting);
+ CallService(MS_DB_SETSETTINGRESIDENT, 1, (WPARAM)pszSetting);
+}
+
+
+
+BYTE __stdcall ICQGetContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bDef)
+{
+ return DBGetContactSettingByte(hContact, gpszICQProtoName, szSetting, bDef);
+}
+
+
+
+WORD __stdcall ICQGetContactSettingWord(HANDLE hContact, const char* szSetting, WORD wDef)
+{
+ return DBGetContactSettingWord(hContact, gpszICQProtoName, szSetting, wDef);
+}
+
+
+
+DWORD __stdcall 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 __stdcall ICQGetContactSettingUIN(HANDLE hContact)
+{
+ return ICQGetContactSettingDword(hContact, UNIQUEIDSETTING, 0);
+}
+
+
+
+int __stdcall 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 __stdcall ICQGetContactSetting(HANDLE hContact, const char* szSetting, DBVARIANT *dbv)
+{
+ if (bUtfReadyDB)
+ return DBGetContactSettingW(hContact, gpszICQProtoName, szSetting, dbv);
+ else
+ return DBGetContactSetting(hContact, gpszICQProtoName, szSetting, dbv);
+}
+
+
+
+int __stdcall ICQGetContactSettingString(HANDLE hContact, const char* szSetting, DBVARIANT *dbv)
+{
+ if (bUtfReadyDB)
+ return DBGetContactSettingString(hContact, gpszICQProtoName, szSetting, dbv);
+ else
+ return ICQGetContactSetting(hContact, szSetting, dbv);
+}
+
+
+
+char* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szDef)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ char* szRes;
+
+ if (bUtfReadyDB)
+ {
+ if (DBGetContactSettingUTF8String(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* __stdcall ICQGetContactSettingUtf(HANDLE hContact, const char* szSetting, char* szDef)
+{
+ return UniGetContactSettingUtf(hContact, gpszICQProtoName, szSetting, szDef);
+}
+
+
+
+WORD __stdcall ICQGetContactStatus(HANDLE hContact)
+{
+ return ICQGetContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+}
+
+
+
+// (c) by George Hazan
+int __stdcall 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 __stdcall ICQDeleteContactSetting(HANDLE hContact, const char* szSetting)
+{
+ return DBDeleteContactSetting(hContact, gpszICQProtoName, szSetting);
+}
+
+
+
+int __stdcall ICQWriteContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bValue)
+{
+ return DBWriteContactSettingByte(hContact, gpszICQProtoName, szSetting, bValue);
+}
+
+
+
+int __stdcall ICQWriteContactSettingWord(HANDLE hContact, const char* szSetting, WORD wValue)
+{
+ return DBWriteContactSettingWord(hContact, gpszICQProtoName, szSetting, wValue);
+}
+
+
+
+int __stdcall ICQWriteContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwValue)
+{
+ return DBWriteContactSettingDword(hContact, gpszICQProtoName, szSetting, dwValue);
+}
+
+
+
+int __stdcall ICQWriteContactSettingString(HANDLE hContact, const char* szSetting, char* szValue)
+{
+ return DBWriteContactSettingString(hContact, gpszICQProtoName, szSetting, szValue);
+}
+
+
+
+int __stdcall UniWriteContactSettingUtf(HANDLE hContact, const char *szModule, const char* szSetting, char* szValue)
+{
+ if (bUtfReadyDB)
+ return DBWriteContactSettingUTF8String(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 __stdcall ICQWriteContactSettingUtf(HANDLE hContact, const char* szSetting, char* szValue)
+{
+ return UniWriteContactSettingUtf(hContact, gpszICQProtoName, szSetting, szValue);
+}
+
+
+
+int __stdcall ICQWriteContactSettingBlob(HANDLE hContact,const char *szSetting,const char *val, const int cbVal)
+{
+ DBCONTACTWRITESETTING cws;
+
+ 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 __stdcall ICQFreeVariant(DBVARIANT* dbv)
+{
+ return DBFreeVariant(dbv);
+}
+
+
+
+int __fastcall IsICQContact(HANDLE hContact)
+{
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ return !strcmpnull(szProto, gpszICQProtoName);
+}
+
+
+
+HANDLE __stdcall ICQAddEvent(HANDLE hContact, WORD wType, DWORD dwTime, DWORD flags, DWORD cbBlob, PBYTE pBlob)
+{
+ DBEVENTINFO dbei = {0};
+
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = gpszICQProtoName;
+ dbei.timestamp = dwTime;
+ dbei.flags = flags;
+ dbei.eventType = wType;
+ dbei.cbBlob = cbBlob;
+ dbei.pBlob = pBlob;
+
+ return (HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);
+}
+
+
+
+HANDLE __fastcall ICQFindFirstContact()
+{
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, (LPARAM)gpszICQProtoName);
+
+ if (IsICQContact(hContact))
+ {
+ return hContact;
+ }
+ return ICQFindNextContact(hContact);
+}
+
+
+
+HANDLE __fastcall ICQFindNextContact(HANDLE hContact)
+{
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,(LPARAM)gpszICQProtoName);
+
+ while (hContact != NULL)
+ {
+ if (IsICQContact(hContact))
+ {
+ return hContact;
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,(LPARAM)gpszICQProtoName);
+ }
+ return hContact;
+}
+
+
+
+char* __stdcall ICQGetContactCListGroup(HANDLE hContact)
+{
+ return UniGetContactSettingUtf(hContact, "CList", "Group", NULL);
+}
+
+
+
+int __stdcall ICQSetContactCListGroup(HANDLE hContact, const char *szGroup)
+{
+ /// TODO
+ return 0;
+}
diff --git a/icqj_s7_sss_mod/icq_db.h b/icqj_s7_sss_mod/icq_db.h new file mode 100644 index 0000000..4fb90c4 --- /dev/null +++ b/icqj_s7_sss_mod/icq_db.h @@ -0,0 +1,83 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_DB_H
+#define __ICQ_DB_H
+
+void InitDB();
+
+void __stdcall ICQCreateResidentSetting(const char* szSetting);
+
+BYTE __stdcall ICQGetContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bDef);
+WORD __stdcall ICQGetContactSettingWord(HANDLE hContact, const char* szSetting, WORD wDef);
+DWORD __stdcall ICQGetContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwDef);
+DWORD __stdcall ICQGetContactSettingUIN(HANDLE hContact);
+int __stdcall ICQGetContactSettingUID(HANDLE hContact, DWORD *pdwUin, uid_str* ppszUid);
+int __stdcall ICQGetContactSetting(HANDLE hContact, const char* szSetting, DBVARIANT *dbv);
+int __stdcall ICQGetContactSettingString(HANDLE hContact, const char* szSetting, DBVARIANT *dbv);
+char* __stdcall ICQGetContactSettingUtf(HANDLE hContact, const char* szSetting, char* szDef);
+
+WORD __stdcall ICQGetContactStatus(HANDLE hContact);
+
+int __stdcall ICQGetContactStaticString(HANDLE hContact, const char* valueName, char* dest, int dest_len);
+
+int __stdcall ICQDeleteContactSetting(HANDLE hContact, const char* szSetting);
+
+int __stdcall ICQWriteContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bValue);
+int __stdcall ICQWriteContactSettingWord(HANDLE hContact, const char* szSetting, WORD wValue);
+int __stdcall ICQWriteContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwValue);
+int __stdcall ICQWriteContactSettingString(HANDLE hContact, const char* szSetting, char* szValue);
+int __stdcall ICQWriteContactSettingUtf(HANDLE hContact, const char* szSetting, char* szValue);
+
+int __stdcall ICQWriteContactSettingBlob(HANDLE hContact,const char *szSetting,const char *val, const int cbVal);
+
+char* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szDef);
+int __stdcall UniWriteContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szValue);
+
+int __stdcall ICQFreeVariant(DBVARIANT* dbv);
+
+HANDLE __stdcall ICQAddEvent(HANDLE hContact, WORD wType, DWORD dwTime, DWORD flags, DWORD cbBlob, PBYTE pBlob);
+
+int __fastcall IsICQContact(HANDLE hContact);
+HANDLE __fastcall ICQFindFirstContact();
+HANDLE __fastcall ICQFindNextContact(HANDLE hContact);
+
+char* __stdcall ICQGetContactCListGroup(HANDLE hContact);
+int __stdcall ICQSetContactCListGroup(HANDLE hContact, const char *szGroup);
+
+
+#endif /* __ICQ_DB_H */
diff --git a/icqj_s7_sss_mod/icq_direct.c b/icqj_s7_sss_mod/icq_direct.c new file mode 100644 index 0000000..7681680 --- /dev/null +++ b/icqj_s7_sss_mod/icq_direct.c @@ -0,0 +1,1497 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 44 $
+// Last change on : $Date: 2007-08-22 04:03:43 +0300 (Ср, 22 авг 2007) $
+// Last change by : $Author: redeemerXx $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_cluiframes.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;
+
+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);
+
+
+
+HANDLE hDirect;
+static HANDLE hHookExtraIconsRebuild = NULL;
+static HANDLE hHookExtraIconsApply = NULL;
+
+static int CListMW_ExtraIconsRebuild(WPARAM wParam, LPARAM lParam);
+static int CListMW_ExtraIconsApply(WPARAM wParam, LPARAM lParam);
+
+
+void InitDCEvents(void)
+{
+ char szSection[MAX_PATH + 64];
+ char str[MAX_PATH], prt[MAX_PATH];
+ null_snprintf(szSection, sizeof(szSection), ICQTranslateUtfStatic("%s", str, MAX_PATH), ICQTranslateUtfStatic(gpszICQProtoName, prt, MAX_PATH));
+ IconLibDefine(ICQTranslateUtfStatic("Direct Connection", str, MAX_PATH), szSection, "dcico", LoadIcon(hIconInst, MAKEINTRESOURCE(IDI_DC)), NULL, -(IDI_DC));
+ hHookExtraIconsRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, CListMW_ExtraIconsRebuild);
+ hHookExtraIconsApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, CListMW_ExtraIconsApply);
+}
+
+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);
+
+ if (hHookExtraIconsRebuild)
+ UnhookEvent(hHookExtraIconsRebuild);
+
+ if (hHookExtraIconsApply)
+ UnhookEvent(hHookExtraIconsApply);
+}
+
+
+
+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_CloseConnection(&hConnection, FALSE);
+ }
+ }
+
+ LeaveCriticalSection(&directConnListMutex);
+}
+
+
+
+static void ResizeDirectList(int nSize)
+{
+ if ((directConnSize < nSize) || ((directConnSize > nSize + 6) && nSize))
+ {
+ if (directConnSize < nSize)
+ directConnSize += 4;
+ else
+ directConnSize -= 4;
+
+ directConnList = (directconnect**)SAFE_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** )SAFE_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**)SAFE_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 bPassive)
+{
+ 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 (!bPassive && !bIsCreated && !bIsOpen && type == DIRECTCONN_STANDARD && gbDCMsgEnabled == 2)
+ { // do not try to open DC to offline contact
+ if (ICQGetContactStatus(hContact) == ID_STATUS_OFFLINE) return FALSE;
+ // do not try to open DC if previous attempt was not successfull
+ if (ICQGetContactSettingByte(hContact, "DCStatus", 0)) return FALSE;
+
+ // Set DC status as tried
+ ICQWriteContactSettingByte(hContact, "DCStatus", 1);
+ // Create a new connection
+ OpenDirectConnection(hContact, DIRECTCONN_STANDARD, NULL);
+ }
+
+ return bIsOpen;
+}
+//by chaos.persei - simplified var of prev func
+BOOL IsDCOpen(HANDLE hContact)
+{
+ int i;
+ BOOL bIsOpen = FALSE;
+
+
+ EnterCriticalSection(&directConnListMutex);
+
+ for (i = 0; i < directConnCount; i++)
+ {
+ if (directConnList[i])
+ {
+ if (directConnList[i]->hContact == hContact)
+ if (directConnList[i]->bIconShown)
+ {
+ // Connection is OK
+ bIsOpen = TRUE;
+ // we are going to use the conn, so prevent timeout
+ break;
+ }
+ }
+ }
+
+ LeaveCriticalSection(&directConnListMutex);
+
+ 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, void *pExtra)
+{
+ // Start a new thread for the incomming connection
+ ICQCreateThread(icq_directThread, CreateDTSI(NULL, hNewConnection, -1));
+}
+
+//by chaos.persei - direct connections clist icons
+//TODO - ???
+
+void setShown(HANDLE hContact, BOOL bShown)
+{
+ int i;
+
+
+ EnterCriticalSection(&directConnListMutex);
+
+ for (i = 0; i < directConnCount; i++)
+ {
+ if (directConnList[i])
+ {
+ if (directConnList[i]->hContact == hContact)
+ directConnList[i]->bIconShown = bShown;
+ }
+ }
+
+ LeaveCriticalSection(&directConnListMutex);
+
+}
+
+HICON GetDCIcon(UINT flags)
+{
+ char szTemp[64];
+ HICON icon;
+ null_snprintf(szTemp, sizeof(szTemp), "dcico");
+ icon = IconLibGetIcon(szTemp);
+ if (flags & LR_SHARED)
+ return icon;
+ else
+ return CopyIcon(icon);
+}
+
+static void setContactExtraIcon(HANDLE hContact, BOOL bFunc, BOOL bRem)
+{
+ WORD icon_pos = ICQGetContactSettingWord(NULL, "dc_icon_pos", 5);
+ if( DBGetContactSettingByte(NULL, "ICQ", "ShowDCIcon", 1)==0 ) return;
+ if(icon_pos<=0||icon_pos>9)
+ {
+ icon_pos=5;
+ }
+ {
+ IconExtraColumn iec;
+ iec.cbSize = sizeof(iec);
+ iec.hImage = ((IsDCOpen(hContact) || bFunc) && DBGetContactSettingByte(NULL, "ICQ", "ShowDCIcon", 1) && !bRem ? hDirect : (HANDLE)-1);
+ iec.ColumnType = icon_pos;
+ if (bFunc)
+ setShown(hContact, 1);
+ if (bRem)
+ setShown(hContact, 0);
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)&iec);
+ }
+}
+
+static int CListMW_ExtraIconsRebuild(WPARAM wParam, LPARAM lParam)
+{
+ if (ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+ hDirect = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)GetDCIcon(1), 0);
+ }
+
+ return 0;
+}
+static int CListMW_ExtraIconsApply(WPARAM wParam, LPARAM lParam)
+{
+ if (ServiceExists(MS_CLIST_EXTRA_SET_ICON))
+ {
+ if (IsICQContact((HANDLE)wParam))
+ {
+ setContactExtraIcon((HANDLE)wParam, 0, 0);
+ }
+ }
+ return 0;
+}
+//eo
+
+// Opens direct connection of specified type to specified contact
+void OpenDirectConnection(HANDLE hContact, int type, void* pvExtra)
+{
+ directthreadstartinfo* dtsi;
+
+ // Create a new connection
+ dtsi = CreateDTSI(hContact, NULL, type);
+ dtsi->pvExtra = pvExtra;
+
+ ICQCreateThread(icq_directThread, dtsi);
+}
+
+
+
+// Safely close NetLib connection - do not corrupt direct connection list
+void CloseDirectConnection(directconnect *dc)
+{
+ HANDLE hContact2;
+
+ EnterCriticalSection(&directConnListMutex);
+
+ hContact2 = &dc->hContact;
+ NetLib_CloseConnection(&dc->hConnection, FALSE);
+#ifdef _DEBUG
+ if (dc->hConnection)
+ NetLog_Direct("Direct conn closed (%p)", dc->hConnection);
+#endif
+
+ LeaveCriticalSection(&directConnListMutex);
+
+ setContactExtraIcon(hContact2, 0, 1);
+}
+
+
+
+// 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;
+ int nSkipPacketBytes = 0;
+ DWORD dwReqMsgID1;
+ DWORD dwReqMsgID2;
+
+
+ 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.dwConnectionCookie = ICQGetContactSettingDword(dtsi->hContact, "DirectCookie", 0);
+ dc.wVersion = ICQGetContactSettingWord(dtsi->hContact, "Version", 0);
+
+ if (!dc.dwRemoteExternalIP && !dc.dwRemoteInternalIP)
+ { // we do not have any ip, do not try to connect
+ RemoveDirectConnFromList(&dc);
+ SAFE_FREE(&dtsi);
+ return 0;
+ }
+ if (!dc.dwRemotePort)
+ { // we do not have port, do not try to connect
+ RemoveDirectConnFromList(&dc);
+ SAFE_FREE(&dtsi);
+ return 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)
+ {
+ reverse_cookie *pCookie = (reverse_cookie*)dtsi->pvExtra;
+
+ dwReqMsgID1 = pCookie->pMessage.dwMsgID1;
+ dwReqMsgID2 = pCookie->pMessage.dwMsgID2;
+ dc.dwReqId = (DWORD)pCookie->ft;
+ SAFE_FREE(&pCookie);
+ }
+ }
+ 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 = {0}, addr2 = {0};
+
+ if (dc.dwRemoteExternalIP == dc.dwLocalExternalIP && dc.dwRemoteInternalIP)
+ addr.S_un.S_addr = htonl(dc.dwRemoteInternalIP);
+ else
+ {
+ addr.S_un.S_addr = htonl(dc.dwRemoteExternalIP);
+ // for different internal, try it also (for LANs with multiple external IP, VPNs, etc.)
+ if (dc.dwRemoteInternalIP != dc.dwRemoteExternalIP)
+ addr2.S_un.S_addr = htonl(dc.dwRemoteInternalIP);
+ }
+
+ 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;
+ nloc.timeout = 8; // 8 secs to connect
+ dc.hConnection = NetLib_OpenConnection(ghDirectNetlibUser, dc.type==DIRECTCONN_REVERSE?"Reverse ":NULL, &nloc);
+ if(dc.hConnection)
+ setContactExtraIcon(dc.hContact, 1, 0);
+ if (!dc.hConnection && addr2.S_un.S_addr)
+ { // first address failed, try second one if available
+ nloc.szHost = inet_ntoa(addr2);
+ dc.hConnection = NetLib_OpenConnection(ghDirectNetlibUser, dc.type==DIRECTCONN_REVERSE?"Reverse ":NULL, &nloc);
+ }
+ if (!dc.hConnection)
+ {
+ if (CheckContactCapabilities(dc.hContact, CAPF_DIRECT))
+ { // only if the contact support ICQ DC connections
+ 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)
+ { // init cookie
+ InitMessageCookie(&pCookie->pMessage);
+ pCookie->pMessage.bMessageType = MTYPE_REVERSE_REQUEST;
+ pCookie->hContact = dc.hContact;
+ pCookie->dwUin = dc.dwRemoteUin;
+ pCookie->type = dc.type;
+ pCookie->ft = dc.ft;
+ dwCookie = AllocateCookie(CKT_REVERSEDIRECT, 0, dc.hContact, pCookie);
+ icq_sendReverseReq(&dc, dwCookie, (message_cookie_data*)pCookie);
+ RemoveDirectConnFromList(&dc);
+
+ return 0;
+ }
+ else
+ NetLog_Direct("Reverse failed (%s)", "malloc failed");
+ }
+ }
+ else // Set DC status to failed
+ ICQWriteContactSettingByte(dc.hContact, "DCStatus", 2);
+
+ if (dc.type == DIRECTCONN_REVERSE) // failed reverse connection
+ { // announce we failed
+ icq_sendReverseFailed(&dc, dwReqMsgID1, dwReqMsgID2, 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);
+ // Release transfer
+ SafeReleaseFileTransfer(&dc.ft);
+ }
+ 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
+ setContactExtraIcon(dc.hContact, 1, 0);
+ 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 if (packetRecv.bytesAvailable < nSkipPacketBytes)
+ { // the whole buffer needs to be skipped
+ nSkipPacketBytes -= packetRecv.bytesAvailable;
+ packetRecv.bytesUsed = packetRecv.bytesAvailable;
+ }
+ else
+ {
+ int i;
+
+ for (i = nSkipPacketBytes, nSkipPacketBytes = 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;
+ }
+ else
+ {
+ if (packetRecv.bytesAvailable >= i + 2 && wLen > 8190)
+ { // check for too big packages
+ NetLog_Direct("Error: Package too big: %d bytes, skipping.");
+ nSkipPacketBytes = wLen;
+ packetRecv.bytesUsed = i + 2;
+ break;
+ }
+ }
+
+ 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;
+ }
+ }
+ if(!dc.hConnection) setContactExtraIcon(dc.hContact, 0, 1);
+ // End of packet receiving loop
+
+ NetLib_SafeCloseHandle(&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);
+
+ SafeReleaseFileTransfer(&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;
+
+ dc->incoming = 0;
+
+ if (FindCookie(dc->dwReqId, NULL, &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 (dc->incoming)
+ { // this is the first PEER_INIT with our cookie
+ if (dwCookie != ICQGetContactSettingDword(hContact, "DirectCookie", 0))
+ {
+ NetLog_Direct("Error: Received PEER_INIT with broken cookie");
+ CloseDirectConnection(dc);
+ return;
+ }
+ }
+ else
+ { // this is the second PEER_INIT with peer cookie
+ if (dwCookie != dc->dwConnectionCookie)
+ {
+ 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;
+
+ if (FindCookie(dc->dwReqId, NULL, &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->dwConnectionCookie = 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;
+ }
+ }
+ // Set DC Status to successful
+ ICQWriteContactSettingByte(dc->hContact, "DCStatus", 0);
+ }
+ 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;
+}
+
+
+
+// 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->dwConnectionCookie); // 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 (ICQGetContactSettingString(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_s7_sss_mod/icq_direct.h b/icqj_s7_sss_mod/icq_direct.h new file mode 100644 index 0000000..f80c378 --- /dev/null +++ b/icqj_s7_sss_mod/icq_direct.h @@ -0,0 +1,133 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_DIRECT_H
+#define __ICQ_DIRECT_H
+
+typedef struct {
+ message_cookie_data pMessage;
+ BYTE ft_magic;
+ 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;
+ DWORD dwConnectionCookie;
+ int type;
+ WORD wVersion;
+ int incoming;
+ int wantIdleTime;
+ int packetPending;
+ DWORD dwRemotePort;
+ DWORD dwRemoteUin;
+ DWORD dwRemoteExternalIP;
+ DWORD dwRemoteInternalIP;
+ DWORD dwLocalExternalIP;
+ DWORD dwLocalInternalIP;
+ int initialised;
+ int handshake;
+ DWORD dwThreadId;
+ filetransfer *ft;
+ DWORD dwReqId; // Reverse Connect request cookie
+ BOOL bIconShown;
+} directconnect;
+
+void OpenDirectConnection(HANDLE hContact, int type, void *pvExtra);
+int IsDirectConnectionOpen(HANDLE hContact, int type, int bPassive);
+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 *pExtra);
+void InitDCEvents(void);
+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_s7_sss_mod/icq_directmsg.c b/icqj_s7_sss_mod/icq_directmsg.c new file mode 100644 index 0000000..f96286c --- /dev/null +++ b/icqj_s7_sss_mod/icq_directmsg.c @@ -0,0 +1,381 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 48 $
+// Last change on : $Date: 2007-08-26 16:12:47 +0300 (Вс, 26 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_AUTOONLINE:
+ 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:
+ {
+ message_ack_params pMsgAck = {0};
+
+ buf -= wTextLen;
+ wLen += wTextLen;
+
+ pMsgAck.bType = MAT_DIRECT;
+ pMsgAck.pDC = dc;
+ pMsgAck.wCookie = wCookie;
+ pMsgAck.msgType = bMsgType;
+ pMsgAck.bFlags = bMsgFlags;
+ handleMessageTypes(dc->dwRemoteUin, time(NULL), 0, 0, wCookie, dc->wVersion, (int)bMsgType, (int)bMsgFlags, 0, (DWORD)wLen, wTextLen, buf, TRUE, &pMsgAck);
+ 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, NULL);
+ }
+ else
+ {
+ HANDLE hCookieContact;
+ message_cookie_data* pCookieData = NULL;
+
+ if (!FindCookie(wCookie, &hCookieContact, &pCookieData))
+ {
+ NetLog_Direct("Received an unexpected direct ack");
+ }
+ else if (hCookieContact != dc->hContact)
+ {
+ NetLog_Direct("Direct Contact does not match Cookie Contact(0x%x != 0x%x)", dc->hContact, hCookieContact);
+ 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 dwLengthToEnd;
+ DWORD dwDataLength;
+ char* pszFileName = NULL;
+ int typeId;
+ 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
+
+ NetLog_Direct("Parsing Greeting message through direct");
+
+ if (!unpackPluginTypeId(&buf, &wLen, &typeId, &qt, TRUE)) return;
+
+ // 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)
+ {
+ message_ack_params pMsgAck = {0};
+
+ pMsgAck.bType = MAT_DIRECT;
+ pMsgAck.pDC = dc;
+ pMsgAck.wCookie = wCookie;
+ pMsgAck.msgType = typeId;
+ handleMessageTypes(dc->dwRemoteUin, time(NULL), 0, 0, wCookie, dc->wVersion, typeId, 0, 0, dwLengthToEnd, (WORD)dwDataLength, buf, TRUE, &pMsgAck);
+ }
+ 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, NULL);
+ }
+ else if (typeId && wCommand == DIRECT_ACK)
+ {
+ HANDLE hCookieContact;
+ message_cookie_data* pCookieData = NULL;
+
+ if (!FindCookie(wCookie, &hCookieContact, &pCookieData))
+ {
+ NetLog_Direct("Received an unexpected direct ack");
+ }
+ else if (hCookieContact != dc->hContact)
+ {
+ NetLog_Direct("Direct Contact does not match Cookie Contact(0x%x != 0x%x)", dc->hContact, hCookieContact);
+ 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(dc->dwRemoteUin, 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", typeId);
+ }
+}
diff --git a/icqj_s7_sss_mod/icq_fieldnames.c b/icqj_s7_sss_mod/icq_fieldnames.c new file mode 100644 index 0000000..0e1b41f --- /dev/null +++ b/icqj_s7_sss_mod/icq_fieldnames.c @@ -0,0 +1,281 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+struct fieldnames_t interestsField[]={
+ {100, LPGEN("Art")},
+ {101, LPGEN("Cars")},
+ {102, LPGEN("Celebrity Fans")},
+ {103, LPGEN("Collections")},
+ {104, LPGEN("Computers")},
+ {105, LPGEN("Culture & Literature")},
+ {106, LPGEN("Fitness")},
+ {107, LPGEN("Games")},
+ {108, LPGEN("Hobbies")},
+ {109, LPGEN("ICQ - Providing Help")},
+ {110, LPGEN("Internet")},
+ {111, LPGEN("Lifestyle")},
+ {112, LPGEN("Movies/TV")},
+ {113, LPGEN("Music")},
+ {114, LPGEN("Outdoor Activities")},
+ {115, LPGEN("Parenting")},
+ {116, LPGEN("Pets/Animals")},
+ {117, LPGEN("Religion")},
+ {118, LPGEN("Science/Technology")},
+ {119, LPGEN("Skills")},
+ {120, LPGEN("Sports")},
+ {121, LPGEN("Web Design")},
+ {122, LPGEN("Nature and Environment")},
+ {123, LPGEN("News & Media")},
+ {124, LPGEN("Government")},
+ {125, LPGEN("Business & Economy")},
+ {126, LPGEN("Mystics")},
+ {127, LPGEN("Travel")},
+ {128, LPGEN("Astronomy")},
+ {129, LPGEN("Space")},
+ {130, LPGEN("Clothing")},
+ {131, LPGEN("Parties")},
+ {132, LPGEN("Women")},
+ {133, LPGEN("Social science")},
+ {134, LPGEN("60's")},
+ {135, LPGEN("70's")},
+ {136, LPGEN("80's")},
+ {137, LPGEN("50's")},
+ {138, LPGEN("Finance and corporate")},
+ {139, LPGEN("Entertainment")},
+ {140, LPGEN("Consumer electronics")},
+ {141, LPGEN("Retail stores")},
+ {142, LPGEN("Health and beauty")},
+ {143, LPGEN("Media")},
+ {144, LPGEN("Household products")},
+ {145, LPGEN("Mail order catalog")},
+ {146, LPGEN("Business services")},
+ {147, LPGEN("Audio and visual")},
+ {148, LPGEN("Sporting and athletic")},
+ {149, LPGEN("Publishing")},
+ {150, LPGEN("Home automation")},
+ {-1, NULL}};
+
+struct fieldnames_t languageField[]={
+ {1, LPGEN("Arabic")},
+ {2, LPGEN("Bhojpuri")},
+ {3, LPGEN("Bulgarian")},
+ {4, LPGEN("Burmese")},
+ {5, LPGEN("Cantonese")},
+ {6, LPGEN("Catalan")},
+ {7, LPGEN("Chinese")},
+ {8, LPGEN("Croatian")},
+ {9, LPGEN("Czech")},
+ {10, LPGEN("Danish")},
+ {11, LPGEN("Dutch")},
+ {12, LPGEN("English")},
+ {13, LPGEN("Esperanto")},
+ {14, LPGEN("Estonian")},
+ {15, LPGEN("Farci")},
+ {16, LPGEN("Finnish")},
+ {17, LPGEN("French")},
+ {18, LPGEN("Gaelic")},
+ {19, LPGEN("German")},
+ {20, LPGEN("Greek")},
+ {21, LPGEN("Hebrew")},
+ {22, LPGEN("Hindi")},
+ {23, LPGEN("Hungarian")},
+ {24, LPGEN("Icelandic")},
+ {25, LPGEN("Indonesian")},
+ {26, LPGEN("Italian")},
+ {27, LPGEN("Japanese")},
+ {28, LPGEN("Khmer")},
+ {29, LPGEN("Korean")},
+ {30, LPGEN("Lao")},
+ {31, LPGEN("Latvian")},
+ {32, LPGEN("Lithuanian")},
+ {33, LPGEN("Malay")},
+ {34, LPGEN("Norwegian")},
+ {35, LPGEN("Polish")},
+ {36, LPGEN("Portuguese")},
+ {37, LPGEN("Romanian")},
+ {38, LPGEN("Russian")},
+ {39, LPGEN("Serbo-Croatian")},
+ {40, LPGEN("Slovak")},
+ {41, LPGEN("Slovenian")},
+ {42, LPGEN("Somali")},
+ {43, LPGEN("Spanish")},
+ {44, LPGEN("Swahili")},
+ {45, LPGEN("Swedish")},
+ {46, LPGEN("Tagalog")},
+ {47, LPGEN("Tatar")},
+ {48, LPGEN("Thai")},
+ {49, LPGEN("Turkish")},
+ {50, LPGEN("Ukrainian")},
+ {51, LPGEN("Urdu")},
+ {52, LPGEN("Vietnamese")},
+ {53, LPGEN("Yiddish")},
+ {54, LPGEN("Yoruba")},
+ {55, LPGEN("Afrikaans")},
+ {56, LPGEN("Bosnian")},
+ {57, LPGEN("Persian")},
+ {58, LPGEN("Albanian")},
+ {59, LPGEN("Armenian")},
+ {60, LPGEN("Punjabi")},
+ {61, LPGEN("Chamorro")},
+ {62, LPGEN("Mongolian")},
+ {63, LPGEN("Mandarin")},
+ {64, LPGEN("Taiwaness")},
+ {65, LPGEN("Macedonian")},
+ {66, LPGEN("Sindhi")},
+ {67, LPGEN("Welsh")},
+ {68, LPGEN("Azerbaijani")},
+ {69, LPGEN("Kurdish")},
+ {70, LPGEN("Gujarati")},
+ {71, LPGEN("Tamil")},
+ {72, LPGEN("Belorussian")},
+ {-1, NULL}};
+
+struct fieldnames_t pastField[]={
+ {300, LPGEN("Elementary School")},
+ {301, LPGEN("High School")},
+ {302, LPGEN("College")},
+ {303, LPGEN("University")},
+ {304, LPGEN("Military")},
+ {305, LPGEN("Past Work Place")},
+ {306, LPGEN("Past Organization")},
+ {399, LPGEN("Other")},
+ {-1, NULL}};
+
+struct fieldnames_t genderField[]={
+ {1, LPGEN("Female")},
+ {2, LPGEN("Male")},
+ {-1, NULL}};
+
+struct fieldnames_t workField[]={
+ {1, LPGEN("Academic")},
+ {2, LPGEN("Administrative")},
+ {3, LPGEN("Art/Entertainment")},
+ {4, LPGEN("College Student")},
+ {5, LPGEN("Computers")},
+ {6, LPGEN("Community & Social")},
+ {7, LPGEN("Education")},
+ {8, LPGEN("Engineering")},
+ {9, LPGEN("Financial Services")},
+ {10, LPGEN("Government")},
+ {11, LPGEN("High School Student")},
+ {12, LPGEN("Home")},
+ {13, LPGEN("ICQ - Providing Help")},
+ {14, LPGEN("Law")},
+ {15, LPGEN("Managerial")},
+ {16, LPGEN("Manufacturing")},
+ {17, LPGEN("Medical/Health")},
+ {18, LPGEN("Military")},
+ {19, LPGEN("Non-Government Organization")},
+ {20, LPGEN("Professional")},
+ {21, LPGEN("Retail")},
+ {22, LPGEN("Retired")},
+ {23, LPGEN("Science & Research")},
+ {24, LPGEN("Sports")},
+ {25, LPGEN("Technical")},
+ {26, LPGEN("University Student")},
+ {27, LPGEN("Web building")},
+ {99, LPGEN("Other services")},
+ {-1, NULL}};
+
+struct fieldnames_t affiliationField[]={
+ {200, LPGEN("Alumni Org.")},
+ {201, LPGEN("Charity Org.")},
+ {202, LPGEN("Club/Social Org.")},
+ {203, LPGEN("Community Org.")},
+ {204, LPGEN("Cultural Org.")},
+ {205, LPGEN("Fan Clubs")},
+ {206, LPGEN("Fraternity/Sorority")},
+ {207, LPGEN("Hobbyists Org.")},
+ {208, LPGEN("International Org.")},
+ {209, LPGEN("Nature and Environment Org.")},
+ {210, LPGEN("Professional Org.")},
+ {211, LPGEN("Scientific/Technical Org.")},
+ {212, LPGEN("Self Improvement Group")},
+ {213, LPGEN("Spiritual/Religious Org.")},
+ {214, LPGEN("Sports Org.")},
+ {215, LPGEN("Support Org.")},
+ {216, LPGEN("Trade and Business Org.")},
+ {217, LPGEN("Union")},
+ {218, LPGEN("Volunteer Org.")},
+ {299, LPGEN("Other")},
+ {-1, NULL}};
+
+struct fieldnames_t agesField[]={
+ {0x0011000D, LPGEN("13-17")},
+ {0x00160012, LPGEN("18-22")},
+ {0x001D0017, LPGEN("23-29")},
+ {0x0027001E, LPGEN("30-39")},
+ {0x00310028, LPGEN("40-49")},
+ {0x003B0032, LPGEN("50-59")},
+ {0x2710003C, LPGEN("60-above")},
+ {-1, NULL}};
+
+struct fieldnames_t maritalField[]={
+ {10, LPGEN("Single")},
+ {11, LPGEN("Close relationships")},
+ {12, LPGEN("Engaged")},
+ {20, LPGEN("Married")},
+ {30, LPGEN("Divorced")},
+ {31, LPGEN("Separated")},
+ {40, LPGEN("Widowed")},
+ {-1, NULL}};
+
+
+
+char *LookupFieldNameUtf(struct fieldnames_t *table, int code, char *str, size_t strsize)
+{
+ 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, strsize);
+ }
+
+ // 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_s7_sss_mod/icq_fieldnames.h b/icqj_s7_sss_mod/icq_fieldnames.h new file mode 100644 index 0000000..62e32ae --- /dev/null +++ b/icqj_s7_sss_mod/icq_fieldnames.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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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, size_t strsize);
diff --git a/icqj_s7_sss_mod/icq_filerequests.c b/icqj_s7_sss_mod/icq_filerequests.c new file mode 100644 index 0000000..b8656ff --- /dev/null +++ b/icqj_s7_sss_mod/icq_filerequests.c @@ -0,0 +1,248 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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;
+ HANDLE hCookieContact;
+ WORD wPort;
+ WORD wFilenameLength;
+ filetransfer* ft;
+
+
+ // Find the filetransfer that belongs to this response
+ if (!FindCookie(dwCookie, &hCookieContact, &ft))
+ {
+ NetLog_Direct("Error: Received unexpected file transfer request response");
+ return;
+ }
+
+ FreeCookie(dwCookie);
+
+ if (hCookieContact != HContactFromUIN(dwUin, NULL))
+ {
+ 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;
+ }
+
+ if (wLen < 6)
+ { // sanity check
+ NetLog_Direct("Ignoring malformed file transfer request response");
+ 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)
+ {
+ if (wFilenameLength > wLen - 2)
+ wFilenameLength = wLen - 2;
+ pszFileName = _alloca(wFilenameLength+1);
+ unpackString(&buf, pszFileName, wFilenameLength);
+ pszFileName[wFilenameLength] = '\0';
+ }
+ wLen = wLen - 2 - wFilenameLength;
+
+ if (wLen >= 4)
+ { // Total filesize
+ unpackLEDWord(&buf, &dwFileSize);
+ wLen -= 4;
+ }
+ else
+ dwFileSize = 0;
+
+ NetLog_Direct("File transfer ack from %u, port %u, name %s, size %u", dwUin, ft->dwRemotePort, pszFileName, dwFileSize);
+
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)ft, 0);
+
+ OpenDirectConnection(ft->hContact, DIRECTCONN_FILE, ft);
+}
+
+
+
+filetransfer *CreateFileTransfer(HANDLE hContact, DWORD dwUin, int nVersion)
+{
+ filetransfer *ft = CreateIcqFileTransfer();
+
+ ft->dwUin = dwUin;
+ ft->hContact = hContact;
+ ft->nVersion = nVersion;
+ ft->pMessage.bMessageType = MTYPE_FILEREQ;
+ InitMessageCookie(&ft->pMessage);
+
+ 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 (IsValidFileTransfer(ft))
+ { // Transfer still out there, end it
+ NetLib_CloseConnection(&ft->hConnection, FALSE);
+
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+
+ if (!FindFileTransferDC(ft))
+ { // Release orphan structure only
+ SafeReleaseFileTransfer(&ft);
+ }
+ }
+}
diff --git a/icqj_s7_sss_mod/icq_filetransfer.c b/icqj_s7_sss_mod/icq_filetransfer.c new file mode 100644 index 0000000..73dd2b8 --- /dev/null +++ b/icqj_s7_sss_mod/icq_filetransfer.c @@ -0,0 +1,530 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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 (ICQGetContactSettingString(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;
+ }
+
+ pszThisFileName = FindFilePathContainer(dc->ft->files, dc->ft->iCurrentFile, szThisSubDir);
+
+ 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_CloseConnection(&ft->hConnection, FALSE);
+ 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
+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 (!IsValidRelativePath(dc->ft->szThisFile) || !IsValidRelativePath(dc->ft->szThisSubdir))
+ {
+ 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_s7_sss_mod/icq_firstrun.c b/icqj_s7_sss_mod/icq_firstrun.c new file mode 100644 index 0000000..264586a --- /dev/null +++ b/icqj_s7_sss_mod/icq_firstrun.c @@ -0,0 +1,131 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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;
+
+ DialogBoxUtf(TRUE, hInst, MAKEINTRESOURCE(IDD_ICQACCOUNT), NULL, icq_FirstRunDlgProc, 0);
+}
+
+
+
+BOOL CALLBACK icq_FirstRunDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ char* pszPwd;
+ DWORD dwUIN;
+ char pszUIN[20];
+
+ InitIconLib();
+
+ ICQTranslateDialog(hwndDlg);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) IconLibGetIcon("proto"));
+
+ 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_REG:
+ {
+ ShowRegUinDialog();
+ 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(gpszPassword));
+ strcpy(gpszPassword, str);
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(gpszPassword), (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_s7_sss_mod/icq_http.c b/icqj_s7_sss_mod/icq_http.c new file mode 100644 index 0000000..5675fd1 --- /dev/null +++ b/icqj_s7_sss_mod/icq_http.c @@ -0,0 +1,229 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// HTTP Gateway Handling routines
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+int icq_httpGatewayInit(HANDLE hConn, NETLIBOPENCONNECTION *nloc, NETLIBHTTPREQUEST *nlhr)
+{ // initial response from ICQ http gateway
+ 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)
+{ // open our "virual data connection"
+ 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)
+{
+ PBYTE sendBuf = buf;
+ int sendLen = len;
+ int sendResult = 0;
+
+ while (sendLen > 0)
+ { // imitate polite behaviour of icq5.1 and split large packets
+ icq_packet packet;
+ WORD curLen;
+ int curResult;
+
+ if (sendLen > 512) curLen = 512; else curLen = (WORD)sendLen;
+ // send wrapped data
+ packet.wLen = curLen;
+ write_httphdr(&packet, HTTP_PACKETTYPE_FLAP, GetGatewayIndex(hConn));
+ packBuffer(&packet, sendBuf, (WORD)curLen);
+ curResult = Netlib_Send(hConn, packet.pData, packet.wLen, flags);
+ SAFE_FREE(&packet.pData);
+
+ // sending failed, end loop
+ if (curResult <= 0)
+ return curResult;
+ // calculare real number of data bytes sent
+ if (curResult > 14) sendResult += curResult - 14;
+ // move on
+ sendLen -= curLen;
+ sendBuf += curLen;
+ }
+
+ return sendResult;
+}
+
+
+
+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)
+ { // it is normal data packet
+ 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)
+ { // our "virtual connection" was established, good
+ 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)
+ { // "virtual connection" closed - only received if any other "virual connection" still active
+ NetLog_Server("Gateway Connection #%d Closed.", dwPackSeq);
+ }
+ tbuf += wLen - 12;
+ }
+ *outBufLen = i;
+
+ return buf;
+}
+
+
+
+int icq_httpGatewayWalkTo(HANDLE hConn, NETLIBOPENCONNECTION* nloc)
+{ // this is bad simplification - for avatars to work we need to handle
+ // two "virtual connections" at the same time
+ 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_s7_sss_mod/icq_http.h b/icqj_s7_sss_mod/icq_http.h new file mode 100644 index 0000000..f31ed5b --- /dev/null +++ b/icqj_s7_sss_mod/icq_http.h @@ -0,0 +1,56 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/icq_infoupdate.c b/icqj_s7_sss_mod/icq_infoupdate.c new file mode 100644 index 0000000..98af4d9 --- /dev/null +++ b/icqj_s7_sss_mod/icq_infoupdate.c @@ -0,0 +1,361 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+#define LISTSIZE 100
+static CRITICAL_SECTION listmutex;
+static HANDLE hQueueEvent = NULL;
+static int nUserCount = 0;
+static int bPendingUsers = 0;
+static BOOL bEnabled = FALSE;
+static BOOL bRunning = FALSE;
+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);
+
+ if (hQueueEvent)
+ {
+ // 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;
+
+ hInfoThread = ICQCreateThreadEx(icq_InfoUpdateThread, NULL, NULL);
+ }
+
+ 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;
+
+ // Notify worker thread
+ if (bEnabled && hQueueEvent)
+ SetEvent(hQueueEvent);
+}
+
+
+
+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 || !bEnabled || !icqOnline)
+ {
+ dwWait = WAIT_TIMEOUT;
+ 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
+
+#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)
+ {
+ WORD wGroup;
+
+ EnterCriticalSection(&ratesMutex);
+ if (!gRates)
+ { // we cannot send info request - icq is offline
+ LeaveCriticalSection(&ratesMutex);
+ break;
+ }
+ wGroup = ratesGroupFromSNAC(gRates, ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQ);
+ while (ratesNextRateLevel(gRates, wGroup) < ratesGetLimitLevel(gRates, wGroup, RML_IDLE_50))
+ { // we are over rate, need to wait before sending
+ int nDelay = ratesDelayToLevel(gRates, wGroup, ratesGetLimitLevel(gRates, wGroup, RML_IDLE_50) + 200);
+
+ LeaveCriticalSection(&ratesMutex);
+ LeaveCriticalSection(&listmutex);
+#ifdef _DEBUG
+ NetLog_Server("Rates: InfoUpdate delayed %dms", nDelay);
+#endif
+ SleepEx(nDelay, TRUE); // do not keep things locked during sleep
+ if (!bRunning)
+ { // need to end as fast as possible
+ NetLog_Server("%s thread ended.", "Info-Update");
+
+ return 0;
+ }
+ EnterCriticalSection(&listmutex);
+ EnterCriticalSection(&ratesMutex);
+ if (!gRates) // we lost connection when we slept, go away
+ break;
+ }
+ if (!gRates)
+ { // we cannot send info request - icq is offline
+ LeaveCriticalSection(&ratesMutex);
+ break;
+ }
+ LeaveCriticalSection(&ratesMutex);
+
+ if (!userList[i].hContact) continue; // user was dequeued during our sleep
+#ifdef _DEBUG
+ NetLog_Server("Request info for user %u", userList[i].dwUin);
+#endif
+ sendUserInfoAutoRequest(userList[i].hContact, 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;
+ }
+ }
+ NetLog_Server("%s thread ended.", "Info-Update");
+
+ return 0;
+}
+
+
+
+// Clean up before exit
+void icq_InfoUpdateCleanup(void)
+{
+ bRunning = FALSE;
+ SetEvent(hQueueEvent); // break queue loop
+ if (hInfoThread) WaitForSingleObjectEx(hInfoThread, INFINITE, TRUE);
+ // Uninit mutex
+ DeleteCriticalSection(&listmutex);
+ CloseHandle(hQueueEvent);
+ CloseHandle(hInfoThread);
+}
diff --git a/icqj_s7_sss_mod/icq_infoupdate.h b/icqj_s7_sss_mod/icq_infoupdate.h new file mode 100644 index 0000000..bc48867 --- /dev/null +++ b/icqj_s7_sss_mod/icq_infoupdate.h @@ -0,0 +1,56 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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);
diff --git a/icqj_s7_sss_mod/icq_opts.c b/icqj_s7_sss_mod/icq_opts.c new file mode 100644 index 0000000..7e28136 --- /dev/null +++ b/icqj_s7_sss_mod/icq_opts.c @@ -0,0 +1,1778 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007,2008 [sss], chaos.persei, [sin], Faith Healer, Thief, nullbie
+// Copyright 2008 [sss], chaos.persei, nullbie, baloo, jarvis
+//
+// 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$
+// Revision : $Revision: 64 $
+// Last change on : $Date: 2007-10-16 17:39:11 +0300 (Вт, 16 окт 2007) $
+// Last change by : $Author: chaos.persei $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#include <win2k.h>
+#include <uxtheme.h>
+
+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 DlgProcIcqFeatures2Opts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqPrivacyOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqEventLogOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqClientIDOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqNewUINOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqPopupOpts2(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcIcqASDOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+extern BOOL bXstatusIconShow;
+
+extern void ShowSrvListDialog(HWND hwndCaller);
+extern void ShowCapsListDialog( HWND hwndCaller );
+extern void setUserInfo();
+
+static const char* szLogLevelDescr[] = {"Display all problems", "Display problems causing possible loss of data", "Display explanations for disconnection", "Display problems requiring user intervention", "Do not display problems"};
+
+static BOOL (WINAPI *pfnEnableThemeDialogTexture)(HANDLE, DWORD) = 0;
+
+static HWND hwndRegUin = NULL;
+static HWND hwndPopUpsOpts = NULL;
+static HWND hwndASDOpts = NULL;
+
+extern char szHttpUserAgent[255];
+
+int IcqOptInit(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+
+
+ odp.cbSize = sizeof(odp);
+// odp.position = 100000000;
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_ICQ);
+ odp.pszTitle = gpszICQProtoName;
+ odp.pszGroup = LPGEN("Network");
+ odp.pszTab = LPGEN("Account");
+// odp.groupPosition = 910000000;
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = DlgProcIcqOpts;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_ICQCONTACTS);
+ odp.pszTitle = gpszICQProtoName;
+ odp.pszGroup = LPGEN("Network");
+ odp.pszTab = LPGEN("Contacts");
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = DlgProcIcqContactsOpts;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+// odp.position = 100000000;
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_ICQFEATURES);
+ odp.pszTitle = gpszICQProtoName;
+ odp.pszGroup = LPGEN("Network");
+ odp.pszTab = LPGEN("Main Features");
+// odp.groupPosition = 910000000;
+ odp.flags=ODPF_BOLDGROUPS | ODPF_EXPERTONLY;
+ odp.pfnDlgProc = DlgProcIcqFeaturesOpts;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+// odp.position = 100000000;
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_ICQFEATURES2);
+ odp.pszTitle = gpszICQProtoName;
+ odp.pszGroup = LPGEN("Network");
+ odp.pszTab = LPGEN("Advanced Features");
+// odp.groupPosition = 910000000;
+ odp.flags=ODPF_BOLDGROUPS | ODPF_EXPERTONLY;
+ odp.pfnDlgProc = DlgProcIcqFeatures2Opts;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_ICQPRIVACY);
+ odp.pszTitle = gpszICQProtoName;
+ odp.pszGroup = LPGEN("Network");
+ odp.pszTab = LPGEN("Privacy");
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = DlgProcIcqPrivacyOpts;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_ICQ_EVENTS);
+ odp.pszTitle = gpszICQProtoName;
+ odp.pszGroup = LPGEN("Network");
+ odp.pszTab = LPGEN("Log");
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = DlgProcIcqEventLogOpts;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_ICQ_CLIENT_ID);
+ odp.pszTitle = gpszICQProtoName;
+ odp.pszGroup = LPGEN("Network");
+ odp.pszTab = LPGEN("Client ID");
+ odp.flags=ODPF_BOLDGROUPS | ODPF_EXPERTONLY;
+ odp.pfnDlgProc = DlgProcIcqClientIDOpts;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+ if (bPopUpService)
+ {
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_POPUPS);
+ odp.pszTitle = gpszICQProtoName;
+ odp.pszGroup = LPGEN("PopUps");
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = DlgProcIcqPopupOpts;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+ }
+
+ 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);
+}
+
+
+// standalone option pages
+static void IcqPasswordBox_Init(HWND hwndDlg, int idCtrl);
+
+char HttpUserAgents [][255] =
+{
+ "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)",
+ "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
+ "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9",
+ "Opera/9.23 (Windows NT 5.1; U; ru)",
+ "Opera/8.01 (J2ME/MIDP; Opera Mini/3.0.6306/1528; nb; U; ssr)",
+ "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2) Gecko/20070221 SeaMonkey/1.1.1",
+ "Mozilla/5.0 (compatible; Konqueror/3.5; Linux 2.6.21-rc1; x86_64; cs, en_US) KHTML/3.5.6 (like Gecko)",
+ "Lynx/2.8.4rel.1 libwww-FM/2.14",
+ "Mozilla/4.08 [en] (WinNT; U ;Nav)"
+};
+
+static BOOL CALLBACK DlgProcIcqOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static char DBModule[64], buf[64];
+ WORD SrvCount;
+ int i, iIndex;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ static char pszPwd[16];
+ static 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);
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_ICQSERVER, CB_RESETCONTENT, 0, 0);
+ mir_snprintf(DBModule, 64, "%sSrvs", gpszICQProtoName);
+ SrvCount = DBGetContactSettingWord(0, DBModule, "SrvCount", 0);
+
+ for(i = 1; i <= SrvCount; i++){
+ mir_snprintf(buf, 64, "server%luhost", i);
+ SendDlgItemMessage(hwndDlg, IDC_ICQSERVER, CB_ADDSTRING, 0, (LPARAM)UniGetContactSettingUtf(NULL, DBModule, buf, 0));
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_HTTPUSERAGENT, CB_RESETCONTENT, 0, 0);
+ for(i = 0; i < SIZEOF(HttpUserAgents); i++)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_HTTPUSERAGENT, CB_ADDSTRING, 0, (LPARAM)HttpUserAgents[i]);
+ }
+
+ if (!ICQGetContactStaticString(NULL, "OscarServer", szServer, MAX_PATH))
+ {
+ SetDlgItemText(hwndDlg, IDC_ICQSERVER, szServer);
+ }
+ else
+ {
+ SetDlgItemText(hwndDlg, IDC_ICQSERVER, DEFAULT_SERVER_HOST);
+ }
+
+ SetDlgItemText(hwndDlg, IDC_HTTPUSERAGENT, szHttpUserAgent);
+
+ SetDlgItemInt(hwndDlg, IDC_ICQPORT, ICQGetContactSettingWord(NULL, "OscarPort", DEFAULT_SERVER_PORT), FALSE);
+ LoadDBCheckState(hwndDlg, IDC_KEEPALIVE, "KeepAlive", 1);
+ LoadDBCheckState(hwndDlg, IDC_SECURE, "SecureLogin", DEFAULT_SECURE_LOGIN);
+ SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_SETRANGE, FALSE, MAKELONG(0, 4));
+ SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_SETPOS, TRUE, 4-ICQGetContactSettingByte(NULL, "ShowLogLevel", LOG_WARNING));
+ SetDlgItemTextUtf(hwndDlg, IDC_LEVELDESCR, ICQTranslateUtfStatic(szLogLevelDescr[4-SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_GETPOS, 0, 0)], szServer, MAX_PATH));
+ ShowWindow(GetDlgItem(hwndDlg, IDC_RECONNECTREQD), SW_HIDE);
+ LoadDBCheckState(hwndDlg, IDC_NOERRMULTI, "IgnoreMultiErrorBox", 0);
+ LoadDBCheckState(hwndDlg, IDC_AUTOCHANGE, "ServerAutoChange", 1);
+
+ IcqPasswordBox_Init(hwndDlg, IDC_PASSWORD);
+
+ return TRUE;
+ }
+
+ case WM_HSCROLL:
+ {
+ char str[MAX_PATH];
+
+ SetDlgItemTextUtf(hwndDlg, IDC_LEVELDESCR, ICQTranslateUtfStatic(szLogLevelDescr[4-SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL,TBM_GETPOS, 0, 0)], str, MAX_PATH));
+ OptDlgChanged(hwndDlg);
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+
+ case IDC_PASSWORD:
+ if ((HIWORD(wParam) == EN_CHANGE))
+ {
+ if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_PASSWORD)) > 8)
+ SendDlgItemMessage(hwndDlg, IDC_PASSWORD, WM_APP, (WPARAM)Translate("Warning"), (LPARAM)Translate("ICQ servers do not accept passwords longer than 8 characters."));
+ else
+ SendDlgItemMessage(hwndDlg, IDC_PASSWORD, WM_APP, 0, 0);
+ }
+ break;
+
+ case IDC_REGUIN:
+ ShowRegUinDialog();
+ return TRUE;
+
+ case IDC_SERVERBOX:
+ ShowSrvListDialog(hwndDlg);
+ return TRUE;
+
+ case IDC_ICQSERVER:
+ switch(HIWORD(wParam))
+ {
+ case CBN_SELCHANGE:
+
+ iIndex = (int)SendDlgItemMessage(hwndDlg, IDC_ICQSERVER, CB_GETCURSEL, 0, 0);
+ if(iIndex < 0) return FALSE;
+ mir_snprintf(DBModule, 64, "%sSrvs", gpszICQProtoName);
+ mir_snprintf(buf, 64, "server%luport", iIndex + 1);
+ DBWriteContactSettingWord(0, DBModule, "CurrServ", (WORD)(iIndex + 1));
+ SetDlgItemInt(hwndDlg, IDC_ICQPORT, DBGetContactSettingWord(0, DBModule, buf, DEFAULT_SERVER_PORT), 0);
+ OptDlgChanged(hwndDlg);
+ break;
+ }
+ break;
+ }
+
+ if (icqOnline && LOWORD(wParam) != IDC_NOERRMULTI)
+ {
+ char szClass[80];
+
+
+ GetClassName((HWND)lParam, szClass, sizeof(szClass));
+
+ if (stricmp(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(gpszPassword));
+ if (strlennull(str))
+ {
+ strcpy(gpszPassword, str);
+ gbRememberPwd = TRUE;
+ }
+ else
+ {
+ gbRememberPwd = ICQGetContactSettingByte(NULL, "RememberPass", 0);
+ }
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(gpszPassword), (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_SECURE, "SecureLogin");
+ StoreDBCheckState(hwndDlg, IDC_NOERRMULTI, "IgnoreMultiErrorBox");
+ StoreDBCheckState(hwndDlg, IDC_AUTOCHANGE, "ServerAutoChange");
+ bServerAutoChange = ICQGetContactSettingByte(NULL,"ServerAutoChange",1);
+ ICQWriteContactSettingByte(NULL, "ShowLogLevel", (BYTE)(4-SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_GETPOS, 0, 0)));
+ GetDlgItemText(hwndDlg, IDC_HTTPUSERAGENT, szHttpUserAgent, sizeof(szHttpUserAgent));
+ ICQWriteContactSettingString(NULL, "HttpUserAgent", szHttpUserAgent);
+ 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;
+ BYTE bData;
+
+ 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_NOSTATUSREPLY, "NoStatusReply", 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);
+ bData = DBGetContactSettingByte(NULL,gpszICQProtoName,"NoStatusReply", 0);
+ CheckDlgButton(hwndDlg, IDC_NOSTATUSREPLY, bData);
+
+ 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_NOSTATUSREPLY:
+ if (IsDlgButtonChecked(hwndDlg, IDC_NOSTATUSREPLY))
+ icq_sendSetAimAwayMsgServ("");//set aim message to nothing
+ 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_NOSTATUSREPLY, "NoStatusReply");
+ 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");
+ bNoStatusReply = ICQGetContactSettingByte(NULL, "NoStatusReply", 0);
+ 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, FALSE);
+ // Tell who is on our visible list
+ icq_sendEntireVisInvisList(0);
+ }
+ else
+ {
+ icq_setstatus(wStatus, FALSE);
+ if (gbSsiEnabled)
+ updateServVisibilityCode(4);
+ // Tell who is on our invisible list
+ icq_sendEntireVisInvisList(1);
+ }
+ }
+ }
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static const UINT icqPopupsControls[] = {IDC_POPUPS_LOG_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,IDC_POPUP_UNKNOWN_TIMEOUT,IDC_POPUP_LOG6_TIMEOUT,IDC_POPUP_FOR_NOTONLIST,IDC_UINPOPUP};
+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_UNKNOWN_TEXTCOLOR,IDC_POPUP_LOG6_TEXTCOLOR,IDC_POPUP_CLIENT_CHANGE_TEXTCOLOR,IDC_POPUP_REMOVE_HIMSELF_TEXTCOLOR,IDC_POPUP_INFO_REQUEST_TEXTCOLOR,IDC_POPUP_IGNORECHECK_TEXTCOLOR,IDC_POPUP_AUTH_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,IDC_POPUP_UNKNOWN_BACKCOLOR,IDC_POPUP_LOG6_BACKCOLOR,IDC_POPUP_CLIENT_CHANGE_BACKCOLOR,IDC_POPUP_REMOVE_HIMSELF_BACKCOLOR,IDC_POPUP_INFO_REQUEST_BACKCOLOR,IDC_POPUP_IGNORECHECK_BACKCOLOR,IDC_POPUP_AUTH_BACKCOLOR
+};
+void ShowPopUpsOpts(void);
+static BOOL CALLBACK DlgProcIcqPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BYTE bEnabled;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ LoadDBCheckState(hwndDlg, IDC_POPUP_FOR_NOTONLIST, "PopUpForNotOnList", 0);
+ LoadDBCheckState(hwndDlg, IDC_UINPOPUP, "UinPopup", 0);
+ CheckDlgButton(hwndDlg, IDC_POPUPS_LOG_ENABLED, ICQGetContactSettingByte(NULL,"PopupsLogEnabled",1));
+ bEnabled = ICQGetContactSettingByte(NULL,"PopupsWinColors",0);
+ CheckDlgButton(hwndDlg, IDC_USEWINCOLORS, bEnabled);
+ CheckDlgButton(hwndDlg, IDC_USESYSICONS, ICQGetContactSettingByte(NULL,"PopupsSysIcons",0));
+ bEnabled = ICQGetContactSettingByte(NULL,"PopupsEnabled",1);
+ CheckDlgButton(hwndDlg, IDC_POPUPS_ENABLED, bEnabled);
+ icq_EnableMultipleControls(hwndDlg, icqPopupsControls, SIZEOF(icqPopupsControls), bEnabled);
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_PREVIEW:
+ {
+ extern BOOL bXUpdaterPopUp;
+ if (ICQGetContactSettingByte(NULL,"PopupsLogEnabled",1))
+ {
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample Note", LOG_NOTE);
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample Warning", LOG_WARNING);
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample Error", LOG_ERROR);
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample Fatal", LOG_FATAL);
+ }
+ if(bFoundPopUp)
+ ShowPopUpMsg(NULL, 0, "Contact", "Sample ...was found!", POPTYPE_FOUND);
+ if(bScanPopUp)
+ { gbScan = TRUE;
+ ShowPopUpMsg(NULL, 0, "Entire List Check", "Sample Users Status Scan Started", POPTYPE_SCAN);
+
+ gbScan = FALSE;
+ ShowPopUpMsg(NULL, 0, "Active Status Scan", "Sample Users Status Scan Complete", POPTYPE_SCAN);
+ }
+ if(bSpamPopUp)
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample Spambot Found", POPTYPE_SPAM);
+ if(bUnknownPopUp)
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample Unknown Found", POPTYPE_UNKNOWN);
+ if(bVisPopUp)
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample Visibility event", POPTYPE_VIS);
+ if(bClientChangePopUp)
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample ClientChange event", POPTYPE_CLIENT_CHANGE);
+ if(bInfoRequestPopUp)
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample InfoRequest event", POPTYPE_INFO_REQUEST);
+ if(bIgnoreCheckPop)
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Check Your Ignore State", POPTYPE_IGNORE_CHECK);
+ if(bPopSelfRem)
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Removed Himself", POPTYPE_SELFREMOVE);
+ if(bAuthPopUp)
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample Auth PopUp", POPTYPE_AUTH);
+ if(bXUpdaterPopUp)
+ ShowPopUpMsg(NULL, 0, "Popup Title", "Sample XStatus Updater PopUp", POPTYPE_XUPDATER);
+ }
+ return FALSE;
+
+ case IDC_POPUPS_ENABLED:
+ bEnabled = IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED);
+ icq_EnableMultipleControls(hwndDlg, icqPopupsControls, SIZEOF(icqPopupsControls), bEnabled);
+ break;
+ case IDC_USEWINCOLORS:
+ bEnabled = IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED);
+ icq_EnableMultipleControls(hwndDlg, icqPopupColorControls, SIZEOF(icqPopupColorControls), bEnabled & !IsDlgButtonChecked(hwndDlg,IDC_USEWINCOLORS));
+ break;
+ case IDC_POPUPS_OPTIONS:
+ ShowPopUpsOpts();
+ return TRUE;
+ }
+ OptDlgChanged(hwndDlg);
+ 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,"PopupsWinColors",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_USEWINCOLORS));
+ ICQWriteContactSettingByte(NULL,"PopupsSysIcons",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_USESYSICONS));
+ StoreDBCheckState(hwndDlg, IDC_POPUP_FOR_NOTONLIST , "PopUpForNotOnList");
+ bPopUpForNotOnList = ICQGetContactSettingByte(NULL, "PopUpForNotOnList", 0);
+ StoreDBCheckState(hwndDlg, IDC_UINPOPUP , "UinPopup");
+ bUinPopup = ICQGetContactSettingByte(NULL, "UinPopup", 0);
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+
+
+static BOOL CALLBACK DlgProcIcqPopupOpts2(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ extern BOOL bXUpdaterPopUp;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ LoadDBCheckState(hwndDlg, IDC_SPAM_POPUP_ENABLE, "SpamPopUpEnabled", 0);
+ LoadDBCheckState(hwndDlg, IDC_UNKNOWN_POPUP_ENABLE, "UnknownPopUpEnabled", 0);
+ LoadDBCheckState(hwndDlg, IDC_WAS_FOUND_POPUP_ENABLE, "FoundPopUpEnabled", 1);
+ LoadDBCheckState(hwndDlg, IDC_SCAN_POPUP_ENABLE, "ScanPopUpEnabled", 1);
+ LoadDBCheckState(hwndDlg, IDC_VIS_POPUP_ENABLE, "VisPopUpEnabled", 1);
+ LoadDBCheckState(hwndDlg, IDC_CLIENT_CHANGE_POPUP, "ClientChangePopup", 0);
+ LoadDBCheckState(hwndDlg, IDC_POPSELFREM, "PopSelfRem", 1);
+ LoadDBCheckState(hwndDlg, IDC_IGNCHECKPOP, "IgnoreCheckPop", 1);
+ LoadDBCheckState(hwndDlg, IDC_INFO_REQUEST_POPUP, "InfoRequestPopUp", 0);
+ LoadDBCheckState(hwndDlg, IDC_POPAUTH, "AuthPopUp", 0);
+ LoadDBCheckState(hwndDlg, IDC_POPXUPDATER, "XUpdaterPopUp", 0);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG0_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups0TextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG0_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups0BackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG0_TIMEOUT, ICQGetContactSettingDword(NULL,"Popups0Timeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG1_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups1TextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG1_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups1BackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG1_TIMEOUT, ICQGetContactSettingDword(NULL,"Popups1Timeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG2_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups2TextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG2_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups2BackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG2_TIMEOUT, ICQGetContactSettingDword(NULL,"Popups2Timeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG3_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups3TextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG3_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"Popups3BackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG3_TIMEOUT, ICQGetContactSettingDword(NULL,"Popups3Timeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG4_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsFoundTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG4_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsFoundBackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG4_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsFoundTimeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG5_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsFinishedTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG5_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsFinishedBackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG5_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsFinishedTimeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_SPAM_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsSpamTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_SPAM_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsSpamBackColor",RGB(0,0,255)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_SPAM_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsSpamTimeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_UNKNOWN_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsUnknownTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_UNKNOWN_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsUnknownBackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_UNKNOWN_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsUnknownTimeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG6_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsVisTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG6_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsVisBackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG6_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsVisTimeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_CLIENT_CHANGE_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsClientChangeTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_CLIENT_CHANGE_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsClientChangeBackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_CLIENT_CHANGE_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsClientChangeTimeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_INFO_REQUEST_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsInfoRequestTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_INFO_REQUEST_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsInfoRequestBackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_INFO_REQUEST_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsInfoRequestTimeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_IGNORECHECK_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsIgnoreCheckTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_IGNORECHECK_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsIgnoreCheckBackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_IGNORECHECK_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsIgnoreCheckTimeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_REMOVE_HIMSELF_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsRemoveHimselfTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_REMOVE_HIMSELF_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsRemoveHimselfBackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_REMOVE_HIMSELF_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsRemoveHimselfTimeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_AUTH_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsAuthTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_AUTH_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsAuthBackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_AUTH_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsAuthTimeout",0),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_XUPDATER_TEXTCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsXUpdaterTextColor",RGB(255,255,255)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_XUPDATER_BACKCOLOR, CPM_SETCOLOUR, 0, ICQGetContactSettingDword(NULL,"PopupsXUpdaterBackColor",RGB(0,0,0)));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_XUPDATER_TIMEOUT, ICQGetContactSettingDword(NULL,"PopupsXUpdaterTimeout",0),FALSE);
+ icq_EnableMultipleControls(hwndDlg, icqPopupColorControls, SIZEOF(icqPopupColorControls), ICQGetContactSettingByte(NULL, "PopupsWinColors", 0)-1);
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_OK:
+ 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));
+ ICQWriteContactSettingDword(NULL,"PopupsUnknownTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_UNKNOWN_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsUnknownBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_UNKNOWN_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsUnknownTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_UNKNOWN_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"PopupsVisTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG6_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsVisBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG6_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsVisTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG6_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"PopupsClientChangeTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_CLIENT_CHANGE_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsClientChangeBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_CLIENT_CHANGE_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsClientChangeTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_CLIENT_CHANGE_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"PopupsInfoRequestTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_INFO_REQUEST_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsInfoRequestBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_INFO_REQUEST_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsInfoRequestTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_INFO_REQUEST_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"PopupsIgnoreCheckTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_IGNORECHECK_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsIgnoreCheckBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_IGNORECHECK_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsIgnoreCheckTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_IGNORECHECK_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"PopupsRemoveHimselfTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_REMOVE_HIMSELF_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsRemoveHimselfBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_REMOVE_HIMSELF_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsRemoveHimselfTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_REMOVE_HIMSELF_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"PopupsAuthTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_AUTH_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsAuthBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_AUTH_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsAuthTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_AUTH_TIMEOUT, NULL, FALSE));
+ ICQWriteContactSettingDword(NULL,"PopupsXUpdaterTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_XUPDATER_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsXUpdaterBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_XUPDATER_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ICQWriteContactSettingDword(NULL,"PopupsXUpdaterTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_XUPDATER_TIMEOUT, NULL, FALSE));
+ StoreDBCheckState(hwndDlg, IDC_SPAM_POPUP_ENABLE , "SpamPopUpEnabled");
+ bSpamPopUp = ICQGetContactSettingByte(NULL, "SpamPopUpEnabled", 0);
+ StoreDBCheckState(hwndDlg, IDC_UNKNOWN_POPUP_ENABLE , "UnknownPopUpEnabled");
+ bUnknownPopUp = ICQGetContactSettingByte(NULL, "UnknownPopUpEnabled", 0);
+ StoreDBCheckState(hwndDlg, IDC_WAS_FOUND_POPUP_ENABLE , "FoundPopUpEnabled");
+ bFoundPopUp = ICQGetContactSettingByte(NULL, "FoundPopUpEnabled", 1);
+ StoreDBCheckState(hwndDlg, IDC_SCAN_POPUP_ENABLE , "ScanPopUpEnabled");
+ bScanPopUp = ICQGetContactSettingByte(NULL, "ScanPopUpEnabled", 1);
+ StoreDBCheckState(hwndDlg, IDC_VIS_POPUP_ENABLE , "VisPopUpEnabled");
+ bVisPopUp = ICQGetContactSettingByte(NULL, "VisPopUpEnabled", 1);
+ StoreDBCheckState(hwndDlg, IDC_CLIENT_CHANGE_POPUP , "ClientChangePopup");
+ bClientChangePopUp = ICQGetContactSettingByte(NULL, "ClientChangePopup", 0);
+ StoreDBCheckState(hwndDlg, IDC_IGNCHECKPOP , "IgnoreCheckPop");
+ bIgnoreCheckPop = ICQGetContactSettingByte(NULL, "IgnoreCheckPop", 1);
+ StoreDBCheckState(hwndDlg, IDC_POPSELFREM , "PopSelfRem");
+ bPopSelfRem = ICQGetContactSettingByte(NULL, "PopSelfRem", 1);
+ StoreDBCheckState(hwndDlg, IDC_INFO_REQUEST_POPUP , "InfoRequestPopUp");
+ bInfoRequestPopUp = ICQGetContactSettingByte(NULL, "InfoRequestPopUp", 0);
+ StoreDBCheckState(hwndDlg, IDC_POPAUTH , "AuthPopUp");
+ bAuthPopUp = ICQGetContactSettingByte(NULL, "AuthPopUp", 0);
+ StoreDBCheckState(hwndDlg, IDC_POPXUPDATER , "XUpdaterPopUp");
+ bXUpdaterPopUp = ICQGetContactSettingByte(NULL, "XUpdaterPopUp", 0);
+ DestroyWindow(hwndDlg);
+ }
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ hwndPopUpsOpts = NULL;
+ break;
+ }
+ return FALSE;
+}
+
+static BOOL CALLBACK DlgProcIcqASDOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ void ShowASDOpts(void);
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+ LoadDBCheckState(hwndDlg, IDC_DETECT_VIA_STATUS_MESSAGE, "bASDViaAwayMsg", 0);
+ LoadDBCheckState(hwndDlg, IDC_DETECT_VIA_XTRAZ, "bASDViaXtraz", 0);
+ LoadDBCheckState(hwndDlg, IDC_DETECT_VIA_URL, "bASDViaURL", 0);
+ LoadDBCheckState(hwndDlg, IDC_DETECT_UNAUTHORIZED, "bASDUnauthorized", 0);
+ LoadDBCheckState(hwndDlg, IDC_DETECT_VIA_AUTH, "bASDViaAuth", 0);
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_OK:
+ StoreDBCheckState(hwndDlg, IDC_DETECT_VIA_STATUS_MESSAGE, "bASDViaAwayMsg");
+ bASDViaAwayMsg = ICQGetContactSettingByte(NULL, "bASDViaAwayMsg", 0);
+ StoreDBCheckState(hwndDlg, IDC_DETECT_VIA_XTRAZ, "bASDViaXtraz");
+ bASDViaXtraz = ICQGetContactSettingByte(NULL, "bASDViaXtraz", 0);
+ StoreDBCheckState(hwndDlg, IDC_DETECT_VIA_URL, "bASDViaURL");
+ bASDViaURL = ICQGetContactSettingByte(NULL, "bASDViaURL", 0);
+ StoreDBCheckState(hwndDlg, IDC_DETECT_UNAUTHORIZED, "bASDUnauthorized");
+ bASDUnauthorized = ICQGetContactSettingByte(NULL, "bASDUnauthorized", 0);
+ StoreDBCheckState(hwndDlg, IDC_DETECT_VIA_AUTH, "bASDViaAuth");
+ bASDViaAuth = ICQGetContactSettingByte(NULL, "bASDViaAuth", 0);
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ hwndASDOpts = NULL;
+ 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 icqDCIconsControls[] = {IDC_DC_ICON_POS,IDC_DC_ICON_POS_TEXT};
+static const UINT icqXStatusControls[] = {IDC_XSTNONSTD,IDC_XSTUPDATERATE,IDC_XSTUPDATE,IDC_XSTATUSAUTO,IDC_XSTATUSRESET,IDC_FORCEXSTATUS,IDC_XSTATUS_ICON_POS,IDC_XSTATUS_SHOW,IDC_REPLACEXTEXT,IDC_ICON_POS_TEXT};
+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_XSTUPDATE, "UpdateXStatus", 1);
+ SetDlgItemInt(hwndDlg, IDC_XSTUPDATERATE, ICQGetContactSettingDword(NULL, "XStatusUpdatePeriod", 15), 0);
+ EnableDlgItem(hwndDlg, IDC_XSTUPDATERATE, IsDlgButtonChecked(hwndDlg, IDC_XSTUPDATE));
+ 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);
+ LoadDBCheckState(hwndDlg, IDC_DCICON, "ShowDCIcon", 1);
+ 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 = 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_XSTATUS_SHOW, "XStatusIconShow", 1);
+ LoadDBCheckState(hwndDlg, IDC_FORCEXSTATUS, "ForceXstatus", 0);
+ LoadDBCheckState(hwndDlg, IDC_KILLSPAMBOTS, "KillSpambots", DEFAULT_KILLSPAM_ENABLED);
+ LoadDBCheckState(hwndDlg, IDC_KILLUNKNOWN, "KillUnknown", 0);
+ LoadDBCheckState(hwndDlg, IDC_AIMENABLE, "AimEnabled", DEFAULT_AIM_ENABLED);
+ LoadDBCheckState(hwndDlg, IDC_RTF, "RTF", 0);
+ LoadDBCheckState(hwndDlg, IDC_REPLACEXTEXT, "ShowMyXText", 1);
+ icq_EnableMultipleControls(hwndDlg, icqAimControls, sizeof(icqAimControls)/sizeof(icqAimControls[0]), icqOnline?FALSE:TRUE);
+ {
+ char* CIdComboBox[] =
+ {
+ "Email","Protocol","SMS","Advanced 1","Advanced 2","Web","Client","VisMode","Advanced 3","Advanced 4"
+ };
+ int i;
+ for (i=0; i<sizeof(CIdComboBox)/sizeof(CIdComboBox[0]); i++)
+ {
+ ComboBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_DC_ICON_POS), CIdComboBox[i],i);
+ ComboBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_XSTATUS_ICON_POS), CIdComboBox[i],i);
+ }
+ }
+ SendDlgItemMessage(hwndDlg, IDC_DC_ICON_POS, CB_SETCURSEL, (DBGetContactSettingWord(NULL,gpszICQProtoName,"dc_icon_pos", 5))-1, 0);
+ SendDlgItemMessage(hwndDlg, IDC_XSTATUS_ICON_POS, CB_SETCURSEL, (DBGetContactSettingWord(NULL,gpszICQProtoName,"xstatus_icon_pos", 4))-1, 0);
+ 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;
+ }
+ }
+ }
+ LoadDBCheckState(hwndDlg, IDC_XSTNONSTD, "NonStandartXstatus", 1);
+ 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;
+ case IDC_DCICON:
+ icq_EnableMultipleControls(hwndDlg, icqDCIconsControls, sizeof(icqDCIconsControls)/sizeof(icqDCIconsControls[0]), IsDlgButtonChecked(hwndDlg, IDC_DCICON));
+ break;
+ case IDC_XSTUPDATE:
+ EnableDlgItem(hwndDlg, IDC_XSTUPDATERATE, IsDlgButtonChecked(hwndDlg, IDC_XSTUPDATE));
+ }
+ OptDlgChanged(hwndDlg);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ int i = SendDlgItemMessage(hwndDlg, IDC_DC_ICON_POS, CB_GETCURSEL, 0, 0)+1;
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "dc_icon_pos", (WORD)i);
+ }
+ {
+ int i = SendDlgItemMessage(hwndDlg, IDC_XSTATUS_ICON_POS, CB_GETCURSEL, 0, 0)+1;
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "xstatus_icon_pos", (WORD)i);
+ }
+ if( DBGetContactSettingByte(NULL,gpszICQProtoName,"RTF", 0) != (BYTE)IsDlgButtonChecked(hwndDlg,IDC_RTF))
+ {
+ MessageBox(0,Translate("To enable RTF text reciving you must reconnect your Miranda after option is enabled"),Translate("Warning"),MB_OK);
+ ICQWriteContactSettingByte(NULL,"RTF",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_RTF));
+ }
+ 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_DCICON, "ShowDCIcon");
+ StoreDBCheckState(hwndDlg, IDC_XSTATUSAUTO, "XStatusAuto");
+ StoreDBCheckState(hwndDlg, IDC_XSTATUSRESET, "XStatusReset");
+ StoreDBCheckState(hwndDlg, IDC_FORCEXSTATUS , "ForceXstatus");
+ StoreDBCheckState(hwndDlg, IDC_XSTATUS_SHOW, "XStatusIconShow");
+ bXstatusIconShow = ICQGetContactSettingByte(NULL, "XStatusIconShow", 1);
+ StoreDBCheckState(hwndDlg, IDC_KILLSPAMBOTS , "KillSpambots");
+ StoreDBCheckState(hwndDlg, IDC_KILLUNKNOWN , "KillUnknown");
+ StoreDBCheckState(hwndDlg, IDC_AIMENABLE, "AimEnabled");
+ StoreDBCheckState(hwndDlg, IDC_RTF, "RTF");
+ StoreDBCheckState(hwndDlg, IDC_REPLACEXTEXT, "ShowMyXText");
+ {
+ DWORD dwRate;
+ StoreDBCheckState(hwndDlg, IDC_XSTUPDATE, "UpdateXStatus");
+ dwRate = GetDlgItemInt(hwndDlg, IDC_XSTUPDATERATE, 0, 0);
+ if(dwRate < 1 || dwRate > 60)
+ dwRate = 15;
+ SetDlgItemInt(hwndDlg, IDC_XSTUPDATERATE, dwRate, 0);
+ ICQWriteContactSettingDword(NULL, "XStatusUpdatePeriod", dwRate);
+ }
+ StoreDBCheckState(hwndDlg, IDC_XSTNONSTD, "NonStandartXstatus");
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+static const UINT icqASDControls[] = {IDC_NOASD, IDC_CHECKITEM, IDC_ASDSTARTUP};
+static const UINT icqPSDControls[] = {IDC_NOPSD_FOR_HIDDEN};
+static BOOL CALLBACK DlgProcIcqFeatures2Opts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ extern BOOL bShowAuth;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ BYTE bData;
+
+ ICQTranslateDialog(hwndDlg);
+// LoadDBCheckState(hwndDlg, IDC_STEALTHRQST, "StealthRequest", 0);
+ LoadDBCheckState(hwndDlg, IDC_PSD, "PSD", 0);
+ LoadDBCheckState(hwndDlg, IDC_NOASD, "NoASD", 0);
+ LoadDBCheckState(hwndDlg, IDC_SHOW_AUTH, "ShowAuth", 0);
+// LoadDBCheckState(hwndDlg, IDC_INV4INV, "Inv4Inv", DEFAULT_INV4INV_DISABLED);
+// LoadDBCheckState(hwndDlg, IDC_LOGSELFREM, "LogSelfRem", 0);
+// LoadDBCheckState(hwndDlg, IDC_IGNCHECKLOG, "IgnoreCheckLog", 0);
+ LoadDBCheckState(hwndDlg, IDC_ASDSTARTUP, "ASDStartup", 0);
+ LoadDBCheckState(hwndDlg, IDC_NOPSD_FOR_HIDDEN, "NoPSDForHidden", 1);
+ bData = DBGetContactSettingByte(NULL,gpszICQProtoName,"ASD", 0);
+ CheckDlgButton(hwndDlg, IDC_ASD, bData);
+ icq_EnableMultipleControls(hwndDlg, icqASDControls, sizeof(icqASDControls)/sizeof(icqASDControls[0]), bData?TRUE:FALSE);
+// bData = DBGetContactSettingByte(NULL,gpszICQProtoName,"Inv4Inv", DEFAULT_INV4INV_DISABLED);
+// CheckDlgButton(hwndDlg, IDC_INV4INV, bData);
+ bData = DBGetContactSettingByte(NULL,gpszICQProtoName,"ASDStartup", 0);
+ CheckDlgButton(hwndDlg, IDC_ASDSTARTUP, bData);
+ LoadDBCheckState(hwndDlg, IDC_TZER, "tZer", 0);
+// icq_EnableMultipleControls(hwndDlg, icqIncognitoControls, sizeof(icqIncognitoControls)/sizeof(icqIncognitoControls[0]), bStealthRequest?TRUE:FALSE);
+ CheckDlgButton(hwndDlg, IDC_INCUSER, (bIncognitoGlobal == 0));
+ CheckDlgButton(hwndDlg, IDC_INCGLOBAL, (bIncognitoGlobal == 1));
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_ASD:
+ icq_EnableMultipleControls(hwndDlg, icqASDControls, sizeof(icqASDControls)/sizeof(icqASDControls[0]), IsDlgButtonChecked(hwndDlg, IDC_ASD));
+ break;
+ case IDC_PSD:
+ icq_EnableMultipleControls(hwndDlg, icqPSDControls, sizeof(icqPSDControls)/sizeof(icqPSDControls[0]), IsDlgButtonChecked(hwndDlg, IDC_PSD));
+ break;
+// case IDC_STEALTHRQST:
+// icq_EnableMultipleControls(hwndDlg, icqIncognitoControls, sizeof(icqIncognitoControls)/sizeof(icqIncognitoControls[0]), IsDlgButtonChecked(hwndDlg, IDC_STEALTHRQST));
+ case IDC_ASDOPTIONS:
+ ShowASDOpts();
+ break;
+ }
+ OptDlgChanged(hwndDlg);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ if( gbASD != (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ASD))
+ {
+ ICQWriteContactSettingByte(NULL,"ASD",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ASD));
+ gbASD = (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ASD);
+ gbASD?icq_InitISee():icq_ISeeCleanup();
+ //here we need remove menu item from ASD
+ }
+/* if( DBGetContactSettingByte(NULL,gpszICQProtoName,"Inv4Inv", 0) != (BYTE)IsDlgButtonChecked(hwndDlg,IDC_INV4INV))
+ {
+ MessageBox(0,"To enable/disable Inv4Inv you must restart your Miranda","Warning",MB_OK);
+ ICQWriteContactSettingByte(NULL,"Inv4Inv",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_INV4INV));
+ }*/
+ if( DBGetContactSettingByte(NULL,gpszICQProtoName,"ASDStartup", 0) != (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ASDSTARTUP))
+ {
+ MessageBox(0,Translate("To enable/disable Entire list check you must restart your Miranda"),Translate("Warning"),MB_OK);
+ ICQWriteContactSettingByte(NULL,"ASDStartup",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ASDSTARTUP));
+ }
+// StoreDBCheckState(hwndDlg, IDC_STEALTHRQST , "StealthRequest");
+// if(ICQGetContactSettingByte(NULL, "StealthRequest", 0) == 1)
+// bStealthRequest = TRUE;
+// else
+// bStealthRequest = FALSE;
+ StoreDBCheckState(hwndDlg, IDC_SHOW_AUTH, "ShowAuth");
+ bShowAuth = ICQGetContactSettingByte(NULL, "ShowAuth", 0);
+ StoreDBCheckState(hwndDlg, IDC_PSD , "PSD");
+ bPSD = ICQGetContactSettingByte(NULL, "PSD", 1);
+ StoreDBCheckState(hwndDlg, IDC_NOASD , "NoASD");
+ bNoASD = ICQGetContactSettingByte(NULL, "NoASD", 1);
+ StoreDBCheckState(hwndDlg, IDC_NOPSD_FOR_HIDDEN, "NoPSDForHidden");
+ bNoPSDForHidden = ICQGetContactSettingByte(NULL, "NoPSDForHidden", 1);
+// StoreDBCheckState(hwndDlg, IDC_INV4INV , "Inv4Inv");
+ StoreDBCheckState(hwndDlg, IDC_INCGLOBAL , "IncognitoGlobal");
+ bIncognitoGlobal = ICQGetContactSettingByte(NULL, "IncognitoGlobal", 0);
+ StoreDBCheckState(hwndDlg, IDC_NOASD , "NoASD");
+ StoreDBCheckState(hwndDlg, IDC_ASDSTARTUP , "ASDStartup");
+ StoreDBCheckState(hwndDlg, IDC_TZER, "tZer");
+ gbTzerEnabled = ICQGetContactSettingByte(NULL,"tZer",0);
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static BOOL CALLBACK DlgProcIcqEventLogOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ extern BOOL bHcontactHistory;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hwndDlg);
+
+ LoadDBCheckState(hwndDlg, IDC_LOG_REMOVE_FILE, "LogSelfRemoveFile", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_IGNORECHECK_FILE, "LogIgnoreCheckFile", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_CHECKSTATUS_FILE, "LogStatusCheckFile", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_ASD_FILE, "LogASDFile", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_CLIENTCHANGE_FILE, "LogClientChangeFile", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_AUTH_FILE, "LogAuthFile", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_REQUEST_FILE, "LogRequestFile", 0);
+
+ LoadDBCheckState(hwndDlg, IDC_LOG_REMOVE_HISTORY, "LogSelfRemoveHistory", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_IGNORECHECK_HISTORY, "LogIgnoreCheckHistory", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_CHECKSTATUS_HISTORY, "LogStatusCheckHistory", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_ASD_HISTORY, "LogASDHistory", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_CLIENTCHANGE_HISTORY, "LogClientChangeHistory", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_AUTH_HISTORY, "LogAuthHistory", 0);
+ LoadDBCheckState(hwndDlg, IDC_LOG_REQUEST_HISTORY, "LogRequestHistory", 0);
+
+ LoadDBCheckState(hwndDlg, IDC_LOG_TO_HCONTACT_HISTORY, "LogToHcontact", 0);
+
+
+ SetDlgItemText(hwndDlg, IDC_FILEPATH, UniGetContactSettingUtf(NULL, gpszICQProtoName, "EventsLog", "EventsLog.txt"));
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_BROWSE), BUTTONSETASFLATBTN, 0, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_BROWSE), BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadSkinnedIcon(SKINICON_EVENT_FILE));
+
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_BROWSE:
+ { TCHAR str[MAX_PATH+2];
+ OPENFILENAME ofn={0};
+ TCHAR filter[512],*pfilter;
+
+ GetWindowText(GetWindow((HWND)lParam,GW_HWNDPREV),str,SIZEOF(str));
+ ofn.lStructSize=CDSIZEOF_STRUCT(OPENFILENAME,lpTemplateName);
+ ofn.hwndOwner=hwndDlg;
+ ofn.Flags=OFN_HIDEREADONLY;
+ if (LOWORD(wParam)==IDC_BROWSE) {
+ ofn.lpstrTitle=TranslateT("Select where log file will be created");
+ } else {
+ ofn.Flags|=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
+ ofn.lpstrTitle=TranslateT("Select program to be run");
+ }
+ _tcscpy(filter,TranslateT("All Files"));
+ _tcscat(filter,_T(" (*)"));
+ pfilter=filter+lstrlen(filter)+1;
+ _tcscpy(pfilter,_T("*"));
+ pfilter=pfilter+lstrlen(pfilter)+1;
+ *pfilter='\0';
+ ofn.lpstrFilter=filter;
+ ofn.lpstrFile=str;
+ ofn.nMaxFile=SIZEOF(str)-2;
+ ofn.nMaxFileTitle=MAX_PATH;
+ if (LOWORD(wParam)==IDC_BROWSE) {
+ if(!GetSaveFileName(&ofn)) return 1;
+ } else {
+ if(!GetOpenFileName(&ofn)) return 1;
+ }
+ SetWindowText(GetWindow((HWND)lParam,GW_HWNDPREV),str);
+ break;
+ }
+ break;
+ }
+ OptDlgChanged(hwndDlg);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ StoreDBCheckState(hwndDlg, IDC_LOG_REMOVE_FILE, "LogSelfRemoveFile");
+ bLogSelfRemoveFile = ICQGetContactSettingByte(NULL, "LogSelfRemoveFile", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_IGNORECHECK_FILE, "LogIgnoreCheckFile");
+ bLogIgnoreCheckFile= ICQGetContactSettingByte(NULL, "LogIgnoreCheckFile", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_CHECKSTATUS_FILE, "LogStatusCheckFile");
+ bLogStatusCheckFile = ICQGetContactSettingByte(NULL, "LogStatusCheckFile", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_ASD_FILE, "LogASDFile");
+ bLogASDFile = ICQGetContactSettingByte(NULL, "LogASDFile", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_CLIENTCHANGE_FILE, "LogClientChangeFile");
+ bLogClientChangeFile = ICQGetContactSettingByte(NULL, "LogClientChangeFile", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_AUTH_FILE, "LogAuthFile");
+ bLogAuthFile = ICQGetContactSettingByte(NULL, "LogAuthFile", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_REQUEST_FILE, "LogRequestFile");
+ bLogInfoRequestFile = ICQGetContactSettingByte(NULL, "LogRequestFile", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_REMOVE_HISTORY, "LogSelfRemoveHistory");
+ bLogSelfRemoveHistory = ICQGetContactSettingByte(NULL, "LogSelfRemoveHistory", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_IGNORECHECK_HISTORY, "LogIgnoreCheckHistory");
+ bLogIgnoreCheckHistory= ICQGetContactSettingByte(NULL, "LogIgnoreCheckHistory", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_CHECKSTATUS_HISTORY, "LogStatusCheckHistory");
+ bLogStatusCheckHistory = ICQGetContactSettingByte(NULL, "LogStatusCheckHistory", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_ASD_HISTORY, "LogASDHistory");
+ bLogASDHistory = ICQGetContactSettingByte(NULL, "LogASDHistory", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_CLIENTCHANGE_HISTORY, "LogClientChangeHistory");
+ bLogClientChangeHistory = ICQGetContactSettingByte(NULL, "LogClientChangeHistory", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_AUTH_HISTORY, "LogAuthHistory");
+ bLogAuthHistory = ICQGetContactSettingByte(NULL, "LogAuthHistory", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_REQUEST_HISTORY, "LogRequestHistory");
+ bLogInfoRequestHistory = ICQGetContactSettingByte(NULL, "LogRequestHistory", 0);
+ StoreDBCheckState(hwndDlg, IDC_LOG_TO_HCONTACT_HISTORY, "LogToHcontact");
+ bHcontactHistory = ICQGetContactSettingByte(NULL, "LogToHcontact", 0);
+ {
+ char i[1024];
+ GetDlgItemText(hwndDlg, IDC_FILEPATH, i, sizeof(i) );
+ UniWriteContactSettingUtf(NULL, gpszICQProtoName, "EventsLog", i);
+ }
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+BOOL id = FALSE;
+static const UINT icqVersionControls[] = {IDC_VERSION_CHECKBOX,IDC_SET_VERSION};
+static BOOL CALLBACK DlgProcIcqClientIDOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static BYTE bIdChanged = FALSE;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ ICQTranslateDialog(hwndDlg);
+ LoadDBCheckState(hwndDlg, IDC_HIDEID, "Hide ID", 1);
+ LoadDBCheckState(hwndDlg, IDC_CUSTOM_CAP, "customcap", 1);
+ LoadDBCheckState(hwndDlg, IDC_VERSION_CHECKBOX, "CurrentVer", 0);
+ id = FALSE;
+ {
+ char* CIdComboBox[] =
+ {
+ "MirandaIM","unknown","QIP2005a","YSM","pyICQ","&RQ","Jimm","Trillian",
+ "Licq","Kopete","ICQ for MAC","Miranda IM v6.6.6","ICQ 5 (Rambler)","ICQ 5.1","ICQ 5 (abv)",
+ "ICQ netvigator","Sim/MacOS X","Sim/Win32","Centericq","libicq2k","mChat","stICQ","KXicq2",
+ "QIP PDA (Windows)","QIP Mobile (Java)","ICQ 2002","ICQ 6","ICQ for Pocket PC",
+ "Anastasia","Virus","alicq","mICQ","StrICQ","vICQ","IM2","GAIM","ICQ99","WebICQ","SmartICQ",
+ "IM+","uIM","TICQClient","IC@","PreludeICQ","Qnext","ICQ Lite","QIP Infium","JICQ",
+ "SpamBot","MIP","Trillian Astra","R&Q","NanoICQ","IMadering","MirandaMobile"
+ };
+ int i;
+ for (i=0; i<sizeof(CIdComboBox)/sizeof(CIdComboBox[0]); i++)
+ ComboBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_CHANGEID), CIdComboBox[i],i);
+ }
+ // Miranda IM ICQ mods
+ {
+ char* MIMIdComboBox[] =
+ {
+ "original (Joe@Whale)", "BM Mod", "S7&SSS Mod",
+ "S!N Mod", "Plus Mod", "eternity/PlusPlus++"
+ };
+ int i;
+ for (i=0; i<sizeof(MIMIdComboBox)/sizeof(MIMIdComboBox[0]); i++)
+ ComboBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_ENIFMIRCBX), MIMIdComboBox[i],i);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_ENIFMIRCBX, CB_SETCURSEL, (DBGetContactSettingWord(NULL,gpszICQProtoName,"CurrentICQModID",0)),0);
+ if(DBGetContactSettingWord(NULL,gpszICQProtoName,"CurrentID",0))
+ SetDlgItemText(hwndDlg, IDC_FAKEWARNING, Translate("Your client ID is changed!\nChanging client id can result in serious messaging problems!\n\nIf you experience such problems, set your client ID back to \"Miranda\""));
+ else
+ bIdChanged = TRUE;
+
+ SendDlgItemMessage(hwndDlg, IDC_CHANGEID, CB_SETCURSEL, (DBGetContactSettingWord(NULL,gpszICQProtoName,"CurrentID",0)),0);
+ SetDlgItemInt(hwndDlg, IDC_SET_VERSION, (DBGetContactSettingWord(NULL,gpszICQProtoName,"setVersion", 0)), FALSE );
+ {
+ char tmp[MAXMODULELABELLENGTH];
+ mir_snprintf(tmp, MAXMODULELABELLENGTH, "%sCaps", gpszICQProtoName);
+ SetDlgItemText(hwndDlg, IDC_CUSTCAPEDIT, UniGetContactSettingUtf(NULL,tmp,"capability", 0));
+ }
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ // changing ClientID ComboBox to cause ICQ Mod ComboBox enable/disable
+ case IDC_CHANGEID:
+ {
+ int curID;
+ curID = SendDlgItemMessage(hwndDlg, IDC_CHANGEID, CB_GETCURSEL, 0, 0);
+ EnableWindow( GetDlgItem( hwndDlg, IDC_ENIFMIR ), curID == 0 );
+ EnableWindow( GetDlgItem( hwndDlg, IDC_ENIFMIRCBX ), curID == 0 );
+ }
+ break;
+ case IDC_CAPSBOX:
+ ShowCapsListDialog( hwndDlg );
+ return TRUE;
+ }
+ OptDlgChanged(hwndDlg);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ int i, fakeId, fakeICQModID;
+ fakeId = SendDlgItemMessage(hwndDlg, IDC_CHANGEID, CB_GETCURSEL, 0, 0);
+ if(DBGetContactSettingWord(NULL, gpszICQProtoName, "CurrentID", 0) != fakeId)
+ {
+ id = TRUE;
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "CurrentID", (WORD)fakeId);
+ }
+ // Miranda IM ICQ mods
+ fakeICQModID = SendDlgItemMessage(hwndDlg, IDC_ENIFMIRCBX, CB_GETCURSEL, 0, 0);
+ if(DBGetContactSettingWord(NULL, gpszICQProtoName, "CurrentICQModID", 0) != fakeICQModID)
+ {
+ id = TRUE;
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "CurrentICQModID", (WORD)fakeICQModID);
+ }
+ StoreDBCheckState(hwndDlg, IDC_VERSION_CHECKBOX, "CurrentVer");
+ gbVerEnabled = DBGetContactSettingByte(NULL, gpszICQProtoName, "CurrentVer", 0);
+ i = GetDlgItemInt(hwndDlg, IDC_SET_VERSION, 0, 0);
+ if(DBGetContactSettingWord(NULL, gpszICQProtoName, "setVersion", 0) != i)
+ {
+ id = TRUE;
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "setVersion", (WORD)i);
+ }
+ i = IsDlgButtonChecked(hwndDlg, IDC_HIDEID);
+ if(DBGetContactSettingByte(NULL, gpszICQProtoName, "Hide ID", 0) != i)
+ {
+ id = TRUE;
+ DBWriteContactSettingByte(NULL, gpszICQProtoName, "Hide ID", i);
+ }
+ if(DBGetContactSettingByte(NULL, gpszICQProtoName, "Hide ID", 0))
+ gbHideIdEnabled = 1;
+ else
+ gbHideIdEnabled = 0;
+
+ i = IsDlgButtonChecked(hwndDlg, IDC_CUSTOM_CAP);
+ if(DBGetContactSettingByte(NULL, gpszICQProtoName, "customcap", 0) != i)
+ {
+ id = TRUE;
+ DBWriteContactSettingByte(NULL, gpszICQProtoName, "customcap", i);
+ gbCustomCapEnabled=i;
+ }
+ if (id)
+ {
+ setUserInfo();
+ {
+ extern int icqGoingOnlineStatus;
+ icq_packet packet;
+ WORD wStatus;
+ DWORD dwFT1;
+ DWORD dwFT2;
+ DWORD dwFT3;
+ int nPort = ICQGetContactSettingWord(NULL, "UserPort", 0);
+ DWORD dwDirectCookie = rand() ^ (rand() << 16);
+ // Get status
+ wStatus = MirandaStatusToIcq(icqGoingOnlineStatus);
+ wStatus = MirandaStatusToIcq(icqGoingOnlineStatus);
+ 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, (WORD)GetProtoVersion());
+ packDWord(&packet, dwDirectCookie); // DC Cookie
+ packDWord(&packet, WEBFRONTPORT); // Web front port
+ packDWord(&packet, CLIENTFEATURES); // Client features
+ SetTimeStamps(&dwFT1, &dwFT2, &dwFT3);
+ packDWord(&packet, dwFT1);
+ packDWord(&packet, dwFT2);
+ packDWord(&packet, dwFT3);
+ packWord(&packet, 0x0000); // Unknown
+ packTLVWord(&packet, 0x001F, 0x0000);
+ sendServPacket(&packet);
+ }
+ }
+ if(fakeId != 0)
+ SetDlgItemText(hwndDlg, IDC_FAKEWARNING, Translate("Your client ID is changed!\nChanging client id can result in serious messaging problems!\n\nIf you experience such problems, set your client ID back to \"Miranda\""));
+ else
+ SetDlgItemText(hwndDlg, IDC_FAKEWARNING, "");
+ if(bIdChanged && (fakeId != 0))
+ {
+ MessageBox(0,Translate("Changing client ID can result in serious messaging problems!"),Translate("Warning"),MB_OK);
+ bIdChanged = FALSE;
+ }
+ }
+ // custom capability edit control
+/* {
+ char cap[24];
+ char tmp[MAXMODULELABELLENGTH];
+ mir_snprintf(tmp, MAXMODULELABELLENGTH, "%sCaps", gpszICQProtoName);
+ GetDlgItemText(hwndDlg, IDC_CUSTCAPEDIT, cap, sizeof(cap));
+ DBWriteContactSettingStringUtf(NULL, tmp, "capability", cap);
+ }*/
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+static const UINT icqContactsControls[] = {IDC_ADDSERVER,IDC_LOADFROMSERVER,IDC_SAVETOSERVER,IDC_UPLOADNOW,IDC_FORCEREFRESH};
+static const UINT icqAvatarControls[] = {IDC_AUTOLOADAVATARS,IDC_BIGGERAVATARS,IDC_STRICTAVATARCHECK};
+static const UINT icqAddTempControls[] = {IDC_ADDTEMP,IDC_TMP_CONTACTS_GROUP};
+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_BIGGERAVATARS, "AvatarsAllowBigger", DEFAULT_BIGGER_AVATARS);
+ LoadDBCheckState(hwndDlg, IDC_STRICTAVATARCHECK, "StrictAvatarCheck", DEFAULT_AVATARS_CHECK);
+
+ 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);
+ CheckDlgButton(hwndDlg, IDC_DELETE_TMP_CONTACTS, (bTmpContacts == 0));
+ CheckDlgButton(hwndDlg, IDC_ADD_TMP_CONTACTS, (bTmpContacts == 1));
+ SetDlgItemText(hwndDlg, IDC_TMP_CONTACTS_GROUP, UniGetContactSettingUtf(NULL,gpszICQProtoName,"TmpContactsGroup", 0));
+ LoadDBCheckState(hwndDlg, IDC_ADDTEMP, "AddTemp", 0);
+ icq_EnableMultipleControls(hwndDlg, icqAddTempControls, sizeof(icqAddTempControls)/sizeof(icqAddTempControls[0]), bTmpContacts?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);
+ }
+ if (!DBGetContactSettingDword(NULL,gpszICQProtoName,"SrvLastUpdate",0) &&
+ !DBGetContactSettingWord(NULL,gpszICQProtoName,"SrvRecordCount",0))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FORCEREFRESH), FALSE);
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_UPLOADNOW:
+ ShowUploadContactsDialog();
+ return TRUE;
+ case IDC_FORCEREFRESH:
+ DBWriteContactSettingDword(NULL,gpszICQProtoName,"SrvLastUpdate",0);
+ DBWriteContactSettingWord(NULL,gpszICQProtoName,"SrvRecordCount",0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FORCEREFRESH), FALSE);
+ 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;
+ case IDC_ADD_TMP_CONTACTS:
+ icq_EnableMultipleControls(hwndDlg, icqAddTempControls, sizeof(icqAddTempControls)/sizeof(icqAddTempControls[0]), IsDlgButtonChecked(hwndDlg, IDC_ADD_TMP_CONTACTS));
+ break;
+ case IDC_DELETE_TMP_CONTACTS:
+ icq_EnableMultipleControls(hwndDlg, icqAddTempControls, sizeof(icqAddTempControls)/sizeof(icqAddTempControls[0]), IsDlgButtonChecked(hwndDlg, IDC_ADD_TMP_CONTACTS));
+ 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_BIGGERAVATARS, "AvatarsAllowBigger");
+ StoreDBCheckState(hwndDlg, IDC_STRICTAVATARCHECK, "StrictAvatarCheck");
+ if (IsDlgButtonChecked(hwndDlg, IDC_DELETE_TMP_CONTACTS))
+ {
+ ICQWriteContactSettingByte(NULL, "TempContacts", 0);
+ bTmpContacts = 0;
+ }
+ else if (IsDlgButtonChecked(hwndDlg, IDC_ADD_TMP_CONTACTS))
+ {
+ ICQWriteContactSettingByte(NULL, "TempContacts", 1);
+ bTmpContacts = 1;
+ }
+ {
+ static char NewTmpGroupName[128] = {0},
+ CurrentTmpGroupName[128] = {0};
+ GetDlgItemText(hwndDlg, IDC_TMP_CONTACTS_GROUP, NewTmpGroupName, sizeof(NewTmpGroupName));
+ strcpy(CurrentTmpGroupName, UniGetContactSettingUtf(NULL, gpszICQProtoName, "TmpContactsGroup", "0"));
+ if(strcmp(CurrentTmpGroupName, NewTmpGroupName) != 0)
+ {
+ int GroupNumber = 0;
+ BYTE GroupExist = 0;
+ char szNumber[32] = {0}, szValue[96] = {0};
+ extern int CreateCListGroup(const char* szGroupName);
+ strcpy(szNumber, "0");
+ while(strcmp(UniGetContactSettingUtf(NULL, "CListGroups", szNumber, "0"), "0") != 0)
+ {
+#if defined(_MSC_VER) && _MSC_VER >= 1300
+ _itoa_s(GroupNumber, szNumber, sizeof(szNumber), 10);
+#else
+ _itoa(GroupNumber, szNumber, 10);
+#endif
+ strcpy(szValue, UniGetContactSettingUtf(NULL, "CListGroups", szNumber, "0"));
+ if(strcmp(NewTmpGroupName, szValue + 1) == 0)
+ {
+ GroupExist = 1;
+ break;
+ }
+ GroupNumber++;
+ }
+ UniWriteContactSettingUtf(NULL,gpszICQProtoName, "TmpContactsGroup", NewTmpGroupName);
+ TmpGroupName = UniGetContactSettingUtf(NULL,gpszICQProtoName,"TmpContactsGroup", Translate("General"));
+ if(!GroupExist)
+ CreateCListGroup(TmpGroupName);
+ }
+ }
+ StoreDBCheckState(hwndDlg, IDC_ADDTEMP, "AddTemp");
+ bAddTemp = ICQGetContactSettingByte(NULL, "AddTemp", 0);
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+
+static BOOL CALLBACK DlgProcIcqNewUINOpts(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ ICQTranslateDialog(hwndDlg);
+ return TRUE;
+ }
+ 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_UIN);
+ return TRUE;
+
+ case IDC_PICTURE:
+ if(icqOnline)
+ {
+ if (MessageBox(0,Translate("If you continue, you will lose current connection with a server,\nContinue?"),Translate("Warning"),MB_YESNO) == IDYES)
+ icq_requestRegImage(hwndDlg);
+ }
+ else
+ icq_requestRegImage(hwndDlg);
+ break;
+ case IDC_REGISTER:
+ {
+ char password[128];
+ char regimage[128];
+ GetDlgItemText(hwndDlg, IDC_NEWUIN_PASS, password, sizeof(password));
+ GetDlgItemText(hwndDlg, IDC_PICTURE_CONTENT, regimage, sizeof(regimage));
+ icq_registerNewUin(password, regimage);
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ hwndRegUin = NULL;
+ break;
+ }
+ return FALSE;
+}
+
+
+void ShowRegUinDialog(void)
+{
+ if (hwndRegUin == NULL)
+ {
+ hwndRegUin = CreateDialogUtf(hInst, MAKEINTRESOURCE(IDD_ICQ_REG_UIN), NULL, DlgProcIcqNewUINOpts);
+ }
+ SetForegroundWindow(hwndRegUin);
+}
+
+void ShowPopUpsOpts(void)
+{
+ if (hwndPopUpsOpts == NULL)
+ {
+ hwndPopUpsOpts = CreateDialogUtf(hInst, MAKEINTRESOURCE(IDD_OPT_POPUPS2), NULL, DlgProcIcqPopupOpts2);
+ }
+ SetForegroundWindow(hwndPopUpsOpts);
+}
+void ShowASDOpts(void){
+ if (hwndASDOpts == NULL)
+ {
+ hwndASDOpts = CreateDialogUtf(hInst, MAKEINTRESOURCE(IDD_OPT_ASD), NULL, DlgProcIcqASDOpts);
+ }
+ SetForegroundWindow(hwndASDOpts);
+}
+
+
+
+// password input box subclassing
+typedef struct
+{
+ WNDPROC oldWndProc;
+ HWND hwndTip;
+} TPasswordBoxData;
+
+static void IcqPasswordBox_Destroy(HWND hwndDlg, int idCtrl);
+
+static LRESULT CALLBACK IcqPasswordBox_WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ WNDPROC oldWndProc;
+ TPasswordBoxData *dat = (TPasswordBoxData *)GetWindowLong(hwnd, GWL_USERDATA);
+ if (!dat) return DefWindowProc(hwnd, msg, wParam, lParam);
+ oldWndProc = dat->oldWndProc;
+
+ switch(msg)
+ {
+ case WM_APP:
+ {
+ if (dat->hwndTip)
+ {
+ SendMessage(dat->hwndTip, TTM_TRACKACTIVATE, FALSE, 0);
+ DestroyWindow(dat->hwndTip);
+ dat->hwndTip = 0;
+ }
+
+ if (wParam && lParam)
+ {
+ TOOLINFO ti = {0};
+ RECT rc;
+
+ dat->hwndTip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, WS_POPUP|TTS_NOPREFIX|TTS_BALLOON, 0, 0, 0, 0, hwnd, NULL, hInst, 0);
+
+ ti.cbSize = sizeof(ti);
+ ti.lpszText = (TCHAR *)lParam;
+ ti.hinst = hInst;
+ ti.hwnd = hwnd;
+ ti.uFlags = TTF_TRACK|TTF_IDISHWND|TTF_TRANSPARENT;
+ ti.uId = (UINT_PTR)hwnd;
+ SendMessage(dat->hwndTip, TTM_ADDTOOL, 0, (LPARAM)&ti);
+
+ GetWindowRect(hwnd, &rc);
+ SendMessage(dat->hwndTip, TTM_TRACKPOSITION, 0, (LPARAM)MAKELONG(rc.left+20, rc.bottom));
+ SendMessage(dat->hwndTip, TTM_SETTITLE, 1, (LPARAM)wParam);
+ SendMessage(dat->hwndTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti);
+ }
+
+ break;
+ }
+
+ case WM_KILLFOCUS:
+ {
+ if (dat->hwndTip)
+ {
+ SendMessage(dat->hwndTip, TTM_TRACKACTIVATE, FALSE, 0);
+ DestroyWindow(dat->hwndTip);
+ dat->hwndTip = 0;
+ }
+
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ IcqPasswordBox_Destroy(GetParent(hwnd), GetWindowLong(hwnd, GWL_ID));
+ break;
+ }
+ }
+
+ return CallWindowProcUtf(oldWndProc, hwnd, msg, wParam, lParam);
+}
+
+static void IcqPasswordBox_Init(HWND hwndDlg, int idCtrl)
+{
+ HWND hwnd = GetDlgItem(hwndDlg, idCtrl);
+
+ if(GetWindowLong(hwnd, GWL_USERDATA)) return;
+
+ if (IsWinVer2000Plus())
+ {
+ TPasswordBoxData *dat = (TPasswordBoxData *)mir_alloc(sizeof(TPasswordBoxData));
+ dat->hwndTip = NULL;
+ SetWindowLong(hwnd, GWL_USERDATA, (LONG)dat);
+ dat->oldWndProc = (WNDPROC)SetWindowLongUtf(hwnd, GWL_WNDPROC, (LONG)IcqPasswordBox_WndProc);
+ }
+}
+
+static void IcqPasswordBox_Destroy(HWND hwndDlg, int idCtrl)
+{
+ HWND hwnd = GetDlgItem(hwndDlg, idCtrl);
+ TPasswordBoxData *dat = (TPasswordBoxData *)GetWindowLong(hwnd, GWL_USERDATA);
+ SetWindowLongUtf(hwnd, GWL_WNDPROC, (LONG)dat->oldWndProc);
+ SetWindowLong(hwnd, GWL_USERDATA, 0);
+ if (dat->hwndTip)
+ {
+ SendMessage(dat->hwndTip, TTM_TRACKACTIVATE, FALSE, 0);
+ DestroyWindow(dat->hwndTip);
+ dat->hwndTip = 0;
+ }
+ mir_free(dat);
+}
diff --git a/icqj_s7_sss_mod/icq_opts.h b/icqj_s7_sss_mod/icq_opts.h new file mode 100644 index 0000000..39426af --- /dev/null +++ b/icqj_s7_sss_mod/icq_opts.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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 37 $
+// Last change on : $Date: 2007-08-07 04:37:56 +0300 (Вт, 07 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+int IcqOptInit(WPARAM, LPARAM);
+void ShowRegUinDialog(void);
+//this must be in other place ...
+BOOL bPSD;
+BOOL bNoASD;
+BOOL bNoPSDForHidden;
+BOOL bLogSelfRemoveFile;
+BOOL bLogIgnoreCheckFile;
+BOOL bLogStatusCheckFile;
+BOOL bLogASDFile;
+BOOL bLogClientChangeFile;
+BOOL bLogAuthFile;
+BOOL bLogInfoRequestFile;
+BOOL bLogSelfRemoveHistory;
+BOOL bLogIgnoreCheckHistory;
+BOOL bLogStatusCheckHistory;
+BOOL bLogASDHistory;
+BOOL bLogClientChangeHistory;
+BOOL bLogAuthHistory;
+BOOL bLogInfoRequestHistory;
+BOOL bTmpContacts;
+char* TmpGroupName;
+BOOL bAddTemp;
+BOOL bNoStatusReply;
+BOOL bServerAutoChange;
+BOOL bIncognitoGlobal;
+//BOOL bStealthRequest;
\ No newline at end of file diff --git a/icqj_s7_sss_mod/icq_packet.c b/icqj_s7_sss_mod/icq_packet.c new file mode 100644 index 0000000..05bcf43 --- /dev/null +++ b/icqj_s7_sss_mod/icq_packet.c @@ -0,0 +1,750 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+void __fastcall init_generic_packet(icq_packet* pPacket, WORD wHeaderLen)
+{
+ pPacket->wPlace = 0;
+ pPacket->wLen += wHeaderLen;
+ pPacket->pData = (BYTE*)SAFE_MALLOC(pPacket->wLen);
+}
+
+
+
+void write_httphdr(icq_packet* pPacket, WORD wType, DWORD dwSeq)
+{
+ init_generic_packet(pPacket, 14);
+
+ 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)
+{
+ init_generic_packet(pPacket, 6);
+
+ pPacket->nChannel = byFlapChannel;
+
+ 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 + sizeof(CLIENT_ID_STRING) + 61);
+
+ write_flap(pPacket, ICQ_LOGIN_CHAN);
+ packDWord(pPacket, 0x00000001);
+ packTLV(pPacket, 0x06, wCookieSize, pCookie);
+
+ // Pack client identification details.
+ packTLV(pPacket, 0x0003, (WORD)sizeof(CLIENT_ID_STRING)-1, CLIENT_ID_STRING);
+ packTLVWord(pPacket, 0x0016, CLIENT_ID_CODE);
+ packTLVWord(pPacket, 0x0017, CLIENT_VERSION_MAJOR);
+ packTLVWord(pPacket, 0x0018, CLIENT_VERSION_MINOR);
+ packTLVWord(pPacket, 0x0019, CLIENT_VERSION_LESSER);
+ packTLVWord(pPacket, 0x001a, CLIENT_VERSION_BUILD);
+ packTLVDWord(pPacket, 0x0014, CLIENT_DISTRIBUTION);
+ packTLV(pPacket, 0x000f, 0x0002, CLIENT_LANGUAGE);
+ packTLV(pPacket, 0x000e, 0x0002, CLIENT_LANGUAGE);
+
+ packTLVDWord(pPacket, 0x8003, 0x00100000); // Unknown
+}
+
+
+
+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 __fastcall packQWord(icq_packet* pPacket, DWORD64 qwValue)
+{
+ packDWord(pPacket, (DWORD)(qwValue >> 32));
+ packDWord(pPacket, (DWORD)(qwValue & 0xffffffff));
+}
+
+
+
+void packTLV(icq_packet *pPacket, WORD wType, WORD wLength, const 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)SAFE_REALLOC(*buf,1+*buflen);
+ *(*buf+*buflen)=b;
+ ++*buflen;
+}
+
+
+
+void ppackLEWord(PBYTE *buf,int *buflen,WORD w)
+{
+ *buf=(PBYTE)SAFE_REALLOC(*buf,2+*buflen);
+ *(PWORD)(*buf+*buflen)=w;
+ *buflen+=2;
+}
+
+
+
+void ppackLEDWord(PBYTE *buf, int *buflen, DWORD d)
+{
+ *buf = (PBYTE)SAFE_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)SAFE_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)SAFE_REALLOC(*buf, *buflen + len);
+ memcpy(*buf + *buflen, str, len);
+ *buflen += len;
+}
+
+
+
+void ppackLELNTSfromDB(PBYTE *buf, int *buflen, const char *szSetting)
+{
+ DBVARIANT dbv;
+
+ if (ICQGetContactSettingString(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)SAFE_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)SAFE_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)SAFE_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)SAFE_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)SAFE_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)SAFE_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 unpackQWord(BYTE** pSource, DWORD64* qwDestination)
+{
+ DWORD dwData;
+
+ if (qwDestination)
+ {
+ unpackDWord(pSource, &dwData);
+ *qwDestination = ((DWORD64)dwData) << 32;
+ unpackDWord(pSource, &dwData);
+ *qwDestination |= dwData;
+ }
+ else
+ {
+ *pSource += 8;
+ }
+}
+
+
+
+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;
+
+NextTLV:
+ // Unpack type and length
+ unpackWord(&buf, &wType);
+ unpackWord(&buf, &wLen);
+ buflen -= 4;
+
+ if (wType != type && buflen >= wLen + 4)
+ { // Not the right TLV, try next
+ buflen -= wLen;
+ buf += wLen;
+ goto NextTLV;
+ }
+ // Check buffer size
+ if (wLen > buflen) wLen = buflen;
+
+ // Make sure we have a good pointer
+ if (tlv)
+ {
+ if (wLen)
+ { // Unpack and save value
+ *tlv = (char *)SAFE_MALLOC(wLen + 1); // Add 1 for \0
+ unpackString(&buf, *tlv, wLen);
+ *(*tlv + wLen) = '\0';
+ }
+ else
+ *tlv = NULL;
+ }
+
+ // Save type and length
+ if (ttype)
+ *ttype = wType;
+ if (tlen)
+ *tlen = wLen;
+}
+
+
+
+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_s7_sss_mod/icq_packet.h b/icqj_s7_sss_mod/icq_packet.h new file mode 100644 index 0000000..0a64271 --- /dev/null +++ b/icqj_s7_sss_mod/icq_packet.h @@ -0,0 +1,116 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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 wLen;
+ BYTE *pData;
+} icq_packet;
+
+/*---------* Functions *---------------*/
+
+void __fastcall init_generic_packet(icq_packet* pPacket, WORD wHeaderLen);
+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 __fastcall packQWord(icq_packet *, DWORD64);
+void packTLV(icq_packet *pPacket, WORD wType, WORD wLength, const BYTE *pbyValue);
+void packTLVWord(icq_packet *pPacket, WORD wType, WORD wData);
+void packTLVDWord(icq_packet *pPacket, WORD wType, 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 __fastcall unpackQWord(unsigned char **, DWORD64 *);
+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_s7_sss_mod/icq_popups.c b/icqj_s7_sss_mod/icq_popups.c new file mode 100644 index 0000000..ef5a20e --- /dev/null +++ b/icqj_s7_sss_mod/icq_popups.c @@ -0,0 +1,274 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 50 $
+// Last change on : $Date: 2007-08-28 02:57:00 +0300 (Вт, 28 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// PopUp Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static BOOL CALLBACK DlgProcIcqPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+
+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 int CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message) {
+ case WM_COMMAND:
+ if (HIWORD(wParam) == STN_CLICKED) {
+ // HANDLE hContact = PUGetContact(hWnd);
+ // if (hContact)
+ // NotifyEventHooks(hHookSendMessage, (WPARAM)hContact, 0);
+ PUDeletePopUp(hWnd);
+ return 1;
+ }
+ break;
+ case WM_CONTEXTMENU:
+ PUDeletePopUp(hWnd);
+ return 1;
+ case UM_INITPOPUP:
+ WindowList_Add(hPopUpsList,hWnd,(HANDLE)CallService(MS_POPUP_GETCONTACT,(WPARAM)hWnd,0));
+ return 1;
+ case UM_FREEPLUGINDATA:
+ WindowList_Remove(hPopUpsList,hWnd);
+ return 1;
+ default:
+ break;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+
+
+int ShowPopUpMsg(HANDLE hContact, DWORD dwUin, const char* szTitle, const char* szMsg, BYTE bType)
+{
+ if (bPopUpService && bPopUpsEnabled)
+ {
+ POPUPDATAEX ppd = {0};
+ POPUPDATAW ppdw = {0};
+ LPCTSTR rsIcon;
+ HINSTANCE hIcons = NULL;
+ HWND hPopUpWnd = NULL;
+ char szPrefix[64], szSetting[32], szText [64];
+
+ strcpy(szPrefix, "Popups");
+ ppd.iSeconds = 0;
+
+ switch(bType)
+ {
+ case LOG_NOTE:
+ rsIcon = MAKEINTRESOURCE(IDI_INFORMATION);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "0");
+ break;
+
+ case LOG_WARNING:
+ rsIcon = MAKEINTRESOURCE(IDI_WARNING);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "1");
+ break;
+
+ case LOG_ERROR:
+ rsIcon = MAKEINTRESOURCE(IDI_ERROR);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "2");
+ break;
+
+ case LOG_FATAL:
+ rsIcon = MAKEINTRESOURCE(IDI_ERROR);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "3");
+ break;
+
+ case POPTYPE_SPAM:
+ rsIcon = MAKEINTRESOURCE(IDI_WARNING);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "Spam");
+ break;
+
+ case POPTYPE_UNKNOWN:
+ rsIcon = MAKEINTRESOURCE(IDI_WARNING);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "Unknown");
+ break;
+
+ case POPTYPE_VIS:
+ rsIcon = MAKEINTRESOURCE(IDI_INFORMATION);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "Vis");
+ break;
+
+
+ case POPTYPE_FOUND:
+ hIcons = hInst;
+ rsIcon = MAKEINTRESOURCE(IDI_HIDDEN);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "Found");
+ break;
+
+ case POPTYPE_SCAN:
+ hIcons = hInst;
+ rsIcon = gbScan?MAKEINTRESOURCE(IDI_START):MAKEINTRESOURCE(IDI_STOP);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "Finished");
+ break;
+ case POPTYPE_CLIENT_CHANGE:
+ rsIcon = MAKEINTRESOURCE(IDI_INFORMATION);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "ClientChange");
+ break;
+ case POPTYPE_INFO_REQUEST:
+ rsIcon = MAKEINTRESOURCE(IDI_INFORMATION);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "InfoRequest");
+ break;
+ case POPTYPE_IGNORE_CHECK:
+ rsIcon = MAKEINTRESOURCE(IDI_INFORMATION);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "IgnoreCheck");
+ break;
+ case POPTYPE_SELFREMOVE:
+ rsIcon = MAKEINTRESOURCE(IDI_INFORMATION);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "RemoveHimself");
+ break;
+ case POPTYPE_AUTH:
+ rsIcon = MAKEINTRESOURCE(IDI_INFORMATION);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "Auth");
+ break;
+ case POPTYPE_XUPDATER:
+ rsIcon = MAKEINTRESOURCE(IDI_INFORMATION);
+ ppd.colorBack = RGB(0,0,0);
+ ppd.colorText = RGB(255,255,255);
+ strcat(szPrefix, "XUpdater");
+ break;
+ default:
+ return -1;
+ }
+ if (!ICQGetContactSettingByte(NULL, "PopupsSysIcons", 1))
+ {
+ hIcons = hInst;
+ rsIcon = MAKEINTRESOURCE(IDI_ICQ);
+ }
+ ppd.lchIcon = (HICON)LoadImage(hIcons, rsIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ if (ICQGetContactSettingByte(NULL, "PopupsWinColors", 0))
+ {
+ ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ ppd.colorBack = GetSysColor(COLOR_WINDOW);
+ }
+ else
+ {
+ 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);
+
+ //by chaos.persei @ 9.12.2006 15:25
+ //bug - unhiding popups - fix
+ if (ppd.iSeconds == 0) ppd.iSeconds = 10;
+
+ hPopUpWnd = WindowList_Find(hPopUpsList,hContact);
+ if ((bType == POPTYPE_VIS) && hPopUpWnd)
+ return -1;
+ if(dwUin && bUinPopup)
+ mir_snprintf(szText, sizeof(szText), "%s, %s: (%u)", szTitle, ICQTranslateUtf("UIN"), dwUin);
+ else
+ strcpy(szText,szTitle);
+
+ if (gbUnicodeAPI && ServiceExists(MS_POPUP_ADDPOPUPW))
+ { // call unicode popup module - only on unicode OS otherwise it will not work properly :(
+ // due to Popup Plug bug in ADDPOPUPW implementation
+ char str[MAX_PATH];
+
+ make_unicode_string_static(ICQTranslateUtfStatic(szText, str, MAX_PATH), ppdw.lpwzContactName, MAX_CONTACTNAME);
+ make_unicode_string_static(ICQTranslateUtfStatic(szMsg, str, MAX_PATH), ppdw.lpwzText, MAX_SECONDLINE);
+ ppdw.lchContact = hContact;
+ ppdw.lchIcon = ppd.lchIcon;
+ ppdw.colorBack = ppd.colorBack;
+ ppdw.colorText = ppd.colorText;
+ ppdw.PluginWindowProc = (WNDPROC)PopupDlgProc;
+ ppdw.PluginData = NULL;
+ ppdw.iSeconds = ppd.iSeconds;
+
+ return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&ppdw, 0);
+ }
+ else
+ {
+ char str[MAX_PATH];
+
+ utf8_decode_static(ICQTranslateUtfStatic(szText, str, MAX_PATH), ppd.lpzContactName, MAX_CONTACTNAME);
+ utf8_decode_static(ICQTranslateUtfStatic(szMsg, str, MAX_PATH), ppd.lpzText, MAX_SECONDLINE);
+ ppd.lchContact = hContact;
+ ppd.PluginWindowProc = (WNDPROC)PopupDlgProc;
+ ppd.PluginData = NULL;
+
+ return CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+ }
+ }
+ return -1; // Failure
+}
diff --git a/icqj_s7_sss_mod/icq_popups.h b/icqj_s7_sss_mod/icq_popups.h new file mode 100644 index 0000000..0f69f52 --- /dev/null +++ b/icqj_s7_sss_mod/icq_popups.h @@ -0,0 +1,84 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 50 $
+// Last change on : $Date: 2007-08-28 02:57:00 +0300 (Вт, 28 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Headers for PopUp Plugin support
+//
+// -----------------------------------------------------------------------------
+
+
+BOOL bPopUpService;
+BOOL bPopUpsEnabled;
+BOOL bSpamPopUp;
+BOOL bUnknownPopUp;
+BOOL bFoundPopUp;
+BOOL bScanPopUp;
+BOOL bClientChangePopUp;
+BOOL bVisPopUp;
+BOOL bPopUpForNotOnList;
+BOOL bIgnoreCheckPop;
+BOOL bPopSelfRem;
+BOOL bInfoRequestPopUp;
+BOOL bAuthPopUp;
+BOOL bUinPopup;
+
+extern HANDLE hPopUpsList;
+
+
+
+#ifndef __ICQ_POPUPS_H
+#define __ICQ_POPUPS_H
+
+
+#define POPTYPE_SPAM 254 // this is for spambots
+#define POPTYPE_UNKNOWN 253
+#define POPTYPE_VIS 252
+#define POPTYPE_INFO_REQUEST 251
+#define POPTYPE_CLIENT_CHANGE 250
+#define POPTYPE_IGNORE_CHECK 249
+#define POPTYPE_SELFREMOVE 248
+#define POPTYPE_AUTH 247
+#define POPTYPE_XUPDATER 246
+
+
+#define POPTYPE_FOUND 5
+#define POPTYPE_SCAN 6
+
+
+
+//void InitPopUps();
+void InitPopupOpts(WPARAM wParam);
+
+int ShowPopUpMsg(HANDLE hContact, DWORD dwUin, const char* szTitle, const char* szMsg, BYTE bType);
+
+
+#endif /* __ICQ_POPUPS_H */
diff --git a/icqj_s7_sss_mod/icq_rates.c b/icqj_s7_sss_mod/icq_rates.c new file mode 100644 index 0000000..1a0cbfe --- /dev/null +++ b/icqj_s7_sss_mod/icq_rates.c @@ -0,0 +1,664 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Rate Management stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+//
+// Rate Level 1 Management
+/////////////////////////////
+
+CRITICAL_SECTION ratesMutex;
+
+
+rates* ratesCreate(BYTE* pBuffer, WORD wLen)
+{
+ rates* pRates;
+ WORD wCount;
+ int i;
+
+ unpackWord(&pBuffer, &wCount);
+ wLen -= 2;
+
+ pRates = (rates*)SAFE_MALLOC(sizeof(rates)+(wCount)*sizeof(rates_group));
+ pRates->nGroups = wCount;
+ // Parse Group details
+ for (i=0; i<wCount; i++)
+ {
+ rates_group* pGroup = &pRates->groups[i];
+
+ if (wLen >= 35)
+ {
+ pBuffer += 2; // Group ID
+ unpackDWord(&pBuffer, &pGroup->dwWindowSize);
+ unpackDWord(&pBuffer, &pGroup->dwClearLevel);
+ unpackDWord(&pBuffer, &pGroup->dwAlertLevel);
+ unpackDWord(&pBuffer, &pGroup->dwLimitLevel);
+ pBuffer += 8;
+ unpackDWord(&pBuffer, &pGroup->dwMaxLevel);
+ pBuffer += 5;
+ wLen -= 35;
+ }
+ else
+ { // packet broken, put some basic defaults
+ pGroup->dwWindowSize = 10;
+ pGroup->dwMaxLevel = 5000;
+ }
+ pGroup->rCurrentLevel = pGroup->dwMaxLevel;
+ }
+ // Parse Group associated pairs
+ for (i=0; i<wCount; i++)
+ {
+ rates_group* pGroup = &pRates->groups[i];
+ WORD wNum;
+ int n;
+
+ if (wLen<4) break;
+ pBuffer += 2; // Group ID
+ unpackWord(&pBuffer, &wNum);
+ wLen -= 4;
+ if (wLen < wNum*4) break;
+ pGroup->nPairs = wNum;
+ pGroup->pPairs = (WORD*)SAFE_MALLOC(wNum*4);
+ for (n=0; n<wNum*2; n++)
+ {
+ WORD wItem;
+
+ unpackWord(&pBuffer, &wItem);
+ pGroup->pPairs[n] = wItem;
+ }
+#ifdef _DEBUG
+ NetLog_Server("Rates: %d# %d pairs.", i+1, wNum);
+#endif
+ wLen -= wNum*4;
+ }
+
+ return pRates;
+}
+
+
+
+void ratesRelease(rates** pRates)
+{
+ if (pRates)
+ {
+ rates* rates = *pRates;
+
+ EnterCriticalSection(&ratesMutex);
+
+ if (rates)
+ {
+ int i;
+
+ for (i = 0; i < rates->nGroups; i++)
+ {
+ SAFE_FREE(&rates->groups[i].pPairs);
+ }
+ SAFE_FREE(pRates);
+ }
+ LeaveCriticalSection(&ratesMutex);
+ }
+}
+
+
+
+WORD ratesGroupFromSNAC(rates* pRates, WORD wFamily, WORD wCommand)
+{
+ int i;
+
+ if (pRates)
+ {
+ for (i = 0; i < pRates->nGroups; i++)
+ {
+ rates_group* group = &pRates->groups[i];
+ int j;
+
+ for (j = 0; j < 2*group->nPairs; j += 2)
+ {
+ if (group->pPairs[j] == wFamily && group->pPairs[j + 1] == wCommand)
+ { // we found the group
+ return (WORD)(i + 1);
+ }
+ }
+ }
+ _ASSERTE(0);
+ }
+
+ return 0; // Failure
+}
+
+
+
+WORD ratesGroupFromPacket(rates* pRates, icq_packet* pPacket)
+{
+ if (pRates)
+ {
+ if (pPacket->nChannel == ICQ_DATA_CHAN && pPacket->wLen >= 0x10)
+ {
+ WORD wFam, wCmd;
+ BYTE* pBuf = pPacket->pData + 6;
+
+ unpackWord(&pBuf, &wFam);
+ unpackWord(&pBuf, &wCmd);
+
+ return ratesGroupFromSNAC(pRates, wFam, wCmd);
+ }
+ }
+ return 0;
+}
+
+
+
+static rates_group* getRatesGroup(rates* pRates, WORD wGroup)
+{
+ if (pRates && wGroup <= pRates->nGroups)
+ {
+ return &pRates->groups[wGroup-1];
+ }
+ return NULL;
+}
+
+
+int ratesNextRateLevel(rates* pRates, WORD wGroup)
+{
+ rates_group* pGroup = getRatesGroup(pRates, wGroup);
+
+ if (pGroup)
+ {
+ int nLevel = pGroup->rCurrentLevel*(pGroup->dwWindowSize-1)/pGroup->dwWindowSize + (GetTickCount() - pGroup->tCurrentLevel)/pGroup->dwWindowSize;
+
+ return nLevel < (int)pGroup->dwMaxLevel ? nLevel : pGroup->dwMaxLevel;
+ }
+ return -1; // Failure
+}
+
+
+
+int ratesDelayToLevel(rates* pRates, WORD wGroup, int nLevel)
+{
+ rates_group* pGroup = getRatesGroup(pRates, wGroup);
+
+ if (pGroup)
+ {
+ return (nLevel - pGroup->rCurrentLevel)*pGroup->dwWindowSize + pGroup->rCurrentLevel;
+ }
+ return 0; // Failure
+}
+
+
+
+void ratesPacketSent(rates* pRates, icq_packet* pPacket)
+{
+ if (pRates)
+ {
+ WORD wGroup = ratesGroupFromPacket(pRates, pPacket);
+
+ if (wGroup)
+ ratesUpdateLevel(pRates, wGroup, ratesNextRateLevel(pRates, wGroup));
+ }
+}
+
+
+
+void ratesUpdateLevel(rates* pRates, WORD wGroup, int nLevel)
+{
+ rates_group* pGroup = getRatesGroup(pRates, wGroup);
+
+ if (pGroup)
+ {
+ pGroup->rCurrentLevel = nLevel;
+ pGroup->tCurrentLevel = GetTickCount();
+#ifdef _DEBUG
+ NetLog_Server("Rates: New level %d for #%d", nLevel, wGroup);
+#endif
+ }
+}
+
+
+
+int ratesGetLimitLevel(rates* pRates, WORD wGroup, int nLevel)
+{
+ rates_group* pGroup = getRatesGroup(pRates, wGroup);
+
+ if (pGroup)
+ {
+ switch(nLevel)
+ {
+ case RML_CLEAR:
+ return pGroup->dwClearLevel;
+
+ case RML_ALERT:
+ return pGroup->dwAlertLevel;
+
+ case RML_LIMIT:
+ return pGroup->dwLimitLevel;
+
+ case RML_IDLE_10:
+ return pGroup->dwClearLevel + ((pGroup->dwMaxLevel - pGroup->dwClearLevel)/10);
+
+ case RML_IDLE_30:
+ return pGroup->dwClearLevel + (3*(pGroup->dwMaxLevel - pGroup->dwClearLevel)/10);
+
+ case RML_IDLE_50:
+ return pGroup->dwClearLevel + ((pGroup->dwMaxLevel - pGroup->dwClearLevel)/2);
+
+ case RML_IDLE_70:
+ return pGroup->dwClearLevel + (7*(pGroup->dwMaxLevel - pGroup->dwClearLevel)/10);
+ }
+ }
+ return 9999; // some high number - without rates we allow anything
+}
+
+
+//
+// Rate Level 2 Management
+/////////////////////////////
+
+// links to functions that are under Rate Control
+extern DWORD sendXStatusDetailsRequest(HANDLE hContact, int bForced);
+
+static CRITICAL_SECTION ratesListsMutex; // 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;
+
+static DWORD __stdcall rateDelayThread(rate_delay_args* pArgs)
+{
+ SleepEx(pArgs->nDelay, TRUE);
+ pArgs->delaycode();
+
+ SAFE_FREE(&pArgs);
+ return 0;
+}
+
+
+
+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;
+
+ ICQCreateThread(rateDelayThread, pArgs);
+}
+
+
+
+static void RatesTimer1()
+{
+ rate_record *item;
+ int bSetupTimer = 0;
+
+ EnterCriticalSection(&ratesListsMutex);
+ if (!pendingList1)
+ {
+ LeaveCriticalSection(&ratesListsMutex);
+ return;
+ }
+
+ if (!icqOnline)
+ {
+ int i;
+
+ for (i=0; i<pendingListSize1; i++) SAFE_FREE(&pendingList1[i]);
+ SAFE_FREE((void**)&pendingList1);
+ pendingListSize1 = 0;
+ LeaveCriticalSection(&ratesListsMutex);
+
+ return;
+ }
+ // take from queue, execute
+ item = pendingList1[0];
+
+ EnterCriticalSection(&ratesMutex);
+ if (ratesNextRateLevel(gRates, item->wGroup) < ratesGetLimitLevel(gRates, item->wGroup, RML_IDLE_30))
+ { // the rate is higher, keep sleeping
+ int nDelay = ratesDelayToLevel(gRates, item->wGroup, ratesGetLimitLevel(gRates, item->wGroup, RML_IDLE_50));
+
+ LeaveCriticalSection(&ratesMutex);
+ LeaveCriticalSection(&ratesListsMutex);
+ if (nDelay < 10) nDelay = 10;
+ InitDelay(nDelay, RatesTimer1);
+
+ return;
+ }
+ LeaveCriticalSection(&ratesMutex);
+
+ if (pendingListSize1 > 1)
+ { // we need to keep order
+ memmove(&pendingList1[0], &pendingList1[1], (pendingListSize1 - 1)*sizeof(rate_record*));
+ }
+ else
+ SAFE_FREE((void**)&pendingList1);
+ pendingListSize1--;
+
+ if (pendingListSize1)
+ bSetupTimer = 1;
+
+ LeaveCriticalSection(&ratesListsMutex);
+
+ if (icqOnline)
+ {
+ NetLog_Server("Rates: Resuming Xtraz request.");
+ if (item->bType = RIT_XSTATUS_REQUEST)
+ sendXStatusDetailsRequest(item->hContact, FALSE);
+ }
+ else
+ NetLog_Server("Rates: Discarding request.");
+
+ if (bSetupTimer)
+ { // in queue remained some items, setup timer
+ int nDelay;
+
+ EnterCriticalSection(&ratesMutex);
+ nDelay = ratesDelayToLevel(gRates, item->wGroup, ratesGetLimitLevel(gRates, item->wGroup, RML_IDLE_50));
+ LeaveCriticalSection(&ratesMutex);
+
+ if (nDelay < 10) nDelay = 10;
+ InitDelay(nDelay, RatesTimer1);
+ }
+ SAFE_FREE(&item);
+}
+
+
+
+static void putItemToQueue1(rate_record *item, int nLev)
+{
+ 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**)SAFE_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;
+ int nDelay;
+
+ EnterCriticalSection(&ratesMutex);
+ nDelay = ratesDelayToLevel(gRates, item->wGroup, ratesGetLimitLevel(gRates, item->wGroup, RML_IDLE_50));
+ LeaveCriticalSection(&ratesMutex);
+
+ 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 bSetupTimer = 0;
+
+ EnterCriticalSection(&ratesListsMutex);
+ if (!pendingList2)
+ {
+ LeaveCriticalSection(&ratesListsMutex);
+ return;
+ }
+
+ if (!icqOnline)
+ {
+ int i;
+
+ for (i=0; i<pendingListSize2; i++)
+ {
+ SAFE_FREE(&pendingList2[i]->szData);
+ SAFE_FREE(&pendingList2[i]);
+ }
+ SAFE_FREE((void**)&pendingList2);
+ pendingListSize2 = 0;
+ LeaveCriticalSection(&ratesListsMutex);
+
+ return;
+ }
+ // take from queue, execute
+ item = pendingList2[0];
+
+ EnterCriticalSection(&ratesMutex);
+ if (ratesNextRateLevel(gRates, item->wGroup) < ratesGetLimitLevel(gRates, item->wGroup, RML_IDLE_10))
+ { // the rate is higher, keep sleeping
+ int nDelay = ratesDelayToLevel(gRates, item->wGroup, ratesGetLimitLevel(gRates, item->wGroup, RML_IDLE_30));
+
+ LeaveCriticalSection(&ratesMutex);
+ LeaveCriticalSection(&ratesListsMutex);
+ if (nDelay < 10) nDelay = 10;
+ InitDelay(nDelay, RatesTimer2);
+
+ return;
+ }
+
+ LeaveCriticalSection(&ratesMutex);
+ if (pendingListSize2 > 1)
+ { // we need to keep order
+ memmove(&pendingList2[0], &pendingList2[1], (pendingListSize2 - 1)*sizeof(rate_record*));
+ }
+ else
+ SAFE_FREE((void**)&pendingList2);
+ pendingListSize2--;
+
+ if (pendingListSize2)
+ bSetupTimer = 1;
+
+ LeaveCriticalSection(&ratesListsMutex);
+
+ 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);
+
+ if (bSetupTimer)
+ { // in queue remained some items, setup timer
+ int nDelay;
+
+ EnterCriticalSection(&ratesMutex);
+ nDelay = ratesDelayToLevel(gRates, item->wGroup, ratesGetLimitLevel(gRates, item->wGroup, RML_IDLE_30));
+ LeaveCriticalSection(&ratesMutex);
+
+ if (nDelay < 10) nDelay = 10;
+ InitDelay(nDelay, RatesTimer2);
+ }
+ SAFE_FREE(&item);
+}
+
+
+
+static void putItemToQueue2(rate_record *item, int nLev)
+{
+ rate_record *tmp;
+ int bFound = FALSE;
+
+ if (!icqOnline) return;
+
+ NetLog_Server("Rates: Delaying operation.");
+
+ if (pendingListSize2)
+ {
+ int i;
+
+ for (i = 0; i < pendingListSize2; i++)
+ {
+ if (pendingList2[i]->hContact == item->hContact && pendingList2[i]->bType == item->bType)
+ { // there is older response in the queue, discard it (server won't accept it anyway)
+ SAFE_FREE(&pendingList2[i]->szData);
+ SAFE_FREE(&pendingList2[i]);
+ memcpy(&pendingList2[i], &pendingList2[i + 1], (pendingListSize2 - i - 1)*sizeof(rate_record*));
+ bFound = TRUE;
+ }
+ }
+ }
+ if (!bFound)
+ { // not found, enlarge the queue
+ pendingListSize2++;
+ pendingList2 = (rate_record**)SAFE_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
+ int nDelay;
+
+ EnterCriticalSection(&ratesMutex);
+ nDelay = ratesDelayToLevel(gRates, item->wGroup, ratesGetLimitLevel(gRates, item->wGroup, RML_IDLE_30));
+ LeaveCriticalSection(&ratesMutex);
+
+ if (nDelay < 10) nDelay = 10;
+ InitDelay(nDelay, RatesTimer2);
+ }
+}
+
+
+
+int handleRateItem(rate_record *item, BOOL bAllowDelay)
+{
+ if (!gRates) return 0;
+
+ EnterCriticalSection(&ratesListsMutex);
+
+ if (item->nRequestType == 0x101)
+ { // xtraz request
+ int nLev, nLimit;
+
+ EnterCriticalSection(&ratesMutex);
+ nLev = ratesNextRateLevel(gRates, item->wGroup);
+ nLimit = ratesGetLimitLevel(gRates, item->wGroup, RML_IDLE_50) + 200;
+ LeaveCriticalSection(&ratesMutex);
+
+ if ((nLev < nLimit || item->nMinDelay) && bAllowDelay)
+ { // limit reached or min delay configured, add to queue
+ putItemToQueue1(item, nLev);
+ LeaveCriticalSection(&ratesListsMutex);
+ return 1;
+ }
+ }
+ else if (item->nRequestType == 0x102)
+ { // msg response
+ int nLev, nLimit;
+
+ EnterCriticalSection(&ratesMutex);
+ nLev = ratesNextRateLevel(gRates, item->wGroup);
+ nLimit = ratesGetLimitLevel(gRates, item->wGroup, RML_IDLE_30) + 100;
+ LeaveCriticalSection(&ratesMutex);
+
+ if (nLev < nLimit)
+ { // limit reached, add to queue
+ putItemToQueue2(item, nLev);
+ LeaveCriticalSection(&ratesListsMutex);
+ return 1;
+ }
+ }
+ LeaveCriticalSection(&ratesListsMutex);
+
+ return 0;
+}
+
+
+
+void InitRates()
+{
+ InitializeCriticalSection(&ratesMutex);
+ InitializeCriticalSection(&ratesListsMutex);
+
+ pendingListSize1 = 0;
+ pendingList1 = NULL;
+ pendingListSize2 = 0;
+ pendingList2 = NULL;
+}
+
+
+
+void UninitRates()
+{
+ SAFE_FREE((void**)&pendingList1);
+ SAFE_FREE((void**)&pendingList2);
+ DeleteCriticalSection(&ratesMutex);
+ DeleteCriticalSection(&ratesListsMutex);
+}
diff --git a/icqj_s7_sss_mod/icq_rates.h b/icqj_s7_sss_mod/icq_rates.h new file mode 100644 index 0000000..c75e3a0 --- /dev/null +++ b/icqj_s7_sss_mod/icq_rates.h @@ -0,0 +1,117 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_RATES_H
+#define __ICQ_RATES_H
+
+extern CRITICAL_SECTION ratesMutex;
+
+typedef struct rates_group_s
+{
+ DWORD dwWindowSize;
+ DWORD dwClearLevel;
+ DWORD dwAlertLevel;
+ DWORD dwLimitLevel;
+ DWORD dwMaxLevel;
+ // current level
+ int rCurrentLevel;
+ int tCurrentLevel;
+ // links
+ WORD* pPairs;
+ int nPairs;
+} rates_group;
+
+typedef struct rates_s
+{
+ int nGroups;
+ rates_group groups[];
+} rates;
+
+rates* gRates;
+
+rates* ratesCreate(BYTE* pBuffer, WORD wLen);
+void ratesRelease(rates** pRates);
+
+WORD ratesGroupFromSNAC(rates* pRates, WORD wFamily, WORD wCommand);
+WORD ratesGroupFromPacket(rates* pRates, icq_packet* pPacket);
+
+int ratesNextRateLevel(rates* pRates, WORD wGroup);
+int ratesDelayToLevel(rates* pRates, WORD wGroup, int nLevel);
+void ratesPacketSent(rates* pRates, icq_packet* pPacket);
+void ratesUpdateLevel(rates* pRates, WORD wGroup, int nLevel);
+
+#define RML_CLEAR 1
+#define RML_ALERT 2
+#define RML_LIMIT 3
+#define RML_IDLE_10 0x10
+#define RML_IDLE_30 0x11
+#define RML_IDLE_50 0x12
+#define RML_IDLE_70 0x13
+
+int ratesGetLimitLevel(rates* pRates, WORD wGroup, int nLevel);
+
+// Rates - Level 2
+
+#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
+ WORD wGroup;
+ int nRequestType;
+ 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_s7_sss_mod/icq_reguin.c b/icqj_s7_sss_mod/icq_reguin.c new file mode 100644 index 0000000..6b42b58 --- /dev/null +++ b/icqj_s7_sss_mod/icq_reguin.c @@ -0,0 +1,64 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Registers new uin
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+void icq_registerNewUin(char* password, char* image)
+{
+ strcpy(icq_regpassword, password);
+ icq_regNewUin = 2;
+ registerUin(password, image);
+}
+
+void icq_requestRegImage(HWND hwndDlg)
+{
+ icq_serverDisconnect(0);
+ iIcqNewStatus = ID_STATUS_OFFLINE;
+ hwndRegImageDialog = hwndDlg;
+ bImageRequested = 1;
+ SetDlgItemText(hwndRegImageDialog, IDC_NEWUININFO, Translate("Connecting to server..."));
+ icq_login(NULL);
+ icq_regNewUin = 1;
+}
+
+
+void InitReguin()
+{
+ //0 - default icq working, 1 - get image, 2 - request image
+ icq_regNewUin = 0;
+ bImageRequested = 0;
+}
\ No newline at end of file diff --git a/icqj_s7_sss_mod/icq_reguin.h b/icqj_s7_sss_mod/icq_reguin.h new file mode 100644 index 0000000..95494a2 --- /dev/null +++ b/icqj_s7_sss_mod/icq_reguin.h @@ -0,0 +1,15 @@ +#ifndef __ICQ_REGUIN_H
+#define __ICQ_REGUIN_H
+
+int icq_regNewUin;
+char icq_regpassword[10];
+DWORD icq_regedUin;
+HWND hwndRegImageDialog;
+
+BOOL bImageRequested; //need to simply connect to ICQ if network error during registering
+
+void InitReguin();
+void icq_requestRegImage();
+void icq_registerNewUin(char* password, char* image);
+
+#endif /* __ICQ_REGUIN_H */
diff --git a/icqj_s7_sss_mod/icq_server.c b/icqj_s7_sss_mod/icq_server.c new file mode 100644 index 0000000..920d333 --- /dev/null +++ b/icqj_s7_sss_mod/icq_server.c @@ -0,0 +1,529 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 62 $
+// Last change on : $Date: 2007-10-16 14:56:05 +0300 (Вт, 16 окт 2007) $
+// Last change by : $Author: chaos.persei $
+//
+// DESCRIPTION:
+//
+// Manages main server connection, low-level communication
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern CRITICAL_SECTION connectionHandleMutex;
+extern WORD wLocalSequence;
+extern CRITICAL_SECTION localSeqMutex;
+extern int icqGoingOnlineStatus;
+HANDLE hServerConn;
+WORD wListenPort;
+WORD wLocalSequence;
+static DWORD serverThreadId;
+static HANDLE serverThreadHandle;
+BOOL TryNextWorking;
+
+static int handleServerPackets(unsigned char* buf, int len, serverthread_info* info);
+
+static DWORD __stdcall icq_TryNextServerThread(LPVOID lp)
+{
+ WORD CurrServ, SrvCount, Port;
+ char DBModule[64], buf[1024], buf1[64], buf2[64];
+
+ TryNextWorking = 1;
+
+ WaitForSingleObject(serverThreadHandle, INFINITE);
+
+ mir_snprintf(DBModule, 64, "%sSrvs", gpszICQProtoName);
+
+ SrvCount = DBGetContactSettingWord(0, DBModule, "SrvCount", 0);
+ if(SrvCount == 0) { TryNextWorking = 0; return 0; }
+ CurrServ = DBGetContactSettingWord(0, DBModule, "CurrServ", 0);
+
+ if(CurrServ >= SrvCount){
+ DBWriteContactSettingWord(0, DBModule, "CurrServ", 0);
+ icq_LogMessage(LOG_FATAL, "Server AutoChange: servers list end, exiting");
+ TryNextWorking = 0;
+ return 0;
+ }
+
+
+ CurrServ = CurrServ + 1;
+
+ DBWriteContactSettingWord(0, DBModule, "CurrServ", CurrServ);
+
+ mir_snprintf(buf1, 64, "server%luhost", CurrServ);
+ mir_snprintf(buf2, 64, "server%luport", CurrServ);
+ mir_snprintf(buf, 64, "server%luuse", CurrServ);
+
+ if(!DBGetContactSettingByte(0, DBModule, buf, 1)){
+ TryNextWorking = 0;
+ TryNextServer();
+ return 0;
+ }
+
+ Port = DBGetContactSettingWord(0, DBModule, buf2, DEFAULT_SERVER_PORT);
+
+
+ DBWriteContactSettingWord(0, gpszICQProtoName, "OscarPort", Port);
+ ICQWriteContactSettingString(NULL, "OscarServer", UniGetContactSettingUtf(NULL, DBModule, buf1, 0));
+
+ icq_LogMessage(LOG_NOTE, "Server AutoChange: connection problems with current server, switching to next");
+
+ IcqSetStatus((WPARAM)iIcqNewStatus, 0);
+
+ TryNextWorking = 0;
+
+ return 0;
+}
+
+void TryNextServer()
+{
+ if(TryNextWorking) return;
+
+ ICQCreateThread(icq_TryNextServerThread, NULL);
+}
+
+
+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);
+ // store server port
+ info.wServerPort = infoParam->nloc.wPort;
+
+ srand(time(NULL));
+
+ ResetSettingsOnConnect();
+
+ // Connect to the login server
+ NetLog_Server("Authenticating to server");
+ {
+ NETLIBOPENCONNECTION nloc = infoParam->nloc;
+
+ hServerConn = NetLib_OpenConnection(ghServerNetlibUser, NULL, &nloc);
+
+ SAFE_FREE((void**)&nloc.szHost);
+ }
+ SAFE_FREE(&infoParam);
+
+
+ // Login error
+ if (hServerConn == NULL)
+ {
+ DWORD dwError = GetLastError();
+
+ hServerConn = NULL;
+
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+
+ if(bServerAutoChange)
+ TryNextServer();
+ else
+ icq_LogUsingErrorCode(LOG_ERROR, dwError, "Unable to connect to ICQ login server");
+
+ return 0;
+ }
+
+
+ // Initialize direct connection ports
+ {
+ DWORD dwInternalIP;
+ BYTE bConstInternalIP = ICQGetContactSettingByte(NULL, "ConstRealIP", 0);
+
+ info.hDirectBoundPort = NetLib_BindPort(icq_newConnectionReceived, NULL, &wListenPort, &dwInternalIP);
+ if (!info.hDirectBoundPort)
+ {
+ 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;
+ if (!bConstInternalIP) ICQDeleteContactSetting(NULL, "RealIP");
+ }
+ else if (!bConstInternalIP)
+ ICQWriteContactSettingDword(NULL, "RealIP", 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};
+
+ info.hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 0x2400);
+ 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)info.hPacketRecver, (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_SafeCloseHandle(&info.hPacketRecver);
+
+ // Close DC port
+ NetLib_SafeCloseHandle(&info.hDirectBoundPort);
+ }
+
+ // signal keep-alive thread to stop
+ StopKeepAlive(&info);
+
+ // disable auto info-update thread
+ icq_EnableUserLookup(FALSE);
+
+ // Time to shutdown
+ icq_serverDisconnect(FALSE);
+ if (gnCurrentStatus != ID_STATUS_OFFLINE && icqGoingOnlineStatus != ID_STATUS_OFFLINE)
+ {
+ if (!info.bLoggedIn)
+ {
+ if(bServerAutoChange)
+ TryNextServer();
+ else
+ 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);
+
+ // Close avatar connection if any
+ StopAvatarThread();
+
+ // 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, 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
+ ratesRelease(&gRates);
+
+ 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_CloseConnection(&hServerConn, TRUE);
+ LeaveCriticalSection(&connectionHandleMutex);
+
+ // Not called from network thread?
+ if (bBlock && GetCurrentThreadId() != serverThreadId)
+ {
+ while (WaitForSingleObjectEx(serverThreadHandle, INFINITE, TRUE) != WAIT_OBJECT_0);
+ CloseHandle(serverThreadHandle);
+ }
+ else
+ CloseHandle(serverThreadHandle);
+ }
+ else
+ LeaveCriticalSection(&connectionHandleMutex);
+}
+
+
+
+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);
+ }
+
+ // Rates management
+ EnterCriticalSection(&ratesMutex);
+ ratesPacketSent(gRates, pPacket);
+ LeaveCriticalSection(&ratesMutex);
+
+ // 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);
+}
+
+
+
+typedef struct icq_packet_async_s
+{
+ icq_packet packet;
+
+} icq_packet_async;
+
+static DWORD __stdcall sendPacketAsyncThread(icq_packet_async* pArgs)
+{
+ sendServPacket(&pArgs->packet);
+
+ SAFE_FREE(&pArgs);
+ return 0;
+}
+
+
+void sendServPacketAsync(icq_packet *packet)
+{
+ icq_packet_async *pArgs;
+
+ pArgs = (icq_packet_async*)SAFE_MALLOC(sizeof(icq_packet_async)); // This will be freed in the new thread
+ memcpy(&pArgs->packet, packet, sizeof(icq_packet));
+
+ ICQCreateThread(sendPacketAsyncThread, pArgs);
+}
+
+
+
+int IsServerOverRate(WORD wFamily, WORD wCommand, int nLevel)
+{
+ WORD wGroup;
+ int result = FALSE;
+
+ EnterCriticalSection(&ratesMutex);
+ wGroup = ratesGroupFromSNAC(gRates, wFamily, wCommand);
+
+ // check if the rate is not over specified level
+ if (ratesNextRateLevel(gRates, wGroup) < ratesGetLimitLevel(gRates, wGroup, nLevel))
+ result = TRUE;
+
+ LeaveCriticalSection(&ratesMutex);
+
+ return result;
+}
+
+
+
+void icq_login(const char* szPassword)
+{
+ DBVARIANT dbvServer = {DBVT_DELETED};
+ char szServer[MAX_PATH];
+ serverthread_start_info* stsi;
+ DWORD dwUin;
+ //MessageBox(0, szPassword, 0, MB_OK);
+ if (bImageRequested){
+ icq_serverDisconnect(0);
+ icq_regNewUin = 0;
+ bImageRequested = 0;
+ EnableWindow(GetDlgItem(hwndRegImageDialog, IDC_REGISTER), FALSE);
+ }
+
+ dwUin = ICQGetContactSettingUIN(NULL);
+ stsi = (serverthread_start_info*)SAFE_MALLOC(sizeof(serverthread_start_info));
+
+ // 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;
+
+ serverThreadHandle = ICQCreateThreadEx(icq_serverThread, stsi, &serverThreadId);
+}
diff --git a/icqj_s7_sss_mod/icq_server.h b/icqj_s7_sss_mod/icq_server.h new file mode 100644 index 0000000..924f60b --- /dev/null +++ b/icqj_s7_sss_mod/icq_server.h @@ -0,0 +1,79 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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;
+ WORD wServerPort;
+ char *newServer;
+ BYTE* cookieData;
+ int cookieDataLen;
+ int newServerReady;
+ int isMigrating;
+ HANDLE hPacketRecver;
+ int bReinitRecver;
+ int bMyAvatarInited;
+ //
+ HANDLE hDirectBoundPort;
+ //
+ HANDLE hKeepAliveEvent;
+ HANDLE hKeepAliveThread;
+} serverthread_info;
+
+/*---------* Functions *---------------*/
+
+void icq_serverDisconnect(BOOL bBlock);
+void sendServPacket(icq_packet *);
+void sendServPacketAsync(icq_packet *);
+void icq_login(const char *szPassword);
+void TryNextServer();
+
+int IsServerOverRate(WORD wFamily, WORD wCommand, int nLevel);
+
+
+#endif /* __ICQ_SERVER_H */
diff --git a/icqj_s7_sss_mod/icq_servlist.c b/icqj_s7_sss_mod/icq_servlist.c new file mode 100644 index 0000000..e7ba6b1 --- /dev/null +++ b/icqj_s7_sss_mod/icq_servlist.c @@ -0,0 +1,1997 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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*)SAFE_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*)SAFE_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**)SAFE_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*)SAFE_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, "SrvPhotoID", 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;
+}
+
+void ResetUserSSISettings(HANDLE hContact)
+{
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "ServerId", 0);
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "SrvGroupId", 0);
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "SrvPermitId", 0);
+ DBWriteContactSettingWord(hContact, gpszICQProtoName, "SrvDenyId", 0);
+ DBWriteContactSettingByte(hContact, gpszICQProtoName, "Auth", 0);
+}
+
+
+void ResetAllSSISettings(void)
+{
+
+ HANDLE hContact;
+ int ID = 0;
+
+ while (GetFromCacheByID(ID++, &hContact, NULL))
+ {
+ ResetUserSSISettings(hContact);
+ }
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "SrvAvatarID", 0);
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "SrvVisibilityID", 0);
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "SrvDefGroupId", 0);
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "SrvRecordCount", 0);
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "SrvImportId", 0);
+ DBWriteContactSettingDword(NULL, gpszICQProtoName, "ImportTS", 0);
+
+ // reset only if we reload list
+ FlushServerIDs();
+
+}
+
+
+// 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);
+
+ // Force reload of server-list after change
+ ICQWriteContactSettingWord(NULL, "SrvRecordCount", 0);
+
+ 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;
+ int bDataTooLong = FALSE;
+
+ // 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 (!ICQGetContactSetting(hContact, "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);
+
+ // Limit the strings
+ if (nNickLen > MAX_SSI_TLV_NAME_SIZE)
+ {
+ bDataTooLong = TRUE;
+ nNickLen = null_strcut(szNick, MAX_SSI_TLV_NAME_SIZE);
+ }
+ if (nNoteLen > MAX_SSI_TLV_COMMENT_SIZE)
+ {
+ bDataTooLong = TRUE;
+ nNoteLen = null_strcut(szNote, MAX_SSI_TLV_COMMENT_SIZE);
+ }
+ if (bDataTooLong)
+ { // Inform the user
+ /// TODO: do something with this for Manage Server-List dialog.
+ if (wAction != ICQ_LISTS_REMOVEFROMLIST) // do not report this when removing from list
+ icq_LogMessage(LOG_WARNING, "The contact's information was too big and was truncated.");
+ }
+
+ // 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
+
+ SAFE_FREE(&szNick);
+ SAFE_FREE(&szNote);
+
+ 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, hContact, 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*)SAFE_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*)SAFE_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 = SAFE_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, ack->hContact, ack);
+
+ sendAddStart(0);
+ icq_sendServerContact(ack->hContact, dwCookie, ICQ_LISTS_ADDTOLIST, wGroupID, wItemID);
+ ICQWriteContactSettingByte(ack->hContact,"CheckSelfRemove", 0);//checkselfremove
+}
+
+
+
+// Called when contact should be added to server list, if group does not exist, create one
+DWORD addServContact(HANDLE hContact, 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, hContact, 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, ack->hContact, ack);
+ dwCookie2 = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, ack->hContact, 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, hContact, 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);
+ }
+}
+
+
+
+void resetServContactAuthState(HANDLE hContact, DWORD dwUin)
+{
+ WORD wContactId = ICQGetContactSettingWord(hContact, "ServerId", 0);
+ WORD wGroupId = ICQGetContactSettingWord(hContact, "SrvGroupId", 0);
+
+ if (wContactId && wGroupId)
+ {
+ 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_CONTACT_FIX_AUTH;
+ ack->dwUin = dwUin;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, 0, hContact, ack);
+
+ sendAddStart(0);
+ icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_REMOVEFROMLIST, wGroupId, wContactId);
+ ICQDeleteContactSetting(hContact, "ServerData");
+ icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_ADDTOLIST, wGroupId, wContactId);
+ sendAddEnd();
+ }
+ }
+}
+
+
+
+/*****************************************
+ *
+ * --- 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;
+
+ // 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))
+ { // Add to server-list
+ IcqAddServerContact(wParam, 0);
+ }
+
+ // 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)
+ { // contact was deleted only locally - retrieve full list on next connect
+ ICQWriteContactSettingWord((HANDLE)wParam, "SrvRecordCount", 0);
+ }
+
+ 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;
+
+ 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)
+ { // delete 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_s7_sss_mod/icq_servlist.h b/icqj_s7_sss_mod/icq_servlist.h new file mode 100644 index 0000000..af15cc7 --- /dev/null +++ b/icqj_s7_sss_mod/icq_servlist.h @@ -0,0 +1,131 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_CONTACT_FIX_AUTH 0x40 // reuploading contact for auth re-request
+#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 ResetAllSSISettings(void);
+void ResetUserSSISettings(HANDLE hContact);
+
+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);
+
+
+void resetServContactAuthState(HANDLE hContact, DWORD dwUin);
+
+// 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_s7_sss_mod/icq_srv_list.c b/icqj_s7_sss_mod/icq_srv_list.c new file mode 100644 index 0000000..138932a --- /dev/null +++ b/icqj_s7_sss_mod/icq_srv_list.c @@ -0,0 +1,236 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+//
+// DESCRIPTION:
+//
+// Server List GUI
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+static HWND hwndSrvList = NULL;
+HWND hCaller;
+static BOOL CALLBACK DlgProcSrvList(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam)
+{
+ char DBModule[64];
+ char buf[64];
+ char buf2[64];
+ char buf3[64];
+ WORD SrvCount;
+ int iIndex, i, iRow;
+ LVCOLUMN col;
+ LVITEM item;
+ HWND hwndList=GetDlgItem(hwndDlg, IDC_SERVERS);
+ NMLISTVIEW * hdr = (NMLISTVIEW *) lParam;
+ DBCONTACTGETSETTING dbgcs;
+ mir_snprintf(DBModule, 64, "%sSrvs", gpszICQProtoName);
+ SrvCount = DBGetContactSettingWord(NULL,DBModule,"SrvCount",0);
+ switch(message)
+ {
+ case WM_INITDIALOG:
+ {
+ ICQTranslateDialog(hwndDlg);
+ col.pszText = Translate("Use");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 50;
+ ListView_InsertColumn(hwndList, 1, &col);
+ col.pszText = Translate("Server");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 1000;
+ ListView_InsertColumn(hwndList, 1, &col);
+ col.pszText = Translate("Port");
+ col.cx = 1000;
+ ListView_InsertColumn(hwndList, 2, &col);
+ ListView_SetExtendedListViewStyleEx(hwndList, 0, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
+
+ if(!DBGetContactSettingWord(NULL,DBModule,"SrvCount",0))
+ DBWriteContactSettingWord(NULL,DBModule,"SrvCount",0);
+ for(i = 1; i <= SrvCount; i++)
+ {
+ mir_snprintf(buf2, 64, "server%luhost", i);
+ mir_snprintf(buf3, 64, "server%luport", i);
+ item.mask = LVIF_TEXT;
+ item.iItem = i;
+ item.iSubItem = 0;
+ item.pszText = buf2;
+ iRow = ListView_InsertItem(hwndList, &item);
+ ListView_SetItemText(hwndList, iRow, 0, NULL);
+ ListView_SetItemText(hwndList, iRow, 1, UniGetContactSettingUtf(NULL, DBModule, buf2, 0));
+ mir_snprintf(buf, 64, "%d", DBGetContactSettingWord(NULL, DBModule, buf3, 0));
+ ListView_SetItemText(hwndList, iRow, 2, buf);
+ mir_snprintf(buf, 64, "server%luuse", i);
+ if(DBGetContactSettingByte(0, DBModule, buf, 1))
+ ListView_SetItemState(hwndList, iRow, 0x2000, 0xF000);
+ }
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE);
+ }
+ return TRUE;
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+
+ case IDADD:
+ SrvCount = DBGetContactSettingWord(NULL, DBModule, "SrvCount", 0);
+ mir_snprintf(buf, 64, "server%luuse", SrvCount + 1);
+ DBWriteContactSettingWord(NULL, DBModule, buf, 1);
+ GetDlgItemText(hwndDlg, IDC_EDIT_SERVER, buf , 64);
+ if(buf[0]==0)
+ break;
+ mir_snprintf(buf2, 64, "server%luhost", SrvCount + 1);
+ DBWriteContactSettingString(NULL, DBModule, buf2, buf);
+ mir_snprintf(buf3, 64, "server%luport", SrvCount + 1);
+ if(GetDlgItemInt(hwndDlg, IDC_EDIT_PORT, NULL, FALSE)==0)
+ DBWriteContactSettingWord(NULL, DBModule, buf3, 5190);
+ else
+ DBWriteContactSettingWord(NULL, DBModule, buf3, (WORD)GetDlgItemInt(hwndDlg, IDC_EDIT_PORT, NULL, FALSE));
+
+ item.mask = LVIF_TEXT;
+ item.iItem = SrvCount + 1;
+ item.iSubItem = 0;
+ item.pszText = buf2;
+
+ iRow = ListView_InsertItem(hwndList, &item);
+ ListView_SetItemText(hwndList, iRow, 1, UniGetContactSettingUtf(NULL, DBModule, buf2, 0));
+ mir_snprintf(buf, 64, "%d", DBGetContactSettingWord(NULL, DBModule, buf3, 0));
+ ListView_SetItemText(hwndList, iRow, 2, buf);
+ ListView_SetItemText(hwndList, iRow, 0, NULL);
+ DBWriteContactSettingWord(NULL, DBModule, "SrvCount", (WORD)(SrvCount + 1));
+
+ mir_snprintf(buf, 64, "server%luuse", SrvCount + 1);
+ if(DBGetContactSettingByte(0, DBModule, buf, 1))
+ ListView_SetItemState(hwndList, iRow, 0x2000, 0xF000);
+ break;
+ case IDEDIT:
+ iIndex = ListView_GetSelectionMark(hwndList);
+ if(iIndex < 0) return FALSE;
+ mir_snprintf(buf, 64, "server%luhost", iIndex + 1);
+ mir_snprintf(buf2, 64, "server%luport", iIndex + 1);
+ DBWriteContactSettingWord(0, DBModule, buf2, (WORD)GetDlgItemInt(hwndDlg, IDC_EDIT_PORT, 0, 0));
+ GetDlgItemText(hwndDlg, IDC_EDIT_SERVER, buf3 , 64);
+ DBWriteContactSettingString(NULL, DBModule, buf, buf3);
+
+ ListView_SetItemText(hwndList, iIndex, 0, NULL);
+ ListView_SetItemText(hwndList, iIndex, 1, UniGetContactSettingUtf(NULL, DBModule, buf, 0));
+ mir_snprintf(buf, 64, "%d", DBGetContactSettingWord(NULL, DBModule, buf2, 0));
+ ListView_SetItemText(hwndList, iIndex, 2, buf);
+
+ break;
+ case IDDEL:
+ iIndex = ListView_GetSelectionMark(hwndList);
+ if(iIndex < 0) return FALSE;
+ ListView_DeleteItem(hwndList, iIndex);
+
+ dbgcs.szModule = DBModule;
+ mir_snprintf(buf, 64, "server%luhost", iIndex + 1);
+ dbgcs.szSetting = buf;
+ CallService(MS_DB_CONTACT_DELETESETTING, (WPARAM)NULL, (LPARAM)&dbgcs);
+ mir_snprintf(buf, 64, "server%luport", iIndex + 1);
+ dbgcs.szSetting = buf;
+ CallService(MS_DB_CONTACT_DELETESETTING, (WPARAM)NULL, (LPARAM)&dbgcs);
+ mir_snprintf(buf, 64, "server%luuse", iIndex + 1);
+ dbgcs.szSetting = buf;
+ CallService(MS_DB_CONTACT_DELETESETTING, (WPARAM)NULL, (LPARAM)&dbgcs);
+ SrvCount = DBGetContactSettingWord(0, DBModule, "SrvCount", 0);
+ for(i = iIndex + 2; i <= SrvCount; i++){
+ dbgcs.szModule = DBModule;
+
+ mir_snprintf(buf2, 64, "server%luuse", i);
+ mir_snprintf(buf3, 64, "server%luuse", i - 1);
+ DBWriteContactSettingByte(NULL, DBModule, buf3, (BYTE)DBGetContactSettingByte(0, DBModule, buf2, 1));
+ dbgcs.szSetting = buf2;
+ CallService(MS_DB_CONTACT_DELETESETTING, (WPARAM)0, (LPARAM)&dbgcs);
+
+ mir_snprintf(buf2, 64, "server%luhost", i);
+ mir_snprintf(buf3, 64, "server%luhost", i - 1);
+ DBWriteContactSettingString(NULL, DBModule, buf3, UniGetContactSettingUtf(NULL, DBModule, buf2, 0));
+ dbgcs.szSetting = buf2;
+ CallService(MS_DB_CONTACT_DELETESETTING, (WPARAM)0, (LPARAM)&dbgcs);
+
+ mir_snprintf(buf2, 64, "server%luport", i);
+ mir_snprintf(buf3, 64, "server%luport", i - 1);
+ DBWriteContactSettingWord(NULL, DBModule, buf3, (WORD)DBGetContactSettingWord(NULL,DBModule,buf2,0));
+ dbgcs.szSetting = buf2;
+ CallService(MS_DB_CONTACT_DELETESETTING, (WPARAM)0, (LPARAM)&dbgcs);
+ }
+ DBWriteContactSettingWord(NULL, DBModule, "SrvCount", (WORD)(SrvCount - 1));
+ break;
+ case IDCCLOSE:
+ SendMessage(hCaller, WM_INITDIALOG, 0, 0);
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ }
+ break;
+ case WM_NOTIFY:
+ if ( hdr && hdr->hdr.code == LVN_ITEMCHANGED && IsWindowVisible(hdr->hdr.hwndFrom)
+ && hdr->iItem != (-1) ) {
+ iIndex = hdr->iItem;
+ if(iIndex < 0) return FALSE;
+ mir_snprintf(buf, 64, "server%luhost", iIndex + 1);
+ mir_snprintf(buf2, 64, "server%luport", iIndex + 1);
+ SetDlgItemText(hwndDlg, IDC_EDIT_SERVER, UniGetContactSettingUtf(NULL, DBModule, buf, 0));
+ SetDlgItemInt(hwndDlg, IDC_EDIT_PORT, (UINT)DBGetContactSettingWord(0, DBModule, buf2, 5190), 0);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ hwndSrvList = NULL;
+ for (iRow = 0 ; iRow != (-1) ; ) {
+ int iState = ListView_GetItemState(hwndList, iRow, LVIS_STATEIMAGEMASK);
+ mir_snprintf(buf, 64, "server%luuse", iRow + 1);
+ DBWriteContactSettingByte(0, DBModule, buf, (BYTE)(iState&0x2000?1:0));
+ iRow = ListView_GetNextItem(hwndList, iRow, LVNI_ALL);
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+void ShowSrvListDialog(HWND hwndCaller)
+{
+ hCaller = hwndCaller;
+ if (hwndSrvList == NULL)
+ {
+ hwndSrvList = CreateDialogUtf(hInst, MAKEINTRESOURCE(IDD_ICQ_SRV_LIST), NULL, DlgProcSrvList);
+ }
+ SetForegroundWindow(hwndSrvList);
+}
diff --git a/icqj_s7_sss_mod/icq_tzers.c b/icqj_s7_sss_mod/icq_tzers.c new file mode 100644 index 0000000..222d2d0 --- /dev/null +++ b/icqj_s7_sss_mod/icq_tzers.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,2007 Joe Kucera, LubomirR
+//
+// 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$
+// Last change on : $Date$
+// Last change by : $Author$
+//
+// DESCRIPTION:
+//
+// tZers
+//
+// -----------------------------------------------------------------------------
+
+
+#include "icqoscar.h"
+
+CALLBACK tZersWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ int DialogWidth = 0;
+ int DialogHeight = 0;
+ int x = GetSystemMetrics(SM_CXSCREEN);
+ int y = GetSystemMetrics(SM_CYSCREEN);
+ int newleft = 0;
+ int newtop = 0;
+ int curSel;
+ int len;
+ char * txt;
+ char * txt2;
+ char * tzid;
+ char * tzurl;
+ RECT rect;
+
+ static HANDLE hContact;
+ static DWORD dwUin;
+
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ ICQTranslateDialog(hWnd);
+ hContact = (HANDLE)lParam;
+ if (!hContact) {
+ EndDialog(hWnd, 0);
+ return FALSE;
+ }
+
+ if (!(dwUin = ICQGetContactSettingUIN(hContact))) {
+ EndDialog(hWnd, 0);
+ return FALSE;
+ }
+
+ GetWindowRect(hWnd, &rect);
+ DialogWidth = rect.right - rect.left;
+ DialogHeight = rect.bottom - rect.top;
+
+ newleft = ((x + 1) - DialogWidth) / 2;
+ newtop = ((y + 1) - DialogHeight) / 2;
+
+ MoveWindow(hWnd, newleft, newtop, DialogWidth, DialogHeight, TRUE);
+
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("Gangsta"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("Can't Hear U"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("Scratch"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("Booooo"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("Kisses"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("Chill Out!"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("Akitaka"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("I'm Sorry"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("Hilaaarious"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("Like Duh!"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("L8R"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_ADDSTRING, 0, (LPARAM)("Like U!"));
+ SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_SETCURSEL, 0, 0);
+
+ SendDlgItemMessage(hWnd, IDC_TZER_NAME, WM_SETTEXT, 0, (LPARAM)"Gangsta");
+
+ ShowWindow(hWnd, SW_SHOW);
+ break;
+ case WM_COMMAND:
+ if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_TZER_COMBO) {
+ curSel = SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_GETCURSEL, 0, 0);
+ switch(curSel) {
+ case 0:
+ txt = "Gangsta";
+ break;
+ case 1:
+ txt = "Can't Hear U";
+ break;
+ case 2:
+ txt = "Scratch";
+ break;
+ case 3:
+ txt = "Booooo";
+ break;
+ case 4:
+ txt = "Kisses";
+ break;
+ case 5:
+ txt = "Chill Out!";
+ break;
+ case 6:
+ txt = "Akitaka";
+ break;
+ case 7:
+ txt = "I'm Sorry";
+ break;
+ case 8:
+ txt = "Hilaaarious";
+ break;
+ case 9:
+ txt = "Like Duh!";
+ break;
+ case 10:
+ txt = "L8R";
+ break;
+ case 11:
+ txt = "Like U!";
+ break;
+ }
+ SendDlgItemMessage(hWnd, IDC_TZER_NAME, WM_SETTEXT, 0, (LPARAM)txt);
+ }
+
+ if (LOWORD(wParam) == IDOK) {
+ curSel = SendDlgItemMessage(hWnd, IDC_TZER_COMBO, CB_GETCURSEL, 0, 0);
+ len = SendDlgItemMessage(hWnd, IDC_TZER_NAME, WM_GETTEXTLENGTH, 0, 0);
+ txt = malloc(len + 1);
+ if (txt) {
+ SendDlgItemMessage(hWnd, IDC_TZER_NAME, WM_GETTEXT, (WPARAM)(len + 1), (LPARAM)txt);
+ switch(curSel) {
+ case 0:
+ tzid = "gangSh";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/gangsterSheep.swf";
+ break;
+ case 1:
+ tzid = "cantH";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/cant_hear.swf";
+ break;
+ case 2:
+ tzid = "scratch";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/scratch.swf";
+ break;
+ case 3:
+ tzid = "boo";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/boo.swf";
+ break;
+ case 4:
+ tzid = "kisses";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/kisses.swf";
+ break;
+ case 5:
+ tzid = "rasta";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/rastamab.swf";
+ break;
+ case 6:
+ tzid = "arakiri";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/sappuko.swf";
+ break;
+ case 7:
+ tzid = "sorry";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/sorry.swf";
+ break;
+ case 8:
+ tzid = "laugh";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/laugh.swf";
+ break;
+ case 9:
+ tzid = "da";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/dahh.swf";
+ break;
+ case 10:
+ tzid = "beback";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/beBack.swf";
+ break;
+ case 11:
+ tzid = "ilikeu";
+ tzurl = "http://c.icq.com/xtraz/products/teaser/anims/common/iLikeU.swf";
+ break;
+ }
+ txt2 = MangleXml(txt, len);
+ free(txt);
+ SendtZer(hContact, dwUin, "ID", txt2, tzurl);
+ free(txt2);
+ EndDialog(hWnd, 0);
+ }
+ }
+
+ if (LOWORD(wParam) == IDCANCEL) {
+ EndDialog(hWnd, 0);
+ }
+ }
+ return FALSE;
+}
diff --git a/icqj_s7_sss_mod/icq_tzers.h b/icqj_s7_sss_mod/icq_tzers.h new file mode 100644 index 0000000..e00dae5 --- /dev/null +++ b/icqj_s7_sss_mod/icq_tzers.h @@ -0,0 +1,2 @@ +
+CALLBACK tZersWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
diff --git a/icqj_s7_sss_mod/icq_uploadui.c b/icqj_s7_sss_mod/icq_uploadui.c new file mode 100644 index 0000000..081df9e --- /dev/null +++ b/icqj_s7_sss_mod/icq_uploadui.c @@ -0,0 +1,1084 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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;
+
+// Init default clist options
+static void ResetCListOptions(HWND hwndList)
+{
+ int i;
+
+ SendMessage(hwndList, CLM_SETBKBITMAP, 0, (LPARAM)(HBITMAP)NULL);
+ SendMessage(hwndList, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0);
+ SendMessage(hwndList, CLM_SETGREYOUTFLAGS, 0, 0);
+ SendMessage(hwndList, CLM_SETLEFTMARGIN, 2, 0);
+ SendMessage(hwndList, CLM_SETINDENT, 10, 0);
+ for(i=0; i<=FONTID_MAX; i++)
+ SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+ SetWindowLong(hwndList, GWL_STYLE, GetWindowLong(hwndList, GWL_STYLE)|CLS_SHOWHIDDEN);
+ if (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_HIDEEMPTYGROUPS) // hide empty groups
+ SendMessage(hwndList, CLM_SETHIDEEMPTYGROUPS, (WPARAM) TRUE, 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, size_t cbBuf)
+{
+ if (gbUnicodeAPI)
+ {
+ WCHAR str[MAX_PATH];
+
+ SendDlgItemMessageW(hwndDlg, IDC_LOG, LB_GETTEXT, SendDlgItemMessage(hwndDlg, IDC_LOG, LB_GETCOUNT, 0, 0)-1, (LPARAM)str);
+ make_utf8_string_static(str, szBuf, cbBuf);
+ }
+ 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*)SAFE_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, hContact, 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;
+
+ ResetCListOptions(GetDlgItem(hwndDlg, IDC_CLIST));
+
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Select contacts you want to store on server.", str, MAX_PATH));
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Ready...", str, MAX_PATH));
+ }
+ 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, MAX_PATH);
+ DeleteLastUploadLogLine(hwndDlg);
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Server rate warning -> slowing down the process.", str, MAX_PATH));
+ 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 = SAFE_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, MAX_PATH);
+ DeleteLastUploadLogLine(hwndDlg);
+ AppendToUploadLog(hwndDlg, "%s%s", szLastLogLine,
+ ICQTranslateUtfStatic(getServerResultDesc(ack->lParam), str, MAX_PATH));
+
+ 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, MAX_PATH), 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, MAX_PATH), pszNick);
+ else
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Uploading %s...", str, MAX_PATH), 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[MAX_PATH];
+ // Update the log window with the failure and continue with next contact
+ GetLastUploadLogLine(hwndDlg, szLastLogLine, MAX_PATH);
+ DeleteLastUploadLogLine(hwndDlg);
+ AppendToUploadLog(hwndDlg, "%s%s", szLastLogLine, ICQTranslateUtfStatic("FAILED", str, MAX_PATH));
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("No upload group available", str, MAX_PATH));
+ NetLog_Server("Upload failed, no group");
+ currentState = STATE_READY;
+ }
+ }
+ else
+ { // Queue for deletion
+ if (pszNick)
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Deleting %s...", str, MAX_PATH), pszNick);
+ else
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Deleting %s...", str, MAX_PATH), 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, MAX_PATH), 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, MAX_PATH), pszNick, pszGroup);
+ else
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("Moving %s to group \"%s\"...", str, MAX_PATH), 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, MAX_PATH), 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, MAX_PATH), 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, MAX_PATH), 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, MAX_PATH), 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, MAX_PATH));
+ 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, MAX_PATH), 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, MAX_PATH), 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, MAX_PATH), 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, MAX_PATH));
+ EnableDlgItem(hwndDlg, IDCANCEL, TRUE);
+ SetDlgItemTextUtf(hwndDlg, IDCANCEL, ICQTranslateUtfStatic("Close", str, MAX_PATH));
+ 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 (!icqOnline)
+ {
+ char str[MAX_PATH];
+
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic("You have to be online to sychronize the server-list !", str, MAX_PATH));
+ break;
+ }
+ working = 1;
+ hCurrentContact = NULL;
+ currentState = STATE_REGROUP;
+ currentAction = ACTION_NONE;
+ icq_ShowMultipleControls(hwndDlg, settingsControls, SIZEOF(settingsControls), 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:
+ {
+ ResetCListOptions(hClist);
+ }
+ 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_s7_sss_mod/icq_uploadui.h b/icqj_s7_sss_mod/icq_uploadui.h new file mode 100644 index 0000000..7404453 --- /dev/null +++ b/icqj_s7_sss_mod/icq_uploadui.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
+// Copyright 2004,2005,2006,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+void ShowUploadContactsDialog(void);
diff --git a/icqj_s7_sss_mod/icq_xstatus.c b/icqj_s7_sss_mod/icq_xstatus.c new file mode 100644 index 0000000..d24ebeb --- /dev/null +++ b/icqj_s7_sss_mod/icq_xstatus.c @@ -0,0 +1,1298 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 64 $
+// Last change on : $Date: 2007-10-16 17:39:11 +0300 (Вт, 16 окт 2007) $
+// Last change by : $Author: chaos.persei $
+//
+// DESCRIPTION:
+//
+// Support for Custom Statuses
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_cluiframes.h"
+
+extern void setUserInfo();
+
+extern BOOL bXstatusIconShow;
+
+extern HANDLE hxstatusiconchanged;
+extern HANDLE hxstatuschanged;
+
+int bHideXStatusUI = 0;
+static int bStatusMenu = 0;
+static HANDLE hHookExtraIconsRebuild = NULL;
+static HANDLE hHookStatusBuild = NULL;
+static HANDLE hHookExtraIconsApply = NULL;
+static HANDLE hXStatusIcons[37];
+static HANDLE hXStatusItems[38];
+static HANDLE hXStatusIconsHandle[37];
+static int hXStatusCListIcons[37]; //
+static BOOL bXStatusCListIconsValid[37]; //need to be changed dinamicly
+
+
+void CListShowMenuItem(HANDLE hMenuItem, BYTE bShow);
+DWORD dwLastXUpdateTime;
+
+BYTE fXstatusIcons()
+{
+ if(ICQGetContactSettingByte(NULL, "NonStandartXstatus", 1))
+ return 37;
+ else
+ return 32;
+}
+
+BYTE fXstatusItems()
+{
+ if(ICQGetContactSettingByte(NULL, "NonStandartXstatus", 1))
+ return 38;
+ else
+ return 33;
+}
+
+#define XstatusIcons fXstatusIcons()
+#define XstatusItems fXstatusItems()
+
+
+BYTE __stdcall ICQGetContactXStatus(HANDLE hContact)
+{
+ BYTE bXStatus = ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, 0);
+
+ if (!gbXStatusEnabled || bXStatus < 1 || bXStatus > XstatusIcons) return 0;
+
+ return bXStatus;
+}
+
+
+DWORD sendXStatusDetailsRequest(HANDLE hContact, int bForced)
+{
+ if (invis_for(0,hContact))
+ {
+ return 0;
+ }
+ {
+ DWORD dwCookie = 0;
+ if (ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, -1) != -1)
+ { // only request custom status detail when the contact has one
+ char *szNotify;
+ int nNotifyLen;
+ 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.nRequestType = 0x101; // request
+ rr.nMinDelay = 1000; // delay at least 1s
+ EnterCriticalSection(&ratesMutex);
+ rr.wGroup = ratesGroupFromSNAC(gRates, ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND);
+ LeaveCriticalSection(&ratesMutex);
+
+ if (!handleRateItem(&rr, bAllowDelay))
+ return sendXStatusDetailsRequest(hContact, !bAllowDelay);
+
+ return -1; // delayed
+}
+
+void UpdateXStatuses()
+{
+ HANDLE hContact;
+ extern BOOL bXUpdaterPopUp;
+
+ if(!icqOnline)
+ return;
+ if(!gbXStatusEnabled)
+ return;
+
+ hContact = ICQFindFirstContact();
+ if(hContact){
+ do{
+ if (ICQGetContactStatus(hContact) != ID_STATUS_OFFLINE && (CheckContactCapabilities(hContact, CAPF_XTRAZ) && !invis_for(ICQGetContactSettingDword(hContact, "UIN",0),hContact) && ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, 0) != 0))
+ requestXStatusDetails(hContact, 1);
+ }while(hContact = ICQFindNextContact(hContact));
+ }
+ if(bXUpdaterPopUp)
+ {
+ static char title[32];
+ strcpy(title, gpszICQProtoName);
+ strcat(title, " XStatus Updater");
+ ShowPopUpMsg(0,0,title, "Requests sent to all contacts", LOG_NOTE);
+ }
+}
+
+DWORD __stdcall icq_XStatusUpdaterThread(LPVOID lp)
+{
+ dwLastXUpdateTime = 0;
+ while(1){
+ Sleep(60000);
+ if(time(NULL) - dwLastXUpdateTime < DBGetContactSettingDword(0, gpszICQProtoName, "XStatusUpdatePeriod", 5) * 60)
+ continue;
+ if(!DBGetContactSettingByte(NULL, gpszICQProtoName, "UpdateXStatus", 1))
+ continue;
+
+ UpdateXStatuses();
+ dwLastXUpdateTime = time(NULL);
+ }
+ return 0;
+}
+
+static HANDLE LoadXStatusIconLibrary(char* path, const char* sub)
+{
+ char* p = strrchr(path, '\\');
+ HANDLE hLib;
+
+ strcpy(p, sub);
+ strcat(p, "\\xStatus_icons.dll");
+ if (hLib = LoadLibrary(path)) return hLib;
+ strcpy(p, sub);
+ strcat(p, "\\xStatus_ICQ.dll");
+ if (hLib = LoadLibrary(path)) return hLib;
+ strcpy(p, "\\");
+ return hLib;
+}
+
+
+
+static char* InitXStatusIconLibrary(char* buf)
+{
+ char path[2*MAX_PATH];
+ HMODULE hXStatusIconsDLL;
+
+ // get miranda's exe path
+ GetModuleFileNameA(NULL, path, MAX_PATH);
+
+ hXStatusIconsDLL = LoadXStatusIconLibrary(path, "\\Icons");
+ if (!hXStatusIconsDLL) // TODO: add "Custom Folders" support
+ hXStatusIconsDLL = LoadXStatusIconLibrary(path, "\\Plugins");
+
+ if (hXStatusIconsDLL)
+ strcpy(buf, path);
+/* {
+ strcpy(buf, path);
+
+ if (LoadStringA(hXStatusIconsDLL, IDS_IDENTIFY, path, sizeof(path)) == 0 || strcmpnull(path, "# Custom Status Icons #"))
+ { // library is invalid
+ *buf = '\0';
+ }
+ FreeLibrary(hXStatusIconsDLL);
+ }
+ else
+ *buf = '\0';
+*/
+
+ return buf;
+}
+
+
+
+HICON GetXStatusIcon(int bStatus, UINT flags)
+{
+ char szTemp[64];
+ HICON icon;
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", bStatus - 1);
+ icon = IconLibGetIcon(szTemp);
+
+ if (flags & LR_SHARED)
+ return icon;
+ else
+ return CopyIcon(icon);
+}
+
+
+
+static void setContactExtraIcon(HANDLE hContact, HANDLE hIcon)
+{
+ WORD icon_pos = ICQGetContactSettingWord(NULL, "xstatus_icon_pos", 9);
+ if(icon_pos<=0||icon_pos>9)
+ {
+ icon_pos=9;
+ }
+ if (bXstatusIconShow)
+ {
+ IconExtraColumn iec;
+ iec.cbSize = sizeof(iec);
+ iec.hImage = hIcon;
+ iec.ColumnType = icon_pos;
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)&iec);
+ NotifyEventHooks(hxstatusiconchanged, (WPARAM)hContact, (LPARAM)hIcon);
+ }
+}
+
+
+
+static int CListMW_ExtraIconsRebuild(WPARAM wParam, LPARAM lParam)
+{
+ BYTE i;
+
+ if (gbXStatusEnabled && ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+ for (i = 0; i < XstatusIcons; i++)
+ {
+ hXStatusIcons[i] = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)GetXStatusIcon(i + 1, LR_SHARED), 0);
+ }
+ }
+
+ 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 = ICQGetContactXStatus((HANDLE)wParam);
+
+ if (bXStatus)
+ {
+ 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[37] = {
+ {0x01, 0xD8, 0xD7, 0xEE, 0xAC, 0x3B, 0x49, 0x2A, 0xA5, 0x8D, 0xD3, 0xD8, 0x77, 0xE6, 0x6B, 0x92},// XStatus(Angry)
+ {0x5A, 0x58, 0x1E, 0xA1, 0xE5, 0x80, 0x43, 0x0C, 0xA0, 0x6F, 0x61, 0x22, 0x98, 0xB7, 0xE4, 0xC7},// XStatus(Duck)
+ {0x83, 0xC9, 0xB7, 0x8E, 0x77, 0xE7, 0x43, 0x78, 0xB2, 0xC5, 0xFB, 0x6C, 0xFC, 0xC3, 0x5B, 0xEC},// XStatus(Tired)
+ {0xE6, 0x01, 0xE4, 0x1C, 0x33, 0x73, 0x4B, 0xD1, 0xBC, 0x06, 0x81, 0x1D, 0x6C, 0x32, 0x3D, 0x81},// XStatus(Party)
+ {0x8C, 0x50, 0xDB, 0xAE, 0x81, 0xED, 0x47, 0x86, 0xAC, 0xCA, 0x16, 0xCC, 0x32, 0x13, 0xC7, 0xB7},// XStatus(Beer)
+ {0x3F, 0xB0, 0xBD, 0x36, 0xAF, 0x3B, 0x4A, 0x60, 0x9E, 0xEF, 0xCF, 0x19, 0x0F, 0x6A, 0x5A, 0x7F},// XStatus(Thinking)
+ {0xF8, 0xE8, 0xD7, 0xB2, 0x82, 0xC4, 0x41, 0x42, 0x90, 0xF8, 0x10, 0xC6, 0xCE, 0x0A, 0x89, 0xA6},// XStatus(Eating)
+ {0x80, 0x53, 0x7D, 0xE2, 0xA4, 0x67, 0x4A, 0x76, 0xB3, 0x54, 0x6D, 0xFD, 0x07, 0x5F, 0x5E, 0xC6},// XStatus(TV)
+ {0xF1, 0x8A, 0xB5, 0x2E, 0xDC, 0x57, 0x49, 0x1D, 0x99, 0xDC, 0x64, 0x44, 0x50, 0x24, 0x57, 0xAF},// XStatus(Friends)
+ {0x1B, 0x78, 0xAE, 0x31, 0xFA, 0x0B, 0x4D, 0x38, 0x93, 0xD1, 0x99, 0x7E, 0xEE, 0xAF, 0xB2, 0x18},// XStatus(Coffee)
+ {0x61, 0xBE, 0xE0, 0xDD, 0x8B, 0xDD, 0x47, 0x5D, 0x8D, 0xEE, 0x5F, 0x4B, 0xAA, 0xCF, 0x19, 0xA7},// XStatus(Music)
+ {0x48, 0x8E, 0x14, 0x89, 0x8A, 0xCA, 0x4A, 0x08, 0x82, 0xAA, 0x77, 0xCE, 0x7A, 0x16, 0x52, 0x08},// XStatus(Business)
+ {0x10, 0x7A, 0x9A, 0x18, 0x12, 0x32, 0x4D, 0xA4, 0xB6, 0xCD, 0x08, 0x79, 0xDB, 0x78, 0x0F, 0x09},// XStatus(Camera)
+ {0x6F, 0x49, 0x30, 0x98, 0x4F, 0x7C, 0x4A, 0xFF, 0xA2, 0x76, 0x34, 0xA0, 0x3B, 0xCE, 0xAE, 0xA7},// XStatus(Funny)
+ {0x12, 0x92, 0xE5, 0x50, 0x1B, 0x64, 0x4F, 0x66, 0xB2, 0x06, 0xB2, 0x9A, 0xF3, 0x78, 0xE4, 0x8D},// XStatus(Phone)
+ {0xD4, 0xA6, 0x11, 0xD0, 0x8F, 0x01, 0x4E, 0xC0, 0x92, 0x23, 0xC5, 0xB6, 0xBE, 0xC6, 0xCC, 0xF0},// XStatus(Games)
+ {0x60, 0x9D, 0x52, 0xF8, 0xA2, 0x9A, 0x49, 0xA6, 0xB2, 0xA0, 0x25, 0x24, 0xC5, 0xE9, 0xD2, 0x60},// XStatus(College)
+ {0x63, 0x62, 0x73, 0x37, 0xA0, 0x3F, 0x49, 0xFF, 0x80, 0xE5, 0xF7, 0x09, 0xCD, 0xE0, 0xA4, 0xEE},// XStatus(Shopping)
+ {0x1F, 0x7A, 0x40, 0x71, 0xBF, 0x3B, 0x4E, 0x60, 0xBC, 0x32, 0x4C, 0x57, 0x87, 0xB0, 0x4C, 0xF1},// XStatus(Sick)
+ {0x78, 0x5E, 0x8C, 0x48, 0x40, 0xD3, 0x4C, 0x65, 0x88, 0x6F, 0x04, 0xCF, 0x3F, 0x3F, 0x43, 0xDF},// XStatus(Sleeping)
+ {0xA6, 0xED, 0x55, 0x7E, 0x6B, 0xF7, 0x44, 0xD4, 0xA5, 0xD4, 0xD2, 0xE7, 0xD9, 0x5C, 0xE8, 0x1F},// XStatus(Surfing)
+ {0x12, 0xD0, 0x7E, 0x3E, 0xF8, 0x85, 0x48, 0x9E, 0x8E, 0x97, 0xA7, 0x2A, 0x65, 0x51, 0xE5, 0x8D},// XStatus(@)
+ {0xBA, 0x74, 0xDB, 0x3E, 0x9E, 0x24, 0x43, 0x4B, 0x87, 0xB6, 0x2F, 0x6B, 0x8D, 0xFE, 0xE5, 0x0F},// XStatus(Engineering)
+ {0x63, 0x4F, 0x6B, 0xD8, 0xAD, 0xD2, 0x4A, 0xA1, 0xAA, 0xB9, 0x11, 0x5B, 0xC2, 0x6D, 0x05, 0xA1},// XStatus(Typing)
+ //Netvigator (China)
+ {0x2C, 0xE0, 0xE4, 0xE5, 0x7C, 0x64, 0x43, 0x70, 0x9C, 0x3A, 0x7A, 0x1C, 0xE8, 0x78, 0xA7, 0xDC},// XStatus(China1)
+ {0x10, 0x11, 0x17, 0xC9, 0xA3, 0xB0, 0x40, 0xF9, 0x81, 0xAC, 0x49, 0xE1, 0x59, 0xFB, 0xD5, 0xD4},// XStatus(China2)
+ {0x16, 0x0C, 0x60, 0xBB, 0xDD, 0x44, 0x43, 0xF3, 0x91, 0x40, 0x05, 0x0F, 0x00, 0xE6, 0xC0, 0x09},// XStatus(China3)
+ {0x64, 0x43, 0xC6, 0xAF, 0x22, 0x60, 0x45, 0x17, 0xB5, 0x8C, 0xD7, 0xDF, 0x8E, 0x29, 0x03, 0x52},// XStatus(China4)
+ {0x16, 0xF5, 0xB7, 0x6F, 0xA9, 0xD2, 0x40, 0x35, 0x8C, 0xC5, 0xC0, 0x84, 0x70, 0x3C, 0x98, 0xFA},// XStatus(China5)
+ //ProSieben (De)
+ {0x63, 0x14, 0x36, 0xff, 0x3f, 0x8a, 0x40, 0xd0, 0xa5, 0xcb, 0x7b, 0x66, 0xe0, 0x51, 0xb3, 0x64},// XStatus(De1)
+ {0xb7, 0x08, 0x67, 0xf5, 0x38, 0x25, 0x43, 0x27, 0xa1, 0xff, 0xcf, 0x4c, 0xc1, 0x93, 0x97, 0x97},// XStatus(De2)
+ {0xdd, 0xcf, 0x0e, 0xa9, 0x71, 0x95, 0x40, 0x48, 0xa9, 0xc6, 0x41, 0x32, 0x06, 0xd6, 0xf2, 0x80},// XStatus(De3)
+ //Rambler (Ru) // by BeteTest
+ {0xD4, 0xE2, 0xB0, 0xBA, 0x33, 0x4E, 0x4F, 0xA5, 0x98, 0xD0, 0x11, 0x7D, 0xBF, 0x4D, 0x3C, 0xC8},// XStatus(Ru1)
+ {0xCD, 0x56, 0x43, 0xA2, 0xC9, 0x4C, 0x47, 0x24, 0xB5, 0x2C, 0xDC, 0x01, 0x24, 0xA1, 0xD0, 0xCD},// XStatus(Ru2)
+ {0x00, 0x72, 0xD9, 0x08, 0x4A, 0xD1, 0x43, 0xDD, 0x91, 0x99, 0x6F, 0x02, 0x69, 0x66, 0x02, 0x6F},// XStatus(Ru3)
+ //RnQ
+ {0xe6, 0x01, 0xe4, 0x1c, 0x33, 0x73, 0x4b, 0xd1, 0xbc, 0x06, 0x81, 0x1d, 0x6c, 0x32, 0x3d, 0x82},// XStatus(Smoking)
+ {0xd6, 0x68, 0x7f, 0x4f, 0x3d, 0xc3, 0x4b, 0xdb, 0x8a, 0x8c, 0x4c, 0x1a, 0x57, 0x27, 0x63, 0xcd}};//XStatus(Sex)
+
+const char* nameXStatus[37] = {
+ LPGEN("Angry"), // 23
+ LPGEN("Taking a bath"), // 1
+ LPGEN("Tired"), // 2
+ LPGEN("Party"), // 3
+ LPGEN("Drinking beer"), // 4
+ LPGEN("Thinking"), // 5
+ LPGEN("Eating"), // 6
+ LPGEN("Watching TV"), // 7
+ LPGEN("Meeting"), // 8
+ LPGEN("Coffee"), // 9
+ LPGEN("Listening to music"),// 10
+ LPGEN("Business"), // 11
+ LPGEN("Shooting"), // 12
+ LPGEN("Having fun"), // 13
+ LPGEN("On the phone"), // 14
+ LPGEN("Gaming"), // 15
+ LPGEN("Studying"), // 16
+ LPGEN("Shopping"), // 0
+ LPGEN("Feeling sick"), // 17
+ LPGEN("Sleeping"), // 18
+ LPGEN("Surfing"), // 19
+ LPGEN("Browsing"), // 20
+ LPGEN("Working"), // 21
+ LPGEN("Typing"), // 22
+ //Netvigator (China)
+ LPGEN("Picnic"),
+ LPGEN("Cooking"),
+ LPGEN("Mobile"),
+ LPGEN("I'm high"),
+ LPGEN("On WC"),
+ //ProSieben (De)
+ LPGEN("To be or not to be"),
+ LPGEN("Watching pro7 on TV"),
+ LPGEN("Love"),
+ //Rambler (Ru)
+ LPGEN("Searching"),
+ LPGEN("Love"),
+ LPGEN("Journal"),
+ //RnQ
+ LPGEN("Sex"),
+ LPGEN("Smoking")};
+const int moodXStatus[37] = {
+ 23,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 0,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1};
+
+
+void handleXStatusCaps(HANDLE hContact, char* caps, int capsize, char* moods, int moodsize)
+{
+ int bChanged = FALSE;
+ HANDLE hIcon = (HANDLE)-1;
+
+ if (!gbXStatusEnabled)
+ return;
+
+ if (caps)
+ { // detect custom status capabilities
+ BYTE i;
+
+ for (i = 0; i<XstatusIcons; i++)
+ {
+ if (MatchCap(caps, capsize, (const capstr*)capXStatus[i], 0x10))
+ {
+ BYTE bXStatusId = (BYTE)(i+1);
+ char str[MAX_PATH];
+
+ if (ICQGetContactXStatus(hContact) != bXStatusId)
+ { // only write default name when it is really needed, i.e. on Custom Status change
+ ICQWriteContactSettingByte(hContact, DBSETTING_XSTATUSID, bXStatusId);
+ ICQWriteContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, ICQTranslateUtfStatic(nameXStatus[i], str, MAX_PATH));
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSMSG);
+
+ bChanged = TRUE;
+ }
+
+ if (ICQGetContactSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO))
+ requestXStatusDetails(hContact, TRUE);
+
+ hIcon = hXStatusIcons[i];
+
+ break;
+ }
+ }
+ }
+ if (hIcon == (HANDLE)-1 && moods && moodsize < 32)
+ { // process custom statuses (moods) from ICQ6
+ int i;
+
+ for (i = 0; i < XstatusIcons; i++)
+ {
+ char szMoodId[32], szMoodData[32];
+
+ strncpy(szMoodData, moods, moodsize);
+ szMoodData[moodsize] = '\0';
+
+ if (moodXStatus[i] == -1) continue;
+ null_snprintf(szMoodId, 32, "icqmood%d", moodXStatus[i]);
+ if (!strcmpnull(szMoodId, szMoodData))
+ {
+ BYTE bXStatusId = (BYTE)(i+1);
+ char str[MAX_PATH];
+
+ if (ICQGetContactXStatus(hContact) != bXStatusId)
+ { // only write default name when it is really needed, i.e. on Custom Status change
+ ICQWriteContactSettingByte(hContact, DBSETTING_XSTATUSID, bXStatusId);
+ ICQWriteContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, ICQTranslateUtfStatic(nameXStatus[i], str, MAX_PATH));
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSMSG);
+
+ bChanged = TRUE;
+ }
+ // cannot retrieve mood details here - need to be processed with new user details
+ hIcon = hXStatusIcons[i];
+
+ break;
+ }
+ }
+ }
+ if (hIcon == (HANDLE)-1)
+ {
+ if (ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, -1) != -1)
+ bChanged = TRUE;
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSID);
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSNAME);
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSMSG);
+ }
+
+ if (gbXStatusEnabled != 10)
+ {
+ setContactExtraIcon(hContact, hIcon);
+
+ if (bChanged)
+ NotifyEventHooks(hxstatuschanged, (WPARAM)hContact, 0);
+ }
+}
+
+
+static void updateServerCustomStatus()
+{
+ setUserInfo();
+
+ icq_setstatus(MirandaStatusToIcq(gnCurrentStatus), TRUE);
+ // Tell whos on our invisible/visible list
+ icq_sendEntireVisInvisList(gnCurrentStatus == ID_STATUS_INVISIBLE ? 0 : 1);
+}
+
+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;
+ char *szXStatusName;
+ char *szXStatusMsg;
+ 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, MAX_PATH));
+ 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
+ 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);
+
+ SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, init->szXStatusName);
+ SetDlgItemTextUtf(hwndDlg, IDC_XMSG, init->szXStatusMsg);
+
+ dat->countdown=5;
+ SendMessage(hwndDlg, WM_TIMER, 0, 0);
+ SetTimer(hwndDlg,1,1000,0);
+ }
+ else
+ { // retrieve contact's xStatus
+ dat->hContact = init->hContact;
+ dat->bXStatus = ICQGetContactXStatus(dat->hContact);
+ 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, MAX_PATH));
+ 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, MAX_PATH));
+ 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)
+ {
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)GetXStatusIcon(dat->bXStatus, LR_SHARED));
+ }
+
+ {
+ char *format;
+ char buf[MAX_PATH];
+
+ format = GetWindowTextUtf(hwndDlg);
+ null_snprintf(str, sizeof(str), format, dat->bXStatus?ICQTranslateUtfStatic(nameXStatus[dat->bXStatus-1], buf, MAX_PATH):"");
+ 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, MAX_PATH));
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ if (!dat->bAction)
+ { // set our xStatus
+ char szSetting[64];
+ char* szValue;
+ char *ansi = NULL;
+ CLISTMENUITEM mi = {0};
+
+ ICQWriteContactSettingByte(NULL, DBSETTING_XSTATUSID, dat->bXStatus);
+ 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) && DBGetContactSettingByte(NULL, gpszICQProtoName, "ShowMyXText", 1)) ? 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);
+
+
+ updateServerCustomStatus();
+
+ 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);
+ 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 <= XstatusIcons)
+ {
+ mi.flags = CMIM_FLAGS;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[bOldXStatus], (LPARAM)&mi);
+ }
+
+ mi.flags = CMIM_FLAGS | CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[bXStatus], (LPARAM)&mi);
+
+ if (bXStatus)
+ {
+ char szSetting[64];
+ char str[MAX_PATH];
+ char *szName, *szMsg;
+
+ sprintf(szSetting, "XStatus%dName", bXStatus);
+ szName = ICQGetContactSettingUtf(NULL, szSetting, ICQTranslateUtfStatic(nameXStatus[bXStatus-1], str, MAX_PATH));
+ sprintf(szSetting, "XStatus%dMsg", bXStatus);
+ szMsg = ICQGetContactSettingUtf(NULL, szSetting, "");
+
+ sprintf(szSetting, "XStatus%dStat", bXStatus);
+ if (!bQuiet && !ICQGetContactSettingByte(NULL, szSetting, 0))
+ {
+ InitXStatusData init;
+
+ //set xstatus to null, wenn dialog box opened
+ setXStatusEx(0, 1);
+
+ init.bAction = 0; // set
+ init.bXStatus = bXStatus;
+ init.szXStatusName = szName;
+ init.szXStatusMsg = szMsg;
+ DialogBoxUtf(FALSE, hInst, MAKEINTRESOURCEA(IDD_SETXSTATUS),NULL,SetXStatusDlgProc,(LPARAM)&init);
+ }
+ else
+ {
+ //by [sin]
+ if(ICQGetContactSettingByte(NULL, "ForceXstatus", 0))
+ {
+ if(bXStatus != 0 && icqOnline){
+ setXStatusEx(0, 1);
+ SleepEx(500, TRUE);//should be 500, less makes icq sometimes not reread
+ }
+ }
+
+ ICQWriteContactSettingByte(NULL, DBSETTING_XSTATUSID, bXStatus);
+ ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, szName);
+ ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, szMsg);
+
+ updateServerCustomStatus();
+ }
+ SAFE_FREE(&szName);
+ SAFE_FREE(&szMsg);
+ }
+ else
+ {
+ ICQWriteContactSettingByte(NULL, DBSETTING_XSTATUSID, bXStatus);
+ ICQDeleteContactSetting(NULL, DBSETTING_XSTATUSNAME);
+ ICQDeleteContactSetting(NULL, DBSETTING_XSTATUSMSG);
+
+ updateServerCustomStatus();
+ }
+}
+
+
+
+static int menuXStatus(WPARAM wParam,LPARAM lParam,LPARAM fParam)
+{
+ setXStatusEx((BYTE)fParam, 0);
+
+ return 0;
+}
+
+
+
+void InitXStatusItems(BOOL bAllowStatus)
+{
+ CLISTMENUITEM mi;
+ BYTE i = 0;
+ BYTE j = 0;
+ char srvFce[MAX_PATH + 64];
+ char szItem[MAX_PATH + 64];
+ HANDLE hXStatusRoot;
+ int bXStatusMenuBuilt = 0;
+
+ BYTE bXStatus = ICQGetContactXStatus(NULL);
+
+ 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;
+
+ while (i < XstatusItems)
+ {
+ char szTemp[64];
+ char* szValue;
+ char* ansi = NULL;
+
+ //if(i == 34) j--;//by BeteTest
+
+ null_snprintf(srvFce, sizeof(srvFce), "%s/menuXStatus%d", gpszICQProtoName, j);
+
+ mi.position++;
+
+ if (!i)
+ bXStatusMenuBuilt = ServiceExists(srvFce);
+
+ if (!bXStatusMenuBuilt)
+ CreateServiceFunctionParam(srvFce, menuXStatus, j);
+
+ mi.flags = (j ? CMIF_ICONFROMICOLIB : 0) | (bXStatus == j?CMIF_CHECKED:0);
+ mi.icolibItem = j ? hXStatusIconsHandle[j-1] : NULL;
+ mi.pszName = j ? (char*)nameXStatus[j-1] : LPGEN("None");
+ sprintf(szTemp, "XStatus%dName", j);
+ szValue = ICQGetContactSettingUtf(NULL, szTemp, "");
+ utf8_decode(szValue, &ansi);
+ mi.pszName = (strlen(ansi) == 0 || !DBGetContactSettingByte(NULL, gpszICQProtoName, "ShowMyXText", 1)) ? ICQTranslate(j?nameXStatus[j-1]:"None") : ansi;
+ /*if(i==33)
+ {
+ mi.pszName = LPGEN("Other clients");
+ mi.pszName = ICQTranslate("Other clients");
+ }*/
+ mi.pszService = srvFce;
+ mi.pszContactOwner = gpszICQProtoName;
+ //Create menu icons
+ if (bStatusMenu)
+ hXStatusItems[j] = (HANDLE)CallService(MS_CLIST_ADDSTATUSMENUITEM, (WPARAM)&hXStatusRoot, (LPARAM)&mi);
+ else
+ hXStatusItems[j] = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi);
+
+ SAFE_FREE(&szValue);
+ SAFE_FREE(&ansi);
+ i++;
+ j++;
+ }
+
+}
+
+
+
+void InitXStatusIcons()
+{
+ char szSection[MAX_PATH + 64];
+ char str[MAX_PATH], prt[MAX_PATH];
+ char lib[2*MAX_PATH] = {0};
+ char* icon_lib;
+ BYTE i;
+
+ if (!gbXStatusEnabled) return;
+
+ icon_lib = InitXStatusIconLibrary(lib);
+
+ null_snprintf(szSection, sizeof(szSection), ICQTranslateUtfStatic("%s/Custom Status", str, MAX_PATH), ICQTranslateUtfStatic(gpszICQProtoName, prt, MAX_PATH));
+
+ for (i = 0; i < XstatusIcons; i++)
+ {
+ char szTemp[64];
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", i);
+ hXStatusIconsHandle[i] = IconLibDefine(nameXStatus[i], szSection, szTemp, 0, icon_lib, -(IDI_XSTATUS1+i));
+ }
+
+ // initialize arrays for CList custom status icons
+ memset(bXStatusCListIconsValid,0,sizeof(bXStatusCListIconsValid));
+ memset(hXStatusCListIcons,-1,sizeof(hXStatusCListIcons));
+}
+
+
+
+void ChangedIconsXStatus()
+{
+ memset(bXStatusCListIconsValid,0,sizeof(bXStatusCListIconsValid));
+}
+
+
+
+int IcqShowXStatusDetails(WPARAM wParam, LPARAM lParam)
+{
+ InitXStatusData init;
+
+ sendXStatusDetailsRequest((HANDLE)wParam, 1);
+
+ 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 <= XstatusIcons)
+ {
+ setXStatusEx((BYTE)wParam, 1);
+
+ return wParam;
+ }
+ return 0;
+}
+
+
+
+int IcqGetXStatus(WPARAM wParam, LPARAM lParam)
+{ // obsolete (TODO: remove in next version)
+ BYTE status = ICQGetContactXStatus(NULL);
+
+ if (!gbXStatusEnabled) return 0;
+
+ if (!icqOnline) return 0;
+
+ if (status < 1 || status > XstatusIcons) 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
+ BYTE status = *pData->status;
+
+ if (status >= 0 && status <= XstatusIcons)
+ {
+ setXStatusEx((BYTE)status, 1);
+ }
+ else
+ return 1; // Failure
+ }
+
+ if (pData->flags & (CSSF_MASK_NAME | CSSF_MASK_MESSAGE))
+ {
+ BYTE status = ICQGetContactXStatus(NULL);
+
+ if (!status) 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
+ BYTE n;
+
+ bHideXStatusUI = (*pData->wParam) ? 0 : 1;
+
+ for (n = 0; n<=XstatusIcons; 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 = ICQGetContactXStatus(hContact);
+ }
+
+ if (pData->flags & CSSF_MASK_NAME)
+ { // fill status name member
+ if (pData->flags & CSSF_DEFAULT_NAME)
+ {
+ BYTE status = *pData->wParam;
+
+ if (status < 1 || status > XstatusIcons) return 1; // Failure
+
+ if (pData->flags & CSSF_UNICODE)
+ {
+ char *text = (char*)nameXStatus[status -1];
+
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text, -1, 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};
+
+ if (!ICQGetContactSettingString(hContact, DBSETTING_XSTATUSNAME, &dbv) && dbv.pszVal)
+ strcpy(pData->pszName, dbv.pszVal);
+ else
+ strcpy(pData->pszName, "");
+
+ 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};
+
+ if (!ICQGetContactSettingString(hContact, DBSETTING_XSTATUSMSG, &dbv) && dbv.pszVal)
+ strcpy(pData->pszMessage, dbv.pszVal);
+ else
+ strcpy(pData->pszMessage, "");
+
+ 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 = XstatusIcons;
+ }
+
+ if (pData->flags & CSSF_STR_SIZES)
+ {
+ DBVARIANT dbv = {0};
+
+ if (pData->wParam)
+ {
+ if (!ICQGetContactSettingString(hContact, DBSETTING_XSTATUSNAME, &dbv))
+ {
+ *pData->wParam = strlennull(dbv.pszVal);
+ ICQFreeVariant(&dbv);
+ }
+ else
+ *pData->wParam = 0;
+ }
+ if (pData->lParam)
+ {
+ if (!ICQGetContactSettingString(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 = ICQGetContactXStatus(NULL);
+
+ if (wParam >= 1 && wParam <= XstatusIcons)
+ {
+ if (lParam == LR_SHARED)
+ return (int)GetXStatusIcon((BYTE)wParam, lParam);
+ else
+ return (int)GetXStatusIcon((BYTE)wParam, 0);
+ }
+ return 0;
+}
+
+
+
+int IcqRequestXStatusDetails(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+
+ if (!gbXStatusEnabled)
+ return 0;
+ if (hContact && !ICQGetContactSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO) &&
+ ICQGetContactXStatus(hContact))
+ { // user has xstatus, no auto-retrieve details, valid contact, request details
+ return requestXStatusDetails(hContact, TRUE);
+ }
+ return 0;
+}
+
+
+
+int IcqRequestAdvStatusIconIdx(WPARAM wParam, LPARAM lParam)
+{
+ BYTE bXStatus;
+
+ if (!gbXStatusEnabled) return -1;
+
+ bXStatus = ICQGetContactXStatus((HANDLE)wParam);
+
+ if (bXStatus)
+ {
+ int idx=-1;
+
+ if (!bXStatusCListIconsValid[bXStatus-1])
+ { // adding icon
+ int idx = hXStatusCListIcons[bXStatus-1];
+ HIMAGELIST hCListImageList = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST,0,0);
+
+ if (hCListImageList)
+ {
+ HICON hXStatusIcon = GetXStatusIcon(bXStatus, LR_SHARED);
+
+ if (idx > 0)
+ ImageList_ReplaceIcon(hCListImageList, idx, hXStatusIcon);
+ else
+ hXStatusCListIcons[bXStatus-1] = ImageList_AddIcon(hCListImageList, hXStatusIcon);
+ // mark icon index in the array as valid
+ bXStatusCListIconsValid[bXStatus-1] = TRUE;
+ }
+ }
+ idx = bXStatusCListIconsValid[bXStatus-1] ? hXStatusCListIcons[bXStatus-1] : -1;
+
+ if (idx > 0)
+ return (idx & 0xFFFF) << 16;
+ }
+ return -1;
+}
diff --git a/icqj_s7_sss_mod/icq_xtraz.c b/icqj_s7_sss_mod/icq_xtraz.c new file mode 100644 index 0000000..f95d698 --- /dev/null +++ b/icqj_s7_sss_mod/icq_xtraz.c @@ -0,0 +1,535 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Internal Xtraz API
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+extern HANDLE hsmsgrequest;
+extern HANDLE hxstatuschanged;
+
+
+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, *tmp;
+ BYTE dwXId = ICQGetContactXStatus(NULL);
+
+ if (dwXId && validateStatusMessageRequest(hContact, MTYPE_SCRIPT_NOTIFY))
+ { // apply privacy rules
+ NotifyEventHooks(hsmsgrequest, (WPARAM)MTYPE_SCRIPT_NOTIFY, (LPARAM)dwUin);
+
+ tmp = ICQGetContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, "");
+ szXName = MangleXml(tmp, strlennull(tmp));
+ SAFE_FREE(&tmp);
+ tmp = ICQGetContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, "");
+ szXMsg = MangleXml(tmp, strlennull(tmp));
+ SAFE_FREE(&tmp);
+
+ 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);
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact=hContact;
+ chk.dwUin=dwUin;
+ chk.nottmpcontact=TRUE;
+ CheckContact(chk);
+ }
+
+ SAFE_FREE(&szXName);
+ SAFE_FREE(&szXMsg);
+
+ {
+ 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.nRequestType = 0x102;
+ EnterCriticalSection(&ratesMutex);
+ rr.wGroup = ratesGroupFromSNAC(gRates, ICQ_MSG_FAMILY, ICQ_MSG_RESPONSE);
+ LeaveCriticalSection(&ratesMutex);
+ if (bThruDC || !handleRateItem(&rr, TRUE))
+ SendXtrazNotifyResponse(dwUin, dwMID, dwMID2, wCookie, szResponse, nResponseLen, bThruDC);
+ }
+ if(!gbXStatusEnabled){
+ CHECKCONTACT chk = {0};
+ chk.dbeventflag=DBEF_READ;
+ chk.dwUin=dwUin;
+ chk.hContact=hContact;
+ chk.logtofile=chk.popup=chk.historyevent=TRUE;
+ chk.icqeventtype=ICQEVENTTYPE_CHECK_STATUS;
+ chk.msg="(Xtraz notify when it's disabled)";
+ chk.popuptype=POPTYPE_VIS;
+ CheckContact(chk);
+ }
+ }
+ else if (dwXId){
+ NetLog_Server("Privacy: Ignoring XStatus request");
+ {
+ CHECKCONTACT chk = {0};
+ chk.dbeventflag=DBEF_READ;
+ chk.dwUin=dwUin;
+ chk.hContact=hContact;
+ chk.logtofile=chk.popup=chk.historyevent=TRUE;
+ chk.icqeventtype=ICQEVENTTYPE_CHECK_STATUS;
+ chk.msg="(xstatus not set)";
+ chk.popuptype=POPTYPE_VIS;
+ CheckContact(chk);
+ }
+ }
+ else{
+ NetLog_Server("Error: We are not in XStatus, skipping");
+ {
+ CHECKCONTACT chk = {0};
+ chk.dbeventflag=DBEF_READ;
+ chk.dwUin=dwUin;
+ chk.hContact=hContact;
+ chk.logtofile=chk.popup=chk.historyevent=TRUE;
+ chk.icqeventtype=ICQEVENTTYPE_CHECK_STATUS;
+ chk.msg="(xtraz request)";
+ chk.popuptype=POPTYPE_VIS;
+ CheckContact(chk);
+ }
+ }
+ }
+ 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");
+ {
+ CHECKCONTACT chk = {0};
+ chk.dwUin=dwUin;
+ chk.hContact=hContact;
+ chk.nottmpcontact=TRUE;
+ CheckContact(chk);
+ }
+
+ 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)
+ {
+ int bChanged = FALSE;
+
+ *szEnd = ' ';
+ szNode = strstr(szWork, "<index>");
+ szEnd = strstr(szWork, "</index>");
+
+ if (szNode && szEnd)
+ {
+ szNode += 7;
+ *szEnd = '\0';
+ if (atoi(szNode) != ICQGetContactXStatus(hContact))
+ { // 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
+ char *szXName, *szOldXName;
+
+ szNode += 7;
+ *szEnd = '\0';
+ szXName = DemangleXml(szNode, strlennull(szNode));
+ // check if the name changed
+ szOldXName = ICQGetContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, NULL);
+ if (strcmpnull(szOldXName, szXName))
+ bChanged = TRUE;
+ SAFE_FREE(&szOldXName);
+ ICQWriteContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, szXName);
+ SAFE_FREE(&szXName);
+ *szEnd = ' ';
+ }
+ szNode = strstr(szWork, "<desc>");
+ szEnd = strstr(szWork, "</desc>");
+
+ if (szNode && szEnd)
+ { // we got XStatus mode msg, save it
+ char *szXMsg, *szOldXMsg;
+
+ szNode += 6;
+ *szEnd = '\0';
+ szXMsg = DemangleXml(szNode, strlennull(szNode));
+ // check if the decription changed
+ szOldXMsg = ICQGetContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, NULL);
+ if (strcmpnull(szOldXMsg, szXMsg))
+ bChanged = TRUE;
+ SAFE_FREE(&szOldXMsg);
+ ICQWriteContactSettingUtf(hContact, DBSETTING_XSTATUSMSG, szXMsg);
+ SAFE_FREE(&szXMsg);
+ }
+ ICQBroadcastAck(hContact, ICQACKTYPE_XSTATUS_RESPONSE, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
+
+ if (bChanged)
+ NotifyEventHooks(hxstatuschanged, (WPARAM)hContact, 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*)SAFE_MALLOC(nDataLen + MAX_PATH);
+ ICQTranslateUtfStatic("Greeting card:", szWork, MAX_PATH);
+ strcat(szWork, "\r\nhttp://www.icq.com/friendship/pages/view_page_");
+ strcat(szWork, szNum);
+
+ // Create message to notify user
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+ int bAdded;
+
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = HContactFromUIN(dwUin, &bAdded);
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.timestamp = time(NULL);
+ pre.szMessage = szWork;
+ pre.flags = PREF_UTF;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+ SAFE_FREE(&szWork);
+ }
+ 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 (invis_for(dwUin,hContact))
+ return 0; //we do not want be detected
+
+ 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, hContact, (void*)pCookieData);
+
+ // have we a open DC, send through that
+ if (gbDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
+ icq_sendXtrazRequestDirect(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, 0))
+ icq_sendXtrazResponseDirect(hContact, wCookie, szBody, nBodyLen, MTYPE_SCRIPT_NOTIFY);
+ else
+ icq_sendXtrazResponseServ(dwUin, dwMID, dwMID2, wCookie, szBody, nBodyLen, MTYPE_SCRIPT_NOTIFY);
+}
diff --git a/icqj_s7_sss_mod/icq_xtraz.h b/icqj_s7_sss_mod/icq_xtraz.h new file mode 100644 index 0000000..4fe9522 --- /dev/null +++ b/icqj_s7_sss_mod/icq_xtraz.h @@ -0,0 +1,78 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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);
+
+// helper functions
+BYTE __stdcall ICQGetContactXStatus(HANDLE hContact);
+
+// custom status support
+void InitXStatusItems(BOOL bAllowStatus);
+void InitXStatusEvents();
+void UninitXStatusEvents();
+
+void InitXStatusIcons();
+void ChangedIconsXStatus();
+HICON GetXStatusIcon(int bStatus, UINT flags);
+
+void handleXStatusCaps(HANDLE hContact, char* caps, int capsize, char* moods, int moodsize);
+
+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);
+int IcqRequestAdvStatusIconIdx(WPARAM wParam, LPARAM lParam);
+
+DWORD __stdcall icq_XStatusUpdaterThread(LPVOID lp);
+
+
+#endif /* __ICQ_XTRAZ_H */
diff --git a/icqj_s7_sss_mod/icqosc_proto.h b/icqj_s7_sss_mod/icqosc_proto.h new file mode 100644 index 0000000..3618f60 --- /dev/null +++ b/icqj_s7_sss_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: 35 $
+// Last change on : $Date: 2007-08-01 18:35:56 +0300 (Ср, 01 авг 2007) $
+// Last change by : $Author: chaos.persei $
+//
+// 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_s7_sss_mod/icqosc_svcs.c b/icqj_s7_sss_mod/icqosc_svcs.c new file mode 100644 index 0000000..7e0fb6c --- /dev/null +++ b/icqj_s7_sss_mod/icqosc_svcs.c @@ -0,0 +1,2599 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 51 $
+// Last change on : $Date: 2007-08-30 23:46:51 +0300 (Чт, 30 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// High-level code for exported API services
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+int gbIdleAllow;
+int icqGoingOnlineStatus;
+int iIcqNewStatus = ID_STATUS_OFFLINE;
+extern HANDLE hIconProtocol;
+
+extern WORD wListenPort;
+
+extern char* calcMD5Hash(char* szFile);
+extern filetransfer *CreateFileTransfer(HANDLE hContact, DWORD dwUin, int nVersion);
+extern DWORD addServContact(HANDLE hContact, const char *pszGroup);
+
+
+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_ONLINE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND |
+ PF2_FREECHAT;
+ break;
+
+ case PFLAGNUM_4:
+ nReturn = PF4_SUPPORTIDLE | PF4_IMSENDUTF;
+ 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:
+ if (lParam)
+ { // determine per contact
+ BYTE bClientId = ICQGetContactSettingByte((HANDLE)lParam, "ClientID", CLID_GENERIC);
+
+ if (bClientId == CLID_MIRANDA)
+ {
+ if (CheckContactCapabilities((HANDLE)lParam, CAPF_CONTACTS) && ICQGetContactStatus((HANDLE)lParam) != ID_STATUS_OFFLINE)
+ nReturn = 0x100; // limited only by packet size
+ else
+ nReturn = MAX_CONTACTSSEND;
+ }
+ else if (bClientId == CLID_ICQ6)
+ {
+ if (CheckContactCapabilities((HANDLE)lParam, CAPF_CONTACTS))
+ nReturn = 1; // crapy ICQ6 cannot handle multiple contacts in the transfer
+ else
+ nReturn = 0; // this version does not support contacts transfer at all
+ }
+ else
+ nReturn = MAX_CONTACTSSEND;
+ }
+ else // return generic limit
+ 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)
+{
+ char *id;
+
+
+ switch (wParam & 0xFFFF)
+ {
+ case PLI_PROTOCOL:
+ id = "proto";
+ break;
+
+ default:
+ return 0; // Failure
+ }
+
+ if (wParam&PLIF_ICOLIBHANDLE)
+ return (int)hIconProtocol;
+ else
+ {
+ HICON icon = IconLibGetIcon(id);
+
+ if (wParam&PLIF_ICOLIB)
+ return (int)icon;
+ else
+ return (int)CopyIcon(icon);
+ }
+}
+
+
+
+int IcqSetPassword(WPARAM wParam, LPARAM lParam)
+{
+ char *pwd = (char*)lParam;
+ int len = strlennull(pwd);
+
+ if (len && len <= 8)
+ {
+ strcpy(gpszPassword, pwd);
+ gbRememberPwd = 1;
+ }
+ return 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.type != DBVT_BLOB || (dbv.cpbVal != 0x14 && dbv.cpbVal != 0x09))
+ 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, dbv.cpbVal))
+ { // 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, dbv.cpbVal))
+ { // 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 IcqGetAvatarCaps(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam == AF_MAXSIZE)
+ {
+ POINT *size = (POINT*)lParam;
+
+ if (size)
+ {
+ if (ICQGetContactSettingByte(NULL, "AvatarsAllowBigger", DEFAULT_BIGGER_AVATARS))
+ { // experimental server limits
+ size->x = 128;
+ size->y = 128;
+ }
+ else
+ { // default limits (older)
+ size->x = 64;
+ size->y = 64;
+ }
+
+ return 0;
+ }
+ }
+ else if (wParam == AF_PROPORTION)
+ {
+ return PIP_NONE;
+ }
+ else if (wParam == AF_FORMATSUPPORTED)
+ {
+ if (lParam == PA_FORMAT_JPEG || lParam == PA_FORMAT_GIF || lParam == PA_FORMAT_XML || lParam == PA_FORMAT_BMP)
+ return 1;
+ else
+ return 0;
+ }
+ else if (wParam == AF_ENABLED)
+ {
+ if (gbSsiEnabled && gbAvatarsEnabled)
+ return 1;
+ else
+ return 0;
+ }
+ else if (wParam == AF_DONTNEEDDELAYS)
+ {
+ return 0;
+ }
+ else if (wParam == AF_MAXFILESIZE)
+ { // server accepts images of 7168 bytees, not bigger
+ return 7168;
+ }
+ else if (wParam == AF_DELAYAFTERFAIL)
+ { // do not request avatar again if server gave an error
+ return 1 * 60 * 60 * 1000; // one hour
+ }
+ 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 not in our storage, copy
+ if (strcmpnull(szFile, szMyFile) && !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 ? AVATAR_HASH_FLASH : AVATAR_HASH_STATIC; //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
+ ICQDeleteContactSetting(NULL, "AvatarFile");
+ ICQWriteContactSettingBlob(NULL, "AvatarHash", hashEmptyAvatar, 9);
+ updateServAvatarHash(hashEmptyAvatar, 9); // set blank avatar
+ iRet = 0;
+ }
+
+ return iRet;
+}
+
+
+
+void updateAimAwayMsg()
+{
+ char** szMsg = MirandaStatusToAwayMsg(gnCurrentStatus);
+
+ EnterCriticalSection(&modeMsgsMutex);
+ if (szMsg && !bNoStatusReply)
+ icq_sendSetAimAwayMsgServ(*szMsg);
+ LeaveCriticalSection(&modeMsgsMutex);
+}
+
+
+
+int IcqSetStatus(WPARAM wParam, LPARAM lParam)
+{
+ int nNewStatus = MirandaStatusToSupported(wParam);
+ iIcqNewStatus = nNewStatus;
+ // 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), FALSE);
+ // Tell whos on our visible list
+ icq_sendEntireVisInvisList(0);
+ if (gbAimEnabled)
+ updateAimAwayMsg();
+ }
+ else
+ {
+ icq_setstatus(MirandaStatusToIcq(gnCurrentStatus), FALSE);
+ 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) && !bNoStatusReply)
+ 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, "");
+
+ // auth granted, remove contact menu item
+ ICQDeleteContactSetting((HANDLE)wParam, "Grant");
+
+ 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
+}
+
+
+
+int IcqGetInfo(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam && icqOnline)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ DWORD dwUin;
+ uid_str szUid;
+ DWORD dwCookie;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUid))
+ {
+ return 1; // Invalid contact
+ }
+
+ if (dwUin)
+ dwCookie = icq_sendGetInfoServ(ccs->hContact, dwUin, (ccs->wParam & SGIF_MINIMAL) != 0, (ccs->wParam & SGIF_ONOPEN) != 0);
+ else // TODO: this needs something better
+ dwCookie = icq_sendGetAimProfileServ(ccs->hContact, szUid);
+
+ if (dwCookie)
+ return 0; // Success
+ else
+ return 1; // Failure
+ }
+
+ return 1; // Failure
+}
+
+
+
+int IcqFileAllow(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUid))
+ return 0; // Invalid contact
+
+ if (icqOnline && ccs->hContact && ccs->lParam && ccs->wParam)
+ { // approve old fashioned file transfer
+ basic_filetransfer* ft = ((basic_filetransfer *)ccs->wParam);
+
+ if (dwUin && ft->ft_magic == FT_MAGIC_ICQ)
+ {
+ 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, 0))
+ icq_sendFileAcceptDirect(ccs->hContact, ft);
+ else
+ icq_sendFileAcceptServ(dwUin, ft, 0);
+
+ return ccs->wParam; // Success
+ }
+ else if (ft->ft_magic == FT_MAGIC_OSCAR)
+ { // approve oscar file transfer
+ return oftFileAllow(ccs->hContact, ccs->wParam, ccs->lParam);
+ }
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+
+int IcqFileDeny(WPARAM wParam, LPARAM lParam)
+{
+ int nReturnValue = 1;
+
+ if (lParam)
+ {
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ DWORD dwUin;
+ uid_str szUid;
+ basic_filetransfer *ft = (basic_filetransfer*)ccs->wParam;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+ if (icqOnline && ccs->wParam && ccs->hContact)
+ {
+ if (dwUin && ft->ft_magic == FT_MAGIC_ICQ)
+ { // deny old fashioned file transfer
+ filetransfer *ft = (filetransfer*)ccs->wParam;
+ // Was request received thru DC and have we a open DC, send through that
+ if (ft->bDC && IsDirectConnectionOpen(ccs->hContact, DIRECTCONN_STANDARD, 0))
+ icq_sendFileDenyDirect(ccs->hContact, ft, (char*)ccs->lParam);
+ else
+ icq_sendFileDenyServ(dwUin, ft, (char*)ccs->lParam, 0);
+
+ nReturnValue = 0; // Success
+ }
+ else if (ft->ft_magic == FT_MAGIC_OSCAR)
+ { // deny oscar file transfer
+ return oftFileDeny(ccs->hContact, ccs->wParam, ccs->lParam);
+ }
+ }
+ // Release possible orphan structure
+ SafeReleaseFileTransfer(&ft);
+ }
+
+ return nReturnValue;
+}
+
+
+
+int IcqFileCancel(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam /*&& icqOnline*/)
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+ if (ccs->hContact && ccs->wParam)
+ {
+ basic_filetransfer *ft = (basic_filetransfer *)ccs->wParam;
+
+ if (dwUin && ft->ft_magic == FT_MAGIC_ICQ)
+ { // cancel old fashioned file transfer
+ filetransfer * ft = (filetransfer * ) ccs->wParam;
+
+ icq_CancelFileTransfer(ccs->hContact, ft);
+
+ return 0; // Success
+ }
+ else if (ft->ft_magic = FT_MAGIC_OSCAR)
+ { // cancel oscar file transfer
+ return oftFileCancel(ccs->hContact, ccs->wParam, ccs->lParam);
+ }
+ }
+ }
+
+ return 1; // Failure
+}
+
+
+
+int IcqFileResume(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline && wParam)
+ {
+ PROTOFILERESUME *pfr = (PROTOFILERESUME*)lParam;
+ basic_filetransfer *ft = (basic_filetransfer *)wParam;
+
+ if (ft->ft_magic == FT_MAGIC_ICQ)
+ {
+ icq_sendFileResume((filetransfer *)wParam, pfr->action, pfr->szFilename);
+ }
+ else if (ft->ft_magic == FT_MAGIC_OSCAR)
+ {
+ oftFileResume((oscar_filetransfer *)wParam, pfr->action, pfr->szFilename);
+ }
+ else
+ return 1; // Failure
+
+ 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
+ if (oldMode == ID_STATUS_OFFLINE && ICQGetContactSettingWord(ccs->hContact, "SrvIgnoreID", 0))
+ { // Need to remove Ignore item as well
+ icq_removeServerPrivacyItem(ccs->hContact, uin, uid, ICQGetContactSettingWord(ccs->hContact, "SrvIgnoreID", 0), SSI_ITEM_IGNORE);
+
+ ICQWriteContactSettingWord(ccs->hContact, "SrvIgnoreID", 0);
+ }
+ icq_sendChangeVisInvis(ccs->hContact, uin, uid, oldMode==ID_STATUS_OFFLINE, 0);
+ }
+ if (ccs->wParam != 0)
+ { // Add to new list
+ if (ccs->wParam==ID_STATUS_OFFLINE && ICQGetContactSettingWord(ccs->hContact, "SrvIgnoreID", 0))
+ return 0; // Success: offline by ignore item
+
+ icq_sendChangeVisInvis(ccs->hContact, uin, uid, ccs->wParam==ID_STATUS_OFFLINE, 1);
+ }
+ }
+
+ 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_ONLINE:
+ wMessageType = MTYPE_AUTOONLINE;
+ break;
+
+ 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, 0)&& !invis_for(0,ccs->hContact))
+ {
+ int iRes = icq_sendGetAwayMsgDirect(ccs->hContact, wMessageType);
+ if (iRes) return iRes; // we succeded, return
+ }
+ else if(/*bStealthRequest && */(bIncognitoRequest || bIncognitoGlobal))
+ {
+ bIncognitoRequest = FALSE;
+ return icq_sendGetStealthAwayMsgServ(ccs->hContact, dwUin, wMessageType,
+ (WORD)(ICQGetContactSettingWord(ccs->hContact, "Version", 0)==9?9:ICQ_VERSION)); // Success
+ }
+ else if(CheckContactCapabilities(ccs->hContact, CAPF_STATUSMSGEXT)&& !invis_for(0,ccs->hContact))
+ {
+ return icq_sendGetAwayMsgServExt(ccs->hContact, dwUin, wMessageType,
+ (WORD)(ICQGetContactSettingWord(ccs->hContact, "Version", 0)==9?9:ICQ_VERSION)); // Success
+ }
+ else if(!invis_for(0,ccs->hContact))
+ {
+ return icq_sendGetAwayMsgServ(ccs->hContact, dwUin, wMessageType, (WORD)(ICQGetContactSettingWord(ccs->hContact, "Version", 0)==9?9:ICQ_VERSION)); // Success
+ }
+ }
+ }
+ else
+ {
+ if (wStatus == ID_STATUS_AWAY)
+ {
+ return icq_sendGetAimAwayMsgServ(ccs->hContact, szUID, MTYPE_AUTOAWAY);
+ }
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+
+static message_cookie_data* CreateMsgCookieData(BYTE bMsgType, HANDLE hContact, DWORD dwUin, int bUseSrvRelay)
+{
+ BYTE bAckType;
+ WORD wStatus = ICQGetContactStatus(hContact);
+
+ if (!ICQGetContactSettingByte(NULL, "SlowSend", DEFAULT_SLOWSEND))
+ bAckType = ACKTYPE_NONE;
+ else if ((bUseSrvRelay && ((!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);
+}
+
+
+
+static DWORD reportGenericSendError(HANDLE hContact, int nType, const char* szErrorMsg)
+{ // just broadcast generic send error with dummy cookie and return that cookie
+ DWORD dwCookie = GenerateCookie(0);
+
+ icq_SendProtoAck(hContact, dwCookie, ACKRESULT_FAILED, nType, ICQTranslate(szErrorMsg));
+
+ return dwCookie;
+}
+
+
+
+static char* convertMsgToUserSpecificAnsi(HANDLE hContact, const unsigned char* szMsg)
+{ // this takes utf-8 encoded message
+ WORD wCP = ICQGetContactSettingWord(hContact, "CodePage", gwAnsiCodepage);
+ char* szAnsi = NULL;
+
+ if (wCP != CP_ACP)
+ { // convert to proper codepage
+ if (!utf8_decode_codepage(szMsg, &szAnsi, wCP))
+ return NULL;
+ }
+ return szAnsi;
+}
+
+
+
+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 = NULL;
+ unsigned char* puszText = NULL;
+ int bNeedFreeA = 0, bNeedFreeU = 0;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUID))
+ { // Invalid contact
+ return reportGenericSendError(ccs->hContact, ACKTYPE_MESSAGE, "The receiver has an invalid user ID.");
+ }
+
+ if ((ccs->wParam & PREF_UTF) == PREF_UTF)
+ puszText = (unsigned char*)ccs->lParam;
+ else
+ pszText = (char*)ccs->lParam;
+
+ if ((ccs->wParam & PREF_UNICODE) == PREF_UNICODE)
+ {
+ puszText = make_utf8_string((WCHAR*)((char*)ccs->lParam+strlennull(pszText)+1)); // get the UTF-16 part
+ bNeedFreeU = 1;
+ }
+
+ wRecipientStatus = ICQGetContactStatus(ccs->hContact);
+
+ if (puszText)
+ { // we have unicode message, check if it is possible and reasonable to send it as unicode
+ BOOL plain_ascii = IsUSASCII(puszText, strlennull(puszText));
+
+ if (plain_ascii || !gbUtfEnabled || !CheckContactCapabilities(ccs->hContact, CAPF_UTF) ||
+ !ICQGetContactSettingByte(ccs->hContact, "UnicodeSend", 1))
+ { // unicode is not available for target contact, convert to good codepage
+ if (!plain_ascii)
+ { // do not convert plain ascii messages
+ char* szUserAnsi = convertMsgToUserSpecificAnsi(ccs->hContact, puszText);
+
+ if (szUserAnsi)
+ { // we have special encoding, use it
+ pszText = szUserAnsi;
+ bNeedFreeA = 1;
+ }
+ else if (!pszText)
+ { // no ansi available, create basic
+ utf8_decode(puszText, &pszText);
+ bNeedFreeA = 1;
+ }
+ }
+ else if (!pszText)
+ { // plain ascii unicode message, take as ansi if no ansi available
+ pszText = puszText;
+ bNeedFreeA = bNeedFreeU;
+ puszText = NULL;
+ }
+ // dispose unicode message
+ if (bNeedFreeU)
+ SAFE_FREE(&puszText);
+ else
+ puszText = NULL;
+ }
+ }
+
+ if (gbTempVisListEnabled && gnCurrentStatus == ID_STATUS_INVISIBLE)
+ makeContactTemporaryVisible(ccs->hContact); // make us temporarily visible to contact
+
+ // Failure scenarios
+ if (!icqOnline)
+ {
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_MESSAGE, "You cannot send messages when you are offline.");
+ }
+ else if ((wRecipientStatus == ID_STATUS_OFFLINE) && (strlennull(pszText) > 4096))
+ {
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_MESSAGE, "Messages to offline contacts must be shorter than 4096 characters.");
+ }
+ // Looks OK
+ else
+ {
+ message_cookie_data* pCookieData;
+
+ if (!puszText && gbUtfEnabled == 2 && !IsUSASCII(pszText, strlennull(pszText))
+ && CheckContactCapabilities(ccs->hContact, CAPF_UTF) && ICQGetContactSettingByte(ccs->hContact, "UnicodeSend", 1))
+ { // text is not unicode and contains national chars and we should send all this as Unicode, so do it
+ puszText = ansi_to_utf8(pszText);
+ bNeedFreeU = 1;
+ }
+
+ if (!dwUin)
+ { // prepare AIM Html message
+ char *src, *mng;
+
+ if (puszText)
+ src = puszText;
+ else
+ src = pszText;
+ mng = MangleXml(src, strlennull(src));
+ src = (char*)SAFE_MALLOC(strlennull(mng) + 28);
+ strcpy(src, "<HTML><BODY>");
+ strcat(src, mng);
+ SAFE_FREE(&mng);
+ strcat(src, "</BODY></HTML>");
+ if (puszText)
+ { // convert to UCS-2
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+ puszText = src;
+ bNeedFreeU = 1;
+ }
+ else
+ {
+ if (bNeedFreeA) SAFE_FREE(&pszText);
+ pszText = src;
+ bNeedFreeA = 1;
+ }
+ }
+ // Set up the ack type
+ pCookieData = CreateMsgCookieData(MTYPE_PLAIN, ccs->hContact, dwUin, TRUE);
+
+#ifdef _DEBUG
+ NetLog_Server("Send %s message - Message cap is %u", puszText ? "unicode" : "", CheckContactCapabilities(ccs->hContact, CAPF_SRV_RELAY));
+ NetLog_Server("Send %s message - Contact status is %u", puszText ? "unicode" : "", wRecipientStatus);
+#endif
+ if (dwUin && gbDCMsgEnabled && IsDirectConnectionOpen(ccs->hContact, DIRECTCONN_STANDARD, 0))
+ { // send thru direct
+ char* dc_msg = pszText;
+ char* dc_cap = NULL;
+
+ if (puszText)
+ { // direct connection uses utf-8, prepare
+ dc_msg = puszText;
+ dc_cap = CAP_UTF8MSGS;
+ }
+ dwCookie = icq_SendDirectMessage(ccs->hContact, dc_msg, strlennull(dc_msg), 1, pCookieData, dc_cap);
+
+ if (dwCookie)
+ { // free the buffers if alloced
+ if (bNeedFreeA) SAFE_FREE(&pszText);
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+
+ return dwCookie; // we succeded, return
+ }
+ // on failure, fallback to send thru server
+ }
+ if (!dwUin || !CheckContactCapabilities(ccs->hContact, CAPF_SRV_RELAY) || wRecipientStatus == ID_STATUS_OFFLINE)
+ {
+ WCHAR* pwszText = NULL;
+
+ if (puszText) pwszText = make_unicode_string(puszText);
+ if ((pwszText ? wcslen(pwszText)*sizeof(WCHAR) : strlennull(pszText)) > MAX_MESSAGESNACSIZE)
+ { // max length check // TLV(2) is currently limited to 0xA00 bytes in online mode
+ // only limit to not get disconnected, all other will be handled by error 0x0A
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_MESSAGE, "The message could not be delivered, it is too long.");
+
+ SAFE_FREE(&pCookieData);
+ // free the buffers if alloced
+ SAFE_FREE(&pwszText);
+ if (bNeedFreeA) SAFE_FREE(&pszText);
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+
+ return dwCookie;
+ }
+ // Rate check
+ if (IsServerOverRate(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, RML_LIMIT))
+ { // rate is too high, the message will not go thru...
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_MESSAGE, "The message could not be delivered. You are sending too fast. Wait a while and try again.");
+
+ SAFE_FREE(&pCookieData);
+ // free the buffers if alloced
+ SAFE_FREE(&pwszText);
+ if (bNeedFreeA) SAFE_FREE(&pszText);
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+
+ return dwCookie;
+ }
+ // set flag for offline messages - to allow proper error handling
+ if (wRecipientStatus == ID_STATUS_OFFLINE) ((message_cookie_data_ex*)pCookieData)->isOffline = TRUE;
+
+ if (pwszText)
+ dwCookie = icq_SendChannel1MessageW(dwUin, szUID, ccs->hContact, pwszText, pCookieData);
+ else
+ dwCookie = icq_SendChannel1Message(dwUin, szUID, ccs->hContact, pszText, pCookieData);
+ // free the unicode message
+ SAFE_FREE(&pwszText);
+ }
+ else
+ {
+ WORD wPriority;
+ char* srv_msg = pszText;
+ char* srv_cap = NULL;
+
+ if (wRecipientStatus == ID_STATUS_ONLINE || wRecipientStatus == ID_STATUS_FREECHAT)
+ wPriority = 0x0001;
+ else
+ wPriority = 0x0021;
+
+ if (puszText)
+ { // type-2 messages are utf-8 encoded, prepare
+ srv_msg = puszText;
+ srv_cap = CAP_UTF8MSGS;
+ }
+ if (strlennull(srv_msg) + (puszText ? 144 : 102) > MAX_MESSAGESNACSIZE)
+ { // max length check
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_MESSAGE, "The message could not be delivered, it is too long.");
+
+ SAFE_FREE(&pCookieData);
+ // free the buffers if alloced
+ if (bNeedFreeA) SAFE_FREE(&pszText);
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+
+ return dwCookie;
+ }
+ // Rate check
+ if (IsServerOverRate(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, RML_LIMIT))
+ { // rate is too high, the message will not go thru...
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_MESSAGE, "The message could not be delivered. You are sending too fast. Wait a while and try again.");
+
+ SAFE_FREE(&pCookieData);
+ // free the buffers if alloced
+ if (bNeedFreeA) SAFE_FREE(&pszText);
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+
+ return dwCookie;
+ }
+ // WORKAROUND!!
+ // Nasty workaround for ICQ6 client's bug - it does not send acknowledgement when in temporary visible mode
+ // - This uses only server ack, but also for visible invisible contact!
+ if (wRecipientStatus == ID_STATUS_INVISIBLE && pCookieData->nAckType == ACKTYPE_CLIENT && ICQGetContactSettingByte(ccs->hContact, "ClientID", CLID_GENERIC) == CLID_ICQ6)
+ pCookieData->nAckType = ACKTYPE_SERVER;
+
+ dwCookie = icq_SendChannel2Message(dwUin, ccs->hContact, srv_msg, strlennull(srv_msg), wPriority, pCookieData, srv_cap);
+ }
+
+ // 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);
+ }
+ }
+ // free the buffers if alloced
+ if (bNeedFreeA) SAFE_FREE(&pszText);
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+
+ 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
+ return reportGenericSendError(ccs->hContact, ACKTYPE_URL, "The receiver has an invalid user ID.");
+ }
+
+ wRecipientStatus = ICQGetContactStatus(ccs->hContact);
+
+ // Failure
+ if (!icqOnline)
+ {
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_URL, "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, TRUE);
+
+ // 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, 0))
+ {
+ int iRes = icq_SendDirectMessage(ccs->hContact, szBody, nBodyLen, 1, pCookieData, NULL);
+ if (iRes) return iRes; // we succeded, return
+ }
+
+ // Rate check
+ if (IsServerOverRate(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, RML_LIMIT))
+ { // rate is too high, the message will not go thru...
+ SAFE_FREE(&pCookieData);
+
+ return reportGenericSendError(ccs->hContact, ACKTYPE_URL, "The message could not be delivered. You are sending too fast. Wait a while and try again.");
+ }
+ // Select channel and send
+ if (!CheckContactCapabilities(ccs->hContact, CAPF_SRV_RELAY) ||
+ wRecipientStatus == ID_STATUS_OFFLINE)
+ {
+ dwCookie = icq_SendChannel4Message(dwUin, ccs->hContact, 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, ccs->hContact, 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;
+ uid_str szUid;
+ WORD wRecipientStatus;
+ DWORD dwCookie;
+
+ if (ICQGetContactSettingUID(ccs->hContact, &dwUin, &szUid))
+ { // Invalid contact
+ return reportGenericSendError(ccs->hContact, ACKTYPE_CONTACTS, "The receiver has an invalid user ID.");
+ }
+
+ wRecipientStatus = ICQGetContactStatus(ccs->hContact);
+ nContacts = HIWORD(ccs->wParam);
+
+ // Failures
+ if (!icqOnline)
+ {
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_CONTACTS, "You cannot send messages when you are offline.");
+ }
+ else if (!hContactsList || (nContacts < 1) || (nContacts > MAX_CONTACTSSEND))
+ {
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_CONTACTS, "Bad data (internal error #1)");
+ }
+ // OK
+ else
+ {
+ if (CheckContactCapabilities(ccs->hContact, CAPF_CONTACTS) && wRecipientStatus != ID_STATUS_OFFLINE)
+ { // Use the new format if possible
+ int nDataLen, nNamesLen;
+ struct icq_contactsend_s* contacts = NULL;
+
+ // Format the data part and the names part
+ // This is kinda messy, but there is no simple way to do it. First
+ // we need to calculate the length of the packet.
+ contacts = (struct icq_contactsend_s*)_alloca(sizeof(struct icq_contactsend_s)*nContacts);
+ ZeroMemory(contacts, sizeof(struct icq_contactsend_s)*nContacts);
+ {
+ nDataLen = 0; nNamesLen = 0;
+ for (i = 0; i < nContacts; i++)
+ {
+ uid_str szContactUid;
+
+ if (!IsICQContact(hContactsList[i]))
+ break; // Abort if a non icq contact is found
+ if (ICQGetContactSettingUID(hContactsList[i], &contacts[i].uin, &szContactUid))
+ break; // Abort if invalid contact
+ contacts[i].uid = contacts[i].uin?NULL:null_strdup(szContactUid);
+ contacts[i].szNick = NickFromHandleUtf(hContactsList[i]);
+ nDataLen += getUIDLen(contacts[i].uin, contacts[i].uid) + 4;
+ nNamesLen += strlennull(contacts[i].szNick) + 8;
+ }
+
+ if (i == nContacts)
+ {
+ message_cookie_data* pCookieData;
+ icq_packet mData, mNames;
+
+#ifdef _DEBUG
+ NetLog_Server("Sending contacts to %s.", strUID(dwUin, szUid));
+#endif
+ // Do not calculate the exact size of the data packet - only the maximal size (easier)
+ // Sumarize size of group information
+ // - we do not utilize the full power of the protocol and send all contacts with group "General"
+ // just like ICQ6 does
+ nDataLen += 9;
+ nNamesLen += 9;
+
+ // Create data structures
+ mData.wPlace = 0;
+ mData.pData = (char*)SAFE_MALLOC(nDataLen);
+ mData.wLen = nDataLen;
+ mNames.wPlace = 0;
+ mNames.pData = (char*)SAFE_MALLOC(nNamesLen);
+
+ // pack Group Name
+ packWord(&mData, 7);
+ packBuffer(&mData, "General", 7);
+ packWord(&mNames, 7);
+ packBuffer(&mNames, "General", 7);
+
+ // all contacts in one group
+ packWord(&mData, (WORD)nContacts);
+ packWord(&mNames, (WORD)nContacts);
+ for (i = 0; i < nContacts; i++)
+ {
+ uid_str szContactUid;
+ WORD wLen;
+
+ if (contacts[i].uin)
+ strUID(contacts[i].uin, szContactUid);
+ else
+ strcpy(szContactUid, contacts[i].uid);
+
+ // prepare UID
+ wLen = strlennull(szContactUid);
+ packWord(&mData, wLen);
+ packBuffer(&mData, szContactUid, wLen);
+
+ // prepare Nick
+ wLen = strlennull(contacts[i].szNick);
+ packWord(&mNames, (WORD)(wLen + 4));
+ packTLV(&mNames, 0x01, wLen, contacts[i].szNick);
+ }
+
+ // Cleanup temporary list
+ for(i = 0; i < nContacts; i++)
+ {
+ SAFE_FREE(&contacts[i].szNick);
+ SAFE_FREE(&contacts[i].uid);
+ }
+
+ // Rate check
+ if (IsServerOverRate(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, RML_LIMIT))
+ { // rate is too high, the message will not go thru...
+ SAFE_FREE(&mData.pData);
+ SAFE_FREE(&mNames.pData);
+
+ return reportGenericSendError(ccs->hContact, ACKTYPE_CONTACTS, "The message could not be delivered. You are sending too fast. Wait a while and try again.");
+ }
+
+ // Set up the ack type
+ pCookieData = CreateMsgCookieData(MTYPE_CONTACTS, ccs->hContact, dwUin, FALSE);
+
+ // AIM clients do not send acknowledgement
+ if (!dwUin && pCookieData->nAckType == ACKTYPE_CLIENT)
+ pCookieData->nAckType = ACKTYPE_SERVER;
+ // Send the message
+ dwCookie = icq_SendChannel2Contacts(dwUin, szUid, ccs->hContact, mData.pData, mData.wPlace, mNames.pData, mNames.wPlace, pCookieData);
+
+ // 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);
+ }
+ // Release our buffers
+ SAFE_FREE(&mData.pData);
+ SAFE_FREE(&mNames.pData);
+ }
+ else
+ {
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_CONTACTS, "Bad data (internal error #2)");
+ }
+
+ for(i = 0; i < nContacts; i++)
+ {
+ SAFE_FREE(&contacts[i].szNick);
+ SAFE_FREE(&contacts[i].uid);
+ }
+ }
+ }
+ else if (dwUin)
+ { // old format is only understood by ICQ clients
+ int nBodyLength;
+ char szContactUin[UINMAXLEN];
+ char szCount[17];
+ struct icq_contactsend_s* contacts = NULL;
+ uid_str szContactUid;
+
+
+ // 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.
+ contacts = (struct icq_contactsend_s*)_alloca(sizeof(struct icq_contactsend_s)*nContacts);
+ ZeroMemory(contacts, 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, &szContactUid))
+ break; // Abort if invalid contact
+ contacts[i].uid = contacts[i].uin?NULL:null_strdup(szContactUid);
+ 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, szContactUin, 10);
+ strcpy(pBuffer, szContactUin);
+ }
+ else
+ strcpy(pBuffer, contacts[i].uid);
+ pBuffer += strlennull(pBuffer);
+ *pBuffer++ = (char)0xFE;
+ strcpy(pBuffer, contacts[i].szNick);
+ pBuffer += strlennull(pBuffer);
+ *pBuffer++ = (char)0xFE;
+ }
+
+ for (i = 0; i < nContacts; i++)
+ { // release memory
+ SAFE_FREE(&contacts[i].szNick);
+ SAFE_FREE(&contacts[i].uid);
+ }
+
+ // Set up the ack type
+ pCookieData = CreateMsgCookieData(MTYPE_CONTACTS, ccs->hContact, dwUin, TRUE);
+
+ if (gbDCMsgEnabled && IsDirectConnectionOpen(ccs->hContact, DIRECTCONN_STANDARD, 0))
+ {
+ int iRes = icq_SendDirectMessage(ccs->hContact, pBody, nBodyLength, 1, pCookieData, NULL);
+
+ if (iRes)
+ {
+ SAFE_FREE(&pBody);
+
+ return iRes; // we succeded, return
+ }
+ }
+
+ // Rate check
+ if (IsServerOverRate(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, RML_LIMIT))
+ { // rate is too high, the message will not go thru...
+ SAFE_FREE(&pCookieData);
+ SAFE_FREE(&pBody);
+
+ return reportGenericSendError(ccs->hContact, ACKTYPE_CONTACTS, "The message could not be delivered. You are sending too fast. Wait a while and try again.");
+ }
+ // Select channel and send
+ if (!CheckContactCapabilities(ccs->hContact, CAPF_SRV_RELAY) || wRecipientStatus == ID_STATUS_OFFLINE)
+ {
+ dwCookie = icq_SendChannel4Message(dwUin, ccs->hContact, 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, ccs->hContact, 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 = reportGenericSendError(ccs->hContact, ACKTYPE_CONTACTS, "Bad data (internal error #2)");
+ }
+ }
+ }
+ else
+ {
+ dwCookie = reportGenericSendError(ccs->hContact, ACKTYPE_CONTACTS, "The reciever does not support receiving of contacts.");
+ }
+ }
+ 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;
+ uid_str szUid;
+
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ return 0; // Invalid contact
+
+ if (ICQGetContactStatus(hContact) != ID_STATUS_OFFLINE)
+ {
+ if (CheckContactCapabilities(hContact, CAPF_AIM_FILE))
+ {
+ return oftInitTransfer(hContact, dwUin, szUid, files, pszDesc);
+ }
+ else if (dwUin)
+ {
+ 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, hContact, 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, 0))
+ {
+ 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, 0))
+ {
+ 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);
+ // auth granted, remove contact menu item
+ ICQDeleteContactSetting((HANDLE)wParam, "Grant");
+ }
+
+ return 0;
+}
+
+
+
+int IcqRevokeAuthorization(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
+
+ if (MessageBoxUtf(NULL, LPGEN("Are you sure you want to revoke user's authorization (this will remove you from his/her list on some clients) ?"), LPGEN("Confirmation"), 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;
+}
+
+
+
+int IcqAddServerContact(WPARAM wParam, LPARAM lParam)
+{
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (!gbSsiEnabled) return 0;
+
+ // Does this contact have a UID?
+ if (!ICQGetContactSettingUID((HANDLE)wParam, &dwUin, &szUid) && !ICQGetContactSettingWord((HANDLE)wParam, "ServerId", 0) && !ICQGetContactSettingWord((HANDLE)wParam, "SrvIgnoreId", 0))
+ {
+ char *pszGroup;
+
+ // Read group from DB
+ pszGroup = ICQGetContactCListGroup((HANDLE)wParam);
+
+ addServContact((HANDLE)wParam, pszGroup);
+
+ SAFE_FREE(&pszGroup);
+ if(ICQGetContactSettingByte((HANDLE)wParam,"CheckSelfRemove", 0))
+ ICQWriteContactSettingByte((HANDLE)wParam,"CheckSelfRemove", 0);
+ }
+ return 0;
+}
+
+int IcqSendtZer(WPARAM wParam, LPARAM lParam) {
+ if (wParam && icqOnline)
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_TZER), NULL, tZersWndProc, (LPARAM)(HANDLE)wParam);
+ return 0;
+}
+
+/*
+ ---------------------------------
+ | Receiving |
+ ---------------------------------
+*/
+
+static void ICQAddRecvEvent(HANDLE hContact, WORD wType, PROTORECVEVENT* pre, DWORD cbBlob, PBYTE pBlob, DWORD flags)
+{
+ if (pre->flags & PREF_CREATEREAD)
+ flags |= DBEF_READ;
+
+ if (hContact && DBGetContactSettingByte(hContact, "CList", "Hidden", 0))
+ {
+ DWORD dwUin;
+ uid_str szUid;
+
+ SetContactHidden(hContact, 0);
+ // if the contact was hidden, add to client-list if not in server-list authed
+ if (!ICQGetContactSettingWord(hContact, "ServerId", 0) || ICQGetContactSettingByte(hContact, "Auth", 0))
+ {
+ ICQGetContactSettingUID(hContact, &dwUin, &szUid);
+ icq_sendNewContact(dwUin, szUid);
+ }
+ }
+
+ ICQAddEvent(hContact, wType, pre->timestamp, flags, cbBlob, pBlob);
+}
+
+
+
+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)
+{
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam;
+ DWORD cbBlob;
+ DWORD flags = 0;
+
+ cbBlob = strlennull(pre->szMessage) + 1;
+ // process utf-8 encoded messages
+ if ((pre->flags & PREF_UTF) && !IsUSASCII(pre->szMessage, strlennull(pre->szMessage)))
+ flags |= DBEF_UTF;
+ // process unicode ucs-2 messages
+ if ((pre->flags & PREF_UNICODE) && !IsUnicodeAscii((WCHAR*)(pre->szMessage+cbBlob), wcslen((WCHAR*)(pre->szMessage+cbBlob))))
+ cbBlob *= (sizeof(WCHAR)+1);
+
+ ICQAddRecvEvent(ccs->hContact, EVENTTYPE_MESSAGE, pre, cbBlob, (PBYTE)pre->szMessage, flags);
+
+ // 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 IcqRecvContacts(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam;
+ ICQSEARCHRESULT** isrList = (ICQSEARCHRESULT**)pre->szMessage;
+ int i;
+ char szUin[UINMAXLEN];
+ DWORD cbBlob = 0;
+ PBYTE pBlob,pCurBlob;
+ DWORD flags = 0;
+
+ for (i = 0; i < pre->lParam; i++)
+ {
+ cbBlob += strlennull(isrList[i]->hdr.nick) + 2; // both trailing zeros
+ if (isrList[i]->uin)
+ cbBlob += getUINLen(isrList[i]->uin);
+ else
+ cbBlob += strlennull(isrList[i]->uid);
+ }
+ pBlob = (PBYTE)_alloca(cbBlob);
+ for (i = 0, pCurBlob = pBlob; i < pre->lParam; i++)
+ {
+ strcpy(pCurBlob, isrList[i]->hdr.nick);
+ pCurBlob += strlennull(pCurBlob) + 1;
+ if (isrList[i]->uin)
+ {
+ _itoa(isrList[i]->uin, szUin, 10);
+ strcpy(pCurBlob, szUin);
+ }
+ else // aim contact
+ strcpy(pCurBlob, isrList[i]->uid);
+ pCurBlob += strlennull(pCurBlob) + 1;
+ }
+ if (pre->flags & PREF_UTF)
+ flags |= DBEF_UTF;
+
+ ICQAddRecvEvent(ccs->hContact, EVENTTYPE_CONTACTS, pre, cbBlob, pBlob, flags);
+
+ return 0;
+}
+
+
+
+int IcqRecvFile(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam;
+ char* szDesc;
+ char* szFile;
+ DWORD cbBlob;
+
+ szFile = pre->szMessage + sizeof(DWORD);
+ szDesc = szFile + strlennull(szFile) + 1;
+
+ cbBlob = sizeof(DWORD) + strlennull(szFile) + strlennull(szDesc) + 2;
+
+ ICQAddRecvEvent(ccs->hContact, EVENTTYPE_FILE, pre, cbBlob, (PBYTE)pre->szMessage, 0);
+
+ return 0;
+}
+
+
+
+int IcqRecvAuth(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam;
+
+ SetContactHidden(ccs->hContact, 0);
+
+ ICQAddRecvEvent(NULL, EVENTTYPE_AUTHREQUEST, pre, pre->lParam, (PBYTE)pre->szMessage, 0);
+
+ return 0;
+}
+int IcqAddCapability(WPARAM wParam, LPARAM lParam)
+{
+ ICQ_CUSTOMCAP *icqCustomCapIn = (ICQ_CUSTOMCAP *)lParam;
+ ICQ_CUSTOMCAP *icqCustomCap = (ICQ_CUSTOMCAP *)malloc(sizeof(ICQ_CUSTOMCAP));
+ memcpy(icqCustomCap, icqCustomCapIn, sizeof(ICQ_CUSTOMCAP));
+ listInterface.List_Insert(lstCustomCaps, icqCustomCap, lstCustomCaps->realCount);
+// MessageBoxA(NULL, ((ICQ_CUSTOMCAP *)(lstCustomCaps->items[lstCustomCaps->realCount-1]))->name, "custom cap", MB_OK);
+ return 0;
+}
+
+int IcqCheckCapability(WPARAM wParam, LPARAM lParam)
+{
+ int res = 0;
+ DBCONTACTGETSETTING dbcgs;
+ DBVARIANT dbvariant;
+ HANDLE hContact = (HANDLE)wParam;
+ ICQ_CUSTOMCAP *icqCustomCap = (ICQ_CUSTOMCAP *)lParam;
+ dbcgs.pValue = &dbvariant;
+ dbcgs.szModule = gpszICQProtoName;
+ dbcgs.szSetting = "CapBuf";
+
+
+ if (dbvariant.type == DBVT_BLOB)
+ {
+ res = MatchCap(dbvariant.pbVal, dbvariant.cpbVal, &icqCustomCap->caps, 0x10)?1:0;
+ }
+
+ CallService(MS_DB_CONTACT_FREEVARIANT,0,(LPARAM)(DBVARIANT*)&dbvariant);
+
+ return res;
+}
\ No newline at end of file diff --git a/icqj_s7_sss_mod/icqosc_svcs.h b/icqj_s7_sss_mod/icqosc_svcs.h new file mode 100644 index 0000000..9feee99 --- /dev/null +++ b/icqj_s7_sss_mod/icqosc_svcs.h @@ -0,0 +1,100 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 51 $
+// Last change on : $Date: 2007-08-30 23:46:51 +0300 (Чт, 30 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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 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 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 IcqSendtZer(WPARAM,LPARAM);
+int IcqSendAuthRequest(WPARAM,LPARAM);
+int IcqSendYouWereAdded(WPARAM,LPARAM);
+int IcqSendUserIsTyping(WPARAM wParam, LPARAM lParam);
+int IcqAddServerContact(WPARAM wParam, LPARAM lParam);
+
+
+int IcqRecvMessage(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 IcqGetAvatarCaps(WPARAM wParam, LPARAM lParam);
+int IcqGetMyAvatar(WPARAM wParam, LPARAM lParam);
+int IcqSetMyAvatar(WPARAM wParam, LPARAM lParam);
+
+int IcqSetPassword(WPARAM wParam, LPARAM lParam);
+
+int IcqAddCapability(WPARAM wParam, LPARAM lParam);
+int IcqCheckCapability(WPARAM wParam, LPARAM lParam);
+
+int iIcqNewStatus;
+#endif /* __ICQOSC_SVCS_H */
diff --git a/icqj_s7_sss_mod/icqoscar.c b/icqj_s7_sss_mod/icqoscar.c new file mode 100644 index 0000000..b84ef87 --- /dev/null +++ b/icqj_s7_sss_mod/icqoscar.c @@ -0,0 +1,44 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/icqoscar.h b/icqj_s7_sss_mod/icqoscar.h new file mode 100644 index 0000000..335f896 --- /dev/null +++ b/icqj_s7_sss_mod/icqoscar.h @@ -0,0 +1,161 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 51 $
+// Last change on : $Date: 2007-08-30 23:46:51 +0300 (Чт, 30 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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.
+
+#define _USE_32BIT_TIME_T
+#pragma warning(disable: 4996)
+
+#define MIRANDA_VER 0x700
+#define ICQ_MODNAME "Plus"
+
+#include "m_stdhdr.h"
+
+// Windows includes
+#include <windows.h>
+#include <commctrl.h>
+//#include <shlwapi.h>
+
+// Standard includes
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <direct.h>
+#include <fcntl.h>
+#ifndef _DEBUG
+ #include <crtdbg.h>
+#endif
+#include <process.h>
+#include <malloc.h>
+
+#include "changeinfo/changeinfo.h"
+// Miranda IM SDK includes
+#include <newpluginapi.h> // This must be included first
+#include <m_awaymsg.h>
+#include <m_button.h>
+#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_ignore.h>
+#include <m_avatars.h>
+#include <m_skin.h>
+#include <m_system.h>
+#include <win2k.h>
+//other plugins api
+#include "m_fingerprint.h"
+#include "m_assocmgr.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 "icq_packet.h"
+#include "icq_direct.h"
+#include "oscar_filetransfer.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 "icq_infoupdate.h"
+#include "icq_avatar.h"
+#include "guids.h"
+#include "capabilities.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 "icq_reguin.h"
+#include "UI/askauthentication.h"
+#include "UI/userinfotab.h"
+#include "UI/loginpassword.h"
+
+#include "icq_rates.h"
+
+#include "icq_popups.h"
+#include "iconlib.h"
+
+#include "icq_tzers.h"
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+
+#define TTS_BALLOON 0x40
+#define TTM_SETTITLE (WM_USER + 32)
+
+#endif
+
+#ifndef CDSIZEOF_STRUCT
+#define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
+#endif
+
+// :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_s7_sss_mod/icqoscar8.dep b/icqj_s7_sss_mod/icqoscar8.dep new file mode 100644 index 0000000..459a333 --- /dev/null +++ b/icqj_s7_sss_mod/icqoscar8.dep @@ -0,0 +1,77 @@ +# 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_clistint.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"\
+ ".\cookies.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_s7_sss_mod/icqoscar8.dsp b/icqj_s7_sss_mod/icqoscar8.dsp new file mode 100644 index 0000000..d0d7f6e --- /dev/null +++ b/icqj_s7_sss_mod/icqoscar8.dsp @@ -0,0 +1,794 @@ +# 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/ICQJ_BM", 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 1
+# 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" /I "./" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR /YX /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 /pdb:none /machine:I386 /out:"../../bin/release/plugins/ICQ.dll" /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /map /debug
+
+!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=.\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_reguin.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_proto.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_icolib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\m_icq.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\m_popupw.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\m_updater.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
+# Begin Source File
+
+SOURCE=.\icos\xstatus33.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus34.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus35.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus36.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus37.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=.\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_caps_list.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_reguin.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_srv_list.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_tzers.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=.\oscar_filetransfer.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_s7_sss_mod/icqoscar8.dsw b/icqj_s7_sss_mod/icqoscar8.dsw new file mode 100644 index 0000000..233a2d6 --- /dev/null +++ b/icqj_s7_sss_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_s7_sss_mod/icqoscar8.mak b/icqj_s7_sss_mod/icqoscar8.mak new file mode 100644 index 0000000..ba2ef6c --- /dev/null +++ b/icqj_s7_sss_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_s7_sss_mod/icqoscar8.sln b/icqj_s7_sss_mod/icqoscar8.sln new file mode 100644 index 0000000..b11cf67 --- /dev/null +++ b/icqj_s7_sss_mod/icqoscar8.sln @@ -0,0 +1,55 @@ +Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "icqoscar8_Plus", "icqoscar8.vcproj", "{8BAA8998-A967-4935-8220-3673DBF425A7}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xstatus_icons", "icons_pack\ICONS.vcproj", "{47204E10-B438-4DFD-B115-E0F5A3F8A05E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release(sse2)|Win32 = Release(sse2)|Win32
+ Release(static)(sse2)|Win32 = Release(static)(sse2)|Win32
+ Release(static)|Win32 = Release(static)|Win32
+ Release(win98)(static)|Win32 = Release(win98)(static)|Win32
+ Release(win98)|Win32 = Release(win98)|Win32
+ Release|Win32 = Release|Win32
+ Working(sse2, some debug symbols)|Win32 = Working(sse2, some debug symbols)|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(sse2)|Win32.ActiveCfg = Release(sse2)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release(sse2)|Win32.Build.0 = Release(sse2)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release(static)(sse2)|Win32.ActiveCfg = Release(static)(sse2)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release(static)(sse2)|Win32.Build.0 = Release(static)(sse2)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release(static)|Win32.ActiveCfg = Release(static)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release(static)|Win32.Build.0 = Release(static)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release(win98)(static)|Win32.ActiveCfg = Release(win98)(static)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release(win98)(static)|Win32.Build.0 = Release(win98)(static)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release(win98)|Win32.ActiveCfg = Release(win98)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release(win98)|Win32.Build.0 = Release(win98)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release|Win32.ActiveCfg = Release|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Release|Win32.Build.0 = Release|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Working(sse2, some debug symbols)|Win32.ActiveCfg = Working(sse2, some debug symbols)|Win32
+ {8BAA8998-A967-4935-8220-3673DBF425A7}.Working(sse2, some debug symbols)|Win32.Build.0 = Working(sse2, some debug symbols)|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(sse2)|Win32.ActiveCfg = Release(sse2)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release(sse2)|Win32.Build.0 = Release(sse2)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release(static)(sse2)|Win32.ActiveCfg = Release(static)(sse2)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release(static)(sse2)|Win32.Build.0 = Release(static)(sse2)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release(static)|Win32.ActiveCfg = Release(static)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release(static)|Win32.Build.0 = Release(static)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release(win98)(static)|Win32.ActiveCfg = Release(win98)(static)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release(win98)(static)|Win32.Build.0 = Release(win98)(static)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release(win98)|Win32.ActiveCfg = Release(win98)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release(win98)|Win32.Build.0 = Release(win98)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release|Win32.ActiveCfg = Release|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Release|Win32.Build.0 = Release|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Working(sse2, some debug symbols)|Win32.ActiveCfg = Working(sse2, some debug symbols)|Win32
+ {47204E10-B438-4DFD-B115-E0F5A3F8A05E}.Working(sse2, some debug symbols)|Win32.Build.0 = Working(sse2, some debug symbols)|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/icqj_s7_sss_mod/icqoscar8.vcproj b/icqj_s7_sss_mod/icqoscar8.vcproj new file mode 100644 index 0000000..b66bdcb --- /dev/null +++ b/icqj_s7_sss_mod/icqoscar8.vcproj @@ -0,0 +1,4212 @@ +<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="icqoscar8_Plus"
+ ProjectGUID="{8BAA8998-A967-4935-8220-3673DBF425A7}"
+ RootNamespace="icqoscar8"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ManagedExtensions="0"
+ 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="false"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="true"
+ EnableFiberSafeOptimizations="true"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="0"
+ SmallerTypeCheck="false"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ EnableEnhancedInstructionSet="0"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"
+ AssemblerListingLocation="$(IntDir)\"
+ ObjectFile="$(IntDir)\"
+ ProgramDataBaseFileName="$(IntDir)\"
+ BrowseInformation="0"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="false"
+ UseLibraryDependencyInputs="false"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ LinkIncremental="0"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories=""
+ IgnoreAllDefaultLibraries="false"
+ IgnoreDefaultLibraryNames=""
+ GenerateDebugInformation="false"
+ GenerateMapFile="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ OptimizeForWindows98="1"
+ LinkTimeCodeGeneration="1"
+ EntryPointSymbol=""
+ BaseAddress="0x25000000"
+ 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="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ 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="D:\temp\icqj_s7_sss_mod;D:\temp\svn\mir_06\miranda\include;E:\cplus\mAPI"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ PrecompiledHeaderFile=".\Debug/icqoscar8.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <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="$(OutDir)\icq.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ GenerateMapFile="true"
+ 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>
+ <Configuration
+ Name="Release (static)|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ 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="1"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="true"
+ EnableFiberSafeOptimizations="true"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include;./;D:\temp\icqj_s7_sss_mod;D:\temp\svn\mir_06\miranda\include;E:\cplus\mAPI"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="true"
+ EnableEnhancedInstructionSet="0"
+ FloatingPointExceptions="false"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderThrough="icqoscar.h"
+ PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"
+ AssemblerListingLocation="$(IntDir)\"
+ ObjectFile="$(IntDir)\"
+ ProgramDataBaseFileName="$(IntDir)\"
+ BrowseInformation="0"
+ WarningLevel="3"
+ 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 shlwapi.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="false"
+ GenerateMapFile="true"
+ MapFileName="$(IntDir)\$(ProjectName).map"
+ BaseAddress="0x25000000"
+ 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="Release(static)|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="true"
+ EnableFiberSafeOptimizations="false"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BufferSecurityCheck="true"
+ EnableFunctionLevelLinking="false"
+ EnableEnhancedInstructionSet="1"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="true"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ OptimizeForWindows98="1"
+ 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>
+ <Configuration
+ Name="Release(win98)|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="true"
+ EnableFiberSafeOptimizations="false"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="true"
+ EnableEnhancedInstructionSet="0"
+ FloatingPointModel="0"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="true"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ LargeAddressAware="1"
+ TerminalServerAware="0"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ OptimizeForWindows98="2"
+ LinkTimeCodeGeneration="1"
+ 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>
+ <Configuration
+ Name="Release(static)(sse2)|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="true"
+ EnableFiberSafeOptimizations="false"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BufferSecurityCheck="true"
+ EnableEnhancedInstructionSet="2"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="true"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ OptimizeForWindows98="1"
+ 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>
+ <Configuration
+ Name="Release(sse2)|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ManagedExtensions="0"
+ 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="false"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="true"
+ EnableFiberSafeOptimizations="false"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="0"
+ SmallerTypeCheck="false"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ EnableEnhancedInstructionSet="2"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"
+ AssemblerListingLocation="$(IntDir)\"
+ ObjectFile="$(IntDir)\"
+ ProgramDataBaseFileName="$(IntDir)\"
+ BrowseInformation="0"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="false"
+ UseLibraryDependencyInputs="false"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ LinkIncremental="0"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories=""
+ IgnoreAllDefaultLibraries="false"
+ IgnoreDefaultLibraryNames=""
+ GenerateDebugInformation="false"
+ GenerateMapFile="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ OptimizeForWindows98="1"
+ LinkTimeCodeGeneration="1"
+ EntryPointSymbol=""
+ BaseAddress="0x25000000"
+ 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="Working(sse2, some debug symbols)|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ManagedExtensions="0"
+ 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="false"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="false"
+ EnableFiberSafeOptimizations="false"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="false"
+ MinimalRebuild="false"
+ ExceptionHandling="1"
+ BasicRuntimeChecks="0"
+ SmallerTypeCheck="false"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="true"
+ EnableFunctionLevelLinking="false"
+ EnableEnhancedInstructionSet="2"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"
+ AssemblerListingLocation="$(IntDir)\"
+ ObjectFile="$(IntDir)\"
+ ProgramDataBaseFileName="$(IntDir)\"
+ BrowseInformation="0"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="false"
+ UseLibraryDependencyInputs="false"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ LinkIncremental="0"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories=""
+ IgnoreAllDefaultLibraries="false"
+ IgnoreDefaultLibraryNames=""
+ GenerateDebugInformation="true"
+ GenerateMapFile="true"
+ SubSystem="2"
+ OptimizeForWindows98="1"
+ LinkTimeCodeGeneration="1"
+ EntryPointSymbol=""
+ BaseAddress="0x25000000"
+ 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="Release(win98)(static)|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="true"
+ EnableFiberSafeOptimizations="false"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BufferSecurityCheck="true"
+ EnableEnhancedInstructionSet="0"
+ FloatingPointModel="0"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="true"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ LargeAddressAware="1"
+ TerminalServerAware="0"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ OptimizeForWindows98="2"
+ LinkTimeCodeGeneration="1"
+ 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="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\dc.ICO"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\dot.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\changeinfo\expandst.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\hidden.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\icon1.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\icq.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\incognito_request.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\srvlist_add.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\start.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\stop.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icos\tzer.ico"
+ >
+ </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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_caps_list.c"
+ >
+ </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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_srv_list.c"
+ >
+ </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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Change Info"
+ >
+ <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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="UI\askauthentication.h"
+ >
+ </File>
+ <File
+ RelativePath="capabilities.h"
+ >
+ </File>
+ <File
+ RelativePath="changeinfo\changeinfo.h"
+ >
+ </File>
+ <File
+ RelativePath="channels.h"
+ >
+ </File>
+ <File
+ RelativePath="cookies.h"
+ >
+ </File>
+ <File
+ RelativePath="directpackets.h"
+ >
+ </File>
+ <File
+ RelativePath="families.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_tzers.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_folders.h"
+ >
+ </File>
+ <File
+ RelativePath="m_icq.h"
+ >
+ </File>
+ <File
+ RelativePath=".\m_updater.h"
+ >
+ </File>
+ <File
+ RelativePath="md5.h"
+ >
+ </File>
+ <File
+ RelativePath=".\oscar_filetransfer.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="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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_reguin.c"
+ >
+ </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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_tzers.c"
+ >
+ </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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(win98)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(static)(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(win98)(static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\isee.c"
+ >
+ </File>
+ <File
+ RelativePath=".\oscar_filetransfer.c"
+ >
+ </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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|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>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release(sse2)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Working(sse2, some debug symbols)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/icqj_s7_sss_mod/icqoscar8.vcproj.vspscc b/icqj_s7_sss_mod/icqoscar8.vcproj.vspscc new file mode 100644 index 0000000..feffdec --- /dev/null +++ b/icqj_s7_sss_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_s7_sss_mod/init.c b/icqj_s7_sss_mod/init.c new file mode 100644 index 0000000..3735d33 --- /dev/null +++ b/icqj_s7_sss_mod/init.c @@ -0,0 +1,1069 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 62 $
+// Last change on : $Date: 2007-10-16 14:56:05 +0300 (Вт, 16 окт 2007) $
+// Last change by : $Author: chaos.persei $
+//
+// DESCRIPTION:
+//
+// Miranda init file - exported functions of plugin
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "isee.h"
+
+#include "m_updater.h"
+
+
+PLUGINLINK* pluginLink;
+struct MM_INTERFACE mmi;
+struct MD5_INTERFACE md5i;
+HANDLE hHookUserInfoInit = NULL;
+HANDLE hHookOptionInit = NULL;
+HANDLE hHookUserMenu = NULL;
+HANDLE hHookIdleEvent = NULL;
+HANDLE hHookIconsChanged = NULL;
+static HANDLE hUserMenuAddServ = NULL;
+static HANDLE hUserMenuAuth = NULL;
+static HANDLE hUserMenuGrant = NULL;
+static HANDLE hUserMenuRevoke = NULL;
+static HANDLE hUserMenuXStatus = NULL;
+HANDLE hIconProtocol = NULL;
+static HANDLE hIconMenuAuth = NULL;
+static HANDLE hIconMenuGrant = NULL;
+static HANDLE hIconMenuRevoke = NULL;
+static HANDLE hIconMenuAddServ = NULL;
+static HANDLE hUserMenuSetVis = NULL;
+static HANDLE hUserMenuSetInvis = NULL;
+static HANDLE hUserMenuIncognito = NULL;
+static HANDLE hUserMenuSendtZer = NULL;
+HANDLE hPopUpsList = NULL;
+HANDLE hUserMenuStatus = NULL;
+
+extern HANDLE hServerConn;
+CRITICAL_SECTION localSeqMutex;
+CRITICAL_SECTION connectionHandleMutex;
+HANDLE hsmsgrequest;
+HANDLE hxstatuschanged;
+HANDLE hxstatusiconchanged;
+//popup settings
+BOOL bPopUpService = FALSE;
+BOOL bPopUpsEnabled = FALSE;
+BOOL bSpamPopUp = FALSE;
+BOOL bUnknownPopUp = FALSE;
+BOOL bFoundPopUp = TRUE;
+BOOL bScanPopUp = TRUE;
+BOOL bClientChangePopUp = FALSE;
+BOOL bVisPopUp = TRUE;
+BOOL bPopUpForNotOnList = FALSE;
+BOOL bPopSelfRem = TRUE;
+BOOL bIgnoreCheckPop = TRUE;
+BOOL bInfoRequestPopUp = FALSE;
+BOOL bAuthPopUp = FALSE;
+BOOL bXUpdaterPopUp = FALSE;
+BOOL bUinPopup = FALSE;
+//visibility variable
+BYTE bVisibility = 0;
+BOOL bIncognitoRequest = FALSE;
+BOOL bIncognitoGlobal = FALSE;
+BOOL bShowAuth = FALSE;
+//BOOL bStealthRequest = FALSE;
+BOOL bPSD = TRUE;
+BYTE gbASD = 0;
+BOOL bExcludePSD = FALSE;
+BOOL bNoASD = TRUE;
+BOOL bNoPSDForHidden = TRUE;
+BOOL bNoStatusReply = FALSE;
+//xstatus settings
+BOOL bXstatusIconShow = TRUE;
+//loging options
+BOOL bLogSelfRemoveFile = FALSE;
+BOOL bLogIgnoreCheckFile = FALSE;
+BOOL bLogStatusCheckFile = FALSE;
+BOOL bLogASDFile = FALSE;
+BOOL bLogClientChangeFile = FALSE;
+BOOL bLogAuthFile = FALSE;
+BOOL bLogInfoRequestFile = FALSE;
+BOOL bLogSelfRemoveHistory = FALSE;
+BOOL bLogIgnoreCheckHistory = FALSE;
+BOOL bLogStatusCheckHistory = FALSE;
+BOOL bLogASDHistory = FALSE;
+BOOL bLogClientChangeHistory = FALSE;
+BOOL bLogAuthHistory = FALSE;
+BOOL bLogInfoRequestHistory = FALSE;
+BOOL bHcontactHistory = FALSE;
+//ASD settings
+BOOL bASDViaAwayMsg = FALSE;
+BOOL bASDViaXtraz = FALSE;
+BOOL bASDViaURL = FALSE;
+BOOL bASDUnauthorized = FALSE; //work in progress
+BOOL bASDViaAuth = FALSE; //work in progress
+//other settings
+BOOL bTmpContacts = FALSE;
+BOOL gbSecureIM = FALSE;
+char* TmpGroupName = 0;
+BOOL bAddTemp = FALSE;
+BOOL bServerAutoChange = TRUE;
+WORD wClass;
+char szHttpUserAgent[255];
+
+extern int bHideXStatusUI;
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "IcqOscarJ (" ICQ_MODNAME " Mod) Protocol [build #98 (rc 2)]",
+ PLUGIN_MAKE_VERSION(0,3,8,105),
+ "Support for ICQ network, enhanced.",
+ "J.Kucera, Bio, M.berg, R.Hughes, Jon Keating, Faith, S7, BM, sss, chaos.persei, ghazan, baloo, nullbie etc",
+ "sss123next@list.ru, chaos.persei@gmail.com, sin@miranda-me.org, jokusoftware@miranda-im.org",
+ "(C) 2000-2007 M. berg, R.Hughes, J.Keating, Bio, J.Kucera, Angeli-Ka, Faith Healer, chaos.persei, Se7ven, BM, sss, [sin], nullbie and others",
+ "http://dev.mirandaim.ru/sss",
+ 0,
+ 0, //doesn't replace anything built-in
+ { 0xc78614bf, 0x878e, 0x43e4, { 0xa3, 0xf4, 0xa, 0xf9, 0x9a, 0xa5, 0x7a, 0x78 } }
+};
+
+
+struct LIST_INTERFACE listInterface;
+SortedList *lstCustomCaps;
+
+
+static char UnicodeAware[32];
+
+
+static int OnSystemModulesLoaded(WPARAM wParam,LPARAM lParam);
+static int OnSystemPreShutdown(WPARAM wParam,LPARAM lParam);
+static int icq_PrebuildContactMenu(WPARAM wParam, LPARAM lParam);
+static int IconLibIconsChanged(WPARAM wParam, LPARAM lParam);
+
+
+static BOOL bInited = FALSE;
+
+__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 7, 0, 30))
+ {
+ MessageBox( NULL, "ICQ plugin cannot be loaded. It requires Miranda IM 0.7.0.30 or later.", "ICQ Plugin",
+ MB_OK|MB_ICONWARNING|MB_SETFOREGROUND|MB_TOPMOST );
+ return NULL;
+ }
+ else
+ {
+ // Are we running under Unicode Windows version ?
+ gbUnicodeAPI = (GetVersion() & 0x80000000) == 0;
+ if (gbUnicodeAPI)
+ {
+ pluginInfo.flags = 1;
+ }
+ MIRANDA_VERSION = mirandaVersion;
+ bInited = TRUE;
+ }
+
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_PROTOCOL, MIID_LAST};
+__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+
+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);
+}
+
+static HANDLE ICQCreateHookableEvent(const char* szEvent)
+{
+ char str[MAX_PATH + 32];
+ strcpy(str, gpszICQProtoName);
+ strcat(str, szEvent);
+ return CreateHookableEvent(str);
+}
+
+
+static int EnumCustomCapsProc(const char *szSetting,LPARAM lParam)
+{
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING dbcgs;
+ dbcgs.szModule = (char *)lParam;
+ dbcgs.szSetting = szSetting;
+ dbcgs.pValue = &dbv;
+ CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&dbcgs);
+ if (dbv.type == DBVT_BLOB)
+ {
+ ICQ_CUSTOMCAP icqCustomCap;
+ icqCustomCap.cbSize = sizeof(icqCustomCap);
+ strncpy(icqCustomCap.name, szSetting, 64);
+ memcpy(icqCustomCap.caps, dbv.pbVal, min(0x10, dbv.cpbVal));
+ CallProtoService(gpszICQProtoName, PS_ICQ_ADDCAPABILITY, 0, (LPARAM)&icqCustomCap);
+ } else
+ if (dbv.type == DBVT_ASCIIZ)
+ {
+ ICQ_CUSTOMCAP icqCustomCap;
+ icqCustomCap.cbSize = sizeof(icqCustomCap);
+ strncpy(icqCustomCap.name, szSetting, 64);
+ strncpy(icqCustomCap.caps, dbv.pszVal, 0x10);
+ CallProtoService(gpszICQProtoName, PS_ICQ_ADDCAPABILITY, 0, (LPARAM)&icqCustomCap);
+ }
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ return 0;
+}
+
+void RegEventType(int EventType, char* EventDescription)
+{
+ DBEVENTTYPEDESCR evt;
+ evt.cbSize=sizeof(evt);
+ evt.module=gpszICQProtoName;
+ evt.eventType=EventType;
+ evt.descr=EventDescription;
+ CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&evt);
+}
+
+void InitVars()
+{
+ bSpamPopUp = ICQGetContactSettingByte(NULL,"SpamPopUpEnabled",1);
+ bUnknownPopUp = ICQGetContactSettingByte(NULL,"UnknownPopUpEnabled",1);
+ bFoundPopUp = ICQGetContactSettingByte(NULL,"FoundPopUpEnabled",1);
+ bScanPopUp = ICQGetContactSettingByte(NULL,"ScanPopUpEnabled",1);
+ bVisPopUp = ICQGetContactSettingByte(NULL,"VisPopUpEnabled",1);
+ bClientChangePopUp = ICQGetContactSettingByte(NULL,"ClientChangePopup",0);
+ bPopUpForNotOnList = ICQGetContactSettingByte(NULL,"PopUpForNotOnList",0);
+ bPopUpsEnabled = ICQGetContactSettingByte(NULL, "PopupsEnabled", 1);
+ bXstatusIconShow = ICQGetContactSettingByte(NULL, "XStatusIconShow", 1);
+ bIgnoreCheckPop = ICQGetContactSettingByte(NULL, "IgnoreCheckPop", 1);
+ bPopSelfRem = ICQGetContactSettingByte(NULL, "PopSelfRem", 1);
+ bInfoRequestPopUp = ICQGetContactSettingByte(NULL, "InfoRequestPopUp", 0);
+ bAuthPopUp = ICQGetContactSettingByte(NULL, "AuthPopUp", 0);
+ bXUpdaterPopUp = ICQGetContactSettingByte(NULL, "XUpdaterPopUp", 0);
+ bPSD = ICQGetContactSettingByte(NULL, "PSD", 1);
+ bNoASD = ICQGetContactSettingByte(NULL, "NoASD", 1);
+ bLogSelfRemoveFile = ICQGetContactSettingByte(NULL, "LogSelfRemoveFile", 0);
+ bLogIgnoreCheckFile = ICQGetContactSettingByte(NULL, "LogIgnoreCheckFile", 0);
+ bLogStatusCheckFile = ICQGetContactSettingByte(NULL, "LogStatusCheckFile", 0);
+ bLogASDFile = ICQGetContactSettingByte(NULL, "LogASDFile", 0);
+ bLogClientChangeFile = ICQGetContactSettingByte(NULL, "LogClientChangeFile", 0);
+ bLogAuthFile = ICQGetContactSettingByte(NULL, "LogAuthFile", 0);
+ bLogInfoRequestFile = ICQGetContactSettingByte(NULL, "LogRequestFile", 0);
+ bLogSelfRemoveHistory = ICQGetContactSettingByte(NULL, "LogSelfRemoveHistory", 0);
+ bLogIgnoreCheckHistory = ICQGetContactSettingByte(NULL, "LogIgnoreCheckHistory", 0);
+ bLogStatusCheckHistory = ICQGetContactSettingByte(NULL, "LogStatusCheckHistory", 0);
+ bLogASDHistory = ICQGetContactSettingByte(NULL, "LogASDHistory", 0);
+ bLogClientChangeHistory = ICQGetContactSettingByte(NULL, "LogClientChangeHistory", 0);
+ bLogAuthHistory = ICQGetContactSettingByte(NULL, "LogAuthHistory", 0);
+ bLogInfoRequestHistory = ICQGetContactSettingByte(NULL, "LogRequestHistory", 0);
+ bHcontactHistory = ICQGetContactSettingByte(NULL,"LogToHcontact",0);
+ bTmpContacts = ICQGetContactSettingByte(NULL, "TempContacts", 0);
+ TmpGroupName = UniGetContactSettingUtf(NULL,gpszICQProtoName,"TmpContactsGroup", Translate("General"));
+ bAddTemp = ICQGetContactSettingByte(NULL, "AddTemp", 0);
+ bNoStatusReply = ICQGetContactSettingByte(NULL,"NoStatusReply", 0);
+ bServerAutoChange = ICQGetContactSettingByte(NULL,"ServerAutoChange", 1);
+ bIncognitoGlobal = ICQGetContactSettingByte(NULL, "IncognitoGlobal", 0);
+ bShowAuth = ICQGetContactSettingByte(NULL, "ShowAuth", 0);
+ bUinPopup = ICQGetContactSettingByte(NULL, "UinPopup", 0);
+ bNoPSDForHidden = ICQGetContactSettingByte(NULL, "NoPSDForHidden", 1);
+ gbASD = ICQGetContactSettingByte(NULL, "ASD", 0);
+ bASDViaAwayMsg = ICQGetContactSettingByte(NULL, "bASDViaAwayMsg", 0);
+ bASDViaXtraz = ICQGetContactSettingByte(NULL, "bASDViaXtraz", 0);
+ bASDViaURL = ICQGetContactSettingByte(NULL, "bASDViaURL", 0);
+ bASDUnauthorized = ICQGetContactSettingByte(NULL, "bASDUnauthorized", 0);
+ bASDViaAuth = ICQGetContactSettingByte(NULL, "bASDViaAuth", 0);
+ strcpy(szHttpUserAgent, ICQGetContactSettingUtf(NULL, "HttpUserAgent", "Mozilla/4.08 [en] (WinNT; U ;Nav)"));
+// if(ICQGetContactSettingByte(NULL, "StealthRequest", 0) == 1)
+// bStealthRequest = TRUE;
+}
+
+
+int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ PROTOCOLDESCRIPTOR pd = {0};
+ extern void icq_BuildPrivacyMenu();
+
+ pluginLink = link;
+ mir_getMMI( &mmi );
+ mir_getMD5I( &md5i );
+
+ ghServerNetlibUser = NULL;
+
+
+
+ // Are we running under Unicode Windows version ?
+ gbUnicodeAPI = (GetVersion() & 0x80000000) == 0;
+ { // Are we running under unicode Miranda core ?
+ char szVer[MAX_PATH];
+
+ CallService(MS_SYSTEM_GETVERSIONTEXT, MAX_PATH, (LPARAM)szVer);
+ _strlwr(szVer); // make sure it is lowercase
+ gbUnicodeCore = (strstr(szVer, "unicode") != NULL);
+
+ if (strstr(szVer, "alpha") != NULL)
+ { // Are we running under Alpha Core
+ MIRANDA_VERSION |= 0x80000000;
+ }
+ else if (MIRANDA_VERSION >= 0x00050000 && strstr(szVer, "preview") == NULL)
+ { // for Final Releases of Miranda 0.5+ clear build number
+ MIRANDA_VERSION &= 0xFFFFFF00;
+ }
+ }
+
+ 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));
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, OnSystemModulesLoaded);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, OnSystemPreShutdown);
+
+ InitializeCriticalSection(&connectionHandleMutex);
+ InitializeCriticalSection(&localSeqMutex);
+ InitializeCriticalSection(&modeMsgsMutex);
+
+ // Initialize core modules
+ InitDB(); // DB interface
+ InitVars(); // global variables
+ InitCookies(); // cookie utils
+ InitCache(); // contacts cache
+ InitReguin(); // reguin module
+
+ DBWriteContactSettingDword(NULL, gpszICQProtoName, "SrvLastUpdate", 0);
+ DBWriteContactSettingWord(NULL, gpszICQProtoName, "SrvRecordCount", 0);
+
+ 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));
+
+ // Initialize temporary DB settings
+ ICQCreateResidentSetting("Status"); // NOTE: XStatus cannot be temporary
+ ICQCreateResidentSetting("TemporaryVisible");
+ ICQCreateResidentSetting("TickTS");
+ ICQCreateResidentSetting("IdleTS");
+ ICQCreateResidentSetting("LogonTS");
+ ICQCreateResidentSetting("CapBuf");
+ ICQCreateResidentSetting("DCStatus");
+
+ // 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_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_CONTACTS, IcqRecvContacts);
+ ICQCreateServiceFunction(PSR_AUTH, IcqRecvAuth);
+ ICQCreateServiceFunction(PSS_AUTHREQUEST, IcqSendAuthRequest);
+ ICQCreateServiceFunction(PSS_ADDED, IcqSendYouWereAdded);
+ ICQCreateServiceFunction(PSS_USERISTYPING, IcqSendUserIsTyping);
+ // Session password API
+ ICQCreateServiceFunction(PS_ICQ_SETPASSWORD, IcqSetPassword);
+ // ChangeInfo API
+ ICQCreateServiceFunction(PS_CHANGEINFOEX, IcqChangeInfoEx);
+ // Avatar API
+ ICQCreateServiceFunction(PS_GETAVATARINFO, IcqGetAvatarInfo);
+ ICQCreateServiceFunction(PS_GETAVATARCAPS, IcqGetAvatarCaps);
+ ICQCreateServiceFunction(PS_GETMYAVATAR, IcqGetMyAvatar);
+ ICQCreateServiceFunction(PS_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);
+ ICQCreateServiceFunction(PS_ICQ_GETADVANCEDSTATUSICON, IcqRequestAdvStatusIconIdx);
+ // Custom caps
+ ICQCreateServiceFunction(PS_ICQ_ADDCAPABILITY, IcqAddCapability);
+ ICQCreateServiceFunction(PS_ICQ_CHECKCAPABILITY, IcqCheckCapability);
+
+
+
+ hsmsgrequest = ICQCreateHookableEvent(ME_ICQ_STATUSMSGREQ);
+ hxstatuschanged = ICQCreateHookableEvent(ME_ICQ_CUSTOMSTATUS_CHANGED);
+ hxstatusiconchanged = ICQCreateHookableEvent(ME_ICQ_CUSTOMSTATUS_EXTRAICON_CHANGED);
+
+ InitDirectConns();
+ InitOscarFileTransfer();
+ InitServerLists();
+ icq_InitInfoUpdate();
+ RegEventType(ICQEVENTTYPE_IGNORECHECK_STATUS, "Check ICQ Ignore State");
+ RegEventType(ICQEVENTTYPE_CHECK_STATUS, "Check ICQ Status");
+ RegEventType(ICQEVENTTYPE_CLIENT_CHANGE, "Chenge ICQ Client");
+ RegEventType(ICQEVENTTYPE_SELF_REMOVE, "ICQ Contact SelfRemove");
+ RegEventType(ICQEVENTTYPE_AUTH_DENIED, "ICQ Auth Denied");
+ RegEventType(ICQEVENTTYPE_AUTH_GRANTED, "ICQ Auth Granted");
+ RegEventType(ICQEVENTTYPE_AUTH_REQUESTED, "ICQ Auth Requested");
+ RegEventType(ICQEVENTTYPE_YOU_ADDED, "ICQ You Added");
+ RegEventType(ICQEVENTTYPE_WAS_FOUND, "Detected via ASD\\PSD");
+
+
+ icq_InitISee();
+
+ // Initialize charset conversion routines
+ InitI18N();
+
+ UpdateGlobalSettings();
+
+ gnCurrentStatus = ID_STATUS_OFFLINE;
+
+ ICQCreateServiceFunction(MS_ICQ_ADDSERVCONTACT, IcqAddServerContact);
+
+ 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_INCOGNITO_REQUEST, IncognitoAwayRequest);
+ ICQCreateServiceFunction(MS_SEND_TZER, IcqSendtZer);
+
+ ICQCreateServiceFunction(MS_XSTATUS_SHOWDETAILS, IcqShowXStatusDetails);
+
+ hHookIconsChanged = IconLibHookIconsChanged(IconLibIconsChanged);
+
+ InitXStatusIcons();
+
+ // This must be here - the events are called too early, WTF?
+ InitXStatusEvents();
+
+ if (DBGetContactSettingByte(NULL, gpszICQProtoName, "PrivacyMenu", DEFAULT_PRIVACY_ENABLED))
+ icq_BuildPrivacyMenu();
+
+
+
+ //Custom caps
+ mir_getLI(&listInterface);
+ lstCustomCaps = listInterface.List_Create(0,1);
+ lstCustomCaps->sortFunc = NULL;
+
+ {
+ char tmp[MAXMODULELABELLENGTH];
+ DBCONTACTENUMSETTINGS dbces;
+ mir_snprintf(tmp, MAXMODULELABELLENGTH, "%sCaps", gpszICQProtoName);
+ dbces.pfnEnumProc = EnumCustomCapsProc;
+ dbces.lParam = (LPARAM)tmp;
+ dbces.szModule = tmp;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS, 0, (LPARAM)&dbces);
+ }
+
+
+
+ ICQCreateThread(icq_XStatusUpdaterThread, NULL);
+
+/*
+ {
+ ICQ_CUSTOMCAP icqCustomCap;
+ IcqBuildMirandaCap(&icqCustomCap, "Miranda ICQ Capability Test", NULL, "TestTest");
+ CallProtoService(gpszICQProtoName, PS_ICQ_ADDCAPABILITY, 0, (LPARAM)&icqCustomCap);
+ }
+*/
+ return 0;
+
+}
+
+
+
+int __declspec(dllexport) Unload(void)
+{
+ extern void icq_DestroyPrivacyMenu();
+ if (gbXStatusEnabled) gbXStatusEnabled = 10; // block clist changing
+
+ UninitXStatusEvents();
+
+ if (hServerConn)
+ {
+ icq_sendCloseConnection();
+
+ icq_serverDisconnect(TRUE);
+ }
+
+ UninitServerLists();
+ UninitOscarFileTransfer();
+ UninitDirectConns();
+ icq_InfoUpdateCleanup();
+ icq_ISeeCleanup();
+ icq_DestroyPrivacyMenu();
+
+ NetLib_SafeCloseHandle(&ghDirectNetlibUser);
+ NetLib_SafeCloseHandle(&ghServerNetlibUser);
+ UninitRates();
+ UninitCookies();
+ UninitCache();
+ DeleteCriticalSection(&modeMsgsMutex);
+ DeleteCriticalSection(&localSeqMutex);
+ DeleteCriticalSection(&connectionHandleMutex);
+ SAFE_FREE(&modeMsgs.szOnline);
+ 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 (hxstatuschanged)
+ DestroyHookableEvent(hxstatuschanged);
+
+ if (hxstatusiconchanged)
+ DestroyHookableEvent(hxstatusiconchanged);
+
+ if (hHookUserMenu)
+ UnhookEvent(hHookUserMenu);
+
+ if (hHookIdleEvent)
+ UnhookEvent(hHookIdleEvent);
+
+ bVisibility = ICQGetContactSettingByte(NULL, "SrvVisibility", 0);
+
+ 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 pszCapsName[MAX_PATH+10];
+ char szBuffer[MAX_PATH+64];
+ char* modules[6] = {0,0,0,0,0,0};
+
+ if (ServiceExists(MS_POPUP_ADDPOPUPEX))
+ bPopUpService = TRUE;
+ if (ServiceExists("SecureIM/IsContactSecured"))
+ gbSecureIM = TRUE;
+
+
+ /* if(ServiceExists(MS_ASSOCMGR_ADDNEWFILETYPE)) //need to be finishaed
+ {
+ {
+ FILETYPEDESC ftd;
+ ftd.cbSize=sizeof(ftd);
+ ftd.pwszDescription=TranslateW("ICQ link file");
+ ftd.pszDescription=Translate("ICQ link file");
+ ftd.ptszDescription=TranslateT("ICQ link file");
+ ftd.pszFileExt=".icq";
+ ftd.pszMimeType="application/x-icq";
+ ftd.pszService=0;
+ ftd.flags=FTDF_DEFAULTDISABLED;
+ CallService(MS_ASSOCMGR_ADDNEWFILETYPE,0,(LPARAM)&ftd);
+ }
+ {
+ URLTYPEDESC utd;
+ utd.cbSize=sizeof(utd);
+ utd.pszDescription=Translate("ICQ Link");
+ utd.ptszDescription=TranslateT("ICQ Link");
+ utd.pwszDescription=TranslateW("ICQ Link");
+ utd.flags=UTDF_DEFAULTDISABLED;
+ utd.pszService=0;
+ utd.pszProtoPrefix="http:";
+ CallService(MS_ASSOCMGR_ADDNEWURLTYPE,0,(LPARAM)&utd);
+ }
+ }*/
+
+/* if(ServiceExists(MS_UPDATE_REGISTER))
+ {
+ Update upd = {0};
+ char szCurrentVersion[30];
+ char pszBuild[10];
+ int i=0;
+ BOOL testing = DBGetContactSettingByte(NULL, "Updater", "UseBetaIcqOscarJ (" ICQ_MODNAME " Mod) Protocol", 0);
+
+ // get build number
+ char *p=strstr(pluginInfo.shortName, "#");
+ if(p) p++;
+ while (p && (*p>='0')&&(*p<='9'))
+ {
+ pszBuild[i++]=*p;
+ p++;
+ }
+ pszBuild[i]=0;
+
+ upd.cbSize = sizeof(upd);
+ upd.szComponentName = "IcqOscarJ (" ICQ_MODNAME " Mod) Protocol";
+ upd.pbVersion = testing?(BYTE*)pszBuild:(BYTE*)CreateVersionString(pluginInfo.version, szCurrentVersion);
+ upd.cpbVersion = strlen(( char *)upd.pbVersion);
+
+ upd.szBetaUpdateURL = "http://dev.mirandaim.ru/~sss/get.php?file=icq_test.zip";
+ upd.szBetaVersionURL = "http://dev.mirandaim.ru/~sss/get.php?file=icq_test.txt";
+ upd.pbBetaVersionPrefix = (BYTE *)"icq test build ";
+ upd.cpbBetaVersionPrefix = strlen(( char *)upd.pbBetaVersionPrefix);
+
+ upd.szUpdateURL = testing?upd.szBetaUpdateURL:"http://dev.mirandaim.ru/~sss/get.php?file=icq.zip";
+ upd.szVersionURL = testing?upd.szBetaVersionURL:"http://dev.mirandaim.ru/~sss/get.php?file=icq.txt";
+ upd.pbVersionPrefix = testing?upd.pbBetaVersionPrefix:(BYTE *)"icq ";
+ upd.cpbVersionPrefix = strlen(( char *)upd.pbVersionPrefix);
+
+ upd.szBetaChangelogURL = "http://dev.mirandaim.ru/~sss/get.php?file=icq_test.txt";
+
+ CallService(MS_UPDATE_REGISTER, 0, (LPARAM)&upd);
+ } //thx sje */
+
+
+ strcpy(pszP2PName, gpszICQProtoName);
+ strcat(pszP2PName, "P2P");
+
+ strcpy(pszGroupsName, gpszICQProtoName);
+ strcat(pszGroupsName, "Groups");
+ strcpy(pszSrvGroupsName, gpszICQProtoName);
+ strcat(pszSrvGroupsName, "SrvGroups");
+ strcpy(pszCapsName, gpszICQProtoName);
+ strcat(pszCapsName, "Caps");
+ modules[0] = gpszICQProtoName;
+ modules[1] = pszP2PName;
+ modules[2] = pszGroupsName;
+ modules[3] = pszSrvGroupsName;
+ modules[4] = pszCapsName;
+ CallService("DBEditorpp/RegisterModule",(WPARAM)modules,(LPARAM)5);
+
+
+ null_snprintf(szBuffer, sizeof szBuffer, ICQTranslate("%s server connection"), gpszICQProtoName);
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_OUTGOING | NUF_HTTPGATEWAY;
+ nlu.szDescriptiveName = szBuffer;
+ nlu.szSettingsModule = gpszICQProtoName;
+ nlu.szHttpGatewayHello = "http://http.proxy.icq.com/hello";
+ nlu.szHttpGatewayUserAgent = szHttpUserAgent;
+ 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);
+
+ hPopUpsList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0);
+
+ icq_FirstRunCheck();
+
+ InitAvatars();
+
+ // Init extra optional modules
+ //InitPopUps();
+ InitIconLib();
+
+ hHookIconsChanged = IconLibHookIconsChanged(IconLibIconsChanged);
+ // Initialize IconLib icons
+ InitXStatusIcons();
+ InitXStatusEvents();
+ InitXStatusItems(FALSE);
+
+ InitDCEvents();
+
+ {
+ // userinfo
+ ICQWriteContactSettingUtf(NULL, "MirVer", Translate("you need to be connected..."));
+ DBWriteContactSettingDword(NULL, gpszICQProtoName, "IP", 0);
+ if(!DBGetContactSettingByte(NULL, gpszICQProtoName, "ConstRealIP", 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);
+ }
+ {
+ 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.hIcon = IconLibGetIcon("req_auth");
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = LPGEN("Request authorization");
+ mi.pszService = pszServiceName;
+ hUserMenuAuth = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+ IconLibReleaseIcon("req_auth");
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_GRANT_AUTH);
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1000029999;
+ mi.hIcon = IconLibGetIcon("grant_auth");
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = LPGEN("Grant authorization");
+ mi.pszService = pszServiceName;
+ hUserMenuGrant = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+ IconLibReleaseIcon("grant_auth");
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_REVOKE_AUTH);
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1000029998;
+ mi.hIcon = IconLibGetIcon("revoke_auth");
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = LPGEN("Revoke authorization");
+ mi.pszService = pszServiceName;
+ hUserMenuRevoke = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+ IconLibReleaseIcon("revoke_auth");
+
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_ICQ_ADDSERVCONTACT);
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = -2049999999;
+ mi.hIcon = IconLibGetIcon("add_to_server");
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = LPGEN("Add to server list");
+ mi.pszService = pszServiceName;
+ hUserMenuAddServ = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+ IconLibReleaseIcon("add_to_server");
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_XSTATUS_SHOWDETAILS);
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = -2000004999;
+ mi.hIcon = NULL; // dynamically updated
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = LPGEN("Show custom status details");
+ mi.pszService = pszServiceName;
+ mi.flags=CMIF_NOTOFFLINE;
+ hUserMenuXStatus = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_SETVIS);
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 2106000000;
+ mi.flags = 0;
+ mi.hIcon = IconLibGetIcon("set_vis");
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = LPGEN("Always visible");
+ mi.pszService = pszServiceName;
+ hUserMenuSetVis=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+ IconLibReleaseIcon("set_vis");
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_SETINVIS);
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 2107000000;
+ mi.flags = 0;
+ mi.hIcon = IconLibGetIcon("set_invis");
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = LPGEN("Always invisible");
+ mi.pszService = pszServiceName;
+ hUserMenuSetInvis=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+ IconLibReleaseIcon("set_invis");
+
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_INCOGNITO_REQUEST);
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = -2000005000;
+ mi.flags = 0;
+ mi.hIcon = IconLibGetIcon("incognito");
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = LPGEN("Incognito Away-Request");
+ mi.pszService = pszServiceName;
+ hUserMenuIncognito=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+ IconLibReleaseIcon("incognito");
+
+
+ strcpy(pszServiceName, gpszICQProtoName);
+ strcat(pszServiceName, MS_SEND_TZER);
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 2108000000;
+ mi.flags = 0;
+ mi.hIcon = IconLibGetIcon("send_tzer");
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = LPGEN("Send tZer");
+ mi.pszService = pszServiceName;
+ hUserMenuSendtZer=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+ IconLibReleaseIcon("send_tzer");
+
+
+ }
+
+ return 0;
+}
+
+
+
+static int OnSystemPreShutdown(WPARAM wParam,LPARAM lParam)
+{ // all threads should be terminated here
+ if (hServerConn)
+ {
+ icq_sendCloseConnection();
+
+ icq_serverDisconnect(TRUE);
+ }
+ CheckSelfRemoveShutdown();
+
+ 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};
+ extern HANDLE hStatusMenu;
+
+ CListShowMenuItem(hUserMenuAuth, bShowAuth?1:ICQGetContactSettingByte((HANDLE)wParam, "Auth", 0) && icqOnline);
+ CListShowMenuItem(hUserMenuGrant, bShowAuth?1:ICQGetContactSettingByte((HANDLE)wParam, "Grant", 0) && icqOnline);
+ CListShowMenuItem(hUserMenuRevoke, icqOnline);
+ CListShowMenuItem(hUserMenuSetVis, icqOnline);
+ CListShowMenuItem(hUserMenuSetInvis, icqOnline);
+ CListShowMenuItem(hUserMenuStatus, icqOnline && gbASD);
+// CListShowMenuItem(hStatusMenu, icqOnline && gbASD); //not woking ? %), looks like we need other method
+ CListShowMenuItem(hUserMenuIncognito, (/*bStealthRequest && */!bIncognitoGlobal &&
+ (ICQGetContactSettingWord((HANDLE)wParam, "Status", 0)!= ID_STATUS_OFFLINE) &&
+ (ICQGetContactSettingWord((HANDLE)wParam, "Status", 0)!= ID_STATUS_INVISIBLE) && icqOnline)); //now away messages for online supported
+ CListShowMenuItem(hUserMenuSendtZer, icqOnline && gbTzerEnabled);
+
+ cli.cbSize=sizeof(CLISTMENUITEM);
+ cli.flags=CMIM_FLAGS;
+ cli.hIcon=NULL;
+ cli.pszContactOwner=NULL;
+
+ 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;
+ }
+
+
+ if (gbSsiEnabled && !ICQGetContactSettingWord((HANDLE)wParam, "ServerId", 0) && !ICQGetContactSettingWord((HANDLE)wParam, "SrvIgnoreId", 0))
+ CListShowMenuItem(hUserMenuAddServ, 1);
+ else
+ CListShowMenuItem(hUserMenuAddServ, 0);
+
+ bXStatus = ICQGetContactXStatus((HANDLE)wParam);
+ CListShowMenuItem(hUserMenuXStatus, (BYTE)(bHideXStatusUI ? 0 : bXStatus));
+ if (bXStatus && !bHideXStatusUI)
+ {
+ CListSetMenuItemIcon(hUserMenuXStatus, GetXStatusIcon(bXStatus, LR_SHARED));
+ }
+
+ return 0;
+}
+
+
+
+static int IconLibIconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ CListSetMenuItemIcon(hUserMenuAuth, IconLibGetIcon("req_auth"));
+ IconLibReleaseIcon("req_auth");
+ CListSetMenuItemIcon(hUserMenuGrant, IconLibGetIcon("grant_auth"));
+ IconLibReleaseIcon("grant_auth");
+ CListSetMenuItemIcon(hUserMenuRevoke, IconLibGetIcon("revoke_auth"));
+ IconLibReleaseIcon("revoke_auth");
+ CListSetMenuItemIcon(hUserMenuAddServ, IconLibGetIcon("add_to_server"));
+ IconLibReleaseIcon("add_to_server");
+ CListSetMenuItemIcon(hUserMenuIncognito, IconLibGetIcon("incognito_request"));
+ IconLibReleaseIcon("incognito_request");
+ CListSetMenuItemIcon(hUserMenuSendtZer, IconLibGetIcon("send_tzer"));
+ IconLibReleaseIcon("send_tzer");
+
+ ChangedIconsXStatus();
+
+ return 0;
+}
+
+
+
+void UpdateGlobalSettings()
+{
+ if (ghServerNetlibUser)
+ {
+ NETLIBUSERSETTINGS nlus = {0};
+
+ nlus.cbSize = sizeof(NETLIBUSERSETTINGS);
+ if (CallService(MS_NETLIB_GETUSERSETTINGS, (WPARAM)ghServerNetlibUser, (LPARAM)&nlus))
+ {
+ if (nlus.useProxy && nlus.proxyType == PROXYTYPE_HTTP)
+ gbGatewayMode = 1;
+ else
+ gbGatewayMode = 0;
+ }
+ else
+ gbGatewayMode = 0;
+ }
+
+ 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);
+ gbCustomCapEnabled = ICQGetContactSettingByte(NULL, "customcap", 1);
+ gbHideIdEnabled = ICQGetContactSettingByte(NULL, "Hide ID", 1);
+ gbRTFEnabled = ICQGetContactSettingByte(NULL, "RTF", 0);
+ gbVerEnabled = ICQGetContactSettingByte(NULL, "CurrentVer", 0);
+ gbTzerEnabled = ICQGetContactSettingByte(NULL, "tZer", 0);
+}
diff --git a/icqj_s7_sss_mod/init.h b/icqj_s7_sss_mod/init.h new file mode 100644 index 0000000..30504c3 --- /dev/null +++ b/icqj_s7_sss_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,2006,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+void UpdateGlobalSettings(void);
+
+
+// Debug defines
+#undef DBG_CAPHTML
+#define DBG_CAPMTN
+#define DBG_CAPXTRAZ
+#undef DBG_CAPXTRAZ_MUC
+#define DBG_NEWCAPS
+#define DBG_OSCARFT
+#define DBG_AIMCONTACTSEND
diff --git a/icqj_s7_sss_mod/isee.c b/icqj_s7_sss_mod/isee.c new file mode 100644 index 0000000..0984cf2 --- /dev/null +++ b/icqj_s7_sss_mod/isee.c @@ -0,0 +1,1600 @@ +// ---------------------------------------------------------------------------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, Bi0
+// Copyright 2004,2005,2006,2007 Joe Kucera, Bi0
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Thief, nullbie
+//
+// 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$
+// Revision : $Revision: 47 $
+// Last change on : $Date: 2007-08-24 14:45:13 +0300 (Пт, 24 авг 2007) $
+// Last change by : $Author: redeemerXx $
+
+
+// !
+// ITS SHIT MUST BE REWRITTEN! (c) persei
+
+#include "icqoscar.h"
+#include "resource.h"
+#include "isee.h"
+#include "m_cluiframes.h"
+#include "m_genmenu.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;
+HANDLE hStatusMenu = NULL;
+static HANDLE hHookPrivacyBuild = 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 int hCAUSTimer = 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;
+ BYTE bManualCheck;
+} checkstatus;
+
+static checkstatus StatusList[LISTSIZE];
+static HANDLE hPrivacy[8] = {0}; // Def, 1, 2, 3, 4, 5, 6, Old
+
+static void RebuildMenu();
+
+
+//ASD
+
+static HANDLE hASD = NULL;
+static int icq_ASD(WPARAM wParam,LPARAM lParam);
+
+// webaware
+static HANDLE hWebAware = NULL;
+static int icq_WebAware(WPARAM wParam,LPARAM lParam);
+
+// privacy tools
+//static HANDLE hTools = NULL;
+//static HANDLE hVisTools = NULL;
+
+void detectViaAuth(HANDLE hContact, DWORD dwCookie)
+{
+ DWORD dwUin, dwMyUin;
+ uid_str szUid, szMyUid;
+ icq_packet packet;
+ DWORD dwID1;
+ DWORD dwID2;
+
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ return; // Invalid contact
+
+ ICQGetContactSettingUID(NULL, &dwMyUin, &szMyUid);
+
+ dwID1 = time(NULL);
+ dwID2 = RandRange(0, 0x00FF);
+
+ packServMsgSendHeader(&packet, dwCookie, 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);
+}
+
+BOOL PopUpErrMsg(char* aMsg)
+{
+ if (ServiceExists(MS_POPUP_ADDPOPUPEX) &&
+ !(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;
+ }
+ Netlib_Logf(ghServerNetlibUser, "Rate status recieved: %u. Delay: %u ms", wStatus, nSpeed);
+
+}
+
+
+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 ?!
+
+ if(!(bNoASD && gnCurrentStatus == ID_STATUS_INVISIBLE)){
+
+ DWORD dwUin = 0;
+
+ if (hContact && hContact != INVALID_HANDLE_VALUE)
+ dwUin = ICQGetContactSettingDword(hContact, UNIQUEIDSETTING, 0);
+
+ if (!gbASD || !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;
+ StatusList[c].bManualCheck = (wEvent == 1);
+ 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, HANDLE hContact)
+{/* 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
+
+
+
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Set status cmd: %d, Cookie: 0x%X, Uin: %d", nStatus, dwCookie, dwUin);
+#endif
+ if (!gbSetStatus) return;
+
+ if (!dwUin && gbASD)
+ {
+
+ 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 && !hContact) return;
+
+ hContact = HContactFromUIN(dwUin, 0);
+
+ if (hContact && hContact != INVALID_HANDLE_VALUE)
+ {
+ char name[128];
+
+ NickFromHandleStatic(hContact, name, sizeof(name));
+
+ if ((nStatus < 0) && gbASD) { // 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>=21) && (nStatus<=29))
+ PopUpMsg(hContact, 3);
+
+ if (nStatus != 5)
+ {
+ ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_INVISIBLE);
+ ICQWriteContactSettingDword(hContact, "OldLogonTS", (DWORD)TimeStamp);
+ ClearAllContactCapabilities(hContact);
+ }
+
+ SetContactCapabilities(hContact, WAS_FOUND);
+ {
+ CHECKCONTACT chk;
+ chk.dbeventflag=DBEF_READ;
+ chk.dwUin=dwUin;
+ chk.hContact=hContact;
+ chk.historyevent=chk.logtofile=TRUE;
+ chk.icqeventtype=ICQEVENTTYPE_WAS_FOUND;
+ if(nStatus < 20 && nStatus > 0)
+ chk.msg="detected via ASD";
+ else if(nStatus > 20)
+ chk.msg="detected via PSD";
+ chk.PSD=-1;
+ CheckContact(chk);
+ }
+
+ ClearContactCapabilities(hContact, CAPF_SRV_RELAY); // for compability
+
+ // dim icon
+ if (!ICQGetContactSettingDword(hContact, "IdleTS", 0))
+ ICQWriteContactSettingDword(hContact, "IdleTS", (DWORD)TimeStamp);
+
+ }
+ }
+
+ if (hDummyEventS) SetEvent(hDummyEventS);
+ }
+
+}
+
+static DWORD SendDetectionPacket2(HANDLE hContact, char* szQuery, char* szNotify)
+{
+ char *szQueryBody;
+ char *szNotifyBody;
+ DWORD dwUin;
+ int nBodyLen;
+ char *szBody;
+ DWORD dwCookie;
+ message_cookie_data* pCookieData;
+
+
+ ICQGetContactSettingUID(hContact, &dwUin, NULL);
+
+ //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, hContact, (void*)pCookieData);
+
+ // have we a open DC, send through that
+ // if (gbDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
+ // icq_sendXtrazRequestDirect(hContact, dwCookie, szBody, nBodyLen, MTYPE_SCRIPT_NOTIFY);
+ // else
+ icq_sendXtrazRequestServ(dwUin, dwCookie, szBody, nBodyLen, pCookieData);
+
+
+ return dwCookie;
+}
+
+
+static DWORD sendDetectionPacket(HANDLE hContact)
+{
+ 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 = SendDetectionPacket2(hContact, "<Q><PluginID>srvMng</PluginID></Q>", szNotify);
+ return dwCookie;
+}
+
+
+
+static DWORD __stdcall 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) {
+ HANDLE hContact = NULL;
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Users statuses %u", nCount);
+#endif
+ hContact = HContactFromUIN(StatusList[nPointer].dwUin, 0);
+ if (nCount > 0 && !(gnCurrentStatus == ID_STATUS_INVISIBLE && bNoASD))
+ {
+ //icq_packet p;
+ //int iRes = FALSE;
+ //int success = FALSE;
+
+ sent = 1;
+
+ EnterCriticalSection(&slistmutex);
+#ifdef _DEBUG
+ Netlib_Logf(ghServerNetlibUser, "Request user %u status", StatusList[nPointer].dwUin);
+#endif
+
+ StatusList[nPointer].dwCookie = GenerateCookie(0);
+
+ if(CheckContactCapabilities(hContact, WAS_FOUND))
+ makeUserOffline(hContact); // ensure that contact was made offline, before beeing checked
+
+
+ // getting invisibility via status message
+ if(bASDViaAwayMsg)
+ icq_sendGetAwayMsgServ(hContact, StatusList[nPointer].dwUin, MTYPE_AUTOAWAY, (WORD)(ICQGetContactSettingWord(hContact, "Version", 0)==9?9:ICQ_VERSION)); // Success
+
+ // getting invisibility via xtraz notify request
+ if(bASDViaXtraz)
+ sendDetectionPacket(hContact); //detect icq6 invisibility (added by [sin])
+
+ // getting invisibility via malformed url message
+ if(bASDViaURL)
+ icq_sendGetAwayMsgServ(hContact, StatusList[nPointer].dwUin, MTYPE_URL, (WORD)(ICQGetContactSettingWord(hContact, "Version", 0)==9?9:ICQ_VERSION)); //detect miranda invisibility (added by [sin])
+
+ if(bASDUnauthorized)
+ icq_sendGetLocationInfo(hContact ,StatusList[nPointer].dwUin, 0); //method reported by D@rkNeo
+
+ if(bASDViaAuth && StatusList[nPointer].bManualCheck) //
+ detectViaAuth(hContact, StatusList[nPointer].dwCookie);
+
+ // 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 0;
+
+}
+
+
+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", (BYTE)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", (BYTE)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", (BYTE)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;
+ }
+
+ }
+
+ }
+
+}
+
+static void CALLBACK TimeToCheckAll(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
+{
+ if((gnCurrentStatus == ID_STATUS_INVISIBLE)&& bNoASD)
+ {
+ KillTimer(NULL, hCAUSTimer);
+ return;
+ }
+
+ else
+ {
+ if (icqOnline)
+ {
+ icq_CheckAllUsersStatus(0,0);
+
+ KillTimer(NULL, hCAUSTimer);
+ }
+ }
+}
+
+
+// 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:
+ PopUpMsg(NULL, 6);
+ 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 = IconLibGetIcon("stop");
+ break;
+
+ case 1: // paused
+ mi.hIcon = IconLibGetIcon("pause");
+ break;
+
+ default: // working
+ mi.hIcon = IconLibGetIcon("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 = IconLibGetIcon("dot");
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hPrivacy[7], (LPARAM)&mi);
+ IconLibReleaseIcon("dot");
+ }
+
+ mi.hIcon = IconLibGetIcon("check");
+ hPrivacy[7] = hPrivacy[gbVisibility];
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hPrivacy[7], (LPARAM)&mi);
+ IconLibReleaseIcon("check");
+
+ if (icqOnline)
+ {
+ if (gbVisibility)
+ updateServVisibilityCode((BYTE)gbVisibility);
+ else
+ updateServVisibilityCode((BYTE)(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); //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(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 = IconLibGetIcon(gbTools?"check":"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 = IconLibGetIcon(gbVTools?"check":"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, (WORD)(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)
+{
+ DWORD uin = ICQGetContactSettingDword(hContact, "UIN", 0);
+ switch(bType)
+ {
+ case 3: // User was found (PSD)
+ if (bFoundPopUp)
+ ShowPopUpMsg(hContact, uin, NickFromHandleUtf(hContact), ICQTranslateUtf ("...was found! (Passive)"), POPTYPE_FOUND);
+ break;
+ case 4: // User was found (ASD)
+ if (bFoundPopUp)
+ ShowPopUpMsg(hContact, uin, NickFromHandleUtf(hContact), ICQTranslateUtf ("...was found! (Active)"), POPTYPE_FOUND);
+ break;
+ case 5: // Scan complete
+ if(bScanPopUp){
+ gbScan = FALSE;
+ ShowPopUpMsg(hContact, uin, ICQTranslateUtf ("Active Status Scan"), ICQTranslateUtf ("Users Status Scan Complete"), POPTYPE_SCAN);
+ }
+ break;
+ case 6: // Startup Check started
+ if(bScanPopUp){
+ gbScan = TRUE;
+ ShowPopUpMsg(hContact, uin, ICQTranslateUtf ("Entire List Check"), ICQTranslateUtf ("Users Status Scan Started"), POPTYPE_SCAN);
+ }
+ break;
+ default:
+ return;
+ }
+}
+
+void icq_ISeeCleanup()
+{
+ if (gbASD)
+ {
+ if (hHidTimer) KillTimer(NULL, hHidTimer);
+ if (hFavTimer) KillTimer(NULL, hFavTimer);
+ if (hVIPTimer) KillTimer(NULL, hVIPTimer);
+ DeleteCriticalSection(&slistmutex);
+ CloseHandle(hQueueEventS);
+ CloseHandle(hDummyEventS);
+ }
+}
+
+int icq_PrivacyMenu(WPARAM wParam, LPARAM lParam)
+{
+ BOOL bStausMenu = FALSE; //ServiceExists(MS_CLIST_ADDSTATUSMENUITEM);
+ HANDLE hPrivacyRoot;
+ char pszName[MAX_PATH+30], pszServiceName[MAX_PATH+30];
+ CLISTMENUITEM mi={0};
+ mi.cbSize = sizeof(mi);
+ mi.pszContactOwner = gpszICQProtoName;
+
+ gbVisibility = DBGetContactSettingByte(NULL, gpszICQProtoName, "Privacy", DEFAULT_VISIBILITY);
+ if (gbVisibility > 6) gbVisibility = DEFAULT_VISIBILITY;
+
+ mir_snprintf(pszName, sizeof(pszName), "%s", Translate("Advanced Features"));
+
+ mi.pszPopupName = pszName;
+ mi.flags = 0;
+ mi.popupPosition=500084000;//400059000;
+ // icon for menu
+ mi.hIcon = IconLibGetIcon("dot");
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_PR0");
+ CreateServiceFunction(pszServiceName, icq_Privacy0);
+
+ mi.position = 1000010000;
+ mi.pszName = Translate("Default, corresponding to status");
+ mi.pszService = pszServiceName;
+
+ hPrivacy[0] = (HANDLE) CallService(MS_CLIST_ADDSTATUSMENUITEM, (WPARAM)&hPrivacyRoot, (LPARAM) & mi);
+
+ {
+ CLISTMENUITEM miTmp = {0};
+ miTmp.cbSize = sizeof(miTmp);
+ miTmp.flags = CMIM_ICON|CMIM_FLAGS;
+ miTmp.hIcon = IconLibGetIcon("privacy");
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hPrivacyRoot, (LPARAM)&miTmp);
+ IconLibReleaseIcon("privacy");
+ }
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_PR1");
+ CreateServiceFunction(pszServiceName, icq_Privacy1);
+
+ // icon for other items
+ mi.hIcon = IconLibGetIcon("dot");
+
+ mi.position = 2000010000;
+ mi.pszName = Translate("Allow all users to see you");
+ mi.pszService = pszServiceName;
+ hPrivacy[1] = (HANDLE) CallService(MS_CLIST_ADDSTATUSMENUITEM, (WPARAM)&hPrivacyRoot, (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_ADDSTATUSMENUITEM, (WPARAM)&hPrivacyRoot, (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_ADDSTATUSMENUITEM, (WPARAM)&hPrivacyRoot, (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_ADDSTATUSMENUITEM, (WPARAM)&hPrivacyRoot, (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_ADDSTATUSMENUITEM, (WPARAM)&hPrivacyRoot, (LPARAM) & mi);
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_PR6");
+ CreateServiceFunction(pszServiceName, icq_Privacy6);
+
+ mi.position = 2000060000;
+ mi.pszName = Translate("Allow only users in the Contact list to see you, except Invisible list users");
+ mi.pszService = pszServiceName;
+ hPrivacy[6] = (HANDLE) CallService(MS_CLIST_ADDSTATUSMENUITEM, (WPARAM)&hPrivacyRoot, (LPARAM) & mi);
+
+ IconLibReleaseIcon("dot");
+
+
+
+ // set checkmark
+ mi.flags = CMIM_ICON;
+ mi.hIcon = IconLibGetIcon("check");
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hPrivacy[gbVisibility], (LPARAM)&mi);
+ IconLibReleaseIcon("check");
+
+ hPrivacy[7] = hPrivacy[gbVisibility];
+
+ mi.flags = 0;
+
+ //ASD
+ mi.hIcon = IconLibGetIcon(gbASD?"check":"dot");
+
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_ASD");
+ CreateServiceFunction(pszServiceName, icq_ASD);
+
+ mi.position = 2100000000;
+ mi.pszName = Translate("ASD");
+ mi.pszService = pszServiceName;
+ hASD = (HANDLE) CallService(MS_CLIST_ADDSTATUSMENUITEM, (WPARAM)&hPrivacyRoot, (LPARAM) & mi);
+
+
+ // webaware
+ mi.hIcon = IconLibGetIcon(gbWebAware?"check":"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_ADDSTATUSMENUITEM, (WPARAM)&hPrivacyRoot, (LPARAM) & mi);
+
+ // Remove option
+/* mi.hIcon = IconLibGetIcon(gbTools?"check":"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(
+ bStausMenu?MS_CLIST_ADDSTATUSMENUITEM:MS_CLIST_ADDMAINMENUITEM,
+ bStausMenu?0:(WPARAM)&hPrivacyRoot, (LPARAM) & mi);*/
+
+ //Vis Tools
+// mi.hIcon = IconLibGetIcon(gbVTools?"check":"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(
+ bStausMenu?MS_CLIST_ADDSTATUSMENUITEM:MS_CLIST_ADDMAINMENUITEM,
+ bStausMenu?0:(WPARAM)&hPrivacyRoot, (LPARAM) & mi); */
+
+ // Manage server list
+ mi.hIcon = IconLibGetIcon("servlist");
+
+ 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_ADDSTATUSMENUITEM, (WPARAM)&hPrivacyRoot, (LPARAM) & mi);
+ IconLibReleaseIcon("servlist");
+ return 0;
+}
+
+static HANDLE hhkPrebuildStatusMenu = NULL;
+void icq_BuildPrivacyMenu()
+{
+ hhkPrebuildStatusMenu = HookEvent( ME_CLIST_PREBUILDSTATUSMENU, icq_PrivacyMenu );
+}
+void icq_DestroyPrivacyMenu()
+{
+ UnhookEvent(hhkPrebuildStatusMenu);
+}
+
+
+void icq_InitISee()
+{
+ static DWORD icq_StatusCheckThreadId;
+
+ int i;
+ char pszName[MAX_PATH+30], pszServiceName[MAX_PATH+30];
+
+ CLISTMENUITEM mi={0};
+ mi.cbSize = sizeof(mi);
+
+ InitIconLib();
+ // some globals
+ gbSetStatus = 1;
+// gbTools = DBGetContactSettingByte(NULL, gpszICQProtoName, "PrivacyItems", 0);
+// gbVTools = DBGetContactSettingByte(NULL, gpszICQProtoName, "VisItems", 0);
+ 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
+*/
+
+ switch (gbASD) {
+
+/* case 2: ICQWriteContactSettingByte(NULL, "ASD", (BYTE)(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"));
+ }
+
+ defSpeed = ICQGetContactSettingWord(NULL, "_defSpeed", 3000);
+ nSpeed = defSpeed;
+
+ if (hQueueEventS && hDummyEventS) {
+
+ InitializeCriticalSection(&slistmutex);
+
+ // Init list
+ for (i = 0; i<LISTSIZE; i++) {
+ StatusList[i].dwUin = 0;
+ StatusList[i].dwCookie = 0x100;
+ }
+ ICQCreateThreadEx(icq_StatusCheckThread, 0, &icq_StatusCheckThreadId); //maybe broken
+ }
+
+ if (TRUE) hHidTimer = SetTimer(NULL, 1, 600000, TimeToCheckHidden);
+ if (TRUE) hFavTimer = SetTimer(NULL, 1, 450000, TimeToCheckFav);
+ if (TRUE) hVIPTimer = SetTimer(NULL, 1, 300000, TimeToCheckVIP);
+
+ if(ICQGetContactSettingByte(NULL, "ASDStartup", 0))
+ if (TRUE) hCAUSTimer = SetTimer(NULL, 1, 15000, TimeToCheckAll);
+ {
+ strcpy(pszServiceName, gpszICQProtoName); strcat(pszServiceName, "PS_ISEE_CUS");
+ CreateServiceFunction(pszServiceName, icq_CheckUserStatus);
+
+ mi.position = 1000055000;
+ mi.flags = 0;
+ mi.hIcon = IconLibGetIcon("scan");
+ mi.pszContactOwner = gpszICQProtoName;
+ mi.pszName = Translate("Us&er Status");
+ mi.pszService = pszServiceName;
+ hUserMenuStatus = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi);
+ IconLibReleaseIcon("scan");
+
+ 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();
+ }
+ break;
+ case 0:
+ break;
+ }
+
+
+ // Added by BM
+ SkinAddNewSoundEx("AuthRequest", Translate(gpszICQProtoName), Translate("Authorization Request"));
+ SkinAddNewSoundEx("AuthDenied", Translate(gpszICQProtoName), Translate("Authorization Denied"));
+ SkinAddNewSoundEx("AuthGranted", Translate(gpszICQProtoName), Translate("Authorization Granted"));
+ SkinAddNewSoundEx("YouWereAdded", Translate(gpszICQProtoName), Translate("You Were Added"));
+ SkinAddNewSoundEx("ContactRemovedSelf", Translate(gpszICQProtoName), Translate("Contact Removed Self"));
+ SkinAddNewSoundEx("ASDScanComplete", Translate(gpszICQProtoName), Translate("Status Scan Complete"));
+}
+
+
+
+void SetWebAware(BYTE bSend)
+{
+ CLISTMENUITEM mi = {0};
+
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_ICON;
+ mi.hIcon = IconLibGetIcon(gbWebAware?"check":"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),0);
+ }
+}
+
+static int icq_ASD(WPARAM wParam,LPARAM lParam)
+{
+ CLISTMENUITEM mi = {0};
+
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_ICON;
+ gbASD?(gbASD=0):(gbASD=1);
+ ICQWriteContactSettingByte(NULL,"ASD",gbASD);
+ gbASD?icq_InitISee():icq_ISeeCleanup();
+ mi.hIcon = IconLibGetIcon(gbASD?"check":"dot");
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hASD, (LPARAM)&mi);
+ return 0;
+}
+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);
+ 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);
+ packBuffer(&packet, szList, wListLen);
+ sendServPacket(&packet);
+ }
+
+}
+/*
+int CheckIgnoreState() //nothing built yet
+{
+ if ((icqOnline && //we do not want to be detected
+ ICQGetContactSettingWord(dat->hContact, "Status", 0) != ID_STATUS_OFFLINE) && (!invis_for(0,dat->hContact)))
+ {
+
+ ACKDATA *ack = (ACKDATA*)lParam;
+ message_cookie_data* pCookieData;
+
+
+ if (!dat->hProtoAck)
+ dat->hProtoAck = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_PROTOACK);
+
+ pCookieData = malloc(sizeof(message_cookie_data));
+ pCookieData->bMessageType = MTYPE_PLAIN;
+ pCookieData->nAckType = ACKTYPE_SERVER;
+ dat->dwCookie = icq_SendChannel4Message(dat->dwUin, NULL,0 ,0, "", pCookieData);
+
+ if (!ack || !ack->szModule ||
+ ack->hProcess != (HANDLE)dat->dwCookie ||
+ ack->hContact != dat->hContact ||
+ strcmp(ack->szModule, gpszICQProtoName))
+ return 0;
+
+ 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);
+ }
+
+ SetTimer(hwndDlg, TIMEOUT_IGNORE, 10000, NULL);
+ }
+
+}*/
\ No newline at end of file diff --git a/icqj_s7_sss_mod/isee.h b/icqj_s7_sss_mod/isee.h new file mode 100644 index 0000000..6836bf8 --- /dev/null +++ b/icqj_s7_sss_mod/isee.h @@ -0,0 +1,65 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//BOOL ASD = FALSE;
+
+
+#define hIconInst hInst
+
+#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, HANDLE hContact);
+void icq_CheckSpeed(WORD wStatus);
+void icq_SetCustomStatus(HANDLE hContact, int xstatus);
+//void handleXStatusCaps(HANDLE hContact, char* caps, int capsize);
+BOOL PopUpErrMsg(char* aMsg);
+
+int icq_SelfRemove(WPARAM wParam,LPARAM lParam);
+int icq_GrantAuth(WPARAM wParam,LPARAM lParam);
+
+BYTE gbASD;
+
+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);
+BOOL bASDViaAwayMsg;
+BOOL bASDViaXtraz;
+BOOL bASDViaURL;
+BOOL bASDUnauthorized; //work in progress
+BOOL bASDViaAuth; //
+
diff --git a/icqj_s7_sss_mod/log.c b/icqj_s7_sss_mod/log.c new file mode 100644 index 0000000..c8bb4a4 --- /dev/null +++ b/icqj_s7_sss_mod/log.c @@ -0,0 +1,161 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 50 $
+// Last change on : $Date: 2007-08-28 02:57:00 +0300 (Вт, 28 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static const char *szLevelDescr[] = {"ICQ Note", "ICQ Warning", "ICQ Error", "ICQ Fatal", "ICQ Critical"};
+
+typedef struct {
+ char *szMsg;
+ char *szTitle;
+} LogMessageInfo;
+
+static BOOL bErrorVisible = FALSE;
+
+static DWORD __stdcall icq_LogMessageThread(void* arg)
+{
+ LogMessageInfo *err = (LogMessageInfo*)arg;
+
+ if (!err) return 0;
+ 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;
+
+ return 0;
+}
+
+
+
+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", 1))
+ {
+ if (!ShowPopUpMsg(NULL, 0, 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]);
+ ICQCreateThread(icq_LogMessageThread, lmi);
+ }
+ }
+}
+
+
+
+void icq_LogUsingErrorCode(int level, DWORD dwError, const char *szMsg)
+{
+ char szBuf[1024];
+ char str[1024];
+ char str2[64];
+ char szErrorMsg[512];
+ 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, 1024):"", szMsg?"\r\n\r\n":"", ICQTranslateUtfStatic(pszErrorMsgUtf, szErrorMsg, 512), ICQTranslateUtfStatic("error", str2, 64), dwError);
+ SAFE_FREE(&pszErrorMsgUtf);
+
+ icq_LogMessage(level, szBuf);
+}
+
+
+
+void icq_LogFatalParam(const char* szMsg, WORD wError)
+{
+ char str[MAX_PATH];
+ char buf[MAX_PATH];
+
+ null_snprintf(buf, MAX_PATH, ICQTranslateUtfStatic(szMsg, str, MAX_PATH), wError);
+ icq_LogMessage(LOG_FATAL, buf);
+}
diff --git a/icqj_s7_sss_mod/log.h b/icqj_s7_sss_mod/log.h new file mode 100644 index 0000000..bb28f95 --- /dev/null +++ b/icqj_s7_sss_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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 40 $
+// Last change on : $Date: 2007-08-16 00:42:00 +0300 (Чт, 16 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_CRITICAL 4 //there are no problems at this level. This level needs to avoid error messages.
+
+/*---------* 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_s7_sss_mod/m_assocmgr.h b/icqj_s7_sss_mod/m_assocmgr.h new file mode 100644 index 0000000..5274884 --- /dev/null +++ b/icqj_s7_sss_mod/m_assocmgr.h @@ -0,0 +1,268 @@ +/*
+
+'File Association Manager'-Plugin for
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2005-2007 H. Herkenrath
+
+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 (AssocMgr-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef M_ASSOCMGR_H__
+#define M_ASSOCMGR_H__
+
+#if defined (_MSC_VER) && (_MSC_VER >= 1020)
+ #pragma once
+#endif
+
+#if !defined(_TCHAR_DEFINED)
+ #include <tchar.h>
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning(push) /* save warning settings */
+#pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union */
+#endif
+
+/*
+ File Association Manager v0.1.0.3
+*/
+
+/* interface id */
+#if !defined(MIID_ASSOCMGR)
+ #define MIID_ASSOCMGR {0xa05b56c0,0xcf7b,0x4389,{0xa1,0xe9,0xf1,0x3d,0xb9,0x36,0xe,0xf1}}
+#endif
+
+/* Add a new file type v0.1.0.0+
+Add a new file type to be registered with Windows.
+You probably want to call this event when
+ME_SYSTEM_MODULESLOADED is fired.
+ wParam=0
+ lParam=(LPARAM)(FILETYPEDESC*)ftd
+Returns 0 on success, nonzero otherwise.
+*/
+#define MS_ASSOCMGR_ADDNEWFILETYPE "AssocMgr/AddNewFileType"
+
+typedef struct {
+ int cbSize; // set to sizeof(FILETYPEDESC), in bytes
+ union {
+ const char *pszDescription; // description for options dialog and in registry.
+ const TCHAR *ptszDescription; // please Translate().
+ const WCHAR *pwszDescription;
+ };
+ HINSTANCE hInstance; // instance where the icon resource is located
+
+ UINT nIconResID; // resource id of an icon to use for the file type.
+ // this icon should contain icons of all sizes and color depths
+ // needed by Windows.
+ // set this to 0 to use the generic 'miranda file' icon
+ // provided by assocmgr.
+
+ const char *pszService; // service to call when a file is opened
+ // this service will be called with lParam set to
+ // the file name being opened including path.
+ // it can be assumed that the provided file name
+ // is always the long path name.
+ // return zero on suceess, nonzero on error.
+ // Note: set this to NULL to pass the file name as
+ // commandline argument to miranda32.exe (db file).
+
+ DWORD flags; // see FTDF_* flags below
+
+ const char *pszFileExt; // file extension, e.g. ".ext"
+ // first character must be a dot, assumed to be all lower case.
+ // may only consist of ascii characters.
+
+ const char *pszMimeType; // MIME type of the file, e.g. "application/x-icq"
+ // may only consist of ascii characters.
+ union {
+ const char *pszVerbDesc; // description for the open verb e.g. "&Install".
+ const TCHAR *ptszVerbDesc; // set this to NULL to use the default description.
+ const WCHAR *pwszVerbDesc; // include an ampersand (&) character for a mnemonic key.
+ }; // please Translate().
+} FILETYPEDESC;
+
+#define FTDF_UNICODE 0x0001 // pszDescription and pszVerbDesc in struct are Unicode.
+ // the specified service is called with Unicode parameters.
+
+#define FTDF_DEFAULTDISABLED 0x0002 // file type is not registered by default, it needs to be
+ // enabled explicitly on the options page.
+
+#define FTDF_BROWSERAUTOOPEN 0x0004 // tells the browser to download and open the file directly
+ // without prompt (currently IE and Opera6+) - be careful!
+ // use only in conjunction with pszMimeType set.
+ // this tells Windows that open can be safely invoked for
+ // downloaded files.
+ // Note that this flag may create a security risk,
+ // because downloaded files could contain malicious content.
+ // you need to protect against such an exploit.
+
+#define FTDF_ISTEXT 0x0008 // tells Windows that this file can be opened
+ // as a text file using e.g Notepad.
+ // only has an effect on Windows XP and higher.
+#if defined(_UNICODE)
+ #define FTDF_TCHAR FTDF_UNICODE // strings in struct are WCHAR*, service accepts WCHAR*
+#else
+ #define FTDF_TCHAR 0 // strings in struct are char*, service accepts char*
+#endif
+
+#if !defined(ASSOCMGR_NOHELPERFUNCTIONS)
+__inline static int AssocMgr_AddNewFileType(const char *ext,const char *mime,const char *desc,const char *verb,HINSTANCE hinst,UINT iconid,const char *service,DWORD flags)
+{
+ FILETYPEDESC ftd;
+ ftd.cbSize=sizeof(FILETYPEDESC);
+ ftd.pszFileExt=ext;
+ ftd.pszMimeType=mime;
+ ftd.pszDescription=desc;
+ ftd.pszVerbDesc=verb;
+ ftd.hInstance=hinst;
+ ftd.nIconResID=iconid;
+ ftd.pszService=service;
+ ftd.flags=flags&~FTDF_UNICODE;
+ return CallService(MS_ASSOCMGR_ADDNEWFILETYPE,0,(LPARAM)&ftd);
+}
+__inline static int AssocMgr_AddNewFileTypeW(const char *ext,const char *mime,const WCHAR *desc,const WCHAR *verb,HINSTANCE hinst,UINT iconid,const char *service,DWORD flags)
+{
+ FILETYPEDESC ftd;
+ ftd.cbSize=sizeof(FILETYPEDESC);
+ ftd.pszFileExt=ext;
+ ftd.pszMimeType=mime;
+ ftd.pwszDescription=desc;
+ ftd.pwszVerbDesc=verb;
+ ftd.hInstance=hinst;
+ ftd.nIconResID=iconid;
+ ftd.pszService=service;
+ ftd.flags=flags|FTDF_UNICODE;
+ return CallService(MS_ASSOCMGR_ADDNEWFILETYPE,0,(LPARAM)&ftd);
+}
+#if defined(_UNICODE)
+ #define AssocMgr_AddNewFileTypeT AssocMgr_AddNewFileTypeW
+#else
+ #define AssocMgr_AddNewFileTypeT AssocMgr_AddNewFileType
+#endif
+#endif
+
+/* Remove a file type v0.1.0.0+
+Remove a file type registered previously using
+MS_ASSOCMGR_ADDNEWFILETYPE.
+This removes all settings in database and in registry
+associated with the file type.
+ wParam=0
+ lParam=(WPARAM)(char*)pszFileExt
+Returns 0 on success, nonzero otherwise.
+*/
+#define MS_ASSOCMGR_REMOVEFILETYPE "AssocMgr/RemoveFileType"
+
+/* Add a new url protocol type v0.1.0.0+
+Add a new url type to be registered with Windows.
+You probably want to call this event when
+ME_SYSTEM_MODULESLOADED is fired.
+ wParam=0
+ lParam=(LPARAM)(URLTYPEDESC*)utd
+Returns 0 on success, nonzero otherwise.
+*/
+#define MS_ASSOCMGR_ADDNEWURLTYPE "AssocMgr/AddNewUrlType"
+
+typedef struct {
+ int cbSize; // set to sizeof(URLTYPEDESC), in bytes
+ union {
+ const char *pszDescription; // description for options dialog and in registry.
+ const TCHAR *ptszDescription; // please Translate().
+ const WCHAR *pwszDescription;
+ };
+ HINSTANCE hInstance; // instance where the icon resource is located
+
+ UINT nIconResID; // resource id of an icon to use for the url type.
+ // only a small one (16x16) is needed by Windows,
+ // e.g. proto icon as used in Miranda.
+ // set this to 0 to use the default miranda icon.
+
+ const char *pszService; // service to call when a url is opened (can't be NULL)
+ // this service will be called with lParam set to
+ // the url being opened including the prefix.
+ // the provided string has already been urldecoded.
+ // return zero on suceess, nonzero on error.
+
+ DWORD flags; // see UTDF_* flags below
+
+ const char *pszProtoPrefix; // protocol prefix, e.g. "http:"
+ // last character must be a colon, assumed to be all lower case.
+ // may only consist of ascii characters.
+} URLTYPEDESC;
+
+#define UTDF_UNICODE 0x0001 // pszDescription in struct is Unicode.
+ // the specified service is called with Unicode parameters.
+
+#define UTDF_DEFAULTDISABLED 0x0002 // url type is not registered by default, it needs to be
+ // enabled explicitly on the options page.
+#if defined(_UNICODE)
+ #define UTDF_TCHAR UTDF_UNICODE // strings in struct are WCHAR*, service accepts WCHAR*
+#else
+ #define UTDF_TCHAR 0 // strings in struct are char*, service accepts char*
+#endif
+
+#if !defined(ASSOCMGR_NOHELPERFUNCTIONS)
+static int __inline AssocMgr_AddNewUrlType(const char *prefix,const char *desc,HINSTANCE hinst,UINT iconid,const char *service,DWORD flags)
+{
+ URLTYPEDESC utd;
+ utd.cbSize=sizeof(URLTYPEDESC);
+ utd.pszProtoPrefix=prefix;
+ utd.pszDescription=desc;
+ utd.hInstance=hinst;
+ utd.nIconResID=iconid;
+ utd.pszService=service;
+ utd.flags=flags&~UTDF_UNICODE;
+ return CallService(MS_ASSOCMGR_ADDNEWURLTYPE,0,(LPARAM)&utd);
+}
+static int __inline AssocMgr_AddNewUrlTypeW(const char *prefix,const WCHAR *desc,HINSTANCE hinst,UINT iconid,const char *service,DWORD flags)
+{
+ URLTYPEDESC utd;
+ utd.cbSize=sizeof(URLTYPEDESC);
+ utd.pszProtoPrefix=prefix;
+ utd.pwszDescription=desc;
+ utd.hInstance=hinst;
+ utd.nIconResID=iconid;
+ utd.pszService=service;
+ utd.flags=flags|UTDF_UNICODE;
+ return CallService(MS_ASSOCMGR_ADDNEWURLTYPE,0,(LPARAM)&utd);
+}
+#if defined(_UNICODE)
+ #define AssocMgr_AddNewUrlTypeT AssocMgr_AddNewUrlTypeW
+#else
+ #define AssocMgr_AddNewUrlTypeT AssocMgr_AddNewUrlType
+#endif
+#endif
+
+/* Remove an url protocol type v0.1.0.0+
+Remove an url registered previously using
+MS_ASSOCMGR_ADDNEWURLTYPE.
+This removes all settings in database and in registry
+associated with the url type.
+ wParam=0
+ lParam=(WPARAM)(char*)pszProtoPrefix
+Returns 0 on success, nonzero otherwise.
+*/
+#define MS_ASSOCMGR_REMOVEURLTYPE "AssocMgr/RemoveUrlType"
+
+
+#if defined(_MSC_VER)
+#pragma warning(pop) /* restore warning settings */
+#endif
+
+#ifndef ASSOCMGR_NOSETTINGS
+#define SETTING_ONLYWHILERUNNING_DEFAULT 0
+#endif
+
+#endif // M_ASSOCMGR_H
\ No newline at end of file diff --git a/icqj_s7_sss_mod/m_cluiframes.h b/icqj_s7_sss_mod/m_cluiframes.h new file mode 100644 index 0000000..bf6d565 --- /dev/null +++ b/icqj_s7_sss_mod/m_cluiframes.h @@ -0,0 +1,338 @@ +/*
+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.
+*/
+
+/************************************************************************/
+/* Extra Image Column Support +0.5.0.0 */
+/************************************************************************/
+/*
+ HINT: Common usage of Extra icons by modules
+ Usage sequence is next:
+ The Plugin have to be subscribed to ME_CLIST_EXTRA_LIST_REBUILD and
+ ME_CLIST_EXTRA_IMAGE_APPLY notifications.
+
+ During .._REBUILD Notification handle plugin should register required
+ icons in CList internal list via MS_CLIST_EXTRA_ADD_ICON servise
+ and should to keep returned icon indexes.
+
+ Note: _REBUILD notification means that list was rebuilded and
+ all previously registered icon indexes became invalid and can not be used.
+
+ Note: After calling _ADD_ICON services the icon handle you provided is not
+ need for extra images porpouses and have to be released by you in order
+ to reduce GDI resources consumptions.
+
+ Note: Don't forget that icon handle loaded by LoadIcon GDI function is
+ shared and will be kept in memory till plugin unloading. So it is not
+ better way to load icon. Please use appropriate Iconlib services.
+
+ Note: The icon can be registered in Clist at any time.
+
+ During .._ME_CLIST_EXTRA_IMAGE_APPLY the plugin has to call
+ MS_CLIST_EXTRA_SET_ICON passing appropriate icon index for contact. This
+ service can be called any time in order to change current extra image.
+
+ ATTENTION: Currently Module support only 254 registered extra icons. The returned
+ value 0xFF internally means 'No extra icon' so thry t register only realy required
+ icons. The best solution - register not registered/invalidated icon just before
+ setting of extra image.
+
+ ATTENTION: Due to different module may use same extra icons slot - they will be conflicted.
+ Please provide ability to end-user to change extra image slot to be used to show
+ your plugin information.
+
+*/
+
+//Extra columns type.
+//column arranged in this way
+//
+// [statusicon] ContactName [WEB][ADV1][ADV2][SMS][EMAIL][PROTO][CLIENT]
+//
+#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
+#define EXTRA_ICON_WEB 6
+#define EXTRA_ICON_CLIENT 7
+#define EXTRA_ICON_VISMODE 8
+#define EXTRA_ICON_ADV3 9
+#define EXTRA_ICON_ADV4 10
+
+#define EXTRA_ICON_COUNT 10
+
+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"
+
+//End of extra images header. TODO move it to separate m_extraimages.h file
+//Cause it has not any relationship to cluiframes engine
+
+
+/************************************************************************/
+/* CLUI Frames Support */
+/************************************************************************/
+
+// NOTE: Clui frames engine is in to be reconsructed..
+
+// Constants used bellow
+typedef struct tagCLISTFrame {
+ DWORD cbSize;
+ HWND hWnd ;
+ HICON hIcon;
+ int align; //al flags below
+ union _tagMinSize{
+ int height;
+ int minSize; //the actual meaning depends from type of frame
+ };
+ int Flags; //F_flags below
+ union {
+ char *name; //frame window name indentifier (DO NOT TRANSLATE)
+ wchar_t *wname;
+ LPTSTR tname;
+ };
+ union {
+ char *TBname; //titlebar & menu caption
+ wchar_t *TBwname;
+ LPTSTR TBtname;
+ };
+} 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
+#define F_CANBEVERTICAL 64 //frames can be vertical
+#define F_CANNOTBEHORIZONTAL 128 //frames can NOT be horizontal F_CANBEVERTICAL have to be set
+#define F_NO_SUBCONTAINER 1024 //Support skining no subcontainer needed
+#define F_UNICODE 32768 //Use unicode text
+#ifdef _UNICODE
+# define F_TCHAR F_UNICODE
+#else
+# define F_TCHAR 0
+#endif
+
+// frame alignment
+#define alTop 0x00000001
+#define alBottom 0x00000002
+#define alClient 0x00000004 //only one alClient frame
+
+// since 0.7.0.20
+#define alLeft 0x00000011 // frame is vertical
+#define alRight 0x00000012
+
+#define alVertFrameMask 0x00000010
+
+#define FU_TBREDRAW 1 //redraw titlebar
+#define FU_FMREDRAW 2 //redraw Frame
+#define FU_FMPOS 4 //update Frame position
+
+#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 FO_UNICODETEXT 0x8000 // flag for FO_NAME,FO_TBNAME, FO_TBTIPNAME set/get lPAram as unicode wchar_t
+#ifdef _UNICODE
+ #define FO_TCHAR FO_UNICODETEXT
+#else
+ #define FO_TCHAR 0x0000
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////
+//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.
+#define MS_CLIST_FRAMES_ADDFRAME "CListFrames/AddFrame"
+
+//////////////////////////////////////////////////////////////////////////
+// remove frame. It destroy your window
+//
+#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 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 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"
+
+//////////////////////////////////////////////////////////////////////////
+//Frames related 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"
diff --git a/icqj_s7_sss_mod/m_fingerprint.h b/icqj_s7_sss_mod/m_fingerprint.h new file mode 100644 index 0000000..d45179f --- /dev/null +++ b/icqj_s7_sss_mod/m_fingerprint.h @@ -0,0 +1,63 @@ +/*
+Based on Miranda plugin template, originally by Richard Hughes
+http://miranda-icq.sourceforge.net/
+
+Miranda IM: the free IM client for Microsoft Windows
+
+Copyright 2000-2006 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+
+/************************************************************************/
+/* Author: Artem Shpynov aka FYR mailto:shpynov@nm.ru */
+/* icons by Angeli-Ka */
+/* January 12, 2006 */
+/************************************************************************/
+
+
+/*
+ * FINGERPRINT PLUGIN SERVICES HEADER
+ */
+
+/*
+ * Service SameClients MS_FP_SAMECLIENTS
+ * wParam - char * first MirVer value
+ * lParam - char * second MirVer value
+ * return pointer to char string - client desription (DO NOT DESTROY) if clients are same otherwise NULL
+ */
+#define MS_FP_SAMECLIENTS "Fingerprint/SameClients"
+
+/*
+ * ServiceGetClientIcon MS_FP_GETCLIENTICON
+ * wParam - char * MirVer value to get client for.
+ * lParam - int noCopy - if wParam is equal to "1" will return icon handler without copiing icon.
+ * the returned in this case handler is static valid only till next service call.
+ */
+#define MS_FP_GETCLIENTICON "Fingerprint/GetClientIcon"
+
+
+// Plugin UUIDs for New plugin loader
+// req. 0.7.18+ core
+#define MIID_FINGERPRINT {0xFFF4B77A, 0xCE40, 0x11DB, { 0xA5, 0xCD, 0x06, 0xA7, 0x55, 0xD8, 0x95, 0x93 }} //FFF4B77A-CE40-11DB-A5CD-06A755D89593
+#define MIID_FINGERPRINT_MOD {0xBAC0BBBE, 0xCE40, 0x11DB, { 0xA1, 0x1E, 0x72, 0xA6, 0x55, 0xD8, 0x95, 0x93 }} //BAC0BBBE-CE40-11DB-A11E-72A655D89593
+#define MIID_FINGERPRINT_MOD_FULL {0x0afe5bbb, 0xce62, 0x11db, { 0x83, 0x14, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 }} //0afe5bbb-ce62-11db-8314-0800200c9a66
+#define MIID_FINGERPRINT_MOD_STANDARD {0x0afe5abc, 0xce62, 0x11db, { 0x83, 0x14, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 }} //0afe5abc-ce62-11db-8314-0800200c9a66
+#define MIID_FINGERPRINT_MOD_LITE {0x0afe5def, 0xce62, 0x11db, { 0x83, 0x14, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 }} //0afe5def-ce62-11db-8314-0800200c9a66
+#define MIID_FINGERPRINT_MOD_CUSTOM {0x0afe5bad, 0xce62, 0x11db, { 0x83, 0x14, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 }} //0afe5bad-ce62-11db-8314-0800200c9a66
+
+
diff --git a/icqj_s7_sss_mod/m_folders.h b/icqj_s7_sss_mod/m_folders.h new file mode 100644 index 0000000..c6820ab --- /dev/null +++ b/icqj_s7_sss_mod/m_folders.h @@ -0,0 +1,282 @@ +/*
+Custom profile folders plugin for Miranda IM
+
+Copyright 2005 Cristian Libotean
+
+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.
+*/
+
+#ifndef M_CUSTOM_FOLDERS_H
+#define M_CUSTOM_FOLDERS_H
+
+#define FOLDERS_API 501 //dunno why it's here but it is :)
+
+#define PROFILE_PATH "%profile_path%"
+#define CURRENT_PROFILE "%current_profile%"
+#define MIRANDA_PATH "%miranda_path%"
+#define PLUGINS_PATH "%miranda_path%" "\\plugins"
+
+#define TO_WIDE(x) L ## x
+
+#define PROFILE_PATHW L"%profile_path%"
+#define CURRENT_PROFILEW L"%current_profile%"
+#define MIRANDA_PATHW L"%miranda_path%"
+
+#define FOLDER_AVATARS PROFILE_PATH "\\" CURRENT_PROFILE "\\avatars"
+#define FOLDER_VCARDS PROFILE_PATH "\\" CURRENT_PROFILE "\\vcards"
+#define FOLDER_LOGS PROFILE_PATH "\\" CURRENT_PROFILE "\\logs"
+#define FOLDER_RECEIVED_FILES PROFILE_PATH "\\" CURRENT_PROFILE "\\received files"
+#define FOLDER_DOCS MIRANDA_PATH "\\" "docs"
+
+#define FOLDER_CONFIG PLUGINS_PATH "\\" "config"
+
+#define FOLDER_SCRIPTS MIRANDA_PATH "\\" "scripts"
+
+#define FOLDER_UPDATES MIRANDA_PATH "\\" "updates"
+
+#define FOLDER_CUSTOMIZE MIRANDA_PATH "\\" "customize"
+#define FOLDER_CUSTOMIZE_SOUNDS FOLDER_CUSTOMIZE "\\sounds"
+#define FOLDER_CUSTOMIZE_ICONS FOLDER_CUSTOMIZE "\\icons"
+#define FOLDER_CUSTOMIZE_SMILEYS FOLDER_CUSTOMIZE "\\smileys"
+#define FOLDER_CUSTOMIZE_SKINS FOLDER_CUSTOMIZE "\\skins"
+#define FOLDER_CUSTOMIZE_THEMES FOLDER_CUSTOMIZE "\\themes"
+
+
+#define FOLDERS_NAME_MAX_SIZE 64 //maximum name and section size
+
+#define FF_UNICODE 0x00000001
+
+#if defined (UNICODE)
+ #define FF_TCHAR FF_UNICODE
+#else
+ #define FF_TCHAR 0
+#endif
+
+typedef struct{
+ int cbSize; //size of struct
+ char szSection[FOLDERS_NAME_MAX_SIZE]; //section name, if it doesn't exist it will be created otherwise it will just add this entry to it
+ char szName[FOLDERS_NAME_MAX_SIZE]; //entry name - will be shown in options
+ union{
+ const char *szFormat; //default string format. Fallback string in case there's no entry in the database for this folder. This should be the initial value for the path, users will be able to change it later.
+ const wchar_t *szFormatW; //String is dup()'d so you can free it later. If you set the unicode string don't forget to set the flag accordingly.
+ const TCHAR *szFormatT;
+ };
+ DWORD flags; //FF_* flags
+} FOLDERSDATA;
+
+/*Folders/Register/Path service
+ wParam - not used, must be 0
+ lParam - (LPARAM) (const FOLDERDATA *) - Data structure filled with
+ the necessary information.
+ Returns a handle to the registered path or 0 on error.
+ You need to use this to call the other services.
+*/
+#define MS_FOLDERS_REGISTER_PATH "Folders/Register/Path"
+
+/*Folders/Get/PathSize service
+ wParam - (WPARAM) (int) - handle to registered path
+ lParam - (LPARAM) (int *) - pointer to the variable that receives the size of the path
+ string (not including the null character). Depending on the flags set when creating the path
+ it will either call strlen() or wcslen() to get the length of the string.
+ Returns the size of the buffer.
+*/
+#define MS_FOLDERS_GET_SIZE "Folders/Get/PathSize"
+
+typedef struct{
+ int cbSize;
+ int nMaxPathSize; //maximum size of buffer. This represents the number of characters that can be copied to it (so for unicode strings you don't send the number of bytes but the length of the string).
+ union{
+ char *szPath; //pointer to the buffer that receives the path without the last "\\"
+ wchar_t *szPathW; //unicode version of the buffer.
+ TCHAR *szPathT;
+ };
+} FOLDERSGETDATA;
+
+/*Folders/Get/Path service
+ wParam - (WPARAM) (int) - handle to registered path
+ lParam - (LPARAM) (FOLDERSGETDATA *) pointer to a FOLDERSGETDATA that has all the relevant fields filled.
+ Should return 0 on success, or nonzero otherwise.
+*/
+#define MS_FOLDERS_GET_PATH "Folders/Get/Path"
+
+typedef struct{
+ int cbSize;
+ union{
+ char **szPath; //address of a string variable (char *) or (wchar_t*) where the path should be stored (the last \ won't be copied).
+ wchar_t **szPathW; //unicode version of string.
+ TCHAR **szPathT;
+ };
+} FOLDERSGETALLOCDATA;
+
+/*Folders/GetRelativePath/Alloc service
+ wParam - (WPARAM) (int) - Handle to registered path
+ lParam - (LPARAM) (FOLDERSALLOCDATA *) data
+ This service is the same as MS_FOLDERS_GET_PATH with the difference that this service
+ allocates the needed space for the buffer. It uses miranda's memory functions for that and you need
+ to use those to free the resulting buffer.
+ Should return 0 on success, or nonzero otherwise. Currently it only returns 0.
+*/
+#define MS_FOLDERS_GET_PATH_ALLOC "Folders/Get/Path/Alloc"
+
+
+/*Folders/On/Path/Changed
+ wParam - (WPARAM) 0
+ lParam - (LPARAM) 0
+ Triggered when the folders change, you should reget the paths you registered.
+*/
+#define ME_FOLDERS_PATH_CHANGED "Folders/On/Path/Changed"
+
+#ifndef FOLDERS_NO_HELPER_FUNCTIONS
+
+#ifndef M_UTILS_H__
+#error The helper functions require that m_utils.h be included in the project. Please include that file if you want to use the helper functions. If you don't want to use the functions just define FOLDERS_NO_HELPER_FUNCTIONS.
+#endif
+//#include "../../../include/newpluginapi.h"
+
+__inline static HANDLE FoldersRegisterCustomPath(const char *section, const char *name, const char *defaultPath)
+{
+ FOLDERSDATA fd = {0};
+ if (!ServiceExists(MS_FOLDERS_REGISTER_PATH)) return 0;
+ fd.cbSize = sizeof(FOLDERSDATA);
+ strncpy(fd.szSection, section, FOLDERS_NAME_MAX_SIZE);
+ fd.szSection[FOLDERS_NAME_MAX_SIZE - 1] = '\0';
+ strncpy(fd.szName, name, FOLDERS_NAME_MAX_SIZE);
+ fd.szName[FOLDERS_NAME_MAX_SIZE - 1] = '\0';
+ fd.szFormat = defaultPath;
+ return (HANDLE) CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM) &fd);
+}
+
+__inline static HANDLE FoldersRegisterCustomPathW(const char *section, const char *name, const wchar_t *defaultPathW)
+{
+ FOLDERSDATA fd = {0};
+ if (!ServiceExists(MS_FOLDERS_REGISTER_PATH)) return 0;
+ fd.cbSize = sizeof(FOLDERSDATA);
+ strncpy(fd.szSection, section, FOLDERS_NAME_MAX_SIZE);
+ fd.szSection[FOLDERS_NAME_MAX_SIZE - 1] = '\0'; //make sure it's NULL terminated
+ strncpy(fd.szName, name, FOLDERS_NAME_MAX_SIZE);
+ fd.szName[FOLDERS_NAME_MAX_SIZE - 1] = '\0'; //make sure it's NULL terminated
+ fd.szFormatW = defaultPathW;
+ fd.flags = FF_UNICODE;
+ return (HANDLE) CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM) &fd);
+}
+
+__inline static int FoldersGetCustomPath(HANDLE hFolderEntry, char *path, const int size, char *notFound)
+{
+ FOLDERSGETDATA fgd = {0};
+ int res;
+ fgd.cbSize = sizeof(FOLDERSGETDATA);
+ fgd.nMaxPathSize = size;
+ fgd.szPath = path;
+ res = CallService(MS_FOLDERS_GET_PATH, (WPARAM) hFolderEntry, (LPARAM) &fgd);
+ if (res)
+ {
+ char buffer[MAX_PATH];
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM) notFound, (LPARAM) buffer);
+ mir_snprintf(path, size, "%s", buffer);
+ }
+
+ return res;
+}
+
+__inline static int FoldersGetCustomPathW(HANDLE hFolderEntry, wchar_t *pathW, const int count, wchar_t *notFoundW)
+{
+ FOLDERSGETDATA fgd = {0};
+ int res;
+ fgd.cbSize = sizeof(FOLDERSGETDATA);
+ fgd.nMaxPathSize = count;
+ fgd.szPathW = pathW;
+ res = CallService(MS_FOLDERS_GET_PATH, (WPARAM) hFolderEntry, (LPARAM) &fgd);
+ if (res)
+ {
+ wcsncpy(pathW, notFoundW, count);
+ pathW[count - 1] = '\0';
+ }
+
+ return res;
+}
+
+__inline static int FoldersGetCustomPathEx(HANDLE hFolderEntry, char *path, const int size, char *notFound, char *fileName)
+{
+ FOLDERSGETDATA fgd = {0};
+ int res;
+ fgd.cbSize = sizeof(FOLDERSGETDATA);
+ fgd.nMaxPathSize = size;
+ fgd.szPath = path;
+ res = CallService(MS_FOLDERS_GET_PATH, (WPARAM) hFolderEntry, (LPARAM) &fgd);
+ if (res)
+ {
+ char buffer[MAX_PATH];
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM) notFound, (LPARAM) buffer);
+ mir_snprintf(path, size, "%s", buffer);
+ }
+ if (strlen(path) > 0)
+ {
+ strcat(path, "\\");
+ }
+ else{
+ path[0] = '\0';
+ }
+
+ if (fileName)
+ {
+ strcat(path, fileName);
+ }
+
+ return res;
+}
+
+__inline static int FoldersGetCustomPathExW(HANDLE hFolderEntry, wchar_t *pathW, const int count, wchar_t *notFoundW, wchar_t *fileNameW)
+{
+ FOLDERSGETDATA fgd = {0};
+ int res;
+ fgd.cbSize = sizeof(FOLDERSGETDATA);
+ fgd.nMaxPathSize = count;
+ fgd.szPathW = pathW;
+ res = CallService(MS_FOLDERS_GET_PATH, (WPARAM) hFolderEntry, (LPARAM) &fgd);
+ if (res)
+ {
+ wcsncpy(pathW, notFoundW, count);
+ pathW[count - 1] = '\0';
+ }
+
+ if (wcslen(pathW) > 0)
+ {
+ wcscat(pathW, L"\\");
+ }
+ else{
+ pathW[0] = L'\0';
+ }
+
+ if (fileNameW)
+ {
+ wcscat(pathW, fileNameW);
+ }
+
+ return res;
+}
+
+# ifdef _UNICODE
+# define FoldersGetCustomPathT FoldersGetCustomPathW
+# define FoldersGetCustomPathExT FoldersGetCustomPathExW
+# define FoldersRegisterCustomPathT FoldersRegisterCustomPathW
+#else
+# define FoldersGetCustomPathT FoldersGetCustomPath
+# define FoldersGetCustomPathExT FoldersGetCustomPath
+# define FoldersRegisterCustomPathT FoldersRegisterCustomPath
+#endif
+
+#endif
+
+#endif //M_CUSTOM_FOLDERS_H
\ No newline at end of file diff --git a/icqj_s7_sss_mod/m_icq.h b/icqj_s7_sss_mod/m_icq.h new file mode 100644 index 0000000..2f4a19e --- /dev/null +++ b/icqj_s7_sss_mod/m_icq.h @@ -0,0 +1,346 @@ +// ---------------------------------------------------------------------------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,2007 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 : $URL: https://miranda.svn.sourceforge.net/svnroot/miranda/trunk/miranda/include/m_icq.h $
+// Revision : $Revision: 6572 $
+// Last change on : $Date: 2007-10-12 00:37:38 +0300 (Пт, 12 окт 2007) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef M_ICQ_H__
+#define M_ICQ_H__ 1
+
+#define MS_SETINVIS "/SetInvis"
+#define MS_SETVIS "/SetVis"
+
+#define MS_INCOGNITO_REQUEST "/IncognitoRequest"
+
+
+// Add contact to server-list
+// wParam=(WPARAM)hContact
+#define MS_ICQ_ADDSERVCONTACT "/AddServerContact"
+
+
+
+// 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"
+
+// Add contact to server-list
+// wParam=(WPARAM)hContact
+#define MS_ICQ_ADDSERVCONTACT "/AddServerContact"
+
+// Display XStatus detail (internal use only)
+// wParam=(WPARAM)hContact;
+#define MS_XSTATUS_SHOWDETAILS "/ShowXStatusDetails"
+
+#define MS_SEND_TZER "/SendtZer"
+
+//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"
+
+//Set password for current session
+//lParam=(LPARAM)(const char*)szPassword
+#define PS_ICQ_SETPASSWORD "/SetPassword"
+
+//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"
+
+
+
+/* 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-37)
+//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-37), 0 = my current custom status
+//lParam = flags // use LR_SHARED for shared HICON
+//return = HICON // custom status icon (use DestroyIcon to release resources if not LR_SHARED)
+#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"
+
+// Called when a contact changes its custom status
+// wParam = hContact
+// lParam = 0
+#define ME_ICQ_CUSTOMSTATUS_CHANGED "/XStatusChanged"
+
+// Called from contact list in order to get index of custom status icon in list
+// wParam = hContact
+// lParam = 0
+// rerurn = (int) index of extra contact icon shifted <<16 (the low word will be normal status icon, the high will be xStatus Icon
+#define PS_ICQ_GETADVANCEDSTATUSICON "/GetAdvancedStatusIcon"
+
+
+#define MAX_CAPNAME 64
+typedef struct
+{
+ int cbSize;
+ char caps[0x10];
+ HANDLE hIcon;
+ char name[MAX_CAPNAME];
+} ICQ_CUSTOMCAP;
+
+// Add a custom icq capability.
+// wParam = 0;
+// lParam = (LPARAM)(ICQ_CUSTOMCAP *)&icqCustomCap;
+#define PS_ICQ_ADDCAPABILITY "/IcqAddCapability"
+
+// Check if capability is supportes. Only icqCustomCap.caps does matter.
+// wParam = (WPARAM)(HANDLE)hContact;
+// lParam = (LPARAM)(ICQ_CUSTOMCAP *)&icqCustomCap;
+// returns non-zero if capability is supported
+#define PS_ICQ_CHECKCAPABILITY "/IcqCheckCapability"
+
+
+#ifndef ICQ_NOHELPERS
+static __inline void IcqBuildMirandaCap(ICQ_CUSTOMCAP *icqCustomCap, const char *name, HICON hIcon, const char *id)
+{
+ if (!icqCustomCap) return;
+ icqCustomCap->cbSize = sizeof(*icqCustomCap);
+ icqCustomCap->hIcon = hIcon;
+ strncpy(icqCustomCap->name, name, sizeof(icqCustomCap->name))[sizeof(icqCustomCap->name)-1]=0;
+ memset(icqCustomCap->caps, 0, 0x10);
+ strncpy(icqCustomCap->caps+0, "Miranda/", 8);
+ strncpy(icqCustomCap->caps+8, id, 8);
+}
+#endif
+
+/* usage:
+char icqCustomCapStr[0x10] = {...};
+ICQ_CUSTOMCAP icqCustomCap;
+icqCustomCap.cbSize = sizeof(icqCustomCap);
+memcpy(icqCustomCap.caps, icqCustomCapStr, 0x10);
+lstrcpy(icqCustomCap.name, "Custom Name");
+CallProtoService("ICQ", PS_ICQ_ADDCAPABILITY, 0, (LPARAM)&icqCustomCap);
+*/
+
+#endif // M_ICQ_H__
\ No newline at end of file diff --git a/icqj_s7_sss_mod/m_updater.h b/icqj_s7_sss_mod/m_updater.h new file mode 100644 index 0000000..488d372 --- /dev/null +++ b/icqj_s7_sss_mod/m_updater.h @@ -0,0 +1,150 @@ +#ifndef _M_UPDATER_H
+#define _M_UPDATER_H
+
+// NOTES:
+// - For langpack updates, include a string of the following format in the langpack text file:
+// ";FLID: <file listing name> <version>"
+// version must be four numbers seperated by '.', in the range 0-255 inclusive
+// - Updater will disable plugins that are downloaded but were not active prior to the update (this is so that, if an archive contains e.g. ansi and
+// unicode versions, the correct plugin will be the only one active after the new version is installed)...so if you add a support plugin, you may need
+// to install an ini file to make the plugin activate when miranda restarts after the update
+// - Updater will replace all dlls that have the same internal shortName as a downloaded update dll (this is so that msn1.dll and msn2.dll, for example,
+// will both be updated) - so if you have a unicode and a non-unicode version of a plugin in your archive, you should make the internal names different (which will break automatic
+// updates from the file listing if there is only one file listing entry for both versions, unless you use the 'MS_UPDATE_REGISTER' service below)
+// - Updater will install all files in the root of the archive into the plugins folder, except for langpack files that contain the FLID string which go into the root folder (same
+// folder as miranda32.exe)...all folders in the archive will also be copied to miranda's root folder, and their contents transferred into the new folders. The only exception is a
+// special folder called 'root_files' - if there is a folder by that name in the archive, it's contents will also be copied into miranda's root folder - this is intended to be used
+// to install additional dlls etc that a plugin may require)
+
+// 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"
+// Updater will also use the backend xml data if you provide URL's that reference the miranda file listing for updates (so you can use that method
+// if e.g. your plugin shortName does not match the file listing) - it will grab the file listing id from the end of these URLs
+
+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
+ // (note that this URL could point at a binary file - dunno why, but it could :)
+ int cpbVersionPrefix; // number of bytes pointed 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 pointed 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 pointed to by pbVersion
+
+ char *szBetaChangelogURL; // url for displaying changelog for beta versions
+} Update;
+
+// register a comonent with 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);
+}
+
+__inline static char *CreateVersionStringPluginEx(PLUGININFOEX *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 version string on the file listing must be the string version of the version in pluginInfo (i.e. 0.0.0.1,
+// four numbers between 0 and 255 inclusivem, 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 function can be used to 'unregister' components - useful for plugins that register non-plugin/langpack components and
+// may need to change those components on the fly
+// lParam = (char *)szComponentName
+#define MS_UPDATE_UNREGISTER "Update/Unregister"
+
+// 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.
+
+// this service can be used to determine whether updates are possible for a component with the given name
+// wParam = 0
+// lParam = (char *)szComponentName
+// returns TRUE if updates are supported, FALSE otherwise
+#define MS_UPDATE_ISUPDATESUPPORTED "Update/IsUpdateSupported"
+
+#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);
+
+ // do the same for the beta versions of the above struct members if you wish to allow beta updates from another URL
+
+ 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_s7_sss_mod/oscar_filetransfer.c b/icqj_s7_sss_mod/oscar_filetransfer.c new file mode 100644 index 0000000..e7849f9 --- /dev/null +++ b/icqj_s7_sss_mod/oscar_filetransfer.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,2007 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 : $URL: https://icqjplusmod.googlecode.com/svn/trunk/oscar_filetransfer.c $
+// Revision : $Revision: 50 $
+// Last change on : $Date: 2007-08-28 02:57:00 +0300 (Вт, 28 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+typedef struct {
+ int type;
+ int incoming;
+ HANDLE hContact;
+ HANDLE hConnection;
+ DWORD dwRemoteIP;
+ oscar_filetransfer *ft;
+ oscar_listener *listener;
+} oscarthreadstartinfo;
+
+
+// small utility function
+extern void NormalizeBackslash(char* path);
+
+static void oft_newConnectionReceived(HANDLE hNewConnection, DWORD dwRemoteIP, void *pExtra);
+
+static DWORD __stdcall oft_connectionThread(oscarthreadstartinfo *otsi);
+static void sendOscarPacket(oscar_connection *oc, icq_packet *packet);
+static int oft_handlePackets(oscar_connection *oc, unsigned char *buf, int len);
+static int oft_handleFileData(oscar_connection *oc, unsigned char *buf, int len);
+static int oft_handleProxyData(oscar_connection *oc, unsigned char *buf, int len);
+static void handleOFT2FramePacket(oscar_connection *oc, WORD datatype, BYTE *pBuffer, WORD wLen);
+static void sendOFT2FramePacket(oscar_connection *oc, WORD datatype);
+
+static void oft_sendFileData(oscar_connection *oc);
+static void oft_sendPeerInit(oscar_connection *oc);
+
+static void proxy_sendInitTunnel(oscar_connection *oc);
+static void proxy_sendJoinTunnel(oscar_connection *oc, WORD wPort);
+
+
+static CRITICAL_SECTION oftMutex;
+static int fileTransferCount = 0;
+static basic_filetransfer** fileTransferList = NULL;
+
+static oscar_filetransfer* CreateOscarTransfer();
+static void ReleaseFileTransfer(void *ft);
+static oscar_filetransfer* FindOscarTransfer(HANDLE hContact, DWORD dwID1, DWORD dwID2);
+
+
+//
+// Common functions
+/////////////////////////////
+
+char* FindFilePathContainer(const char** files, int iFile, char* szContainer)
+{
+ int i;
+ const char* szThisFile = files[iFile];
+ char* szFileName = ExtractFileName(szThisFile);
+
+ szContainer[0] = '\0';
+
+ if (szThisFile != szFileName)
+ { // find an earlier subdirectory to be used as a container
+ for (i = iFile - 1; i >= 0; i--)
+ {
+ int len = strlennull(files[i]);
+
+ if (!_strnicmp(files[i], szThisFile, len) && (szThisFile[len] == '\\' || szThisFile[len] == '/'))
+ {
+ char* pszLastBackslash;
+
+ if (((pszLastBackslash = strrchr(files[i], '\\')) == NULL) &&
+ ((pszLastBackslash = strrchr(files[i], '/')) == NULL))
+ {
+ strcpy(szContainer, files[i]);
+ }
+ else
+ {
+ len = pszLastBackslash - files[i] + 1;
+ strncpy(szContainer, szThisFile + len, szFileName - szThisFile - len);
+ szContainer[szFileName - szThisFile - len] = '\0';
+ }
+ }
+ }
+ }
+ return szFileName;
+}
+
+
+//
+// Utility functions
+/////////////////////////////
+
+
+static oscar_filetransfer* CreateOscarTransfer()
+{
+ oscar_filetransfer* ft = (oscar_filetransfer*)SAFE_MALLOC(sizeof(oscar_filetransfer));
+
+ ft->ft_magic = FT_MAGIC_OSCAR; // Setup signature
+ // Init members
+ ft->fileId = -1;
+
+ EnterCriticalSection(&oftMutex);
+
+ fileTransferList = (basic_filetransfer**)SAFE_REALLOC(fileTransferList, sizeof(basic_filetransfer*)*(fileTransferCount + 1));
+ fileTransferList[fileTransferCount++] = (basic_filetransfer*)ft;
+
+#ifdef _DEBUG
+ NetLog_Direct("OFT: FT struct 0x%x created", ft);
+#endif
+ LeaveCriticalSection(&oftMutex);
+
+ return ft;
+}
+
+
+
+filetransfer *CreateIcqFileTransfer()
+{
+ filetransfer *ft = (filetransfer*)SAFE_MALLOC(sizeof(filetransfer));
+
+ ft->ft_magic = FT_MAGIC_ICQ;
+
+ EnterCriticalSection(&oftMutex);
+
+ fileTransferList = (basic_filetransfer**)SAFE_REALLOC(fileTransferList, sizeof(basic_filetransfer*)*(fileTransferCount + 1));
+ fileTransferList[fileTransferCount++] = (basic_filetransfer*)ft;
+
+#ifdef _DEBUG
+ NetLog_Direct("FT struct 0x%x created", ft);
+#endif
+ LeaveCriticalSection(&oftMutex);
+
+ return ft;
+}
+
+
+
+static int getFileTransferIndex(void *ft)
+{
+ int i;
+
+ for (i = 0; i < fileTransferCount; i++)
+ {
+ if (fileTransferList[i] == ft)
+ return i;
+ }
+ return -1;
+}
+
+
+
+static void ReleaseFileTransfer(void *ft)
+{
+ int i = getFileTransferIndex(ft);
+
+ if (i != -1)
+ {
+ fileTransferCount--;
+ fileTransferList[i] = fileTransferList[fileTransferCount];
+ fileTransferList = (basic_filetransfer**)SAFE_REALLOC(fileTransferList, sizeof(basic_filetransfer*)*fileTransferCount);
+ }
+}
+
+
+
+int IsValidFileTransfer(void *ft)
+{
+ int res = 0;
+
+ EnterCriticalSection(&oftMutex);
+
+ if (getFileTransferIndex(ft) != -1) res = 1;
+
+ LeaveCriticalSection(&oftMutex);
+
+ return res;
+}
+
+
+
+int IsValidOscarTransfer(void *ft)
+{
+ int res = 0;
+
+ EnterCriticalSection(&oftMutex);
+
+ if (getFileTransferIndex(ft) != -1 && ((basic_filetransfer*)ft)->ft_magic == FT_MAGIC_OSCAR)
+ res = 1;
+
+ LeaveCriticalSection(&oftMutex);
+
+ return res;
+}
+
+
+
+static oscar_filetransfer* FindOscarTransfer(HANDLE hContact, DWORD dwID1, DWORD dwID2)
+{
+ int i;
+
+ EnterCriticalSection(&oftMutex);
+
+ for (i = 0; i < fileTransferCount; i++)
+ {
+ if (((basic_filetransfer*)fileTransferList[i])->ft_magic == FT_MAGIC_OSCAR)
+ {
+ oscar_filetransfer *oft = (oscar_filetransfer*)fileTransferList[i];
+
+ if (oft->hContact == hContact && oft->pMessage.dwMsgID1 == dwID1 && oft->pMessage.dwMsgID2 == dwID2)
+ {
+ LeaveCriticalSection(&oftMutex);
+
+ return oft;
+ }
+ }
+ }
+
+ LeaveCriticalSection(&oftMutex);
+
+ return NULL;
+}
+
+
+
+// Release file transfer structure
+void SafeReleaseFileTransfer(void **ft)
+{
+ basic_filetransfer **bft = (basic_filetransfer**)ft;
+
+ EnterCriticalSection(&oftMutex);
+
+ // Check for filetransfer validity
+ if (getFileTransferIndex(*ft) == -1)
+ {
+ LeaveCriticalSection(&oftMutex);
+ return;
+ }
+
+ if (*bft)
+ {
+ if ((*bft)->ft_magic == FT_MAGIC_ICQ)
+ { // release ICQ filetransfer structure and its contents
+ filetransfer *ift = (filetransfer*)(*bft);
+
+ SAFE_FREE(&ift->szFilename);
+ SAFE_FREE(&ift->szDescription);
+ SAFE_FREE(&ift->szSavePath);
+ SAFE_FREE(&ift->szThisFile);
+ SAFE_FREE(&ift->szThisSubdir);
+ if (ift->files)
+ {
+ int i;
+
+ for (i = 0; i < (int)ift->dwFileCount; i++)
+ SAFE_FREE(&ift->files[i]);
+ SAFE_FREE((char**)&ift->files);
+ }
+ // Invalidate transfer
+ ReleaseFileTransfer(ift);
+#ifdef _DEBUG
+ NetLog_Direct("FT struct 0x%x released", ft);
+#endif
+ // Release memory
+ SAFE_FREE(ft);
+ }
+ else if ((*bft)->ft_magic == FT_MAGIC_OSCAR)
+ { // release oscar filetransfer structure and its contents
+ oscar_filetransfer *oft = (oscar_filetransfer*)(*bft);
+ // If connected, close connection
+ if (oft->connection)
+ CloseOscarConnection(oft->connection);
+ // Release oscar listener
+ if (oft->listener)
+ ReleaseOscarListener((oscar_listener**)&oft->listener);
+ // Release cookie
+ if (oft->dwCookie)
+ FreeCookie(oft->dwCookie);
+ // Release all dynamic members
+ SAFE_FREE(&oft->rawFileName);
+ SAFE_FREE(&oft->szSavePath);
+ SAFE_FREE(&oft->szThisFile);
+ SAFE_FREE(&oft->szThisPath);
+ if (oft->files)
+ {
+ int i;
+
+ for (i = 0; i < oft->wFilesCount; i++)
+ SAFE_FREE(&oft->files[i].szFile);
+ SAFE_FREE((void**)&oft->files);
+ }
+ if (oft->files_ansi)
+ {
+ int i;
+
+ for (i = 0; i < oft->wFilesCount; i++)
+ SAFE_FREE(&oft->files_ansi[i]);
+ SAFE_FREE((void**)&oft->files_ansi);
+ }
+ if (oft->file_containers)
+ {
+ int i;
+
+ for (i = 0; i < oft->containerCount; i++)
+ SAFE_FREE(&oft->file_containers[i]);
+ SAFE_FREE((void**)&oft->file_containers);
+ }
+ if (oft->fileId != -1)
+ {
+#ifdef _DEBUG
+ NetLog_Direct("OFT: _close(%u)", oft->fileId);
+#endif
+ _close(oft->fileId);
+ }
+ // Invalidate transfer
+ ReleaseFileTransfer(oft);
+#ifdef _DEBUG
+ NetLog_Direct("OFT: FT struct 0x%x released", ft);
+#endif
+ // Release memory
+ SAFE_FREE(ft);
+ }
+ }
+ LeaveCriticalSection(&oftMutex);
+}
+
+
+
+
+// Calculate oft checksum of buffer
+// --------------------------------
+// Information was gathered from Gaim's sources, thanks
+//
+DWORD oft_calc_checksum(int offset, const BYTE *buffer, int len, DWORD dwChecksum)
+{
+ DWORD checksum;
+ int i;
+
+ checksum = (dwChecksum >> 16) & 0xffff;
+ for (i = 0; i < len; i++)
+ {
+ WORD val = buffer[i];
+ DWORD oldchecksum = checksum;
+
+ if (((i + offset) & 1) == 0)
+ val = val << 8;
+
+ if (checksum < val)
+ checksum -= val + 1;
+ else // simulate carry
+ checksum -= val;
+ }
+ checksum = ((checksum & 0x0000ffff) + (checksum >> 16));
+ checksum = ((checksum & 0x0000ffff) + (checksum >> 16));
+ return checksum << 16;
+}
+
+
+
+DWORD oft_calc_file_checksum(int hFile, __int64 maxSize)
+{
+ BYTE buf[OFT_BUFFER_SIZE];
+ int bytesRead;
+ __int64 offset = 0;
+ DWORD dwCheck = 0xFFFF0000;
+
+ _lseek(hFile, 0, SEEK_SET);
+ bytesRead = _read(hFile, buf, sizeof(buf));
+ if (bytesRead == -1)
+ return dwCheck;
+
+ while(bytesRead)
+ {
+ dwCheck = oft_calc_checksum((int)offset, buf, bytesRead, dwCheck);
+ offset += bytesRead;
+ bytesRead = _read(hFile, buf, sizeof(buf));
+ if (bytesRead + offset > maxSize) bytesRead = (int)(maxSize - offset);
+ }
+ _lseek(hFile, 0, SEEK_SET); // back to beginning
+
+ return dwCheck;
+}
+
+
+
+oscar_listener* CreateOscarListener(oscar_filetransfer *ft, NETLIBNEWCONNECTIONPROC_V2 handler)
+{
+ oscar_listener *listener = (oscar_listener*)SAFE_MALLOC(sizeof(oscar_listener));
+
+ listener->ft = ft;
+ if (listener->hBoundPort = NetLib_BindPort(handler, listener, &listener->wPort, NULL))
+ return listener; // Success
+
+ SAFE_FREE(&listener);
+
+ return NULL; // Failure
+}
+
+
+
+void ReleaseOscarListener(oscar_listener **pListener)
+{
+ oscar_listener *listener = *pListener;
+
+ if (listener)
+ { // Close listening port
+ if (listener->hBoundPort)
+ NetLib_SafeCloseHandle(&listener->hBoundPort);
+
+ NetLog_Direct("Oscar listener on port %d released.", listener->wPort);
+ }
+ SAFE_FREE(pListener);
+}
+
+
+//
+// Miranda FT interface handlers & services
+/////////////////////////////
+
+void InitOscarFileTransfer()
+{
+ InitializeCriticalSection(&oftMutex);
+}
+
+
+
+void UninitOscarFileTransfer()
+{
+ DeleteCriticalSection(&oftMutex);
+}
+
+
+
+void handleRecvServMsgOFT(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwID1, DWORD dwID2, WORD wCommand)
+{
+ HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
+
+ if (wCommand == 0)
+ { // this is OFT request
+ oscar_tlv_chain* chain = readIntoTLVChain(&buf, wLen, 0);
+
+ if (chain)
+ {
+ WORD wAckType = getWordFromChain(chain, 0x0A, 1);
+
+ if (wAckType == 1)
+ { // This is first request in this OFT
+ oscar_filetransfer *ft = CreateOscarTransfer();
+ char* pszFileName = NULL;
+ char* pszDescription = NULL;
+ WORD wFilenameLength;
+
+ NetLog_Server("This is a file request");
+
+ // This TLV chain may contain the following TLVs:
+ // TLV(A): Acktype 0x0001 - file request / abort request
+ // 0x0002 - file ack
+ // TLV(F): Unknown
+ // TLV(E): Language ?
+ // TLV(2): Proxy IP
+ // TLV(16): Proxy IP Check
+ // TLV(3): External IP
+ // TLV(4): Internal IP
+ // TLV(5): Port
+ // TLV(17): Port Check
+ // TLV(10): Proxy Flag
+ // TLV(D): Charset of User Message
+ // TLV(C): User Message (ICQ_COOL_FT)
+ // TLV(2711): FT info
+ // TLV(2712): Charset of file name
+
+ // init filetransfer structure
+ ft->pMessage.dwMsgID1 = dwID1;
+ ft->pMessage.dwMsgID2 = dwID2;
+ ft->bUseProxy = getTLV(chain, 0x10, 1) ? 1 : 0;
+ ft->dwProxyIP = getDWordFromChain(chain, 0x02, 1);
+ ft->dwRemoteInternalIP = getDWordFromChain(chain, 0x03, 1);
+ ft->dwRemoteExternalIP = getDWordFromChain(chain, 0x04, 1);
+ ft->wRemotePort = getWordFromChain(chain, 0x05, 1);
+ ft->wReqNum = wAckType;
+
+ { // User Message
+ oscar_tlv* tlv = getTLV(chain, 0x0C, 1);
+
+ if (tlv)
+ { // parse User Message
+ BYTE* tBuf = tlv->pData;
+
+ pszDescription = (char*)_alloca(tlv->wLen + 2);
+ unpackString(&tBuf, pszDescription, tlv->wLen);
+ pszDescription[tlv->wLen] = '\0';
+ pszDescription[tlv->wLen+1] = '\0';
+ { // apply User Message encoding
+ oscar_tlv *charset = getTLV(chain, 0x0D, 1);
+ char *str = pszDescription;
+ char *bTag,*eTag;
+
+ if (charset)
+ { // decode charset
+ char *szEnc = (char*)_alloca(charset->wLen + 1);
+
+ strncpy(szEnc, charset->pData, charset->wLen);
+ szEnc[charset->wLen] = '\0';
+ str = ApplyEncoding(pszDescription, szEnc);
+ }
+ else
+ str = null_strdup(str);
+ // eliminate HTML tags
+ pszDescription = EliminateHtml(str, strlennull(str));
+
+ bTag = strstr(pszDescription, "<DESC>");
+ if (bTag)
+ { // take special Description - ICQJ's extension
+ eTag = strstr(bTag, "</DESC>");
+ if (eTag)
+ {
+ *eTag = '\0';
+ str = null_strdup(bTag + 6);
+ SAFE_FREE(&pszDescription);
+ pszDescription = str;
+ }
+ }
+ else
+ {
+ bTag = strstr(pszDescription, "<FS>");
+ if (bTag)
+ { // take only <FS> - Description tag if present
+ eTag = strstr(bTag, "</FS>");
+ if (eTag)
+ {
+ *eTag = '\0';
+ str = null_strdup(bTag + 4);
+ SAFE_FREE(&pszDescription);
+ pszDescription = str;
+ }
+ }
+ }
+ }
+ }
+ if (!strlennull(pszDescription)) pszDescription = ICQTranslateUtf("No description given");
+ }
+ { // parse File Transfer Info block
+ oscar_tlv* tlv = getTLV(chain, 0x2711, 1);
+ BYTE* tBuf = tlv->pData;
+ WORD tLen = tlv->wLen;
+ WORD wFlag;
+
+ unpackWord(&tBuf, &wFlag); // FT flag
+ unpackWord(&tBuf, &ft->wFilesCount);
+ unpackDWord(&tBuf, (DWORD*)&ft->qwTotalSize);
+ tLen -= 8;
+ // Filename / Directory Name
+ wFilenameLength = tLen - 1;
+ pszFileName = (char*)_alloca(tLen);
+ unpackString(&tBuf, pszFileName, wFilenameLength);
+ pszFileName[wFilenameLength] = '\0';
+ { // apply Filename / Directory Name encoding
+ oscar_tlv* charset = getTLV(chain, 0x2712, 1);
+
+ if (charset)
+ {
+ char* szEnc = (char*)_alloca(charset->wLen + 1);
+
+ strncpy(szEnc, charset->pData, charset->wLen);
+ szEnc[charset->wLen] = '\0';
+ pszFileName = ApplyEncoding(pszFileName, szEnc);
+ }
+ else
+ pszFileName = ansi_to_utf8(pszFileName);
+ }
+ if (ft->wFilesCount == 1)
+ { // Filename - use for DB event (convert to Ansi - File DB events does not support Unicode)
+ char* szAnsi = (char*)_alloca(strlennull(pszFileName) + 2);
+ utf8_decode_static(pszFileName, szAnsi, strlennull(pszFileName) + 1);
+ SAFE_FREE(&pszFileName);
+ pszFileName = szAnsi;
+ }
+ else
+ { // Save Directory name for future use
+ ft->szThisPath = pszFileName;
+ // for multi-file transfer we do not display "folder" name, but create only a simple notice
+ pszFileName = (char*)_alloca(64);
+
+ null_snprintf(pszFileName, 64, ICQTranslate("%d Files"), ft->wFilesCount);
+ }
+ }
+ { // Total Size TLV (ICQ 6 and AIM 6)
+ oscar_tlv *tlv = getTLV(chain, 0x2713, 1);
+
+ if (tlv && tlv->wLen >= 8)
+ {
+ BYTE *tBuf = tlv->pData;
+
+ unpackQWord(&tBuf, &ft->qwTotalSize);
+ }
+ }
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ char* szBlob;
+ int bAdded;
+ HANDLE hContact = HContactFromUID(dwUin, szUID, &bAdded);
+ char* szAnsi;
+
+ ft->hContact = hContact;
+ ft->szDescription = pszDescription;
+ ft->fileId = -1;
+
+ szAnsi = (char*)_alloca(strlennull(pszDescription)+2);
+ utf8_decode_static(pszDescription, szAnsi, strlennull(pszDescription)+1);
+
+ // Send chain event
+ szBlob = (char*)_alloca(sizeof(DWORD) + strlennull(pszFileName) + strlennull(szAnsi) + 2);
+ *(PDWORD)szBlob = (DWORD)ft;
+ strcpy(szBlob + sizeof(DWORD), pszFileName);
+ strcpy(szBlob + sizeof(DWORD) + strlennull(pszFileName) + 1, szAnsi); // DB event is ansi only!
+ 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);
+ }
+ }
+ else if (wAckType == 2)
+ { // First attempt failed, reverse requested
+ oscar_filetransfer *ft = FindOscarTransfer(hContact, dwID1, dwID2);
+
+ if (ft)
+ {
+ NetLog_Direct("OFT: Redirect received (%d)", wAckType);
+
+ ft->wReqNum = wAckType;
+
+ if (ft->sending)
+ {
+ ReleaseOscarListener((oscar_listener**)&ft->listener);
+
+ ft->bUseProxy = getTLV(chain, 0x10, 1) ? 1 : 0;
+ ft->dwProxyIP = getDWordFromChain(chain, 0x02, 1);
+ ft->dwRemoteInternalIP = getDWordFromChain(chain, 0x03, 1);
+ ft->dwRemoteExternalIP = getDWordFromChain(chain, 0x04, 1);
+ ft->wRemotePort = getWordFromChain(chain, 0x05, 1);
+
+ OpenOscarConnection(hContact, ft, ft->bUseProxy ? OCT_PROXY_RECV: OCT_REVERSE);
+ }
+ else
+ { // Just sanity
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&ft);
+ }
+ }
+ else
+ NetLog_Server("Error: Invalid request, no such transfer");
+ }
+ else if (wAckType == 3)
+ { // Transfering thru proxy, join tunnel
+ oscar_filetransfer *ft = FindOscarTransfer(hContact, dwID1, dwID2);
+
+ if (ft)
+ { // release possible previous listener
+ NetLog_Direct("OFT: Redirect received (%d)", wAckType);
+
+ ft->wReqNum = wAckType;
+
+ ReleaseOscarListener((oscar_listener**)&ft->listener);
+
+ ft->bUseProxy = getTLV(chain, 0x10, 1) ? 1 : 0;
+ ft->dwProxyIP = getDWordFromChain(chain, 0x02, 1);
+ ft->wRemotePort = getWordFromChain(chain, 0x05, 1);
+
+ if (ft->bUseProxy && ft->dwProxyIP)
+ { // Init proxy connection
+ OpenOscarConnection(hContact, ft, OCT_PROXY_RECV);
+ }
+ else
+ { // try Stage 4
+ OpenOscarConnection(hContact, ft, OCT_PROXY);
+ }
+ }
+ else
+ NetLog_Server("Error: Invalid request, no such transfer");
+ }
+ else if (wAckType == 4)
+ {
+ oscar_filetransfer *ft = FindOscarTransfer(hContact, dwID1, dwID2);
+
+ if (ft)
+ {
+ NetLog_Direct("OFT: Redirect received (%d)", wAckType);
+
+ ft->wReqNum = wAckType;
+ ft->bUseProxy = getTLV(chain, 0x10, 1) ? 1 : 0;
+ ft->dwProxyIP = getDWordFromChain(chain, 0x02, 1);
+ ft->wRemotePort = getWordFromChain(chain, 0x05, 1);
+
+ if (ft->bUseProxy && ft->dwProxyIP)
+ { // Init proxy connection
+ OpenOscarConnection(hContact, ft, OCT_PROXY_RECV);
+ }
+ else
+ NetLog_Server("Error: Invalid request, IP missing.");
+ }
+ else
+ NetLog_Server("Error: Invalid request, no such transfer");
+ }
+ else
+ NetLog_Server("Error: Uknown Stage %d request", wAckType);
+
+ disposeChain(&chain);
+ }
+ else
+ NetLog_Server("Error: Missing TLV chain in OFT request");
+ }
+ else if (wCommand == 1)
+ { // transfer cancelled/aborted
+ oscar_filetransfer *ft = FindOscarTransfer(hContact, dwID1, dwID2);
+
+ if (ft)
+ {
+ NetLog_Server("OFT: File transfer cancelled by %s", strUID(dwUin, szUID));
+
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ft, 0);
+ // Notify user, that the FT was cancelled // TODO: new ACKRESULT_?
+ icq_LogMessage(LOG_ERROR, "The file transfer was aborted by the other user.");
+ // Release transfer
+ SafeReleaseFileTransfer(&ft);
+ }
+ else
+ NetLog_Server("Error: Invalid request, no such transfer");
+ }
+ else if (wCommand == 2)
+ { // transfer accepted - connection established
+ oscar_filetransfer *ft = FindOscarTransfer(hContact, dwID1, dwID2);
+
+ if (ft)
+ {
+ NetLog_Direct("OFT: Session established.");
+ // Init connection
+ if (ft->sending)
+ {
+ if (ft->connection && ((oscar_connection*)(ft->connection))->status == OCS_CONNECTED)
+ oft_sendPeerInit((oscar_connection*)ft->connection);
+ else
+ ft->initialized = 1; // accept was received
+ }
+ else
+ NetLog_Server("Warning: Received invalid rendezvous accept");
+ }
+ else
+ NetLog_Server("Error: Invalid request, no such transfer");
+ }
+ else
+ {
+ NetLog_Server("Error: Unknown wCommand=0x%x in OFT request", wCommand);
+ }
+}
+
+
+
+void handleRecvServResponseOFT(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, void* ft)
+{
+ WORD wDataLen;
+
+ if (wLen < 2) return;
+
+ unpackWord(&buf, &wDataLen);
+
+ if (wDataLen == 2)
+ {
+ oscar_filetransfer *oft = (oscar_filetransfer*)ft;
+ WORD wStatus;
+
+ unpackWord(&buf, &wStatus);
+
+ switch (wStatus)
+ {
+ case 1:
+ { // FT denied (icq5)
+ NetLog_Server("OFT: File transfer denied by %s", strUID(dwUin, szUID));
+
+ ICQBroadcastAck(oft->hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)oft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&oft);
+ }
+ break;
+
+ case 4: // Proxy error
+ {
+ icq_LogMessage(LOG_ERROR, "The file transfer failed: Proxy error");
+
+ ICQBroadcastAck(oft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)oft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&oft);
+ }
+ break;
+
+ case 5: // Invalid request
+ {
+ icq_LogMessage(LOG_ERROR, "The file transfer failed: Invalid request");
+
+ ICQBroadcastAck(oft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)oft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&oft);
+ }
+ break;
+
+ case 6: // Proxy Failed (IP = 0)
+ {
+ icq_LogMessage(LOG_ERROR, "The file transfer failed: Proxy unavailable");
+
+ ICQBroadcastAck(oft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)oft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&oft);
+ }
+ break;
+
+ default:
+ {
+ NetLog_Server("OFT: Uknown request response code 0x%x", wStatus);
+
+ ICQBroadcastAck(oft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)oft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&oft);
+ }
+ }
+ }
+}
+
+
+
+static char* oftGetFileContainer(oscar_filetransfer* oft, const char** files, int iFile)
+{
+ char szPath[MAX_PATH];
+ char* szFileName = FindFilePathContainer(files, iFile, szPath);
+ char* szPathUtf = ansi_to_utf8(szPath);
+ int i;
+
+ // try to find existing container
+ for (i = 0; i < oft->containerCount; i++)
+ if (!strcmp(szPathUtf, oft->file_containers[i]))
+ {
+ SAFE_FREE(&szPathUtf);
+
+ return oft->file_containers[i];
+ }
+
+ // create new container
+ i = oft->containerCount++;
+ oft->file_containers = (char**)SAFE_REALLOC(oft->file_containers, (sizeof(char*) * oft->containerCount));
+ oft->file_containers[i] = szPathUtf;
+
+ return oft->file_containers[i];
+}
+
+
+
+int oftInitTransfer(HANDLE hContact, DWORD dwUin, char* szUid, char** files, char* pszDesc)
+{
+ oscar_filetransfer *ft;
+ int i, filesCount;
+ struct _stati64 statbuf;
+
+ // Initialize filetransfer struct
+ NetLog_Server("Init file send");
+
+ ft = CreateOscarTransfer();
+ ft->hContact = hContact;
+ ft->pMessage.bMessageType = MTYPE_FILEREQ;
+ InitMessageCookie(&ft->pMessage);
+
+ for (filesCount = 0; files[filesCount]; filesCount++);
+ ft->files = (oft_file_record *)SAFE_MALLOC(sizeof(oft_file_record) * filesCount);
+ ft->files_ansi = (char **)SAFE_MALLOC(sizeof(char *) * filesCount);
+ ft->qwTotalSize = 0;
+ // Prepare files arrays
+ for (i = 0; i < filesCount; i++)
+ {
+ if (_stati64(files[i], &statbuf))
+ NetLog_Server("IcqSendFile() was passed invalid filename \"%s\"", files[i]);
+ else
+ {
+ if (!(statbuf.st_mode&_S_IFDIR))
+ { // take only files
+ ft->files[ft->wFilesCount].szFile = FileNameToUtf(files[i]);
+ ft->files[ft->wFilesCount].szContainer = oftGetFileContainer(ft, files, i);
+ ft->files_ansi[ft->wFilesCount] = null_strdup(files[i]);
+
+ ft->wFilesCount++;
+ ft->qwTotalSize += statbuf.st_size;
+ }
+ }
+ }
+ if (!ft->wFilesCount)
+ { // found no valid files to send
+ icq_LogMessage(LOG_ERROR, LPGEN("Failed to Initialize File Transfer. No valid files were specified."));
+ // Notify UI
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&ft);
+
+ return 0; // Failure
+ }
+ if (ft->qwTotalSize >= 0x100000000 && ft->wFilesCount > 1)
+ { // file larger than 4GB can be send only as single
+ icq_LogMessage(LOG_ERROR, "The files are too big to be sent at once. Files bigger than 4GB can be sent only separately.");
+ // Notify UI
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&ft);
+
+ return 0; // Failure
+ }
+
+ NetLog_Server("OFT: Found %d files.", ft->wFilesCount);
+
+ ft->szDescription = ansi_to_utf8(pszDesc);
+ ft->sending = 1;
+ ft->fileId = -1;
+ ft->iCurrentFile = 0;
+ ft->dwCookie = AllocateCookie(CKT_FILE, ICQ_MSG_SRV_SEND, hContact, ft);
+
+ // Init oscar fields
+ {
+ ft->wEncrypt = 0;
+ ft->wCompress = 0;
+ ft->wPartsCount = 1;
+ ft->wPartsLeft = 1;
+ strcpy(ft->rawIDString, "Cool FileXfer");
+ ft->bHeaderFlags = 0x20;
+ ft->bNameOff = 0x1C;
+ ft->bSizeOff = 0x11;
+ ft->dwRecvForkCheck = 0xFFFF0000;
+ ft->dwThisForkCheck = 0xFFFF0000;
+ ft->dwRecvFileCheck = 0xFFFF0000;
+ }
+
+ // Send file transfer request
+ {
+ char* pszFiles;
+
+ if (ft->wFilesCount == 1)
+ { // transfering single file, give filename
+ pszFiles = ExtractFileName(ft->files[0].szFile);
+ }
+ else
+ { // check if transfering one directory
+ char *szFirstDiv, *szFirstDir = ft->file_containers[0];
+ int nFirstDirLen;
+
+ // default is no root dir
+ pszFiles = "";
+
+ if ((szFirstDiv = strstr(szFirstDir, "\\")) || (szFirstDiv = strstr(szFirstDir, "/")))
+ nFirstDirLen = szFirstDiv - szFirstDir;
+ else
+ nFirstDirLen = strlennull(szFirstDir);
+
+ if (nFirstDirLen)
+ { // got root dir from first container, check if others are only sub-dirs
+ for (i = 0; i < ft->containerCount; i++)
+ {
+ if (strnicmp(ft->file_containers[i], szFirstDir, nFirstDirLen))
+ {
+ szFirstDir = NULL;
+ break;
+ }
+ }
+ if (szFirstDir)
+ { // fine, we are sending only one directory
+ pszFiles = szFirstDir;
+ if (szFirstDiv) szFirstDiv[0] = '\0';
+ nFirstDirLen++; // include backslash
+ // cut all files container by root dir - it is transferred as root separately
+ for (i = 0; i < ft->wFilesCount; i++)
+ ft->files[i].szContainer += nFirstDirLen;
+ }
+ }
+ }
+
+ // Create listener
+ ft->listener = CreateOscarListener(ft, oft_newConnectionReceived);
+
+ // Send packet
+ if (ft->listener)
+ {
+ oft_sendFileRequest(dwUin, szUid, ft, pszFiles, ICQGetContactSettingDword(NULL, "RealIP", 0));
+ }
+ else
+ { // try stage 1 proxy
+ ft->szThisFile = null_strdup(pszFiles);
+ OpenOscarConnection(hContact, ft, OCT_PROXY_INIT);
+ }
+ }
+
+ return (int)(HANDLE)ft; // Success
+}
+
+
+
+DWORD oftFileAllow(HANDLE hContact, WPARAM wParam, LPARAM lParam)
+{
+ oscar_filetransfer* ft = (oscar_filetransfer*)wParam;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ return 0; // Invalid contact
+
+ ft->szSavePath = ansi_to_utf8((char *)lParam);
+ if (ft->szThisPath)
+ { // Append Directory name to the save path, when transfering a directory
+ ft->szSavePath = (char*)SAFE_REALLOC(ft->szSavePath, strlennull(ft->szSavePath) + strlennull(ft->szThisPath) + 4);
+ NormalizeBackslash(ft->szSavePath);
+ strcat(ft->szSavePath, ft->szThisPath);
+ NormalizeBackslash(ft->szSavePath);
+ }
+#ifdef _DEBUG
+ NetLog_Direct("OFT: Request accepted, saving to '%s'.", ft->szSavePath);
+#endif
+
+ // Create cookie
+ ft->dwCookie = AllocateCookie(CKT_FILE, ICQ_MSG_SRV_SEND, hContact, ft);
+
+ OpenOscarConnection(hContact, ft, ft->bUseProxy ? OCT_PROXY_RECV: OCT_NORMAL);
+
+ return wParam; // Success
+}
+
+
+
+DWORD oftFileDeny(HANDLE hContact, WPARAM wParam, LPARAM lParam)
+{
+ oscar_filetransfer* ft = (oscar_filetransfer*)wParam;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (IsValidOscarTransfer(ft))
+ {
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+#ifdef _DEBUG
+ NetLog_Direct("OFT: Request denied.");
+#endif
+
+ oft_sendFileDeny(dwUin, szUid, ft);
+
+ // Release structure
+ SafeReleaseFileTransfer(&ft);
+
+ return 0; // Success
+ }
+ return 1; // Invalid transfer
+}
+
+
+
+DWORD oftFileCancel(HANDLE hContact, WPARAM wParam, LPARAM lParam)
+{
+ oscar_filetransfer* ft = (oscar_filetransfer*)wParam;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (IsValidOscarTransfer(ft))
+ {
+ if (ft->hContact != hContact)
+ return 1; // Bad contact or hTransfer
+
+ if (ICQGetContactSettingUID(hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+#ifdef _DEBUG
+ NetLog_Direct("OFT: Transfer cancelled.");
+#endif
+
+ oft_sendFileCancel(dwUin, szUid, ft);
+
+ ICQBroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+
+ // Release structure
+ SafeReleaseFileTransfer(&ft);
+
+ return 0; // Success
+ }
+ return 1; // Invalid transfer
+}
+
+
+
+void oftFileResume(oscar_filetransfer *ft, int action, const char *szFilename)
+{
+ oscar_connection *oc;
+ int openFlags;
+
+ if (ft->connection == NULL)
+ return;
+
+ oc = (oscar_connection*)ft->connection;
+
+#ifdef _DEBUG
+ NetLog_Direct("OFT: Resume Transfer, Action: %d, FileName: '%s'", action, szFilename);
+#endif
+
+ switch (action)
+ {
+ case FILERESUME_RESUME:
+ openFlags = _O_BINARY | _O_RDWR;
+ break;
+
+ case FILERESUME_OVERWRITE:
+ openFlags = _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY;
+ ft->qwFileBytesDone = 0;
+ break;
+
+ case FILERESUME_SKIP:
+ openFlags = _O_BINARY | _O_WRONLY;
+ ft->qwFileBytesDone = ft->qwThisFileSize;
+ break;
+
+ case FILERESUME_RENAME:
+ openFlags = _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY;
+ SAFE_FREE(&ft->szThisFile);
+ ft->szThisFile = ansi_to_utf8(szFilename);
+ ft->qwFileBytesDone = 0;
+ break;
+
+ default: // workaround for bug in Miranda Core
+ if (ft->resumeAction == FILERESUME_RESUME)
+ openFlags = _O_BINARY | _O_RDWR;
+ else
+ { // default to overwrite
+ openFlags = _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY;
+ ft->qwFileBytesDone = 0;
+ }
+ }
+ ft->resumeAction = action;
+
+ ft->fileId = OpenFileUtf(ft->szThisFile, openFlags, _S_IREAD | _S_IWRITE);
+#ifdef _DEBUG
+ NetLog_Direct("OFT: OpenFileUtf(%s, %u) returned %u", ft->szThisFile, openFlags, ft->fileId);
+#endif
+ if (ft->fileId == -1)
+ {
+#ifdef _DEBUG
+ NetLog_Direct("OFT: errno=%d", errno);
+#endif
+ 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.");
+
+ ICQBroadcastAck(oc->ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc->ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&oc->ft);
+ return;
+ }
+
+ if (action == FILERESUME_RESUME)
+ ft->qwFileBytesDone = _lseeki64(ft->fileId, 0, SEEK_END);
+ else
+ _lseeki64(ft->fileId, ft->qwFileBytesDone, SEEK_SET);
+
+ ft->qwBytesDone += ft->qwFileBytesDone;
+
+ if (action == FILERESUME_RESUME)
+ { // use smart-resume
+ oc->status = OCS_RESUME;
+ ft->dwRecvFileCheck = oft_calc_file_checksum(ft->fileId, ft->qwFileBytesDone);
+ _lseek(ft->fileId, 0, SEEK_END);
+
+#ifdef _DEBUG
+ NetLog_Direct("OFT: Starting Smart-Resume");
+#endif
+
+ sendOFT2FramePacket(oc, OFT_TYPE_RESUMEREQUEST);
+
+ return;
+ }
+ else if (action == FILERESUME_SKIP)
+ { // we are skiping the file, send "we are done"
+ oc->status = OCS_NEGOTIATION;
+ }
+ else
+ { // Send "we are ready"
+ oc->status = OCS_DATA;
+
+ sendOFT2FramePacket(oc, OFT_TYPE_READY);
+ }
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
+
+ if (!ft->qwThisFileSize || action == FILERESUME_SKIP)
+ { // if the file is empty we will not receive any data
+ BYTE buf;
+ oft_handleFileData(oc, &buf, 0);
+ }
+}
+
+
+
+static void oft_buildProtoFileTransferStatus(oscar_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_ansi;
+ else
+ pfts->files = NULL; /* FIXME */
+ pfts->totalFiles = ft->wFilesCount;
+ pfts->currentFileNumber = ft->iCurrentFile;
+ pfts->totalBytes = (DWORD)ft->qwTotalSize; // FIXME
+ pfts->totalProgress = (DWORD)ft->qwBytesDone; // FIXME
+// utf8_decode(ft->szPath, &pfts->workingDir); // not used by the UI anyway
+ utf8_decode(ft->szThisFile, &pfts->currentFile);
+ pfts->currentFileSize = (DWORD)ft->qwThisFileSize; // FIXME
+ pfts->currentFileTime = ft->dwThisFileDate;
+ pfts->currentFileProgress = (DWORD)ft->qwFileBytesDone; // FIXME
+}
+
+
+
+void CloseOscarConnection(oscar_connection *oc)
+{
+ EnterCriticalSection(&oftMutex);
+
+ if (oc)
+ {
+ oc->type = OCT_CLOSING;
+
+ if (oc->hConnection)
+ { // we need this for Netlib handle consistency
+ NetLib_CloseConnection(&oc->hConnection, FALSE);
+ }
+ }
+ LeaveCriticalSection(&oftMutex);
+}
+
+
+
+void OpenOscarConnection(HANDLE hContact, oscar_filetransfer *ft, int type)
+{
+ oscarthreadstartinfo *otsi = (oscarthreadstartinfo*)SAFE_MALLOC(sizeof(oscarthreadstartinfo));
+
+ otsi->hContact = hContact;
+ otsi->type = type;
+ otsi->ft = ft;
+
+ ICQCreateThread(oft_connectionThread, otsi);
+}
+
+
+
+static int CreateOscarProxyConnection(oscar_connection *oc)
+{
+ NETLIBOPENCONNECTION nloc = {0};
+
+ // inform UI
+ ICQBroadcastAck(oc->ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTPROXY, oc->ft, 0);
+
+ nloc.szHost = OSCAR_PROXY_HOST;
+ nloc.wPort = ICQGetContactSettingWord(NULL, "OscarPort", DEFAULT_SERVER_PORT);
+ if (nloc.wPort == 0)
+ nloc.wPort = RandRange(1024, 65535);
+
+ oc->hConnection = NetLib_OpenConnection(ghServerNetlibUser, "Proxy ", &nloc);
+ if (!oc->hConnection)
+ { // proxy connection failed
+ return 0;
+ }
+ oc->type = OCT_PROXY;
+ oc->status = OCS_PROXY;
+ oc->ft->connection = oc;
+ // init proxy
+ proxy_sendInitTunnel(oc);
+
+ return 1; // Success
+}
+
+
+
+// This function is called from the Netlib when someone is connecting to our oscar_listener
+static void oft_newConnectionReceived(HANDLE hNewConnection, DWORD dwRemoteIP, void *pExtra)
+{
+ oscarthreadstartinfo *otsi = (oscarthreadstartinfo*)SAFE_MALLOC(sizeof(oscarthreadstartinfo));
+ oscar_listener* listener = (oscar_listener*)pExtra;
+
+ otsi->type = listener->ft->sending ? OCT_NORMAL : OCT_REVERSE;
+ otsi->incoming = 1;
+ otsi->hConnection = hNewConnection;
+ otsi->dwRemoteIP = dwRemoteIP;
+ otsi->listener = listener;
+
+ // Start a new thread for the incomming connection
+ ICQCreateThread(oft_connectionThread, otsi);
+}
+
+
+
+static DWORD __stdcall oft_connectionThread(oscarthreadstartinfo *otsi)
+{
+ oscar_connection oc = {0};
+ oscar_listener *source;
+ NETLIBPACKETRECVER packetRecv={0};
+ HANDLE hPacketRecver;
+
+ oc.hContact = otsi->hContact;
+ oc.hConnection = otsi->hConnection;
+ oc.type = otsi->type;
+ oc.incoming = otsi->incoming;
+ oc.ft = otsi->ft;
+ source = otsi->listener;
+ if (oc.incoming)
+ {
+ if (IsValidOscarTransfer(source->ft))
+ {
+ oc.ft = source->ft;
+ oc.ft->dwRemoteExternalIP = otsi->dwRemoteIP;
+ oc.hContact = oc.ft->hContact;
+ oc.ft->connection = &oc;
+ oc.status = OCS_CONNECTED;
+
+ ReleaseOscarListener((oscar_listener**)&oc.ft->listener);
+ }
+ else
+ { // FT is already over, kill listener
+ NetLog_Direct("Received unexpected connection, closing.");
+
+ CloseOscarConnection(&oc);
+ ReleaseOscarListener(&source);
+
+ SAFE_FREE(&otsi);
+
+ return 0;
+ }
+ }
+ SAFE_FREE(&otsi);
+
+ if (oc.hContact)
+ { // Load contact information
+ ICQGetContactSettingUID(oc.hContact, &oc.dwUin, &oc.szUid);
+ }
+
+ // Load local IP information
+ oc.dwLocalExternalIP = ICQGetContactSettingDword(NULL, "IP", 0);
+ oc.dwLocalInternalIP = ICQGetContactSettingDword(NULL, "RealIP", 0);
+
+ if (!oc.incoming)
+ { // create outgoing connection
+ if (oc.type == OCT_NORMAL || oc.type == OCT_REVERSE)
+ { // create outgoing connection to peer
+ NETLIBOPENCONNECTION nloc = {0};
+ IN_ADDR addr = {0}, addr2 = {0};
+
+ if (oc.ft->dwRemoteExternalIP == oc.dwLocalExternalIP && oc.ft->dwRemoteInternalIP)
+ addr.S_un.S_addr = htonl(oc.ft->dwRemoteInternalIP);
+ else
+ {
+ addr.S_un.S_addr = htonl(oc.ft->dwRemoteExternalIP);
+ // for different internal, try it also (for LANs with multiple external IP, VPNs, etc.)
+ if (oc.ft->dwRemoteInternalIP != oc.ft->dwRemoteExternalIP)
+ addr2.S_un.S_addr = htonl(oc.ft->dwRemoteInternalIP);
+ }
+
+ // Inform UI that we will attempt to connect
+ ICQBroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, oc.ft, 0);
+
+ if (!addr.S_un.S_addr && oc.type == OCT_NORMAL)
+ { // IP to connect to is empty, request reverse
+ oscar_listener* listener = CreateOscarListener(oc.ft, oft_newConnectionReceived);
+
+ if (listener)
+ { // we got listening port, fine send request
+ oc.ft->listener = listener;
+ // notify UI
+ ICQBroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_LISTENING, oc.ft, 0);
+
+ oft_sendFileRedirect(oc.dwUin, oc.szUid, oc.ft, oc.dwLocalInternalIP, listener->wPort, FALSE);
+
+ return 0;
+ }
+ if (!CreateOscarProxyConnection(&oc))
+ { // normal connection failed, notify peer, wait for error or stage 3 proxy
+ oft_sendFileRedirect(oc.dwUin, oc.szUid, oc.ft, 0, 0, FALSE);
+ // stage 3 can follow
+ return 0;
+ }
+ }
+ else if (addr.S_un.S_addr && oc.ft->wRemotePort)
+ {
+ nloc.szHost = inet_ntoa(addr);
+ nloc.wPort = oc.ft->wRemotePort;
+ nloc.timeout = 8; // 8 secs to connect
+ oc.hConnection = NetLib_OpenConnection(ghDirectNetlibUser, oc.type==OCT_REVERSE?"Reverse ":NULL, &nloc);
+ if (!oc.hConnection && addr2.S_un.S_addr)
+ { // first address failed, try second one if available
+ nloc.szHost = inet_ntoa(addr2);
+ oc.hConnection = NetLib_OpenConnection(ghDirectNetlibUser, oc.type==OCT_REVERSE?"Reverse ":NULL, &nloc);
+ }
+ if (!oc.hConnection)
+ {
+ if (oc.type == OCT_NORMAL)
+ { // connection failed, try reverse
+ oscar_listener* listener = CreateOscarListener(oc.ft, oft_newConnectionReceived);
+
+ if (listener)
+ { // we got listening port, fine send request
+ oc.ft->listener = listener;
+ // notify UI that we await connection
+ ICQBroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_LISTENING, oc.ft, 0);
+
+ oft_sendFileRedirect(oc.dwUin, oc.szUid, oc.ft, oc.dwLocalInternalIP, listener->wPort, FALSE);
+
+ return 0;
+ }
+ }
+ if (!CreateOscarProxyConnection(&oc))
+ { // proxy connection failed, notify peer, wait for error or stage 4 proxy
+ oft_sendFileRedirect(oc.dwUin, oc.szUid, oc.ft, 0, 0, FALSE);
+ // stage 3 or stage 4 can follow
+ return 0;
+ }
+ }
+ else
+ {
+ oc.status = OCS_CONNECTED;
+ // ack normal connection
+ oc.ft->connection = &oc;
+ // acknowledge OFT - connection is ready
+ oft_sendFileAccept(oc.dwUin, oc.szUid, oc.ft);
+ // signal UI
+ ICQBroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, oc.ft, 0);
+ }
+ }
+ else
+ { // try proxy, stage 3 (sending)
+ if (!CreateOscarProxyConnection(&oc))
+ { // proxy connection failed, notify peer, wait for error or stage 4 proxy
+ oft_sendFileRedirect(oc.dwUin, oc.szUid, oc.ft, 0, 0, FALSE);
+ // stage 4 can follow
+ return 0;
+ }
+ }
+ }
+ else if (oc.type == OCT_PROXY_RECV)
+ { // stage 2 & stage 4
+ if (oc.ft->dwProxyIP && oc.ft->wRemotePort)
+ { // create proxy connection, join tunnel
+ NETLIBOPENCONNECTION nloc = {0};
+ IN_ADDR addr = {0};
+
+ // inform UI that we will connect to file proxy
+ ICQBroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTPROXY, oc.ft, 0);
+
+ addr.S_un.S_addr = htonl(oc.ft->dwProxyIP);
+ nloc.szHost = inet_ntoa(addr);
+ nloc.wPort = ICQGetContactSettingWord(NULL, "OscarPort", DEFAULT_SERVER_PORT);
+ if (nloc.wPort == 0)
+ nloc.wPort = RandRange(1024, 65535);
+ oc.hConnection = NetLib_OpenConnection(ghServerNetlibUser, "Proxy ", &nloc);
+ if (!oc.hConnection)
+ { // proxy connection failed, we are out of possibilities
+ ICQBroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc.ft, 0);
+ // notify the other side, that we failed
+ oft_sendFileResponse(oc.dwUin, oc.szUid, oc.ft, 0x04);
+ // Release structure
+ SafeReleaseFileTransfer(&oc.ft);
+
+ return 0;
+ }
+ oc.status = OCS_PROXY;
+ oc.ft->connection = &oc;
+ // Join proxy tunnel
+ proxy_sendJoinTunnel(&oc, oc.ft->wRemotePort);
+ }
+ else // stage 2 failed (empty IP)
+ { // try stage 3, or send response error 0x06
+ if (!CreateOscarProxyConnection(&oc))
+ {
+ oft_sendFileResponse(oc.dwUin, oc.szUid, oc.ft, 0x06);
+ // notify UI
+ ICQBroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc.ft, 0);
+ // Release structure
+ SafeReleaseFileTransfer(&oc.ft);
+
+ return 0;
+ }
+ }
+ }
+ else if (oc.type == OCT_PROXY)
+ { // stage 4
+ if (!CreateOscarProxyConnection(&oc))
+ { // proxy connection failed, we are out of possibilities
+ ICQBroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc.ft, 0);
+ // notify the other side, that we failed
+ oft_sendFileResponse(oc.dwUin, oc.szUid, oc.ft, 0x06);
+ // Release structure
+ SafeReleaseFileTransfer(&oc.ft);
+
+ return 0;
+ }
+ }
+ else if (oc.type == OCT_PROXY_INIT)
+ { // stage 1
+ if (!CreateOscarProxyConnection(&oc))
+ { // We failed to init transfer, notify UI
+ icq_LogMessage(LOG_ERROR, "Failed to Initialize File Transfer. Unable to bind local port and File proxy unavailable.");
+ // Release transfer
+ SafeReleaseFileTransfer(&oc.ft);
+
+ return 0;
+ }
+ else
+ oc.type = OCT_PROXY_INIT;
+ }
+ }
+ if (!oc.hConnection)
+ { // one more sanity check
+ NetLog_Direct("Error: No OFT connection.");
+ return 0;
+ }
+ if (oc.status != OCS_PROXY)
+ { // Connected, notify FT UI
+ ICQBroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, oc.ft, 0);
+
+ // send init OFT frame - just for different order of packets (just like Trillian)
+ if (oc.status == OCS_CONNECTED && oc.ft->sending && (oc.ft->initialized || oc.type == OCT_REVERSE))
+ oft_sendPeerInit((oscar_connection*)oc.ft->connection);
+ }
+ hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)oc.hConnection, 8192);
+ packetRecv.cbSize = sizeof(packetRecv);
+
+ // Packet receiving loop
+
+ while (oc.hConnection)
+ {
+ int recvResult;
+
+ packetRecv.dwTimeout = oc.wantIdleTime ? 0 : 120000;
+
+ recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPacketRecver, (LPARAM)&packetRecv);
+ if (!recvResult)
+ {
+ NetLog_Direct("Clean closure of oscar socket (%p)", oc.hConnection);
+ break;
+ }
+
+ if (recvResult == SOCKET_ERROR)
+ {
+ if (GetLastError() == ERROR_TIMEOUT)
+ { // TODO: this will not work on some systems
+ if (oc.wantIdleTime)
+ { // here we want to send file data packets
+ oft_sendFileData(&oc);
+ }
+ else if (oc.status != OCS_WAITING)
+ {
+ NetLog_Direct("Connection timeouted, closing.");
+ break;
+ }
+ }
+ else if (oc.type != OCT_CLOSING || GetLastError() != 87)
+ { // log only significant errors, not "connection killed by us"
+ NetLog_Direct("Abortive closure of oscar socket (%p) (%d)", oc.hConnection, GetLastError());
+ break;
+ }
+ }
+
+ if (oc.type == OCT_CLOSING)
+ packetRecv.bytesUsed = packetRecv.bytesAvailable;
+ else
+ packetRecv.bytesUsed = oft_handlePackets(&oc, packetRecv.buffer, packetRecv.bytesAvailable);
+ }
+
+ // End of packet receiving loop
+
+ NetLib_SafeCloseHandle(&hPacketRecver);
+
+ CloseOscarConnection(&oc);
+
+ // Clean up
+ EnterCriticalSection(&oftMutex);
+ if (getFileTransferIndex(oc.ft) != -1)
+ {
+ oc.ft->connection = NULL; // release link
+ }
+ LeaveCriticalSection(&oftMutex);
+ // Give server some time for abort/cancel to arrive
+ SleepEx(1000, TRUE);
+ // Error handling
+ if (IsValidOscarTransfer(oc.ft))
+ {
+ if (oc.status == OCS_DATA)
+ {
+ ICQBroadcastAck(oc.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc.ft, 0);
+
+ icq_LogMessage(LOG_ERROR, "Connection lost during file transfer.");
+ // Release structure
+ SafeReleaseFileTransfer(&oc.ft);
+ }
+ else if (oc.status == OCS_NEGOTIATION)
+ {
+ ICQBroadcastAck(oc.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc.ft, 0);
+
+ icq_LogMessage(LOG_ERROR, "File transfer negotiation failed for unknown reason.");
+ // Release structure
+ SafeReleaseFileTransfer(&oc.ft);
+ }
+ }
+
+ return 0;
+}
+
+
+
+static void sendOscarPacket(oscar_connection *oc, icq_packet *packet)
+{
+ if (oc->hConnection)
+ {
+ int nResult;
+
+ nResult = Netlib_Send(oc->hConnection, (const char*)packet->pData, packet->wLen, 0);
+
+ if (nResult == SOCKET_ERROR)
+ {
+ NetLog_Direct("Oscar %p socket error: %d, closing", oc->hConnection, GetLastError());
+ CloseOscarConnection(oc);
+ }
+ }
+
+ SAFE_FREE(&packet->pData);
+}
+
+
+
+static int oft_handlePackets(oscar_connection *oc, unsigned char *buf, int len)
+{
+ BYTE *pBuf;
+ DWORD dwHead;
+ WORD datalen;
+ WORD datatype;
+ int bytesUsed = 0;
+
+ while (len > 0)
+ {
+ if (oc->status == OCS_DATA && !oc->ft->sending)
+ {
+ return oft_handleFileData(oc, buf, len);
+ }
+ else if (oc->status == OCS_PROXY)
+ {
+ return oft_handleProxyData(oc, buf, len);
+ }
+ if (len < 6)
+ break;
+
+ pBuf = buf;
+ unpackDWord(&pBuf, &dwHead);
+ if (dwHead != 0x4F465432)
+ { // bad packet
+ NetLog_Direct("OFT: Received invalid packet (dwHead = 0x%x).", dwHead);
+
+ CloseOscarConnection(oc);
+ break;
+ }
+
+ unpackWord(&pBuf, &datalen);
+
+ if (len < datalen) // wait for whole packet
+ break;
+
+ unpackWord(&pBuf, &datatype);
+#ifdef _DEBUG
+ NetLog_Direct("OFT2: Type %u, Length %u bytes", datatype, datalen);
+#endif
+ handleOFT2FramePacket(oc, datatype, pBuf, (WORD)(datalen - 8));
+
+ /* Increase pointers so we can check for more data */
+ buf += datalen;
+ len -= datalen;
+ bytesUsed += datalen;
+ }
+
+ return bytesUsed;
+}
+
+
+
+static int oft_handleProxyData(oscar_connection *oc, unsigned char *buf, int len)
+{
+ oscar_filetransfer *ft = oc->ft;
+ BYTE *pBuf;
+ WORD datalen;
+ WORD wCommand;
+ int bytesUsed = 0;
+
+
+ while (len > 2)
+ {
+ pBuf = buf;
+
+ unpackWord(&pBuf, &datalen);
+ datalen += 2;
+
+ if (len < datalen)
+ break; // packet is not complete
+
+ if (datalen < 12)
+ { // malformed packet
+ CloseOscarConnection(oc);
+ break;
+ }
+ pBuf += 2; // packet version
+ unpackWord(&pBuf, &wCommand);
+ pBuf += 6;
+ // handle packet
+ switch (wCommand)
+ {
+ case 0x01: // Error
+ {
+ WORD wError;
+ char* szError;
+
+ unpackWord(&pBuf, &wError);
+ switch(wError)
+ {
+ case 0x0D:
+ szError = "Bad request";
+ break;
+ case 0x0E:
+ szError = "Malformed packet";
+ break;
+ case 0x10:
+ szError = "Initial request timeout";
+ break;
+ case 0x1A:
+ szError = "Accept period timeout";
+ break;
+ case 0x1C:
+ szError = "Invalid data";
+ break;
+
+ default:
+ szError = "Unknown";
+ }
+ // Notify peer
+ oft_sendFileResponse(oc->dwUin, oc->szUid, oc->ft, 0x06);
+
+ NetLog_Server("Proxy Error: %s (0x%x)", szError, wError);
+ // Notify UI
+ ICQBroadcastAck(oc->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc->ft, 0);
+ // Release structure
+ SafeReleaseFileTransfer(&oc->ft);
+ }
+ break;
+
+ case 0x03: // Tunnel created
+ {
+ WORD wCode;
+ DWORD dwIP;
+
+ unpackWord(&pBuf, &wCode);
+ unpackDWord(&pBuf, &dwIP);
+
+ if (oc->type == OCT_PROXY_INIT)
+ { // Proxy ready, send Stage 1 Request
+ ft->bUseProxy = 1;
+ ft->wRemotePort = wCode;
+ ft->dwProxyIP = dwIP;
+ oft_sendFileRequest(oc->dwUin, oc->szUid, ft, ft->szThisFile, 0);
+ SAFE_FREE(&ft->szThisFile);
+ // Notify UI
+ ICQBroadcastAck(oc->hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, oc->ft, 0);
+ }
+ else
+ {
+ NetLog_Server("Proxy Tunnel ready, notify peer.");
+ oft_sendFileRedirect(oc->dwUin, oc->szUid, ft, dwIP, wCode, TRUE);
+ }
+ }
+ break;
+
+ case 0x05: // Connection ready
+ oc->status = OCS_CONNECTED; // connection ready to send packets
+ // Notify UI
+ ICQBroadcastAck(oc->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, oc->ft, 0);
+ // signal we are ready
+ if (oc->type == OCT_PROXY_RECV)
+ {
+ oft_sendFileAccept(oc->dwUin, oc->szUid, ft);
+ if (ft->sending) // accept processed (sending only)
+ ft->initialized = 1;
+ }
+
+ NetLog_Server("Proxy Tunnel established");
+
+ if (ft->initialized && ft->sending)
+ oft_sendPeerInit((oscar_connection*)ft->connection);
+ break;
+
+ default:
+ NetLog_Server("Unknown proxy command 0x%x", wCommand);
+ }
+
+ buf += datalen;
+ len -= datalen;
+ bytesUsed += datalen;
+ }
+
+ return bytesUsed;
+}
+
+
+
+static int oft_handleFileData(oscar_connection *oc, unsigned char *buf, int len)
+{
+ oscar_filetransfer *ft = oc->ft;
+ DWORD dwLen = len;
+ int bytesUsed = 0;
+
+ // do not accept more data than expected
+ if (ft->qwThisFileSize - ft->qwFileBytesDone < dwLen)
+ dwLen = (int)(ft->qwThisFileSize - ft->qwFileBytesDone);
+
+ if (ft->fileId == -1)
+ { // something went terribly bad
+#ifdef _DEBUG
+ NetLog_Direct("Error: handleFileData(%u bytes) without fileId!", len);
+#endif
+ CloseOscarConnection(oc);
+ return 0;
+ }
+ _write(ft->fileId, buf, dwLen);
+ // update checksum
+ ft->dwRecvFileCheck = oft_calc_checksum((int)ft->qwFileBytesDone, buf, dwLen, ft->dwRecvFileCheck);
+ bytesUsed += dwLen;
+ ft->qwBytesDone += dwLen;
+ ft->qwFileBytesDone += dwLen;
+
+ if (GetTickCount() > ft->dwLastNotify + 700 || ft->qwFileBytesDone == ft->qwThisFileSize)
+ { // notify FT UI of our progress, at most every 700ms - do not be faster than Miranda
+ PROTOFILETRANSFERSTATUS pfts;
+
+ oft_buildProtoFileTransferStatus(ft, &pfts);
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&pfts);
+ SAFE_FREE(&pfts.currentFile);
+ SAFE_FREE(&pfts.workingDir);
+ oc->ft->dwLastNotify = GetTickCount();
+ }
+ if (ft->qwFileBytesDone == ft->qwThisFileSize)
+ {
+ /* EOF */
+#ifdef _DEBUG
+ NetLog_Direct("OFT: _close(%u)", ft->fileId);
+#endif
+ _close(ft->fileId);
+ ft->fileId = -1;
+
+ if (ft->resumeAction != FILERESUME_SKIP && ft->dwRecvFileCheck != ft->dwThisFileCheck)
+ {
+ NetLog_Direct("Error: File checksums does not match!");
+ { // Notify UI
+ char *pszMsg = ICQTranslateUtf("The checksum of file \"%s\" does not match, the file is probably damaged.");
+ char szBuf[MAX_PATH];
+
+ null_snprintf(szBuf, MAX_PATH, pszMsg, ExtractFileName(ft->szThisFile));
+ icq_LogMessage(LOG_ERROR, szBuf);
+
+ SAFE_FREE(&pszMsg);
+ }
+ } // keep transfer going (icq6 ignores checksums completely)
+ else if (ft->resumeAction == FILERESUME_SKIP)
+ NetLog_Direct("OFT: File receive skipped.");
+ else
+ NetLog_Direct("OFT: File received successfully.");
+
+ if ((DWORD)(ft->iCurrentFile + 1) == ft->wFilesCount)
+ {
+ ft->bHeaderFlags = 0x01; // the whole process is over
+ // ack received file
+ sendOFT2FramePacket(oc, OFT_TYPE_DONE);
+ oc->type = OCT_CLOSING;
+ NetLog_Direct("File Transfer completed successfully.");
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&ft);
+ }
+ else
+ { // ack received file
+ sendOFT2FramePacket(oc, OFT_TYPE_DONE);
+ oc->status = OCS_NEGOTIATION;
+ }
+
+ }
+ return bytesUsed;
+}
+
+
+
+static void handleOFT2FramePacket(oscar_connection *oc, WORD datatype, BYTE *pBuffer, WORD wLen)
+{
+ DWORD dwID1;
+ DWORD dwID2;
+
+ if (wLen < 232)
+ { // allow shorter packets, but at least with filename
+ NetLog_Direct("Error: Malformed OFT2 Frame, ignoring.");
+ return;
+ }
+
+ unpackLEDWord(&pBuffer, &dwID1);
+ wLen -= 4;
+ unpackLEDWord(&pBuffer, &dwID2);
+ wLen -= 4;
+
+ if (datatype == OFT_TYPE_REQUEST && !oc->ft->initialized)
+ { // first request does not contain MsgIDs we need to send them in ready packet
+ dwID1 = oc->ft->pMessage.dwMsgID1;
+ dwID2 = oc->ft->pMessage.dwMsgID2;
+ }
+
+ if (oc->ft->pMessage.dwMsgID1 != dwID1 || oc->ft->pMessage.dwMsgID2 != dwID2)
+ { // this is not the right packet - bad Message IDs
+ NetLog_Direct("Error: Invalid Packet Cookie, closing.");
+ CloseOscarConnection(oc);
+
+ return;
+ }
+
+ switch (datatype)
+ {
+ case OFT_TYPE_REQUEST:
+ { // Sender ready
+ oscar_filetransfer *ft = oc->ft;
+ char *szFullPath;
+
+ if (ft->sending)
+ { // just sanity check - this is only for receiving client
+ NetLog_Direct("Error: Invalid Packet, closing.");
+ CloseOscarConnection(oc);
+
+ return;
+ }
+
+ // Read Frame data
+ if (!ft->initialized)
+ {
+ unpackWord(&pBuffer, &ft->wEncrypt);
+ unpackWord(&pBuffer, &ft->wCompress);
+ unpackWord(&pBuffer, &ft->wFilesCount);
+ }
+ else
+ pBuffer += 6;
+ unpackWord(&pBuffer, &ft->wFilesLeft);
+ ft->iCurrentFile = ft->wFilesCount - oc->ft->wFilesLeft;
+ if (!ft->initialized)
+ unpackWord(&pBuffer, &ft->wPartsCount);
+ else
+ pBuffer += 2;
+ unpackWord(&pBuffer, &ft->wPartsLeft);
+ if (!ft->initialized)
+ { // just check it
+ DWORD dwSize;
+
+ unpackDWord(&pBuffer, &dwSize);
+ if (dwSize != (DWORD)ft->qwTotalSize)
+ { // the 32bits does not match, use them as full size
+ ft->qwTotalSize = dwSize;
+
+ NetLog_Server("Warning: Invalid total size.");
+ }
+ }
+ else
+ pBuffer += 4;
+ { // this allows us to receive single >4GB file correctly
+ DWORD dwSize;
+
+ unpackDWord(&pBuffer, &dwSize);
+ if (dwSize == (DWORD)ft->qwTotalSize && ft->wFilesCount == 1)
+ ft->qwThisFileSize = ft->qwTotalSize;
+ else
+ ft->qwThisFileSize = dwSize;
+ }
+ unpackDWord(&pBuffer, &ft->dwThisFileDate);
+ unpackDWord(&pBuffer, &ft->dwThisFileCheck);
+ unpackDWord(&pBuffer, &ft->dwRecvForkCheck);
+ unpackDWord(&pBuffer, &ft->dwThisForkSize);
+ unpackDWord(&pBuffer, &ft->dwThisFileCreation);
+ unpackDWord(&pBuffer, &ft->dwThisForkCheck);
+ pBuffer += 4; // File Bytes Done
+ unpackDWord(&pBuffer, &ft->dwRecvFileCheck);
+ if (!ft->initialized)
+ unpackString(&pBuffer, ft->rawIDString, 32);
+ else
+ pBuffer += 32;
+ unpackByte(&pBuffer, &ft->bHeaderFlags);
+ unpackByte(&pBuffer, &ft->bNameOff);
+ unpackByte(&pBuffer, &ft->bSizeOff);
+ if (!ft->initialized)
+ {
+ unpackString(&pBuffer, ft->rawDummy, 69);
+ unpackString(&pBuffer, ft->rawMacInfo, 16);
+ }
+ else
+ pBuffer += 85;
+ unpackWord(&pBuffer, &ft->wEncoding);
+ unpackWord(&pBuffer, &ft->wSubEncoding);
+ ft->cbRawFileName = wLen - 176;
+ SAFE_FREE(&ft->rawFileName); // release previous buffers
+ SAFE_FREE(&ft->szThisFile);
+ ft->rawFileName = (char*)SAFE_MALLOC(ft->cbRawFileName + 2);
+ unpackString(&pBuffer, ft->rawFileName, ft->cbRawFileName);
+ // Prepare file
+ if (ft->wEncoding == 2)
+ { // UCS-2 encoding
+ ft->szThisFile = ApplyEncoding(ft->rawFileName, "unicode-2-0");
+ }
+ else
+ {
+ ft->szThisFile = ansi_to_utf8(ft->rawFileName);
+ }
+
+ { // convert dir markings to normal backslashes
+ DWORD i;
+
+ for (i = 0; i < strlennull(ft->szThisFile); i++)
+ {
+ if (ft->szThisFile[i] == 0x01) ft->szThisFile[i] = '\\';
+ }
+ }
+
+ ft->initialized = 1; // First Frame Processed
+
+ NetLog_Direct("File '%s', %I64u Bytes", ft->szThisFile, ft->qwThisFileSize);
+
+ { // Prepare Path Information
+ char* szFile = strrchr(ft->szThisFile, '\\');
+
+ SAFE_FREE(&ft->szThisPath); // release previous path
+ if (szFile)
+ {
+ ft->szThisPath = ft->szThisFile;
+ szFile[0] = '\0'; // split that strings
+ ft->szThisFile = null_strdup(szFile + 1);
+ // no cheating with paths
+ if (!IsValidRelativePath(ft->szThisPath))
+ {
+ NetLog_Direct("Invalid path information");
+ break;
+ }
+ }
+ else
+ ft->szThisPath = null_strdup("");
+ }
+
+ /* no cheating with paths */
+ if (!IsValidRelativePath(ft->szThisFile))
+ {
+ NetLog_Direct("Invalid path information");
+ break;
+ }
+ szFullPath = (char*)SAFE_MALLOC(strlennull(ft->szSavePath)+strlennull(ft->szThisPath)+strlennull(ft->szThisFile)+3);
+ strcpy(szFullPath, ft->szSavePath);
+ NormalizeBackslash(szFullPath);
+ strcat(szFullPath, ft->szThisPath);
+ NormalizeBackslash(szFullPath);
+ // make sure the dest dir exists
+ if (MakeDirUtf(szFullPath))
+ NetLog_Direct("Failed to create destination directory!");
+
+ strcat(szFullPath, ft->szThisFile);
+ // we joined the full path to dest file
+ SAFE_FREE(&ft->szThisFile);
+ ft->szThisFile = szFullPath;
+
+ ft->qwFileBytesDone = 0;
+
+ {
+ /* file resume */
+ PROTOFILETRANSFERSTATUS pfts;
+
+ oft_buildProtoFileTransferStatus(ft, &pfts);
+ if (ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, ft, (LPARAM)&pfts))
+ {
+ oc->status = OCS_WAITING;
+
+ SAFE_FREE(&pfts.currentFile);
+ SAFE_FREE(&pfts.workingDir);
+ break; /* UI supports resume: it will call PS_FILERESUME */
+ }
+ SAFE_FREE(&pfts.currentFile);
+ SAFE_FREE(&pfts.workingDir);
+
+ ft->fileId = OpenFileUtf(ft->szThisFile, _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY, _S_IREAD | _S_IWRITE);
+#ifdef _DEBUG
+ NetLog_Direct("OFT: OpenFileUtf(%s, %u) returned %u", ft->szThisFile, _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY, ft->fileId);
+#endif
+ if (ft->fileId == -1)
+ {
+#ifdef _DEBUG
+ NetLog_Direct("OFT: errno=%d", errno);
+#endif
+ 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.");
+
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&oc->ft);
+ return;
+ }
+ }
+ // Send "we are ready"
+ oc->status = OCS_DATA;
+
+ sendOFT2FramePacket(oc, OFT_TYPE_READY);
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
+ if (!ft->qwThisFileSize)
+ { // if the file is empty we will not receive any data
+ BYTE buf;
+
+ oft_handleFileData(oc, &buf, 0);
+ }
+ return;
+ }
+
+ case OFT_TYPE_READY:
+ case OFT_TYPE_RESUMEACK:
+ { // Receiver is ready
+ oscar_filetransfer *ft = oc->ft;
+
+ oc->status = OCS_DATA;
+ oc->wantIdleTime = 1;
+
+ NetLog_Direct("OFT: Receiver ready.");
+ }
+ break;
+
+ case OFT_TYPE_RESUMEREQUEST:
+ { // Receiver wants to resume file transfer from point
+ oscar_filetransfer *ft = oc->ft;
+ DWORD dwResumeCheck, dwResumeOffset, dwFileCheck;
+
+ if (!ft->sending)
+ { // just sanity check - this is only for sending client
+ NetLog_Direct("Error: Invalid Packet, closing.");
+ CloseOscarConnection(oc);
+
+ return;
+ }
+ // Read Resume Frame data
+ pBuffer += 44;
+ unpackDWord(&pBuffer, &dwResumeOffset);
+ unpackDWord(&pBuffer, &dwResumeCheck);
+
+ dwFileCheck = oft_calc_file_checksum(ft->fileId, dwResumeOffset);
+ if (dwFileCheck == dwResumeCheck && dwResumeOffset <= ft->qwThisFileSize)
+ { // resume seems ok
+ ft->qwFileBytesDone = dwResumeOffset;
+ ft->qwBytesDone += dwResumeOffset;
+ lseek(ft->fileId, dwResumeOffset, SEEK_SET);
+
+ NetLog_Direct("OFT: Resume request, ready.");
+ }
+ else
+ NetLog_Direct("OFT: Resume request, restarting.");
+
+ // Ready for resume
+ sendOFT2FramePacket(oc, OFT_TYPE_RESUMEREADY);
+ }
+ break;
+
+ case OFT_TYPE_RESUMEREADY:
+ { // Process Smart-resume reply
+ oscar_filetransfer *ft = oc->ft;
+ DWORD dwResumeOffset, dwResumeCheck;
+
+ if (ft->sending)
+ { // just sanity check - this is only for receiving client
+ NetLog_Direct("Error: Invalid Packet, closing.");
+ CloseOscarConnection(oc);
+
+ return;
+ }
+ // Read Resume Reply data
+ pBuffer += 44;
+ unpackDWord(&pBuffer, &dwResumeOffset);
+ unpackDWord(&pBuffer, &dwResumeCheck);
+
+ if (ft->qwFileBytesDone != dwResumeOffset)
+ {
+ ft->qwBytesDone -= (ft->qwFileBytesDone - dwResumeOffset);
+ ft->qwFileBytesDone = dwResumeOffset;
+ ft->dwRecvFileCheck = dwResumeCheck;
+ }
+ lseek(ft->fileId, dwResumeOffset, SEEK_SET);
+
+ if (ft->qwThisFileSize != ft->qwFileBytesDone)
+ NetLog_Direct("OFT: Resuming from offset %u.", dwResumeOffset);
+
+ // Prepare to receive data
+ oc->status = OCS_DATA;
+
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
+
+ // Ready for receive
+ sendOFT2FramePacket(oc, OFT_TYPE_RESUMEACK);
+
+ if (ft->qwThisFileSize == ft->qwFileBytesDone)
+ { // all data already processed
+ BYTE buf;
+
+ oft_handleFileData(oc, &buf, 0);
+ }
+ }
+ break;
+
+ case OFT_TYPE_DONE:
+ { // File done
+ oscar_filetransfer *ft = oc->ft;
+
+ oc->status = OCS_NEGOTIATION;
+ oc->wantIdleTime = 0;
+
+ NetLog_Direct("OFT: File sent successfully.");
+
+#ifdef _DEBUG
+ NetLog_Direct("OFT: _close(%u)", ft->fileId);
+#endif
+ _close(ft->fileId); // FIXME: this needs fix for "skip file" feature
+ ft->fileId = -1;
+ ft->iCurrentFile++;
+ // continue with next file
+ oft_sendPeerInit(oc);
+ }
+ break;
+
+ default:
+ NetLog_Direct("Error: Uknown OFT frame type 0x%x", datatype);
+ }
+}
+
+
+//
+// Proxy packets
+/////////////////////////////
+
+static void proxy_sendInitTunnel(oscar_connection *oc)
+{
+ icq_packet packet;
+ WORD wLen = 39 + getUINLen(dwLocalUIN);
+
+ packet.wLen = wLen;
+ init_generic_packet(&packet, 2);
+
+ packWord(&packet, wLen);
+ packWord(&packet, OSCAR_PROXY_VERSION);
+ packWord(&packet, 0x02); // wCommand
+ packDWord(&packet, 0); // Unknown
+ packWord(&packet, 0); // Flags?
+ packUIN(&packet, dwLocalUIN);
+ packLEDWord(&packet, oc->ft->pMessage.dwMsgID1);
+ packLEDWord(&packet, oc->ft->pMessage.dwMsgID2);
+ packDWord(&packet, 0x00010010); // TLV(1)
+ packGUID(&packet, MCAP_FILE_TRANSFER);
+
+ sendOscarPacket(oc, &packet);
+}
+
+
+
+static void proxy_sendJoinTunnel(oscar_connection *oc, WORD wPort)
+{
+ icq_packet packet;
+ WORD wLen = 41 + getUINLen(dwLocalUIN);
+
+ packet.wLen = wLen;
+ init_generic_packet(&packet, 2);
+
+ packWord(&packet, wLen);
+ packWord(&packet, OSCAR_PROXY_VERSION);
+ packWord(&packet, 0x04); // wCommand
+ packDWord(&packet, 0); // Unknown
+ packWord(&packet, 0); // Flags?
+ packUIN(&packet, dwLocalUIN);
+ packWord(&packet, wPort);
+ packLEDWord(&packet, oc->ft->pMessage.dwMsgID1);
+ packLEDWord(&packet, oc->ft->pMessage.dwMsgID2);
+ packDWord(&packet, 0x00010010); // TLV(1)
+ packGUID(&packet, MCAP_FILE_TRANSFER);
+
+ sendOscarPacket(oc, &packet);
+}
+
+
+//
+// Direct packets
+/////////////////////////////
+
+static void oft_sendFileData(oscar_connection *oc)
+{
+ oscar_filetransfer *ft = oc->ft;
+ BYTE buf[OFT_BUFFER_SIZE];
+ int bytesRead = 0;
+ icq_packet packet;
+
+ if (ft->fileId == -1)
+ return;
+ bytesRead = _read(ft->fileId, buf, sizeof(buf));
+ if (bytesRead == -1)
+ return;
+
+ if (!bytesRead)
+ { //
+ oc->wantIdleTime = 0;
+ return;
+ }
+
+ if ((DWORD)bytesRead > (ft->qwThisFileSize - ft->qwFileBytesDone))
+ { // do not send more than expected, limit to known size
+ bytesRead = (DWORD)(ft->qwThisFileSize - ft->qwFileBytesDone);
+ oc->wantIdleTime = 0;
+ }
+ packet.wLen = bytesRead;
+ init_generic_packet(&packet, 0);
+ packBuffer(&packet, buf, (WORD)bytesRead); // we are sending raw data
+ sendOscarPacket(oc, &packet);
+
+ ft->qwBytesDone += bytesRead;
+ ft->qwFileBytesDone += bytesRead;
+
+ if (GetTickCount() > ft->dwLastNotify + 700 || oc->wantIdleTime == 0 || ft->qwFileBytesDone == ft->qwThisFileSize)
+ { // notify only once a while or after last data packet sent
+ PROTOFILETRANSFERSTATUS pfts;
+
+ oft_buildProtoFileTransferStatus(ft, &pfts);
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&pfts);
+ SAFE_FREE(&pfts.currentFile);
+ SAFE_FREE(&pfts.workingDir);
+ ft->dwLastNotify = GetTickCount();
+ }
+}
+
+
+
+static void oft_sendPeerInit(oscar_connection *oc)
+{
+ oscar_filetransfer *ft = oc->ft;
+ struct _stati64 statbuf;
+ char *pszThisFileName;
+ wchar_t *pwsThisFile;
+
+ // prepare init frame
+ if (ft->iCurrentFile >= (int)ft->wFilesCount)
+ { // All files done, great!
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&oc->ft);
+ return;
+ }
+
+ SAFE_FREE(&ft->szThisFile);
+ ft->szThisFile = null_strdup(ft->files[ft->iCurrentFile].szFile);
+ if (FileStatUtf(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.");
+
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&oc->ft);
+ return;
+ }
+
+ { // create full relative filename
+ char* szThisContainer = ft->files[ft->iCurrentFile].szContainer;
+
+ pszThisFileName = (char*)SAFE_MALLOC(strlennull(ft->szThisFile) + strlennull(szThisContainer) + 4);
+ strcpy(pszThisFileName, szThisContainer);
+ NormalizeBackslash(pszThisFileName);
+ strcat(pszThisFileName, ExtractFileName(ft->szThisFile));
+ }
+ { // convert backslashes to dir markings
+ DWORD i;
+
+ for (i = 0; i < strlennull(pszThisFileName); i++)
+ {
+ if (pszThisFileName[i] == '\\' || pszThisFileName[i] == '/') pszThisFileName[i] = 0x01;
+ }
+ }
+
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
+
+ ft->fileId = OpenFileUtf(ft->szThisFile, _O_BINARY | _O_RDONLY, 0);
+#ifdef _DEBUG
+ NetLog_Direct("OFT: OpenFileUtf(%s, %u) returned %u", ft->szThisFile, _O_BINARY | _O_RDONLY, ft->fileId);
+#endif
+ if (ft->fileId == -1)
+ {
+#ifdef _DEBUG
+ NetLog_Direct("OFT: errno=%d", errno);
+#endif
+ SAFE_FREE(&pszThisFileName);
+ 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.");
+ //
+ ICQBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer(&oc->ft);
+ return;
+ }
+
+ ft->qwThisFileSize = statbuf.st_size;
+ ft->dwThisFileDate = statbuf.st_mtime;
+ ft->dwThisFileCreation = statbuf.st_ctime;
+ ft->dwThisFileCheck = oft_calc_file_checksum(ft->fileId, ft->qwThisFileSize);
+ ft->qwFileBytesDone = 0;
+ ft->dwRecvFileCheck = 0xFFFF0000;
+ SAFE_FREE(&ft->rawFileName);
+
+ if (IsUSASCII(pszThisFileName, strlennull(pszThisFileName)))
+ {
+ ft->wEncoding = 0; // ascii
+ ft->cbRawFileName = strlennull(pszThisFileName) + 1;
+ if (ft->cbRawFileName < 64) ft->cbRawFileName = 64;
+ ft->rawFileName = (char*)SAFE_MALLOC(ft->cbRawFileName);
+ strcpy(ft->rawFileName, pszThisFileName);
+ SAFE_FREE(&pszThisFileName);
+ }
+ else
+ {
+ ft->wEncoding = 2; // ucs-2
+ pwsThisFile = make_unicode_string(pszThisFileName);
+ SAFE_FREE(&pszThisFileName);
+ ft->cbRawFileName = wcslen(pwsThisFile) * sizeof(wchar_t) + 2;
+ if (ft->cbRawFileName < 64) ft->cbRawFileName = 64;
+ ft->rawFileName = (char*)SAFE_MALLOC(ft->cbRawFileName);
+ // convert to LE ordered string
+ unpackWideString((char**)&pwsThisFile, (wchar_t*)ft->rawFileName, (WORD)(wcslen(pwsThisFile) * sizeof(wchar_t)));
+ SAFE_FREE(&pwsThisFile);
+ }
+ ft->wFilesLeft = (WORD)(ft->wFilesCount - ft->iCurrentFile);
+
+ sendOFT2FramePacket(oc, OFT_TYPE_REQUEST);
+}
+
+
+
+static void sendOFT2FramePacket(oscar_connection *oc, WORD datatype)
+{
+ oscar_filetransfer *ft = oc->ft;
+ icq_packet packet;
+
+ packet.wLen = 192 + ft->cbRawFileName;
+ init_generic_packet(&packet, 0);
+ // Basic Oscar Frame
+ packDWord(&packet, 0x4F465432); // Magic
+ packWord(&packet, packet.wLen);
+ packWord(&packet, datatype);
+ // Cookie
+ packLEDWord(&packet, ft->pMessage.dwMsgID1);
+ packLEDWord(&packet, ft->pMessage.dwMsgID2);
+ packWord(&packet, ft->wEncrypt);
+ packWord(&packet, ft->wCompress);
+ packWord(&packet, ft->wFilesCount);
+ packWord(&packet, ft->wFilesLeft);
+ packWord(&packet, ft->wPartsCount);
+ packWord(&packet, ft->wPartsLeft);
+ packDWord(&packet, (DWORD)ft->qwTotalSize);
+ packDWord(&packet, (DWORD)ft->qwThisFileSize);
+ packDWord(&packet, ft->dwThisFileDate);
+ packDWord(&packet, ft->dwThisFileCheck);
+ packDWord(&packet, ft->dwRecvForkCheck);
+ packDWord(&packet, ft->dwThisForkSize);
+ packDWord(&packet, ft->dwThisFileCreation);
+ packDWord(&packet, ft->dwThisForkCheck);
+ packDWord(&packet, (DWORD)ft->qwFileBytesDone);
+ packDWord(&packet, ft->dwRecvFileCheck);
+ packBuffer(&packet, ft->rawIDString, 32);
+ packByte(&packet, ft->bHeaderFlags);
+ packByte(&packet, ft->bNameOff);
+ packByte(&packet, ft->bSizeOff);
+ packBuffer(&packet, ft->rawDummy, 69);
+ packBuffer(&packet, ft->rawMacInfo, 16);
+ packWord(&packet, ft->wEncoding);
+ packWord(&packet, ft->wSubEncoding);
+ packBuffer(&packet, ft->rawFileName, ft->cbRawFileName);
+
+ sendOscarPacket(oc, &packet);
+}
diff --git a/icqj_s7_sss_mod/oscar_filetransfer.h b/icqj_s7_sss_mod/oscar_filetransfer.h new file mode 100644 index 0000000..ec9e68a --- /dev/null +++ b/icqj_s7_sss_mod/oscar_filetransfer.h @@ -0,0 +1,184 @@ +// ---------------------------------------------------------------------------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,2007 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 : $URL: https://icqjplusmod.googlecode.com/svn/trunk/oscar_filetransfer.h $
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __OSCAR_FILETRANSFER_H
+#define __OSCAR_FILETRANSFER_H
+
+
+void InitOscarFileTransfer();
+void UninitOscarFileTransfer();
+
+
+#define FT_MAGIC_ICQ 0x00
+#define FT_MAGIC_OSCAR 0x4F
+
+#define OFT_BUFFER_SIZE 8192
+
+typedef struct {
+ char* szContainer;
+ char* szFile;
+} oft_file_record;
+
+char* FindFilePathContainer(const char** files, int iFile, char* szContainer);
+
+
+typedef struct {
+ message_cookie_data pMessage;
+ BYTE ft_magic;
+} basic_filetransfer;
+
+typedef struct {
+ message_cookie_data pMessage;
+ BYTE ft_magic;
+ HANDLE hContact;
+ int initialized;
+ int sending;
+ int containerCount;
+ char **file_containers;
+ oft_file_record* files;
+ char **files_ansi; // sending only
+ int iCurrentFile;
+ int currentIsDir;
+ int bUseProxy;
+ DWORD dwProxyIP;
+ DWORD dwRemoteInternalIP;
+ DWORD dwRemoteExternalIP;
+ WORD wRemotePort;
+ char *szSavePath;
+ char *szDescription;
+ char *szThisFile;
+ char *szThisPath;
+ // Request sequence
+ DWORD dwCookie;
+ WORD wReqNum;
+ // OFT2 header data
+ WORD wEncrypt, wCompress;
+ WORD wFilesCount,wFilesLeft;
+ WORD wPartsCount, wPartsLeft;
+ DWORD64 qwTotalSize;
+ DWORD64 qwThisFileSize;
+ DWORD dwThisFileDate; // modification date
+ DWORD dwThisFileCheck;
+ DWORD dwRecvForkCheck, dwThisForkSize;
+ DWORD dwThisFileCreation; // creation date (not used)
+ DWORD dwThisForkCheck;
+ DWORD64 qwBytesDone;
+ DWORD dwRecvFileCheck;
+ char rawIDString[32];
+ BYTE bHeaderFlags;
+ BYTE bNameOff, bSizeOff;
+ BYTE rawDummy[69];
+ BYTE rawMacInfo[16];
+ WORD wEncoding, wSubEncoding;
+ WORD cbRawFileName;
+ char *rawFileName;
+ // helper data
+ DWORD64 qwFileBytesDone;
+ int fileId;
+ void* connection;
+ void* listener;
+ DWORD dwLastNotify;
+ int resumeAction;
+} oscar_filetransfer;
+
+#define OFT_TYPE_REQUEST 0x0101 // I am going to send you this file, is that ok?
+#define OFT_TYPE_READY 0x0202 // Yes, it is ok for you to send me that file
+#define OFT_TYPE_DONE 0x0204 // I received that file with no problems
+#define OFT_TYPE_RESUMEREQUEST 0x0205 // Resume transferring from position
+#define OFT_TYPE_RESUMEREADY 0x0106 // Ok, I am ready to send it
+#define OFT_TYPE_RESUMEACK 0x0207 // Fine, ready to receive
+
+void SafeReleaseFileTransfer(void **ft);
+
+typedef struct {
+ HANDLE hContact;
+ HANDLE hConnection;
+ int status;
+ DWORD dwUin;
+ uid_str szUid;
+ DWORD dwLocalInternalIP;
+ DWORD dwLocalExternalIP;
+ int type;
+ int incoming;
+ oscar_filetransfer *ft;
+ int wantIdleTime;
+} oscar_connection;
+
+#define OCT_NORMAL 0
+#define OCT_REVERSE 1
+#define OCT_PROXY 2
+#define OCT_PROXY_INIT 3
+#define OCT_PROXY_RECV 4
+#define OCT_CLOSING 10
+
+#define OCS_READY 0
+#define OCS_CONNECTED 1
+#define OCS_NEGOTIATION 2
+#define OCS_RESUME 3
+#define OCS_DATA 4
+#define OCS_PROXY 8
+#define OCS_WAITING 10
+
+typedef struct {
+ WORD wPort;
+ HANDLE hBoundPort;
+ oscar_filetransfer* ft;
+} oscar_listener;
+
+oscar_listener* CreateOscarListener(oscar_filetransfer *ft, NETLIBNEWCONNECTIONPROC_V2 handler);
+void ReleaseOscarListener(oscar_listener **pListener);
+
+filetransfer *CreateIcqFileTransfer();
+
+int IsValidFileTransfer(void *ft);
+int IsValidOscarTransfer(void *ft);
+
+void OpenOscarConnection(HANDLE hContact, oscar_filetransfer *ft, int type);
+void CloseOscarConnection(oscar_connection *oc);
+
+void handleRecvServMsgOFT(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwID1, DWORD dwID2, WORD wCommand);
+void handleRecvServResponseOFT(unsigned char *buf, WORD wLen, DWORD dwUin, char *szUID, void* ft);
+
+int oftInitTransfer(HANDLE hContact, DWORD dwUin, char *szUid, char** files, char* pszDesc);
+
+DWORD oftFileAllow(HANDLE hContact, WPARAM wParam, LPARAM lParam);
+DWORD oftFileDeny(HANDLE hContact, WPARAM wParam, LPARAM lParam);
+DWORD oftFileCancel(HANDLE hContact, WPARAM wParam, LPARAM lParam);
+
+void oftFileResume(oscar_filetransfer *ft, int action, const char *szFilename);
+
+#endif /* __OSCAR_FILETRANSFER_H */
+
diff --git a/icqj_s7_sss_mod/resource.h b/icqj_s7_sss_mod/resource.h new file mode 100644 index 0000000..425c287 --- /dev/null +++ b/icqj_s7_sss_mod/resource.h @@ -0,0 +1,412 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resources.rc
+//
+#define ID_FIRSTICON 1
+#define IDDEL 3
+#define IDEDIT 4
+#define IDI_ICQ 101
+#define IDD_ICQACCOUNT 102
+#define IDD_ASKAUTH 103
+#define IDD_LOGINPW 104
+#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_DC 128
+#define IDI_ICON1 130
+#define IDI_INCOGNITO_R 130
+#define IDI_AUTH 131
+#define IDD_OPT_POPUPS2 131
+#define IDI_GRANT 132
+#define IDI_REMOVE 133
+#define IDI_SET_VIS 134
+#define IDI_SET_INVIS 135
+#define IDI_SERVLIST_ADD 136
+#define IDD_TZER 137
+#define IDI_SEND_TZER 138
+#define IDD_ICQ_CAPS_LIST 140
+#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 IDI_XSTATUS33 233
+#define IDI_XSTATUS34 234
+#define IDI_XSTATUS35 236
+#define IDI_XSTATUS36 236
+#define IDI_XSTATUS37 237
+#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 IDD_INFO_ICQ1 401
+#define IDD_INFO_ICQ_CLIENT 401
+#define IDD_OPT_ICQ_CLIENT_ID 403
+#define IDD_ICQ_SRV_LIST 404
+#define IDD_OPT_ICQFEATURES2 405
+#define IDD_ICQ_REG_UIN 406
+#define IDD_OPT_ICQ_EVENTS 407
+#define IDC_TZER_COMBO 408
+#define IDD_OPT_ASD 408
+#define IDC_TZER_NAME 409
+#define IDC_POPUPS_ENABLED 410
+#define IDC_POPUPS_LOG_ENABLED 411
+#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_UNKNOWN_TEXTCOLOR 426
+#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_UNKNOWN_BACKCOLOR 436
+#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_POPUP_UNKNOWN_TIMEOUT 445
+#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_POPUP_LOG6_BACKCOLOR 462
+#define IDC_POPUP_LOG6_TEXTCOLOR 463
+#define IDC_POPUP_LOG6_TIMEOUT 464
+#define IDC_POPUP_CLIENT_CHANGE_BACKCOLOR 465
+#define IDC_POPUP_CLIENT_CHANGE_TEXTCOLOR 466
+#define IDC_POPUP_CLIENT_CHANGE_TIMEOUT 467
+#define IDC_POPUP_INFO_REQUEST_BACKCOLOR 468
+#define IDC_POPUP_INFO_REQUEST_TEXTCOLOR 469
+#define IDC_POPUP_INFO_REQUEST_TIMEOUT 470
+#define IDC_POPUP_IGNORECHECK_BACKCOLOR 471
+#define IDC_POPUP_IGNORECHECK_TEXTCOLOR 472
+#define IDC_POPUP_IGNORECHECK_TIMEOUT 473
+#define IDC_POPUP_REMOVE_HIMSELF_BACKCOLOR5 477
+#define IDC_POPUP_REMOVE_HIMSELF_BACKCOLOR 477
+#define IDC_POPUP_REMOVE_HIMSELF_TEXTCOLOR 478
+#define IDC_POPUP_REMOVE_HIMSELF_TIMEOUT 479
+#define IDC_POPUP_REMOVE_HIMSELF_BACKCOLOR2 480
+#define IDC_POPUP_AUTH_BACKCOLOR 480
+#define IDC_POPUP_AUTH_TEXTCOLOR 481
+#define IDC_POPUP_AUTH_TIMEOUT 482
+#define IDC_POPUP_XUPDATER_BACKCOLOR 483
+#define IDC_POPUP_XUPDATER_TEXTCOLOR 484
+#define IDC_POPUP_XUPDATER_TIMEOUT 485
+#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_XMSG 1011
+#define IDC_KEEPALIVE 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_DCPASSIVE2 1022
+#define IDC_DCICON 1022
+#define IDC_ICQNUM 1022
+#define IDC_RETRIEVE 1024
+#define IDC_SCROLLBAR1 1026
+#define IDC_CHANGEID 1027
+#define IDC_IDSTATIC 1028
+#define IDC_HIDE_ID 1029
+#define IDC_HIDEID 1029
+#define IDC_AIMENABLE 1030
+#define IDC_GETSTATUS 1030
+#define IDC_BUTTON1 1032
+#define IDC_FORCEREFRESH 1032
+#define IDC_PICTURE 1032
+#define IDC_REG 1032
+#define IDC_REGUIN 1032
+#define IDC_POPUPS_OPTIONS 1032
+#define IDC_OK 1032
+#define IDC_ASDOPTIONS 1032
+#define IDC_CAPSBOX 1032
+#define IDC_VERSION_CHECKBOX 1034
+#define IDC_CLIST 1035
+#define IDC_KILLUNKNOWN 1038
+#define IDC_XSTATUSENABLE 1040
+#define IDC_NOTE_POPUP_ENABLE 1040
+#define IDC_XSTATUSAUTO 1041
+#define IDC_WARN_POPUP_ENABLE 1041
+#define IDC_XSTATUSRESET 1042
+#define IDC_ERROR_POPUP_ENABLE 1042
+#define IDC_CHECK1 1043
+#define IDC_RTF 1043
+#define IDC_FATAL_POPUP_ENABLE 1043
+#define IDC_TRY_NEXT 1043
+#define IDC_AUTOCHANGE 1043
+#define IDC_ADDTEMP 1043
+#define IDC_TZER 1043
+#define IDC_LOG_REMOVE_HISTORY 1043
+#define IDC_UINPOPUP 1043
+#define IDC_DETECT_VIA_STATUS_MESSAGE 1043
+#define IDC_CUSTOM_CAP 1044
+#define IDC_SPAM_POPUP_ENABLE 1044
+#define IDC_CHECK4 1044
+#define IDC_DETECT_VIA_ZTRAZ 1044
+#define IDC_DETECT_VIA_XTRAZ 1044
+#define IDC_KILLSPAMBOTS 1045
+#define IDC_LIST1 1045
+#define IDC_CLIENTCAPS 1045
+#define IDC_WAS_FOUND_POPUP_ENABLE 1045
+#define IDC_SERVERS 1045
+#define IDC_CHECK5 1045
+#define IDC_DETECT_VIA_URL 1045
+#define IDC_CAPABILITIES 1045
+#define IDC_CLIENTICON 1046
+#define IDC_SCAN_POPUP_ENABLE 1046
+#define IDC_DETECT_UNAUTHORIZED 1046
+#define IDC_TIMESTAMPS 1047
+#define IDC_UNKNOWN_POPUP_ENABLE 1047
+#define IDC_DETECT_VIA_AUTH 1047
+#define IDC_EMAIL 1048
+#define IDC_ICON_POS_TEXT 1048
+#define IDC_VIS_POPUP_ENABLE 1048
+#define IDC_PICTURE_CONTENT 1049
+#define IDC_NEWUIN_PASS 1051
+#define IDC_NICK 1053
+#define IDC_NEWUININFO 1053
+#define IDC_UIN_IMAGE 1054
+#define IDC_REPLACEXTEXT 1055
+#define IDC_NEEDRESTART 1056
+#define IDC_SET_VERSION 1057
+#define IDC_FORCEXSTATUS 1057
+#define IDC_CUSTCAPEDIT 1058
+#define IDC_CUSTCAPSTATIC 1059
+#define IDC_GENDER 1060
+#define IDADD 1060
+#define IDC_CITY 1061
+#define IDCCLOSE 1061
+#define IDC_STATE 1062
+#define IDC_EDIT_SERVER 1062
+#define IDC_COUNTRY 1063
+#define IDC_EDIT_PORT 1063
+#define IDC_DELETE_TMP_CONTACTS 1064
+#define IDC_ADD_TMP_CONTACTS 1065
+#define IDC_COMPANY 1066
+#define IDC_GROUP 1066
+#define IDC_TMP_CONTACTS_GROUP 1066
+#define IDC_DEPARTMENT 1067
+#define IDC_CHECK2 1067
+#define IDC_LOG_IGNORECHECK_HISTORY 1067
+#define IDC_SHOW_AUTH 1067
+#define IDC_CLIENTC_CHANGE_POPUP 1067
+#define IDC_CLIENT_CHANGE_POPUP 1067
+#define IDC_XSTUPDATE 1067
+#define IDC_EDIT1 1068
+#define IDC_FILEPATH 1068
+#define IDC_XSTUPDATERATE 1068
+#define IDC_CAPL_EDIT 1068
+#define IDC_POSITION 1069
+#define IDC_BROWSE 1069
+#define IDC_LOG_CHECKSTATUS_FILE 1070
+#define IDC_LOG_CHECKSTATUS_HISTORY 1071
+#define IDC_LOG_CLIENTCHANGE_FILE 1072
+#define IDC_LOG_CLIENTCHANGE_HISTORY 1073
+#define IDC_LOG_AUTH_FILE 1074
+#define IDC_LOG_AUTH_HISTORY 1075
+#define IDC_CHECK3 1076
+#define IDC_LOG_TO_HCONTACT_HISTORY 1076
+#define IDC_NOPSD_FOR_HIDDEN 1076
+#define IDC_VIS_POPUP_FOR_NOT_ON_LIST 1076
+#define IDC_POPUP_FOR_NOTONLIST 1076
+#define IDC_X 1076
+#define IDC_XSTNONSTD 1076
+#define IDC_INCUSER 1077
+#define IDC_INCGLOBAL 1078
+#define IDC_FAKEWARNING 1079
+#define IDC_REQUEST_LOG_FILE 1080
+#define IDC_LOG_REQUEST_FILE 1080
+#define IDC_LOG_REQUEST_HISTORY 1081
+#define IDC_LOG_ASD_FILE 1082
+#define IDC_DC_ICON_POS_TEXT 1083
+#define IDC_LOG_REQUEST_HISTORY2 1083
+#define IDC_LOG_ASD_HISTORY 1083
+#define IDC_HTTPUSERAGENT 1084
+#define IDC_COMBO1 1085
+#define IDC_ENIFMIR 1086
+#define IDC_ENIFMIRCBX 1087
+#define IDC_CAPL_ADD 1090
+#define IDC_CAPL_MODIFY 1091
+#define IDC_CAPL_DELETE 1092
+#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_XSTATUS_ICON_POS 1180
+#define IDC_DC_ICON_POS 1183
+#define IDC_DC_ICON_POS2 1184
+#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_XSTATUS_SHOW 1381
+#define IDC_STEALTHRQST 1382
+#define IDC_NOASD 1383
+#define IDC_PSD 1384
+#define IDC_LOGSELFREM 1385
+#define IDC_LOG_REMOVE_FILE 1385
+#define IDC_POPSELFREM 1386
+#define IDC_IGNCHECKLOG 1387
+#define IDC_LOG_IGNORECHECK_FILE 1387
+#define IDC_INFOREQUEST_POPUP 1387
+#define IDC_INFO_REQUEST_POPUP 1387
+#define IDC_IGNCHECKPOP 1388
+#define IDC_ASDSTARTUP 1389
+#define IDC_POPAUTH 1389
+#define IDC_CHECKITEM 1390
+#define IDC_POPXUPDATER 1390
+#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_NEWAIMLINK 1440
+#define IDC_SERVERBOX 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_BIGGERAVATARS 1531
+#define IDC_ADDSERVER 1532
+#define IDC_SAVETOSERVER 1533
+#define IDC_ENABLEAVATARS 1536
+#define IDC_AUTOLOADAVATARS 1537
+#define IDC_IGNORECHECK 1537
+#define IDC_STRICTAVATARCHECK 1539
+#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_NOSTATUSREPLY 1559
+#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 133
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1086
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/icqj_s7_sss_mod/resources.rc b/icqj_s7_sss_mod/resources.rc new file mode 100644 index 0000000..38dcc96 --- /dev/null +++ b/icqj_s7_sss_mod/resources.rc @@ -0,0 +1,934 @@ +// 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
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+#ifdef _WIN32
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_DC ICON "icos\\dc.ICO"
+#endif // Russian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// German (Germany) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_INCOGNITO_R ICON "icos\\incognito_request.ico"
+#endif // German (Germany) 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_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_SERVLIST_ADD ICON "icos\\srvlist_add.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"
+IDI_SEND_TZER ICON "icos\\tzer.ico"
+IDI_DC ICON "icos\\dc.ico"
+IDI_INCOGNITO_R ICON "icos\\incognito_request.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ICQACCOUNT DIALOGEX 0, 0, 200, 101
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | 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 | ES_NUMBER
+ 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
+ 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
+ PUSHBUTTON "Create UIN",IDC_REG,13,80,50,14
+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_ICQCONTACTS DIALOGEX 0, 0, 302, 215
+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,291,78
+ PUSHBUTTON "Manage server's list...",IDC_UPLOADNOW,12,61,97,14
+ CONTROL "Enable server-side contact lists",IDC_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,12,275,10
+ CONTROL "Add contacts to the server's list when I add them to mine",IDC_ADDSERVER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,25,281,10
+ CONTROL "Update my contacts' details from the server *",IDC_LOADFROMSERVER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,36,277,10
+ CONTROL "Update contacts' details on the server's list when I change them in mine",IDC_SAVETOSERVER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,48,277,10
+ GROUPBOX "ICQ avatars",IDC_STATIC,4,126,292,52
+ CONTROL "Enable avatar support",IDC_ENABLEAVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,137,174,10
+ CONTROL "Load avatars automatically (like ICQ Lite)",IDC_AUTOLOADAVATARS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,157,210,10
+ CONTROL "Allow bigger owner avatars (up to 128x128) [experimental]",IDC_BIGGERAVATARS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,167,274,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,4,183,279,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,198,275,16
+ PUSHBUTTON "Force update of list from server at next connect",IDC_FORCEREFRESH,121,61,169,14
+ CONTROL "Check avatar validity before saving",IDC_STRICTAVATARCHECK,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,147,174,10
+ GROUPBOX "Not on list contacts",IDC_STATIC,4,79,291,46
+ CONTROL "Do not add contacts that request info",IDC_DELETE_TMP_CONTACTS,
+ "Button",BS_AUTORADIOBUTTON,13,88,176,10
+ CONTROL "Add contacts that request info to special group:",IDC_ADD_TMP_CONTACTS,
+ "Button",BS_AUTORADIOBUTTON,13,99,176,10
+ EDITTEXT IDC_TMP_CONTACTS_GROUP,193,96,63,14,ES_AUTOHSCROLL
+ CONTROL "add temporarily",IDC_ADDTEMP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,27,110,125,10
+END
+
+IDD_OPT_ICQFEATURES DIALOGEX 0, 0, 296, 230
+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,291,74
+ CONTROL "Enable unicode messaging support",IDC_UTFENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,8,134,10
+ CONTROL "Send all messages in unicode if possible",IDC_UTFALL,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,17,136,10
+ RTEXT "Use this codepage for Ansi <-> Unicode translation :",IDC_UTFSTATIC,12,29,174,10
+ COMBOBOX IDC_UTFCODEPAGE,190,26,99,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,8,40,284,10
+ CONTROL "Notify me when a message delivery has failed (recommended)",IDC_SLOWSEND,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,49,283,10
+ CONTROL "Use only server's acknowledgement (faster)",IDC_ONLYSERVERACKS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,59,285,10
+ GROUPBOX "Peer-to-peer Messaging",IDC_STATIC,4,75,291,34
+ CONTROL "Enable peer-to-peer message connections",IDC_DCENABLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,84,222,10
+ CONTROL "Passive mode, i.e. do not initiate new connections",IDC_DCPASSIVE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,94,221,11
+ CONTROL "Enable Custom status support",IDC_XSTATUSENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,120,144,10
+ CONTROL "Reset Custom status on status change",IDC_XSTATUSRESET,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,139,143,10
+ CONTROL "Auto-retrieve Custom status details",IDC_XSTATUSAUTO,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,129,143,10
+ CONTROL "Block known Spam Bots",IDC_KILLSPAMBOTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,161,123,8
+ CONTROL "Enable AIM support",IDC_AIMENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,8,176,122,10
+ CONTROL "Block unknown clients",IDC_KILLUNKNOWN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,149,127,10
+ CONTROL "Accept RTF (if ID Miranda)",IDC_RTF,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,155,9,135,10
+ CONTROL "Show DC icon in contact list",IDC_DCICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,120,125,10
+ LTEXT "X-Status icon slot:",IDC_ICON_POS_TEXT,147,211,59,8
+ LTEXT "DC icon slot:",IDC_DC_ICON_POS_TEXT,15,135,41,8
+ COMBOBOX IDC_DC_ICON_POS,56,133,75,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_XSTATUS_ICON_POS,209,208,79,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Replace Custom status name in menu*",IDC_REPLACEXTEXT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,158,141,10
+ RTEXT "*need restart",IDC_NEEDRESTART,32,206,61,8
+ CONTROL "Display Custom status icon in contact list",IDC_XSTATUS_SHOW,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,148,141,10
+ GROUPBOX "xStatus options",IDC_STATIC,140,110,155,112
+ CONTROL "Force to reread xstatus",IDC_FORCEXSTATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,168,140,10
+ GROUPBOX "Other",IDC_STATIC,4,110,133,84
+ CONTROL "Update contacts xStatuses every",IDC_XSTUPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,189,141,10
+ LTEXT "minutes",IDC_STATIC,190,200,42,8
+ EDITTEXT IDC_XSTUPDATERATE,161,199,26,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Enable non-standart statuses*",IDC_XSTNONSTD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,179,140,8
+END
+
+IDD_OPT_ICQPRIVACY DIALOGEX 0, 0, 300, 229
+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,4,287,69
+ LTEXT "Allowing direct connections will expose your IP address but may be necessary for some ICQ features to work properly.",IDC_STATIC_DC2,13,15,276,17
+ CONTROL "Allow direct connections with any user",IDC_DCALLOW_ANY,
+ "Button",BS_AUTORADIOBUTTON,14,34,274,10
+ CONTROL "Allow direct connections with users on my contact list",IDC_DCALLOW_CLIST,
+ "Button",BS_AUTORADIOBUTTON,14,44,275,10
+ CONTROL "Allow direct connections only when I authorize or initiate them",IDC_DCALLOW_AUTH,
+ "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,14,55,274,10
+ GROUPBOX "Contact List Authorization",IDC_STATIC_CLIST,7,75,287,38,WS_GROUP
+ CONTROL "All users may add me to their Contact List",IDC_ADD_ANY,
+ "Button",BS_AUTORADIOBUTTON,14,86,277,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,14,97,266,10
+ CONTROL "Allow others to view my Online / Offline status from the web (Web Aware)",IDC_WEBAWARE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,128,276,10
+ CONTROL "Allow others to view my primary e-mail address",IDC_PUBLISHPRIMARY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,138,276,10
+ CONTROL "Only reply to status message requests from users on my contact list",IDC_STATUSMSG_CLIST,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,159,277,10
+ CONTROL "Only reply to status message request from visible contacts",IDC_STATUSMSG_VISIBLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,26,169,264,10
+ GROUPBOX "Misc Settings",IDC_STATIC,7,118,287,65
+ CTEXT "Some options are greyed out because they can only be changed when you are online.",IDC_STATIC_NOTONLINE,0,191,294,8
+ CONTROL "Don't send Status Message Reply (no away-message)",IDC_NOSTATUSREPLY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,148,274,10
+END
+
+IDD_OPT_POPUPS DIALOGEX 0, 0, 309, 247
+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,164
+ CONTROL "Enable popup support",IDC_POPUPS_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,14,127,9
+ CONTROL "Display errors using popups",IDC_POPUPS_LOG_ENABLED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,23,125,10
+ DEFPUSHBUTTON "Previe&w",IDC_PREVIEW,250,216,52,12
+ CONTROL "Show contact's UIN in Popups",IDC_UINPOPUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,32,153,9
+ CONTROL "Show popups for hidden/notonlist users",IDC_POPUP_FOR_NOTONLIST,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,42,158,10
+ PUSHBUTTON "More...",IDC_POPUPS_OPTIONS,195,216,50,12
+ CONTROL "&Use Windows colors",IDC_USEWINCOLORS,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,11,61,117,8
+ CONTROL "Use system &icons",IDC_USESYSICONS,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,11,52,109,8
+END
+
+IDD_INFO_ICQ DIALOGEX 0, 0, 294, 170
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ 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 "Online since:",IDC_STATIC,5,50,71,8
+ EDITTEXT IDC_ONLINESINCE,74,50,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "System up since:",IDC_SUPTIME,5,61,71,8
+ EDITTEXT IDC_SYSTEMUPTIME,74,61,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Idle since:",IDC_STATIC,5,72,71,8
+ EDITTEXT IDC_IDLETIME,74,72,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Status:",IDC_STATIC,5,83,71,8
+ EDITTEXT IDC_STATUS,74,82,131,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ PUSHBUTTON "&Check Status",IDC_GETSTATUS,75,96,66,12,NOT WS_VISIBLE
+ PUSHBUTTON "&Retrieve IP",IDC_RETRIEVE,148,96,66,12,NOT WS_VISIBLE
+ PUSHBUTTON "&Ignore Check",IDC_IGNORECHECK,4,96,66,12,NOT WS_VISIBLE
+ CTEXT "",IDC_IGNORE,72,110,77,8
+ LTEXT "UIN:",IDC_UINSTATIC,5,5,57,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_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 | 0x2c9,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,ES_AUTOHSCROLL
+ 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
+
+IDD_INFO_ICQ_CLIENT DIALOGEX 0, 0, 297, 173
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Protocol Version:",IDC_STATIC,1,3,67,8
+ EDITTEXT IDC_VERSION,76,3,137,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Client Name:",IDC_STATIC,1,18,67,8
+ EDITTEXT IDC_MIRVER,109,18,104,20,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ ICON IDI_ICQ,IDC_CLIENTICON,78,16,21,20,SS_CENTERIMAGE | SS_REALSIZEIMAGE
+ LTEXT "Flags:",IDC_FLAGS,1,32,65,8
+ LISTBOX IDC_CLIENTCAPS,1,45,217,105,LBS_SORT | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT | LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_OPT_ICQ_CLIENT_ID DIALOGEX 0, 0, 296, 217
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Client ID",IDC_STATIC,4,0,287,85
+ COMBOBOX IDC_CHANGEID,45,10,107,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Client ID:",IDC_IDSTATIC,13,12,31,8
+ CONTROL "Show my real ClientID for ICQJ Mod users",IDC_HIDEID,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,56,151,10
+ CONTROL "Send custom protocol version:",IDC_VERSION_CHECKBOX,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,68,109,10
+ EDITTEXT IDC_SET_VERSION,125,66,25,12,ES_AUTOHSCROLL | ES_NUMBER
+ GROUPBOX "Capabilities",IDC_STATIC,4,89,287,29
+ CONTROL "Send custom capabilities",IDC_CUSTOM_CAP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,100,152,10
+ CTEXT "",IDC_FAKEWARNING,3,124,284,58
+ LTEXT "..and if MirandaIM, use this ICQ mod:",IDC_ENIFMIR,13,25,136,8
+ COMBOBOX IDC_ENIFMIRCBX,45,35,107,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "(range 0-255)",IDC_STATIC,155,68,55,8,WS_DISABLED
+ PUSHBUTTON "Edit capabilities",IDC_CAPSBOX,173,98,114,14
+END
+
+IDD_OPT_ICQ DIALOGEX 0, 0, 301, 222
+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,3,0,298,63
+ RTEXT "ICQ number:",IDC_STATIC11,24,12,51,8
+ EDITTEXT IDC_ICQNUM,80,10,106,12,ES_AUTOHSCROLL | ES_NUMBER
+ RTEXT "Password:",IDC_STATIC12,24,26,51,8
+ EDITTEXT IDC_PASSWORD,80,24,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,41,280,19
+ GROUPBOX "Connection settings",IDC_STATIC,3,67,297,154
+ LTEXT "Login Server:",IDC_STATIC,12,79,55,8
+ LTEXT "Port:",IDC_STATIC,182,79,25,8
+ EDITTEXT IDC_ICQPORT,208,77,29,12,ES_AUTOHSCROLL
+ PUSHBUTTON "Edit",IDC_SERVERBOX,244,77,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,11,98,286,19
+ CONTROL "Secure (MD5) login",IDC_SECURE,"Button",BS_AUTOCHECKBOX | BS_TOP | WS_TABSTOP,11,153,282,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,11,166,282,18
+ CONTROL "Ignore concurrent error messages",IDC_NOERRMULTI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,185,150,10
+ LTEXT "Show connection error messages:",IDC_STATIC,12,199,148,8
+ CONTROL "Slider1",IDC_LOGLEVEL,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,18,209,52,10
+ LTEXT "",IDC_LEVELDESCR,71,209,226,8,SS_NOPREFIX
+ COMBOBOX IDC_ICQSERVER,63,77,110,47,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Register new UIN",IDC_REGUIN,205,9,79,26
+ CONTROL "Try to connect to next server in list if connection error occured (Server AutoChange)",IDC_AUTOCHANGE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,141,284,8
+ LTEXT "HTTP User Agent for proxy",IDC_STATIC,12,123,103,8
+ COMBOBOX IDC_HTTPUSERAGENT,121,122,172,87,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_ICQ_SRV_LIST DIALOGEX 0, 0, 272, 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 Servers List"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "List1",IDC_SERVERS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,11,16,245,160
+ DEFPUSHBUTTON "Add",IDADD,4,219,56,16
+ PUSHBUTTON "Close",IDCCLOSE,209,219,55,16
+ PUSHBUTTON "Delete",IDDEL,124,219,56,16
+ PUSHBUTTON "Update",IDEDIT,64,219,56,16
+ GROUPBOX "Servers List",IDC_STATIC,4,6,262,176
+ EDITTEXT IDC_EDIT_SERVER,31,191,89,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_PORT,145,191,35,14,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Server:",IDC_STATIC,4,193,25,8
+ LTEXT "Port:",IDC_STATIC,124,193,17,8
+END
+
+IDD_ICQ_CAPS_LIST DIALOGEX 0, 0, 204, 213
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Manage ICQ Capabilities List"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "Capabilities List",IDC_STATIC,0,1,203,161
+ PUSHBUTTON "A",IDC_CAPL_ADD,0,198,35,14
+ PUSHBUTTON "M",IDC_CAPL_MODIFY,40,198,35,14
+ PUSHBUTTON "D",IDC_CAPL_DELETE,80,198,35,14
+ PUSHBUTTON "Close",IDOK,153,198,50,14
+ CONTROL "",IDC_CAPABILITIES,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,4,10,195,149
+ LTEXT "Capability text:",IDC_STATIC,4,166,131,8
+ EDITTEXT IDC_CAPL_EDIT,4,175,195,14,ES_AUTOHSCROLL
+END
+
+IDD_OPT_ICQFEATURES2 DIALOGEX 0, 0, 294, 231
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Other...",IDC_STATIC,2,130,287,45
+ CONTROL "Enable tZer support",IDC_TZER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,142,212,10
+ CONTROL "Disable Statuscheck in invisible status",IDC_NOASD,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,39,174,10
+ CONTROL "Check entire list on startup",IDC_ASDSTARTUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,28,153,10
+ CONTROL "Enable Passive Status Discovery",IDC_PSD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,19,170,10
+ CONTROL "Enable Active Status Discovery",IDC_ASD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,10,149,10
+ GROUPBOX "Status Discovery System",IDC_STATIC,2,0,287,78
+ GROUPBOX "Stealth away message request",IDC_STATIC,2,81,287,24
+ CONTROL "Usermenu entry",IDC_INCUSER,"Button",BS_AUTORADIOBUTTON,6,91,119,10
+ CONTROL "Global (affects every plugin)",IDC_INCGLOBAL,"Button",BS_AUTORADIOBUTTON,145,90,137,11
+ CONTROL "Always show auth items in menu",IDC_SHOW_AUTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,153,192,10
+ CONTROL "Disable Passive Status Discovery for hidden contacts",IDC_NOPSD_FOR_HIDDEN,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,49,227,10
+ PUSHBUTTON "Options",IDC_ASDOPTIONS,160,8,50,10
+END
+
+IDD_ICQ_REG_UIN DIALOGEX 0, 0, 314, 150
+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 "Create new UIN"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_UIN_IMAGE,"Static",SS_BITMAP | SS_CENTERIMAGE | SS_SUNKEN,12,42,163,64
+ EDITTEXT IDC_PICTURE_CONTENT,86,26,71,12,ES_UPPERCASE | ES_AUTOHSCROLL
+ LTEXT "3. Picture Content:",IDC_STATIC,12,27,62,8
+ LTEXT "1. New UIN password:",IDC_STATIC,12,13,73,8
+ EDITTEXT IDC_NEWUIN_PASS,86,11,71,12,ES_PASSWORD | ES_AUTOHSCROLL
+ PUSHBUTTON "2. Show Picture",IDC_PICTURE,169,9,133,14
+ PUSHBUTTON "4. Register",IDC_REGISTER,169,24,133,14,WS_DISABLED
+ CTEXT "5. New UIN info",IDC_NEWUININFO,193,40,99,66
+ CONTROL "Create a new ICQ account using the ICQ website (https://www.icq.com/register/)",IDC_NEWUINLINK,
+ "Hyperlink",WS_TABSTOP,11,118,273,8
+ CONTROL "Retrieve a lost password or ICQ number (https://www.icq.com/password/)",IDC_LOOKUPLINK,
+ "Hyperlink",WS_TABSTOP,11,132,259,8
+ GROUPBOX "UIN registration options",IDC_STATIC,4,1,306,144
+END
+
+IDD_OPT_ICQ_EVENTS DIALOGEX 0, 0, 294, 231
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_LOG_REMOVE_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,21,13,10
+ CONTROL "",IDC_LOG_IGNORECHECK_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,31,12,10
+ LTEXT "Checking ignore state:",IDC_STATIC,6,31,116,8
+ LTEXT "Removed himself from my Serverlist:",IDC_STATIC,6,21,156,8
+ LTEXT "File",IDC_STATIC,170,11,34,8
+ LTEXT "History",IDC_STATIC,225,11,48,8
+ CONTROL "",IDC_LOG_REMOVE_HISTORY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,225,21,16,10
+ CONTROL "",IDC_LOG_IGNORECHECK_HISTORY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,225,31,13,10
+ EDITTEXT IDC_FILEPATH,6,130,193,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_BROWSE,"MButtonClass",WS_TABSTOP,201,130,14,10
+ LTEXT "Checking real status:",IDC_STATIC,6,41,138,8
+ CONTROL "",IDC_LOG_CHECKSTATUS_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,41,16,10
+ CONTROL "",IDC_LOG_CHECKSTATUS_HISTORY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,225,41,16,10
+ LTEXT "Client change:",IDC_STATIC,6,51,118,8
+ CONTROL "",IDC_LOG_CLIENTCHANGE_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,51,16,10
+ CONTROL "",IDC_LOG_CLIENTCHANGE_HISTORY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,225,51,16,10
+ LTEXT "Auth grant/denied:",IDC_STATIC,6,61,124,8
+ CONTROL "",IDC_LOG_AUTH_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,61,16,10
+ CONTROL "",IDC_LOG_AUTH_HISTORY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,225,61,16,10
+ CONTROL "Write events to contact history (if not set writing to system history)",IDC_LOG_TO_HCONTACT_HISTORY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,114,233,10
+ CONTROL "",IDC_LOG_REQUEST_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,71,16,10
+ CONTROL "",IDC_LOG_REQUEST_HISTORY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,225,71,16,10
+ LTEXT "Request your info",IDC_STATIC,6,71,143,8
+ GROUPBOX "Events log",IDC_STATIC,2,7,287,153
+ CONTROL "",IDC_LOG_ASD_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,80,16,10
+ CONTROL "",IDC_LOG_ASD_HISTORY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,225,80,16,10
+ LTEXT "Detected via ASD/PSD",IDC_STATIC,6,80,143,8
+END
+
+IDD_OPT_POPUPS2 DIALOGEX 0, 0, 293, 311
+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 "Advanced PopUps options"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ PUSHBUTTON "Ok",IDC_OK,231,283,50,14
+ LTEXT "Warning",IDC_STATIC,15,36,60,8
+ CONTROL "",IDC_POPUP_LOG1_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,35,39,10
+ CONTROL "",IDC_POPUP_LOG1_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,35,39,10
+ EDITTEXT IDC_POPUP_LOG1_TIMEOUT,185,34,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Error",IDC_STATIC,15,51,60,8
+ CONTROL "",IDC_POPUP_LOG2_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,50,39,10
+ CONTROL "",IDC_POPUP_LOG2_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,50,39,10
+ EDITTEXT IDC_POPUP_LOG2_TIMEOUT,185,49,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Fatal",IDC_STATIC,15,66,60,8
+ CONTROL "",IDC_POPUP_LOG3_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,65,39,10
+ CONTROL "",IDC_POPUP_LOG3_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,65,39,10
+ EDITTEXT IDC_POPUP_LOG3_TIMEOUT,185,64,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Spam detected",IDC_STATIC,15,81,60,8
+ CONTROL "",IDC_POPUP_SPAM_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,80,39,10
+ CONTROL "",IDC_POPUP_SPAM_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,80,39,10
+ EDITTEXT IDC_POPUP_SPAM_TIMEOUT,185,79,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "User Found",IDC_STATIC,15,110,60,8
+ CONTROL "",IDC_POPUP_LOG4_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,109,39,10
+ CONTROL "",IDC_POPUP_LOG4_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,109,39,10
+ EDITTEXT IDC_POPUP_LOG4_TIMEOUT,185,107,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Active Status Scan",IDC_STATIC,15,124,60,8
+ CONTROL "",IDC_POPUP_LOG5_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,123,39,10
+ CONTROL "",IDC_POPUP_LOG5_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,123,39,10
+ EDITTEXT IDC_POPUP_LOG5_TIMEOUT,185,122,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Unknown detected",IDC_STATIC,15,95,60,8
+ CONTROL "",IDC_POPUP_UNKNOWN_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,94,39,10
+ CONTROL "",IDC_POPUP_UNKNOWN_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,94,39,10
+ EDITTEXT IDC_POPUP_UNKNOWN_TIMEOUT,185,93,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Visibility",IDC_STATIC,15,138,60,8
+ CONTROL "",IDC_POPUP_LOG6_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,138,39,10
+ CONTROL "",IDC_POPUP_LOG6_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,138,39,10
+ EDITTEXT IDC_POPUP_LOG6_TIMEOUT,185,136,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Enabled ?",IDC_STATIC,230,9,38,8
+ CONTROL "",IDC_SPAM_POPUP_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,81,11,10
+ CONTROL "",IDC_WAS_FOUND_POPUP_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,109,11,10
+ CONTROL "",IDC_SCAN_POPUP_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,124,11,10
+ CONTROL "",IDC_UNKNOWN_POPUP_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,95,11,10
+ CONTROL "",IDC_VIS_POPUP_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,138,11,10
+ LTEXT "Back Color",IDC_STATIC,83,9,42,8
+ LTEXT "Text Color",IDC_STATIC,133,9,40,8
+ LTEXT "Timeout",IDC_STATIC,187,9,26,8
+ LTEXT "Note",IDC_STATIC,15,21,60,8
+ CONTROL "",IDC_POPUP_LOG0_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,20,39,10
+ CONTROL "",IDC_POPUP_LOG0_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,20,39,10
+ EDITTEXT IDC_POPUP_LOG0_TIMEOUT,185,19,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_CLIENT_CHANGE_POPUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,152,12,10
+ CONTROL "",IDC_POPSELFREM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,192,9,10
+ CONTROL "",IDC_IGNCHECKPOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,179,10,10
+ LTEXT "Change Client",IDC_STATIC,15,152,46,8
+ CONTROL "",IDC_POPUP_CLIENT_CHANGE_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,152,39,10
+ CONTROL "",IDC_POPUP_CLIENT_CHANGE_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,152,39,10
+ EDITTEXT IDC_POPUP_CLIENT_CHANGE_TIMEOUT,185,151,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_INFO_REQUEST_POPUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,165,11,10
+ LTEXT "Info Request",IDC_STATIC,15,166,43,8
+ CONTROL "",IDC_POPUP_INFO_REQUEST_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,166,39,10
+ CONTROL "",IDC_POPUP_INFO_REQUEST_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,166,39,10
+ EDITTEXT IDC_POPUP_INFO_REQUEST_TIMEOUT,185,164,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Check Ignore State",IDC_STATIC,15,179,63,8
+ CONTROL "",IDC_POPUP_IGNORECHECK_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,179,39,10
+ CONTROL "",IDC_POPUP_IGNORECHECK_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,179,39,10
+ EDITTEXT IDC_POPUP_IGNORECHECK_TIMEOUT,185,178,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Removed Himself",IDC_STATIC,15,192,55,8
+ CONTROL "",IDC_POPUP_REMOVE_HIMSELF_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,192,39,10
+ CONTROL "",IDC_POPUP_REMOVE_HIMSELF_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,192,39,10
+ EDITTEXT IDC_POPUP_REMOVE_HIMSELF_TIMEOUT,185,191,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_POPAUTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,206,9,10
+ LTEXT "Auth",IDC_STATIC,15,206,55,8
+ CONTROL "",IDC_POPUP_AUTH_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,206,39,10
+ CONTROL "",IDC_POPUP_AUTH_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,206,39,10
+ EDITTEXT IDC_POPUP_AUTH_TIMEOUT,185,204,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_POPXUPDATER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,235,219,9,10
+ LTEXT "XStatus Updater",IDC_STATIC,15,220,55,8
+ CONTROL "",IDC_POPUP_XUPDATER_BACKCOLOR,"ColourPicker",WS_TABSTOP,83,220,39,10
+ CONTROL "",IDC_POPUP_XUPDATER_TEXTCOLOR,"ColourPicker",WS_TABSTOP,133,220,39,10
+ EDITTEXT IDC_POPUP_XUPDATER_TIMEOUT,185,218,34,12,ES_AUTOHSCROLL | ES_NUMBER
+END
+
+IDD_TZER DIALOG 0, 0, 186, 90
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Send T-Zer"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,33,69,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,102,69,50,14
+ COMBOBOX IDC_TZER_COMBO,43,35,129,92,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Name: ",IDC_STATIC,13,16,24,9
+ EDITTEXT IDC_TZER_NAME,43,13,129,12,ES_AUTOHSCROLL
+ LTEXT "T-Zer:",IDC_STATIC,13,38,21,9
+END
+
+IDD_OPT_ASD DIALOGEX 0, 0, 240, 86
+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 "ASD Options"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Detect via status message (some old clients)",IDC_DETECT_VIA_STATUS_MESSAGE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,7,229,10
+ CONTROL "Detect via malformed xtraz (icq6) (by [sin])",IDC_DETECT_VIA_XTRAZ,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,18,230,10
+ CONTROL "Detect via malformed url (old miranda, some other clients)",IDC_DETECT_VIA_URL,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,29,231,10
+ PUSHBUTTON "Ok",IDC_OK,183,65,50,14
+ CONTROL "Detect unauthorized contacts status (reported by D@rkNeo)",IDC_DETECT_UNAUTHORIZED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,40,230,10
+ CONTROL "Detect via Auth server bug",IDC_DETECT_VIA_AUTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,51,230,10
+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,8,105
+ PRODUCTVERSION 0,7,0,1
+ 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 modification s7_sss"
+ VALUE "FileVersion", "0, 3, 8, 105"
+ VALUE "InternalName", "ICQJ protocol plugin for Miranda IM"
+ VALUE "LegalCopyright", "Copyright (C) 2000-2007 Joe Kucera, Angeli-Ka, Bio, Martin Oberg, Richard Hughes, Jon Keating, Se7en, [sss], chaos.persei, [sin], nullbie, Big Muscle"
+ VALUE "OriginalFilename", "ICQ.dll"
+ VALUE "ProductName", "ICQ Protocol Support"
+ VALUE "ProductVersion", "0, 7, 0, 1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1252
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPT_ICQCONTACTS, DIALOG
+ BEGIN
+ RIGHTMARGIN, 296
+ VERTGUIDE, 4
+ VERTGUIDE, 12
+ VERTGUIDE, 295
+ END
+
+ IDD_OPT_ICQFEATURES, DIALOG
+ BEGIN
+ RIGHTMARGIN, 295
+ VERTGUIDE, 4
+ VERTGUIDE, 8
+ VERTGUIDE, 147
+ BOTTOMMARGIN, 219
+ END
+
+ IDD_OPT_ICQPRIVACY, DIALOG
+ BEGIN
+ VERTGUIDE, 14
+ END
+
+ IDD_OPT_POPUPS, DIALOG
+ BEGIN
+ VERTGUIDE, 11
+ END
+
+ IDD_INFO_ICQ, DIALOG
+ BEGIN
+ RIGHTMARGIN, 293
+ BOTTOMMARGIN, 167
+ END
+
+ IDD_INFO_ICQ_CLIENT, DIALOG
+ BEGIN
+ LEFTMARGIN, 1
+ RIGHTMARGIN, 291
+ VERTGUIDE, 76
+ VERTGUIDE, 92
+ VERTGUIDE, 213
+ TOPMARGIN, 3
+ BOTTOMMARGIN, 168
+ HORZGUIDE, 38
+ HORZGUIDE, 45
+ END
+
+ IDD_OPT_ICQ_CLIENT_ID, DIALOG
+ BEGIN
+ RIGHTMARGIN, 291
+ END
+
+ IDD_ICQ_SRV_LIST, DIALOG
+ BEGIN
+ VERTGUIDE, 4
+ END
+
+ IDD_OPT_ICQFEATURES2, DIALOG
+ BEGIN
+ RIGHTMARGIN, 289
+ VERTGUIDE, 2
+ VERTGUIDE, 6
+ VERTGUIDE, 289
+ HORZGUIDE, 101
+ HORZGUIDE, 163
+ END
+
+ IDD_ICQ_REG_UIN, DIALOG
+ BEGIN
+ VERTGUIDE, 4
+ END
+
+ IDD_OPT_ICQ_EVENTS, DIALOG
+ BEGIN
+ RIGHTMARGIN, 289
+ VERTGUIDE, 2
+ VERTGUIDE, 6
+ VERTGUIDE, 170
+ VERTGUIDE, 225
+ VERTGUIDE, 289
+ HORZGUIDE, 11
+ HORZGUIDE, 21
+ HORZGUIDE, 31
+ HORZGUIDE, 41
+ HORZGUIDE, 51
+ HORZGUIDE, 61
+ HORZGUIDE, 71
+ HORZGUIDE, 130
+ HORZGUIDE, 140
+ END
+
+ IDD_OPT_POPUPS2, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 286
+ VERTGUIDE, 15
+ VERTGUIDE, 83
+ VERTGUIDE, 133
+ VERTGUIDE, 185
+ VERTGUIDE, 235
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 304
+ END
+
+ IDD_OPT_ASD, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 233
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 79
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_OPT_ICQ DLGINIT
+BEGIN
+ IDC_ICQSERVER, 0x403, 24, 0
+0x6f4d, 0x697a, 0x6c6c, 0x2f61, 0x2e34, 0x2030, 0x6328, 0x6d6f, 0x6170,
+0x6974, 0x6c62, 0x0065,
+ IDC_ICQSERVER, 0x403, 10, 0
+0x4d20, 0x4953, 0x2045, 0x2e35, 0x0030,
+ IDC_ICQSERVER, 0x403, 17, 0
+0x5320, 0x6e75, 0x534f, 0x3520, 0x392e, 0x7320, 0x6e75, 0x7534, "\000"
+ IDC_ICQSERVER, 0x403, 6, 0
+0x5820, 0x3131, 0x0029,
+ 0
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/icqj_s7_sss_mod/stdpackets.c b/icqj_s7_sss_mod/stdpackets.c new file mode 100644 index 0000000..4aeb598 --- /dev/null +++ b/icqj_s7_sss_mod/stdpackets.c @@ -0,0 +1,1901 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 51 $
+// Last change on : $Date: 2007-08-30 23:46:51 +0300 (Чт, 30 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+extern int gbIdleAllow;
+extern WORD wListenPort;
+extern HANDLE hsmsgrequest;
+extern const int moodXStatus[];
+
+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
+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 packServTLV5HeaderBasic(icq_packet *p, WORD wLen, DWORD ID1, DWORD ID2, WORD wCommand, plugin_guid pGuid)
+{
+ // TLV(5) header
+ packWord(p, 0x05); // Type
+ packWord(p, (WORD)(26 + wLen)); // Len
+ // TLV(5) data
+ packWord(p, wCommand); // Command
+ packLEDWord(p, ID1); // msgid1
+ packLEDWord(p, ID2); // msgid2
+ packGUID(p, pGuid); // capabilities (4 dwords)
+}
+
+
+
+static void packServTLV5HeaderMsg(icq_packet *p, WORD wLen, DWORD ID1, DWORD ID2, WORD wAckType)
+{
+ packServTLV5HeaderBasic(p, (WORD)(wLen + 10), ID1, ID2, 0, MCAP_SRV_RELAY_FMT);
+
+ packTLVWord(p, 0x0A, wAckType); // TLV: 0x0A Acktype: 1 for normal, 2 for ack
+ 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_SRV_RELAY_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 packServAdvancedReply(icq_packet *p, DWORD dwUin, char* szUid, DWORD dwID1, DWORD dwID2, WORD wCookie, WORD wLen)
+{
+ unsigned char nUidLen = getUIDLen(dwUin, szUid);
+
+ serverPacketInit(p, (WORD)(nUidLen + 23 + wLen));
+ packFNACHeaderFull(p, ICQ_MSG_FAMILY, ICQ_MSG_RESPONSE, 0, ICQ_MSG_RESPONSE<<0x10 | (wCookie & 0x7FFF));
+ packLEDWord(p, dwID1); // Msg ID part 1
+ packLEDWord(p, dwID2); // Msg ID part 2
+ packWord(p, 0x02); // Channel
+ packUIN(p, dwUin); // Contact UID
+ packWord(p, 0x03); // Msg specific formating
+}
+
+
+
+static void packServAdvancedMsgReply(icq_packet *p, DWORD dwUin, DWORD dwID1, DWORD dwID2, WORD wCookie, WORD wVersion, BYTE bMsgType, BYTE bMsgFlags, WORD wLen)
+{
+ packServAdvancedReply(p, dwUin, NULL, dwID1, dwID2, wCookie, (WORD)(wLen + 51));
+
+ packLEWord(p, 0x1B); // Unknown
+ packByte(p, (BYTE)wVersion); // 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, int bSetMood)
+{
+ icq_packet packet;
+ BYTE bXStatus = ICQGetContactXStatus(NULL);
+ char szMoodId[32];
+ WORD cbMoodId = 0;
+ WORD cbMoodData = 0;
+
+ if (bSetMood)
+ { // update mood
+ cbMoodData = 8;
+
+ if (bXStatus && moodXStatus[bXStatus-1] != -1)
+ { // prepare mood id
+ null_snprintf(szMoodId, SIZEOF(szMoodId), "icqmood%d", moodXStatus[bXStatus-1]);
+ cbMoodId = strlennull(szMoodId);
+ }
+ }
+ // Pack data in packet
+ serverPacketInit(&packet, (WORD)(18 + cbMoodId + cbMoodData));
+ 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
+ if (bSetMood)
+ { // Pack mood data
+ packWord(&packet, 0x1D); // TLV 1D
+ packWord(&packet, (WORD)(cbMoodId + 4)); // TLV length
+ packWord(&packet, 0x0E); // Item Type
+ packWord(&packet, cbMoodId); // Flags + Item Length
+ if (cbMoodId)
+ packBuffer(&packet, szMoodId, cbMoodId); // Mood
+ }
+
+ // 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, hContact, (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, hContact, (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, HANDLE hContact, const char *szMessage, int nBodyLen, WORD wPriority, message_cookie_data *pCookieData, char *szCap)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+
+
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (void*)pCookieData);
+
+ // Pack the standard header
+ packServChannel2Header(&packet, dwUin, (WORD)(nBodyLen + (szCap ? 53:11)), pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwCookie, GetProtoVersion(), (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_SendChannel2Contacts(DWORD dwUin, char *szUid, HANDLE hContact, const char *pData, WORD wDataLen, const char *pNames, WORD wNamesLen, message_cookie_data *pCookieData)
+{
+ icq_packet packet;
+ WORD wPacketLength;
+ DWORD dwCookie;
+
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, pCookieData);
+
+ wPacketLength = wDataLen + wNamesLen + 0x12;
+
+ // Pack the standard header
+ packServMsgSendHeader(&packet, dwCookie, pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwUin, szUid, 2, (WORD)(wPacketLength + ((pCookieData->nAckType == ACKTYPE_SERVER)?0x22:0x1E)));
+
+ packServTLV5HeaderBasic(&packet, wPacketLength, pCookieData->dwMsgID1, pCookieData->dwMsgID2, 0, MCAP_CONTACTS);
+
+ packTLVWord(&packet, 0x0A, 1); // TLV: 0x0A Acktype: 1 for normal, 2 for ack
+ packDWord(&packet, 0x000F0000); // TLV: 0x0F empty
+ packTLV(&packet, 0x2711, wDataLen, pData); // TLV: 0x2711 Content (Contact UIDs)
+ packTLV(&packet, 0x2712, wNamesLen, pNames);// TLV: 0x2712 Extended Content (Contact NickNames)
+
+ // Pack request ack TLV
+ if (pCookieData->nAckType == ACKTYPE_SERVER)
+ {
+ packDWord(&packet, 0x00030000); // TLV(3)
+ }
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+
+DWORD icq_SendChannel4Message(DWORD dwUin, HANDLE hContact, BYTE bMsgType, WORD wMsgLen, const char *szMsg, message_cookie_data *pCookieData)
+{
+ icq_packet packet;
+ WORD wPacketLength;
+ DWORD dwCookie;
+
+
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (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, NULL, (void*)pCookieData);
+
+ packServIcqExtensionHeader(&packet, 6, 0x07D0, (WORD)dwCookie);
+ packLEWord(&packet, META_REQUEST_SELF_INFO);
+ packLEDWord(&packet, dwLocalUIN);
+
+ sendServPacket(&packet);
+}
+
+
+
+void sendUserInfoAutoRequest(HANDLE hContact, 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, hContact, (void*)pCookieData);
+
+ packServIcqExtensionHeader(&packet, 6, 0x07D0, (WORD)dwCookie);
+ packLEWord(&packet, META_REQUEST_SHORT_INFO);
+ packLEDWord(&packet, dwUin);
+
+ sendServPacket(&packet);
+}
+
+
+
+DWORD icq_sendGetInfoServ(HANDLE hContact, DWORD dwUin, int bMinimal, int bManual)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ fam15_cookie_data *pCookieData = NULL;
+
+ if (IsServerOverRate(ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQ, bManual ? RML_IDLE_10 : RML_IDLE_50))
+ return 0;
+
+ pCookieData = SAFE_MALLOC(sizeof(fam15_cookie_data));
+ dwCookie = AllocateCookie(CKT_FAMILYSPECIAL, 0, hContact, (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);
+
+ if (IsServerOverRate(ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, RML_IDLE_10))
+ return 0;
+
+ pCookieData = SAFE_MALLOC(sizeof(fam15_cookie_data));
+ dwCookie = AllocateCookie(CKT_FAMILYSPECIAL, ICQ_LOCATION_REQ_USER_INFO, hContact, (void*)pCookieData);
+ pCookieData->bRequestType = REQUESTTYPE_PROFILE;
+
+ 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(HANDLE hContact, DWORD dwUin, int type, WORD wVersion)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ message_cookie_data *pCookieData = NULL;
+
+ if (IsServerOverRate(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, RML_IDLE_30))
+ return 0;
+
+ pCookieData = CreateMessageCookie(MTYPE_AUTOAWAY, (BYTE)type);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (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_sendGetAwayMsgServExt(HANDLE hContact, DWORD dwUin, int type, WORD wVersion)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ message_cookie_data *pCookieData = NULL;
+
+ if (IsServerOverRate(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, RML_IDLE_30))
+ return 0;
+
+ pCookieData = CreateMessageCookie(MTYPE_AUTOAWAY, (BYTE)type);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (void*)pCookieData);
+
+/* serverPacketInit(&packet, (WORD)(13 + getUINLen(dwUin)));
+ packFNACHeaderFull(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, 0, (WORD)dwCookie);
+ packWord(&packet, 0x03);
+ packUIN(&packet, dwUin); */
+ packServMsgSendHeader(&packet, dwCookie, pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwUin, NULL, 2, 182);
+
+ // TLV(5) header
+ packServTLV5HeaderMsg(&packet, 142, pCookieData->dwMsgID1, pCookieData->dwMsgID2, 1);
+
+ // TLV(0x2711) header
+ packServTLV2711Header(&packet, (WORD)dwCookie, wVersion, MTYPE_PLUGIN, 0, 0, 0x100, 87);
+ //
+ packLEWord(&packet, 0); // Empty msg
+
+ packPluginTypeId(&packet, type);
+
+ packLEDWord(&packet, 0x15);
+ packLEDWord(&packet, 0);
+ packLEDWord(&packet, 0x0D);
+ packBuffer(&packet, "text/x-aolrtf", 0x0D);
+
+ // Send the monster
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+//away-message request without beeing detected :) by [sin]
+DWORD icq_sendGetStealthAwayMsgServ(HANDLE hContact, DWORD dwUin, int type, WORD wVersion)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ message_cookie_data *pCookieData = NULL;
+
+ if (IsServerOverRate(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, RML_IDLE_30))
+ return 0;
+
+ pCookieData = CreateMessageCookie(MTYPE_AUTOAWAY, (BYTE)type);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (void*)pCookieData);
+
+ serverPacketInit(&packet, (WORD)(13 + getUINLen(dwUin)));
+ packFNACHeaderFull(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, 0, (WORD)dwCookie);
+ packWord(&packet, 0x03);
+ packUIN(&packet, dwUin);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD icq_sendGetAimAwayMsgServ(HANDLE hContact, 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, hContact, (void*)pCookieData);
+
+ serverPacketInit(&packet, (WORD)(13 + bUIDlen));
+ packFNACHeaderFull(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, 0, dwCookie);
+ packWord(&packet, 0x03);
+ packUID(&packet, 0, szUID);
+
+ 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
+ packServTLV5HeaderMsg(&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
+ packServTLV5HeaderMsg(&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
+ packServTLV5HeaderMsg(&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;
+ WORD wReplyVersion = GetProtoVersion();
+
+
+ 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)
+ {
+ pszMsg = (char*)*szMsg;
+ wReplyVersion = 9;
+ }
+ 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, wReplyVersion, 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, ICQ_VERSION, bMsgType, bMsgFlags, 11);
+ packEmptyMsg(&packet); // Status message
+ packMsgColorInfo(&packet);
+
+ sendServPacket(&packet);
+}
+
+
+
+void icq_sendContactsAck(DWORD dwUin, char *szUid, DWORD dwMsgID1, DWORD dwMsgID2)
+{
+ icq_packet packet;
+
+ packServMsgSendHeader(&packet, 0, dwMsgID1, dwMsgID2, dwUin, szUid, 2, 0x1E);
+ packServTLV5HeaderBasic(&packet, 0, dwMsgID1, dwMsgID2, 2, MCAP_CONTACTS);
+
+ 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);
+ }
+
+ // 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
+ packServTLV5HeaderMsg(&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, GetProtoVersion(), 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);
+
+ packServTLV5HeaderBasic(&packet, 0x29, pCookie->dwMsgID1, pCookie->dwMsgID2, 0, MCAP_REVERSE_DC_REQ);
+
+ packTLVWord(&packet, 0x0A, 1); // TLV: 0x0A Acktype: 1 for normal, 2 for ack
+ 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);
+}
+
+
+// OSCAR file-transfer packets starts here
+//
+void oft_sendFileRequest(DWORD dwUin, char *szUid, oscar_filetransfer* ft, char* pszFiles, DWORD dwLocalInternalIP)
+{
+ icq_packet packet;
+ char *szCoolStr;
+ WORD wDataLen;
+
+ szCoolStr = (char*)_alloca(strlennull(ft->szDescription)+strlennull(pszFiles) + 160);
+ sprintf(szCoolStr, "<ICQ_COOL_FT><FS>%s</FS><S>%I64u</S><SID>1</SID><DESC>%s</DESC></ICQ_COOL_FT>", pszFiles, ft->qwTotalSize, ft->szDescription);
+ szCoolStr = MangleXml(szCoolStr, strlennull(szCoolStr));
+
+ wDataLen = 93 + strlennull(szCoolStr) + strlennull(pszFiles);
+ if (ft->bUseProxy) wDataLen += 4;
+
+ packServMsgSendHeader(&packet, ft->dwCookie, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, dwUin, szUid, 2, (WORD)(wDataLen + 0x1E));
+ packServTLV5HeaderBasic(&packet, wDataLen, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, 0, MCAP_FILE_TRANSFER);
+
+ packTLVWord(&packet, 0x0A, ++ft->wReqNum); // Request sequence
+ packDWord(&packet, 0x000F0000); // Unknown
+ packTLV(&packet, 0x0D, 5, "utf-8"); // Charset
+ packTLV(&packet, 0x0C, (WORD)strlennull(szCoolStr), szCoolStr); // User message (CoolData XML)
+ SAFE_FREE(&szCoolStr);
+ if (ft->bUseProxy)
+ {
+ packTLVDWord(&packet, 0x02, ft->dwProxyIP); // Proxy IP
+ packTLVDWord(&packet, 0x16, ft->dwProxyIP ^ 0x0FFFFFFFF); // Proxy IP check
+ }
+ else
+ {
+ packTLVDWord(&packet, 0x02, dwLocalInternalIP);
+ packTLVDWord(&packet, 0x16, dwLocalInternalIP ^ 0x0FFFFFFFF);
+ }
+ packTLVDWord(&packet, 0x03, dwLocalInternalIP); // Client IP
+ if (ft->bUseProxy)
+ {
+ packTLVWord(&packet, 0x05, ft->wRemotePort);
+ packTLVWord(&packet, 0x17, (WORD)(ft->wRemotePort ^ 0x0FFFF));
+ packDWord(&packet, 0x00100000); // Proxy flag
+ }
+ else
+ {
+ oscar_listener *pListener = (oscar_listener*)ft->listener;
+
+ packTLVWord(&packet, 0x05, pListener->wPort);
+ packTLVWord(&packet, 0x15, (WORD)((pListener->wPort) ^ 0x0FFFF));
+ }
+ { // TLV(0x2711)
+ packWord(&packet, 0x2711);
+ packWord(&packet, (WORD)(9 + strlennull(pszFiles)));
+ packWord(&packet, (WORD)(ft->wFilesCount == 1 ? 1 : 2));
+ packWord(&packet, ft->wFilesCount);
+ packDWord(&packet, (DWORD)ft->qwTotalSize);
+ packBuffer(&packet, pszFiles, (WORD)(strlennull(pszFiles) + 1));
+ }
+ packTLV(&packet, 0x2712, 5, "utf-8");
+ { // TLV(0x2713)
+ packWord(&packet, 0x2713);
+ packWord(&packet, 8);
+ packQWord(&packet, ft->qwTotalSize);
+ }
+
+ sendServPacket(&packet); // Send the monster
+}
+
+
+
+static void oft_sendFileReply(DWORD dwUin, char *szUid, oscar_filetransfer* ft, WORD wResult)
+{
+ icq_packet packet;
+
+ packServMsgSendHeader(&packet, 0, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, dwUin, szUid, 2, 0x1E);
+ packServTLV5HeaderBasic(&packet, 0, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, wResult, MCAP_FILE_TRANSFER);
+
+ sendServPacket(&packet);
+}
+
+
+
+void oft_sendFileAccept(DWORD dwUin, char *szUid, oscar_filetransfer* ft)
+{
+ oft_sendFileReply(dwUin, szUid, ft, 0x02);
+}
+
+
+
+void oft_sendFileResponse(DWORD dwUin, char *szUid, oscar_filetransfer* ft, WORD wResponse)
+{
+ icq_packet packet;
+
+ packServAdvancedReply(&packet, dwUin, szUid, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, 0, 4);
+ packWord(&packet, 0x02); // Length of following data
+ packWord(&packet, wResponse); // Response code
+
+ sendServPacket(&packet);
+}
+
+
+
+void oft_sendFileDeny(DWORD dwUin, char *szUid, oscar_filetransfer* ft)
+{
+ if (dwUin)
+ { // ICQ clients uses special deny file transfer
+ oft_sendFileResponse(dwUin, szUid, ft, 0x01);
+ }
+ else
+ oft_sendFileReply(dwUin, szUid, ft, 0x01);
+}
+
+
+
+void oft_sendFileCancel(DWORD dwUin, char *szUid, oscar_filetransfer* ft)
+{
+ oft_sendFileReply(dwUin, szUid, ft, 0x01);
+}
+
+
+
+void oft_sendFileRedirect(DWORD dwUin, char *szUid, oscar_filetransfer* ft, DWORD dwIP, WORD wPort, int bProxy)
+{
+ icq_packet packet;
+
+ packServMsgSendHeader(&packet, 0, ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, dwUin, szUid, 2, (WORD)(bProxy ? 0x4a : 0x4e));
+ packServTLV5HeaderBasic(&packet, (WORD)(bProxy ? 0x2C : 0x30), ft->pMessage.dwMsgID1, ft->pMessage.dwMsgID2, 0, MCAP_FILE_TRANSFER);
+ // Connection point data
+ packTLVWord(&packet, 0x0A, ++ft->wReqNum); // Ack Type
+ packTLVWord(&packet, 0x14, 0x0A); // Unknown ?
+ packTLVDWord(&packet, 0x02, dwIP); // Internal IP / Proxy IP
+ packTLVDWord(&packet, 0x16, dwIP ^ 0x0FFFFFFFF); // IP Check ?
+ if (!bProxy)
+ packTLVDWord(&packet, 0x03, dwIP);
+ packTLVWord(&packet, 0x05, wPort); // Listening Port
+ packTLVWord(&packet, 0x17, (WORD)(wPort ^ 0x0FFFF)); // Port Check ?
+ if (bProxy)
+ packDWord(&packet, 0x00100000); // Proxy Flag
+
+ sendServPacket(&packet);
+}
+
+void SendtZer(HANDLE hContact, DWORD dwUin, char * sztZId, char * sztZName, char * sztZUrl) {
+ icq_packet packet;
+ WORD wCoreLen;
+ DWORD dwCookie;
+
+ int nBodyLen;
+ message_cookie_data* pCookieData;
+
+ char * szBody = (char *) malloc(66 + strlen(sztZId) + strlen(sztZName) + strlen(sztZUrl) + getUINLen(dwUin) + 1);
+ sprintf(szBody, "<tzer id=\"%s\" name=\"%s\" url=\"%s\" preview=\"0\" freeData=\"preview=0;uin=%lu\"/>", sztZId, sztZName, sztZUrl, dwUin);
+ nBodyLen = strlen(szBody);
+
+ pCookieData = CreateMessageCookie(MTYPE_TZER_MESSAGE, ACKTYPE_CLIENT);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (void*)pCookieData);
+
+
+ wCoreLen = 11 + getPluginTypeIdLen(pCookieData->bMessageType) + nBodyLen;
+
+
+ packServMsgSendHeader(&packet, dwCookie, pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwUin, NULL, 2, (WORD)(/*99*/99 + wCoreLen));
+
+ packServTLV5HeaderMsg(&packet, (WORD)(55 + wCoreLen), pCookieData->dwMsgID1, pCookieData->dwMsgID2, 1); //36
+
+ packServTLV2711Header(&packet, (WORD)dwCookie, ICQ_VERSION, MTYPE_PLUGIN, 0, 0, 0x100, wCoreLen); //55
+
+ packEmptyMsg(&packet); //3
+
+ packPluginTypeId(&packet, pCookieData->bMessageType);
+
+ packLEDWord(&packet, nBodyLen + 4); //4
+ packLEDWord(&packet, nBodyLen); //4
+ packBuffer(&packet, szBody, (WORD)nBodyLen);
+
+ packDWord(&packet, 0x00030000); // TLV(3)
+
+ sendServPacket(&packet);
+
+}
+
+DWORD icq_sendGetLocationInfo(HANDLE hContact, DWORD dwUIN, char *szUID)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ BYTE bUIDlen = getUIDLen(dwUIN, szUID);
+
+ dwCookie = AllocateCookie(CKT_CHECKSPAMBOT, ICQ_LOCATION_QRY_USER_INFO, hContact, NULL);
+
+ serverPacketInit(&packet, (WORD)(15 + bUIDlen));
+ packFNACHeaderFull(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_QRY_USER_INFO, 0, dwCookie);
+ packDWord(&packet, 0x04);
+ packUID(&packet, dwUIN, szUID);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
diff --git a/icqj_s7_sss_mod/stdpackets.h b/icqj_s7_sss_mod/stdpackets.h new file mode 100644 index 0000000..2f09419 --- /dev/null +++ b/icqj_s7_sss_mod/stdpackets.h @@ -0,0 +1,128 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 51 $
+// Last change on : $Date: 2007-08-30 23:46:51 +0300 (Чт, 30 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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, int bSetMood);
+DWORD icq_sendGetInfoServ(HANDLE, DWORD, int, int);
+DWORD icq_sendGetAimProfileServ(HANDLE hContact, char *szUid);
+DWORD icq_sendGetAwayMsgServ(HANDLE, DWORD, int, WORD);
+DWORD icq_sendGetStealthAwayMsgServ(HANDLE hContact, DWORD dwUin, int type, WORD wVersion);
+DWORD icq_sendGetAwayMsgServExt(HANDLE hContact, DWORD dwUin, int type, WORD wVersion);
+DWORD icq_sendGetAimAwayMsgServ(HANDLE hContact, char *szUID, int type);
+void icq_sendSetAimAwayMsgServ(char *szMsg);
+
+DWORD icq_sendGetLocationInfo(HANDLE hContact, DWORD dwUIN, char *szUID);
+
+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 **);
+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(HANDLE hContact, 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, HANDLE hContact, const char *szMessage, int nBodyLength, WORD wPriority, message_cookie_data *pCookieData, char *szCap);
+DWORD icq_SendChannel2Contacts(DWORD dwUin, char *szUid, HANDLE hContact, const char *pData, WORD wDataLen, const char *pNames, WORD wNamesLen, message_cookie_data *pCookieData);
+DWORD icq_SendChannel4Message(DWORD dwUin, HANDLE hContact, BYTE bMsgType, WORD wMsgLen, const char *szMsg, message_cookie_data *pCookieData);
+
+void icq_sendAdvancedMsgAck(DWORD, DWORD, DWORD, WORD, BYTE, BYTE);
+void icq_sendContactsAck(DWORD dwUin, char *szUid, DWORD dwMsgID1, DWORD dwMsgID2);
+
+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);
+
+void oft_sendFileRequest(DWORD dwUin, char *szUid, oscar_filetransfer* ft, char* pszFiles, DWORD dwLocalInternalIP);
+void oft_sendFileAccept(DWORD dwUin, char *szUid, oscar_filetransfer* ft);
+void oft_sendFileDeny(DWORD dwUin, char *szUid, oscar_filetransfer* ft);
+void oft_sendFileCancel(DWORD dwUin, char *szUid, oscar_filetransfer* ft);
+void oft_sendFileResponse(DWORD dwUin, char *szUid, oscar_filetransfer* ft, WORD wResponse);
+void oft_sendFileRedirect(DWORD dwUin, char *szUid, oscar_filetransfer* ft, DWORD dwIP, WORD wPort, int bProxy);
+
+void SendtZer(HANDLE hContact, DWORD dwUin, char * sztZId, char * sztZName, char * sztZUrl);
+
+void packServMsgSendHeader(icq_packet *p, DWORD dwSequence, DWORD dwID1, DWORD dwID2, DWORD dwUin, char *szUID, WORD wFmt, WORD wLen);
+void packEmptyMsg(icq_packet *packet);
+
+#endif /* __STDPACKETS_H */
diff --git a/icqj_s7_sss_mod/tlv.c b/icqj_s7_sss_mod/tlv.c new file mode 100644 index 0000000..18adff7 --- /dev/null +++ b/icqj_s7_sss_mod/tlv.c @@ -0,0 +1,223 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/tlv.h b/icqj_s7_sss_mod/tlv.h new file mode 100644 index 0000000..4dc4920 --- /dev/null +++ b/icqj_s7_sss_mod/tlv.h @@ -0,0 +1,69 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
+//
+// 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$
+// Revision : $Revision: 36 $
+// Last change on : $Date: 2007-08-05 03:45:10 +0300 (Вс, 05 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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_s7_sss_mod/utilities.c b/icqj_s7_sss_mod/utilities.c new file mode 100644 index 0000000..c6cd863 --- /dev/null +++ b/icqj_s7_sss_mod/utilities.c @@ -0,0 +1,2909 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright 2006,2007,2008 [sss], chaos.persei, [sin], Faith Healer, Thief, Angeli-Ka, nullbie
+// Copyright 2008 [sss], chaos.persei, nullbie, baloo, jarvis
+//
+// 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 : $HeadURL: https://icqjplusmod.googlecode.com/svn/trunk/utilities.c $
+// Revision : $Revision: 51 $
+// Last change on : $Date: 2007-08-30 23:46:51 +0300 (Чт, 30 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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 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)
+{ // return miranda status description in utf-8, use unicode service is possible
+ return mtchar_to_utf8((TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, mirandaStatus, gbUnicodeCore ? GCMDF_UNICODE : 0));
+}
+
+
+
+char**MirandaStatusToAwayMsg(int nStatus)
+{
+ switch (nStatus)
+ {
+
+ case ID_STATUS_ONLINE:
+ return &modeMsgs.szOnline;
+ break;
+
+ 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_AUTOONLINE:
+ return ID_STATUS_ONLINE;
+
+ 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 *)SAFE_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*)SAFE_REALLOC(gateways, sizeof(gateway_index) * gatewayCount);
+
+ // Gateway found, exit loop
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+}
+
+
+
+void AddToSpammerList(DWORD dwUIN)
+{
+ EnterCriticalSection(&cookieMutex);
+
+ spammerList = (DWORD *)SAFE_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 *)SAFE_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);
+ }
+ if (ICQGetContactSettingByte(NULL, "KillSpambots", DEFAULT_KILLSPAM_ENABLED))
+ icq_sendGetLocationInfo(hContact, uin, NULL);
+ }
+ 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);
+ }
+ if (ICQGetContactSettingByte(NULL, "KillSpambots", DEFAULT_KILLSPAM_ENABLED))
+ icq_sendGetLocationInfo(hContact, 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>");
+
+ return mtchar_to_utf8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, gbUnicodeCore ? GCDNF_UNICODE : 0));
+}
+
+
+
+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;
+}
+
+
+
+size_t __fastcall null_strcut(char *string, size_t maxlen)
+{ // limit the string to max length (null & utf-8 strings ready)
+ size_t len = strlennull(string);
+
+ if (len < maxlen)
+ return len;
+
+ len = maxlen;
+
+ if (UTF8_IsValid(string)) // handle utf-8 string
+ { // find the first byte of possible multi-byte character
+ while ((string[len] & 0xc0) == 0x80) len--;
+ }
+ // simply cut the string
+ string[len] = '\0';
+
+ return len;
+}
+
+
+
+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]);
+ } // otherwise do not change port
+
+ 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);
+}
+
+char* ApplyEncoding(const char *string, const char* pszEncoding)
+{ // decode encoding to Utf-8
+ if (string && pszEncoding)
+ { // we do only encodings known to icq5.1 // TODO: check if this is enough
+ if (!strnicmp(pszEncoding, "utf-8", 5))
+ { // it is utf-8 encoded
+ return null_strdup(string);
+ }
+ else if (!strnicmp(pszEncoding, "unicode-2-0", 11))
+ { // it is UCS-2 encoded
+ int wLen = wcslen((WCHAR*)string) + 1;
+ WCHAR *szStr = (WCHAR*)_alloca(wLen*2);
+ char *tmp = (char*)string;
+
+ unpackWideString(&tmp, szStr, (WORD)(wLen*2));
+
+ return make_utf8_string(szStr);
+ }
+ else if (!strnicmp(pszEncoding, "iso-8859-1", 10))
+ { // we use "Latin I" instead - it does the job
+ return ansi_to_utf8_codepage(string, 1252);
+ }
+ }
+ if (string)
+ { // consider it CP_ACP
+ return ansi_to_utf8(string);
+ }
+
+ return NULL;
+}
+
+
+
+void ResetSettingsOnListReload()
+{
+ HANDLE hContact;
+
+ // Reset a bunch of session specific settings
+ ICQWriteContactSettingWord(NULL, "SrvVisibilityID", 0);
+ ICQWriteContactSettingWord(NULL, "SrvAvatarID", 0);
+ ICQWriteContactSettingWord(NULL, "SrvPhotoID", 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;
+
+ // 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);
+ ICQWriteContactSettingByte(hContact, "TemporaryVisible", 0);
+
+ // 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);
+ }
+ ICQWriteContactSettingByte(hContact, "DCStatus", 0);
+
+ 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;
+}
+
+
+
+static DWORD __stdcall 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 0;
+}
+
+
+
+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);
+
+ ICQCreateThread(icq_ProtocolAckThread, 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, MAX_PATH);
+ 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, MAX_PATH);
+ 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)
+{
+ DWORD uin = DBGetContactSettingDword(hContact,gpszICQProtoName,"UIN",0);
+ // 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;
+ }
+ }
+
+ //Don't send any status message reply, if on
+ if(bNoStatusReply)
+ return FALSE;
+
+ // Dont send messages to people you are hiding from
+ if (hContact != INVALID_HANDLE_VALUE &&
+ ICQGetContactSettingWord(hContact, "ApparentMode", 0) == ID_STATUS_OFFLINE)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact = hContact;
+ chk.dbeventflag=DBEF_READ;
+ chk.popup=chk.logtofile=chk.historyevent=TRUE;
+ chk.popuptype=POPTYPE_VIS;
+ chk.icqeventtype=ICQEVENTTYPE_CHECK_STATUS;
+ chk.dwUin = uin;
+ chk.msg = "contact which you are invisible for requests your status message";
+ CheckContact(chk);
+ 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))
+ {
+ CHECKCONTACT chk = {0};
+ chk.dwUin=uin;
+ chk.hContact=hContact;
+ chk.dbeventflag=DBEF_READ;
+ chk.popup=chk.logtofile=chk.historyevent=TRUE;
+ chk.icqeventtype=ICQEVENTTYPE_CHECK_STATUS;
+ chk.popuptype=POPTYPE_INFO_REQUEST;
+ chk.msg="requested wrong status type";
+ CheckContact(chk);
+ return FALSE;
+ }
+
+ if (hContact != INVALID_HANDLE_VALUE && gnCurrentStatus==ID_STATUS_INVISIBLE)
+ {
+ if (!ICQGetContactSettingByte(hContact, "TemporaryVisible", 0))
+ { // Allow request to temporary visible contacts
+ return FALSE;
+ }
+ }
+
+ {
+ CHECKCONTACT chk = {0};
+ chk.dwUin = uin;
+ chk.hContact=hContact;
+ chk.PSD = -1;
+ CheckContact(chk);
+ }
+ // 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 = NULL;
+
+ if (size)
+ {
+ p = malloc(size);
+
+ if (p)
+ ZeroMemory(p, size);
+ }
+ return p;
+}
+
+
+
+void* __fastcall SAFE_REALLOC(void* p, size_t size)
+{
+ if (p)
+ {
+ return realloc(p, size);
+ }
+ else
+ return SAFE_MALLOC(size);
+}
+
+
+
+HANDLE NetLib_OpenConnection(HANDLE hUser, const char* szIdent, NETLIBOPENCONNECTION* nloc)
+{
+ HANDLE hConnection;
+
+ Netlib_Logf(hUser, "%sConnecting to %s:%u", szIdent?szIdent:"", nloc->szHost, nloc->wPort);
+
+ nloc->cbSize = sizeof(NETLIBOPENCONNECTION);
+ nloc->flags |= NLOCF_V2;
+
+ 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;
+}
+
+
+
+HANDLE NetLib_BindPort(NETLIBNEWCONNECTIONPROC_V2 pFunc, void* lParam, WORD* pwPort, DWORD* pdwIntIP)
+{
+ NETLIBBIND nlb = {0};
+ HANDLE hBoundPort;
+
+ nlb.cbSize = sizeof(NETLIBBIND);
+ nlb.pfnNewConnectionV2 = pFunc;
+ nlb.pExtra = lParam;
+ SetLastError(ERROR_INVALID_PARAMETER); // this must be here - NetLib does not set any error :((
+ hBoundPort = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)ghDirectNetlibUser, (LPARAM)&nlb);
+ if (!hBoundPort && (GetLastError() == ERROR_INVALID_PARAMETER))
+ { // this ensures older Miranda also can bind a port for a dc - pre 0.6
+ nlb.cbSize = NETLIBBIND_SIZEOF_V2;
+ hBoundPort = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)ghDirectNetlibUser, (LPARAM)&nlb);
+ }
+ if (pwPort) *pwPort = nlb.wPort;
+ if (pdwIntIP) *pdwIntIP = nlb.dwInternalIP;
+
+ return hBoundPort;
+}
+
+
+
+void NetLib_CloseConnection(HANDLE *hConnection, int bServerConn)
+{
+ if (*hConnection)
+ {
+ int sck = CallService(MS_NETLIB_GETSOCKET, (WPARAM)*hConnection, (LPARAM)0);
+
+ if (sck!=INVALID_SOCKET) shutdown(sck, 2); // close gracefully
+
+ NetLib_SafeCloseHandle(hConnection);
+
+ if (bServerConn)
+ FreeGatewayIndex(*hConnection);
+ }
+}
+
+
+
+void NetLib_SafeCloseHandle(HANDLE *hConnection)
+{
+ if (*hConnection)
+ {
+ Netlib_CloseHandle(*hConnection);
+ *hConnection = NULL;
+ }
+}
+
+
+
+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);
+ }
+
+ { // we can use unicode translate (0.5+)
+ WCHAR* usrc = make_unicode_string(src);
+
+ szRes = make_utf8_string(TranslateW(usrc));
+
+ SAFE_FREE(&usrc);
+ }
+ return szRes;
+}
+
+
+
+char* __fastcall ICQTranslateUtfStatic(const char* src, char* buf, size_t bufsize)
+{ // this takes UTF-8 strings only!!!
+ if (strlennull(src))
+ { // we can use unicode translate (0.5+)
+ WCHAR* usrc = make_unicode_string(src);
+
+ make_utf8_string_static(TranslateW(usrc), buf, bufsize);
+
+ SAFE_FREE(&usrc);
+ }
+ else
+ buf[0] = '\0';
+
+ return buf;
+}
+
+
+
+HANDLE ICQCreateThreadEx(pThreadFuncEx AFunc, void* arg, DWORD* pThreadID)
+{
+ FORK_THREADEX_PARAMS params;
+ DWORD dwThreadId;
+ HANDLE hThread;
+
+ params.pFunc = AFunc;
+ params.arg = arg;
+ params.iStackSize = 0;
+ params.threadID = &dwThreadId;
+ hThread = (HANDLE)CallService(MS_SYSTEM_FORK_THREAD_EX, 0, (LPARAM)¶ms);
+ if (pThreadID)
+ *pThreadID = dwThreadId;
+
+ return hThread;
+}
+
+
+
+void ICQCreateThread(pThreadFuncEx AFunc, void* arg)
+{
+ HANDLE hThread = ICQCreateThreadEx(AFunc, arg, NULL);
+
+ CloseHandle(hThread);
+}
+
+
+
+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;
+}
+
+
+
+int IsValidRelativePath(const char *filename)
+{
+ if (strstr(filename, "..\\") || strstr(filename, "../") ||
+ strstr(filename, ":\\") || strstr(filename, ":/") ||
+ filename[0] == '\\' || filename[0] == '/')
+ return 0; // Contains malicious chars, Failure
+
+ return 1; // Success
+}
+
+
+
+char* ExtractFileName(const char *fullname)
+{
+ char* szFileName;
+
+ if (((szFileName = strrchr(fullname, '\\')) == NULL) && ((szFileName = strrchr(fullname, '/')) == NULL))
+ { // already is only filename
+ return (char*)fullname;
+ }
+ szFileName++; // skip backslash
+
+ return szFileName;
+}
+
+
+
+char* FileNameToUtf(const char *filename)
+{
+ if (gbUnicodeAPI)
+ { // reasonable only on NT systems
+ HINSTANCE hKernel;
+ DWORD (CALLBACK *RealGetLongPathName)(LPCWSTR, LPWSTR, DWORD);
+
+ hKernel = GetModuleHandle("KERNEL32");
+ *(FARPROC *)&RealGetLongPathName = GetProcAddress(hKernel, "GetLongPathNameW");
+
+ if (RealGetLongPathName)
+ { // the function is available (it is not on old NT systems)
+ WCHAR *unicode, *usFileName = NULL;
+ int wchars;
+
+ wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, filename,
+ strlennull(filename), NULL, 0);
+
+ unicode = (WCHAR*)_alloca((wchars + 1) * sizeof(WCHAR));
+ unicode[wchars] = 0;
+
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, filename,
+ strlennull(filename), unicode, wchars);
+
+ wchars = RealGetLongPathName(unicode, usFileName, 0);
+ usFileName = (WCHAR*)_alloca((wchars + 1) * sizeof(WCHAR));
+ RealGetLongPathName(unicode, usFileName, wchars);
+
+ return make_utf8_string(usFileName);
+ }
+ else
+ return ansi_to_utf8(filename);
+ }
+ else
+ return ansi_to_utf8(filename);
+}
+
+
+
+int FileStatUtf(const char *path, struct _stati64 *buffer)
+{
+ int wRes = -1;
+
+ if (gbUnicodeAPI)
+ {
+ WCHAR* usPath = make_unicode_string(path);
+
+ wRes = _wstati64(usPath, buffer);
+ SAFE_FREE(&usPath);
+ }
+ else
+ {
+ int size = strlennull(path)+2;
+ char* szAnsiPath = (char*)_alloca(size);
+
+ if (utf8_decode_static(path, szAnsiPath, size))
+ wRes = _stati64(szAnsiPath, buffer);
+ }
+ return wRes;
+}
+
+
+
+int MakeDirUtf(const char *dir)
+{
+ int wRes = -1;
+ char *szLast;
+
+ if (gbUnicodeAPI)
+ {
+ WCHAR* usDir = make_unicode_string(dir);
+ // _wmkdir can created only one dir at once
+ wRes = _wmkdir(usDir);
+ // check if dir not already existed - return success if yes
+ if (wRes == -1 && errno == 17 /* EEXIST */)
+ wRes = 0;
+ else if (wRes && errno == 2 /* ENOENT */)
+ { // failed, try one directory less first
+ szLast = strrchr(dir, '\\');
+ if (!szLast) szLast = strrchr(dir, '/');
+ if (szLast)
+ {
+ char cOld = *szLast;
+
+ *szLast = '\0';
+ if (!MakeDirUtf(dir))
+ wRes = _wmkdir(usDir);
+ *szLast = cOld;
+ }
+ }
+ SAFE_FREE(&usDir);
+ }
+ else
+ {
+ int size = strlennull(dir)+2;
+ char* szAnsiDir = (char*)_alloca(size);
+
+ if (utf8_decode_static(dir, szAnsiDir, size))
+ { // _mkdir can create only one dir at once
+ wRes = _mkdir(szAnsiDir);
+ // check if dir not already existed - return success if yes
+ if (wRes == -1 && errno == 17 /* EEXIST */)
+ wRes = 0;
+ else if (wRes && errno == 2 /* ENOENT */)
+ { // failed, try one directory less first
+ szLast = strrchr(dir, '\\');
+ if (!szLast) szLast = strrchr(dir, '/');
+ if (szLast)
+ {
+ char cOld = *szLast;
+
+ *szLast = '\0';
+ if (!MakeDirUtf(dir))
+ wRes = _mkdir(szAnsiDir);
+ *szLast = cOld;
+ }
+ }
+ }
+ }
+ return wRes;
+}
+
+
+
+int OpenFileUtf(const char *filename, int oflag, int pmode)
+{
+ int hFile = -1;
+
+ if (gbUnicodeAPI)
+ {
+ WCHAR* usFile = make_unicode_string(filename);
+
+ hFile = _wopen(usFile, oflag, pmode);
+ SAFE_FREE(&usFile);
+ }
+ else
+ {
+ int size = strlennull(filename)+2;
+ char* szAnsiFile = (char*)_alloca(size);
+
+ if (utf8_decode_static(filename, szAnsiFile, size))
+ hFile = _open(szAnsiFile, oflag, pmode);
+ }
+ return hFile;
+}
+
+
+
+WCHAR *GetWindowTextUcs(HWND hWnd)
+{
+ WCHAR *utext;
+
+ if (gbUnicodeAPI)
+ {
+ int nLen = GetWindowTextLengthW(hWnd);
+
+ utext = (WCHAR*)SAFE_MALLOC((nLen+2)*sizeof(WCHAR));
+ 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*)SAFE_MALLOC((wchars + 1)*sizeof(WCHAR));
+
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text,
+ strlennull(text), utext, wchars);
+ }
+ return utext;
+}
+
+
+
+void SetWindowTextUcs(HWND hWnd, WCHAR *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)
+{
+ TCHAR* szText;
+
+ if (gbUnicodeAPI)
+ {
+ int nLen = GetWindowTextLengthW(hWnd);
+
+ szText = (TCHAR*)_alloca((nLen+2)*sizeof(WCHAR));
+ GetWindowTextW(hWnd, (WCHAR*)szText, nLen + 1);
+ }
+ else
+ {
+ int nLen = GetWindowTextLengthA(hWnd);
+
+ szText = (TCHAR*)_alloca(nLen+2);
+ GetWindowTextA(hWnd, (char*)szText, nLen + 1);
+ }
+ return tchar_to_utf8(szText);
+}
+
+
+
+char* GetDlgItemTextUtf(HWND hwndDlg, int iItem)
+{
+ return GetWindowTextUtf(GetDlgItem(hwndDlg, iItem));
+}
+
+
+
+void SetWindowTextUtf(HWND hWnd, const char* szText)
+{
+ if (gbUnicodeAPI)
+ {
+ WCHAR* 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, MAX_PATH);
+ int item = -1;
+
+ if (gbUnicodeAPI)
+ {
+ WCHAR *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);
+
+ if (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 *text = make_unicode_string(ICQTranslateUtfStatic(szText, str, 1024));
+ WCHAR *caption = make_unicode_string(ICQTranslateUtfStatic(szCaption, cap, MAX_PATH));
+ 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, 1024), text, size);
+ utf8_decode_static(ICQTranslateUtfStatic(szCaption, cap, MAX_PATH), 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
+
+}
+
+/*BOOL invis_for(DWORD dwUin, HANDLE hContact) //this function checking are you invisible for hContact or dwUin, need optimization...
+{
+ WORD wApparent = DBGetContactSettingWord(hContact,gpszICQProtoName,"ApparentMode",0);
+
+ if(bVisibility==0x02)
+ return TRUE;
+ if (dwUin && !hContact)
+ hContact=HContactFromUIN(dwUin,0);
+ if (!hContact)
+ {
+ return TRUE;
+ }
+ if(DBGetContactSettingByte(hContact, "CList", "NotOnList", 0)&&bVisibility!=0x01||bVisibility!=0x04)
+ return TRUE;
+ if((wApparent==ID_STATUS_OFFLINE||gnCurrentStatus == ID_STATUS_INVISIBLE&&bVisibility!=0x04&&wApparent!=ID_STATUS_ONLINE)&&bVisibility!=0x01)
+ return TRUE;
+ return FALSE;
+} */
+
+
+
+BOOL invis_for(DWORD dwUin, HANDLE hContact) //this function checking are you invisible for hContact or dwUin, need optimization... (modified by Bio)
+{
+ WORD wApparent;
+
+ // Block all users from seeing you
+// if ( bVisibility==0x02 || !dwUin )
+ if ( bVisibility==0x02) //we support AIM which do not use UIN's
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+
+ // Allow all users to see you
+ if ( bVisibility == 0x01 )
+ return FALSE;
+
+ if ( !hContact ) {
+ hContact=HContactFromUIN(dwUin,0);
+ if (!hContact)
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+ }
+
+ if ( DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) )
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+
+ // Allow only users in the buddy list to see you
+ if ( bVisibility == 0x05 ) {
+ if ( DBGetContactSettingByte(hContact, "CList", "Hidden", 0) )
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ wApparent = DBGetContactSettingWord(hContact,gpszICQProtoName,"ApparentMode",0);
+
+ // Allow only users in the permit list to see you
+ if ( bVisibility == 0x03 ) {
+ if ( wApparent == ID_STATUS_ONLINE )
+ return FALSE;
+ else
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+ }
+
+ // Block only users in the invisible list from seeing you
+ if ( bVisibility == 0x04 ) {
+ if ( wApparent == ID_STATUS_OFFLINE )
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ // invisible by default
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+}
+
+void CheckContact(CHECKCONTACT chk) //dwUin necessary, function for show popups, write events, log to file, call PSD, parsing temporary contacts, NEED TO BE FINISHED
+{
+ BYTE Hidden = DBGetContactSettingByte(chk.hContact, "CList", "Hidden", 0);
+ BYTE InDb = CallService(MS_DB_CONTACT_IS, (WPARAM)chk.hContact, 0);
+ BYTE NotOnList = DBGetContactSettingByte(chk.hContact,"CList","NotOnList",0);
+ BOOL Cancel = FALSE;
+ BOOL showpopup = TRUE;
+ char popmsg[512] = {0}, eventmsghistory[512] = {0}, eventmsgfile[512] = {0};
+ if(!InDb||NotOnList||Hidden)
+ {
+ if(!bPopUpForNotOnList)
+ showpopup = FALSE;
+ if(bNoPSDForHidden)
+ Cancel = TRUE;
+ }
+ if(!chk.popuptype) //
+ chk.popup=FALSE; //
+ if(!chk.icqeventtype) //
+ { //wrong call check ... (missing event types)
+ chk.historyevent=FALSE; //
+ chk.logtofile=FALSE; //
+ } //
+ if(chk.dwUin)
+ {
+ if (bTmpContacts == 1)
+ {
+ int added;
+ chk.hContact = HContactFromUIN(chk.dwUin, &added);
+ if(NotOnList)
+ {
+ {
+ DBCONTACTWRITESETTING dbcws;
+ dbcws.value.type = DBVT_UTF8;
+ dbcws.value.pszVal = TmpGroupName;
+ dbcws.szModule = "CList";
+ dbcws.szSetting = "Group";
+ CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)chk.hContact, (LPARAM)&dbcws);
+ }
+ DBWriteContactSettingByte(chk.hContact,"CList","Hidden",0);
+ DBWriteContactSettingByte(chk.hContact,"CList","NotOnList",bAddTemp);
+ DBWriteContactSettingByte(chk.hContact, gpszICQProtoName, "CheckSelfRemove", 1);//excluding from checkselfremove
+ // DBWriteContactSettingByte(hContact, gpszICQProtoName, "FoundedContact", 1); //mark founded contacts
+ }
+ }
+ if(InDb)
+ {
+ if(chk.msg)
+ {
+ if(strlen(chk.msg) > 1 && showpopup)
+ {
+ popmsg[0] = '\0';
+ switch(chk.popuptype)
+ {
+ case POPTYPE_SPAM:
+ //nothing here, used direct ShowPopupMsg call
+ break;
+ case POPTYPE_UNKNOWN:
+ //nothing here, used direct ShowPopupMsg call
+ break;
+ case POPTYPE_VIS:
+ if(bVisPopUp)
+ {
+ strcpy(popmsg,"... is checking your real status ");
+ }
+ break;
+ case LOG_NOTE:
+ case LOG_WARNING:
+ case LOG_ERROR:
+ case LOG_FATAL:
+ strcpy(popmsg,chk.msg);
+ break;
+ case POPTYPE_FOUND:
+ if(bFoundPopUp)
+ {
+ strcpy(popmsg,chk.msg);
+ }
+ break;
+ case POPTYPE_SCAN:
+ if(bScanPopUp)
+ {
+ strcpy(popmsg,chk.msg);
+ }
+ break;
+ case POPTYPE_CLIENT_CHANGE:
+ if(bClientChangePopUp)
+ {
+ strcpy(popmsg,chk.msg);
+ }
+ break;
+ case POPTYPE_INFO_REQUEST:
+ if(bInfoRequestPopUp)
+ strcpy(popmsg,chk.msg);
+ break;
+ case POPTYPE_IGNORE_CHECK:
+ if(bIgnoreCheckPop)
+ strcpy(popmsg,chk.msg);
+ break;
+ case POPTYPE_SELFREMOVE:
+ if(bPopSelfRem)
+ strcpy(popmsg,chk.msg);
+ break;
+ case POPTYPE_AUTH:
+ if(bAuthPopUp)
+ strcpy(popmsg,chk.msg);
+ break;
+ default:
+ break;
+ }
+ if(chk.historyevent||chk.logtofile)
+ {
+ switch(chk.icqeventtype)
+ {
+ case ICQEVENTTYPE_AUTH_DENIED:
+ if(bLogAuthHistory)
+ strcpy(eventmsghistory,"was denied your authorization request");
+ if(bLogAuthFile)
+ strcpy(eventmsgfile,"was denied your authorization request");
+ break;
+ case ICQEVENTTYPE_AUTH_GRANTED:
+ if(bLogAuthHistory)
+ strcpy(eventmsghistory,"Authorization request granted");
+ if(bLogAuthFile)
+ strcpy(eventmsgfile,"Authorization request granted");
+ break;
+ case ICQEVENTTYPE_CHECK_STATUS:
+ if(bLogStatusCheckHistory)
+ strcpy(eventmsghistory,"check your status ");
+ if(bLogStatusCheckFile)
+ strcpy(eventmsgfile,"check your status ");
+ break;
+ case ICQEVENTTYPE_WAS_FOUND:
+ if(bLogASDHistory)
+ strcpy(eventmsghistory,"");
+ if(bLogASDFile)
+ strcpy(eventmsgfile,"");
+ break;
+ case ICQEVENTTYPE_CLIENT_CHANGE:
+ if(bLogIgnoreCheckHistory)
+ strcpy(eventmsghistory,chk.msg);
+ if(bLogIgnoreCheckFile)
+ strcpy(eventmsgfile,chk.msg);
+ break;
+ case ICQEVENTTYPE_EMAILEXPRESS:
+ //nothing to do here at this time ...
+ break;
+ case ICQEVENTTYPE_FUTURE_AUTH:
+ //i do not know what can i do here, fix me....
+ break;
+ case ICQEVENTTYPE_IGNORECHECK_STATUS:
+ if(bLogIgnoreCheckHistory)
+ strcpy(eventmsghistory,"check your ignore list");
+ if(bLogIgnoreCheckFile)
+ strcpy(eventmsgfile,"check your ignore list");
+ break;
+ case ICQEVENTTYPE_SELF_REMOVE:
+ if(bLogSelfRemoveHistory)
+ strcpy(eventmsghistory,"removed himself from your Serverlist!");
+ if(bLogSelfRemoveFile)
+ strcpy(eventmsgfile,"removed himself from your Serverlist!");
+ break;
+ case ICQEVENTTYPE_SMS:
+ //nothing to do here at this time ...
+ break;
+ case ICQEVENTTYPE_WEBPAGER:
+ //nothing to do here at this time ...
+ break;
+ case ICQEVENTTYPE_YOU_ADDED:
+ break;
+ case ICQEVENTTYPE_AUTH_REQUESTED:
+ break;
+ default:
+ break;
+ }
+ if(popmsg && strlen(popmsg) > 1)
+ {
+ if(!strstr(chk.msg,popmsg))
+ strcat(popmsg, chk.msg);
+ ShowPopUpMsg(chk.hContact, chk.dwUin, NickFromHandleUtf(chk.hContact), popmsg, chk.popuptype);
+ }
+ if(eventmsghistory && strlen(eventmsghistory) > 1)
+ {
+ if(!strstr(chk.msg,eventmsghistory))
+ strcat(eventmsghistory, chk.msg);
+ HistoryLog(chk.hContact, chk.dwUin, eventmsghistory, chk.icqeventtype, chk.dbeventflag);
+ }
+ if(eventmsgfile && strlen(eventmsgfile) > 1)
+ {
+ if(!strstr(chk.msg,eventmsgfile))
+ strcat(eventmsgfile, chk.msg);
+ LogToFile(chk.hContact, chk.dwUin, eventmsgfile, chk.icqeventtype);
+ }
+ }
+ }
+ }
+ if(chk.PSD != -1 && !Cancel)
+ {
+ if(!chk.PSD)
+ chk.PSD=21;
+ if(gbASD&&chk.PSD<10)
+ icq_SetUserStatus(chk.dwUin, 0, chk.PSD, 0);
+ else if(ICQGetContactSettingWord(chk.hContact, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE && (bPSD&&chk.PSD>20)) //check for wrong PSD call
+ icq_SetUserStatus(chk.dwUin, 0, chk.PSD, 0);
+ }
+ }
+ }
+}
+int IncognitoAwayRequest(WPARAM wParam, LPARAM lParam)
+{
+ bIncognitoRequest = TRUE;
+
+ CallService(MS_AWAYMSG_SHOWAWAYMSG, wParam, 0);
+ return 0;
+}
+
+
+
+void HistoryLog(HANDLE hContact, DWORD dwUin, char *data, int event_type, int flag)
+{
+ extern BOOL bHcontactHistory;
+ PBYTE pCurBlob;
+ WORD wTextLen;
+ char szText[MAX_PATH];
+ DBEVENTINFO Event = {0};
+ Event.cbSize=sizeof(Event);
+ Event.szModule=gpszICQProtoName;
+ Event.eventType=event_type;
+ Event.flags=flag,DBEF_UTF;
+ Event.timestamp=(DWORD)time(NULL);
+ mir_snprintf(szText, sizeof(szText), "%s %s ( %s: %s, %s: (%u) )", Translate(data), Translate("by"), Translate("Nick"), (NickFromHandle(hContact)), Translate("UIN"), dwUin);
+ wTextLen = strlen(szText);
+ Event.cbBlob = sizeof(DWORD)+sizeof(HANDLE)+wTextLen+1;
+ pCurBlob = Event.pBlob = (PBYTE)_alloca(Event.cbBlob);
+ memcpy(pCurBlob,&szText,wTextLen); pCurBlob+=wTextLen;
+ *(char *)pCurBlob = 0; pCurBlob++;
+ memcpy(pCurBlob,&dwUin,sizeof(DWORD)); pCurBlob+=sizeof(DWORD);
+ memcpy(pCurBlob,&hContact,sizeof(HANDLE));
+ if(bHcontactHistory)
+ CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)hContact,(LPARAM)&Event);
+ else
+ CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&Event);
+ //we need show popups for events from here
+}
+
+
+void LogToFile(HANDLE hContact, DWORD dwUin, char *string, int event_type)
+{
+
+ char szTime[30];
+ char content[MAX_PATH];
+ char filename[1024];
+ time_t now;
+ FILE *f;
+
+ wsprintf(filename, UniGetContactSettingUtf(NULL, gpszICQProtoName, "EventsLog", "EventsLog.txt"));
+
+
+ switch(event_type)
+ {
+ case ICQEVENTTYPE_AUTH_GRANTED:
+ if(!bLogAuthFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("granted your authorization request "), Translate(string));
+ break;
+ case ICQEVENTTYPE_AUTH_DENIED:
+ if(!bLogAuthFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("denied your authorization request "), Translate(string));
+ break;
+ case ICQEVENTTYPE_SELF_REMOVE:
+ if(!bLogSelfRemoveFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("removed himself from your serverlist "), Translate(string));
+ break;
+ case ICQEVENTTYPE_FUTURE_AUTH:
+ if(!bLogAuthFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("granted you future authorization "), Translate(string));
+ break;
+ case ICQEVENTTYPE_CLIENT_CHANGE:
+ if(!bLogClientChangeFile)
+ return;
+ utf8_decode_static(string, content, strlen(string));
+ break;
+
+ case ICQEVENTTYPE_CHECK_STATUS:
+ if(!bLogStatusCheckFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("checked your real status "), Translate(string));
+ break;
+ case ICQEVENTTYPE_WAS_FOUND:
+ if(!bLogASDFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s", Translate(string));
+ break;
+ case ICQEVENTTYPE_IGNORECHECK_STATUS:
+ if(!bLogIgnoreCheckFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("checked his ignore state"), Translate(string));
+ break;
+
+ default:
+ wsprintf(content, "unknown eventype processed");
+ return;
+ }
+
+
+ now = time(NULL);
+ strftime(szTime, sizeof(szTime), "%a, %d %b %Y %H:%M:%S", localtime(&now));
+ /* Sun, 00 Jan 0000 00:00:00 */
+ f = fopen( filename, "a+" );
+ if( f != NULL )
+ {
+ fprintf( f, "[%s] %s (%u) %s\n", szTime, NickFromHandle(hContact), dwUin, content);
+ fclose(f);
+ }
+}
+
+WORD GetProtoVersion()
+{
+ int ver = 0;
+ if (gbVerEnabled)
+ {
+ ver = (DBGetContactSettingWord(NULL,gpszICQProtoName,"setVersion", 0));
+ }
+ else
+ {
+ switch (DBGetContactSettingWord(NULL,gpszICQProtoName,"CurrentID",0)) //client change version
+ {
+ case 1: //unknown
+ ver = 66;
+ break;
+ case 23:
+ case 24:
+ case 2: //qip
+ case 3: //ysm
+ case 7: //trillian
+ case 46: //qip infium
+ ver = 11;
+ break;
+ case 6: //Jimm
+ ver = 5;
+ break;
+ case 9: //Kopete
+ case 52: //NanoICQ
+ ver = 10;
+ break;
+ case 11:
+ ver = 13;
+ break;
+ case 4: //icq lite
+ case 5: //&RQ
+ case 12: //rambler
+ case 13: //icq 5.1
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 26: //icq6
+ case 44: //QNEXT
+ case 45: //pyICQ
+ ver = 9;
+ break;
+ case 21: //stICQ
+ ver = 2;
+ break;
+ case 36: //ICQ99
+ ver = 6;
+ break;
+ case 37: //WebICQ
+ ver = 7;
+ break;
+ case 35: //GAIM
+ ver = 0;
+ break;
+ default : //miranda
+ ver = 8;
+ break;
+ }
+ }
+ DBWriteContactSettingWord(NULL,gpszICQProtoName,"setVersion",(WORD)ver);
+ return ver;
+}
+
+void SetTimeStamps(DWORD *dwFT1, DWORD *dwFT2, DWORD *dwFT3)
+{
+ switch (DBGetContactSettingWord(NULL, gpszICQProtoName, "CurrentID", 0)) //client change dwFT
+ {
+ case 3: //ysm
+ *dwFT1=0xFFFFFFAB; // Abused timestamp
+ *dwFT2=0x00000000; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 4: //ICQ lite
+ *dwFT1=0x3AA773EE; // Abused timestamp
+ *dwFT2=0x00000000; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 5: //&RQ
+ *dwFT1=0xFFFFFF7F; // Abused timestamp
+ *dwFT2=0x00000000; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 7: //trillian
+ *dwFT1=0x3B75AC09; // Abused timestamp
+ *dwFT2=0x00000000; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 8: //licq
+ *dwFT1=0x2C0BA3DD; // Abused timestamp
+ *dwFT2=0x7D800403; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 2: //qip
+ *dwFT1=0x08000300; // Abused timestamp
+ *dwFT2=0x0000000E; // Abused timestamp
+ *dwFT3=0x0000000F; // Timestamp
+ break;
+ case 46: //QIP Infium
+ *dwFT1=0x0000232C; // Abused timestamp
+ *dwFT2=0x0000000B; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 18:
+ case 19:
+ *dwFT1=0x3AA773EE; // Abused timestamp
+ *dwFT2=0x3AA66380; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 21:
+ *dwFT1=0x3BA8DBAF;
+ *dwFT2=0x3BEB5373;
+ *dwFT3=0x3BEB5262;
+ break;
+ case 22:
+ *dwFT1=0x3B4C4C0C;
+ *dwFT2=0x00000000;
+ *dwFT3=0x3B7248ed;
+ break;
+ case 1: //unknown
+ case 6: //Jimm
+ case 9: //Kopete
+ case 10: ////icq for mac
+ case 12: //rambler
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 20:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 40: //uIM
+ case 41: //TICQClient
+ case 42: //IC@
+ case 43: //PreludeICQ
+ case 44: //QNEXT
+ case 45: //pyICQ
+ case 47: //JICQ
+ case 49: //MIP
+ case 50: //Trillian Astra
+ case 52: //NanoICQ
+ case 53: //IMadering
+ *dwFT1=0x00000000;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 29:
+ *dwFT1=0x44F523B0;
+ *dwFT2=0x44F523A6;
+ *dwFT3=0x44F523A6;
+ break;
+ case 30: //alicq
+ *dwFT1=0xffffffbe;
+ *dwFT2=0x00090800;
+ *dwFT3=0x00000000;
+ break;
+ case 31: //mICQ
+ *dwFT1=0xFFFFFF42;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 32: //StrICQ 0.4
+ *dwFT1=0xFFFFFF8F;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 33: //vICQ 0.43.0.0
+ *dwFT1=0x04031980;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 34: //IM2
+ *dwFT1=0x3FF19BEB;
+ *dwFT2=0x00000000;
+ *dwFT3=0x3FF19BEB;
+ break;
+ case 35: //GAIM
+ *dwFT1=0xffffffff;
+ *dwFT2=0xffffffff;
+ *dwFT3=0xffffffff;
+ break;
+ case 36: //ICQ99
+ *dwFT1=0x3AA773EE;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 37: //WebICQ
+ *dwFT1=0xFFFFFFFF;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 38: //SmartICQ
+ *dwFT1=0xDDDDEEFF;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 39: //IM+
+ *dwFT1=0x494D2B00;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 48: //SpamBot
+ *dwFT1=0xffffffff;
+ *dwFT2=0x00000000;
+ *dwFT3=0x3B7248ED;
+ break;
+ case 51: //R&Q
+ *dwFT1=0xFFFFF666;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 11:
+ *dwFT1=0xFFFFFFFF; //Abused timestamp
+ *dwFT2=0x06060600; //Abused timestamp
+ if(gbHideIdEnabled)
+ *dwFT3=gbUnicodeCore?0x80000000:0x00000000;
+ else
+ *dwFT3=gbSecureIM?0x5AFEC0DE:0x00000000;
+ break;
+ default : //miranda
+ *dwFT1=gbHideIdEnabled?0xffffffff:(gbUnicodeCore?0x7fffffff:0xffffffff); //Abused timestamp
+ *dwFT2=ICQ_PLUG_VERSION; //Abused timestamp
+ if(gbHideIdEnabled)
+ *dwFT3=gbUnicodeCore?0x80000000:0x00000000;
+ else
+ *dwFT3=gbSecureIM?0x5AFEC0DE:0x00000000;
+ break;
+ }
+}
+
+/*void logtofile(HANDLE hContact, DWORD dwUin, char *string, int event_type)
+{
+
+ char szTime[30];
+ char content[MAX_PATH];
+ char filename[1024];
+ time_t now;
+ FILE *f;
+ int i;
+
+
+ static struct
+ {
+ int type;
+ BOOL *flag;
+ char *message;
+ } eventTypes[] =
+ {
+ { ICQEVENTTYPE_AUTH_GRANTED, &bLogAuthFile, "granted your authorization request" },
+ { ICQEVENTTYPE_SELF_REMOVE, &bLogSelfRemoveFile, "removed himself from your serverlist" },
+ };
+ int eventTypesCount = sizeof(eventTypes) / sizeof(*eventTypes);
+
+ for (i = 0; i < eventTypesCount; ++i)
+ if (eventTypes.type == event_type)
+ {
+ if (!*eventTypes.flag) return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate(eventTypes.message), Translate(string)) ;
+ break;
+ }
+
+ // type not found
+ if (i == eventTypesCount)
+ return;
+
+ now = time(NULL);
+ strftime(szTime, sizeof(szTime), "%a, %d %b %Y %H:%M:%S", localtime(&now)) ;
+ // Sun, 00 Jan 0000 00:00:00
+
+ wsprintf(filename, UniGetContactSettingUtf(NULL, gpszICQProtoName, "EventsLog", "EventsLog.txt")) ;
+ f = fopen( filename, "a+" );
+ if( f != NULL )
+ {
+ fprintf( f, "[%s] %s (%u) %s\n", szTime, NickFromHandleUtf(hContact), dwUin, content);
+ fclose(f);
+ }
+ //another realisation by Nullbie
+} */
diff --git a/icqj_s7_sss_mod/utilities.h b/icqj_s7_sss_mod/utilities.h new file mode 100644 index 0000000..ca9970c --- /dev/null +++ b/icqj_s7_sss_mod/utilities.h @@ -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,2007 Joe Kucera
+// Copyright 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Thief, Angeli-Ka, nullbie
+//
+// 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 : $HeadURL: https://icqjplusmod.googlecode.com/svn/trunk/utilities.h $
+// Revision : $Revision: 43 $
+// Last change on : $Date: 2007-08-20 01:51:06 +0300 (Пн, 20 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __UTILITIES_H
+#define __UTILITIES_H
+#define F_TEMPVIS 1
+#define mir_asctime(ptr) ((ptr==NULL)?("<invalid timestamp>"):asctime(ptr))
+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;
+
+
+/*---------* 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);
+size_t __fastcall null_strcut(char *string, size_t maxlen);
+
+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);
+char* ApplyEncoding(const char *string, const char* pszEncoding);
+
+
+void ResetSettingsOnListReload(void);
+void ResetSettingsOnConnect(void);
+void ResetSettingsOnLoad(void);
+int RandRange(int nLow, int nHigh);
+
+BOOL IsStringUIN(char* pszString);
+
+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* __fastcall SAFE_REALLOC(void* p, size_t size);
+
+HANDLE NetLib_OpenConnection(HANDLE hUser, const char* szIdent, NETLIBOPENCONNECTION* nloc);
+HANDLE NetLib_BindPort(NETLIBNEWCONNECTIONPROC_V2 pFunc, void* lParam, WORD* pwPort, DWORD* pdwIntIP);
+void NetLib_CloseConnection(HANDLE *hConnection, int bServerConn);
+void NetLib_SafeCloseHandle(HANDLE *hConnection);
+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, size_t bufsize);
+
+HANDLE ICQCreateThreadEx(pThreadFuncEx AFunc, void* arg, DWORD* pThreadID);
+void ICQCreateThread(pThreadFuncEx AFunc, void* arg);
+
+char* GetUserPassword(BOOL bAlways);
+WORD GetMyStatusFlags();
+
+BOOL invis_for(DWORD dwUin, HANDLE hContact);
+
+typedef struct{
+ DWORD dwUin; //contact uin (dword)
+ HANDLE hContact; //(HANDLE)
+ int PSD; //value for calling setuserstatus (-1 for disable)
+ BOOL popup; //set TRUE for show popup (BOOL)
+ int popuptype; //set popup event type (int)
+ BOOL historyevent; //set history event type (BOOL)
+ BOOL logtofile; //set TRUE for write event to file (BOOL)
+ char* msg; //set event message (char)
+ int icqeventtype; //set db event type for history (int)
+ int dbeventflag; //set additional db flags (int)
+ BOOL nottmpcontact; //work with contact which not temporary (BOOL)
+ BOOL fornotonlist; //work with contact which not on list (BOOL)
+ BOOL foroffline; //work with offline contact (BOOL)
+ BOOL weofflinefor; //work with contact which we offline for (BOOL)
+}CHECKCONTACT;
+void CheckContact(CHECKCONTACT chk);
+BYTE bVisibility;
+
+int IncognitoAwayRequest(WPARAM wParam, LPARAM lParam);
+BOOL bIncognitoRequest;
+
+/* Unicode FS utility functions */
+
+int IsValidRelativePath(const char *filename);
+char* ExtractFileName(const char *fullname);
+char* FileNameToUtf(const char *filename);
+int FileStatUtf(const char *path, struct _stati64 *buffer);
+int MakeDirUtf(const char *dir);
+int OpenFileUtf(const char *filename, int oflag, int pmode);
+
+/* Unicode UI utility functions */
+WCHAR* GetWindowTextUcs(HWND hWnd);
+void SetWindowTextUcs(HWND hWnd, WCHAR *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);
+
+void HistoryLog(HANDLE hContact, DWORD dwUin, char *data, int event_type, int flag);
+void LogToFile(HANDLE hContact, DWORD dwUin, char *string, int event_type);
+void SetTimeStamps(DWORD *dwFT1, DWORD *dwFT2, DWORD *dwFT3);
+BOOL gbSecureIM;
+WORD GetProtoVersion();
+
+#endif /* __UTILITIES_H */
|