summaryrefslogtreecommitdiff
path: root/protocols/IcqOscarJ
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /protocols/IcqOscarJ
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/IcqOscarJ')
-rw-r--r--protocols/IcqOscarJ/UI/askauthentication.cpp103
-rw-r--r--protocols/IcqOscarJ/UI/askauthentication.h35
-rw-r--r--protocols/IcqOscarJ/UI/icqoscar.h2
-rw-r--r--protocols/IcqOscarJ/UI/loginpassword.cpp104
-rw-r--r--protocols/IcqOscarJ/UI/loginpassword.h36
-rw-r--r--protocols/IcqOscarJ/UI/userinfotab.cpp327
-rw-r--r--protocols/IcqOscarJ/UI/userinfotab.h34
-rw-r--r--protocols/IcqOscarJ/capabilities.cpp278
-rw-r--r--protocols/IcqOscarJ/capabilities.h52
-rw-r--r--protocols/IcqOscarJ/chan_01login.cpp112
-rw-r--r--protocols/IcqOscarJ/chan_02data.cpp229
-rw-r--r--protocols/IcqOscarJ/chan_03error.cpp42
-rw-r--r--protocols/IcqOscarJ/chan_04close.cpp321
-rw-r--r--protocols/IcqOscarJ/chan_05ping.cpp103
-rw-r--r--protocols/IcqOscarJ/changeinfo/changeinfo.h129
-rw-r--r--protocols/IcqOscarJ/changeinfo/constants.cpp205
-rw-r--r--protocols/IcqOscarJ/changeinfo/db.cpp231
-rw-r--r--protocols/IcqOscarJ/changeinfo/dlgproc.cpp554
-rw-r--r--protocols/IcqOscarJ/changeinfo/editlist.cpp208
-rw-r--r--protocols/IcqOscarJ/changeinfo/editstring.cpp374
-rw-r--r--protocols/IcqOscarJ/changeinfo/expandst.icobin0 -> 318 bytes
-rw-r--r--protocols/IcqOscarJ/changeinfo/icqoscar.h2
-rw-r--r--protocols/IcqOscarJ/changeinfo/main.cpp35
-rw-r--r--protocols/IcqOscarJ/changeinfo/upload.cpp98
-rw-r--r--protocols/IcqOscarJ/channels.h54
-rw-r--r--protocols/IcqOscarJ/cookies.cpp308
-rw-r--r--protocols/IcqOscarJ/cookies.h155
-rw-r--r--protocols/IcqOscarJ/directpackets.cpp300
-rw-r--r--protocols/IcqOscarJ/directpackets.h43
-rw-r--r--protocols/IcqOscarJ/docs/IcqOscarJ-translation.txt379
-rw-r--r--protocols/IcqOscarJ/docs/icq-license.txt340
-rw-r--r--protocols/IcqOscarJ/docs/icq-readme.txt480
-rw-r--r--protocols/IcqOscarJ/fam_01service.cpp981
-rw-r--r--protocols/IcqOscarJ/fam_02location.cpp301
-rw-r--r--protocols/IcqOscarJ/fam_03buddy.cpp801
-rw-r--r--protocols/IcqOscarJ/fam_04message.cpp3050
-rw-r--r--protocols/IcqOscarJ/fam_09bos.cpp113
-rw-r--r--protocols/IcqOscarJ/fam_0alookup.cpp137
-rw-r--r--protocols/IcqOscarJ/fam_0bstatus.cpp69
-rw-r--r--protocols/IcqOscarJ/fam_13servclist.cpp2075
-rw-r--r--protocols/IcqOscarJ/fam_15icqserver.cpp1208
-rw-r--r--protocols/IcqOscarJ/fam_17signon.cpp182
-rw-r--r--protocols/IcqOscarJ/families.h81
-rw-r--r--protocols/IcqOscarJ/globals.h64
-rw-r--r--protocols/IcqOscarJ/guids.h88
-rw-r--r--protocols/IcqOscarJ/i18n.cpp548
-rw-r--r--protocols/IcqOscarJ/i18n.h87
-rw-r--r--protocols/IcqOscarJ/iconlib.cpp101
-rw-r--r--protocols/IcqOscarJ/iconlib.h59
-rw-r--r--protocols/IcqOscarJ/icons_pack/ICONS.dep36
-rw-r--r--protocols/IcqOscarJ/icons_pack/ICONS.dsp194
-rw-r--r--protocols/IcqOscarJ/icons_pack/ICONS.dsw29
-rw-r--r--protocols/IcqOscarJ/icons_pack/ICONS.mak113
-rw-r--r--protocols/IcqOscarJ/icons_pack/ICONS.rc132
-rw-r--r--protocols/IcqOscarJ/icons_pack/ICONS.vcxproj317
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus34.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus35.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus36.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus38.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus39.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus40.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus41.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus42.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus45.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus46.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus47.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus48.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus49.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus50.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus51.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus52.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus53.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus54.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus56.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus57.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus58.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus59.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus60.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus61.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus62.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus63.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus65.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus66.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus67.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus68.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus69.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus70.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus71.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus72.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus73.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus74.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus75.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus76.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus77.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus78.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus79.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus81.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus82.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus83.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus84.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/Xstatus86.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/auth_ask.icobin0 -> 2038 bytes
-rw-r--r--protocols/IcqOscarJ/icos/auth_grant.icobin0 -> 2038 bytes
-rw-r--r--protocols/IcqOscarJ/icos/auth_revoke.icobin0 -> 2038 bytes
-rw-r--r--protocols/IcqOscarJ/icos/icq.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/srvlist_add.icobin0 -> 2038 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus01.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus02.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus03.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus04.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus05.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus06.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus07.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus08.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus09.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus10.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus11.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus12.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus13.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus14.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus15.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus16.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus17.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus18.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus19.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus20.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus21.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus22.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus23.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus24.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus25.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus26.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus27.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus28.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus29.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus30.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus31.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus32.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus33.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus37.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus43.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus44.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus55.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus64.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus80.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icos/xstatus85.icobin0 -> 6830 bytes
-rw-r--r--protocols/IcqOscarJ/icq_advsearch.cpp192
-rw-r--r--protocols/IcqOscarJ/icq_advsearch.h39
-rw-r--r--protocols/IcqOscarJ/icq_avatar.cpp1823
-rw-r--r--protocols/IcqOscarJ/icq_avatar.h134
-rw-r--r--protocols/IcqOscarJ/icq_clients.cpp1149
-rw-r--r--protocols/IcqOscarJ/icq_constants.h657
-rw-r--r--protocols/IcqOscarJ/icq_db.cpp409
-rw-r--r--protocols/IcqOscarJ/icq_db.h51
-rw-r--r--protocols/IcqOscarJ/icq_direct.cpp1178
-rw-r--r--protocols/IcqOscarJ/icq_direct.h101
-rw-r--r--protocols/IcqOscarJ/icq_directmsg.cpp368
-rw-r--r--protocols/IcqOscarJ/icq_fieldnames.cpp602
-rw-r--r--protocols/IcqOscarJ/icq_fieldnames.h56
-rw-r--r--protocols/IcqOscarJ/icq_filerequests.cpp230
-rw-r--r--protocols/IcqOscarJ/icq_filetransfer.cpp522
-rw-r--r--protocols/IcqOscarJ/icq_firstrun.cpp131
-rw-r--r--protocols/IcqOscarJ/icq_http.cpp219
-rw-r--r--protocols/IcqOscarJ/icq_http.h55
-rw-r--r--protocols/IcqOscarJ/icq_infoupdate.cpp415
-rw-r--r--protocols/IcqOscarJ/icq_infoupdate.h35
-rw-r--r--protocols/IcqOscarJ/icq_menu.cpp244
-rw-r--r--protocols/IcqOscarJ/icq_opts.cpp628
-rw-r--r--protocols/IcqOscarJ/icq_opts.h37
-rw-r--r--protocols/IcqOscarJ/icq_packet.cpp908
-rw-r--r--protocols/IcqOscarJ/icq_packet.h127
-rw-r--r--protocols/IcqOscarJ/icq_popups.cpp257
-rw-r--r--protocols/IcqOscarJ/icq_popups.h48
-rw-r--r--protocols/IcqOscarJ/icq_proto.cpp2415
-rw-r--r--protocols/IcqOscarJ/icq_proto.h996
-rw-r--r--protocols/IcqOscarJ/icq_rates.cpp536
-rw-r--r--protocols/IcqOscarJ/icq_rates.h153
-rw-r--r--protocols/IcqOscarJ/icq_server.cpp452
-rw-r--r--protocols/IcqOscarJ/icq_server.h79
-rw-r--r--protocols/IcqOscarJ/icq_servlist.cpp2858
-rw-r--r--protocols/IcqOscarJ/icq_servlist.h179
-rw-r--r--protocols/IcqOscarJ/icq_uploadui.cpp1036
-rw-r--r--protocols/IcqOscarJ/icq_uploadui.h35
-rw-r--r--protocols/IcqOscarJ/icq_xstatus.cpp1388
-rw-r--r--protocols/IcqOscarJ/icq_xtraz.cpp473
-rw-r--r--protocols/IcqOscarJ/icq_xtraz.h43
-rw-r--r--protocols/IcqOscarJ/icqosc_svcs.cpp788
-rw-r--r--protocols/IcqOscarJ/icqosc_svcs.h46
-rw-r--r--protocols/IcqOscarJ/icqoscar.cpp42
-rw-r--r--protocols/IcqOscarJ/icqoscar.h143
-rw-r--r--protocols/IcqOscarJ/icqoscar8.dep4421
-rw-r--r--protocols/IcqOscarJ/icqoscar8.dsp768
-rw-r--r--protocols/IcqOscarJ/icqoscar8.dsw29
-rw-r--r--protocols/IcqOscarJ/icqoscar8.mak1710
-rw-r--r--protocols/IcqOscarJ/icqoscar8.vcproj1991
-rw-r--r--protocols/IcqOscarJ/icqoscar8_10.vcxproj690
-rw-r--r--protocols/IcqOscarJ/icqoscar8_10.vcxproj.filters311
-rw-r--r--protocols/IcqOscarJ/icqoscar8_8.vcproj2406
-rw-r--r--protocols/IcqOscarJ/icqoscar8_9.vcproj1381
-rw-r--r--protocols/IcqOscarJ/init.cpp320
-rw-r--r--protocols/IcqOscarJ/init.h47
-rw-r--r--protocols/IcqOscarJ/log.cpp170
-rw-r--r--protocols/IcqOscarJ/log.h45
-rw-r--r--protocols/IcqOscarJ/m_extraicons.h158
-rw-r--r--protocols/IcqOscarJ/m_folders.h282
-rw-r--r--protocols/IcqOscarJ/m_updater.h117
-rw-r--r--protocols/IcqOscarJ/oscar_filetransfer.cpp2452
-rw-r--r--protocols/IcqOscarJ/oscar_filetransfer.h171
-rw-r--r--protocols/IcqOscarJ/resource.h260
-rw-r--r--protocols/IcqOscarJ/resources.rc594
-rw-r--r--protocols/IcqOscarJ/stdpackets.cpp1902
-rw-r--r--protocols/IcqOscarJ/stdpackets.h50
-rw-r--r--protocols/IcqOscarJ/tlv.cpp398
-rw-r--r--protocols/IcqOscarJ/tlv.h88
-rw-r--r--protocols/IcqOscarJ/utilities.cpp2243
-rw-r--r--protocols/IcqOscarJ/utilities.h203
-rw-r--r--protocols/IcqOscarJ/version.h5
217 files changed, 61928 insertions, 0 deletions
diff --git a/protocols/IcqOscarJ/UI/askauthentication.cpp b/protocols/IcqOscarJ/UI/askauthentication.cpp
new file mode 100644
index 0000000000..7f541814fb
--- /dev/null
+++ b/protocols/IcqOscarJ/UI/askauthentication.cpp
@@ -0,0 +1,103 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/UI/askauthentication.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+struct AskAuthParam
+{
+ CIcqProto* ppro;
+ HANDLE hContact;
+};
+
+static INT_PTR CALLBACK AskAuthProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ AskAuthParam* dat = (AskAuthParam*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ dat = (AskAuthParam*)lParam;
+ if (!dat->hContact || !dat->ppro->icqOnline())
+ EndDialog(hwndDlg, 0);
+
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
+ SendDlgItemMessage(hwndDlg, IDC_EDITAUTH, EM_LIMITTEXT, (WPARAM)255, 0);
+ SetDlgItemText(hwndDlg, IDC_EDITAUTH, TranslateT("Please authorize me to add you to my contact list."));
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ if (dat->ppro->icqOnline())
+ {
+ DWORD dwUin;
+ uid_str szUid;
+ if ( dat->ppro->getContactUid(dat->hContact, &dwUin, &szUid))
+ return TRUE; // Invalid contact
+
+ char* szReason = GetDlgItemTextUtf(hwndDlg, IDC_EDITAUTH);
+ dat->ppro->icq_sendAuthReqServ(dwUin, szUid, szReason);
+ SAFE_FREE((void**)&szReason);
+
+ // auth bug fix (thx Bio)
+ if (dat->ppro->m_bSsiEnabled && dwUin)
+ dat->ppro->resetServContactAuthState(dat->hContact, dwUin);
+
+ EndDialog(hwndDlg, 0);
+ }
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hwndDlg,0);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+INT_PTR CIcqProto::RequestAuthorization(WPARAM wParam, LPARAM lParam)
+{
+ AskAuthParam param = { this, (HANDLE)wParam };
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ASKAUTH), NULL, AskAuthProc, (LPARAM)&param);
+ return 0;
+}
diff --git a/protocols/IcqOscarJ/UI/askauthentication.h b/protocols/IcqOscarJ/UI/askauthentication.h
new file mode 100644
index 0000000000..e60c034699
--- /dev/null
+++ b/protocols/IcqOscarJ/UI/askauthentication.h
@@ -0,0 +1,35 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001,2002 Jon Keating, Richard Hughes
+// Copyright 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/askauthentication.h,v $
+// Revision : $Revision: 7500 $
+// Last change on : $Date: 2008-03-24 20:07:37 +0200 (Пн, 24 мар 2008) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
diff --git a/protocols/IcqOscarJ/UI/icqoscar.h b/protocols/IcqOscarJ/UI/icqoscar.h
new file mode 100644
index 0000000000..77283f6f7f
--- /dev/null
+++ b/protocols/IcqOscarJ/UI/icqoscar.h
@@ -0,0 +1,2 @@
+/* For MinGW sake */
+#include "../icqoscar.h"
diff --git a/protocols/IcqOscarJ/UI/loginpassword.cpp b/protocols/IcqOscarJ/UI/loginpassword.cpp
new file mode 100644
index 0000000000..b31f000f23
--- /dev/null
+++ b/protocols/IcqOscarJ/UI/loginpassword.cpp
@@ -0,0 +1,104 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/UI/loginpassword.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+INT_PTR CALLBACK LoginPasswdDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = (CIcqProto*)GetWindowLongPtr( hwndDlg, GWLP_USERDATA );
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ ppro = (CIcqProto*)lParam;
+ SetWindowLongPtr( hwndDlg, GWLP_USERDATA, lParam );
+ {
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)ppro->m_hIconProtocol->GetIcon(true));
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)ppro->m_hIconProtocol->GetIcon());
+
+ DWORD dwUin = ppro->getContactUin(NULL);
+
+ char pszUIN[MAX_PATH], str[MAX_PATH];
+ null_snprintf(pszUIN, 128, ICQTranslateUtfStatic(LPGEN("Enter a password for UIN %u:"), str, MAX_PATH), dwUin);
+ SetDlgItemTextUtf(hwndDlg, IDC_INSTRUCTION, pszUIN);
+
+ SendDlgItemMessage(hwndDlg, IDC_LOGINPW, EM_LIMITTEXT, PASSWORDMAXLEN - 1, 0);
+
+ CheckDlgButton(hwndDlg, IDC_SAVEPASS, ppro->getSettingByte(NULL, "RememberPass", 0));
+ }
+ break;
+
+ case WM_DESTROY:
+ ppro->m_hIconProtocol->ReleaseIcon(true);
+ ppro->m_hIconProtocol->ReleaseIcon();
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ ppro->m_bRememberPwd = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SAVEPASS);
+ ppro->setSettingByte(NULL, "RememberPass", ppro->m_bRememberPwd);
+
+ GetDlgItemTextA(hwndDlg, IDC_LOGINPW, ppro->m_szPassword, sizeof(ppro->m_szPassword));
+
+ ppro->icq_login(ppro->m_szPassword);
+
+ EndDialog(hwndDlg, IDOK);
+ break;
+
+ case IDCANCEL:
+ ppro->SetCurrentStatus(ID_STATUS_OFFLINE);
+ EndDialog(hwndDlg, IDCANCEL);
+ break;
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+void CIcqProto::RequestPassword()
+{
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_LOGINPW), NULL, LoginPasswdDlgProc, LPARAM(this));
+}
diff --git a/protocols/IcqOscarJ/UI/loginpassword.h b/protocols/IcqOscarJ/UI/loginpassword.h
new file mode 100644
index 0000000000..cfc31a354d
--- /dev/null
+++ b/protocols/IcqOscarJ/UI/loginpassword.h
@@ -0,0 +1,36 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001,2002 Jon Keating, Richard Hughes
+// Copyright 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004,2005 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/loginpassword.h,v $
+// Revision : $Revision: 7500 $
+// Last change on : $Date: 2008-03-24 20:07:37 +0200 (Пн, 24 мар 2008) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
diff --git a/protocols/IcqOscarJ/UI/userinfotab.cpp b/protocols/IcqOscarJ/UI/userinfotab.cpp
new file mode 100644
index 0000000000..36f90347ca
--- /dev/null
+++ b/protocols/IcqOscarJ/UI/userinfotab.cpp
@@ -0,0 +1,327 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/UI/userinfotab.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Code for User details ICQ specific pages
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#define SVS_NORMAL 0
+#define SVS_ZEROISUNSPEC 2
+#define SVS_IP 3
+#define SVS_SIGNED 6
+#define SVS_ICQVERSION 8
+#define SVS_TIMESTAMP 9
+#define SVS_STATUSID 10
+
+char* MirandaVersionToString(char* szStr, int bUnicode, int v, int m);
+
+extern const char *nameXStatus[];
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void SetValue(CIcqProto* ppro, HWND hwndDlg, int idCtrl, HANDLE hContact, char* szModule, char* szSetting, int special)
+{
+ DBVARIANT dbv = {0};
+ char str[MAX_PATH];
+ char* pstr = NULL;
+ int unspecified = 0;
+ int bUtf = 0, bDbv = 0, bAlloc = 0;
+
+ dbv.type = DBVT_DELETED;
+
+ if ((hContact == NULL) && ((int)szModule<0x100))
+ {
+ dbv.type = (BYTE)szModule;
+
+ switch((int)szModule) {
+ case DBVT_BYTE:
+ dbv.cVal = (BYTE)szSetting;
+ break;
+ case DBVT_WORD:
+ dbv.wVal = (WORD)szSetting;
+ break;
+ case DBVT_DWORD:
+ dbv.dVal = (DWORD)szSetting;
+ break;
+ case DBVT_ASCIIZ:
+ dbv.pszVal = pstr = szSetting;
+ break;
+ default:
+ unspecified = 1;
+ dbv.type = DBVT_DELETED;
+ }
+ }
+ else
+ {
+ if (szModule == NULL)
+ unspecified = 1;
+ else
+ {
+ unspecified = DBGetContactSetting(hContact, szModule, szSetting, &dbv);
+ bDbv = 1;
+ }
+ }
+
+ if (!unspecified)
+ {
+ switch (dbv.type) {
+ case DBVT_BYTE:
+ unspecified = (special == SVS_ZEROISUNSPEC && dbv.bVal == 0);
+ pstr = _itoa(special == SVS_SIGNED ? dbv.cVal:dbv.bVal, str, 10);
+ break;
+
+ case DBVT_WORD:
+ if (special == SVS_ICQVERSION)
+ {
+ if (dbv.wVal != 0)
+ {
+ char szExtra[80];
+
+ null_snprintf(str, 250, "%d", dbv.wVal);
+ pstr = str;
+
+ if (hContact && ppro->IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 1))
+ {
+ ICQTranslateUtfStatic(LPGEN(" (DC Established)"), szExtra, 80);
+ strcat(str, (char*)szExtra);
+ bUtf = 1;
+ }
+ }
+ else
+ unspecified = 1;
+ }
+ else if (special == SVS_STATUSID)
+ {
+ char *pXName;
+ char *pszStatus = MirandaStatusToStringUtf(dbv.wVal);
+ BYTE bXStatus = ppro->getContactXStatus(hContact);
+
+ if (bXStatus)
+ {
+ pXName = ppro->getSettingStringUtf(hContact, DBSETTING_XSTATUS_NAME, NULL);
+ if (!strlennull(pXName))
+ { // give default name
+ pXName = ICQTranslateUtf(nameXStatus[bXStatus-1]);
+ }
+ null_snprintf(str, sizeof(str), "%s (%s)", pszStatus, pXName);
+ SAFE_FREE((void**)&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 = time2text(dbv.dVal);
+ }
+ 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 = ppro->getSettingStringUtf(hContact, szModule, szSetting, NULL);
+ bUtf = 1;
+ bAlloc = 1;
+ }
+ if (idCtrl == IDC_UIN)
+ SetDlgItemTextUtf(hwndDlg, IDC_UINSTATIC, ICQTranslateUtfStatic(LPGEN("ScreenName:"), str, MAX_PATH));
+ break;
+
+ default:
+ pstr = str;
+ strcpy(str,"???");
+ break;
+ }
+ }
+
+ EnableDlgItem(hwndDlg, idCtrl, !unspecified);
+ if (unspecified)
+ SetDlgItemTextUtf(hwndDlg, idCtrl, ICQTranslateUtfStatic(LPGEN("<not specified>"), str, MAX_PATH));
+ else if (bUtf)
+ SetDlgItemTextUtf(hwndDlg, idCtrl, pstr);
+ else
+ SetDlgItemTextA(hwndDlg, idCtrl, pstr);
+
+ if (bDbv)
+ ICQFreeVariant(&dbv);
+
+ if (bAlloc)
+ SAFE_FREE(&pstr);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR CALLBACK IcqDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_PARAMCHANGED:
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (( PSHNOTIFY* )lParam )->lParam );
+ break;
+
+ case PSN_INFOCHANGED:
+ {
+ CIcqProto* ppro = (CIcqProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ if (!ppro)
+ break;
+
+ char* szProto;
+ HANDLE hContact = (HANDLE)((LPPSHNOTIFY)lParam)->lParam;
+
+ if (hContact == NULL)
+ szProto = ppro->m_szModuleName;
+ else
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if (!szProto)
+ break;
+
+ SetValue(ppro, hwndDlg, IDC_UIN, hContact, szProto, UNIQUEIDSETTING, SVS_NORMAL);
+ SetValue(ppro, hwndDlg, IDC_ONLINESINCE, hContact, szProto, "LogonTS", SVS_TIMESTAMP);
+ SetValue(ppro, hwndDlg, IDC_IDLETIME, hContact, szProto, "IdleTS", SVS_TIMESTAMP);
+ SetValue(ppro, hwndDlg, IDC_IP, hContact, szProto, "IP", SVS_IP);
+ SetValue(ppro, hwndDlg, IDC_REALIP, hContact, szProto, "RealIP", SVS_IP);
+
+ if (hContact)
+ {
+ SetValue(ppro, hwndDlg, IDC_PORT, hContact, szProto, "UserPort", SVS_ZEROISUNSPEC);
+ SetValue(ppro, hwndDlg, IDC_VERSION, hContact, szProto, "Version", SVS_ICQVERSION);
+ SetValue(ppro, hwndDlg, IDC_MIRVER, hContact, szProto, "MirVer", SVS_ZEROISUNSPEC);
+ if (ppro->getSettingByte(hContact, "ClientID", 0))
+ ppro->setSettingDword(hContact, "TickTS", 0);
+ SetValue(ppro, hwndDlg, IDC_SYSTEMUPTIME, hContact, szProto, "TickTS", SVS_TIMESTAMP);
+ SetValue(ppro, hwndDlg, IDC_STATUS, hContact, szProto, "Status", SVS_STATUSID);
+ }
+ else
+ {
+ char str[MAX_PATH];
+
+ SetValue(ppro, hwndDlg, IDC_PORT, hContact, (char*)DBVT_WORD, (char*)ppro->wListenPort, SVS_ZEROISUNSPEC);
+ SetValue(ppro, hwndDlg, IDC_VERSION, hContact, (char*)DBVT_WORD, (char*)ICQ_VERSION, SVS_ICQVERSION);
+#if defined( _UNICODE )
+ SetValue(ppro, hwndDlg, IDC_MIRVER, hContact, (char*)DBVT_ASCIIZ, MirandaVersionToString(str, TRUE, ICQ_PLUG_VERSION, MIRANDA_VERSION), SVS_ZEROISUNSPEC);
+#else
+ SetValue(ppro, hwndDlg, IDC_MIRVER, hContact, (char*)DBVT_ASCIIZ, MirandaVersionToString(str, FALSE, ICQ_PLUG_VERSION, MIRANDA_VERSION), SVS_ZEROISUNSPEC);
+#endif
+ SetDlgItemTextUtf(hwndDlg, IDC_SUPTIME, ICQTranslateUtfStatic(LPGEN("Member since:"), str, MAX_PATH));
+ SetValue(ppro, hwndDlg, IDC_SYSTEMUPTIME, hContact, szProto, "MemberTS", SVS_TIMESTAMP);
+ SetValue(ppro, hwndDlg, IDC_STATUS, hContact, (char*)DBVT_WORD, (char*)ppro->m_iStatus, SVS_STATUSID);
+ }
+ }
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDCANCEL:
+ SendMessage(GetParent(hwndDlg),msg,wParam,lParam);
+ break;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+int CIcqProto::OnUserInfoInit(WPARAM wParam, LPARAM lParam)
+{
+ if ((!IsICQContact((HANDLE)lParam)) && lParam)
+ return 0;
+
+ OPTIONSDIALOGPAGE odp = {0};
+ odp.cbSize = sizeof(odp);
+ odp.flags = ODPF_TCHAR | ODPF_DONTTRANSLATE;
+ odp.hInstance = hInst;
+ odp.dwInitParam = LPARAM(this);
+ odp.pfnDlgProc = IcqDlgProc;
+ odp.position = -1900000000;
+ odp.ptszTitle = m_tszUserName;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_INFO_ICQ);
+ CallService( MS_USERINFO_ADDPAGE, wParam, ( LPARAM )&odp );
+
+ if (!lParam)
+ {
+ TCHAR buf[200];
+ null_snprintf(buf, SIZEOF(buf), TranslateT("%s Details"), m_tszUserName);
+ odp.ptszTitle = buf;
+
+ odp.position = -1899999999;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_INFO_CHANGEINFO);
+ odp.pfnDlgProc = ChangeInfoDlgProc;
+ CallService( MS_USERINFO_ADDPAGE, wParam, ( LPARAM )&odp );
+ }
+ return 0;
+}
diff --git a/protocols/IcqOscarJ/UI/userinfotab.h b/protocols/IcqOscarJ/UI/userinfotab.h
new file mode 100644
index 0000000000..4ba7d69e34
--- /dev/null
+++ b/protocols/IcqOscarJ/UI/userinfotab.h
@@ -0,0 +1,34 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001,2002 Jon Keating, Richard Hughes
+// Copyright 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/UI/userinfotab.h,v $
+// Revision : $Revision: 7500 $
+// Last change on : $Date: 2008-03-24 20:07:37 +0200 (Пн, 24 мар 2008) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
diff --git a/protocols/IcqOscarJ/capabilities.cpp b/protocols/IcqOscarJ/capabilities.cpp
new file mode 100644
index 0000000000..f0781d5f97
--- /dev/null
+++ b/protocols/IcqOscarJ/capabilities.cpp
@@ -0,0 +1,278 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/capabilities.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// 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"
+
+
+struct icq_capability
+{
+ DWORD capID; // A bitmask, we use it in order to save database space
+ capstr capCLSID; // A binary representation of a oscar capability
+};
+
+static const icq_capability CapabilityRecord[] =
+{
+ {CAPF_SRV_RELAY, {CAP_SRV_RELAY }},
+ {CAPF_UTF, {CAP_UTF }},
+ {CAPF_RTF, {CAP_RTF }},
+ {CAPF_CONTACTS, {CAP_CONTACTS }},
+ {CAPF_TYPING, {CAP_TYPING }},
+ {CAPF_ICQDIRECT, {CAP_ICQDIRECT }},
+ {CAPF_XTRAZ, {CAP_XTRAZ }},
+ {CAPF_OSCAR_FILE,{CAP_OSCAR_FILE}}
+};
+
+// Mask of all handled capabilities' flags
+#define CapabilityFlagsMask (CAPF_SRV_RELAY | CAPF_UTF | CAPF_RTF | CAPF_CONTACTS | CAPF_TYPING | CAPF_ICQDIRECT | CAPF_XTRAZ | CAPF_OSCAR_FILE)
+
+
+#ifdef _DEBUG
+struct icq_capability_name
+{
+ DWORD capID;
+ const char* capName;
+};
+
+static const icq_capability_name CapabilityNames[] =
+{
+ {CAPF_SRV_RELAY, "ServerRelay"},
+ {CAPF_UTF, "UTF8 Messages"},
+ {CAPF_RTF, "RTF Messages"},
+ {CAPF_CONTACTS, "Contact Transfer"},
+ {CAPF_TYPING, "Typing Notifications"},
+ {CAPF_ICQDIRECT, "Direct Connections"},
+ {CAPF_XTRAZ, "Xtraz"},
+ {CAPF_OSCAR_FILE, "File Transfers"},
+ {CAPF_STATUS_MESSAGES,"Individual Status Messages"},
+ {CAPF_STATUS_MOOD, "Mood"},
+ {CAPF_XSTATUS, "Custom Status"}
+};
+
+void NetLog_CapabilityChange(CIcqProto *ppro, const char *szChange, DWORD fdwCapabilities)
+{
+ char szBuffer[MAX_PATH] = {0};
+
+ if (!fdwCapabilities) return;
+
+ for (int nIndex = 0; nIndex < SIZEOF(CapabilityNames); nIndex++)
+ {
+ // Check if the current capability is present
+ if ((fdwCapabilities & CapabilityNames[nIndex].capID) == CapabilityNames[nIndex].capID)
+ {
+ if (strlennull(szBuffer))
+ strcat(szBuffer, ", ");
+ strcat(szBuffer, CapabilityNames[nIndex].capName);
+ }
+ }
+ // Log the change
+ ppro->NetLog_Server("Capabilities: %s %s", szChange, szBuffer);
+}
+#endif
+
+
+// Deletes all oscar capabilities for a given contact
+void CIcqProto::ClearAllContactCapabilities(HANDLE hContact)
+{
+ setSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+}
+
+
+// Deletes one or many oscar capabilities for a given contact
+void CIcqProto::ClearContactCapabilities(HANDLE hContact, DWORD fdwCapabilities)
+{
+ // Get current capability flags
+ DWORD fdwContactCaps = getSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+
+ if (fdwContactCaps != (fdwContactCaps & ~fdwCapabilities))
+ {
+#ifdef _DEBUG
+ NetLog_CapabilityChange(this, "Removed", fdwCapabilities & fdwContactCaps);
+#endif
+ // Clear unwanted capabilities
+ fdwContactCaps &= ~fdwCapabilities;
+
+ // And write it back to disk
+ setSettingDword(hContact, DBSETTING_CAPABILITIES, fdwContactCaps);
+ }
+}
+
+
+// Sets one or many oscar capabilities for a given contact
+void CIcqProto::SetContactCapabilities(HANDLE hContact, DWORD fdwCapabilities)
+{
+ // Get current capability flags
+ DWORD fdwContactCaps = getSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+
+ if (fdwContactCaps != (fdwContactCaps | fdwCapabilities))
+ {
+#ifdef _DEBUG
+ NetLog_CapabilityChange(this, "Added", fdwCapabilities & ~fdwContactCaps);
+#endif
+ // Update them
+ fdwContactCaps |= fdwCapabilities;
+
+ // And write it back to disk
+ setSettingDword(hContact, DBSETTING_CAPABILITIES, fdwContactCaps);
+ }
+}
+
+
+// Returns true if the given contact supports the requested capabilites
+BOOL CIcqProto::CheckContactCapabilities(HANDLE hContact, DWORD fdwCapabilities)
+{
+ // Get current capability flags
+ DWORD fdwContactCaps = getSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+
+ // Check if all requested capabilities are supported
+ if ((fdwContactCaps & fdwCapabilities) == fdwCapabilities)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+// Scan capability against the capability buffer
+capstr* MatchCapability(BYTE *buf, int bufsize, const capstr *cap, int capsize)
+{
+ while (bufsize >= BINARY_CAP_SIZE) // search the buffer for a capability
+ {
+ if (!memcmp(buf, cap, capsize))
+ {
+ return (capstr*)buf; // give found capability for version info
+ }
+ else
+ {
+ buf += BINARY_CAP_SIZE;
+ bufsize -= BINARY_CAP_SIZE;
+ }
+ }
+ return 0;
+}
+
+
+// Scan short capability against the capability buffer
+capstr* MatchShortCapability(BYTE *buf, int bufsize, const shortcapstr *cap)
+{
+ capstr fullCap;
+
+ memcpy(fullCap, capShortCaps, BINARY_CAP_SIZE);
+ fullCap[2] = (*cap)[0];
+ fullCap[3] = (*cap)[1];
+
+ return MatchCapability(buf, bufsize, &fullCap, BINARY_CAP_SIZE);
+}
+
+
+// Scans a binary buffer for OSCAR capabilities.
+DWORD GetCapabilitiesFromBuffer(BYTE *pBuffer, int nLength)
+{
+ DWORD fdwCaps = 0;
+
+ // Calculate the number of records
+ int nRecordSize = SIZEOF(CapabilityRecord);
+
+ // Loop over all capabilities in the buffer and
+ // compare them to our own record of capabilities
+ for (int nIndex = 0; nIndex < nRecordSize; nIndex++)
+ {
+ if (MatchCapability(pBuffer, nLength, &CapabilityRecord[nIndex].capCLSID, BINARY_CAP_SIZE))
+ { // Match, add capability flag
+ fdwCaps |= CapabilityRecord[nIndex].capID;
+ }
+ }
+
+ return fdwCaps;
+}
+
+
+// Scans a binary buffer for oscar capabilities and adds them to the contact.
+// You probably want to call ClearAllContactCapabilities() first.
+void CIcqProto::AddCapabilitiesFromBuffer(HANDLE hContact, BYTE *pBuffer, int nLength)
+{
+ // Get current capability flags
+ DWORD fdwContactCaps = getSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+ // Get capability flags from buffer
+ DWORD fdwCapabilities = GetCapabilitiesFromBuffer(pBuffer, nLength);
+
+ if (fdwContactCaps != (fdwContactCaps | fdwCapabilities))
+ {
+#ifdef _DEBUG
+ NetLog_CapabilityChange(this, "Added", fdwCapabilities & ~fdwContactCaps);
+#endif
+ // Add capability flags from buffer
+ fdwContactCaps |= fdwCapabilities;
+
+ // And write them back to database
+ setSettingDword(hContact, DBSETTING_CAPABILITIES, fdwContactCaps);
+ }
+}
+
+
+// Scans a binary buffer for oscar capabilities and adds them to the contact.
+// You probably want to call ClearAllContactCapabilities() first.
+void CIcqProto::SetCapabilitiesFromBuffer(HANDLE hContact, BYTE *pBuffer, int nLength, BOOL bReset)
+{
+ // Get current capability flags
+ DWORD fdwContactCaps = bReset ? 0 : getSettingDword(hContact, DBSETTING_CAPABILITIES, 0);
+ // Get capability flags from buffer
+ DWORD fdwCapabilities = GetCapabilitiesFromBuffer(pBuffer, nLength);
+
+#ifdef _DEBUG
+ if (bReset)
+ NetLog_CapabilityChange(this, "Set", fdwCapabilities);
+ else
+ {
+ NetLog_CapabilityChange(this, "Removed", fdwContactCaps & ~fdwCapabilities & CapabilityFlagsMask);
+ NetLog_CapabilityChange(this, "Added", fdwCapabilities & ~fdwContactCaps);
+ }
+#endif
+
+ if (fdwCapabilities != (fdwContactCaps & ~CapabilityFlagsMask))
+ { // Get current unmanaged capability flags
+ fdwContactCaps &= ~CapabilityFlagsMask;
+
+ // Add capability flags from buffer
+ fdwContactCaps |= fdwCapabilities;
+
+ // And write them back to database
+ setSettingDword(hContact, DBSETTING_CAPABILITIES, fdwContactCaps);
+ }
+}
diff --git a/protocols/IcqOscarJ/capabilities.h b/protocols/IcqOscarJ/capabilities.h
new file mode 100644
index 0000000000..7ea66d41c2
--- /dev/null
+++ b/protocols/IcqOscarJ/capabilities.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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/capabilities.h $
+// Revision : $Revision: 11353 $
+// Last change on : $Date: 2010-03-10 02:21:03 +0200 (Ср, 10 мар 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Contains helper functions to handle OSCAR user capabilities.
+//
+// -----------------------------------------------------------------------------
+
+
+#ifndef __CAPABILITIES_H
+#define __CAPABILITIES_H
+
+
+// capabilities
+typedef BYTE capstr[BINARY_CAP_SIZE];
+typedef BYTE shortcapstr[BINARY_SHORT_CAP_SIZE];
+
+extern const capstr capShortCaps;
+
+capstr* MatchCapability(BYTE *buf, int bufsize, const capstr *cap, int capsize = BINARY_CAP_SIZE);
+capstr* MatchShortCapability(BYTE *buf, int bufsize, const shortcapstr *cap);
+
+
+#endif /* __CAPABILITIES_H */
diff --git a/protocols/IcqOscarJ/chan_01login.cpp b/protocols/IcqOscarJ/chan_01login.cpp
new file mode 100644
index 0000000000..8fdeceda22
--- /dev/null
+++ b/protocols/IcqOscarJ/chan_01login.cpp
@@ -0,0 +1,112 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/chan_01login.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void CIcqProto::handleLoginChannel(BYTE *buf, WORD datalen, serverthread_info *info)
+{
+ icq_packet packet;
+
+#ifdef _DEBUG
+ NetLog_Server("Received SRV_HELLO from %s", info->isLoginServer ? "login server" : "communication server");
+#endif
+
+ // isLoginServer is "1" if we just received SRV_HELLO
+ if (info->isLoginServer)
+ {
+ if (m_bSecureLogin)
+ {
+ char szUin[UINMAXLEN];
+ WORD wUinLen;
+
+#ifdef _DEBUG
+ NetLog_Server("Sending %s to %s", "CLI_HELLO", "login server");
+#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(m_dwLocalUIN, szUin));
+#ifdef _DEBUG
+ NetLog_Server("Sending %s to %s", "ICQ_SIGNON_AUTH_REQUEST", "login server");
+#endif
+
+ serverPacketInit(&packet, (WORD)(14 + wUinLen));
+ packFNACHeader(&packet, ICQ_AUTHORIZATION_FAMILY, ICQ_SIGNON_AUTH_REQUEST, 0, 0);
+ packTLV(&packet, 0x0001, wUinLen, (LPBYTE)szUin);
+ sendServPacket(&packet); // request login digest
+ }
+ else
+ {
+ sendClientAuth((char*)info->szAuthKey, info->wAuthKeyLen, FALSE);
+#ifdef _DEBUG
+ NetLog_Server("Sent CLI_IDENT to %s", "login server");
+#endif
+ }
+
+ info->isLoginServer = 0;
+ if (info->cookieDataLen)
+ {
+ SAFE_FREE((void**)&info->cookieData);
+ info->cookieDataLen = 0;
+ }
+ }
+ else
+ {
+ if (info->cookieDataLen)
+ {
+ wLocalSequence = generate_flap_sequence();
+
+ serverCookieInit(&packet, info->cookieData, (WORD)info->cookieDataLen);
+ sendServPacket(&packet);
+
+#ifdef _DEBUG
+ NetLog_Server("Sent CLI_IDENT to %s", "communication server");
+#endif
+
+ SAFE_FREE((void**)&info->cookieData);
+ info->cookieDataLen = 0;
+ }
+ else
+ {
+ // We need a cookie to identify us to the communication server
+ NetLog_Server("Error: Connected to %s without a cookie!", "communication server");
+ }
+ }
+}
diff --git a/protocols/IcqOscarJ/chan_02data.cpp b/protocols/IcqOscarJ/chan_02data.cpp
new file mode 100644
index 0000000000..991558474f
--- /dev/null
+++ b/protocols/IcqOscarJ/chan_02data.cpp
@@ -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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/chan_02data.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Handle channel 2 (Data) packets
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void CIcqProto::handleDataChannel(BYTE *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
+ if (snacHeader.wFlags & 0x8000)
+ NetLog_Server(" Received SNAC(x%02X,x%02X), version %u", snacHeader.wFamily, snacHeader.wSubtype, snacHeader.wVersion);
+ else
+ 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, BYTE **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 CIcqProto::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 is too evil"; break;
+ case 0x12: msg = "Receiver is 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 0x1C: msg = "General failure"; break;
+ case 0x1D: msg = "Progress"; break;
+ case 0x1E: msg = "In free area"; break;
+ case 0x1F: msg = "Restricted by parental controls"; break;
+ case 0x20: msg = "Remote restricted by parental controls"; break;
+ default: msg = ""; break;
+ }
+
+ NetLog_Server("SNAC(x%02X,x01) - Error(%u): %s", wFamily, wError, msg);
+}
diff --git a/protocols/IcqOscarJ/chan_03error.cpp b/protocols/IcqOscarJ/chan_03error.cpp
new file mode 100644
index 0000000000..5a67b0f95d
--- /dev/null
+++ b/protocols/IcqOscarJ/chan_03error.cpp
@@ -0,0 +1,42 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001,2002 Jon Keating, Richard Hughes
+// Copyright 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004,2005 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/chan_03error.c,v $
+// Revision : $Revision: 7500 $
+// Last change on : $Date: 2008-03-24 20:07:37 +0200 (Пн, 24 мар 2008) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+void CIcqProto::handleErrorChannel(unsigned char* buf, WORD datalen)
+{
+ NetLog_Server("Ignoring server packet on ERROR channel");
+}
diff --git a/protocols/IcqOscarJ/chan_04close.cpp b/protocols/IcqOscarJ/chan_04close.cpp
new file mode 100644
index 0000000000..744d0316a3
--- /dev/null
+++ b/protocols/IcqOscarJ/chan_04close.cpp
@@ -0,0 +1,321 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/chan_04close.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void CIcqProto::handleCloseChannel(BYTE *buf, WORD datalen, serverthread_info *info)
+{
+ oscar_tlv_chain *chain = NULL;
+
+ // 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(), LPGEN("Unable to connect to migrated ICQ communication server"));
+ else
+ icq_LogUsingErrorCode(LOG_ERROR, GetLastError(), LPGEN("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?)
+ WORD wError = chain->getWord(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 CIcqProto::handleLoginReply(BYTE *buf, WORD datalen, serverthread_info *info)
+{
+ oscar_tlv_chain *chain = NULL;
+
+ 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?)
+ WORD wError = chain->getWord(0x08, 1);
+ if (wError)
+ {
+ handleSignonError(wError);
+
+ // we return only if the server did not gave us cookie (possible to connect with soft error)
+ if (!chain->getLength(0x06, 1))
+ {
+ disposeChain(&chain);
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ icq_serverDisconnect(FALSE);
+ return; // Failure
+ }
+ }
+
+ // We are in the login phase and no errors were reported.
+ // Extract communication server info.
+ info->newServer = chain->getString(0x05, 1);
+ info->newServerSSL = chain->getNumber(0x8E, 1);
+ info->cookieData = (BYTE*)chain->getString(0x06, 1);
+ info->cookieDataLen = chain->getLength(0x06, 1);
+
+ // We dont need this anymore
+ disposeChain(&chain);
+
+ if (!info->newServer || !info->cookieData)
+ {
+ icq_LogMessage(LOG_FATAL, LPGEN("You could not sign on because the server returned invalid data. Try again."));
+
+ SAFE_FREE(&info->newServer);
+ SAFE_FREE((void**)&info->cookieData);
+ info->cookieDataLen = 0;
+
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ NetLib_CloseConnection(&hServerConn, TRUE);
+ return; // Failure
+ }
+
+ NetLog_Server("Authenticated.");
+ info->newServerReady = 1;
+
+ return;
+}
+
+
+int CIcqProto::connectNewServer(serverthread_info *info)
+{
+ int res = 0;
+
+ /* Get the ip and port */
+ WORD wServerPort = info->wServerPort; // prepare default port
+ parseServerAddress(info->newServer, &wServerPort);
+
+ NETLIBOPENCONNECTION nloc = {0};
+ nloc.flags = 0;
+ nloc.szHost = info->newServer;
+ nloc.wPort = wServerPort;
+
+ if (!m_bGatewayMode)
+ {
+ NetLib_SafeCloseHandle(&info->hPacketRecver);
+ NetLib_CloseConnection(&hServerConn, TRUE);
+
+ NetLog_Server("Closed connection to login server");
+
+ hServerConn = NetLib_OpenConnection(m_hServerNetlibUser, NULL, &nloc);
+ if (hServerConn && info->newServerSSL)
+ { /* Start SSL session if requested */
+ if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)hServerConn, 0))
+ NetLib_CloseConnection(&hServerConn, FALSE);
+ }
+
+ 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((void**)&info->cookieData);
+
+ // Free allocated memory
+ // NOTE: "cookie" will get freed when we have connected to the communication server.
+ SAFE_FREE(&info->newServer);
+
+ return res;
+}
+
+
+void CIcqProto::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, LPGEN("You have been disconnected from the ICQ network because the current server shut down."));
+
+ SAFE_FREE(&info->newServer);
+ SAFE_FREE((void**)&info->cookieData);
+ info->newServerReady = 0;
+ info->isMigrating = 0;
+ }
+}
+
+void CIcqProto::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
+ BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPASSWORD);
+ ZeroMemory(m_szPassword, sizeof(m_szPassword));
+ icq_LogFatalParam(LPGEN("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
+ BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NOSERVER);
+ icq_LogFatalParam(LPGEN("Connection failed.\nThe server is temporarily unavailable (%d)."), wError);
+ break;
+
+ case 0x16: // The users num connected from this IP has reached the maximum
+ case 0x17: // The users num connected from this IP has reached the maximum (reserved)
+ icq_LogFatalParam(LPGEN("Connection failed.\nServer has too many connections from your IP (%d)."), wError);
+ break;
+
+ case 0x18: // Reservation rate limit exceeded
+ case 0x1D: // Rate limit exceeded
+ BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NOSERVER);
+ icq_LogFatalParam(LPGEN("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
+ BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPROTOCOL);
+ icq_LogMessage(LOG_FATAL, LPGEN("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, LPGEN("The server sent warning, this version is getting old.\nTry to look for a new one."));
+ break;
+
+ case 0x1E: // Can't register on the ICQ network
+ icq_LogMessage(LOG_FATAL, LPGEN("Connection failed.\nYou were rejected by the server for an unknown reason.\nThis can happen if the UIN is already connected."));
+ break;
+
+ case 0x0C: // Invalid database fields, MD5 login not supported
+ icq_LogMessage(LOG_FATAL, LPGEN("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(LPGEN("Connection failed.\nUnknown error during sign on: 0x%02x"), wError);
+ break;
+ }
+}
+
+
+void CIcqProto::handleRuntimeError(WORD wError)
+{
+ switch (wError)
+ {
+
+ case 0x01:
+ {
+ BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_OTHERLOCATION);
+ icq_LogMessage(LOG_FATAL, LPGEN("You have been disconnected from the ICQ network because you logged on from another location using the same ICQ number."));
+ break;
+ }
+
+ default:
+ icq_LogFatalParam(LPGEN("Unknown runtime error: 0x%02x"), wError);
+ break;
+ }
+}
diff --git a/protocols/IcqOscarJ/chan_05ping.cpp b/protocols/IcqOscarJ/chan_05ping.cpp
new file mode 100644
index 0000000000..ac0dc1d87f
--- /dev/null
+++ b/protocols/IcqOscarJ/chan_05ping.cpp
@@ -0,0 +1,103 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/chan_05ping.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void CIcqProto::handlePingChannel(BYTE *buf, WORD datalen)
+{
+ NetLog_Server("Warning: Ignoring server packet on PING channel");
+}
+
+
+void __cdecl CIcqProto::KeepAliveThread(void *arg)
+{
+ serverthread_info *info = (serverthread_info*)arg;
+ icq_packet packet;
+ DWORD dwInterval = getSettingDword(NULL, "KeepAliveInterval", KEEPALIVE_INTERVAL);
+
+ NetLog_Server("Keep alive thread starting.");
+
+ info->hKeepAliveEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ for(;;)
+ {
+ DWORD dwWait = ICQWaitForSingleObject(info->hKeepAliveEvent, dwInterval);
+ if (serverThreadHandle == NULL) // connection lost, end
+ break;
+ if (dwWait == WAIT_TIMEOUT)
+ {
+ // Send a keep alive packet to server
+ packet.wLen = 0;
+ write_flap(&packet, ICQ_PING_CHAN);
+ sendServPacket(&packet);
+ }
+ else if (dwWait == WAIT_IO_COMPLETION)
+ // Possible shutdown in progress
+ if (Miranda_Terminated()) break;
+ else
+ break;
+ }
+
+ NetLog_Server("Keep alive thread shutting down.");
+
+ CloseHandle(info->hKeepAliveEvent);
+ info->hKeepAliveEvent = NULL;
+}
+
+
+void CIcqProto::StartKeepAlive(serverthread_info *info)
+{
+ if (info->hKeepAliveEvent) // start only once
+ return;
+
+ if (getSettingByte(NULL, "KeepAlive", DEFAULT_KEEPALIVE_ENABLED))
+ info->hKeepAliveThread = ForkThreadEx(&CIcqProto::KeepAliveThread, info);
+}
+
+
+void CIcqProto::StopKeepAlive(serverthread_info *info)
+{ // finish keep alive thread
+ if (info->hKeepAliveEvent)
+ {
+ SetEvent(info->hKeepAliveEvent);
+
+ // wait for the thread to finish
+ ICQWaitForSingleObject(info->hKeepAliveThread, INFINITE, TRUE);
+ CloseHandle(info->hKeepAliveThread);
+ info->hKeepAliveThread = NULL;
+ }
+}
diff --git a/protocols/IcqOscarJ/changeinfo/changeinfo.h b/protocols/IcqOscarJ/changeinfo/changeinfo.h
new file mode 100644
index 0000000000..ed1005ba5f
--- /dev/null
+++ b/protocols/IcqOscarJ/changeinfo/changeinfo.h
@@ -0,0 +1,129 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2001-2004 Richard Hughes, Martin berg
+// Copyright 2004-2010 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/changeinfo/changeinfo.h $
+// Revision : $Revision: 12945 $
+// Last change on : $Date: 2010-10-13 06:48:50 +0200 (Ср, 13 окт 2010) $
+// Last change by : $Author: borkra $
+//
+// 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
+
+struct SettingItem
+{
+ const char *szDescription;
+ unsigned displayType; //LI_ constant
+ int dbType; //DBVT_ constant
+ const char *szDbSetting;
+ const void *pList;
+};
+
+struct SettingItemData
+{
+ LPARAM value;
+ int changed;
+};
+
+// contants.c
+extern const SettingItem setting[];
+extern const int settingCount;
+
+//dlgproc.c
+struct ChangeInfoData : public void_struct
+{
+ HWND hwndDlg;
+ CIcqProto *ppro;
+ HFONT hListFont;
+ HWND hwndList;
+ int editTopIndex;
+ int iEditItem;
+ char Password[PASSWORDMAXLEN];
+
+ SettingItemData *settingData;
+
+ HANDLE hAckHook;
+ HANDLE hUpload[2];
+
+ ChangeInfoData() { settingData = (SettingItemData*)SAFE_MALLOC(sizeof(SettingItemData) * settingCount); hAckHook = NULL; hUpload[0] = NULL; hUpload[1] = NULL;}
+ ~ChangeInfoData() { SAFE_FREE((void**)&settingData); }
+
+ char* GetItemSettingText(int i, char *buf, size_t buf_size);
+ void PaintItemSetting(HDC hdc, RECT *rc, int i, UINT itemState);
+
+ //db.cpp
+ void LoadSettingsFromDb(int keepChanged);
+ void FreeStoredDbSettings(void);
+ int ChangesMade(void);
+ void ClearChangeFlags(void);
+ int SaveSettingsToDb(HWND hwndDlg);
+
+ //upload.cpp
+ int UploadSettings(void);
+
+ //editstring.cpp
+ void BeginStringEdit(int iItem,RECT *rc,int i,WORD wVKey);
+ void EndStringEdit(int save);
+ //editlist.cpp
+ void BeginListEdit(int iItem, RECT *rc, int iSetting, WORD wVKey);
+ void EndListEdit(int save);
+};
+
+INT_PTR CALLBACK ChangeInfoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+//editstring.c
+int IsStringEditWindow(HWND hwnd);
+char* BinaryToEscapes(char *str);
+
+//editlist.c
+int IsListEditWindow(HWND hwnd);
+
+#endif /* __CHANGEINFO_H */
diff --git a/protocols/IcqOscarJ/changeinfo/constants.cpp b/protocols/IcqOscarJ/changeinfo/constants.cpp
new file mode 100644
index 0000000000..eaf402a9b0
--- /dev/null
+++ b/protocols/IcqOscarJ/changeinfo/constants.cpp
@@ -0,0 +1,205 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2001-2004 Richard Hughes, Martin berg
+// Copyright 2004-2009 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/changeinfo/constants.cpp $
+// Revision : $Revision: 8822 $
+// Last change on : $Date: 2009-01-11 19:17:05 +0200 (Вс, 11 янв 2009) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static FieldNamesItem timezones[]={
+ {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.")},
+ {-100,NULL}
+};
+
+
+static FieldNamesItem months[]={
+ {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")},
+ {0, NULL}
+};
+
+
+const int ageRange[]={13,0x7FFF}; // 14, 130
+const int yearRange[]={1753,0x7FFF}; // 1880, 2000
+const int dayRange[]={1,31};
+
+
+const SettingItem setting[]={
+ //personal
+ {LPGEN("Personal"), LI_DIVIDER},
+ {LPGEN("Nickname"), LI_STRING, DBVT_UTF8, "Nick"},
+ {LPGEN("First name"), LI_STRING, DBVT_UTF8, "FirstName"},
+ {LPGEN("Last name"), LI_STRING, DBVT_UTF8, "LastName"},
+// {LPGEN("Age"), LI_NUMBER, DBVT_WORD, "Age", ageRange},
+ {LPGEN("Gender"), LI_LIST, DBVT_BYTE, "Gender", genderField},
+ {LPGEN("About"), LI_LONGSTRING, DBVT_UTF8, "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-mail0"},
+ {LPGEN("Secondary e-mail"), LI_STRING, DBVT_ASCIIZ, "e-mail1"},
+ {LPGEN("Tertiary e-mail"), LI_STRING, DBVT_ASCIIZ, "e-mail2"},
+ {LPGEN("Homepage"), LI_STRING, DBVT_ASCIIZ, "Homepage"},
+ {LPGEN("Street"), LI_STRING, DBVT_UTF8, "Street"},
+ {LPGEN("City"), LI_STRING, DBVT_UTF8, "City"},
+ {LPGEN("State"), LI_STRING, DBVT_UTF8, "State"},
+ {LPGEN("ZIP/postcode"), LI_STRING, DBVT_UTF8, "ZIP"},
+ {LPGEN("Country"), LI_LIST, DBVT_WORD, "Country", countryField},
+ {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},
+ {LPGEN("Year of birth"), LI_NUMBER, DBVT_WORD, "BirthYear", yearRange},
+ {LPGEN("Month of birth"), LI_LIST, DBVT_BYTE, "BirthMonth", months},
+ {LPGEN("Day of birth"), LI_NUMBER, DBVT_BYTE, "BirthDay", dayRange},
+ {LPGEN("Marital Status"), LI_LIST, DBVT_BYTE, "MaritalStatus", maritalField},
+ {LPGEN("Spoken language 1"), LI_LIST, DBVT_BYTE, "Language1", languageField},
+ {LPGEN("Spoken language 2"), LI_LIST, DBVT_BYTE, "Language2", languageField},
+ {LPGEN("Spoken language 3"), LI_LIST, DBVT_BYTE, "Language3", languageField},
+ //more
+ {LPGEN("Originally from"),LI_DIVIDER},
+ {LPGEN("Street"), LI_STRING, DBVT_UTF8, "OriginStreet"},
+ {LPGEN("City"), LI_STRING, DBVT_UTF8, "OriginCity"},
+ {LPGEN("State"), LI_STRING, DBVT_UTF8, "OriginState"},
+ {LPGEN("Country"), LI_LIST, DBVT_WORD, "OriginCountry", countryField},
+ //study
+ {LPGEN("Education"), LI_DIVIDER},
+ {LPGEN("Level"), LI_LIST, DBVT_WORD, "StudyLevel", studyLevelField},
+ {LPGEN("Institute"), LI_STRING, DBVT_UTF8, "StudyInstitute"},
+ {LPGEN("Degree"), LI_STRING, DBVT_UTF8, "StudyDegree"},
+ {LPGEN("Graduation Year"),LI_NUMBER, DBVT_WORD, "StudyYear", yearRange},
+ //work
+ {LPGEN("Work"), LI_DIVIDER},
+ {LPGEN("Company name"), LI_STRING, DBVT_UTF8, "Company"},
+ {LPGEN("Company homepage"),LI_STRING, DBVT_ASCIIZ, "CompanyHomepage"},
+ {LPGEN("Company street"), LI_STRING, DBVT_UTF8, "CompanyStreet"},
+ {LPGEN("Company city"), LI_STRING, DBVT_UTF8, "CompanyCity"},
+ {LPGEN("Company state"), LI_STRING, DBVT_UTF8, "CompanyState"},
+ {LPGEN("Company phone"), LI_STRING, DBVT_ASCIIZ, "CompanyPhone"},
+ {LPGEN("Company fax"), LI_STRING, DBVT_ASCIIZ, "CompanyFax"},
+ {LPGEN("Company ZIP/postcode"),LI_STRING,DBVT_UTF8, "CompanyZIP"},
+ {LPGEN("Company country"),LI_LIST, DBVT_WORD, "CompanyCountry", countryField},
+ {LPGEN("Company department"),LI_STRING, DBVT_UTF8, "CompanyDepartment"},
+ {LPGEN("Company position"),LI_STRING, DBVT_UTF8, "CompanyPosition"},
+ {LPGEN("Company industry"),LI_LIST, DBVT_WORD, "CompanyIndustry", industryField},
+// {LPGEN("Company occupation"),LI_LIST, DBVT_WORD, "CompanyOccupation", occupationField},
+ //interests
+ {LPGEN("Personal Interests"), LI_DIVIDER},
+ {LPGEN("Interest category 1"),LI_LIST, DBVT_WORD, "Interest0Cat", interestsField},
+ {LPGEN("Interest areas 1"),LI_STRING, DBVT_ASCIIZ, "Interest0Text"},
+ {LPGEN("Interest category 2"),LI_LIST, DBVT_WORD, "Interest1Cat", interestsField},
+ {LPGEN("Interest areas 2"),LI_STRING, DBVT_ASCIIZ, "Interest1Text"},
+ {LPGEN("Interest category 3"),LI_LIST, DBVT_WORD, "Interest2Cat", interestsField},
+ {LPGEN("Interest areas 3"),LI_STRING, DBVT_ASCIIZ, "Interest2Text"},
+ {LPGEN("Interest category 4"),LI_LIST, DBVT_WORD, "Interest3Cat", interestsField},
+ {LPGEN("Interest areas 4"),LI_STRING, DBVT_ASCIIZ, "Interest3Text"},
+ //pastbackground
+// {LPGEN("Past Background"), LI_DIVIDER},
+// {LPGEN("Category 1"), LI_LIST, DBVT_ASCIIZ, "Past0", pastField},
+// {LPGEN("Past Background 1"),LI_STRING, DBVT_ASCIIZ, "Past0Text"},
+// {LPGEN("Category 2"), LI_LIST, DBVT_ASCIIZ, "Past1", pastField},
+// {LPGEN("Past Background 2"),LI_STRING, DBVT_ASCIIZ, "Past1Text"},
+// {LPGEN("Category 3"), LI_LIST, DBVT_ASCIIZ, "Past2", pastField},
+// {LPGEN("Past Background 3"),LI_STRING, DBVT_ASCIIZ, "Past2Text"},
+ //affiliation
+// {LPGEN("Affiliations"), LI_DIVIDER},
+// {LPGEN("Affiliation category 1"),LI_LIST,DBVT_ASCIIZ, "Affiliation0", affiliationField},
+// {LPGEN("Affiliation 1"), LI_STRING, DBVT_ASCIIZ, "Affiliation0Text"},
+// {LPGEN("Affiliation category 2"),LI_LIST,DBVT_ASCIIZ, "Affiliation1", affiliationField},
+// {LPGEN("Affiliation 2"), LI_STRING, DBVT_ASCIIZ, "Affiliation1Text"},
+// {LPGEN("Affiliation category 3"),LI_LIST,DBVT_ASCIIZ, "Affiliation2", affiliationField},
+// {LPGEN("Affiliation 3"), LI_STRING, DBVT_ASCIIZ, "Affiliation2Text"}
+};
+
+const int settingCount = SIZEOF(setting);
diff --git a/protocols/IcqOscarJ/changeinfo/db.cpp b/protocols/IcqOscarJ/changeinfo/db.cpp
new file mode 100644
index 0000000000..c9af84339d
--- /dev/null
+++ b/protocols/IcqOscarJ/changeinfo/db.cpp
@@ -0,0 +1,231 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2001-2004 Richard Hughes, Martin berg
+// Copyright 2004-2009 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/changeinfo/db.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void ChangeInfoData::LoadSettingsFromDb(int keepChanged)
+{
+ for (int i=0; i < settingCount; i++)
+ {
+ if (setting[i].displayType == LI_DIVIDER) continue;
+ if (keepChanged && settingData[i].changed) continue;
+ if (setting[i].dbType == DBVT_ASCIIZ || setting[i].dbType == DBVT_UTF8)
+ SAFE_FREE((void**)(char**)&settingData[i].value);
+ else if (!keepChanged)
+ settingData[i].value = 0;
+
+ settingData[i].changed = 0;
+
+ if (setting[i].displayType & LIF_PASSWORD) continue;
+
+ DBVARIANT dbv = {DBVT_DELETED};
+ if (!ppro->getSetting(NULL, setting[i].szDbSetting, &dbv))
+ {
+ switch(dbv.type) {
+ case DBVT_ASCIIZ:
+ settingData[i].value = (LPARAM)ppro->getSettingStringUtf(NULL, setting[i].szDbSetting, NULL);
+ break;
+
+ case DBVT_UTF8:
+ settingData[i].value = (LPARAM)null_strdup(dbv.pszVal);
+ break;
+
+ case DBVT_WORD:
+ if (setting[i].displayType & LIF_SIGNED)
+ settingData[i].value = dbv.sVal;
+ else
+ settingData[i].value = dbv.wVal;
+ break;
+
+ case DBVT_BYTE:
+ if (setting[i].displayType & LIF_SIGNED)
+ settingData[i].value = dbv.cVal;
+ else
+ settingData[i].value = dbv.bVal;
+ break;
+
+#ifdef _DEBUG
+ default:
+ MessageBoxA(NULL, "That's not supposed to happen either", "Huh?", MB_OK);
+ break;
+#endif
+ }
+ ICQFreeVariant(&dbv);
+ }
+
+ char buf[MAX_PATH];
+ TCHAR tbuf[MAX_PATH];
+
+ if (utf8_to_tchar_static(GetItemSettingText(i, buf, SIZEOF(buf)), tbuf, SIZEOF(tbuf)))
+ ListView_SetItemText(hwndList, i, 1, tbuf);
+ }
+}
+
+
+void ChangeInfoData::FreeStoredDbSettings(void)
+{
+ for (int i=0; i < settingCount; i++ )
+ if (setting[i].dbType == DBVT_ASCIIZ || setting[i].dbType == DBVT_UTF8)
+ SAFE_FREE((void**)&settingData[i].value);
+}
+
+
+int ChangeInfoData::ChangesMade(void)
+{
+ for (int i=0; i < settingCount; i++ )
+ if (settingData[i].changed)
+ return 1;
+ return 0;
+}
+
+
+void ChangeInfoData::ClearChangeFlags(void)
+{
+ for (int i=0; i < settingCount; i++)
+ settingData[i].changed = 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct PwConfirmDlgParam
+{
+ CIcqProto* ppro;
+ char* Pass;
+};
+
+static INT_PTR CALLBACK PwConfirmDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ PwConfirmDlgParam* dat = (PwConfirmDlgParam*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 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, dat->ppro->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, dat->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 ChangeInfoData::SaveSettingsToDb(HWND hwndDlg)
+{
+ int ret = 1;
+
+ for (int i = 0; i < settingCount; i++)
+ {
+ if (!settingData[i].changed) continue;
+ if (!(setting[i].displayType & LIF_ZEROISVALID) && settingData[i].value==0)
+ {
+ ppro->deleteSetting(NULL, setting[i].szDbSetting);
+ continue;
+ }
+ switch(setting[i].dbType) {
+ case DBVT_ASCIIZ:
+ if (setting[i].displayType & LIF_PASSWORD)
+ {
+ int nSettingLen = strlennull((char*)settingData[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;
+ }
+ PwConfirmDlgParam param = { ppro, (char*)settingData[i].value };
+ if (IDOK != DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_PWCONFIRM), hwndDlg, PwConfirmDlgProc, (LPARAM)&param))
+ {
+ ret = 0;
+ break;
+ }
+ strcpy(ppro->m_szPassword, (char*)settingData[i].value);
+ }
+ else {
+ if (*(char*)settingData[i].value)
+ ppro->setSettingStringUtf(NULL, setting[i].szDbSetting, (char*)settingData[i].value);
+ else
+ ppro->deleteSetting(NULL, setting[i].szDbSetting);
+ }
+ break;
+
+ case DBVT_UTF8:
+ if (*(char*)settingData[i].value)
+ ppro->setSettingStringUtf(NULL, setting[i].szDbSetting, (char*)settingData[i].value);
+ else
+ ppro->deleteSetting(NULL, setting[i].szDbSetting);
+ break;
+
+ case DBVT_WORD:
+ ppro->setSettingWord(NULL, setting[i].szDbSetting, (WORD)settingData[i].value);
+ break;
+
+ case DBVT_BYTE:
+ ppro->setSettingByte(NULL, setting[i].szDbSetting, (BYTE)settingData[i].value);
+ break;
+ }
+ }
+ return ret;
+}
diff --git a/protocols/IcqOscarJ/changeinfo/dlgproc.cpp b/protocols/IcqOscarJ/changeinfo/dlgproc.cpp
new file mode 100644
index 0000000000..dd9b9800a8
--- /dev/null
+++ b/protocols/IcqOscarJ/changeinfo/dlgproc.cpp
@@ -0,0 +1,554 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2001-2004 Richard Hughes, Martin berg
+// Copyright 2004-2010 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/changeinfo/dlgproc.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+#define DM_PROTOACK (WM_USER+10)
+
+static int DrawTextUtf(HDC hDC, char *text, LPRECT lpRect, UINT uFormat, LPSIZE lpSize)
+{
+ int res;
+
+ #if defined( _UNICODE )
+ WCHAR *tmp = make_unicode_string(text);
+ res = DrawTextW(hDC, tmp, -1, lpRect, uFormat);
+ if (lpSize)
+ GetTextExtentPoint32W(hDC, tmp, strlennull(tmp), lpSize);
+ SAFE_FREE((void**)&tmp);
+ #else
+ // caution, here we change text's contents
+ utf8_decode_static(text, (char*)text, strlennull(text) + 1);
+ res = DrawTextA(hDC, (char*)text, -1, lpRect, uFormat);
+ if (lpSize)
+ GetTextExtentPoint32A(hDC, (char*)text, strlennull(text), lpSize);
+ #endif
+ return res;
+}
+
+
+char* ChangeInfoData::GetItemSettingText(int i, char *buf, size_t bufsize)
+{
+ char *text = buf;
+ int alloced = 0;
+
+ buf[0] = '\0';
+
+ if (settingData[i].value == 0 && !(setting[i].displayType & LIF_ZEROISVALID))
+ {
+ if (setting[i].displayType & LIF_CHANGEONLY)
+ text = ICQTranslateUtfStatic(LPGEN("<unremovable once applied>"), buf, bufsize);
+ else
+ text = ICQTranslateUtfStatic(LPGEN("<empty>"), buf, bufsize);
+ }
+ else
+ {
+ switch (setting[i].displayType & LIM_TYPE) {
+ case LI_STRING:
+ case LI_LONGSTRING:
+ text = BinaryToEscapes((char*)settingData[i].value);
+ alloced = 1;
+ break;
+
+ case LI_NUMBER:
+ _itoa(settingData[i].value, text, 10);
+ break;
+
+ case LI_LIST:
+ if (setting[i].dbType == DBVT_ASCIIZ)
+ text = ICQTranslateUtfStatic((char*)settingData[i].value, buf, bufsize);
+ else
+ {
+ text = ICQTranslateUtfStatic(LPGEN("Unknown value"), buf, bufsize);
+
+ FieldNamesItem *list = (FieldNamesItem*)setting[i].pList;
+ for (int j=0; TRUE; j++)
+ if (list[j].code == settingData[i].value)
+ {
+ text = ICQTranslateUtfStatic(list[j].text, buf, bufsize);
+ break;
+ }
+ else if (!list[j].text)
+ {
+ if (list[j].code == settingData[i].value)
+ text = ICQTranslateUtfStatic("Unspecified", buf, bufsize);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ if (setting[i].displayType & LIF_PASSWORD)
+ {
+ if (settingData[i].changed)
+ for (int j=0; text[j]; j++) text[j] = '*';
+ else
+ {
+ if (alloced)
+ {
+ SAFE_FREE(&text);
+ alloced = 0;
+ }
+ text = "********";
+ }
+ }
+ if (text != buf)
+ {
+ char *tmp = text;
+
+ text = null_strcpy(buf, text, bufsize - 1);
+ if (alloced)
+ SAFE_FREE(&tmp);
+ }
+
+ return text;
+}
+
+
+void ChangeInfoData::PaintItemSetting(HDC hdc, RECT *rc, int i, UINT itemState)
+{
+ char str[MAX_PATH];
+ char *text = GetItemSettingText(i, str, SIZEOF(str));
+
+ if (settingData[i].value == 0 && !(setting[i].displayType & LIF_ZEROISVALID))
+ SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
+
+ 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);
+}
+
+
+static int ChangeInfoDlg_Resize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL *urc)
+{
+ switch (urc->wId) {
+ case IDC_LIST:
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
+
+ case IDC_SAVE:
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
+
+ case IDC_UPLOADING:
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM;
+ }
+
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; // default
+}
+
+
+INT_PTR CALLBACK ChangeInfoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ChangeInfoData* dat = (ChangeInfoData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ dat = new ChangeInfoData();
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+
+ dat->hwndDlg = hwndDlg;
+ dat->ppro = (CIcqProto*)lParam;
+ dat->hwndList = GetDlgItem(hwndDlg, IDC_LIST);
+
+ ListView_SetExtendedListViewStyle(dat->hwndList, LVS_EX_FULLROWSELECT);
+ dat->iEditItem = -1;
+ {
+ HFONT hFont;
+ LOGFONT lf;
+
+ dat->hListFont = (HFONT)SendMessage(dat->hwndList, WM_GETFONT, 0, 0);
+ GetObject(dat->hListFont, sizeof(lf), &lf);
+ lf.lfHeight -= 5;
+ hFont = CreateFontIndirect(&lf);
+ SendMessage(dat->hwndList, WM_SETFONT, (WPARAM)hFont, 0);
+ }
+ { // Prepare ListView Columns
+ LV_COLUMN lvc = {0};
+ RECT rc;
+
+ GetClientRect(dat->hwndList, &rc);
+ rc.right -= GetSystemMetrics(SM_CXVSCROLL);
+ lvc.mask = LVCF_WIDTH;
+ lvc.cx = rc.right / 3;
+ ListView_InsertColumn(dat->hwndList, 0, &lvc);
+ lvc.cx = rc.right - lvc.cx;
+ ListView_InsertColumn(dat->hwndList, 1, &lvc);
+ }
+ { // Prepare Setting Items
+ LV_ITEM lvi = {0};
+ lvi.mask = LVIF_PARAM | LVIF_TEXT;
+
+ for (lvi.iItem = 0; lvi.iItem < settingCount; lvi.iItem++)
+ {
+ TCHAR text[MAX_PATH];
+
+ lvi.lParam = lvi.iItem;
+ lvi.pszText = text;
+ utf8_to_tchar_static(setting[lvi.iItem].szDescription, text, SIZEOF(text));
+ ListView_InsertItem(dat->hwndList, &lvi);
+ }
+ }
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ return TRUE;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_PARAMCHANGED:
+ dat->ppro = (CIcqProto*)((PSHNOTIFY*)lParam)->lParam;
+ dat->LoadSettingsFromDb(0);
+ {
+ char *pwd = dat->ppro->GetUserPassword(TRUE);
+ strcpy(dat->Password, (pwd) ? pwd : "" ); /// FIXME
+ }
+ break;
+
+ case PSN_INFOCHANGED:
+ dat->LoadSettingsFromDb(1);
+ break;
+
+ case PSN_KILLACTIVE:
+ dat->EndStringEdit(1);
+ dat->EndListEdit(1);
+ break;
+
+ case PSN_APPLY:
+ if (dat->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))
+ {
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+
+ case IDC_LIST:
+ switch (((LPNMHDR)lParam)->code) {
+ case LVN_GETDISPINFO:
+ if (dat->iEditItem != -1)
+ {
+ if (dat->editTopIndex != ListView_GetTopIndex(dat->hwndList))
+ {
+ dat->EndStringEdit(1);
+ dat->EndListEdit(1);
+ }
+ }
+ break;
+
+ case NM_CUSTOMDRAW:
+ {
+ LPNMLVCUSTOMDRAW cd=(LPNMLVCUSTOMDRAW)lParam;
+
+ switch(cd->nmcd.dwDrawStage) {
+ case CDDS_PREPAINT:
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW);
+ return TRUE;
+
+ case CDDS_ITEMPREPAINT:
+ {
+ RECT rcItem;
+
+ if (dat->iEditItem != -1)
+ {
+ if (dat->editTopIndex != ListView_GetTopIndex(dat->hwndList))
+ {
+ dat->EndStringEdit(1);
+ dat->EndListEdit(1);
+ }
+ }
+
+ ListView_GetItemRect(dat->hwndList, cd->nmcd.dwItemSpec, &rcItem, LVIR_BOUNDS);
+
+ if (GetWindowLong(dat->hwndList, GWL_STYLE) & WS_DISABLED)
+ { // Disabled List
+ SetTextColor(cd->nmcd.hdc, cd->clrText);
+ FillRect(cd->nmcd.hdc, &rcItem, GetSysColorBrush(COLOR_3DFACE));
+ }
+ else if ((cd->nmcd.uItemState & CDIS_SELECTED || dat->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, &rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
+ }
+ else
+ { // Unselected item
+ SetTextColor(cd->nmcd.hdc, GetSysColor(COLOR_WINDOWTEXT));
+ FillRect(cd->nmcd.hdc, &rcItem, GetSysColorBrush(COLOR_WINDOW));
+ }
+
+ HFONT hoFont = (HFONT)SelectObject(cd->nmcd.hdc, dat->hListFont);
+
+ 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);
+
+ SetTextColor(cd->nmcd.hdc, GetSysColor(COLOR_3DSHADOW));
+ DrawTextUtf(cd->nmcd.hdc, szText, &rcItem, DT_CENTER|DT_NOCLIP|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER, &textSize);
+ rcLine.top = (rcItem.top + rcItem.bottom) / 2 - 1;
+ rcLine.bottom = rcLine.top + 2;
+ rcLine.left = rcItem.left + 3;
+ rcLine.right = (rcItem.left + rcItem.right - textSize.cx) / 2 - 3;
+ DrawEdge(cd->nmcd.hdc, &rcLine, BDR_SUNKENOUTER, BF_RECT);
+ rcLine.left = (rcItem.left + rcItem.right + textSize.cx) / 2 + 3;
+ rcLine.right = rcItem.right - 3;
+ DrawEdge(cd->nmcd.hdc, &rcLine, BDR_SUNKENOUTER, BF_RECT);
+ }
+ else
+ {
+ RECT rcItemDescr, rcItemValue;
+ char str[MAX_PATH];
+
+ ListView_GetSubItemRect(dat->hwndList, cd->nmcd.dwItemSpec, 0, LVIR_BOUNDS, &rcItemDescr);
+ ListView_GetSubItemRect(dat->hwndList, cd->nmcd.dwItemSpec, 1, LVIR_BOUNDS, &rcItemValue);
+
+ rcItemDescr.right = rcItemValue.left;
+ rcItemDescr.left += 2;
+ DrawTextUtf(cd->nmcd.hdc, ICQTranslateUtfStatic(setting[cd->nmcd.lItemlParam].szDescription, str, MAX_PATH), &rcItemDescr, DT_END_ELLIPSIS|DT_LEFT|DT_NOCLIP|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER, NULL);
+
+ dat->PaintItemSetting(cd->nmcd.hdc, &rcItemValue, cd->nmcd.lItemlParam, cd->nmcd.uItemState);
+ }
+ SelectObject(cd->nmcd.hdc, hoFont);
+
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_SKIPDEFAULT);
+
+ return TRUE;
+ }
+ }
+ break;
+ }
+ case NM_CLICK:
+ {
+ LPNMLISTVIEW nm=(LPNMLISTVIEW)lParam;
+ LV_ITEM lvi;
+ RECT rc;
+
+ dat->EndStringEdit(1);
+ dat->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(dat->hwndList, &lvi);
+ if (!(lvi.state & LVIS_SELECTED)) break;
+ ListView_EnsureVisible(dat->hwndList, lvi.iItem, FALSE);
+ ListView_GetSubItemRect(dat->hwndList, lvi.iItem, lvi.iSubItem, LVIR_BOUNDS, &rc);
+ dat->editTopIndex = ListView_GetTopIndex(dat->hwndList);
+ switch (setting[lvi.lParam].displayType & LIM_TYPE) {
+ case LI_STRING:
+ case LI_LONGSTRING:
+ case LI_NUMBER:
+ dat->BeginStringEdit(nm->iItem, &rc, lvi. lParam, 0);
+ break;
+ case LI_LIST:
+ dat->BeginListEdit(nm->iItem, &rc, lvi. lParam, 0);
+ break;
+ }
+ break;
+ }
+ case LVN_KEYDOWN:
+ {
+ LPNMLVKEYDOWN nm=(LPNMLVKEYDOWN)lParam;
+ LV_ITEM lvi;
+ RECT rc;
+
+ dat->EndStringEdit(1);
+ dat->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(dat->hwndList, -1, LVNI_ALL|LVNI_SELECTED);
+ if (lvi.iItem==-1) break;
+ lvi.iSubItem=1;
+ ListView_GetItem(dat->hwndList,&lvi);
+ ListView_EnsureVisible(dat->hwndList,lvi.iItem,FALSE);
+ ListView_GetSubItemRect(dat->hwndList,lvi.iItem,lvi.iSubItem,LVIR_BOUNDS,&rc);
+ dat->editTopIndex = ListView_GetTopIndex(dat->hwndList);
+ switch(setting[lvi.lParam].displayType & LIM_TYPE) {
+ case LI_STRING:
+ case LI_LONGSTRING:
+ case LI_NUMBER:
+ dat->BeginStringEdit(lvi.iItem,&rc,lvi.lParam,nm->wVKey);
+ break;
+ case LI_LIST:
+ dat->BeginListEdit(lvi.iItem,&rc,lvi.lParam,nm->wVKey);
+ break;
+ }
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ case NM_KILLFOCUS:
+ if(!IsStringEditWindow(GetFocus())) dat->EndStringEdit(1);
+ if(!IsListEditWindow(GetFocus())) dat->EndListEdit(1);
+ break;
+ }
+ break;
+ }
+ break;
+ case WM_KILLFOCUS:
+ dat->EndStringEdit(1);
+ dat->EndListEdit(1);
+ break;
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDCANCEL:
+ SendMessage(GetParent(hwndDlg), msg, wParam, lParam);
+ break;
+
+ case IDC_SAVE:
+ if (!dat->SaveSettingsToDb(hwndDlg))
+ break;
+
+ EnableDlgItem(hwndDlg, IDC_SAVE, FALSE);
+ EnableDlgItem(hwndDlg, IDC_LIST, FALSE);
+ {
+ char str[MAX_PATH];
+ SetDlgItemTextUtf(hwndDlg, IDC_UPLOADING, ICQTranslateUtfStatic(LPGEN("Upload in progress..."), str, MAX_PATH));
+ }
+ EnableDlgItem(hwndDlg, IDC_UPLOADING, TRUE);
+ ShowDlgItem(hwndDlg, IDC_UPLOADING, SW_SHOW);
+ dat->hAckHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, DM_PROTOACK);
+
+ if (!dat->UploadSettings())
+ {
+ EnableDlgItem(hwndDlg, IDC_SAVE, TRUE);
+ EnableDlgItem(hwndDlg, IDC_LIST, TRUE);
+ ShowDlgItem(hwndDlg, IDC_UPLOADING, SW_HIDE);
+ UnhookEvent(dat->hAckHook);
+ dat->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 = ChangeInfoDlg_Resize;
+ CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM) &urd);
+
+ { // update listview column widths
+ RECT rc;
+
+ GetClientRect(dat->hwndList, &rc);
+ rc.right -= GetSystemMetrics(SM_CXVSCROLL);
+ ListView_SetColumnWidth(dat->hwndList, 0, rc.right / 3);
+ ListView_SetColumnWidth(dat->hwndList, 1, rc.right - rc.right / 3);
+ }
+ break;
+ }
+
+ case DM_PROTOACK:
+ {
+ ACKDATA *ack=(ACKDATA*)lParam;
+ int i,done;
+ char str[MAX_PATH];
+ char buf[MAX_PATH];
+
+ if (ack->type != ACKTYPE_SETINFO) break;
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ for (i=0; i < SIZEOF(dat->hUpload); i++)
+ if (dat->hUpload[i] && ack->hProcess == dat->hUpload[i]) break;
+
+ if (i == SIZEOF(dat->hUpload)) break;
+ dat->hUpload[i] = NULL;
+ for (done = 0, i = 0; i < SIZEOF(dat->hUpload); i++)
+ done += dat->hUpload[i] == NULL;
+ null_snprintf(buf, sizeof(buf), "%s%d%%", ICQTranslateUtfStatic(LPGEN("Upload in progress..."), str, MAX_PATH), 100*done/(SIZEOF(dat->hUpload)));
+ SetDlgItemTextUtf(hwndDlg, IDC_UPLOADING, buf);
+ if (done < SIZEOF(dat->hUpload)) break;
+
+ dat->ClearChangeFlags();
+ UnhookEvent(dat->hAckHook);
+ dat->hAckHook = NULL;
+ EnableDlgItem(hwndDlg, IDC_LIST, TRUE);
+ EnableDlgItem(hwndDlg, IDC_UPLOADING, FALSE);
+ SetDlgItemTextUtf(hwndDlg, IDC_UPLOADING, ICQTranslateUtfStatic(LPGEN("Upload complete"), str, MAX_PATH));
+ SendMessage(GetParent(hwndDlg), PSM_FORCECHANGED, 0, 0);
+ }
+ else if (ack->result==ACKRESULT_FAILED)
+ {
+ UnhookEvent(dat->hAckHook);
+ dat->hAckHook = NULL;
+ EnableDlgItem(hwndDlg, IDC_LIST, TRUE);
+ EnableDlgItem(hwndDlg, IDC_UPLOADING, FALSE);
+ SetDlgItemTextUtf(hwndDlg, IDC_UPLOADING, ICQTranslateUtfStatic(LPGEN("Upload FAILED"), str, MAX_PATH));
+ SendMessage(GetParent(hwndDlg), PSM_FORCECHANGED, 0, 0);
+ EnableDlgItem(hwndDlg, IDC_SAVE, TRUE);
+ }
+ break;
+ }
+ case WM_DESTROY:
+ if (dat->hAckHook)
+ {
+ UnhookEvent(dat->hAckHook);
+ dat->hAckHook = NULL;
+ }
+ {
+ HFONT hFont = (HFONT)SendMessage(dat->hwndList, WM_GETFONT, 0, 0);
+ DeleteObject(hFont);
+ }
+ dat->FreeStoredDbSettings();
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ SAFE_DELETE((void_struct**)&dat);
+ break;
+ }
+ return FALSE;
+}
diff --git a/protocols/IcqOscarJ/changeinfo/editlist.cpp b/protocols/IcqOscarJ/changeinfo/editlist.cpp
new file mode 100644
index 0000000000..98411f0bb4
--- /dev/null
+++ b/protocols/IcqOscarJ/changeinfo/editlist.cpp
@@ -0,0 +1,208 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2001-2004 Richard Hughes, Martin berg
+// Copyright 2004-2009 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/changeinfo/editlist.cpp $
+// Revision : $Revision: 11081 $
+// Last change on : $Date: 2009-12-22 00:10:01 +0200 (Вт, 22 дек 2009) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static ChangeInfoData *dataListEdit = NULL;
+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:
+ CallWindowProc(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 = SendMessage(hwnd, LB_GETCURSEL, 0, 0);
+
+ if (dataListEdit)
+ dataListEdit->EndListEdit(i != LB_ERR);
+ }
+ return 0;
+
+ case WM_CHAR:
+ if (wParam != '\r') break;
+ {
+ int i = SendMessage(hwnd, LB_GETCURSEL, 0, 0);
+
+ if (dataListEdit)
+ dataListEdit->EndListEdit(i != LB_ERR);
+ }
+ return 0;
+ case WM_KILLFOCUS:
+ if (dataListEdit)
+ dataListEdit->EndListEdit(1);
+ return 0;
+ }
+ return CallWindowProc(OldListEditProc, hwnd, msg, wParam, lParam);
+}
+
+
+void ChangeInfoData::BeginListEdit(int iItem, RECT *rc, int iSetting, WORD wVKey)
+{
+ int j,n;
+ POINT pt;
+ int itemHeight;
+ char str[MAX_PATH];
+
+ if (dataListEdit)
+ dataListEdit->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);
+
+ dataListEdit = this;
+ hwndListEdit = CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_TOPMOST, _T("LISTBOX"), _T(""), 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);
+
+ FieldNamesItem *list = (FieldNamesItem*)setting[iSetting].pList;
+
+ if (list == countryField)
+ { // some country codes were changed leaving old details uknown, convert it for the user
+ if (settingData[iSetting].value == 420) settingData[iSetting].value = 42; // conversion of obsolete codes (OMG!)
+ else if (settingData[iSetting].value == 421) settingData[iSetting].value = 4201;
+ else if (settingData[iSetting].value == 102) settingData[iSetting].value = 1201;
+ }
+
+ n = ListBoxAddStringUtf(hwndListEdit, "Unspecified");
+ for (j=0; ; j++)
+ if (!list[j].text)
+ {
+ SendMessage(hwndListEdit, LB_SETITEMDATA, n, j);
+ if ((settingData[iSetting].value == 0 && list[j].code == 0)
+ || (setting[iSetting].dbType != DBVT_ASCIIZ && settingData[iSetting].value == list[j].code))
+ SendMessage(hwndListEdit, LB_SETCURSEL, n, 0);
+ break;
+ }
+
+ for (j=0; list[j].text; j++)
+ {
+ n = ListBoxAddStringUtf(hwndListEdit, list[j].text);
+ SendMessage(hwndListEdit, LB_SETITEMDATA, n, j);
+ if ((setting[iSetting].dbType == DBVT_ASCIIZ && (!strcmpnull((char*)settingData[iSetting].value, list[j].text))
+ || (setting[iSetting].dbType == DBVT_ASCIIZ && (!strcmpnull((char*)settingData[iSetting].value, ICQTranslateUtfStatic(list[j].text, str, MAX_PATH))))
+ || ((char*)settingData[iSetting].value == NULL && list[j].code == 0))
+ || (setting[iSetting].dbType != DBVT_ASCIIZ && settingData[iSetting].value == list[j].code))
+ SendMessage(hwndListEdit, LB_SETCURSEL, n, 0);
+ }
+ SendMessage(hwndListEdit, LB_SETTOPINDEX, SendMessage(hwndListEdit, LB_GETCURSEL, 0, 0) - 3, 0);
+ int listCount = SendMessage(hwndListEdit, LB_GETCOUNT, 0, 0);
+ if (itemHeight * listCount < 150)
+ SetWindowPos(hwndListEdit, 0, 0, 0, rc->right - rc->left, itemHeight * listCount + GetSystemMetrics(SM_CYBORDER) * 2, SWP_NOZORDER|SWP_NOMOVE);
+ OldListEditProc = (WNDPROC)SetWindowLongPtr(hwndListEdit, GWLP_WNDPROC, (LONG_PTR)ListEditSubclassProc);
+ if (MyAnimateWindow = (BOOL (WINAPI*)(HWND,DWORD,DWORD))GetProcAddress(GetModuleHandleA("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 ChangeInfoData::EndListEdit(int save)
+{
+ if (hwndListEdit == NULL || iEditItem == -1 || this != dataListEdit) return;
+ if (save)
+ {
+ int iItem = SendMessage(hwndListEdit, LB_GETCURSEL, 0, 0);
+ int i = SendMessage(hwndListEdit, LB_GETITEMDATA, iItem, 0);
+
+ if (setting[iEditItem].dbType == DBVT_ASCIIZ)
+ {
+ char *szNewValue = (((FieldNamesItem*)setting[iEditItem].pList)[i].text);
+ if (((FieldNamesItem*)setting[iEditItem].pList)[i].code || setting[iEditItem].displayType & LIF_ZEROISVALID)
+ {
+ settingData[iEditItem].changed = strcmpnull(szNewValue, (char*)settingData[iEditItem].value);
+ SAFE_FREE((void**)&settingData[iEditItem].value);
+ settingData[iEditItem].value = (LPARAM)null_strdup(szNewValue);
+ }
+ else
+ {
+ settingData[iEditItem].changed = (char*)settingData[iEditItem].value!=NULL;
+ SAFE_FREE((void**)&settingData[iEditItem].value);
+ }
+ }
+ else
+ {
+ settingData[iEditItem].changed = ((FieldNamesItem*)setting[iEditItem].pList)[i].code != settingData[iEditItem].value;
+ settingData[iEditItem].value = ((FieldNamesItem*)setting[iEditItem].pList)[i].code;
+ }
+ if (settingData[iEditItem].changed)
+ {
+ char buf[MAX_PATH];
+ TCHAR tbuf[MAX_PATH];
+
+ if (utf8_to_tchar_static(ICQTranslateUtfStatic(((FieldNamesItem*)setting[iEditItem].pList)[i].text, buf, SIZEOF(buf)), tbuf, SIZEOF(buf)))
+ ListView_SetItemText(hwndList, iEditItem, 1, tbuf);
+
+ EnableDlgItem(GetParent(hwndList), IDC_SAVE, TRUE);
+
+ }
+ }
+ ListView_RedrawItems(hwndList, iEditItem, iEditItem);
+ iEditItem = -1;
+ dataListEdit = NULL;
+ DestroyWindow(hwndListEdit);
+ hwndListEdit = NULL;
+}
+
+
+int IsListEditWindow(HWND hwnd)
+{
+ if (hwnd == hwndListEdit) return 1;
+ return 0;
+}
diff --git a/protocols/IcqOscarJ/changeinfo/editstring.cpp b/protocols/IcqOscarJ/changeinfo/editstring.cpp
new file mode 100644
index 0000000000..1a4d7138c6
--- /dev/null
+++ b/protocols/IcqOscarJ/changeinfo/editstring.cpp
@@ -0,0 +1,374 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2001-2004 Richard Hughes, Martin berg
+// Copyright 2004-2009 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/changeinfo/editstring.cpp $
+// Revision : $Revision: 11081 $
+// Last change on : $Date: 2009-12-22 00:10:01 +0200 (Вт, 22 дек 2009) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static ChangeInfoData *dataStringEdit = NULL;
+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 *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)*(strlennull(str)-1));
+
+ if (*selStart>i) --*selStart;
+ if (*selEnd>i) --*selEnd;
+ }
+ }
+}
+
+
+
+static void EscapesToBinary(char *str)
+{
+ for(;*str;str++)
+ {
+ if(*str!='\\') continue;
+ if(str[1]=='n') {*str++='\r'; *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(int i=0;i<SIZEOF(escapes);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); i += 2)
+ if(*str==escapes[i+1])
+ {
+ *pout++=escapes[i];
+ extra--;
+ break;
+ }
+ if(i < SIZEOF(escapes)) 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)
+ {
+ if (dataStringEdit)
+ dataStringEdit->EndStringEdit(0);
+ return 0;
+ }
+ if (wParam==VK_RETURN)
+ {
+ if (GetWindowLong(hwnd, GWL_STYLE) & ES_MULTILINE && !(GetKeyState(VK_CONTROL) & 0x8000)) break;
+ if (dataStringEdit)
+ dataStringEdit->EndStringEdit(1);
+ return 0;
+ }
+ break;
+
+ case WM_GETDLGCODE:
+ return DLGC_WANTALLKEYS|CallWindowProc(OldStringEditProc, hwnd, msg, wParam, lParam);
+
+ case WM_KILLFOCUS:
+ if ((HWND)wParam == hwndExpandButton) break;
+ if (dataStringEdit)
+ dataStringEdit->EndStringEdit(1);
+ return 0;
+ }
+ return CallWindowProc(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 *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=CreateWindowExA(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)SetWindowLongPtr(hwndEdit,GWLP_WNDPROC,(LONG_PTR)StringEditSubclassProc);
+ SendMessage(hwndEdit,WM_SETFONT,(WPARAM)dataStringEdit->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((void**)&text);
+ }
+ break;
+ }
+ return CallWindowProc(OldExpandButtonProc,hwnd,msg,wParam,lParam);
+}
+
+
+void ChangeInfoData::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 && !settingData[i].changed)
+ szValue = " ";
+ else if ((setting[i].displayType & LIM_TYPE) == LI_NUMBER)
+ {
+ szValue = str;
+ null_snprintf(str, sizeof(str), "%d", settingData[i].value );
+ }
+ else if (settingData[i].value)
+ {
+ szValue = BinaryToEscapes((char*)settingData[i].value);
+ alloced = 1;
+ }
+ else szValue = "";
+
+ iEditItem = iItem;
+
+ if ((setting[i].displayType & LIM_TYPE)==LI_LONGSTRING)
+ {
+ rc->right-=rc->bottom-rc->top;
+ hwndExpandButton=CreateWindowA("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)SetWindowLongPtr(hwndExpandButton,GWLP_WNDPROC,(LONG_PTR)ExpandButtonSubclassProc);
+ }
+
+ dataStringEdit = this;
+ hwndEdit = CreateWindow(_T("EDIT"),_T(""),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)SetWindowLongPtr(hwndEdit,GWLP_WNDPROC,(LONG_PTR)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,_T(""),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, settingData[i].value);
+ if(!(setting[i].displayType & LIF_ZEROISVALID) && settingData[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 ChangeInfoData::EndStringEdit(int save)
+{
+ if (hwndEdit == NULL || iEditItem == -1 || this != dataStringEdit) return;
+ if (save)
+ {
+ char *text = (char*)SAFE_MALLOC(GetWindowTextLength(hwndEdit)+1);
+
+ GetWindowTextA(hwndEdit,(char*)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];
+ }
+ settingData[iEditItem].changed = settingData[iEditItem].value != newValue;
+ settingData[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*)settingData[iEditItem].value) && (strlennull(text) + strlennull((char*)settingData[iEditItem].value))))
+ {
+ SAFE_FREE((void**)&settingData[iEditItem].value);
+ if (strlennull(text))
+ settingData[iEditItem].value = (LPARAM)text;
+ else
+ {
+ settingData[iEditItem].value = 0;
+ SAFE_FREE(&text);
+ }
+ settingData[iEditItem].changed = 1;
+ }
+ }
+ if (settingData[iEditItem].changed)
+ {
+ TCHAR tbuf[MAX_PATH];
+
+ GetWindowText(hwndEdit, tbuf, SIZEOF(tbuf));
+ ListView_SetItemText(hwndList, iEditItem, 1, tbuf);
+
+ EnableDlgItem(hwndDlg, IDC_SAVE, TRUE);
+ }
+ }
+ ListView_RedrawItems(hwndList, iEditItem, iEditItem);
+ iEditItem = -1;
+ dataStringEdit = NULL;
+ 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/protocols/IcqOscarJ/changeinfo/expandst.ico b/protocols/IcqOscarJ/changeinfo/expandst.ico
new file mode 100644
index 0000000000..17367fe8d3
--- /dev/null
+++ b/protocols/IcqOscarJ/changeinfo/expandst.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/changeinfo/icqoscar.h b/protocols/IcqOscarJ/changeinfo/icqoscar.h
new file mode 100644
index 0000000000..77283f6f7f
--- /dev/null
+++ b/protocols/IcqOscarJ/changeinfo/icqoscar.h
@@ -0,0 +1,2 @@
+/* For MinGW sake */
+#include "../icqoscar.h"
diff --git a/protocols/IcqOscarJ/changeinfo/main.cpp b/protocols/IcqOscarJ/changeinfo/main.cpp
new file mode 100644
index 0000000000..9be4f7f6a3
--- /dev/null
+++ b/protocols/IcqOscarJ/changeinfo/main.cpp
@@ -0,0 +1,35 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2001-2004 Richard Hughes, Martin berg
+// Copyright 2004-2008 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/changeinfo/main.cpp $
+// Revision : $Revision: 7484 $
+// Last change on : $Date: 2008-03-21 11:43:39 +0200 (Пт, 21 мар 2008) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
diff --git a/protocols/IcqOscarJ/changeinfo/upload.cpp b/protocols/IcqOscarJ/changeinfo/upload.cpp
new file mode 100644
index 0000000000..0f82a87b99
--- /dev/null
+++ b/protocols/IcqOscarJ/changeinfo/upload.cpp
@@ -0,0 +1,98 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2001-2004 Richard Hughes, Martin berg
+// Copyright 2004-2009 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/changeinfo/upload.cpp $
+// Revision : $Revision: 11081 $
+// Last change on : $Date: 2009-12-22 00:10:01 +0200 (Вт, 22 дек 2009) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// ChangeInfo Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+int CIcqProto::StringToListItemId(const char *szSetting,int def)
+{
+ int i;
+
+ for(i=0;i<settingCount;i++)
+ if(!strcmpnull(szSetting,setting[i].szDbSetting))
+ break;
+
+ if (i==settingCount) return def;
+
+ FieldNamesItem *list = (FieldNamesItem*)setting[i].pList;
+
+ char *szValue = getSettingStringUtf(NULL, szSetting, NULL);
+ if (!szValue)
+ return def;
+
+ for (i=0; list[i].text; i++)
+ if (!strcmpnull(list[i].text, szValue))
+ break;
+
+ SAFE_FREE(&szValue);
+ if (!list[i].text) return def;
+
+ return list[i].code;
+}
+
+
+int ChangeInfoData::UploadSettings(void)
+{
+ if (!ppro->icqOnline())
+ {
+ MessageBoxUtf(hwndDlg, 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;
+ }
+
+ hUpload[0] = (HANDLE)ppro->ChangeInfoEx(CIXT_FULL, 0);
+
+ //password
+ char* tmp = ppro->GetUserPassword(TRUE);
+ if (tmp)
+ {
+ if (strlennull(Password) > 0 && strcmpnull(Password, tmp))
+ {
+ hUpload[1] = (HANDLE)ppro->icq_changeUserPasswordServ(tmp);
+ char szPwd[PASSWORDMAXLEN] = {0};
+
+ if (ppro->GetUserStoredPassword(szPwd, sizeof(szPwd)))
+ { // password is stored in DB, update
+ char ptmp[PASSWORDMAXLEN];
+
+ strcpy(ptmp, tmp);
+
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(ptmp), (LPARAM)ptmp);
+
+ ppro->setSettingString(NULL, "Password", ptmp);
+ }
+ }
+ }
+
+ return 1;
+}
diff --git a/protocols/IcqOscarJ/channels.h b/protocols/IcqOscarJ/channels.h
new file mode 100644
index 0000000000..7c61ff09b4
--- /dev/null
+++ b/protocols/IcqOscarJ/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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/channels.h $
+// Revision : $Revision: 11353 $
+// Last change on : $Date: 2010-03-10 02:21:03 +0200 (Ср, 10 мар 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Header for FLAP Channel packet handlers
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __CHANNELS_H
+#define __CHANNELS_H
+
+
+struct snac_header
+{
+ BOOL bValid;
+ WORD wFamily;
+ WORD wSubtype;
+ WORD wFlags;
+ DWORD dwRef;
+ WORD wVersion;
+};
+
+int unpackSnacHeader(snac_header *pSnacHeader, BYTE **pBuffer, WORD *pwBufferLength);
+
+
+#endif /* __CHANNELS_H */
diff --git a/protocols/IcqOscarJ/cookies.cpp b/protocols/IcqOscarJ/cookies.cpp
new file mode 100644
index 0000000000..2b9bc91cd0
--- /dev/null
+++ b/protocols/IcqOscarJ/cookies.cpp
@@ -0,0 +1,308 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/cookies.cpp $
+// Revision : $Revision: 14075 $
+// Last change on : $Date: 2012-02-11 16:41:20 +0200 (Сб, 11 фев 2012) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Handles packet & message cookies
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+#define INVALID_COOKIE_INDEX -1
+
+void CIcqProto::RemoveExpiredCookies()
+{
+ time_t tNow = time(NULL);
+
+ for (int i = cookies.getCount()-1; i >= 0; i--)
+ {
+ icq_cookie_info *cookie = cookies[i];
+
+ if ((cookie->dwTime + COOKIE_TIMEOUT) < tNow)
+ {
+ cookies.remove(i);
+ SAFE_FREE((void**)&cookie);
+ }
+ }
+}
+
+
+// Generate and allocate cookie
+DWORD CIcqProto::AllocateCookie(BYTE bType, WORD wIdent, HANDLE hContact, void *pvExtra)
+{
+ icq_lock l(cookieMutex);
+
+ DWORD dwThisSeq = wCookieSeq++;
+ dwThisSeq &= 0x7FFF;
+ dwThisSeq |= wIdent<<0x10;
+
+ icq_cookie_info* p = (icq_cookie_info*)SAFE_MALLOC(sizeof(icq_cookie_info));
+ if (p)
+ {
+ p->bType = bType;
+ p->dwCookie = dwThisSeq;
+ p->hContact = hContact;
+ p->pvExtra = pvExtra;
+ p->dwTime = time(NULL);
+ cookies.insert(p);
+ }
+ return dwThisSeq;
+}
+
+
+DWORD CIcqProto::GenerateCookie(WORD wIdent)
+{
+ icq_lock l(cookieMutex);
+
+ DWORD dwThisSeq = wCookieSeq++;
+ dwThisSeq &= 0x7FFF;
+ dwThisSeq |= wIdent<<0x10;
+
+ return dwThisSeq;
+}
+
+
+int CIcqProto::GetCookieType(DWORD dwCookie)
+{
+ icq_lock l(cookieMutex);
+
+ int i = cookies.getIndex(( icq_cookie_info* )&dwCookie );
+ if ( i != INVALID_COOKIE_INDEX )
+ i = cookies[i]->bType;
+
+ return i;
+}
+
+
+int CIcqProto::FindCookie(DWORD dwCookie, HANDLE *phContact, void **ppvExtra)
+{
+ icq_lock l(cookieMutex);
+
+ int i = cookies.getIndex(( icq_cookie_info* )&dwCookie );
+ if (i != INVALID_COOKIE_INDEX)
+ {
+ if (phContact)
+ *phContact = cookies[i]->hContact;
+ if (ppvExtra)
+ *ppvExtra = cookies[i]->pvExtra;
+
+ // Cookie found
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int CIcqProto::FindCookieByData(void *pvExtra, DWORD *pdwCookie, HANDLE *phContact)
+{
+ icq_lock l(cookieMutex);
+
+ for (int i = 0; i < cookies.getCount(); i++)
+ {
+ if (pvExtra == cookies[i]->pvExtra)
+ {
+ if (phContact)
+ *phContact = cookies[i]->hContact;
+ if (pdwCookie)
+ *pdwCookie = cookies[i]->dwCookie;
+
+ // Cookie found
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+int CIcqProto::FindCookieByType(BYTE bType, DWORD *pdwCookie, HANDLE *phContact, void** ppvExtra)
+{
+ icq_lock l(cookieMutex);
+
+ for (int i = 0; i < cookies.getCount(); i++)
+ {
+ if (bType == cookies[i]->bType)
+ {
+ if (pdwCookie)
+ *pdwCookie = cookies[i]->dwCookie;
+ if (phContact)
+ *phContact = cookies[i]->hContact;
+ if (ppvExtra)
+ *ppvExtra = cookies[i]->pvExtra;
+
+ // Cookie found
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+int CIcqProto::FindMessageCookie(DWORD dwMsgID1, DWORD dwMsgID2, DWORD *pdwCookie, HANDLE *phContact, cookie_message_data **ppvExtra)
+{
+ icq_lock l(cookieMutex);
+
+ for (int i = 0; i < cookies.getCount(); i++)
+ {
+ if (cookies[i]->bType == CKT_MESSAGE || cookies[i]->bType == CKT_FILE || cookies[i]->bType == CKT_REVERSEDIRECT)
+ { // message cookie found
+ cookie_message_data *pCookie = (cookie_message_data*)cookies[i]->pvExtra;
+
+ if (pCookie->dwMsgID1 == dwMsgID1 && pCookie->dwMsgID2 == dwMsgID2)
+ {
+ if (phContact)
+ *phContact = cookies[i]->hContact;
+ if (pdwCookie)
+ *pdwCookie = cookies[i]->dwCookie;
+ if (ppvExtra)
+ *ppvExtra = pCookie;
+
+ // Cookie found
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+void CIcqProto::FreeCookie(DWORD dwCookie)
+{
+ icq_lock l(cookieMutex);
+
+ int i = cookies.getIndex((icq_cookie_info*)&dwCookie);
+ if (i != INVALID_COOKIE_INDEX)
+ { // Cookie found, remove from list
+ icq_cookie_info *cookie = cookies[i];
+
+ cookies.remove(i);
+ SAFE_FREE((void**)&cookie);
+ }
+
+ RemoveExpiredCookies();
+}
+
+
+void CIcqProto::FreeCookieByData(BYTE bType, void *pvExtra)
+{
+ icq_lock l(cookieMutex);
+
+ for (int i = 0; i < cookies.getCount(); i++)
+ {
+ icq_cookie_info *cookie = cookies[i];
+
+ if (bType == cookie->bType && pvExtra == cookie->pvExtra)
+ { // Cookie found, remove from list
+ cookies.remove(i);
+ SAFE_FREE((void**)&cookie);
+ break;
+ }
+ }
+
+ RemoveExpiredCookies();
+}
+
+
+void CIcqProto::ReleaseCookie(DWORD dwCookie)
+{
+ icq_lock l(cookieMutex);
+
+ int i = cookies.getIndex(( icq_cookie_info* )&dwCookie );
+ if (i != INVALID_COOKIE_INDEX)
+ { // Cookie found, remove from list
+ icq_cookie_info *cookie = cookies[i];
+
+ cookies.remove(i);
+ SAFE_FREE((void**)&cookie->pvExtra);
+ SAFE_FREE((void**)&cookie);
+ }
+ RemoveExpiredCookies();
+}
+
+
+void CIcqProto::InitMessageCookie(cookie_message_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;
+ }
+}
+
+
+cookie_message_data* CIcqProto::CreateMessageCookie(WORD bMsgType, BYTE bAckType)
+{
+ cookie_message_data *pCookie = (cookie_message_data*)SAFE_MALLOC(sizeof(cookie_message_data));
+ if (pCookie)
+ {
+ pCookie->bMessageType = bMsgType;
+ pCookie->nAckType = bAckType;
+
+ InitMessageCookie(pCookie);
+ }
+ return pCookie;
+}
+
+
+cookie_message_data* CIcqProto::CreateMessageCookieData(BYTE bMsgType, HANDLE hContact, DWORD dwUin, int bUseSrvRelay)
+{
+ BYTE bAckType;
+ WORD wStatus = getContactStatus(hContact);
+
+ if (!getSettingByte(hContact, "SlowSend", getSettingByte(NULL, "SlowSend", DEFAULT_SLOWSEND)) ||
+ (!dwUin && wStatus == ID_STATUS_OFFLINE))
+ bAckType = ACKTYPE_NONE;
+ else if (bUseSrvRelay)
+ bAckType = ACKTYPE_CLIENT;
+ else
+ bAckType = ACKTYPE_SERVER;
+
+ cookie_message_data* pCookieData = CreateMessageCookie(bMsgType, bAckType);
+
+ // set flag for offline messages - to allow proper error handling
+ if (wStatus == ID_STATUS_OFFLINE || wStatus == ID_STATUS_INVISIBLE)
+ pCookieData->isOffline = TRUE;
+
+ return pCookieData;
+}
diff --git a/protocols/IcqOscarJ/cookies.h b/protocols/IcqOscarJ/cookies.h
new file mode 100644
index 0000000000..486674e77e
--- /dev/null
+++ b/protocols/IcqOscarJ/cookies.h
@@ -0,0 +1,155 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/cookies.h $
+// Revision : $Revision: 14141 $
+// Last change on : $Date: 2012-03-09 22:52:15 +0200 (Пт, 09 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// 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_DIRECTORY_QUERY 0x18
+#define CKT_DIRECTORY_UPDATE 0x19
+#define CKT_AVATAR 0x20
+
+struct CIcqProto;
+
+/* Basic structure used to hold operation cookies list */
+struct icq_cookie_info
+{
+ DWORD dwCookie;
+ HANDLE hContact;
+ void *pvExtra;
+ time_t dwTime;
+ BYTE bType;
+};
+
+
+/* Specific structures to hold request specific data - pvExtra */
+
+struct cookie_family_request
+{
+ WORD wFamily;
+ void (CIcqProto::*familyHandler)(HANDLE hConn, char* cookie, WORD cookieLen);
+};
+
+
+struct cookie_offline_messages
+{
+ int nMessages;
+ int nMissed;
+};
+
+
+#define ACKTYPE_NONE 0
+#define ACKTYPE_SERVER 1
+#define ACKTYPE_CLIENT 2
+
+struct cookie_message_data
+{
+ DWORD dwMsgID1;
+ DWORD dwMsgID2;
+ WORD bMessageType;
+ BYTE nAckType;
+ BYTE isOffline;
+};
+
+#define REQUESTTYPE_OWNER 0
+#define REQUESTTYPE_USERAUTO 1
+#define REQUESTTYPE_USERMINIMAL 2
+#define REQUESTTYPE_USERDETAILED 3
+#define REQUESTTYPE_PROFILE 4
+
+struct cookie_fam15_data
+{
+ BYTE bRequestType;
+};
+
+
+#define SEARCHTYPE_UID 0
+#define SEARCHTYPE_EMAIL 1
+#define SEARCHTYPE_NAMES 2
+#define SEARCHTYPE_DETAILS 4
+
+struct cookie_search
+{
+ BYTE bSearchType;
+ char* szObject;
+ DWORD dwMainId;
+ DWORD dwStatus;
+};
+
+
+struct cookie_avatar
+{
+ DWORD dwUin;
+ HANDLE hContact;
+ unsigned int hashlen;
+ BYTE *hash;
+ unsigned int cbData;
+ TCHAR *szFile;
+};
+
+
+struct cookie_reverse_connect: public cookie_message_data
+{
+ HANDLE hContact;
+ DWORD dwUin;
+ int type;
+ void *ft;
+};
+
+
+#define DIRECTORYREQUEST_INFOUSER 0x01
+#define DIRECTORYREQUEST_INFOOWNER 0x02
+#define DIRECTORYREQUEST_INFOMULTI 0x03
+#define DIRECTORYREQUEST_SEARCH 0x08
+#define DIRECTORYREQUEST_UPDATEOWNER 0x10
+#define DIRECTORYREQUEST_UPDATENOTE 0x11
+#define DIRECTORYREQUEST_UPDATEPRIVACY 0x12
+
+struct cookie_directory_data
+{
+ BYTE bRequestType;
+};
+
+
+#endif /* __COOKIES_H */
diff --git a/protocols/IcqOscarJ/directpackets.cpp b/protocols/IcqOscarJ/directpackets.cpp
new file mode 100644
index 0000000000..71658f2665
--- /dev/null
+++ b/protocols/IcqOscarJ/directpackets.cpp
@@ -0,0 +1,300 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/directpackets.cpp $
+// Revision : $Revision: 11570 $
+// Last change on : $Date: 2010-04-11 16:58:57 +0300 (Вс, 11 апр 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+void EncryptDirectPacket(directconnect* dc, icq_packet* p);
+
+void packEmptyMsg(icq_packet *packet);
+
+void packDirectMsgHeader(icq_packet* packet, WORD wDataLen, WORD wCommand, DWORD dwCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wX1, WORD wX2)
+{
+ directPacketInit(packet, 29 + wDataLen);
+ packByte(packet, 2); /* channel */
+ packLEDWord(packet, 0); /* space for crypto */
+ packLEWord(packet, wCommand);
+ packLEWord(packet, 14); /* unknown */
+ packLEWord(packet, (WORD)dwCookie);
+ packLEDWord(packet, 0); /* unknown */
+ packLEDWord(packet, 0); /* unknown */
+ packLEDWord(packet, 0); /* unknown */
+ packByte(packet, bMsgType);
+ packByte(packet, bMsgFlags);
+ packLEWord(packet, wX1); /* unknown. Is 1 for getawaymsg, 0 otherwise */
+ packLEWord(packet, wX2); // this is probably priority
+}
+
+
+void CIcqProto::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, (LPBYTE)szCap, 0x26); /* GUID */
+ }
+ }
+ EncryptDirectPacket(dc, &packet);
+ sendDirectPacket(dc, &packet);
+
+ NetLog_Direct("Sent acknowledgement thru direct connection");
+}
+
+
+DWORD CIcqProto::icq_sendGetAwayMsgDirect(HANDLE hContact, int type)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ cookie_message_data *pCookieData;
+
+ if (getSettingWord(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
+
+ return (SendDirectMessage(hContact, &packet)) ? dwCookie : 0;
+}
+
+
+void CIcqProto::icq_sendAwayMsgReplyDirect(directconnect* dc, WORD wCookie, BYTE msgType, const char** szMsg)
+{
+ icq_packet packet;
+
+ if (validateStatusMessageRequest(dc->hContact, msgType))
+ {
+ NotifyEventHooks(m_modeMsgsEvent, (WPARAM)msgType, (LPARAM)dc->dwRemoteUin);
+
+ icq_lock l(m_modeMsgsMutex);
+
+ if (szMsg && *szMsg)
+ {
+ // prepare Ansi message - only Ansi supported
+ WORD wMsgLen = strlennull(*szMsg) + 1;
+ char *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, (LPBYTE)szAnsiMsg, (WORD)(wMsgLen + 1));
+ EncryptDirectPacket(dc, &packet);
+
+ sendDirectPacket(dc, &packet);
+ }
+ }
+}
+
+
+void CIcqProto::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 CIcqProto::icq_sendFileDenyDirect(HANDLE hContact, filetransfer *ft, const char *szReason)
+{
+ // v7 packet
+ icq_packet packet;
+ char *szReasonAnsi = NULL;
+ int cbReasonAnsi = 0;
+
+ if (!utf8_decode(szReason, &szReasonAnsi))
+ szReasonAnsi = NULL;
+ else
+ cbReasonAnsi = strlennull(szReasonAnsi);
+
+ packDirectMsgHeader(&packet, (WORD)(18 + cbReasonAnsi), DIRECT_ACK, ft->dwCookie, MTYPE_FILEREQ, 0, 1, 0);
+ packLEWord(&packet, (WORD)(1 + cbReasonAnsi)); // description
+ if (szReasonAnsi) packBuffer(&packet, (LPBYTE)szReasonAnsi, (WORD)cbReasonAnsi);
+ 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);
+
+ SAFE_FREE(&szReasonAnsi);
+
+ SendDirectMessage(hContact, &packet);
+
+ NetLog_Direct("Sent file deny direct.");
+}
+
+
+int CIcqProto::icq_sendFileSendDirectv7(filetransfer *ft, const char *pszFiles)
+{
+ icq_packet packet;
+ char *szFilesAnsi = NULL;
+ WORD wDescrLen = strlennull(ft->szDescription), wFilesLen = 0;
+
+ if (!utf8_decode(pszFiles, &szFilesAnsi))
+ szFilesAnsi = NULL;
+ else
+ wFilesLen = strlennull(szFilesAnsi);
+
+ packDirectMsgHeader(&packet, (WORD)(18 + wDescrLen + wFilesLen), DIRECT_MESSAGE, (WORD)ft->dwCookie, MTYPE_FILEREQ, 0, 0, 0);
+ packLEWord(&packet, (WORD)(wDescrLen + 1));
+ packBuffer(&packet, (LPBYTE)ft->szDescription, (WORD)(wDescrLen + 1));
+ packLEDWord(&packet, 0); // listen port
+ packLEWord(&packet, (WORD)(wFilesLen + 1));
+ packBuffer(&packet, (LPBYTE)szFilesAnsi, (WORD)(wFilesLen + 1));
+ packLEDWord(&packet, ft->dwTotalSize);
+ packLEDWord(&packet, 0); // listen port (again)
+
+ SAFE_FREE(&szFilesAnsi);
+
+ NetLog_Direct("Sending v%u file transfer request direct", 7);
+
+ return SendDirectMessage(ft->hContact, &packet);
+}
+
+
+int CIcqProto::icq_sendFileSendDirectv8(filetransfer *ft, const char *pszFiles)
+{
+ icq_packet packet;
+ char *szFilesAnsi = NULL;
+ WORD wDescrLen = strlennull(ft->szDescription), wFilesLen = 0;
+
+ if (!utf8_decode(pszFiles, &szFilesAnsi))
+ szFilesAnsi = NULL;
+ else
+ wFilesLen = strlennull(szFilesAnsi);
+
+ 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, (LPBYTE)ft->szDescription, wDescrLen);
+ packWord(&packet, 0x8c82); // Unknown (port?), seen 0x80F6
+ packWord(&packet, 0x0222); // Unknown, seen 0x2e01
+ packLEWord(&packet, (WORD)(wFilesLen + 1));
+ packBuffer(&packet, (LPBYTE)szFilesAnsi, (WORD)(wFilesLen + 1));
+ packLEDWord(&packet, ft->dwTotalSize);
+ packLEDWord(&packet, 0x0008c82); // Unknown, (seen 0xf680 ~33000)
+
+ SAFE_FREE(&szFilesAnsi);
+
+ NetLog_Direct("Sending v%u file transfer request direct", 8);
+
+ return SendDirectMessage(ft->hContact, &packet);
+}
+
+
+DWORD CIcqProto::icq_SendDirectMessage(HANDLE hContact, const char *szMessage, int nBodyLength, WORD wPriority, cookie_message_data *pCookieData, char *szCap)
+{
+ icq_packet packet;
+ DWORD 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, (LPBYTE)szMessage, (WORD)(nBodyLength+1)); // Message
+ packMsgColorInfo(&packet);
+ if (szCap)
+ {
+ packLEDWord(&packet, 0x00000026); // length of GUID
+ packBuffer(&packet, (LPBYTE)szCap, 0x26); // UTF-8 GUID
+ }
+
+ if (SendDirectMessage(hContact, &packet))
+ return dwCookie; // Success
+
+ FreeCookie(dwCookie); // release cookie
+ return 0; // Failure
+}
+
+void CIcqProto::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, (LPBYTE)szBody, (WORD)nBodyLen);
+
+ SendDirectMessage(hContact, &packet);
+}
+
+void CIcqProto::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, (LPBYTE)szBody, (WORD)nBodyLen);
+
+ SendDirectMessage(hContact, &packet);
+}
diff --git a/protocols/IcqOscarJ/directpackets.h b/protocols/IcqOscarJ/directpackets.h
new file mode 100644
index 0000000000..65f06e36d7
--- /dev/null
+++ b/protocols/IcqOscarJ/directpackets.h
@@ -0,0 +1,43 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000-2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001-2002 Jon Keating, Richard Hughes
+// Copyright 2002-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/directpackets.h $
+// Revision : $Revision: 7484 $
+// Last change on : $Date: 2008-03-21 11:43:39 +0200 (Пт, 21 мар 2008) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_DIRECTPACKETS_H
+#define __ICQ_DIRECTPACKETS_H
+
+// Direct packet senders
+void packDirectMsgHeader(icq_packet *packet, WORD wDataLen, WORD wCommand, DWORD dwCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wX1, WORD wX2);
+
+#endif /* __ICQ_DIRECTPACKETS_H */
diff --git a/protocols/IcqOscarJ/docs/IcqOscarJ-translation.txt b/protocols/IcqOscarJ/docs/IcqOscarJ-translation.txt
new file mode 100644
index 0000000000..cc8b0bf54d
--- /dev/null
+++ b/protocols/IcqOscarJ/docs/IcqOscarJ-translation.txt
@@ -0,0 +1,379 @@
+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.7
+Plugins-included: IcqOscarJ
+
+; Generated by lpgen on Wed Jun 7 20:24:25 2006
+; Translations: 330
+
+; chan_04close.c
+;[Unable to connect to migrated ICQ communication server]
+;[Unable to connect to ICQ communication server]
+;[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.\nSecure (MD5) login is not supported on this account.]
+;[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.]
+;[Failed to request offline messages. They may be received next time you log in.]
+
+; fam_04message.c
+;[Incoming URL:]
+;[You are sending too fast. Wait a while and try again.\r\nSNAC(4.1) Error x02]
+;[You are sending too fast. Wait a while and try again.\r\nSNAC(4.1) Error x03]
+;[The contact does not support receiving offline messages.]
+;[The user has logged off. Select 'Retry' to send an offline message.\r\nSNAC(4.1) Error x04]
+;[The messaging service is temporarily unavailable. Wait a while and try again.\r\nSNAC(4.1) Error x05]
+;[The receiving client does not support this type of message.\r\nSNAC(4.1) Error x09]
+;[You sent too long message. The receiving client does not support it.\r\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.\r\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.]
+;[%s has closed the message window.]
+
+; fam_13servclist.c
+;[Contact \"%s\" was authorized in the server list.]
+;[Contact \"%s\" lost its authorization in the server list.]
+;[User \"%s\" was removed from server list.]
+;[Server contact list is unavailable, Miranda will use local contact list.]
+;[Updating of server contact 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.]
+
+; oscar_filetransfer.c
+;[The file transfer was aborted by the other user.]
+;[The file transfer failed: Proxy error]
+;[The file transfer failed: Invalid request]
+;[The file transfer failed: Proxy unavailable]
+;[Failed to Initialize File Transfer. No valid files were specified.]
+;[The files are too big to be sent at once. Files bigger than 4GB can be sent only separately.]
+;[Failed to Initialize File Transfer. Unable to bind local port and File proxy unavailable.]
+;[Connection lost during file transfer.]
+;[File transfer negotiation failed for unknown reason.]
+;[The checksum of file \"%s\" does not match, the file is probably damaged.]
+
+; icq_opts.c
+;[Network]
+;[Account]
+;[Contacts]
+;[Features]
+;[Privacy]
+;[Display all problems]
+;[Display problems causing possible loss of data]
+;[Display explanations for disconnection]
+;[Display problems requiring user intervention]
+;[Do not display any problems (not recommended)]
+;[System default codepage]
+;[Thai]
+;[Japanese]
+;[Simplified Chinese]
+;[Korean]
+;[Traditional Chinese]
+;[Central European]
+;[Cyrillic]
+;[Latin I]
+;[Greek]
+;[Turkish]
+;[Hebrew]
+;[Arabic]
+;[Baltic]
+;[Vietnamese]
+;[Korean (Johab)]
+
+; icq_server.c
+;[Connection failed.\nLogin sequence failed for unknown reason.\nTry again later.]
+
+; icq_serverlist.c
+;[The contact's information was too big and was truncated.]
+
+; icq_uploadui.c
+;[Select contacts you want to store on server.]
+;[Ready...]
+;[Server rate warning -> slowing down the process.]
+;[Adding group \"%s\"...]
+;[Uploading %s...]
+;[OK]
+;[NOT FOUND]
+;[ALREADY EXISTS]
+;[INVALID DATA]
+;[LIST FULL]
+;[FAILED]
+;[No upload group available]
+;[Deleting %s...]
+;[Moving %s to group \"%s\"...]
+;[Adding %s to visible list...]
+;[Adding %s to invisible list...]
+;[Deleting %s from visible list...]
+;[Deleting %s 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 **]
+
+; icq_xstatus.c
+;[Cancel]
+;[%s Custom Status]
+;[%s/Custom Status]
+;[None]
+;[Angry]
+;[Taking a bath]
+;[Tired]
+;[Party]
+;[Drinking beer]
+;[Thinking]
+;[Eating]
+;[Watching TV]
+;[Meeting]
+;[Coffee]
+;[Listening to music]
+;[Business]
+;[Shooting]
+;[Having fun]
+;[On the phone]
+;[Gaming]
+;[Studying]
+;[Shopping]
+;[Feeling sick]
+;[Sleeping]
+;[Surfing]
+;[Browsing]
+;[Working]
+;[Typing]
+;[Picnic]
+;[Cooking]
+;[Smoking]
+;[I'm high]
+;[On WC]
+;[To be or not to be]
+;[Watching pro7 on TV]
+;[Love]
+
+; icq_avatar.c
+;[Avatars Cache]
+
+; 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 4096 characters.]
+;[The message could not be delivered, it is too long.]
+;[The message could not be delivered. You are sending too fast. Wait a while and try again.]
+;[Bad data (internal error #1)]
+;[Bad data (internal error #2)]
+;[The reciever does not support receiving of contacts.]
+;[Confirmation]
+;[Are you sure you want to revoke user's autorisation (this will remove you from his/her list on some clients) ?]
+;[%d Files]
+
+; init.c
+;[%s server connection]
+;[%s client-to-client connections]
+;[Request authorization]
+;[Grant authorization]
+;[Revoke authorization]
+;[Add to server list]
+;[Show custom status details]
+
+; log.c
+;[ICQ Note]
+;[ICQ Warning]
+;[ICQ Error]
+;[ICQ Fatal]
+;[The server did not respond to the connection attempt within a reasonable time, it may be temporarily down. Try again later.]
+;[The connection with the server was abortively closed during the connection attempt. You may have lost your local network connection.]
+;[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.]
+;[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.]
+;[Your proxy rejected the user name and password that you provided. Please check them in M->Options->Network.]
+;[The server to which you are trying to connect does not exist. Check your spelling in M->Options->Network->ICQ.]
+
+; utilities.c
+;[<invalid>]
+
+; 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:]
+;[ (DC Established)]
+;[ScreenName:]
+;[<not specified>]
+
+; resources.rc
+;[Create new account]
+;[Remember this session password]
+;[Retrieve a lost password or ICQ number]
+;[Create a new ICQ account using the ICQ website]
+;[Secure (MD5) login]
+;[Use HTTP Gateway mode for HTTP proxy]
+;[Send 'Keep-alives' (enable this if you use a proxy server and frequently get disconnected)]
+;[Ignore concurrent error messages]
+;[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)]
+;[Allow bigger owner avatars (up to 128x128) [experimental]]
+;[Enable unicode messaging support]
+;[Send all messages in unicode if possible]
+;[Make me temporarily visible to contacts I send message to]
+;[Notify me when a message delivery has failed (recommended)]
+;[Use only server's acknowledgement (faster)]
+;[Enable peer-to-peer message connections]
+;[Passive mode, i.e. do not initiate new connections]
+;[Enable Custom status support]
+;[Reset Custom status on status change]
+;[Auto-retrieve Custom status details]
+;[Block known Spam Bots]
+;[Enable AIM support]
+;[Allow direct connections with any user]
+;[Allow direct connections with users on my contact list]
+;[Allow direct connections only when I authorize or initiate them]
+;[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]
+;[Enable popup support]
+;[Display errors using popups]
+;[Display popup when spambot is detected]
+;[&Use Windows colors]
+;[Use system &icons]
+;[Search online users only]
+;[OK]
+;[&Send]
+;[Previe&w]
+;[Synchronize]
+;[Closing in %d]
+;[Cancel]
+;[&Cancel]
+;[Default]
+;[Manage server's list...]
+;[Set]
+;[Delete]
+;[&Save changes]
+;[Please enter your ICQ account details to continue:]
+;[ICQ number:]
+;[Password:]
+;[Enter a password for UIN %d:]
+;[Hint: If you don't enter your password here, Miranda will ask for the password everytime you try to go online.]
+;[Login Server:]
+;[Port:]
+;[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.]
+;[Show connection error messages:]
+;[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.]
+;[Note: The support is VERY limited, only messaging and status supported.]
+;[Allowing direct connections will expose your IP address but may be necessary for some ICQ features to work properly.]
+;[Back Color]
+;[Text Color]
+;[Timeout (*)]
+;[Note]
+;[Warning]
+;[Error]
+;[Fatal]
+;[Spam detected]
+;[(*) Timeouts require Popup v. 1.0.1.9 or later]
+;[UIN:]
+;[External IP:]
+;[Internal IP:]
+;[Protocol Version:]
+;[User Client:]
+;[Online since:]
+;[System up since:]
+;[Idle since:]
+;[Status:]
+;[Nickname:]
+;[First name:]
+;[Last name:]
+;[E-mail:]
+;[Gender:]
+;[Age:]
+;[Marital status:]
+;[Keywords:]
+;[Occupation:]
+;[Company:]
+;[Department:]
+;[Position:]
+;[Organisation:]
+;[Language:]
+;[Country:]
+;[State:]
+;[City:]
+;[Interests]
+;[Category:]
+;[Past]
+;[Homepage]
+;[Note: Only JPGs and GIFs\nImage size max 64x64\nFile size max 6kB]
+;[Select contacts to store:]
+;[Title:]
+;[Message:]
+;[Please re-type your new password:]
+;[Enter your current password:]
+;[Use this codepage for Ansi <-> Unicode translation :]
+;[ICQ]
+;[Connection settings]
+;[ICQ contacts stored on server]
+;[ICQ avatars]
+;[Messaging]
+;[Peer-to-peer Messaging]
+;[Extra Features]
+;[Direct connections]
+;[Contact List Authorization]
+;[Misc Settings]
+;[Options]
+;[Look && Feel]
+;[Summary]
+;[Work]
+;[Location]
+;[Background]
+;[Other]
+;[ICQ Account Setup]
+;[Enter an authorization request]
+;[Enter ICQ Password]
+;[Manage ICQ Server Contacts]
+;[Custom Status ]
+;[Confirm Password Change]
+
+
diff --git a/protocols/IcqOscarJ/docs/icq-license.txt b/protocols/IcqOscarJ/docs/icq-license.txt
new file mode 100644
index 0000000000..7f1161073d
--- /dev/null
+++ b/protocols/IcqOscarJ/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/protocols/IcqOscarJ/docs/icq-readme.txt b/protocols/IcqOscarJ/docs/icq-readme.txt
new file mode 100644
index 0000000000..b5d582e28a
--- /dev/null
+++ b/protocols/IcqOscarJ/docs/icq-readme.txt
@@ -0,0 +1,480 @@
+
+ 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)
+
+- 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.
+
+- With HTTP Proxy Mode in Connection settings, neither Avatars nor File Transfer can work.
+ This is partly a limitation of current Miranda's network module implementation. But
+ File Transfer cannot work with HTTP Proxy, that is a protocol limitation.
+
+
+TO-DO List
+__________
+
+0.6
+ Multi-user chat
+ Mid-NetLib module for HTTP gateway (for Avatars to work) [icq_net]
+
+0.5
+ Full support for sub-groups in Manage server-list dialog
+ Simple sub-groups support (optional)
+
+
+
+Changes
+_______
+
+0.5 Development
+
+Bugfixes:
+ Fixed receiving of multi-part messages (only first part was received)
+ Fixed processing of UTF-8 encoded status messages from QIP
+ Fixed AIM away message handling (caused online status to be seen as away in some clients)
+
+New Features
+ Account management (requires Miranda IM 0.8 and newer)
+ New user details protocol support
+ Added support for status notes & moods (introduced by ICQ6)
+
+Improvements:
+ URL events are now received as normal messages
+ Use new offline messages protocol (supports unicode)
+ Ability to send/receive contacts to/from ICQ6 and AIM
+ Server-list support now groups requests - much more faster & reliable
+ Improved ChangeInfo module compatibility with screen readers
+ Client detection improvements
+ Avatars are now retrieved even for offline contacts
+
+
+0.3.9.5
+
+Bugfixes:
+ Fixed connection problems with many contacts in server-list
+ Do not lose server-list contacts due to too long nicknames/comments
+
+Improvements:
+ Reinvented known spam bot blocking
+
+
+0.3.9.4
+
+Improvements:
+ Added ability to handle malformed UCS-2 encoded offline messages
+ Fixed possible local buffer overflow
+
+
+0.3.9.3
+
+Bugfixes:
+ Fixed problem with utf-8 message API and some message plugins (weird chars)
+ Fixed double Avatar pages in User Details for newer Miranda IM
+
+
+0.3.9.2
+
+Bugfixes:
+ Fixed possible memory corruption caused by malformed langpack
+ Added support for new utf-8 message API (when available)
+ Fixed possible rare problems with Folders plug-in support
+ Other minor fixes merged from trunk (0.3.10.x Development)
+
+
+0.3.9.1
+
+Bugfixes:
+ Fixes several minor problems
+
+Improvements:
+ Oscar File Transfers now fully handle directory transfers
+
+
+0.3.9
+
+Bugfixes:
+ Fixed peer-to-peer session cookie checking (was working only due to coincidence)
+ Fixed SMS message handling, made message parsing more consistent
+ Applied fix for re-requesting authorization (thx Bio)
+ Fixed handling of message acks & status msg replies from ICQ 6
+ Fixed handling of malformed messages acks
+ Minor fixes for Popup plugin support
+ Minor protocol related tweaks
+ Fixed possible lags caused by typing notifications (on slow connections)
+ Fixed message handling (fixes bug used for stealth invisibility detection)
+ Several fixes to Rate Level 2 handling - more propper handling of message responses
+
+New Features:
+ Oscar File Transfers - like icq5 (including: transfer thru server, resume)
+
+Improvements:
+ Client detection improvements
+ Level 1 Rate management (global) - should solve problems with many contacts in list
+ Support for Custom Profile Folders plug-in - configurable avatars cache folder
+ Ability to send long offline messages (up to 4096 characters)
+ Messsage Error handling is now complete (no more disconnections on long msgs)
+ Support for Aim contacts enhanced
+ Better support for Miranda Ignore module
+
+
+0.3.7.5
+
+Bugfixes:
+ Fixed possible crash in avatar queue
+ Fixed special character conversion in Custom Status messages
+ Minor changes to client detection
+
+
+0.3.7.4
+
+Bugfixes:
+ Some small fixes to Custom Status API
+ Fixed possible buffer overrun problem in status change packet handling
+ Some avatar related fixes
+
+Improvements:
+ Added avatar validity checking
+
+
+0.3.7.3
+
+Bugfixes:
+ Fixed HTTP/HTTPS proxy support (removed useless gateway option), long messages are now sent properly
+ Improved status change handling (can handle broken packets)
+
+
+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):
+(DWORD)KeepAliveInterval - Period in which Keep-Alive packets are send if enabled - default is one minute
+
+(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-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
diff --git a/protocols/IcqOscarJ/fam_01service.cpp b/protocols/IcqOscarJ/fam_01service.cpp
new file mode 100644
index 0000000000..1d46fad6c1
--- /dev/null
+++ b/protocols/IcqOscarJ/fam_01service.cpp
@@ -0,0 +1,981 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/fam_01service.cpp $
+// Revision : $Revision: 14141 $
+// Last change on : $Date: 2012-03-09 22:52:15 +0200 (Пт, 09 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Handles packets from Service family
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+extern capstr capXStatus[];
+
+void CIcqProto::handleServiceFam(BYTE *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");
+#endif
+ /* init rates management */
+ m_rates = new rates(this, pBuffer, wBufferLength);
+ /* ack rate levels */
+#ifdef _DEBUG
+ NetLog_Server("Sending Rate Info Ack");
+#endif
+ m_rates->initAckPacket(&packet);
+ 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 (m_bSsiEnabled)
+ {
+ cookie_servlist_action* ack;
+ DWORD dwCookie;
+
+ DWORD dwLastUpdate = getSettingDword(NULL, "SrvLastUpdate", 0);
+ WORD wRecordCount = getSettingWord(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 = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ 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;
+
+ packFNACHeader(&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 = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ 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;
+
+ packFNACHeader(&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);
+ // Query flags: 1 = Enable Avatars
+ // 2 = Enable offline status message notification
+ // 4 = Enable Avatars for offline contacts
+ // 8 = Use reject for not authorized contacts
+ packTLVWord(&packet, 0x05, 0x0007);
+ 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:
+ {
+#ifdef _DEBUG
+ NetLog_Server("Server migration requested (Flags: %u)", pSnacHeader->wFlags);
+#endif
+ pBuffer += 2; // Unknown, seen: 0
+ wBufferLength -= 2;
+
+ oscar_tlv_chain *chain = readIntoTLVChain(&pBuffer, wBufferLength, 0);
+
+ if (info->cookieDataLen > 0)
+ SAFE_FREE((void**)&info->cookieData);
+
+ info->newServer = chain->getString(0x05, 1);
+ info->newServerSSL = chain->getNumber(0x8E, 1);
+ info->cookieData = (BYTE*)chain->getString(0x06, 1);
+ info->cookieDataLen = chain->getLength(0x06, 1);
+
+ disposeChain(&chain);
+
+ if (!info->newServer || !info->cookieData)
+ {
+ icq_LogMessage(LOG_FATAL, LPGEN("A server migration has failed because the server returned invalid data. You must reconnect manually."));
+ SAFE_FREE(&info->newServer);
+ SAFE_FREE((void**)&info->cookieData);
+ info->cookieDataLen = 0;
+ info->newServerReady = 0;
+ return;
+ }
+
+ NetLog_Server("Migration has started. New server will be %s", info->newServer);
+
+ m_iDesiredStatus = m_iStatus;
+ 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 = chain->getDWord(0x0A, 1);
+ setSettingDword(NULL, "IP", dwValue);
+
+ // Save member since timestamp
+ dwValue = chain->getDWord(0x05, 1);
+ if (dwValue) setSettingDword(NULL, "MemberTS", dwValue);
+
+ dwValue = chain->getDWord(0x03, 1);
+ setSettingDword(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 (!m_bSsiEnabled || info->isMigrating)
+ handleServUINSettings(wListenPort, info);
+ }
+ else if (m_hNotifyNameInfoEvent)
+ // Just notify that the set status note & mood process is finished
+ SetEvent(m_hNotifyNameInfoEvent);
+ }
+ 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);
+
+ m_ratesMutex->Enter();
+ m_rates->updateLevel(wClass, dwLevel);
+ m_ratesMutex->Leave();
+
+ if (wStatus == 2 || wStatus == 3)
+ { // this is only the simplest solution, needs rate management to every section
+ BroadcastAck(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)
+ {
+ BroadcastAck(NULL, ICQACKTYPE_RATEWARNING, ACKRESULT_STATUS, (HANDLE)wClass, wStatus);
+ NetLog_Server("Rates #%u: Clear", wClass);
+ }
+ }
+
+ break;
+
+ case ICQ_SERVER_REDIRECT_SERVICE: // reply to family request, got new connection point
+ {
+ oscar_tlv_chain *pChain = NULL;
+ cookie_family_request *pCookieData;
+
+ if (!(pChain = readIntoTLVChain(&pBuffer, wBufferLength, 0)))
+ {
+ NetLog_Server("Received Broken Redirect Service SNAC(1,5).");
+ break;
+ }
+ WORD wFamily = pChain->getWord(0x0D, 1);
+
+ // pick request data
+ if ((!FindCookie(pSnacHeader->dwRef, NULL, (void**)&pCookieData)) || (pCookieData->wFamily != wFamily))
+ {
+ disposeChain(&pChain);
+ NetLog_Server("Received unexpected SNAC(1,5), skipping.");
+ break;
+ }
+
+ FreeCookie(pSnacHeader->dwRef);
+
+ { // new family entry point received
+ char *pServer = pChain->getString(0x05, 1);
+ BYTE bServerSSL = pChain->getNumber(0x8E, 1);
+ char *pCookie = pChain->getString(0x06, 1);
+ WORD wCookieLen = pChain->getLength(0x06, 1);
+
+ if (!pServer || !pCookie)
+ {
+ NetLog_Server("Server returned invalid data, family unavailable.");
+
+ SAFE_FREE(&pServer);
+ SAFE_FREE(&pCookie);
+ SAFE_FREE((void**)&pCookieData);
+ disposeChain(&pChain);
+ break;
+ }
+
+ // Get new family server ip and port
+ WORD wPort = info->wServerPort; // get default port
+ parseServerAddress(pServer, &wPort);
+
+ // establish connection
+ NETLIBOPENCONNECTION nloc = {0};
+ if (m_bGatewayMode)
+ nloc.flags |= NLOCF_HTTPGATEWAY;
+ nloc.szHost = pServer;
+ nloc.wPort = wPort;
+
+ HANDLE hConnection = NetLib_OpenConnection(m_hServerNetlibUser, 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
+ else if (bServerSSL)
+ { /* Start SSL session if requested */
+#ifdef _DEBUG
+ NetLog_Server("(%d) Starting SSL negotiation", CallService(MS_NETLIB_GETSOCKET, (WPARAM)hConnection, 0));
+#endif
+ if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)hConnection, 0))
+ {
+ NetLog_Server("Unable to connect to ICQ new family server, SSL could not be negotiated");
+ NetLib_CloseConnection(&hConnection, FALSE);
+ }
+ }
+
+ (this->*pCookieData->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((void**)&pCookieData);
+ }
+
+ break;
+ }
+
+ case ICQ_SERVER_EXTSTATUS: // our session data
+ {
+#ifdef _DEBUG
+ NetLog_Server("Received owner session data.");
+#endif
+ while (wBufferLength > 4)
+ { // loop thru all items
+ WORD itemType = pBuffer[0] * 0x10 | pBuffer[1];
+ BYTE itemFlags = pBuffer[2];
+ BYTE itemLen = pBuffer[3];
+
+ if (itemType == AVATAR_HASH_PHOTO) /// TODO: handle photo item
+ { // skip photo item
+#ifdef _DEBUG
+ NetLog_Server("Photo item recognized");
+#endif
+ }
+ else if ((itemType == AVATAR_HASH_STATIC || itemType == AVATAR_HASH_FLASH) && (itemLen >= 0x10))
+ {
+#ifdef _DEBUG
+ NetLog_Server("Avatar item recognized");
+#endif
+ if (m_bAvatarsEnabled && !info->bMyAvatarInited) // signal the server after login
+ { // this refreshes avatar state - it used to work automatically, but now it does not
+ if (getSettingByte(NULL, "ForceOurAvatar", 0))
+ { // keep our avatar
+ TCHAR *file = GetOwnAvatarFileName();
+ SetMyAvatar(0, (LPARAM)file);
+ SAFE_FREE(&file);
+ }
+ else // only change avatar hash to the same one
+ {
+ BYTE hash[0x14];
+
+ memcpy(hash, pBuffer, 0x14);
+ hash[2] = 1; // update image status
+ updateServAvatarHash(hash, 0x14);
+ }
+ info->bMyAvatarInited = TRUE;
+ break;
+ }
+ // process owner avatar hash changed notification
+ handleAvatarOwnerHash(itemType, itemFlags, pBuffer, itemLen + 4);
+ }
+ else if (itemType == 0x02)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Status message item recognized");
+#endif
+ }
+ else if (itemType == 0x0E)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Status mood item recognized");
+#endif
+ }
+
+ // move to next item
+ if (wBufferLength >= itemLen + 4)
+ {
+ wBufferLength -= itemLen + 4;
+ pBuffer += itemLen + 4;
+ }
+ else
+ {
+ pBuffer += wBufferLength;
+ wBufferLength = 0;
+ }
+ }
+ 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* CIcqProto::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 = FindFirstContact();
+
+ while (hContact != NULL)
+ {
+ if (!getContactUid(hContact, &dwUIN, &szUID))
+ {
+ szLen[0] = strlennull(strUID(dwUIN, szUID));
+
+ switch (subtype)
+ {
+
+ case BUL_VISIBLE:
+ add = ID_STATUS_ONLINE == getSettingWord(hContact, "ApparentMode", 0);
+ break;
+
+ case BUL_INVISIBLE:
+ add = ID_STATUS_OFFLINE == getSettingWord(hContact, "ApparentMode", 0);
+ break;
+
+ case BUL_TEMPVISIBLE:
+ add = getSettingByte(hContact, "TemporaryVisible", 0);
+ // clear temporary flag
+ // Here we assume that all temporary contacts will be in one packet
+ setSettingByte(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 (m_bSsiEnabled && getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0) &&
+ !getSettingByte(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 = FindNextContact(hContact);
+ }
+ *hContactResume = NULL;
+
+ return szList;
+}
+
+
+void CIcqProto::sendEntireListServ(WORD wFamily, WORD wSubtype, int listType)
+{
+ HANDLE hResumeContact = NULL;
+
+ do
+ { // server doesn't seem to be able to cope with packets larger than 8k
+ // send only about 100contacts per packet
+ char *szList = buildUinList(listType, 0x3E8, &hResumeContact);
+ int nListLen = strlennull(szList);
+
+ if (nListLen)
+ {
+ icq_packet packet;
+
+ serverPacketInit(&packet, (WORD)(nListLen + 10));
+ packFNACHeader(&packet, wFamily, wSubtype);
+ packBuffer(&packet, (LPBYTE)szList, (WORD)nListLen);
+ sendServPacket(&packet);
+ }
+
+ SAFE_FREE((void**)&szList);
+ }
+ while (hResumeContact);
+}
+
+
+static void packShortCapability(icq_packet *packet, WORD wCapability)
+{ // pack standard capability
+ DWORD dwQ1 = 0x09460000 | wCapability;
+
+ packDWord(packet, dwQ1);
+ packDWord(packet, 0x4c7f11d1);
+ packDWord(packet, 0x82224445);
+ packDWord(packet, 0x53540000);
+}
+
+
+// CLI_SETUSERINFO
+void CIcqProto::setUserInfo()
+{
+ icq_packet packet;
+ WORD wAdditionalData = 0;
+ BYTE bXStatus = getContactXStatus(NULL);
+
+ if (m_bAimEnabled)
+ wAdditionalData += 16;
+#ifdef DBG_CAPMTN
+ wAdditionalData += 16;
+#endif
+ if (m_bUtfEnabled)
+ wAdditionalData += 16;
+#ifdef DBG_NEWCAPS
+ wAdditionalData += 16;
+#endif
+#ifdef DBG_CAPXTRAZ
+ wAdditionalData += 16;
+#endif
+#ifdef DBG_OSCARFT
+ wAdditionalData += 16;
+#endif
+ if (m_bAvatarsEnabled)
+ wAdditionalData += 16;
+ if (m_bXStatusEnabled && bXStatus != 0)
+ wAdditionalData += 16;
+#ifdef DBG_CAPHTML
+ wAdditionalData += 16;
+#endif
+#ifdef DBG_AIMCONTACTSEND
+ wAdditionalData += 16;
+#endif
+
+ //MIM/PackName
+ bool bHasPackName = false;
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingString(NULL, "ICQCaps", "PackName", &dbv )) {
+ //MIM/PackName
+ bHasPackName = true;
+ 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)(48 + wAdditionalData));
+
+#ifdef DBG_CAPMTN
+ {
+ packDWord(&packet, 0x563FC809); // CAP_TYPING
+ packDWord(&packet, 0x0B6F41BD);
+ packDWord(&packet, 0x9F794226);
+ packDWord(&packet, 0x09DFA2F3);
+ }
+#endif
+ {
+ packShortCapability(&packet, 0x1349); // AIM_CAPS_ICQSERVERRELAY
+ }
+ if (m_bUtfEnabled)
+ {
+ packShortCapability(&packet, 0x134E); // CAP_UTF8MSGS
+ } // Broadcasts the capability to receive UTF8 encoded messages
+#ifdef DBG_NEWCAPS
+ {
+ packShortCapability(&packet, 0x0000); // CAP_SHORTCAPS
+ } // Tells server we understand to new format of caps
+#endif
+#ifdef DBG_CAPXTRAZ
+ {
+ packDWord(&packet, 0x1a093c6c); // CAP_XTRAZ
+ packDWord(&packet, 0xd7fd4ec5); // Broadcasts the capability to handle
+ packDWord(&packet, 0x9d51a647); // Xtraz
+ packDWord(&packet, 0x4e34f5a0);
+ }
+#endif
+ if (m_bAvatarsEnabled)
+ {
+ packShortCapability(&packet, 0x134C); // CAP_DEVILS
+ }
+#ifdef DBG_OSCARFT
+ {
+ packShortCapability(&packet, 0x1343); // CAP_AIM_FILE
+ } // Broadcasts the capability to receive Oscar File Transfers
+#endif
+ if (m_bAimEnabled)
+ {
+ packShortCapability(&packet, 0x134D); // CAP_AIM_COMPATIBLE
+ } // Tells the server we can speak to AIM
+#ifdef DBG_AIMCONTACTSEND
+ {
+ packShortCapability(&packet, 0x134B); // CAP_SENDBUDDYLIST
+ }
+#endif
+ if (m_bXStatusEnabled && bXStatus != 0)
+ {
+ packBuffer(&packet, capXStatus[bXStatus-1], BINARY_CAP_SIZE);
+ }
+
+ packShortCapability(&packet, 0x1344); // CAP_ICQDIRECT
+
+#ifdef DBG_CAPHTML
+ packShortCapability(&packet, 0x0002); // CAP_HTMLMSGS
+#endif
+
+ packDWord(&packet, 0x4D697261); // Miranda Signature
+ packDWord(&packet, 0x6E64614D);
+ packDWord(&packet, MIRANDA_VERSION);
+ packDWord(&packet, ICQ_PLUG_VERSION);
+
+ //MIM/PackName
+ if ( bHasPackName ) {
+ packBuffer(&packet, (BYTE*)dbv.pszVal, 0x10);
+ ICQFreeVariant(&dbv);
+ }
+
+ sendServPacket(&packet);
+}
+
+
+void CIcqProto::handleServUINSettings(int nPort, serverthread_info *info)
+{
+ icq_packet packet;
+
+ setUserInfo();
+
+ /* SNAC 3,4: Tell server who's on our list (deprecated) */
+ /* SNAC 3,15: Try to add unauthorised contacts to temporary list */
+ sendEntireListServ(ICQ_BUDDY_FAMILY, ICQ_USER_ADDTOTEMPLIST, BUL_ALLCONTACTS);
+
+ if (m_iDesiredStatus == ID_STATUS_INVISIBLE)
+ {
+ /* Tell server who's on our visible list (deprecated) */
+ if (!m_bSsiEnabled)
+ sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_ADDVISIBLE, BUL_VISIBLE);
+ else
+ updateServVisibilityCode(3);
+ }
+
+ if (m_iDesiredStatus != ID_STATUS_INVISIBLE)
+ {
+ /* Tell server who's on our invisible list (deprecated) */
+ if (!m_bSsiEnabled)
+ sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_ADDINVISIBLE, BUL_INVISIBLE);
+ else
+ updateServVisibilityCode(4);
+ }
+
+ // SNAC 1,1E: Set status
+ {
+ DWORD dwDirectCookie = rand() ^ (rand() << 16);
+
+ // Get status
+ WORD wStatus = MirandaStatusToIcq(m_iDesiredStatus);
+
+ // Get status note & mood
+ char *szStatusNote = PrepareStatusNote(m_iDesiredStatus);
+ BYTE bXStatus = getContactXStatus(NULL);
+ char szMoodData[32];
+
+ // prepare mood id
+ if (m_bMoodsEnabled && bXStatus && moodXStatus[bXStatus-1] != -1)
+ null_snprintf(szMoodData, SIZEOF(szMoodData), "icqmood%d", moodXStatus[bXStatus-1]);
+ else
+ szMoodData[0] = '\0';
+
+ //! Tricky code, this ensures that the status note will be saved to the directory
+ SetStatusNote(szStatusNote, m_bGatewayMode ? 5000 : 2500, TRUE);
+
+ WORD wStatusNoteLen = strlennull(szStatusNote);
+ WORD wStatusMoodLen = strlennull(szMoodData);
+ WORD wSessionDataLen = (wStatusNoteLen ? wStatusNoteLen + 4 : 0) + 4 + wStatusMoodLen + 4;
+
+ serverPacketInit(&packet, (WORD)(71 + (wSessionDataLen ? wSessionDataLen + 4 : 0)));
+ 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, 0x0A06); // TLV 8: Independent Status Messages
+ packDWord(&packet, 0x000c0025); // TLV C: Direct connection info
+ packDWord(&packet, getSettingDword(NULL, "RealIP", 0));
+ packDWord(&packet, nPort);
+ packByte(&packet, DC_TYPE); // TCP/FLAG firewall settings
+ packWord(&packet, ICQ_VERSION);
+ packDWord(&packet, dwDirectCookie); // DC Cookie
+ packDWord(&packet, WEBFRONTPORT); // Web front port
+ packDWord(&packet, CLIENTFEATURES); // Client features
+#if defined( _UNICODE )
+ packDWord(&packet, 0x7fffffff); // Abused timestamp
+#else
+ packDWord(&packet, 0xffffffff); // Abused timestamp
+#endif
+ packDWord(&packet, ICQ_PLUG_VERSION); // Abused timestamp
+ if (ServiceExists("SecureIM/IsContactSecured"))
+ packDWord(&packet, 0x5AFEC0DE); // SecureIM Abuse
+ else
+ packDWord(&packet, 0x00000000); // Timestamp
+ packWord(&packet, 0x0000); // Unknown
+ packTLVWord(&packet, 0x001F, 0x0000);
+
+ if (wSessionDataLen)
+ { // Pack session data
+ packWord(&packet, 0x1D); // TLV 1D
+ packWord(&packet, wSessionDataLen); // TLV length
+ packWord(&packet, 0x02); // Item Type
+ if (wStatusNoteLen)
+ {
+ packWord(&packet, 0x400 | (WORD)(wStatusNoteLen + 4)); // Flags + Item Length
+ packWord(&packet, wStatusNoteLen); // Text Length
+ packBuffer(&packet, (LPBYTE)szStatusNote, wStatusNoteLen);
+ packWord(&packet, 0); // Encoding not specified (utf-8 is default)
+ }
+ else
+ packWord(&packet, 0); // Flags + Item Length
+ packWord(&packet, 0x0E); // Item Type
+ packWord(&packet, wStatusMoodLen); // Flags + Item Length
+ if (wStatusMoodLen)
+ packBuffer(&packet, (LPBYTE)szMoodData, wStatusMoodLen); // Mood
+
+ // Save current status note & mood
+ setSettingStringUtf(NULL, DBSETTING_STATUS_NOTE, szStatusNote);
+ setSettingString(NULL, DBSETTING_STATUS_MOOD, szMoodData);
+ }
+ // Release memory
+ SAFE_FREE(&szStatusNote);
+
+ sendServPacket(&packet);
+ }
+
+ /* SNAC 1,11 */
+ serverPacketInit(&packet, 14);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_IDLE);
+ packDWord(&packet, 0x00000000);
+
+ sendServPacket(&packet);
+ m_bIdleAllow = 0;
+
+ // Change status
+ SetCurrentStatus(m_iDesiredStatus);
+
+ // Finish Login sequence
+ serverPacketInit(&packet, 98);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_READY);
+ packDWord(&packet, 0x00220001); // imitate ICQ 6 behaviour
+ packDWord(&packet, 0x0110164f);
+ packDWord(&packet, 0x00010004);
+ packDWord(&packet, 0x0110164f);
+ packDWord(&packet, 0x00130004);
+ packDWord(&packet, 0x0110164f);
+ packDWord(&packet, 0x00020001);
+ packDWord(&packet, 0x0110164f);
+ packDWord(&packet, 0x00030001);
+ packDWord(&packet, 0x0110164f);
+ packDWord(&packet, 0x00150001);
+ packDWord(&packet, 0x0110164f);
+ packDWord(&packet, 0x00040001);
+ packDWord(&packet, 0x0110164f);
+ packDWord(&packet, 0x00060001);
+ packDWord(&packet, 0x0110164f);
+ packDWord(&packet, 0x00090001);
+ packDWord(&packet, 0x0110164f);
+ packDWord(&packet, 0x000A0001);
+ packDWord(&packet, 0x0110164f);
+ packDWord(&packet, 0x000B0001);
+ packDWord(&packet, 0x0110164f);
+
+ sendServPacket(&packet);
+
+ NetLog_Server(" *** Yeehah, login sequence complete");
+
+ // login sequence is complete enter logged-in mode
+ info->bLoggedIn = 1;
+ m_bConnectionLost = FALSE;
+
+ // enable auto info-update routine
+ icq_EnableUserLookup(TRUE);
+
+ if (!info->isMigrating)
+ { /* Get Offline Messages Reqeust */
+ cookie_offline_messages *ack = (cookie_offline_messages*)SAFE_MALLOC(sizeof(cookie_offline_messages));
+ if (ack)
+ {
+ DWORD dwCookie = AllocateCookie(CKT_OFFLINEMESSAGE, ICQ_MSG_CLI_REQ_OFFLINE, 0, ack);
+
+ serverPacketInit(&packet, 10);
+ packFNACHeader(&packet, ICQ_MSG_FAMILY, ICQ_MSG_CLI_REQ_OFFLINE, 0, dwCookie);
+
+ sendServPacket(&packet);
+ }
+ else
+ icq_LogMessage(LOG_WARNING, LPGEN("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 (m_bAvatarsEnabled)
+ { // Send SNAC 1,4 - request avatar family 0x10 connection
+ icq_requestnewfamily(ICQ_AVATAR_FAMILY, &CIcqProto::StartAvatarThread);
+
+ m_avatarsConnectionPending = TRUE;
+ NetLog_Server("Requesting Avatar family entry point.");
+ }
+ }
+ info->isMigrating = 0;
+
+ if (m_bAimEnabled)
+ {
+ char **szAwayMsg = NULL;
+ icq_lock l(m_modeMsgsMutex);
+
+ szAwayMsg = MirandaStatusToAwayMsg(m_iStatus);
+ if (szAwayMsg)
+ icq_sendSetAimAwayMsgServ(*szAwayMsg);
+ }
+}
diff --git a/protocols/IcqOscarJ/fam_02location.cpp b/protocols/IcqOscarJ/fam_02location.cpp
new file mode 100644
index 0000000000..5510116e73
--- /dev/null
+++ b/protocols/IcqOscarJ/fam_02location.cpp
@@ -0,0 +1,301 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/fam_02location.cpp $
+// Revision : $Revision: 13284 $
+// Last change on : $Date: 2011-01-17 00:42:01 +0200 (Пн, 17 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Handles packets from Location family
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+extern const char* cliSpamBot;
+
+void CIcqProto::handleLocationFam(BYTE *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;
+ cookie_fam15_data *pCookieData;
+
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ if (wError == 4)
+ {
+ if (FindCookie(pSnacHeader->dwRef, &hCookieContact, (void**)&pCookieData) && !getContactUin(hCookieContact) && pCookieData->bRequestType == REQUESTTYPE_PROFILE)
+ {
+ BroadcastAck(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)
+ {
+ const char *szEnc = strstrnull(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((void**)&pszStr);
+ utf8_decode(szStr, &szRes);
+ SAFE_FREE((void**)&szStr);
+
+ return szRes;
+ }
+ }
+ return pszStr;
+}
+
+void CIcqProto::handleLocationUserInfoReply(BYTE* buf, WORD wLen, DWORD dwCookie)
+{
+ HANDLE hContact;
+ DWORD dwUIN;
+ uid_str szUID;
+ WORD wTLVCount;
+ WORD wWarningLevel;
+ HANDLE hCookieContact;
+ WORD status;
+ cookie_message_data *pCookieData;
+
+ // Unpack the sender's user ID
+ if (!unpackUID(&buf, &wLen, &dwUIN, &szUID)) return;
+
+ // Syntax check
+ if (wLen < 4)
+ return;
+
+ // Warning level?
+ unpackWord(&buf, &wWarningLevel);
+ wLen -= 2;
+
+ // TLV count
+ unpackWord(&buf, &wTLVCount);
+ wLen -= 2;
+
+ // Determine contact
+ hContact = HContactFromUID(dwUIN, szUID, NULL);
+
+ // Ignore away status if the user is not already on our list
+ if (hContact == INVALID_HANDLE_VALUE)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Ignoring away reply (%s)", strUID(dwUIN, szUID));
+#endif
+ return;
+ }
+
+ if (!FindCookie(dwCookie, &hCookieContact, (void**)&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;
+ 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))
+ {
+ oscar_tlv *pTLV;
+ char *szEncoding = NULL;
+
+ // Get Profile encoding TLV
+ pTLV = pChain->getTLV(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 = pChain->getTLV(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);
+ }
+
+ setSettingString(hContact, "About", szMsg);
+ BroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1 ,0);
+
+ SAFE_FREE((void**)&szMsg);
+ }
+ 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 = pChain->getTLV(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 = pChain->getTLV(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;
+ pre.flags = 0;
+ pre.szMessage = szMsg?szMsg:(char *)"";
+ pre.timestamp = time(NULL);
+ pre.lParam = dwCookie;
+
+ CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
+
+ SAFE_FREE((void**)&szMsg);
+ }
+ break;
+ }
+ }
+}
diff --git a/protocols/IcqOscarJ/fam_03buddy.cpp b/protocols/IcqOscarJ/fam_03buddy.cpp
new file mode 100644
index 0000000000..b551066248
--- /dev/null
+++ b/protocols/IcqOscarJ/fam_03buddy.cpp
@@ -0,0 +1,801 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/fam_03buddy.cpp $
+// Revision : $Revision: 13414 $
+// Last change on : $Date: 2011-03-09 15:17:26 +0200 (Ср, 09 мар 2011) $
+// Last change by : $Author: ashpynov@gmail.com $
+//
+// DESCRIPTION:
+//
+// Handles packets from Buddy family
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+extern const char* cliSpamBot;
+
+void CIcqProto::handleBuddyFam(BYTE *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 CIcqProto::handleReplyBuddy(BYTE *buf, WORD wPackLen)
+{
+ oscar_tlv_chain *pChain = readIntoTLVChain(&buf, wPackLen, 0);
+
+ if (pChain)
+ {
+ DWORD wMaxUins = pChain->getWord(1, 1);
+ DWORD wMaxWatchers = pChain->getWord(2, 1);
+ DWORD wMaxTemporary = pChain->getWord(4, 1);
+
+ NetLog_Server("MaxUINs %u", wMaxUins);
+ NetLog_Server("MaxWatchers %u", wMaxWatchers);
+ NetLog_Server("MaxTemporary %u", wMaxTemporary);
+
+ disposeChain(&pChain);
+ }
+ else
+ {
+ NetLog_Server("Error: Malformed BuddyReply");
+ }
+}
+
+
+int unpackSessionDataItem(oscar_tlv_chain *pChain, WORD wItemType, BYTE **ppItemData, WORD *pwItemSize, BYTE *pbItemFlags)
+{
+ oscar_tlv *tlv = pChain->getTLV(0x1D, 1);
+ int len = 0;
+ BYTE *data;
+
+ if (tlv)
+ {
+ len = tlv->wLen;
+ data = tlv->pData;
+ }
+
+ while (len >= 4)
+ { // parse session data items one by one
+ WORD itemType;
+ BYTE itemFlags;
+ BYTE itemLen;
+
+ unpackWord(&data, &itemType);
+ unpackByte(&data, &itemFlags);
+ unpackByte(&data, &itemLen);
+ len -= 4;
+
+ // just some validity check
+ if (itemLen > len)
+ itemLen = len;
+
+ if (itemType == wItemType)
+ { // found the requested item
+ if (ppItemData)
+ *ppItemData = data;
+ if (pwItemSize)
+ *pwItemSize = itemLen;
+ if (pbItemFlags)
+ *pbItemFlags = itemFlags;
+
+ return 1; // Success
+ }
+ data += itemLen;
+ len -= itemLen;
+ }
+ return 0;
+}
+
+
+// TLV(1) User class
+// TLV(3) Signon time
+// TLV(4) Idle time (in minutes)
+// TLV(5) Member since
+// TLV(6) New status
+// TLV(8) Status Capabilities
+// TLV(A) External IP
+// TLV(C) DC Info
+// TLV(D) Capabilities
+// TLV(F) Session timer (in seconds)
+// TLV(14) Instance number (AIM only)
+// TLV(19) Short capabilities
+// TLV(1D) Session Data (Avatar, Mood, etc.)
+// TLV(1F) User class (upper bytes)
+// TLV(26) AIM Profile update time
+// TLV(27) AIM Away message update time
+// TLV(29) Away status since
+// TLV(2B) URL to protocol icon
+// TLV(2F) unknown key
+// TLV(30) unknown timestamp
+
+void CIcqProto::handleUserOnline(BYTE *buf, WORD wLen, serverthread_info *info)
+{
+ DWORD dwPort = 0;
+ DWORD dwRealIP = 0;
+ DWORD dwUIN;
+ uid_str szUID;
+ DWORD dwDirectConnCookie = 0;
+ DWORD dwWebPort = 0;
+ DWORD dwFT1 = 0, dwFT2 = 0, dwFT3 = 0;
+ const char *szClient = NULL;
+ BYTE bClientId = 0;
+ WORD wVersion = 0;
+ WORD wTLVCount;
+ WORD wWarningLevel;
+ WORD wStatusFlags;
+ WORD wStatus = 0, wOldStatus = 0;
+ BYTE nTCPFlag = 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
+ HANDLE 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
+ WORD wClass = pChain->getWord(0x01, 1);
+ int nIsICQ = wClass & CLASS_ICQ;
+
+ if (dwUIN)
+ {
+ // Get DC info TLV
+ pTLV = pChain->getTLV(0x0C, 1);
+ if (pTLV && (pTLV->wLen >= 15))
+ {
+ BYTE *pBuffer = pTLV->pData;
+
+ nIsICQ = TRUE;
+
+ 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 = pChain->getTLV(0x06, 1);
+ if (pTLV && (pTLV->wLen >= 4))
+ {
+ BYTE *pBuffer = pTLV->pData;
+
+ unpackWord(&pBuffer, &wStatusFlags);
+ unpackWord(&pBuffer, &wStatus);
+ }
+ else if (!nIsICQ)
+ {
+ // Connected thru AIM client, guess by user class
+ if (wClass & CLASS_AWAY)
+ wStatus = ID_STATUS_AWAY;
+ else if (wClass & CLASS_WIRELESS)
+ wStatus = ID_STATUS_ONTHEPHONE;
+ else
+ wStatus = ID_STATUS_ONLINE;
+
+ wStatusFlags = 0;
+ }
+ else
+ {
+ // Huh? No status TLV? Lets guess then...
+ wStatusFlags = 0;
+ wStatus = ICQ_STATUS_ONLINE;
+ }
+ }
+ else
+ {
+ nIsICQ = FALSE;
+
+ if (wClass & CLASS_AWAY)
+ wStatus = ID_STATUS_AWAY;
+ else if (wClass & CLASS_WIRELESS)
+ wStatus = ID_STATUS_ONTHEPHONE;
+ 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
+ DWORD dwIP = pChain->getDWord(0x0A, 1);
+
+ // Get Online Since TLV
+ DWORD dwOnlineSince = pChain->getDWord(0x03, 1);
+
+ // Get Away Since TLV
+ DWORD dwAwaySince = pChain->getDWord(0x29, 1);
+
+ // Get Member Since TLV
+ DWORD dwMemberSince = pChain->getDWord(0x05, 1);
+
+ // Get Idle timer TLV
+ WORD wIdleTimer = pChain->getWord(0x04, 1);
+ time_t tIdleTS = 0;
+ if (wIdleTimer)
+ {
+ time(&tIdleTS);
+ tIdleTS -= (wIdleTimer*60);
+ };
+
+#ifdef _DEBUG
+ if (wIdleTimer)
+ NetLog_Server("Idle timer is %u.", wIdleTimer);
+ NetLog_Server("Online since %s", time2text(dwOnlineSince));
+ if (dwAwaySince)
+ NetLog_Server("Status was set on %s", time2text(dwAwaySince));
+#endif
+
+ // Check client capabilities
+ if (hContact != NULL)
+ {
+ wOldStatus = getContactStatus(hContact);
+
+ // Collect all Capability info from TLV chain
+ BYTE *capBuf = NULL;
+ WORD capLen = 0;
+
+ // Get Location Capability Info TLVs
+ oscar_tlv *pFullTLV = pChain->getTLV(0x0D, 1);
+ oscar_tlv *pShortTLV = pChain->getTLV(0x19, 1);
+
+ if (pFullTLV && (pFullTLV->wLen >= BINARY_CAP_SIZE))
+ capLen += pFullTLV->wLen;
+
+ if (pShortTLV && (pShortTLV->wLen >= 2))
+ capLen += (pShortTLV->wLen * 8);
+
+ capBuf = (BYTE*)_alloca(capLen + BINARY_CAP_SIZE);
+
+ if (capLen)
+ {
+ BYTE *pCapability = capBuf;
+
+ capLen = 0; // we need to recount that
+
+ if (pFullTLV && (pFullTLV->wLen >= BINARY_CAP_SIZE))
+ { // copy classic Capabilities
+ BYTE *cData = pFullTLV->pData;
+ int cLen = pFullTLV->wLen;
+
+ while (cLen)
+ { // be impervious to duplicates (AOL sends them sometimes)
+ if (!capLen || !MatchCapability(capBuf, capLen, (capstr*)cData, BINARY_CAP_SIZE))
+ { // not present, add
+ memcpy(pCapability, cData, BINARY_CAP_SIZE);
+ capLen += BINARY_CAP_SIZE;
+ pCapability += BINARY_CAP_SIZE;
+ }
+ cData += BINARY_CAP_SIZE;
+ cLen -= BINARY_CAP_SIZE;
+ }
+ }
+
+ if (pShortTLV && (pShortTLV->wLen >= 2))
+ { // copy short Capabilities
+ capstr tmp;
+ BYTE *cData = pShortTLV->pData;
+ int cLen = pShortTLV->wLen;
+
+ memcpy(tmp, capShortCaps, BINARY_CAP_SIZE);
+ while (cLen)
+ { // be impervious to duplicates (AOL sends them sometimes)
+ tmp[2] = cData[0];
+ tmp[3] = cData[1];
+
+ if (!capLen || !MatchCapability(capBuf, capLen, &tmp, BINARY_CAP_SIZE))
+ { // not present, add
+ memcpy(pCapability, tmp, BINARY_CAP_SIZE);
+ capLen += BINARY_CAP_SIZE;
+ pCapability += BINARY_CAP_SIZE;
+ }
+ cData += 2;
+ cLen -= 2;
+ }
+ }
+#ifdef _DEBUG
+ NetLog_Server("Detected %d capability items.", capLen / BINARY_CAP_SIZE);
+#endif
+ }
+
+ if (capLen)
+ { // Update the contact's capabilies if present in packet
+ SetCapabilitiesFromBuffer(hContact, capBuf, capLen, wOldStatus == ID_STATUS_OFFLINE);
+
+ char *szCurrentClient = wOldStatus == ID_STATUS_OFFLINE ? NULL : getSettingStringUtf(hContact, "MirVer", NULL);
+
+ szClient = detectUserClient(hContact, nIsICQ, wClass, dwOnlineSince, szCurrentClient, wVersion, dwFT1, dwFT2, dwFT3, nTCPFlag, dwDirectConnCookie, dwWebPort, capBuf, capLen, &bClientId, szStrBuf);
+ // Check if the client changed, if not do not change
+ if (szCurrentClient && !strcmpnull(szCurrentClient, szClient))
+ szClient = (const char*)-1;
+ SAFE_FREE(&szCurrentClient);
+ }
+ else if (wOldStatus == ID_STATUS_OFFLINE)
+ {
+ // Remove the contact's capabilities if coming from offline
+ ClearAllContactCapabilities(hContact);
+
+ // no capability
+ NetLog_Server("No capability info TLVs");
+
+ szClient = detectUserClient(hContact, nIsICQ, wClass, dwOnlineSince, NULL, wVersion, dwFT1, dwFT2, dwFT3, nTCPFlag, dwDirectConnCookie, dwWebPort, NULL, capLen, &bClientId, szStrBuf);
+ }
+ else
+ {
+ // Capabilities not present in update packet, do not touch
+ szClient = (const char*)-1; // we don't want to client be overwritten
+ }
+
+ // handle Xtraz status
+ char *moodData = NULL;
+ WORD moodSize = 0;
+
+ unpackSessionDataItem(pChain, 0x0E, (BYTE**)&moodData, &moodSize, NULL);
+ if (capLen || wOldStatus == ID_STATUS_OFFLINE)
+ handleXStatusCaps(dwUIN, szUID, hContact, capBuf, capLen, moodData, moodSize);
+ else
+ handleXStatusCaps(dwUIN, szUID, hContact, NULL, 0, moodData, moodSize);
+
+ // Determine support for extended status messages
+ if (pChain->getWord(0x08, 1) == 0x0A06)
+ SetContactCapabilities(hContact, CAPF_STATUS_MESSAGES);
+ else if (wOldStatus == ID_STATUS_OFFLINE)
+ ClearContactCapabilities(hContact, CAPF_STATUS_MESSAGES);
+
+#ifdef _DEBUG
+ if (wOldStatus == ID_STATUS_OFFLINE)
+ {
+ if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY))
+ NetLog_Server("Supports advanced messages");
+ else
+ NetLog_Server("Does NOT support advanced messages");
+ }
+#endif
+
+ if (!nIsICQ)
+ {
+ // AIM clients does not advertise these, but do support them
+ SetContactCapabilities(hContact, CAPF_UTF | CAPF_TYPING);
+ // Server relayed messages are only supported by ICQ clients
+ ClearContactCapabilities(hContact, CAPF_SRV_RELAY);
+
+ if (dwUIN && wOldStatus == ID_STATUS_OFFLINE)
+ NetLog_Server("Logged in with AIM client");
+ }
+
+ if (nIsICQ && wVersion < 8)
+ {
+ ClearContactCapabilities(hContact, CAPF_SRV_RELAY);
+ if (wOldStatus == ID_STATUS_OFFLINE)
+ NetLog_Server("Forcing simple messages due to compability issues");
+ }
+
+ // Process Avatar Hash
+ pTLV = pChain->getTLV(0x1D, 1);
+ if (pTLV)
+ handleAvatarContactHash(dwUIN, szUID, hContact, pTLV->pData, pTLV->wLen, wOldStatus);
+ else
+ handleAvatarContactHash(dwUIN, szUID, hContact, NULL, 0, wOldStatus);
+
+ // Process Status Note
+ parseStatusNote(dwUIN, szUID, hContact, pChain);
+ }
+ // Free TLV chain
+ disposeChain(&pChain);
+
+ // Save contacts details in database
+ if (hContact != NULL)
+ {
+ setSettingDword(hContact, "LogonTS", dwOnlineSince);
+ setSettingDword(hContact, "AwayTS", dwAwaySince);
+ setSettingDword(hContact, "IdleTS", tIdleTS);
+
+ if (dwMemberSince)
+ setSettingDword(hContact, "MemberTS", dwMemberSince);
+
+ if (nIsICQ)
+ { // on AIM these are not used
+ setSettingDword(hContact, "DirectCookie", dwDirectConnCookie);
+ setSettingByte(hContact, "DCType", (BYTE)nTCPFlag);
+ setSettingWord(hContact, "UserPort", (WORD)(dwPort & 0xffff));
+ setSettingWord(hContact, "Version", wVersion);
+ }
+ else
+ {
+ deleteSetting(hContact, "DirectCookie");
+ deleteSetting(hContact, "DCType");
+ deleteSetting(hContact, "UserPort");
+ deleteSetting(hContact, "Version");
+ }
+
+ if (!szClient)
+ {
+ // if no detection, set uknown
+ szClient = (nIsICQ ? "Unknown" : "Unknown AIM");
+ }
+ if (szClient != (char*)-1)
+ {
+ setSettingStringUtf(hContact, "MirVer", szClient);
+ setSettingByte(hContact, "ClientID", bClientId);
+ }
+
+ if (wOldStatus == ID_STATUS_OFFLINE)
+ {
+ setSettingDword(hContact, "IP", dwIP);
+ setSettingDword(hContact, "RealIP", dwRealIP);
+ }
+ else
+ { // if not first notification only write significant information
+ if (dwIP)
+ setSettingDword(hContact, "IP", dwIP);
+ if (dwRealIP)
+ setSettingDword(hContact, "RealIP", dwRealIP);
+ }
+ setSettingWord(hContact, "Status", (WORD)IcqStatusToMiranda(wStatus));
+
+ // Update info?
+ if (dwUIN)
+ { // check if the local copy of user details is up-to-date
+ if (IsMetaInfoChanged(hContact))
+ icq_QueueUser(hContact);
+ }
+ }
+
+ if (wOldStatus != IcqStatusToMiranda(wStatus))
+ { // And a small log notice... if status was changed
+ if (nIsICQ)
+ NetLog_Server("%u changed status to %s (v%d).", dwUIN, MirandaStatusToString(IcqStatusToMiranda(wStatus)), wVersion);
+ else
+ NetLog_Server("%s changed status to %s.", strUID(dwUIN, szUID), MirandaStatusToString(IcqStatusToMiranda(wStatus)));
+ }
+#ifdef _DEBUG
+ else
+ {
+ if (nIsICQ)
+ NetLog_Server("%u has status %s (v%d).", dwUIN, MirandaStatusToString(IcqStatusToMiranda(wStatus)), wVersion);
+ else
+ NetLog_Server("%s has status %s.", strUID(dwUIN, szUID), MirandaStatusToString(IcqStatusToMiranda(wStatus)));
+ }
+#endif
+
+ if (szClient == cliSpamBot)
+ {
+ if (getSettingByte(NULL, "KillSpambots", DEFAULT_KILLSPAM_ENABLED) && DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ { // kill spammer
+ icq_DequeueUser(dwUIN);
+ icq_sendRemoveContact(dwUIN, NULL);
+ AddToSpammerList(dwUIN);
+ if (getSettingByte(NULL, "PopupsSpamEnabled", DEFAULT_SPAM_POPUPS_ENABLED))
+ ShowPopUpMsg(hContact, LPGEN("Spambot Detected"), LPGEN("Contact deleted & further events blocked."), POPTYPE_SPAM);
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+
+ NetLog_Server("Contact %u deleted", dwUIN);
+ }
+ }
+}
+
+
+void CIcqProto::handleUserOffline(BYTE *buf, WORD wLen)
+{
+ DWORD dwUIN;
+ uid_str szUID;
+
+ do {
+ oscar_tlv_chain *pChain = NULL;
+ WORD wTLVCount;
+ DWORD dwAwaySince;
+
+ // 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)
+ {
+ disposeChain(&pChain);
+ return;
+ }
+
+ if (wTLVType == 0x1D)
+ { // read only TLV with Session data into chain
+ BYTE *pTLV = buf - 4;
+ disposeChain(&pChain);
+ pChain = readIntoTLVChain(&pTLV, wLen + 4, 1);
+ }
+ else if (wTLVType == 0x29 && wTLVLen == sizeof(DWORD))
+ { // get Away Since value
+ BYTE *pData = buf;
+ unpackDWord(&pData, &dwAwaySince);
+ }
+
+ buf += wTLVLen;
+ wLen -= wTLVLen;
+ wTLVCount--;
+ }
+
+ // Determine contact
+ HANDLE hContact = HContactFromUID(dwUIN, szUID, NULL);
+
+ // Skip contacts that are not already on our list or are already offline
+ if (hContact != INVALID_HANDLE_VALUE)
+ {
+ WORD wOldStatus = getContactStatus(hContact);
+
+ // Process Avatar Hash
+ oscar_tlv *pAvatarTLV = pChain ? pChain->getTLV(0x1D, 1) : NULL;
+ if (pAvatarTLV)
+ handleAvatarContactHash(dwUIN, szUID, hContact, pAvatarTLV->pData, pAvatarTLV->wLen, wOldStatus);
+ else
+ handleAvatarContactHash(dwUIN, szUID, hContact, NULL, 0, wOldStatus);
+
+ // Process Status Note (offline status note)
+ parseStatusNote(dwUIN, szUID, hContact, pChain);
+
+ // Update status times
+ setSettingDword(hContact, "IdleTS", 0);
+ setSettingDword(hContact, "AwayTS", dwAwaySince);
+
+ // Clear custom status & mood
+ char tmp = NULL;
+ handleXStatusCaps(dwUIN, szUID, hContact, (BYTE*)&tmp, 0, &tmp, 0);
+
+ if (wOldStatus != ID_STATUS_OFFLINE)
+ {
+ NetLog_Server("%s went offline.", strUID(dwUIN, szUID));
+
+ setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+ // close Direct Connections to that user
+ CloseContactDirectConns(hContact);
+ // Reset DC status
+ setSettingByte(hContact, "DCStatus", 0);
+ }
+#ifdef _DEBUG
+ else
+ NetLog_Server("%s is offline.", strUID(dwUIN, szUID));
+#endif
+ }
+
+ // Release memory
+ disposeChain(&pChain);
+ }
+ while (wLen >= 1);
+}
+
+
+void CIcqProto::parseStatusNote(DWORD dwUin, char *szUid, HANDLE hContact, oscar_tlv_chain *pChain)
+{
+ DWORD dwStatusNoteTS = time(NULL);
+ BYTE *pStatusNoteTS, *pStatusNote;
+ WORD wStatusNoteTSLen, wStatusNoteLen;
+ BYTE bStatusNoteFlags;
+
+ if (unpackSessionDataItem(pChain, 0x0D, &pStatusNoteTS, &wStatusNoteTSLen, NULL) && wStatusNoteTSLen == sizeof(DWORD))
+ unpackDWord(&pStatusNoteTS, &dwStatusNoteTS);
+
+ // Get Status Note session item
+ if (unpackSessionDataItem(pChain, 0x02, &pStatusNote, &wStatusNoteLen, &bStatusNoteFlags))
+ {
+ char *szStatusNote = NULL;
+
+ if ((bStatusNoteFlags & 4) == 4 && wStatusNoteLen >= 4)
+ {
+ BYTE *buf = pStatusNote;
+ WORD buflen = wStatusNoteLen - 2;
+ WORD wTextLen;
+
+ unpackWord(&buf, &wTextLen);
+ if (wTextLen > buflen)
+ wTextLen = buflen;
+
+ if (wTextLen > 0)
+ {
+ szStatusNote = (char*)_alloca(wStatusNoteLen + 1);
+ unpackString(&buf, szStatusNote, wTextLen);
+ szStatusNote[wTextLen] = '\0';
+ buflen -= wTextLen;
+
+ WORD wEncodingType = 0;
+ char *szEncoding = NULL;
+
+ if (buflen >= 2)
+ unpackWord(&buf, &wEncodingType);
+
+ if (wEncodingType == 1 && buflen > 6)
+ { // Encoding specified
+ buf += 2;
+ buflen -= 2;
+ unpackWord(&buf, &wTextLen);
+ if (wTextLen > buflen)
+ wTextLen = buflen;
+ szEncoding = (char*)_alloca(wTextLen + 1);
+ unpackString(&buf, szEncoding, wTextLen);
+ szEncoding[wTextLen] = '\0';
+ }
+ else if (UTF8_IsValid(szStatusNote))
+ szEncoding = "utf-8";
+
+ szStatusNote = ApplyEncoding(szStatusNote, szEncoding);
+ }
+ }
+ // Check if the status note was changed
+ if (dwStatusNoteTS > getSettingDword(hContact, DBSETTING_STATUS_NOTE_TIME, 0))
+ {
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ if (strlennull(szStatusNote) || (!getSettingString(hContact, DBSETTING_STATUS_NOTE, &dbv) && (dbv.type == DBVT_ASCIIZ || dbv.type == DBVT_UTF8) && strlennull(dbv.pszVal)))
+ NetLog_Server("%s changed status note to \"%s\"", strUID(dwUin, szUid), szStatusNote ? szStatusNote : "");
+
+ ICQFreeVariant(&dbv);
+
+ if (szStatusNote)
+ setSettingStringUtf(hContact, DBSETTING_STATUS_NOTE, szStatusNote);
+ else
+ deleteSetting(hContact, DBSETTING_STATUS_NOTE);
+ setSettingDword(hContact, DBSETTING_STATUS_NOTE_TIME, dwStatusNoteTS);
+
+ { // Broadcast a notification
+ int nNoteLen = strlennull(szStatusNote);
+ char *szNoteAnsi = NULL;
+
+ if (nNoteLen)
+ { // the broadcast does not support unicode
+ szNoteAnsi = (char*)_alloca(nNoteLen + 1);
+ utf8_decode_static(szStatusNote, szNoteAnsi, strlennull(szStatusNote) + 1);
+ }
+ if (getContactXStatus(hContact) != 0 || !CheckContactCapabilities(hContact, CAPF_STATUS_MESSAGES))
+ {
+ setStatusMsgVar(hContact, szStatusNote, false);
+ BroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, NULL, (LPARAM)szNoteAnsi);
+ }
+ }
+ }
+ SAFE_FREE(&szStatusNote);
+ }
+ else
+ {
+ if (getContactStatus(hContact) == ID_STATUS_OFFLINE)
+ {
+ setStatusMsgVar(hContact, NULL, false);
+ deleteSetting(hContact, DBSETTING_STATUS_NOTE);
+ setSettingDword(hContact, DBSETTING_STATUS_NOTE_TIME, dwStatusNoteTS);
+ }
+ }
+}
+
+
+void CIcqProto::handleNotifyRejected(BYTE *buf, WORD wPackLen)
+{
+ DWORD dwUIN;
+ uid_str szUID;
+
+ while (wPackLen)
+ if (unpackUID(&buf, &wPackLen, &dwUIN, &szUID))
+ NetLog_Server("%s status notification rejected.", strUID(dwUIN, szUID));
+}
diff --git a/protocols/IcqOscarJ/fam_04message.cpp b/protocols/IcqOscarJ/fam_04message.cpp
new file mode 100644
index 0000000000..bf2ed45578
--- /dev/null
+++ b/protocols/IcqOscarJ/fam_04message.cpp
@@ -0,0 +1,3050 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/fam_04message.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Handles packets from Family 4 ICBM Messages
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void CIcqProto::handleMsgFam(BYTE *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_REPLYICBM: // SNAC(4, 0x05) SRV_REPLYICBM
+ handleReplyICBM(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;
+
+ 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(CIcqProto *ppro, 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
+ ppro->sendServPacket(&packet);
+}
+
+
+void CIcqProto::handleReplyICBM(BYTE *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(this, 0x0000, dwFlags);
+}
+
+
+void CIcqProto::handleRecvServMsg(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{
+ DWORD dwUin;
+ DWORD dwMsgID1;
+ DWORD dwMsgID2;
+ 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, &dwMsgID1); // TODO: msg cookies should be main
+ wLen -= 4;
+ unpackLEDWord(&buf, &dwMsgID2);
+ 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.
+ BYTE *pBufStart = buf;
+ oscar_tlv_chain *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 -= buf - pBufStart;
+ }
+
+
+ // This is where the format specific data begins
+
+ switch (wMessageFormat) {
+
+ case 1: // Simple message format
+ handleRecvServMsgType1(buf, wLen, dwUin, szUID, dwMsgID1, dwMsgID2, dwRef);
+ break;
+
+ case 2: // Encapsulated messages
+ handleRecvServMsgType2(buf, wLen, dwUin, szUID, dwMsgID1, dwMsgID2, dwRef);
+ break;
+
+ case 4: // Typed messages
+ handleRecvServMsgType4(buf, wLen, dwUin, szUID, dwMsgID1, dwMsgID2, dwRef);
+ break;
+
+ default:
+ NetLog_Server("Unknown format message thru server - Ref %u, Type: %u, UID: %s", dwRef, wMessageFormat, strUID(dwUin, szUID));
+ break;
+
+ }
+}
+
+
+char* CIcqProto::convertMsgToUserSpecificUtf(HANDLE hContact, const char *szMsg)
+{
+ WORD wCP = getSettingWord(hContact, "CodePage", m_wAnsiCodepage);
+ char *usMsg = NULL;
+
+ if (wCP != CP_ACP)
+ usMsg = ansi_to_utf8_codepage(szMsg, wCP);
+
+ return usMsg;
+}
+
+
+void CIcqProto::handleRecvServMsgType1(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef)
+{
+ WORD wTLVType;
+ WORD wTLVLen;
+ BYTE* pMsgTLV;
+
+ if (wLen < 4)
+ { // just perform basic structure check
+ 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 = 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 = pChain->getTLV(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;
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+ int bAdded;
+
+ HANDLE hContact = HContactFromUID(dwUin, szUID, &bAdded);
+
+ while (pMessageTLV = pChain->getTLV(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, getSettingWord(hContact, "CodePage", m_wAnsiCodepage));
+
+ 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((char*)szMsgPart, getSettingWord(hContact, "CodePage", m_wAnsiCodepage));
+
+ 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))
+ {
+ if (_strnicmp(szMsg, "<html>", 6) == 0)
+ { // 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
+ cookie_offline_messages *cookie;
+
+ if (!(dwRef & 0x80000000) && FindCookie(dwRef, NULL, (void**)&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;
+
+ unpackDWord(&pBuf, &dwRecvTime);
+ NetLog_Server("Message (format %u) - Offline timestamp is %s", 1, time2text(dwRecvTime));
+ }
+ SAFE_FREE((void**)&pTimeTLV);
+ }
+ }
+ // Create and send the message event
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)&pre;
+ pre.timestamp = dwRecvTime;
+ pre.szMessage = (char *)szMsg;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+
+ NetLog_Server("Message (format 1) received");
+
+ // Save tick value
+ setSettingDword(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);
+
+ SAFE_FREE((void**)&pMsgTLV);
+}
+
+
+void CIcqProto::handleRecvServMsgType2(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef)
+{
+ WORD wTLVType;
+ WORD wTLVLen;
+ BYTE *pDataBuf = NULL;
+ BYTE *pBuf;
+
+ if (wLen < 4)
+ {
+ 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 q1,q2,q3,q4;
+
+ if (wTLVLen < 26)
+ { // just check if all basic data is there
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+ SAFE_FREE((void**)&pBuf);
+ 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
+ HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
+
+ if (wCommand == 1)
+ {
+ NetLog_Server("Cannot handle abort messages yet... :(");
+ SAFE_FREE((void**)&pBuf);
+ return;
+ }
+
+ if (wTLVLen < 4)
+ { // just check if at least one tlv is there
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+ SAFE_FREE((void**)&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);
+ if (!chain)
+ { // sanity check
+ NetLog_Server("Message (format %u) - Invalid data", 2);
+ SAFE_FREE((void**)&pBuf);
+ return;
+ }
+
+ WORD wAckType = chain->getWord(0x0A, 1);
+
+ // Update the saved DC info (if contact already exists)
+ if (hContact != INVALID_HANDLE_VALUE)
+ {
+ DWORD dwIP, dwExternalIP;
+ WORD wPort;
+
+ if (dwExternalIP = chain->getDWord(0x03, 1))
+ setSettingDword(hContact, "RealIP", dwExternalIP);
+ if (dwIP = chain->getDWord(0x04, 1))
+ setSettingDword(hContact, "IP", dwIP);
+ if (wPort = chain->getWord(0x05, 1))
+ setSettingWord(hContact, "UserPort", wPort);
+
+ // Save tick value
+ BYTE bClientID = getSettingByte(hContact, "ClientID", 0);
+ if (bClientID == CLID_GENERIC || bClientID == CLID_ICQ6)
+ setSettingDword(hContact, "TickTS", time(NULL) - (dwMsgID1/1000));
+ else
+ setSettingDword(hContact, "TickTS", 0);
+ }
+
+ // Parse the next message level
+ if (tlv = chain->getTLV(0x2711, 1))
+ {
+ parseServRelayData(tlv->pData, tlv->wLen, hContact, dwUin, szUID, dwMsgID1, dwMsgID2, wAckType);
+ }
+ 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)
+ {
+ NetLog_Server("Cannot handle abort messages yet... :(");
+ SAFE_FREE((void**)&pBuf);
+ return;
+ }
+ if (wTLVLen < 4)
+ { // just check if at least one tlv is there
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+ SAFE_FREE((void**)&pBuf);
+ return;
+ }
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ SAFE_FREE((void**)&pBuf);
+ return;
+ }
+ chain = readIntoTLVChain(&pDataBuf, wTLVLen, 0);
+ if (!chain)
+ { // Malformed packet
+ NetLog_Server("Error: Malformed data in packet");
+ SAFE_FREE((void**)&pBuf);
+ return;
+ }
+
+ WORD wAckType = chain->getWord(0x0A, 1);
+ // Parse the next message level
+ if (tlv = chain->getTLV(0x2711, 1))
+ {
+ if (tlv->wLen == 0x1B)
+ {
+ BYTE *buf = tlv->pData;
+ DWORD dwUin;
+
+ unpackLEDWord(&buf, &dwUin);
+
+ HANDLE hContact = HContactFromUIN(dwUin, NULL);
+ if (hContact == INVALID_HANDLE_VALUE)
+ {
+ NetLog_Server("Error: %s from unknown contact %u", "Reverse Connect Request", dwUin);
+ }
+ else
+ {
+ DWORD dwIp, dwPort;
+ WORD wVersion;
+ BYTE bMode;
+
+ 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);
+
+ setSettingDword(hContact, "IP", dwIp);
+ setSettingWord(hContact, "UserPort", (WORD)dwPort);
+ setSettingByte(hContact, "DCType", bMode);
+ setSettingWord(hContact, "Version", wVersion);
+ if (wVersion > 6)
+ {
+ cookie_reverse_connect *pCookie = (cookie_reverse_connect*)SAFE_MALLOC(sizeof(cookie_reverse_connect));
+
+ unpackLEDWord(&buf, (DWORD*)&pCookie->ft);
+ pCookie->dwMsgID1 = dwMsgID1;
+ pCookie->dwMsgID2 = dwMsgID2;
+
+ 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, dwMsgID1, dwMsgID2, wCommand);
+ }
+ else if (CompareGUIDs(q1,q2,q3,q4, MCAP_CONTACTS))
+ { // this is Contacts Transfer
+ handleRecvServMsgContacts(pDataBuf, wTLVLen, dwUin, szUID, dwMsgID1, dwMsgID2, 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);
+ }
+
+ SAFE_FREE((void**)&pBuf);
+}
+
+
+void CIcqProto::parseServRelayData(BYTE *pDataBuf, WORD wLen, HANDLE hContact, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, WORD wAckType)
+{
+ WORD wId;
+
+ if (wLen < 2)
+ {
+ 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;
+ DWORD dwGuid1,dwGuid2,dwGuid3,dwGuid4;
+
+ if (wLen < 31)
+ { // just check if we have data to work with
+ NetLog_Server("Message (format %u) - Ignoring empty message", 2);
+ return;
+ }
+
+ unpackLEWord(&pDataBuf, &wVersion);
+ wLen -= 2;
+
+ if (hContact != INVALID_HANDLE_VALUE)
+ setSettingWord(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 ?
+ BYTE bMsgType;
+ BYTE bFlags;
+ WORD wStatus, wPritority;
+ WORD wMsgLen;
+
+ if (wLen < 20)
+ { // check if there is everything that should be there
+ 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:
+ {
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ return;
+ }
+
+ char* 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, dwMsgID1, dwMsgID2, 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:
+ {
+ if (wLen < wMsgLen)
+ { // sanity check
+ NetLog_Server("Error: Malformed server Greeting message");
+ return;
+ }
+
+ parseServRelayPluginData(pDataBuf + wMsgLen, wLen - wMsgLen, hContact, dwUin, szUID, dwMsgID1, dwMsgID2, wAckType, bFlags, wStatus, wCookie, wVersion);
+ break;
+ }
+
+ // Everything else
+ default:
+ {
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ return;
+ }
+ message_ack_params pMsgAck = {0};
+
+ pMsgAck.bType = MAT_SERVER_ADVANCED;
+ pMsgAck.dwUin = dwUin;
+ pMsgAck.dwMsgID1 = dwMsgID1;
+ pMsgAck.dwMsgID2 = dwMsgID2;
+ pMsgAck.wCookie = wCookie;
+ pMsgAck.msgType = bMsgType;
+ pMsgAck.bFlags = bFlags;
+ handleMessageTypes(dwUin, szUID, time(NULL), dwMsgID1, dwMsgID2, wCookie, wVersion, bMsgType, bFlags, wAckType, wLen, wMsgLen, (char*)pDataBuf, 0, &pMsgAck);
+ break;
+ }
+ }
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PSIG_INFO_PLUGIN))
+ { // info manager plugin - obsolete
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ return;
+ }
+
+ BYTE bMsgType;
+ BYTE bLevel;
+
+ pDataBuf += 16; /* unused stuff */
+ wLen -= 16;
+ unpackByte(&pDataBuf, &bMsgType);
+ wLen -= 1;
+
+ pDataBuf += 3; // unknown
+ wLen -= 3;
+ unpackByte(&pDataBuf, &bLevel);
+ if (bLevel != 0 || wLen < 16)
+ {
+ NetLog_Server("Invalid %s Manager Plugin message from %u", "Info", dwUin);
+ return;
+ }
+ unpackDWord(&pDataBuf, &dwGuid1); // plugin request GUID
+ unpackDWord(&pDataBuf, &dwGuid2);
+ unpackDWord(&pDataBuf, &dwGuid3);
+ unpackDWord(&pDataBuf, &dwGuid4);
+ wLen -= 16;
+
+ if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PMSG_QUERY_INFO))
+ {
+ NetLog_Server("User %u requests our %s plugin list. NOT SUPPORTED", dwUin, "info");
+ }
+ else
+ NetLog_Server("Unknown %s Manager message from %u", "Info", dwUin);
+ }
+ else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PSIG_STATUS_PLUGIN))
+ { // status manager plugin - obsolete
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ return;
+ }
+
+ BYTE bMsgType;
+ BYTE bLevel;
+
+ pDataBuf += 16; /* unused stuff */
+ wLen -= 16;
+ unpackByte(&pDataBuf, &bMsgType);
+ wLen -= 1;
+
+ pDataBuf += 3; // unknown
+ wLen -= 3;
+ unpackByte(&pDataBuf, &bLevel);
+ if (bLevel != 0 || wLen < 16)
+ {
+ NetLog_Server("Invalid %s Manager Plugin message from %u", "Status", dwUin);
+ return;
+ }
+ unpackDWord(&pDataBuf, &dwGuid1); // plugin request GUID
+ unpackDWord(&pDataBuf, &dwGuid2);
+ unpackDWord(&pDataBuf, &dwGuid3);
+ unpackDWord(&pDataBuf, &dwGuid4);
+ wLen -= 16;
+
+ if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PMSG_QUERY_STATUS))
+ NetLog_Server("User %u requests our %s plugin list. NOT SUPPORTED", dwUin, "status");
+ else
+ NetLog_Server("Unknown %s Manager message from %u", "Status", dwUin);
+ }
+ else
+ NetLog_Server("Unknown signature (%08x-%08x-%08x-%08x) in message (format 2)", dwGuid1, dwGuid2, dwGuid3, dwGuid4);
+ }
+ else
+ NetLog_Server("Unknown wId1 (%u) in message (format 2)", wId);
+}
+
+
+void CIcqProto::parseServRelayPluginData(BYTE *pDataBuf, WORD wLen, HANDLE hContact, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, WORD wAckType, BYTE bFlags, WORD wStatus, WORD wCookie, WORD wVersion)
+{
+ int nTypeId;
+ WORD wFunction;
+
+ NetLog_Server("Parsing Greeting message through server");
+
+ // Message plugin identification
+ if (!unpackPluginTypeId(&pDataBuf, &wLen, &nTypeId, &wFunction, FALSE)) return;
+
+ if (wLen > 8)
+ {
+ DWORD dwLengthToEnd;
+ DWORD dwDataLen;
+
+ // Length of remaining data
+ unpackLEDWord(&pDataBuf, &dwLengthToEnd);
+
+ // Length of message
+ unpackLEDWord(&pDataBuf, &dwDataLen);
+ wLen -= 8;
+
+ if (dwDataLen > wLen)
+ dwDataLen = wLen;
+
+ if (nTypeId == MTYPE_FILEREQ && wAckType == 2)
+ {
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ return;
+ }
+ NetLog_Server("This is file ack");
+
+ char *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 (nTypeId == MTYPE_FILEREQ && wAckType == 1)
+ {
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ return;
+ }
+ NetLog_Server("This is a file request");
+
+ char *szMsg = (char *)_alloca(dwDataLen + 1);
+ memcpy(szMsg, pDataBuf, dwDataLen);
+ szMsg[dwDataLen] = '\0';
+ pDataBuf += dwDataLen;
+ wLen -= (WORD)dwDataLen;
+
+ handleFileRequest(pDataBuf, wLen, dwUin, wCookie, dwMsgID1, dwMsgID2, szMsg, 8, FALSE);
+ }
+ else if (nTypeId == MTYPE_CHAT && wAckType == 1)
+ { // TODO: this is deprecated
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ return;
+ }
+ NetLog_Server("This is a chat request");
+
+ char *szMsg = (char *)_alloca(dwDataLen + 1);
+ memcpy(szMsg, pDataBuf, dwDataLen);
+ szMsg[dwDataLen] = '\0';
+ pDataBuf += dwDataLen;
+ wLen -= (WORD)dwDataLen;
+
+ // handleChatRequest(pDataBuf, wLen, dwUin, wCookie, dwMsgID1, dwMsgID2, szMsg, 8);
+ }
+ else if (nTypeId == MTYPE_STATUSMSGEXT && wFunction >= 1 && wFunction <= 3)
+ { // handle extended status message request
+ int nMsgType = 0;
+
+ switch (wFunction)
+ {
+ case 1: // Away
+ if (m_iStatus == ID_STATUS_ONLINE || m_iStatus == ID_STATUS_INVISIBLE)
+ nMsgType = MTYPE_AUTOONLINE;
+ else if (m_iStatus == ID_STATUS_AWAY)
+ nMsgType = MTYPE_AUTOAWAY;
+ else if (m_iStatus == ID_STATUS_FREECHAT)
+ nMsgType = MTYPE_AUTOFFC;
+ break;
+
+ case 2: // Busy
+ if (m_iStatus == ID_STATUS_OCCUPIED)
+ nMsgType = MTYPE_AUTOBUSY;
+ else if (m_iStatus == ID_STATUS_DND)
+ nMsgType = MTYPE_AUTODND;
+ break;
+
+ case 3: // N/A
+ if (m_iStatus == ID_STATUS_NA)
+ nMsgType = MTYPE_AUTONA;
+ }
+ handleMessageTypes(dwUin, szUID, time(NULL), dwMsgID1, dwMsgID2, wCookie, wVersion, nMsgType, bFlags, wAckType, dwLengthToEnd, 0, (char*)pDataBuf, MTF_PLUGIN | MTF_STATUS_EXTENDED, NULL);
+ }
+ else if (nTypeId)
+ {
+ if (!dwUin)
+ { // AIM cannot send this, just sanity
+ NetLog_Server("Error: Malformed UIN in packet");
+ return;
+ }
+ message_ack_params pMsgAck = {0};
+
+ pMsgAck.bType = MAT_SERVER_ADVANCED;
+ pMsgAck.dwUin = dwUin;
+ pMsgAck.dwMsgID1 = dwMsgID1;
+ pMsgAck.dwMsgID2 = dwMsgID2;
+ pMsgAck.wCookie = wCookie;
+ pMsgAck.msgType = nTypeId;
+ pMsgAck.bFlags = bFlags;
+ handleMessageTypes(dwUin, szUID, time(NULL), dwMsgID1, dwMsgID2, wCookie, wVersion, nTypeId, bFlags, wAckType, dwLengthToEnd, (WORD)dwDataLen, (char*)pDataBuf, MTF_PLUGIN, &pMsgAck);
+ }
+ else
+ {
+ NetLog_Server("Unsupported plugin message type %d", nTypeId);
+ }
+ }
+ else
+ NetLog_Server("Error: Malformed server plugin message");
+}
+
+
+void CIcqProto::handleRecvServMsgContacts(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwID1, DWORD dwID2, WORD wCommand)
+{
+ HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
+
+ if (wCommand == 0)
+ { // received contacts
+ if (wLen < 4)
+ { // just check if at least one tlv is there
+ NetLog_Server("Message (format %u) - Ignoring empty contacts message", 2);
+ return;
+ }
+ oscar_tlv_chain *chain = readIntoTLVChain(&buf, wLen, 0);
+ if (!chain)
+ { // sanity check
+ NetLog_Server("Message (format %u) - Invalid data", 2);
+ return;
+ }
+
+ WORD wAckType = chain->getWord(0x0A, 1);
+
+ if (wAckType == 1)
+ { // it is really message containing contacts, parse them
+ oscar_tlv *tlvUins = chain->getTLV(0x2711, 1);
+ oscar_tlv *tlvNames = chain->getTLV(0x2712, 1);
+
+ if (!tlvUins || tlvUins->wLen < 4)
+ {
+ NetLog_Server("Malformed '%s' message", "contacts");
+ disposeChain(&chain);
+ return;
+ }
+ int nContacts = 0x10, iContact = 0;
+ ICQSEARCHRESULT **contacts = (ICQSEARCHRESULT**)SAFE_MALLOC(nContacts * sizeof(ICQSEARCHRESULT*));
+ WORD wContactsGroup = 0;
+ int valid = 1;
+ BYTE *pBuffer = tlvUins->pData;
+ int 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)
+ {
+ char *szUid = (char*)SAFE_MALLOC(wUidLen + 1);
+ unpackString(&pBuffer, szUid, wUidLen);
+ 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.flags = PSR_TCHAR;
+ contacts[iContact]->hdr.nick = null_strdup(_T(""));
+ contacts[iContact]->hdr.id = ansi_to_tchar(szUid);
+
+ if (IsStringUIN(szUid))
+ { // icq contact
+ contacts[iContact]->uin = atoi(szUid);
+ if (contacts[iContact]->uin == 0)
+ valid = 0;
+ }
+ else
+ { // aim contact
+ if (!strlennull(szUid))
+ valid = 0;
+ }
+ iContact++;
+
+ SAFE_FREE(&szUid);
+ }
+ else
+ {
+ if (wContactsGroup) valid = 0;
+ break;
+ }
+
+ wContactsGroup--;
+ }
+ }
+ if (!iContact || !valid)
+ {
+ NetLog_Server("Malformed '%s' message", "contacts");
+ disposeChain(&chain);
+ for (int i = 0; i < iContact; i++)
+ {
+ SAFE_FREE(&contacts[i]->hdr.id);
+ SAFE_FREE(&contacts[i]->hdr.nick);
+ SAFE_FREE((void**)&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, (LPBYTE*)&pNick);
+ if (wNickTLV == 0x01)
+ {
+ SAFE_FREE(&contacts[iContact]->hdr.nick);
+ contacts[iContact]->hdr.nick = utf8_to_tchar(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;
+ pre.timestamp = (DWORD)time(NULL);
+ pre.szMessage = (char *)contacts;
+ pre.lParam = nContacts;
+ pre.flags = PREF_TCHAR;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+
+ for (int i = 0; i < iContact; i++)
+ {
+ SAFE_FREE(&contacts[i]->hdr.id);
+ SAFE_FREE(&contacts[i]->hdr.nick);
+ SAFE_FREE((void**)&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);
+
+ BroadcastAck(hContact, ACKTYPE_CONTACTS, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+
+ ReleaseCookie(dwCookie);
+ }
+ else
+ NetLog_Server("Warning: Unexpected Contact Transfer ack from %s", strUID(dwUin, szUID));
+ }
+}
+
+
+void CIcqProto::handleRecvServMsgType4(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef)
+{
+ WORD wTLVType;
+ WORD wTLVLen;
+ BYTE* pDataBuf;
+ DWORD dwUin2;
+
+ if (wLen < 2)
+ {
+ 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)
+ {
+ NetLog_Server("User %u probably checks his ignore state.", dwUin);
+ }
+ else
+ {
+ cookie_offline_messages *cookie;
+ DWORD dwRecvTime = (DWORD)time(NULL);
+
+ if (!(dwRef & 0x80000000) && FindCookie(dwRef, NULL, (void**)&cookie))
+ {
+ WORD wTimeTLVType, wTimeTLVLen;
+ BYTE *pTimeTLV = NULL;
+
+ cookie->nMessages++;
+
+ unpackTypedTLV(buf, wLen, 0x16, &wTimeTLVType, &wTimeTLVLen, &pTimeTLV);
+ if (pTimeTLV && wTimeTLVType == 0x16 && wTimeTLVLen == 4)
+ { // found Offline timestamp
+ BYTE *pBuf = pTimeTLV;
+
+ unpackDWord(&pBuf, &dwRecvTime);
+ NetLog_Server("Message (format %u) - Offline timestamp is %s", 4, time2text(dwRecvTime));
+ }
+ SAFE_FREE((void**)&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)
+ {
+ uid_str szUID;
+ handleMessageTypes(dwUin, szUID, dwRecvTime, dwMsgID1, dwMsgID2, 0, 0, typeId, bFlags, 0, dwLengthToEnd, (WORD)dwDataLen, (char*)pmsg, MTF_PLUGIN, NULL);
+ }
+ else
+ {
+ NetLog_Server("Unsupported plugin message type %d", typeId);
+ }
+ }
+ }
+ else
+ {
+ uid_str szUID;
+ handleMessageTypes(dwUin, szUID, dwRecvTime, dwMsgID1, dwMsgID2, 0, 0, bMsgType, bFlags, 0, wTLVLen - 8, wMsgLen, (char*)pmsg, 0, 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((void**)&pDataBuf);
+}
+
+
+//
+// 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 (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 CIcqProto::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;
+
+ 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.");
+ }
+ char *szPluginName = (char *)_alloca(dwPluginNameLen + 1);
+ memcpy(szPluginName, *pBuffer, dwPluginNameLen);
+ szPluginName[dwPluginNameLen] = '\0';
+ wLen -= (WORD)dwPluginNameLen;
+
+ *pBuffer += dwPluginNameLen;
+
+ int 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_AUTOONLINE:
+ case MTYPE_AUTOAWAY:
+ case MTYPE_AUTOBUSY:
+ case MTYPE_AUTODND:
+ case MTYPE_AUTOFFC:
+ return 0x3C;
+
+ case MTYPE_AUTONA:
+ return 0x3B;
+
+ 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, (LPBYTE)"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, (LPBYTE)"File", 0x0004);
+
+ packDWord(packet, 0x00000100); // More unknown binary stuff
+ packDWord(packet, 0x00010000);
+ packDWord(packet, 0x00000000);
+ packWord(packet, 0x0000);
+ packByte(packet, 0x00);
+
+ break;
+
+ case MTYPE_AUTOONLINE:
+ case MTYPE_AUTOAWAY:
+ case MTYPE_AUTOFFC:
+ packLEWord(packet, 0x03A); // Length
+
+ packGUID(packet, MGTYPE_STATUSMSGEXT); // Message Type GUID
+
+ packLEWord(packet, 1); // Function ID
+ packLEDWord(packet, 0x13); // Request type string
+ packBuffer(packet, (LPBYTE)"Away Status Message", 0x13);
+
+ packDWord(packet, 0x01000000); // Unknown binary stuff
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packByte(packet, 0x00);
+
+ break;
+
+ case MTYPE_AUTOBUSY:
+ case MTYPE_AUTODND:
+ packLEWord(packet, 0x03A); // Length
+
+ packGUID(packet, MGTYPE_STATUSMSGEXT); // Message Type GUID
+
+ packLEWord(packet, 2); // Function ID
+ packLEDWord(packet, 0x13); // Request type string
+ packBuffer(packet, (LPBYTE)"Busy Status Message", 0x13);
+
+ packDWord(packet, 0x02000000); // Unknown binary stuff
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packByte(packet, 0x00);
+
+ break;
+
+ case MTYPE_AUTONA:
+ packLEWord(packet, 0x039); // Length
+
+ packGUID(packet, MGTYPE_STATUSMSGEXT); // Message Type GUID
+
+ packLEWord(packet, 3); // Function ID
+ packLEDWord(packet, 0x12); // Request type string
+ packBuffer(packet, (LPBYTE)"N/A Status Message", 0x12);
+
+ packDWord(packet, 0x03000000); // Unknown binary stuff
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packDWord(packet, 0x00000000);
+ packByte(packet, 0x00);
+
+ break;
+ }
+}
+
+
+void CIcqProto::handleStatusMsgReply(const char *szPrefix, HANDLE hContact, DWORD dwUin, WORD wVersion, int bMsgType, WORD wCookie, const char *szMsg, int nMsgFlags)
+{
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+
+ if (hContact == INVALID_HANDLE_VALUE)
+ {
+ NetLog_Server("%sIgnoring status message from unknown contact %u", szPrefix, dwUin);
+ return;
+ }
+
+ int status = AwayMsgTypeToStatus(bMsgType);
+ if (status == ID_STATUS_OFFLINE)
+ {
+ NetLog_Server("%sIgnoring unknown status message from %u", szPrefix, dwUin);
+ return;
+ }
+
+ // it is probably UTF-8 status reply
+ if (wVersion == 9 || (nMsgFlags & MTF_PLUGIN) && wVersion == 10)
+ {
+ if (UTF8_IsValid(szMsg)) pre.flags |= PREF_UTF;
+ }
+
+ ccs.szProtoService = PSR_AWAYMSG;
+ ccs.hContact = hContact;
+ ccs.wParam = status;
+ ccs.lParam = (LPARAM)&pre;
+ pre.szMessage = (char*)szMsg;
+ pre.timestamp = time(NULL);
+ pre.lParam = wCookie;
+
+ CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
+}
+
+
+HANDLE CIcqProto::handleMessageAck(DWORD dwUin, char *szUID, WORD wCookie, WORD wVersion, int type, WORD wMsgLen, PBYTE buf, BYTE bFlags, int nMsgFlags)
+{
+ if (bFlags == 3)
+ {
+ HANDLE hCookieContact;
+ cookie_message_data *pCookieData = NULL;
+
+ HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
+
+ if (!FindCookie(wCookie, &hCookieContact, (void**)&pCookieData))
+ {
+ NetLog_Server("%sIgnoring unrequested status message from %u", "handleMessageAck: ", dwUin);
+
+ ReleaseCookie(wCookie);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (hContact != hCookieContact)
+ {
+ 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, nMsgFlags);
+ }
+ 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 */
+void CIcqProto::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 ? (char *)CAP_UTF8MSGS : NULL);
+ }
+ }
+ }
+}
+
+
+/* this function also processes direct packets, so it should be bulletproof */
+/* pMsg points to the beginning of the message */
+void CIcqProto::handleMessageTypes(DWORD dwUin, char *szUID, DWORD dwTimestamp, DWORD dwMsgID, DWORD dwMsgID2, WORD wCookie, WORD wVersion, int type, int flags, WORD wAckType, DWORD dwDataLen, WORD wMsgLen, char *pMsg, int nMsgFlags, message_ack_params *pAckParams)
+{
+ HANDLE hContact = INVALID_HANDLE_VALUE;
+ BOOL bThruDC = (nMsgFlags & MTF_DIRECT) == MTF_DIRECT;
+ int bAdded;
+
+
+ if (dwDataLen < wMsgLen)
+ {
+ NetLog_Uni(bThruDC, "Ignoring overflowed message");
+ return;
+ }
+
+ if (wAckType == 2)
+ {
+ handleMessageAck(dwUin, szUID, wCookie, wVersion, type, wMsgLen, (LPBYTE)pMsg, (BYTE)flags, nMsgFlags);
+ return;
+ }
+
+ char *szMsg = (char *)SAFE_MALLOC(wMsgLen + 1);
+ if (wMsgLen > 0)
+ {
+ memcpy(szMsg, pMsg, wMsgLen);
+ pMsg += wMsgLen;
+ dwDataLen -= wMsgLen;
+ }
+ szMsg[wMsgLen] = '\0';
+
+
+ char* pszMsgField[2*MAX_CONTACTSSEND+1];
+ int nMsgFields = 0;
+
+ pszMsgField[0] = szMsg;
+ if (type == MTYPE_URL || type == MTYPE_AUTHREQ || type == MTYPE_ADDED || type == MTYPE_CONTACTS || type == MTYPE_EEXPRESS || type == MTYPE_WWP)
+ {
+ for (char *pszMsg=szMsg, nMsgFields=1; *pszMsg; pszMsg++)
+ {
+ if ((BYTE)*pszMsg == 0xFE)
+ {
+ *pszMsg = '\0';
+ pszMsgField[nMsgFields++] = pszMsg + 1;
+ if (nMsgFields >= SIZEOF(pszMsgField))
+ break;
+ }
+ }
+ }
+
+ switch (type) {
+
+ 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 = (char*)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 = (char*)usMsg;
+ pre.flags = PREF_UTF;
+ }
+ }
+
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)&pre;
+ pre.timestamp = dwTimestamp;
+ pre.szMessage = (char *)szMsg;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+ break;
+
+ case MTYPE_URL:
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+
+ if (nMsgFields < 2)
+ {
+ NetLog_Uni(bThruDC, "Malformed '%s' message", "URL");
+ break;
+ }
+
+ hContact = HContactFromUIN(dwUin, &bAdded);
+ sendMessageTypesAck(hContact, 0, pAckParams);
+
+ char *szTitle = ICQTranslateUtf(LPGEN("Incoming URL:"));
+ char *szDataDescr = ansi_to_utf8(pszMsgField[0]);
+ char *szDataUrl = ansi_to_utf8(pszMsgField[1]);
+ char *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;
+ 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)
+ {
+ NetLog_Server("Malformed '%s' message", "auth req");
+ break;
+ }
+
+ ccs.szProtoService=PSR_AUTH;
+ ccs.hContact=hContact=HContactFromUIN(dwUin, &bAdded);
+ ccs.wParam=0;
+ ccs.lParam=(LPARAM)&pre;
+ 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)
+ {
+ NetLog_Server("Malformed '%s' message", "you were added");
+ break;
+ }
+
+ hContact = HContactFromUIN(dwUin, &bAdded);
+
+ /*blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ) */
+ 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]);
+
+ AddEvent(NULL, EVENTTYPE_ADDED, dwTimestamp, 0, cbBlob, pBlob);
+ }
+ break;
+
+ case MTYPE_CONTACTS:
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre = {0};
+ char* pszNContactsEnd;
+ int nContacts;
+ int i;
+
+
+ if (nMsgFields < 3
+ || (nContacts = strtol(pszMsgField[0], &pszNContactsEnd, 10)) == 0
+ || pszNContactsEnd - pszMsgField[0] != (int)strlennull(pszMsgField[0])
+ || nMsgFields < nContacts * 2 + 1)
+ {
+ NetLog_Uni(bThruDC, "Malformed '%s' message", "contacts");
+ break;
+ }
+
+ int valid = 1;
+ ICQSEARCHRESULT** 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);
+ isrList[i]->hdr.flags = PSR_TCHAR;
+ 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
+ if (!strlennull(pszMsgField[1 + i * 2]))
+ valid = 0;
+ }
+ isrList[i]->hdr.id = ansi_to_tchar(pszMsgField[1 + i * 2]);
+ isrList[i]->hdr.nick = ansi_to_tchar(pszMsgField[2 + i * 2]);
+ }
+
+ if (!valid)
+ {
+ NetLog_Uni(bThruDC, "Malformed '%s' message", "contacts");
+ }
+ else
+ {
+ hContact = HContactFromUIN(dwUin, &bAdded);
+ sendMessageTypesAck(hContact, 0, pAckParams);
+
+ ccs.szProtoService = PSR_CONTACTS;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)&pre;
+ pre.timestamp = dwTimestamp;
+ pre.szMessage = (char *)isrList;
+ pre.lParam = nContacts;
+ pre.flags = PREF_TCHAR;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ }
+
+ for (i = 0; i < nContacts; i++)
+ {
+ SAFE_FREE(&isrList[i]->hdr.id);
+ SAFE_FREE(&isrList[i]->hdr.nick);
+ SAFE_FREE((void**)&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 */
+ break;
+ }
+ break;
+
+ case MTYPE_SMS_MESSAGE:
+ /* it's a SMS message from a mobile - broadcast to SMS plugin */
+ if (dwUin != 1002)
+ {
+ NetLog_Uni(bThruDC, "Malformed '%s' message", "SMS Mobile");
+ break;
+ }
+ NetLog_Server("Received SMS Mobile message");
+
+ BroadcastAck(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)
+ {
+ NetLog_Server("Malformed '%s' message", "web pager");
+ 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]);
+
+ AddEvent(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)
+ {
+ NetLog_Server("Malformed '%s' message", "e-mail express");
+ 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]);
+
+ AddEvent(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)
+ {
+ struct rates_status_message_response: public rates_queue_item
+ {
+ protected:
+ virtual rates_queue_item* copyItem(rates_queue_item *aDest = NULL)
+ {
+ rates_status_message_response *pDest = (rates_status_message_response*)aDest;
+ if (!pDest)
+ pDest = new rates_status_message_response(ppro, wGroup);
+
+ pDest->bExtended = bExtended;
+ pDest->dwMsgID1 = dwMsgID1;
+ pDest->dwMsgID2 = dwMsgID2;
+ pDest->wCookie = wCookie;
+ pDest->wVersion = wVersion;
+ pDest->nMsgType = nMsgType;
+
+ return rates_queue_item::copyItem(pDest);
+ };
+ public:
+ rates_status_message_response(CIcqProto *ppro, WORD wGroup): rates_queue_item(ppro, wGroup) { };
+ virtual ~rates_status_message_response() { };
+
+ virtual void execute()
+ {
+ char **pszMsg = ppro->MirandaStatusToAwayMsg(AwayMsgTypeToStatus(nMsgType));
+ if (bExtended)
+ ppro->icq_sendAwayMsgReplyServExt(dwUin, szUid, dwMsgID1, dwMsgID2, wCookie, wVersion, nMsgType, pszMsg);
+ else if (dwUin)
+ ppro->icq_sendAwayMsgReplyServ(dwUin, dwMsgID1, dwMsgID2, wCookie, wVersion, (BYTE)nMsgType, pszMsg);
+ else
+ ppro->NetLog_Server("Error: Malformed UIN in packet");
+ };
+
+ BOOL bExtended;
+ DWORD dwMsgID1;
+ DWORD dwMsgID2;
+ WORD wCookie;
+ WORD wVersion;
+ int nMsgType;
+ };
+
+ m_ratesMutex->Enter();
+ WORD wGroup = m_rates->getGroupFromSNAC(ICQ_MSG_FAMILY, ICQ_MSG_RESPONSE);
+ m_ratesMutex->Leave();
+
+ rates_status_message_response rr(this, wGroup);
+ rr.bExtended = (nMsgFlags & MTF_STATUS_EXTENDED) == MTF_STATUS_EXTENDED;
+ rr.hContact = hContact;
+ rr.dwUin = dwUin;
+ rr.szUid = szUID;
+ rr.dwMsgID1 = dwMsgID;
+ rr.dwMsgID2 = dwMsgID2;
+ rr.wCookie = wCookie;
+ rr.wVersion = wVersion;
+ rr.nMsgType = type;
+
+ handleRateItem(&rr, RQT_RESPONSE);
+ }
+
+ break;
+ }
+
+ case MTYPE_FILEREQ: // Never happens
+ default:
+ NetLog_Uni(bThruDC, "Unprocessed message type %d", type);
+ break;
+
+ }
+
+ SAFE_FREE(&szMsg);
+}
+
+
+void CIcqProto::handleRecvMsgResponse(BYTE *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 hCookieContact;
+ DWORD dwMsgID1, dwMsgID2;
+ WORD wVersion = 0;
+ cookie_message_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;
+
+ HANDLE hContact = HContactFromUID(dwUin, szUid, NULL);
+
+ buf += 2; // 3. unknown
+ wLen -= 2;
+
+ if (!FindMessageCookie(dwMsgID1, dwMsgID2, &dwCookie, &hCookieContact, &pCookieData))
+ {
+ 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, (void**)&pCookieData))
+ { // use old reliable method
+ 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...
+ 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
+ {
+ handleStatusMsgReply("SNAC(4.B) ", hContact, dwUin, wVersion, bMsgType, (WORD)dwCookie, (char*)(buf + 2), 0);
+ }
+ 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)
+ {
+ ReleaseCookie(dwCookie);
+ return;
+ }
+
+ if (!unpackPluginTypeId(&buf, &wLen, &typeId, &wFunctionId, FALSE))
+ {
+ ReleaseCookie(dwCookie);
+ 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 = (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, 0);
+
+ ReleaseCookie(dwCookie);
+ return;
+ }
+ else
+ ackType = ACKTYPE_MESSAGE;
+ break;
+
+ case MTYPE_URL:
+ ackType = ACKTYPE_URL;
+ break;
+
+ case MTYPE_CONTACTS:
+ ackType = ACKTYPE_CONTACTS;
+ break;
+
+ case MTYPE_FILEREQ:
+ {
+ NetLog_Server("This is file ack");
+
+ char *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 = (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 = (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, MTF_PLUGIN | MTF_STATUS_EXTENDED);
+
+ SAFE_FREE(&szMsg);
+
+ ReleaseCookie(dwCookie);
+ }
+ return;
+
+ 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:
+ {
+ cookie_reverse_connect *pReverse = (cookie_reverse_connect*)pCookieData;
+
+ if (pReverse->ft)
+ {
+ filetransfer *ft = (filetransfer*)pReverse->ft;
+
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ }
+ NetLog_Server("Reverse Connect request failed");
+ // Set DC status to failed
+ setSettingByte(hContact, "DCStatus", 2);
+
+ ReleaseCookie(dwCookie);
+ }
+ return;
+
+ case MTYPE_CHAT:
+ default:
+ NetLog_Server("SNAC(4.B) Unknown message type (%u) in switch", bMsgType);
+ return;
+ }
+
+ if ((ackType == MTYPE_PLAIN && pCookieData && (pCookieData->nAckType == ACKTYPE_CLIENT)) || ackType != MTYPE_PLAIN)
+ {
+ BroadcastAck(hContact, ackType, ACKRESULT_SUCCESS, (HANDLE)(WORD)dwCookie, 0);
+ }
+ }
+
+ ReleaseCookie(dwCookie);
+}
+
+
+// A response to a CLI_SENDMSG
+void CIcqProto::handleRecvServMsgError(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwSequence)
+{
+ WORD wError;
+ char *pszErrorMessage;
+ HANDLE hContact;
+ cookie_message_data *pCookieData = NULL;
+ int nMessageType;
+
+
+ if (wLen < 2)
+ return;
+
+ if (FindCookie((WORD)dwSequence, &hContact, (void**)&pCookieData))
+ { // all packet cookies from msg family has command 0 in the queue
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (getContactUid(hContact, &dwUin, &szUid))
+ { // Invalid contact
+ FreeCookie((WORD)dwSequence);
+ return;
+ }
+
+ // 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)));
+ packFNACHeader(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, 0, (WORD)dwSequence);
+ packWord(&packet, 0x03);
+ packUIN(&packet, dwUin);
+
+ sendServPacket(&packet);
+ return;
+ }
+
+ // 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 = Translate("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 = Translate("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 (pCookieData->bMessageType == MTYPE_PLAIN)
+ {
+ if (pCookieData->isOffline)
+ { // offline failed - most probably to AIM contact
+ pszErrorMessage = Translate("The contact does not support receiving offline messages.");
+ break;
+ }
+ // TODO: this needs better solution
+ setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+ }
+ pszErrorMessage = Translate("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 = Translate("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 = Translate("The receiving client does not support this type of message.\r\nSNAC(4.1) Error x09");
+ break;
+
+ case 0x000A: // Refused by client
+ pszErrorMessage = Translate("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 = Translate("The SNAC format was rejected by the server.\nSNAC(4.1) Error x0E");
+ break;
+
+ case 0x0013: // User temporarily unavailable
+ pszErrorMessage = Translate("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 = (char*)_alloca(256))
+ null_snprintf(pszErrorMessage, 256, Translate("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)
+ {
+ BroadcastAck(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((void**)&pCookieData);
+ }
+ else
+ {
+ unpackWord(&buf, &wError);
+
+ LogFamilyError(ICQ_MSG_FAMILY, wError);
+ }
+}
+
+
+void CIcqProto::handleServerAck(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwSequence)
+{
+ DWORD dwUin;
+ uid_str szUID;
+ WORD wChannel;
+ cookie_message_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;
+
+ HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
+
+ if (FindCookie((WORD)dwSequence, NULL, (void**)&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)
+ BroadcastAck(hContact, ackType, ackRes, (HANDLE)(WORD)dwSequence, 0);
+
+ if (pCookieData->bMessageType != MTYPE_FILEREQ)
+ SAFE_FREE((void**)&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");
+ }
+}
+
+
+void CIcqProto::handleMissedMsg(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ WORD wChannel;
+ WORD wWarningLevel;
+ WORD wCount;
+ WORD wError;
+ WORD wTLVCount;
+
+ if (wLen < 14)
+ return; // Too short
+
+ // Message channel?
+ unpackWord(&buf, &wChannel);
+ wLen -= 2;
+
+ // Sender
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) 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
+ oscar_tlv_chain *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;
+
+ { // offline retrieval process in progress, note that we received missed message notification
+ cookie_offline_messages *cookie;
+
+ if (FindCookieByType(CKT_OFFLINEMESSAGE, NULL, NULL, (void**)&cookie))
+ cookie->nMissed++;
+ }
+
+ switch (wError) {
+
+ case 0: // The message was invalid
+ case 1: // The message was too long
+ case 2: // The sender has flooded the server
+ case 4: // You are too evil
+ break;
+
+ default:
+ // 3 = Sender too evil (sender warn level > your max_msg_sevil)
+ return;
+ break;
+ }
+
+ // Create event to notify user
+ int bAdded;
+
+ AddEvent(HContactFromUID(dwUin, szUid, &bAdded), ICQEVENTTYPE_MISSEDMESSAGE, time(NULL), 0, sizeof(wError), (PBYTE)&wError);
+}
+
+
+void CIcqProto::handleOffineMessagesReply(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{
+ cookie_offline_messages *cookie;
+
+ if (FindCookie(dwRef, NULL, (void**)&cookie))
+ {
+ NetLog_Server("End of offline msgs, %u received", cookie->nMessages);
+ if (cookie->nMissed)
+ { // NASTY WORKAROUND!!
+ // The ICQ server has a bug that causes offline messages to be received again and again when some
+ // missed message notification is present (most probably it is not processed correctly and causes
+ // the server to fail the purging process); try to purge them using the old offline messages
+ // protocol. 2008/05/21
+ NetLog_Server("Warning: Received %u missed message notifications, trying to fix the server.", cookie->nMissed);
+
+ icq_packet packet;
+ // This will delete the messages stored on server
+ serverPacketInit(&packet, 24);
+ packFNACHeader(&packet, ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQUEST);
+ packWord(&packet, 1); // TLV Type
+ packWord(&packet, 10); // TLV Length
+ packLEWord(&packet, 8); // Data length
+ packLEDWord(&packet, m_dwLocalUIN); // My UIN
+ packLEWord(&packet, CLI_DELETE_OFFLINE_MSGS_REQ); // Ack offline msgs
+ packLEWord(&packet, 0x0000); // Request sequence number (we dont use this for now)
+
+ // Send it
+ sendServPacket(&packet);
+ }
+
+ ReleaseCookie(dwRef);
+ }
+ else
+ NetLog_Server("Error: Received unexpected end of offline msgs.");
+}
+
+
+void CIcqProto::handleTypingNotification(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ WORD wChannel;
+ WORD wNotification;
+
+ 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;
+
+ HANDLE hContact = HContactFromUID(dwUin, szUid, NULL);
+
+ if (hContact == INVALID_HANDLE_VALUE) return;
+
+ // Typing notification code
+ unpackWord(&buf, &wNotification);
+ wLen -= 2;
+
+ 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(LPGEN("Contact \"%s\" has closed the message window."), szFormat, MAX_PATH), nick);
+ ShowPopUpMsg(hContact, ICQTranslateUtfStatic(LPGEN("ICQ Note"), szFormat, MAX_PATH), szMsg, LOG_NOTE);
+ SAFE_FREE((void**)&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;
+ }
+}
+
+
+void CIcqProto::sendTypingNotification(HANDLE hContact, WORD wMTNCode)
+{
+ _ASSERTE((wMTNCode == MTN_FINISHED) || (wMTNCode == MTN_TYPED) || (wMTNCode == MTN_BEGUN) || (wMTNCode == MTN_WINDOW_CLOSED));
+
+ DWORD dwUin;
+ uid_str szUid;
+ if (getContactUid(hContact, &dwUin, &szUid))
+ return; // Invalid contact
+
+ WORD wLen = getUIDLen(dwUin, szUid);
+
+ icq_packet packet;
+ serverPacketInit(&packet, 23 + wLen);
+ packFNACHeader(&packet, ICQ_MSG_FAMILY, ICQ_MSG_MTN);
+ packLEDWord(&packet, 0x0000); // Msg ID
+ packLEDWord(&packet, 0x0000); // Msg ID
+ packWord(&packet, 0x01); // Channel
+ packUID(&packet, dwUin, szUid); // User ID
+ packWord(&packet, wMTNCode); // Notification type
+
+ sendServPacketAsync(&packet);
+}
diff --git a/protocols/IcqOscarJ/fam_09bos.cpp b/protocols/IcqOscarJ/fam_09bos.cpp
new file mode 100644
index 0000000000..e40d041543
--- /dev/null
+++ b/protocols/IcqOscarJ/fam_09bos.cpp
@@ -0,0 +1,113 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000-2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001-2002 Jon Keating, Richard Hughes
+// Copyright 2002-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/fam_09bos.cpp $
+// Revision : $Revision: 8822 $
+// Last change on : $Date: 2009-01-11 19:17:05 +0200 (Вс, 11 янв 2009) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+void CIcqProto::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;
+
+ }
+}
+
+void CIcqProto::handlePrivacyRightsReply(unsigned char *pBuffer, WORD wBufferLength)
+{
+ if (wBufferLength >= 12)
+ {
+ oscar_tlv_chain* pChain = readIntoTLVChain(&pBuffer, wBufferLength, 0);
+ if (pChain)
+ {
+ WORD wMaxVisibleContacts;
+ WORD wMaxInvisibleContacts;
+ WORD wMaxTemporaryVisibleContacts;
+
+ wMaxVisibleContacts = pChain->getWord(0x0001, 1);
+ wMaxInvisibleContacts = pChain->getWord(0x0002, 1);
+ wMaxTemporaryVisibleContacts = pChain->getWord(0x0003, 1);
+
+ disposeChain(&pChain);
+
+ NetLog_Server("PRIVACY: Max visible %u, max invisible %u, max temporary visible %u items.", wMaxVisibleContacts, wMaxInvisibleContacts, wMaxTemporaryVisibleContacts);
+
+ // Success
+ return;
+ }
+ }
+
+ // Failure
+ NetLog_Server("Warning: Malformed SRV_PRIVACY_RIGHTS_REPLY");
+}
+
+void CIcqProto::makeContactTemporaryVisible(HANDLE hContact)
+{
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (getSettingByte(hContact, "TemporaryVisible", 0))
+ return; // already there
+
+ if (getContactUid(hContact, &dwUin, &szUid))
+ return; // Invalid contact
+
+ icq_sendGenericContact(dwUin, szUid, ICQ_BOS_FAMILY, ICQ_CLI_ADDTEMPVISIBLE);
+
+ setSettingByte(hContact, "TemporaryVisible", 1);
+
+#ifdef _DEBUG
+ NetLog_Server("Added contact %s to temporary visible list", strUID(dwUin, szUid));
+#endif
+}
diff --git a/protocols/IcqOscarJ/fam_0alookup.cpp b/protocols/IcqOscarJ/fam_0alookup.cpp
new file mode 100644
index 0000000000..f37f31f165
--- /dev/null
+++ b/protocols/IcqOscarJ/fam_0alookup.cpp
@@ -0,0 +1,137 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/fam_0alookup.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+void CIcqProto::handleLookupFam(BYTE *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;
+ cookie_search *pCookie;
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, (void**)&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;
+ }
+}
+
+void CIcqProto::ReleaseLookupCookie(DWORD dwCookie, cookie_search *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)
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)pCookie->dwMainId, 0);
+ else // we are single
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+
+ SAFE_FREE((void**)&pCookie);
+ }
+}
+
+void CIcqProto::handleLookupEmailReply(BYTE* buf, WORD wLen, DWORD dwCookie)
+{
+ ICQSEARCHRESULT sr = {0};
+ oscar_tlv_chain *pChain;
+ cookie_search *pCookie;
+
+ if (!FindCookie(dwCookie, NULL, (void**)&pCookie))
+ {
+ NetLog_Server("Error: Received unexpected lookup reply");
+ return;
+ }
+
+ NetLog_Server("SNAC(0x0A,0x3): Lookup reply");
+
+ sr.hdr.cbSize = sizeof(sr);
+ sr.hdr.flags = PSR_TCHAR;
+ sr.hdr.email = ansi_to_tchar(pCookie->szObject);
+
+ // Syntax check, read chain
+ if (wLen >= 4 && (pChain = readIntoTLVChain(&buf, wLen, 0)))
+ {
+ for (WORD i = 1; TRUE; i++)
+ { // collect the results
+ char *szUid = pChain->getString(0x01, i);
+ if (!szUid) break;
+ sr.hdr.id = ansi_to_tchar(szUid);
+ sr.hdr.nick = sr.hdr.id;
+ // broadcast the result
+ if (pCookie->dwMainId)
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)pCookie->dwMainId, (LPARAM)&sr);
+ else
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)dwCookie, (LPARAM)&sr);
+ SAFE_FREE(&sr.hdr.id);
+ SAFE_FREE(&szUid);
+ }
+ disposeChain(&pChain);
+ }
+ SAFE_FREE(&sr.hdr.email);
+
+ ReleaseLookupCookie(dwCookie, pCookie);
+}
diff --git a/protocols/IcqOscarJ/fam_0bstatus.cpp b/protocols/IcqOscarJ/fam_0bstatus.cpp
new file mode 100644
index 0000000000..cde1395a33
--- /dev/null
+++ b/protocols/IcqOscarJ/fam_0bstatus.cpp
@@ -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 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/fam_0bstatus.c,v $
+// Revision : $Revision: 7500 $
+// Last change on : $Date: 2008-03-24 20:07:37 +0200 (Пн, 24 мар 2008) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void CIcqProto::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/protocols/IcqOscarJ/fam_13servclist.cpp b/protocols/IcqOscarJ/fam_13servclist.cpp
new file mode 100644
index 0000000000..7c5e0fffa1
--- /dev/null
+++ b/protocols/IcqOscarJ/fam_13servclist.cpp
@@ -0,0 +1,2075 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/fam_13servclist.cpp $
+// Revision : $Revision: 13699 $
+// Last change on : $Date: 2011-07-10 00:15:09 +0300 (Вс, 10 июл 2011) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static int unpackServerListItem(BYTE **pbuf, WORD *pwLen, char *pszRecordName, WORD *pwGroupId, WORD *pwItemId, WORD *pwItemType, WORD *pwTlvLength);
+
+
+void CIcqProto::handleServCListFam(BYTE *pBuffer, WORD wBufferLength, snac_header* pSnacHeader, serverthread_info *info)
+{
+ switch (pSnacHeader->wSubtype) {
+
+ case ICQ_LISTS_ACK: // UPDATE_ACK
+ if (wBufferLength >= 2)
+ {
+ WORD wError;
+ cookie_servlist_action* sc;
+
+ unpackWord(&pBuffer, &wError);
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, (void**)&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
+
+ if (sc->dwAction == SSA_ACTION_GROUP)
+ { // group cookie, handle sub-items
+ int i;
+
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Grouped action contains %d actions.", sc->dwGroupCount);
+#endif
+ pBuffer -= 2; // revoke unpack
+ if (wBufferLength != 2*sc->dwGroupCount)
+ NetLog_Server("Error: Server list ack does not contain expected amount of result codes (%u != %u)", wBufferLength/2, sc->dwGroupCount);
+
+ for (i = 0; i < sc->dwGroupCount; i++)
+ {
+ if (wBufferLength >= 2)
+ { // get proper result code
+ unpackWord(&pBuffer, &wError);
+ wBufferLength -= 2;
+ }
+ else // missing result code, give some special
+ wError = -1;
+
+#ifdef _DEBUG
+ NetLog_Server("Action: %d, ack result: %d", sc->pGroupItems[i]->dwAction, wError);
+#endif
+ // call normal ack handler
+ handleServerCListAck(sc->pGroupItems[i], wError);
+ }
+ // Release cookie
+ SAFE_FREE((void**)&sc->pGroupItems);
+ SAFE_FREE((void**)&sc);
+ }
+ else // single ack
+ handleServerCListAck(sc, wError);
+ }
+ else
+ {
+ NetLog_Server("Received unexpected server list ack %u", wError);
+ }
+ }
+ break;
+
+ case ICQ_LISTS_SRV_REPLYLISTS:
+ { /* received server-list rights */
+ handleServerCListRightsReply(pBuffer, wBufferLength);
+
+#ifdef _DEBUG
+ NetLog_Server("Server sent SNAC(x13,x03) - SRV_REPLYLISTS");
+#endif
+ }
+ break;
+
+ case ICQ_LISTS_LIST: // SRV_REPLYROSTER
+ {
+ cookie_servlist_action* sc;
+ BOOL blWork;
+
+ blWork = bIsSyncingCL;
+ bIsSyncingCL = TRUE; // this is not used if cookie takes place
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, (void**)&sc))
+ { // we do it by reliable cookie
+ if (!sc->lParam)
+ { // is this first packet ?
+ ResetSettingsOnListReload();
+ sc->lParam = 1;
+ }
+ handleServerCListReply(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();
+ }
+ handleServerCListReply(pBuffer, wBufferLength, pSnacHeader->wFlags, info);
+ }
+ break;
+ }
+
+ case ICQ_LISTS_UPTODATE: // SRV_REPLYROSTEROK
+ {
+ cookie_servlist_action* sc;
+
+ bIsSyncingCL = FALSE;
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, (void**)&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", ICQ_LISTS_CLI_MODIFYSTART, "Server is modifying contact list");
+ break;
+
+ case ICQ_LISTS_CLI_MODIFYEND:
+ NetLog_Server("Server sent SNAC(x13,x%02x) - %s", ICQ_LISTS_CLI_MODIFYEND, "End of server modification");
+ break;
+
+ case ICQ_LISTS_ADDTOLIST:
+ case ICQ_LISTS_UPDATEGROUP:
+ case ICQ_LISTS_REMOVEFROMLIST:
+ {
+ int nItems = 0;
+
+ while (wBufferLength >= 10)
+ {
+ WORD wGroupId, wItemId, wItemType, wTlvLen;
+ uid_str szRecordName;
+
+ if (unpackServerListItem(&pBuffer, &wBufferLength, szRecordName, &wGroupId, &wItemId, &wItemType, &wTlvLen))
+ {
+ BYTE *buf = pBuffer;
+ oscar_tlv_chain *pChain = NULL;
+
+ nItems++;
+
+ // parse possible item's data
+ if (wBufferLength >= wTlvLen && wTlvLen > 0)
+ {
+ pChain = readIntoTLVChain(&buf, wTlvLen, 0);
+ pBuffer += wTlvLen;
+ wBufferLength -= wTlvLen;
+ }
+ else if (wTlvLen > 0)
+ wBufferLength = 0;
+
+ // process item change
+ if (pSnacHeader->wSubtype == ICQ_LISTS_ADDTOLIST)
+ handleServerCListItemAdd(szRecordName, wGroupId, wItemId, wItemType, pChain);
+ else if (pSnacHeader->wSubtype == ICQ_LISTS_UPDATEGROUP)
+ handleServerCListItemUpdate(szRecordName, wGroupId, wItemId, wItemType, pChain);
+ else if (pSnacHeader->wSubtype == ICQ_LISTS_REMOVEFROMLIST)
+ handleServerCListItemDelete(szRecordName, wGroupId, wItemId, wItemType, pChain);
+
+ // release memory
+ disposeChain(&pChain);
+ }
+ }
+ { // log packet basics
+ char *szChange;
+ char szLogText[MAX_PATH];
+
+ if (pSnacHeader->wSubtype == ICQ_LISTS_ADDTOLIST)
+ szChange = "Server added %u item(s) to list";
+ else if (pSnacHeader->wSubtype == ICQ_LISTS_UPDATEGROUP)
+ szChange = "Server updated %u item(s) on list";
+ else if (pSnacHeader->wSubtype == ICQ_LISTS_REMOVEFROMLIST)
+ szChange = "Server removed %u item(s) from list";
+
+ null_snprintf(szLogText, MAX_PATH, szChange, nItems);
+ NetLog_Server("Server sent SNAC(x13,x%02x) - %s", pSnacHeader->wSubtype, szLogText);
+ }
+ }
+ 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", ICQ_LISTS_AUTHGRANTED, "User granted us future authorization");
+ break;
+
+ case ICQ_LISTS_YOUWEREADDED:
+ handleRecvAdded(pBuffer, wBufferLength);
+ break;
+
+ case ICQ_LISTS_ERROR:
+ if (wBufferLength >= 2)
+ {
+ WORD wError;
+ cookie_servlist_action* sc;
+
+ unpackWord(&pBuffer, &wError);
+
+ if (FindCookie(pSnacHeader->dwRef, NULL, (void**)&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, LPGEN("Server contact list is unavailable, Miranda will use local contact list."));
+ m_bSsiEnabled = 0;
+ handleServUINSettings(wListenPort, info);
+ }
+ /// FIXME: properly release pending operations & cookie memory
+ SAFE_FREE((void**)&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(BYTE **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
+}
+
+
+void CIcqProto::handleServerCListRightsReply(BYTE *buf, WORD wLen)
+{ /* received list rights, store the item limits for future use */
+ oscar_tlv_chain* chain;
+
+ memset(m_wServerListLimits, -1, sizeof(m_wServerListLimits));
+ m_wServerListGroupMaxContacts = 0;
+ m_wServerListRecordNameMaxLength = 0xFFFF;
+
+ if (chain = readIntoTLVChain(&buf, wLen, 0))
+ {
+ oscar_tlv* pTLV;
+
+ // determine max number of contacts in a group
+ m_wServerListGroupMaxContacts = chain->getWord(0x0C, 1);
+ // determine length limit for server-list item's name
+ m_wServerListRecordNameMaxLength = chain->getWord(0x06, 1);
+
+ if (pTLV = chain->getTLV(0x04, 1))
+ { // limits for item types
+ int i;
+ WORD *pLimits = (WORD*)pTLV->pData;
+
+ for (i = 0; i < pTLV->wLen / 2; i++)
+ {
+ m_wServerListLimits[i] = (pLimits[i] & 0xFF) << 8 | (pLimits[i] >> 8);
+
+ if (i + 1 >= SIZEOF(m_wServerListLimits)) break;
+ }
+
+ NetLog_Server("SSI: Max %d contacts (%d per group), %d groups, %d permit, %d deny, %d ignore items.", m_wServerListLimits[SSI_ITEM_BUDDY], m_wServerListGroupMaxContacts, m_wServerListLimits[SSI_ITEM_GROUP], m_wServerListLimits[SSI_ITEM_PERMIT], m_wServerListLimits[SSI_ITEM_DENY], m_wServerListLimits[SSI_ITEM_IGNORE]);
+ }
+
+ disposeChain(&chain);
+ }
+}
+
+
+DWORD CIcqProto::updateServerGroupData(WORD wGroupId, void *groupData, int groupSize, DWORD dwOperationFlags)
+{
+ DWORD dwCookie;
+ cookie_servlist_action* ack;
+
+ ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ if (!ack)
+ {
+ NetLog_Server("Updating of group on server list failed (malloc error)");
+ return 0;
+ }
+ ack->dwAction = SSA_GROUP_UPDATE;
+ ack->szGroupName = getServListGroupName(wGroupId);
+ ack->wGroupId = wGroupId;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+
+ return icq_sendServerGroup(dwCookie, ICQ_LISTS_UPDATEGROUP, ack->wGroupId, ack->szGroupName, groupData, groupSize, dwOperationFlags);
+}
+
+
+void CIcqProto::handleServerCListAck(cookie_servlist_action* 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:
+ {
+ servlistPendingRemoveContact(sc->hContact, sc->wContactId, sc->wGroupId, wError ? PENDING_RESULT_FAILED : PENDING_RESULT_SUCCESS);
+ if (wError)
+ {
+ NetLog_Server("Updating of server contact failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, LPGEN("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, LPGEN("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, LPGEN("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.");
+
+ setSettingByte(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, SSOP_ITEM_ACTION | SSOF_CONTACT, 500, NULL);
+
+ sc = NULL; // we do not want it to be freed now
+ break;
+ }
+ FreeServerID(sc->wContactId, SSIT_ITEM);
+
+ NetLog_Server("Adding of contact to server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, LPGEN("Adding of contact to server list failed."));
+
+ servlistPendingRemoveContact(sc->hContact, 0, sc->wGroupId, PENDING_RESULT_FAILED);
+
+ servlistPostPacket(NULL, 0, SSO_END_OPERATION, 100); // end server modifications here
+ }
+ else
+ {
+ void* groupData;
+ int groupSize;
+
+ setSettingWord(sc->hContact, DBSETTING_SERVLIST_ID, sc->wContactId);
+ setSettingWord(sc->hContact, DBSETTING_SERVLIST_GROUP, sc->wGroupId);
+
+ servlistPendingRemoveContact(sc->hContact, sc->wContactId, sc->wGroupId, PENDING_RESULT_SUCCESS);
+
+ if (groupData = collectBuddyGroup(sc->wGroupId, &groupSize))
+ { // the group is not empty, just update it
+ updateServerGroupData(sc->wGroupId, groupData, groupSize, SSOF_END_OPERATION);
+ SAFE_FREE((void**)&groupData);
+ }
+ else
+ { // this should never happen
+ NetLog_Server("Group update failed.");
+ servlistPostPacket(NULL, 0, SSO_END_OPERATION, 100); // end server modifications here
+ }
+ }
+ 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, LPGEN("Adding of group to server list failed."));
+
+ servlistPendingRemoveGroup(sc->szGroup, 0, PENDING_RESULT_FAILED);
+ }
+ else // group added, we need to update master group
+ {
+ void* groupData;
+ int groupSize;
+ cookie_servlist_action* ack;
+ DWORD dwCookie;
+
+ setServListGroupName(sc->wGroupId, sc->szGroupName); // add group to namelist
+ { // add group to known
+ char *szCListGroup = getServListGroupCListPath(sc->wGroupId);
+
+ // create link to the original CList group
+ setServListGroupLinkID(sc->szGroup, sc->wGroupId);
+
+ servlistPendingRemoveGroup(sc->szGroup, sc->wGroupId, PENDING_RESULT_SUCCESS);
+ SAFE_FREE((void**)&szCListGroup);
+ }
+
+ groupData = collectGroups(&groupSize);
+ groupData = SAFE_REALLOC(groupData, groupSize+2);
+ *(((WORD*)groupData)+(groupSize>>1)) = sc->wGroupId; // add this new group id
+ groupSize += 2;
+
+ ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ if (ack)
+ {
+ ack->dwAction = SSA_GROUP_UPDATE;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+
+ icq_sendServerGroup(dwCookie, ICQ_LISTS_UPDATEGROUP, 0, ack->szGroupName, groupData, groupSize, SSOF_END_OPERATION);
+ }
+ else // end server modifications here
+ servlistPostPacket(NULL, 0, SSO_END_OPERATION, 100);
+
+ SAFE_FREE((void**)&groupData);
+ }
+ if (sc->szGroup != sc->szGroupName)
+ SAFE_FREE((void**)&sc->szGroup);
+
+ SAFE_FREE((void**)&sc->szGroupName);
+ break;
+ }
+ case SSA_CONTACT_REMOVE:
+ {
+ if (!wError)
+ {
+ void* groupData;
+ int groupSize;
+
+ setSettingWord(sc->hContact, DBSETTING_SERVLIST_ID, 0); // clear the values
+ setSettingWord(sc->hContact, DBSETTING_SERVLIST_GROUP, 0);
+
+ FreeServerID(sc->wContactId, SSIT_ITEM);
+
+ servlistPendingRemoveContact(sc->hContact, 0, sc->wGroupId, PENDING_RESULT_SUCCESS);
+
+ if (groupData = collectBuddyGroup(sc->wGroupId, &groupSize))
+ { // the group is still not empty, just update it
+ updateServerGroupData(sc->wGroupId, groupData, groupSize, SSOF_END_OPERATION);
+ }
+ else // the group is empty, delete it
+ {
+ char *szGroup = getServListGroupCListPath(sc->wGroupId);
+
+ servlistRemoveGroup(szGroup, sc->wGroupId);
+ SAFE_FREE((void**)&szGroup);
+ }
+ SAFE_FREE((void**)&groupData); // free the memory
+ }
+ else
+ {
+ NetLog_Server("Removing of contact from server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, LPGEN("Removing of contact from server list failed."));
+
+ servlistPendingRemoveContact(sc->hContact, sc->wContactId, sc->wGroupId, PENDING_RESULT_FAILED);
+
+ servlistPostPacket(NULL, 0, SSO_END_OPERATION, 100); // 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, LPGEN("Updating of group on server list failed."));
+ }
+ SAFE_FREE((void**)&sc->szGroupName);
+ break;
+ }
+ case SSA_GROUP_REMOVE:
+ {
+ SAFE_FREE((void**)&sc->szGroupName);
+ if (wError)
+ {
+ NetLog_Server("Removing of group from server list failed, error %d", wError);
+ icq_LogMessage(LOG_WARNING, LPGEN("Removing of group from server list failed."));
+
+ servlistPendingRemoveGroup(sc->szGroup, 0, PENDING_RESULT_FAILED);
+
+ servlistPostPacket(NULL, 0, SSO_END_OPERATION, 100); // end server modifications here
+ SAFE_FREE((void**)&sc->szGroup);
+ }
+ else // group removed, we need to update master group
+ {
+ void* groupData;
+ int groupSize;
+ DWORD dwCookie;
+
+ setServListGroupName(sc->wGroupId, NULL); // clear group from namelist
+ FreeServerID(sc->wGroupId, SSIT_GROUP);
+ removeGroupPathLinks(sc->wGroupId);
+
+ servlistPendingRemoveGroup(sc->szGroup, 0, PENDING_RESULT_SUCCESS);
+ SAFE_FREE((void**)&sc->szGroup);
+
+ groupData = collectGroups(&groupSize);
+ sc->wGroupId = 0;
+ sc->dwAction = SSA_GROUP_UPDATE;
+ sc->szGroupName = NULL;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, sc);
+
+ icq_sendServerGroup(dwCookie, ICQ_LISTS_UPDATEGROUP, 0, sc->szGroupName, groupData, groupSize, SSOF_END_OPERATION);
+ // end server modifications here
+
+ sc = NULL; // we do not want to be freed here
+
+ SAFE_FREE((void**)&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 (!getSettingByte(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.");
+
+ setSettingByte(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.");
+
+ setSettingByte(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, SSOP_ITEM_ACTION | SSOF_CONTACT, 400, NULL);
+
+ sc->lParam = 2; // do not cycle
+ sc = NULL; // we do not want to be freed here
+ break;
+ }
+ FreeServerID(sc->wNewContactId, SSIT_ITEM);
+ NetLog_Server("Moving of user to another group on server list failed, error %d", wError);
+ icq_LogMessage(LOG_ERROR, LPGEN("Moving of user to another group on server list failed."));
+
+ servlistPendingRemoveContact(sc->hContact, 0, (WORD)(sc->lParam ? sc->wGroupId : sc->wNewGroupId), PENDING_RESULT_FAILED);
+
+ servlistPostPacket(NULL, 0, SSO_END_OPERATION, 100); // end server modifications here
+
+ 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
+
+ setSettingWord(sc->hContact, DBSETTING_SERVLIST_ID, sc->wNewContactId);
+ setSettingWord(sc->hContact, DBSETTING_SERVLIST_GROUP, sc->wNewGroupId);
+
+ servlistPendingRemoveContact(sc->hContact, sc->wNewContactId, sc->wNewGroupId, PENDING_RESULT_SUCCESS);
+
+ 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, 0);
+ SAFE_FREE((void**)&groupData); // free the memory
+ }
+ else
+ { // the group is empty, delete it
+ char* szGroup = getServListGroupCListPath(sc->wGroupId);
+
+ servlistRemoveGroup(szGroup, sc->wGroupId);
+ SAFE_FREE((void**)&szGroup);
+ bEnd = 0; // here the modifications go on
+ }
+
+ groupData = collectBuddyGroup(sc->wNewGroupId, &groupSize); // update the group we moved to
+ updateServerGroupData(sc->wNewGroupId, groupData, groupSize, bEnd ? SSOF_END_OPERATION : 0);
+ // end server modifications here
+ SAFE_FREE((void**)&groupData);
+
+ }
+ else // contact was deleted from server-list
+ {
+ deleteSetting(sc->hContact, DBSETTING_SERVLIST_ID);
+ deleteSetting(sc->hContact, DBSETTING_SERVLIST_GROUP);
+ FreeServerID(sc->wContactId, SSIT_ITEM); // release old contact id
+ 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, LPGEN("Renaming of server group failed."));
+
+ servlistPendingRemoveGroup(sc->szGroup, sc->wGroupId, PENDING_RESULT_FAILED);
+ }
+ else
+ {
+ setServListGroupName(sc->wGroupId, sc->szGroupName);
+ removeGroupPathLinks(sc->wGroupId);
+ { // add group to known
+ char *szCListGroup = getServListGroupCListPath(sc->wGroupId);
+
+ /// FIXME: need to create link to the new group name before unique item name correction as well
+ setServListGroupLinkID(szCListGroup, sc->wGroupId);
+ SAFE_FREE((void**)&szCListGroup);
+ }
+ servlistPendingRemoveGroup(sc->szGroup, sc->wGroupId, PENDING_RESULT_SUCCESS);
+ }
+ SAFE_FREE((void**)&sc->szGroupName);
+ SAFE_FREE((void**)&sc->szGroup);
+ 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);
+ deleteSetting(NULL, DBSETTING_SERVLIST_AVATAR); // to fix old versions
+ }
+ }
+ else
+ {
+ setSettingWord(NULL, DBSETTING_SERVLIST_AVATAR, sc->wContactId);
+ }
+ break;
+ }
+ case SSA_REMOVEAVATAR:
+ {
+ if (wError)
+ NetLog_Server("Removing of avatar hash failed.");
+ else
+ {
+ FreeServerID(sc->wContactId, SSIT_ITEM);
+ deleteSetting(NULL, DBSETTING_SERVLIST_AVATAR);
+ }
+ break;
+ }
+ case SSA_SERVLIST_ACK:
+ {
+ BroadcastAck(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
+ {
+ setSettingWord(NULL, "SrvImportID", 0);
+ deleteSetting(NULL, "ImportTS");
+ }
+ break;
+ }
+ default:
+ NetLog_Server("Server ack cookie type (%d) not recognized.", sc->dwAction);
+ }
+ SAFE_FREE((void**)&sc); // free the memory
+
+ return;
+}
+
+
+HANDLE CIcqProto::HContactFromRecordName(const 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 = atoi(szRecordName);
+
+ hContact = HContactFromUIN(dwUin, bAdded);
+ }
+ return hContact;
+}
+
+
+int CIcqProto::getServerDataFromItemTLV(oscar_tlv_chain* pChain, unsigned char *buf) /// FIXME: need to keep original order
+{ // 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 &&
+ list->tlv.wType != SSI_TLV_METAINFO_TOKEN &&
+ list->tlv.wType != SSI_TLV_METAINFO_TIME)
+ { // 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;
+}
+
+
+void CIcqProto::handleServerCListReply(BYTE *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;
+ char *szActiveSrvGroup = NULL;
+ WORD wActiveSrvGroupId = -1;
+
+
+ // 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;
+
+ if (bAdded)
+ { // Not already on list: added
+ NetLog_Server("SSI added new %s contact '%s'", "ICQ", szRecordName);
+
+ 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);
+ }
+
+ // Save group and item ID
+ setSettingWord(hContact, DBSETTING_SERVLIST_ID, wItemId);
+ setSettingWord(hContact, DBSETTING_SERVLIST_GROUP, wGroupId);
+ ReserveServerID(wItemId, SSIT_ITEM, 0);
+
+ if (!bAdded && getSettingByte(NULL, "LoadServerDetails", DEFAULT_SS_LOAD))
+ { // check if the contact has been moved on the server
+ if (wActiveSrvGroupId != wGroupId || !szActiveSrvGroup)
+ {
+ SAFE_FREE(&szActiveSrvGroup);
+ szActiveSrvGroup = getServListGroupCListPath(wGroupId);
+ wActiveSrvGroupId = wGroupId;
+ }
+ char *szLocalGroup = getContactCListGroup(hContact);
+
+ if (!strlennull(szLocalGroup))
+ { // no CListGroup
+ SAFE_FREE(&szLocalGroup);
+
+ szLocalGroup = null_strdup(DEFAULT_SS_GROUP);
+ }
+
+ if (strcmpnull(szActiveSrvGroup, szLocalGroup) &&
+ (strlennull(szActiveSrvGroup) >= strlennull(szLocalGroup) || _strnicmp(szActiveSrvGroup, szLocalGroup, strlennull(szLocalGroup))))
+ { // contact moved to new group or sub-group or not to master group
+ bRegroup = 1;
+ }
+ if (bRegroup && !stricmpnull(DEFAULT_SS_GROUP, szActiveSrvGroup)) /// TODO: invent something more clever for "root" group
+ { // is it the default "General" group ?
+ bRegroup = 0; // if yes, do not move to it - cause it would hide the contact
+ }
+ SAFE_FREE(&szLocalGroup);
+ }
+
+ if (bRegroup || bAdded)
+ { // if we should load server details or contact was just added, update its group
+ if (wActiveSrvGroupId != wGroupId || !szActiveSrvGroup)
+ {
+ SAFE_FREE(&szActiveSrvGroup);
+ szActiveSrvGroup = getServListGroupCListPath(wGroupId);
+ wActiveSrvGroupId = wGroupId;
+ }
+
+ if (szActiveSrvGroup)
+ { // try to get Miranda Group path from groupid, if succeeded save to db
+ moveContactToCListGroup(hContact, szActiveSrvGroup);
+ }
+ }
+
+ if (pChain)
+ { // Look for nickname TLV and copy it to the db if necessary
+ if (pTLV = pChain->getTLV(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 (getSettingByte(NULL, "LoadServerDetails", DEFAULT_SS_LOAD) || bAdded)
+ { // if just added contact, save details always - does no harm
+ char *szOldNick;
+
+ if (szOldNick = getSettingStringUtf(hContact, "CList", "MyHandle", NULL))
+ {
+ 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");
+ setSettingStringUtf(hContact, "CList", "MyHandle", pszNick);
+ }
+ }
+ SAFE_FREE(&szOldNick);
+ }
+ else if (strlennull(pszNick) > 0)
+ {
+ DBDeleteContactSetting(hContact,"CList","MyHandle");
+ setSettingStringUtf(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 = pChain->getTLV(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 (getSettingByte(NULL, "LoadServerDetails", DEFAULT_SS_LOAD) || bAdded)
+ { // if just added contact, save details always - does no harm
+ char *szOldComment;
+
+ if (szOldComment = getSettingStringUtf(hContact, "UserInfo", "MyNotes", NULL))
+ {
+ 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((char*)szOldComment, (char*)pszComment, null_strcut(szOldComment, MAX_SSI_TLV_COMMENT_SIZE)))
+ {
+ setSettingStringUtf(hContact, "UserInfo", "MyNotes", pszComment);
+ }
+ }
+ SAFE_FREE((void**)&szOldComment);
+ }
+ else if (strlennull(pszComment) > 0)
+ {
+ setSettingStringUtf(hContact, "UserInfo", "MyNotes", pszComment);
+ }
+ }
+ SAFE_FREE((void**)&pszComment);
+ }
+ else
+ {
+ NetLog_Server("Invalid comment");
+ }
+ }
+
+ // Look for need-authorization TLV
+ if (pChain->getTLV(SSI_TLV_AWAITING_AUTH, 1))
+ {
+ setSettingByte(hContact, "Auth", 1);
+ NetLog_Server("SSI contact need authorization");
+ }
+ else
+ {
+ setSettingByte(hContact, "Auth", 0);
+ }
+
+ if (pTLV = pChain->getTLV(SSI_TLV_METAINFO_TOKEN, 1))
+ {
+ setSettingBlob(hContact, DBSETTING_METAINFO_TOKEN, pTLV->pData, pTLV->wLen);
+ if (pChain->getTLV(SSI_TLV_METAINFO_TIME, 1))
+ setSettingDouble(hContact, DBSETTING_METAINFO_TIME, pChain->getDouble(SSI_TLV_METAINFO_TIME, 1));
+ NetLog_Server("SSI contact has meta info token");
+ }
+ else
+ {
+ deleteSetting(hContact, DBSETTING_METAINFO_TOKEN);
+ deleteSetting(hContact, DBSETTING_METAINFO_TIME);
+ }
+
+ { // store server-list item's TLV data
+ BYTE* data = (BYTE*)SAFE_MALLOC(wTlvLength);
+ int datalen = getServerDataFromItemTLV(pChain, data);
+
+ if (datalen > 0)
+ setSettingBlob(hContact, DBSETTING_SERVLIST_DATA, data, datalen);
+ else
+ deleteSetting(hContact, DBSETTING_SERVLIST_DATA);
+
+ SAFE_FREE((void**)&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 */
+ ReserveServerID(wGroupId, SSIT_GROUP, 0);
+
+ setServListGroupName(wGroupId, szRecordName);
+
+ NetLog_Server("Group %s added to known groups.", szRecordName);
+
+ /* demangle full grouppath, set it to known */
+ SAFE_FREE(&szActiveSrvGroup);
+ szActiveSrvGroup = getServListGroupCListPath(wGroupId);
+ wActiveSrvGroupId = wGroupId;
+
+ /* 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
+ setSettingWord(hContact, DBSETTING_SERVLIST_PERMIT, wItemId);
+ ReserveServerID(wItemId, SSIT_ITEM, 0);
+ // Set apparent mode
+ setSettingWord(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);
+
+ ReserveServerID(wItemId, SSIT_ITEM, SSIF_UNHANDLED);
+ }
+ }
+ 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
+ setSettingWord(hContact, DBSETTING_SERVLIST_DENY, wItemId);
+ ReserveServerID(wItemId, SSIT_ITEM, 0);
+
+ // Set apparent mode
+ setSettingWord(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);
+
+ ReserveServerID(wItemId, SSIT_ITEM, SSIF_UNHANDLED);
+ }
+ }
+ break;
+
+ case SSI_ITEM_VISIBILITY: /* My visibility settings */
+ {
+ BYTE bVisibility;
+
+ // Look for visibility TLV
+ if (bVisibility = pChain->getByte(SSI_TLV_VISIBILITY, 1))
+ { // found it, store the id, we do not need current visibility - we do not rely on it
+ setSettingWord(NULL, DBSETTING_SERVLIST_PRIVACY, wItemId);
+ ReserveServerID(wItemId, SSIT_ITEM, 0);
+
+ NetLog_Server("Visibility is %u", bVisibility);
+ }
+ else
+ ReserveServerID(wItemId, SSIT_ITEM, SSIF_UNHANDLED);
+ }
+ 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
+ setSettingWord(hContact, DBSETTING_SERVLIST_IGNORE, wItemId);
+ ReserveServerID(wItemId, SSIT_ITEM, 0);
+
+ // Set apparent mode & ignore
+ setSettingWord(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);
+
+ ReserveServerID(wItemId, SSIT_ITEM, SSIF_UNHANDLED);
+ }
+ }
+ break;
+
+ case SSI_ITEM_UNKNOWN2:
+ NetLog_Server("SSI unknown type 0x11");
+
+ ReserveServerID(wItemId, SSIT_ITEM, SSIF_UNHANDLED);
+ 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}} */
+ setSettingDword(NULL, "ImportTS", pChain->getDWord(SSI_TLV_TIMESTAMP, 1));
+ setSettingWord(NULL, "SrvImportID", wItemId);
+ ReserveServerID(wItemId, SSIT_ITEM, 0);
+ 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
+ setSettingWord(NULL, DBSETTING_SERVLIST_PHOTO, wItemId);
+ NetLog_Server("SSI %s item recognized", "Photo");
+ }
+ else
+ {
+ setSettingWord(NULL, DBSETTING_SERVLIST_AVATAR, wItemId);
+ NetLog_Server("SSI %s item recognized", "Avatar");
+ }
+ ReserveServerID(wItemId, SSIT_ITEM, 0);
+ }
+ break;
+
+ case SSI_ITEM_METAINFO:
+ if (wGroupId == 0)
+ {
+ /* our meta info token & last update time */
+ /* pszRecordName is "ICQ-MDIR" */
+ /* data is TLV(15C) and TLV(15D) */
+ oscar_tlv* pToken = pChain->getTLV(SSI_TLV_METAINFO_TOKEN, 1);
+ oscar_tlv* pTime = pChain->getTLV(SSI_TLV_METAINFO_TIME, 1);
+ if (pToken)
+ setSettingBlob(NULL, DBSETTING_METAINFO_TOKEN, pToken->pData, pToken->wLen);
+ if (pTime)
+ setSettingDouble(NULL, DBSETTING_METAINFO_TIME, pChain->getDouble(SSI_TLV_METAINFO_TIME, 1));
+
+ setSettingWord(NULL, DBSETTING_SERVLIST_METAINFO, wItemId);
+ ReserveServerID(wItemId, SSIT_ITEM, 0);
+
+ NetLog_Server("SSI %s item recognized", "Meta info");
+ }
+ break;
+
+ case SSI_ITEM_CLIENTDATA:
+ if (wGroupId == 0)
+ {
+ /* ICQ2k ShortcutBar Items */
+ /* data is TLV(CD) text */
+ if (wItemId)
+ ReserveServerID(wItemId, SSIT_ITEM, SSIF_UNHANDLED);
+ }
+
+ case SSI_ITEM_SAVED:
+ case SSI_ITEM_PREAUTH:
+ break;
+
+ default:
+ NetLog_Server("SSI unhandled item %2x", wTlvType);
+
+ if (wItemId)
+ ReserveServerID(wItemId, SSIT_ITEM, SSIF_UNHANDLED);
+ break;
+ }
+
+ disposeChain(&pChain);
+ } // end for
+
+ // Release Memory
+ SAFE_FREE(&szActiveSrvGroup);
+
+ NetLog_Server("Bytes left: %u", wLen);
+
+ setSettingWord(NULL, "SrvRecordCount", (WORD)(wRecord + getSettingWord(NULL, "SrvRecordCount", 0)));
+
+ if (bIsLastPacket)
+ {
+ // No contacts left to sync
+ bIsSyncingCL = FALSE;
+
+ StoreServerIDs();
+
+ icq_RescanInfoUpdate();
+
+ if (wLen >= 4)
+ {
+ DWORD dwLastUpdateTime;
+
+ /* finally we get a time_t of the last update time */
+ unpackDWord(&buf, &dwLastUpdateTime);
+ setSettingDword(NULL, "SrvLastUpdate", dwLastUpdateTime);
+ NetLog_Server("Last update of server list was (%u) %s", dwLastUpdateTime, time2text(dwLastUpdateTime));
+
+ sendRosterAck();
+ handleServUINSettings(wListenPort, info);
+
+ servlistProcessLogin();
+ }
+ else
+ {
+ NetLog_Server("Last packet missed update time...");
+ }
+ if (getSettingWord(NULL, "SrvRecordCount", 0) == 0)
+ { // we got empty serv-list, create master group
+ cookie_servlist_action* ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ if (ack)
+ {
+ DWORD dwCookie;
+
+ ack->dwAction = SSA_GROUP_UPDATE;
+ ack->szGroupName = null_strdup("");
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, 0, ack);
+ icq_sendServerGroup(dwCookie, ICQ_LISTS_ADDTOLIST, 0, ack->szGroupName, NULL, 0, 0);
+ }
+ }
+ // serv-list sync finished, clear just added contacts
+ FlushJustAddedContacts();
+ }
+ else
+ {
+ NetLog_Server("Waiting for more packets");
+ }
+}
+
+
+void CIcqProto::handleServerCListItemAdd(const char *szRecordName, WORD wGroupId, WORD wItemId, WORD wItemType, oscar_tlv_chain *pItemData)
+{
+ if (wItemType == SSI_ITEM_IMPORTTIME)
+ {
+ if (pItemData)
+ {
+ setSettingDword(NULL, "ImportTS", pItemData->getDWord(SSI_TLV_TIMESTAMP, 1));
+ setSettingWord(NULL, "SrvImportID", wItemId);
+ ReserveServerID(wItemId, SSIT_ITEM, 0);
+
+ NetLog_Server("Server added Import timestamp to list");
+
+ return;
+ }
+ }
+ // Reserve server-list ID
+ ReserveServerID(wItemId, wItemType == SSI_ITEM_GROUP ? SSIT_GROUP : SSIT_ITEM, SSIF_UNHANDLED);
+}
+
+
+void CIcqProto::handleServerCListItemUpdate(const char *szRecordName, WORD wGroupId, WORD wItemId, WORD wItemType, oscar_tlv_chain *pItemData)
+{
+ HANDLE hContact = (wItemType == SSI_ITEM_BUDDY || wItemType == SSI_ITEM_DENY || wItemType == SSI_ITEM_PERMIT || wItemType == SSI_ITEM_IGNORE) ? HContactFromRecordName(szRecordName, NULL) : NULL;
+
+ if (hContact != INVALID_HANDLE_VALUE && wItemType == SSI_ITEM_BUDDY)
+ { // a contact was updated on server
+ if (pItemData)
+ {
+ oscar_tlv* pAuth = pItemData->getTLV(SSI_TLV_AWAITING_AUTH, 1);
+ BYTE bAuth = getSettingByte(hContact, "Auth", 0);
+
+ if (bAuth && !pAuth)
+ { // server authorized our contact
+ char str[MAX_PATH];
+ char msg[MAX_PATH];
+ char *nick = NickFromHandleUtf(hContact);
+
+ setSettingByte(hContact, "Auth", 0);
+ null_snprintf(str, MAX_PATH, ICQTranslateUtfStatic(LPGEN("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);
+
+ setSettingByte(hContact, "Auth", 1);
+ null_snprintf(str, MAX_PATH, ICQTranslateUtfStatic(LPGEN("Contact \"%s\" lost its authorization in the server list."), msg, MAX_PATH), nick);
+ icq_LogMessage(LOG_WARNING, str);
+ SAFE_FREE(&nick);
+ }
+
+ { // update metainfo data
+ DBVARIANT dbv = {0};
+ oscar_tlv *pToken = pItemData->getTLV(SSI_TLV_METAINFO_TOKEN, 1);
+ oscar_tlv *pTime = pItemData->getTLV(SSI_TLV_METAINFO_TIME, 1);
+
+ if (!getSetting(hContact, DBSETTING_METAINFO_TOKEN, &dbv))
+ {
+ if (!pToken || dbv.cpbVal != pToken->wLen || memcmp(dbv.pbVal, pToken->pData, dbv.cpbVal))
+ {
+ if (!pToken)
+ NetLog_Server("Contact %s, meta info token removed", szRecordName);
+ else
+ NetLog_Server("Contact %s, meta info token changed", szRecordName);
+
+ // user info was changed, refresh
+ if (IsMetaInfoChanged(hContact))
+ icq_QueueUser(hContact);
+ }
+
+ ICQFreeVariant(&dbv);
+ }
+ else if (pToken)
+ {
+ NetLog_Server("Contact %s, meta info token added", szRecordName);
+
+ // user info was changed, refresh
+ if (IsMetaInfoChanged(hContact))
+ icq_QueueUser(hContact);
+ }
+
+ if (pToken)
+ setSettingBlob(hContact, DBSETTING_METAINFO_TOKEN, pToken->pData, pToken->wLen);
+ if (pTime)
+ setSettingDouble(hContact, DBSETTING_METAINFO_TIME, pItemData->getDouble(SSI_TLV_METAINFO_TIME, 1));
+ }
+
+ { // update server's data - otherwise consequent operations can fail with 0x0E
+ BYTE *data = (BYTE*)_alloca(pItemData->getChainLength());
+ int datalen = getServerDataFromItemTLV(pItemData, data);
+
+ if (datalen > 0)
+ setSettingBlob(hContact, DBSETTING_SERVLIST_DATA, data, datalen);
+ else
+ deleteSetting(hContact, DBSETTING_SERVLIST_DATA);
+ }
+ }
+ }
+ else if (wItemType == SSI_ITEM_METAINFO)
+ { // owner MetaInfo data updated
+ if (pItemData)
+ {
+ DBVARIANT dbv = {0};
+ oscar_tlv *pToken = pItemData->getTLV(SSI_TLV_METAINFO_TOKEN, 1);
+ oscar_tlv *pTime = pItemData->getTLV(SSI_TLV_METAINFO_TIME, 1);
+
+ if (!getSetting(hContact, DBSETTING_METAINFO_TOKEN, &dbv))
+ {
+ if (!pToken || dbv.cpbVal != pToken->wLen || memcmp(dbv.pbVal, pToken->pData, dbv.cpbVal))
+ {
+ if (!pToken)
+ NetLog_Server("Owner meta info token removed");
+ else
+ NetLog_Server("Owner meta info token changed");
+ }
+
+ ICQFreeVariant(&dbv);
+ }
+
+ if (pToken)
+ setSettingBlob(hContact, DBSETTING_METAINFO_TOKEN, pToken->pData, pToken->wLen);
+ if (pTime)
+ setSettingDouble(hContact, DBSETTING_METAINFO_TIME, pItemData->getDouble(SSI_TLV_METAINFO_TIME, 1));
+ }
+ }
+ else if (wItemType == SSI_ITEM_GROUP)
+ { // group updated
+ NetLog_Server("Server updated our group \"%s\" on list", szRecordName);
+ }
+}
+
+
+void CIcqProto::handleServerCListItemDelete(const char *szRecordName, WORD wGroupId, WORD wItemId, WORD wItemType, oscar_tlv_chain *pItemData)
+{
+ HANDLE hContact = (wItemType == SSI_ITEM_BUDDY || wItemType == SSI_ITEM_DENY || wItemType == SSI_ITEM_PERMIT || wItemType == SSI_ITEM_IGNORE) ? HContactFromRecordName(szRecordName, NULL) : NULL;
+
+ if (hContact != INVALID_HANDLE_VALUE && wItemType == SSI_ITEM_BUDDY)
+ { // a contact was removed from our list
+ if (getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0) == wItemId)
+ {
+ deleteSetting(hContact, DBSETTING_SERVLIST_ID);
+ deleteSetting(hContact, DBSETTING_SERVLIST_GROUP);
+ deleteSetting(hContact, "Auth");
+
+ {
+ char str[MAX_PATH];
+ char msg[MAX_PATH];
+ char *nick = NickFromHandleUtf(hContact);
+
+ null_snprintf(str, MAX_PATH, ICQTranslateUtfStatic(LPGEN("User \"%s\" was removed from server list."), msg, MAX_PATH), nick);
+ icq_LogMessage(LOG_WARNING, str);
+ SAFE_FREE(&nick);
+ }
+ }
+ }
+ // Release server-list ID
+ FreeServerID(wItemId, wItemType == SSI_ITEM_GROUP ? SSIT_GROUP : SSIT_ITEM);
+}
+
+
+void CIcqProto::handleRecvAuthRequest(unsigned char *buf, WORD wLen)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ int bAdded;
+
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) return;
+
+ if (dwUin && IsOnSpammerList(dwUin))
+ {
+ NetLog_Server("Ignored Message from known Spammer");
+ return;
+ }
+
+ WORD wReasonLen;
+ unpackWord(&buf, &wReasonLen);
+ wLen -= 2;
+ if (wReasonLen > wLen)
+ return;
+
+ HANDLE hContact = HContactFromUID(dwUin, szUid, &bAdded);
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+
+ ccs.szProtoService = PSR_AUTH;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)&pre;
+ pre.flags = 0;
+ pre.timestamp = time(NULL);
+ pre.lParam = sizeof(DWORD) + sizeof(HANDLE) + 5;
+ // Prepare reason
+ char *szReason = (char*)SAFE_MALLOC(wReasonLen + 1);
+ int nReasonLen = 0;
+ if (szReason)
+ {
+ memcpy(szReason, buf, wReasonLen);
+ szReason[wReasonLen] = '\0';
+ nReasonLen = strlennull(szReason);
+
+ char *temp = (char*)_alloca(nReasonLen + 2);
+ if (!IsUSASCII(szReason, nReasonLen) && UTF8_IsValid(szReason) && utf8_decode_static(szReason, temp, nReasonLen + 1))
+ pre.flags |= PREF_UTF;
+ }
+ // Read nick name from DB
+ char *szNick = NULL;
+ if (dwUin)
+ {
+ DBVARIANT dbv = { 0 };
+ if (pre.flags & PREF_UTF)
+ szNick = getSettingStringUtf(hContact, "Nick", NULL);
+ else if (!getSettingString(hContact, "Nick", &dbv))
+ {
+ szNick = null_strdup(dbv.pszVal);
+ ICQFreeVariant(&dbv);
+ }
+ }
+ else
+ szNick = null_strdup(szUid);
+ int nNickLen = strlennull(szNick);
+
+ pre.lParam += nNickLen + nReasonLen;
+
+ setSettingByte(ccs.hContact, "Grant", 1);
+
+ /*blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ), reason(ASCIIZ)*/
+ char *szBlob = (char *)_alloca(pre.lParam);
+ char *pCurBlob = szBlob;
+ memcpy(pCurBlob, &dwUin, sizeof(DWORD)); pCurBlob += sizeof(DWORD);
+ memcpy(pCurBlob, &hContact, sizeof(HANDLE)); pCurBlob += sizeof(HANDLE);
+ if (nNickLen)
+ { // if we have nick we add it, otherwise keep trailing zero
+ memcpy(pCurBlob, szNick, nNickLen);
+ pCurBlob += nNickLen;
+ }
+ *pCurBlob = 0; pCurBlob++; // Nick
+ *pCurBlob = 0; pCurBlob++; // FirstName
+ *pCurBlob = 0; pCurBlob++; // LastName
+ *pCurBlob = 0; pCurBlob++; // email
+ if (nReasonLen)
+ {
+ memcpy(pCurBlob, szReason, nReasonLen);
+ pCurBlob += nReasonLen;
+ }
+ *pCurBlob = 0; // Reason
+ pre.szMessage = szBlob;
+
+ // TODO: Change for new auth system, include all known informations
+ CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
+
+ SAFE_FREE(&szNick);
+ SAFE_FREE(&szReason);
+ return;
+}
+
+
+void CIcqProto::handleRecvAdded(unsigned char *buf, WORD wLen)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ DWORD cbBlob;
+ PBYTE pBlob,pCurBlob;
+ int bAdded;
+ char* szNick;
+ int nNickLen;
+ DBVARIANT dbv = {0};
+
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) return;
+
+ if (dwUin && IsOnSpammerList(dwUin))
+ {
+ NetLog_Server("Ignored Message from known Spammer");
+ return;
+ }
+
+ HANDLE hContact = HContactFromUID(dwUin, szUid, &bAdded);
+
+ cbBlob=sizeof(DWORD)+sizeof(HANDLE)+4;
+
+ if (dwUin)
+ {
+ if (getSettingString(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
+
+ AddEvent(NULL, EVENTTYPE_ADDED, time(NULL), 0, cbBlob, pBlob);
+}
+
+
+void CIcqProto::handleRecvAuthResponse(unsigned char *buf, WORD wLen)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ char* szNick = NULL;
+ WORD nReasonLen;
+ char* szReason;
+ int bAdded;
+
+ BYTE bResponse = 0xFF;
+
+ if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) return;
+
+ if (dwUin && IsOnSpammerList(dwUin))
+ {
+ NetLog_Server("Ignored Message from known Spammer");
+ return;
+ }
+
+ HANDLE hContact = HContactFromUID(dwUin, szUid, &bAdded);
+
+ if (hContact != INVALID_HANDLE_VALUE) szNick = NickFromHandle(hContact);
+
+ if (wLen > 0)
+ {
+ unpackByte(&buf, &bResponse);
+ wLen -= 1;
+ }
+ if (wLen >= 2)
+ {
+ unpackWord(&buf, &nReasonLen);
+ wLen -= 2;
+ if (wLen >= nReasonLen)
+ {
+ szReason = (char*)_alloca(nReasonLen+1);
+ unpackString(&buf, szReason, nReasonLen);
+ szReason[nReasonLen] = '\0';
+ }
+ }
+
+ switch (bResponse)
+ {
+
+ case 0:
+ NetLog_Server("Authorization request %s by %s", "denied", strUID(dwUin, szUid));
+ // TODO: Add to system history as soon as new auth system is ready
+ break;
+
+ case 1:
+ setSettingByte(hContact, "Auth", 0);
+ NetLog_Server("Authorization request %s by %s", "granted", strUID(dwUin, szUid));
+ // TODO: Add to system history as soon as new auth system is ready
+ break;
+
+ default:
+ NetLog_Server("Unknown Authorization request response (%u) from %s", bResponse, strUID(dwUin, szUid));
+ break;
+
+ }
+ SAFE_FREE(&szNick);
+}
+
+
+// Updates the visibility code used while in SSI mode. If a server ID is
+// not stored in the local DB, a new ID will be added to the server list.
+//
+// Possible values are:
+// 01 - Allow all users to see you
+// 02 - Block all users from seeing you
+// 03 - Allow only users in the permit list to see you
+// 04 - Block only users in the invisible list from seeing you
+// 05 - Allow only users in the buddy list to see you
+//
+void CIcqProto::updateServVisibilityCode(BYTE bCode)
+{
+ icq_packet packet;
+ WORD wVisibilityID;
+ WORD wCommand;
+
+ if ((bCode > 0) && (bCode < 6))
+ {
+ cookie_servlist_action* ack;
+ DWORD dwCookie;
+ BYTE bVisibility = getSettingByte(NULL, "SrvVisibility", 0);
+
+ if (bVisibility == bCode) // if no change was made, not necescary to update that
+ return;
+ setSettingByte(NULL, "SrvVisibility", bCode);
+
+ // Do we have a known server visibility ID? We should, unless we just subscribed to the serv-list for the first time
+ if ((wVisibilityID = getSettingWord(NULL, DBSETTING_SERVLIST_PRIVACY, 0)) == 0)
+ {
+ // No, create a new random ID
+ wVisibilityID = GenerateServerID(SSIT_ITEM, 0);
+ setSettingWord(NULL, DBSETTING_SERVLIST_PRIVACY, wVisibilityID);
+ wCommand = ICQ_LISTS_ADDTOLIST;
+#ifdef _DEBUG
+ NetLog_Server("Made new srvVisibilityID, id is %u, code is %u", wVisibilityID, bCode);
+#endif
+ }
+ else
+ {
+#ifdef _DEBUG
+ NetLog_Server("Reused srvVisibilityID, id is %u, code is %u", wVisibilityID, bCode);
+#endif
+ wCommand = ICQ_LISTS_UPDATEGROUP;
+ }
+
+ ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ 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);
+ packFNACHeader(&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
+ }
+}
+
+// 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 CIcqProto::updateServAvatarHash(BYTE *pHash, int size)
+{
+ void** pDoubleObject = NULL;
+ void* doubleObject = NULL;
+ DWORD dwOperationFlags = 0;
+ WORD wAvatarID;
+ WORD wCommand;
+ DBVARIANT dbvHash;
+ int bResetHash = 0;
+ char szItemName[2] = {0, 0};
+
+ if (!getSetting(NULL, "AvatarHash", &dbvHash))
+ {
+ szItemName[0] = 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
+ { // pair the packets (need to be send in the correct order
+ dwOperationFlags |= SSOF_BEGIN_OPERATION | SSOF_END_OPERATION;
+ pDoubleObject = &doubleObject;
+ }
+
+ if (bResetHash || !pHash)
+ {
+ cookie_servlist_action* ack;
+ DWORD dwCookie;
+
+ // Do we have a known server avatar ID?
+ if (wAvatarID = getSettingWord(NULL, DBSETTING_SERVLIST_AVATAR, 0))
+ {
+ ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ 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
+
+ icq_sendServerItem(dwCookie, ICQ_LISTS_REMOVEFROMLIST, 0, wAvatarID, szItemName, NULL, 0, SSI_ITEM_BUDDYICON, SSOP_ITEM_ACTION | dwOperationFlags, 400, pDoubleObject);
+ }
+ }
+
+ if (pHash)
+ {
+ cookie_servlist_action* ack;
+ DWORD dwCookie;
+ WORD wTLVlen;
+ icq_packet pBuffer;
+ 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 = getSettingWord(NULL, DBSETTING_SERVLIST_AVATAR, 0)) == 0)
+ {
+ // No, create a new random ID
+ wAvatarID = GenerateServerID(SSIT_ITEM, 0);
+ wCommand = ICQ_LISTS_ADDTOLIST;
+#ifdef _DEBUG
+ NetLog_Server("Made new srvAvatarID, id is %u", wAvatarID);
+#endif
+ }
+ else
+ {
+#ifdef _DEBUG
+ NetLog_Server("Reused srvAvatarID, id is %u", wAvatarID);
+#endif
+ wCommand = ICQ_LISTS_UPDATEGROUP;
+ }
+
+ ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ 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
+
+ szItemName[0] = 0x30 + pHash[1];
+
+ // Build the packet
+ wTLVlen = 8 + hashsize;
+
+ // Initialize our handy data buffer
+ pBuffer.wPlace = 0;
+ pBuffer.pData = (BYTE *)_alloca(wTLVlen);
+ pBuffer.wLen = wTLVlen;
+
+ packTLV(&pBuffer, SSI_TLV_NAME, 0, NULL); // TLV (Name)
+ packTLV(&pBuffer, SSI_TLV_AVATARHASH, hashsize, pHash + 2); // TLV (Hash)
+
+ icq_sendServerItem(dwCookie, wCommand, 0, wAvatarID, szItemName, pBuffer.pData, wTLVlen, SSI_ITEM_BUDDYICON, SSOP_ITEM_ACTION | dwOperationFlags, 400, pDoubleObject);
+ // There is no need to send ICQ_LISTS_CLI_MODIFYSTART or
+ // ICQ_LISTS_CLI_MODIFYEND when modifying the avatar hash
+ }
+}
+
+// Should be called before the server list is modified. When all
+// modifications are done, call icq_sendServerEndOperation().
+// Called automatically thru server-list update board!
+void CIcqProto::icq_sendServerBeginOperation(int bImport)
+{
+ icq_packet packet;
+ WORD wImportID = getSettingWord(NULL, "SrvImportID", 0);
+
+ if (bImport && wImportID)
+ { // we should be importing, check if already have import item
+ if (getSettingDword(NULL, "ImportTS", 0) + 604800 < getSettingDword(NULL, "LogonTS", 0))
+ { // is the timestamp week older, clear it and begin new import
+ DWORD dwCookie;
+ cookie_servlist_action* ack;
+
+ if (ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action)))
+ { // 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, SSOP_ITEM_ACTION | SSOF_SEND_DIRECTLY, 100);
+ }
+ }
+ }
+
+ 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.
+// Called automatically thru server-list update board!
+void CIcqProto::icq_sendServerEndOperation()
+{
+ 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 CIcqProto::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/protocols/IcqOscarJ/fam_15icqserver.cpp b/protocols/IcqOscarJ/fam_15icqserver.cpp
new file mode 100644
index 0000000000..6df21796c4
--- /dev/null
+++ b/protocols/IcqOscarJ/fam_15icqserver.cpp
@@ -0,0 +1,1208 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/fam_15icqserver.cpp $
+// Revision : $Revision: 13027 $
+// Last change on : $Date: 2010-10-24 16:23:07 +0200 (Вс, 24 окт 2010) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+void CIcqProto::handleIcqExtensionsFam(BYTE *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;
+ }
+}
+
+
+void CIcqProto::handleExtensionError(BYTE *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 = chain->getTLV(0x21, 1); // get meta error data
+ if (pTLV && pTLV->wLen >= 8)
+ {
+ BYTE *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;
+ cookie_fam15_data *pCookieData = NULL;
+ int foundCookie;
+
+ foundCookie = FindCookie(wCookie, &hContact, (void**)&pCookieData);
+ if (foundCookie && pCookieData)
+ {
+ BroadcastAck(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 if (wSubType == META_SET_PASSWORD_REQ)
+ { // failed to change user password, report to UI
+ BroadcastAck(NULL, ACKTYPE_SETINFO, ACKRESULT_FAILED, (HANDLE)wCookie, 0);
+
+ NetLog_Server("Meta change password request failed, error 0x%02x", wErrorCode);
+ }
+ else
+ NetLog_Server("Meta 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);
+}
+
+
+void CIcqProto::handleExtensionServerInfo(BYTE *buf, WORD wPackLen, WORD wFlags)
+{
+ oscar_tlv_chain *chain;
+ oscar_tlv *dataTlv;
+
+ // 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 = chain->getTLV(0x0001, 1);
+ if (dataTlv == NULL)
+ {
+ disposeChain(&chain);
+ NetLog_Server("Error: Broken snac 15/3 %d", 2);
+ return;
+ }
+ BYTE *databuf = dataTlv->pData;
+ wPackLen -= 4;
+
+ _ASSERTE(dataTlv->wLen == wPackLen);
+ _ASSERTE(wPackLen >= 10);
+
+ if ((dataTlv->wLen == wPackLen) && (wPackLen >= 10))
+ {
+ WORD wBytesRemaining;
+ WORD wRequestType;
+ WORD wCookie;
+ DWORD dwMyUin;
+
+ 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);
+}
+
+
+void CIcqProto::handleExtensionMetaResponse(BYTE *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:
+ 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_PROCESSING_ERROR: // Meta processing error server reply
+ // Todo: We only use this as an SMS ack, that will have to change
+ {
+ // Terminate buffer
+ char *pszInfo = (char *)_alloca(wPacketLen + 1);
+ if (wPacketLen > 0)
+ memcpy(pszInfo, databuf, wPacketLen);
+ pszInfo[wPacketLen] = 0;
+
+ BroadcastAck(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;
+
+ BroadcastAck(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;
+
+ case META_DIRECTORY_DATA:
+ case META_DIRECTORY_RESPONSE:
+ if (bResultCode == 0x0A)
+ handleDirectoryQueryResponse(databuf, wPacketLen, wCookie, wReplySubtype, wFlags);
+ else
+ NetLog_Server("Error: Directory request failed, code %u", bResultCode);
+ break;
+
+ case META_DIRECTORY_UPDATE_ACK:
+ if (bResultCode == 0x0A)
+ handleDirectoryUpdateResponse(databuf, wPacketLen, wCookie, wReplySubtype);
+ else
+ NetLog_Server("Error: Directory request failed, code %u", bResultCode);
+ 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");
+}
+
+
+void CIcqProto::ReleaseSearchCookie(DWORD dwCookie, cookie_search *pCookie)
+{
+ if (pCookie)
+ {
+ FreeCookie(dwCookie);
+ if (pCookie->dwMainId)
+ {
+ if (pCookie->dwStatus)
+ {
+ SAFE_FREE((void**)&pCookie);
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+ }
+ else
+ pCookie->dwStatus = 1;
+ }
+ else
+ {
+ SAFE_FREE((void**)&pCookie);
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+ }
+ }
+ else
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+}
+
+
+void CIcqProto::parseSearchReplies(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype, BYTE bResultCode)
+{
+ BYTE bParsingOK = FALSE; // For debugging purposes only
+ BOOL bLastUser = FALSE;
+ cookie_search *pCookie;
+
+ if (!FindCookie(wCookie, NULL, (void**)&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;
+ char szUin[UINMAXLEN];
+ 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;
+ _itoa(dwUin, szUin, 10);
+ sr.hdr.id = (FNAMECHAR*)szUin;
+
+ // Nick
+ if (wPacketLen < 2)
+ break;
+ unpackLEWord(&databuf, &wLen);
+ wPacketLen -= 2;
+ if (wLen > 0)
+ {
+ if (wPacketLen < wLen || (databuf[wLen-1] != 0))
+ break;
+ sr.hdr.nick = (FNAMECHAR*)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 = (FNAMECHAR*)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 = (FNAMECHAR*)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 = (FNAMECHAR*)databuf;
+ databuf += wLen;
+ }
+ else
+ {
+ sr.hdr.email = NULL;
+ }
+
+ // Authentication needed flag
+ if (wPacketLen < 1)
+ break;
+ unpackByte(&databuf, &sr.auth);
+
+ // Finally, broadcast the result
+ BroadcastAck(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);
+ }
+}
+
+
+void CIcqProto::parseUserInfoUpdateAck(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype, BYTE bResultCode)
+{
+ switch (wReplySubtype) {
+ case META_SET_PASSWORD_ACK: // Set user password server ack
+
+ if (bResultCode == 0xA)
+ BroadcastAck(NULL, ACKTYPE_SETINFO, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
+ else
+ BroadcastAck(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;
+ }
+}
+
+
+UserInfoRecordItem rEmail[] = {
+ {0x64, DBVT_ASCIIZ, "e-mail%u"}
+};
+
+UserInfoRecordItem rAddress[] = {
+ {0x64, DBVT_UTF8, "Street"},
+ {0x6E, DBVT_UTF8, "City"},
+ {0x78, DBVT_UTF8, "State"},
+ {0x82, DBVT_UTF8, "ZIP"},
+ {0x8C, DBVT_WORD, "Country"}
+};
+
+UserInfoRecordItem rOriginAddress[] = {
+ {0x64, DBVT_UTF8, "OriginStreet"},
+ {0x6E, DBVT_UTF8, "OriginCity"},
+ {0x78, DBVT_UTF8, "OriginState"},
+ {0x8C, DBVT_WORD, "OriginCountry"}
+};
+
+UserInfoRecordItem rCompany[] = {
+ {0x64, DBVT_UTF8, "CompanyPosition"},
+ {0x6E, DBVT_UTF8, "Company"},
+ {0x7D, DBVT_UTF8, "CompanyDepartment"},
+ {0x78, DBVT_ASCIIZ, "CompanyHomepage"},
+ {0x82, DBVT_WORD, "CompanyIndustry"},
+ {0xAA, DBVT_UTF8, "CompanyStreet"},
+ {0xB4, DBVT_UTF8, "CompanyCity"},
+ {0xBE, DBVT_UTF8, "CompanyState"},
+ {0xC8, DBVT_UTF8, "CompanyZIP"},
+ {0xD2, DBVT_WORD, "CompanyCountry"}
+};
+
+UserInfoRecordItem rEducation[] = {
+ {0x64, DBVT_WORD, "StudyLevel"},
+ {0x6E, DBVT_UTF8, "StudyInstitute"},
+ {0x78, DBVT_UTF8, "StudyDegree"},
+ {0x8C, DBVT_WORD, "StudyYear"}
+};
+
+UserInfoRecordItem rInterest[] = {
+ {0x64, DBVT_UTF8, "Interest%uText"},
+ {0x6E, DBVT_WORD, "Interest%uCat"}
+};
+
+
+int CIcqProto::parseUserInfoRecord(HANDLE hContact, oscar_tlv *pData, UserInfoRecordItem pRecordDef[], int nRecordDef, int nMaxRecords)
+{
+ int nRecords = 0;
+
+ if (pData && pData->wLen >= 2)
+ {
+ BYTE *pRecords = pData->pData;
+ WORD wRecordCount;
+ unpackWord(&pRecords, &wRecordCount);
+ oscar_tlv_record_list *cData = readIntoTLVRecordList(&pRecords, pData->wLen - 2, nMaxRecords > wRecordCount ? wRecordCount : nMaxRecords);
+ oscar_tlv_record_list *cDataItem = cData;
+ while (cDataItem)
+ {
+ oscar_tlv_chain *cItem = cDataItem->item;
+
+ for (int i = 0; i < nRecordDef; i++)
+ {
+ char szItemKey[MAX_PATH];
+
+ null_snprintf(szItemKey, MAX_PATH, pRecordDef[i].szDbSetting, nRecords);
+
+ switch (pRecordDef[i].dbType)
+ {
+ case DBVT_ASCIIZ:
+ writeDbInfoSettingTLVString(hContact, szItemKey, cItem, pRecordDef[i].wTLV);
+ break;
+
+ case DBVT_UTF8:
+ writeDbInfoSettingTLVStringUtf(hContact, szItemKey, cItem, pRecordDef[i].wTLV);
+ break;
+
+ case DBVT_WORD:
+ writeDbInfoSettingTLVWord(hContact, szItemKey, cItem, pRecordDef[i].wTLV);
+ break;
+ }
+ }
+ nRecords++;
+
+ cDataItem = cDataItem->next;
+ }
+ // release memory
+ disposeRecordList(&cData);
+ }
+ // remove old data from database
+ if (!nRecords || nMaxRecords > 1)
+ for (int i = nRecords; i <= nMaxRecords; i++)
+ for (int j = 0; j < nRecordDef; j++)
+ {
+ char szItemKey[MAX_PATH];
+
+ null_snprintf(szItemKey, MAX_PATH, pRecordDef[j].szDbSetting, i);
+
+ deleteSetting(hContact, szItemKey);
+ }
+
+ return nRecords;
+}
+
+
+void CIcqProto::handleDirectoryQueryResponse(BYTE *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype, WORD wFlags)
+{
+ WORD wBytesRemaining = 0;
+ snac_header requestSnac = {0};
+ BYTE requestResult;
+
+#ifdef _DEBUG
+ NetLog_Server("Received directory query response");
+#endif
+ if (wPacketLen >= 2)
+ unpackLEWord(&databuf, &wBytesRemaining);
+ wPacketLen -= 2;
+ _ASSERTE(wPacketLen == wBytesRemaining);
+
+ if (!unpackSnacHeader(&requestSnac, &databuf, &wPacketLen) || !requestSnac.bValid)
+ {
+ NetLog_Server("Error: Failed to parse directory response");
+ return;
+ }
+
+ cookie_directory_data *pCookieData;
+ HANDLE hContact;
+ // check request cookie
+ if (!FindCookie(wCookie, &hContact, (void**)&pCookieData) || !pCookieData)
+ {
+ NetLog_Server("Warning: Ignoring unrequested directory reply type (x%x, x%x)", requestSnac.wFamily, requestSnac.wSubtype);
+ return;
+ }
+ /// FIXME: we should really check the snac contents according to cookie data here ??
+
+ // Check if this is the last packet for this request
+ BOOL bMoreDataFollows = wFlags&0x0001 && requestSnac.wFlags&0x0001;
+
+ if (wPacketLen >= 3)
+ unpackByte(&databuf, &requestResult);
+ else
+ {
+ NetLog_Server("Error: Malformed directory response");
+ if (!bMoreDataFollows)
+ ReleaseCookie(wCookie);
+ return;
+ }
+ if (requestResult != 1 && requestResult != 4)
+ {
+ NetLog_Server("Error: Directory request failed, status %u", requestResult);
+
+ if (!bMoreDataFollows)
+ {
+ if (pCookieData->bRequestType == DIRECTORYREQUEST_INFOUSER)
+ BroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_FAILED, (HANDLE)1 ,0);
+ else if (pCookieData->bRequestType == DIRECTORYREQUEST_SEARCH)
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0); // should report error here, but Find/Add module does not support that
+ ReleaseCookie(wCookie);
+ }
+ return;
+ }
+ WORD wLen;
+
+ unpackWord(&databuf, &wLen);
+ wPacketLen -= 3;
+ if (wLen)
+ NetLog_Server("Warning: Data in error message present!");
+
+ if (wPacketLen <= 0x16)
+ { // sanity check
+ NetLog_Server("Error: Malformed directory response");
+
+ if (!bMoreDataFollows)
+ {
+ if (pCookieData->bRequestType == DIRECTORYREQUEST_INFOUSER)
+ BroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_FAILED, (HANDLE)1 ,0);
+ else if (pCookieData->bRequestType == DIRECTORYREQUEST_SEARCH)
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0); // should report error here, but Find/Add module does not support that
+ ReleaseCookie(wCookie);
+ }
+ return;
+ }
+ databuf += 0x10; // unknown stuff
+ wPacketLen -= 0x10;
+
+ DWORD dwItemCount;
+ WORD wPageCount;
+
+ /// FIXME: check itemcount, pagecount against the cookie data ???
+
+ unpackDWord(&databuf, &dwItemCount);
+ unpackWord(&databuf, &wPageCount);
+ wPacketLen -= 6;
+
+ if (pCookieData->bRequestType == DIRECTORYREQUEST_SEARCH && !bMoreDataFollows)
+ NetLog_Server("Directory Search: %d contacts found (%u pages)", dwItemCount, wPageCount);
+
+ if (wPacketLen <= 2)
+ { // sanity check, block expected
+ NetLog_Server("Error: Malformed directory response");
+
+ if (!bMoreDataFollows)
+ {
+ if (pCookieData->bRequestType == DIRECTORYREQUEST_INFOUSER)
+ BroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_FAILED, (HANDLE)1 ,0);
+ else if (pCookieData->bRequestType == DIRECTORYREQUEST_SEARCH)
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0); // should report error here, but Find/Add module does not support that
+ ReleaseCookie(wCookie);
+ }
+ return;
+ }
+ WORD wData;
+
+ unpackWord(&databuf, &wData); // This probably the count of items following (a block)
+ wPacketLen -= 2;
+ if (wPacketLen >= 2 && wData >= 1)
+ {
+ unpackWord(&databuf, &wLen); // This is the size of the first item
+ wPacketLen -= 2;
+ }
+
+ if (wData == 0 && pCookieData->bRequestType == DIRECTORYREQUEST_SEARCH)
+ {
+ NetLog_Server("Directory Search: No contacts found");
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
+ ReleaseCookie(wCookie);
+ return;
+ }
+
+ _ASSERTE(wData == 1 && wPacketLen == wLen);
+ if (wData != 1 || wPacketLen != wLen)
+ {
+ NetLog_Server("Error: Malformed directory response (missing data)");
+
+ if (!bMoreDataFollows)
+ {
+ if (pCookieData->bRequestType == DIRECTORYREQUEST_INFOUSER)
+ BroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_FAILED, (HANDLE)1 ,0);
+ else if (pCookieData->bRequestType == DIRECTORYREQUEST_SEARCH)
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0); // should report error here, but Find/Add module does not support that
+ ReleaseCookie(wCookie);
+ }
+ return;
+ }
+ oscar_tlv_chain *pDirectoryData = readIntoTLVChain(&databuf, wLen, -1);
+ if (pDirectoryData)
+ {
+ switch (pCookieData->bRequestType)
+ {
+ case DIRECTORYREQUEST_INFOOWNER:
+ parseDirectoryUserDetailsData(NULL, pDirectoryData, wCookie, pCookieData, wReplySubtype);
+ break;
+
+ case DIRECTORYREQUEST_INFOUSER:
+ {
+ DWORD dwUin = 0;
+ char *szUid = pDirectoryData->getString(0x32, 1);
+ if (!szUid)
+ {
+ NetLog_Server("Error: Received unrecognized data from the directory");
+ break;
+ }
+
+ if (IsStringUIN(szUid))
+ dwUin = atoi(szUid);
+
+ if (hContact != HContactFromUID(dwUin, szUid, NULL))
+ {
+ NetLog_Server("Error: Received data does not match cookie contact, ignoring.");
+ SAFE_FREE(&szUid);
+ break;
+ }
+ else
+ SAFE_FREE(&szUid);
+ }
+
+ case DIRECTORYREQUEST_INFOMULTI:
+ parseDirectoryUserDetailsData(hContact, pDirectoryData, wCookie, pCookieData, wReplySubtype);
+ break;
+
+ case DIRECTORYREQUEST_SEARCH:
+ parseDirectorySearchData(pDirectoryData, wCookie, pCookieData, wReplySubtype);
+ break;
+
+ default:
+ NetLog_Server("Error: Unknown cookie type %x for directory response!", pCookieData->bRequestType);
+ }
+ disposeChain(&pDirectoryData);
+ }
+ else
+ NetLog_Server("Error: Failed parsing directory response");
+
+ // Release Memory
+ if (!bMoreDataFollows)
+ ReleaseCookie(wCookie);
+}
+
+
+static int calcAgeFromBirthDate(double dDate)
+{
+ if (dDate > 0)
+ { // date is stored as double with unit equal to a day, incrementing since 1/1/1900 0:00 GMT
+ SYSTEMTIME sDate = {0};
+ if (VariantTimeToSystemTime(dDate + 2, &sDate))
+ {
+ SYSTEMTIME sToday = {0};
+
+ GetLocalTime(&sToday);
+
+ int nAge = sToday.wYear - sDate.wYear;
+
+ if (sToday.wMonth < sDate.wMonth || (sToday.wMonth == sDate.wMonth && sToday.wDay < sDate.wDay))
+ nAge--;
+
+ return nAge;
+ }
+ }
+ return 0;
+}
+
+
+void CIcqProto::parseDirectoryUserDetailsData(HANDLE hContact, oscar_tlv_chain *cDetails, DWORD dwCookie, cookie_directory_data *pCookieData, WORD wReplySubType)
+{
+ oscar_tlv *pTLV;
+ WORD wRecordCount;
+
+ if (pCookieData->bRequestType == DIRECTORYREQUEST_INFOMULTI && !hContact)
+ {
+ DWORD dwUin = 0;
+ char *szUid = cDetails->getString(0x32, 1);
+ if (!szUid)
+ {
+ NetLog_Server("Error: Received unrecognized data from the directory");
+ return;
+ }
+
+ if (IsStringUIN(szUid))
+ dwUin = atoi(szUid);
+
+ hContact = HContactFromUID(dwUin, szUid, NULL);
+ if (hContact == INVALID_HANDLE_VALUE)
+ {
+ NetLog_Server("Error: Received details for unknown contact \"%s\"", szUid);
+ SAFE_FREE(&szUid);
+ return;
+ }
+#ifdef _DEBUG
+ else
+ NetLog_Server("Received user info for %s from directory", szUid);
+#endif
+ SAFE_FREE(&szUid);
+ }
+#ifdef _DEBUG
+ else
+ {
+ char *szUid = cDetails->getString(0x32, 1);
+
+ if (!hContact)
+ NetLog_Server("Received owner user info from directory");
+ else
+ NetLog_Server("Received user info for %s from directory", szUid);
+ SAFE_FREE(&szUid);
+ }
+#endif
+
+ pTLV = cDetails->getTLV(0x50, 1);
+ if (pTLV && pTLV->wLen > 0)
+ writeDbInfoSettingTLVString(hContact, "e-mail", cDetails, 0x50); // Verified e-mail
+ else
+ writeDbInfoSettingTLVString(hContact, "e-mail", cDetails, 0x55); // Pending e-mail
+
+ writeDbInfoSettingTLVStringUtf(hContact, "FirstName", cDetails, 0x64);
+ writeDbInfoSettingTLVStringUtf(hContact, "LastName", cDetails, 0x6E);
+ writeDbInfoSettingTLVStringUtf(hContact, "Nick", cDetails, 0x78);
+ // Home Address
+ parseUserInfoRecord(hContact, cDetails->getTLV(0x96, 1), rAddress, SIZEOF(rAddress), 1);
+ // Origin Address
+ parseUserInfoRecord(hContact, cDetails->getTLV(0xA0, 1), rOriginAddress, SIZEOF(rOriginAddress), 1);
+ // Phones
+ pTLV = cDetails->getTLV(0xC8, 1);
+ if (pTLV && pTLV->wLen >= 2)
+ {
+ BYTE *pRecords = pTLV->pData;
+ unpackWord(&pRecords, &wRecordCount);
+ oscar_tlv_record_list *cPhones = readIntoTLVRecordList(&pRecords, pTLV->wLen - 2, wRecordCount);
+ if (cPhones)
+ {
+ oscar_tlv_chain *cPhone;
+ cPhone = cPhones->getRecordByTLV(0x6E, 1);
+ writeDbInfoSettingTLVString(hContact, "Phone", cPhone, 0x64);
+ cPhone = cPhones->getRecordByTLV(0x6E, 2);
+ writeDbInfoSettingTLVString(hContact, "CompanyPhone", cPhone, 0x64);
+ cPhone = cPhones->getRecordByTLV(0x6E, 3);
+ writeDbInfoSettingTLVString(hContact, "Cellular", cPhone, 0x64);
+ cPhone = cPhones->getRecordByTLV(0x6E, 4);
+ writeDbInfoSettingTLVString(hContact, "Fax", cPhone, 0x64);
+ cPhone = cPhones->getRecordByTLV(0x6E, 5);
+ writeDbInfoSettingTLVString(hContact, "CompanyFax", cPhone, 0x64);
+
+ disposeRecordList(&cPhones);
+ }
+ else
+ { // Remove old data when phones not available
+ deleteSetting(hContact, "Phone");
+ deleteSetting(hContact, "CompanyPhone");
+ deleteSetting(hContact, "Cellular");
+ deleteSetting(hContact, "Fax");
+ deleteSetting(hContact, "CompanyFax");
+ }
+ }
+ else
+ { // Remove old data when phones not available
+ deleteSetting(hContact, "Phone");
+ deleteSetting(hContact, "CompanyPhone");
+ deleteSetting(hContact, "Cellular");
+ deleteSetting(hContact, "Fax");
+ deleteSetting(hContact, "CompanyFax");
+ }
+ // Emails
+ parseUserInfoRecord(hContact, cDetails->getTLV(0x8C, 1), rEmail, SIZEOF(rEmail), 4);
+
+ writeDbInfoSettingTLVByte(hContact, "Timezone", cDetails, 0x17C);
+ // Company
+ parseUserInfoRecord(hContact, cDetails->getTLV(0x118, 1), rCompany, SIZEOF(rCompany), 1);
+ // Education
+ parseUserInfoRecord(hContact, cDetails->getTLV(0x10E, 1), rEducation, SIZEOF(rEducation), 1);
+
+ switch (cDetails->getNumber(0x82, 1))
+ {
+ case 1:
+ setSettingByte(hContact, "Gender", 'F');
+ break;
+ case 2:
+ setSettingByte(hContact, "Gender", 'M');
+ break;
+ default:
+ deleteSetting(hContact, "Gender");
+ }
+
+ writeDbInfoSettingTLVString(hContact, "Homepage", cDetails, 0xFA);
+ writeDbInfoSettingTLVDate(hContact, "BirthYear", "BirthMonth", "BirthDay", cDetails, 0x1A4);
+
+ writeDbInfoSettingTLVByte(hContact, "Language1", cDetails, 0xAA);
+ writeDbInfoSettingTLVByte(hContact, "Language2", cDetails, 0xB4);
+ writeDbInfoSettingTLVByte(hContact, "Language3", cDetails, 0xBE);
+
+ writeDbInfoSettingTLVByte(hContact, "MaritalStatus", cDetails, 0x12C);
+ // Interests
+ parseUserInfoRecord(hContact, cDetails->getTLV(0x122, 1), rInterest, SIZEOF(rInterest), 4);
+
+ writeDbInfoSettingTLVStringUtf(hContact, "About", cDetails, 0x186);
+
+// if (hContact)
+// writeDbInfoSettingTLVStringUtf(hContact, DBSETTING_STATUS_NOTE, cDetails, 0x226);
+// else
+ if (!hContact)
+ { // Owner contact needs special processing, in the database is current status note for the client
+ // We just received the last status note set on directory, if it differs call SetStatusNote() to
+ // ensure the directory will be updated (it should be in process anyway)
+ char *szClientStatusNote = getSettingStringUtf(hContact, DBSETTING_STATUS_NOTE, NULL);
+ char *szDirectoryStatusNote = cDetails->getString(0x226, 1);
+
+ if (strcmpnull(szClientStatusNote, szDirectoryStatusNote))
+ SetStatusNote(szClientStatusNote, 1000, TRUE);
+
+ // Release memory
+ SAFE_FREE(&szDirectoryStatusNote);
+ SAFE_FREE(&szClientStatusNote);
+ }
+
+ writeDbInfoSettingTLVByte(hContact, "PrivacyLevel", cDetails, 0x1F9);
+
+ if (!hContact)
+ {
+ setSettingByte(hContact, "Auth", !cDetails->getByte(0x19A, 1));
+ writeDbInfoSettingTLVByte(hContact, "WebAware", cDetails, 0x212);
+ writeDbInfoSettingTLVByte(hContact, "AllowSpam", cDetails, 0x1EA);
+ }
+
+ writeDbInfoSettingTLVWord(hContact, "InfoCP", cDetails, 0x1C2);
+
+ if (hContact)
+ { // Handle deprecated setting (Age & Birthdate are not separate fields anymore)
+ int nAge = calcAgeFromBirthDate(cDetails->getDouble(0x1A4, 1));
+
+ if (nAge)
+ setSettingWord(hContact, "Age", nAge);
+ else
+ deleteSetting(hContact, "Age");
+ }
+ else // we do not need to calculate age for owner
+ deleteSetting(hContact, "Age");
+
+ { // Save user info last update time and privacy token
+ double dInfoTime;
+ BYTE pbEmptyMetaToken[0x10] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ int bHasMetaToken = FALSE;
+
+ // Check if the details arrived with privacy token!
+ if ((pTLV = cDetails->getTLV(0x3C, 1)) && pTLV->wLen == 0x10 && memcmp(pTLV->pData, pbEmptyMetaToken, 0x10))
+ bHasMetaToken = TRUE;
+
+ // !Important, we need to save the MDir server-item time - it can be newer than the one from the directory
+ if ((dInfoTime = getSettingDouble(hContact, DBSETTING_METAINFO_TIME, 0)) > 0)
+ setSettingDouble(hContact, DBSETTING_METAINFO_SAVED, dInfoTime);
+ else if (bHasMetaToken || !hContact)
+ writeDbInfoSettingTLVDouble(hContact, DBSETTING_METAINFO_SAVED, cDetails, 0x1CC);
+ else
+ setSettingDword(hContact, DBSETTING_METAINFO_SAVED, time(NULL));
+ }
+
+ if (wReplySubType == META_DIRECTORY_RESPONSE)
+ if (pCookieData->bRequestType == DIRECTORYREQUEST_INFOUSER)
+ BroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1 ,0);
+
+ // 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.
+ if (hContact)
+ icq_DequeueUser(getContactUin(hContact));
+}
+
+
+void CIcqProto::parseDirectorySearchData(oscar_tlv_chain *cDetails, DWORD dwCookie, cookie_directory_data *pCookieData, WORD wReplySubType)
+{
+ ICQSEARCHRESULT isr = {0};
+ char *szUid = cDetails->getString(0x32, 1); // User ID
+
+#ifdef _DEBUG
+ NetLog_Server("Directory Search: Found user %s", szUid);
+#endif
+ isr.hdr.cbSize = sizeof(ICQSEARCHRESULT);
+ isr.hdr.flags = PSR_TCHAR;
+ isr.hdr.id = ansi_to_tchar(szUid);
+
+ if (IsStringUIN(szUid))
+ isr.uin = atoi(szUid);
+ else
+ isr.uin = 0;
+
+ SAFE_FREE(&szUid);
+
+ oscar_tlv *pTLV = cDetails->getTLV(0x50, 1);
+ char *szData = NULL;
+
+ if (pTLV && pTLV->wLen > 0)
+ szData = cDetails->getString(0x50, 1); // Verified e-mail
+ else
+ szData = cDetails->getString(0x55, 1); // Pending e-mail
+ if (strlennull(szData))
+ isr.hdr.email = ansi_to_tchar(szData);
+ SAFE_FREE(&szData);
+
+ szData = cDetails->getString(0x64, 1); // First Name
+ if (strlennull(szData))
+ isr.hdr.firstName = utf8_to_tchar(szData);
+ SAFE_FREE(&szData);
+
+ szData = cDetails->getString(0x6E, 1); // Last Name
+ if (strlennull(szData))
+ isr.hdr.lastName = utf8_to_tchar(szData);
+ SAFE_FREE(&szData);
+
+ szData = cDetails->getString(0x78, 1); // Nick
+ if (strlennull(szData))
+ isr.hdr.nick = utf8_to_tchar(szData);
+ SAFE_FREE(&szData);
+
+ switch (cDetails->getNumber(0x82, 1)) // Gender
+ {
+ case 1:
+ isr.gender = 'F';
+ break;
+ case 2:
+ isr.gender = 'M';
+ break;
+ }
+
+ pTLV = cDetails->getTLV(0x96, 1);
+ if (pTLV && pTLV->wLen >= 4)
+ {
+ BYTE *buf = pTLV->pData;
+ oscar_tlv_chain *chain = readIntoTLVChain(&buf, pTLV->wLen, 0);
+ if (chain)
+ isr.country = chain->getDWord(0x8C, 1); // Home Country
+ disposeChain(&chain);
+ }
+
+ isr.auth = !cDetails->getByte(0x19A, 1); // Require Authorization
+ isr.maritalStatus = cDetails->getNumber(0x12C, 1); // Marital Status
+
+ // calculate Age if Birthdate is available
+ isr.age = calcAgeFromBirthDate(cDetails->getDouble(0x1A4, 1));
+
+ // Finally, broadcast the result
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)dwCookie, (LPARAM)&isr);
+
+ // Release memory
+ SAFE_FREE(&isr.hdr.id);
+ SAFE_FREE(&isr.hdr.nick);
+ SAFE_FREE(&isr.hdr.firstName);
+ SAFE_FREE(&isr.hdr.lastName);
+ SAFE_FREE(&isr.hdr.email);
+
+ // Search is over, broadcast final ack
+ if (wReplySubType == META_DIRECTORY_RESPONSE)
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
+}
+
+
+void CIcqProto::handleDirectoryUpdateResponse(BYTE *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype)
+{
+ WORD wBytesRemaining = 0;
+ snac_header requestSnac = {0};
+ BYTE requestResult;
+
+#ifdef _DEBUG
+ NetLog_Server("Received directory update response");
+#endif
+ if (wPacketLen >= 2)
+ unpackLEWord(&databuf, &wBytesRemaining);
+ wPacketLen -= 2;
+ _ASSERTE(wPacketLen == wBytesRemaining);
+
+ if (!unpackSnacHeader(&requestSnac, &databuf, &wPacketLen) || !requestSnac.bValid)
+ {
+ NetLog_Server("Error: Failed to parse directory response");
+ return;
+ }
+
+ cookie_directory_data *pCookieData;
+ HANDLE hContact;
+ // check request cookie
+ if (!FindCookie(wCookie, &hContact, (void**)&pCookieData) || !pCookieData)
+ {
+ NetLog_Server("Warning: Ignoring unrequested directory reply type (x%x, x%x)", requestSnac.wFamily, requestSnac.wSubtype);
+ return;
+ }
+ /// FIXME: we should really check the snac contents according to cookie data here ??
+
+ if (wPacketLen >= 3)
+ unpackByte(&databuf, &requestResult);
+ else
+ {
+ NetLog_Server("Error: Malformed directory response");
+ ReleaseCookie(wCookie);
+ return;
+ }
+ if (requestResult != 1 && requestResult != 4)
+ {
+ NetLog_Server("Error: Directory request failed, status %u", requestResult);
+
+ if (pCookieData->bRequestType == DIRECTORYREQUEST_UPDATEOWNER)
+ BroadcastAck(NULL, ACKTYPE_SETINFO, ACKRESULT_FAILED, (HANDLE)wCookie, 0);
+
+ ReleaseCookie(wCookie);
+ return;
+ }
+ WORD wLen;
+
+ unpackWord(&databuf, &wLen);
+ wPacketLen -= 3;
+ if (wLen)
+ NetLog_Server("Warning: Data in error message present!");
+
+ if (pCookieData->bRequestType == DIRECTORYREQUEST_UPDATEOWNER)
+ BroadcastAck(NULL, ACKTYPE_SETINFO, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
+ if (wPacketLen == 0x18)
+ {
+ DWORD64 qwMetaTime;
+ BYTE pbEmptyMetaToken[0x10] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ unpackQWord(&databuf, &qwMetaTime);
+ setSettingBlob(NULL, DBSETTING_METAINFO_TIME, (BYTE*)&qwMetaTime, 8);
+
+ if (memcmp(databuf, pbEmptyMetaToken, 0x10))
+ setSettingBlob(NULL, DBSETTING_METAINFO_TOKEN, databuf, 0x10);
+ }
+ ReleaseCookie(wCookie);
+}
diff --git a/protocols/IcqOscarJ/fam_17signon.cpp b/protocols/IcqOscarJ/fam_17signon.cpp
new file mode 100644
index 0000000000..c2a87f2ae0
--- /dev/null
+++ b/protocols/IcqOscarJ/fam_17signon.cpp
@@ -0,0 +1,182 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/fam_17signon.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+void CIcqProto::handleAuthorizationFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader, serverthread_info *info)
+{
+ switch (pSnacHeader->wSubtype) {
+
+ case ICQ_SIGNON_ERROR:
+ {
+ WORD wError;
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ LogFamilyError(ICQ_AUTHORIZATION_FAMILY, wError);
+ break;
+ }
+
+ case ICQ_SIGNON_AUTH_KEY:
+ handleAuthKeyResponse(pBuffer, wBufferLength, info);
+ break;
+
+ case ICQ_SIGNON_LOGIN_REPLY:
+ handleLoginReply(pBuffer, wBufferLength, info);
+ break;
+
+ default:
+ NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_AUTHORIZATION_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
+ break;
+ }
+}
+
+static void icq_encryptPassword(const char *szPassword, BYTE *encrypted)
+{
+ BYTE table[] =
+ {
+ 0xf3, 0x26, 0x81, 0xc4,
+ 0x39, 0x86, 0xdb, 0x92,
+ 0x71, 0xa3, 0xb9, 0xe6,
+ 0x53, 0x7a, 0x95, 0x7c
+ };
+
+ for (int i = 0; szPassword[i]; i++)
+ encrypted[i] = (szPassword[i] ^ table[i % 16]);
+}
+
+void CIcqProto::sendClientAuth(const char *szKey, WORD wKeyLen, BOOL bSecure)
+{
+ char szUin[UINMAXLEN];
+ WORD wUinLen;
+ icq_packet packet;
+
+ wUinLen = strlennull(strUID(m_dwLocalUIN, szUin));
+
+ packet.wLen = 70 + sizeof(CLIENT_ID_STRING) + wUinLen + wKeyLen + (m_bSecureConnection ? 4 : 0);
+
+ if (bSecure)
+ {
+ serverPacketInit(&packet, (WORD)(packet.wLen + 10));
+ packFNACHeader(&packet, ICQ_AUTHORIZATION_FAMILY, ICQ_SIGNON_LOGIN_REQUEST, 0, 0);
+ }
+ else
+ {
+ write_flap(&packet, ICQ_LOGIN_CHAN);
+ packDWord(&packet, 0x00000001);
+ }
+ packTLV(&packet, 0x0001, wUinLen, (LPBYTE)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
+ BYTE hash[20];
+
+ icq_encryptPassword(szKey, hash);
+ packTLV(&packet, 0x0002, wKeyLen, hash);
+ }
+
+ // Pack client identification details.
+ packTLV(&packet, 0x0003, (WORD)sizeof(CLIENT_ID_STRING)-1, (LPBYTE)CLIENT_ID_STRING);
+ packTLVWord(&packet, 0x0017, CLIENT_VERSION_MAJOR);
+ packTLVWord(&packet, 0x0018, CLIENT_VERSION_MINOR);
+ packTLVWord(&packet, 0x0019, CLIENT_VERSION_LESSER);
+ packTLVWord(&packet, 0x001a, CLIENT_VERSION_BUILD);
+ packTLVWord(&packet, 0x0016, CLIENT_ID_CODE);
+ packTLVDWord(&packet, 0x0014, CLIENT_DISTRIBUTION);
+ packTLV(&packet, 0x000f, 0x0002, (LPBYTE)CLIENT_LANGUAGE);
+ packTLV(&packet, 0x000e, 0x0002, (LPBYTE)CLIENT_COUNTRY);
+ packTLV(&packet, 0x0094, 0x0001, &m_bConnectionLost); // CLIENT_RECONNECT flag
+ if (m_bSecureConnection)
+ packDWord(&packet, 0x008C0000); // empty TLV(0x8C): use SSL
+
+ sendServPacket(&packet);
+}
+
+void CIcqProto::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, LPGEN("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, LPGEN("Secure login failed.\nInvalid key length."));
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ unpackString(&buf, szKey, wKeyLen);
+
+ mir_md5_init(&state);
+ mir_md5_append(&state, info->szAuthKey, info->wAuthKeyLen);
+ mir_md5_finish(&state, digest);
+
+ mir_md5_init(&state);
+ mir_md5_append(&state, (LPBYTE)szKey, wKeyLen);
+ mir_md5_append(&state, digest, 16);
+ mir_md5_append(&state, (LPBYTE)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((char*)digest, 0x10, TRUE);
+}
diff --git a/protocols/IcqOscarJ/families.h b/protocols/IcqOscarJ/families.h
new file mode 100644
index 0000000000..efc1cabab7
--- /dev/null
+++ b/protocols/IcqOscarJ/families.h
@@ -0,0 +1,81 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/families.h $
+// Revision : $Revision: 11353 $
+// Last change on : $Date: 2010-03-10 02:21:03 +0200 (Ср, 10 мар 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Declaration for handlers of Channel 2 SNAC Families
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __FAMILIES_H
+#define __FAMILIES_H
+
+
+struct message_ack_params
+{
+ BYTE bType;
+ DWORD dwUin;
+ DWORD dwMsgID1;
+ DWORD dwMsgID2;
+ directconnect *pDC;
+ WORD wCookie;
+ int msgType;
+ BYTE bFlags;
+};
+
+#define MAT_SERVER_ADVANCED 0
+#define MAT_DIRECT 1
+
+
+/* handleMessageTypes(): mMsgFlags constants */
+#define MTF_DIRECT 1
+#define MTF_PLUGIN 2
+#define MTF_STATUS_EXTENDED 4
+
+
+struct UserInfoRecordItem
+{
+ WORD wTLV;
+ int dbType;
+ char *szDbSetting;
+};
+
+/*---------* Functions *---------------*/
+
+int getPluginTypeIdLen(int nTypeID);
+void packPluginTypeId(icq_packet *packet, int nTypeID);
+
+#define BUL_ALLCONTACTS 0
+#define BUL_VISIBLE 1
+#define BUL_INVISIBLE 2
+#define BUL_TEMPVISIBLE 4
+
+
+#endif /* __FAMILIES_H */
diff --git a/protocols/IcqOscarJ/globals.h b/protocols/IcqOscarJ/globals.h
new file mode 100644
index 0000000000..34a34cf2f9
--- /dev/null
+++ b/protocols/IcqOscarJ/globals.h
@@ -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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/globals.h $
+// Revision : $Revision: 11353 $
+// Last change on : $Date: 2010-03-10 02:21:03 +0200 (Ср, 10 мар 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Contains global types & variables declarations.
+//
+// -----------------------------------------------------------------------------
+
+
+#ifndef __GLOBALS_H
+#define __GLOBALS_H
+
+
+typedef char uid_str[MAX_PATH];
+
+// from init.cpp
+extern HINSTANCE hInst;
+extern DWORD MIRANDA_VERSION;
+
+extern IcqIconHandle hStaticIcons[];
+
+extern const int moodXStatus[];
+
+// from fam_04message.cpp
+struct icq_mode_messages
+{
+ char *szOnline;
+ char *szAway;
+ char *szNa;
+ char *szDnd;
+ char *szOccupied;
+ char *szFfc;
+};
+
+
+#endif /* __GLOBALS_H */
diff --git a/protocols/IcqOscarJ/guids.h b/protocols/IcqOscarJ/guids.h
new file mode 100644
index 0000000000..ae4d50552f
--- /dev/null
+++ b/protocols/IcqOscarJ/guids.h
@@ -0,0 +1,88 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/guids.h $
+// Revision : $Revision: 11353 $
+// Last change on : $Date: 2010-03-10 02:21:03 +0200 (Ср, 10 мар 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Contains helper functions to handle oscar message GUIDs.
+//
+// -----------------------------------------------------------------------------
+
+
+#ifndef __GUIDS_H
+#define __GUIDS_H
+
+
+typedef DWORD plugin_guid[4];
+
+// Message Capability GUIDs
+static const plugin_guid MCAP_SRV_RELAY_FMT = {MCAP_SRV_RELAY_FMT_s};
+static const plugin_guid MCAP_REVERSE_DC_REQ = {MCAP_REVERSE_DC_REQ_s};
+static const plugin_guid MCAP_FILE_TRANSFER = {MCAP_FILE_TRANSFER_s};
+static const plugin_guid MCAP_CONTACTS = {MCAP_CONTACTS_s};
+
+// Plugin GUIDs
+static const plugin_guid PSIG_MESSAGE = {PSIG_MESSAGE_s};
+static const plugin_guid PSIG_INFO_PLUGIN = {PSIG_INFO_PLUGIN_s};
+static const plugin_guid PSIG_STATUS_PLUGIN = {PSIG_STATUS_PLUGIN_s};
+
+// Plugin Message GUIDs
+static const plugin_guid PMSG_QUERY_INFO = {PMSG_QUERY_INFO_s};
+static const plugin_guid PMSG_QUERY_STATUS = {PMSG_QUERY_STATUS_s};
+
+// Message GUIDs
+static const plugin_guid MGTYPE_MESSAGE = {MGTYPE_MESSAGE_s};
+static const plugin_guid MGTYPE_STATUSMSGEXT = {MGTYPE_STATUSMSGEXT_s};
+static const plugin_guid MGTYPE_FILE = {MGTYPE_FILE_s};
+static const plugin_guid MGTYPE_WEBURL = {MGTYPE_WEBURL_s};
+static const plugin_guid MGTYPE_CONTACTS = {MGTYPE_CONTACTS_s};
+static const plugin_guid MGTYPE_GREETING_CARD = {MGTYPE_GREETING_CARD_s};
+static const plugin_guid MGTYPE_CHAT = {MGTYPE_CHAT_s};
+static const plugin_guid MGTYPE_SMS_MESSAGE = {MGTYPE_SMS_MESSAGE_s};
+static const plugin_guid MGTYPE_XTRAZ_SCRIPT = {MGTYPE_XTRAZ_SCRIPT_s};
+
+
+// make GUID checks easy
+static BOOL CompareGUIDs(DWORD q1,DWORD q2,DWORD q3,DWORD q4, const 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, const plugin_guid guid)
+{
+ packDWord(packet, guid[0]);
+ packDWord(packet, guid[1]);
+ packDWord(packet, guid[2]);
+ packDWord(packet, guid[3]);
+}
+
+
+#endif /* __GUIDS_H */
diff --git a/protocols/IcqOscarJ/i18n.cpp b/protocols/IcqOscarJ/i18n.cpp
new file mode 100644
index 0000000000..afd61d2583
--- /dev/null
+++ b/protocols/IcqOscarJ/i18n.cpp
@@ -0,0 +1,548 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/i18n.cpp $
+// Revision : $Revision: 11818 $
+// Last change on : $Date: 2010-05-23 15:37:24 +0300 (Вс, 23 май 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Contains helper functions to convert text messages between different
+// character sets.
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static BOOL bHasCP_UTF8 = FALSE;
+
+
+void InitI18N(void)
+{
+ CPINFO CPInfo;
+
+
+ bHasCP_UTF8 = GetCPInfo(CP_UTF8, &CPInfo);
+}
+
+
+
+// Returns true if the buffer only contains 7-bit characters.
+BOOL __stdcall IsUSASCII(const char *pBuffer, int nSize)
+{
+ for (int nIndex = 0; nIndex < nSize; nIndex++)
+ if (BYTE(pBuffer[nIndex]) > 0x7F)
+ return FALSE;
+
+ return TRUE;
+}
+
+// Returns true if the unicode buffer only contains 7-bit characters.
+BOOL __stdcall IsUnicodeAscii(const WCHAR *pBuffer, int nSize)
+{
+ for (int nIndex = 0; nIndex < nSize; nIndex++)
+ if (WORD(pBuffer[nIndex]) > 0x7F)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+// 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 __stdcall UTF8_IsValid(const char *pszInput)
+{
+ int nb;
+ if (!pszInput)
+ return 0;
+
+ for ( BYTE* c = ( BYTE*)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;
+ else nb = 0;
+
+ for (int i = 1; i<=nb; i++) // we this forward, do not cross end of string
+ if ((*(c + i) & 0xc0) != 0x80)
+ return 0;
+ }
+
+ return 1;
+}
+
+
+int __stdcall get_utf8_size(const WCHAR *unicode)
+{
+ int size = 0;
+ int index = 0;
+ /* calculate the size of the utf-8 string */
+ WCHAR c = unicode[index++];
+ while (c)
+ {
+ if (c < 0x0080)
+ size += 1;
+ else if (c < 0x0800)
+ size += 2;
+ else
+ size += 3;
+ c = unicode[index++];
+ }
+ return size;
+}
+
+
+// returns ansi string in all cases
+char* __stdcall 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((void**)&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.
+*/
+char* __stdcall make_utf8_string_static(const WCHAR *unicode, 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;
+}
+
+
+char* __stdcall make_utf8_string(const WCHAR *unicode)
+{
+ if (!unicode) return NULL;
+
+ /* first calculate the size of the target string */
+ size_t size = get_utf8_size(unicode);
+
+ char *out = (char*)SAFE_MALLOC(size + 1);
+ if (!out)
+ return NULL;
+
+ return make_utf8_string_static(unicode, out, size + 1);
+}
+
+
+WCHAR* __stdcall make_unicode_string_static(const char *utf8, WCHAR *unicode, size_t unicode_size)
+{
+ unsigned int out_index = 0;
+
+ if (utf8)
+ {
+ unsigned int index = 0;
+ unsigned char c = utf8[index++];
+
+ while (c)
+ {
+ if (out_index + 1 >= unicode_size) 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* __stdcall make_unicode_string(const char *utf8)
+{
+ int size = 0, index = 0;
+
+ if (!utf8) return NULL;
+
+ /* first calculate the size of the target string */
+ unsigned char 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++];
+ }
+
+ WCHAR *out = (WCHAR*)SAFE_MALLOC((size + 1) * sizeof(WCHAR));
+ if (!out)
+ return NULL;
+ else
+ return make_unicode_string_static(utf8, out, size + 1);
+}
+
+
+int __stdcall utf8_encode(const char *from, char **to)
+{
+ int wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, strlennull(from), NULL, 0);
+
+ if (wchars == 0)
+ {
+#ifdef _DEBUG
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+#endif
+ return -1;
+ }
+
+ WCHAR *unicode = (WCHAR*)_alloca((wchars + 1) * sizeof(WCHAR));
+ ZeroMemory(unicode, (wchars + 1) * sizeof(WCHAR));
+
+ int err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, strlennull(from), unicode, wchars);
+ if (err != wchars)
+ {
+#ifdef _DEBUG
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+#endif
+ 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* __stdcall ansi_to_utf8(const char *ansi)
+{
+ char *szUtf = NULL;
+
+ if (strlennull(ansi))
+ {
+ utf8_encode(ansi, &szUtf);
+ return szUtf;
+ }
+
+ return null_strdup("");
+}
+
+
+char* __stdcall ansi_to_utf8_codepage(const char *ansi, WORD wCp)
+{
+ int wchars = strlennull(ansi);
+ WCHAR *unicode = (WCHAR*)_alloca((wchars + 1) * sizeof(WCHAR));
+ ZeroMemory(unicode, (wchars + 1) * sizeof(WCHAR));
+
+ MultiByteToWideChar(wCp, MB_PRECOMPOSED, ansi, wchars, unicode, wchars);
+
+ return make_utf8_string(unicode);
+}
+
+
+// Returns 0 on error, 1 on success
+int __stdcall 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)
+ {
+ int inlen = strlennull(from) + 1;
+ WCHAR *wszTemp = (WCHAR *)_alloca(inlen * sizeof(WCHAR));
+ ZeroMemory(wszTemp, inlen * sizeof(WCHAR));
+
+ // Convert the UTF-8 string to UCS
+ if (MultiByteToWideChar(CP_UTF8, 0, from, -1, wszTemp, inlen))
+ {
+ // Convert the UCS string to local ANSI codepage
+ *to = (char*)SAFE_MALLOC(inlen);
+ if (WideCharToMultiByte(wCp, 0, wszTemp, -1, *to, inlen, NULL, NULL))
+ {
+ nResult = 1;
+ }
+ else
+ {
+ SAFE_FREE(to);
+ }
+ }
+ }
+ else
+ {
+ int chars = strlennull(from) + 1;
+ WCHAR *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)
+ {
+#ifdef _DEBUG
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+#endif
+ return 0;
+ }
+
+ *to = (char*)SAFE_MALLOC((chars + 1)*sizeof(char));
+ if (*to == NULL)
+ {
+#ifdef _DEBUG
+ fprintf(stderr, "Out of memory processing string to local charset\n");
+#endif
+ return 0;
+ }
+
+ int err = WideCharToMultiByte(wCp, WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL);
+ if (err != chars)
+ {
+#ifdef _DEBUG
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+#endif
+ SAFE_FREE(to);
+ return 0;
+ }
+
+ nResult = 1;
+ }
+
+ return nResult;
+}
+
+
+// Standard version with current codepage
+int __stdcall utf8_decode(const char *from, char **to)
+{
+ return utf8_decode_codepage(from, to, CP_ACP);
+}
+
+
+// Returns 0 on error, 1 on success
+int __stdcall 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;
+
+ // Clear target
+ ZeroMemory(to, to_size);
+
+ // Use the native conversion routines when available
+ if (bHasCP_UTF8)
+ {
+ int inlen = strlennull(from) + 1;
+ WCHAR *wszTemp = (WCHAR*)_alloca(inlen * sizeof(WCHAR));
+ ZeroMemory(wszTemp, inlen * sizeof(WCHAR));
+
+ // Convert the UTF-8 string to UCS
+ if (MultiByteToWideChar(CP_UTF8, 0, from, -1, wszTemp, inlen))
+ {
+ // Convert the UCS string to local ANSI codepage
+ if (WideCharToMultiByte(CP_ACP, 0, wszTemp, -1, to, to_size, NULL, NULL))
+ {
+ nResult = 1;
+ }
+ }
+ }
+ else
+ {
+ size_t 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;
+}
+
+
+WCHAR* __stdcall ansi_to_unicode(const char *ansi)
+{
+ int wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ansi, strlennull(ansi), NULL, 0);
+
+ if (wchars == 0)
+ {
+#ifdef _DEBUG
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+#endif
+ return NULL;
+ }
+
+ WCHAR *unicode = (WCHAR*)SAFE_MALLOC((wchars + 1) * sizeof(WCHAR));
+
+ int err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ansi, strlennull(ansi), unicode, wchars);
+ if (err != wchars)
+ {
+#ifdef _DEBUG
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+#endif
+ SAFE_FREE(&unicode);
+ return NULL;
+ }
+ return unicode;
+}
+
+
+char* __stdcall unicode_to_ansi_static(const WCHAR *unicode, char *ansi, int ansi_size)
+{
+ ZeroMemory(ansi, ansi_size);
+
+ if (WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, strlennull(unicode), ansi, ansi_size, NULL, NULL) > 1)
+ return ansi;
+
+ return NULL;
+}
+
+
+char* __stdcall unicode_to_ansi(const WCHAR *unicode)
+{
+ int chars = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, strlennull(unicode), NULL, 0, NULL, NULL);
+
+ if (chars == 0)
+ {
+#ifdef _DEBUG
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+#endif
+ return NULL;
+ }
+
+ char* ansi = (char*)SAFE_MALLOC((chars + 1)*sizeof(char));
+ if (ansi == NULL)
+ {
+#ifdef _DEBUG
+ fprintf(stderr, "Out of memory processing string to local charset\n");
+#endif
+ return NULL;
+ }
+
+ int err = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, strlennull(unicode), ansi, chars, NULL, NULL);
+ if (err != chars)
+ {
+#ifdef _DEBUG
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+#endif
+ return NULL;
+ }
+
+ return ansi;
+}
diff --git a/protocols/IcqOscarJ/i18n.h b/protocols/IcqOscarJ/i18n.h
new file mode 100644
index 0000000000..d1e1f48af9
--- /dev/null
+++ b/protocols/IcqOscarJ/i18n.h
@@ -0,0 +1,87 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/i18n.h $
+// Revision : $Revision: 11599 $
+// Last change on : $Date: 2010-04-19 09:00:16 +0300 (Пн, 19 апр 2010) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Helper functions to convert text messages between different character sets.
+//
+// -----------------------------------------------------------------------------
+
+
+#ifndef __I18N_H
+#define __I18N_H
+
+
+BOOL __stdcall IsUSASCII(const char *pBuffer, int nSize);
+BOOL __stdcall IsUnicodeAscii(const WCHAR *pBuffer, int nSize);
+int __stdcall UTF8_IsValid(const char *pszInput);
+
+int __stdcall get_utf8_size(const WCHAR *unicode);
+
+char* __stdcall detect_decode_utf8(const char *from);
+
+WCHAR* __stdcall make_unicode_string(const char *utf8);
+WCHAR* __stdcall make_unicode_string_static(const char *utf8, WCHAR *unicode, size_t unicode_size);
+
+char* __stdcall make_utf8_string(const WCHAR *unicode);
+char* __stdcall make_utf8_string_static(const WCHAR *unicode, char *utf8, size_t utf_size);
+
+char* __stdcall ansi_to_utf8(const char *ansi);
+char* __stdcall ansi_to_utf8_codepage(const char *ansi, WORD wCp);
+
+WCHAR* __stdcall ansi_to_unicode(const char *ansi);
+char* __stdcall unicode_to_ansi(const WCHAR *unicode);
+char* __stdcall unicode_to_ansi_static(const WCHAR *unicode, char *ansi, int ansi_size);
+
+int __stdcall utf8_encode(const char *from, char **to);
+int __stdcall utf8_decode(const char *from, char **to);
+int __stdcall utf8_decode_codepage(const char *from, char **to, WORD wCp);
+int __stdcall utf8_decode_static(const char *from, char *to, int to_size);
+
+#ifdef _UNICODE
+ #define tchar_to_utf8 make_utf8_string
+ #define utf8_to_tchar_static make_unicode_string_static
+ #define utf8_to_tchar make_unicode_string
+ #define ansi_to_tchar ansi_to_unicode
+ #define tchar_to_ansi unicode_to_ansi
+#else
+ __inline char* utf8_decode_func(const char *utf8) { char *ansi = NULL; utf8_decode(utf8, &ansi); return ansi; };
+
+ #define tchar_to_utf8 ansi_to_utf8
+ #define utf8_to_tchar_static utf8_decode_static
+ #define utf8_to_tchar utf8_decode_func
+ #define ansi_to_tchar null_strdup
+ #define tchar_to_ansi null_strdup
+#endif
+
+void InitI18N(void);
+
+
+#endif /* __I18N_H */
diff --git a/protocols/IcqOscarJ/iconlib.cpp b/protocols/IcqOscarJ/iconlib.cpp
new file mode 100644
index 0000000000..bc378bc094
--- /dev/null
+++ b/protocols/IcqOscarJ/iconlib.cpp
@@ -0,0 +1,101 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/iconlib.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Support for IcoLib plug-in
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_icolib.h"
+
+
+IcqIconHandle IconLibDefine(const char *desc, const char *section, const char *module, const char *ident, const TCHAR *def_file, int def_idx)
+{
+ SKINICONDESC sid = {0};
+
+ sid.cbSize = SKINICONDESC_SIZE;
+ sid.pwszSection = make_unicode_string(section);
+ sid.pwszDescription = make_unicode_string(desc);
+ sid.flags = SIDF_UNICODE | SIDF_PATH_TCHAR;
+
+ char szName[MAX_PATH + 128];
+ null_snprintf(szName, sizeof(szName), "%s_%s", module ? module : ICQ_PROTOCOL_NAME, ident);
+ sid.pszName = szName;
+ sid.ptszDefaultFile = (TCHAR*)def_file;
+ sid.iDefaultIndex = def_idx;
+
+ IcqIconHandle hIcon = (IcqIconHandle)SAFE_MALLOC(sizeof(IcqIconHandle_s));
+ hIcon->szName = null_strdup(sid.pszName);
+ hIcon->hIcoLib = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ SAFE_FREE(&sid.pwszSection);
+ SAFE_FREE(&sid.pwszDescription);
+
+ return hIcon;
+}
+
+
+void IconLibRemove(IcqIconHandle *phIcon)
+{
+ if (phIcon && *phIcon)
+ {
+ IcqIconHandle hIcon = *phIcon;
+
+ CallService(MS_SKIN2_REMOVEICON, 0, (LPARAM)hIcon->szName);
+ SAFE_FREE(&hIcon->szName);
+ SAFE_FREE((void**)phIcon);
+ }
+}
+
+
+HANDLE IcqIconHandle_s::Handle()
+{
+ if (this)
+ return hIcoLib;
+
+ return NULL;
+}
+
+
+HICON IcqIconHandle_s::GetIcon(bool big)
+{
+ if (this)
+ return (HICON)CallService(MS_SKIN2_GETICONBYHANDLE, big, (LPARAM)hIcoLib);
+
+ return NULL;
+}
+
+void IcqIconHandle_s::ReleaseIcon(bool big)
+{
+ CallService(big ? MS_SKIN2_RELEASEICONBIG : MS_SKIN2_RELEASEICON, 0, (LPARAM)szName);
+}
+
diff --git a/protocols/IcqOscarJ/iconlib.h b/protocols/IcqOscarJ/iconlib.h
new file mode 100644
index 0000000000..7cd72bb8cf
--- /dev/null
+++ b/protocols/IcqOscarJ/iconlib.h
@@ -0,0 +1,59 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/iconlib.h $
+// Revision : $Revision: 11719 $
+// Last change on : $Date: 2010-05-09 01:01:13 +0300 (Вс, 09 май 2010) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Headers for IconLib Plugin / module support
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICONLIB_H
+#define __ICONLIB_H
+
+
+struct IcqIconHandle_s
+{
+ char *szName;
+ HANDLE hIcoLib;
+
+ HANDLE Handle();
+ HICON GetIcon(bool big = false);
+ void ReleaseIcon(bool big = false);
+};
+
+typedef IcqIconHandle_s *IcqIconHandle;
+
+
+IcqIconHandle IconLibDefine(const char *desc, const char *section, const char *module, const char *ident, const TCHAR *def_file, int def_idx);
+void IconLibRemove(IcqIconHandle *phIcon);
+
+
+
+#endif /* __ICONLIB_H */
diff --git a/protocols/IcqOscarJ/icons_pack/ICONS.dep b/protocols/IcqOscarJ/icons_pack/ICONS.dep
new file mode 100644
index 0000000000..743fff533c
--- /dev/null
+++ b/protocols/IcqOscarJ/icons_pack/ICONS.dep
@@ -0,0 +1,36 @@
+# Microsoft Developer Studio Generated Dependency File, included by ICONS.mak
+
+.\ICONS.rc : \
+ "..\icos\xstatus01.ico"\
+ "..\icos\xstatus02.ico"\
+ "..\icos\xstatus03.ico"\
+ "..\icos\xstatus04.ico"\
+ "..\icos\xstatus05.ico"\
+ "..\icos\xstatus06.ico"\
+ "..\icos\xstatus07.ico"\
+ "..\icos\xstatus08.ico"\
+ "..\icos\xstatus09.ico"\
+ "..\icos\xstatus10.ico"\
+ "..\icos\xstatus11.ico"\
+ "..\icos\xstatus12.ico"\
+ "..\icos\xstatus13.ico"\
+ "..\icos\xstatus14.ico"\
+ "..\icos\xstatus15.ico"\
+ "..\icos\xstatus16.ico"\
+ "..\icos\xstatus17.ico"\
+ "..\icos\xstatus18.ico"\
+ "..\icos\xstatus19.ico"\
+ "..\icos\xstatus20.ico"\
+ "..\icos\xstatus21.ico"\
+ "..\icos\xstatus22.ico"\
+ "..\icos\xstatus23.ico"\
+ "..\icos\xstatus24.ico"\
+ "..\icos\xstatus25.ico"\
+ "..\icos\xstatus26.ico"\
+ "..\icos\xstatus27.ico"\
+ "..\icos\xstatus28.ico"\
+ "..\icos\xstatus29.ico"\
+ "..\icos\xstatus30.ico"\
+ "..\icos\xstatus31.ico"\
+ "..\icos\xstatus32.ico"\
+
diff --git a/protocols/IcqOscarJ/icons_pack/ICONS.dsp b/protocols/IcqOscarJ/icons_pack/ICONS.dsp
new file mode 100644
index 0000000000..285875934f
--- /dev/null
+++ b/protocols/IcqOscarJ/icons_pack/ICONS.dsp
@@ -0,0 +1,194 @@
+# Microsoft Developer Studio Project File - Name="ICONS" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=ICONS - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ICONS.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ICONS.mak" CFG="ICONS - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ICONS - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "ICONS_EXPORTS" /D "_MBCS" /Yu"stdafx.h" /c
+# ADD CPP /nologo /MT /W3 /GX /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "ICONS_EXPORTS" /D "_MBCS" /Yu"stdafx.h" /c
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /dll /debug /machine:I386
+# ADD LINK32 /nologo /dll /debug /machine:I386 /out:"..\..\..\bin\release\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\xstatus32.ico
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/protocols/IcqOscarJ/icons_pack/ICONS.dsw b/protocols/IcqOscarJ/icons_pack/ICONS.dsw
new file mode 100644
index 0000000000..17255a815d
--- /dev/null
+++ b/protocols/IcqOscarJ/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/protocols/IcqOscarJ/icons_pack/ICONS.mak b/protocols/IcqOscarJ/icons_pack/ICONS.mak
new file mode 100644
index 0000000000..5a3a8325f7
--- /dev/null
+++ b/protocols/IcqOscarJ/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
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\bin\release\Icons\xstatus_ICQ.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ICONS.res"
+ -@erase "$(OUTDIR)\xstatus_ICQ.exp"
+ -@erase "$(OUTDIR)\xstatus_ICQ.lib"
+ -@erase "$(OUTDIR)\xstatus_ICQ.pdb"
+ -@erase "..\..\..\bin\release\Icons\xstatus_ICQ.dll"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+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=midl.exe
+MTL_PROJ=/nologo /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\ICONS.res"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ICONS.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /dll /incremental:no /pdb:"$(OUTDIR)\xstatus_ICQ.pdb" /debug /machine:I386 /out:"..\..\..\bin\release\Icons\xstatus_ICQ.dll" /implib:"$(OUTDIR)\xstatus_ICQ.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)
+<<
+
+
+!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/protocols/IcqOscarJ/icons_pack/ICONS.rc b/protocols/IcqOscarJ/icons_pack/ICONS.rc
new file mode 100644
index 0000000000..b0c7ea1b05
--- /dev/null
+++ b/protocols/IcqOscarJ/icons_pack/ICONS.rc
@@ -0,0 +1,132 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "../resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_XSTATUS1 ICON DISCARDABLE "../icos/xstatus01.ico"
+IDI_XSTATUS2 ICON DISCARDABLE "../icos/xstatus02.ico"
+IDI_XSTATUS3 ICON DISCARDABLE "../icos/xstatus03.ico"
+IDI_XSTATUS4 ICON DISCARDABLE "../icos/xstatus04.ico"
+IDI_XSTATUS5 ICON DISCARDABLE "../icos/xstatus05.ico"
+IDI_XSTATUS6 ICON DISCARDABLE "../icos/xstatus06.ico"
+IDI_XSTATUS7 ICON DISCARDABLE "../icos/xstatus07.ico"
+IDI_XSTATUS8 ICON DISCARDABLE "../icos/xstatus08.ico"
+IDI_XSTATUS9 ICON DISCARDABLE "../icos/xstatus09.ico"
+IDI_XSTATUS10 ICON DISCARDABLE "../icos/xstatus10.ico"
+IDI_XSTATUS11 ICON DISCARDABLE "../icos/xstatus11.ico"
+IDI_XSTATUS12 ICON DISCARDABLE "../icos/xstatus12.ico"
+IDI_XSTATUS13 ICON DISCARDABLE "../icos/xstatus13.ico"
+IDI_XSTATUS14 ICON DISCARDABLE "../icos/xstatus14.ico"
+IDI_XSTATUS15 ICON DISCARDABLE "../icos/xstatus15.ico"
+IDI_XSTATUS16 ICON DISCARDABLE "../icos/xstatus16.ico"
+IDI_XSTATUS17 ICON DISCARDABLE "../icos/xstatus17.ico"
+IDI_XSTATUS18 ICON DISCARDABLE "../icos/xstatus18.ico"
+IDI_XSTATUS19 ICON DISCARDABLE "../icos/xstatus19.ico"
+IDI_XSTATUS20 ICON DISCARDABLE "../icos/xstatus20.ico"
+IDI_XSTATUS21 ICON DISCARDABLE "../icos/xstatus21.ico"
+IDI_XSTATUS22 ICON DISCARDABLE "../icos/xstatus22.ico"
+IDI_XSTATUS23 ICON DISCARDABLE "../icos/xstatus23.ico"
+IDI_XSTATUS24 ICON DISCARDABLE "../icos/xstatus24.ico"
+IDI_XSTATUS25 ICON DISCARDABLE "../icos/xstatus25.ico"
+IDI_XSTATUS26 ICON DISCARDABLE "../icos/xstatus26.ico"
+IDI_XSTATUS27 ICON DISCARDABLE "../icos/xstatus27.ico"
+IDI_XSTATUS28 ICON DISCARDABLE "../icos/xstatus28.ico"
+IDI_XSTATUS29 ICON DISCARDABLE "../icos/xstatus29.ico"
+IDI_XSTATUS30 ICON DISCARDABLE "../icos/xstatus30.ico"
+IDI_XSTATUS31 ICON DISCARDABLE "../icos/xstatus31.ico"
+IDI_XSTATUS32 ICON DISCARDABLE "../icos/xstatus32.ico"
+IDI_XSTATUS33 ICON DISCARDABLE "../icos/xstatus33.ico"
+IDI_XSTATUS34 ICON DISCARDABLE "../icos/xstatus34.ico"
+IDI_XSTATUS35 ICON DISCARDABLE "../icos/xstatus35.ico"
+IDI_XSTATUS36 ICON DISCARDABLE "../icos/xstatus36.ico"
+IDI_XSTATUS37 ICON DISCARDABLE "../icos/xstatus37.ico"
+IDI_XSTATUS38 ICON DISCARDABLE "../icos/xstatus38.ico"
+IDI_XSTATUS39 ICON DISCARDABLE "../icos/xstatus39.ico"
+IDI_XSTATUS40 ICON DISCARDABLE "../icos/xstatus40.ico"
+IDI_XSTATUS41 ICON DISCARDABLE "../icos/xstatus41.ico"
+IDI_XSTATUS42 ICON DISCARDABLE "../icos/xstatus42.ico"
+IDI_XSTATUS43 ICON DISCARDABLE "../icos/xstatus43.ico"
+IDI_XSTATUS44 ICON DISCARDABLE "../icos/xstatus44.ico"
+IDI_XSTATUS45 ICON DISCARDABLE "../icos/xstatus45.ico"
+IDI_XSTATUS46 ICON DISCARDABLE "../icos/xstatus46.ico"
+IDI_XSTATUS47 ICON DISCARDABLE "../icos/xstatus47.ico"
+IDI_XSTATUS48 ICON DISCARDABLE "../icos/xstatus48.ico"
+IDI_XSTATUS49 ICON DISCARDABLE "../icos/xstatus49.ico"
+IDI_XSTATUS50 ICON DISCARDABLE "../icos/xstatus50.ico"
+IDI_XSTATUS51 ICON DISCARDABLE "../icos/xstatus51.ico"
+IDI_XSTATUS52 ICON DISCARDABLE "../icos/xstatus52.ico"
+IDI_XSTATUS53 ICON DISCARDABLE "../icos/xstatus53.ico"
+IDI_XSTATUS54 ICON DISCARDABLE "../icos/xstatus54.ico"
+IDI_XSTATUS55 ICON DISCARDABLE "../icos/xstatus55.ico"
+IDI_XSTATUS56 ICON DISCARDABLE "../icos/xstatus56.ico"
+IDI_XSTATUS57 ICON DISCARDABLE "../icos/xstatus57.ico"
+IDI_XSTATUS58 ICON DISCARDABLE "../icos/xstatus58.ico"
+IDI_XSTATUS59 ICON DISCARDABLE "../icos/xstatus59.ico"
+IDI_XSTATUS60 ICON DISCARDABLE "../icos/xstatus60.ico"
+IDI_XSTATUS61 ICON DISCARDABLE "../icos/xstatus61.ico"
+IDI_XSTATUS62 ICON DISCARDABLE "../icos/xstatus62.ico"
+IDI_XSTATUS63 ICON DISCARDABLE "../icos/xstatus63.ico"
+IDI_XSTATUS64 ICON DISCARDABLE "../icos/xstatus64.ico"
+IDI_XSTATUS65 ICON DISCARDABLE "../icos/xstatus65.ico"
+IDI_XSTATUS66 ICON DISCARDABLE "../icos/xstatus66.ico"
+IDI_XSTATUS67 ICON DISCARDABLE "../icos/xstatus67.ico"
+IDI_XSTATUS68 ICON DISCARDABLE "../icos/xstatus68.ico"
+IDI_XSTATUS69 ICON DISCARDABLE "../icos/xstatus69.ico"
+IDI_XSTATUS70 ICON DISCARDABLE "../icos/xstatus70.ico"
+IDI_XSTATUS71 ICON DISCARDABLE "../icos/xstatus71.ico"
+IDI_XSTATUS72 ICON DISCARDABLE "../icos/xstatus72.ico"
+IDI_XSTATUS73 ICON DISCARDABLE "../icos/xstatus73.ico"
+IDI_XSTATUS74 ICON DISCARDABLE "../icos/xstatus74.ico"
+IDI_XSTATUS75 ICON DISCARDABLE "../icos/xstatus75.ico"
+IDI_XSTATUS76 ICON DISCARDABLE "../icos/xstatus76.ico"
+IDI_XSTATUS77 ICON DISCARDABLE "../icos/xstatus77.ico"
+IDI_XSTATUS78 ICON DISCARDABLE "../icos/xstatus78.ico"
+IDI_XSTATUS79 ICON DISCARDABLE "../icos/xstatus79.ico"
+IDI_XSTATUS80 ICON DISCARDABLE "../icos/xstatus80.ico"
+IDI_XSTATUS81 ICON DISCARDABLE "../icos/xstatus81.ico"
+IDI_XSTATUS82 ICON DISCARDABLE "../icos/xstatus82.ico"
+IDI_XSTATUS83 ICON DISCARDABLE "../icos/xstatus83.ico"
+IDI_XSTATUS84 ICON DISCARDABLE "../icos/xstatus84.ico"
+IDI_XSTATUS85 ICON DISCARDABLE "../icos/xstatus85.ico"
+IDI_XSTATUS86 ICON DISCARDABLE "../icos/xstatus86.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_IDENTIFY "# Custom Status Icons #"
+END
+
+
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
diff --git a/protocols/IcqOscarJ/icons_pack/ICONS.vcxproj b/protocols/IcqOscarJ/icons_pack/ICONS.vcxproj
new file mode 100644
index 0000000000..d12c0fabd2
--- /dev/null
+++ b/protocols/IcqOscarJ/icons_pack/ICONS.vcxproj
@@ -0,0 +1,317 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Release Unicode|Win32">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|x64">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <SccProjectName />
+ <SccLocalPath />
+ <ProjectName>xstatus_ICQ</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(SolutionDir)$(Configuration)\Icons\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(SolutionDir)$(Configuration)64\Icons\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
+ <OutDir>$(SolutionDir)$(Configuration)\Icons\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
+ <OutDir>$(SolutionDir)$(Configuration)64\Icons\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ICONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>.\Release\</AssemblerListingLocation>
+ <PrecompiledHeaderOutputFile>.\Release\ICONS.pch</PrecompiledHeaderOutputFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+ <ObjectFileName>.\Release\</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release\ICONS.tlb</TypeLibraryName>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release\ICONS.bsc</OutputFile>
+ </Bscmake>
+ <Link>
+ <LinkDLL>true</LinkDLL>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <AdditionalOptions> /ALIGN:4096 /ignore:4108</AdditionalOptions>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ICONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>.\Release\</AssemblerListingLocation>
+ <PrecompiledHeaderOutputFile>.\Release\ICONS.pch</PrecompiledHeaderOutputFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+ <ObjectFileName>.\Release\</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release\ICONS.tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release\ICONS.bsc</OutputFile>
+ </Bscmake>
+ <Link>
+ <LinkDLL>true</LinkDLL>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <AdditionalOptions> /ALIGN:4096 /ignore:4108</AdditionalOptions>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ICONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>.\Release\</AssemblerListingLocation>
+ <PrecompiledHeaderOutputFile>.\Release\ICONS.pch</PrecompiledHeaderOutputFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+ <ObjectFileName>.\Release\</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release\ICONS.tlb</TypeLibraryName>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release\ICONS.bsc</OutputFile>
+ </Bscmake>
+ <Link>
+ <LinkDLL>true</LinkDLL>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <AdditionalOptions> /ALIGN:4096 /ignore:4108</AdditionalOptions>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ICONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>.\Release\</AssemblerListingLocation>
+ <PrecompiledHeaderOutputFile>.\Release\ICONS.pch</PrecompiledHeaderOutputFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+ <ObjectFileName>.\Release\</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release\ICONS.tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release\ICONS.bsc</OutputFile>
+ </Bscmake>
+ <Link>
+ <LinkDLL>true</LinkDLL>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <AdditionalOptions> /ALIGN:4096 /ignore:4108</AdditionalOptions>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ResourceCompile Include="ICONS.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\icos\xstatus01.ico" />
+ <CustomBuild Include="..\icos\xstatus02.ico" />
+ <CustomBuild Include="..\icos\xstatus03.ico" />
+ <CustomBuild Include="..\icos\xstatus04.ico" />
+ <CustomBuild Include="..\icos\xstatus05.ico" />
+ <CustomBuild Include="..\icos\xstatus06.ico" />
+ <CustomBuild Include="..\icos\xstatus07.ico" />
+ <CustomBuild Include="..\icos\xstatus08.ico" />
+ <CustomBuild Include="..\icos\xstatus09.ico" />
+ <CustomBuild Include="..\icos\xstatus10.ico" />
+ <CustomBuild Include="..\icos\xstatus11.ico" />
+ <CustomBuild Include="..\icos\xstatus12.ico" />
+ <CustomBuild Include="..\icos\xstatus13.ico" />
+ <CustomBuild Include="..\icos\xstatus14.ico" />
+ <CustomBuild Include="..\icos\xstatus15.ico" />
+ <CustomBuild Include="..\icos\xstatus16.ico" />
+ <CustomBuild Include="..\icos\xstatus17.ico" />
+ <CustomBuild Include="..\icos\xstatus18.ico" />
+ <CustomBuild Include="..\icos\xstatus19.ico" />
+ <CustomBuild Include="..\icos\xstatus20.ico" />
+ <CustomBuild Include="..\icos\xstatus21.ico" />
+ <CustomBuild Include="..\icos\xstatus22.ico" />
+ <CustomBuild Include="..\icos\xstatus23.ico" />
+ <CustomBuild Include="..\icos\xstatus24.ico" />
+ <CustomBuild Include="..\icos\xstatus25.ico" />
+ <CustomBuild Include="..\icos\xstatus26.ico" />
+ <CustomBuild Include="..\icos\xstatus27.ico" />
+ <CustomBuild Include="..\icos\xstatus28.ico" />
+ <CustomBuild Include="..\icos\xstatus29.ico" />
+ <CustomBuild Include="..\icos\xstatus30.ico" />
+ <CustomBuild Include="..\icos\xstatus31.ico" />
+ <CustomBuild Include="..\icos\xstatus32.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\icos\xstatus33.ico" />
+ <CustomBuild Include="..\icos\Xstatus34.ico" />
+ <CustomBuild Include="..\icos\Xstatus35.ico" />
+ <CustomBuild Include="..\icos\Xstatus36.ico" />
+ <CustomBuild Include="..\icos\xstatus37.ico" />
+ <CustomBuild Include="..\icos\Xstatus38.ico" />
+ <CustomBuild Include="..\icos\Xstatus39.ico" />
+ <CustomBuild Include="..\icos\Xstatus40.ico" />
+ <CustomBuild Include="..\icos\Xstatus41.ico" />
+ <CustomBuild Include="..\icos\Xstatus42.ico" />
+ <CustomBuild Include="..\icos\xstatus43.ico" />
+ <CustomBuild Include="..\icos\xstatus44.ico" />
+ <CustomBuild Include="..\icos\Xstatus45.ico" />
+ <CustomBuild Include="..\icos\Xstatus46.ico" />
+ <CustomBuild Include="..\icos\Xstatus47.ico" />
+ <CustomBuild Include="..\icos\Xstatus48.ico" />
+ <CustomBuild Include="..\icos\Xstatus49.ico" />
+ <CustomBuild Include="..\icos\Xstatus50.ico" />
+ <CustomBuild Include="..\icos\Xstatus51.ico" />
+ <CustomBuild Include="..\icos\Xstatus52.ico" />
+ <CustomBuild Include="..\icos\Xstatus53.ico" />
+ <CustomBuild Include="..\icos\Xstatus54.ico" />
+ <CustomBuild Include="..\icos\xstatus55.ico" />
+ <CustomBuild Include="..\icos\Xstatus56.ico" />
+ <CustomBuild Include="..\icos\Xstatus57.ico" />
+ <CustomBuild Include="..\icos\Xstatus58.ico" />
+ <CustomBuild Include="..\icos\Xstatus59.ico" />
+ <CustomBuild Include="..\icos\Xstatus60.ico" />
+ <CustomBuild Include="..\icos\Xstatus61.ico" />
+ <CustomBuild Include="..\icos\Xstatus62.ico" />
+ <CustomBuild Include="..\icos\Xstatus63.ico" />
+ <CustomBuild Include="..\icos\xstatus64.ico" />
+ <CustomBuild Include="..\icos\Xstatus65.ico" />
+ <CustomBuild Include="..\icos\Xstatus66.ico" />
+ <CustomBuild Include="..\icos\Xstatus67.ico" />
+ <CustomBuild Include="..\icos\Xstatus68.ico" />
+ <CustomBuild Include="..\icos\Xstatus69.ico" />
+ <CustomBuild Include="..\icos\Xstatus70.ico" />
+ <CustomBuild Include="..\icos\Xstatus71.ico" />
+ <CustomBuild Include="..\icos\Xstatus72.ico" />
+ <CustomBuild Include="..\icos\Xstatus73.ico" />
+ <CustomBuild Include="..\icos\Xstatus74.ico" />
+ <CustomBuild Include="..\icos\Xstatus75.ico" />
+ <CustomBuild Include="..\icos\Xstatus76.ico" />
+ <CustomBuild Include="..\icos\Xstatus77.ico" />
+ <CustomBuild Include="..\icos\Xstatus78.ico" />
+ <CustomBuild Include="..\icos\Xstatus79.ico" />
+ <CustomBuild Include="..\icos\xstatus80.ico" />
+ <CustomBuild Include="..\icos\Xstatus81.ico" />
+ <CustomBuild Include="..\icos\Xstatus82.ico" />
+ <CustomBuild Include="..\icos\Xstatus83.ico" />
+ <CustomBuild Include="..\icos\Xstatus84.ico" />
+ <CustomBuild Include="..\icos\xstatus85.ico" />
+ <CustomBuild Include="..\icos\Xstatus86.ico" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/IcqOscarJ/icos/Xstatus34.ico b/protocols/IcqOscarJ/icos/Xstatus34.ico
new file mode 100644
index 0000000000..38114d9acf
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus34.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus35.ico b/protocols/IcqOscarJ/icos/Xstatus35.ico
new file mode 100644
index 0000000000..c5c30aaeb7
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus35.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus36.ico b/protocols/IcqOscarJ/icos/Xstatus36.ico
new file mode 100644
index 0000000000..dee0c22ca5
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus36.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus38.ico b/protocols/IcqOscarJ/icos/Xstatus38.ico
new file mode 100644
index 0000000000..afadf91c75
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus38.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus39.ico b/protocols/IcqOscarJ/icos/Xstatus39.ico
new file mode 100644
index 0000000000..b54a71dfe4
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus39.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus40.ico b/protocols/IcqOscarJ/icos/Xstatus40.ico
new file mode 100644
index 0000000000..ea17ad64eb
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus40.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus41.ico b/protocols/IcqOscarJ/icos/Xstatus41.ico
new file mode 100644
index 0000000000..59782c42e0
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus41.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus42.ico b/protocols/IcqOscarJ/icos/Xstatus42.ico
new file mode 100644
index 0000000000..bb73d54be7
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus42.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus45.ico b/protocols/IcqOscarJ/icos/Xstatus45.ico
new file mode 100644
index 0000000000..dbbd46b51b
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus45.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus46.ico b/protocols/IcqOscarJ/icos/Xstatus46.ico
new file mode 100644
index 0000000000..377b5b7a1b
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus46.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus47.ico b/protocols/IcqOscarJ/icos/Xstatus47.ico
new file mode 100644
index 0000000000..f2333035af
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus47.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus48.ico b/protocols/IcqOscarJ/icos/Xstatus48.ico
new file mode 100644
index 0000000000..af9bc70b11
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus48.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus49.ico b/protocols/IcqOscarJ/icos/Xstatus49.ico
new file mode 100644
index 0000000000..274eb57cc2
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus49.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus50.ico b/protocols/IcqOscarJ/icos/Xstatus50.ico
new file mode 100644
index 0000000000..f86143e326
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus50.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus51.ico b/protocols/IcqOscarJ/icos/Xstatus51.ico
new file mode 100644
index 0000000000..a0cd9fb014
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus51.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus52.ico b/protocols/IcqOscarJ/icos/Xstatus52.ico
new file mode 100644
index 0000000000..47addb388a
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus52.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus53.ico b/protocols/IcqOscarJ/icos/Xstatus53.ico
new file mode 100644
index 0000000000..d3ef8d1154
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus53.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus54.ico b/protocols/IcqOscarJ/icos/Xstatus54.ico
new file mode 100644
index 0000000000..8cfb718724
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus54.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus56.ico b/protocols/IcqOscarJ/icos/Xstatus56.ico
new file mode 100644
index 0000000000..60dbf31dc6
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus56.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus57.ico b/protocols/IcqOscarJ/icos/Xstatus57.ico
new file mode 100644
index 0000000000..cf58a2c4f9
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus57.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus58.ico b/protocols/IcqOscarJ/icos/Xstatus58.ico
new file mode 100644
index 0000000000..e421d43285
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus58.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus59.ico b/protocols/IcqOscarJ/icos/Xstatus59.ico
new file mode 100644
index 0000000000..9ebab2cb61
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus59.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus60.ico b/protocols/IcqOscarJ/icos/Xstatus60.ico
new file mode 100644
index 0000000000..44c7c56542
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus60.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus61.ico b/protocols/IcqOscarJ/icos/Xstatus61.ico
new file mode 100644
index 0000000000..70751da56c
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus61.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus62.ico b/protocols/IcqOscarJ/icos/Xstatus62.ico
new file mode 100644
index 0000000000..1024cd9af3
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus62.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus63.ico b/protocols/IcqOscarJ/icos/Xstatus63.ico
new file mode 100644
index 0000000000..ae1e0c8c87
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus63.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus65.ico b/protocols/IcqOscarJ/icos/Xstatus65.ico
new file mode 100644
index 0000000000..784978cc7b
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus65.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus66.ico b/protocols/IcqOscarJ/icos/Xstatus66.ico
new file mode 100644
index 0000000000..46174f0280
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus66.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus67.ico b/protocols/IcqOscarJ/icos/Xstatus67.ico
new file mode 100644
index 0000000000..52cd285f23
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus67.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus68.ico b/protocols/IcqOscarJ/icos/Xstatus68.ico
new file mode 100644
index 0000000000..72e77bbe24
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus68.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus69.ico b/protocols/IcqOscarJ/icos/Xstatus69.ico
new file mode 100644
index 0000000000..f4c396f5e3
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus69.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus70.ico b/protocols/IcqOscarJ/icos/Xstatus70.ico
new file mode 100644
index 0000000000..9c422ad470
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus70.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus71.ico b/protocols/IcqOscarJ/icos/Xstatus71.ico
new file mode 100644
index 0000000000..4fc5b36117
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus71.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus72.ico b/protocols/IcqOscarJ/icos/Xstatus72.ico
new file mode 100644
index 0000000000..f759dca12d
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus72.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus73.ico b/protocols/IcqOscarJ/icos/Xstatus73.ico
new file mode 100644
index 0000000000..3a6edc17ce
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus73.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus74.ico b/protocols/IcqOscarJ/icos/Xstatus74.ico
new file mode 100644
index 0000000000..52683e7266
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus74.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus75.ico b/protocols/IcqOscarJ/icos/Xstatus75.ico
new file mode 100644
index 0000000000..2ff37ebed6
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus75.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus76.ico b/protocols/IcqOscarJ/icos/Xstatus76.ico
new file mode 100644
index 0000000000..b4b1304d0a
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus76.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus77.ico b/protocols/IcqOscarJ/icos/Xstatus77.ico
new file mode 100644
index 0000000000..4394522002
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus77.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus78.ico b/protocols/IcqOscarJ/icos/Xstatus78.ico
new file mode 100644
index 0000000000..e7681eaaa1
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus78.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus79.ico b/protocols/IcqOscarJ/icos/Xstatus79.ico
new file mode 100644
index 0000000000..22b8bde3f3
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus79.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus81.ico b/protocols/IcqOscarJ/icos/Xstatus81.ico
new file mode 100644
index 0000000000..658c06df23
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus81.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus82.ico b/protocols/IcqOscarJ/icos/Xstatus82.ico
new file mode 100644
index 0000000000..5a02cd4b0e
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus82.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus83.ico b/protocols/IcqOscarJ/icos/Xstatus83.ico
new file mode 100644
index 0000000000..df1b96b669
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus83.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus84.ico b/protocols/IcqOscarJ/icos/Xstatus84.ico
new file mode 100644
index 0000000000..59461759dc
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus84.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/Xstatus86.ico b/protocols/IcqOscarJ/icos/Xstatus86.ico
new file mode 100644
index 0000000000..6a1c484040
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/Xstatus86.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/auth_ask.ico b/protocols/IcqOscarJ/icos/auth_ask.ico
new file mode 100644
index 0000000000..1db6f7f23e
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/auth_ask.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/auth_grant.ico b/protocols/IcqOscarJ/icos/auth_grant.ico
new file mode 100644
index 0000000000..44d5b29a31
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/auth_grant.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/auth_revoke.ico b/protocols/IcqOscarJ/icos/auth_revoke.ico
new file mode 100644
index 0000000000..e483681727
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/auth_revoke.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/icq.ico b/protocols/IcqOscarJ/icos/icq.ico
new file mode 100644
index 0000000000..98a99aca1c
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/icq.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/srvlist_add.ico b/protocols/IcqOscarJ/icos/srvlist_add.ico
new file mode 100644
index 0000000000..18b12f8c38
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/srvlist_add.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus01.ico b/protocols/IcqOscarJ/icos/xstatus01.ico
new file mode 100644
index 0000000000..98e1a70a8c
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus01.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus02.ico b/protocols/IcqOscarJ/icos/xstatus02.ico
new file mode 100644
index 0000000000..6153e0d4ab
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus02.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus03.ico b/protocols/IcqOscarJ/icos/xstatus03.ico
new file mode 100644
index 0000000000..70796a2128
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus03.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus04.ico b/protocols/IcqOscarJ/icos/xstatus04.ico
new file mode 100644
index 0000000000..0c86d1a6b3
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus04.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus05.ico b/protocols/IcqOscarJ/icos/xstatus05.ico
new file mode 100644
index 0000000000..a7f0bfc99e
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus05.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus06.ico b/protocols/IcqOscarJ/icos/xstatus06.ico
new file mode 100644
index 0000000000..7f565d4ac1
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus06.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus07.ico b/protocols/IcqOscarJ/icos/xstatus07.ico
new file mode 100644
index 0000000000..46c7087662
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus07.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus08.ico b/protocols/IcqOscarJ/icos/xstatus08.ico
new file mode 100644
index 0000000000..63c385f9da
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus08.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus09.ico b/protocols/IcqOscarJ/icos/xstatus09.ico
new file mode 100644
index 0000000000..d7fdbd4bd5
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus09.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus10.ico b/protocols/IcqOscarJ/icos/xstatus10.ico
new file mode 100644
index 0000000000..baf014ec1c
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus10.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus11.ico b/protocols/IcqOscarJ/icos/xstatus11.ico
new file mode 100644
index 0000000000..2007ba936a
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus11.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus12.ico b/protocols/IcqOscarJ/icos/xstatus12.ico
new file mode 100644
index 0000000000..b0daef70f4
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus12.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus13.ico b/protocols/IcqOscarJ/icos/xstatus13.ico
new file mode 100644
index 0000000000..b0ae976442
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus13.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus14.ico b/protocols/IcqOscarJ/icos/xstatus14.ico
new file mode 100644
index 0000000000..17cfd90007
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus14.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus15.ico b/protocols/IcqOscarJ/icos/xstatus15.ico
new file mode 100644
index 0000000000..702ba16f2d
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus15.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus16.ico b/protocols/IcqOscarJ/icos/xstatus16.ico
new file mode 100644
index 0000000000..853dc12fd2
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus16.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus17.ico b/protocols/IcqOscarJ/icos/xstatus17.ico
new file mode 100644
index 0000000000..dd891cf169
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus17.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus18.ico b/protocols/IcqOscarJ/icos/xstatus18.ico
new file mode 100644
index 0000000000..a95d361dcd
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus18.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus19.ico b/protocols/IcqOscarJ/icos/xstatus19.ico
new file mode 100644
index 0000000000..8eb3821554
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus19.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus20.ico b/protocols/IcqOscarJ/icos/xstatus20.ico
new file mode 100644
index 0000000000..0d90d8ba1c
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus20.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus21.ico b/protocols/IcqOscarJ/icos/xstatus21.ico
new file mode 100644
index 0000000000..fa21d3a4e3
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus21.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus22.ico b/protocols/IcqOscarJ/icos/xstatus22.ico
new file mode 100644
index 0000000000..ad8faded21
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus22.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus23.ico b/protocols/IcqOscarJ/icos/xstatus23.ico
new file mode 100644
index 0000000000..f6b92255b6
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus23.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus24.ico b/protocols/IcqOscarJ/icos/xstatus24.ico
new file mode 100644
index 0000000000..3ad736d73b
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus24.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus25.ico b/protocols/IcqOscarJ/icos/xstatus25.ico
new file mode 100644
index 0000000000..1c0214cd1a
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus25.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus26.ico b/protocols/IcqOscarJ/icos/xstatus26.ico
new file mode 100644
index 0000000000..b085157f52
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus26.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus27.ico b/protocols/IcqOscarJ/icos/xstatus27.ico
new file mode 100644
index 0000000000..c3fb1e6678
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus27.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus28.ico b/protocols/IcqOscarJ/icos/xstatus28.ico
new file mode 100644
index 0000000000..e3cc32037e
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus28.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus29.ico b/protocols/IcqOscarJ/icos/xstatus29.ico
new file mode 100644
index 0000000000..3217396cbe
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus29.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus30.ico b/protocols/IcqOscarJ/icos/xstatus30.ico
new file mode 100644
index 0000000000..db97d2d4ea
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus30.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus31.ico b/protocols/IcqOscarJ/icos/xstatus31.ico
new file mode 100644
index 0000000000..1176383b5b
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus31.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus32.ico b/protocols/IcqOscarJ/icos/xstatus32.ico
new file mode 100644
index 0000000000..c68ca5bd2a
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus32.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus33.ico b/protocols/IcqOscarJ/icos/xstatus33.ico
new file mode 100644
index 0000000000..ed8632d5eb
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus33.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus37.ico b/protocols/IcqOscarJ/icos/xstatus37.ico
new file mode 100644
index 0000000000..4bb33ec9ac
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus37.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus43.ico b/protocols/IcqOscarJ/icos/xstatus43.ico
new file mode 100644
index 0000000000..6f49a31dc4
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus43.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus44.ico b/protocols/IcqOscarJ/icos/xstatus44.ico
new file mode 100644
index 0000000000..4644afa89f
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus44.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus55.ico b/protocols/IcqOscarJ/icos/xstatus55.ico
new file mode 100644
index 0000000000..7ad6286985
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus55.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus64.ico b/protocols/IcqOscarJ/icos/xstatus64.ico
new file mode 100644
index 0000000000..1144ba9b49
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus64.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus80.ico b/protocols/IcqOscarJ/icos/xstatus80.ico
new file mode 100644
index 0000000000..30f7dd2670
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus80.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icos/xstatus85.ico b/protocols/IcqOscarJ/icos/xstatus85.ico
new file mode 100644
index 0000000000..b9db7058ba
--- /dev/null
+++ b/protocols/IcqOscarJ/icos/xstatus85.ico
Binary files differ
diff --git a/protocols/IcqOscarJ/icq_advsearch.cpp b/protocols/IcqOscarJ/icq_advsearch.cpp
new file mode 100644
index 0000000000..bbddbcbb8e
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_advsearch.cpp
@@ -0,0 +1,192 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_advsearch.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+static void InitComboBox(HWND hwndCombo, const FieldNamesItem *names)
+{
+ int iItem;
+ int i;
+
+ iItem = ComboBoxAddStringUtf(hwndCombo, NULL, 0);
+ SendMessage(hwndCombo, CB_SETCURSEL, iItem, 0);
+
+ if (names){
+ for (i = 0; names[i].text; i++) {
+ iItem = ComboBoxAddStringUtf(hwndCombo, names[i].text, names[i].code);
+ }
+ }
+ else {
+ int ctryCount;
+ struct CountryListEntry *countries;
+ CallService( MS_UTILS_GETCOUNTRYLIST, ( WPARAM )&ctryCount, ( LPARAM )&countries );
+ for (i = 0; i < ctryCount; i++) {
+ if (countries[i].id != 0xFFFF && countries[i].id != 0)
+ iItem = ComboBoxAddStringUtf(hwndCombo, LPGEN(countries[i].szName), countries[i].id);
+ }
+ }
+}
+
+INT_PTR CALLBACK AdvancedSearchDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_GENDER), genderField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_AGERANGE), agesField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_MARITALSTATUS), maritalField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_WORKFIELD), occupationField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_ORGANISATION), affiliationField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_LANGUAGE), languageField);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_COUNTRY), countryField);
+ 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];
+
+ GetDlgItemTextA(hwndDlg, idControl, str, sizeof(str));
+
+ ppackLETLVLNTS(buf, buflen, str, wType, 0);
+}
+
+static void searchPackTLVWordLNTS(PBYTE *buf, int *buflen, HWND hwndDlg, UINT idControl, WORD w, WORD wType)
+{
+ char str[512];
+
+ GetDlgItemTextA(hwndDlg, idControl, str, sizeof(str));
+
+ ppackLETLVWordLNTS(buf, buflen, w, str, wType, 0);
+}
+
+static PBYTE createAdvancedSearchStructureTLV(HWND hwndDlg, int *length)
+{
+ PBYTE buf = NULL;
+ int buflen = 0;
+
+ 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);
+
+ ppackLETLVDWord(&buf, &buflen, (DWORD)getCurItemData(hwndDlg, IDC_AGERANGE), TLV_AGERANGE, 0);
+
+ BYTE b = (BYTE)getCurItemData(hwndDlg, IDC_GENDER);
+ switch (b) {
+ case 'F': b = 1; break;
+ case 'M': b = 2; break;
+ default: b = 0;
+ };
+ ppackLETLVByte(&buf, &buflen, b, TLV_GENDER, 0);
+ ppackLETLVByte(&buf, &buflen, (BYTE)getCurItemData(hwndDlg, IDC_MARITALSTATUS), TLV_MARITAL, 0);
+ ppackLETLVWord(&buf, &buflen, (WORD)getCurItemData(hwndDlg, IDC_LANGUAGE), TLV_LANGUAGE, 0);
+ ppackLETLVWord(&buf, &buflen, (WORD)getCurItemData(hwndDlg, IDC_COUNTRY), TLV_COUNTRY, 0);
+ ppackLETLVWord(&buf, &buflen, (WORD)getCurItemData(hwndDlg, IDC_WORKFIELD), TLV_OCUPATION, 0);
+
+ WORD 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);
+ if (w != 0xFFFF)
+ searchPackTLVWordLNTS(&buf, &buflen, hwndDlg, IDC_HOMEPAGEKEY, w, TLV_HOMEPAGE);
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_ONLINEONLY))
+ ppackLETLVByte(&buf, &buflen, 1, 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/protocols/IcqOscarJ/icq_advsearch.h b/protocols/IcqOscarJ/icq_advsearch.h
new file mode 100644
index 0000000000..0151450a41
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_advsearch.h
@@ -0,0 +1,39 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001,2002 Jon Keating, Richard Hughes
+// Copyright 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_advsearch.h,v $
+// Revision : $Revision: 9261 $
+// Last change on : $Date: 2009-03-28 22:16:39 +0300 (Сб, 28 мар 2009) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+
+
+INT_PTR CALLBACK AdvancedSearchDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam);
+PBYTE createAdvancedSearchStructure(HWND hwndDlg,int *length);
diff --git a/protocols/IcqOscarJ/icq_avatar.cpp b/protocols/IcqOscarJ/icq_avatar.cpp
new file mode 100644
index 0000000000..c49fefe699
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_avatar.cpp
@@ -0,0 +1,1823 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_avatar.cpp $
+// Revision : $Revision: 14141 $
+// Last change on : $Date: 2012-03-09 22:52:15 +0200 (Пт, 09 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Manages Avatar connection, provides internal service for handling avatars
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_folders.h"
+
+
+BYTE hashEmptyAvatar[9] = {0x00, 0x01, 0x00, 0x05, 0x02, 0x01, 0xD2, 0x04, 0x72};
+
+
+avatars_request::avatars_request(int type)
+{
+ this->type = type;
+}
+
+
+avatars_request::~avatars_request()
+{
+ if (this)
+ {
+ switch (type)
+ {
+ case ART_UPLOAD:
+ SAFE_FREE((void**)&pData);
+ break;
+ case ART_GET:
+ SAFE_FREE((void**)&hash);
+ SAFE_FREE(&szFile);
+ break;
+ case ART_BLOCK:
+ break;
+ }
+ }
+}
+
+
+avatars_request* CIcqProto::ReleaseAvatarRequestInQueue(avatars_request *request)
+{
+ avatars_request *pNext = request->pNext;
+
+ avatars_request **par = &m_avatarsQueue;
+ avatars_request *ar = m_avatarsQueue;
+
+ while (ar)
+ {
+ if (ar == request)
+ { // found it, remove
+ *par = ar->pNext;
+ break;
+ }
+ par = &ar->pNext;
+ ar = ar->pNext;
+ }
+
+ SAFE_DELETE(&request);
+
+ return pNext;
+}
+
+
+void CIcqProto::InitAvatars()
+{
+ if (!bAvatarsFolderInited)
+ { // do it only once
+ bAvatarsFolderInited = TRUE;
+
+ if (ServiceExists(MS_FOLDERS_REGISTER_PATH))
+ { // check if it does make sense
+ TCHAR tszPath[MAX_PATH * 2];
+ TCHAR *tmpPath = Utils_ReplaceVarsT(_T("%miranda_avatarcache%"));
+ null_snprintf(tszPath, MAX_PATH * 2, _T("%s\\") _T(TCHAR_STR_PARAM) _T("\\"), tmpPath, m_szModuleName);
+ mir_free(tmpPath);
+
+ hAvatarsFolder = FoldersRegisterCustomPathT(m_szModuleName, "Avatars Cache", tszPath);
+ }
+ }
+}
+
+
+TCHAR* CIcqProto::GetOwnAvatarFileName()
+{
+ DBVARIANT dbvFile = {DBVT_DELETED};
+
+ if (!getSettingStringT(NULL, "AvatarFile", &dbvFile))
+ {
+ TCHAR tmp[MAX_PATH * 2];
+ CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)dbvFile.ptszVal, (LPARAM)tmp);
+ ICQFreeVariant(&dbvFile);
+
+ return null_strdup(tmp);
+ }
+ return NULL;
+}
+
+
+void CIcqProto::GetFullAvatarFileName(int dwUin, const char *szUid, int dwFormat, TCHAR *pszDest, int cbLen)
+{
+ GetAvatarFileName(dwUin, szUid, pszDest, cbLen);
+ AddAvatarExt(dwFormat, pszDest);
+}
+
+
+void CIcqProto::GetAvatarFileName(int dwUin, const char *szUid, TCHAR *pszDest, int cbLen)
+{
+ TCHAR szPath[MAX_PATH * 2];
+ FOLDERSGETDATA fgd = {0};
+
+ InitAvatars();
+
+ fgd.cbSize = sizeof(FOLDERSGETDATA);
+ fgd.nMaxPathSize = MAX_PATH * 2;
+ fgd.szPathT = szPath;
+ if (CallService(MS_FOLDERS_GET_PATH, (WPARAM)hAvatarsFolder, (LPARAM)&fgd))
+ {
+ TCHAR *tmpPath = Utils_ReplaceVarsT(_T("%miranda_avatarcache%"));
+ null_snprintf(szPath, MAX_PATH * 2, _T("%s\\") _T(TCHAR_STR_PARAM) _T("\\"), tmpPath, m_szModuleName);
+ mir_free(tmpPath);
+ }
+ else
+ _tcscat(szPath, _T("\\"));
+
+ // fill the destination
+ lstrcpyn(pszDest, szPath, cbLen - 1);
+ int tPathLen = strlennull(pszDest);
+
+ // make sure the avatar cache directory exists
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)szPath);
+
+ if (dwUin != 0)
+ {
+ _ltot(dwUin, pszDest + tPathLen, 10);
+ }
+ else if (szUid)
+ {
+ TCHAR* p = mir_a2t(szUid);
+ _tcscpy(pszDest + tPathLen, p);
+ mir_free( p );
+ }
+ else
+ {
+ TCHAR szBuf[MAX_PATH];
+
+ if (CallService(MS_DB_GETPROFILENAMET, MAX_PATH, (LPARAM)szBuf))
+ _tcscpy(pszDest + tPathLen, _T("avatar"));
+ else
+ {
+ TCHAR *szLastDot = _tcsrchr(szBuf, '.');
+ if (szLastDot) szLastDot[0] = '\0';
+
+ _tcscpy(pszDest + tPathLen, szBuf);
+ _tcscat(pszDest + tPathLen, _T("_avt"));
+ }
+ }
+}
+
+
+void AddAvatarExt(int dwFormat, TCHAR *pszDest)
+{
+ if (dwFormat == PA_FORMAT_JPEG)
+ _tcscat(pszDest, _T(".jpg"));
+ else if (dwFormat == PA_FORMAT_GIF)
+ _tcscat(pszDest, _T(".gif"));
+ else if (dwFormat == PA_FORMAT_PNG)
+ _tcscat(pszDest, _T(".png"));
+ else if (dwFormat == PA_FORMAT_BMP)
+ _tcscat(pszDest, _T(".bmp"));
+ else if (dwFormat == PA_FORMAT_XML)
+ _tcscat(pszDest, _T(".xml"));
+ else if (dwFormat == PA_FORMAT_SWF)
+ _tcscat(pszDest, _T(".swf"));
+ else
+ _tcscat(pszDest, _T(".dat"));
+}
+
+
+int DetectAvatarFormatBuffer(const 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(const TCHAR *tszFile)
+{
+ int src = _topen(tszFile, _O_BINARY | _O_RDONLY, 0);
+ if (src == -1)
+ return PA_FORMAT_UNKNOWN;
+
+ char pBuf[32];
+ _read(src, pBuf, 32);
+ _close(src);
+
+ return DetectAvatarFormatBuffer(pBuf);
+}
+
+
+#define MD5_BLOCK_SIZE 1024*1024 /* use 1MB blocks */
+
+BYTE* calcMD5HashOfFile(const TCHAR *tszFile)
+{
+ BYTE *res = NULL;
+
+ HANDLE hFile = NULL, hMap = NULL;
+
+ if ((hFile = CreateFile(tszFile, 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 = (BYTE*)SAFE_MALLOC(16 * sizeof(mir_md5_byte_t));
+ 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)
+ {
+ BYTE *ppMap = NULL;
+ 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 * sizeof(mir_md5_byte_t));
+ }
+ }
+
+ if (hMap != NULL) CloseHandle(hMap);
+ if (hFile != NULL) CloseHandle(hFile);
+ }
+
+ return res;
+}
+
+
+int CIcqProto::IsAvatarChanged(HANDLE hContact, const BYTE *pHash, int nHashLen)
+{
+ DBVARIANT dbvSaved = {0};
+
+ if (!getSetting(hContact, "AvatarSaved", &dbvSaved))
+ {
+ if ((dbvSaved.cpbVal != nHashLen) || memcmp(dbvSaved.pbVal, pHash, nHashLen))
+ { // the hashes are 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 CIcqProto::StartAvatarThread(HANDLE hConn, char *cookie, WORD cookieLen) // called from event
+{
+ if (!hConn)
+ {
+ icq_lock l(m_avatarsMutex); // place avatars lock
+
+ if (m_avatarsConnection && m_avatarsConnection->isPending())
+ {
+ NetLog_Server("Avatar, Multiple start thread attempt, ignored.");
+ SAFE_FREE((void**)&cookie);
+ return;
+ }
+ NetLog_Server("Avatars: Connection failed");
+
+ m_avatarsConnectionPending = FALSE;
+
+ { // check if any upload request are waiting in the queue
+ avatars_request *ar = m_avatarsQueue;
+ int bYet = 0;
+
+ while (ar)
+ {
+ if (ar->type == ART_UPLOAD)
+ { // we found it, return error
+ if (!bYet)
+ {
+ icq_LogMessage(LOG_WARNING, LPGEN("Error uploading avatar to server, server temporarily unavailable."));
+ bYet = 1;
+ }
+ // remove upload request from queue
+ ar = ReleaseAvatarRequestInQueue(ar);
+ continue;
+ }
+ ar = ar->pNext;
+ }
+ }
+ SAFE_FREE((void**)&cookie);
+
+ return;
+ }
+
+ icq_lock l(m_avatarsMutex);
+
+ if (m_avatarsConnection && m_avatarsConnection->isPending())
+ {
+ NetLog_Server("Avatar, Multiple start thread attempt, ignored.");
+
+ NetLib_CloseConnection(&hConn, FALSE);
+
+ SAFE_FREE((void**)&cookie);
+
+ return;
+ }
+ else if (m_avatarsConnection)
+ m_avatarsConnection->closeConnection();
+
+ m_avatarsConnection = new avatars_server_connection(this, hConn, cookie, cookieLen); // the old connection should not be used anymore
+
+ // connection object created, remove the connection request pending flag
+ m_avatarsConnectionPending = FALSE;
+}
+
+
+void CIcqProto::StopAvatarThread()
+{
+ icq_lock l(m_avatarsMutex); // the connection is about to close
+
+ if (m_avatarsConnection)
+ {
+ m_avatarsConnection->shutdownConnection(); // make the thread stop
+ }
+
+ return;
+}
+
+
+#ifdef _DEBUG
+static void NetLog_Hash(CIcqProto *ppro, const char *pszIdent, const BYTE *pHash, int nHashLen)
+{
+ if (nHashLen == 0x14)
+ ppro->NetLog_Server("Avatars: %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)
+ ppro->NetLog_Server("Avatars: %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
+ ppro->NetLog_Server("Avatars: %s hash: Unknown hash format.", pszIdent);
+}
+#endif
+
+
+// handle Owner's avatar hash changes
+void CIcqProto::handleAvatarOwnerHash(WORD wItemID, BYTE bFlags, BYTE *pData, BYTE nDataLen)
+{
+ if ((nDataLen >= 0x14) && m_bAvatarsEnabled)
+ {
+ switch (bFlags)
+ {
+ case 1: // our avatar is on the server
+ {
+ setSettingBlob(NULL, "AvatarHash", pData, 0x14); /// TODO: properly handle multiple avatar items (more formats)
+
+ setUserInfo();
+ // here we need to find a file, check its hash, if invalid get avatar from server
+ TCHAR *file = GetOwnAvatarFileName();
+ if (!file)
+ { // we have no avatar file, download from server
+ TCHAR szFile[MAX_PATH * 2 + 4];
+#ifdef _DEBUG
+ NetLog_Server("We have no avatar, requesting from server.");
+#endif
+ GetAvatarFileName(0, NULL, szFile, MAX_PATH * 2);
+ GetAvatarData(NULL, m_dwLocalUIN, NULL, pData, 0x14, szFile);
+ }
+ else
+ { // we know avatar filename
+ BYTE *hash = calcMD5HashOfFile(file);
+
+ if (!hash)
+ { // hash could not be calculated - probably missing file, get avatar from server
+ TCHAR szFile[MAX_PATH * 2 + 4];
+#ifdef _DEBUG
+ NetLog_Server("We have no avatar, requesting from server.");
+#endif
+ GetAvatarFileName(0, NULL, szFile, MAX_PATH * 2);
+ GetAvatarData(NULL, m_dwLocalUIN, NULL, pData, 0x14, szFile);
+ } // check if we had set any avatar if yes set our, if not download from server
+ else if (memcmp(hash, pData + 4, 0x10))
+ { // we have different avatar, sync that
+ if (m_bSsiEnabled && getSettingByte(NULL, "ForceOurAvatar", 1))
+ { // we want our avatar, update hash
+ DWORD dwPaFormat = DetectAvatarFormat(file);
+ BYTE *pHash = (BYTE*)_alloca(0x14);
+
+ NetLog_Server("Our avatar is different, setting 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
+ TCHAR tszFile[MAX_PATH * 2 + 4];
+#ifdef _DEBUG
+ NetLog_Server("We have different avatar, requesting new from server.");
+#endif
+ GetAvatarFileName(0, NULL, tszFile, MAX_PATH * 2);
+ GetAvatarData(NULL, m_dwLocalUIN, NULL, pData, 0x14, tszFile);
+ }
+ }
+ SAFE_FREE((void**)&hash);
+ SAFE_FREE(&file);
+ }
+ break;
+ }
+ case 0x41: // request to upload avatar data
+ case 0x81:
+ { // request to re-upload avatar data
+ if (!m_bSsiEnabled) break; // we could not change serv-list if it is disabled...
+
+ TCHAR *file = GetOwnAvatarFileName();
+ if (!file)
+ { // we have no file to upload, remove hash from server
+ NetLog_Server("We do not have avatar, removing hash.");
+ SetMyAvatar(0, 0);
+ break;
+ }
+ DWORD dwPaFormat = DetectAvatarFormat(file);
+ BYTE *hash = calcMD5HashOfFile(file);
+
+ if (!hash)
+ { // the hash could not be calculated, remove from server
+ NetLog_Server("We could not obtain hash, removing hash.");
+ SetMyAvatar(0, 0);
+ }
+ else if (!memcmp(hash, pData + 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((void**)&hash);
+ }
+ else
+ {
+ BYTE *pHash = (BYTE*)_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((void**)&hash);
+ }
+
+ SAFE_FREE(&file);
+ break;
+ }
+ default:
+ NetLog_Server("Received UNKNOWN Avatar Status.");
+ }
+ }
+}
+
+
+// handle Contact's avatar hash
+void CIcqProto::handleAvatarContactHash(DWORD dwUIN, char *szUID, HANDLE hContact, BYTE *pHash, int nHashLen, WORD wOldStatus)
+{
+ int bJob = FALSE;
+ BOOL avatarInfoPresent = FALSE;
+ 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 (!m_bAvatarsEnabled) 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 (itemLen && 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: Last update time of online message
+ // 000E: Status mood
+ if (itemType == AVATAR_HASH_MINI && itemLen == 0x05 && avatarType == -1)
+ { // mini avatar
+ pAvatarHash = pHash;
+ cbAvatarHash = itemLen + 4;
+ avatarType = itemType;
+ }
+ else if (itemType == AVATAR_HASH_STATIC && (itemLen == 0x05 || itemLen == 0x10) && (avatarType == -1 || avatarType == AVATAR_HASH_MINI))
+ { // normal avatar
+ pAvatarHash = pHash;
+ cbAvatarHash = itemLen + 4;
+ avatarType = itemType;
+ }
+ else if (itemType == AVATAR_HASH_FLASH && itemLen == 0x10 && (avatarType == -1 || avatarType == AVATAR_HASH_MINI || avatarType == AVATAR_HASH_STATIC))
+ { // 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;
+ }
+ }
+ else if ((itemLen == 0) && (itemType == AVATAR_HASH_MINI || itemType == AVATAR_HASH_STATIC || itemType == AVATAR_HASH_FLASH || itemType == AVATAR_HASH_PHOTO))
+ { // empty item - indicating that avatar of that type was removed
+ avatarInfoPresent = TRUE;
+ }
+
+ pHash += itemLen + 4;
+ nHashLen -= itemLen + 4;
+ }
+
+ if (avatarType != -1)
+ { // check settings, should we request avatar immediatelly?
+ DBVARIANT dbv = {DBVT_DELETED};
+ TCHAR tszAvatar[MAX_PATH * 2 +4];
+ BYTE bAutoLoad = getSettingByte(NULL, "AvatarsAutoLoad", DEFAULT_LOAD_AVATARS);
+
+ if ((avatarType == AVATAR_HASH_STATIC || avatarType == AVATAR_HASH_MINI) && cbAvatarHash == 0x09 && !memcmp(pAvatarHash + 4, hashEmptyAvatar + 4, 0x05))
+ { // empty avatar - unlink image, clear hash
+ if (!getSetting(hContact, "AvatarHash", &dbv))
+ { // contact had avatar, clear hash, notify UI
+#ifdef _DEBUG
+ NetLog_Hash(this, "old", dbv.pbVal, dbv.cpbVal);
+#endif
+ ICQFreeVariant(&dbv);
+ NetLog_Server("%s has removed Avatar.", strUID(dwUIN, szUID));
+
+ deleteSetting(hContact, "AvatarHash");
+ BroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, (LPARAM)NULL);
+ }
+#ifdef _DEBUG
+ else
+ NetLog_Server("%s has empty Avatar.", strUID(dwUIN, szUID));
+#endif
+ return;
+ }
+
+ if (getSetting(hContact, "AvatarHash", &dbv))
+ { // we did not find old avatar hash, i.e. get new avatar
+ int avatarState = IsAvatarChanged(hContact, pAvatarHash, cbAvatarHash);
+
+ // check saved hash and file, if equal only store hash
+ if (!avatarState)
+ { // hashes are the same
+ int dwPaFormat = getSettingByte(hContact, "AvatarType", PA_FORMAT_UNKNOWN);
+
+ GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, tszAvatar, MAX_PATH * 2);
+ if (_taccess(tszAvatar, 0) == 0)
+ { // the file is there, link to contactphoto, save hash
+ NetLog_Server("%s has published Avatar. Image was found in the cache.", strUID(dwUIN, szUID));
+#ifdef _DEBUG
+ NetLog_Hash(this, "new", pAvatarHash, cbAvatarHash);
+#endif
+ setSettingBlob(hContact, "AvatarHash", pAvatarHash, cbAvatarHash);
+ BroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, (LPARAM)NULL);
+ }
+ else
+ { // the file was lost, request avatar again
+ NetLog_Server("%s has published Avatar.", strUID(dwUIN, szUID));
+#ifdef _DEBUG
+ NetLog_Hash(this, "new", pAvatarHash, cbAvatarHash);
+#endif
+ bJob = TRUE;
+ }
+ }
+ else
+ { // the hash is not the one we want, request avatar
+ NetLog_Server("%s has published a new Avatar.", strUID(dwUIN, szUID));
+#ifdef _DEBUG
+ NetLog_Hash(this, "new", pAvatarHash, cbAvatarHash);
+#endif
+ bJob = TRUE;
+ }
+ }
+ else
+ { // we found hash check if it changed or not
+ if ((dbv.cpbVal != cbAvatarHash) || memcmp(dbv.pbVal, pAvatarHash, cbAvatarHash))
+ { // the hash is different, request new avatar
+#ifdef _DEBUG
+ NetLog_Hash(this, "old", dbv.pbVal, dbv.cpbVal);
+#endif
+ NetLog_Server("%s has changed Avatar.", strUID(dwUIN, szUID));
+#ifdef _DEBUG
+ NetLog_Hash(this, "new", pAvatarHash, cbAvatarHash);
+#endif
+ bJob = TRUE;
+ }
+ else
+ { // the hash was not changed, check if we have the correct file
+ int avatarState = IsAvatarChanged(hContact, pAvatarHash, cbAvatarHash);
+
+ // we should have file, check if the file really exists
+ if (!avatarState)
+ {
+ int dwPaFormat = getSettingByte(hContact, "AvatarType", PA_FORMAT_UNKNOWN);
+ if (dwPaFormat == PA_FORMAT_UNKNOWN)
+ { // we do not know the format, get avatar again
+#ifdef _DEBUG
+ NetLog_Hash(this, "current", dbv.pbVal, dbv.cpbVal);
+#endif
+ NetLog_Server("%s has Avatar. Image is missing.", strUID(dwUIN, szUID));
+ bJob = 2;
+ }
+ else
+ {
+ GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, tszAvatar, MAX_PATH * 2);
+ if (_taccess(tszAvatar, 0) != 0)
+ { // the file was lost, get it again
+#ifdef _DEBUG
+ NetLog_Hash(this, "current", dbv.pbVal, dbv.cpbVal);
+#endif
+ NetLog_Server("%s has Avatar. Image is missing.", strUID(dwUIN, szUID));
+ bJob = 2;
+ }
+#ifdef _DEBUG
+ else
+ {
+ NetLog_Hash(this, "current", dbv.pbVal, dbv.cpbVal);
+
+ NetLog_Server("%s has Avatar. Image was found in the cache.", strUID(dwUIN, szUID));
+ }
+#endif
+ }
+ }
+ else
+ { // the hash is not the one we want, request avatar
+#ifdef _DEBUG
+ NetLog_Hash(this, "current", dbv.pbVal, dbv.cpbVal);
+#endif
+ NetLog_Server("%s has Avatar. Image was not retrieved yet.", strUID(dwUIN, szUID));
+ bJob = 2;
+ }
+ }
+ ICQFreeVariant(&dbv);
+ }
+
+ if (bJob)
+ {
+ if (bJob == TRUE)
+ { // Remove possible block - hash changed, try again.
+ icq_lock l(m_avatarsMutex);
+
+ avatars_request *ar = m_avatarsQueue;
+
+ while (ar)
+ {
+ if (ar->hContact == hContact && ar->type == ART_BLOCK)
+ { // found one, remove
+ ReleaseAvatarRequestInQueue(ar);
+ break;
+ }
+ ar = ar->pNext;
+ }
+ }
+
+ setSettingBlob(hContact, "AvatarHash", pAvatarHash, cbAvatarHash);
+
+ BroadcastAck(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, tszAvatar, MAX_PATH * 2);
+ GetAvatarData(hContact, dwUIN, szUID, pAvatarHash, cbAvatarHash, tszAvatar);
+ } // avatar request sent or added to queue
+ }
+ }
+ else if (avatarInfoPresent)
+ { // hash was not found, clear the hash
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ if (!getSetting(hContact, "AvatarHash", &dbv))
+ { // contact had avatar, clear hash, notify UI
+#ifdef _DEBUG
+ NetLog_Hash(this, "old", dbv.pbVal, dbv.cpbVal);
+#endif
+ ICQFreeVariant(&dbv);
+ NetLog_Server("%s has removed Avatar.", strUID(dwUIN, szUID));
+
+ deleteSetting(hContact, "AvatarHash");
+ BroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, (LPARAM)NULL);
+ }
+#ifdef _DEBUG
+ else
+ NetLog_Server("%s has no Avatar.", strUID(dwUIN, szUID));
+#endif
+ }
+}
+
+
+// request avatar data from server
+int CIcqProto::GetAvatarData(HANDLE hContact, DWORD dwUin, const char *szUid, const BYTE *hash, unsigned int hashlen, const TCHAR *file)
+{
+ uid_str szUidData;
+ char *pszUid = NULL;
+ if (!dwUin && szUid)
+ { // create a copy in local writable buffer
+ strcpy(szUidData, szUid);
+ pszUid = szUidData;
+ }
+
+ m_avatarsMutex->Enter();
+
+ if (m_avatarsConnection && m_avatarsConnection->isReady()) // check if we are ready
+ { // check if requests for this user are not blocked
+ DWORD dwNow = GetTickCount();
+ avatars_request *ar = m_avatarsQueue;
+
+ 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;
+ }
+ m_avatarsMutex->Leave();
+ NetLog_Server("Avatars: Requests for %s avatar are blocked.", strUID(dwUin, pszUid));
+ return 0;
+ }
+ ar = ar->pNext;
+ }
+
+ avatars_server_connection *pConnection = m_avatarsConnection;
+
+ pConnection->_Lock();
+ m_avatarsMutex->Leave();
+
+ DWORD dwCookie = pConnection->sendGetAvatarRequest(hContact, dwUin, pszUid, hash, hashlen, file);
+
+ m_avatarsMutex->Enter();
+ pConnection->_Release();
+
+ if (dwCookie)
+ { // return now if the request was sent successfully
+ m_avatarsMutex->Leave();
+ return dwCookie;
+ }
+ }
+ // we failed to send request, or avatar thread not ready
+
+ // check if any request for this user is not already in the queue
+ avatars_request *ar = m_avatarsQueue;
+
+ 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;
+ }
+ m_avatarsMutex->Leave();
+ NetLog_Server("Avatars: Ignoring duplicate get %s avatar request.", strUID(dwUin, pszUid));
+
+ // make sure avatar connection is in progress
+ requestAvatarConnection();
+ return 0;
+ }
+ ar = ar->pNext;
+ }
+ // add request to queue, processed after successful login
+ ar = new avatars_request(ART_GET); // get avatar
+ if (!ar)
+ { // out of memory, go away
+ m_avatarsMutex->Leave();
+ return 0;
+ }
+ ar->hContact = hContact;
+ ar->dwUin = dwUin;
+ if (!dwUin)
+ strcpy(ar->szUid, szUid);
+ ar->hash = (BYTE*)SAFE_MALLOC(hashlen);
+ if (!ar->hash)
+ { // alloc failed
+ m_avatarsMutex->Leave();
+ SAFE_DELETE(&ar);
+ return 0;
+ }
+ memcpy(ar->hash, hash, hashlen); // copy the data
+ ar->hashlen = hashlen;
+ ar->szFile = null_strdup(file); // duplicate the string
+ ar->pNext = m_avatarsQueue;
+ m_avatarsQueue = ar;
+ m_avatarsMutex->Leave();
+
+ NetLog_Server("Avatars: Request to get %s image added to queue.", strUID(dwUin, pszUid));
+
+ // make sure avatar connection is in progress
+ requestAvatarConnection();
+
+ return -1; // we added to queue
+}
+
+
+// upload avatar data to server
+int CIcqProto::SetAvatarData(HANDLE hContact, WORD wRef, const BYTE *data, unsigned int datalen)
+{
+ m_avatarsMutex->Enter();
+
+ if (m_avatarsConnection && m_avatarsConnection->isReady()) // check if we are ready
+ {
+ avatars_server_connection *pConnection = m_avatarsConnection;
+
+ pConnection->_Lock();
+ m_avatarsMutex->Leave();
+
+ DWORD dwCookie = pConnection->sendUploadAvatarRequest(hContact, wRef, data, datalen);
+
+ m_avatarsMutex->Enter();
+ pConnection->_Release();
+
+ if (dwCookie)
+ { // return now if the request was sent successfully
+ m_avatarsMutex->Leave();
+ return dwCookie;
+ }
+ }
+ // we failed to send request, or avatar thread not ready
+
+ // check if any request for this user is not already in the queue
+ avatars_request *ar = m_avatarsQueue;
+ int bYet = 0;
+
+ while (ar)
+ {
+ if (ar->hContact == hContact && ar->type == ART_UPLOAD)
+ { // we found it, return error
+ m_avatarsMutex->Leave();
+ NetLog_Server("Avatars: Ignoring duplicate upload avatar request.");
+
+ // make sure avatar connection is in progress
+ requestAvatarConnection();
+ return 0;
+ }
+ ar = ar->pNext;
+ }
+ // add request to queue, processed after successful login
+ ar = new avatars_request(ART_UPLOAD); // upload avatar
+ if (!ar)
+ { // out of memory, go away
+ m_avatarsMutex->Leave();
+ return 0;
+ }
+ ar->hContact = hContact;
+ ar->pData = (BYTE*)SAFE_MALLOC(datalen);
+ if (!ar->pData)
+ { // alloc failed
+ m_avatarsMutex->Leave();
+ SAFE_DELETE(&ar);
+ return 0;
+ }
+ memcpy(ar->pData, data, datalen); // copy the data
+ ar->cbData = datalen;
+ ar->wRef = wRef;
+ ar->pNext = m_avatarsQueue;
+ m_avatarsQueue = ar;
+ m_avatarsMutex->Leave();
+
+ NetLog_Server("Avatars: Request to upload image added to queue.");
+
+ // make sure avatar connection is in progress
+ requestAvatarConnection();
+
+ return -1; // we added to queue
+}
+
+
+void CIcqProto::requestAvatarConnection()
+{
+ m_avatarsMutex->Enter();
+ if (!m_avatarsConnectionPending && (!m_avatarsConnection || (!m_avatarsConnection->isPending() && !m_avatarsConnection->isReady())))
+ { // avatar connection is not pending, request new one
+ m_avatarsConnectionPending = TRUE;
+ m_avatarsMutex->Leave();
+
+ icq_requestnewfamily(ICQ_AVATAR_FAMILY, &CIcqProto::StartAvatarThread);
+ }
+ else
+ m_avatarsMutex->Leave();
+}
+
+
+void __cdecl CIcqProto::AvatarThread(avatars_server_connection *pInfo)
+{
+ NetLog_Server("%s thread started.", "Avatar");
+
+ // Execute connection handler
+ pInfo->connectionThread();
+
+ { // Remove connection reference
+ icq_lock l(m_avatarsMutex);
+ if (m_avatarsConnection == pInfo)
+ m_avatarsConnection = NULL;
+ }
+
+ { // Release connection handler
+ icq_lock l(m_avatarsMutex);
+ SAFE_DELETE(&pInfo);
+ }
+
+ NetLog_Server("%s thread ended.", "Avatar");
+}
+
+
+avatars_server_connection::avatars_server_connection(CIcqProto *ppro, HANDLE hConnection, char *pCookie, WORD wCookieLen):
+isLoggedIn(FALSE), stopThread(FALSE), isActive(FALSE)
+{
+ this->ppro = ppro;
+ this->hConnection = hConnection;
+ this->pCookie = pCookie;
+ this->wCookieLen = wCookieLen;
+
+ // Initialize packet sequence
+ localSeqMutex = new icq_critical_section();
+ wLocalSequence = generate_flap_sequence();
+
+ // Initialize rates
+ m_ratesMutex = new icq_critical_section();
+
+ // Create connection thread
+ ppro->ForkThread(( IcqThreadFunc )&CIcqProto::AvatarThread, this);
+}
+
+
+avatars_server_connection::~avatars_server_connection()
+{
+ SAFE_DELETE(&m_ratesMutex);
+ SAFE_DELETE(&localSeqMutex);
+}
+
+
+int avatars_server_connection::NetLog_Server(const char *fmt,...)
+{
+ va_list va;
+ char szText[1024 + 9];
+
+ strcpy(szText, "Avatars: ");
+ va_start(va, fmt);
+ mir_vsnprintf(szText + 9, sizeof(szText) - 9, fmt, va);
+ va_end(va);
+ return CallService(MS_NETLIB_LOG,(WPARAM)ppro->m_hServerNetlibUser,(LPARAM)szText);
+}
+
+
+void avatars_server_connection::closeConnection()
+{
+ stopThread = TRUE;
+
+ icq_lock l(localSeqMutex);
+ if (hConnection)
+ NetLib_SafeCloseHandle(&hConnection);
+}
+
+
+void avatars_server_connection::shutdownConnection()
+{
+ stopThread = TRUE;
+
+ icq_lock l(localSeqMutex);
+ if (hConnection)
+ Netlib_Shutdown(hConnection);
+}
+
+DWORD avatars_server_connection::sendGetAvatarRequest(HANDLE hContact, DWORD dwUin, char *szUid, const BYTE *hash, unsigned int hashlen, const TCHAR *file)
+{
+ int i;
+ DWORD dwNow = GetTickCount();
+
+ ppro->m_avatarsMutex->Enter();
+
+ for(i = 0; i < runCount;)
+ { // look for timeouted requests
+ if (runTime[i] < dwNow)
+ { // found outdated, remove
+ runContact[i] = runContact[runCount - 1];
+ runTime[i] = runTime[runCount - 1];
+ runCount--;
+ }
+ else
+ i++;
+ }
+
+ for(i = 0; i < runCount; i++)
+ {
+ if (runContact[i] == hContact)
+ {
+ ppro->m_avatarsMutex->Leave();
+ NetLog_Server("Ignoring duplicate get %s image request.", strUID(dwUin, szUid));
+
+ return -1; // Success: request ignored
+ }
+ }
+
+ if (runCount < 4)
+ { // 4 concurent requests at most
+ int bSendNow = TRUE;
+
+ { // rate management
+ icq_lock l(m_ratesMutex);
+ WORD wGroup = m_rates->getGroupFromSNAC(ICQ_AVATAR_FAMILY, ICQ_AVATAR_GET_REQUEST);
+
+ if (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(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
+ }
+ }
+
+ if (bSendNow)
+ {
+ runContact[runCount] = hContact;
+ runTime[runCount] = GetTickCount() + 30000; // 30sec to complete request
+ runCount++;
+
+ ppro->m_avatarsMutex->Leave();
+
+ int nUinLen = getUIDLen(dwUin, szUid);
+
+ cookie_avatar *ack = (cookie_avatar*)SAFE_MALLOC(sizeof(cookie_avatar));
+ if (!ack) return 0; // Failure: out of memory
+
+ ack->dwUin = 1; //dwUin; // I should be damned for this - only to identify get request
+ ack->hContact = hContact;
+ ack->hash = (BYTE*)SAFE_MALLOC(hashlen);
+ memcpy(ack->hash, hash, hashlen); // copy the data
+ ack->hashlen = hashlen;
+ ack->szFile = null_strdup(file); // duplicate the string
+
+ DWORD dwCookie = ppro->AllocateCookie(CKT_AVATAR, ICQ_AVATAR_GET_REQUEST, hContact, ack);
+ icq_packet packet;
+
+ serverPacketInit(&packet, (WORD)(12 + nUinLen + hashlen));
+ packFNACHeader(&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, (WORD)hashlen);
+
+ if (sendServerPacket(&packet))
+ {
+ NetLog_Server("Request to get %s image sent.", strUID(dwUin, szUid));
+
+ return dwCookie;
+ }
+ ppro->FreeCookie(dwCookie); // sending failed, free resources
+ SAFE_FREE(&ack->szFile);
+ SAFE_FREE((void**)&ack->hash);
+ SAFE_FREE((void**)&ack);
+ }
+ else
+ ppro->m_avatarsMutex->Leave();
+ }
+ else
+ ppro->m_avatarsMutex->Leave();
+
+ return 0; // Failure
+}
+
+
+DWORD avatars_server_connection::sendUploadAvatarRequest(HANDLE hContact, WORD wRef, const BYTE *data, unsigned int datalen)
+{
+ cookie_avatar *ack = (cookie_avatar*)SAFE_MALLOC(sizeof(cookie_avatar));
+ if (!ack) return 0; // Failure: out of memory
+
+ ack->hContact = hContact;
+
+ DWORD dwCookie = ppro->AllocateCookie(CKT_AVATAR, ICQ_AVATAR_UPLOAD_REQUEST, 0, ack);
+ icq_packet packet;
+
+ serverPacketInit(&packet, (WORD)(14 + datalen));
+ packFNACHeader(&packet, ICQ_AVATAR_FAMILY, ICQ_AVATAR_UPLOAD_REQUEST, 0, dwCookie);
+ packWord(&packet, wRef); // unknown, probably reference
+ packWord(&packet, (WORD)datalen);
+ packBuffer(&packet, data, (WORD)datalen);
+
+ if (sendServerPacket(&packet))
+ {
+ NetLog_Server("Upload image packet sent.");
+
+ return dwCookie;
+ }
+ ppro->ReleaseCookie(dwCookie); // failed to send, free resources
+
+ return 0;
+}
+
+
+void avatars_server_connection::checkRequestQueue()
+{
+#ifdef _DEBUG
+ NetLog_Server("Checking request queue...");
+#endif
+
+ ppro->m_avatarsMutex->Enter();
+
+ while (ppro->m_avatarsQueue && runCount < 3) // pick up an request and send it - happens immediatelly after login
+ { // do not fill queue to top, leave one place free
+ avatars_request *pRequest = ppro->m_avatarsQueue;
+
+ { // rate management
+ icq_lock l(m_ratesMutex);
+ WORD wGroup = m_rates->getGroupFromSNAC(ICQ_AVATAR_FAMILY, (WORD)(pRequest->type == ART_UPLOAD ? ICQ_AVATAR_GET_REQUEST : ICQ_AVATAR_UPLOAD_REQUEST));
+
+ if (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(wGroup, RML_ALERT))
+ { // we are over rate, leave queue and wait
+#ifdef _DEBUG
+ NetLog_Server("Rates: Leaving avatar queue processing");
+#endif
+ break;
+ }
+ }
+
+ if (pRequest->type == ART_BLOCK)
+ { // block contact processing
+ avatars_request **ppRequest = &ppro->m_avatarsQueue;
+
+ while (pRequest)
+ {
+ if (GetTickCount() > pRequest->timeOut)
+ { // expired contact block, remove
+ *ppRequest = pRequest->pNext;
+ SAFE_DELETE(&pRequest);
+ }
+ else // it is not time, move to next request
+ ppRequest = &pRequest->pNext;
+
+ pRequest = *ppRequest;
+ }
+ // end queue processing (only block requests follows)
+ break;
+ }
+ else
+ ppro->m_avatarsQueue = pRequest->pNext;
+
+ ppro->m_avatarsMutex->Leave();
+
+#ifdef _DEBUG
+ NetLog_Server("Picked up the %s request from queue.", strUID(pRequest->dwUin, pRequest->szUid));
+#endif
+ switch (pRequest->type)
+ {
+ case ART_GET: // get avatar
+ sendGetAvatarRequest(pRequest->hContact, pRequest->dwUin, pRequest->szUid, pRequest->hash, pRequest->hashlen, pRequest->szFile);
+ break;
+
+ case ART_UPLOAD: // set avatar
+ sendUploadAvatarRequest(pRequest->hContact, pRequest->wRef, pRequest->pData, pRequest->cbData);
+ break;
+ }
+ SAFE_DELETE(&pRequest);
+
+ ppro->m_avatarsMutex->Enter();
+ }
+
+ ppro->m_avatarsMutex->Leave();
+}
+
+
+void avatars_server_connection::connectionThread()
+{
+ // This is the "infinite" loop that receives the packets from the ICQ avatar server
+ NETLIBPACKETRECVER packetRecv = {0};
+ DWORD wLastKeepAlive = 0; // we send keep-alive at most one per 30secs
+ DWORD dwKeepAliveInterval = ppro->getSettingDword(NULL, "KeepAliveInterval", KEEPALIVE_INTERVAL);
+
+ hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hConnection, 65536);
+ packetRecv.cbSize = sizeof(packetRecv);
+ packetRecv.dwTimeout = dwKeepAliveInterval < KEEPALIVE_INTERVAL ? dwKeepAliveInterval: KEEPALIVE_INTERVAL; // timeout - for stopThread to work
+ while (!stopThread)
+ {
+ int recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPacketRecver, (LPARAM)&packetRecv);
+
+ if (recvResult == 0)
+ {
+ NetLog_Server("Clean closure of server socket");
+ break;
+ }
+
+ if (recvResult == SOCKET_ERROR)
+ {
+ if (GetLastError() == ERROR_TIMEOUT)
+ { // timeout, check if we should be still running
+ if (Miranda_Terminated())
+ { // we must stop here, cause due to a hack in netlib, we always get timeout, even if the connection is already dead
+ stopThread = 1;
+ continue;
+ }
+#ifdef _DEBUG
+ else
+ NetLog_Server("Thread is Idle.");
+#endif
+ if (GetTickCount() > wLastKeepAlive)
+ { // limit frequency (HACK: on some systems select() does not work well)
+ if (!ppro->m_bGatewayMode && ppro->getSettingByte(NULL, "KeepAlive", DEFAULT_KEEPALIVE_ENABLED))
+ { // send keep-alive packet
+ icq_packet packet;
+
+ packet.wLen = 0;
+ write_flap(&packet, ICQ_PING_CHAN);
+ sendServerPacket(&packet);
+ }
+ wLastKeepAlive = GetTickCount() + dwKeepAliveInterval;
+ }
+ else
+ { // this is bad, the system does not handle select() properly
+#ifdef _DEBUG
+ NetLog_Server("Thread is Forcing Idle.");
+#endif
+ SleepEx(500, TRUE); // wait some time, can we do anything else ??
+ if (Miranda_Terminated())
+ {
+ stopThread = 1;
+ continue;
+ }
+ }
+ // check if we got something to request
+ checkRequestQueue();
+ continue;
+ }
+ if (!stopThread)
+ NetLog_Server("Abortive closure of server socket, error: %d", GetLastError());
+ else
+ NetLog_Server("Connection closed.");
+ break;
+ }
+
+ // Deal with the packet
+ packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable);
+
+ if (isActive && (packetRecv.bytesAvailable == packetRecv.bytesUsed)) // no packets pending
+ { // process request queue
+ checkRequestQueue();
+ }
+ }
+ { // release connection
+ icq_lock l(localSeqMutex);
+ NetLib_SafeCloseHandle(&hPacketRecver); // Close the packet receiver
+ NetLib_CloseConnection(&hConnection, FALSE); // Close the connection
+ }
+
+ { // release rates
+ icq_lock l(m_ratesMutex);
+ SAFE_DELETE((void_struct**)&m_rates);
+ }
+
+ SAFE_FREE((void**)&pCookie);
+}
+
+
+int avatars_server_connection::sendServerPacket(icq_packet *pPacket)
+{
+ int lResult = 0;
+
+ // This critsec makes sure that the sequence order doesn't get screwed up
+ localSeqMutex->Enter();
+
+ if (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.
+ wLocalSequence++;
+
+ // Pack sequence number
+ pPacket->pData[2] = ((wLocalSequence & 0xff00) >> 8);
+ pPacket->pData[3] = (wLocalSequence & 0x00ff);
+
+ for (nRetries = 3; nRetries >= 0; nRetries--)
+ {
+ nSendResult = Netlib_Send(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
+
+ icq_lock l(m_ratesMutex);
+ if (m_rates)
+ m_rates->packetSent(pPacket);
+ }
+ }
+ else
+ {
+ NetLog_Server("Error: Failed to send packet (no connection)");
+ }
+
+ localSeqMutex->Leave();
+
+ SAFE_FREE((void**)&pPacket->pData);
+
+ return lResult;
+}
+
+
+int avatars_server_connection::handleServerPackets(BYTE *buf, int buflen)
+{
+ 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("Server FLAP: Channel %u, Seq %u, Length %u bytes", channel, sequence, datalen);
+#endif
+
+ switch (channel)
+ {
+ case ICQ_LOGIN_CHAN:
+ handleLoginChannel(buf, datalen);
+ break;
+
+ case ICQ_DATA_CHAN:
+ handleDataChannel(buf, datalen);
+ break;
+
+ default:
+ NetLog_Server("Warning: Unhandled Server FLAP Channel: Channel %u, Seq %u, Length %u bytes", channel, sequence, datalen);
+ break;
+ }
+
+ /* Increase pointers so we can check for more FLAPs */
+ buf += datalen;
+ buflen -= (datalen + 6);
+ bytesUsed += (datalen + 6);
+ }
+
+ return bytesUsed;
+}
+
+
+void avatars_server_connection::handleLoginChannel(BYTE *buf, WORD datalen)
+{
+ icq_packet packet;
+
+ if (*(DWORD*)buf == 0x1000000)
+ { // here check if we received SRV_HELLO
+ wLocalSequence = generate_flap_sequence();
+
+ serverCookieInit(&packet, (LPBYTE)pCookie, wCookieLen);
+ sendServerPacket(&packet);
+
+#ifdef _DEBUG
+ NetLog_Server("Sent CLI_IDENT to %s", "avatar server");
+#endif
+
+ SAFE_FREE((void**)&pCookie);
+ wCookieLen = 0;
+ }
+ else
+ {
+ NetLog_Server("Invalid Server response, Channel 1.");
+ }
+}
+
+
+void avatars_server_connection::handleDataChannel(BYTE *buf, WORD datalen)
+{
+ snac_header snacHeader = {0};
+
+ if (!unpackSnacHeader(&snacHeader, &buf, &datalen) || !snacHeader.bValid)
+ {
+ NetLog_Server("Error: Failed to parse SNAC header");
+ }
+ else
+ {
+#ifdef _DEBUG
+ if (snacHeader.wFlags & 0x8000)
+ NetLog_Server(" Received SNAC(x%02X,x%02X), version %u", snacHeader.wFamily, snacHeader.wSubtype, snacHeader.wVersion);
+ else
+ NetLog_Server(" Received SNAC(x%02X,x%02X)", snacHeader.wFamily, snacHeader.wSubtype);
+#endif
+
+ switch (snacHeader.wFamily)
+ {
+
+ case ICQ_SERVICE_FAMILY:
+ handleServiceFam(buf, datalen, &snacHeader);
+ break;
+
+ case ICQ_AVATAR_FAMILY:
+ handleAvatarFam(buf, datalen, &snacHeader);
+ break;
+
+ default:
+ NetLog_Server("Ignoring SNAC(x%02X,x%02X) - FAMILYx%02X not implemented", snacHeader.wFamily, snacHeader.wSubtype, snacHeader.wFamily);
+ break;
+ }
+ }
+}
+
+
+void avatars_server_connection::handleServiceFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader)
+{
+ 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
+
+ // Miranda mimics the behaviour of Icq5
+ serverPacketInit(&packet, 18);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_FAMILIES);
+ packDWord(&packet, 0x00010004);
+ packDWord(&packet, 0x00100001);
+ sendServerPacket(&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);
+ sendServerPacket(&packet);
+ break;
+
+ case ICQ_SERVER_RATE_INFO:
+#ifdef _DEBUG
+ NetLog_Server("Server sent Rate Info");
+#endif
+ /* init rates management */
+ m_rates = new rates(ppro, pBuffer, wBufferLength);
+ /* ack rate levels */
+#ifdef _DEBUG
+ NetLog_Server("Sending Rate Info Ack");
+#endif
+ m_rates->initAckPacket(&packet);
+ sendServerPacket(&packet);
+
+ // send cli_ready
+ serverPacketInit(&packet, 26);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_READY);
+ packDWord(&packet, 0x00010004); // mimic ICQ 6
+ packDWord(&packet, 0x0010164f);
+ packDWord(&packet, 0x00100001);
+ packDWord(&packet, 0x0010164f);
+ sendServerPacket(&packet);
+
+ isActive = TRUE; // we are ready to process requests
+ isLoggedIn = TRUE;
+
+ NetLog_Server(" *** Yeehah, login sequence complete");
+ 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 avatars_server_connection::handleAvatarFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader)
+{
+ switch (pSnacHeader->wSubtype) {
+
+ case ICQ_AVATAR_GET_REPLY: // received avatar data, store to file
+ { // handle new avatar, notify
+ cookie_avatar *pCookieData;
+
+ if (ppro->FindCookie(pSnacHeader->dwRef, NULL, (void**)&pCookieData))
+ {
+ PROTO_AVATAR_INFORMATIONT ai = {0};
+ BYTE bResult;
+
+ { // remove from active request list
+ icq_lock l(ppro->m_avatarsMutex);
+ for(int i = 0; i < runCount; i++)
+ { // look for our record
+ if (runContact[i] == pCookieData->hContact)
+ { // found, remove
+ runContact[i] = runContact[runCount - 1];
+ runTime[i] = runTime[runCount - 1];
+ runCount--;
+ break;
+ }
+ }
+ }
+
+ ai.cbSize = sizeof(PROTO_AVATAR_INFORMATION);
+ ai.format = PA_FORMAT_JPEG; // this is for error only
+ ai.hContact = pCookieData->hContact;
+ lstrcpyn(ai.filename, pCookieData->szFile, SIZEOF(ai.filename)); // Avatar API does not support unicode :-(
+ AddAvatarExt(PA_FORMAT_JPEG, ai.filename);
+
+ ppro->FreeCookie(pSnacHeader->dwRef);
+
+ BYTE len;
+ WORD datalen;
+
+ unpackByte(&pBuffer, &len);
+ if (wBufferLength < ((pCookieData->hashlen)<<1)+4+len)
+ {
+ NetLog_Server("Received invalid avatar reply.");
+
+ ppro->BroadcastAck(pCookieData->hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, (HANDLE)&ai, 0);
+
+ SAFE_FREE(&pCookieData->szFile);
+ SAFE_FREE((void**)&pCookieData->hash);
+ SAFE_FREE((void**)&pCookieData);
+
+ break;
+ }
+
+ pBuffer += len;
+ pBuffer += pCookieData->hashlen;
+ unpackByte(&pBuffer, &bResult);
+ pBuffer += pCookieData->hashlen;
+ unpackWord(&pBuffer, &datalen);
+
+ wBufferLength -= 4 + len + (pCookieData->hashlen<<1);
+ if (datalen > wBufferLength)
+ {
+ datalen = wBufferLength;
+ NetLog_Server("Avatar reply broken, trying to do my best.");
+ }
+
+ if (datalen > 4)
+ { // store to file...
+ int aValid = 1;
+
+ if (pCookieData->hashlen == 0x14 && pCookieData->hash[3] == 0x10 && ppro->getSettingByte(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(pCookieData->hash+4, digest, 0x10)) aValid = 0;
+ }
+
+ if (aValid)
+ {
+ NetLog_Server("Received user avatar, storing (%d bytes).", datalen);
+
+ int dwPaFormat = DetectAvatarFormatBuffer((char*)pBuffer);
+ TCHAR *tszImageFile = (TCHAR*)_alloca(sizeof(TCHAR)*(strlennull(pCookieData->szFile) + 6));
+
+ _tcscpy(tszImageFile, pCookieData->szFile);
+ AddAvatarExt(dwPaFormat, tszImageFile);
+
+ ppro->setSettingByte(pCookieData->hContact, "AvatarType", (BYTE)dwPaFormat);
+ ai.format = dwPaFormat; // set the format
+ lstrcpyn(ai.filename, tszImageFile, SIZEOF(ai.filename));
+
+ int out = _topen(tszImageFile, _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY, _S_IREAD | _S_IWRITE);
+ if (out != -1)
+ {
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ _write(out, pBuffer, datalen);
+ _close(out);
+
+ if (!pCookieData->hContact) // our avatar, set filename
+ {
+ TCHAR tmp[MAX_PATH * 2];
+ CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)tszImageFile, (LPARAM)tmp);
+ ppro->setSettingStringT(NULL, "AvatarFile", tmp);
+ }
+ else
+ { // contact's avatar set hash
+ if (!ppro->getSetting(pCookieData->hContact, "AvatarHash", &dbv))
+ {
+ if (ppro->setSettingBlob(pCookieData->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 (ppro->setSettingBlob(pCookieData->hContact, "AvatarSaved", pCookieData->hash, pCookieData->hashlen) ||
+ ppro->setSettingBlob(pCookieData->hContact, "AvatarHash", pCookieData->hash, pCookieData->hashlen))
+ {
+ NetLog_Server("Failed to save avatar hash to DB");
+ }
+ }
+ }
+
+ ppro->BroadcastAck(pCookieData->hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&ai, 0);
+ }
+ }
+ else
+ { // avatar is broken
+ NetLog_Server("Error: Avatar data does not match avatar hash, ignoring.");
+
+ if (pCookieData->hContact)
+ {
+ avatars_request *ar = new avatars_request(ART_BLOCK);
+
+ icq_lock l(ppro->m_avatarsMutex);
+
+ if (ar)
+ {
+ avatars_request *last = ppro->m_avatarsQueue;
+
+ ar->hContact = pCookieData->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
+ ppro->m_avatarsQueue = ar;
+ }
+ }
+ ppro->BroadcastAck(pCookieData->hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, (HANDLE)&ai, 0);
+ }
+ }
+ else
+ { // the avatar is empty
+ NetLog_Server("Received empty avatar, nothing written (error 0x%x).", bResult);
+
+ ppro->BroadcastAck(pCookieData->hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, (HANDLE)&ai, 0);
+ }
+ SAFE_FREE(&pCookieData->szFile);
+ SAFE_FREE((void**)&pCookieData->hash);
+ SAFE_FREE((void**)&pCookieData);
+ }
+ 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))
+ {
+ cookie_avatar *pCookieData;
+ if (ppro->FindCookie(pSnacHeader->dwRef, NULL, (void**)&pCookieData))
+ {
+ // here we store the local hash
+ ppro->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);
+
+ ppro->icq_LogMessage(LOG_WARNING, LPGEN("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;
+ cookie_avatar *pCookieData;
+
+ if (ppro->FindCookie(pSnacHeader->dwRef, NULL, (void**)&pCookieData))
+ {
+ if (pCookieData->dwUin)
+ {
+ NetLog_Server("Error: Avatar request failed");
+ SAFE_FREE(&pCookieData->szFile);
+ SAFE_FREE((void**)&pCookieData->hash);
+ }
+ else
+ {
+ NetLog_Server("Error: Avatar upload failed");
+ }
+ ppro->ReleaseCookie(pSnacHeader->dwRef);
+ }
+
+ if (wBufferLength >= 2)
+ unpackWord(&pBuffer, &wError);
+ else
+ wError = 0;
+
+ ppro->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/protocols/IcqOscarJ/icq_avatar.h b/protocols/IcqOscarJ/icq_avatar.h
new file mode 100644
index 0000000000..e6d140795a
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_avatar.h
@@ -0,0 +1,134 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_avatar.h $
+// Revision : $Revision: 14141 $
+// Last change on : $Date: 2012-03-09 22:52:15 +0200 (Пт, 09 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Avatars connection support declarations
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_AVATAR_H
+#define __ICQ_AVATAR_H
+
+
+extern BYTE hashEmptyAvatar[9];
+
+#define AVATAR_HASH_MINI 0x00
+#define AVATAR_HASH_STATIC 0x01
+#define AVATAR_HASH_FLASH 0x08
+#define AVATAR_HASH_PHOTO 0x0C
+
+struct CIcqProto;
+
+struct avatars_server_connection : public lockable_struct
+{
+protected:
+ CIcqProto *ppro;
+ HANDLE hConnection; // handle to the connection
+ HANDLE hPacketRecver;
+ WORD wLocalSequence;
+ icq_critical_section *localSeqMutex;
+
+ BOOL isLoggedIn;
+ BOOL isActive;
+ BOOL stopThread; // horrible, but simple - signal for thread to stop
+
+ char *pCookie; // auth to server
+ WORD wCookieLen;
+
+ int sendServerPacket(icq_packet *pPacket);
+
+ int handleServerPackets(BYTE *buf, int buflen);
+
+ void handleLoginChannel(BYTE *buf, WORD datalen);
+ void handleDataChannel(BYTE *buf, WORD datalen);
+
+ void handleServiceFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader);
+ void handleAvatarFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader);
+
+ rates *m_rates;
+ icq_critical_section *m_ratesMutex;
+
+ int NetLog_Server(const char *fmt,...);
+
+ HANDLE runContact[4];
+ DWORD runTime[4];
+ int runCount;
+ void checkRequestQueue();
+public:
+ avatars_server_connection(CIcqProto *ppro, HANDLE hConnection, char *pCookie, WORD wCookieLen);
+ virtual ~avatars_server_connection();
+
+ void connectionThread();
+ void closeConnection();
+ void shutdownConnection();
+
+ __inline BOOL isPending() { return !isLoggedIn; };
+ __inline BOOL isReady() { return isLoggedIn && isActive && !stopThread; };
+
+ DWORD sendGetAvatarRequest(HANDLE hContact, DWORD dwUin, char *szUid, const BYTE *hash, unsigned int hashlen, const TCHAR *file);
+ DWORD sendUploadAvatarRequest(HANDLE hContact, WORD wRef, const BYTE *data, unsigned int datalen);
+};
+
+__inline static void SAFE_DELETE(avatars_server_connection **p) { SAFE_DELETE((lockable_struct**)p); };
+
+
+struct avatars_request : public void_struct
+{
+ int type;
+ HANDLE hContact;
+ DWORD dwUin;
+ uid_str szUid;
+ BYTE *hash;
+ unsigned int hashlen;
+ TCHAR *szFile;
+ BYTE *pData;
+ unsigned int cbData;
+ WORD wRef;
+ DWORD timeOut;
+ avatars_request *pNext;
+public:
+ avatars_request(int type);
+ virtual ~avatars_request();
+};
+
+__inline static void SAFE_DELETE(avatars_request **p) { SAFE_DELETE((void_struct**)p); };
+
+#define ART_GET 1
+#define ART_UPLOAD 2
+#define ART_BLOCK 4
+
+
+int DetectAvatarFormat(const TCHAR *szFile);
+void AddAvatarExt(int dwFormat, TCHAR *pszDest);
+
+BYTE* calcMD5HashOfFile(const TCHAR *szFile);
+
+#endif /* __ICQ_AVATAR_H */
diff --git a/protocols/IcqOscarJ/icq_clients.cpp b/protocols/IcqOscarJ/icq_clients.cpp
new file mode 100644
index 0000000000..8c028a424e
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_clients.cpp
@@ -0,0 +1,1149 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_clients.cpp $
+// Revision : $Revision: 13847 $
+// Last change on : $Date: 2011-09-07 22:12:32 +0300 (Ср, 07 сен 2011) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Provides capability & signature based client detection
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+const capstr capShortCaps = {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}; // CAP_AIM_BUDDYICON
+
+static const char* 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);
+
+ return szBuf;
+}
+
+static void verToStr(char *szStr, int v)
+{
+ char szVer[64];
+
+ makeClientVersion(szVer, "", (v>>24)&0x7F, (v>>16)&0xFF, (v>>8)&0xFF, v&0xFF);
+ strcat(szStr, szVer);
+ if (v&0x80000000) strcat(szStr, " alpha");
+}
+
+static char* MirandaVersionToStringEx(char* szStr, int bUnicode, const char* szPlug, int v, int m)
+{
+ if (!v) // this is not Miranda
+ return NULL;
+
+ strcpy(szStr, "Miranda IM ");
+
+ if (!m && v == 1)
+ verToStr(szStr, 0x80010200);
+ else if (!m && (v&0x7FFFFFFF) <= 0x030301)
+ verToStr(szStr, v);
+ else {
+ if (m) {
+ verToStr(szStr, m);
+ strcat(szStr, " ");
+ }
+ if (bUnicode)
+ strcat(szStr, "Unicode ");
+
+ strcat(szStr, "(");
+ strcat(szStr, szPlug);
+ strcat(szStr, " v");
+ verToStr(szStr, v);
+ strcat(szStr, ")");
+ }
+
+ return szStr;
+}
+
+char* MirandaVersionToString(char* szStr, int bUnicode, int v, int m)
+{
+ return MirandaVersionToStringEx(szStr, bUnicode, "ICQ", v, m);
+}
+
+char* MirandaModToString(char* szStr, capstr* capId, int bUnicode, const char* szModName)
+{ // decode icqj mod version
+ char* szClient;
+ DWORD mver = (*capId)[0x4] << 0x18 | (*capId)[0x5] << 0x10 | (*capId)[0x6] << 8 | (*capId)[0x7];
+ DWORD iver = (*capId)[0x8] << 0x18 | (*capId)[0x9] << 0x10 | (*capId)[0xA] << 8 | (*capId)[0xB];
+ DWORD scode = (*capId)[0xC] << 0x18 | (*capId)[0xD] << 0x10 | (*capId)[0xE] << 8 | (*capId)[0xF];
+
+ szClient = MirandaVersionToStringEx(szStr, bUnicode, szModName, iver, mver);
+ if (scode == 0x5AFEC0DE)
+ {
+ strcat(szClient, " + SecureIM");
+ }
+ return szClient;
+}
+
+const capstr capMirandaIm = {'M', 'i', 'r', 'a', 'n', 'd', 'a', 'M', 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capIcqJs7 = {'i', 'c', 'q', 'j', ' ', 'S', 'e', 'c', 'u', 'r', 'e', ' ', 'I', 'M', 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 capIcqJp = {'i', 'c', 'q', 'p', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capAimOscar = {'M', 'i', 'r', 'a', 'n', 'd', 'a', 'A', 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capMimMobile = {'M', 'i', 'r', 'a', 'n', 'd', 'a', 'M', 'o', 'b', 'i', 'l', 'e', 0, 0, 0};
+const capstr capMimPack = {'M', 'I', 'M', '/', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Custom Miranda Pack
+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 capIMadering = {'I', 'M', 'a', 'd', 'e', 'r', 'i', 'n', 'g', ' ', 'C', 'l', 'i', 'e', 'n', 't'};
+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 capVmIcq = {'V', 'm', 'I', 'C', 'Q', ' ', 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 capAnastasia = {0x44, 0xE5, 0xBF, 0xCE, 0xB0, 0x96, 0xE5, 0x47, 0xBD, 0x65, 0xEF, 0xD6, 0xA3, 0x7E, 0x36, 0x02};
+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 capYapp = {'Y', 'a', 'p', 'p', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capMipClient = {0x4d, 0x49, 0x50, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x76, 0x00, 0x00, 0x00, 0x00};
+const capstr capPigeon = {'P', 'I', 'G', 'E', 'O', 'N', '!', 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capDigsbyBeta= {0x09, 0x46, 0x01, 0x05, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x45, 0x53, 0x54, 0x00};
+const capstr capDigsby = {'d', 'i', 'g', 's', 'b', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capJapp = {0x6a, 0x61, 0x70, 0x70, 0xa9, 0x20, 0x62, 0x79, 0x20, 0x53, 0x65, 0x72, 0x67, 0x6f, 0x00, 0x00};
+const capstr capNaim = {0xFF, 0xFF, 0xFF, 0xFF, 'n', 'a', 'i', 'm', 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capCitron = {0x09, 0x19, 0x19, 0x82, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+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 capQipSymbian= {0x51, 0xAD, 0xD1, 0x90, 0x72, 0x04, 0x47, 0x3D, 0xA1, 0xA1, 0x49, 0xF4, 0xA3, 0x97, 0xA4, 0x1F};
+const capstr capQipIphone = {0x60, 0xDE, 0x5C, 0x8A, 0xDF, 0x8C, 0x4E, 0x1D, 0xA4, 0xC8, 0xBC, 0x3B, 0xD9, 0x79, 0x4D, 0xD8};
+const capstr capQipMobile = {0xB0, 0x82, 0x62, 0xF6, 0x7F, 0x7C, 0x45, 0x61, 0xAD, 0xC1, 0x1C, 0x6D, 0x75, 0x70, 0x5E, 0xC5};
+const capstr capQipInfium = {0x7C, 0x73, 0x75, 0x02, 0xC3, 0xBE, 0x4F, 0x3E, 0xA6, 0x9F, 0x01, 0x53, 0x13, 0x43, 0x1E, 0x1A};
+const capstr capQip2010 = {0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x0A, 0x03, 0x0B, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, 0x00};
+const capstr capQip2012 = {0x7F, 0x7F, 0x7C, 0x7D, 0x7E, 0x7F, 0x0A, 0x03, 0x0B, 0x04, 0x01, 0x53, 0x13, 0x43, 0x1E, 0x1A};
+const capstr capIm2 = {0x74, 0xED, 0xC3, 0x36, 0x44, 0xDF, 0x48, 0x5B, 0x8B, 0x1C, 0x67, 0x1A, 0x1F, 0x86, 0x09, 0x9F}; // IM2 Ext Msg
+const capstr capQutIm = {'q', 'u', 't', 'i', 'm', 0x30, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+const capstr capBayan = {'b', 'a', 'y', 'a', 'n', 'I', 'C', 'Q', 0, 0, 0, 0, 0, 0, 0, 0};
+const capstr capJabberJIT = {'J', 'I', 'T', ' ', 0x76, 0x2E, 0x31, 0x2E, 0x78, 0x2E, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00};
+const capstr capIcqKid2 = {'I', 'c', 'q', 'K', 'i', 'd', '2', 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+const capstr capWebIcqPro = {'W', 'e', 'b', 'I', 'c', 'q', 'P', 'r', 'o', ' ', 0, 0, 0, 0, 0, 0};
+const capstr capMraJava = {0x4a, 0x32, 0x4d, 0x45, 0x20, 0x6d, 0x40, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00};
+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 shortcapstr capAimIcon = {0x13, 0x46}; // CAP_AIM_BUDDYICON
+const shortcapstr capAimDirect = {0x13, 0x45}; // CAP_AIM_DIRECTIM
+const shortcapstr capAimFileShare = {0x13, 0x48}; // CAP_AIM_FILE_SHARE
+const shortcapstr capIcqDevils = {0x13, 0x4C}; // CAP_DEVILS
+const shortcapstr capAimSmartCaps = {0x01, 0xFF};
+const shortcapstr capAimLiveVideo = {0x01, 0x01}; // CAP_AIM_LIVE_VIDEO
+const shortcapstr capAimLiveAudio = {0x01, 0x04}; // CAP_AIM_LIVE_AUDIO
+const shortcapstr capStatusTextAware = {0x01, 0x0A}; // CAP_HOST_STATUS_TEXT_AWARE
+const capstr capIcqLiteNew= {0xc8, 0x95, 0x3a, 0x9f, 0x21, 0xf1, 0x4f, 0xaa, 0xb0, 0xb2, 0x6d, 0xe6, 0x63, 0xab, 0xf5, 0xb7};
+const capstr capXtrazVideo= {0x17, 0x8C, 0x2D, 0x9B, 0xDA, 0xA5, 0x45, 0xBB, 0x8D, 0xDB, 0xF3, 0xBD, 0xBD, 0x53, 0xA1, 0x0A};
+const capstr capOscarChat = {0x74, 0x8F, 0x24, 0x20, 0x62, 0x87, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00};
+const capstr capUim = {0xA7, 0xE4, 0x0A, 0x96, 0xB3, 0xA0, 0x47, 0x9A, 0xB8, 0x45, 0xC9, 0xE4, 0x67, 0xC5, 0x6B, 0x1F};
+const capstr capRambler = {0x7E, 0x11, 0xB7, 0x78, 0xA3, 0x53, 0x49, 0x26, 0xA8, 0x02, 0x44, 0x73, 0x52, 0x08, 0xC4, 0x2A};
+const capstr capAbv = {0x00, 0xE7, 0xE0, 0xDF, 0xA9, 0xD0, 0x4F, 0xe1, 0x91, 0x62, 0xC8, 0x90, 0x9A, 0x13, 0x2A, 0x1B};
+const capstr capNetvigator= {0x4C, 0x6B, 0x90, 0xA3, 0x3D, 0x2D, 0x48, 0x0E, 0x89, 0xD6, 0x2E, 0x4B, 0x2C, 0x10, 0xD9, 0x9F};
+const capstr captZers = {0xb2, 0xec, 0x8f, 0x16, 0x7c, 0x6f, 0x45, 0x1b, 0xbd, 0x79, 0xdc, 0x58, 0x49, 0x78, 0x88, 0xb9}; // CAP_TZERS
+const capstr capSimpLite = {0x53, 0x49, 0x4D, 0x50, 0x53, 0x49, 0x4D, 0x50, 0x53, 0x49, 0x4D, 0x50, 0x53, 0x49, 0x4D, 0x50};
+const capstr capSimpPro = {0x53, 0x49, 0x4D, 0x50, 0x5F, 0x50, 0x52, 0x4F, 0x53, 0x49, 0x4D, 0x50, 0x5F, 0x50, 0x52, 0x4F};
+const capstr capIMsecure = {'I', 'M', 's', 'e', 'c', 'u', 'r', 'e', 'C', 'p', 'h', 'r', 0x00, 0x00, 0x06, 0x01}; // ZoneLabs
+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 capFakeHtml = {0x01, 0x38, 0xca, 0x7b, 0x76, 0x9a, 0x49, 0x15, 0x88, 0xf2, 0x13, 0xfc, 0x00, 0x97, 0x9e, 0xa8};
+
+const char* cliLibicq2k = "libicq2000";
+const char* cliLicqVer = "Licq ";
+const char* cliCentericq = "Centericq";
+const char* cliLibicqUTF = "libicq2000 (Unicode)";
+const char* cliTrillian = "Trillian";
+const char* cliTrillian4 = "Trillian Astra";
+const char* cliQip = "QIP %s";
+const char* cliIM2 = "IM2";
+const char* cliSpamBot = "Spam Bot";
+
+const char* CIcqProto::detectUserClient(HANDLE hContact, int nIsICQ, WORD wUserClass, DWORD dwOnlineSince, const char *szCurrentClient,
+ WORD wVersion, DWORD dwFT1, DWORD dwFT2, DWORD dwFT3, BYTE bDirectFlag, DWORD dwDirectCookie, DWORD dwWebPort, /* ICQ specific */
+ BYTE *caps, WORD wLen, /* Client capabilities */
+ BYTE *bClientId, /* Output: detected client-type */
+ char *szClientBuf)
+{
+ LPCSTR szClient = NULL;
+ int bMirandaIM = FALSE;
+
+ *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
+ { // Yes this is most probably Miranda, get the version info
+ szClient = MirandaVersionToString(szClientBuf, 0, dwFT2, 0);
+ *bClientId = CLID_MIRANDA;
+ bMirandaIM = TRUE;
+ }
+ }
+ else if (dwFT1 == 0x7fffffff)
+ { // This is Miranda with unicode core
+ szClient = MirandaVersionToString(szClientBuf, 1, dwFT2, 0);
+ *bClientId = CLID_MIRANDA;
+ bMirandaIM = TRUE;
+ }
+ else if ((dwFT1 & 0xFF7F0000) == 0x7D000000)
+ { // This is probably an Licq client
+ DWORD ver = dwFT1 & 0xFFFF;
+
+ szClient = makeClientVersion(szClientBuf, cliLicqVer, ver / 1000, (ver / 10) % 100, ver % 10, 0);
+ if (dwFT1 & 0x00800000)
+ strcat(szClientBuf, "/SSL");
+ }
+ 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;
+
+ szClient = makeClientVersion(szClientBuf, "Alicq ", ver1, ver2, ver3, 0);
+ }
+ 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/
+ if (dwFT2 == 0x10000)
+ {
+ strcpy(szClientBuf, "D[i]Chat v.");
+ strcat(szClientBuf, "0.1a");
+ }
+ else
+ {
+ makeClientVersion(szClientBuf, "D[i]Chat v.", (dwFT2 >> 8) & 0x0F, (dwFT2 >> 4) & 0x0F, 0, 0);
+ if ((dwFT2 & 0x0F) == 1)
+ strcat(szClientBuf, " alpha");
+ else if ((dwFT2 & 0x0F) == 2)
+ strcat(szClientBuf, " beta");
+ else if ((dwFT2 & 0x0F) == 3)
+ strcat(szClientBuf, " final");
+ }
+ 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
+ capstr* capId;
+
+ if (nIsICQ && caps)
+ {
+ // check capabilities for client identification
+ if (capId = MatchCapability(caps, wLen, &capMirandaIm, 8))
+ { // new Miranda Signature
+ DWORD iver = (*capId)[0xC] << 0x18 | (*capId)[0xD] << 0x10 | (*capId)[0xE] << 8 | (*capId)[0xF];
+ DWORD mver = (*capId)[0x8] << 0x18 | (*capId)[0x9] << 0x10 | (*capId)[0xA] << 8 | (*capId)[0xB];
+
+ szClient = MirandaVersionToString(szClientBuf, dwFT1 == 0x7fffffff, iver, mver);
+
+ if (MatchCapability(caps, wLen, &capIcqJs7, 0x4))
+ { // detect mod
+ strcat(szClientBuf, " (s7 & sss)");
+ if (MatchCapability(caps, wLen, &capIcqJs7, 0xE))
+ {
+ strcat(szClientBuf, " + SecureIM");
+ }
+ }
+ else if ((dwFT1 & 0x7FFFFFFF) == 0x7FFFFFFF)
+ {
+ if (MatchCapability(caps, wLen, &capMimMobile))
+ strcat(szClientBuf, " (Mobile)");
+
+ if (dwFT3 == 0x5AFEC0DE)
+ strcat(szClientBuf, " + SecureIM");
+ }
+ *bClientId = CLID_MIRANDA;
+ bMirandaIM = TRUE;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capIcqJs7, 4))
+ { // detect newer icqj mod
+ szClient = MirandaModToString(szClientBuf, capId, dwFT3 == 0x80000000, "ICQ S7 & SSS");
+ bMirandaIM = TRUE;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capIcqJSin, 4))
+ { // detect newer icqj mod
+ szClient = MirandaModToString(szClientBuf, capId, dwFT3 == 0x80000000, "ICQ S!N");
+ bMirandaIM = TRUE;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capIcqJp, 4))
+ { // detect icqj plus mod
+ szClient = MirandaModToString(szClientBuf, capId, dwFT3 == 0x80000000, "ICQ Plus");
+ bMirandaIM = TRUE;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capMraJava, 12))
+ {
+ unsigned ver1 = (*capId)[13];
+ unsigned ver2 = (*capId)[14];
+
+ szClient = makeClientVersion(szClientBuf, "Mail.ru Agent (Java) v", ver1, ver2, 0, 0);
+ }
+ else if (MatchCapability(caps, wLen, &capTrillian) || MatchCapability(caps, wLen, &capTrilCrypt))
+ { // this is Trillian, check for new versions
+ if (CheckContactCapabilities(hContact, CAPF_RTF))
+ {
+ if (CheckContactCapabilities(hContact, CAPF_OSCAR_FILE))
+ szClient = cliTrillian4;
+ 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 if (MatchCapability(caps, wLen, &capFakeHtml) || CheckContactCapabilities(hContact, CAPF_OSCAR_FILE))
+ szClient = cliTrillian4;
+ else
+ szClient = cliTrillian;
+ }
+ else if ((capId = MatchCapability(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
+ szClient = makeClientVersion(szClientBuf, "SIM ", (unsigned)hiVer, loVer, 0, 0);
+ }
+ else if (capId = MatchCapability(caps, wLen, &capSim, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ szClient = makeClientVersion(szClientBuf, "SIM ", ver1, ver2, ver3, ver4 & 0x0F);
+ if (ver4 & 0x80)
+ strcat(szClientBuf,"/Win32");
+ else if (ver4 & 0x40)
+ strcat(szClientBuf,"/MacOS X");
+ }
+ else if (capId = MatchCapability(caps, wLen, &capLicq, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD] % 100;
+ unsigned ver3 = (*capId)[0xE];
+
+ szClient = makeClientVersion(szClientBuf, cliLicqVer, ver1, ver2, ver3, 0);
+ if ((*capId)[0xF])
+ strcat(szClientBuf,"/SSL");
+ }
+ else if (capId = MatchCapability(caps, wLen, &capKopete, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ szClient = makeClientVersion(szClientBuf, "Kopete ", ver1, ver2, ver3, ver4);
+ }
+ else if (capId = MatchCapability(caps, wLen, &capClimm, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ szClient = 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");
+ }
+ else if (capId = MatchCapability(caps, wLen, &capmIcq, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ szClient = makeClientVersion(szClientBuf, "mICQ ", ver1, ver2, ver3, ver4);
+ if ((ver1 & 0x80) == 0x80)
+ strcat(szClientBuf, " alpha");
+ }
+ else if (MatchCapability(caps, wLen, &capIm2))
+ { // IM2 v2 provides also Aim Icon cap
+ szClient = cliIM2;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capAndRQ, 9))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xB];
+ unsigned ver3 = (*capId)[0xA];
+ unsigned ver4 = (*capId)[9];
+
+ szClient = makeClientVersion(szClientBuf, "&RQ ", ver1, ver2, ver3, ver4);
+ }
+ else if (capId = MatchCapability(caps, wLen, &capRAndQ, 9))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xB];
+ unsigned ver3 = (*capId)[0xA];
+ unsigned ver4 = (*capId)[9];
+
+ szClient = makeClientVersion(szClientBuf, "R&Q ", ver1, ver2, ver3, ver4);
+ }
+ else if (MatchCapability(caps, wLen, &capIMadering))
+ { // http://imadering.com
+ szClient = "IMadering";
+ }
+ else if (MatchCapability(caps, wLen, &capQipPDA))
+ {
+ szClient = "QIP PDA (Windows)";
+ }
+ else if (MatchCapability(caps, wLen, &capQipSymbian))
+ {
+ szClient = "QIP PDA (Symbian)";
+ }
+ else if (MatchCapability(caps, wLen, &capQipIphone))
+ {
+ szClient = "QIP Mobile (IPhone)";
+ }
+ else if (MatchCapability(caps, wLen, &capQipMobile))
+ {
+ szClient = "QIP Mobile (Java)";
+ }
+ else if (MatchCapability(caps, wLen, &capQipInfium))
+ {
+ char ver[10];
+
+ strcpy(szClientBuf, "QIP Infium");
+ if (dwFT1)
+ { // add build
+ null_snprintf(ver, 10, " (%d)", dwFT1);
+ strcat(szClientBuf, ver);
+ }
+ if (dwFT2 == 0x0B)
+ strcat(szClientBuf, " Beta");
+
+ szClient = szClientBuf;
+ }
+ else if (MatchCapability(caps, wLen, &capQip2010, 12))
+ {
+ char ver[10];
+
+ strcpy(szClientBuf, "QIP 2010");
+ if (dwFT1)
+ { // add build
+ null_snprintf(ver, 10, " (%d)", dwFT1);
+ strcat(szClientBuf, ver);
+ }
+
+ szClient = szClientBuf;
+ }
+ else if (MatchCapability(caps, wLen, &capQip2012, 12))
+ {
+ char ver[10];
+
+ strcpy(szClientBuf, "QIP 2012");
+ if (dwFT1)
+ { // add build
+ null_snprintf(ver, 10, " (%d)", dwFT1);
+ strcat(szClientBuf, ver);
+ }
+
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capQip, 0xE))
+ {
+ char ver[10];
+
+ if (dwFT3 == 0x0F)
+ strcpy(ver, "2005");
+ else
+ null_strcpy(ver, (char*)(*capId) + 11, 5);
+
+ 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 = MatchCapability(caps, wLen, &capmChat, 0xA))
+ {
+ strcpy(szClientBuf, "mChat ");
+ strncat(szClientBuf, (char*)(*capId) + 0xA, 6);
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capJimm, 5))
+ {
+ strcpy(szClientBuf, "Jimm ");
+ strncat(szClientBuf, (char*)(*capId) + 5, 11);
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCapability(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 (capId = MatchCapability(caps, wLen, &capDiChat, 9))
+ { // http://darkjimm.ucoz.ru/
+ strcpy(szClientBuf, "D[i]Chat");
+ strncat(szClientBuf, (char*)(*capId) + 8, 8);
+ szClient = szClientBuf;
+ }
+ else if (MatchCapability(caps, wLen, &capMacIcq))
+ {
+ szClient = "ICQ for Mac";
+ }
+ else if (MatchCapability(caps, wLen, &capUim))
+ {
+ szClient = "uIM";
+ }
+ else if (MatchCapability(caps, wLen, &capAnastasia))
+ { // http://chis.nnov.ru/anastasia
+ szClient = "Anastasia";
+ }
+ else if (capId = MatchCapability(caps, wLen, &capPalmJicq, 0xC))
+ { // http://www.jsoft.ru
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ szClient = makeClientVersion(szClientBuf, "JICQ ", ver1, ver2, ver3, ver4);
+ }
+ else if (MatchCapability(caps, wLen, &capInluxMsgr))
+ { // http://www.inlusoft.com
+ szClient = "Inlux Messenger";
+ }
+ else if (capId = MatchCapability(caps, wLen, &capMipClient, 0xC))
+ { // http://mip.rufon.net
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ if (ver1 < 30)
+ {
+ makeClientVersion(szClientBuf, "MIP ", ver1, ver2, ver3, ver4);
+ }
+ else
+ {
+ strcpy(szClientBuf, "MIP ");
+ strncat(szClientBuf, (char*)(*capId) + 11, 5);
+ }
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capMipClient, 0x04))
+ { //http://mip.rufon.net - new signature
+ strcpy(szClientBuf, "MIP ");
+ strncat(szClientBuf, (char*)(*capId) + 4, 12);
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capVmIcq, 0x06))
+ {
+ strcpy(szClientBuf, "VmICQ");
+ strncat(szClientBuf, (char*)(*capId) + 5, 11);
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capSmapeR, 0x07))
+ { // http://www.smape.com/smaper
+ strcpy(szClientBuf, "SmapeR");
+ strncat(szClientBuf, (char*)(*capId) + 6, 10);
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capYapp, 0x04))
+ { // http://yapp.ru
+ strcpy(szClientBuf, "Yapp! v");
+ strncat(szClientBuf, (char*)(*capId) + 8, 5);
+ szClient = szClientBuf;
+ }
+ else if (MatchCapability(caps, wLen, &capDigsby, 0x06))
+ { // http://www.dibsby.com (newer builds)
+ szClient = "Digsby";
+ }
+ else if (MatchCapability(caps, wLen, &capDigsbyBeta))
+ { // http://www.digsby.com - probably by mistake (feature detection as well)
+ szClient = "Digsby";
+ }
+ else if (MatchCapability(caps, wLen, &capJapp))
+ { // http://www.japp.org.ua
+ szClient = "japp";
+ }
+ else if (MatchCapability(caps, wLen, &capPigeon, 0x07))
+ { // http://pigeon.vpro.ru
+ szClient = "PIGEON!";
+ }
+ else if (capId = MatchCapability(caps, wLen, &capQutIm, 0x05))
+ { // http://www.qutim.org
+ if ((*capId)[0x6] == 0x2E)
+ { // old qutim id
+ unsigned ver1 = (*capId)[0x5] - 0x30;
+ unsigned ver2 = (*capId)[0x7] - 0x30;
+
+ makeClientVersion(szClientBuf, "qutIM ", ver1, ver2, 0, 0);
+ }
+ else
+ { // new qutim id
+ unsigned ver1 = (*capId)[0x6];
+ unsigned ver2 = (*capId)[0x7];
+ unsigned ver3 = (*capId)[0x8];
+ unsigned ver4 = ((*capId)[0x9] << 8) || (*capId)[0xA];
+
+ makeClientVersion(szClientBuf, "qutIM ", ver1, ver2, ver3, ver4);
+
+ switch ((*capId)[0x5])
+ {
+ case 'l':
+ strcat(szClientBuf, "/Linux");
+ break;
+ case 'w':
+ strcat(szClientBuf, "/Win32");
+ break;
+ case 'm':
+ strcat(szClientBuf, "/MacOS X");
+ break;
+ }
+ }
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capBayan, 8))
+ { // http://www.barobin.com/bayanICQ.html
+ strcpy(szClientBuf, "bayanICQ ");
+ strncat(szClientBuf, (char*)(*capId) + 8, 5);
+ szClient = szClientBuf;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capJabberJIT, 0x04))
+ {
+ szClient = "Jabber ICQ Transport";
+ }
+ else if (capId = MatchCapability(caps, wLen, &capIcqKid2, 0x07))
+ { // http://sourceforge.net/projects/icqkid2
+ unsigned ver1 = (*capId)[0x7];
+ unsigned ver2 = (*capId)[0x8];
+ unsigned ver3 = (*capId)[0x9];
+ unsigned ver4 = (*capId)[0xA];
+
+ szClient = makeClientVersion(szClientBuf, "IcqKid2 v", ver1, ver2, ver3, ver4);
+ }
+ else if (capId = MatchCapability(caps, wLen, &capWebIcqPro, 0x0A))
+ { // http://intrigue.ru/workshop/webicqpro/webicqpro.html
+ szClient = "WebIcqPro";
+ }
+ else if (capId = MatchCapability(caps, wLen, &capCitron))
+ { // http://www.citron-im.com
+ szClient = "Citron IM";
+ }
+ 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) // HERE ENDS THE SIGNATURE DETECTION, after this only feature default will be detected
+ {
+ if (wVersion == 8 && CheckContactCapabilities(hContact, CAPF_XTRAZ) && (MatchCapability(caps, wLen, &capIMSecKey1, 6) || MatchCapability(caps, wLen, &capIMSecKey2, 6)))
+ { // ZA mangled the version, OMG!
+ wVersion = 9;
+ }
+ if (wVersion == 8 && (MatchCapability(caps, wLen, &capComm20012) || CheckContactCapabilities(hContact, CAPF_SRV_RELAY)))
+ { // try to determine 2001-2003 versions
+ if (MatchCapability(caps, wLen, &capIs2001))
+ {
+ 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 (MatchCapability(caps, wLen, &capIs2002))
+ {
+ *bClientId = CLID_GENERIC;
+ szClient = "ICQ 2002";
+ }
+ else if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY | CAPF_UTF | CAPF_RTF))
+ {
+ if (!dwFT1 && !dwFT2 && !dwFT3)
+ {
+ if (!dwWebPort)
+ szClient = "GnomeICU 0.99.5+"; // no other way
+ else
+ szClient = "IC@";
+ }
+ else
+ {
+ *bClientId = CLID_GENERIC;
+ szClient = "ICQ 2002/2003a";
+ }
+ }
+ else if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY | CAPF_UTF | CAPF_TYPING | CAPF_XTRAZ) &&
+ MatchCapability(caps, wLen, &capOscarChat) && MatchShortCapability(caps, wLen, &capAimIcon) &&
+ MatchCapability(caps, wLen, &capFakeHtml))
+ { // libpurple (e.g. Pidgin 2.7.x)
+ if (MatchShortCapability(caps, wLen, &capAimDirect))
+ szClient = "libpurple";
+ else
+ szClient = "Meebo";
+ }
+ else if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY | CAPF_UTF | CAPF_TYPING))
+ {
+ if (!dwFT1 && !dwFT2 && !dwFT3)
+ {
+ szClient = "PreludeICQ";
+ }
+ }
+ }
+ else if (wVersion == 8)
+ {
+ if (CheckContactCapabilities(hContact, CAPF_UTF | CAPF_TYPING) && MatchShortCapability(caps, wLen, &capAimIcon) && MatchShortCapability(caps, wLen, &capAimDirect))
+ szClient = "imo.im"; //https://imo.im/ - Web IM
+ }
+ else if (wVersion == 9)
+ { // try to determine lite versions
+ if (CheckContactCapabilities(hContact, CAPF_XTRAZ))
+ {
+ *bClientId = CLID_GENERIC;
+ if (CheckContactCapabilities(hContact, CAPF_OSCAR_FILE))
+ {
+ if (MatchCapability(caps, wLen, &captZers))
+ { // capable of tZers ?
+ if (MatchCapability(caps, wLen, &capIcqLiteNew) && MatchShortCapability(caps, wLen, &capStatusTextAware) &&
+ MatchShortCapability(caps, wLen, &capAimLiveVideo) && MatchShortCapability(caps, wLen, &capAimLiveAudio))
+ {
+ strcpy(szClientBuf, "ICQ 7");
+ }
+ else if (MatchCapability(caps, wLen, &capFakeHtml))
+ {
+ if (MatchShortCapability(caps, wLen, &capAimLiveVideo) && MatchShortCapability(caps, wLen, &capAimLiveAudio))
+ {
+ strcpy(szClientBuf, "ICQ 6");
+ *bClientId = CLID_ICQ6;
+ }
+ else if (CheckContactCapabilities(hContact, CAPF_RTF) && !CheckContactCapabilities(hContact, CAPF_CONTACTS) && MatchShortCapability(caps, wLen, &capIcqDevils))
+ {
+ strcpy(szClientBuf, "Qnext v4"); // finally handles SRV_RELAY correctly
+ *bClientId = CLID_ALTERNATIVE;
+ }
+ }
+ else
+ {
+ strcpy(szClientBuf, "icq5.1");
+ }
+ }
+ else
+ {
+ strcpy(szClientBuf, "icq5");
+ }
+
+ if (MatchCapability(caps, wLen, &capRambler))
+ {
+ strcat(szClientBuf, " (Rambler)");
+ }
+ else if (MatchCapability(caps, wLen, &capAbv))
+ {
+ strcat(szClientBuf, " (Abv)");
+ }
+ else if (MatchCapability(caps, wLen, &capNetvigator))
+ {
+ strcat(szClientBuf, " (Netvigator)");
+ }
+ szClient = szClientBuf;
+ }
+ else if (!CheckContactCapabilities(hContact, CAPF_ICQDIRECT))
+ {
+ *bClientId = CLID_ALTERNATIVE;
+ 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 if (CheckContactCapabilities(hContact, CAPF_TYPING) && MatchCapability(caps, wLen, &captZers) && MatchCapability(caps, wLen, &capFakeHtml))
+ {
+ if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY | CAPF_UTF) && MatchShortCapability(caps, wLen, &capAimLiveAudio))
+ szClient = "Mail.ru Agent (PC)";
+ else
+ szClient = "Fring";
+ }
+ else
+ szClient = "pyICQ";
+ }
+ else
+ szClient = "ICQ Lite v4";
+ }
+ else if (MatchCapability(caps, wLen, &capIcqLiteNew))
+ szClient = "ICQ Lite"; // the new ICQ Lite based on ICQ6
+ else if (!CheckContactCapabilities(hContact, CAPF_ICQDIRECT))
+ {
+ if (MatchCapability(caps, wLen, &capFakeHtml) && MatchCapability(caps, wLen, &capOscarChat) && MatchShortCapability(caps, wLen, &capAimSmartCaps))
+ szClient = cliTrillian4;
+ else 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 (wUserClass & CLASS_WIRELESS)
+ szClient = "Pocket Web 1&1";
+ else
+ szClient = "Icq2Go!";
+ }
+ }
+ 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 == 0xB)
+ {
+ if (CheckContactCapabilities(hContact, CAPF_XTRAZ | CAPF_SRV_RELAY | CAPF_TYPING | CAPF_UTF) && MatchShortCapability(caps, wLen, &capIcqDevils))
+ {
+ szClient = "Mail.ru Agent (Symbian)";
+ }
+ }
+ 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) && MatchCapability(caps, wLen, &capIs2001) &&
+ MatchCapability(caps, wLen, &capIs2002) && MatchCapability(caps, wLen, &capComm20012))
+ szClient = cliSpamBot;
+ else if (MatchShortCapability(caps, wLen, &capAimIcon) && MatchShortCapability(caps, wLen, &capAimDirect) &&
+ CheckContactCapabilities(hContact, CAPF_OSCAR_FILE | CAPF_UTF))
+ { // detect libgaim/libpurple versions
+ if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY))
+ szClient = "Adium X"; // yeah, AFAIK only Adium has this fixed
+ else if (CheckContactCapabilities(hContact, CAPF_TYPING))
+ szClient = "libpurple";
+ else
+ szClient = "libgaim";
+ }
+ else if (MatchShortCapability(caps, wLen, &capAimIcon) && MatchShortCapability(caps, wLen, &capAimDirect) &&
+ MatchCapability(caps, wLen, &capOscarChat) && CheckContactCapabilities(hContact, CAPF_OSCAR_FILE) && wLen == 0x40)
+ szClient = "libgaim"; // Gaim 1.5.1 most probably
+ else if (CheckContactCapabilities(hContact, CAPF_OSCAR_FILE) && MatchCapability(caps, wLen, &capOscarChat) && wLen == 0x20)
+ szClient = "Easy Message";
+ else if (CheckContactCapabilities(hContact, CAPF_UTF | CAPF_TYPING) && MatchShortCapability(caps, wLen, &capAimIcon) && MatchCapability(caps, wLen, &capOscarChat) && wLen == 0x40)
+ szClient = "Meebo";
+ else if (CheckContactCapabilities(hContact, CAPF_UTF) && MatchShortCapability(caps, wLen, &capAimIcon) && wLen == 0x20)
+ szClient = "PyICQ-t Jabber Transport";
+ else if (CheckContactCapabilities(hContact, CAPF_UTF | CAPF_XTRAZ) && MatchShortCapability(caps, wLen, &capAimIcon) && MatchCapability(caps, wLen, &capXtrazVideo))
+ szClient = "PyICQ-t Jabber Transport";
+ else if (CheckContactCapabilities(hContact, CAPF_UTF | CAPF_SRV_RELAY | CAPF_ICQDIRECT | CAPF_TYPING) && wLen == 0x40)
+ szClient = "Agile Messenger"; // Smartphone 2002
+ else if (CheckContactCapabilities(hContact, CAPF_UTF | CAPF_SRV_RELAY | CAPF_ICQDIRECT | CAPF_OSCAR_FILE) && MatchShortCapability(caps, wLen, &capAimFileShare))
+ szClient = "Slick"; // http://lonelycatgames.com/?app=slick
+ else if (CheckContactCapabilities(hContact, CAPF_UTF | CAPF_SRV_RELAY | CAPF_OSCAR_FILE | CAPF_CONTACTS) && MatchShortCapability(caps, wLen, &capAimFileShare) && MatchShortCapability(caps, wLen, &capAimIcon))
+ szClient = "Digsby"; // http://www.digsby.com
+ else if (CheckContactCapabilities(hContact, CAPF_UTF | CAPF_SRV_RELAY | CAPF_CONTACTS) && MatchShortCapability(caps, wLen, &capAimIcon) && MatchCapability(caps, wLen, &capFakeHtml))
+ szClient = "mundu IM"; // http://messenger.mundu.com
+ else if (CheckContactCapabilities(hContact, CAPF_UTF | CAPF_OSCAR_FILE) && MatchCapability(caps, wLen, &capOscarChat))
+ szClient = "eBuddy"; //http://www.ebuddy.com
+ else if (CheckContactCapabilities(hContact, CAPF_CONTACTS | CAPF_OSCAR_FILE) && MatchShortCapability(caps, wLen, &capAimIcon) && MatchShortCapability(caps, wLen, &capAimDirect) && MatchCapability(caps, wLen, &capOscarChat))
+ szClient = "IloveIM"; //http://www.iloveim.com/
+
+ }
+ }
+ }
+ }
+ else if (!nIsICQ)
+ { // detect AIM clients
+ if (caps)
+ {
+ if (capId = MatchCapability(caps, wLen, &capAimOscar, 8))
+ { // AimOscar Signature
+ DWORD aver = (*capId)[0xC] << 0x18 | (*capId)[0xD] << 0x10 | (*capId)[0xE] << 8 | (*capId)[0xF];
+ DWORD mver = (*capId)[0x8] << 0x18 | (*capId)[0x9] << 0x10 | (*capId)[0xA] << 8 | (*capId)[0xB];
+
+ szClient = MirandaVersionToStringEx(szClientBuf, 0, "AimOscar", aver, mver);
+ bMirandaIM = TRUE;
+ }
+ else if (capId = MatchCapability(caps, wLen, &capSim, 0xC))
+ { // Sim is universal
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+
+ szClient = makeClientVersion(szClientBuf, "SIM ", ver1, ver2, ver3, 0);
+ if ((*capId)[0xF] & 0x80)
+ strcat(szClientBuf,"/Win32");
+ else if ((*capId)[0xF] & 0x40)
+ strcat(szClientBuf,"/MacOS X");
+ }
+ else if (capId = MatchCapability(caps, wLen, &capKopete, 0xC))
+ {
+ unsigned ver1 = (*capId)[0xC];
+ unsigned ver2 = (*capId)[0xD];
+ unsigned ver3 = (*capId)[0xE];
+ unsigned ver4 = (*capId)[0xF];
+
+ szClient = makeClientVersion(szClientBuf, "Kopete ", ver1, ver2, ver3, ver4);
+ }
+ else if (MatchCapability(caps, wLen, &capIm2))
+ { // IM2 extensions
+ szClient = cliIM2;
+ }
+ else if (MatchCapability(caps, wLen, &capNaim, 0x8))
+ {
+ szClient = "naim";
+ }
+ else if (MatchCapability(caps, wLen, &capDigsby, 0x06) || MatchCapability(caps, wLen, &capDigsbyBeta))
+ { // http://www.dibsby.com
+ szClient = "Digsby";
+ }
+ else if (MatchShortCapability(caps, wLen, &capAimIcon) && MatchCapability(caps, wLen, &capOscarChat) &&
+ CheckContactCapabilities(hContact, CAPF_UTF | CAPF_TYPING) && wLen == 0x40)
+ szClient = "Meebo";
+ else if (wLen == 0x90 && CheckContactCapabilities(hContact, CAPF_SRV_RELAY | CAPF_UTF | CAPF_TYPING | CAPF_XTRAZ) &&
+ MatchCapability(caps, wLen, &capOscarChat) && MatchShortCapability(caps, wLen, &capAimIcon) &&
+ MatchShortCapability(caps, wLen, &capAimDirect) && MatchCapability(caps, wLen, &capFakeHtml))
+ { // libpurple (e.g. Pidgin 2.7.x)
+ szClient = "libpurple";
+ }
+ else if (wLen == 0x70 && CheckContactCapabilities(hContact, CAPF_SRV_RELAY | CAPF_UTF | CAPF_TYPING | CAPF_XTRAZ) &&
+ MatchCapability(caps, wLen, &capOscarChat) && MatchShortCapability(caps, wLen, &capAimIcon) &&
+ MatchCapability(caps, wLen, &capFakeHtml))
+ { // libpurple - Meebo (without DirectIM and OFT)
+ szClient = "Meebo";
+ }
+ else
+ szClient = "AIM";
+ }
+ else
+ szClient = "AIM";
+ }
+ }
+ if (caps && bMirandaIM)
+ { // custom miranda packs
+ capstr* capId;
+
+ if (capId = MatchCapability(caps, wLen, &capMimPack, 4))
+ {
+ char szPack[16];
+
+ null_snprintf(szPack, 16, " [%.12s]", (*capId)+4);
+
+ if (szClient != szClientBuf)
+ { // make sure client string is not constant
+ strcpy(szClientBuf, szClient);
+ szClient = szClientBuf;
+ }
+
+ strcat(szClientBuf, szPack);
+ }
+ }
+
+ BOOL bClientDetected = (szClient != NULL);
+
+ if (!szClient)
+ {
+ *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";
+ }
+ }
+
+ if (szClient)
+ {
+ char *szExtra = NULL;
+
+ if (MatchCapability(caps, wLen, &capSimpLite))
+ szExtra = " + SimpLite";
+ else if (MatchCapability(caps, wLen, &capSimpPro))
+ szExtra = " + SimpPro";
+ else if (MatchCapability(caps, wLen, &capIMsecure) || MatchCapability(caps, wLen, &capIMSecKey1, 6) || MatchCapability(caps, wLen, &capIMSecKey2, 6))
+ szExtra = " + IMsecure";
+
+ if (szExtra)
+ {
+ if (szClient != szClientBuf)
+ {
+ strcpy(szClientBuf, szClient);
+ szClient = szClientBuf;
+ }
+ strcat(szClientBuf, szExtra);
+ }
+ }
+
+ if (!szCurrentClient || strcmpnull(szCurrentClient, szClient))
+ { // Log the detection result if it has changed or contact just logged on...
+ if (bClientDetected)
+ NetLog_Server("Client identified as %s", szClient);
+ else
+ NetLog_Server("No client identification, put default ICQ client for protocol.");
+ }
+
+ return szClient;
+}
diff --git a/protocols/IcqOscarJ/icq_constants.h b/protocols/IcqOscarJ/icq_constants.h
new file mode 100644
index 0000000000..2b38866bdd
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_constants.h
@@ -0,0 +1,657 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_constants.h $
+// Revision : $Revision: 14075 $
+// Last change on : $Date: 2012-02-11 16:41:20 +0200 (Сб, 11 фев 2012) $
+// Last change by : $Author: borkra $
+//
+// 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
+
+
+/* Static icon indexes */
+#define ISI_AUTH_REQUEST 0
+#define ISI_AUTH_GRANT 1
+#define ISI_AUTH_REVOKE 2
+#define ISI_ADD_TO_SERVLIST 3
+
+/* Contact menu item indexes */
+#define ICMI_AUTH_REQUEST 0
+#define ICMI_AUTH_GRANT 1
+#define ICMI_AUTH_REVOKE 2
+#define ICMI_ADD_TO_SERVLIST 3
+#define ICMI_XSTATUS_DETAILS 4
+
+/* Some default settings */
+#define DEFAULT_SERVER_PORT 5190
+#define DEFAULT_SERVER_PORT_SSL 443
+#define DEFAULT_SERVER_HOST "login.icq.com"
+#define DEFAULT_SERVER_HOST_SSL "slogin.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_SECURE_CONNECTION 1
+#define DEFAULT_KEEPALIVE_ENABLED 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_AVATARS_ENABLED 1
+#define DEFAULT_LOAD_AVATARS 1
+#define DEFAULT_BIGGER_AVATARS 0
+#define DEFAULT_AVATARS_CHECK 1
+#define DEFAULT_XSTATUS_ENABLED 0
+#define DEFAULT_XSTATUS_AUTO 1
+#define DEFAULT_XSTATUS_RESET 0
+#define DEFAULT_MOODS_ENABLED 1
+#define DEFAULT_KILLSPAM_ENABLED 1
+
+#define DEFAULT_SLOWSEND 1
+#define DEFAULT_ONLYSERVERACKS 1
+
+#define DEFAULT_POPUPS_ENABLED 1
+#define DEFAULT_SPAM_POPUPS_ENABLED 1
+#define DEFAULT_LOG_POPUPS_ENABLED 1
+#define DEFAULT_POPUPS_SYS_ICONS 1
+#define DEFAULT_LOG0_TEXT_COLORS RGB(0,0,0) // LOG_NOTE
+#define DEFAULT_LOG0_BACK_COLORS RGB(255,255,255)
+#define DEFAULT_LOG0_TIMEOUT 0
+#define DEFAULT_LOG1_TEXT_COLORS RGB(0,0,0) // LOG_WARNING
+#define DEFAULT_LOG1_BACK_COLORS RGB(255,255,255)
+#define DEFAULT_LOG1_TIMEOUT 0
+#define DEFAULT_LOG2_TEXT_COLORS RGB(0,0,0) // LOG_ERROR
+#define DEFAULT_LOG2_BACK_COLORS RGB(255,255,255)
+#define DEFAULT_LOG2_TIMEOUT 0
+#define DEFAULT_LOG3_TEXT_COLORS RGB(0,0,0) // LOG_FATAL
+#define DEFAULT_LOG3_BACK_COLORS RGB(255,255,255)
+#define DEFAULT_LOG3_TIMEOUT 0
+#define DEFAULT_SPAM_TEXT_COLORS RGB(193,0,38)
+#define DEFAULT_SPAM_BACK_COLORS RGB(213,209,208)
+#define DEFAULT_SPAM_TIMEOUT 0
+#define DEFAULT_POPUPS_WIN_COLORS 0
+
+/* Database setting names */
+#define DBSETTING_CAPABILITIES "caps"
+// Contact's server-list items
+#define DBSETTING_SERVLIST_ID "ServerId"
+#define DBSETTING_SERVLIST_GROUP "SrvGroupId"
+#define DBSETTING_SERVLIST_PERMIT "SrvPermitId"
+#define DBSETTING_SERVLIST_DENY "SrvDenyId"
+#define DBSETTING_SERVLIST_IGNORE "SrvIgnoreId"
+// Owner's server-list items
+#define DBSETTING_SERVLIST_PRIVACY "SrvVisibilityID"
+#define DBSETTING_SERVLIST_PHOTO "SrvPhotoID"
+#define DBSETTING_SERVLIST_AVATAR "SrvAvatarID"
+#define DBSETTING_SERVLIST_METAINFO "SrvMetaInfoID"
+#define DBSETTING_SERVLIST_UNHANDLED "SrvUnhandledIDList"
+// Contact's data from server-list
+#define DBSETTING_SERVLIST_DATA "ServerData"
+// User Details
+#define DBSETTING_METAINFO_TOKEN "MetaInfoToken"
+#define DBSETTING_METAINFO_TIME "MetaInfoTime"
+#define DBSETTING_METAINFO_SAVED "InfoTS"
+// Status Note & Mood
+#define DBSETTING_STATUS_NOTE "StatusNote"
+#define DBSETTING_STATUS_NOTE_TIME "StatusNoteTS"
+#define DBSETTING_STATUS_MOOD "StatusMood"
+// Custom Status
+#define DBSETTING_XSTATUS_ID "XStatusId"
+#define DBSETTING_XSTATUS_NAME "XStatusName"
+#define DBSETTING_XSTATUS_MSG "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 Sizes
+#define BINARY_CAP_SIZE 16
+#define BINARY_SHORT_CAP_SIZE 2
+
+// Binary Capability IDs
+#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_RTF 0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92
+#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
+
+// Miranda IM Capability bitmask
+#define CAPF_SRV_RELAY 0x00000001
+#define CAPF_UTF 0x00000002
+#define CAPF_RTF 0x00000004
+#define CAPF_CONTACTS 0x00000010
+#define CAPF_TYPING 0x00000020
+#define CAPF_ICQDIRECT 0x00000080
+#define CAPF_XTRAZ 0x00000100
+#define CAPF_OSCAR_FILE 0x00000400
+#define CAPF_STATUS_MESSAGES 0x10000000
+#define CAPF_STATUS_MOOD 0x40000000
+#define CAPF_XSTATUS 0x80000000
+
+
+// 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
+
+
+
+// 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 (internal only)
+#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
+
+// 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
+
+// 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_CHAT_NAVIGATION_FAMILY 0x000d
+#define ICQ_CHAT_FAMILY 0x000e
+#define ICQ_AVATAR_FAMILY 0x0010
+#define ICQ_LISTS_FAMILY 0x0013
+#define ICQ_EXTENSIONS_FAMILY 0x0015
+#define ICQ_AUTHORIZATION_FAMILY 0x0017
+#define ICQ_DIRECTORY_FAMILY 0x0025
+
+/* 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 /* deprecated */
+#define ICQ_USER_REMOVEFROMLIST 0x0005 /* deprecated */
+#define ICQ_USER_NOTIFY_REJECTED 0x000a
+#define ICQ_USER_ONLINE 0x000b
+#define ICQ_USER_OFFLINE 0x000c
+#define ICQ_USER_ADDTOTEMPLIST 0x000f
+#define ICQ_USER_REMOVEFROMTEMPLIST 0x0010
+
+/* 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_REQUEST 0x0002
+#define ICQ_META_SRV_REPLY 0x0003
+#define ICQ_META_SRV_UPDATE 0x0004
+
+/* 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
+#define CLASS_FORWARDING 0x0200
+#define CLASS_BOT 0x0400
+
+// Reply types for SNAC 15/02 & 15/03
+#define CLI_DELETE_OFFLINE_MSGS_REQ 0x003E
+#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_DIRECTORY_QUERY 0x0FA0
+#define META_DIRECTORY_DATA 0x0FAA
+#define META_DIRECTORY_RESPONSE 0x0FB4
+#define META_DIRECTORY_UPDATE 0x0FD2
+#define META_DIRECTORY_UPDATE_ACK 0x0FDC
+
+#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
+
+// Subtypes for Directory meta requests (family 0x5b9)
+#define DIRECTORY_QUERY_INFO 0x0002
+#define DIRECTORY_SET_INFO 0x0003
+#define DIRECTORY_QUERY_MULTI_INFO 0x0006
+#define DIRECTORY_QUERY_INFO_ACK 0x0009
+#define DIRECTORY_SET_INFO_ACK 0x000A
+
+// 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_CLIENTDATA 0x0009 // Client specific, e.g. 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: "1", "8", etc. according ot the icon type)
+#define SSI_ITEM_SAVED 0x0019
+#define SSI_ITEM_PREAUTH 0x001B
+#define SSI_ITEM_METAINFO 0x0020 // Owner Details' token & last update time
+
+#define SSI_TLV_AWAITING_AUTH 0x0066 // Contact not authorized in list
+#define SSI_TLV_NOT_IN_LIST 0x006A // Always empty
+#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_GROUP_OPENNED 0x0134
+#define SSI_TLV_EMAIL 0x0137 // Custom contact email
+#define SSI_TLV_PHONE 0x0138 // Custom contact phone number
+#define SSI_TLV_PHONE_CELLULAR 0x0139 // Custom contact cellphone number
+#define SSI_TLV_PHONE_SMS 0x013A // Custom contact SMS number
+#define SSI_TLV_COMMENT 0x013C // User comment
+#define SSI_TLV_METAINFO_TOKEN 0x015C // Privacy token for Contact's details
+#define SSI_TLV_METAINFO_TIME 0x015D // Contact's details last update time
+
+#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_PROTOCOL_NAME LPGEN("ICQ")
+#define ICQ_PLUG_VERSION __VERSION_DWORD
+#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 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 "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 PASSWORDMAXLEN 128
+#define OSCAR_PROXY_HOST "ars.icq.com"
+#define OSCAR_PROXY_VERSION 0x044A
+
+#define CLIENT_ID_STRING "ICQ Client" // Client identification, mimic ICQ 6.5
+#define CLIENT_ID_CODE 0x010a
+#define CLIENT_VERSION_MAJOR 0x0014
+#define CLIENT_VERSION_MINOR 0x0034
+#define CLIENT_VERSION_LESSER 0x0000
+#define CLIENT_VERSION_BUILD 0x0c18
+#define CLIENT_DISTRIBUTION 0x00000611
+#define CLIENT_LANGUAGE "en"
+#define CLIENT_COUNTRY "us"
+
+#endif /* __ICQ_CONSTANTS_H */
diff --git a/protocols/IcqOscarJ/icq_db.cpp b/protocols/IcqOscarJ/icq_db.cpp
new file mode 100644
index 0000000000..12b412ced3
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_db.cpp
@@ -0,0 +1,409 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_db.cpp $
+// Revision : $Revision: 12062 $
+// Last change on : $Date: 2010-06-25 10:49:28 +0300 (Пт, 25 июн 2010) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Internal Database API
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void CIcqProto::CreateResidentSetting(const char *szSetting)
+{
+ char pszSetting[2*MAX_PATH];
+
+ strcpy(pszSetting, m_szModuleName);
+ strcat(pszSetting, "/");
+ strcat(pszSetting, szSetting);
+ CallService(MS_DB_SETSETTINGRESIDENT, 1, (WPARAM)pszSetting);
+}
+
+
+int CIcqProto::getSetting(HANDLE hContact, const char *szSetting, DBVARIANT *dbv)
+{
+ return DBGetContactSettingW(hContact, m_szModuleName, szSetting, dbv);
+}
+
+
+BYTE CIcqProto::getSettingByte(HANDLE hContact, const char *szSetting, BYTE byDef)
+{
+ return DBGetContactSettingByte(hContact, m_szModuleName, szSetting, byDef);
+}
+
+
+WORD CIcqProto::getSettingWord(HANDLE hContact, const char *szSetting, WORD wDef)
+{
+ return DBGetContactSettingWord(hContact, m_szModuleName, szSetting, wDef);
+}
+
+
+DWORD CIcqProto::getSettingDword(HANDLE hContact, const char *szSetting, DWORD dwDef)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ DWORD dwRes;
+
+ if (getSetting(hContact, szSetting, &dbv))
+ 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;
+}
+
+
+double CIcqProto::getSettingDouble(HANDLE hContact, const char *szSetting, double dDef)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ double dRes;
+
+ if (getSetting(hContact, szSetting, &dbv))
+ return dDef; // not found, give default
+
+ if (dbv.type != DBVT_BLOB || dbv.cpbVal != sizeof(double))
+ dRes = dDef;
+ else
+ dRes = *(double*)dbv.pbVal;
+
+ ICQFreeVariant(&dbv);
+ return dRes;
+}
+
+
+DWORD CIcqProto::getContactUin(HANDLE hContact)
+{
+ return getSettingDword(hContact, UNIQUEIDSETTING, 0);
+}
+
+
+int CIcqProto::getContactUid(HANDLE hContact, DWORD *pdwUin, uid_str *ppszUid)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ int iRes = 1;
+
+ *pdwUin = 0;
+ if (ppszUid) *ppszUid[0] = '\0';
+
+ if (!getSetting(hContact, UNIQUEIDSETTING, &dbv))
+ {
+ if (dbv.type == DBVT_DWORD)
+ {
+ *pdwUin = dbv.dVal;
+ iRes = 0;
+ }
+ else if (dbv.type == DBVT_ASCIIZ)
+ {
+ if (ppszUid && m_bAimEnabled)
+ {
+ strcpy(*ppszUid, dbv.pszVal);
+ iRes = 0;
+ }
+ else
+ NetLog_Server("AOL screennames not accepted");
+ }
+ ICQFreeVariant(&dbv);
+ }
+ return iRes;
+}
+
+
+int CIcqProto::getSettingString(HANDLE hContact, const char *szSetting, DBVARIANT *dbv)
+{
+ int res = DBGetContactSettingString(hContact, m_szModuleName, szSetting, dbv);
+
+ if (res)
+ ICQFreeVariant(dbv);
+
+ return res;
+}
+
+
+int CIcqProto::getSettingStringW(HANDLE hContact, const char *szSetting, DBVARIANT *dbv)
+{
+ int res = DBGetContactSettingWString(hContact, m_szModuleName, szSetting, dbv);
+
+ if (res)
+ ICQFreeVariant(dbv);
+
+ return res;
+}
+
+
+char* CIcqProto::getSettingStringUtf(HANDLE hContact, const char *szModule, const char *szSetting, char *szDef)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ if (DBGetContactSettingUTF8String(hContact, szModule, szSetting, &dbv))
+ {
+ ICQFreeVariant(&dbv); // for a setting with invalid contents/type
+ return null_strdup(szDef);
+ }
+
+ char *szRes = null_strdup(dbv.pszVal);
+ ICQFreeVariant(&dbv);
+ return szRes;
+}
+
+
+char* CIcqProto::getSettingStringUtf(HANDLE hContact, const char *szSetting, char *szDef)
+{
+ return getSettingStringUtf(hContact, m_szModuleName, szSetting, szDef);
+}
+
+
+WORD CIcqProto::getContactStatus(HANDLE hContact)
+{
+ return getSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+}
+
+
+int CIcqProto::getSettingStringStatic(HANDLE hContact, const char *szSetting, char *dest, int dest_len)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ DBCONTACTGETSETTING sVal = {0};
+
+ dbv.pszVal = dest;
+ dbv.cchVal = dest_len;
+ dbv.type = DBVT_ASCIIZ;
+
+ sVal.pValue = &dbv;
+ sVal.szModule = m_szModuleName;
+ sVal.szSetting = szSetting;
+
+ if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&sVal) != 0)
+ { // due to MS_DB_CONTACT_GETSETTINGSTATIC setting type check, we need to request UTF8 as well
+ dbv.pszVal = dest;
+ dbv.cchVal = dest_len;
+ dbv.type = DBVT_UTF8;
+
+ if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&sVal) != 0)
+ return 1; // nothing found
+ }
+
+ return (dbv.type != DBVT_ASCIIZ);
+}
+
+
+int CIcqProto::deleteSetting(HANDLE hContact, const char *szSetting)
+{
+ return DBDeleteContactSetting(hContact, m_szModuleName, szSetting);
+}
+
+
+int CIcqProto::setSettingByte(HANDLE hContact, const char *szSetting, BYTE byValue)
+{
+ return DBWriteContactSettingByte(hContact, m_szModuleName, szSetting, byValue);
+}
+
+
+int CIcqProto::setSettingWord(HANDLE hContact, const char *szSetting, WORD wValue)
+{
+ return DBWriteContactSettingWord(hContact, m_szModuleName, szSetting, wValue);
+}
+
+
+int CIcqProto::setSettingDword(HANDLE hContact, const char *szSetting, DWORD dwValue)
+{
+ return DBWriteContactSettingDword(hContact, m_szModuleName, szSetting, dwValue);
+}
+
+
+int CIcqProto::setSettingDouble(HANDLE hContact, const char *szSetting, double dValue)
+{
+ return setSettingBlob(hContact, szSetting, (BYTE*)&dValue, sizeof(double));
+}
+
+
+int CIcqProto::setSettingString(HANDLE hContact, const char *szSetting, const char *szValue)
+{
+ return DBWriteContactSettingString(hContact, m_szModuleName, szSetting, szValue);
+}
+
+
+int CIcqProto::setSettingStringW(HANDLE hContact, const char *szSetting, const WCHAR *wszValue)
+{
+ return DBWriteContactSettingWString(hContact, m_szModuleName, szSetting, wszValue);
+}
+
+
+int CIcqProto::setSettingStringUtf(HANDLE hContact, const char *szModule, const char *szSetting, const char *szValue)
+{
+ return DBWriteContactSettingUTF8String(hContact, szModule, szSetting, (char*)szValue);
+}
+
+
+int CIcqProto::setSettingStringUtf(HANDLE hContact, const char *szSetting, const char *szValue)
+{
+ return setSettingStringUtf(hContact, m_szModuleName, szSetting, szValue);
+}
+
+
+int CIcqProto::setSettingBlob(HANDLE hContact, const char *szSetting, const BYTE *pValue, const int cbValue)
+{
+ return DBWriteContactSettingBlob(hContact, m_szModuleName, szSetting, (void*)pValue, cbValue);
+}
+
+
+int CIcqProto::setContactHidden(HANDLE hContact, BYTE bHidden)
+{
+ int nResult = DBWriteContactSettingByte(hContact, "CList", "Hidden", bHidden);
+
+ if (!bHidden) // clear zero setting
+ DBDeleteContactSetting(hContact, "CList", "Hidden");
+
+ return nResult;
+}
+
+void CIcqProto::setStatusMsgVar(HANDLE hContact, char* szStatusMsg, bool isAnsi)
+{
+ if (szStatusMsg && szStatusMsg[0])
+ {
+ if (isAnsi)
+ {
+ char* szStatusNote = getSettingStringUtf(hContact, DBSETTING_STATUS_NOTE, "");
+ wchar_t* szStatusNoteW = make_unicode_string(szStatusNote);
+ int len = (int)wcslen(szStatusNoteW) * 3 + 1;
+ char* szStatusNoteAnsi = (char*)alloca(len);
+ WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, szStatusNoteW, -1, szStatusNoteAnsi, len, NULL, NULL);
+ bool notmatch = false;
+ for (int i=0; ;++i)
+ {
+ if (szStatusNoteAnsi[i] != szStatusMsg[i] && szStatusNoteAnsi[i] != '?' && szStatusMsg[i] != '?')
+ {
+ notmatch = true;
+ break;
+ }
+ if (!szStatusNoteAnsi[i] || !szStatusMsg[i])
+ break;
+ }
+ szStatusMsg = notmatch ? ansi_to_utf8(szStatusMsg) : szStatusNote;
+ SAFE_FREE(&szStatusNoteW);
+ if (notmatch) SAFE_FREE(&szStatusNote);
+ }
+
+ char* oldStatusMsg = NULL;
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(hContact, "CList", "StatusMsg", &dbv))
+ {
+ switch (dbv.type)
+ {
+ case DBVT_UTF8:
+ oldStatusMsg = null_strdup(dbv.pszVal);
+ break;
+
+ case DBVT_WCHAR:
+ oldStatusMsg = make_utf8_string(dbv.pwszVal);
+ break;
+ }
+ ICQFreeVariant(&dbv);
+ }
+
+ if (!oldStatusMsg || strcmp(oldStatusMsg, szStatusMsg))
+ setSettingStringUtf(hContact, "CList", "StatusMsg", szStatusMsg);
+ SAFE_FREE(&oldStatusMsg);
+ if (isAnsi) SAFE_FREE(&szStatusMsg);
+ }
+ else
+ DBDeleteContactSetting(hContact, "CList", "StatusMsg");
+}
+
+int __fastcall ICQFreeVariant(DBVARIANT *dbv)
+{
+ return DBFreeVariant(dbv);
+}
+
+
+int CIcqProto::IsICQContact(HANDLE hContact)
+{
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ return !strcmpnull(szProto, m_szModuleName);
+}
+
+
+HANDLE CIcqProto::AddEvent(HANDLE hContact, WORD wType, DWORD dwTime, DWORD flags, DWORD cbBlob, PBYTE pBlob)
+{
+ DBEVENTINFO dbei = {0};
+
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = m_szModuleName;
+ 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 CIcqProto::FindFirstContact()
+{
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, (LPARAM)m_szModuleName);
+
+ if (IsICQContact(hContact))
+ return hContact;
+
+ return FindNextContact(hContact);
+}
+
+
+HANDLE CIcqProto::FindNextContact(HANDLE hContact)
+{
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,(LPARAM)m_szModuleName);
+
+ while (hContact != NULL)
+ {
+ if (IsICQContact(hContact))
+ {
+ return hContact;
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,(LPARAM)m_szModuleName);
+ }
+ return hContact;
+}
+
+
+char* CIcqProto::getContactCListGroup(HANDLE hContact)
+{
+ return getSettingStringUtf(hContact, "CList", "Group", NULL);
+}
+
+
+int __stdcall ICQSetContactCListGroup(HANDLE hContact, const char *szGroup)
+{
+ /// TODO
+ return 0;
+}
diff --git a/protocols/IcqOscarJ/icq_db.h b/protocols/IcqOscarJ/icq_db.h
new file mode 100644
index 0000000000..1d841f4860
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_db.h
@@ -0,0 +1,51 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000-2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001-2002 Jon Keating, Richard Hughes
+// Copyright 2002-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_db.h $
+// Revision : $Revision: 11353 $
+// Last change on : $Date: 2010-03-10 02:21:03 +0200 (Ср, 10 мар 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_DB_H
+#define __ICQ_DB_H
+
+
+#ifdef _UNICODE
+ #define getSettingStringT getSettingStringW
+ #define setSettingStringT setSettingStringW
+#else
+ #define getSettingStringT getSettingString
+ #define setSettingStringT setSettingString
+#endif
+
+int __fastcall ICQFreeVariant(DBVARIANT* dbv);
+
+#endif /* __ICQ_DB_H */
diff --git a/protocols/IcqOscarJ/icq_direct.cpp b/protocols/IcqOscarJ/icq_direct.cpp
new file mode 100644
index 0000000000..6a81a9b253
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_direct.cpp
@@ -0,0 +1,1178 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_direct.cpp $
+// Revision : $Revision: 11570 $
+// Last change on : $Date: 2010-04-11 16:58:57 +0300 (Вс, 11 апр 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+struct directthreadstartinfo
+{
+ 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
+};
+
+static 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"
+};
+
+void CIcqProto::CloseContactDirectConns(HANDLE hContact)
+{
+ icq_lock l(directConnListMutex);
+
+ for ( int i = 0; i < directConns.getCount(); i++)
+ {
+ if (!hContact || directConns[i]->hContact == hContact)
+ {
+ HANDLE hConnection = directConns[i]->hConnection;
+
+ directConns[i]->hConnection = NULL; // do not allow reuse
+ NetLib_CloseConnection(&hConnection, FALSE);
+ }
+ }
+}
+
+
+directconnect* CIcqProto::FindFileTransferDC(filetransfer* ft)
+{
+ directconnect* dc = NULL;
+ icq_lock l(directConnListMutex);
+
+ for (int i = 0; i < directConns.getCount(); i++)
+ {
+ if ( directConns[i]->ft == ft )
+ {
+ dc = directConns[i];
+ break;
+ }
+ }
+
+ return dc;
+}
+
+
+filetransfer* CIcqProto::FindExpectedFileRecv(DWORD dwUin, DWORD dwTotalSize)
+{
+ filetransfer* pFt = NULL;
+ icq_lock l(expectedFileRecvMutex);
+
+ for (int i = 0; i < expectedFileRecvs.getCount(); i++)
+ {
+ if (expectedFileRecvs[i]->dwUin == dwUin && expectedFileRecvs[i]->dwTotalSize == dwTotalSize)
+ {
+ pFt = expectedFileRecvs[i];
+ expectedFileRecvs.remove( i );
+ break;
+ }
+ }
+
+ return pFt;
+}
+
+
+int CIcqProto::sendDirectPacket(directconnect* dc, icq_packet* pkt)
+{
+ int 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((void**)&pkt->pData);
+
+ return nResult;
+}
+
+directthreadstartinfo* CreateDTSI(HANDLE hContact, HANDLE hConnection, int type)
+{
+ directthreadstartinfo* 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 CIcqProto::IsDirectConnectionOpen(HANDLE hContact, int type, int bPassive)
+{
+ BOOL bIsOpen = FALSE, bIsCreated = FALSE;
+
+ {
+ icq_lock l(directConnListMutex);
+
+ for (int i = 0; i < directConns.getCount(); i++)
+ {
+ if (directConns[i] && (directConns[i]->type == type))
+ {
+ if (directConns[i]->hContact == hContact)
+ if (directConns[i]->initialised)
+ {
+ // Connection is OK
+ bIsOpen = TRUE;
+ // we are going to use the conn, so prevent timeout
+ directConns[i]->packetPending = 1;
+ break;
+ }
+ else
+ bIsCreated = TRUE; // we found pending connection
+ }
+ }
+ }
+
+ if (!bPassive && !bIsCreated && !bIsOpen && type == DIRECTCONN_STANDARD && m_bDCMsgEnabled == 2)
+ { // do not try to open DC to offline contact
+ if (getContactStatus(hContact) == ID_STATUS_OFFLINE) return FALSE;
+ // do not try to open DC if previous attempt was not successfull
+ if (getSettingByte(hContact, "DCStatus", 0)) return FALSE;
+
+ // Set DC status as tried
+ setSettingByte(hContact, "DCStatus", 1);
+ // Create a new connection
+ OpenDirectConnection(hContact, DIRECTCONN_STANDARD, NULL);
+ }
+
+ return bIsOpen;
+}
+
+// This function is called from the Netlib when someone is connecting to
+// one of our incomming DC ports
+void icq_newConnectionReceived(HANDLE hNewConnection, DWORD dwRemoteIP, void *pExtra)
+{
+ // Start a new thread for the incomming connection
+ CIcqProto* ppro = (CIcqProto*)pExtra;
+ ppro->ForkThread(( IcqThreadFunc )&CIcqProto::icq_directThread, CreateDTSI(NULL, hNewConnection, -1));
+}
+
+// Opens direct connection of specified type to specified contact
+void CIcqProto::OpenDirectConnection(HANDLE hContact, int type, void* pvExtra)
+{
+ // Create a new connection
+ directthreadstartinfo* dtsi = CreateDTSI(hContact, NULL, type);
+ dtsi->pvExtra = pvExtra;
+ ForkThread(( IcqThreadFunc )&CIcqProto::icq_directThread, dtsi);
+}
+
+// Safely close NetLib connection - do not corrupt direct connection list
+void CIcqProto::CloseDirectConnection(directconnect *dc)
+{
+ icq_lock l(directConnListMutex);
+
+ NetLib_CloseConnection(&dc->hConnection, FALSE);
+#ifdef _DEBUG
+ if (dc->hConnection)
+ NetLog_Direct("Direct conn closed (%p)", dc->hConnection);
+#endif
+}
+
+// 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
+
+void __cdecl CIcqProto::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));
+
+ { // add to DC connection list
+ icq_lock l(directConnListMutex);
+ directConns.insert( &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 = getSettingDword(dtsi->hContact, "IP", 0);
+ dc.dwRemoteInternalIP = getSettingDword(dtsi->hContact, "RealIP", 0);
+ dc.dwRemotePort = getSettingWord(dtsi->hContact, "UserPort", 0);
+ dc.dwRemoteUin = getContactUin(dtsi->hContact);
+ dc.dwConnectionCookie = getSettingDword(dtsi->hContact, "DirectCookie", 0);
+ dc.wVersion = getSettingWord(dtsi->hContact, "Version", 0);
+
+ if (!dc.dwRemoteExternalIP && !dc.dwRemoteInternalIP)
+ { // we do not have any ip, do not try to connect
+ SAFE_FREE((void**)&dtsi);
+ goto LBL_Exit;
+ }
+ if (!dc.dwRemotePort)
+ { // we do not have port, do not try to connect
+ SAFE_FREE((void**)&dtsi);
+ goto LBL_Exit;
+ }
+
+ 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)
+ {
+ cookie_reverse_connect *pCookie = (cookie_reverse_connect*)dtsi->pvExtra;
+
+ dwReqMsgID1 = pCookie->dwMsgID1;
+ dwReqMsgID2 = pCookie->dwMsgID2;
+ dc.dwReqId = (DWORD)pCookie->ft;
+ SAFE_FREE((void**)&pCookie);
+ }
+ }
+ else
+ {
+ dc.type = DIRECTCONN_STANDARD;
+ }
+
+ SAFE_FREE((void**)&dtsi);
+
+ // Load local IP information
+ dc.dwLocalExternalIP = getSettingDword(NULL, "IP", 0);
+ dc.dwLocalInternalIP = getSettingDword(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);
+ }
+
+ // IP to connect to is empty, go away
+ if (!addr.S_un.S_addr)
+ goto LBL_Exit;
+
+ nloc.szHost = inet_ntoa(addr);
+ nloc.wPort = (WORD)dc.dwRemotePort;
+ nloc.timeout = 8; // 8 secs to connect
+ dc.hConnection = NetLib_OpenConnection(m_hDirectNetlibUser, dc.type==DIRECTCONN_REVERSE?"Reverse ":NULL, &nloc);
+ 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(m_hDirectNetlibUser, dc.type==DIRECTCONN_REVERSE?"Reverse ":NULL, &nloc);
+ }
+ if (!dc.hConnection)
+ {
+ if (CheckContactCapabilities(dc.hContact, CAPF_ICQDIRECT))
+ { // only if the contact support ICQ DC connections
+ if (dc.type != DIRECTCONN_REVERSE)
+ { // try reverse connect
+ cookie_reverse_connect *pCookie = (cookie_reverse_connect*)SAFE_MALLOC(sizeof(cookie_reverse_connect));
+ DWORD dwCookie;
+
+ NetLog_Direct("connect() failed (%d), trying reverse.", GetLastError());
+
+ if (pCookie)
+ { // init cookie
+ InitMessageCookie(pCookie);
+ pCookie->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, (cookie_message_data*)pCookie);
+ goto LBL_Exit;
+ }
+
+ NetLog_Direct("Reverse failed (%s)", "malloc failed");
+ }
+ }
+ else // Set DC status to failed
+ setSettingByte(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());
+ if (dc.type == DIRECTCONN_FILE)
+ {
+ BroadcastAck(dc.ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, dc.ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&dc.ft);
+ }
+ goto LBL_Exit;
+ }
+
+ 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);
+ goto LBL_Exit;
+ }
+ }
+
+ hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)dc.hConnection, 8192);
+ packetRecv.cbSize = sizeof(packetRecv);
+ packetRecv.bytesUsed = 0;
+
+ // Packet receiving loop
+
+ while (dc.hConnection)
+ {
+ int recvResult;
+
+ packetRecv.dwTimeout = dc.wantIdleTime ? 0 : 600000;
+
+ recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPacketRecver, (LPARAM)&packetRecv);
+ if (recvResult == 0)
+ {
+ NetLog_Direct("Clean closure of direct socket (%p)", dc.hConnection);
+ break;
+ }
+
+ if (recvResult == SOCKET_ERROR)
+ {
+ if (GetLastError() == ERROR_TIMEOUT)
+ { // TODO: this will not work on some systems
+ if (dc.wantIdleTime)
+ {
+ switch (dc.type)
+ {
+ case DIRECTCONN_FILE:
+ handleFileTransferIdle(&dc);
+ break;
+ }
+ }
+ else if (dc.packetPending)
+ { // do we expect packet soon?
+ NetLog_Direct("Keeping connection, packet pending.");
+ }
+ else
+ {
+ NetLog_Direct("Connection inactive for 10 minutes, closing.");
+ break;
+ }
+ }
+ else
+ {
+ NetLog_Direct("Abortive closure of direct socket (%p) (%d)", dc.hConnection, GetLastError());
+ break;
+ }
+ }
+
+ if (dc.type == DIRECTCONN_CLOSING)
+ packetRecv.bytesUsed = packetRecv.bytesAvailable;
+ else 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;
+ }
+ }
+
+ // End of packet receiving loop
+
+ NetLib_SafeCloseHandle(&hPacketRecver);
+ CloseDirectConnection(&dc);
+
+ if (dc.ft)
+ {
+ if (dc.ft->fileId != -1)
+ {
+ _close(dc.ft->fileId);
+ BroadcastAck(dc.ft->hContact, ACKTYPE_FILE, dc.ft->dwBytesDone==dc.ft->dwTotalSize ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, dc.ft, 0);
+ }
+ else if (dc.ft->hConnection)
+ BroadcastAck(dc.ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, dc.ft, 0);
+
+ SafeReleaseFileTransfer((void**)&dc.ft);
+ _chdir("\\"); /* so we don't leave a subdir handle open so it can't be deleted */
+ }
+
+LBL_Exit:
+ { // remove from DC connection list
+ icq_lock l(directConnListMutex);
+ directConns.remove( &dc );
+ }
+}
+
+
+void CIcqProto::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)
+ {
+ cookie_reverse_connect *pCookie;
+
+ dc->incoming = 0;
+
+ if (FindCookie(dc->dwReqId, NULL, (void**)&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 = (filetransfer*)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((void**)&pCookie);
+ break;
+ }
+ else
+ {
+ SAFE_FREE((void**)&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 != m_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 != getSettingDword(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)
+ cookie_reverse_connect *pCookie;
+
+ if (FindCookie(dc->dwReqId, NULL, (void**)&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;
+ setSettingDword(dc->hContact, "IP", dc->dwRemoteExternalIP);
+ setSettingDword(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
+ setSettingByte(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 (!m_bDCMsgEnabled)
+ { // 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;
+}
+
+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 += wsprintfA(pszBuf, "%08X: ", line);
+
+ for (col = 0; col<colsInLine; col++)
+ pszBuf += wsprintfA(pszBuf, "%02X%c", buf[line+col], (col&3)==3 && col!=15?'-':' ');
+
+ for (; col<16; col++)
+ {
+ lstrcpyA(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';
+
+ Netlib_Logf( NULL, szBuf );
+ }
+#endif
+
+ return 1;
+}
+
+// This should be called only if connection already exists
+int CIcqProto::SendDirectMessage(HANDLE hContact, icq_packet *pkt)
+{
+ icq_lock l(directConnListMutex);
+
+ for (int i = 0; i < directConns.getCount(); i++)
+ {
+ if (directConns[i] == NULL)
+ continue;
+
+ if (directConns[i]->hContact == hContact)
+ {
+ if (directConns[i]->initialised)
+ {
+ // This connection can be reused, send packet and exit
+ NetLog_Direct("Sending direct message");
+
+ if (pkt->pData[2] == 2)
+ EncryptDirectPacket(directConns[i], pkt);
+
+ sendDirectPacket(directConns[i], pkt);
+ directConns[i]->packetPending = 0; // packet done
+
+ return TRUE; // Success
+ }
+ break; // connection not ready, use server instead
+ }
+ }
+
+ return FALSE; // connection pending, we failed, use server instead
+}
+
+// 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.
+
+void CIcqProto::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, m_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.
+
+void CIcqProto::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.
+
+void CIcqProto::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.
+
+void CIcqProto::sendPeerFileInit(directconnect* dc)
+{
+ icq_packet packet;
+ DBVARIANT dbv;
+ char* szNick;
+ int nNickLen;
+
+ dbv.type = DBVT_DELETED;
+ if (getSettingString(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, (LPBYTE)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/protocols/IcqOscarJ/icq_direct.h b/protocols/IcqOscarJ/icq_direct.h
new file mode 100644
index 0000000000..851f0cc046
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_direct.h
@@ -0,0 +1,101 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_direct.h $
+// Revision : $Revision: 10352 $
+// Last change on : $Date: 2009-07-18 01:39:53 +0300 (Сб, 18 июл 2009) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_DIRECT_H
+#define __ICQ_DIRECT_H
+
+struct filetransfer: public basic_filetransfer
+{
+ 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 **pszFiles;
+ 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 ?
+};
+
+#define DIRECTCONN_STANDARD 0
+#define DIRECTCONN_FILE 1
+#define DIRECTCONN_CHAT 2
+#define DIRECTCONN_REVERSE 10
+#define DIRECTCONN_CLOSING 15
+
+struct directconnect
+{
+ 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
+};
+
+int DecryptDirectPacket(directconnect* dc, PBYTE buf, WORD wLen);
+
+#endif /* __ICQ_DIRECT_H */
diff --git a/protocols/IcqOscarJ/icq_directmsg.cpp b/protocols/IcqOscarJ/icq_directmsg.cpp
new file mode 100644
index 0000000000..5220c91cd3
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_directmsg.cpp
@@ -0,0 +1,368 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_directmsg.cpp $
+// Revision : $Revision: 11353 $
+// Last change on : $Date: 2010-03-10 02:21:03 +0200 (Ср, 10 мар 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+void CIcqProto::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 = (char*)_alloca(wTextLen+1);
+ unpackString(&buf, pszText, wTextLen);
+ pszText[wTextLen] = '\0';
+ }
+ wLen = (wLen - 2) - wTextLen;
+
+#ifdef _DEBUG
+ NetLog_Direct("Handling PEER_MSG '%s', command %u, cookie %u, messagetype %u, messageflags %u, status %u, flags %u", pszText, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags);
+#else
+ NetLog_Direct("Message through direct - UID: %u", dc->dwRemoteUin);
+#endif
+
+ // The remaining actual message is handled either as a status message request,
+ // a greeting message, a acknowledge or a normal (text, url, file) message
+ if (wCommand == DIRECT_MESSAGE)
+ switch (bMsgType)
+ {
+ case MTYPE_FILEREQ: // File inits
+ handleFileRequest(buf, wLen, dc->dwRemoteUin, wCookie, 0, 0, pszText, 7, TRUE);
+ break;
+
+ case MTYPE_AUTOAWAY:
+ case MTYPE_AUTOBUSY:
+ case MTYPE_AUTONA:
+ case MTYPE_AUTODND:
+ case MTYPE_AUTOFFC:
+ {
+ char **szMsg = MirandaStatusToAwayMsg(AwayMsgTypeToStatus(bMsgType));
+ if (szMsg)
+ icq_sendAwayMsgReplyDirect(dc, wCookie, bMsgType, ( const char** )szMsg);
+ }
+ break;
+
+ case MTYPE_PLUGIN: // Greeting
+ handleDirectGreetingMessage(dc, buf, wLen, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags, pszText);
+ break;
+
+ default:
+ {
+ message_ack_params pMsgAck = {0};
+ uid_str szUID;
+
+ buf -= wTextLen;
+ wLen += wTextLen;
+
+ pMsgAck.bType = MAT_DIRECT;
+ pMsgAck.pDC = dc;
+ pMsgAck.wCookie = wCookie;
+ pMsgAck.msgType = bMsgType;
+ pMsgAck.bFlags = bMsgFlags;
+ handleMessageTypes(dc->dwRemoteUin, szUID, time(NULL), 0, 0, wCookie, dc->wVersion, (int)bMsgType, (int)bMsgFlags, 0, (DWORD)wLen, wTextLen, (char*)buf, MTF_DIRECT, &pMsgAck);
+ break;
+ }
+ }
+ else if (wCommand == DIRECT_ACK)
+ {
+ if (bMsgFlags == 3)
+ { // this is status reply
+ uid_str szUID;
+
+ buf -= wTextLen;
+ wLen += wTextLen;
+
+ handleMessageTypes(dc->dwRemoteUin, szUID, time(NULL), 0, 0, wCookie, dc->wVersion, (int)bMsgType, (int)bMsgFlags, 2, (DWORD)wLen, wTextLen, (char*)buf, MTF_DIRECT, NULL);
+ }
+ else
+ {
+ HANDLE hCookieContact;
+ cookie_message_data *pCookieData = NULL;
+
+ if (!FindCookie(wCookie, &hCookieContact, (void**)&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 ?
+ BroadcastAck(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 CIcqProto::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 = (char*)_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 = (char*)_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)
+ {
+ uid_str szUID;
+ message_ack_params pMsgAck = {0};
+
+ pMsgAck.bType = MAT_DIRECT;
+ pMsgAck.pDC = dc;
+ pMsgAck.wCookie = wCookie;
+ pMsgAck.msgType = typeId;
+ handleMessageTypes(dc->dwRemoteUin, szUID, time(NULL), 0, 0, wCookie, dc->wVersion, typeId, 0, 0, dwLengthToEnd, (WORD)dwDataLength, (char*)buf, MTF_PLUGIN | MTF_DIRECT, &pMsgAck);
+ }
+ else if (typeId == MTYPE_STATUSMSGEXT && wCommand == DIRECT_ACK)
+ { // especially for icq2003b
+ NetLog_Direct("This is extended status reply");
+
+ char *szMsg = (char*)_alloca(dwDataLength+1);
+ uid_str szUID;
+ unpackString(&buf, szMsg, (WORD)dwDataLength);
+ szMsg[dwDataLength] = '\0';
+
+ handleMessageTypes(dc->dwRemoteUin, szUID, time(NULL), 0, 0, wCookie, dc->wVersion, (int)(qt + 0xE7), 3, 2, (DWORD)wLen, (WORD)dwDataLength, szMsg, MTF_PLUGIN | MTF_DIRECT, NULL);
+ }
+ else if (typeId && wCommand == DIRECT_ACK)
+ {
+ HANDLE hCookieContact;
+ cookie_message_data *pCookieData = NULL;
+
+ if (!FindCookie(wCookie, &hCookieContact, (void**)&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 ?
+ BroadcastAck(dc->hContact, ackType, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
+ }
+ // Release cookie
+ ReleaseCookie(wCookie);
+ }
+ }
+ else
+ NetLog_Direct("Unsupported plugin message type %s", typeId);
+}
diff --git a/protocols/IcqOscarJ/icq_fieldnames.cpp b/protocols/IcqOscarJ/icq_fieldnames.cpp
new file mode 100644
index 0000000000..85a7aad8e9
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_fieldnames.cpp
@@ -0,0 +1,602 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_fieldnames.cpp $
+// Revision : $Revision: 11199 $
+// Last change on : $Date: 2010-01-29 14:45:44 +0200 (Пт, 29 янв 2010) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+const FieldNamesItem countryField[]={
+ {9999, LPGEN("Other")},
+ {93, LPGEN("Afghanistan")},
+ {355, LPGEN("Albania")},
+ {213, LPGEN("Algeria")},
+ {376, LPGEN("Andorra")},
+ {244, LPGEN("Angola")},
+ {1264, LPGEN("Anguilla")},
+ {1268, LPGEN("Antigua and Barbuda")},
+//{5902, LPGEN("Antilles")}, /* removed: it is not a country, it's a group of islands from diffrent countries (all are included in the list)*/
+ {54, LPGEN("Argentina")},
+ {374, LPGEN("Armenia")},
+ {297, LPGEN("Aruba")},
+ {247, LPGEN("Ascension Island")},
+ {61, LPGEN("Australia")},
+ {6720, LPGEN("Australia, Antarctic Territory")}, /* added country code 672(0)*/
+ {614, LPGEN("Australia, Christmas Island")}, /* rename (from Christmas Island) and change to official county code 61(4) (from 672) */
+ {61891, LPGEN("Australia, Cocos (Keeling) Islands")}, /* rename and change to official county code 61(891) (from 6102) */
+ {6723 , LPGEN("Australia, Norfolk Island")}, /* rename (from Norfolk Island) and change to official county code 672(3) (from 6722) */
+ {43, LPGEN("Austria")},
+ {994, LPGEN("Azerbaijan")},
+ {1242, LPGEN("Bahamas")},
+ {973, LPGEN("Bahrain")},
+ {880, LPGEN("Bangladesh")},
+ {1246, LPGEN("Barbados")},
+//{120, LPGEN("Barbuda")}, /* removed: it is not a country and no special island, see Antigua and Barbuda*/
+ {375, LPGEN("Belarus")},
+ {32, LPGEN("Belgium")},
+ {501, LPGEN("Belize")},
+ {229, LPGEN("Benin")},
+ {1441, 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")},
+ {1002, LPGEN("Canada")},
+ {178, LPGEN("Canary Islands")},
+ {238, LPGEN("Cape Verde Islands")},
+ {1345, LPGEN("Cayman Islands")},
+ {236, LPGEN("Central African Republic")},
+ {235, LPGEN("Chad")},
+ {56, LPGEN("Chile, Republic of")},
+ {86, LPGEN("China")},
+//{6101, LPGEN("Cocos (Keeling) Islands")}, /* removed (double): see Australia, Cocos (Keeling) Islands */
+ {57, LPGEN("Colombia")},
+ {269, 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("Greek, Republic of South Cyprus")}, /* rename coz Turkey, Republic of Northern Cyprus */
+ {420, LPGEN("Czech Republic")},
+ {45, LPGEN("Denmark")},
+ {246, LPGEN("Diego Garcia")},
+ {253, LPGEN("Djibouti")},
+ {1767, LPGEN("Dominica")},
+ {1809, 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")},
+ {3883,LPGEN("Europe")}, /* add county code +388 3 official European Telephony Numbering Space*/
+ {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")},
+ {1473, LPGEN("Grenada")},
+ {590, LPGEN("Guadeloupe")},
+ {1671, 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")},
+ {1876, 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")},
+ {996, LPGEN("Kyrgyzstan")},
+ {856, LPGEN("Laos")},
+ {371, LPGEN("Latvia")},
+ {961, LPGEN("Lebanon")},
+ {266, LPGEN("Lesotho")},
+ {231, LPGEN("Liberia")},
+ {218, LPGEN("Libyan Arab Jamahiriya")},
+ {423, LPGEN("Liechtenstein")},
+ {370, LPGEN("Lithuania")},
+ {352, LPGEN("Luxembourg")},
+ {853, LPGEN("Macau")},
+ {389, LPGEN("Macedonia, Republic of")},
+ {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")},
+ {262, LPGEN("Mayotte Island")},
+ {52, LPGEN("Mexico")},
+ {691, LPGEN("Micronesia, Federated States of")},
+ {373, LPGEN("Moldova, Republic of")},
+ {377, LPGEN("Monaco")},
+ {976, LPGEN("Mongolia")},
+ {1664, 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")}, /* dissolved 2010 */
+ {5995, LPGEN("St. Maarten")}, /* add new country in 2010 (from Netherlands Antilles) */
+ {5999, LPGEN("Curacao")}, /* add new country in 2010 (from Netherlands Antilles) */
+ {5997, LPGEN("Netherlands (Bonaire Island)")}, /* add new Part of Netherlands in 2010 (from Netherlands Antilles) */
+ {59946, LPGEN("Netherlands (Saba Island)")}, /* add new Part of Netherlands in 2010 (from Netherlands Antilles) */
+ {59938, LPGEN("Netherlands (St. Eustatius Island)")}, /* add new Part of Netherlands in 2010 (from Netherlands Antilles) */
+//{114, LPGEN("Nevis")}, /* removed: it is not a country, it's part of Saint Kitts and Nevis*/
+ {687, LPGEN("New Caledonia")},
+ {64, LPGEN("New Zealand")},
+ {505, LPGEN("Nicaragua")},
+ {227, LPGEN("Niger")},
+ {234, LPGEN("Nigeria")},
+ {683, LPGEN("Niue")},
+ {1670, LPGEN("Northern Mariana Islands, US Territory of")}, /* added NANP */
+ {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")},
+ {1939, LPGEN("Puerto Rico")},
+ {974, LPGEN("Qatar")},
+ {262, LPGEN("Reunion Island")},
+ {40, LPGEN("Romania")},
+//{6701, LPGEN("Rota Island")}, /* removed: it is not a country it is part of Northern Mariana Islands, US Territory of */
+ {7, LPGEN("Russia")},
+ {250, LPGEN("Rwanda")},
+ {1684, LPGEN("Samoa (USA)")}, /* rename (from American Samoa) change county code to NANP (from 684) */
+ {685, LPGEN("Samoa, Western")}, /* rename (from Western Samoa) */
+ {290, LPGEN("Saint Helena")},
+//{115, LPGEN("Saint Kitts")}, /* removed: it is not a country it is part of Saint Kitts and Nevis*/
+ {1869, LPGEN("Saint Kitts and Nevis")},
+ {1758, LPGEN("Saint Lucia")},
+ {508, LPGEN("Saint Pierre and Miquelon")},
+ {1784, LPGEN("Saint Vincent and the Grenadines")},
+//{670, LPGEN("Saipan Island")}, /* removed: it is not a country it is part of Northern Mariana Islands, US Territory of */
+ {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")},
+ {3492, LPGEN("Spain, Canary Islands")}, /*rename and change county code to 34(92) spain + canary code*/
+ {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")},
+ {992, LPGEN("Tajikistan")},
+ {255, LPGEN("Tanzania")},
+ {66, LPGEN("Thailand")},
+//{6702, LPGEN("Tinian Island")}, /* removed: it is not a country it is part of Northern Mariana Islands, US Territory of */
+ {670 , LPGEN("Timor, East")}, /* added (is part off Northern Mariana Islands but not US Territory*/
+ {228, LPGEN("Togo")},
+ {690, LPGEN("Tokelau")},
+ {676, LPGEN("Tonga")},
+ {1868, LPGEN("Trinidad and Tobago")},
+ {216, LPGEN("Tunisia")},
+ {90, LPGEN("Turkey")},
+ {90392, LPGEN("Turkey, Republic of Northern Cyprus")}, /* added (is diffrent from Greek part)*/
+ {993, LPGEN("Turkmenistan")},
+ {1649, 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")},
+ {998, LPGEN("Uzbekistan")},
+ {678, LPGEN("Vanuatu")},
+ {379, LPGEN("Vatican City")},
+ {58, LPGEN("Venezuela")},
+ {84, LPGEN("Vietnam")},
+ {1284, LPGEN("Virgin Islands (UK)")}, /* change county code to NANP (from 105) - rename coz Virgin Islands (USA) */
+ {1340, LPGEN("Virgin Islands (USA)")}, /* change county code to NANP (from 123) */
+ {441, LPGEN("Wales")},
+ {681, LPGEN("Wallis and Futuna Islands")},
+ {967, LPGEN("Yemen")},
+ {38, LPGEN("Yugoslavia")},
+ {381, LPGEN("Serbia, Republic of")}, /* rename need (from Yugoslavia)*/
+ {383, LPGEN("Kosovo, Republic of")}, /*change country code (from 3811), rename need (from Yugoslavia - Serbia) */
+ {382, LPGEN("Montenegro, Republic of")}, /* rename need (from Yugoslavia - Montenegro) */
+ {260, LPGEN("Zambia")},
+ {263, LPGEN("Zimbabwe")},
+ {0, NULL}
+};
+
+
+const FieldNamesItem interestsField[]={
+ {137, LPGEN("50's")},
+ {134, LPGEN("60's")},
+ {135, LPGEN("70's")},
+ {136, LPGEN("80's")},
+ {100, LPGEN("Art")},
+ {128, LPGEN("Astronomy")},
+ {147, LPGEN("Audio and Visual")},
+ {125, LPGEN("Business")},
+ {146, LPGEN("Business Services")},
+ {101, LPGEN("Cars")},
+ {102, LPGEN("Celebrity Fans")},
+ {130, LPGEN("Clothing")},
+ {103, LPGEN("Collections")},
+ {104, LPGEN("Computers")},
+ {105, LPGEN("Culture")},
+ {122, LPGEN("Ecology")},
+ {139, LPGEN("Entertainment")},
+ {138, LPGEN("Finance and Corporate")},
+ {106, LPGEN("Fitness")},
+ {142, LPGEN("Health and Beauty")},
+ {108, LPGEN("Hobbies")},
+ {150, LPGEN("Home Automation")},
+ {144, LPGEN("Household Products")},
+ {107, LPGEN("Games")},
+ {124, LPGEN("Government")},
+ {109, LPGEN("ICQ - Help")},
+ {110, LPGEN("Internet")},
+ {111, LPGEN("Lifestyle")},
+ {145, LPGEN("Mail Order Catalog")},
+ {143, LPGEN("Media")},
+ {112, LPGEN("Movies and TV")},
+ {113, LPGEN("Music")},
+ {126, LPGEN("Mystics")},
+ {123, LPGEN("News and Media")},
+ {114, LPGEN("Outdoors")},
+ {115, LPGEN("Parenting")},
+ {131, LPGEN("Parties")},
+ {116, LPGEN("Pets and Animals")},
+ {149, LPGEN("Publishing")},
+ {117, LPGEN("Religion")},
+ {141, LPGEN("Retail Stores")},
+ {118, LPGEN("Science")},
+ {119, LPGEN("Skills")},
+ {133, LPGEN("Social science")},
+ {129, LPGEN("Space")},
+ {148, LPGEN("Sporting and Athletic")},
+ {120, LPGEN("Sports")},
+ {127, LPGEN("Travel")},
+ {121, LPGEN("Web Design")},
+ {132, LPGEN("Women")},
+ {-1, NULL}
+};
+
+
+const FieldNamesItem languageField[]={
+ {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("Farsi")},
+ {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("Serbian")},
+ {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("Taiwanese")},
+ {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")},
+ {0, NULL}
+};
+
+
+const FieldNamesItem 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")},
+ {0, NULL}
+};
+
+
+const FieldNamesItem genderField[]={
+ {'F', LPGEN("Female")},
+ {'M', LPGEN("Male")},
+ {0, NULL}
+};
+
+
+const FieldNamesItem studyLevelField[]={
+ {4, LPGEN("Associated degree")},
+ {5, LPGEN("Bachelor's degree")},
+ {1, LPGEN("Elementary")},
+ {2, LPGEN("High-school")},
+ {6, LPGEN("Master's degree")},
+ {7, LPGEN("PhD")},
+ {8, LPGEN("Postdoctoral")},
+ {3, LPGEN("University / College")},
+ {0, NULL}
+};
+
+
+const FieldNamesItem industryField[]={
+ {2, LPGEN("Agriculture")},
+ {3, LPGEN("Arts")},
+ {4, LPGEN("Construction")},
+ {5, LPGEN("Consumer Goods")},
+ {6, LPGEN("Corporate Services")},
+ {7, LPGEN("Education")},
+ {8, LPGEN("Finance")},
+ {9, LPGEN("Government")},
+ {10, LPGEN("High Tech")},
+ {11, LPGEN("Legal")},
+ {12, LPGEN("Manufacturing")},
+ {13, LPGEN("Media")},
+ {14, LPGEN("Medical & Health Care")},
+ {15, LPGEN("Non-Profit Organization Management")},
+ {19, LPGEN("Other")},
+ {16, LPGEN("Recreation, Travel & Entertainment")},
+ {17, LPGEN("Service Industry")},
+ {18, LPGEN("Transportation")},
+ {0, NULL}
+};
+
+
+const FieldNamesItem occupationField[]={
+ {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")},
+ {0, NULL}
+};
+
+
+const FieldNamesItem 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")},
+ {0, NULL}
+};
+
+
+const FieldNamesItem 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}
+};
+
+
+const FieldNamesItem maritalField[]={
+ {10, LPGEN("Single")},
+ {11, LPGEN("Close relationships")},
+ {12, LPGEN("Engaged")},
+ {20, LPGEN("Married")},
+ {30, LPGEN("Divorced")},
+ {31, LPGEN("Separated")},
+ {40, LPGEN("Widowed")},
+ {50, LPGEN("Open relationship")},
+ {255, LPGEN("Other")},
+ {0, NULL}
+};
+
+
+char *LookupFieldName(const FieldNamesItem *table, int code)
+{
+ int i;
+
+ if (code != 0)
+ {
+ for(i = 0; table[i].text; i++)
+ {
+ if (table[i].code == code)
+ return table[i].text;
+ }
+
+ // Tried to get unexisting field name, you have an
+ // error in the data or in the table
+ _ASSERT(FALSE);
+ }
+
+ return NULL;
+}
+
+
+char *LookupFieldNameUtf(const FieldNamesItem *table, int code, char *str, size_t strsize)
+{
+ char *szText = LookupFieldName(table, code);
+
+ if (szText)
+ return ICQTranslateUtfStatic(szText, str, strsize);
+
+ return NULL;
+}
diff --git a/protocols/IcqOscarJ/icq_fieldnames.h b/protocols/IcqOscarJ/icq_fieldnames.h
new file mode 100644
index 0000000000..d3cf772c13
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_fieldnames.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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_fieldnames.h $
+// Revision : $Revision: 8822 $
+// Last change on : $Date: 2009-01-11 19:17:05 +0200 (Вс, 11 янв 2009) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+struct FieldNamesItem
+{
+ int code;
+ char *text;
+};
+
+extern const FieldNamesItem countryField[];
+extern const FieldNamesItem interestsField[];
+extern const FieldNamesItem languageField[];
+extern const FieldNamesItem pastField[];
+extern const FieldNamesItem genderField[];
+extern const FieldNamesItem agesField[];
+extern const FieldNamesItem studyLevelField[];
+extern const FieldNamesItem industryField[];
+extern const FieldNamesItem occupationField[];
+extern const FieldNamesItem affiliationField[];
+extern const FieldNamesItem maritalField[];
+
+char *LookupFieldName(const FieldNamesItem *table, int code);
+char *LookupFieldNameUtf(const FieldNamesItem *table, int code, char *str, size_t strsize);
diff --git a/protocols/IcqOscarJ/icq_filerequests.cpp b/protocols/IcqOscarJ/icq_filerequests.cpp
new file mode 100644
index 0000000000..df49717199
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_filerequests.cpp
@@ -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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_filerequests.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+void CIcqProto::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, (void**)&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);
+ BroadcastAck(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 = (char*)_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);
+
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)ft, 0);
+
+ OpenDirectConnection(ft->hContact, DIRECTCONN_FILE, ft);
+}
+
+filetransfer* CIcqProto::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 CIcqProto::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 = Translate("No description given");
+ bEmptyDesc = TRUE;
+ }
+
+ // Empty port+pad
+ buf += 4;
+ wLen -= 4;
+
+ // Filename
+ unpackLEWord(&buf, &wFilenameLength);
+ if (wFilenameLength > 0)
+ {
+ pszFileName = (char*)_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;
+
+ int bAdded;
+ HANDLE hContact = HContactFromUIN(dwUin, &bAdded);
+
+ // Initialize a filetransfer struct
+ filetransfer *ft = CreateFileTransfer(hContact, dwUin, nVersion);
+ ft->dwCookie = dwCookie;
+ ft->szFilename = ansi_to_utf8(pszFileName);
+ ft->szDescription = ansi_to_utf8(pszDescription);
+ ft->fileId = -1;
+ ft->dwTotalSize = dwFileSize;
+ ft->pMessage.dwMsgID1 = dwID1;
+ ft->pMessage.dwMsgID2 = dwID2;
+ ft->bDC = bDC;
+ ft->bEmptyDesc = bEmptyDesc;
+
+ // Send chain event
+ char *szBlob = (char*)_alloca(sizeof(DWORD) + strlennull(pszFileName) + strlennull(pszDescription) + 2);
+ *(PDWORD)szBlob = 0;
+ strcpy(szBlob + sizeof(DWORD), pszFileName);
+ strcpy(szBlob + sizeof(DWORD) + strlennull(pszFileName) + 1, pszDescription);
+
+ PROTORECVEVENT pre;
+ pre.flags = 0;
+ pre.timestamp = time(NULL);
+ pre.szMessage = szBlob;
+ pre.lParam = (LPARAM)ft;
+
+ CCSDATA ccs;
+ ccs.szProtoService = PSR_FILE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)&pre;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+}
+
+
+void CIcqProto::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 CIcqProto::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);
+
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+
+ if (!FindFileTransferDC(ft))
+ { // Release orphan structure only
+ SafeReleaseFileTransfer((void**)&ft);
+ }
+ }
+}
diff --git a/protocols/IcqOscarJ/icq_filetransfer.cpp b/protocols/IcqOscarJ/icq_filetransfer.cpp
new file mode 100644
index 0000000000..ed81ad4c5a
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_filetransfer.cpp
@@ -0,0 +1,522 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_filetransfer.cpp $
+// Revision : $Revision: 12331 $
+// Last change on : $Date: 2010-08-18 16:59:50 +0300 (Ср, 18 авг 2010) $
+// Last change by : $Author: george.hazan $
+//
+// 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->flags = PFTS_UTF | (ft->sending ? PFTS_SENDING : PFTS_RECEIVING); /* Standard FT is Ansi only */
+ if (ft->sending)
+ pfts->pszFiles = ft->pszFiles;
+ else
+ pfts->pszFiles = NULL; /* FIXME */
+ pfts->totalFiles = ft->dwFileCount;
+ pfts->currentFileNumber = ft->iCurrentFile;
+ pfts->totalBytes = ft->dwTotalSize;
+ pfts->totalProgress = ft->dwBytesDone;
+ pfts->szWorkingDir = ft->szSavePath;
+ pfts->szCurrentFile = ft->szThisFile;
+ pfts->currentFileSize = ft->dwThisFileSize;
+ pfts->currentFileTime = ft->dwThisFileDate;
+ pfts->currentFileProgress = ft->dwFileBytesDone;
+}
+
+
+static void file_sendTransferSpeed(CIcqProto* ppro, directconnect* dc)
+{
+ icq_packet packet;
+
+ directPacketInit(&packet, 5);
+ packByte(&packet, PEER_FILE_SPEED); /* Ident */
+ packLEDWord(&packet, dc->ft->dwTransferSpeed);
+ ppro->sendDirectPacket(dc, &packet);
+}
+
+
+static void file_sendNick(CIcqProto* ppro, directconnect* dc)
+{
+ icq_packet packet;
+ char* szNick;
+ WORD wNickLen;
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ if (ppro->getSettingString(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, (LPBYTE)szNick, (WORD)(wNickLen + 1));
+ ppro->sendDirectPacket(dc, &packet);
+ ICQFreeVariant(&dbv);
+}
+
+
+static void file_sendNextFile(CIcqProto* ppro, directconnect* dc)
+{
+ icq_packet packet;
+ struct _stati64 statbuf;
+ char szThisSubDir[MAX_PATH];
+
+ if (dc->ft->iCurrentFile >= (int)dc->ft->dwFileCount)
+ {
+ ppro->BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, dc->ft, 0);
+ ppro->CloseDirectConnection(dc);
+ dc->ft->hConnection = NULL;
+ return;
+ }
+
+ dc->ft->szThisFile = dc->ft->pszFiles[dc->ft->iCurrentFile];
+ if (FileStatUtf(dc->ft->szThisFile, &statbuf))
+ {
+ ppro->icq_LogMessage(LOG_ERROR, LPGEN("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."));
+ ppro->CloseDirectConnection(dc);
+ dc->ft->hConnection = NULL;
+ return;
+ }
+
+ char *pszThisFileName = FindFilePathContainer((LPCSTR*)dc->ft->pszFiles, dc->ft->iCurrentFile, szThisSubDir);
+
+ if (statbuf.st_mode&_S_IFDIR)
+ {
+ dc->ft->currentIsDir = 1;
+ }
+ else
+ {
+ dc->ft->currentIsDir = 0;
+ dc->ft->fileId = OpenFileUtf(dc->ft->szThisFile, _O_BINARY | _O_RDONLY, _S_IREAD);
+ if (dc->ft->fileId == -1)
+ {
+ ppro->icq_LogMessage(LOG_ERROR, LPGEN("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."));
+ ppro->CloseDirectConnection(dc);
+ dc->ft->hConnection = NULL;
+ return;
+ }
+
+ }
+ dc->ft->dwThisFileSize = statbuf.st_size;
+ dc->ft->dwThisFileDate = statbuf.st_mtime;
+ dc->ft->dwFileBytesDone = 0;
+
+ char *szThisFileNameAnsi = NULL, *szThisSubDirAnsi = NULL;
+ if (!utf8_decode(pszThisFileName, &szThisFileNameAnsi))
+ szThisFileNameAnsi = NULL;
+ if (!utf8_decode(szThisSubDir, &szThisSubDirAnsi))
+ szThisSubDirAnsi = NULL;
+ WORD wThisFileNameLen = strlennull(szThisFileNameAnsi);
+ WORD wThisSubDirLen = strlennull(szThisSubDirAnsi);
+
+ 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, (LPBYTE)szThisFileNameAnsi, (WORD)(wThisFileNameLen + 1));
+ packLEWord(&packet, (WORD)(wThisSubDirLen + 1));
+ packBuffer(&packet, (LPBYTE)szThisSubDirAnsi, (WORD)(wThisSubDirLen + 1));
+ packLEDWord(&packet, dc->ft->dwThisFileSize);
+ packLEDWord(&packet, statbuf.st_mtime);
+ packLEDWord(&packet, dc->ft->dwTransferSpeed);
+ SAFE_FREE(&szThisFileNameAnsi);
+ SAFE_FREE(&szThisSubDirAnsi);
+ ppro->sendDirectPacket(dc, &packet);
+
+ ppro->BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, dc->ft, 0);
+}
+
+
+static void file_sendResume(CIcqProto* ppro, 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 */
+ ppro->sendDirectPacket(dc, &packet);
+}
+
+
+static void file_sendData(CIcqProto* ppro, 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);
+ ppro->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);
+ ppro->BroadcastAck(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(ppro, dc); /* this will close the socket if no more files */
+ }
+}
+
+
+void CIcqProto::handleFileTransferIdle(directconnect* dc)
+{
+ file_sendData(this, dc);
+}
+
+
+void CIcqProto::icq_sendFileResume(filetransfer *ft, int action, const char *szFilename)
+{
+ if (ft->hConnection == NULL)
+ return;
+
+ directconnect *dc = FindFileTransferDC(ft);
+ if (!dc) return; // something is broken...
+
+ int openFlags;
+
+ 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 = OpenFileUtf(ft->szThisFile, openFlags, _S_IREAD | _S_IWRITE);
+ if (ft->fileId == -1)
+ {
+ icq_LogMessage(LOG_ERROR, LPGEN("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(this, dc);
+
+ BroadcastAck(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 CIcqProto::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(this, dc);
+ file_sendNick(this, dc);
+ }
+ BroadcastAck(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(this, dc);
+ break;
+
+ case PEER_FILE_NEXTFILE:
+ if (wLen < 20)
+ return;
+ buf++; /* id */
+ {
+ char *szAnsi;
+ WORD wThisFilenameLen, wSubdirLen;
+ BYTE isDirectory;
+
+ unpackByte(&buf, &isDirectory);
+ unpackLEWord(&buf, &wThisFilenameLen);
+ if (wLen < 19 + wThisFilenameLen)
+ return;
+ SAFE_FREE(&dc->ft->szThisFile);
+ szAnsi = (char *)_alloca(wThisFilenameLen + 1);
+ memcpy(szAnsi, buf, wThisFilenameLen);
+ szAnsi[wThisFilenameLen] = '\0';
+ dc->ft->szThisFile = ansi_to_utf8(szAnsi);
+ buf += wThisFilenameLen;
+
+ unpackLEWord(&buf, &wSubdirLen);
+ if (wLen < 18 + wThisFilenameLen + wSubdirLen)
+ return;
+ SAFE_FREE(&dc->ft->szThisSubdir);
+ szAnsi = (char *)_alloca(wSubdirLen + 1);
+ memcpy(szAnsi, buf, wSubdirLen);
+ szAnsi[wSubdirLen] = '\0';
+ dc->ft->szThisSubdir = ansi_to_utf8(szAnsi);
+ 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;
+ }
+
+ char *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)
+ {
+ MakeDirUtf(dc->ft->szThisFile);
+ dc->ft->fileId = -1;
+ }
+ else
+ {
+ /* file resume */
+ PROTOFILETRANSFERSTATUS pfts = {0};
+
+ file_buildProtoFileTransferStatus(dc->ft, &pfts);
+ if (BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, dc->ft, (LPARAM)&pfts))
+ break; /* UI supports resume: it will call PS_FILERESUME */
+
+ dc->ft->fileId = OpenFileUtf(dc->ft->szThisFile, _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY, _S_IREAD | _S_IWRITE);
+ if (dc->ft->fileId == -1)
+ {
+ icq_LogMessage(LOG_ERROR, LPGEN("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(this, dc);
+ BroadcastAck(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);
+ BroadcastAck(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 */
+ BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, dc->ft, 0);
+ }
+ }
+ break;
+
+ default:
+ NetLog_Direct("Unknown file transfer packet ignored.");
+ break;
+ }
+}
diff --git a/protocols/IcqOscarJ/icq_firstrun.cpp b/protocols/IcqOscarJ/icq_firstrun.cpp
new file mode 100644
index 0000000000..c1c596a60b
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_firstrun.cpp
@@ -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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_firstrun.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+static void accountLoadDetails(CIcqProto *ppro, HWND hwndDlg)
+{
+ char pszUIN[20];
+ DWORD dwUIN = ppro->getContactUin(NULL);
+ if (dwUIN)
+ {
+ null_snprintf(pszUIN, 20, "%u", dwUIN);
+ SetDlgItemTextA(hwndDlg, IDC_UIN, pszUIN);
+ }
+
+ char pszPwd[PASSWORDMAXLEN];
+ if (ppro->GetUserStoredPassword(pszPwd, PASSWORDMAXLEN))
+ SetDlgItemTextA(hwndDlg, IDC_PW, pszPwd);
+}
+
+
+INT_PTR CALLBACK icq_FirstRunDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = (CIcqProto*)GetWindowLongPtr( hwndDlg, GWLP_USERDATA );
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ ppro = (CIcqProto*)lParam;
+ SetWindowLongPtr( hwndDlg, GWLP_USERDATA, lParam );
+ {
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)ppro->m_hIconProtocol->GetIcon(true));
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)ppro->m_hIconProtocol->GetIcon());
+
+ SendDlgItemMessage(hwndDlg, IDC_PW, EM_LIMITTEXT, PASSWORDMAXLEN - 1, 0);
+
+ accountLoadDetails(ppro, hwndDlg);
+ }
+ return TRUE;
+
+ case WM_DESTROY:
+ ppro->m_hIconProtocol->ReleaseIcon(true);
+ ppro->m_hIconProtocol->ReleaseIcon();
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_REGISTER:
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM)URL_REGISTER);
+ break;
+
+ case IDC_UIN:
+ case IDC_PW:
+ if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus())
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ char str[128];
+ GetDlgItemTextA(hwndDlg, IDC_UIN, str, sizeof(str));
+ ppro->setSettingDword(NULL, UNIQUEIDSETTING, atoi(str));
+ GetDlgItemTextA(hwndDlg, IDC_PW, str, sizeof(ppro->m_szPassword));
+ strcpy(ppro->m_szPassword, str);
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(ppro->m_szPassword), (LPARAM) str);
+ ppro->setSettingString(NULL, "Password", str);
+ }
+ break;
+
+ case PSN_RESET:
+ accountLoadDetails(ppro, hwndDlg);
+ break;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+INT_PTR CIcqProto::OnCreateAccMgrUI(WPARAM wParam, LPARAM lParam)
+{
+ return (INT_PTR)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ICQACCOUNT), (HWND)lParam, icq_FirstRunDlgProc, LPARAM(this));
+}
diff --git a/protocols/IcqOscarJ/icq_http.cpp b/protocols/IcqOscarJ/icq_http.cpp
new file mode 100644
index 0000000000..1acc5f54d9
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_http.cpp
@@ -0,0 +1,219 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001,2002 Jon Keating, Richard Hughes
+// Copyright 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004,2005,2006 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_http.c,v $
+// Revision : $Revision: 12606 $
+// Last change on : $Date: 2010-09-06 15:38:27 +0300 (Пн, 06 сен 2010) $
+// Last change by : $Author: borkra $
+//
+// 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 *buf;
+ char szSid[33], szHttpServer[256], szHttpGetUrl[300], szHttpPostUrl[300];
+ NETLIBHTTPPROXYINFO nlhpi = {0};
+
+ if (nlhr->dataLength < 31)
+ {
+ SetLastError(ERROR_INVALID_DATA);
+ return 0;
+ }
+
+ buf = (PBYTE)nlhr->pData;
+ 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(nlhr->dataLength < 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;
+ size_t serverNameLen;
+
+ serverNameLen = strlennull(nloc->szHost);
+
+ packet.wLen = (WORD)(serverNameLen + 4);
+ write_httphdr(&packet, HTTP_PACKETTYPE_LOGIN, GetGatewayIndex(hConn));
+ packWord(&packet, (WORD)serverNameLen);
+ packBuffer(&packet, (LPBYTE)nloc->szHost, (WORD)serverNameLen);
+ packWord(&packet, nloc->wPort);
+ INT_PTR res = Netlib_Send(hConn, (char*)packet.pData, packet.wLen, MSG_DUMPPROXY|MSG_NOHTTPGATEWAYWRAP);
+ SAFE_FREE((void**)&packet.pData);
+
+ return res != SOCKET_ERROR;
+}
+
+
+
+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);
+
+ NETLIBBUFFER nlb={ (char*)packet.pData, packet.wLen, flags };
+ curResult = pfnNetlibSend((WPARAM)hConn, (LPARAM)&nlb);
+
+ SAFE_FREE((void**)&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)
+ Netlib_Logf( NULL, "Gateway Connection #%d Established.", dwPackSeq);
+ else
+ Netlib_Logf( NULL, "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
+ Netlib_Logf( NULL, "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, (char*)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/protocols/IcqOscarJ/icq_http.h b/protocols/IcqOscarJ/icq_http.h
new file mode 100644
index 0000000000..60fb2ba416
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_http.h
@@ -0,0 +1,55 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001,2002 Jon Keating, Richard Hughes
+// Copyright 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004,2005 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_http.h,v $
+// Revision : $Revision: 7500 $
+// Last change on : $Date: 2008-03-24 20:07:37 +0200 (Пн, 24 мар 2008) $
+// Last change by : $Author: jokusoftware $
+//
+// 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/protocols/IcqOscarJ/icq_infoupdate.cpp b/protocols/IcqOscarJ/icq_infoupdate.cpp
new file mode 100644
index 0000000000..dd73af7ded
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_infoupdate.cpp
@@ -0,0 +1,415 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_infoupdate.cpp $
+// Revision : $Revision: 13091 $
+// Last change on : $Date: 2010-11-01 21:07:18 +0200 (Пн, 01 ноя 2010) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Background thread for automatic update of user details
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+// Retrieve users' info
+void CIcqProto::icq_InitInfoUpdate(void)
+{
+ // Create wait objects
+ hInfoQueueEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ if (hInfoQueueEvent)
+ {
+ // Init mutexes
+ infoUpdateMutex = new icq_critical_section();
+
+ // Init list
+ for (int i = 0; i<LISTSIZE; i++)
+ {
+ m_infoUpdateList[i].dwUin = 0;
+ m_infoUpdateList[i].hContact = NULL;
+ m_infoUpdateList[i].queued = 0;
+ }
+
+ hInfoThread = ForkThreadEx( &CIcqProto::InfoUpdateThread, NULL );
+ }
+
+ bInfoPendingUsers = 0;
+ dwInfoActiveRequest = 0;
+}
+
+// Returns TRUE if user was queued
+// Returns FALSE if the list was full
+BOOL CIcqProto::icq_QueueUser(HANDLE hContact)
+{
+ if ( !infoUpdateMutex )
+ return FALSE;
+
+ if (nInfoUserCount < LISTSIZE)
+ {
+ int i, nChecked = 0, nFirstFree = -1;
+ BOOL bFound = FALSE;
+
+ infoUpdateMutex->Enter();
+
+ // Check if in list
+ for (i = 0; (i<LISTSIZE && nChecked < nInfoUserCount); i++)
+ {
+ if (m_infoUpdateList[i].hContact)
+ {
+ nChecked++;
+ if (m_infoUpdateList[i].hContact == hContact)
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+ else if (nFirstFree == -1)
+ {
+ nFirstFree = i;
+ }
+ }
+ if (nFirstFree == -1)
+ nFirstFree = i;
+
+ // Add to list
+ if (!bFound)
+ {
+ DWORD dwUin = getContactUin(hContact);
+
+ if (dwUin)
+ {
+ m_infoUpdateList[nFirstFree].dwUin = dwUin;
+ m_infoUpdateList[nFirstFree].hContact = hContact;
+ m_infoUpdateList[nFirstFree].queued = time(NULL);
+ nInfoUserCount++;
+#ifdef _DEBUG
+ NetLog_Server("Queued user %u, place %u, count %u", dwUin, nFirstFree, nInfoUserCount);
+#endif
+ // Notify worker thread
+ if (hInfoQueueEvent && bInfoUpdateEnabled)
+ SetEvent(hInfoQueueEvent);
+ }
+ }
+
+ infoUpdateMutex->Leave();
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+void CIcqProto::icq_DequeueUser(DWORD dwUin)
+{
+ if (nInfoUserCount > 0)
+ {
+ int nChecked = 0;
+ // Check if in list
+ infoUpdateMutex->Enter();
+ for (int i = 0; (i < LISTSIZE && nChecked < nInfoUserCount); i++)
+ {
+ if (m_infoUpdateList[i].dwUin)
+ {
+ nChecked++;
+ // Remove from list
+ if (m_infoUpdateList[i].dwUin == dwUin)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Dequeued user %u", m_infoUpdateList[i].dwUin);
+#endif
+ m_infoUpdateList[i].dwUin = 0;
+ m_infoUpdateList[i].hContact = NULL;
+ m_infoUpdateList[i].queued = 0;
+ nInfoUserCount--;
+ break;
+ }
+ }
+ }
+ infoUpdateMutex->Leave();
+ }
+}
+
+
+void CIcqProto::icq_RescanInfoUpdate()
+{
+ HANDLE hContact = NULL;
+ BOOL bOldEnable = bInfoUpdateEnabled;
+
+ bInfoPendingUsers = 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 */
+ bInfoUpdateEnabled = 0; // freeze thread
+ // Queue all outdated users
+ hContact = FindFirstContact();
+
+ while (hContact != NULL)
+ {
+ if (IsMetaInfoChanged(hContact))
+ { // Queue user
+ if (!icq_QueueUser(hContact))
+ { // The queue is full, pause queuing contacts
+ bInfoPendingUsers = 1;
+ break;
+ }
+ }
+ hContact = FindNextContact(hContact);
+ }
+ icq_EnableUserLookup(bOldEnable); // wake up thread
+}
+
+
+void CIcqProto::icq_EnableUserLookup(BOOL bEnable)
+{
+ bInfoUpdateEnabled = bEnable;
+
+ // Notify worker thread
+ if (bInfoUpdateEnabled && hInfoQueueEvent)
+ SetEvent(hInfoQueueEvent);
+}
+
+
+void __cdecl CIcqProto::InfoUpdateThread( void* )
+{
+ int i;
+ DWORD dwWait = WAIT_OBJECT_0;
+
+ NetLog_Server("%s thread starting.", "Info-Update");
+
+ bInfoUpdateRunning = TRUE;
+
+ while (bInfoUpdateRunning)
+ {
+ // Wait for a while
+ ResetEvent(hInfoQueueEvent);
+
+ if (!nInfoUserCount && bInfoPendingUsers) // whole queue processed, check if more users needs updating
+ icq_RescanInfoUpdate();
+
+ if (!nInfoUserCount || !bInfoUpdateEnabled || !icqOnline())
+ {
+ dwWait = WAIT_TIMEOUT;
+ while (bInfoUpdateRunning && dwWait == WAIT_TIMEOUT)
+ { // wait for new work or until we should end
+ dwWait = ICQWaitForSingleObject(hInfoQueueEvent, 10000);
+ }
+ }
+ if (!bInfoUpdateRunning) 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 (!bInfoUpdateEnabled) continue; // we can't send requests now
+
+ if (nInfoUserCount && icqOnline())
+ {
+ time_t now = time(NULL);
+ BOOL bNotReady = FALSE, bTimeOuted = FALSE;
+
+ // Check the list, take only users that were there for at least 5sec
+ // wait if any user is there shorter than 5sec and not a single user is there longer than 20sec
+ infoUpdateMutex->Enter();
+ for (i = 0; i<LISTSIZE; i++)
+ {
+ if (m_infoUpdateList[i].hContact)
+ {
+ if (m_infoUpdateList[i].queued + 20 < now)
+ {
+ bTimeOuted = TRUE;
+ break;
+ }
+ else if (m_infoUpdateList[i].queued + 5 >= now)
+ bNotReady = TRUE;
+ }
+ }
+ infoUpdateMutex->Leave();
+
+ if (!bTimeOuted && bNotReady)
+ {
+ SleepEx(1000, TRUE);
+ if (!bInfoUpdateRunning)
+ { // need to end as fast as possible
+ NetLog_Server("%s thread ended.", "Info-Update");
+ return;
+ }
+ continue;
+ }
+
+ if (FindCookie(dwInfoActiveRequest, NULL, NULL))
+ { // only send another request, when the previous is completed
+#ifdef _DEBUG
+ NetLog_Server("Info-Update: Request 0x%x still in progress.", dwInfoActiveRequest);
+#endif
+ SleepEx(1000, TRUE);
+ if (!bInfoUpdateRunning)
+ { // need to end as fast as possible
+ NetLog_Server("%s thread ended.", "Info-Update");
+ return;
+ }
+ continue;
+ }
+
+#ifdef _DEBUG
+ NetLog_Server("Info-Update: Users %u in queue.", nInfoUserCount);
+#endif
+ // Either some user is waiting long enough, or all users are ready (waited at least the minimum time)
+ m_ratesMutex->Enter();
+ if (!m_rates)
+ { // we cannot send info request - icq is offline
+ m_ratesMutex->Leave();
+ break;
+ }
+ WORD wGroup = m_rates->getGroupFromSNAC(ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQUEST);
+ while (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(wGroup, RML_IDLE_30))
+ { // we are over rate, need to wait before sending
+ int nDelay = m_rates->getDelayToLimitLevel(wGroup, RML_IDLE_50);
+
+ m_ratesMutex->Leave();
+#ifdef _DEBUG
+ NetLog_Server("Rates: InfoUpdate delayed %dms", nDelay);
+#endif
+ SleepEx(nDelay, TRUE); // do not keep things locked during sleep
+ if (!bInfoUpdateRunning)
+ { // need to end as fast as possible
+ NetLog_Server("%s thread ended.", "Info-Update");
+ return;
+ }
+ m_ratesMutex->Enter();
+ if (!m_rates) // we lost connection when we slept, go away
+ break;
+ }
+ if (!m_rates)
+ { // we cannot send info request - icq is offline
+ m_ratesMutex->Leave();
+ break;
+ }
+ m_ratesMutex->Leave();
+
+ userinfo *hContactList[LISTSIZE];
+ int nListIndex = 0;
+ BYTE *pRequestData = NULL;
+ int nRequestSize = 0;
+
+ infoUpdateMutex->Enter();
+ for (i = 0; i<LISTSIZE; i++)
+ {
+ if (m_infoUpdateList[i].hContact)
+ {
+ // check TS again, maybe it has been updated while we slept
+ if (IsMetaInfoChanged(m_infoUpdateList[i].hContact))
+ {
+ if (m_infoUpdateList[i].queued + 5 < now)
+ {
+ BYTE *pItem = NULL;
+ int nItemSize = 0;
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ if (!getSetting(m_infoUpdateList[i].hContact, DBSETTING_METAINFO_TOKEN, &dbv))
+ { // retrieve user details using privacy token
+ ppackTLV(&pItem, &nItemSize, 0x96, dbv.cpbVal, dbv.pbVal);
+ ICQFreeVariant(&dbv);
+ }
+ // last updated time
+ ppackTLVDouble(&pItem, &nItemSize, 0x64, getSettingDouble(m_infoUpdateList[i].hContact, DBSETTING_METAINFO_TIME, 0));
+
+ ppackTLVUID(&pItem, &nItemSize, 0x32, m_infoUpdateList[i].dwUin, NULL);
+ ppackWord(&pRequestData, &nRequestSize, (WORD)nItemSize);
+ ppackBuffer(&pRequestData, &nRequestSize, nItemSize, pItem);
+ // take a reference
+ SAFE_FREE((void**)&pItem);
+ hContactList[nListIndex++] = &m_infoUpdateList[i];
+ }
+ }
+ else
+ {
+#ifdef _DEBUG
+ NetLog_Server("Dequeued absolete user %u", m_infoUpdateList[i].dwUin);
+#endif
+ // Dequeue user and find another one
+ m_infoUpdateList[i].dwUin = 0;
+ m_infoUpdateList[i].hContact = NULL;
+ nInfoUserCount--;
+ // continue for loop
+ }
+ }
+ }
+
+#ifdef _DEBUG
+ NetLog_Server("Request info for %u user(s).", nListIndex);
+#endif
+ if (!nListIndex)
+ { // no users to request info for
+ infoUpdateMutex->Leave();
+ break;
+ }
+ if (!(dwInfoActiveRequest = sendUserInfoMultiRequest(pRequestData, nRequestSize, nListIndex)))
+ { // sending data packet failed
+ SAFE_FREE((void**)&pRequestData);
+ infoUpdateMutex->Leave();
+ break;
+ }
+ SAFE_FREE((void**)&pRequestData);
+
+ for (i = 0; i<nListIndex; i++)
+ { // Dequeue users and go back to sleep
+ hContactList[i]->dwUin = 0;
+ hContactList[i]->hContact = NULL;
+ hContactList[i]->queued = 0;
+ nInfoUserCount--;
+ }
+ infoUpdateMutex->Leave();
+ }
+ break;
+
+ default:
+ // Something strange happened. Exit
+ bInfoUpdateRunning = FALSE;
+ break;
+ }
+ }
+ NetLog_Server("%s thread ended.", "Info-Update");
+}
+
+
+// Clean up before exit
+void CIcqProto::icq_InfoUpdateCleanup(void)
+{
+ bInfoUpdateRunning = FALSE;
+ SetEvent(hInfoQueueEvent); // break queue loop
+ if (hInfoThread) ICQWaitForSingleObject(hInfoThread, INFINITE, TRUE);
+ // Uninit mutex
+ SAFE_DELETE(&infoUpdateMutex);
+ CloseHandle(hInfoQueueEvent);
+ CloseHandle(hInfoThread);
+}
diff --git a/protocols/IcqOscarJ/icq_infoupdate.h b/protocols/IcqOscarJ/icq_infoupdate.h
new file mode 100644
index 0000000000..6d59811815
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_infoupdate.h
@@ -0,0 +1,35 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_infoupdate.h $
+// Revision : $Revision: 7500 $
+// Last change on : $Date: 2008-03-24 20:07:37 +0200 (Пн, 24 мар 2008) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
diff --git a/protocols/IcqOscarJ/icq_menu.cpp b/protocols/IcqOscarJ/icq_menu.cpp
new file mode 100644
index 0000000000..d576856b32
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_menu.cpp
@@ -0,0 +1,244 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: icq_menu.cpp $
+// Revision : $Revision: 0 $
+// Last change on : $Date: 2009-12-21 19:52:36 +0300 $
+// Last change by : $Author: Unsane $
+//
+// DESCRIPTION:
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#include <m_skin.h>
+
+static HANDLE hPrebuildMenuHook;
+
+HANDLE g_hContactMenuItems[5];
+HANDLE g_hContactMenuSvc[5];
+
+static int sttCompareProtocols(const CIcqProto *p1, const CIcqProto *p2)
+{
+ return strcmp(p1->m_szModuleName, p2->m_szModuleName);
+}
+
+LIST<CIcqProto> g_Instances(1, sttCompareProtocols);
+
+static CIcqProto* IcqGetInstanceByHContact(HANDLE hContact)
+{
+ char* szProto = ( char* )CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto == NULL)
+ return NULL;
+
+ for (int i = 0; i < g_Instances.getCount(); i++)
+ if (!strcmp(szProto, g_Instances[i]->m_szModuleName))
+ return g_Instances[i];
+
+ return NULL;
+}
+
+static INT_PTR IcqMenuHandleRequestAuth(WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = IcqGetInstanceByHContact((HANDLE)wParam);
+ return (ppro) ? ppro->RequestAuthorization(wParam, lParam) : 0;
+}
+
+static INT_PTR IcqMenuHandleGrantAuth(WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = IcqGetInstanceByHContact((HANDLE)wParam);
+ return (ppro) ? ppro->GrantAuthorization(wParam, lParam) : 0;
+}
+
+static INT_PTR IcqMenuHandleRevokeAuth(WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = IcqGetInstanceByHContact((HANDLE)wParam);
+ return (ppro) ? ppro->RevokeAuthorization(wParam, lParam) : 0;
+}
+
+static INT_PTR IcqMenuHandleAddServContact(WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = IcqGetInstanceByHContact((HANDLE)wParam);
+ return (ppro) ? ppro->AddServerContact(wParam, lParam) : 0;
+}
+
+static INT_PTR IcqMenuHandleXStatusDetails(WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = IcqGetInstanceByHContact((HANDLE)wParam);
+ return (ppro) ? ppro->ShowXStatusDetails(wParam, lParam) : 0;
+}
+
+static void sttEnableMenuItem( HANDLE hMenuItem, bool bEnable )
+{
+ CLISTMENUITEM clmi = {0};
+ clmi.cbSize = sizeof( CLISTMENUITEM );
+ clmi.flags = CMIM_FLAGS;
+ if ( !bEnable )
+ clmi.flags |= CMIF_HIDDEN;
+
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuItem, ( LPARAM )&clmi );
+}
+
+static int IcqPrebuildContactMenu( WPARAM wParam, LPARAM lParam )
+{
+ sttEnableMenuItem(g_hContactMenuItems[ICMI_AUTH_REQUEST], FALSE);
+ sttEnableMenuItem(g_hContactMenuItems[ICMI_AUTH_GRANT], FALSE);
+ sttEnableMenuItem(g_hContactMenuItems[ICMI_AUTH_REVOKE], FALSE);
+ sttEnableMenuItem(g_hContactMenuItems[ICMI_ADD_TO_SERVLIST], FALSE);
+ sttEnableMenuItem(g_hContactMenuItems[ICMI_XSTATUS_DETAILS], FALSE);
+
+ CIcqProto* ppro = IcqGetInstanceByHContact((HANDLE)wParam);
+ return (ppro) ? ppro->OnPreBuildContactMenu(wParam, lParam) : 0;
+}
+
+void g_MenuInit(void)
+{
+ ///////////////
+ // Contact menu
+
+ hPrebuildMenuHook = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, IcqPrebuildContactMenu);
+
+ // Contact menu initialization
+
+ char str[MAXMODULELABELLENGTH], *pszDest = str + 3;
+ strcpy( str, "ICQ" );
+
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof( CLISTMENUITEM );
+ mi.pszService = str;
+ mi.flags = CMIF_ICONFROMICOLIB;
+
+ // "Request authorization"
+ mi.pszName = LPGEN("Request authorization");
+ mi.position = 1000030000;
+ mi.icolibItem = hStaticIcons[ISI_AUTH_REQUEST]->Handle();
+ strcpy(pszDest, MS_REQ_AUTH);
+ g_hContactMenuItems[ICMI_AUTH_REQUEST] = (HGENMENU)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+ g_hContactMenuSvc[ICMI_AUTH_REQUEST] = CreateServiceFunction( str, IcqMenuHandleRequestAuth );
+
+ // "Grant authorization"
+ mi.pszName = LPGEN("Grant authorization");
+ mi.position = 1000029999;
+ mi.icolibItem = hStaticIcons[ISI_AUTH_GRANT]->Handle();
+ strcpy(pszDest, MS_GRANT_AUTH);
+ g_hContactMenuItems[ICMI_AUTH_GRANT] = (HGENMENU)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+ g_hContactMenuSvc[ICMI_AUTH_GRANT] = CreateServiceFunction(mi.pszService, IcqMenuHandleGrantAuth);
+
+ // "Revoke authorization"
+ mi.pszName = LPGEN("Revoke authorization");
+ mi.position = 1000029998;
+ mi.icolibItem = hStaticIcons[ISI_AUTH_REVOKE]->Handle();
+ strcpy(pszDest, MS_REVOKE_AUTH);
+ g_hContactMenuItems[ICMI_AUTH_REVOKE] = (HGENMENU)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+ g_hContactMenuSvc[ICMI_AUTH_REVOKE] = CreateServiceFunction(mi.pszService, IcqMenuHandleRevokeAuth);
+
+ // "Add to server list"
+ mi.pszName = LPGEN("Add to server list");
+ mi.position = -2049999999;
+ mi.icolibItem = hStaticIcons[ISI_ADD_TO_SERVLIST]->Handle();
+ strcpy(pszDest, MS_ICQ_ADDSERVCONTACT);
+ g_hContactMenuItems[ICMI_ADD_TO_SERVLIST] = (HGENMENU)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+ g_hContactMenuSvc[ICMI_ADD_TO_SERVLIST] = CreateServiceFunction(mi.pszService, IcqMenuHandleAddServContact);
+
+ // "Show custom status details"
+ mi.pszName = LPGEN("Show custom status details");
+ mi.position = -2000004999;
+ mi.flags = 0;
+ strcpy(pszDest, MS_XSTATUS_SHOWDETAILS);
+ g_hContactMenuItems[ICMI_XSTATUS_DETAILS] = (HGENMENU)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+ g_hContactMenuSvc[ICMI_XSTATUS_DETAILS] = CreateServiceFunction(mi.pszService, IcqMenuHandleXStatusDetails);
+}
+
+void g_MenuUninit(void)
+{
+ UnhookEvent(hPrebuildMenuHook);
+
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)g_hContactMenuItems[ICMI_AUTH_REQUEST], 0);
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)g_hContactMenuItems[ICMI_AUTH_GRANT], 0);
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)g_hContactMenuItems[ICMI_AUTH_REVOKE], 0);
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)g_hContactMenuItems[ICMI_ADD_TO_SERVLIST], 0);
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)g_hContactMenuItems[ICMI_XSTATUS_DETAILS], 0);
+
+ DestroyServiceFunction(g_hContactMenuSvc[ICMI_AUTH_REQUEST]);
+ DestroyServiceFunction(g_hContactMenuSvc[ICMI_AUTH_GRANT]);
+ DestroyServiceFunction(g_hContactMenuSvc[ICMI_AUTH_REVOKE]);
+ DestroyServiceFunction(g_hContactMenuSvc[ICMI_ADD_TO_SERVLIST]);
+ DestroyServiceFunction(g_hContactMenuSvc[ICMI_XSTATUS_DETAILS]);
+
+}
+
+int CIcqProto::OnPreBuildContactMenu(WPARAM wParam, LPARAM)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if (hContact == NULL)
+ return 0;
+
+ if (icqOnline())
+ {
+ BOOL bCtrlPressed = (GetKeyState(VK_CONTROL)&0x8000 ) != 0;
+
+ DWORD dwUin = getContactUin(hContact);
+
+
+ sttEnableMenuItem(g_hContactMenuItems[ICMI_AUTH_REQUEST],
+ dwUin && (bCtrlPressed || (getSettingByte((HANDLE)wParam, "Auth", 0) && getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_ID, 0))));
+ sttEnableMenuItem(g_hContactMenuItems[ICMI_AUTH_GRANT], dwUin && (bCtrlPressed || getSettingByte((HANDLE)wParam, "Grant", 0)));
+ sttEnableMenuItem(g_hContactMenuItems[ICMI_AUTH_REVOKE],
+ dwUin && (bCtrlPressed || (getSettingByte(NULL, "PrivacyItems", 0) && !getSettingByte((HANDLE)wParam, "Grant", 0))));
+
+ sttEnableMenuItem(g_hContactMenuItems[ICMI_ADD_TO_SERVLIST],
+ m_bSsiEnabled && !getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_ID, 0) &&
+ !getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_IGNORE, 0) &&
+ !DBGetContactSettingByte(hContact, "CList", "NotOnList", 0));
+ }
+
+ BYTE bXStatus = getContactXStatus((HANDLE)wParam);
+
+ sttEnableMenuItem(g_hContactMenuItems[ICMI_XSTATUS_DETAILS], m_bHideXStatusUI ? 0 : bXStatus != 0);
+ if (bXStatus && !m_bHideXStatusUI) {
+ CLISTMENUITEM clmi = {0};
+
+ clmi.cbSize = sizeof(clmi);
+ clmi.flags = CMIM_ICON;
+
+ if (bXStatus > 0 && bXStatus <= XSTATUS_COUNT)
+ clmi.hIcon = getXStatusIcon(bXStatus, LR_SHARED);
+ else
+ clmi.hIcon = LoadSkinnedIcon(SKINICON_OTHER_SMALLDOT);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)g_hContactMenuItems[ICMI_XSTATUS_DETAILS], (LPARAM)&clmi);
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// OnPrebuildContactMenu event
+
+int CIcqProto::OnPreBuildStatusMenu(WPARAM wParam, LPARAM lParam)
+{
+ InitXStatusItems(TRUE);
+ return 0;
+}
diff --git a/protocols/IcqOscarJ/icq_opts.cpp b/protocols/IcqOscarJ/icq_opts.cpp
new file mode 100644
index 0000000000..1dca3b4e85
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_opts.cpp
@@ -0,0 +1,628 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_opts.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#include <win2k.h>
+
+extern BOOL bPopUpService;
+
+static const char* szLogLevelDescr[] = {
+ LPGEN("Display all problems"),
+ LPGEN("Display problems causing possible loss of data"),
+ LPGEN("Display explanations for disconnection"),
+ LPGEN("Display problems requiring user intervention"),
+ LPGEN("Do not display any problems (not recommended)")
+};
+
+static BOOL (WINAPI *pfnEnableThemeDialogTexture)(HANDLE, DWORD) = 0;
+
+static void LoadDBCheckState(CIcqProto* ppro, HWND hwndDlg, int idCtrl, const char* szSetting, BYTE bDef)
+{
+ CheckDlgButton(hwndDlg, idCtrl, ppro->getSettingByte(NULL, szSetting, bDef));
+}
+
+static void StoreDBCheckState(CIcqProto* ppro, HWND hwndDlg, int idCtrl, const char* szSetting)
+{
+ ppro->setSettingByte(NULL, szSetting, (BYTE)IsDlgButtonChecked(hwndDlg, idCtrl));
+}
+
+static void OptDlgChanged(HWND hwndDlg)
+{
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// standalone option pages
+
+static INT_PTR CALLBACK DlgProcIcqOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = (CIcqProto*)GetWindowLongPtr( hwndDlg, GWLP_USERDATA );
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ ppro = (CIcqProto*)lParam;
+ SetWindowLongPtr( hwndDlg, GWLP_USERDATA, lParam );
+ {
+ DWORD dwUin = ppro->getContactUin(NULL);
+ if (dwUin)
+ SetDlgItemInt(hwndDlg, IDC_ICQNUM, dwUin, FALSE);
+ else // keep it empty when no UIN entered
+ SetDlgItemTextA(hwndDlg, IDC_ICQNUM, "");
+
+ SendDlgItemMessage(hwndDlg, IDC_PASSWORD, EM_LIMITTEXT, PASSWORDMAXLEN - 1, 0);
+
+ char pszPwd[PASSWORDMAXLEN];
+ if (ppro->GetUserStoredPassword(pszPwd, sizeof(pszPwd)))
+ {
+ //bit of a security hole here, since it's easy to extract a password from an edit box
+ SetDlgItemTextA(hwndDlg, IDC_PASSWORD, pszPwd);
+ }
+
+ LoadDBCheckState(ppro, hwndDlg, IDC_SSL, "SecureConnection", DEFAULT_SECURE_CONNECTION);
+ LoadDBCheckState(ppro, hwndDlg, IDC_MD5LOGIN, "SecureLogin", DEFAULT_SECURE_LOGIN);
+
+ char szServer[MAX_PATH];
+ if (!ppro->getSettingStringStatic(NULL, "OscarServer", szServer, MAX_PATH))
+ SetDlgItemTextA(hwndDlg, IDC_ICQSERVER, szServer);
+ else
+ SetDlgItemTextA(hwndDlg, IDC_ICQSERVER, IsDlgButtonChecked(hwndDlg, IDC_SSL) ? DEFAULT_SERVER_HOST_SSL : DEFAULT_SERVER_HOST);
+
+ SetDlgItemInt(hwndDlg, IDC_ICQPORT, ppro->getSettingWord(NULL, "OscarPort", IsDlgButtonChecked(hwndDlg, IDC_SSL) ? DEFAULT_SERVER_PORT_SSL : DEFAULT_SERVER_PORT), FALSE);
+ LoadDBCheckState(ppro, hwndDlg, IDC_KEEPALIVE, "KeepAlive", DEFAULT_KEEPALIVE_ENABLED);
+ SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_SETRANGE, FALSE, MAKELONG(0, 4));
+ SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_SETPOS, TRUE, 4-ppro->getSettingByte(NULL, "ShowLogLevel", LOG_WARNING));
+ {
+ char buf[MAX_PATH];
+ SetDlgItemTextUtf(hwndDlg, IDC_LEVELDESCR, ICQTranslateUtfStatic(szLogLevelDescr[4-SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_GETPOS, 0, 0)], buf, MAX_PATH));
+ }
+ ShowDlgItem(hwndDlg, IDC_RECONNECTREQD, SW_HIDE);
+ LoadDBCheckState(ppro, hwndDlg, IDC_NOERRMULTI, "IgnoreMultiErrorBox", 0);
+ }
+ 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_LOOKUPLINK:
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM)URL_FORGOT_PASSWORD);
+ return TRUE;
+
+ case IDC_NEWUINLINK:
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM)URL_REGISTER);
+ return TRUE;
+
+ case IDC_RESETSERVER:
+ SetDlgItemInt(hwndDlg, IDC_ICQPORT, IsDlgButtonChecked(hwndDlg, IDC_SSL) ? DEFAULT_SERVER_PORT_SSL : DEFAULT_SERVER_PORT, FALSE);
+
+ case IDC_SSL:
+ SetDlgItemTextA(hwndDlg, IDC_ICQSERVER, IsDlgButtonChecked(hwndDlg, IDC_SSL) ? DEFAULT_SERVER_HOST_SSL : DEFAULT_SERVER_HOST);
+ SetDlgItemInt(hwndDlg, IDC_ICQPORT, IsDlgButtonChecked(hwndDlg, IDC_SSL) ? DEFAULT_SERVER_PORT_SSL : DEFAULT_SERVER_PORT, FALSE);
+ OptDlgChanged(hwndDlg);
+ return TRUE;
+ }
+
+ if (ppro->icqOnline() && LOWORD(wParam) != IDC_NOERRMULTI)
+ {
+ char szClass[80];
+ GetClassNameA((HWND)lParam, szClass, sizeof(szClass));
+
+ if (stricmpnull(szClass, "EDIT") || HIWORD(wParam) == EN_CHANGE)
+ ShowDlgItem(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];
+
+ ppro->setSettingDword(NULL, UNIQUEIDSETTING, GetDlgItemInt(hwndDlg, IDC_ICQNUM, NULL, FALSE));
+ GetDlgItemTextA(hwndDlg, IDC_PASSWORD, str, sizeof(ppro->m_szPassword));
+ if (strlennull(str))
+ {
+ strcpy(ppro->m_szPassword, str);
+ ppro->m_bRememberPwd = TRUE;
+ }
+ else
+ ppro->m_bRememberPwd = ppro->getSettingByte(NULL, "RememberPass", 0);
+
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(ppro->m_szPassword), (LPARAM)str);
+ ppro->setSettingString(NULL, "Password", str);
+ GetDlgItemTextA(hwndDlg,IDC_ICQSERVER, str, sizeof(str));
+ ppro->setSettingString(NULL, "OscarServer", str);
+ ppro->setSettingWord(NULL, "OscarPort", (WORD)GetDlgItemInt(hwndDlg, IDC_ICQPORT, NULL, FALSE));
+ StoreDBCheckState(ppro, hwndDlg, IDC_KEEPALIVE, "KeepAlive");
+ StoreDBCheckState(ppro, hwndDlg, IDC_SSL, "SecureConnection");
+ StoreDBCheckState(ppro, hwndDlg, IDC_MD5LOGIN, "SecureLogin");
+ StoreDBCheckState(ppro, hwndDlg, IDC_NOERRMULTI, "IgnoreMultiErrorBox");
+ ppro->setSettingByte(NULL, "ShowLogLevel", (BYTE)(4-SendDlgItemMessage(hwndDlg, IDC_LOGLEVEL, TBM_GETPOS, 0, 0)));
+
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static const UINT icqPrivacyControls[] = {
+ IDC_DCALLOW_ANY, IDC_DCALLOW_CLIST, IDC_DCALLOW_AUTH, IDC_ADD_ANY, IDC_ADD_AUTH,
+ IDC_WEBAWARE, IDC_PUBLISHPRIMARY, IDC_STATIC_DC1, IDC_STATIC_DC2, IDC_STATIC_CLIST
+};
+
+static INT_PTR CALLBACK DlgProcIcqPrivacyOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = (CIcqProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ ppro = (CIcqProto*)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
+ {
+ int nDcType = ppro->getSettingByte(NULL, "DCType", 0);
+ int nAddAuth = ppro->getSettingByte(NULL, "Auth", 1);
+
+ if (!ppro->icqOnline())
+ {
+ icq_EnableMultipleControls(hwndDlg, icqPrivacyControls, SIZEOF(icqPrivacyControls), FALSE);
+ ShowDlgItem(hwndDlg, IDC_STATIC_NOTONLINE, SW_SHOW);
+ }
+ else
+ ShowDlgItem(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(ppro, hwndDlg, IDC_WEBAWARE, "WebAware", 0);
+ LoadDBCheckState(ppro, hwndDlg, IDC_PUBLISHPRIMARY, "PublishPrimaryEmail", 0);
+ LoadDBCheckState(ppro, hwndDlg, IDC_STATUSMSG_CLIST, "StatusMsgReplyCList", 0);
+ LoadDBCheckState(ppro, hwndDlg, IDC_STATUSMSG_VISIBLE, "StatusMsgReplyVisible", 0);
+ if (!ppro->getSettingByte(NULL, "StatusMsgReplyCList", 0))
+ EnableDlgItem(hwndDlg, IDC_STATUSMSG_VISIBLE, FALSE);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_DCALLOW_ANY:
+ case IDC_DCALLOW_CLIST:
+ case IDC_DCALLOW_AUTH:
+ case IDC_ADD_ANY:
+ case IDC_ADD_AUTH:
+ case IDC_WEBAWARE:
+ case IDC_PUBLISHPRIMARY:
+ case IDC_STATUSMSG_VISIBLE:
+ if ((HWND)lParam != GetFocus()) return 0;
+ break;
+ case IDC_STATUSMSG_CLIST:
+ if (IsDlgButtonChecked(hwndDlg, IDC_STATUSMSG_CLIST))
+ {
+ EnableDlgItem(hwndDlg, IDC_STATUSMSG_VISIBLE, TRUE);
+ LoadDBCheckState(ppro, 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(ppro, hwndDlg, IDC_WEBAWARE, "WebAware");
+ StoreDBCheckState(ppro, hwndDlg, IDC_PUBLISHPRIMARY, "PublishPrimaryEmail");
+ StoreDBCheckState(ppro, hwndDlg, IDC_STATUSMSG_CLIST, "StatusMsgReplyCList");
+ StoreDBCheckState(ppro, hwndDlg, IDC_STATUSMSG_VISIBLE, "StatusMsgReplyVisible");
+ if (IsDlgButtonChecked(hwndDlg, IDC_DCALLOW_AUTH))
+ ppro->setSettingByte(NULL, "DCType", 2);
+ else if (IsDlgButtonChecked(hwndDlg, IDC_DCALLOW_CLIST))
+ ppro->setSettingByte(NULL, "DCType", 1);
+ else
+ ppro->setSettingByte(NULL, "DCType", 0);
+ StoreDBCheckState(ppro, hwndDlg, IDC_ADD_AUTH, "Auth");
+
+ if (ppro->icqOnline())
+ {
+ PBYTE buf=NULL;
+ int buflen=0;
+
+ ppackTLVWord(&buf, &buflen, 0x19A, !ppro->getSettingByte(NULL, "Auth", 1));
+ ppackTLVByte(&buf, &buflen, 0x212, ppro->getSettingByte(NULL, "WebAware", 0));
+ ppackTLVWord(&buf, &buflen, 0x1F9, ppro->getSettingByte(NULL, "PrivacyLevel", 1));
+
+ ppro->icq_changeUserDirectoryInfoServ(buf, (WORD)buflen, DIRECTORYREQUEST_UPDATEPRIVACY);
+
+ SAFE_FREE((void**)&buf);
+
+ // Send a status packet to notify the server about the webaware setting
+ {
+ WORD wStatus = MirandaStatusToIcq(ppro->m_iStatus);
+
+ if (ppro->m_iStatus == ID_STATUS_INVISIBLE)
+ {
+ if (ppro->m_bSsiEnabled)
+ ppro->updateServVisibilityCode(3);
+ ppro->icq_setstatus(wStatus, NULL);
+ }
+ else
+ {
+ ppro->icq_setstatus(wStatus, NULL);
+ if (ppro->m_bSsiEnabled)
+ ppro->updateServVisibilityCode(4);
+ }
+ }
+ }
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static HWND hCpCombo;
+
+struct CPTABLE {
+ WORD cpId;
+ char *cpName;
+};
+
+struct CPTABLE cpTable[] = {
+ { 874, LPGEN("Thai") },
+ { 932, LPGEN("Japanese") },
+ { 936, LPGEN("Simplified Chinese") },
+ { 949, LPGEN("Korean") },
+ { 950, LPGEN("Traditional Chinese") },
+ { 1250, LPGEN("Central European") },
+ { 1251, LPGEN("Cyrillic") },
+ { 1252, LPGEN("Latin I") },
+ { 1253, LPGEN("Greek") },
+ { 1254, LPGEN("Turkish") },
+ { 1255, LPGEN("Hebrew") },
+ { 1256, LPGEN("Arabic") },
+ { 1257, LPGEN("Baltic") },
+ { 1258, LPGEN("Vietnamese") },
+ { 1361, LPGEN("Korean (Johab)") },
+ { -1, NULL}
+};
+
+static BOOL CALLBACK FillCpCombo(LPSTR str)
+{
+ int i;
+ UINT cp;
+
+ cp = atoi(str);
+ for (i=0; cpTable[i].cpName != NULL && cpTable[i].cpId!=cp; i++);
+ if (cpTable[i].cpName)
+ ComboBoxAddStringUtf(hCpCombo, cpTable[i].cpName, cpTable[i].cpId);
+
+ return TRUE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static const UINT icqUnicodeControls[] = {IDC_UTFALL,IDC_UTFSTATIC,IDC_UTFCODEPAGE};
+static const UINT icqDCMsgControls[] = {IDC_DCPASSIVE};
+static const UINT icqXStatusControls[] = {IDC_XSTATUSAUTO};
+static const UINT icqCustomStatusControls[] = {IDC_XSTATUSRESET};
+static const UINT icqAimControls[] = {IDC_AIMENABLE};
+
+static INT_PTR CALLBACK DlgProcIcqFeaturesOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = (CIcqProto*)GetWindowLongPtr( hwndDlg, GWLP_USERDATA );
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ ppro = (CIcqProto*)lParam;
+ SetWindowLongPtr( hwndDlg, GWLP_USERDATA, lParam );
+ {
+ BYTE byData = ppro->getSettingByte(NULL, "UtfEnabled", DEFAULT_UTF_ENABLED);
+ CheckDlgButton(hwndDlg, IDC_UTFENABLE, byData?TRUE:FALSE);
+ CheckDlgButton(hwndDlg, IDC_UTFALL, byData==2?TRUE:FALSE);
+ icq_EnableMultipleControls(hwndDlg, icqUnicodeControls, SIZEOF(icqUnicodeControls), byData?TRUE:FALSE);
+ LoadDBCheckState(ppro, hwndDlg, IDC_TEMPVISIBLE, "TempVisListEnabled",DEFAULT_TEMPVIS_ENABLED);
+ LoadDBCheckState(ppro, hwndDlg, IDC_SLOWSEND, "SlowSend", DEFAULT_SLOWSEND);
+ LoadDBCheckState(ppro, hwndDlg, IDC_ONLYSERVERACKS, "OnlyServerAcks", DEFAULT_ONLYSERVERACKS);
+ byData = ppro->getSettingByte(NULL, "DirectMessaging", DEFAULT_DCMSG_ENABLED);
+ CheckDlgButton(hwndDlg, IDC_DCENABLE, byData?TRUE:FALSE);
+ CheckDlgButton(hwndDlg, IDC_DCPASSIVE, byData==1?TRUE:FALSE);
+ icq_EnableMultipleControls(hwndDlg, icqDCMsgControls, SIZEOF(icqDCMsgControls), byData?TRUE:FALSE);
+ BYTE byXStatusEnabled = ppro->getSettingByte(NULL, "XStatusEnabled", DEFAULT_XSTATUS_ENABLED);
+ CheckDlgButton(hwndDlg, IDC_XSTATUSENABLE, byXStatusEnabled);
+ BYTE byMoodsEnabled = ppro->getSettingByte(NULL, "MoodsEnabled", DEFAULT_MOODS_ENABLED);
+ CheckDlgButton(hwndDlg, IDC_MOODSENABLE, byMoodsEnabled);
+ icq_EnableMultipleControls(hwndDlg, icqXStatusControls, SIZEOF(icqXStatusControls), byXStatusEnabled);
+ icq_EnableMultipleControls(hwndDlg, icqCustomStatusControls, SIZEOF(icqCustomStatusControls), byXStatusEnabled || byMoodsEnabled);
+ LoadDBCheckState(ppro, hwndDlg, IDC_XSTATUSAUTO, "XStatusAuto", DEFAULT_XSTATUS_AUTO);
+ LoadDBCheckState(ppro, hwndDlg, IDC_XSTATUSRESET, "XStatusReset", DEFAULT_XSTATUS_RESET);
+ LoadDBCheckState(ppro, hwndDlg, IDC_KILLSPAMBOTS, "KillSpambots", DEFAULT_KILLSPAM_ENABLED);
+ LoadDBCheckState(ppro, hwndDlg, IDC_AIMENABLE, "AimEnabled", DEFAULT_AIM_ENABLED);
+ icq_EnableMultipleControls(hwndDlg, icqAimControls, SIZEOF(icqAimControls), ppro->icqOnline()?FALSE:TRUE);
+
+ hCpCombo = GetDlgItem(hwndDlg, IDC_UTFCODEPAGE);
+ int sCodePage = ppro->getSettingWord(NULL, "AnsiCodePage", CP_ACP);
+ ComboBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_UTFCODEPAGE), LPGEN("System default codepage"), 0);
+ EnumSystemCodePagesA(FillCpCombo, CP_INSTALLED);
+ if(sCodePage == 0)
+ SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_SETCURSEL, (WPARAM)0, 0);
+ else
+ {
+ for (int i = 0; i < SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_GETCOUNT, 0, 0); i++)
+ {
+ if (SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_GETITEMDATA, (WPARAM)i, 0) == sCodePage)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_SETCURSEL, (WPARAM)i, 0);
+ break;
+ }
+ }
+ }
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_UTFENABLE:
+ icq_EnableMultipleControls(hwndDlg, icqUnicodeControls, SIZEOF(icqUnicodeControls), IsDlgButtonChecked(hwndDlg, IDC_UTFENABLE));
+ OptDlgChanged(hwndDlg);
+ break;
+ case IDC_UTFCODEPAGE:
+ if(HIWORD(wParam)==CBN_SELCHANGE)
+ OptDlgChanged(hwndDlg);
+ break;
+ case IDC_DCENABLE:
+ icq_EnableMultipleControls(hwndDlg, icqDCMsgControls, SIZEOF(icqDCMsgControls), IsDlgButtonChecked(hwndDlg, IDC_DCENABLE));
+ OptDlgChanged(hwndDlg);
+ break;
+ case IDC_XSTATUSENABLE:
+ icq_EnableMultipleControls(hwndDlg, icqXStatusControls, SIZEOF(icqXStatusControls), IsDlgButtonChecked(hwndDlg, IDC_XSTATUSENABLE));
+ case IDC_MOODSENABLE:
+ icq_EnableMultipleControls(hwndDlg, icqCustomStatusControls, SIZEOF(icqCustomStatusControls), IsDlgButtonChecked(hwndDlg, IDC_XSTATUSENABLE) || IsDlgButtonChecked(hwndDlg, IDC_MOODSENABLE));
+ default:
+ OptDlgChanged(hwndDlg);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ if (IsDlgButtonChecked(hwndDlg, IDC_UTFENABLE))
+ ppro->m_bUtfEnabled = IsDlgButtonChecked(hwndDlg, IDC_UTFALL)?2:1;
+ else
+ ppro->m_bUtfEnabled = 0;
+ {
+ int i = SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_GETCURSEL, 0, 0);
+ ppro->m_wAnsiCodepage = (WORD)SendDlgItemMessage(hwndDlg, IDC_UTFCODEPAGE, CB_GETITEMDATA, (WPARAM)i, 0);
+ ppro->setSettingWord(NULL, "AnsiCodePage", ppro->m_wAnsiCodepage);
+ }
+ ppro->setSettingByte(NULL, "UtfEnabled", ppro->m_bUtfEnabled);
+ ppro->m_bTempVisListEnabled = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_TEMPVISIBLE);
+ ppro->setSettingByte(NULL, "TempVisListEnabled", ppro->m_bTempVisListEnabled);
+ StoreDBCheckState(ppro, hwndDlg, IDC_SLOWSEND, "SlowSend");
+ StoreDBCheckState(ppro, hwndDlg, IDC_ONLYSERVERACKS, "OnlyServerAcks");
+ if (IsDlgButtonChecked(hwndDlg, IDC_DCENABLE))
+ ppro->m_bDCMsgEnabled = IsDlgButtonChecked(hwndDlg, IDC_DCPASSIVE)?1:2;
+ else
+ ppro->m_bDCMsgEnabled = 0;
+ ppro->setSettingByte(NULL, "DirectMessaging", ppro->m_bDCMsgEnabled);
+ ppro->m_bXStatusEnabled = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_XSTATUSENABLE);
+ ppro->setSettingByte(NULL, "XStatusEnabled", ppro->m_bXStatusEnabled);
+ ppro->m_bMoodsEnabled = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_MOODSENABLE);
+ ppro->setSettingByte(NULL, "MoodsEnabled", ppro->m_bMoodsEnabled);
+ StoreDBCheckState(ppro, hwndDlg, IDC_XSTATUSAUTO, "XStatusAuto");
+ StoreDBCheckState(ppro, hwndDlg, IDC_XSTATUSRESET, "XStatusReset");
+ StoreDBCheckState(ppro, hwndDlg, IDC_KILLSPAMBOTS , "KillSpambots");
+ StoreDBCheckState(ppro, hwndDlg, IDC_AIMENABLE, "AimEnabled");
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static const UINT icqContactsControls[] = {IDC_ADDSERVER,IDC_LOADFROMSERVER,IDC_SAVETOSERVER,IDC_UPLOADNOW};
+static const UINT icqAvatarControls[] = {IDC_AUTOLOADAVATARS,IDC_STRICTAVATARCHECK};
+
+static INT_PTR CALLBACK DlgProcIcqContactsOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CIcqProto* ppro = (CIcqProto*)GetWindowLongPtr( hwndDlg, GWLP_USERDATA );
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ ppro = (CIcqProto*)lParam;
+ SetWindowLongPtr( hwndDlg, GWLP_USERDATA, lParam );
+
+ LoadDBCheckState(ppro, hwndDlg, IDC_ENABLE, "UseServerCList", DEFAULT_SS_ENABLED);
+ LoadDBCheckState(ppro, hwndDlg, IDC_ADDSERVER, "ServerAddRemove", DEFAULT_SS_ADDSERVER);
+ LoadDBCheckState(ppro, hwndDlg, IDC_LOADFROMSERVER, "LoadServerDetails", DEFAULT_SS_LOAD);
+ LoadDBCheckState(ppro, hwndDlg, IDC_SAVETOSERVER, "StoreServerDetails", DEFAULT_SS_STORE);
+ LoadDBCheckState(ppro, hwndDlg, IDC_ENABLEAVATARS, "AvatarsEnabled", DEFAULT_AVATARS_ENABLED);
+ LoadDBCheckState(ppro, hwndDlg, IDC_AUTOLOADAVATARS, "AvatarsAutoLoad", DEFAULT_LOAD_AVATARS);
+ LoadDBCheckState(ppro, hwndDlg, IDC_STRICTAVATARCHECK, "StrictAvatarCheck", DEFAULT_AVATARS_CHECK);
+
+ icq_EnableMultipleControls(hwndDlg, icqContactsControls, SIZEOF(icqContactsControls),
+ ppro->getSettingByte(NULL, "UseServerCList", DEFAULT_SS_ENABLED)?TRUE:FALSE);
+ icq_EnableMultipleControls(hwndDlg, icqAvatarControls, SIZEOF(icqAvatarControls),
+ ppro->getSettingByte(NULL, "AvatarsEnabled", DEFAULT_AVATARS_ENABLED)?TRUE:FALSE);
+
+ if (ppro->icqOnline())
+ {
+ ShowDlgItem(hwndDlg, IDC_OFFLINETOENABLE, SW_SHOW);
+ EnableDlgItem(hwndDlg, IDC_ENABLE, FALSE);
+ EnableDlgItem(hwndDlg, IDC_ENABLEAVATARS, FALSE);
+ }
+ else
+ EnableDlgItem(hwndDlg, IDC_UPLOADNOW, FALSE);
+
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_UPLOADNOW:
+ ppro->ShowUploadContactsDialog();
+ return TRUE;
+ case IDC_ENABLE:
+ icq_EnableMultipleControls(hwndDlg, icqContactsControls, SIZEOF(icqContactsControls), IsDlgButtonChecked(hwndDlg, IDC_ENABLE));
+ if (ppro->icqOnline())
+ ShowDlgItem(hwndDlg, IDC_RECONNECTREQD, SW_SHOW);
+ else
+ EnableDlgItem(hwndDlg, IDC_UPLOADNOW, FALSE);
+ break;
+ case IDC_ENABLEAVATARS:
+ icq_EnableMultipleControls(hwndDlg, icqAvatarControls, SIZEOF(icqAvatarControls), IsDlgButtonChecked(hwndDlg, IDC_ENABLEAVATARS));
+ break;
+ }
+ OptDlgChanged(hwndDlg);
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == PSN_APPLY )
+ {
+ StoreDBCheckState(ppro, hwndDlg, IDC_ENABLE, "UseServerCList");
+ StoreDBCheckState(ppro, hwndDlg, IDC_ADDSERVER, "ServerAddRemove");
+ StoreDBCheckState(ppro, hwndDlg, IDC_LOADFROMSERVER, "LoadServerDetails");
+ StoreDBCheckState(ppro, hwndDlg, IDC_SAVETOSERVER, "StoreServerDetails");
+ StoreDBCheckState(ppro, hwndDlg, IDC_ENABLEAVATARS, "AvatarsEnabled");
+ StoreDBCheckState(ppro, hwndDlg, IDC_AUTOLOADAVATARS, "AvatarsAutoLoad");
+ StoreDBCheckState(ppro, hwndDlg, IDC_STRICTAVATARCHECK, "StrictAvatarCheck");
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR CALLBACK DlgProcIcqPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+int CIcqProto::OnOptionsInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+ HMODULE hUxTheme = 0;
+
+ if (IsWinVerXPPlus())
+ {
+ hUxTheme = GetModuleHandleA("uxtheme.dll");
+ if (hUxTheme)
+ pfnEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
+ }
+
+ odp.cbSize = sizeof(odp);
+ odp.position = -800000000;
+ odp.hInstance = hInst;
+ odp.ptszGroup = LPGENT("Network");
+ odp.dwInitParam = LPARAM(this);
+ odp.ptszTitle = m_tszUserName;
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR | ODPF_DONTTRANSLATE;
+
+ odp.ptszTab = LPGENT("Account");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQ);
+ odp.pfnDlgProc = DlgProcIcqOpts;
+ CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
+
+ odp.ptszTab = LPGENT("Contacts");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQCONTACTS);
+ odp.pfnDlgProc = DlgProcIcqContactsOpts;
+ CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
+
+ odp.ptszTab = LPGENT("Features");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQFEATURES);
+ odp.pfnDlgProc = DlgProcIcqFeaturesOpts;
+ CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
+
+ odp.ptszTab = LPGENT("Privacy");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQPRIVACY);
+ odp.pfnDlgProc = DlgProcIcqPrivacyOpts;
+ CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
+
+ if (bPopUpService)
+ {
+ odp.position = 100000000;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUPS);
+ odp.groupPosition = 900000000;
+ odp.pfnDlgProc = DlgProcIcqPopupOpts;
+ odp.ptszGroup = LPGENT("Popups");
+ odp.ptszTab = NULL;
+ CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
+ }
+ return 0;
+}
diff --git a/protocols/IcqOscarJ/icq_opts.h b/protocols/IcqOscarJ/icq_opts.h
new file mode 100644
index 0000000000..383a59d7f9
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_opts.h
@@ -0,0 +1,37 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_opts.h $
+// Revision : $Revision: 8822 $
+// Last change on : $Date: 2009-01-11 19:17:05 +0200 (Вс, 11 янв 2009) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+int IcqOptInit(WPARAM, LPARAM);
diff --git a/protocols/IcqOscarJ/icq_packet.cpp b/protocols/IcqOscarJ/icq_packet.cpp
new file mode 100644
index 0000000000..7642c82ace
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_packet.cpp
@@ -0,0 +1,908 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_packet.cpp $
+// Revision : $Revision: 13213 $
+// Last change on : $Date: 2010-12-22 08:54:39 +0200 (Ср, 22 дек 2010) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+WORD generate_flap_sequence()
+{
+ DWORD n = rand(), s = 0;
+
+ for (DWORD i = n; i >>= 3; s += i);
+
+ return (((0 - s) ^ (BYTE)n) & 7 ^ n) + 2;
+}
+
+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) + 66);
+
+ 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, (LPBYTE)CLIENT_ID_STRING);
+ packTLVWord(pPacket, 0x0017, CLIENT_VERSION_MAJOR);
+ packTLVWord(pPacket, 0x0018, CLIENT_VERSION_MINOR);
+ packTLVWord(pPacket, 0x0019, CLIENT_VERSION_LESSER);
+ packTLVWord(pPacket, 0x001a, CLIENT_VERSION_BUILD);
+ packTLVWord(pPacket, 0x0016, CLIENT_ID_CODE);
+ packTLVDWord(pPacket, 0x0014, CLIENT_DISTRIBUTION);
+ packTLV(pPacket, 0x000f, 0x0002, (LPBYTE)CLIENT_LANGUAGE);
+ packTLV(pPacket, 0x000e, 0x0002, (LPBYTE)CLIENT_COUNTRY);
+ packDWord(pPacket, 0x00940001); // reconnect flag
+ packByte(pPacket, 0);
+ 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);
+}
+
+
+void packTLVUID(icq_packet *pPacket, WORD wType, DWORD dwUin, const char *szUid)
+{
+ if (dwUin)
+ {
+ char szUin[UINMAXLEN];
+
+ _ltoa(dwUin, szUin, 10);
+
+ packTLV(pPacket, wType, getUINLen(dwUin), (BYTE*)szUin);
+ }
+ else if (szUid)
+ packTLV(pPacket, wType, strlennull(szUid), (BYTE*)szUid);
+}
+
+
+// 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, const char *szUid)
+{
+ if (dwUin)
+ return getUINLen(dwUin);
+ else
+ return strlennull(szUid);
+}
+
+void __fastcall packUIN(icq_packet *pPacket, DWORD dwUin)
+{
+ char pszUin[UINMAXLEN];
+ BYTE nUinLen = getUINLen(dwUin);
+
+ _ltoa(dwUin, pszUin, 10);
+
+ packByte(pPacket, nUinLen); // Length of user id
+ packBuffer(pPacket, (LPBYTE)pszUin, nUinLen); // Receiving user's id
+}
+
+void __fastcall packUID(icq_packet *pPacket, DWORD dwUin, const char *szUid)
+{
+ if (dwUin)
+ packUIN(pPacket, dwUin);
+ else
+ {
+ BYTE nLen = strlennull(szUid);
+ packByte(pPacket, nLen);
+ packBuffer(pPacket, (LPBYTE)szUid, nLen);
+ }
+}
+
+
+void packFNACHeader(icq_packet *pPacket, WORD wFamily, WORD wSubtype)
+{
+ packFNACHeader(pPacket, wFamily, wSubtype, 0, wSubtype << 0x10);
+}
+
+
+void packFNACHeader(icq_packet *pPacket, WORD wFamily, WORD wSubtype, WORD wFlags, DWORD dwSequence)
+{
+ WORD wSequence = (WORD)dwSequence & 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, wSequence); // SNAC request id (sequence)
+ packWord(pPacket, (WORD)(dwSequence >> 0x10)); // SNAC request id (command)
+}
+
+
+void packFNACHeader(icq_packet *pPacket, WORD wFamily, WORD wSubtype, WORD wFlags, DWORD dwSequence, WORD wVersion)
+{
+ packFNACHeader(pPacket, wFamily, wSubtype, wFlags | 0x8000, dwSequence);
+ packWord(pPacket, 0x06);
+ packTLVWord(pPacket, 0x01, wVersion);
+}
+
+
+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);
+}
+
+
+/* helper function to place numerics to buffer */
+static void packWord(PBYTE buf, WORD wValue)
+{
+ *(buf) = ((wValue & 0xff00) >> 8);
+ *(buf + 1) = (wValue & 0x00ff);
+}
+
+
+static void packDWord(PBYTE buf, DWORD dwValue)
+{
+ *(buf) = (BYTE)((dwValue & 0xff000000) >> 24);
+ *(buf + 1) = (BYTE)((dwValue & 0x00ff0000) >> 16);
+ *(buf + 2) = (BYTE)((dwValue & 0x0000ff00) >> 8);
+ *(buf + 3) = (BYTE) (dwValue & 0x000000ff);
+}
+
+
+static void packQWord(PBYTE buf, DWORD64 qwValue)
+{
+ packDWord(buf, (DWORD)(qwValue >> 32));
+ packDWord(buf + 4, (DWORD)(qwValue & 0xffffffff));
+}
+
+
+void ppackByte(PBYTE *buf, int *buflen, BYTE byValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 1 + *buflen);
+ *(*buf + *buflen) = byValue;
+ ++*buflen;
+}
+
+
+void ppackWord(PBYTE *buf, int *buflen, WORD wValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 2 + *buflen);
+ packWord(*buf + *buflen, wValue);
+ *buflen += 2;
+}
+
+
+void ppackLEWord(PBYTE *buf, int *buflen, WORD wValue)
+{
+ *buf=(PBYTE)SAFE_REALLOC(*buf, 2 + *buflen);
+ *(PWORD)(*buf + *buflen) = wValue;
+ *buflen+=2;
+}
+
+
+void ppackLEDWord(PBYTE *buf, int *buflen, DWORD dwValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 4 + *buflen);
+ *(PDWORD)(*buf + *buflen) = dwValue;
+ *buflen += 4;
+}
+
+
+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 ppackBuffer(PBYTE *buf, int *buflen, WORD wLength, const BYTE *pbyValue)
+{
+ if (wLength)
+ {
+ *buf = (PBYTE)SAFE_REALLOC(*buf, wLength + *buflen);
+ memcpy(*buf + *buflen, pbyValue, wLength);
+ *buflen += wLength;
+ }
+}
+
+
+void ppackTLV(PBYTE *buf, int *buflen, WORD wType, WORD wLength, const BYTE *pbyValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 4 + wLength + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, wLength);
+ if (wLength)
+ memcpy(*buf + *buflen + 4, pbyValue, wLength);
+ *buflen += 4 + wLength;
+}
+
+
+void ppackTLVByte(PBYTE *buf, int *buflen, WORD wType, BYTE byValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 5 + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 1);
+ *(*buf + *buflen + 4) = byValue;
+ *buflen += 5;
+}
+
+
+void ppackTLVWord(PBYTE *buf, int *buflen, WORD wType, WORD wValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 6 + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 2);
+ packWord(*buf + *buflen + 4, wValue);
+ *buflen += 6;
+}
+
+
+void ppackTLVDWord(PBYTE *buf, int *buflen, WORD wType, DWORD dwValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 8 + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 4);
+ packDWord(*buf + *buflen + 4, dwValue);
+ *buflen += 8;
+}
+
+
+void ppackTLVDouble(PBYTE *buf, int *buflen, WORD wType, double dValue)
+{
+ DWORD64 qwValue;
+
+ memcpy(&qwValue, &dValue, 8);
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 12 + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 8);
+ packQWord(*buf + *buflen + 4, qwValue);
+ *buflen += 12;
+}
+
+
+void ppackTLVUID(PBYTE *buf, int *buflen, WORD wType, DWORD dwUin, const char *szUid)
+{
+ if (dwUin)
+ {
+ char szUin[UINMAXLEN];
+
+ _ltoa(dwUin, szUin, 10);
+
+ ppackTLV(buf, buflen, wType, getUINLen(dwUin), (BYTE*)szUin);
+ }
+ else if (szUid)
+ ppackTLV(buf, buflen, wType, strlennull(szUid), (BYTE*)szUid);
+}
+
+
+// *** TLV based (!!! WORDs and DWORDs are LE !!!)
+void ppackLETLVByte(PBYTE *buf, int *buflen, BYTE byValue, WORD wType, BYTE always)
+{
+ if (!always && !byValue) return;
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 5 + *buflen);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = 1;
+ *(*buf + *buflen + 4) = byValue;
+ *buflen += 5;
+}
+
+
+void ppackLETLVWord(PBYTE *buf, int *buflen, WORD wValue, WORD wType, BYTE always)
+{
+ if (!always && !wValue) return;
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 6 + *buflen);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = 2;
+ *(PWORD)(*buf + *buflen + 4) = wValue;
+ *buflen += 6;
+}
+
+
+void ppackLETLVDWord(PBYTE *buf, int *buflen, DWORD dwValue, WORD wType, BYTE always)
+{
+ if (!always && !dwValue) return;
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 8 + *buflen);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = 4;
+ *(PDWORD)(*buf + *buflen + 4) = dwValue;
+ *buflen += 8;
+}
+
+
+void packLETLVLNTS(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 ppackLETLVLNTS(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);
+ packLETLVLNTS(buf, buflen, str, wType);
+}
+
+
+void ppackLETLVWordLNTS(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 ppackLETLVLNTSByte(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 CIcqProto::ppackLETLVLNTSfromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!getSettingStringStatic(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackLETLVLNTS(buf, buflen, str, wType, 1);
+}
+
+void CIcqProto::ppackLETLVWordLNTSfromDB(PBYTE *buf, int *buflen, WORD w, const char *szSetting, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!getSettingStringStatic(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackLETLVWordLNTS(buf, buflen, w, str, wType, 1);
+}
+
+void CIcqProto::ppackLETLVLNTSBytefromDB(PBYTE *buf, int *buflen, const char *szSetting, BYTE b, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!getSettingStringStatic(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackLETLVLNTSByte(buf, buflen, str, b, wType);
+}
+
+
+void CIcqProto::ppackTLVStringFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!getSettingStringStatic(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackTLV(buf, buflen, wType, strlennull(str), (PBYTE)str);
+}
+
+
+void CIcqProto::ppackTLVStringUtfFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType)
+{
+ char *str = getSettingStringUtf(NULL, szSetting, NULL);
+
+ ppackTLV(buf, buflen, wType, strlennull(str), (PBYTE)str);
+
+ SAFE_FREE((void**)&str);
+}
+
+
+void CIcqProto::ppackTLVDateFromDB(PBYTE *buf, int *buflen, const char *szSettingYear, const char *szSettingMonth, const char *szSettingDay, WORD wType)
+{
+ SYSTEMTIME sTime = {0};
+ double time = 0;
+
+ sTime.wYear = getSettingWord(NULL, szSettingYear, 0);
+ sTime.wMonth = getSettingByte(NULL, szSettingMonth, 0);
+ sTime.wDay = getSettingByte(NULL, szSettingDay, 0);
+ if (sTime.wYear || sTime.wMonth || sTime.wDay)
+ {
+ SystemTimeToVariantTime(&sTime, &time);
+ time -= 2;
+ }
+
+ ppackTLVDouble(buf, buflen, wType, time);
+}
+
+
+int CIcqProto::ppackTLVWordStringItemFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wTypeID, WORD wTypeData, WORD wID)
+{
+ char szTmp[1024];
+ char *str = NULL;
+
+ if (!getSettingStringStatic(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ if (str)
+ {
+ WORD wLen = strlennull(str);
+
+ ppackWord(buf, buflen, wLen + 0x0A);
+ ppackTLVWord(buf, buflen, wTypeID, wID);
+ ppackTLV(buf, buflen, wTypeData, wLen, (PBYTE)str);
+
+ return 1; // Success
+ }
+
+ return 0; // No data
+}
+
+
+int CIcqProto::ppackTLVWordStringUtfItemFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wTypeID, WORD wTypeData, WORD wID)
+{
+ char *str = getSettingStringUtf(NULL, szSetting, NULL);
+
+ if (str)
+ {
+ WORD wLen = strlennull(str);
+
+ ppackWord(buf, buflen, wLen + 0x0A);
+ ppackTLVWord(buf, buflen, wTypeID, wID);
+ ppackTLV(buf, buflen, wTypeData, wLen, (PBYTE)str);
+
+ SAFE_FREE(&str);
+
+ return 1; // Success
+ }
+
+ return 0; // No data
+}
+
+
+void ppackTLVBlockItems(PBYTE *buf, int *buflen, WORD wType, int *nItems, PBYTE *pBlock, WORD *wLength, BOOL bSingleItem)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 8 + *buflen + *wLength);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, (bSingleItem ? 4 : 2) + *wLength);
+ packWord(*buf + *buflen + 4, *nItems);
+ if (bSingleItem)
+ packWord(*buf + *buflen + 6, *wLength);
+ if (*wLength)
+ memcpy(*buf + *buflen + (bSingleItem ? 8 : 6), *pBlock, *wLength);
+ *buflen += (bSingleItem ? 8 : 6) + *wLength;
+
+ SAFE_FREE((void**)pBlock);
+ *wLength = 0;
+ *nItems = 0;
+}
+
+
+void ppackTLVBlockItem(PBYTE *buf, int *buflen, WORD wType, PBYTE *pItem, WORD *wLength)
+{
+ if (wLength)
+ {
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 8 + *buflen + *wLength);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 4 + *wLength);
+ packWord(*buf + *buflen + 4, 1);
+ packWord(*buf + *buflen + 6, *wLength);
+ memcpy(*buf + *buflen + 8, *pItem, *wLength);
+ *buflen += 8 + *wLength;
+ }
+ else
+ {
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 6 + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 0x02);
+ packWord(*buf + *buflen + 4, 0);
+ *buflen += 6;
+ }
+
+ SAFE_FREE((void**)pItem);
+ *wLength = 0;
+}
+
+
+void __fastcall unpackByte(BYTE **pSource, BYTE *byDestination)
+{
+ if (byDestination)
+ *byDestination = *(*pSource)++;
+ else
+ *pSource += 1;
+}
+
+void __fastcall unpackWord(BYTE **pSource, WORD *wDestination)
+{
+ BYTE *tmp = *pSource;
+
+ if (wDestination)
+ {
+ *wDestination = *tmp++ << 8;
+ *wDestination |= *tmp++;
+
+ *pSource = tmp;
+ }
+ else
+ *pSource += 2;
+}
+
+void __fastcall unpackDWord(BYTE **pSource, DWORD *dwDestination)
+{
+ BYTE *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(BYTE **buf, WORD *w)
+{
+ BYTE *tmp = *buf;
+
+ if (w)
+ {
+ *w = (*tmp++);
+ *w |= ((*tmp++) << 8);
+ }
+ else
+ tmp += 2;
+
+ *buf = tmp;
+}
+
+void __fastcall unpackLEDWord(BYTE **buf, DWORD *dw)
+{
+ BYTE *tmp = *buf;
+
+ if (dw)
+ {
+ *dw = (*tmp++);
+ *dw |= ((*tmp++) << 8);
+ *dw |= ((*tmp++) << 16);
+ *dw |= ((*tmp++) << 24);
+ }
+ else
+ tmp += 4;
+
+ *buf = tmp;
+}
+
+void unpackString(BYTE **buf, char *string, WORD len)
+{
+ BYTE *tmp = *buf;
+
+ if (string)
+ {
+ while (len) /* Can have 0x00 so go by len */
+ {
+ *string++ = *tmp++;
+ len--;
+ }
+ }
+ else
+ tmp += len;
+
+ *buf = tmp;
+}
+
+void unpackWideString(BYTE **buf, WCHAR *string, WORD len)
+{
+ BYTE *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(BYTE *buf, int buflen, WORD type, WORD *ttype, WORD *tlen, BYTE **ttlv)
+{
+ 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 (ttlv)
+ {
+ if (wLen)
+ { // Unpack and save value
+ *ttlv = (BYTE*)SAFE_MALLOC(wLen + 1); // Add 1 for \0
+ unpackString(&buf, (char*)*ttlv, wLen);
+ *(*ttlv + wLen) = '\0';
+ }
+ else
+ *ttlv = NULL;
+ }
+
+ // Save type and length
+ if (ttype)
+ *ttype = wType;
+ if (tlen)
+ *tlen = wLen;
+}
+
+
+BOOL CIcqProto::unpackUID(BYTE **ppBuf, WORD *pwLen, DWORD *pdwUIN, uid_str *ppszUID)
+{
+ BYTE nUIDLen;
+
+ // sanity check
+ if (!ppBuf || !pwLen || *pwLen < 1)
+ return FALSE;
+
+ // Sender UIN
+ unpackByte(ppBuf, &nUIDLen);
+ *pwLen -= 1;
+
+ if ((nUIDLen > *pwLen) || (nUIDLen == 0))
+ return FALSE;
+
+ if (nUIDLen <= UINMAXLEN)
+ { // it can be uin, check
+ char szUIN[UINMAXLEN+1];
+
+ unpackString(ppBuf, szUIN, nUIDLen);
+ szUIN[nUIDLen] = '\0';
+ *pwLen -= nUIDLen;
+
+ if (IsStringUIN(szUIN))
+ {
+ *pdwUIN = atoi(szUIN);
+ return TRUE;
+ }
+ else
+ { // go back
+ *ppBuf -= nUIDLen;
+ *pwLen += nUIDLen;
+ }
+ }
+ if (!m_bAimEnabled || !ppszUID || !(*ppszUID))
+ { // skip the UID data
+ *ppBuf += nUIDLen;
+ *pwLen -= nUIDLen;
+
+ NetLog_Server("Malformed UIN in packet");
+ 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/protocols/IcqOscarJ/icq_packet.h b/protocols/IcqOscarJ/icq_packet.h
new file mode 100644
index 0000000000..8ffaea6068
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_packet.h
@@ -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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 Joe Kucera, Bio
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_packet.h $
+// Revision : $Revision: 11353 $
+// Last change on : $Date: 2010-03-10 02:21:03 +0200 (Ср, 10 мар 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_PACKET_H
+#define __ICQ_PACKET_H
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+
+/*---------* Structures *--------------*/
+
+struct icq_packet
+{
+ WORD wPlace;
+ BYTE nChannel;
+ WORD wLen;
+ BYTE *pData;
+};
+
+/*---------* Functions *---------------*/
+
+WORD generate_flap_sequence();
+
+void __fastcall init_generic_packet(icq_packet *pPacket, WORD wHeaderLen);
+void write_httphdr(icq_packet *pPacket, WORD wType, DWORD dwSeq);
+void __fastcall write_flap(icq_packet *pPacket, BYTE byFlapChannel);
+void __fastcall serverPacketInit(icq_packet *pPacket, WORD wSize);
+void __fastcall directPacketInit(icq_packet *pPacket, DWORD dwSize);
+
+void __fastcall serverCookieInit(icq_packet *pPacket, BYTE *pCookie, WORD wCookieSize);
+
+void __fastcall packByte(icq_packet *pPacket, BYTE byValue);
+void __fastcall packWord(icq_packet *pPacket, WORD wValue);
+void __fastcall packDWord(icq_packet *pPacket, DWORD dwValue);
+void __fastcall packQWord(icq_packet *pPacket, DWORD64 qwValue);
+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 packTLVUID(icq_packet *pPacket, WORD wType, DWORD dwUin, const char *szUid);
+
+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, const char *szUid);
+void __fastcall packUIN(icq_packet *pPacket, DWORD dwUin);
+void __fastcall packUID(icq_packet *pPacket, DWORD dwUin, const char *szUid);
+
+void packFNACHeader(icq_packet *pPacket, WORD wFamily, WORD wSubtype);
+void packFNACHeader(icq_packet *pPacket, WORD wFamily, WORD wSubtype, WORD wFlags, DWORD dwSequence);
+void packFNACHeader(icq_packet *pPacket, WORD wFamily, WORD wSubtype, WORD wFlags, DWORD dwSequence, WORD wVersion);
+
+void __fastcall packLEWord(icq_packet *pPacket, WORD wValue);
+void __fastcall packLEDWord(icq_packet *pPacket, DWORD dwValue);
+
+void packLETLVLNTS(PBYTE *buf, int *bufpos, const char *str, WORD wType);
+
+void ppackByte(PBYTE *buf, int *buflen, BYTE byValue);
+void ppackWord(PBYTE *buf, int *buflen, WORD wValue);
+void ppackLEWord(PBYTE *buf, int *buflen, WORD wValue);
+void ppackLEDWord(PBYTE *buf, int *buflen, DWORD dwValue);
+void ppackLELNTS(PBYTE *buf, int *buflen, const char *str);
+void ppackBuffer(PBYTE *buf, int *buflen, WORD wLength, const BYTE *pbyValue);
+
+void ppackTLV(PBYTE *buf, int *buflen, WORD wType, WORD wLength, const BYTE *pbyValue);
+void ppackTLVByte(PBYTE *buf, int *buflen, WORD wType, BYTE byValue);
+void ppackTLVWord(PBYTE *buf, int *buflen, WORD wType, WORD wValue);
+void ppackTLVDWord(PBYTE *buf, int *buflen, WORD wType, DWORD dwValue);
+void ppackTLVDouble(PBYTE *buf, int *buflen, WORD wType, double dValue);
+void ppackTLVUID(PBYTE *buf, int *buflen, WORD wType, DWORD dwUin, const char *szUid);
+
+void ppackLETLVByte(PBYTE *buf, int *buflen, BYTE byValue, WORD wType, BYTE always);
+void ppackLETLVWord(PBYTE *buf, int *buflen, WORD wValue, WORD wType, BYTE always);
+void ppackLETLVDWord(PBYTE *buf, int *buflen, DWORD dwValue, WORD wType, BYTE always);
+void ppackLETLVLNTS(PBYTE *buf, int *buflen, const char *str, WORD wType, BYTE always);
+void ppackLETLVWordLNTS(PBYTE *buf, int *buflen, WORD w, const char *str, WORD wType, BYTE always);
+void ppackLETLVLNTSByte(PBYTE *buf, int *buflen, const char *str, BYTE b, WORD wType);
+
+void ppackTLVBlockItems(PBYTE *buf, int *buflen, WORD wType, int *nItems, PBYTE *pBlock, WORD *wLength, BOOL bSingleItem);
+void ppackTLVBlockItem(PBYTE *buf, int *buflen, WORD wType, PBYTE *pItem, WORD *wLength);
+
+void __fastcall unpackByte(BYTE **pSource, BYTE *byDestination);
+void __fastcall unpackWord(BYTE **pSource, WORD *wDestination);
+void __fastcall unpackDWord(BYTE **pSource, DWORD *dwDestination);
+void __fastcall unpackQWord(BYTE **pSource, DWORD64 *qwDestination);
+void unpackString(BYTE **buf, char *string, WORD len);
+void unpackWideString(BYTE **buf, WCHAR *string, WORD len);
+void unpackTypedTLV(BYTE *buf, int buflen, WORD type, WORD *ttype, WORD *tlen, BYTE **ttlv);
+BOOL unpackUID(BYTE **ppBuf, WORD *pwLen, DWORD *pdwUIN, uid_str *ppszUID);
+
+void __fastcall unpackLEWord(BYTE **buf, WORD *w);
+void __fastcall unpackLEDWord(BYTE **buf, DWORD *dw);
+
+#endif /* __ICQ_PACKET_H */
diff --git a/protocols/IcqOscarJ/icq_popups.cpp b/protocols/IcqOscarJ/icq_popups.cpp
new file mode 100644
index 0000000000..d40b2526a1
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_popups.cpp
@@ -0,0 +1,257 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_popups.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// PopUp Plugin stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+BOOL bPopUpService = FALSE;
+
+void InitPopUps()
+{
+ if (ServiceExists(MS_POPUP_ADDPOPUPEX))
+ {
+ bPopUpService = TRUE;
+ }
+}
+
+static const UINT icqPopupsControls[] = {
+ IDC_POPUPS_LOG_ENABLED, IDC_POPUPS_SPAM_ENABLED, IDC_PREVIEW, IDC_USEWINCOLORS, IDC_USESYSICONS, IDC_POPUP_LOG0_TIMEOUT,
+ IDC_POPUP_LOG1_TIMEOUT, IDC_POPUP_LOG2_TIMEOUT, IDC_POPUP_LOG3_TIMEOUT, IDC_POPUP_SPAM_TIMEOUT
+};
+
+static const UINT icqPopupColorControls[] = {
+ IDC_POPUP_LOG0_TEXTCOLOR, IDC_POPUP_LOG1_TEXTCOLOR, IDC_POPUP_LOG2_TEXTCOLOR, IDC_POPUP_LOG3_TEXTCOLOR, IDC_POPUP_SPAM_TEXTCOLOR,
+ IDC_POPUP_LOG0_BACKCOLOR, IDC_POPUP_LOG1_BACKCOLOR, IDC_POPUP_LOG2_BACKCOLOR, IDC_POPUP_LOG3_BACKCOLOR, IDC_POPUP_SPAM_BACKCOLOR
+};
+
+INT_PTR CALLBACK DlgProcIcqPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BYTE bEnabled;
+ CIcqProto* ppro = (CIcqProto*)GetWindowLongPtr( hwndDlg, GWLP_USERDATA );
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ ppro = (CIcqProto*)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
+
+ CheckDlgButton(hwndDlg, IDC_POPUPS_LOG_ENABLED, ppro->getSettingByte(NULL,"PopupsLogEnabled",DEFAULT_LOG_POPUPS_ENABLED));
+ CheckDlgButton(hwndDlg, IDC_POPUPS_SPAM_ENABLED, ppro->getSettingByte(NULL,"PopupsSpamEnabled",DEFAULT_SPAM_POPUPS_ENABLED));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG0_TEXTCOLOR, CPM_SETCOLOUR, 0, ppro->getSettingDword(NULL,"Popups0TextColor",DEFAULT_LOG0_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG0_BACKCOLOR, CPM_SETCOLOUR, 0, ppro->getSettingDword(NULL,"Popups0BackColor",DEFAULT_LOG0_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG0_TIMEOUT, ppro->getSettingDword(NULL,"Popups0Timeout",DEFAULT_LOG0_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG1_TEXTCOLOR, CPM_SETCOLOUR, 0, ppro->getSettingDword(NULL,"Popups1TextColor",DEFAULT_LOG1_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG1_BACKCOLOR, CPM_SETCOLOUR, 0, ppro->getSettingDword(NULL,"Popups1BackColor",DEFAULT_LOG1_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG1_TIMEOUT, ppro->getSettingDword(NULL,"Popups1Timeout",DEFAULT_LOG1_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG2_TEXTCOLOR, CPM_SETCOLOUR, 0, ppro->getSettingDword(NULL,"Popups2TextColor",DEFAULT_LOG2_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG2_BACKCOLOR, CPM_SETCOLOUR, 0, ppro->getSettingDword(NULL,"Popups2BackColor",DEFAULT_LOG2_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG2_TIMEOUT, ppro->getSettingDword(NULL,"Popups2Timeout",DEFAULT_LOG2_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG3_TEXTCOLOR, CPM_SETCOLOUR, 0, ppro->getSettingDword(NULL,"Popups3TextColor",DEFAULT_LOG3_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG3_BACKCOLOR, CPM_SETCOLOUR, 0, ppro->getSettingDword(NULL,"Popups3BackColor",DEFAULT_LOG3_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG3_TIMEOUT, ppro->getSettingDword(NULL,"Popups3Timeout",DEFAULT_LOG3_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_SPAM_TEXTCOLOR, CPM_SETCOLOUR, 0, ppro->getSettingDword(NULL,"PopupsSpamTextColor",DEFAULT_SPAM_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_SPAM_BACKCOLOR, CPM_SETCOLOUR, 0, ppro->getSettingDword(NULL,"PopupsSpamBackColor",DEFAULT_SPAM_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_SPAM_TIMEOUT, ppro->getSettingDword(NULL,"PopupsSpamTimeout",DEFAULT_SPAM_TIMEOUT),FALSE);
+ bEnabled = ppro->getSettingByte(NULL,"PopupsWinColors",DEFAULT_POPUPS_WIN_COLORS);
+ CheckDlgButton(hwndDlg, IDC_USEWINCOLORS, bEnabled);
+ icq_EnableMultipleControls(hwndDlg, icqPopupColorControls, SIZEOF(icqPopupColorControls), bEnabled);
+ CheckDlgButton(hwndDlg, IDC_USESYSICONS, ppro->getSettingByte(NULL,"PopupsSysIcons",DEFAULT_POPUPS_SYS_ICONS));
+ bEnabled = ppro->getSettingByte(NULL,"PopupsEnabled",DEFAULT_POPUPS_ENABLED);
+ CheckDlgButton(hwndDlg, IDC_POPUPS_ENABLED, bEnabled);
+ icq_EnableMultipleControls(hwndDlg, icqPopupsControls, SIZEOF(icqPopupsControls), bEnabled);
+ icq_EnableMultipleControls(hwndDlg, icqPopupColorControls, SIZEOF(icqPopupColorControls), bEnabled & !IsDlgButtonChecked(hwndDlg,IDC_USEWINCOLORS));
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_PREVIEW:
+ {
+ ppro->ShowPopUpMsg(NULL, LPGEN("Popup Title"), LPGEN("Sample Note"), LOG_NOTE);
+ ppro->ShowPopUpMsg(NULL, LPGEN("Popup Title"), LPGEN("Sample Warning"), LOG_WARNING);
+ ppro->ShowPopUpMsg(NULL, LPGEN("Popup Title"), LPGEN("Sample Error"), LOG_ERROR);
+ ppro->ShowPopUpMsg(NULL, LPGEN("Popup Title"), LPGEN("Sample Fatal"), LOG_FATAL);
+ ppro->ShowPopUpMsg(NULL, LPGEN("Popup Title"), LPGEN("Sample Spambot"), POPTYPE_SPAM);
+ }
+ return FALSE;
+
+ case IDC_POPUPS_ENABLED:
+ bEnabled = IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED);
+ icq_EnableMultipleControls(hwndDlg, icqPopupsControls, SIZEOF(icqPopupsControls), bEnabled);
+
+ case IDC_USEWINCOLORS:
+ bEnabled = IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED);
+ icq_EnableMultipleControls(hwndDlg, icqPopupColorControls, SIZEOF(icqPopupColorControls), bEnabled & !IsDlgButtonChecked(hwndDlg,IDC_USEWINCOLORS));
+ break;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ ppro->setSettingByte(NULL,"PopupsEnabled",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED));
+ ppro->setSettingByte(NULL,"PopupsLogEnabled",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_POPUPS_LOG_ENABLED));
+ ppro->setSettingByte(NULL,"PopupsSpamEnabled",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_POPUPS_SPAM_ENABLED));
+ ppro->setSettingDword(NULL,"Popups0TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG0_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ppro->setSettingDword(NULL,"Popups0BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG0_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ppro->setSettingDword(NULL,"Popups0Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG0_TIMEOUT, NULL, FALSE));
+ ppro->setSettingDword(NULL,"Popups1TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG1_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ppro->setSettingDword(NULL,"Popups1BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG1_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ppro->setSettingDword(NULL,"Popups1Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG1_TIMEOUT, NULL, FALSE));
+ ppro->setSettingDword(NULL,"Popups2TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG2_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ppro->setSettingDword(NULL,"Popups2BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG2_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ppro->setSettingDword(NULL,"Popups2Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG2_TIMEOUT, NULL, FALSE));
+ ppro->setSettingDword(NULL,"Popups3TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG3_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ppro->setSettingDword(NULL,"Popups3BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG3_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ppro->setSettingDword(NULL,"Popups3Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG3_TIMEOUT, NULL, FALSE));
+ ppro->setSettingDword(NULL,"PopupsSpamTextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_SPAM_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ ppro->setSettingDword(NULL,"PopupsSpamBackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_SPAM_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ ppro->setSettingDword(NULL,"PopupsSpamTimeout",GetDlgItemInt(hwndDlg, IDC_POPUP_SPAM_TIMEOUT, NULL, FALSE));
+ ppro->setSettingByte(NULL,"PopupsWinColors",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_USEWINCOLORS));
+ ppro->setSettingByte(NULL,"PopupsSysIcons",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_USESYSICONS));
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+int CIcqProto::ShowPopUpMsg(HANDLE hContact, const char *szTitle, const char *szMsg, BYTE bType)
+{
+ if (bPopUpService && getSettingByte(NULL, "PopupsEnabled", DEFAULT_POPUPS_ENABLED))
+ {
+ POPUPDATAEX ppd = {0};
+ POPUPDATAW ppdw = {0};
+ LPCTSTR rsIcon;
+ char szPrefix[32], szSetting[32];
+
+ strcpy(szPrefix, "Popups");
+ ppd.iSeconds = 0;
+
+ switch(bType) {
+ case LOG_NOTE:
+ rsIcon = MAKEINTRESOURCE(IDI_INFORMATION);
+ ppd.colorBack = DEFAULT_LOG0_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG0_TEXT_COLORS;
+ strcat(szPrefix, "0");
+ break;
+
+ case LOG_WARNING:
+ rsIcon = MAKEINTRESOURCE(IDI_WARNING);
+ ppd.colorBack = DEFAULT_LOG1_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG1_TEXT_COLORS;
+ strcat(szPrefix, "1");
+ break;
+
+ case LOG_ERROR:
+ rsIcon = MAKEINTRESOURCE(IDI_ERROR);
+ ppd.colorBack = DEFAULT_LOG2_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG2_TEXT_COLORS;
+ strcat(szPrefix, "2");
+ break;
+
+ case LOG_FATAL:
+ rsIcon = MAKEINTRESOURCE(IDI_ERROR);
+ ppd.colorBack = DEFAULT_LOG3_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG3_TEXT_COLORS;
+ strcat(szPrefix, "3");
+ break;
+
+ case POPTYPE_SPAM:
+ rsIcon = MAKEINTRESOURCE(IDI_WARNING);
+ ppd.colorBack = DEFAULT_SPAM_BACK_COLORS;
+ ppd.colorText = DEFAULT_SPAM_TEXT_COLORS;
+ strcat(szPrefix, "Spam");
+ break;
+ default:
+ return -1;
+ }
+ if (!getSettingByte(NULL, "PopupsSysIcons", DEFAULT_POPUPS_SYS_ICONS))
+ ppd.lchIcon = m_hIconProtocol->GetIcon();
+ else
+ ppd.lchIcon = (HICON)LoadImage( NULL, rsIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ if (getSettingByte(NULL, "PopupsWinColors", DEFAULT_POPUPS_WIN_COLORS))
+ {
+ ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ ppd.colorBack = GetSysColor(COLOR_WINDOW);
+ }
+ else
+ {
+ strcpy(szSetting, szPrefix);
+ strcat(szSetting, "TextColor");
+ ppd.colorText = getSettingDword(NULL, szSetting, ppd.colorText);
+ strcpy(szSetting, szPrefix);
+ strcat(szSetting, "BackColor");
+ ppd.colorBack = getSettingDword(NULL, szSetting, ppd.colorBack);
+ }
+ strcpy(szSetting, szPrefix);
+ strcat(szSetting, "Timeout");
+ ppd.iSeconds = getSettingDword(NULL, szSetting, ppd.iSeconds);
+
+#if defined( _UNICODE )
+ // call unicode popup module - only on unicode OS otherwise it will not work properly :(
+ // due to Popup Plug bug in ADDPOPUPW implementation
+ if ( ServiceExists( MS_POPUP_ADDPOPUPW ))
+ {
+ char str[4096];
+
+ make_unicode_string_static(ICQTranslateUtfStatic(szTitle, str, sizeof(str)), ppdw.lpwzContactName, MAX_CONTACTNAME);
+ make_unicode_string_static(ICQTranslateUtfStatic(szMsg, str, sizeof(str)), ppdw.lpwzText, MAX_SECONDLINE);
+ ppdw.lchContact = hContact;
+ ppdw.lchIcon = ppd.lchIcon;
+ ppdw.colorBack = ppd.colorBack;
+ ppdw.colorText = ppd.colorText;
+ ppdw.PluginWindowProc = NULL;
+ ppdw.PluginData = NULL;
+ ppdw.iSeconds = ppd.iSeconds;
+ return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&ppdw, 0);
+ }
+ else
+#endif
+ {
+ char str[MAX_PATH];
+
+ utf8_decode_static(ICQTranslateUtfStatic(szTitle, str, MAX_PATH), ppd.lpzContactName, MAX_CONTACTNAME);
+ utf8_decode_static(ICQTranslateUtfStatic(szMsg, str, MAX_PATH), ppd.lpzText, MAX_SECONDLINE);
+ ppd.lchContact = hContact;
+ ppd.PluginWindowProc = NULL;
+ ppd.PluginData = NULL;
+
+ return CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+ }
+ }
+ return -1; // Failure
+}
diff --git a/protocols/IcqOscarJ/icq_popups.h b/protocols/IcqOscarJ/icq_popups.h
new file mode 100644
index 0000000000..92c6882554
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_popups.h
@@ -0,0 +1,48 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_popups.h $
+// Revision : $Revision: 7484 $
+// Last change on : $Date: 2008-03-21 11:43:39 +0200 (Пт, 21 мар 2008) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Headers for PopUp Plugin support
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_POPUPS_H
+#define __ICQ_POPUPS_H
+
+
+#define POPTYPE_SPAM 254 // this is for spambots
+
+
+void InitPopUps();
+void InitPopupOpts(WPARAM wParam);
+
+
+#endif /* __ICQ_POPUPS_H */
diff --git a/protocols/IcqOscarJ/icq_proto.cpp b/protocols/IcqOscarJ/icq_proto.cpp
new file mode 100644
index 0000000000..b87f21180a
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_proto.cpp
@@ -0,0 +1,2415 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 Joe Kucera, George Hazan
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_proto.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Protocol Interface Implementation
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+#include "m_icolib.h"
+#include "m_updater.h"
+
+
+extern PLUGININFOEX pluginInfo;
+extern HANDLE hExtraXStatus;
+
+#pragma warning(disable:4355)
+
+static int CompareConns(const directconnect* p1, const directconnect* p2)
+{
+ if (p1 < p2)
+ return -1;
+
+ return (p1 == p2) ? 0 : 1;
+}
+
+static int CompareCookies( const icq_cookie_info* p1, const icq_cookie_info* p2 )
+{
+ if ( p1->dwCookie < p2->dwCookie )
+ return -1;
+
+ return ( p1->dwCookie == p2->dwCookie ) ? 0 : 1;
+}
+
+static int CompareFT( const filetransfer* p1, const filetransfer* p2 )
+{
+ if ( p1->dwCookie < p2->dwCookie )
+ return -1;
+
+ return ( p1->dwCookie == p2->dwCookie ) ? 0 : 1;
+}
+
+static int CompareContactsCache(const icq_contacts_cache *p1, const icq_contacts_cache *p2)
+{
+ if (p1->dwUin < p2->dwUin)
+ return -1;
+
+ if (p1->dwUin > p2->dwUin)
+ return 1;
+
+ return stricmpnull(p1->szUid, p2->szUid);
+}
+
+CIcqProto::CIcqProto( const char* aProtoName, const TCHAR* aUserName ) :
+cookies(10, CompareCookies),
+directConns(10, CompareConns),
+expectedFileRecvs(10, CompareFT),
+contactsCache(10, CompareContactsCache),
+cheekySearchId( -1 )
+{
+ m_iVersion = 2;
+ m_iStatus = ID_STATUS_OFFLINE;
+ m_tszUserName = mir_tstrdup( aUserName );
+ m_szModuleName = mir_strdup( aProtoName );
+ m_szProtoName = mir_strdup( aProtoName );
+ _strlwr( m_szProtoName );
+ m_szProtoName[0] = toupper( m_szProtoName[0] );
+ NetLog_Server( "Setting protocol/module name to '%s/%s'", m_szProtoName, m_szModuleName );
+
+ oftMutex = new icq_critical_section();
+
+ // Initialize direct connections
+ directConnListMutex = new icq_critical_section();
+ expectedFileRecvMutex = new icq_critical_section();
+
+ // Initialize server lists
+ servlistMutex = new icq_critical_section();
+ servlistQueueMutex = new icq_critical_section();
+ HookProtoEvent(ME_CLIST_GROUPCHANGE, &CIcqProto::ServListCListGroupChange);
+
+ // Initialize status message struct
+ ZeroMemory(&m_modeMsgs, sizeof(icq_mode_messages));
+ m_modeMsgsMutex = new icq_critical_section();
+ connectionHandleMutex = new icq_critical_section();
+ localSeqMutex = new icq_critical_section();
+
+ m_modeMsgsEvent = CreateProtoEvent(ME_ICQ_STATUSMSGREQ);
+ hxstatuschanged = CreateProtoEvent(ME_ICQ_CUSTOMSTATUS_CHANGED);
+ hxstatusiconchanged = CreateProtoEvent(ME_ICQ_CUSTOMSTATUS_EXTRAICON_CHANGED);
+
+ // Initialize cookies
+ cookieMutex = new icq_critical_section();
+ wCookieSeq = 2;
+
+ // Initialize rates
+ m_ratesMutex = new icq_critical_section();
+
+ // Initialize avatars
+ m_avatarsMutex = new icq_critical_section();
+
+ // Initialize temporary DB settings
+ CreateResidentSetting("Status"); // NOTE: XStatus cannot be temporary
+ CreateResidentSetting("TemporaryVisible");
+ CreateResidentSetting("TickTS");
+ CreateResidentSetting("IdleTS");
+ CreateResidentSetting("AwayTS");
+ CreateResidentSetting("LogonTS");
+ CreateResidentSetting("DCStatus");
+ CreateResidentSetting(DBSETTING_STATUS_NOTE_TIME);
+ CreateResidentSetting(DBSETTING_STATUS_MOOD);
+
+ // Setup services
+ CreateProtoService(PS_CREATEACCMGRUI, &CIcqProto::OnCreateAccMgrUI );
+ CreateProtoService(MS_ICQ_SENDSMS, &CIcqProto::SendSms);
+ CreateProtoService(PS_SET_NICKNAME, &CIcqProto::SetNickName);
+
+ CreateProtoService(PS_GETMYAWAYMSG, &CIcqProto::GetMyAwayMsg);
+
+ CreateProtoService(PS_GETINFOSETTING, &CIcqProto::GetInfoSetting);
+
+ CreateProtoService(PSS_ADDED, &CIcqProto::SendYouWereAdded);
+ // Session password API
+ CreateProtoService(PS_ICQ_SETPASSWORD, &CIcqProto::SetPassword);
+ // ChangeInfo API
+ CreateProtoService(PS_CHANGEINFOEX, &CIcqProto::ChangeInfoEx);
+ // Avatar API
+ CreateProtoService(PS_GETAVATARINFOT, &CIcqProto::GetAvatarInfo);
+ CreateProtoService(PS_GETAVATARCAPS, &CIcqProto::GetAvatarCaps);
+ CreateProtoService(PS_GETMYAVATART, &CIcqProto::GetMyAvatar);
+ CreateProtoService(PS_SETMYAVATART, &CIcqProto::SetMyAvatar);
+ // Custom Status API
+ CreateProtoService(PS_ICQ_SETCUSTOMSTATUS, &CIcqProto::SetXStatus);
+ CreateProtoService(PS_ICQ_GETCUSTOMSTATUS, &CIcqProto::GetXStatus);
+ CreateProtoService(PS_ICQ_SETCUSTOMSTATUSEX, &CIcqProto::SetXStatusEx);
+ CreateProtoService(PS_ICQ_GETCUSTOMSTATUSEX, &CIcqProto::GetXStatusEx);
+ CreateProtoService(PS_ICQ_GETCUSTOMSTATUSICON, &CIcqProto::GetXStatusIcon);
+ CreateProtoService(PS_ICQ_REQUESTCUSTOMSTATUS, &CIcqProto::RequestXStatusDetails);
+ CreateProtoService(PS_ICQ_GETADVANCEDSTATUSICON, &CIcqProto::RequestAdvStatusIconIdx);
+
+ CreateProtoService(MS_ICQ_ADDSERVCONTACT, &CIcqProto::AddServerContact);
+
+ CreateProtoService(MS_REQ_AUTH, &CIcqProto::RequestAuthorization);
+ CreateProtoService(MS_GRANT_AUTH, &CIcqProto::GrantAuthorization);
+ CreateProtoService(MS_REVOKE_AUTH, &CIcqProto::RevokeAuthorization);
+
+ CreateProtoService(MS_XSTATUS_SHOWDETAILS, &CIcqProto::ShowXStatusDetails);
+
+ HookProtoEvent(ME_SKIN2_ICONSCHANGED, &CIcqProto::OnReloadIcons);
+
+ {
+ // Initialize IconLib icons
+ char szSectionName[MAX_PATH], *szAccountName = tchar_to_utf8(m_tszUserName);
+ null_snprintf(szSectionName, sizeof(szSectionName), "Protocols/%s/Accounts", ICQ_PROTOCOL_NAME);
+
+ TCHAR lib[MAX_PATH];
+ GetModuleFileName(hInst, lib, MAX_PATH);
+
+ m_hIconProtocol = IconLibDefine(szAccountName, szSectionName, m_szModuleName, "main", lib, -IDI_ICQ);
+ SAFE_FREE(&szAccountName);
+ }
+
+ // Reset a bunch of session specific settings
+ UpdateGlobalSettings();
+ ResetSettingsOnLoad();
+
+ // Initialize Contacts Cache
+ InitContactsCache();
+
+ // Startup Auto Info-Update thread
+ icq_InitInfoUpdate();
+
+ // Init extra statuses
+ InitXStatusIcons();
+
+ HookProtoEvent(ME_CLIST_PREBUILDSTATUSMENU, &CIcqProto::OnPreBuildStatusMenu);
+
+ // Register netlib users
+ NETLIBUSER nlu = {0};
+ TCHAR szBuffer[MAX_PATH + 64];
+ null_snprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s server connection"), m_tszUserName);
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_TCHAR;
+ nlu.ptszDescriptiveName = szBuffer;
+ nlu.szSettingsModule = m_szModuleName;
+ nlu.szHttpGatewayHello = "http://http.proxy.icq.com/hello";
+ nlu.szHttpGatewayUserAgent = "Mozilla/4.08 [en] (WinNT; U ;Nav)";
+ nlu.pfnHttpGatewayInit = icq_httpGatewayInit;
+ nlu.pfnHttpGatewayBegin = icq_httpGatewayBegin;
+ nlu.pfnHttpGatewayWrapSend = icq_httpGatewayWrapSend;
+ nlu.pfnHttpGatewayUnwrapRecv = icq_httpGatewayUnwrapRecv;
+ m_hServerNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+
+ char szP2PModuleName[MAX_PATH];
+ null_snprintf(szP2PModuleName, SIZEOF(szP2PModuleName), "%sP2P", m_szModuleName);
+ null_snprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s client-to-client connections"), m_tszUserName);
+ nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_TCHAR;
+ nlu.ptszDescriptiveName = szBuffer;
+ nlu.szSettingsModule = szP2PModuleName;
+ nlu.minIncomingPorts = 1;
+ m_hDirectNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+
+ // Register custom database events
+ DBEVENTTYPEDESCR eventType = {0};
+ eventType.cbSize = DBEVENTTYPEDESCR_SIZE;
+ eventType.eventType = ICQEVENTTYPE_MISSEDMESSAGE;
+ eventType.module = m_szModuleName;
+ eventType.descr = "Missed message notifications";
+ eventType.textService = ICQ_DB_GETEVENTTEXT_MISSEDMESSAGE;
+ eventType.flags = DETF_HISTORY | DETF_MSGWINDOW;
+ // for now keep default "message" icon
+ CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&eventType);
+
+ // Protocol instance is ready
+ NetLog_Server("%s: Protocol instance '%s' created.", ICQ_PROTOCOL_NAME, m_szModuleName);
+}
+
+
+CIcqProto::~CIcqProto()
+{
+ m_bXStatusEnabled = 10; // block clist changing
+ m_bMoodsEnabled = 10;
+
+ // Make sure all connections are closed
+ CloseContactDirectConns(NULL);
+ while ( true ) {
+ if ( !directConns.getCount())
+ break;
+
+ Sleep(10); /* yeah, ugly */
+ }
+
+ // Serv-list update board clean-up
+ FlushServerIDs();
+ /// TODO: make sure server-list handler thread is not running
+ /// TODO: save state of server-list update board to DB
+ servlistPendingFlushOperations();
+ SAFE_FREE((void**)&servlistQueueList);
+
+ // Finalize avatars
+ /// TODO: cleanup remaining avatar requests
+ SAFE_DELETE(&m_avatarsMutex);
+
+ // NetLib clean-up
+ NetLib_SafeCloseHandle(&m_hDirectNetlibUser);
+ NetLib_SafeCloseHandle(&m_hServerNetlibUser);
+
+ // Destroy hookable events
+ if (m_modeMsgsEvent)
+ DestroyHookableEvent(m_modeMsgsEvent);
+
+ if (hxstatuschanged)
+ DestroyHookableEvent(hxstatuschanged);
+
+ if (hxstatusiconchanged)
+ DestroyHookableEvent(hxstatusiconchanged);
+
+ // Clean-up remaining protocol instance members
+ cookies.destroy();
+
+ UninitContactsCache();
+
+ SAFE_DELETE(&m_ratesMutex);
+
+ SAFE_DELETE(&servlistMutex);
+ SAFE_DELETE(&servlistQueueMutex);
+
+ SAFE_DELETE(&m_modeMsgsMutex);
+ SAFE_DELETE(&localSeqMutex);
+ SAFE_DELETE(&connectionHandleMutex);
+ SAFE_DELETE(&oftMutex);
+ SAFE_DELETE(&directConnListMutex);
+ SAFE_DELETE(&expectedFileRecvMutex);
+ SAFE_DELETE(&cookieMutex);
+
+ SAFE_FREE(&m_modeMsgs.szOnline);
+ SAFE_FREE(&m_modeMsgs.szAway);
+ SAFE_FREE(&m_modeMsgs.szNa);
+ SAFE_FREE(&m_modeMsgs.szOccupied);
+ SAFE_FREE(&m_modeMsgs.szDnd);
+ SAFE_FREE(&m_modeMsgs.szFfc);
+
+ // Remove account icons
+ UninitXStatusIcons();
+
+ IconLibRemove(&m_hIconProtocol);
+
+ NetLog_Server("%s: Protocol instance '%s' destroyed.", ICQ_PROTOCOL_NAME, m_szModuleName);
+
+ mir_free( m_szProtoName );
+ mir_free( m_szModuleName );
+ mir_free( m_tszUserName );
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// OnModulesLoadedEx - performs hook registration
+
+
+int CIcqProto::OnModulesLoaded( WPARAM wParam, LPARAM lParam )
+{
+ char pszP2PName[MAX_PATH];
+ char pszGroupsName[MAX_PATH];
+ char pszSrvGroupsName[MAX_PATH];
+ char* modules[5] = {0,0,0,0,0};
+
+ null_snprintf(pszP2PName, SIZEOF(pszP2PName), "%sP2P", m_szModuleName);
+ null_snprintf(pszGroupsName, SIZEOF(pszGroupsName), "%sGroups", m_szModuleName);
+ null_snprintf(pszSrvGroupsName, SIZEOF(pszSrvGroupsName), "%sSrvGroups", m_szModuleName);
+ modules[0] = m_szModuleName;
+ modules[1] = pszP2PName;
+ modules[2] = pszGroupsName;
+ modules[3] = pszSrvGroupsName;
+ CallService("DBEditorpp/RegisterModule",(WPARAM)modules,(LPARAM)4);
+
+ HookProtoEvent(ME_OPT_INITIALISE, &CIcqProto::OnOptionsInit);
+ HookProtoEvent(ME_USERINFO_INITIALISE, &CIcqProto::OnUserInfoInit);
+ HookProtoEvent(ME_IDLE_CHANGED, &CIcqProto::OnIdleChanged);
+
+ InitAvatars();
+
+ // Init extra optional modules
+ InitPopUps();
+ InitXStatusItems(FALSE);
+
+ // TODO: add beta builds support to devel builds :)
+ CallService(MS_UPDATE_REGISTERFL, 1683, (WPARAM)&pluginInfo);
+
+ if (hExtraXStatus == NULL)
+ {
+ if (HookProtoEvent(ME_CLIST_EXTRA_LIST_REBUILD, &CIcqProto::CListMW_ExtraIconsRebuild))
+ { // note if the Hook was successful (e.g. clist_nicer creates them too late)
+ HookProtoEvent(ME_CLIST_EXTRA_IMAGE_APPLY, &CIcqProto::CListMW_ExtraIconsApply);
+ bXStatusExtraIconsReady = 1;
+ }
+ }
+ else
+ {
+ HANDLE hContact = FindFirstContact();
+ while (hContact != NULL)
+ {
+ DWORD bXStatus = getContactXStatus(hContact);
+ if (bXStatus > 0)
+ setContactExtraIcon(hContact, bXStatus);
+
+ hContact = FindNextContact(hContact);
+ }
+ }
+
+ return 0;
+}
+
+int CIcqProto::OnPreShutdown(WPARAM wParam,LPARAM lParam)
+{
+ // all threads should be terminated here
+ icq_InfoUpdateCleanup();
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_AddToList - adds a contact to the contact list
+
+HANDLE CIcqProto::AddToList( int flags, PROTOSEARCHRESULT* psr )
+{
+ if (psr)
+ {
+ if (psr->cbSize == sizeof(ICQSEARCHRESULT))
+ {
+ ICQSEARCHRESULT *isr = (ICQSEARCHRESULT*)psr;
+ if (isr->uin)
+ return AddToListByUIN(isr->uin, flags);
+ else
+ { // aim contact
+ char szUid[MAX_PATH];
+
+ if (isr->hdr.flags & PSR_UNICODE)
+ unicode_to_ansi_static((WCHAR*)isr->hdr.id, szUid, MAX_PATH);
+ else
+ null_strcpy(szUid, (char*)isr->hdr.id, MAX_PATH);
+
+ if (szUid[0] == 0) return 0;
+ return AddToListByUID(szUid, flags);
+ }
+ }
+ else
+ {
+ char szUid[MAX_PATH];
+
+ if (psr->flags & PSR_UNICODE)
+ unicode_to_ansi_static((WCHAR*)psr->id, szUid, MAX_PATH);
+ else
+ null_strcpy(szUid, (char*)psr->id, MAX_PATH);
+
+ if (szUid[0] == 0) return 0;
+ if (IsStringUIN(szUid))
+ return AddToListByUIN(atoi(szUid), flags);
+ else
+ return AddToListByUID(szUid, flags);
+ }
+ }
+
+ return 0; // Failure
+}
+
+HANDLE __cdecl CIcqProto::AddToListByEvent( int flags, int iContact, HANDLE hDbEvent )
+{
+ DWORD uin = 0;
+ uid_str uid = {0};
+
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ if ((dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0)) == -1)
+ return 0;
+
+ dbei.pBlob = (PBYTE)_alloca(dbei.cbBlob + 1);
+ dbei.pBlob[dbei.cbBlob] = '\0';
+
+ if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei))
+ return 0; // failed to get event
+
+ if (strcmpnull(dbei.szModule, m_szModuleName))
+ return 0; // this event is not ours
+
+ if (dbei.eventType == EVENTTYPE_CONTACTS)
+ {
+ int i;
+ char *pbOffset, *pbEnd;
+
+ for (i = 0, pbOffset = (char*)dbei.pBlob, pbEnd = pbOffset + dbei.cbBlob; i <= iContact; i++)
+ {
+ pbOffset += strlennull(pbOffset) + 1; // Nick
+ if (pbOffset >= pbEnd) break;
+ if (i == iContact)
+ { // we found the contact, get uid
+ if (IsStringUIN((char*)pbOffset))
+ uin = atoi((char*)pbOffset);
+ else
+ {
+ uin = 0;
+ strcpy(uid, (char*)pbOffset);
+ }
+ }
+ pbOffset += strlennull(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 + sizeof(DWORD)); // this sucks - awaiting new auth system
+ if (getContactUid(hContact, &uin, &uid))
+ return 0;
+ }
+
+ if (uin != 0)
+ return AddToListByUIN(uin, flags); // Success
+
+ // add aim contact
+ if (strlennull(uid))
+ return AddToListByUID(uid, flags); // Success
+
+ return NULL; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_AuthAllow - processes the successful authorization
+
+int CIcqProto::Authorize( HANDLE hDbEvent )
+{
+ if (icqOnline() && hDbEvent)
+ {
+ HANDLE hContact = HContactFromAuthEvent( hDbEvent );
+ if (hContact == INVALID_HANDLE_VALUE)
+ return 1;
+
+ DWORD uin;
+ uid_str uid;
+ if (getContactUid(hContact, &uin, &uid))
+ return 1;
+
+ icq_sendAuthResponseServ(uin, uid, 1, _T(""));
+
+ deleteSetting(hContact, "Grant");
+
+ return 0; // Success
+ }
+
+ return 1; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_AuthDeny - handles the unsuccessful authorization
+
+int CIcqProto::AuthDeny( HANDLE hDbEvent, const TCHAR* szReason )
+{
+ if (icqOnline() && hDbEvent)
+ {
+ HANDLE hContact = HContactFromAuthEvent(hDbEvent);
+ if (hContact == INVALID_HANDLE_VALUE)
+ return 1;
+
+ DWORD uin;
+ uid_str uid;
+ if (getContactUid(hContact, &uin, &uid))
+ return 1;
+
+ icq_sendAuthResponseServ(uin, uid, 0, szReason);
+
+ if (DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+
+ return 0; // Success
+ }
+
+ return 1; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PSR_AUTH
+
+int __cdecl CIcqProto::AuthRecv( HANDLE hContact, PROTORECVEVENT* pre )
+{
+ setContactHidden( hContact, 0 );
+ ICQAddRecvEvent( NULL, EVENTTYPE_AUTHREQUEST, pre, pre->lParam, (PBYTE)pre->szMessage, 0 );
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PSS_AUTHREQUEST
+
+int __cdecl CIcqProto::AuthRequest( HANDLE hContact, const TCHAR* szMessage )
+{
+ if ( !icqOnline())
+ return 1;
+
+ if (hContact)
+ {
+ DWORD dwUin;
+ uid_str szUid;
+ if (getContactUid(hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+ if (dwUin)
+ {
+ char *utf = tchar_to_utf8(szMessage);
+ icq_sendAuthReqServ(dwUin, szUid, utf);
+ SAFE_FREE(&utf);
+ return 0; // Success
+ }
+ }
+
+ return 1; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// ChangeInfo
+
+HANDLE __cdecl CIcqProto::ChangeInfo( int iInfoType, void* pInfoData )
+{
+ return NULL;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_FileAllow - starts a file transfer
+
+HANDLE __cdecl CIcqProto::FileAllow( HANDLE hContact, HANDLE hTransfer, const TCHAR* szPath )
+{
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (getContactUid(hContact, &dwUin, &szUid))
+ return 0; // Invalid contact
+
+ if (icqOnline() && hContact && szPath && hTransfer)
+ { // approve old fashioned file transfer
+ basic_filetransfer *ft = (basic_filetransfer *)hTransfer;
+
+ if (!IsValidFileTransfer(ft))
+ return 0; // Invalid transfer
+
+ if (dwUin && ft->ft_magic == FT_MAGIC_ICQ)
+ {
+ filetransfer *ft = (filetransfer *)hTransfer;
+ ft->szSavePath = tchar_to_utf8(szPath);
+
+ {
+ icq_lock l(expectedFileRecvMutex);
+ expectedFileRecvs.insert(ft);
+ }
+
+ // Was request received thru DC and have we a open DC, send through that
+ if (ft->bDC && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
+ icq_sendFileAcceptDirect(hContact, ft);
+ else
+ icq_sendFileAcceptServ(dwUin, ft, 0);
+
+ return hTransfer; // Success
+ }
+ else if (ft->ft_magic == FT_MAGIC_OSCAR)
+ { // approve oscar file transfer
+ return oftFileAllow(hContact, hTransfer, szPath);
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_FileCancel - cancels a file transfer
+
+int __cdecl CIcqProto::FileCancel( HANDLE hContact, HANDLE hTransfer )
+{
+ DWORD dwUin;
+ uid_str szUid;
+ if ( getContactUid(hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+ if (hContact && hTransfer)
+ {
+ basic_filetransfer *ft = (basic_filetransfer *)hTransfer;
+
+ if (!IsValidFileTransfer(ft))
+ return 1; // Invalid transfer
+
+ if (dwUin && ft->ft_magic == FT_MAGIC_ICQ)
+ { // cancel old fashioned file transfer
+ filetransfer * ft = (filetransfer*)hTransfer;
+ icq_CancelFileTransfer(hContact, ft);
+ return 0; // Success
+ }
+ else if (ft->ft_magic == FT_MAGIC_OSCAR)
+ { // cancel oscar file transfer
+ return oftFileCancel(hContact, hTransfer);
+ }
+ }
+
+ return 1; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_FileDeny - denies a file transfer
+
+int __cdecl CIcqProto::FileDeny( HANDLE hContact, HANDLE hTransfer, const TCHAR* szReason )
+{
+ int nReturnValue = 1;
+ DWORD dwUin;
+ uid_str szUid;
+ basic_filetransfer *ft = (basic_filetransfer*)hTransfer;
+
+ if (getContactUid(hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+ if (icqOnline() && hTransfer && hContact)
+ {
+ if (!IsValidFileTransfer(hTransfer))
+ return 1; // Invalid transfer
+
+ if (dwUin && ft->ft_magic == FT_MAGIC_ICQ)
+ { // deny old fashioned file transfer
+ filetransfer *ft = (filetransfer*)hTransfer;
+ char *szReasonUtf = tchar_to_utf8(szReason);
+ // Was request received thru DC and have we a open DC, send through that
+ if (ft->bDC && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
+ icq_sendFileDenyDirect(hContact, ft, szReasonUtf);
+ else
+ icq_sendFileDenyServ(dwUin, ft, szReasonUtf, 0);
+ SAFE_FREE(&szReasonUtf);
+
+ nReturnValue = 0; // Success
+ }
+ else if (ft->ft_magic == FT_MAGIC_OSCAR)
+ { // deny oscar file transfer
+ return oftFileDeny(hContact, hTransfer, szReason);
+ }
+ }
+ // Release possible orphan structure
+ SafeReleaseFileTransfer((void**)&ft);
+
+ return nReturnValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_FileResume - processes file renaming etc
+
+int __cdecl CIcqProto::FileResume( HANDLE hTransfer, int* action, const TCHAR** szFilename )
+{
+ if (icqOnline() && hTransfer)
+ {
+ basic_filetransfer *ft = (basic_filetransfer *)hTransfer;
+
+ if (!IsValidFileTransfer(ft))
+ return 1; // Invalid transfer
+
+ if (ft->ft_magic == FT_MAGIC_ICQ)
+ {
+ char *szFileNameUtf = tchar_to_utf8(*szFilename);
+ icq_sendFileResume((filetransfer *)hTransfer, *action, szFileNameUtf);
+ SAFE_FREE(&szFileNameUtf);
+ }
+ else if (ft->ft_magic == FT_MAGIC_OSCAR)
+ {
+ oftFileResume((oscar_filetransfer *)hTransfer, *action, *szFilename);
+ }
+ else
+ return 1; // Failure
+
+ return 0; // Success
+ }
+
+ return 1; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// GetCaps - return protocol capabilities bits
+
+DWORD_PTR __cdecl CIcqProto::GetCaps( int type, HANDLE hContact )
+{
+ DWORD_PTR nReturn = 0;
+
+ switch ( type ) {
+
+ 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 (!m_bAimEnabled)
+ nReturn |= PF1_NUMERICUSERID;
+ if (m_bSsiEnabled && getSettingByte(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;
+ if (m_bAimEnabled)
+ nReturn |= PF2_ONTHEPHONE;
+ break;
+
+ case PFLAGNUM_3:
+ nReturn = PF2_ONLINE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND |
+ PF2_FREECHAT | PF2_INVISIBLE;
+ break;
+
+ case PFLAGNUM_4:
+ nReturn = PF4_SUPPORTIDLE | PF4_IMSENDUTF | PF4_IMSENDOFFLINE | PF4_INFOSETTINGSVC;
+ if (m_bAvatarsEnabled)
+ nReturn |= PF4_AVATARS;
+#ifdef DBG_CAPMTN
+ nReturn |= PF4_SUPPORTTYPING;
+#endif
+ break;
+
+ case PFLAGNUM_5:
+ nReturn = PF2_FREECHAT;
+ if (m_bAimEnabled)
+ nReturn |= PF2_ONTHEPHONE;
+ break;
+
+ case PFLAG_UNIQUEIDTEXT:
+ nReturn = (DWORD_PTR)Translate("User ID");
+ break;
+
+ case PFLAG_UNIQUEIDSETTING:
+ nReturn = (DWORD_PTR)UNIQUEIDSETTING;
+ break;
+
+ case PFLAG_MAXCONTACTSPERPACKET:
+ if ( hContact )
+ { // determine per contact
+ BYTE bClientId = getSettingByte(hContact, "ClientID", CLID_GENERIC);
+
+ if (bClientId == CLID_MIRANDA)
+ {
+ if (CheckContactCapabilities(hContact, CAPF_CONTACTS) && getContactStatus(hContact) != ID_STATUS_OFFLINE)
+ nReturn = 0x100; // limited only by packet size
+ else
+ nReturn = MAX_CONTACTSSEND;
+ }
+ else if (bClientId == CLID_ICQ6)
+ {
+ if (CheckContactCapabilities(hContact, 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;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// GetIcon - loads an icon for the contact list
+
+HICON __cdecl CIcqProto::GetIcon( int iconIndex )
+{
+ if (LOWORD(iconIndex) == PLI_PROTOCOL)
+ {
+ if (iconIndex & PLIF_ICOLIBHANDLE)
+ return (HICON)m_hIconProtocol->Handle();
+
+ bool big = (iconIndex & PLIF_SMALL) == 0;
+ HICON hIcon = m_hIconProtocol->GetIcon(big);
+
+ if (iconIndex & PLIF_ICOLIB)
+ return hIcon;
+
+ hIcon = CopyIcon(hIcon);
+ m_hIconProtocol->ReleaseIcon(big);
+ return hIcon;
+
+ }
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// GetInfo - retrieves a contact info
+
+int __cdecl CIcqProto::GetInfo(HANDLE hContact, int infoType)
+{
+ if (icqOnline())
+ {
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (getContactUid(hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+ DWORD dwCookie;
+ if (dwUin)
+ dwCookie = icq_sendGetInfoServ(hContact, dwUin, (infoType & SGIF_ONOPEN) != 0);
+ else // TODO: this needs something better
+ dwCookie = icq_sendGetAimProfileServ(hContact, szUid);
+
+ return (dwCookie) ? 0 : 1;
+ }
+
+ return 1; // Failure
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SearchBasic - searches the contact by UID
+
+void CIcqProto::CheekySearchThread( void* )
+{
+ char szUin[UINMAXLEN];
+ ICQSEARCHRESULT isr = {0};
+ isr.hdr.cbSize = sizeof(isr);
+
+ if (cheekySearchUin)
+ {
+ _itoa(cheekySearchUin, szUin, 10);
+ isr.hdr.id = (FNAMECHAR*)szUin;
+ }
+ else
+ {
+ isr.hdr.id = (FNAMECHAR*)cheekySearchUid;
+ }
+ isr.uin = cheekySearchUin;
+
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)cheekySearchId, (LPARAM)&isr);
+ BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)cheekySearchId, 0);
+ cheekySearchId = -1;
+}
+
+
+HANDLE __cdecl CIcqProto::SearchBasic( const PROTOCHAR *pszSearch )
+{
+ if (strlennull(pszSearch) == 0)
+ return 0;
+
+ char pszUIN[255];
+ int nHandle = 0;
+ int i, j;
+
+ if (!m_bAimEnabled)
+ {
+ 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]!='-'))
+ {
+#ifdef _UNICODE
+ if (pszSearch[i] >= 0x80) continue;
+#endif
+ pszUIN[j] = pszSearch[i];
+ j++;
+ }
+ }
+ }
+ pszUIN[j] = 0;
+
+ if (strlennull(pszUIN))
+ {
+ DWORD dwUin;
+ 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);
+ ForkThread(&CIcqProto::CheekySearchThread, 0); // The caller needs to get this return value before the results
+ nHandle = cheekySearchId;
+ }
+ else if (icqOnline())
+ {
+ nHandle = SearchByUin(dwUin);
+ }
+
+ // Success
+ return (HANDLE)nHandle;
+ }
+
+ // Failure
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SearchByEmail - searches the contact by its e-mail
+
+HANDLE __cdecl CIcqProto::SearchByEmail( const PROTOCHAR *email )
+{
+ if (email && icqOnline() && strlennull(email) > 0)
+ {
+ DWORD dwSearchId, dwSecId;
+ char *szEmail = tchar_to_ansi(email);
+
+ // Success
+ dwSearchId = SearchByMail(szEmail);
+ if (m_bAimEnabled)
+ dwSecId = icq_searchAimByEmail(szEmail, dwSearchId);
+ else
+ dwSecId = 0;
+
+ SAFE_FREE(&szEmail);
+
+ if (dwSearchId)
+ return ( HANDLE )dwSearchId;
+ else
+ return ( HANDLE )dwSecId;
+ }
+
+ return 0; // Failure
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_SearchByName - searches the contact by its first or last name, or by a nickname
+
+HANDLE __cdecl CIcqProto::SearchByName(const PROTOCHAR *nick, const PROTOCHAR *firstName, const PROTOCHAR *lastName)
+{
+ if (icqOnline())
+ {
+ if (nick || firstName || lastName)
+ {
+ char *nickUtf = tchar_to_utf8(nick);
+ char *firstNameUtf = tchar_to_utf8(firstName);
+ char *lastNameUtf = tchar_to_utf8(lastName);
+
+ // Success
+ HANDLE dwCookie = (HANDLE)SearchByNames(nickUtf, firstNameUtf, lastNameUtf, 0);
+
+ SAFE_FREE(&nickUtf);
+ SAFE_FREE(&firstNameUtf);
+ SAFE_FREE(&lastNameUtf);
+
+ return dwCookie;
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+HWND __cdecl CIcqProto::CreateExtendedSearchUI( HWND parent )
+{
+ if (parent && hInst)
+ return CreateDialog(hInst, MAKEINTRESOURCE(IDD_ICQADVANCEDSEARCH), parent, AdvancedSearchDlgProc);
+
+ return NULL; // Failure
+}
+
+HWND __cdecl CIcqProto::SearchAdvanced( HWND hwndDlg )
+{
+ if (icqOnline() && IsWindow(hwndDlg))
+ {
+ int nDataLen;
+ BYTE* bySearchData;
+
+ if (bySearchData = createAdvancedSearchStructure(hwndDlg, &nDataLen))
+ {
+ int result = icq_sendAdvancedSearchServ(bySearchData, nDataLen);
+ SAFE_FREE((void**)&bySearchData);
+ return ( HWND )result; // Success
+ }
+ }
+
+ return NULL; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// RecvContacts
+
+int __cdecl CIcqProto::RecvContacts( HANDLE hContact, PROTORECVEVENT* pre )
+{
+ ICQSEARCHRESULT **isrList = (ICQSEARCHRESULT**)pre->szMessage;
+ int i;
+ DWORD cbBlob = 0;
+ DWORD flags = 0;
+
+ if (pre->flags & PREF_UTF || pre->flags & PREF_UNICODE)
+ flags |= DBEF_UTF;
+
+ for (i = 0; i < pre->lParam; i++)
+ {
+ if (pre->flags & PREF_UNICODE)
+ cbBlob += get_utf8_size((WCHAR*)isrList[i]->hdr.nick) + 2;
+ else
+ cbBlob += strlennull((char*)isrList[i]->hdr.nick) + 2; // both trailing zeros
+ if (isrList[i]->uin)
+ cbBlob += getUINLen(isrList[i]->uin);
+ else if (pre->flags & PREF_UNICODE)
+ cbBlob += strlennull((WCHAR*)isrList[i]->hdr.id);
+ else
+ cbBlob += strlennull((char*)isrList[i]->hdr.id);
+ }
+ PBYTE pBlob = (PBYTE)_alloca(cbBlob), pCurBlob;
+ for (i = 0, pCurBlob = pBlob; i < pre->lParam; i++)
+ {
+ if (pre->flags & PREF_UNICODE)
+ make_utf8_string_static((WCHAR*)isrList[i]->hdr.nick, (char*)pCurBlob, cbBlob - (pCurBlob - pBlob));
+ else
+ strcpy((char*)pCurBlob, (char*)isrList[i]->hdr.nick);
+ pCurBlob += strlennull((char*)pCurBlob) + 1;
+ if (isrList[i]->uin)
+ {
+ char szUin[UINMAXLEN];
+ _itoa(isrList[i]->uin, szUin, 10);
+ strcpy((char*)pCurBlob, szUin);
+ }
+ else
+ { // aim contact
+ if (pre->flags & PREF_UNICODE)
+ unicode_to_ansi_static((WCHAR*)isrList[i]->hdr.id, (char*)pCurBlob, cbBlob - (pCurBlob - pBlob));
+ else
+ strcpy((char*)pCurBlob, (char*)isrList[i]->hdr.id);
+ }
+ pCurBlob += strlennull((char*)pCurBlob) + 1;
+ }
+
+ ICQAddRecvEvent(hContact, EVENTTYPE_CONTACTS, pre, cbBlob, pBlob, flags);
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// RecvFile
+
+int __cdecl CIcqProto::RecvFile( HANDLE hContact, PROTORECVFILET* evt )
+{
+ CCSDATA ccs = { hContact, PSR_FILE, 0, ( LPARAM )evt };
+ return CallService( MS_PROTO_RECVFILE, 0, ( LPARAM )&ccs );
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// RecvMsg
+
+int __cdecl CIcqProto::RecvMsg( HANDLE hContact, PROTORECVEVENT* pre )
+{
+ 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), strlennull((WCHAR*)(pre->szMessage+cbBlob))))
+ cbBlob *= (sizeof(WCHAR)+1);
+
+ ICQAddRecvEvent(hContact, EVENTTYPE_MESSAGE, pre, cbBlob, (PBYTE)pre->szMessage, flags);
+
+ // stop contact from typing - some clients do not sent stop notify
+ if (CheckContactCapabilities(hContact, CAPF_TYPING))
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, PROTOTYPE_CONTACTTYPING_OFF);
+
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// RecvUrl
+
+int __cdecl CIcqProto::RecvUrl( HANDLE hContact, PROTORECVEVENT* )
+{
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SendContacts
+
+int __cdecl CIcqProto::SendContacts( HANDLE hContact, int flags, int nContacts, HANDLE* hContactsList )
+{
+ if (hContact && hContactsList)
+ {
+ int i;
+ DWORD dwUin;
+ uid_str szUid;
+ WORD wRecipientStatus;
+ DWORD dwCookie;
+
+ if (getContactUid(hContact, &dwUin, &szUid))
+ { // Invalid contact
+ return ReportGenericSendError(hContact, ACKTYPE_CONTACTS, "The receiver has an invalid user ID.");
+ }
+
+ wRecipientStatus = getContactStatus(hContact);
+
+ // Failures
+ if (!icqOnline())
+ {
+ dwCookie = ReportGenericSendError(hContact, ACKTYPE_CONTACTS, "You cannot send messages when you are offline.");
+ }
+ else if (!hContactsList || (nContacts < 1) || (nContacts > MAX_CONTACTSSEND))
+ {
+ dwCookie = ReportGenericSendError(hContact, ACKTYPE_CONTACTS, "Bad data (internal error #1)");
+ }
+ // OK
+ else
+ {
+ if (CheckContactCapabilities(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 (getContactUid(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)
+ {
+ 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 = (LPBYTE)SAFE_MALLOC(nDataLen);
+ mData.wLen = nDataLen;
+ mNames.wPlace = 0;
+ mNames.pData = (LPBYTE)SAFE_MALLOC(nNamesLen);
+
+ // pack Group Name
+ packWord(&mData, 7);
+ packBuffer(&mData, (LPBYTE)"General", 7);
+ packWord(&mNames, 7);
+ packBuffer(&mNames, (LPBYTE)"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, (LPBYTE)szContactUid, wLen);
+
+ // prepare Nick
+ wLen = strlennull(contacts[i].szNick);
+ packWord(&mNames, (WORD)(wLen + 4));
+ packTLV(&mNames, 0x01, wLen, (LPBYTE)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((void**)&mData.pData);
+ SAFE_FREE((void**)&mNames.pData);
+
+ return ReportGenericSendError(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
+ cookie_message_data *pCookieData = CreateMessageCookieData(MTYPE_CONTACTS, 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, hContact, (char*)mData.pData, mData.wPlace, (char*)mNames.pData, mNames.wPlace, pCookieData);
+
+ // This will stop the message dialog from waiting for the real message delivery ack
+ if (pCookieData->nAckType == ACKTYPE_NONE)
+ {
+ SendProtoAck(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((void**)&mData.pData);
+ SAFE_FREE((void**)&mNames.pData);
+ }
+ else
+ {
+ dwCookie = ReportGenericSendError(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 (getContactUid(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)
+ {
+ 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);
+ null_strcpy(pBuffer, szCount, nBodyLength - 1);
+ 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
+ cookie_message_data *pCookieData = CreateMessageCookieData(MTYPE_CONTACTS, hContact, dwUin, TRUE);
+
+ if (m_bDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
+ {
+ int iRes = icq_SendDirectMessage(hContact, pBody, nBodyLength, 1, pCookieData, NULL);
+
+ if (iRes)
+ {
+ SAFE_FREE((void**)&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((void**)&pCookieData);
+ SAFE_FREE((void**)&pBody);
+
+ return ReportGenericSendError(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(hContact, CAPF_SRV_RELAY) || wRecipientStatus == ID_STATUS_OFFLINE)
+ {
+ dwCookie = icq_SendChannel4Message(dwUin, 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, 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)
+ {
+ SendProtoAck(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((void**)&pBody);
+ }
+ else
+ {
+ dwCookie = ReportGenericSendError(hContact, ACKTYPE_CONTACTS, "Bad data (internal error #2)");
+ }
+ }
+ }
+ else
+ {
+ dwCookie = ReportGenericSendError(hContact, ACKTYPE_CONTACTS, "The reciever does not support receiving of contacts.");
+ }
+ }
+ return dwCookie;
+ }
+
+ // Exit with Failure
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SendFile - sends a file
+
+HANDLE __cdecl CIcqProto::SendFile( HANDLE hContact, const TCHAR* szDescription, TCHAR** ppszFiles )
+{
+ if ( !icqOnline())
+ return 0;
+
+ if (hContact && szDescription && ppszFiles)
+ {
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (getContactUid(hContact, &dwUin, &szUid))
+ return 0; // Invalid contact
+
+ if (getContactStatus(hContact) != ID_STATUS_OFFLINE)
+ {
+ if (CheckContactCapabilities(hContact, CAPF_OSCAR_FILE))
+ return oftInitTransfer(hContact, dwUin, szUid, (LPCTSTR*)ppszFiles, szDescription);
+
+ if (dwUin)
+ {
+ WORD wClientVersion = getSettingWord(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; ppszFiles[ft->dwFileCount]; ft->dwFileCount++);
+ ft->pszFiles = (char **)SAFE_MALLOC(sizeof(char *) * ft->dwFileCount);
+ ft->dwTotalSize = 0;
+ for (i = 0; i < (int)ft->dwFileCount; i++)
+ {
+ ft->pszFiles[i] = (ppszFiles[i]) ? tchar_to_utf8(ppszFiles[i]) : NULL;
+
+ if (_tstat(ppszFiles[i], &statbuf))
+ NetLog_Server("IcqSendFile() was passed invalid filename(s)");
+ else
+ ft->dwTotalSize += statbuf.st_size;
+ }
+ ft->szDescription = tchar_to_utf8(szDescription);
+ 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], tmp[64];
+ char *pszFiles;
+
+
+ NetLog_Server("Init file send");
+
+ if (ft->dwFileCount == 1)
+ {
+ pszFiles = strchr(ft->pszFiles[0], '\\');
+ if (pszFiles)
+ pszFiles++;
+ else
+ pszFiles = ft->pszFiles[0];
+ }
+ else
+ {
+ null_snprintf(szFiles, SIZEOF(szFiles), ICQTranslateUtfStatic("%d Files", tmp, SIZEOF(tmp)), ft->dwFileCount);
+ pszFiles = szFiles;
+ }
+
+ // Send packet
+ {
+ if (ft->nVersion == 7)
+ {
+ if (m_bDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
+ {
+ int iRes = icq_sendFileSendDirectv7(ft, pszFiles);
+ if (iRes) return ft; // Success
+ }
+ NetLog_Server("Sending v%u file transfer request through server", 7);
+ icq_sendFileSendServv7(ft, pszFiles);
+ }
+ else
+ {
+ if (m_bDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
+ {
+ int iRes = icq_sendFileSendDirectv8(ft, pszFiles);
+ if (iRes) return ft; // Success
+ }
+ NetLog_Server("Sending v%u file transfer request through server", 8);
+ icq_sendFileSendServv8(ft, pszFiles, ACKTYPE_NONE);
+ }
+ }
+ }
+
+ return ft; // Success
+ }
+ }
+ }
+ }
+
+ return 0; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_SendMessage - sends a message
+
+int __cdecl CIcqProto::SendMsg( HANDLE hContact, int flags, const char* pszSrc )
+{
+ if (hContact && pszSrc)
+ {
+ DWORD dwCookie;
+ char* puszText = NULL;
+ int bNeedFreeU = 0;
+ cookie_message_data *pCookieData = NULL;
+
+ // Invalid contact
+ DWORD dwUin;
+ uid_str szUID;
+ if (getContactUid(hContact, &dwUin, &szUID))
+ return ReportGenericSendError(hContact, ACKTYPE_MESSAGE, "The receiver has an invalid user ID.");
+
+ if (flags & PREF_UNICODE)
+ {
+ puszText = make_utf8_string((WCHAR*)(pszSrc + strlennull(pszSrc) + 1)); // get the UTF-16 part
+ bNeedFreeU = 1;
+ }
+ else if (flags & PREF_UTF)
+ puszText = (char*)pszSrc;
+ else
+ {
+ puszText = (char*)ansi_to_utf8(pszSrc);
+ bNeedFreeU = 1;
+ }
+
+ WORD wRecipientStatus = getContactStatus(hContact);
+
+ BOOL plain_ascii = IsUSASCII(puszText, strlennull(puszText));
+
+ BOOL oldAnsi = plain_ascii || !m_bUtfEnabled ||
+ (!(flags & (PREF_UTF | PREF_UNICODE)) && m_bUtfEnabled == 1) ||
+ !CheckContactCapabilities(hContact, CAPF_UTF) ||
+ !getSettingByte(hContact, "UnicodeSend", 1);
+
+ if (m_bTempVisListEnabled && m_iStatus == ID_STATUS_INVISIBLE)
+ makeContactTemporaryVisible(hContact); // make us temporarily visible to contact
+
+ // Failure scenarios
+ if (!icqOnline())
+ {
+ dwCookie = ReportGenericSendError(hContact, ACKTYPE_MESSAGE, "You cannot send messages when you are offline.");
+ }
+ else if ((wRecipientStatus == ID_STATUS_OFFLINE) && (strlennull(puszText) > 4096))
+ {
+ dwCookie = ReportGenericSendError(hContact, ACKTYPE_MESSAGE, "Messages to offline contacts must be shorter than 4096 characters.");
+ }
+ // Looks OK
+ else
+ {
+#ifdef _DEBUG
+ NetLog_Server("Send %smessage - Message cap is %u", puszText ? "unicode " : "", CheckContactCapabilities(hContact, CAPF_SRV_RELAY));
+ NetLog_Server("Send %smessage - Contact status is %u", puszText ? "unicode " : "", wRecipientStatus);
+#endif
+ if (dwUin && m_bDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
+ { // send thru direct
+ char *dc_msg = puszText;
+ char *dc_cap = plain_ascii ? NULL : CAP_UTF8MSGS;
+ char *szUserAnsi = NULL;
+
+ if (!plain_ascii && oldAnsi)
+ {
+ szUserAnsi = ConvertMsgToUserSpecificAnsi(hContact, puszText);
+ if (szUserAnsi)
+ {
+ dc_msg = szUserAnsi;
+ dc_cap = NULL;
+ }
+ }
+
+ // Set up the ack type
+ pCookieData = CreateMessageCookieData(MTYPE_PLAIN, hContact, dwUin, TRUE);
+ pCookieData->nAckType = ACKTYPE_CLIENT;
+ dwCookie = icq_SendDirectMessage(hContact, dc_msg, strlennull(dc_msg), 1, pCookieData, dc_cap);
+
+ SAFE_FREE(&szUserAnsi);
+ if (dwCookie)
+ { // free the buffers if alloced
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+
+ return dwCookie; // we succeded, return
+ }
+ // on failure, fallback to send thru server
+ }
+
+ if (!dwUin || !CheckContactCapabilities(hContact, CAPF_SRV_RELAY) ||
+ wRecipientStatus == ID_STATUS_OFFLINE || wRecipientStatus == ID_STATUS_INVISIBLE ||
+ getSettingByte(hContact, "OnlyServerAcks", getSettingByte(NULL, "OnlyServerAcks", DEFAULT_ONLYSERVERACKS)) ||
+ !getSettingByte(hContact, "SlowSend", getSettingByte(NULL, "SlowSend", DEFAULT_SLOWSEND)))
+ {
+ /// TODO: add support for RTL & user customizable font
+ {
+ char *mng = MangleXml(puszText, strlennull(puszText));
+ int len = strlennull(mng);
+ mng = (char*)SAFE_REALLOC(mng, len + 28);
+ memmove(mng + 12, mng, len + 1);
+ memcpy(mng, "<HTML><BODY>", 12);
+ strcat(mng, "</BODY></HTML>");
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+ puszText = mng;
+ bNeedFreeU = 1;
+ }
+
+ WCHAR *pwszText = plain_ascii ? NULL : make_unicode_string(puszText);
+ if ((plain_ascii ? strlennull(puszText) : strlennull(pwszText) * sizeof(WCHAR)) > 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(hContact, ACKTYPE_MESSAGE, "The message could not be delivered, it is too long.");
+
+ // free the buffers if alloced
+ SAFE_FREE((void**)&pwszText);
+ 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(hContact, ACKTYPE_MESSAGE, "The message could not be delivered. You are sending too fast. Wait a while and try again.");
+
+ // free the buffers if alloced
+ SAFE_FREE((void**)&pwszText);
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+
+ return dwCookie;
+ }
+
+ pCookieData = CreateMessageCookieData(MTYPE_PLAIN, hContact, dwUin, FALSE);
+
+ if (plain_ascii)
+ dwCookie = icq_SendChannel1Message(dwUin, szUID, hContact, puszText, pCookieData);
+ else
+ dwCookie = icq_SendChannel1MessageW(dwUin, szUID, hContact, pwszText, pCookieData);
+ // free the unicode message
+ SAFE_FREE((void**)&pwszText);
+ }
+ else
+ {
+ WORD wPriority;
+
+ char *srv_msg = puszText;
+ char *srv_cap = plain_ascii ? NULL : CAP_UTF8MSGS;
+ char *szUserAnsi = NULL;
+
+ if (!plain_ascii && oldAnsi)
+ {
+ szUserAnsi = ConvertMsgToUserSpecificAnsi(hContact, puszText);
+ if (szUserAnsi)
+ {
+ srv_msg = szUserAnsi;
+ srv_cap = NULL;
+ }
+ }
+
+ if (wRecipientStatus == ID_STATUS_ONLINE || wRecipientStatus == ID_STATUS_FREECHAT)
+ wPriority = 0x0001;
+ else
+ wPriority = 0x0021;
+
+ if (strlennull(srv_msg) + (!oldAnsi ? 144 : 102) > MAX_MESSAGESNACSIZE)
+ { // max length check
+ dwCookie = ReportGenericSendError(hContact, ACKTYPE_MESSAGE, "The message could not be delivered, it is too long.");
+
+ SAFE_FREE(&szUserAnsi);
+ // free the buffers if alloced
+ 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(hContact, ACKTYPE_MESSAGE, "The message could not be delivered. You are sending too fast. Wait a while and try again.");
+
+ SAFE_FREE(&szUserAnsi);
+ // free the buffers if alloced
+ if (bNeedFreeU) SAFE_FREE(&puszText);
+
+ return dwCookie;
+ }
+
+ pCookieData = CreateMessageCookieData(MTYPE_PLAIN, hContact, dwUin, TRUE);
+ dwCookie = icq_SendChannel2Message(dwUin, hContact, srv_msg, strlennull(srv_msg), wPriority, pCookieData, srv_cap);
+ SAFE_FREE(&szUserAnsi);
+ }
+
+ // This will stop the message dialog from waiting for the real message delivery ack
+ if (pCookieData && pCookieData->nAckType == ACKTYPE_NONE)
+ {
+ SendProtoAck(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 (bNeedFreeU) SAFE_FREE(&puszText);
+
+ return dwCookie; // Success
+ }
+
+ return 0; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SendUrl
+
+int __cdecl CIcqProto::SendUrl( HANDLE hContact, int flags, const char* url )
+{
+ if (hContact && url)
+ {
+ DWORD dwCookie;
+ WORD wRecipientStatus;
+ DWORD dwUin;
+
+ if (getContactUid(hContact, &dwUin, NULL))
+ { // Invalid contact
+ return ReportGenericSendError(hContact, ACKTYPE_URL, "The receiver has an invalid user ID.");
+ }
+
+ wRecipientStatus = getContactStatus(hContact);
+
+ // Failure
+ if (!icqOnline())
+ {
+ dwCookie = ReportGenericSendError(hContact, ACKTYPE_URL, "You cannot send messages when you are offline.");
+ }
+ // Looks OK
+ else
+ {
+ char* szDesc;
+ char* szBody;
+ int nBodyLen;
+ int nDescLen;
+ int nUrlLen;
+
+
+ // Set up the ack type
+ cookie_message_data *pCookieData = CreateMessageCookieData(MTYPE_URL, hContact, dwUin, TRUE);
+
+ // Format the body
+ nUrlLen = strlennull(url);
+ szDesc = (char *)url + 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, url);
+
+ if (m_bDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
+ {
+ int iRes = icq_SendDirectMessage(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((void**)&pCookieData);
+
+ return ReportGenericSendError(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(hContact, CAPF_SRV_RELAY) ||
+ wRecipientStatus == ID_STATUS_OFFLINE)
+ {
+ dwCookie = icq_SendChannel4Message(dwUin, 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, 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)
+ {
+ SendProtoAck(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
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_SetApparentMode - sets the visibility status
+
+int __cdecl CIcqProto::SetApparentMode( HANDLE hContact, int mode )
+{
+ DWORD uin;
+ uid_str uid;
+
+ if (getContactUid(hContact, &uin, &uid))
+ return 1; // Invalid contact
+
+ if (hContact)
+ {
+ // Only 3 modes are supported
+ if (mode == 0 || mode == ID_STATUS_ONLINE || mode == ID_STATUS_OFFLINE)
+ {
+ int oldMode = getSettingWord(hContact, "ApparentMode", 0);
+
+ // Don't send redundant updates
+ if (mode != oldMode)
+ {
+ setSettingWord(hContact, "ApparentMode", (WORD)mode);
+
+ // 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 && getSettingWord(hContact, DBSETTING_SERVLIST_IGNORE, 0))
+ { // Need to remove Ignore item as well
+ icq_removeServerPrivacyItem(hContact, uin, uid, getSettingWord(hContact, DBSETTING_SERVLIST_IGNORE, 0), SSI_ITEM_IGNORE);
+
+ setSettingWord(hContact, DBSETTING_SERVLIST_IGNORE, 0);
+ }
+ icq_sendChangeVisInvis(hContact, uin, uid, oldMode==ID_STATUS_OFFLINE, 0);
+ }
+ if (mode != 0)
+ { // Add to new list
+ if (mode==ID_STATUS_OFFLINE && getSettingWord(hContact, DBSETTING_SERVLIST_IGNORE, 0))
+ return 0; // Success: offline by ignore item
+
+ icq_sendChangeVisInvis(hContact, uin, uid, mode==ID_STATUS_OFFLINE, 1);
+ }
+ }
+
+ return 0; // Success
+ }
+ }
+ }
+
+ return 1; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PrepareStatusNote - returns correct status note for given status
+
+char* CIcqProto::PrepareStatusNote(int nStatus)
+{
+ char *szStatusNote = NULL;
+ BYTE bXStatus = getContactXStatus(NULL);
+
+ // use custom status message as status note
+ if (bXStatus)
+ szStatusNote = getSettingStringUtf(NULL, DBSETTING_XSTATUS_MSG, "");
+
+ if (!szStatusNote || !szStatusNote[0])
+ { // get standard status message (no custom status defined)
+ icq_lock l(m_modeMsgsMutex);
+
+ char **pszStatusNote = MirandaStatusToAwayMsg(nStatus);
+ if (pszStatusNote)
+ szStatusNote = null_strdup(*pszStatusNote);
+ }
+
+ if (!szStatusNote)
+ // nothing available set empty status note
+ szStatusNote = null_strdup("");
+
+ return szStatusNote;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_SetStatus - sets the protocol status
+
+int __cdecl CIcqProto::SetStatus(int iNewStatus)
+{
+ int nNewStatus = MirandaStatusToSupported(iNewStatus);
+
+ // check if netlib handles are ready
+ if (!m_hServerNetlibUser)
+ return 0;
+
+ if (m_bTempVisListEnabled && icqOnline()) // remove temporary visible users
+ sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_REMOVETEMPVISIBLE, BUL_TEMPVISIBLE);
+
+ if (nNewStatus != m_iStatus)
+ {
+ // clear custom status on status change
+ if (getSettingByte(NULL, "XStatusReset", DEFAULT_XSTATUS_RESET))
+ setXStatusEx(0, 0);
+
+ // New status is OFFLINE
+ if (nNewStatus == ID_STATUS_OFFLINE)
+ { // for quick logoff
+ if (icqOnline())
+ { // set offline status note (otherwise the old will remain)
+ char *szOfflineNote = PrepareStatusNote(nNewStatus);
+
+ // Create unnamed event to wait until the status note change process is completed
+ m_hNotifyNameInfoEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ int bNoteChanged = SetStatusNote(szOfflineNote, 0, FALSE);
+
+ SAFE_FREE(&szOfflineNote);
+
+ // Note was changed, wait until the process is over
+ if (bNoteChanged)
+ ICQWaitForSingleObject(m_hNotifyNameInfoEvent, 4000, TRUE);
+
+ // Release the event
+ CloseHandle(m_hNotifyNameInfoEvent);
+ m_hNotifyNameInfoEvent = NULL;
+ }
+
+ m_iDesiredStatus = nNewStatus;
+
+ if (hServerConn)
+ { // Connected, Send disconnect packet
+ icq_sendCloseConnection();
+
+ icq_serverDisconnect(FALSE);
+
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+
+ NetLog_Server("Logged off.");
+ }
+ }
+ else
+ {
+ switch (m_iStatus) {
+
+ // We are offline and need to connect
+ case ID_STATUS_OFFLINE:
+ {
+ // Update user connection settings
+ UpdateGlobalSettings();
+
+ // Read UIN from database
+ m_dwLocalUIN = getContactUin(NULL);
+ if (m_dwLocalUIN == 0)
+ {
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_BADUSERID);
+ icq_LogMessage(LOG_FATAL, LPGEN("You have not entered a ICQ number.\nConfigure this in Options->Network->ICQ and try again."));
+ return 0;
+ }
+
+ // Set status to 'Connecting'
+ m_iDesiredStatus = nNewStatus;
+ SetCurrentStatus(ID_STATUS_CONNECTING);
+
+ // Read password from database
+ char *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:
+ m_iDesiredStatus = nNewStatus;
+ break;
+
+ // We are already connected so we should just change status
+ default:
+ SetCurrentStatus(nNewStatus);
+
+ char *szStatusNote = PrepareStatusNote(nNewStatus);
+
+ //! This is a bit tricky, we do trigger status note change thread and then
+ // change the status note right away (this spares one packet) - so SetStatusNote()
+ // will only change User Details Directory
+ SetStatusNote(szStatusNote, 6000, FALSE);
+
+ if (m_iStatus == ID_STATUS_INVISIBLE)
+ {
+ if (m_bSsiEnabled)
+ updateServVisibilityCode(3);
+ icq_setstatus(MirandaStatusToIcq(m_iStatus), szStatusNote);
+ }
+ else
+ {
+ icq_setstatus(MirandaStatusToIcq(m_iStatus), szStatusNote);
+ if (m_bSsiEnabled)
+ updateServVisibilityCode(4);
+ }
+ SAFE_FREE(&szStatusNote);
+
+ if (m_bAimEnabled)
+ {
+ icq_lock l(m_modeMsgsMutex);
+
+ char ** pszStatusNote = MirandaStatusToAwayMsg(m_iStatus);
+
+ if (pszStatusNote)
+ icq_sendSetAimAwayMsgServ(*pszStatusNote);
+ else // clear the away message
+ icq_sendSetAimAwayMsgServ(NULL);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// RecvAuth - returns a contact's away message
+
+INT_PTR __cdecl CIcqProto::RecvAuth(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;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// GetAwayMsgThread - return a contact's status message
+
+struct status_message_thread_data
+{
+ HANDLE hContact;
+ char *szMessage;
+ HANDLE hProcess;
+};
+
+void __cdecl CIcqProto::GetAwayMsgThread( void *pStatusData )
+{
+ status_message_thread_data *pThreadData = (status_message_thread_data*)pStatusData;
+
+ if (pThreadData)
+ {
+ char *szAnsiMsg = NULL;
+
+ // wait a little
+ Sleep(100);
+
+ setStatusMsgVar(pThreadData->hContact, pThreadData->szMessage, false);
+
+ if (utf8_decode(pThreadData->szMessage, &szAnsiMsg))
+ BroadcastAck(pThreadData->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, pThreadData->hProcess, (LPARAM)szAnsiMsg);
+
+ SAFE_FREE(&szAnsiMsg);
+ SAFE_FREE(&pThreadData->szMessage);
+ SAFE_FREE((void**)&pThreadData);
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_GetAwayMsg - returns a contact's away message
+
+HANDLE __cdecl CIcqProto::GetAwayMsg( HANDLE hContact )
+{
+ DWORD dwUin;
+ uid_str szUID;
+
+ if (getContactUid(hContact, &dwUin, &szUID))
+ return 0; // Invalid contact
+
+ if (!dwUin || !CheckContactCapabilities(hContact, CAPF_STATUS_MESSAGES))
+ { // No individual status messages, check if the contact has Status Note, if yes give it
+ char *szStatusNote = getSettingStringUtf(hContact, DBSETTING_STATUS_NOTE, NULL);
+
+ if (strlennull(szStatusNote) > 0)
+ { // Give Status Note
+ status_message_thread_data *pThreadData = (status_message_thread_data*)SAFE_MALLOC(sizeof(status_message_thread_data));
+
+ pThreadData->hContact = hContact;
+ pThreadData->szMessage = szStatusNote;
+ pThreadData->hProcess = (HANDLE)GenerateCookie(0);
+ ForkThread(&CIcqProto::GetAwayMsgThread, pThreadData);
+
+ return pThreadData->hProcess;
+ }
+ SAFE_FREE(&szStatusNote);
+ }
+
+ if (!icqOnline())
+ return 0;
+
+ WORD wStatus = getContactStatus(hContact);
+
+ if (dwUin)
+ {
+ int wMessageType = 0;
+
+ switch(wStatus)
+ {
+ case ID_STATUS_ONLINE:
+ if (CheckContactCapabilities(hContact, CAPF_STATUS_MESSAGES))
+ 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 (m_bDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
+ {
+ int iRes = icq_sendGetAwayMsgDirect(hContact, wMessageType);
+ if (iRes) return (HANDLE)iRes; // we succeded, return
+ }
+ if (CheckContactCapabilities(hContact, CAPF_STATUS_MESSAGES))
+ return (HANDLE)icq_sendGetAwayMsgServExt(hContact, dwUin, szUID, wMessageType,
+ (WORD)(getSettingWord(hContact, "Version", 0)==9?9:ICQ_VERSION)); // Success
+ else
+ return (HANDLE)icq_sendGetAwayMsgServ(hContact, dwUin, wMessageType,
+ (WORD)(getSettingWord(hContact, "Version", 0)==9?9:ICQ_VERSION)); // Success
+ }
+ }
+ else
+ { // AIM contact
+ if (wStatus == ID_STATUS_AWAY)
+ return (HANDLE)icq_sendGetAimAwayMsgServ(hContact, szUID, MTYPE_AUTOAWAY);
+ }
+
+ return 0; // Failure
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PSR_AWAYMSG - processes received status mode message
+
+int __cdecl CIcqProto::RecvAwayMsg( HANDLE hContact, int statusMode, PROTORECVEVENT* evt )
+{
+ if (evt->flags & PREF_UTF)
+ {
+ setStatusMsgVar(hContact, evt->szMessage, false);
+
+ char* pszMsg = NULL;
+ utf8_decode(evt->szMessage, &pszMsg);
+ BroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)evt->lParam, (LPARAM)pszMsg);
+ SAFE_FREE(&pszMsg);
+ }
+ else
+ {
+ setStatusMsgVar(hContact, evt->szMessage, true);
+ BroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)evt->lParam, (LPARAM)evt->szMessage);
+ }
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PSS_AWAYMSG - send status mode message (individual mode)
+
+int __cdecl CIcqProto::SendAwayMsg( HANDLE hContact, HANDLE hProcess, const char* msg )
+{
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// PS_SetAwayMsg - sets the away status message
+
+int __cdecl CIcqProto::SetAwayMsg(int status, const TCHAR* msg)
+{
+ icq_lock l(m_modeMsgsMutex);
+
+ char **ppszMsg = MirandaStatusToAwayMsg(MirandaStatusToSupported(status));
+ if (!ppszMsg)
+ return 1; // Failure
+
+ // Prepare UTF-8 status message
+ char *szNewUtf = tchar_to_utf8(msg);
+
+ if (strcmpnull(szNewUtf, *ppszMsg))
+ {
+ // Free old message
+ SAFE_FREE(ppszMsg);
+
+ // Set new message
+ *ppszMsg = szNewUtf;
+ szNewUtf = NULL;
+
+ if ((m_iStatus == status) && icqOnline())
+ { // update current status note
+ char *szNote = *ppszMsg ? *ppszMsg : "";
+
+ BYTE bXStatus = getContactXStatus(NULL);
+ if (!bXStatus)
+ SetStatusNote(szNote, 1000, FALSE);
+
+ if (m_bAimEnabled)
+ icq_sendSetAimAwayMsgServ(*ppszMsg);
+ }
+ }
+ SAFE_FREE(&szNewUtf);
+
+ return 0; // Success
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// GetMyAwayMsg - obtain the current away message
+
+INT_PTR CIcqProto::GetMyAwayMsg(WPARAM wParam, LPARAM lParam)
+{
+ icq_lock l(m_modeMsgsMutex);
+
+ char **ppszMsg = MirandaStatusToAwayMsg(wParam ? wParam : m_iStatus);
+
+ if (!ppszMsg || !*ppszMsg)
+ return 0;
+
+ int nMsgLen = strlennull(*ppszMsg) + 1;
+
+ if (lParam & SGMA_UNICODE)
+ {
+ WCHAR *szMsg = (WCHAR*)_alloca(nMsgLen * sizeof(WCHAR));
+
+ make_unicode_string_static(*ppszMsg, szMsg, nMsgLen);
+ return (INT_PTR)mir_wstrdup(szMsg);
+ }
+ else
+ { // convert to ansi
+ char *szMsg = (char*)_alloca(nMsgLen);
+
+ if (utf8_decode_static(*ppszMsg, szMsg, nMsgLen))
+ return (INT_PTR)mir_strdup(szMsg);
+ }
+
+ return 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// PS_UserIsTyping - sends a UTN notification
+
+int __cdecl CIcqProto::UserIsTyping( HANDLE hContact, int type )
+{
+ if (hContact && icqOnline())
+ {
+ if (CheckContactCapabilities(hContact, CAPF_TYPING))
+ {
+ switch (type) {
+ case PROTOTYPE_SELFTYPING_ON:
+ sendTypingNotification(hContact, MTN_BEGUN);
+ return 0;
+
+ case PROTOTYPE_SELFTYPING_OFF:
+ sendTypingNotification(hContact, MTN_FINISHED);
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// OnEvent - maintain protocol events
+
+int __cdecl CIcqProto::OnEvent(PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam)
+{
+ switch( eventType ) {
+ case EV_PROTO_ONLOAD:
+ return OnModulesLoaded(0, 0);
+
+ case EV_PROTO_ONEXIT:
+ return OnPreShutdown(0, 0);
+
+ case EV_PROTO_ONOPTIONS:
+ return OnOptionsInit(wParam, lParam);
+
+ case EV_PROTO_ONERASE:
+ {
+ char szDbSetting[MAX_PATH];
+
+ null_snprintf(szDbSetting, sizeof(szDbSetting), "%sP2P", m_szModuleName);
+ CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)szDbSetting);
+ null_snprintf(szDbSetting, sizeof(szDbSetting), "%sSrvGroups", m_szModuleName);
+ CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)szDbSetting);
+ null_snprintf(szDbSetting, sizeof(szDbSetting), "%sGroups", m_szModuleName);
+ CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)szDbSetting);
+ break;
+ }
+
+ case EV_PROTO_ONCONTACTDELETED:
+ return ServListDbContactDeleted(wParam, lParam);
+
+ case EV_PROTO_DBSETTINGSCHANGED:
+ return ServListDbSettingChanged(wParam, lParam);
+ }
+ return 1;
+}
diff --git a/protocols/IcqOscarJ/icq_proto.h b/protocols/IcqOscarJ/icq_proto.h
new file mode 100644
index 0000000000..cbb149eacc
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_proto.h
@@ -0,0 +1,996 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 Joe Kucera, George Hazan
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_proto.h $
+// Revision : $Revision: 14141 $
+// Last change on : $Date: 2012-03-09 22:52:15 +0200 (Пт, 09 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Protocol Interface declarations
+//
+// -----------------------------------------------------------------------------
+
+#ifndef _ICQ_PROTO_H_
+#define _ICQ_PROTO_H_
+
+#include "m_system_cpp.h"
+#include "m_protoint.h"
+
+#define LISTSIZE 100
+
+#define XSTATUS_COUNT 86
+
+struct CIcqProto;
+typedef void ( __cdecl CIcqProto::*IcqThreadFunc )( void* );
+typedef int ( __cdecl CIcqProto::*IcqEventFunc )( WPARAM, LPARAM );
+typedef INT_PTR ( __cdecl CIcqProto::*IcqServiceFunc )( WPARAM, LPARAM );
+typedef INT_PTR ( __cdecl CIcqProto::*IcqServiceFuncParam )( WPARAM, LPARAM, LPARAM );
+
+// for InfoUpdate
+struct userinfo
+{
+ DWORD dwUin;
+ HANDLE hContact;
+ time_t queued;
+};
+
+struct CIcqProto : public PROTO_INTERFACE
+{
+ CIcqProto( const char*, const TCHAR* );
+ ~CIcqProto();
+
+ __inline void* operator new( size_t size )
+ { return SAFE_MALLOC( size );
+ }
+ __inline void operator delete( void* p )
+ { SAFE_FREE( &p );
+ }
+
+ //====================================================================================
+ // PROTO_INTERFACE
+ //====================================================================================
+
+ virtual HANDLE __cdecl AddToList( int flags, PROTOSEARCHRESULT* psr );
+ virtual HANDLE __cdecl AddToListByEvent( int flags, int iContact, HANDLE hDbEvent );
+
+ virtual int __cdecl Authorize( HANDLE hContact );
+ virtual int __cdecl AuthDeny( HANDLE hContact, const TCHAR* szReason );
+ virtual int __cdecl AuthRecv( HANDLE hContact, PROTORECVEVENT* );
+ virtual int __cdecl AuthRequest( HANDLE hContact, const TCHAR* szMessage );
+
+ virtual HANDLE __cdecl ChangeInfo( int iInfoType, void* pInfoData );
+
+ virtual HANDLE __cdecl FileAllow( HANDLE hContact, HANDLE hTransfer, const TCHAR* szPath );
+ virtual int __cdecl FileCancel( HANDLE hContact, HANDLE hTransfer );
+ virtual int __cdecl FileDeny( HANDLE hContact, HANDLE hTransfer, const TCHAR* szReason );
+ virtual int __cdecl FileResume( HANDLE hTransfer, int* action, const TCHAR** szFilename );
+
+ virtual DWORD_PTR __cdecl GetCaps( int type, HANDLE hContact = NULL );
+ virtual HICON __cdecl GetIcon( int iconIndex );
+ virtual int __cdecl GetInfo( HANDLE hContact, int infoType );
+
+ virtual HANDLE __cdecl SearchBasic( const PROTOCHAR *id );
+ virtual HANDLE __cdecl SearchByEmail( const PROTOCHAR *email );
+ virtual HANDLE __cdecl SearchByName(const PROTOCHAR *nick, const PROTOCHAR *firstName, const PROTOCHAR *lastName);
+ virtual HWND __cdecl SearchAdvanced( HWND owner );
+ virtual HWND __cdecl CreateExtendedSearchUI( HWND owner );
+
+ virtual int __cdecl RecvContacts( HANDLE hContact, PROTORECVEVENT* );
+ virtual int __cdecl RecvFile( HANDLE hContact, PROTORECVFILET* );
+ virtual int __cdecl RecvMsg( HANDLE hContact, PROTORECVEVENT* );
+ virtual int __cdecl RecvUrl( HANDLE hContact, PROTORECVEVENT* );
+
+ virtual int __cdecl SendContacts( HANDLE hContact, int flags, int nContacts, HANDLE* hContactsList );
+ virtual HANDLE __cdecl SendFile( HANDLE hContact, const TCHAR* szDescription, TCHAR** ppszFiles );
+ virtual int __cdecl SendMsg( HANDLE hContact, int flags, const char* msg );
+ virtual int __cdecl SendUrl( HANDLE hContact, int flags, const char* url );
+
+ virtual int __cdecl SetApparentMode( HANDLE hContact, int mode );
+ virtual int __cdecl SetStatus( int iNewStatus );
+
+ virtual HANDLE __cdecl GetAwayMsg( HANDLE hContact );
+ virtual int __cdecl RecvAwayMsg( HANDLE hContact, int mode, PROTORECVEVENT* evt );
+ virtual int __cdecl SendAwayMsg( HANDLE hContact, HANDLE hProcess, const char* msg );
+ virtual int __cdecl SetAwayMsg( int m_iStatus, const TCHAR* msg );
+
+ virtual int __cdecl UserIsTyping( HANDLE hContact, int type );
+
+ virtual int __cdecl OnEvent( PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam );
+
+ //====| Services |====================================================================
+ INT_PTR __cdecl AddServerContact(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GetInfoSetting(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl ChangeInfoEx(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GetAvatarCaps(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GetAvatarInfo(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GetMyAvatar(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GetMyAwayMsg(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GetXStatus(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GetXStatusEx(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GetXStatusIcon(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GrantAuthorization(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl menuXStatus(WPARAM wParam,LPARAM lParam,LPARAM fParam);
+ INT_PTR __cdecl RecvAuth(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl RequestAdvStatusIconIdx(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl RequestAuthorization(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl RequestXStatusDetails(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl RevokeAuthorization(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl SendSms(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl SendYouWereAdded(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl SetMyAvatar(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl SetNickName(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl SetPassword(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl SetXStatus(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl SetXStatusEx(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl ShowXStatusDetails(WPARAM wParam, LPARAM lParam);
+
+ INT_PTR __cdecl OnCreateAccMgrUI(WPARAM, LPARAM);
+
+ //====| Events |======================================================================
+ void __cdecl OnAddContactForever( DBCONTACTWRITESETTING* cws, HANDLE hContact );
+ int __cdecl OnIdleChanged( WPARAM, LPARAM );
+ int __cdecl OnModernOptInit( WPARAM, LPARAM );
+ int __cdecl OnModulesLoaded( WPARAM, LPARAM );
+ int __cdecl OnOptionsInit( WPARAM, LPARAM );
+ int __cdecl OnPreShutdown( WPARAM, LPARAM );
+ int __cdecl OnPreBuildContactMenu( WPARAM, LPARAM );
+ int __cdecl OnMsgUserTyping( WPARAM, LPARAM );
+ int __cdecl OnProcessSrmmIconClick( WPARAM, LPARAM );
+ int __cdecl OnProcessSrmmEvent( WPARAM, LPARAM );
+ int __cdecl OnReloadIcons( WPARAM, LPARAM );
+ void __cdecl OnRenameContact( DBCONTACTWRITESETTING* cws, HANDLE hContact );
+ void __cdecl OnRenameGroup( DBCONTACTWRITESETTING* cws, HANDLE hContact );
+ int __cdecl OnUserInfoInit( WPARAM, LPARAM );
+
+ int __cdecl CListMW_ExtraIconsRebuild( WPARAM, LPARAM );
+ int __cdecl CListMW_ExtraIconsApply( WPARAM, LPARAM );
+ int __cdecl OnPreBuildStatusMenu( WPARAM, LPARAM );
+
+ //====| Data |========================================================================
+ IcqIconHandle m_hIconProtocol;
+ HANDLE m_hServerNetlibUser, m_hDirectNetlibUser;
+ HANDLE hxstatuschanged, hxstatusiconchanged;
+
+ BYTE m_bGatewayMode;
+ BYTE m_bSecureLogin;
+ BYTE m_bSecureConnection;
+ BYTE m_bAimEnabled;
+ BYTE m_bUtfEnabled;
+ WORD m_wAnsiCodepage;
+ BYTE m_bDCMsgEnabled;
+ BYTE m_bTempVisListEnabled;
+ BYTE m_bSsiEnabled;
+ BYTE m_bSsiSimpleGroups;
+ BYTE m_bAvatarsEnabled;
+ BYTE m_bXStatusEnabled;
+ BYTE m_bMoodsEnabled;
+
+ icq_critical_section *localSeqMutex;
+ icq_critical_section *connectionHandleMutex;
+
+ int m_bIdleAllow;
+ DWORD m_dwLocalUIN;
+ BYTE m_bConnectionLost;
+
+ char m_szPassword[PASSWORDMAXLEN];
+ BYTE m_bRememberPwd;
+
+ int cheekySearchId;
+ DWORD cheekySearchUin;
+ char* cheekySearchUid;
+
+ /*******************************************************************
+ * Function declarations
+ *******************************************************************/
+
+ //----| capabilities.cpp |------------------------------------------------------------
+ // 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 contact.
+ void AddCapabilitiesFromBuffer(HANDLE hContact, BYTE *pBuffer, int nLength);
+
+ // Scans a binary buffer for oscar capabilities and sets them to the contact.
+ void SetCapabilitiesFromBuffer(HANDLE hContact, BYTE *pBuffer, int nLength, BOOL bReset);
+
+ //----| chan_01login.cpp |------------------------------------------------------------
+ void handleLoginChannel(BYTE *buf, WORD datalen, serverthread_info *info);
+
+ //----| chan_02data.cpp |-------------------------------------------------------------
+ void handleDataChannel(BYTE *buf, WORD wLen, serverthread_info *info);
+
+ void LogFamilyError(WORD wFamily, WORD wError);
+
+ //----| chan_03error.cpp |------------------------------------------------------------
+ void handleErrorChannel(unsigned char *buf, WORD datalen);
+
+ //----| chan_04close.cpp |------------------------------------------------------------
+ void handleCloseChannel(BYTE *buf, WORD datalen, serverthread_info *info);
+ void handleLoginReply(BYTE *buf, WORD datalen, serverthread_info *info);
+ void handleMigration(serverthread_info *info);
+ void handleSignonError(WORD wError);
+
+ int connectNewServer(serverthread_info *info);
+
+ //----| chan_05ping.cpp |-------------------------------------------------------------
+ void handlePingChannel(BYTE *buf, WORD wLen);
+
+ void __cdecl KeepAliveThread(void *arg);
+
+ void StartKeepAlive(serverthread_info *info);
+ void StopKeepAlive(serverthread_info *info);
+
+ //----| cookies.cpp |-----------------------------------------------------------------
+ icq_critical_section *cookieMutex; // we want this in avatar thread, used as queue lock
+ LIST<icq_cookie_info> cookies;
+ WORD wCookieSeq;
+
+ DWORD AllocateCookie(BYTE bType, WORD wIdent, HANDLE hContact, void *pvExtra);
+ void FreeCookie(DWORD dwCookie);
+ void FreeCookieByData(BYTE bType, void *pvExtra);
+ 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 FindCookieByType(BYTE bType, DWORD *pdwCookie, HANDLE *phContact, void **ppvExtra);
+ int FindMessageCookie(DWORD dwMsgID1, DWORD dwMsgID2, DWORD *pdwCookie, HANDLE *phContact, cookie_message_data **ppvExtra);
+
+ void InitMessageCookie(cookie_message_data *pCookie);
+ cookie_message_data* CreateMessageCookie(WORD bMsgType, BYTE bAckType);
+ cookie_message_data* CreateMessageCookieData(BYTE bMsgType, HANDLE hContact, DWORD dwUin, int bUseSrvRelay);
+
+ void RemoveExpiredCookies(void);
+
+ //----| directpackets.cpp |-----------------------------------------------------------
+ void icq_sendDirectMsgAck(directconnect* dc, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags, char* szCap);
+ DWORD icq_sendGetAwayMsgDirect(HANDLE hContact, int type);
+ void icq_sendAwayMsgReplyDirect(directconnect *dc, WORD wCookie, BYTE msgType, const char** szMsg);
+ void icq_sendFileAcceptDirect(HANDLE hContact, filetransfer *ft);
+ void icq_sendFileDenyDirect(HANDLE hContact, filetransfer *ft, const char *szReason);
+ int icq_sendFileSendDirectv7(filetransfer *ft, const char *pszFiles);
+ int icq_sendFileSendDirectv8(filetransfer *ft, const char *pszFiles);
+ DWORD icq_SendDirectMessage(HANDLE hContact, const char *szMessage, int nBodyLength, WORD wPriority, cookie_message_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);
+
+ //----| fam_01service.cpp |-----------------------------------------------------------
+ HANDLE m_hNotifyNameInfoEvent;
+
+ void handleServiceFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader, serverthread_info *info);
+ char* buildUinList(int subtype, WORD wMaxLen, HANDLE *hContactResume);
+ void sendEntireListServ(WORD wFamily, WORD wSubtype, int listType);
+ void setUserInfo(void);
+ void handleServUINSettings(int nPort, serverthread_info *info);
+
+ //----| fam_02location.cpp |----------------------------------------------------------
+ void handleLocationFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader);
+ void handleLocationUserInfoReply(BYTE* buf, WORD wLen, DWORD dwCookie);
+
+ //----| fam_03buddy.cpp |-------------------------------------------------------------
+ void handleBuddyFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader, serverthread_info *info);
+ void handleReplyBuddy(BYTE *buf, WORD wPackLen);
+ void handleUserOffline(BYTE *buf, WORD wPackLen);
+ void handleUserOnline(BYTE *buf, WORD wPackLen, serverthread_info *info);
+ void parseStatusNote(DWORD dwUin, char *szUid, HANDLE hContact, oscar_tlv_chain *pChain);
+ void handleNotifyRejected(BYTE *buf, WORD wPackLen);
+
+ //----| fam_04message.cpp |-----------------------------------------------------------
+ icq_mode_messages m_modeMsgs;
+ icq_critical_section *m_modeMsgsMutex;
+ HANDLE m_modeMsgsEvent;
+
+ void handleMsgFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader);
+
+ void handleReplyICBM(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+ void handleRecvServMsg(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+ void handleRecvServMsgType1(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef);
+ void handleRecvServMsgType2(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef);
+ void handleRecvServMsgType4(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef);
+ void handleRecvServMsgError(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+ void handleRecvMsgResponse(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+ void handleServerAck(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+ void handleStatusMsgReply(const char *szPrefix, HANDLE hContact, DWORD dwUin, WORD wVersion, int bMsgType, WORD wCookie, const char *szMsg, int nMsgFlags);
+ void handleTypingNotification(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+ void handleMissedMsg(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+ void handleOffineMessagesReply(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef);
+ void handleRecvServMsgContacts(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwID1, DWORD dwID2, WORD wCommand);
+ void handleRuntimeError(WORD wError);
+
+ void parseServRelayData(BYTE *pDataBuf, WORD wLen, HANDLE hContact, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, WORD wAckType);
+ void parseServRelayPluginData(BYTE *pDataBuf, WORD wLen, HANDLE hContact, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, WORD wAckType, BYTE bFlags, WORD wStatus, WORD wCookie, WORD wVersion);
+
+ HANDLE handleMessageAck(DWORD dwUin, char *szUID, WORD wCookie, WORD wVersion, int type, WORD wMsgLen, PBYTE buf, BYTE bFlags, int nMsgFlags);
+ void handleMessageTypes(DWORD dwUin, char *szUID, DWORD dwTimestamp, DWORD dwMsgID, DWORD dwMsgID2, WORD wCookie, WORD wVersion, int type, int flags, WORD wAckType, DWORD dwDataLen, WORD wMsgLen, char *pMsg, int nMsgFlags, message_ack_params *pAckParams);
+ void sendMessageTypesAck(HANDLE hContact, int bUnicode, message_ack_params *pArgs);
+ void sendTypingNotification(HANDLE hContact, WORD wMTNCode);
+
+ int unpackPluginTypeId(BYTE **pBuffer, WORD *pwLen, int *pTypeId, WORD *pFunctionId, BOOL bThruDC);
+
+ char* convertMsgToUserSpecificUtf(HANDLE hContact, const char *szMsg);
+
+ //----| fam_09bos.cpp |---------------------------------------------------------------
+ void handleBosFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+ void handlePrivacyRightsReply(unsigned char *pBuffer, WORD wBufferLength);
+ void makeContactTemporaryVisible(HANDLE hContact);
+
+ //----| fam_0alookup.cpp |------------------------------------------------------------
+ void handleLookupFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+
+ void handleLookupEmailReply(BYTE* buf, WORD wLen, DWORD dwCookie);
+ void ReleaseLookupCookie(DWORD dwCookie, cookie_search *pCookie);
+
+ //----| fam_0bstatus.cpp |------------------------------------------------------------
+ void handleStatusFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+
+ //----| fam_13servclist.cpp |---------------------------------------------------------
+ BOOL bIsSyncingCL;
+
+ WORD m_wServerListLimits[0x20];
+ WORD m_wServerListGroupMaxContacts;
+ WORD m_wServerListRecordNameMaxLength;
+
+ void handleServCListFam(BYTE *pBuffer, WORD wBufferLength, snac_header* pSnacHeader, serverthread_info *info);
+ void handleServerCListRightsReply(BYTE *buf, WORD wLen);
+ void handleServerCListAck(cookie_servlist_action* sc, WORD wError);
+ void handleServerCListReply(BYTE *buf, WORD wLen, WORD wFlags, serverthread_info *info);
+ void handleServerCListItemAdd(const char *szRecordName, WORD wGroupId, WORD wItemId, WORD wItemType, oscar_tlv_chain *pItemData);
+ void handleServerCListItemUpdate(const char *szRecordName, WORD wGroupId, WORD wItemId, WORD wItemType, oscar_tlv_chain *pItemData);
+ void handleServerCListItemDelete(const char *szRecordName, WORD wGroupId, WORD wItemId, WORD wItemType, oscar_tlv_chain *pItemData);
+ void handleRecvAuthRequest(BYTE *buf, WORD wLen);
+ void handleRecvAuthResponse(BYTE *buf, WORD wLen);
+ void handleRecvAdded(BYTE *buf, WORD wLen);
+
+ HANDLE HContactFromRecordName(const char *szRecordName, int *bAdded);
+
+ void processCListReply(const char *szRecordName, WORD wGroupId, WORD wItemId, WORD wItemType, oscar_tlv_chain *pItemData);
+
+ void icq_sendServerBeginOperation(int bImport);
+ void icq_sendServerEndOperation();
+ void sendRosterAck(void);
+
+ int getServerDataFromItemTLV(oscar_tlv_chain* pChain, unsigned char *buf);
+ DWORD updateServerGroupData(WORD wGroupId, void *groupData, int groupSize, DWORD dwOperationFlags);
+ void updateServAvatarHash(BYTE *pHash, int size);
+ void updateServVisibilityCode(BYTE bCode);
+
+ //----| fam_15icqserver.cpp |---------------------------------------------------------
+ void handleIcqExtensionsFam(BYTE *pBuffer, WORD wBufferLength, snac_header* pSnacHeader);
+
+ void handleExtensionError(BYTE *buf, WORD wPackLen);
+ void handleExtensionServerInfo(BYTE *buf, WORD wPackLen, WORD wFlags);
+ void handleExtensionMetaResponse(BYTE *databuf, WORD wPacketLen, WORD wCookie, WORD wFlags);
+
+ int parseUserInfoRecord(HANDLE hContact, oscar_tlv *pData, UserInfoRecordItem pRecordDef[], int nRecordDef, int nMaxRecords);
+
+ void handleDirectoryQueryResponse(BYTE *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype, WORD wFlags);
+ void handleDirectoryUpdateResponse(BYTE *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype);
+
+ void parseDirectoryUserDetailsData(HANDLE hContact, oscar_tlv_chain *cDetails, DWORD dwCookie, cookie_directory_data *pCookieData, WORD wReplySubType);
+ void parseDirectorySearchData(oscar_tlv_chain *cDetails, DWORD dwCookie, cookie_directory_data *pCookieData, WORD wReplySubType);
+
+ void parseSearchReplies(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype, BYTE bResultCode);
+ void parseUserInfoUpdateAck(unsigned char *databuf, WORD wPacketLen, WORD wCookie, WORD wReplySubtype, BYTE bResultCode);
+
+ void ReleaseSearchCookie(DWORD dwCookie, cookie_search *pCookie);
+
+ //----| fam_17signon.cpp |------------------------------------------------------------
+ void handleAuthorizationFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader, serverthread_info *info);
+ void handleAuthKeyResponse(BYTE *buf, WORD wPacketLen, serverthread_info *info);
+
+ void sendClientAuth(const char *szKey, WORD wKeyLen, BOOL bSecure);
+
+ //----| icq_avatars.cpp |-------------------------------------------------------------
+ icq_critical_section *m_avatarsMutex;
+ avatars_request *m_avatarsQueue;
+
+ BOOL m_avatarsConnectionPending;
+ avatars_server_connection *m_avatarsConnection;
+
+ int bAvatarsFolderInited;
+ HANDLE hAvatarsFolder;
+
+ void requestAvatarConnection();
+ void __cdecl AvatarThread(avatars_server_connection *pInfo);
+
+ void handleAvatarOwnerHash(WORD wItemID, BYTE bFlags, BYTE *pData, BYTE nDataLen);
+ void handleAvatarContactHash(DWORD dwUIN, char *szUID, HANDLE hContact, BYTE *pHash, int nHashLen, WORD wOldStatus);
+
+ void InitAvatars();
+ avatars_request *ReleaseAvatarRequestInQueue(avatars_request *request);
+
+ TCHAR* GetOwnAvatarFileName();
+ void GetFullAvatarFileName(int dwUin, const char *szUid, int dwFormat, TCHAR *pszDest, int cbLen);
+ void GetAvatarFileName(int dwUin, const char *szUid, TCHAR *pszDest, int cbLen);
+ int IsAvatarChanged(HANDLE hContact, const BYTE *pHash, int nHashLen);
+
+ int GetAvatarData(HANDLE hContact, DWORD dwUin, const char *szUid, const BYTE *hash, unsigned int hashlen, const TCHAR *file);
+ int SetAvatarData(HANDLE hContact, WORD wRef, const BYTE *data, unsigned int datalen);
+
+ void StartAvatarThread(HANDLE hConn, char* cookie, WORD cookieLen);
+ void StopAvatarThread();
+
+ //----| icq_clients.cpp |-------------------------------------------------------------
+ const char* detectUserClient(HANDLE hContact, int nIsICQ, WORD wUserClass, DWORD dwOnlineSince, const char *szCurrentClient, WORD wVersion, DWORD dwFT1, DWORD dwFT2, DWORD dwFT3, BYTE bDirectFlag, DWORD dwDirectCookie, DWORD dwWebPort, BYTE *caps, WORD wLen, BYTE *bClientId, char *szClientBuf);
+
+ //----| icq_db.cpp |------------------------------------------------------------------
+ HANDLE AddEvent(HANDLE hContact, WORD wType, DWORD dwTime, DWORD flags, DWORD cbBlob, PBYTE pBlob);
+ void CreateResidentSetting(const char* szSetting);
+ HANDLE FindFirstContact();
+ HANDLE FindNextContact(HANDLE hContact);
+ int IsICQContact(HANDLE hContact);
+
+ int getSetting(HANDLE hContact, const char *szSetting, DBVARIANT *dbv);
+ BYTE getSettingByte(HANDLE hContact, const char *szSetting, BYTE byDef);
+ WORD getSettingWord(HANDLE hContact, const char *szSetting, WORD wDef);
+ DWORD getSettingDword(HANDLE hContact, const char *szSetting, DWORD dwDef);
+ double getSettingDouble(HANDLE hContact, const char *szSetting, double dDef);
+ int getSettingString(HANDLE hContact, const char *szSetting, DBVARIANT *dbv);
+ int getSettingStringW(HANDLE hContact, const char *szSetting, DBVARIANT *dbv);
+ int getSettingStringStatic(HANDLE hContact, const char *szSetting, char *dest, int dest_len);
+ char* getSettingStringUtf(HANDLE hContact, const char *szModule, const char *szSetting, char *szDef);
+ char* getSettingStringUtf(HANDLE hContact, const char *szSetting, char *szDef);
+ int getContactUid(HANDLE hContact, DWORD *pdwUin, uid_str *ppszUid);
+ DWORD getContactUin(HANDLE hContact);
+ WORD getContactStatus(HANDLE hContact);
+ char* getContactCListGroup(HANDLE hContact);
+
+ int deleteSetting(HANDLE hContact, const char *szSetting);
+
+ int setSettingByte(HANDLE hContact, const char *szSetting, BYTE byValue);
+ int setSettingWord(HANDLE hContact, const char *szSetting, WORD wValue);
+ int setSettingDword(HANDLE hContact, const char *szSetting, DWORD dwValue);
+ int setSettingDouble(HANDLE hContact, const char *szSetting, double dValue);
+ int setSettingString(HANDLE hContact, const char *szSetting, const char *szValue);
+ int setSettingStringW(HANDLE hContact, const char *szSetting, const WCHAR *wszValue);
+ int setSettingStringUtf(HANDLE hContact, const char *szModule, const char *szSetting, const char *szValue);
+ int setSettingStringUtf(HANDLE hContact, const char *szSetting, const char *szValue);
+ int setSettingBlob(HANDLE hContact, const char *szSetting, const BYTE *pValue, const int cbValue);
+ int setContactHidden(HANDLE hContact, BYTE bHidden);
+ void setStatusMsgVar(HANDLE hContact, char* szStatusMsg, bool isAnsi);
+
+ //----| icq_direct.cpp |--------------------------------------------------------------
+ icq_critical_section *directConnListMutex;
+ LIST<directconnect> directConns;
+
+ icq_critical_section *expectedFileRecvMutex;
+ LIST<filetransfer> expectedFileRecvs;
+
+ void __cdecl icq_directThread(struct directthreadstartinfo* dtsi);
+
+ void handleDirectPacket(directconnect* dc, PBYTE buf, WORD wLen);
+ void sendPeerInit_v78(directconnect* dc);
+ void sendPeerInitAck(directconnect* dc);
+ void sendPeerMsgInit(directconnect* dc, DWORD dwSeq);
+ void sendPeerFileInit(directconnect* dc);
+ int sendDirectPacket(directconnect* dc, icq_packet* pkt);
+
+ void CloseContactDirectConns(HANDLE hContact);
+ directconnect* FindFileTransferDC(filetransfer* ft);
+ filetransfer* FindExpectedFileRecv(DWORD dwUin, DWORD dwTotalSize);
+ BOOL IsDirectConnectionOpen(HANDLE hContact, int type, int bPassive);
+ void OpenDirectConnection(HANDLE hContact, int type, void* pvExtra);
+ void CloseDirectConnection(directconnect *dc);
+ int SendDirectMessage(HANDLE hContact, icq_packet *pkt);
+
+ //----| icq_directmsg.cpp |-----------------------------------------------------------
+ void handleDirectMessage(directconnect* dc, PBYTE buf, WORD wLen);
+ void handleDirectGreetingMessage(directconnect* dc, PBYTE buf, WORD wLen, WORD wCommand, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wStatus, WORD wFlags, char* pszText);
+
+ //----| icq_filerequests.cpp |--------------------------------------------------------
+ filetransfer* CreateFileTransfer(HANDLE hContact, DWORD dwUin, int nVersion);
+
+ void handleFileAck(PBYTE buf, WORD wLen, DWORD dwUin, DWORD dwCookie, WORD wStatus, char* pszText);
+ void handleFileRequest(PBYTE buf, WORD wLen, DWORD dwUin, DWORD dwCookie, DWORD dwID1, DWORD dwID2, char* pszDescription, int nVersion, BOOL bDC);
+ void handleDirectCancel(directconnect *dc, PBYTE buf, WORD wLen, WORD wCommand, DWORD dwCookie, WORD wMessageType, WORD wStatus, WORD wFlags, char* pszText);
+
+ void icq_CancelFileTransfer(HANDLE hContact, filetransfer* ft);
+
+ //----| icq_filetransfer.cpp |--------------------------------------------------------
+ void icq_AcceptFileTransfer(HANDLE hContact, filetransfer *ft);
+ void icq_sendFileResume(filetransfer *ft, int action, const char *szFilename);
+ void icq_InitFileSend(filetransfer *ft);
+
+ void handleFileTransferPacket(directconnect *dc, PBYTE buf, WORD wLen);
+ void handleFileTransferIdle(directconnect *dc);
+
+ //----| icq_infoupdate.cpp |----------------------------------------------------------
+ icq_critical_section *infoUpdateMutex;
+ HANDLE hInfoQueueEvent;
+ int nInfoUserCount;
+ int bInfoPendingUsers;
+ BOOL bInfoUpdateEnabled;
+ BOOL bInfoUpdateRunning;
+ HANDLE hInfoThread;
+ DWORD dwInfoActiveRequest;
+ userinfo m_infoUpdateList[LISTSIZE];
+
+ void __cdecl InfoUpdateThread(void*);
+
+ void icq_InitInfoUpdate(void); // Queues all outdated users
+ BOOL icq_QueueUser(HANDLE hContact); // Queue one UIN to the list for updating
+ void icq_DequeueUser(DWORD dwUin); // Remove one UIN from the list
+ void icq_RescanInfoUpdate(); // Add all outdated contacts to the list
+ void icq_InfoUpdateCleanup(void); // Clean up on exit
+ void icq_EnableUserLookup(BOOL bEnable); // Enable/disable user info lookups
+
+ //----| log.cpp |-----------------------------------------------------------------
+ BOOL bErrorBoxVisible;
+
+ void __cdecl icq_LogMessageThread(void* arg);
+
+ 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);
+
+ //----| icq_packet.cpp |--------------------------------------------------------------
+ void ppackLETLVLNTSfromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType);
+ void ppackLETLVWordLNTSfromDB(PBYTE *buf, int *buflen, WORD w, const char *szSetting, WORD wType);
+ void ppackLETLVLNTSBytefromDB(PBYTE *buf, int *buflen, const char *szSetting, BYTE b, WORD wType);
+
+ void ppackTLVStringFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType);
+ void ppackTLVStringUtfFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType);
+ void ppackTLVDateFromDB(PBYTE *buf, int *buflen, const char *szSettingYear, const char *szSettingMonth, const char *szSettingDay, WORD wType);
+
+ int ppackTLVWordStringItemFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wTypeID, WORD wTypeData, WORD wID);
+ int ppackTLVWordStringUtfItemFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wTypeID, WORD wTypeData, WORD wID);
+
+ BOOL unpackUID(BYTE **ppBuf, WORD *pwLen, DWORD *pdwUIN, uid_str *ppszUID);
+
+ //----| icq_popups.cpp |--------------------------------------------------------------
+ int ShowPopUpMsg(HANDLE hContact, const char *szTitle, const char *szMsg, BYTE bType);
+
+ //----| icq_proto.cpp |--------------------------------------------------------------
+ void __cdecl CheekySearchThread( void* );
+
+ void __cdecl GetAwayMsgThread( void *pStatusData );
+
+ char* PrepareStatusNote(int nStatus);
+
+ //----| icq_rates.cpp |---------------------------------------------------------------
+ icq_critical_section *m_ratesMutex;
+ rates *m_rates;
+
+ rates_queue *m_ratesQueue_Request; // rate queue for xtraz requests
+ rates_queue *m_ratesQueue_Response; // rate queue for msg responses
+
+ int handleRateItem(rates_queue_item *item, int nQueueType = RQT_DEFAULT, int nMinDelay = 0, BOOL bAllowDelay = TRUE);
+
+ void __cdecl rateDelayThread(struct rate_delay_args *pArgs);
+
+ //----| icq_server.cpp |--------------------------------------------------------------
+ HANDLE hServerConn;
+ WORD wListenPort;
+ WORD wLocalSequence;
+ UINT serverThreadId;
+ HANDLE serverThreadHandle;
+
+ __inline bool icqOnline() const
+ { return (m_iStatus != ID_STATUS_OFFLINE && m_iStatus != ID_STATUS_CONNECTING);
+ }
+
+ void __cdecl SendPacketAsyncThread(icq_packet* pArgs);
+ void __cdecl ServerThread(serverthread_start_info *infoParam);
+
+ void icq_serverDisconnect(BOOL bBlock);
+ void icq_login(const char* szPassword);
+
+ int handleServerPackets(BYTE *buf, int len, serverthread_info *info);
+ void sendServPacket(icq_packet *pPacket);
+ void sendServPacketAsync(icq_packet *pPacket);
+
+ int IsServerOverRate(WORD wFamily, WORD wCommand, int nLevel);
+
+ //----| icq_servlist.cpp |------------------------------------------------------------
+ HANDLE hHookSettingChanged;
+ HANDLE hHookContactDeleted;
+ HANDLE hHookCListGroupChange;
+ icq_critical_section *servlistMutex;
+
+ DWORD* pdwServerIDList;
+ int nServerIDListCount;
+ int nServerIDListSize;
+
+ // server-list update board
+ icq_critical_section *servlistQueueMutex;
+ int servlistQueueCount;
+ int servlistQueueSize;
+ ssiqueueditems **servlistQueueList;
+ int servlistQueueState;
+ HANDLE servlistQueueThreadHandle;
+ int servlistEditCount;
+
+ void servlistBeginOperation(int operationCount, int bImport);
+ void servlistEndOperation(int operationCount);
+
+ void __cdecl servlistQueueThread(void* queueState);
+
+ void servlistQueueAddGroupItem(servlistgroupitem* pGroupItem, int dwTimeout);
+ int servlistHandlePrimitives(DWORD dwOperation);
+ void servlistProcessLogin();
+
+ void servlistPostPacket(icq_packet* packet, DWORD dwCookie, DWORD dwOperation, DWORD dwTimeout);
+ void servlistPostPacketDouble(icq_packet* packet1, DWORD dwCookie, DWORD dwOperation, DWORD dwTimeout, icq_packet* packet2, WORD wAction2);
+
+ // server-list pending queue
+ int servlistPendingCount;
+ int servlistPendingSize;
+ servlistpendingitem** servlistPendingList;
+
+ int servlistPendingFindItem(int nType, HANDLE hContact, const char *pszGroup);
+ void servlistPendingAddItem(servlistpendingitem* pItem);
+ servlistpendingitem* servlistPendingRemoveItem(int nType, HANDLE hContact, const char *pszGroup);
+
+ void servlistPendingAddContactOperation(HANDLE hContact, LPARAM param, PENDING_CONTACT_CALLBACK callback, DWORD flags);
+ void servlistPendingAddGroupOperation(const char *pszGroup, LPARAM param, PENDING_GROUP_CALLBACK callback, DWORD flags);
+ int servlistPendingAddContact(HANDLE hContact, WORD wContactID, WORD wGroupID, LPARAM param, PENDING_CONTACT_CALLBACK callback, int bDoInline, LPARAM operationParam = 0, PENDING_CONTACT_CALLBACK operationCallback = NULL);
+ int servlistPendingAddGroup(const char *pszGroup, WORD wGroupID, LPARAM param, PENDING_GROUP_CALLBACK callback, int bDoInline, LPARAM operationParam = 0, PENDING_GROUP_CALLBACK operationCallback = NULL);
+ void servlistPendingRemoveContact(HANDLE hContact, WORD wContactID, WORD wGroupID, int nResult);
+ void servlistPendingRemoveGroup(const char *pszGroup, WORD wGroupID, int nResult);
+ void servlistPendingFlushOperations();
+
+ // server-list support functions
+ int nJustAddedCount;
+ int nJustAddedSize;
+ HANDLE* pdwJustAddedList;
+
+ void AddJustAddedContact(HANDLE hContact);
+ BOOL IsContactJustAdded(HANDLE hContact);
+ void FlushJustAddedContacts();
+
+ WORD GenerateServerID(int bGroupType, int bFlags, int wCount = 0);
+ void ReserveServerID(WORD wID, int bGroupType, int bFlags);
+ void FreeServerID(WORD wID, int bGroupType);
+ BOOL CheckServerID(WORD wID, unsigned int wCount);
+ void FlushServerIDs();
+ void LoadServerIDs();
+ void StoreServerIDs();
+
+ void* collectGroups(int *count);
+ void* collectBuddyGroup(WORD wGroupID, int *count);
+ char* getServListGroupName(WORD wGroupID);
+ void setServListGroupName(WORD wGroupID, const char *szGroupName);
+ WORD getServListGroupLinkID(const char *szPath);
+ void setServListGroupLinkID(const char *szPath, WORD wGroupID);
+ int IsServerGroupsDefined();
+ char* getServListGroupCListPath(WORD wGroupId);
+ char* getServListUniqueGroupName(const char *szGroupName, int bAlloced);
+
+ int __cdecl servlistCreateGroup_gotParentGroup(const char *szGroup, WORD wGroupID, LPARAM param, int nResult);
+ int __cdecl servlistCreateGroup_Ready(const char *szGroup, WORD groupID, LPARAM param, int nResult);
+ void servlistCreateGroup(const char *szGroupPath, LPARAM param, PENDING_GROUP_CALLBACK callback);
+
+ int __cdecl servlistAddContact_gotGroup(const char *szGroup, WORD wGroupID, LPARAM lParam, int nResult);
+ int __cdecl servlistAddContact_Ready(HANDLE hContact, WORD wContactID, WORD wGroupID, LPARAM lParam, int nResult);
+ void servlistAddContact(HANDLE hContact, const char *pszGroup);
+
+ int __cdecl servlistRemoveContact_Ready(HANDLE hContact, WORD contactID, WORD groupID, LPARAM lParam, int nResult);
+ void servlistRemoveContact(HANDLE hContact);
+
+ int __cdecl servlistMoveContact_gotTargetGroup(const char *szGroup, WORD wNewGroupID, LPARAM lParam, int nResult);
+ int __cdecl servlistMoveContact_Ready(HANDLE hContact, WORD contactID, WORD groupID, LPARAM lParam, int nResult);
+ void servlistMoveContact(HANDLE hContact, const char *pszNewGroup);
+
+ int __cdecl servlistUpdateContact_Ready(HANDLE hContact, WORD contactID, WORD groupID, LPARAM lParam, int nResult);
+ void servlistUpdateContact(HANDLE hContact);
+
+ int __cdecl servlistRenameGroup_Ready(const char *szGroup, WORD wGroupID, LPARAM lParam, int nResult);
+ void servlistRenameGroup(char *szGroup, WORD wGroupId, char *szNewGroup);
+
+ int __cdecl servlistRemoveGroup_Ready(const char *szGroup, WORD groupID, LPARAM lParam, int nResult);
+ void servlistRemoveGroup(const char *szGroup, WORD wGroupId);
+
+ void removeGroupPathLinks(WORD wGroupID);
+ int getServListGroupLevel(WORD wGroupId);
+
+ void resetServContactAuthState(HANDLE hContact, DWORD dwUin);
+
+ void FlushSrvGroupsCache();
+ int getCListGroupHandle(const char *szGroup);
+ int getCListGroupExists(const char *szGroup);
+ int moveContactToCListGroup(HANDLE hContact, const char *szGroup); /// TODO: this should be DB function
+
+ DWORD icq_sendServerItem(DWORD dwCookie, WORD wAction, WORD wGroupId, WORD wItemId, const char *szName, BYTE *pTLVs, int nTlvLength, WORD wItemType, DWORD dwOperation, DWORD dwTimeout, void **doubleObject);
+ DWORD icq_sendServerContact(HANDLE hContact, DWORD dwCookie, WORD wAction, WORD wGroupId, WORD wContactId, DWORD dwOperation, DWORD dwTimeout, void **doubleObject);
+ DWORD icq_sendSimpleItem(DWORD dwCookie, WORD wAction, DWORD dwUin, char* szUID, WORD wGroupId, WORD wItemId, WORD wItemType, DWORD dwOperation, DWORD dwTimeout);
+ DWORD icq_sendServerGroup(DWORD dwCookie, WORD wAction, WORD wGroupId, const char *szName, void *pContent, int cbContent, DWORD dwOperationFlags);
+
+ DWORD icq_modifyServerPrivacyItem(HANDLE hContact, DWORD dwUin, char *szUid, WORD wAction, DWORD dwOperation, WORD wItemId, WORD wType);
+ 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);
+
+ time_t dwLastCListGroupsChange;
+
+ int __cdecl ServListDbSettingChanged(WPARAM wParam, LPARAM lParam);
+ int __cdecl ServListDbContactDeleted(WPARAM wParam, LPARAM lParam);
+ int __cdecl ServListCListGroupChange(WPARAM wParam, LPARAM lParam);
+
+ //----| stdpackets.cpp |----------------------------------------------------------
+ void icq_sendCloseConnection();
+
+ void icq_requestnewfamily(WORD wFamily, void (CIcqProto::*familyhandler)(HANDLE hConn, char* cookie, WORD cookieLen));
+
+ void icq_setidle(int bAllow);
+ void icq_setstatus(WORD wStatus, const char *szStatusNote = NULL);
+ DWORD icq_sendGetInfoServ(HANDLE, DWORD, int);
+ DWORD icq_sendGetAimProfileServ(HANDLE hContact, char *szUid);
+ DWORD icq_sendGetAwayMsgServ(HANDLE, DWORD, int, WORD);
+ DWORD icq_sendGetAwayMsgServExt(HANDLE hContact, DWORD dwUin, char *szUID, int type, WORD wVersion);
+ DWORD icq_sendGetAimAwayMsgServ(HANDLE hContact, char *szUID, int type);
+ void icq_sendSetAimAwayMsgServ(const char *szMsg);
+
+ void icq_sendFileSendServv7(filetransfer* ft, const char *szFiles);
+ void icq_sendFileSendServv8(filetransfer* ft, const char *szFiles, int nAckType);
+
+ void icq_sendFileAcceptServ(DWORD dwUin, filetransfer *ft, int nAckType);
+ void icq_sendFileAcceptServv7(DWORD dwUin, DWORD TS1, DWORD TS2, DWORD dwCookie, const char *szFiles, const char *szDescr, DWORD dwTotalSize, WORD wPort, BOOL accepted, int nAckType);
+ void icq_sendFileAcceptServv8(DWORD dwUin, DWORD TS1, DWORD TS2, DWORD dwCookie, const char *szFiles, const char *szDescr, DWORD dwTotalSize, WORD wPort, BOOL accepted, int nAckType);
+
+ void icq_sendFileDenyServ(DWORD dwUin, filetransfer *ft, const char *szReason, int nAckType);
+
+ DWORD icq_sendAdvancedSearchServ(BYTE *fieldsBuffer,int bufferLen);
+ DWORD icq_changeUserPasswordServ(const char *szPassword);
+ DWORD icq_changeUserDirectoryInfoServ(const BYTE *pData, WORD wDataLen, BYTE bRequestType);
+ void icq_sendGenericContact(DWORD dwUin, const char *szUid, WORD wFamily, WORD wSubType);
+ void icq_sendNewContact(DWORD dwUin, const char *szUid);
+ void icq_sendRemoveContact(DWORD dwUin, const 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, char **);
+ void icq_sendAwayMsgReplyServExt(DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, WORD wCookie, WORD wVersion, BYTE msgType, char **szMsg);
+
+ 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, const char *szUid, const char *szMsg);
+ void icq_sendAuthReqServ(DWORD dwUin, char* szUid, const char *szMsg);
+ void icq_sendAuthResponseServ(DWORD dwUin, char* szUid,int auth,const TCHAR *szReason);
+ void icq_sendYouWereAddedServ(DWORD,DWORD);
+
+ DWORD sendDirectorySearchPacket(const BYTE *pSearchData, WORD wDataLen, WORD wPage, BOOL bOnlineUsersOnly);
+ DWORD sendTLVSearchPacket(BYTE bType, char* pSearchDataBuf, WORD wSearchType, WORD wInfoLen, BOOL bOnlineUsersOnly);
+ void sendOwnerInfoRequest(void);
+ DWORD sendUserInfoMultiRequest(BYTE *pRequestData, WORD wDataLen, int nItems);
+
+ DWORD icq_SendChannel1Message(DWORD dwUin, char *szUID, HANDLE hContact, char *pszText, cookie_message_data *pCookieData);
+ DWORD icq_SendChannel1MessageW(DWORD dwUin, char *szUID, HANDLE hContact, WCHAR *pszText, cookie_message_data *pCookieData); // UTF-16
+ DWORD icq_SendChannel2Message(DWORD dwUin, HANDLE hContact, const char *szMessage, int nBodyLength, WORD wPriority, cookie_message_data *pCookieData, char *szCap);
+ DWORD icq_SendChannel2Contacts(DWORD dwUin, char *szUid, HANDLE hContact, const char *pData, WORD wDataLen, const char *pNames, WORD wNamesLen, cookie_message_data *pCookieData);
+ DWORD icq_SendChannel4Message(DWORD dwUin, HANDLE hContact, BYTE bMsgType, WORD wMsgLen, const char *szMsg, cookie_message_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, cookie_message_data *pCookie);
+ void icq_sendReverseFailed(directconnect* dc, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwCookie);
+
+ void icq_sendXtrazRequestServ(DWORD dwUin, DWORD dwCookie, char* szBody, int nBodyLen, cookie_message_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(const char *pszNick, const char *pszFirstName, const char *pszLastName, WORD wPage);
+ DWORD SearchByMail(const char *pszEmail);
+
+ DWORD icq_searchAimByEmail(const char* pszEmail, DWORD dwSearchId);
+
+ void oft_sendFileRequest(DWORD dwUin, char *szUid, oscar_filetransfer *ft, const 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);
+
+ //---- | icq_svcs.cpp |----------------------------------------------------------------
+ HANDLE AddToListByUIN(DWORD dwUin, DWORD dwFlags);
+ HANDLE AddToListByUID(const char *szUID, DWORD dwFlags);
+
+ void ICQAddRecvEvent(HANDLE hContact, WORD wType, PROTORECVEVENT* pre, DWORD cbBlob, PBYTE pBlob, DWORD flags);
+
+ //----| icq_uploadui.cpp |------------------------------------------------------------
+ void ShowUploadContactsDialog(void);
+
+ //----| icq_xstatus.cpp |-------------------------------------------------------------
+ int m_bHideXStatusUI;
+ int m_bHideXStatusMenu;
+ int bXStatusExtraIconsReady;
+ HANDLE hHookExtraIconsRebuild;
+ HANDLE hHookStatusBuild;
+ HANDLE hHookExtraIconsApply;
+ HANDLE hXStatusExtraIcons[XSTATUS_COUNT];
+ IcqIconHandle hXStatusIcons[XSTATUS_COUNT];
+ HANDLE hXStatusItems[XSTATUS_COUNT + 1];
+
+ int hXStatusCListIcons[XSTATUS_COUNT];
+ BOOL bXStatusCListIconsValid[XSTATUS_COUNT];
+
+ void InitXStatusItems(BOOL bAllowStatus);
+ BYTE getContactXStatus(HANDLE hContact);
+ DWORD sendXStatusDetailsRequest(HANDLE hContact, int bForced);
+ DWORD requestXStatusDetails(HANDLE hContact, BOOL bAllowDelay);
+ HICON getXStatusIcon(int bStatus, UINT flags);
+ void releaseXStatusIcon(int bStatus, UINT flags);
+ void setXStatusEx(BYTE bXStatus, BYTE bQuiet);
+ void setContactExtraIcon(HANDLE hContact, int xstatus);
+ void handleXStatusCaps(DWORD dwUIN, char *szUID, HANDLE hContact, BYTE *caps, int capsize, char *moods, int moodsize);
+ void updateServerCustomStatus(int fullUpdate);
+
+ void InitXStatusIcons();
+ void UninitXStatusIcons();
+
+ //----| icq_xtraz.cpp |---------------------------------------------------------------
+ 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);
+
+ //----| init.cpp |--------------------------------------------------------------------
+ void UpdateGlobalSettings();
+
+ //----| loginpassword.cpp |-----------------------------------------------------------
+ void RequestPassword();
+
+ //----| oscar_filetransfer.cpp |------------------------------------------------------
+ icq_critical_section *oftMutex;
+ int fileTransferCount;
+ basic_filetransfer** fileTransferList;
+
+ oscar_filetransfer* CreateOscarTransfer();
+ filetransfer *CreateIcqFileTransfer();
+ void ReleaseFileTransfer(void *ft);
+ void SafeReleaseFileTransfer(void **ft);
+ oscar_filetransfer* FindOscarTransfer(HANDLE hContact, DWORD dwID1, DWORD dwID2);
+
+ oscar_listener* CreateOscarListener(oscar_filetransfer *ft, NETLIBNEWCONNECTIONPROC_V2 handler);
+ void ReleaseOscarListener(oscar_listener **pListener);
+
+ void OpenOscarConnection(HANDLE hContact, oscar_filetransfer *ft, int type);
+ void CloseOscarConnection(oscar_connection *oc);
+ int CreateOscarProxyConnection(oscar_connection *oc);
+
+ int getFileTransferIndex(void *ft);
+ int IsValidFileTransfer(void *ft);
+ int IsValidOscarTransfer(void *ft);
+
+ void handleRecvServMsgOFT(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwID1, DWORD dwID2, WORD wCommand);
+ void handleRecvServResponseOFT(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, void* ft);
+
+ HANDLE oftInitTransfer(HANDLE hContact, DWORD dwUin, char *szUid, const TCHAR **pszFiles, const TCHAR *szDescription);
+ HANDLE oftFileAllow(HANDLE hContact, HANDLE hTransfer, const TCHAR *szPath);
+ DWORD oftFileDeny(HANDLE hContact, HANDLE hTransfer, const TCHAR *szReason);
+ DWORD oftFileCancel(HANDLE hContact, HANDLE hTransfer);
+ void oftFileResume(oscar_filetransfer *ft, int action, const TCHAR *szFilename);
+
+ void sendOscarPacket(oscar_connection *oc, icq_packet *packet);
+ void handleOFT2FramePacket(oscar_connection *oc, WORD datatype, BYTE *pBuffer, WORD wLen);
+ void sendOFT2FramePacket(oscar_connection *oc, WORD datatype);
+
+ void proxy_sendInitTunnel(oscar_connection *oc);
+ void proxy_sendJoinTunnel(oscar_connection *oc, WORD wPort);
+
+ //----| stdpackets.cpp |--------------------------------------------------------------
+ void __cdecl oft_connectionThread(struct oscarthreadstartinfo *otsi);
+
+ int oft_handlePackets(oscar_connection *oc, BYTE *buf, int len);
+ int oft_handleFileData(oscar_connection *oc, BYTE *buf, int len);
+ int oft_handleProxyData(oscar_connection *oc, BYTE *buf, int len);
+ void oft_sendFileData(oscar_connection *oc);
+ void oft_sendPeerInit(oscar_connection *oc);
+ void oft_sendFileReply(DWORD dwUin, char *szUid, oscar_filetransfer *ft, WORD wResult);
+
+ //----| upload.cpp |------------------------------------------------------------------
+ int StringToListItemId(const char *szSetting,int def);
+
+ //----| utilities.cpp |---------------------------------------------------------------
+ int BroadcastAck(HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam);
+ char* ConvertMsgToUserSpecificAnsi(HANDLE hContact, const char* szMsg);
+
+ char* GetUserStoredPassword(char *szBuffer, int cbSize);
+ char* GetUserPassword(BOOL bAlways);
+ WORD GetMyStatusFlags();
+
+ DWORD ReportGenericSendError(HANDLE hContact, int nType, const char* szErrorMsg);
+ void SetCurrentStatus(int nStatus);
+
+ void ForkThread( IcqThreadFunc pFunc, void* arg );
+ HANDLE ForkThreadEx( IcqThreadFunc pFunc, void* arg, UINT* threadID = NULL );
+
+ void __cdecl ProtocolAckThread(icq_ack_args* pArguments);
+ void SendProtoAck(HANDLE hContact, DWORD dwCookie, int nAckResult, int nAckType, char* pszMessage);
+
+ HANDLE CreateProtoEvent(const char* szEvent);
+ void CreateProtoService(const char* szService, IcqServiceFunc serviceProc);
+ void CreateProtoServiceParam(const char* szService, IcqServiceFuncParam serviceProc, LPARAM lParam);
+ HANDLE HookProtoEvent(const char* szEvent, IcqEventFunc pFunc);
+
+ int NetLog_Server(const char *fmt,...);
+ int NetLog_Direct(const char *fmt,...);
+ int NetLog_Uni(BOOL bDC, const char *fmt,...);
+
+ icq_critical_section *contactsCacheMutex;
+ LIST<icq_contacts_cache> contactsCache;
+
+ void AddToContactsCache(HANDLE hContact, DWORD dwUin, const char *szUid);
+ void DeleteFromContactsCache(HANDLE hContact);
+ void InitContactsCache();
+ void UninitContactsCache();
+
+ void AddToSpammerList(DWORD dwUIN);
+ BOOL IsOnSpammerList(DWORD dwUIN);
+
+ HANDLE NetLib_BindPort(NETLIBNEWCONNECTIONPROC_V2 pFunc, void* lParam, WORD* pwPort, DWORD* pdwIntIP);
+
+ HANDLE HandleFromCacheByUid(DWORD dwUin, const char *szUid);
+ HANDLE HContactFromUIN(DWORD dwUin, int *Added);
+ HANDLE HContactFromUID(DWORD dwUin, const char *szUid, int *Added);
+ HANDLE HContactFromAuthEvent(HANDLE hEvent);
+
+ void ResetSettingsOnListReload();
+ void ResetSettingsOnConnect();
+ void ResetSettingsOnLoad();
+
+ int IsMetaInfoChanged(HANDLE hContact);
+
+ char *setStatusNoteText, *setStatusMoodData;
+ void __cdecl SetStatusNoteThread(void *pArguments);
+ int SetStatusNote(const char *szStatusNote, DWORD dwDelay, int bForced);
+ int SetStatusMood(const char *szMoodData, DWORD dwDelay);
+
+ 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, const FieldNamesItem *table, char **buf, WORD* pwLength);
+ BOOL writeDbInfoSettingByte(HANDLE hContact, const char *pszSetting, char **buf, WORD* pwLength);
+ BOOL writeDbInfoSettingByteWithTable(HANDLE hContact, const char *szSetting, const FieldNamesItem *table, char **buf, WORD* pwLength);
+
+ void writeDbInfoSettingTLVStringUtf(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv);
+ void writeDbInfoSettingTLVString(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv);
+ void writeDbInfoSettingTLVWord(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv);
+ void writeDbInfoSettingTLVByte(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv);
+ void writeDbInfoSettingTLVDouble(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv);
+ void writeDbInfoSettingTLVDate(HANDLE hContact, const char *szSettingYear, const char *szSettingMonth, const char *szSettingDay, oscar_tlv_chain *chain, WORD wTlv);
+ void writeDbInfoSettingTLVBlob(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv);
+
+ char** MirandaStatusToAwayMsg(int nStatus);
+
+ BOOL validateStatusMessageRequest(HANDLE hContact, WORD byMessageType);
+};
+
+#endif
diff --git a/protocols/IcqOscarJ/icq_rates.cpp b/protocols/IcqOscarJ/icq_rates.cpp
new file mode 100644
index 0000000000..ebd6a13b8f
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_rates.cpp
@@ -0,0 +1,536 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_rates.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Rate Management stuff
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+//
+// Rate Level 1 Management
+/////////////////////////////
+
+rates::rates(CIcqProto *ppro, BYTE *pBuffer, WORD wLen)
+{
+ nGroups = 0;
+ memset(&groups, 0, MAX_RATES_GROUP_COUNT * sizeof(rates_group));
+ this->ppro = ppro;
+
+ // Parse Rate Data Block
+ WORD wCount;
+ unpackWord(&pBuffer, &wCount);
+ wLen -= 2;
+
+ if (wCount > MAX_RATES_GROUP_COUNT)
+ { // just sanity check
+ ppro->NetLog_Server("Rates: Error: Data packet contains too many rate groups!");
+ wCount = MAX_RATES_GROUP_COUNT;
+ }
+
+ nGroups = wCount;
+ // Parse Group details
+ int i;
+ for (i=0; i<wCount; i++)
+ {
+ rates_group *pGroup = &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 = &groups[i];
+ WORD wNum;
+
+ 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 (int n=0; n<wNum*2; n++)
+ {
+ WORD wItem;
+
+ unpackWord(&pBuffer, &wItem);
+ pGroup->pPairs[n] = wItem;
+ }
+#ifdef _DEBUG
+ ppro->NetLog_Server("Rates: %d# %d pairs.", i+1, wNum);
+#endif
+ wLen -= wNum*4;
+ }
+}
+
+
+rates::~rates()
+{
+ for (int i = 0; i < nGroups; i++)
+ SAFE_FREE((void**)&groups[i].pPairs);
+
+ nGroups = 0;
+}
+
+
+WORD rates::getGroupFromSNAC(WORD wFamily, WORD wCommand)
+{
+ if (this)
+ {
+ for (int i = 0; i < nGroups; i++)
+ {
+ rates_group* pGroup = &groups[i];
+
+ for (int j = 0; j < 2 * pGroup->nPairs; j += 2)
+ {
+ if (pGroup->pPairs[j] == wFamily && pGroup->pPairs[j + 1] == wCommand)
+ { // we found the group
+ return (WORD)(i + 1);
+ }
+ }
+ }
+ _ASSERTE(0);
+ }
+
+ return 0; // Failure
+}
+
+
+WORD rates::getGroupFromPacket(icq_packet *pPacket)
+{
+ if (this)
+ {
+ if (pPacket->nChannel == ICQ_DATA_CHAN && pPacket->wLen >= 0x10)
+ {
+ WORD wFamily, wCommand;
+ BYTE *pBuf = pPacket->pData + 6;
+
+ unpackWord(&pBuf, &wFamily);
+ unpackWord(&pBuf, &wCommand);
+
+ return getGroupFromSNAC(wFamily, wCommand);
+ }
+ }
+ return 0;
+}
+
+
+rates_group* rates::getGroup(WORD wGroup)
+{
+ if (this && wGroup && wGroup <= nGroups)
+ return &groups[wGroup - 1];
+
+ return NULL;
+}
+
+
+int rates::getNextRateLevel(WORD wGroup)
+{
+ rates_group *pGroup = getGroup(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 rates::getDelayToLimitLevel(WORD wGroup, int nLevel)
+{
+ rates_group *pGroup = getGroup(wGroup);
+
+ if (pGroup)
+ return (getLimitLevel(wGroup, nLevel) - pGroup->rCurrentLevel)*pGroup->dwWindowSize + pGroup->rCurrentLevel;
+
+ return 0; // Failure
+}
+
+
+void rates::packetSent(icq_packet *pPacket)
+{
+ if (this)
+ {
+ WORD wGroup = getGroupFromPacket(pPacket);
+
+ if (wGroup)
+ updateLevel(wGroup, getNextRateLevel(wGroup));
+ }
+}
+
+
+void rates::updateLevel(WORD wGroup, int nLevel)
+{
+ rates_group *pGroup = getGroup(wGroup);
+
+ if (pGroup)
+ {
+ pGroup->rCurrentLevel = nLevel;
+ pGroup->tCurrentLevel = GetTickCount();
+#ifdef _DEBUG
+ ppro->NetLog_Server("Rates: New level %d for #%d", nLevel, wGroup);
+#endif
+ }
+}
+
+
+int rates::getLimitLevel(WORD wGroup, int nLevel)
+{
+ rates_group *pGroup = getGroup(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
+}
+
+
+void rates::initAckPacket(icq_packet *pPacket)
+{
+ serverPacketInit(pPacket, 10 + nGroups * (int)sizeof(WORD));
+ packFNACHeader(pPacket, ICQ_SERVICE_FAMILY, ICQ_CLIENT_RATE_ACK);
+ for (WORD wGroup = 1; wGroup <= nGroups; wGroup++)
+ packWord(pPacket, wGroup);
+}
+
+
+
+//
+// Rate Level 2 Management
+/////////////////////////////
+
+
+rates_queue_item::rates_queue_item(CIcqProto *ppro, WORD wGroup) : bCreated(FALSE), dwUin(0), szUid(NULL)
+{
+ this->ppro = ppro;
+ this->wGroup = wGroup;
+}
+
+rates_queue_item::~rates_queue_item()
+{
+ if (bCreated)
+ {
+ SAFE_FREE(&szUid);
+ bCreated = FALSE;
+ }
+}
+
+
+BOOL rates_queue_item::isEqual(rates_queue_item *pItem)
+{ // the same event (equal address of _vftable) for the same contact
+ return (pItem->hContact == this->hContact) && (*(void**)pItem == *(void**)this);
+}
+
+
+rates_queue_item* rates_queue_item::copyItem(rates_queue_item *pDest)
+{
+ if (!pDest)
+ pDest = new rates_queue_item(ppro, wGroup);
+
+ pDest->hContact = hContact;
+ pDest->dwUin = dwUin;
+ pDest->szUid = dwUin ? null_strdup(szUid) : NULL;
+ pDest->bCreated = TRUE;
+
+ return pDest;
+}
+
+
+void rates_queue_item::execute()
+{
+#ifdef _DEBUG
+ ppro->NetLog_Server("Rates: Error executing abstract event.");
+#endif
+}
+
+
+BOOL rates_queue_item::isOverRate(int nLevel)
+{
+ icq_lock l(ppro->m_ratesMutex);
+
+ if (ppro->m_rates)
+ return ppro->m_rates->getNextRateLevel(wGroup) < ppro->m_rates->getLimitLevel(wGroup, nLevel);
+
+ return FALSE;
+}
+
+
+rates_queue::rates_queue(CIcqProto *ppro, const char *szDescr, int nLimitLevel, int nWaitLevel, int nDuplicates)
+{
+ this->listsMutex = new icq_critical_section();
+ this->ppro = ppro;
+ this->szDescr = szDescr;
+ limitLevel = nLimitLevel;
+ waitLevel = nWaitLevel;
+ duplicates = nDuplicates;
+}
+
+
+rates_queue::~rates_queue()
+{
+ cleanup();
+ SAFE_DELETE(&listsMutex);
+}
+
+
+// links to functions that are under Rate Control
+struct rate_delay_args
+{
+ int nDelay;
+ rates_queue *queue;
+ IcqRateFunc delaycode;
+};
+
+void __cdecl CIcqProto::rateDelayThread(rate_delay_args *pArgs)
+{
+ SleepEx(pArgs->nDelay, TRUE);
+ (pArgs->queue->*pArgs->delaycode)();
+ SAFE_FREE((void**)&pArgs);
+}
+
+
+void rates_queue::initDelay(int nDelay, IcqRateFunc delaycode)
+{
+#ifdef _DEBUG
+ ppro->NetLog_Server("Rates: Delay %dms", nDelay);
+#endif
+
+ rate_delay_args *pArgs = (rate_delay_args*)SAFE_MALLOC(sizeof(rate_delay_args)); // This will be freed in the new thread
+ pArgs->queue = this;
+ pArgs->nDelay = nDelay;
+ pArgs->delaycode = delaycode;
+
+ ppro->ForkThread((IcqThreadFunc)&CIcqProto::rateDelayThread, pArgs);
+}
+
+
+void rates_queue::cleanup()
+{
+ icq_lock l(listsMutex);
+
+ if (pendingListSize)
+ ppro->NetLog_Server("Rates: Purging %d %s(s).", pendingListSize, szDescr);
+
+ for (int i=0; i < pendingListSize; i++)
+ SAFE_DELETE((void_struct**)&pendingList[i]);
+ SAFE_FREE((void**)&pendingList);
+ pendingListSize = 0;
+}
+
+
+void rates_queue::processQueue()
+{
+ if (!pendingList)
+ return;
+
+ if (!ppro->icqOnline())
+ {
+ cleanup();
+ return;
+ }
+ // take from queue, execute
+ rates_queue_item *item = pendingList[0];
+
+ ppro->m_ratesMutex->Enter();
+ listsMutex->Enter();
+ if (item->isOverRate(limitLevel))
+ { // the rate is higher, keep sleeping
+ int nDelay = ppro->m_rates->getDelayToLimitLevel(item->wGroup, ppro->m_rates->getLimitLevel(item->wGroup, waitLevel));
+
+ listsMutex->Leave();
+ ppro->m_ratesMutex->Leave();
+ if (nDelay < 10) nDelay = 10;
+ initDelay(nDelay, &rates_queue::processQueue);
+ return;
+ }
+ ppro->m_ratesMutex->Leave();
+
+ if (pendingListSize > 1)
+ { // we need to keep order
+ memmove(&pendingList[0], &pendingList[1], (pendingListSize - 1) * sizeof(rates_queue_item*));
+ }
+ else
+ SAFE_FREE((void**)&pendingList);
+
+ int bSetupTimer = --pendingListSize != 0;
+
+ listsMutex->Leave();
+
+ if (ppro->icqOnline())
+ {
+ ppro->NetLog_Server("Rates: Resuming %s.", szDescr);
+ item->execute();
+ }
+ else
+ ppro->NetLog_Server("Rates: Discarding %s.", szDescr);
+
+ if (bSetupTimer)
+ {
+ // in queue remained some items, setup timer
+ ppro->m_ratesMutex->Enter();
+ int nDelay = ppro->m_rates->getDelayToLimitLevel(item->wGroup, waitLevel);
+ ppro->m_ratesMutex->Leave();
+
+ if (nDelay < 10) nDelay = 10;
+ initDelay(nDelay, &rates_queue::processQueue);
+ }
+ SAFE_DELETE((void_struct**)&item);
+}
+
+
+void rates_queue::putItem(rates_queue_item *pItem, int nMinDelay)
+{
+ int bFound = FALSE;
+
+ if (!ppro->icqOnline())
+ return;
+
+ ppro->NetLog_Server("Rates: Delaying %s.", szDescr);
+
+ listsMutex->Enter();
+ if (pendingListSize)
+ {
+ for (int i = 0; i < pendingListSize; i++)
+ {
+ if (pendingList[i]->isEqual(pItem))
+ {
+ if (duplicates == -1)
+ { // discard existing, append new item
+ SAFE_DELETE((void_struct**)&pendingList[i]);
+ memcpy(&pendingList[i], &pendingList[i + 1], (pendingListSize - i - 1) * sizeof(rates_queue_item*));
+ bFound = TRUE;
+ }
+ else if (duplicates == 1)
+ { // keep existing, ignore new
+ listsMutex->Leave();
+ return;
+ }
+ // otherwise keep existing and append new
+ }
+ }
+ }
+ if (!bFound)
+ { // not found, enlarge the queue
+ pendingListSize++;
+ pendingList = (rates_queue_item**)SAFE_REALLOC(pendingList, pendingListSize * sizeof(rates_queue_item*));
+ }
+ pendingList[pendingListSize - 1] = pItem->copyItem();
+
+ if (pendingListSize == 1)
+ { // queue was empty setup timer
+ listsMutex->Leave();
+ ppro->m_ratesMutex->Enter();
+ int nDelay = ppro->m_rates->getDelayToLimitLevel(pItem->wGroup, waitLevel);
+ ppro->m_ratesMutex->Leave();
+
+ if (nDelay < 10) nDelay = 10;
+ if (nDelay < nMinDelay) nDelay = nMinDelay;
+ initDelay(nDelay, &rates_queue::processQueue);
+ }
+ else
+ listsMutex->Leave();
+}
+
+
+int CIcqProto::handleRateItem(rates_queue_item *item, int nQueueType, int nMinDelay, BOOL bAllowDelay)
+{
+ rates_queue *pQueue = NULL;
+
+ m_ratesMutex->Enter();
+ switch (nQueueType)
+ {
+ case RQT_REQUEST:
+ pQueue = m_ratesQueue_Request;
+ break;
+ case RQT_RESPONSE:
+ pQueue = m_ratesQueue_Response;
+ break;
+ }
+
+ if (pQueue)
+ {
+ if (bAllowDelay && (item->isOverRate(pQueue->waitLevel) || nMinDelay))
+ { // limit reached or min delay configured, add to queue
+ pQueue->putItem(item, nMinDelay);
+
+ m_ratesMutex->Leave();
+ return 1;
+ }
+ }
+ m_ratesMutex->Leave();
+
+ item->execute();
+ return 0;
+}
diff --git a/protocols/IcqOscarJ/icq_rates.h b/protocols/IcqOscarJ/icq_rates.h
new file mode 100644
index 0000000000..ca3212964d
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_rates.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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_rates.h $
+// Revision : $Revision: 11570 $
+// Last change on : $Date: 2010-04-11 16:58:57 +0300 (Вс, 11 апр 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Rate management
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_RATES_H
+#define __ICQ_RATES_H
+
+#define MAX_RATES_GROUP_COUNT 5
+
+struct rates_group
+{
+ DWORD dwWindowSize;
+ DWORD dwClearLevel;
+ DWORD dwAlertLevel;
+ DWORD dwLimitLevel;
+ DWORD dwMaxLevel;
+ // current level
+ int rCurrentLevel;
+ int tCurrentLevel;
+ // links
+ WORD *pPairs;
+ int nPairs;
+};
+
+struct rates : public void_struct
+{
+private:
+ CIcqProto *ppro;
+ int nGroups;
+ rates_group groups[MAX_RATES_GROUP_COUNT];
+
+ rates_group *getGroup(WORD wGroup);
+public:
+ rates(CIcqProto *ppro, BYTE *pBuffer, WORD wLen);
+ ~rates();
+
+ WORD getGroupFromSNAC(WORD wFamily, WORD wCommand);
+ WORD getGroupFromPacket(icq_packet *pPacket);
+
+ int getLimitLevel(WORD wGroup, int nLevel);
+ int getDelayToLimitLevel(WORD wGroup, int nLevel);
+ int getNextRateLevel(WORD wGroup);
+
+ void packetSent(icq_packet *pPacket);
+ void updateLevel(WORD wGroup, int nLevel);
+
+ void initAckPacket(icq_packet *pPacket);
+};
+
+#define RML_CLEAR 0x01
+#define RML_ALERT 0x02
+#define RML_LIMIT 0x03
+#define RML_IDLE_10 0x10
+#define RML_IDLE_30 0x11
+#define RML_IDLE_50 0x12
+#define RML_IDLE_70 0x13
+
+// Rates - Level 2
+
+// queue types
+#define RQT_DEFAULT 0 // standard - pushes all items without much delay
+#define RQT_REQUEST 1 // request - pushes only first item on duplicity
+#define RQT_RESPONSE 2 // response - pushes only last item on duplicity
+
+//
+// generic queue item
+//
+struct rates_queue_item : public void_struct
+{
+ friend struct rates_queue;
+protected:
+ CIcqProto *ppro;
+ BOOL bCreated;
+ WORD wGroup;
+
+ virtual BOOL isEqual(rates_queue_item *pItem);
+ virtual rates_queue_item* copyItem(rates_queue_item *pDest = NULL);
+public:
+ rates_queue_item(CIcqProto *ppro, WORD wGroup);
+ virtual ~rates_queue_item();
+
+ BOOL isOverRate(int nLevel);
+
+ virtual void execute();
+
+ HANDLE hContact;
+ DWORD dwUin;
+ char *szUid;
+};
+
+struct rates_queue;
+typedef void (rates_queue::*IcqRateFunc)(void);
+
+//
+// generic item queue (FIFO)
+//
+struct rates_queue : public void_struct
+{
+private:
+ CIcqProto *ppro;
+ const char *szDescr;
+ icq_critical_section *listsMutex; // we need to be thread safe
+ int pendingListSize;
+ rates_queue_item **pendingList;
+ int duplicates;
+protected:
+ void cleanup();
+ void processQueue();
+ void initDelay(int nDelay, IcqRateFunc delaycode);
+public:
+ rates_queue(CIcqProto *ppro, const char *szDescr, int nLimitLevel, int nWaitLevel, int nDuplicates = 0);
+ ~rates_queue();
+
+ void putItem(rates_queue_item *pItem, int nMinDelay);
+
+ int limitLevel; // RML_*
+ int waitLevel;
+};
+
+
+#endif /* __ICQ_RATES_H */
diff --git a/protocols/IcqOscarJ/icq_server.cpp b/protocols/IcqOscarJ/icq_server.cpp
new file mode 100644
index 0000000000..a3621ec6aa
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_server.cpp
@@ -0,0 +1,452 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_server.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Manages main server connection, low-level communication
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void icq_newConnectionReceived(HANDLE hNewConnection, DWORD dwRemoteIP, void *pExtra);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// ICQ Server thread
+
+void __cdecl CIcqProto::ServerThread(serverthread_start_info *infoParam)
+{
+ serverthread_info info = {0};
+
+ info.isLoginServer = 1;
+ info.wAuthKeyLen = infoParam->wPassLen;
+ null_strcpy((char*)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;
+ nloc.timeout = 6;
+ if (m_bGatewayMode)
+ nloc.flags |= NLOCF_HTTPGATEWAY;
+
+ hServerConn = NetLib_OpenConnection(m_hServerNetlibUser, NULL, &nloc);
+
+ SAFE_FREE((void**)&nloc.szHost);
+ SAFE_FREE((void**)&infoParam);
+
+ if (hServerConn && m_bSecureConnection)
+ {
+ if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)hServerConn, 0))
+ {
+ icq_LogMessage(LOG_ERROR, LPGEN("Unable to connect to ICQ login server, SSL could not be negotiated"));
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ NetLib_CloseConnection(&hServerConn, TRUE);
+ return;
+ }
+ }
+
+ }
+
+ // Login error
+ if (hServerConn == NULL)
+ {
+ DWORD dwError = GetLastError();
+
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+
+ icq_LogUsingErrorCode(LOG_ERROR, dwError, LPGEN("Unable to connect to ICQ login server"));
+ return;
+ }
+
+ // Initialize direct connection ports
+ {
+ DWORD dwInternalIP;
+ BYTE bConstInternalIP = getSettingByte(NULL, "ConstRealIP", 0);
+
+ info.hDirectBoundPort = NetLib_BindPort(icq_newConnectionReceived, this, &wListenPort, &dwInternalIP);
+ if (!info.hDirectBoundPort)
+ {
+ icq_LogUsingErrorCode(LOG_WARNING, GetLastError(), LPGEN("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) deleteSetting(NULL, "RealIP");
+ }
+ else if (!bConstInternalIP)
+ setSettingDword(NULL, "RealIP", dwInternalIP);
+ }
+
+ // Initialize rate limiting queues
+ {
+ icq_lock l(m_ratesMutex);
+
+ m_ratesQueue_Request = new rates_queue(this, "request", RML_IDLE_30, RML_IDLE_50, 1);
+ m_ratesQueue_Response = new rates_queue(this, "response", RML_IDLE_10, RML_IDLE_30, -1);
+ }
+
+ // 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 (serverThreadHandle)
+ {
+ 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;
+ }
+
+ if (m_iDesiredStatus == ID_STATUS_OFFLINE)
+ { // Disconnect requested, send disconnect packet
+ icq_sendCloseConnection();
+
+ // disconnected upon request
+ m_bConnectionLost = FALSE;
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+
+ NetLog_Server("Logged off.");
+ break;
+ }
+
+ // Deal with the packet
+ packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable, &info);
+ }
+ serverThreadHandle = NULL;
+
+ // Time to shutdown
+ NetLib_CloseConnection(&hServerConn, TRUE);
+
+ // Close the packet receiver (connection may still be open)
+ NetLib_SafeCloseHandle(&info.hPacketRecver);
+
+ // Close DC port
+ NetLib_SafeCloseHandle(&info.hDirectBoundPort);
+ }
+
+ // disable auto info-update thread
+ icq_EnableUserLookup(FALSE);
+
+ if (m_iStatus != ID_STATUS_OFFLINE && m_iDesiredStatus != ID_STATUS_OFFLINE)
+ {
+ if (!info.bLoggedIn)
+ icq_LogMessage(LOG_FATAL, LPGEN("Connection failed.\nLogin sequence failed for unknown reason.\nTry again later."));
+
+ // set flag indicating we were kicked out
+ m_bConnectionLost = TRUE;
+
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ }
+
+ // signal keep-alive thread to stop
+ StopKeepAlive(&info);
+
+ // Close all open DC connections
+ CloseContactDirectConns(NULL);
+
+ // Close avatar connection if any
+ StopAvatarThread();
+
+ // Offline all contacts
+ HANDLE hContact = FindFirstContact();
+ while (hContact)
+ {
+ DWORD dwUIN;
+ uid_str szUID;
+
+ if (!getContactUid(hContact, &dwUIN, &szUID))
+ {
+ if (getContactStatus(hContact) != ID_STATUS_OFFLINE)
+ {
+ char tmp = 0;
+
+ setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+
+ handleXStatusCaps(dwUIN, szUID, hContact, (BYTE*)&tmp, 0, &tmp, 0);
+ }
+ }
+
+ hContact = FindNextContact(hContact);
+ }
+
+ setSettingDword(NULL, "LogonTS", 0); // clear logon time
+
+ servlistPendingFlushOperations(); // clear pending operations list
+
+ { // release rates queues
+ icq_lock l(m_ratesMutex);
+
+ SAFE_DELETE((void_struct**)&m_ratesQueue_Request);
+ SAFE_DELETE((void_struct**)&m_ratesQueue_Response);
+ SAFE_DELETE((void_struct**)&m_rates);
+ }
+
+ FlushServerIDs(); // clear server IDs list
+
+ NetLog_Server("%s thread ended.", "Server");
+}
+
+
+void CIcqProto::icq_serverDisconnect(BOOL bBlock)
+{
+ if (hServerConn)
+ {
+ NetLog_Server("Server shutdown requested");
+ Netlib_Shutdown(hServerConn);
+
+ if (serverThreadHandle)
+ {
+ // Not called from network thread?
+ if (bBlock && GetCurrentThreadId() != serverThreadId)
+ while (ICQWaitForSingleObject(serverThreadHandle, INFINITE) != WAIT_OBJECT_0);
+
+ CloseHandle(serverThreadHandle);
+ serverThreadHandle = NULL;
+ }
+ }
+}
+
+
+int CIcqProto::handleServerPackets(BYTE *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 Server FLAP Channel: Channel %u, Seq %u, Length %u bytes", channel, sequence, datalen);
+ break;
+ }
+
+ /* Increase pointers so we can check for more FLAPs */
+ buf += datalen;
+ len -= (datalen + 6);
+ bytesUsed += (datalen + 6);
+ }
+
+ return bytesUsed;
+}
+
+
+void CIcqProto::sendServPacket(icq_packet *pPacket)
+{
+ // make sure to have the connection handle
+ connectionHandleMutex->Enter();
+
+ if (hServerConn)
+ {
+ int nSendResult;
+
+ // This critsec makes sure that the sequence order doesn't get screwed up
+ localSeqMutex->Enter();
+
+ // :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);
+
+ nSendResult = Netlib_Send(hServerConn, (const char *)pPacket->pData, pPacket->wLen, 0);
+
+ localSeqMutex->Leave();
+ connectionHandleMutex->Leave();
+
+ // Send error
+ if (nSendResult == SOCKET_ERROR)
+ {
+ icq_LogUsingErrorCode(LOG_ERROR, GetLastError(), LPGEN("Your connection with the ICQ server was abortively closed"));
+ icq_serverDisconnect(FALSE);
+
+ if (m_iStatus != ID_STATUS_OFFLINE)
+ {
+ SetCurrentStatus(ID_STATUS_OFFLINE);
+ }
+ }
+ else
+ { // Rates management
+ icq_lock l(m_ratesMutex);
+ m_rates->packetSent(pPacket);
+ }
+
+ }
+ else
+ {
+ connectionHandleMutex->Leave();
+ NetLog_Server("Error: Failed to send packet (no connection)");
+ }
+
+ SAFE_FREE((void**)&pPacket->pData);
+}
+
+
+void __cdecl CIcqProto::SendPacketAsyncThread(icq_packet* pkt)
+{
+ sendServPacket( pkt );
+ SAFE_FREE((void**)&pkt);
+}
+
+
+void CIcqProto::sendServPacketAsync(icq_packet *packet)
+{
+ icq_packet *pPacket;
+
+ pPacket = (icq_packet*)SAFE_MALLOC(sizeof(icq_packet)); // This will be freed in the new thread
+ memcpy(pPacket, packet, sizeof(icq_packet));
+
+ ForkThread(( IcqThreadFunc )&CIcqProto::SendPacketAsyncThread, pPacket);
+}
+
+
+int CIcqProto::IsServerOverRate(WORD wFamily, WORD wCommand, int nLevel)
+{
+ icq_lock l(m_ratesMutex);
+
+ if (m_rates)
+ {
+ WORD wGroup = m_rates->getGroupFromSNAC(wFamily, wCommand);
+
+ // check if the rate is not over specified level
+ if (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(wGroup, nLevel))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// ICQ Server thread
+
+void CIcqProto::icq_login(const char* szPassword)
+{
+ DWORD dwUin = getContactUin(NULL);
+ serverthread_start_info* stsi = (serverthread_start_info*)SAFE_MALLOC(sizeof(serverthread_start_info));
+
+ // Server host name
+ char szServer[MAX_PATH];
+ if (getSettingStringStatic(NULL, "OscarServer", szServer, MAX_PATH))
+ stsi->nloc.szHost = null_strdup(m_bSecureConnection ? DEFAULT_SERVER_HOST_SSL : DEFAULT_SERVER_HOST);
+ else
+ stsi->nloc.szHost = null_strdup(szServer);
+
+ // Server port
+ stsi->nloc.wPort = getSettingWord(NULL, "OscarPort", m_bSecureConnection ? DEFAULT_SERVER_PORT_SSL : DEFAULT_SERVER_PORT);
+ if (stsi->nloc.wPort == 0)
+ stsi->nloc.wPort = RandRange(1024, 65535);
+
+ // User password
+ stsi->wPassLen = strlennull(szPassword);
+ if (stsi->wPassLen > 8) stsi->wPassLen = 8;
+ null_strcpy(stsi->szPass, szPassword, stsi->wPassLen);
+
+ // Randomize sequence
+ wLocalSequence = generate_flap_sequence();
+
+ m_dwLocalUIN = dwUin;
+
+ // Initialize members
+ m_avatarsConnectionPending = TRUE;
+
+ serverThreadHandle = ForkThreadEx(( IcqThreadFunc )&CIcqProto::ServerThread, stsi, &serverThreadId);
+}
diff --git a/protocols/IcqOscarJ/icq_server.h b/protocols/IcqOscarJ/icq_server.h
new file mode 100644
index 0000000000..df40332a3d
--- /dev/null
+++ b/protocols/IcqOscarJ/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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_server.h $
+// Revision : $Revision: 13213 $
+// Last change on : $Date: 2010-12-22 08:54:39 +0200 (Ср, 22 дек 2010) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Declarations for server thread
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_SERVER_H
+#define __ICQ_SERVER_H
+
+struct serverthread_start_info
+{
+ NETLIBOPENCONNECTION nloc;
+ WORD wPassLen;
+ char szPass[128];
+};
+
+struct serverthread_info
+{
+ struct CIcqProto *ppro;
+ int bLoggedIn;
+ int isLoginServer;
+ BYTE szAuthKey[20];
+ WORD wAuthKeyLen;
+ WORD wServerPort;
+ char *newServer;
+ BYTE *cookieData;
+ int cookieDataLen;
+ int newServerSSL;
+ int newServerReady;
+ int isMigrating;
+ HANDLE hPacketRecver;
+ int bReinitRecver;
+ int bMyAvatarInited;
+//
+ HANDLE hDirectBoundPort;
+//
+ HANDLE hKeepAliveEvent;
+ HANDLE hKeepAliveThread;
+};
+
+/*---------* Functions *---------------*/
+
+void icq_serverDisconnect(BOOL bBlock);
+void icq_login(const char *szPassword);
+
+int IsServerOverRate(WORD wFamily, WORD wCommand, int nLevel);
+
+
+#endif /* __ICQ_SERVER_H */
diff --git a/protocols/IcqOscarJ/icq_servlist.cpp b/protocols/IcqOscarJ/icq_servlist.cpp
new file mode 100644
index 0000000000..9da5e3e756
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_servlist.cpp
@@ -0,0 +1,2858 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_servlist.cpp $
+// Revision : $Revision: 14146 $
+// Last change on : $Date: 2012-03-09 23:54:49 +0200 (Пт, 09 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Functions that handles list of used server IDs, sends low-level packets for SSI information
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+// SERVER-LIST UPDATE BOARD
+//
+
+void CIcqProto::servlistBeginOperation(int operationCount, int bImport)
+{
+ if (operationCount)
+ { // check if we should send operation begin packet
+ if (!servlistEditCount)
+ icq_sendServerBeginOperation(bImport);
+ // update count of active operations
+ servlistEditCount += operationCount;
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Begin operation processed (%d operations active)", servlistEditCount);
+#endif
+ }
+}
+
+void CIcqProto::servlistEndOperation(int operationCount)
+{
+ if (operationCount)
+ {
+ if (operationCount > servlistEditCount)
+ { // sanity check
+ NetLog_Server("Error: Server-List End operation is not paired!");
+ operationCount = servlistEditCount;
+ }
+ // update count of active operations
+ servlistEditCount -= operationCount;
+ // check if we should send operation end packet
+ if (!servlistEditCount)
+ icq_sendServerEndOperation();
+#ifdef _DEBUG
+ NetLog_Server("Server-List: End operation processed (%d operations active)", servlistEditCount);
+#endif
+ }
+}
+
+void __cdecl CIcqProto::servlistQueueThread(void *param)
+{
+ int* queueState = ( int* )param;
+
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Starting Update board.");
+#endif
+
+ SleepEx(50, FALSE);
+ // handle server-list requests queue
+ servlistQueueMutex->Enter();
+ while (servlistQueueCount)
+ {
+ ssiqueueditems* pItem = NULL;
+ int bItemDouble;
+ WORD wItemAction;
+ icq_packet groupPacket = {0};
+ icq_packet groupPacket2 = {0};
+ cookie_servlist_action* pGroupCookie = NULL;
+ int nEndOperations;
+
+ // first check if the state is calm
+ while (*queueState)
+ {
+ int i;
+ time_t tNow = time(NULL);
+ int bFound = FALSE;
+
+ for (i = 0; i < servlistQueueCount; i++)
+ { // check if we do not have some expired items to handle, otherwise keep sleeping
+ if ((servlistQueueList[i]->tAdded + servlistQueueList[i]->dwTimeout) < tNow)
+ { // got expired item, stop sleep even when changes goes on
+ bFound = TRUE;
+ break;
+ }
+ }
+ if (bFound) break;
+ // reset queue state, keep sleeping
+ *queueState = FALSE;
+ servlistQueueMutex->Leave();
+ SleepEx(100, TRUE);
+ servlistQueueMutex->Enter();
+ }
+ if (!icqOnline())
+ { // do not try to send packets if offline
+ servlistQueueMutex->Leave();
+ SleepEx(100, TRUE);
+ servlistQueueMutex->Enter();
+ continue;
+ }
+#ifdef _DEBUG
+ NetLog_Server("Server-List: %d items in queue.", servlistQueueCount);
+#endif
+ // take the oldest item (keep the board FIFO)
+ pItem = servlistQueueList[0]; // take first (queue contains at least one item here)
+ wItemAction = (WORD)(pItem->pItems[0]->dwOperation & SSOF_ACTIONMASK);
+ bItemDouble = pItem->pItems[0]->dwOperation & SSOG_DOUBLE;
+ // check item rate - too high -> sleep
+ m_ratesMutex->Enter();
+ {
+ WORD wRateGroup = m_rates->getGroupFromSNAC(ICQ_LISTS_FAMILY, wItemAction);
+ int nRateLevel = bItemDouble ? RML_IDLE_30 : RML_IDLE_10;
+
+ while (m_rates->getNextRateLevel(wRateGroup) < m_rates->getLimitLevel(wRateGroup, nRateLevel))
+ { // the rate is higher, keep sleeping
+ int nDelay = m_rates->getDelayToLimitLevel(wRateGroup, nRateLevel);
+
+ m_ratesMutex->Leave();
+ // do not keep the queue frozen
+ servlistQueueMutex->Leave();
+ if (nDelay < 10) nDelay = 10;
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Delaying %dms [Rates]", nDelay);
+#endif
+ SleepEx(nDelay, FALSE);
+ // check if the rate is now ok
+ servlistQueueMutex->Enter();
+ m_ratesMutex->Enter();
+ }
+ }
+ m_ratesMutex->Leave();
+ { // setup group packet(s) & cookie
+ int totalSize = 0;
+ int i;
+ cookie_servlist_action *pGroupCookie;
+ DWORD dwGroupCookie;
+ // determine the total size of the packet
+ for(i = 0; i < pItem->nItems; i++)
+ totalSize += pItem->pItems[i]->packet.wLen - 0x10;
+
+ // process begin & end operation flags
+ {
+ int bImportOperation = FALSE;
+ int nBeginOperations = 0;
+
+ nEndOperations = 0;
+ for(i = 0; i < pItem->nItems; i++)
+ { // collect begin & end operation flags
+ if (pItem->pItems[i]->dwOperation & SSOF_BEGIN_OPERATION)
+ nBeginOperations++;
+ if (pItem->pItems[i]->dwOperation & SSOF_END_OPERATION)
+ nEndOperations++;
+ // check if the operation is import
+ if (pItem->pItems[i]->dwOperation & SSOF_IMPORT_OPERATION)
+ bImportOperation = TRUE;
+ }
+ // really begin operation if requested
+ if (nBeginOperations)
+ servlistBeginOperation(nBeginOperations, bImportOperation);
+ }
+
+ if (pItem->nItems > 1)
+ { // pack all packet's data, create group cookie
+ pGroupCookie = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ pGroupCookie->dwAction = SSA_ACTION_GROUP;
+ pGroupCookie->dwGroupCount = pItem->nItems;
+ pGroupCookie->pGroupItems = (cookie_servlist_action**)SAFE_MALLOC(pItem->nItems * sizeof(cookie_servlist_action*));
+ for (i = 0; i < pItem->nItems; i++)
+ { // build group cookie data - assign cookies datas
+ pGroupCookie->pGroupItems[i] = pItem->pItems[i]->cookie;
+ // release the separate cookie id
+ FreeCookieByData(CKT_SERVERLIST, pItem->pItems[i]->cookie);
+ }
+ // allocate cookie id
+ dwGroupCookie = AllocateCookie(CKT_SERVERLIST, wItemAction, 0, pGroupCookie);
+ // prepare packet data
+ serverPacketInit(&groupPacket, (WORD)(totalSize + 0x0A)); // FLAP size added inside
+ packFNACHeader(&groupPacket, ICQ_LISTS_FAMILY, wItemAction, 0, dwGroupCookie);
+ for (i = 0; i < pItem->nItems; i++)
+ packBuffer(&groupPacket, pItem->pItems[i]->packet.pData + 0x10, (WORD)(pItem->pItems[i]->packet.wLen - 0x10));
+
+ if (bItemDouble)
+ { // prepare second packet
+ wItemAction = ((servlistgroupitemdouble*)(pItem->pItems[0]))->wAction2;
+ totalSize = 0;
+ // determine the total size of the packet
+ for(i = 0; i < pItem->nItems; i++)
+ totalSize += ((servlistgroupitemdouble*)(pItem->pItems[i]))->packet2.wLen - 0x10;
+
+ pGroupCookie = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ pGroupCookie->dwAction = SSA_ACTION_GROUP;
+ pGroupCookie->dwGroupCount = pItem->nItems;
+ pGroupCookie->pGroupItems = (cookie_servlist_action**)SAFE_MALLOC(pItem->nItems * sizeof(cookie_servlist_action*));
+ for (i = 0; i < pItem->nItems; i++)
+ pGroupCookie->pGroupItems[i] = pItem->pItems[i]->cookie;
+ // allocate cookie id
+ dwGroupCookie = AllocateCookie(CKT_SERVERLIST, wItemAction, 0, pGroupCookie);
+ // prepare packet data
+ serverPacketInit(&groupPacket2, (WORD)(totalSize + 0x0A)); // FLAP size added inside
+ packFNACHeader(&groupPacket2, ICQ_LISTS_FAMILY, wItemAction, 0, dwGroupCookie);
+ for (i = 0; i < pItem->nItems; i++)
+ packBuffer(&groupPacket2, ((servlistgroupitemdouble*)(pItem->pItems[i]))->packet2.pData + 0x10, (WORD)(((servlistgroupitemdouble*)(pItem->pItems[i]))->packet2.wLen - 0x10));
+ }
+ }
+ else
+ { // just send the one packet, do not create action group
+ pGroupCookie = pItem->pItems[0]->cookie;
+ memcpy(&groupPacket, &pItem->pItems[0]->packet, sizeof(icq_packet));
+ if (bItemDouble)
+ memcpy(&groupPacket2, &((servlistgroupitemdouble*)(pItem->pItems[0]))->packet2, sizeof(icq_packet));
+ }
+
+ { // remove grouped item from queue & release grouped item
+ servlistQueueCount--;
+ servlistQueueList[0] = servlistQueueList[servlistQueueCount];
+
+ for (i = 0; i < pItem->nItems; i++)
+ { // release memory
+ if (pItem->nItems > 1)
+ { // free the packet only if we created the group packet
+ SAFE_FREE((void**)&pItem->pItems[i]->packet.pData);
+ if (pItem->pItems[i]->dwOperation & SSOG_DOUBLE)
+ SAFE_FREE((void**)&((servlistgroupitemdouble*)(pItem->pItems[i]))->packet2.pData);
+ }
+ SAFE_FREE((void**)&pItem->pItems[i]);
+ break;
+ }
+ SAFE_FREE((void**)&pItem);
+ // resize the queue
+ if (servlistQueueSize > servlistQueueCount + 6)
+ {
+ servlistQueueSize -= 4;
+ servlistQueueList = (ssiqueueditems**)SAFE_REALLOC(servlistQueueList, servlistQueueSize * sizeof(ssiqueueditems*));
+ }
+ }
+ }
+ servlistQueueMutex->Leave();
+ // send group packet
+ sendServPacket(&groupPacket);
+ // send second group packet (if present)
+ if (bItemDouble)
+ sendServPacket(&groupPacket2);
+ // process end operation marks
+ if (nEndOperations)
+ servlistEndOperation(nEndOperations);
+ // loose the loop a bit
+ SleepEx(100, TRUE);
+ servlistQueueMutex->Enter();
+ }
+ // clean-up thread
+ CloseHandle(servlistQueueThreadHandle);
+ servlistQueueThreadHandle = NULL;
+ servlistQueueMutex->Leave();
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Update Board ending.");
+#endif
+}
+
+void CIcqProto::servlistQueueAddGroupItem(servlistgroupitem* pGroupItem, int dwTimeout)
+{
+ icq_lock l(servlistQueueMutex);
+
+ { // add the packet to queue
+ DWORD dwMark = pGroupItem->dwOperation & SSOF_GROUPINGMASK;
+ ssiqueueditems* pItem = NULL;
+
+ // try to find compatible item
+ for (int i = 0; i < servlistQueueCount; i++)
+ {
+ if ((servlistQueueList[i]->pItems[0]->dwOperation & SSOF_GROUPINGMASK) == dwMark && servlistQueueList[i]->nItems < MAX_SERVLIST_PACKET_ITEMS)
+ { // found compatible item, check if it does not contain operation for the same server-list item
+ pItem = servlistQueueList[i];
+
+ for (int j = 0; j < pItem->nItems; j++)
+ if (pItem->pItems[j]->cookie->wContactId == pGroupItem->cookie->wContactId &&
+ pItem->pItems[j]->cookie->wGroupId == pGroupItem->cookie->wGroupId)
+ {
+ pItem = NULL;
+ break;
+ }
+ // cannot send two operations for the same server-list record in one packet, look for another
+ if (!pItem) continue;
+
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Adding packet to item #%d with operation %x.", i, servlistQueueList[i]->pItems[0]->dwOperation);
+#endif
+ break;
+ }
+ }
+ if (!pItem)
+ { // compatible item was not found, create new one, add to queue
+ pItem = (ssiqueueditems*)SAFE_MALLOC(sizeof(ssiqueueditems));
+ pItem->tAdded = time(NULL);
+ pItem->dwTimeout = dwTimeout;
+
+ if (servlistQueueCount == servlistQueueSize)
+ { // resize the queue - it is too small
+ servlistQueueSize += 4;
+ servlistQueueList = (ssiqueueditems**)SAFE_REALLOC(servlistQueueList, servlistQueueSize * sizeof(ssiqueueditems*));
+ }
+ // really add to queue
+ servlistQueueList[servlistQueueCount++] = pItem;
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Adding new item to queue.");
+#endif
+ }
+ else if (pItem->dwTimeout > dwTimeout)
+ { // if the timeout of currently added packet is shorter, update the previous one
+ pItem->dwTimeout = dwTimeout;
+ }
+ // add GroupItem to queueditems (pItem)
+ pItem->pItems[pItem->nItems++] = pGroupItem;
+ }
+ // wake up board thread (keep sleeping or start new one)
+ if (!servlistQueueThreadHandle)
+ {
+ // create new board thread
+ servlistQueueThreadHandle = ForkThreadEx( &CIcqProto::servlistQueueThread, &servlistQueueState );
+ }
+ else // signal thread, that queue was changed during sleep
+ servlistQueueState = TRUE;
+}
+
+int CIcqProto::servlistHandlePrimitives(DWORD dwOperation)
+{
+ if (dwOperation & SSO_BEGIN_OPERATION)
+ { // operation starting, no action ready yet
+ servlistBeginOperation(1, dwOperation & SSOF_IMPORT_OPERATION);
+ return TRUE;
+ }
+ else if (dwOperation & SSO_END_OPERATION)
+ { // operation ending without action
+ servlistEndOperation(1);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void CIcqProto::servlistPostPacket(icq_packet* packet, DWORD dwCookie, DWORD dwOperation, DWORD dwTimeout)
+{
+ cookie_servlist_action* pCookie;
+
+ if (servlistHandlePrimitives(dwOperation))
+ return;
+
+ if (!FindCookie(dwCookie, NULL, (void**)&pCookie))
+ return; // invalid cookie
+
+ if (dwOperation & SSOF_SEND_DIRECTLY)
+ { // send directly - this is for some special cases
+ // begin operation if requested
+ if (dwOperation & SSOF_BEGIN_OPERATION)
+ servlistBeginOperation(1, dwOperation & SSOF_IMPORT_OPERATION);
+
+ // send the packet
+ sendServPacket(packet);
+
+ // end operation if requested
+ if (dwOperation & SSOF_END_OPERATION)
+ servlistEndOperation(1);
+ }
+ else
+ { // add to server-list update board
+ servlistgroupitem* pGroupItem;
+
+ // prepare group item
+ pGroupItem = (servlistgroupitem*)SAFE_MALLOC(sizeof(servlistgroupitem));
+ pGroupItem->dwOperation = dwOperation;
+ pGroupItem->cookie = pCookie;
+ // packet data are alloced, keep them until they are sent
+ memcpy(&pGroupItem->packet, packet, sizeof(icq_packet));
+
+ servlistQueueAddGroupItem(pGroupItem, dwTimeout);
+ }
+}
+
+void CIcqProto::servlistPostPacketDouble(icq_packet* packet1, DWORD dwCookie, DWORD dwOperation, DWORD dwTimeout, icq_packet* packet2, WORD wAction2)
+{
+ cookie_servlist_action* pCookie;
+
+ if (servlistHandlePrimitives(dwOperation))
+ return;
+
+ if (!FindCookie(dwCookie, NULL, (void**)&pCookie))
+ return; // invalid cookie
+
+ if (dwOperation & SSOF_SEND_DIRECTLY)
+ { // send directly - this is for some special cases
+ // begin operation if requested
+ if (dwOperation & SSOF_BEGIN_OPERATION)
+ servlistBeginOperation(1, dwOperation & SSOF_IMPORT_OPERATION);
+
+ // send the packets
+ sendServPacket(packet1);
+ sendServPacket(packet2);
+
+ // end operation if requested
+ if (dwOperation & SSOF_END_OPERATION)
+ servlistEndOperation(1);
+ }
+ else
+ { // add to server-list update board
+ servlistgroupitemdouble* pGroupItem;
+
+ // prepare group item
+ pGroupItem = (servlistgroupitemdouble*)SAFE_MALLOC(sizeof(servlistgroupitemdouble));
+ pGroupItem->dwOperation = dwOperation;
+ pGroupItem->cookie = pCookie;
+ pGroupItem->wAction2 = wAction2;
+ // packets data are alloced, keep them until they are sent
+ memcpy(&pGroupItem->packet, packet1, sizeof(icq_packet));
+ memcpy(&pGroupItem->packet2, packet2, sizeof(icq_packet));
+
+ servlistQueueAddGroupItem((servlistgroupitem*)pGroupItem, dwTimeout);
+ }
+}
+
+void CIcqProto::servlistProcessLogin()
+{
+ // reset edit state counter
+ servlistEditCount = 0;
+
+ /// TODO: preserve queue state in DB! restore here!
+
+ // if the server-list queue contains items and thread is not running, start it
+ if (servlistQueueCount && !servlistQueueThreadHandle)
+ servlistQueueThreadHandle = ForkThreadEx( &CIcqProto::servlistQueueThread, &servlistQueueState );
+}
+
+// HERE ENDS SERVER-LIST UPDATE BOARD IMPLEMENTATION //
+///////////////////////////////////////////////////////
+//===================================================//
+
+// PENDING SERVER-LIST OPERATIONS
+//
+#define ITEM_PENDING_CONTACT 0x01
+#define ITEM_PENDING_GROUP 0x02
+
+#define CALLBACK_RESULT_CONTINUE 0x00
+#define CALLBACK_RESULT_POSTPONE 0x0D
+#define CALLBACK_RESULT_PURGE 0x10
+
+
+#define SPOF_AUTO_CREATE_ITEM 0x01
+
+int CIcqProto::servlistPendingFindItem(int nType, HANDLE hContact, const char *pszGroup)
+{
+ if (servlistPendingList)
+ for (int i = 0; i < servlistPendingCount; i++)
+ if (servlistPendingList[i]->nType == nType)
+ {
+ if (((nType == ITEM_PENDING_CONTACT) && (servlistPendingList[i]->hContact == hContact)) ||
+ ((nType == ITEM_PENDING_GROUP) && (!strcmpnull(servlistPendingList[i]->szGroup, pszGroup))))
+ return i;
+ }
+ return -1;
+}
+
+
+void CIcqProto::servlistPendingAddItem(servlistpendingitem *pItem)
+{
+ if (servlistPendingCount >= servlistPendingSize) // add new
+ {
+ servlistPendingSize += 10;
+ servlistPendingList = (servlistpendingitem**)SAFE_REALLOC(servlistPendingList, servlistPendingSize * sizeof(servlistpendingitem*));
+ }
+
+ servlistPendingList[servlistPendingCount++] = pItem;
+}
+
+
+servlistpendingitem* CIcqProto::servlistPendingRemoveItem(int nType, HANDLE hContact, const char *pszGroup)
+{ // unregister pending item, trigger pending operations
+ int iItem;
+ servlistpendingitem *pItem = NULL;
+
+ icq_lock l(servlistMutex);
+
+ if ((iItem = servlistPendingFindItem(nType, hContact, pszGroup)) != -1)
+ { // found, remove from the pending list
+ pItem = servlistPendingList[iItem];
+
+ servlistPendingList[iItem] = servlistPendingList[--servlistPendingCount];
+
+ if (servlistPendingCount + 10 < servlistPendingSize)
+ {
+ servlistPendingSize -= 5;
+ servlistPendingList = (servlistpendingitem**)SAFE_REALLOC(servlistPendingList, servlistPendingSize * sizeof(servlistpendingitem*));
+ }
+ // was the first operation was created automatically to postpone ItemAdd?
+ if (pItem->operations && pItem->operations[0].flags & SPOF_AUTO_CREATE_ITEM)
+ { // yes, add new item
+ servlistpendingitem *pNewItem = (servlistpendingitem*)SAFE_MALLOC(sizeof(servlistpendingitem));
+
+ if (pNewItem)
+ { // move the remaining operations
+#ifdef _DEBUG
+ if (pItem->nType == ITEM_PENDING_CONTACT)
+ NetLog_Server("Server-List: Resuming contact %x operation.", pItem->hContact);
+ else
+ NetLog_Server("Server-List: Resuming group \"%s\" operation.", pItem->szGroup);
+#endif
+
+ pNewItem->nType = pItem->nType;
+ pNewItem->hContact = pItem->hContact;
+ pNewItem->szGroup = null_strdup(pItem->szGroup);
+ pNewItem->wContactID = pItem->wContactID;
+ pNewItem->wGroupID = pItem->wGroupID;
+ pNewItem->operationsCount = pItem->operationsCount - 1;
+ pNewItem->operations = (servlistpendingoperation*)SAFE_MALLOC(pNewItem->operationsCount * sizeof(servlistpendingoperation));
+ memcpy(pNewItem->operations, pItem->operations + 1, pNewItem->operationsCount * sizeof(servlistpendingoperation));
+ pItem->operationsCount = 1;
+
+ servlistPendingAddItem(pNewItem);
+ // clear the flag
+ pItem->operations[0].flags &= ~SPOF_AUTO_CREATE_ITEM;
+ }
+ }
+ }
+#ifdef _DEBUG
+ else
+ NetLog_Server("Server-List Error: Trying to remove non-existing pending %s.", nType == ITEM_PENDING_CONTACT ? "contact" : "group");
+#endif
+
+ return pItem;
+}
+
+
+void CIcqProto::servlistPendingAddContactOperation(HANDLE hContact, LPARAM param, PENDING_CONTACT_CALLBACK callback, DWORD flags)
+{ // add postponed operation (add contact, update contact, regroup resume, etc.)
+ // - after contact is added
+ int iItem;
+ servlistpendingitem *pItem = NULL;
+
+ icq_lock l(servlistMutex);
+
+ if ((iItem = servlistPendingFindItem(ITEM_PENDING_CONTACT, hContact, NULL)) != -1)
+ pItem = servlistPendingList[iItem];
+
+ if (pItem)
+ {
+ int iOperation = pItem->operationsCount++;
+
+ pItem->operations = (servlistpendingoperation*)SAFE_REALLOC(pItem->operations, pItem->operationsCount * sizeof(servlistpendingoperation));
+ pItem->operations[iOperation].param = param;
+ pItem->operations[iOperation].callback = (PENDING_GROUP_CALLBACK)callback;
+ pItem->operations[iOperation].flags = flags;
+ }
+ else
+ {
+ NetLog_Server("Server-List Error: Trying to add pending operation to a non existing contact.");
+ }
+}
+
+
+void CIcqProto::servlistPendingAddGroupOperation(const char *pszGroup, LPARAM param, PENDING_GROUP_CALLBACK callback, DWORD flags)
+{ // add postponed operation - after group is added
+ int iItem;
+ servlistpendingitem *pItem = NULL;
+
+ icq_lock l(servlistMutex);
+
+ if ((iItem = servlistPendingFindItem(ITEM_PENDING_GROUP, NULL, pszGroup)) != -1)
+ pItem = servlistPendingList[iItem];
+
+ if (pItem)
+ {
+ int iOperation = pItem->operationsCount++;
+
+ pItem->operations = (servlistpendingoperation*)SAFE_REALLOC(pItem->operations, pItem->operationsCount * sizeof(servlistpendingoperation));
+ pItem->operations[iOperation].param = param;
+ pItem->operations[iOperation].callback = callback;
+ pItem->operations[iOperation].flags = flags;
+ }
+ else
+ {
+ NetLog_Server("Server-List Error: Trying to add pending operation to a non existing group.");
+ }
+}
+
+
+int CIcqProto::servlistPendingAddContact(HANDLE hContact, WORD wContactID, WORD wGroupID, LPARAM param, PENDING_CONTACT_CALLBACK callback, int bDoInline, LPARAM operationParam, PENDING_CONTACT_CALLBACK operationCallback)
+{
+ int iItem;
+ servlistpendingitem *pItem = NULL;
+
+ servlistMutex->Enter();
+
+ if ((iItem = servlistPendingFindItem(ITEM_PENDING_CONTACT, hContact, NULL)) != -1)
+ pItem = servlistPendingList[iItem];
+
+ if (pItem)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Pending contact %x already in list; adding as operation.", hContact);
+#endif
+ servlistPendingAddContactOperation(hContact, param, callback, SPOF_AUTO_CREATE_ITEM);
+
+ if (operationCallback)
+ servlistPendingAddContactOperation(hContact, operationParam, operationCallback, 0);
+
+ servlistMutex->Leave();
+
+ return 0; // Pending
+ }
+
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Starting contact %x operation.", hContact);
+#endif
+
+ pItem = (servlistpendingitem *)SAFE_MALLOC(sizeof(servlistpendingitem));
+ pItem->nType = ITEM_PENDING_CONTACT;
+ pItem->hContact = hContact;
+ pItem->wContactID = wContactID;
+ pItem->wGroupID = wGroupID;
+
+ servlistPendingAddItem(pItem);
+
+ if (operationCallback)
+ servlistPendingAddContactOperation(hContact, operationParam, operationCallback, 0);
+
+ servlistMutex->Leave();
+
+ if (bDoInline)
+ { // not postponed, called directly if requested
+ (this->*callback)(hContact, wContactID, wGroupID, param, PENDING_RESULT_INLINE);
+ }
+
+ return 1; // Ready
+}
+
+
+int CIcqProto::servlistPendingAddGroup(const char *pszGroup, WORD wGroupID, LPARAM param, PENDING_GROUP_CALLBACK callback, int bDoInline, LPARAM operationParam, PENDING_GROUP_CALLBACK operationCallback)
+{
+ int iItem;
+ servlistpendingitem *pItem = NULL;
+
+ servlistMutex->Enter();
+
+ if ((iItem = servlistPendingFindItem(ITEM_PENDING_GROUP, NULL, pszGroup)) != -1)
+ pItem = servlistPendingList[iItem];
+
+ if (pItem)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Pending group \"%s\" already in list; adding as operation.", pszGroup);
+#endif
+ servlistPendingAddGroupOperation(pszGroup, param, callback, SPOF_AUTO_CREATE_ITEM);
+
+ if (operationCallback)
+ servlistPendingAddGroupOperation(pszGroup, operationParam, operationCallback, 0);
+
+ servlistMutex->Leave();
+
+ return 0; // Pending
+ }
+
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Starting group \"%s\" operation.", pszGroup);
+#endif
+
+ pItem = (servlistpendingitem *)SAFE_MALLOC(sizeof(servlistpendingitem));
+ pItem->nType = ITEM_PENDING_GROUP;
+ pItem->szGroup = null_strdup(pszGroup);
+ pItem->wGroupID = wGroupID;
+
+ servlistPendingAddItem(pItem);
+
+ if (operationCallback)
+ servlistPendingAddGroupOperation(pszGroup, operationParam, operationCallback, 0);
+
+ servlistMutex->Leave();
+
+ if (bDoInline)
+ { // not postponed, called directly if requested
+ (this->*callback)(pszGroup, wGroupID, param, PENDING_RESULT_INLINE);
+ }
+
+ return 1; // Ready
+}
+
+
+void CIcqProto::servlistPendingRemoveContact(HANDLE hContact, WORD wContactID, WORD wGroupID, int nResult)
+{
+#ifdef _DEBUG
+ NetLog_Server("Server-List: %s contact %x operation.", (nResult != PENDING_RESULT_PURGE) ? "Ending" : "Purging", hContact);
+#endif
+
+ servlistpendingitem *pItem = servlistPendingRemoveItem(ITEM_PENDING_CONTACT, hContact, NULL);
+
+ if (pItem)
+ { // process pending operations
+ if (pItem->operations)
+ {
+ for (int i = 0; i < pItem->operationsCount; i++)
+ {
+ int nCallbackState = (this->*(PENDING_CONTACT_CALLBACK)(pItem->operations[i].callback))(hContact, wContactID, wGroupID, pItem->operations[i].param, nResult);
+
+ if (nResult != PENDING_RESULT_PURGE && nCallbackState == CALLBACK_RESULT_POSTPONE)
+ { // any following pending operations cannot be processed now, move them to the new pending contact
+ for (int j = i + 1; j < pItem->operationsCount; j++)
+ servlistPendingAddContactOperation(hContact, pItem->operations[j].param, (PENDING_CONTACT_CALLBACK)(pItem->operations[j].callback), pItem->operations[j].flags);
+ break;
+ }
+ else if (nCallbackState == CALLBACK_RESULT_PURGE)
+ { // purge all following operations - fatal failure occured
+ nResult = PENDING_RESULT_PURGE;
+ }
+ }
+ SAFE_FREE((void**)&pItem->operations);
+ }
+ // release item's memory
+ SAFE_FREE((void**)&pItem);
+ }
+ else
+ NetLog_Server("Server-List Error: Trying to remove a non existing pending contact.");
+}
+
+
+void CIcqProto::servlistPendingRemoveGroup(const char *pszGroup, WORD wGroupID, int nResult)
+{
+#ifdef _DEBUG
+ NetLog_Server("Server-List: %s group \"%s\" operation.", (nResult != PENDING_RESULT_PURGE) ? "Ending" : "Purging", pszGroup);
+#endif
+
+ servlistpendingitem *pItem = servlistPendingRemoveItem(ITEM_PENDING_GROUP, NULL, pszGroup);
+
+ if (pItem)
+ { // process pending operations
+ if (pItem->operations)
+ {
+ for (int i = 0; i < pItem->operationsCount; i++)
+ {
+ int nCallbackState = (this->*pItem->operations[i].callback)(pItem->szGroup, wGroupID, pItem->operations[i].param, nResult);
+
+ if (nResult != PENDING_RESULT_PURGE && nCallbackState == CALLBACK_RESULT_POSTPONE)
+ { // any following pending operations cannot be processed now, move them to the new pending group
+ for (int j = i + 1; j < pItem->operationsCount; j++)
+ servlistPendingAddGroupOperation(pItem->szGroup, pItem->operations[j].param, pItem->operations[j].callback, pItem->operations[j].flags);
+ break;
+ }
+ else if (nCallbackState == CALLBACK_RESULT_PURGE)
+ { // purge all following operations - fatal failure occured
+ nResult = PENDING_RESULT_PURGE;
+ }
+ }
+ SAFE_FREE((void**)&pItem->operations);
+ }
+ // release item's memory
+ SAFE_FREE((void**)&pItem->szGroup);
+ SAFE_FREE((void**)&pItem);
+ }
+ else
+ NetLog_Server("Server-List Error: Trying to remove a non existing pending group.");
+}
+
+
+// Remove All pending operations
+void CIcqProto::servlistPendingFlushOperations()
+{
+ icq_lock l(servlistMutex);
+
+ for (int i = servlistPendingCount; i; i--)
+ { // purge all items
+ servlistpendingitem *pItem = servlistPendingList[i - 1];
+
+ if (pItem->nType == ITEM_PENDING_CONTACT)
+ servlistPendingRemoveContact(pItem->hContact, 0, 0, PENDING_RESULT_PURGE);
+ else if (pItem->nType == ITEM_PENDING_GROUP)
+ servlistPendingRemoveGroup(pItem->szGroup, 0, PENDING_RESULT_PURGE);
+ }
+ // release the list completely
+ SAFE_FREE((void**)&servlistPendingList);
+ servlistPendingCount = 0;
+ servlistPendingSize = 0;
+}
+
+// END OF SERVER-LIST PENDING OPERATIONS
+////
+
+
+// used for adding new contacts to list - sync with visible items
+void CIcqProto::AddJustAddedContact(HANDLE hContact)
+{
+ icq_lock l(servlistMutex);
+
+ if (nJustAddedCount >= nJustAddedSize)
+ {
+ nJustAddedSize += 10;
+ pdwJustAddedList = (HANDLE*)SAFE_REALLOC(pdwJustAddedList, nJustAddedSize * sizeof(HANDLE));
+ }
+
+ pdwJustAddedList[nJustAddedCount] = hContact;
+ nJustAddedCount++;
+}
+
+
+// was the contact added during this serv-list load
+BOOL CIcqProto::IsContactJustAdded(HANDLE hContact)
+{
+ icq_lock l(servlistMutex);
+
+ if (pdwJustAddedList)
+ {
+ for (int i = 0; i<nJustAddedCount; i++)
+ {
+ if (pdwJustAddedList[i] == hContact)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+void CIcqProto::FlushJustAddedContacts()
+{
+ icq_lock l(servlistMutex);
+
+ SAFE_FREE((void**)&pdwJustAddedList);
+ nJustAddedSize = 0;
+ nJustAddedCount = 0;
+}
+
+
+// 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 CIcqProto::ReserveServerID(WORD wID, int bGroupType, int bFlags)
+{
+ servlistMutex->Enter();
+ if (nServerIDListCount >= nServerIDListSize)
+ {
+ nServerIDListSize += 100;
+ pdwServerIDList = (DWORD*)SAFE_REALLOC(pdwServerIDList, nServerIDListSize * sizeof(DWORD));
+ }
+
+ pdwServerIDList[nServerIDListCount] = wID | (bGroupType & 0x00FF0000) | (bFlags & 0xFF000000);
+ nServerIDListCount++;
+ servlistMutex->Leave();
+
+ if (!bIsSyncingCL)
+ StoreServerIDs();
+}
+
+
+// Remove a server ID from the list of reserved IDs.
+// Used for deleting contacts and other modifications.
+void CIcqProto::FreeServerID(WORD wID, int bGroupType)
+{
+ DWORD dwId = wID | (bGroupType & 0x00FF0000);
+
+ icq_lock l(servlistMutex);
+
+ if (pdwServerIDList)
+ {
+ for (int i = 0; i<nServerIDListCount; i++)
+ {
+ if ((pdwServerIDList[i] & 0x00FFFFFF) == dwId)
+ { // we found it, so remove
+ for (int j = i+1; j<nServerIDListCount; j++)
+ pdwServerIDList[j-1] = pdwServerIDList[j];
+
+ nServerIDListCount--;
+ }
+ }
+ }
+}
+
+
+// Returns true if dwID is reserved
+BOOL CIcqProto::CheckServerID(WORD wID, unsigned int wCount)
+{
+ icq_lock l(servlistMutex);
+
+ if (pdwServerIDList)
+ {
+ for (int i = 0; i<nServerIDListCount; i++)
+ {
+ if (((pdwServerIDList[i] & 0xFFFF) >= wID) && ((pdwServerIDList[i] & 0xFFFF) <= wID + wCount))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void CIcqProto::FlushServerIDs()
+{
+ icq_lock l(servlistMutex);
+
+ SAFE_FREE((void**)&pdwServerIDList);
+ nServerIDListCount = 0;
+ nServerIDListSize = 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct GroupReserveIdsEnumParam
+{
+ CIcqProto *ppro;
+ char *szModule;
+};
+
+static int GroupReserveIdsEnumProc(const char *szSetting,LPARAM lParam)
+{
+ if (szSetting && strlennull(szSetting)<5)
+ {
+ // it is probably server group
+ GroupReserveIdsEnumParam *param = (GroupReserveIdsEnumParam*)lParam;
+ char val[MAX_PATH+2]; // dummy
+
+ DBVARIANT dbv = {DBVT_DELETED};
+ dbv.type = DBVT_ASCIIZ;
+ dbv.pszVal = val;
+ dbv.cchVal = MAX_PATH;
+
+ DBCONTACTGETSETTING cgs;
+ cgs.szModule = param->szModule;
+ 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;
+ }
+ param->ppro->ReserveServerID((WORD)strtoul(szSetting, NULL, 0x10), SSIT_GROUP, 0);
+#ifdef _DEBUG
+ param->ppro->NetLog_Server("Loaded group %u:'%s'", strtoul(szSetting, NULL, 0x10), val);
+#endif
+ }
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Load all known server IDs from DB to list
+void CIcqProto::LoadServerIDs()
+{
+ WORD wSrvID;
+ int nGroups = 0, nContacts = 0, nPermits = 0, nDenys = 0, nIgnores = 0, nUnhandled = 0;
+
+ servlistMutex->Enter();
+ if (wSrvID = getSettingWord(NULL, DBSETTING_SERVLIST_AVATAR, 0))
+ ReserveServerID(wSrvID, SSIT_ITEM, 0);
+ if (wSrvID = getSettingWord(NULL, DBSETTING_SERVLIST_PHOTO, 0))
+ ReserveServerID(wSrvID, SSIT_ITEM, 0);
+ if (wSrvID = getSettingWord(NULL, DBSETTING_SERVLIST_PRIVACY, 0))
+ ReserveServerID(wSrvID, SSIT_ITEM, 0);
+ if (wSrvID = getSettingWord(NULL, DBSETTING_SERVLIST_METAINFO, 0))
+ ReserveServerID(wSrvID, SSIT_ITEM, 0);
+ if (wSrvID = getSettingWord(NULL, "SrvImportID", 0))
+ ReserveServerID(wSrvID, SSIT_ITEM, 0);
+
+ DBCONTACTENUMSETTINGS dbces;
+ int nStart = nServerIDListCount;
+
+ char szModule[MAX_PATH];
+ null_snprintf(szModule, SIZEOF(szModule), "%sSrvGroups", m_szModuleName);
+
+ GroupReserveIdsEnumParam param = { this, szModule };
+ dbces.pfnEnumProc = &GroupReserveIdsEnumProc;
+ dbces.szModule = szModule;
+ dbces.lParam = (LPARAM)&param;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces);
+
+ nGroups = nServerIDListCount - nStart;
+
+ HANDLE hContact = FindFirstContact();
+
+ while (hContact)
+ { // search all our contacts, reserve their server IDs
+ if (wSrvID = getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0))
+ {
+ ReserveServerID(wSrvID, SSIT_ITEM, 0);
+ nContacts++;
+ }
+ if (wSrvID = getSettingWord(hContact, DBSETTING_SERVLIST_DENY, 0))
+ {
+ ReserveServerID(wSrvID, SSIT_ITEM, 0);
+ nDenys++;
+ }
+ if (wSrvID = getSettingWord(hContact, DBSETTING_SERVLIST_PERMIT, 0))
+ {
+ ReserveServerID(wSrvID, SSIT_ITEM, 0);
+ nPermits++;
+ }
+ if (wSrvID = getSettingWord(hContact, DBSETTING_SERVLIST_IGNORE, 0))
+ {
+ ReserveServerID(wSrvID, SSIT_ITEM, 0);
+ nIgnores++;
+ }
+
+ hContact = FindNextContact(hContact);
+ }
+ servlistMutex->Leave();
+
+ DBVARIANT dbv = {0};
+ if (!getSetting(NULL, DBSETTING_SERVLIST_UNHANDLED, &dbv))
+ {
+ int dataLen = dbv.cpbVal;
+ BYTE *pData = dbv.pbVal;
+
+ while (dataLen >= 4)
+ {
+ BYTE bGroupType;
+ BYTE bFlags;
+
+ unpackLEWord(&pData, &wSrvID);
+ unpackByte(&pData, &bGroupType);
+ unpackByte(&pData, &bFlags);
+
+ ReserveServerID(wSrvID, bGroupType, bFlags);
+ dataLen -= 4;
+ nUnhandled++;
+ }
+
+ ICQFreeVariant(&dbv);
+ }
+
+ NetLog_Server("Loaded SSI: %d contacts, %d groups, %d permit, %d deny, %d ignore, %d unknown items.", nContacts, nGroups, nPermits, nDenys, nIgnores, nUnhandled);
+}
+
+
+void CIcqProto::StoreServerIDs() /// TODO: allow delayed
+{
+ BYTE *pUnhandled = NULL;
+ int cbUnhandled = 0;
+
+ servlistMutex->Enter();
+ if (pdwServerIDList)
+ for (int i = 0; i<nServerIDListCount; i++)
+ if ((pdwServerIDList[i] & 0xFF000000) == SSIF_UNHANDLED)
+ {
+ ppackLEWord(&pUnhandled, &cbUnhandled, pdwServerIDList[i] & 0xFFFF);
+ ppackByte(&pUnhandled, &cbUnhandled, (pdwServerIDList[i] & 0x00FF0000) >> 0x10);
+ ppackByte(&pUnhandled, &cbUnhandled, (pdwServerIDList[i] & 0xFF000000) >> 0x18);
+ }
+ servlistMutex->Leave();
+
+ if (pUnhandled)
+ setSettingBlob(NULL, DBSETTING_SERVLIST_UNHANDLED, pUnhandled, cbUnhandled);
+ else
+ deleteSetting(NULL, DBSETTING_SERVLIST_UNHANDLED);
+
+ SAFE_FREE((void**)&pUnhandled);
+}
+
+
+// Generate server ID with wCount IDs free after it, for sub-groups.
+WORD CIcqProto::GenerateServerID(int bGroupType, int bFlags, 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, bGroupType, bFlags);
+
+ return wId;
+}
+
+
+/***********************************************
+*
+* --- Low-level packet sending functions ---
+*
+*/
+
+struct doubleServerItemObject
+{
+ WORD wAction;
+ icq_packet packet;
+};
+
+DWORD CIcqProto::icq_sendServerItem(DWORD dwCookie, WORD wAction, WORD wGroupId, WORD wItemId, const char *szName, BYTE *pTLVs, int nTlvLength, WORD wItemType, DWORD dwOperation, DWORD dwTimeout, void **doubleObject)
+{ // 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));
+ packFNACHeader(&packet, ICQ_LISTS_FAMILY, wAction, 0, dwCookie);
+ packWord(&packet, (WORD)nNameLen);
+ if (nNameLen)
+ packBuffer(&packet, (LPBYTE)szName, (WORD)nNameLen);
+ packWord(&packet, wGroupId);
+ packWord(&packet, wItemId);
+ packWord(&packet, wItemType);
+ packWord(&packet, wTLVlen);
+ if (wTLVlen)
+ packBuffer(&packet, pTLVs, wTLVlen);
+
+ if (!doubleObject)
+ { // Send the packet and return the cookie
+ servlistPostPacket(&packet, dwCookie, dwOperation | wAction, dwTimeout);
+ }
+ else
+ {
+ if (*doubleObject)
+ { // Send both packets and return the cookie
+ doubleServerItemObject* helper = (doubleServerItemObject*)*doubleObject;
+
+ servlistPostPacketDouble(&helper->packet, dwCookie, dwOperation | helper->wAction, dwTimeout, &packet, wAction);
+ SAFE_FREE(doubleObject);
+ }
+ else
+ { // Create helper object, return the cookie
+ doubleServerItemObject* helper = (doubleServerItemObject*)SAFE_MALLOC(sizeof(doubleServerItemObject));
+
+ if (helper)
+ {
+ helper->wAction = wAction;
+ memcpy(&helper->packet, &packet, sizeof(icq_packet));
+ *doubleObject = helper;
+ }
+ else // memory alloc failed
+ return 0;
+ }
+ }
+
+ // Force reload of server-list after change
+ setSettingWord(NULL, "SrvRecordCount", 0);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::icq_sendServerContact(HANDLE hContact, DWORD dwCookie, WORD wAction, WORD wGroupId, WORD wContactId, DWORD dwOperation, DWORD dwTimeout, void **doubleObject)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ icq_packet pBuffer;
+ char *szNick = NULL, *szNote = NULL;
+ BYTE *pData = NULL, *pMetaToken = NULL, *pMetaTime = NULL;
+ int nNickLen, nNoteLen, nDataLen = 0, nMetaTokenLen = 0, nMetaTimeLen = 0;
+ WORD wTLVlen;
+ BYTE bAuth;
+ int bDataTooLong = FALSE;
+
+ // Prepare UID
+ if (getContactUid(hContact, &dwUin, &szUid))
+ {
+ NetLog_Server("Buddy upload failed (UID missing).");
+ return 0;
+ }
+
+ bAuth = getSettingByte(hContact, "Auth", 0);
+ szNick = getSettingStringUtf(hContact, "CList", "MyHandle", NULL);
+ szNote = getSettingStringUtf(hContact, "UserInfo", "MyNotes", NULL);
+
+ DBVARIANT dbv;
+
+ if (!getSetting(hContact, DBSETTING_METAINFO_TOKEN, &dbv))
+ {
+ nMetaTokenLen = dbv.cpbVal;
+ pMetaToken = (BYTE*)_alloca(dbv.cpbVal);
+ memcpy(pMetaToken, dbv.pbVal, dbv.cpbVal);
+
+ ICQFreeVariant(&dbv);
+ }
+ if (!getSetting(hContact, DBSETTING_METAINFO_TIME, &dbv))
+ {
+ nMetaTimeLen = dbv.cpbVal;
+ pMetaTime = (BYTE*)_alloca(dbv.cpbVal);
+ for (int i = 0; i < dbv.cpbVal; i++)
+ pMetaTime[i] = dbv.pbVal[dbv.cpbVal - i - 1];
+
+ ICQFreeVariant(&dbv);
+ }
+
+ if (!getSetting(hContact, DBSETTING_SERVLIST_DATA, &dbv))
+ { // read additional server item data
+ nDataLen = dbv.cpbVal;
+ pData = (BYTE*)_alloca(nDataLen);
+ memcpy(pData, dbv.pbVal, nDataLen);
+
+ ICQFreeVariant(&dbv);
+ }
+
+ 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, LPGEN("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 + (nMetaTokenLen?4+nMetaTokenLen:0) + (nMetaTimeLen?4+nMetaTimeLen:0);
+
+ // 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, (LPBYTE)szNick); // Nickname TLV
+
+ if (nNoteLen)
+ packTLV(&pBuffer, SSI_TLV_COMMENT, (WORD)nNoteLen, (LPBYTE)szNote); // Comment TLV
+
+ if (nMetaTokenLen)
+ packTLV(&pBuffer, SSI_TLV_METAINFO_TOKEN, (WORD)nMetaTokenLen, pMetaToken);
+
+ if (nMetaTimeLen)
+ packTLV(&pBuffer, SSI_TLV_METAINFO_TIME, (WORD)nMetaTimeLen, pMetaTime);
+
+ 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((void**)&szNick);
+ SAFE_FREE((void**)&szNote);
+
+ return icq_sendServerItem(dwCookie, wAction, wGroupId, wContactId, strUID(dwUin, szUid), pBuffer.pData, wTLVlen, SSI_ITEM_BUDDY, dwOperation, dwTimeout, doubleObject);
+}
+
+
+DWORD CIcqProto::icq_sendSimpleItem(DWORD dwCookie, WORD wAction, DWORD dwUin, char* szUID, WORD wGroupId, WORD wItemId, WORD wItemType, DWORD dwOperation, DWORD dwTimeout)
+{ // for privacy items
+ return icq_sendServerItem(dwCookie, wAction, wGroupId, wItemId, strUID(dwUin, szUID), NULL, 0, wItemType, dwOperation, dwTimeout, NULL);
+}
+
+
+DWORD CIcqProto::icq_sendServerGroup(DWORD dwCookie, WORD wAction, WORD wGroupId, const char *szName, void *pContent, int cbContent, DWORD dwOperationFlags)
+{
+ 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, (LPBYTE)pContent); // Groups TLV
+
+ return icq_sendServerItem(dwCookie, wAction, wGroupId, 0, szName, pBuffer.pData, wTLVlen, SSI_ITEM_GROUP, SSOP_GROUP_ACTION | dwOperationFlags, 400, NULL);
+}
+
+
+DWORD CIcqProto::icq_modifyServerPrivacyItem(HANDLE hContact, DWORD dwUin, char *szUid, WORD wAction, DWORD dwOperation, WORD wItemId, WORD wType)
+{
+ cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ DWORD dwCookie;
+
+ if (ack)
+ {
+ ack->dwAction = dwOperation; // remove privacy item
+ ack->hContact = hContact;
+ ack->wContactId = wItemId;
+
+ dwCookie = AllocateCookie(CKT_SERVERLIST, wAction, hContact, ack);
+ }
+ else // cookie failed
+ return 0;
+
+ return icq_sendSimpleItem(dwCookie, wAction, dwUin, szUid, 0, wItemId, wType, SSOP_ITEM_ACTION, 400);
+}
+
+
+DWORD CIcqProto::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 CIcqProto::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 ---
+*
+*/
+
+
+/// TODO: do not check by plugin version, check by ServListStructures version!
+int CIcqProto::IsServerGroupsDefined()
+{
+ int iRes = 1;
+
+ if (getSettingDword(NULL, "Version", 0) < 0x00030608)
+ { // group cache & linking data too old, flush, reload from server
+ char szModule[MAX_PATH];
+
+ // flush obsolete linking data
+ null_snprintf(szModule, SIZEOF(szModule), "%sGroups", m_szModuleName);
+ CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)szModule);
+
+ iRes = 0; // no groups defined, or older version
+ }
+ // store our current version
+ setSettingDword(NULL, "Version", ICQ_PLUG_VERSION & 0x00FFFFFF);
+
+ return iRes;
+}
+
+
+void CIcqProto::FlushSrvGroupsCache()
+{
+ char szModule[MAX_PATH];
+
+ null_snprintf(szModule, SIZEOF(szModule), "%sSrvGroups", m_szModuleName);
+ CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)szModule);
+}
+
+
+// Look thru DB and collect all ContactIDs from a group
+void* CIcqProto::collectBuddyGroup(WORD wGroupID, int *count)
+{
+ WORD* buf = NULL;
+ int cnt = 0;
+ HANDLE hContact;
+ WORD wItemID;
+
+ hContact = FindFirstContact();
+
+ while (hContact)
+ { // search all contacts
+ if (wGroupID == getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0))
+ { // add only buddys from specified group
+ wItemID = getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0);
+
+ if (wItemID)
+ { // valid ID, add
+ cnt++;
+ buf = (WORD*)SAFE_REALLOC(buf, cnt*sizeof(WORD));
+ buf[cnt-1] = wItemID;
+ if (!count) break;
+ }
+ }
+
+ hContact = FindNextContact(hContact);
+ }
+
+ if (count)
+ *count = cnt<<1; // we return size in bytes
+ return buf;
+}
+
+
+// Look thru DB and collect all GroupIDs
+void* CIcqProto::collectGroups(int *count)
+{
+ WORD* buf = NULL;
+ int cnt = 0;
+ int i;
+ HANDLE hContact;
+ WORD wGroupID;
+
+ hContact = FindFirstContact();
+
+ while (hContact)
+ { // search all contacts
+ if (wGroupID = getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 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 = FindNextContact(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 CIcqProto::removeGroupPathLinks(WORD wGroupID)
+{ // remove miranda grouppath links targeting to this groupid
+ DBCONTACTENUMSETTINGS dbces;
+ char szModule[MAX_PATH];
+ char* pars[3];
+
+ null_snprintf(szModule, SIZEOF(szModule), "%sGroups", m_szModuleName);
+
+ 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((void**)&list[1]);
+ bet = list;
+ list = (char**)list[0];
+ SAFE_FREE((void**)&bet);
+ }
+ }
+}
+
+
+char *CIcqProto::getServListGroupName(WORD wGroupID)
+{
+ char szModule[MAX_PATH];
+ char szGroup[16];
+
+ if (!wGroupID)
+ {
+ NetLog_Server("Warning: Cannot get group name (Group ID missing)!");
+ return NULL;
+ }
+
+ null_snprintf(szModule, SIZEOF(szModule), "%sSrvGroups", m_szModuleName);
+ _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 getSettingStringUtf(NULL, szModule, szGroup, NULL);
+}
+
+
+void CIcqProto::setServListGroupName(WORD wGroupID, const char *szGroupName)
+{
+ char szModule[MAX_PATH];
+ char szGroup[16];
+
+ if (!wGroupID)
+ {
+ NetLog_Server("Warning: Cannot set group name (Group ID missing)!");
+ return;
+ }
+
+ null_snprintf(szModule, SIZEOF(szModule), "%sSrvGroups", m_szModuleName);
+ _itoa(wGroupID, szGroup, 0x10);
+
+ if (szGroupName)
+ setSettingStringUtf(NULL, szModule, szGroup, szGroupName);
+ else
+ {
+ DBDeleteContactSetting(NULL, szModule, szGroup);
+ removeGroupPathLinks(wGroupID);
+ }
+ return;
+}
+
+
+WORD CIcqProto::getServListGroupLinkID(const char *szPath)
+{
+ char szModule[MAX_PATH];
+ WORD wGroupId;
+
+ null_snprintf(szModule, SIZEOF(szModule), "%sGroups", m_szModuleName);
+
+ 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 CIcqProto::setServListGroupLinkID(const char *szPath, WORD wGroupID)
+{
+ char szModule[MAX_PATH];
+
+ null_snprintf(szModule, SIZEOF(szModule), "%sGroups", m_szModuleName);
+
+ if (wGroupID)
+ DBWriteContactSettingWord(NULL, szModule, szPath, wGroupID);
+ else
+ DBDeleteContactSetting(NULL, szModule, szPath);
+}
+
+
+// this function takes all backslashes in szGroup as group-level separators
+int CIcqProto::getCListGroupHandle(const char *szGroup)
+{
+ char *pszGroup = (char*)szGroup;
+ int hParentGroup = 0, hGroup = 0;
+
+ if (!strlennull(szGroup)) return 0; // no group
+
+ if (strrchr(szGroup, '\\'))
+ { // create parent group
+ char *szSeparator = (char*)strrchr(szGroup, '\\');
+
+ *szSeparator = '\0';
+ hParentGroup = getCListGroupHandle(szGroup);
+ *szSeparator = '\\';
+ // take only sub-group name
+ pszGroup = ++szSeparator;
+ }
+
+ int size = strlennull(szGroup) + 2;
+ TCHAR *tszGroup = (TCHAR*)_alloca(size * sizeof(TCHAR));
+
+ if (utf8_to_tchar_static(pszGroup, tszGroup, size))
+ hGroup = CallService(MS_CLIST_GROUPCREATE, hParentGroup, (LPARAM)tszGroup); // 0.7+
+
+#ifdef _DEBUG
+ NetLog_Server("Obtained CList group \"%s\" handle %x", szGroup, hGroup);
+#endif
+
+ return hGroup;
+}
+
+
+// determine if the specified clist group path exists
+//!! this function is not thread-safe due to the use of cli->pfnGetGroupName()
+int CIcqProto::getCListGroupExists(const char *szGroup)
+{
+ int hGroup = 0;
+ CLIST_INTERFACE *clint = NULL;
+
+ if (!szGroup) return 0;
+
+ if (ServiceExists(MS_CLIST_RETRIEVE_INTERFACE))
+ clint = (CLIST_INTERFACE*)CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, 0);
+
+ if (clint && clint->version >= 1)
+ { // we've got clist interface, use it
+ int size = strlennull(szGroup) + 2;
+ TCHAR *tszGroup = (TCHAR*)_alloca(size * sizeof(TCHAR));
+
+ if (utf8_to_tchar_static(szGroup, tszGroup, size))
+ for (int i = 1; TRUE; i++)
+ {
+ TCHAR *tszGroupName = (TCHAR*)clint->pfnGetGroupName(i, NULL);
+
+ if (!tszGroupName) break;
+
+ if (!_tcscmp(tszGroup, tszGroupName))
+ { // we have found the group
+ hGroup = i;
+ break;
+ }
+ }
+ }
+ else
+ { // old ansi version - no other way
+ int size = strlennull(szGroup) + 2;
+ char *aszGroup = (char*)_alloca(size);
+
+ utf8_decode_static(szGroup, aszGroup, size);
+
+ for (int i = 1; TRUE; i++)
+ {
+ char *paszGroup = (char*)CallService(MS_CLIST_GROUPGETNAME, i, 0);
+
+ if (!paszGroup) break;
+
+ if (!strcmpnull(aszGroup, paszGroup))
+ { // we found the group
+ hGroup = i;
+ break;
+ }
+ }
+ }
+
+ return hGroup;
+}
+
+
+int CIcqProto::moveContactToCListGroup(HANDLE hContact, const char *szGroup)
+{
+ int hGroup = getCListGroupHandle(szGroup);
+
+ if (ServiceExists(MS_CLIST_CONTACTCHANGEGROUP))
+ return CallService(MS_CLIST_CONTACTCHANGEGROUP, (WPARAM)hContact, hGroup);
+ else /// TODO: is this neccessary ?
+ return setSettingStringUtf(hContact, "CList", "Group", szGroup);
+}
+
+
+// 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;
+}
+
+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 CIcqProto::getServListGroupLevel(WORD wGroupId)
+{
+ char *szGroupName = getServListGroupName(wGroupId);
+ int cnt = -1;
+
+ if (szGroupName)
+ { // groupid is valid count group name level
+ if (m_bSsiSimpleGroups)
+ cnt = countCListGroupLevel(szGroupName);
+ else
+ cnt = countGroupNameLevel(szGroupName);
+
+ SAFE_FREE((void**)&szGroupName);
+ }
+
+ return cnt;
+}
+
+
+// demangle group path
+char *CIcqProto::getServListGroupCListPath(WORD wGroupId)
+{
+ char *szGroup = NULL;
+
+ if (szGroup = getServListGroupName(wGroupId))
+ { // this groupid is valid
+ if (!m_bSsiSimpleGroups)
+ while (strstrnull(szGroup, "\\")) *strstrnull(szGroup, "\\") = '_'; // remove invalid char
+
+ if (getServListGroupLinkID(szGroup) == wGroupId)
+ { // this grouppath is known and is for this group, set user group
+ return szGroup;
+ }
+ else if (m_bSsiSimpleGroups)
+ { // with simple groups it is mapped 1:1, give real serv-list group name
+ setServListGroupLinkID(szGroup, wGroupId);
+ return szGroup;
+ }
+ else
+ { // advanced groups, determine group level
+ int nGroupLevel = getServListGroupLevel(wGroupId);
+
+ if (nGroupLevel > 0)
+ { // it is probably a sub-group locate parent group
+ WORD wParentGroupId = wGroupId;
+ int nParentGroupLevel;
+
+ do
+ { // we look for parent group at the correct level
+ wParentGroupId--;
+ nParentGroupLevel = getServListGroupLevel(wParentGroupId);
+ } while ((nParentGroupLevel >= nGroupLevel) && (nParentGroupLevel != -1));
+
+ if (nParentGroupLevel == -1)
+ { // that was not a sub-group, it was just a group starting with >
+ setServListGroupLinkID(szGroup, wGroupId);
+ return szGroup;
+ }
+
+ { // recursively determine parent group clist path
+ char *szParentGroup = getServListGroupCListPath(wParentGroupId);
+
+ /// FIXME: properly handle ~N suffixes
+ szParentGroup = (char*)SAFE_REALLOC(szParentGroup, strlennull(szGroup) + strlennull(szParentGroup) + 2);
+ strcat(szParentGroup, "\\");
+ strcat(szParentGroup, (char*)szGroup + nGroupLevel);
+ /* if (strstrnull(szGroup, "~"))
+ { // check if the ~ was not added to obtain unique servlist item name
+ char *szUniqueMark = strrchr(szParentGroup, '~');
+
+ *szUniqueMark = '\0';
+ // not the same group without ~, return it
+ if (getServListGroupLinkID(szParentGroup) != wGroupId)
+ *szUniqueMark = '~';
+ } */ /// FIXME: this is necessary, but needs group loading changes
+ SAFE_FREE((void**)&szGroup);
+ szGroup = szParentGroup;
+
+
+ if (getServListGroupLinkID(szGroup) == wGroupId)
+ { // known path, give
+ return szGroup;
+ }
+ else
+ { // unknown path, setup a link
+ setServListGroupLinkID(szGroup, wGroupId);
+ return szGroup;
+ }
+ }
+ }
+ else
+ { // normal group, setup a link
+ setServListGroupLinkID(szGroup, wGroupId);
+ return szGroup;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+static int SrvGroupNamesEnumProc(const char *szSetting, LPARAM lParam)
+{ // check server-group cache item
+ const char **params = (const char**)lParam;
+ CIcqProto *ppro = (CIcqProto*)params[0];
+ char *szGroupName = ppro->getSettingStringUtf(NULL, params[3], szSetting, NULL);
+
+ if (!strcmpnull(szGroupName, params[2]))
+ params[1] = szSetting; // do not need the real value, just arbitrary non-NULL
+
+ SAFE_FREE(&szGroupName);
+ return 0;
+}
+
+char* CIcqProto::getServListUniqueGroupName(const char *szGroupName, int bAlloced)
+{ // enum ICQSrvGroups and create unique name if neccessary
+ DBCONTACTENUMSETTINGS dbces;
+ char szModule[MAX_PATH];
+ char *pars[4];
+ int uniqueID = 1;
+ char *szGroupNameBase = (char*)szGroupName;
+ char *szNewGroupName = NULL;
+
+ if (!bAlloced)
+ szGroupNameBase = null_strdup(szGroupName);
+ null_strcut(szGroupNameBase, m_wServerListRecordNameMaxLength);
+
+ null_snprintf(szModule, SIZEOF(szModule), "%sSrvGroups", m_szModuleName);
+
+ do {
+ pars[0] = (char*)this;
+ pars[1] = NULL;
+ pars[2] = szNewGroupName ? szNewGroupName : szGroupNameBase;
+ pars[3] = szModule;
+
+ dbces.pfnEnumProc = &SrvGroupNamesEnumProc;
+ dbces.szModule = szModule;
+ dbces.lParam = (LPARAM)pars;
+
+ CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces);
+
+ if (pars[1])
+ { // the groupname already exists, create another
+ SAFE_FREE((void**)&szNewGroupName);
+
+ char szUnique[10];
+ _itoa(uniqueID++, szUnique, 10);
+ null_strcut(szGroupNameBase, m_wServerListRecordNameMaxLength - strlennull(szUnique) - 1);
+ szNewGroupName = (char*)SAFE_MALLOC(strlennull(szUnique) + strlennull(szGroupNameBase) + 2);
+ if (szNewGroupName)
+ {
+ strcpy(szNewGroupName, szGroupNameBase);
+ strcat(szNewGroupName, "~");
+ strcat(szNewGroupName, szUnique);
+ }
+ }
+ } while (pars[1] && szNewGroupName);
+
+ if (szNewGroupName)
+ {
+ SAFE_FREE(&szGroupNameBase);
+ return szNewGroupName;
+ }
+ if (szGroupName != szGroupNameBase)
+ {
+ SAFE_FREE(&szGroupNameBase);
+ return (char*)szGroupName;
+ }
+ else
+ return szGroupNameBase;
+}
+
+
+// this is the second part of recursive event-driven procedure
+int CIcqProto::servlistCreateGroup_gotParentGroup(const char *szGroup, WORD wGroupID, LPARAM param, int nResult)
+{
+ cookie_servlist_action* clue = (cookie_servlist_action*)param;
+ char *szSubGroupName = clue->szGroupName;
+ char *szSubGroup;
+ int wSubGroupLevel = -1;
+ WORD wSubGroupID;
+
+ SAFE_FREE((void**)&clue);
+
+ if (nResult == PENDING_RESULT_PURGE)
+ { // only cleanup
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ szSubGroup = (char*)SAFE_MALLOC(strlennull(szGroup) + strlennull(szSubGroupName) + 2);
+ if (szSubGroup)
+ {
+ strcpy(szSubGroup, szGroup);
+ strcat(szSubGroup, "\\");
+ strcat(szSubGroup, szSubGroupName);
+ }
+
+ if (nResult == PENDING_RESULT_SUCCESS) // if we got an id count level
+ wSubGroupLevel = getServListGroupLevel(wGroupID);
+
+ if (wSubGroupLevel == -1)
+ { // something went wrong, give the id and go away
+ servlistPendingRemoveGroup(szSubGroup, wGroupID, PENDING_RESULT_FAILED);
+
+ SAFE_FREE((void**)&szSubGroupName);
+ SAFE_FREE((void**)&szSubGroup);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+ wSubGroupLevel++; // we are a sub-group
+ wSubGroupID = wGroupID + 1;
+
+ // check if on that id is not group of the same or greater level, if yes, try next
+ while (CheckServerID(wSubGroupID, 0) && (getServListGroupLevel(wSubGroupID) >= wSubGroupLevel))
+ {
+ wSubGroupID++;
+ }
+
+ if (!CheckServerID(wSubGroupID, 0))
+ { // the next id is free, so create our group with that id
+ cookie_servlist_action *ack;
+ DWORD dwCookie;
+ char *szSubGroupItem = (char*)SAFE_MALLOC(strlennull(szSubGroupName) + wSubGroupLevel + 1);
+
+ if (szSubGroupItem)
+ {
+ int i;
+
+ for (i=0; i < wSubGroupLevel; i++)
+ szSubGroupItem[i] = '>';
+
+ strcpy(szSubGroupItem + wSubGroupLevel, szSubGroupName);
+ szSubGroupItem[strlennull(szSubGroupName) + wSubGroupLevel] = '\0';
+ SAFE_FREE((void**)&szSubGroupName);
+ // check and create unique group name (Miranda does allow more subgroups with the same name!)
+ szSubGroupItem = getServListUniqueGroupName(szSubGroupItem, TRUE);
+
+ if (ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action)))
+ { // we have cookie good, go on
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Creating sub-group \"%s\", parent group \"%s\".", szSubGroupItem, szGroup);
+#endif
+ ReserveServerID(wSubGroupID, SSIT_GROUP, 0);
+
+ ack->wGroupId = wSubGroupID;
+ ack->szGroupName = szSubGroupItem; // we need that name
+ ack->szGroup = szSubGroup;
+ ack->dwAction = SSA_GROUP_ADD;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, 0, ack);
+
+ icq_sendServerGroup(dwCookie, ICQ_LISTS_ADDTOLIST, ack->wGroupId, szSubGroupItem, NULL, 0, SSOF_BEGIN_OPERATION);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+ SAFE_FREE((void**)&szSubGroupItem);
+ }
+ }
+ // we failed to create sub-group give parent groupid
+ icq_LogMessage(LOG_ERROR, LPGEN("Failed to create the correct sub-group, the using closest parent group."));
+
+ servlistPendingRemoveGroup(szSubGroup, wGroupID, PENDING_RESULT_FAILED);
+
+ SAFE_FREE((void**)&szSubGroupName);
+ SAFE_FREE((void**)&szSubGroup);
+ return CALLBACK_RESULT_CONTINUE;
+}
+
+
+int CIcqProto::servlistCreateGroup_Ready(const char *szGroup, WORD groupID, LPARAM param, int nResult)
+{
+ WORD wGroupID = 0;
+
+ if (nResult == PENDING_RESULT_PURGE)
+ return CALLBACK_RESULT_CONTINUE;
+
+ if (wGroupID = getServListGroupLinkID(szGroup))
+ { // the path is known, continue the process
+ servlistPendingRemoveGroup(szGroup, wGroupID, PENDING_RESULT_SUCCESS);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ if (!strstrnull(szGroup, "\\") || m_bSsiSimpleGroups)
+ { // a root group can be simply created without problems; simple groups are mapped directly
+ cookie_servlist_action* ack;
+ DWORD dwCookie;
+
+ if (ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action)))
+ { // we have cookie good, go on
+#ifdef _DEBUG
+ NetLog_Server("Server-List: Creating root group \"%s\".", szGroup);
+#endif
+ ack->wGroupId = GenerateServerID(SSIT_GROUP, 0);
+ ack->szGroup = null_strdup(szGroup); // we need that name
+ // check if the groupname is unique - just to be sure, Miranda should handle that!
+ ack->szGroupName = getServListUniqueGroupName(ack->szGroup, FALSE);
+ ack->dwAction = SSA_GROUP_ADD;
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, 0, ack);
+
+ icq_sendServerGroup(dwCookie, ICQ_LISTS_ADDTOLIST, ack->wGroupId, ack->szGroup, NULL, 0, SSOF_BEGIN_OPERATION);
+
+ return CALLBACK_RESULT_POSTPONE;
+ }
+ }
+ else
+ { // this is a sub-group
+ char* szSub = null_strdup(szGroup); // create subgroup, recursive, event-driven, possibly relocate
+ cookie_servlist_action* ack;
+ char *szLast;
+
+ if (strstrnull(szSub, "\\"))
+ { // determine parent group
+ szLast = strrchr(szSub, '\\') + 1;
+
+ szLast[-1] = '\0';
+ }
+ // make parent group id
+ ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ if (ack)
+ {
+ ack->szGroupName = null_strdup(szLast); // groupname
+ servlistCreateGroup(szSub, (LPARAM)ack, &CIcqProto::servlistCreateGroup_gotParentGroup);
+ SAFE_FREE((void**)&szSub);
+
+ return CALLBACK_RESULT_POSTPONE;
+ }
+
+ SAFE_FREE((void**)&szSub);
+ }
+ servlistPendingRemoveGroup(szGroup, groupID, PENDING_RESULT_FAILED);
+
+ return CALLBACK_RESULT_CONTINUE;
+}
+
+
+// create group with this path, a bit complex task
+// this supposes that all server groups are known
+void CIcqProto::servlistCreateGroup(const char *szGroupPath, LPARAM param, PENDING_GROUP_CALLBACK callback)
+{
+ char *szGroup = (char*)szGroupPath;
+
+ if (!strlennull(szGroup)) szGroup = DEFAULT_SS_GROUP;
+
+ servlistPendingAddGroup(szGroup, 0, 0, &CIcqProto::servlistCreateGroup_Ready, TRUE, param, callback);
+}
+
+
+/*****************************************
+*
+* --- Server-List Operations ---
+*
+*/
+
+int CIcqProto::servlistAddContact_gotGroup(const char *szGroup, WORD wGroupID, LPARAM lParam, int nResult)
+{
+ cookie_servlist_action* ack = (cookie_servlist_action*)lParam;
+
+ if (ack) SAFE_FREE(&ack->szGroup);
+
+ if (nResult == PENDING_RESULT_PURGE)
+ { // only cleanup
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ if (!ack || !wGroupID) // something went wrong
+ {
+ if (ack) servlistPendingRemoveContact(ack->hContact, 0, wGroupID, PENDING_RESULT_FAILED);
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ WORD wItemID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_ID, 0);
+
+ if (wItemID) /// TODO: redundant ???
+ { // Only add the contact if it doesnt already have an ID
+ servlistPendingRemoveContact(ack->hContact, wItemID, wGroupID, PENDING_RESULT_SUCCESS);
+ NetLog_Server("Failed to add contact to server side list (%s)", "already there");
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ wItemID = GenerateServerID(SSIT_ITEM, 0);
+
+ ack->dwAction = SSA_CONTACT_ADD;
+ ack->wGroupId = wGroupID;
+ ack->wContactId = wItemID;
+
+ DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, ack->hContact, ack);
+
+ icq_sendServerContact(ack->hContact, dwCookie, ICQ_LISTS_ADDTOLIST, wGroupID, wItemID, SSOP_ITEM_ACTION | SSOF_CONTACT | SSOF_BEGIN_OPERATION, 400, NULL);
+
+ return CALLBACK_RESULT_CONTINUE;
+}
+
+
+// Need to be called when Pending Contact is active
+int CIcqProto::servlistAddContact_Ready(HANDLE hContact, WORD wContactID, WORD wGroupID, LPARAM lParam, int nResult)
+{
+ cookie_servlist_action* ack = (cookie_servlist_action*)lParam;
+
+ if (nResult == PENDING_RESULT_PURGE)
+ { // removing obsolete items, just free the memory
+ SAFE_FREE((void**)&ack->szGroup);
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ WORD wItemID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_ID, 0);
+
+ if (wItemID)
+ { // Only add the contact if it doesn't already have an ID
+ servlistPendingRemoveContact(ack->hContact, wItemID, getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0), PENDING_RESULT_SUCCESS);
+ NetLog_Server("Failed to add contact to server side list (%s)", "already there");
+ SAFE_FREE((void**)&ack->szGroup);
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ // obtain a correct groupid first
+ servlistCreateGroup(ack->szGroup, lParam, &CIcqProto::servlistAddContact_gotGroup);
+
+ return CALLBACK_RESULT_POSTPONE;
+}
+
+
+// Called when contact should be added to server list, if group does not exist, create one
+void CIcqProto::servlistAddContact(HANDLE hContact, const char *pszGroup)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ cookie_servlist_action* ack;
+
+ // Get UID
+ if (getContactUid(hContact, &dwUin, &szUid))
+ { // Could not do anything without uid
+ NetLog_Server("Failed to add contact to server side list (%s)", "no UID");
+ return;
+ }
+
+ if (!(ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action))))
+ { // Could not do anything without cookie
+ NetLog_Server("Failed to add contact to server side list (%s)", "malloc failed");
+ return;
+ }
+ else
+ {
+ ack->hContact = hContact;
+ ack->szGroup = null_strdup(pszGroup);
+ // call thru pending operations - makes sure the contact is ready to be added
+ servlistPendingAddContact(hContact, 0, 0, (LPARAM)ack, &CIcqProto::servlistAddContact_Ready, TRUE);
+ return;
+ }
+}
+
+
+int CIcqProto::servlistRemoveContact_Ready(HANDLE hContact, WORD contactID, WORD groupID, LPARAM lParam, int nResult)
+{
+ WORD wGroupID;
+ WORD wItemID;
+ cookie_servlist_action* ack = (cookie_servlist_action*)lParam;
+ DWORD dwCookie;
+
+ if (nResult == PENDING_RESULT_PURGE)
+ {
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ // Get the contact's group ID
+ if (!(wGroupID = getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0)))
+ { // Could not find a usable group ID
+ servlistPendingRemoveContact(hContact, contactID, groupID, PENDING_RESULT_FAILED);
+
+ NetLog_Server("Failed to remove contact from server side list (%s)", "no group ID");
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ // Get the contact's item ID
+ if (!(wItemID = getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0)))
+ { // Could not find usable item ID
+ servlistPendingRemoveContact(hContact, contactID, wGroupID, PENDING_RESULT_FAILED);
+
+ NetLog_Server("Failed to remove contact from server side list (%s)", "no item ID");
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ ack->dwAction = SSA_CONTACT_REMOVE;
+ ack->hContact = hContact;
+ ack->wGroupId = wGroupID;
+ ack->wContactId = wItemID;
+
+ dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, hContact, ack);
+
+ icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_REMOVEFROMLIST, wGroupID, wItemID, SSOP_ITEM_ACTION | SSOF_CONTACT | SSOF_BEGIN_OPERATION, 400, NULL);
+
+ return CALLBACK_RESULT_POSTPONE;
+}
+
+
+// Called when contact should be removed from server list, remove group if it remain empty
+void CIcqProto::servlistRemoveContact(HANDLE hContact)
+{
+ DWORD dwUin;
+ uid_str szUid;
+ cookie_servlist_action* ack;
+
+ // Get UID
+ if (getContactUid(hContact, &dwUin, &szUid))
+ {
+ // Could not do anything without uid
+ NetLog_Server("Failed to remove contact from server side list (%s)", "no UID");
+ return;
+ }
+
+ if (!(ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action))))
+ { // Could not do anything without cookie
+ NetLog_Server("Failed to remove contact from server side list (%s)", "malloc failed");
+ return;
+ }
+ else
+ {
+ ack->hContact = hContact;
+ // call thru pending operations - makes sure the contact is ready to be removed
+ servlistPendingAddContact(hContact, 0, 0, (LPARAM)ack, &CIcqProto::servlistRemoveContact_Ready, TRUE);
+ return;
+ }
+}
+
+
+int CIcqProto::servlistMoveContact_gotTargetGroup(const char *szGroup, WORD wNewGroupID, LPARAM lParam, int nResult)
+{
+ cookie_servlist_action *ack = (cookie_servlist_action*)lParam;
+
+ if (ack) SAFE_FREE(&ack->szGroup);
+
+ if (nResult == PENDING_RESULT_PURGE)
+ { // removing obsolete items, just free the memory
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ if (!ack || !wNewGroupID || !ack->hContact) // something went wrong
+ {
+ if (ack) servlistPendingRemoveContact(ack->hContact, 0, 0, PENDING_RESULT_FAILED);
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ WORD wItemID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_ID, 0);
+ WORD wGroupID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_GROUP, 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
+ return servlistAddContact_gotGroup(szGroup, wNewGroupID, lParam, nResult);
+ }
+
+ if (wGroupID == wNewGroupID)
+ { // Only move the contact if it had different GroupID
+ servlistPendingRemoveContact(ack->hContact, wItemID, wNewGroupID, PENDING_RESULT_SUCCESS);
+ NetLog_Server("Contact not moved to group on server side list (same Group)");
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ ack->szGroupName = NULL;
+ ack->dwAction = SSA_CONTACT_SET_GROUP;
+ ack->wGroupId = wGroupID;
+ ack->wContactId = wItemID;
+ ack->wNewContactId = GenerateServerID(SSIT_ITEM, 0); // icq5 recreates also this, imitate
+ ack->wNewGroupId = wNewGroupID;
+ ack->lParam = 0; // we use this as a sign
+
+ DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, ack->hContact, ack);
+ DWORD dwCookie2 = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, ack->hContact, ack);
+
+ { // imitate icq5, previously here was different order, but AOL changed and it ceased to work
+ void *doubleObject = NULL;
+
+ icq_sendServerContact(ack->hContact, dwCookie2, ICQ_LISTS_ADDTOLIST, wNewGroupID, ack->wNewContactId, SSO_CONTACT_SETGROUP | SSOF_BEGIN_OPERATION, 500, &doubleObject);
+ icq_sendServerContact(ack->hContact, dwCookie, ICQ_LISTS_REMOVEFROMLIST, wGroupID, wItemID, SSO_CONTACT_SETGROUP | SSOF_BEGIN_OPERATION, 500, &doubleObject);
+ }
+ return CALLBACK_RESULT_CONTINUE;
+}
+
+
+int CIcqProto::servlistMoveContact_Ready(HANDLE hContact, WORD contactID, WORD groupID, LPARAM lParam, int nResult)
+{
+ cookie_servlist_action *ack = (cookie_servlist_action*)lParam;
+
+ if (nResult == PENDING_RESULT_PURGE)
+ { // removing obsolete items, just free the memory
+ SAFE_FREE(&ack->szGroup);
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ WORD wItemID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_ID, 0);
+ WORD wGroupID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_GROUP, 0);
+
+ if (!wGroupID && wItemID)
+ { // Only move the contact if it had an GroupID
+ servlistPendingRemoveContact(ack->hContact, contactID, groupID, PENDING_RESULT_FAILED);
+
+ NetLog_Server("Failed to move contact to group on server side list (%s)", "no Group");
+ SAFE_FREE(&ack->szGroup);
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ // obtain a correct target groupid first
+ servlistCreateGroup(ack->szGroup, lParam, &CIcqProto::servlistMoveContact_gotTargetGroup);
+
+ return CALLBACK_RESULT_POSTPONE;
+}
+
+
+// Called when contact should be moved from one group to another, create new, remove empty
+void CIcqProto::servlistMoveContact(HANDLE hContact, const char *pszNewGroup)
+{
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (!hContact) return; // we do not move us, caused our uin was wrongly added to list
+
+ // Get UID
+ if (getContactUid(hContact, &dwUin, &szUid))
+ { // Could not do anything without uin
+ NetLog_Server("Failed to move contact to group on server side list (%s)", "no UID");
+ return;
+ }
+
+ if ((pszNewGroup != NULL) && (pszNewGroup[0]!='\0') && !getCListGroupExists(pszNewGroup))
+ { // the contact moved to non existing group, do not do anything: MetaContact hack
+ NetLog_Server("Contact not moved - probably hiding by MetaContacts.");
+ return;
+ }
+
+ if (!getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0)) /// FIXME:::: this should be in _ready
+ { // the contact is not stored on the server, check if we should try to add
+ if (!getSettingByte(NULL, "ServerAddRemove", DEFAULT_SS_ADDSERVER) ||
+ DBGetContactSettingByte(hContact, "CList", "Hidden", 0))
+ return;
+ }
+ cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+
+ if (!ack)
+ { // Could not do anything without cookie
+ NetLog_Server("Failed to add contact to server side list (%s)", "malloc failed");
+ return;
+ }
+ else
+ {
+ ack->hContact = hContact;
+ ack->szGroup = null_strdup(pszNewGroup);
+ // call thru pending operations - makes sure the contact is ready to be moved
+ servlistPendingAddContact(hContact, 0, 0, (LPARAM)ack, &CIcqProto::servlistMoveContact_Ready, TRUE);
+ return;
+ }
+}
+
+
+int CIcqProto::servlistUpdateContact_Ready(HANDLE hContact, WORD contactID, WORD groupID, LPARAM lParam, int nResult)
+{
+ cookie_servlist_action *ack = (cookie_servlist_action*)lParam;
+
+ if (nResult == PENDING_RESULT_PURGE)
+ { // removing obsolete items, just free the memory
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+ WORD wItemID;
+ WORD wGroupID;
+
+ // Get the contact's group ID
+ if (!(wGroupID = getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0)))
+ {
+ servlistPendingRemoveContact(hContact, contactID, groupID, PENDING_RESULT_FAILED);
+ // Could not find a usable group ID
+ NetLog_Server("Failed to update contact's details on server side list (%s)", "no group ID");
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ // Get the contact's item ID
+ if (!(wItemID = getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0)))
+ {
+ servlistPendingRemoveContact(hContact, contactID, wGroupID, PENDING_RESULT_FAILED);
+ // Could not find usable item ID
+ NetLog_Server("Failed to update contact's details on server side list (%s)", "no item ID");
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ ack->dwAction = SSA_CONTACT_UPDATE;
+ ack->wContactId = wItemID;
+ ack->wGroupId = wGroupID;
+ ack->hContact = hContact;
+
+ DWORD 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, SSOP_ITEM_ACTION | SSOF_CONTACT, 400, NULL);
+
+ return CALLBACK_RESULT_POSTPONE;
+}
+
+
+// Is called when a contact' details has been changed locally to update
+// the server side details.
+void CIcqProto::servlistUpdateContact(HANDLE hContact)
+{
+ DWORD dwUin;
+ uid_str szUid;
+
+ // Get UID
+ if (getContactUid(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");
+ return;
+ }
+ cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+
+ if (!ack)
+ {
+ // Could not allocate cookie - use old fake
+ NetLog_Server("Failed to update contact's details on server side list (%s)", "malloc failed");
+ return;
+ }
+ else
+ {
+ ack->hContact = hContact;
+ // call thru pending operations - makes sure the contact is ready to be updated
+ servlistPendingAddContact(hContact, 0, 0, (LPARAM)ack, &CIcqProto::servlistUpdateContact_Ready, TRUE);
+ return;
+ }
+}
+
+
+int CIcqProto::servlistRenameGroup_Ready(const char *szGroup, WORD wGroupID, LPARAM lParam, int nResult)
+{
+ cookie_servlist_action *ack = (cookie_servlist_action*)lParam;
+
+ if (nResult == PENDING_RESULT_PURGE)
+ { // only cleanup
+ if (ack) SAFE_FREE(&ack->szGroupName);
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ if (!ack || !wGroupID) // something went wrong
+ {
+ servlistPendingRemoveGroup(szGroup, wGroupID, PENDING_RESULT_FAILED);
+
+ if (ack) SAFE_FREE(&ack->szGroupName);
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+ void *groupData;
+ int groupSize;
+
+ if (groupData = collectBuddyGroup(wGroupID, &groupSize))
+ {
+ ack->dwAction = SSA_GROUP_RENAME;
+ ack->wGroupId = wGroupID;
+ ack->szGroup = null_strdup(szGroup); // we need this name
+ // check if the new name is unique, create unique groupname if necessary
+ ack->szGroupName = getServListUniqueGroupName(ack->szGroupName, TRUE);
+
+ DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+
+ icq_sendServerGroup(dwCookie, ICQ_LISTS_UPDATEGROUP, wGroupID, ack->szGroupName, groupData, groupSize, 0);
+ SAFE_FREE(&groupData);
+ }
+ return CALLBACK_RESULT_POSTPONE;
+}
+
+
+void CIcqProto::servlistRenameGroup(char *szGroup, WORD wGroupId, char *szNewGroup)
+{
+ char *szNewGroupName;
+ int nGroupLevel = getServListGroupLevel(wGroupId);
+
+ if (nGroupLevel == -1) return; // we failed to prepare group
+
+ if (!m_bSsiSimpleGroups)
+ {
+ char *szGroupName = szGroup;
+ int i = nGroupLevel;
+ while (i)
+ { // find correct part of grouppath
+ szGroupName = strstrnull(szGroupName, "\\");
+ if (!szGroupName) return; // failed to get correct part of the grouppath
+ szGroupName++;
+ i--;
+ }
+ szNewGroupName = szNewGroup;
+ i = nGroupLevel;
+ while (i)
+ { // find correct part of new grouppath
+ szNewGroupName = strstrnull(szNewGroupName, "\\");
+ if (!szNewGroupName) return; // failed to get correct part of the new grouppath
+ szNewGroupName++;
+ i--;
+ }
+ // truncate possible sub-groups
+ char *szLast = strstrnull(szGroupName, "\\");
+ if (szLast)
+ szLast[0] = '\0';
+ szLast = strstrnull(szNewGroupName, "\\");
+ if (szLast)
+ szLast[0] = '\0';
+
+ // this group was not changed, nothing to rename
+ if (!strcmpnull(szGroupName, szNewGroupName)) return;
+
+ szGroupName = szNewGroupName;
+ szNewGroupName = (char*)SAFE_MALLOC(strlennull(szGroupName) + 1 + nGroupLevel);
+ if (!szNewGroupName) return; // Failure
+
+ for (i = 0; i < nGroupLevel; i++)
+ { // create level prefix
+ szNewGroupName[i] = '>';
+ }
+ strcat(szNewGroupName, szGroupName);
+ }
+ else // simple groups do not require any conversion
+ szNewGroupName = null_strdup(szNewGroup);
+
+ cookie_servlist_action* ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ if (!ack)
+ { // cookie failed
+ NetLog_Server("Error: Failed to allocate cookie");
+
+ SAFE_FREE(&szNewGroupName);
+ return;
+ }
+ // store new group name for future use
+ ack->szGroupName = szNewGroupName;
+ // call thru pending operations - makes sure the group is ready for rename
+ servlistPendingAddGroup(szGroup, wGroupId, (LPARAM)ack, &CIcqProto::servlistRenameGroup_Ready, TRUE);
+}
+
+
+int CIcqProto::servlistRemoveGroup_Ready(const char *szGroup, WORD groupID, LPARAM lParam, int nResult)
+{
+ cookie_servlist_action *ack = (cookie_servlist_action*)lParam;
+
+ if (nResult == PENDING_RESULT_PURGE)
+ { // only cleanup
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+ WORD wGroupID = getServListGroupLinkID(szGroup);
+ char *szGroupName;
+
+ if (wGroupID && (szGroupName = getServListGroupName(wGroupID)))
+ { // the group is valid, check if it is empty
+ void *groupData = collectBuddyGroup(wGroupID, NULL);
+
+ if (groupData)
+ { // the group is not empty, cannot delete
+ SAFE_FREE(&groupData);
+ SAFE_FREE(&szGroupName);
+ // end operation
+ servlistPendingRemoveGroup(szGroup, wGroupID, PENDING_RESULT_SUCCESS);
+ // cleanup
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+ }
+
+ if (!CheckServerID((WORD)(wGroupID+1), 0) || getServListGroupLevel((WORD)(wGroupID+1)) == 0)
+ { // is next id an sub-group, if yes, we cannot delete this group
+ ack->dwAction = SSA_GROUP_REMOVE;
+ ack->wContactId = 0;
+ ack->wGroupId = wGroupID;
+ ack->hContact = NULL;
+ ack->szGroup = null_strdup(szGroup); // we need that name
+ ack->szGroupName = szGroupName;
+ DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, 0, ack);
+
+ icq_sendServerGroup(dwCookie, ICQ_LISTS_REMOVEFROMLIST, ack->wGroupId, ack->szGroupName, NULL, 0, 0);
+ }
+ return CALLBACK_RESULT_POSTPONE;
+ }
+ // end operation
+ servlistPendingRemoveGroup(szGroup, groupID, PENDING_RESULT_SUCCESS);
+ // cleanup
+ SAFE_FREE((void**)&ack);
+ return CALLBACK_RESULT_CONTINUE;
+}
+
+
+void CIcqProto::servlistRemoveGroup(const char *szGroup, WORD wGroupId)
+{
+ if (!szGroup) return;
+
+ cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+
+ if (!ack)
+ { // cookie failed
+ NetLog_Server("Error: Failed to allocate cookie");
+ return;
+ }
+
+ // call thru pending operations - makes sure the group is ready for removal
+ servlistPendingAddGroup(szGroup, wGroupId, (LPARAM)ack, &CIcqProto::servlistRemoveGroup_Ready, TRUE);
+}
+
+
+/*void CIcqProto::servlistMoveGroup(const char *szGroup, WORD wNewGroupId)
+{
+// relocate the group
+}*/
+
+
+void CIcqProto::resetServContactAuthState(HANDLE hContact, DWORD dwUin)
+{
+ WORD wContactId = getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0);
+ WORD wGroupId = getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0);
+
+ if (wContactId && wGroupId)
+ {
+ cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+
+ if (ack)
+ { // we have cookie good, go on
+ ack->hContact = hContact;
+ ack->wContactId = wContactId;
+ ack->wGroupId = wGroupId;
+ ack->dwAction = SSA_CONTACT_FIX_AUTH;
+
+ DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, 0, hContact, ack);
+
+ {
+ void *doubleObject = NULL;
+
+ icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_REMOVEFROMLIST, wGroupId, wContactId, SSO_CONTACT_FIXAUTH | SSOF_BEGIN_OPERATION | SSOF_END_OPERATION, 200, &doubleObject);
+ deleteSetting(hContact, DBSETTING_METAINFO_TOKEN);
+ deleteSetting(hContact, DBSETTING_METAINFO_TIME);
+ deleteSetting(hContact, DBSETTING_SERVLIST_DATA);
+ icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_ADDTOLIST, wGroupId, wContactId, SSO_CONTACT_FIXAUTH | SSOF_BEGIN_OPERATION | SSOF_END_OPERATION, 200, &doubleObject);
+ }
+ }
+ else
+ NetLog_Server("Error: Failed to allocate cookie");
+ }
+}
+
+/*****************************************
+*
+* --- Miranda Contactlist Hooks ---
+*
+*/
+
+int CIcqProto::ServListDbSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING* cws = (DBCONTACTWRITESETTING*)lParam;
+
+ // We can't upload changes to NULL contact
+ if ((HANDLE)wParam == NULL)
+ { // only note last change of CListGroups - contact/group operation detection
+ if (!strcmpnull(cws->szModule, "CListGroups"))
+ dwLastCListGroupsChange = time(NULL);
+
+ return 0;
+ }
+
+ // TODO: Queue changes that occur while offline
+ if (!icqOnline() || !m_bSsiEnabled || bIsSyncingCL)
+ return 0;
+
+#ifdef _DEBUG
+ if (cws->value.type == DBVT_DELETED)
+ NetLog_Server("DB-Events: Module \"%s\", setting \"%s\" deleted.", cws->szModule, cws->szSetting);
+ else
+ NetLog_Server("DB-Events: Module \"%s\", setting \"%s\" changed, data type %x.", cws->szModule, cws->szSetting, cws->value.type);
+#endif
+
+ 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)))
+ { // Add to server-list
+ setContactHidden((HANDLE)wParam, 0);
+ if (getSettingByte(NULL, "ServerAddRemove", DEFAULT_SS_ADDSERVER))
+ AddServerContact(wParam, 0);
+ }
+
+ // Has contact been renamed?
+ if (!strcmpnull(cws->szSetting, "MyHandle") &&
+ getSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
+ { // Update contact's details in server-list
+ servlistUpdateContact((HANDLE)wParam);
+ }
+
+ // Has contact been moved to another group?
+ if (!strcmpnull(cws->szSetting, "Group") &&
+ getSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
+ { // Read group from DB
+ char* szNewGroup = getContactCListGroup((HANDLE)wParam);
+
+ // it is contact operation only ? no, if CListGroups was changed less than 10 secs ago
+ if (szNewGroup && (dwLastCListGroupsChange + 10 < time(NULL)))
+ servlistMoveContact((HANDLE)wParam, szNewGroup);
+
+ SAFE_FREE(&szNewGroup);
+ }
+ }
+ else if (!strcmpnull(cws->szModule, "UserInfo"))
+ {
+ if (!strcmpnull(cws->szSetting, "MyNotes") &&
+ getSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
+ { // Update contact's details in server-list
+ servlistUpdateContact((HANDLE)wParam);
+ }
+ }
+
+ return 0;
+}
+
+
+int CIcqProto::ServListDbContactDeleted(WPARAM wParam, LPARAM lParam)
+{
+#ifdef _DEBUG
+ NetLog_Server("DB-Events: Contact %x deleted.", wParam);
+#endif
+
+ DeleteFromContactsCache((HANDLE)wParam);
+
+ if ( !icqOnline() && m_bSsiEnabled)
+ { // contact was deleted only locally - retrieve full list on next connect
+ setSettingWord((HANDLE)wParam, "SrvRecordCount", 0);
+ }
+
+ if ( !icqOnline() || !m_bSsiEnabled)
+ return 0;
+
+ { // we need all server contacts on local buddy list
+ DWORD dwUIN;
+ uid_str szUID;
+
+ if (getContactUid((HANDLE)wParam, &dwUIN, &szUID))
+ return 0;
+
+ WORD wContactID = getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_ID, 0);
+ WORD wGroupID = getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_GROUP, 0);
+ WORD wVisibleID = getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_PERMIT, 0);
+ WORD wInvisibleID = getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_DENY, 0);
+ WORD wIgnoreID = getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_IGNORE, 0);
+
+ // Remove from queue for user details request
+ icq_DequeueUser(dwUIN);
+
+ // Close all opened peer connections
+ CloseContactDirectConns((HANDLE)wParam);
+
+ if ((wGroupID && wContactID) || wVisibleID || wInvisibleID || wIgnoreID)
+ {
+ if (wContactID)
+ { // delete contact from server
+ servlistRemoveContact((HANDLE)wParam);
+ }
+
+ if (wVisibleID)
+ { // detete permit record
+ icq_removeServerPrivacyItem((HANDLE)wParam, dwUIN, szUID, wVisibleID, SSI_ITEM_PERMIT);
+ }
+
+ if (wInvisibleID)
+ { // delete deny record
+ icq_removeServerPrivacyItem((HANDLE)wParam, dwUIN, szUID, wInvisibleID, SSI_ITEM_DENY);
+ }
+
+ if (wIgnoreID)
+ { // delete ignore record
+ icq_removeServerPrivacyItem((HANDLE)wParam, dwUIN, szUID, wIgnoreID, SSI_ITEM_IGNORE);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+int CIcqProto::ServListCListGroupChange(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ CLISTGROUPCHANGE *grpchg = (CLISTGROUPCHANGE*)lParam;
+
+ if (!icqOnline() || !m_bSsiEnabled || bIsSyncingCL)
+ return 0;
+
+ // only change server-list if it is allowed
+ if (!getSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
+ return 0;
+
+
+ if (hContact == NULL)
+ { // change made to group
+ if (grpchg->pszNewName == NULL && grpchg->pszOldName != NULL)
+ { // group removed
+ char *szOldName = tchar_to_utf8(grpchg->pszOldName);
+ WORD wGroupId = getServListGroupLinkID(szOldName);
+
+#ifdef _DEBUG
+ NetLog_Server("CList-Events: Group %x:\"%s\" deleted.", wGroupId, szOldName);
+#endif
+ if (wGroupId)
+ { // the group is known, remove from server
+ servlistPostPacket(NULL, 0, SSO_BEGIN_OPERATION, 100); // start server modifications here
+ servlistRemoveGroup(szOldName, wGroupId);
+ }
+ SAFE_FREE(&szOldName);
+ }
+ else if (grpchg->pszNewName != NULL && grpchg->pszOldName != NULL)
+ { // group renamed
+ char *szNewName = tchar_to_utf8(grpchg->pszNewName);
+ char *szOldName = tchar_to_utf8(grpchg->pszOldName);
+ WORD wGroupId = getServListGroupLinkID(szOldName);
+
+#ifdef _DEBUG
+ NetLog_Server("CList-Events: Group %x:\"%s\" changed to \"%s\".", wGroupId, szOldName, szNewName);
+#endif
+ if (wGroupId)
+ { // group is known, rename on server
+ servlistRenameGroup(szOldName, wGroupId, szNewName);
+ }
+ SAFE_FREE(&szOldName);
+ SAFE_FREE(&szNewName);
+ }
+ }
+ else
+ { // change to contact
+ if (IsICQContact(hContact))
+ { // our contact, fine move on the server as well
+ char *szNewName = grpchg->pszNewName ? tchar_to_utf8(grpchg->pszNewName) : NULL;
+
+#ifdef _DEBUG
+ NetLog_Server("CList-Events: Contact %x moved to group \"%s\".", hContact, szNewName);
+#endif
+ servlistMoveContact(hContact, szNewName);
+ SAFE_FREE(&szNewName);
+ }
+ }
+ return 0;
+}
diff --git a/protocols/IcqOscarJ/icq_servlist.h b/protocols/IcqOscarJ/icq_servlist.h
new file mode 100644
index 0000000000..c16ee552a5
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_servlist.h
@@ -0,0 +1,179 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_servlist.h $
+// Revision : $Revision: 11805 $
+// Last change on : $Date: 2010-05-20 23:54:42 +0300 (Чт, 20 май 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// 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_ADD 0x10 // add contact w/o 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
+#define SSA_ACTION_GROUP 0x80 // grouped action
+
+struct CIcqProto;
+// callback prototypes for pending operation mechanism:
+typedef int (__cdecl CIcqProto::*PENDING_GROUP_CALLBACK)(const char* pszGroup, WORD wGroupId, LPARAM lParam, int nResult);
+typedef int (__cdecl CIcqProto::*PENDING_CONTACT_CALLBACK)(HANDLE hContact, WORD wContactId, WORD wGroupId, LPARAM lParam, int nResult);
+
+// cookie struct for SSI actions
+struct cookie_servlist_action
+{
+ HANDLE hContact;
+ char *szGroup;
+ WORD wContactId;
+ WORD wGroupId;
+ char *szGroupName;
+ WORD wNewContactId;
+ WORD wNewGroupId;
+ int dwAction;
+ LPARAM lParam;
+ int dwGroupCount;
+ cookie_servlist_action **pGroupItems;
+};
+
+// server id type groups
+#define SSIT_ITEM 0x00000000
+#define SSIT_GROUP 0x00010000
+
+// server id flags
+#define SSIF_UNHANDLED 0x01000000
+
+
+// pending operations
+#define PENDING_RESULT_SUCCESS 0x00
+#define PENDING_RESULT_INLINE 0x01
+#define PENDING_RESULT_FAILED 0x0F
+#define PENDING_RESULT_PURGE 0x10
+
+// serv-list update board
+#define SSOG_SINGLE 0x00010000
+#define SSOG_DOUBLE 0x00020000
+
+#define SSOF_CONTACT 0x00800000
+#define SSOF_BEGIN_OPERATION 0x00100000
+#define SSOF_END_OPERATION 0x00200000
+#define SSOF_IMPORT_OPERATION 0x00400000
+
+#define SSOP_ITEM_ACTION 0x01000000 | SSOG_SINGLE
+// SSA_PRIVACY_ADD
+// SSA_CONTACT_ADD
+// SSA_CONTACT_UPDATE
+// SSA_VISIBILITY
+// SSA_PRIVACY_REMOVE
+// SSA_CONTACT_REMOVE
+// SSA_SETAVATAR
+// SSA_REMOVEAVATAR
+#define SSOP_GROUP_ACTION 0x02000000 | SSOG_SINGLE
+// SSA_GROUP_ADD
+// SSA_GROUP_RENAME
+// SSA_GROUP_UPDATE
+// SSA_GROUP_REMOVE
+#define SSO_CONTACT_SETGROUP 0x04000000 | SSOG_DOUBLE
+// SSA_CONTACT_SET_GROUP
+#define SSO_CONTACT_FIXAUTH 0x06000000 | SSOG_DOUBLE
+// SSA_CONTACT_FIX_AUTH
+
+#define SSO_BEGIN_OPERATION 0x80000000
+#define SSO_END_OPERATION 0x40000000
+
+#define SSOF_SEND_DIRECTLY 0x10000000
+
+#define SSOF_ACTIONMASK 0x0000FFFF
+#define SSOF_GROUPINGMASK 0x0F0FFFFF
+
+
+#define MAX_SERVLIST_PACKET_ITEMS 200
+
+// server-list request handler item
+struct servlistgroupitem
+{ // generic parent
+ DWORD dwOperation;
+ cookie_servlist_action* cookie;
+ icq_packet packet;
+ // perhaps add some dummy bytes
+};
+
+struct servlistgroupitemdouble: public servlistgroupitem
+{
+ icq_packet packet2;
+ WORD wAction2;
+};
+
+struct ssiqueueditems
+{
+ time_t tAdded;
+ int dwTimeout;
+ int nItems;
+ servlistgroupitem* pItems[MAX_SERVLIST_PACKET_ITEMS];
+};
+
+
+// cookie structs for pending records
+struct servlistpendingoperation
+{
+ DWORD flags;
+ PENDING_GROUP_CALLBACK callback;
+ LPARAM param;
+};
+
+struct servlistpendingitem
+{
+ int nType;
+ HANDLE hContact;
+ char* szGroup;
+ WORD wContactID;
+ WORD wGroupID;
+
+ servlistpendingoperation* operations;
+ int operationsCount;
+};
+
+
+#endif /* __ICQ_SERVLIST_H */
diff --git a/protocols/IcqOscarJ/icq_uploadui.cpp b/protocols/IcqOscarJ/icq_uploadui.cpp
new file mode 100644
index 0000000000..500cae1216
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_uploadui.cpp
@@ -0,0 +1,1036 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_uploadui.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// 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, CIcqProto* ppro, HANDLE phItemAll)
+{
+ int check = 1;
+
+ HANDLE hContact = ppro->FindFirstContact();
+ while (hContact)
+ {
+ HANDLE 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 = ppro->FindNextContact(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, CIcqProto* ppro, HANDLE phItemAll)
+{
+ int bAll = 1;
+ bListInit = 1; // lock CLC events
+
+ HANDLE hContact = ppro->FindFirstContact();
+ while (hContact)
+ {
+ HANDLE hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ {
+ if (ppro->getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0))
+ SendMessage(hwndList, CLM_SETCHECKMARK, (WPARAM)hItem, 1);
+ else
+ bAll = 0;
+ }
+ hContact = ppro->FindNextContact(hContact);
+ }
+
+ // Update the "All contacts" checkmark
+ if (phItemAll)
+ SendMessage(hwndList, CLM_SETCHECKMARK, (WPARAM)phItemAll, bAll);
+
+ bListInit = 0;
+
+ return bAll;
+}
+
+static void DeleteOtherContactsFromControl(HWND hCtrl, CIcqProto* ppro)
+{
+ 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 (!ppro->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];
+ 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 defined( _UNICODE )
+ 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((char*)szBuf, (char*)ustr);
+ SAFE_FREE((void**)&ustr);
+ #endif
+}
+
+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(CIcqProto* ppro)
+{
+ DBCONTACTENUMSETTINGS dbces;
+
+ char szModule[MAX_PATH+9];
+
+ strcpy(szModule, ppro->m_szModuleName);
+ 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(CIcqProto* ppro, WORD wAction, WORD wGroupId, char* szItemName)
+{
+ DWORD dwCookie;
+ cookie_servlist_action* ack;
+
+ if (ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action)))
+ { // we have cookie good, go on
+ ack->wGroupId = wGroupId;
+ ack->dwAction = SSA_SERVLIST_ACK;
+ dwCookie = ppro->AllocateCookie(CKT_SERVERLIST, wAction, 0, ack);
+ ack->lParam = dwCookie;
+
+ ppro->icq_sendServerGroup(dwCookie, wAction, ack->wGroupId, szItemName, NULL, 0, 0);
+ return dwCookie;
+ }
+ return 0;
+}
+
+static DWORD sendUploadBuddy(CIcqProto* ppro, HANDLE hContact, WORD wAction, DWORD dwUin, char *szUID, WORD wContactId, WORD wGroupId, WORD wItemType)
+{
+ DWORD dwCookie;
+ cookie_servlist_action* ack;
+
+ if (ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action)))
+ { // we have cookie good, go on
+ ack->hContact = hContact;
+ ack->wContactId = wContactId;
+ ack->wGroupId = wGroupId;
+ ack->dwAction = SSA_SERVLIST_ACK;
+ dwCookie = ppro->AllocateCookie(CKT_SERVERLIST, wAction, hContact, ack);
+ ack->lParam = dwCookie;
+
+ if (wItemType == SSI_ITEM_BUDDY)
+ ppro->icq_sendServerContact(hContact, dwCookie, wAction, ack->wGroupId, ack->wContactId, SSOP_ITEM_ACTION | SSOF_CONTACT, 500, NULL);
+ else
+ ppro->icq_sendSimpleItem(dwCookie, wAction, dwUin, szUID, ack->wGroupId, ack->wContactId, wItemType, SSOP_ITEM_ACTION, 500);
+
+ return dwCookie;
+ }
+ return 0;
+}
+
+static char* getServerResultDesc(int wCode)
+{
+ switch (wCode)
+ {
+ case 0: return LPGEN("OK");
+ case 2: return LPGEN("NOT FOUND");
+ case 3: return LPGEN("ALREADY EXISTS");
+ case 0xA: return LPGEN("INVALID DATA");
+ case 0xC: return LPGEN("LIST FULL");
+ default: return LPGEN("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 INT_PTR CALLBACK DlgProcUploadList(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam)
+{
+ CIcqProto* ppro = (CIcqProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ 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:
+ TranslateDialogDefault(hwndDlg);
+
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
+ {
+ char str[MAX_PATH];
+
+ working = 0;
+ hProtoAckHook = NULL;
+ currentState = STATE_READY;
+
+ ResetCListOptions(GetDlgItem(hwndDlg, IDC_CLIST));
+
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Select contacts you want to store on server."), str, MAX_PATH));
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("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, ppro->m_szModuleName))
+ 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(LPGEN("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)
+ {
+ ppro->setSettingByte(hCurrentContact, "Auth", 0);
+ ppro->setSettingWord(hCurrentContact, DBSETTING_SERVLIST_ID, wNewContactId);
+ ppro->setSettingWord(hCurrentContact, DBSETTING_SERVLIST_GROUP, wNewGroupId);
+ break;
+ }
+ else
+ { // If the server refused to add the contact without authorization,
+ // we try again _with_ authorization TLV
+ DWORD dwUIN;
+ uid_str szUID;
+
+ ppro->setSettingByte(hCurrentContact, "Auth", 1);
+
+ if (!ppro->getContactUid(hCurrentContact, &dwUIN, &szUID))
+ {
+ currentAction = ACTION_ADDBUDDYAUTH;
+ currentSequence = sendUploadBuddy(ppro, hCurrentContact, ICQ_LISTS_ADDTOLIST, dwUIN, szUID, wNewContactId, wNewGroupId, SSI_ITEM_BUDDY);
+ }
+
+ return FALSE;
+ }
+
+ case ACTION_ADDBUDDYAUTH:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ ppro->setSettingWord(hCurrentContact, DBSETTING_SERVLIST_ID, wNewContactId);
+ ppro->setSettingWord(hCurrentContact, DBSETTING_SERVLIST_GROUP, wNewGroupId);
+ }
+ else
+ {
+ ppro->deleteSetting(hCurrentContact, "Auth");
+ ppro->FreeServerID(wNewContactId, SSIT_ITEM);
+ }
+
+ break;
+
+ case ACTION_REMOVEBUDDY:
+ if (ack->result == ACKRESULT_SUCCESS)
+ { // clear obsolete settings
+ ppro->FreeServerID(wNewContactId, SSIT_ITEM);
+ ppro->deleteSetting(hCurrentContact, DBSETTING_SERVLIST_ID);
+ ppro->deleteSetting(hCurrentContact, DBSETTING_SERVLIST_GROUP);
+ ppro->deleteSetting(hCurrentContact, "Auth");
+ }
+ break;
+
+ case ACTION_ADDGROUP:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ void* groupData;
+ int groupSize;
+ cookie_servlist_action* ack;
+
+ ppro->setServListGroupName(wNewGroupId, szNewGroupName); // add group to list
+ ppro->setServListGroupLinkID(szNewGroupName, wNewGroupId); // grouppath is known
+
+ groupData = ppro->collectGroups(&groupSize);
+ groupData = SAFE_REALLOC(groupData, groupSize+2);
+ *(((WORD*)groupData)+(groupSize>>1)) = wNewGroupId; // add this new group id
+ groupSize += 2;
+
+ ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ if (ack)
+ {
+ DWORD dwCookie; // we do not use this
+
+ ack->dwAction = SSA_SERVLIST_ACK;
+ dwCookie = ppro->AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+
+ ppro->icq_sendServerGroup(dwCookie, ICQ_LISTS_UPDATEGROUP, 0, ack->szGroupName, groupData, groupSize, 0);
+ }
+ SAFE_FREE((void**)&groupData);
+ }
+ else
+ ppro->FreeServerID(wNewGroupId, SSIT_GROUP);
+
+ SAFE_FREE((void**)&szNewGroupName);
+ break;
+
+ case ACTION_REMOVEGROUP:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ void* groupData;
+ int groupSize;
+ cookie_servlist_action* ack;
+
+ ppro->FreeServerID(wNewGroupId, SSIT_GROUP);
+ ppro->setServListGroupName(wNewGroupId, NULL); // remove group from list
+ ppro->removeGroupPathLinks(wNewGroupId); // grouppath is known
+
+ groupData = ppro->collectGroups(&groupSize);
+
+ ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+ if (ack)
+ {
+ DWORD dwCookie; // we do not use this
+
+ ack->dwAction = SSA_SERVLIST_ACK;
+ dwCookie = ppro->AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+
+ ppro->icq_sendServerGroup(dwCookie, ICQ_LISTS_UPDATEGROUP, 0, ack->szGroupName, groupData, groupSize, 0);
+ }
+ SAFE_FREE((void**)&groupData);
+ }
+ break;
+
+ case ACTION_UPDATESTATE:
+ // do nothing
+ break;
+
+ case ACTION_MOVECONTACT:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ ppro->FreeServerID(ppro->getSettingWord(hCurrentContact, DBSETTING_SERVLIST_ID, 0), SSIT_ITEM);
+ ppro->setSettingWord(hCurrentContact, DBSETTING_SERVLIST_ID, wNewContactId);
+ ppro->setSettingWord(hCurrentContact, DBSETTING_SERVLIST_GROUP, wNewGroupId);
+ dwUploadDelay *= 2; // we double the delay here (2 packets)
+ }
+ break;
+
+ case ACTION_ADDVISIBLE:
+ if (ack->result == ACKRESULT_SUCCESS)
+ ppro->setSettingWord(hCurrentContact, DBSETTING_SERVLIST_PERMIT, wNewContactId);
+ else
+ ppro->FreeServerID(wNewContactId, SSIT_ITEM);
+ break;
+
+ case ACTION_ADDINVISIBLE:
+ if (ack->result == ACKRESULT_SUCCESS)
+ ppro->setSettingWord(hCurrentContact, DBSETTING_SERVLIST_DENY, wNewContactId);
+ else
+ ppro->FreeServerID(wNewContactId, SSIT_ITEM);
+ break;
+
+ case ACTION_REMOVEVISIBLE:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ ppro->FreeServerID(wNewContactId, SSIT_ITEM);
+ ppro->setSettingWord(hCurrentContact, DBSETTING_SERVLIST_PERMIT, 0);
+ }
+ break;
+
+ case ACTION_REMOVEINVISIBLE:
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ ppro->FreeServerID(wNewContactId, SSIT_ITEM);
+ ppro->setSettingWord(hCurrentContact, DBSETTING_SERVLIST_DENY, 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 = ppro->FindFirstContact();
+ 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 = ppro->FindNextContact(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 = ppro->getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0) != 0;
+
+ bUidOk = !ppro->getContactUid(hContact, &dwUin, &szUid);
+
+ // Is this one out of sync?
+ if (bUidOk && (isChecked != isOnServer))
+ {
+ // Only upload custom nicks
+ pszNick = ppro->getSettingStringUtf(hContact, "CList", "MyHandle", NULL);
+
+ if (isChecked)
+ { // Queue for uploading
+ pszGroup = ppro->getContactCListGroup(hContact);
+ 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 = ppro->getServListGroupLinkID(pszGroup);
+ if (!wNewGroupId && strstrnull(pszGroup, "\\") != NULL)
+ { // if it is sub-group, take master parent
+ strstrnull(pszGroup, "\\")[0] = '\0';
+ wNewGroupId = ppro->getServListGroupLinkID(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(LPGEN("Adding group \"%s\"..."), str, MAX_PATH), pszGroup);
+
+ wNewGroupId = ppro->GenerateServerID(SSIT_GROUP, 0); // ???
+ szNewGroupName = pszGroup;
+ currentAction = ACTION_ADDGROUP;
+ currentSequence = sendUploadGroup(ppro, ICQ_LISTS_ADDTOLIST, wNewGroupId, pszGroup);
+ SAFE_FREE(&pszNick);
+
+ return FALSE;
+ }
+
+ SAFE_FREE(&pszGroup);
+
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Uploading %s..."), str, MAX_PATH), pszNick ? pszNick : strUID(dwUin, szUid));
+
+ currentAction = ACTION_ADDBUDDY;
+
+ if (wNewGroupId)
+ {
+ wNewContactId = ppro->GenerateServerID(SSIT_ITEM, 0);
+
+ currentSequence = sendUploadBuddy(ppro, 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(LPGEN("FAILED"), str, MAX_PATH));
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("No upload group available"), str, MAX_PATH));
+ ppro->NetLog_Server("Upload failed, no group");
+ currentState = STATE_READY;
+ }
+ }
+ else
+ { // Queue for deletion
+ if (pszNick)
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Deleting %s..."), str, MAX_PATH), pszNick);
+ else
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Deleting %s..."), str, MAX_PATH), strUID(dwUin, szUid));
+
+ wNewGroupId = ppro->getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0);
+ wNewContactId = ppro->getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0);
+ currentAction = ACTION_REMOVEBUDDY;
+ currentSequence = sendUploadBuddy(ppro, hContact, ICQ_LISTS_REMOVEFROMLIST, dwUin, szUid,
+ wNewContactId, wNewGroupId, SSI_ITEM_BUDDY);
+ }
+ SAFE_FREE((void**)&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 = ppro->getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0);
+
+ pszGroup = ppro->getContactCListGroup(hContact);
+ if (!strlennull(pszGroup))
+ pszGroup = null_strdup(DEFAULT_SS_GROUP);
+ wNewGroupId = ppro->getServListGroupLinkID(pszGroup);
+ if (!wNewGroupId && strstrnull(pszGroup, "\\") != NULL)
+ { // if it is sub-group, take master parent
+ strstrnull(pszGroup, "\\")[0] = '\0';
+ wNewGroupId = ppro->getServListGroupLinkID(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(LPGEN("Adding group \"%s\"..."), str, MAX_PATH), pszGroup);
+
+ wNewGroupId = ppro->GenerateServerID(SSIT_GROUP, 0);
+ szNewGroupName = pszGroup;
+ currentAction = ACTION_ADDGROUP;
+ currentSequence = sendUploadGroup(ppro, ICQ_LISTS_ADDTOLIST, wNewGroupId, pszGroup);
+
+ return FALSE;
+ }
+ if (wNewGroupId && (wNewGroupId != wCurrentGroupId))
+ { // we have a group the contact should be in, move it
+ WORD wCurrentContactId = ppro->getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0);
+ BYTE bAuth = ppro->getSettingByte(hContact, "Auth", 0);
+
+ pszNick = ppro->getSettingStringUtf(hContact, "CList", "MyHandle", NULL);
+
+ if (pszNick)
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Moving %s to group \"%s\"..."), str, MAX_PATH), pszNick, pszGroup);
+ else
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Moving %s to group \"%s\"..."), str, MAX_PATH), strUID(dwUin, szUid), pszGroup);
+
+ currentAction = ACTION_MOVECONTACT;
+ wNewContactId = ppro->GenerateServerID(SSIT_ITEM, 0);
+ sendUploadBuddy(ppro, hContact, ICQ_LISTS_REMOVEFROMLIST, dwUin, szUid, wCurrentContactId, wCurrentGroupId, SSI_ITEM_BUDDY);
+ currentSequence = sendUploadBuddy(ppro, hContact, ICQ_LISTS_ADDTOLIST, dwUin, szUid, wNewContactId, wNewGroupId, SSI_ITEM_BUDDY);
+ SAFE_FREE((void**)&pszNick);
+ SAFE_FREE((void**)&pszGroup);
+
+ break;
+ }
+ SAFE_FREE((void**)&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 = ppro->FindFirstContact();
+ 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 = ppro->FindNextContact(hContact);
+ }
+
+ while (hContact)
+ {
+ WORD wApparentMode = ppro->getSettingWord(hContact, "ApparentMode", 0);
+ WORD wDenyId = ppro->getSettingWord(hContact, DBSETTING_SERVLIST_DENY, 0);
+ WORD wPermitId = ppro->getSettingWord(hContact, DBSETTING_SERVLIST_PERMIT, 0);
+ WORD wIgnoreId = ppro->getSettingWord(hContact, DBSETTING_SERVLIST_IGNORE, 0);
+
+ hCurrentContact = hContact;
+ ppro->getContactUid(hContact, &dwUin, &szUid);
+
+ if (wApparentMode == ID_STATUS_ONLINE)
+ { // contact is on the visible list
+ if (wPermitId == 0)
+ {
+ currentAction = ACTION_ADDVISIBLE;
+ wNewContactId = ppro->GenerateServerID(SSIT_ITEM, 0);
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Adding %s to visible list..."), str, MAX_PATH), strUID(dwUin, szUid));
+ currentSequence = sendUploadBuddy(ppro, 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 = ppro->GenerateServerID(SSIT_ITEM, 0);
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Adding %s to invisible list..."), str, MAX_PATH), strUID(dwUin, szUid));
+ currentSequence = sendUploadBuddy(ppro, 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(LPGEN("Deleting %s from visible list..."), str, MAX_PATH), strUID(dwUin, szUid));
+ currentSequence = sendUploadBuddy(ppro, 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(LPGEN("Deleting %s from invisible list..."), str, MAX_PATH), strUID(dwUin, szUid));
+ currentSequence = sendUploadBuddy(ppro, 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(LPGEN("Cleaning groups"), str, MAX_PATH));
+ EnableDlgItem(hwndDlg, IDCANCEL, FALSE);
+ enumServerGroups(ppro);
+ 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 = ppro->collectBuddyGroup(wNewGroupId, &groupSize))
+ { // the group is still not empty, just update it
+ char* pszGroup = ppro->getServListGroupName(wNewGroupId);
+ cookie_servlist_action* ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+
+ ack->dwAction = SSA_SERVLIST_ACK;
+ ack->wGroupId = wNewGroupId;
+ currentSequence = ppro->AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+ ack->lParam = currentSequence;
+ currentAction = ACTION_UPDATESTATE;
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Updating group \"%s\"..."), str, MAX_PATH), pszGroup);
+
+ ppro->icq_sendServerGroup(currentSequence, ICQ_LISTS_UPDATEGROUP, wNewGroupId, pszGroup, groupData, groupSize, 0);
+
+ SAFE_FREE((void**)&pszGroup);
+ }
+ else // the group is empty, delete it if it does not have sub-groups
+ {
+ if (!ppro->CheckServerID((WORD)(wNewGroupId+1), 0) || ppro->getServListGroupLevel((WORD)(wNewGroupId+1)) == 0)
+ { // is next id an sub-group, if yes, we cannot delete this group
+ char *pszGroup = ppro->getServListGroupName(wNewGroupId);
+ currentAction = ACTION_REMOVEGROUP;
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Deleting group \"%s\"..."), str, MAX_PATH), pszGroup);
+ currentSequence = sendUploadGroup(ppro, ICQ_LISTS_REMOVEFROMLIST, wNewGroupId, pszGroup);
+ SAFE_FREE((void**)&pszGroup);
+ }
+ else // update empty group
+ {
+ char *pszGroup = ppro->getServListGroupName(wNewGroupId);
+ cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
+
+ ack->dwAction = SSA_SERVLIST_ACK;
+ ack->wGroupId = wNewGroupId;
+ currentSequence = ppro->AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
+ ack->lParam = currentSequence;
+ currentAction = ACTION_UPDATESTATE;
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("Updating group \"%s\"..."), str, MAX_PATH), pszGroup);
+
+ ppro->icq_sendServerGroup(currentSequence, ICQ_LISTS_UPDATEGROUP, wNewGroupId, pszGroup, 0, 0, 0);
+
+ SAFE_FREE((void**)&pszGroup);
+ }
+ }
+ SAFE_FREE((void**)&groupData); // free the memory
+ }
+ else
+ { // all groups processed
+ SAFE_FREE((void**)&pwGroupIds);
+ currentState = STATE_READY;
+ }
+ break;
+ }
+
+ if (currentState == STATE_READY)
+ {
+ // All contacts are in sync
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("All operations complete"), str, MAX_PATH));
+ EnableDlgItem(hwndDlg, IDCANCEL, TRUE);
+ SetDlgItemTextUtf(hwndDlg, IDCANCEL, ICQTranslateUtfStatic(LPGEN("Close"), str, MAX_PATH));
+ // end server modifications here
+ ppro->servlistPostPacket(NULL, 0, SSO_END_OPERATION, 100);
+ working = 0;
+ // SendMessage(hwndList, CLM_SETGREYOUTFLAGS,0,0);
+ UpdateCheckmarks(hwndList, ppro, 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 (!ppro->icqOnline())
+ {
+ char str[MAX_PATH];
+ AppendToUploadLog(hwndDlg, ICQTranslateUtfStatic(LPGEN("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);
+ // start server modifications here
+ ppro->servlistPostPacket(NULL, 0, SSO_BEGIN_OPERATION | SSOF_IMPORT_OPERATION, 100);
+ 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, ppro);
+ if (hItemAll)
+ UpdateAllContactsCheckmark(hClist, ppro, hItemAll);
+ break;
+
+ case CLN_LISTREBUILT:
+ {
+ int bCheck = false;
+
+ // Delete non-icq contacts
+ if ( ppro ) {
+ DeleteOtherContactsFromControl(hClist, ppro);
+ if (!bListInit) // do not enter twice
+ bCheck = UpdateCheckmarks(hClist, ppro, NULL);
+ }
+
+ if (!hItemAll) // Add the "All contacts" item
+ {
+ CLCINFOITEM cii = {0};
+
+ cii.cbSize = sizeof(cii);
+ cii.flags = CLCIIF_GROUPFONT | CLCIIF_CHECKBOX;
+ cii.pszText = TranslateT(LPGEN("** 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 = ppro->FindFirstContact();
+ while (hContact)
+ {
+ hItem = (HANDLE)SendMessage(hClist, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ SendMessage(hClist, CLM_SETCHECKMARK, (WPARAM)hItem, check);
+ hContact = ppro->FindNextContact(hContact);
+ }
+ }
+ else
+ UpdateAllContactsCheckmark(hClist, ppro, hItemAll);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ if (hProtoAckHook)
+ UnhookEvent(hProtoAckHook);
+ if (working)
+ { // end server modifications here
+ ppro->servlistPostPacket(NULL, 0, SSO_END_OPERATION, 100);
+ }
+ hwndUploadContacts = NULL;
+ working = 0;
+ break;
+ }
+
+ return FALSE;
+}
+
+void CIcqProto::ShowUploadContactsDialog(void)
+{
+ if (hwndUploadContacts == NULL)
+ {
+ hItemAll = NULL;
+ hwndUploadContacts = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ICQUPLOADLIST), NULL, DlgProcUploadList, LPARAM(this));
+ }
+
+ SetForegroundWindow(hwndUploadContacts);
+}
diff --git a/protocols/IcqOscarJ/icq_uploadui.h b/protocols/IcqOscarJ/icq_uploadui.h
new file mode 100644
index 0000000000..bc5cd4d17a
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_uploadui.h
@@ -0,0 +1,35 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001,2002 Jon Keating, Richard Hughes
+// Copyright 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004,2005 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_uploadui.h,v $
+// Revision : $Revision: 7500 $
+// Last change on : $Date: 2008-03-24 20:07:37 +0200 (Пн, 24 мар 2008) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
diff --git a/protocols/IcqOscarJ/icq_xstatus.cpp b/protocols/IcqOscarJ/icq_xstatus.cpp
new file mode 100644
index 0000000000..9a1abb5df5
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_xstatus.cpp
@@ -0,0 +1,1388 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 Angeli-Ka, Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_xstatus.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Support for Custom Statuses
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_extraicons.h"
+
+
+extern HANDLE hExtraXStatus;
+
+void CListShowMenuItem(HANDLE hMenuItem, BYTE bShow);
+
+BYTE CIcqProto::getContactXStatus(HANDLE hContact)
+{
+ if (!m_bXStatusEnabled && !m_bMoodsEnabled)
+ return 0;
+
+ BYTE bXStatus = getSettingByte(hContact, DBSETTING_XSTATUS_ID, 0);
+
+ if (bXStatus < 1 || bXStatus > XSTATUS_COUNT) return 0;
+
+ return bXStatus;
+}
+
+
+DWORD CIcqProto::sendXStatusDetailsRequest(HANDLE hContact, int bForced)
+{
+ DWORD dwCookie = 0;
+
+ if (m_bXStatusEnabled && getContactXStatus(hContact) != 0)
+ { // only request custom status detail when the contact has one
+ int nNotifyLen = 94 + UINMAXLEN;
+ char *szNotify = (char*)_alloca(nNotifyLen);
+
+ null_snprintf(szNotify, nNotifyLen, "<srv><id>cAwaySrv</id><req><id>AwayStat</id><trans>1</trans><senderId>%d</senderId></req></srv>", m_dwLocalUIN);
+
+ dwCookie = SendXtrazNotifyRequest(hContact, "<Q><PluginID>srvMng</PluginID></Q>", szNotify, bForced);
+ }
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::requestXStatusDetails(HANDLE hContact, BOOL bAllowDelay)
+{
+ if (!validateStatusMessageRequest(hContact, MTYPE_SCRIPT_NOTIFY))
+ return 0; // apply privacy rules
+
+ if (!CheckContactCapabilities(hContact, CAPF_XSTATUS))
+ return 0; // contact does not have xstatus
+
+ // 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
+
+ struct rates_xstatus_request: public rates_queue_item {
+ protected:
+ virtual rates_queue_item* copyItem(rates_queue_item *aDest = NULL) {
+ rates_xstatus_request *pDest = (rates_xstatus_request*)aDest;
+ if (!pDest)
+ pDest = new rates_xstatus_request(ppro, wGroup);
+
+ pDest->bForced = bForced;
+ return rates_queue_item::copyItem(pDest);
+ };
+ public:
+ rates_xstatus_request(CIcqProto *ppro, WORD wGroup): rates_queue_item(ppro, wGroup) { };
+ virtual ~rates_xstatus_request() { };
+
+ virtual void execute() {
+ dwCookie = ppro->sendXStatusDetailsRequest(hContact, bForced);
+ };
+
+ BOOL bForced;
+ DWORD dwCookie;
+ };
+
+ m_ratesMutex->Enter();
+ WORD wGroup = m_rates->getGroupFromSNAC(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND);
+ m_ratesMutex->Leave();
+
+ rates_xstatus_request rr(this, wGroup);
+ rr.bForced = !bAllowDelay;
+ rr.hContact = hContact;
+
+ // delay at least one sec if allowed
+ if (!handleRateItem(&rr, RQT_REQUEST, 1000, bAllowDelay))
+ return rr.dwCookie;
+
+ return -1; // delayed
+}
+
+
+static HANDLE LoadXStatusIconLibrary(TCHAR *path, const TCHAR *sub)
+{
+ TCHAR* p = _tcsrchr(path, '\\');
+ HANDLE hLib;
+
+ _tcscpy(p, sub);
+ _tcscat(p, _T("\\xstatus_ICQ.dll"));
+ if (hLib = LoadLibrary(path)) return hLib;
+ _tcscpy(p, sub);
+ _tcscat(p, _T("\\xstatus_icons.dll"));
+ if (hLib = LoadLibrary(path)) return hLib;
+ _tcscpy(p, _T("\\"));
+ return hLib;
+}
+
+static TCHAR *InitXStatusIconLibrary(TCHAR *buf, size_t buf_size)
+{
+ TCHAR path[2*MAX_PATH];
+ HMODULE hXStatusIconsDLL;
+
+ // get miranda's exe path
+ GetModuleFileName(NULL, path, MAX_PATH);
+
+ hXStatusIconsDLL = (HMODULE)LoadXStatusIconLibrary(path, _T("\\Icons"));
+ if (!hXStatusIconsDLL) // TODO: add "Custom Folders" support
+ hXStatusIconsDLL = (HMODULE)LoadXStatusIconLibrary(path, _T("\\Plugins"));
+
+ if (hXStatusIconsDLL)
+ {
+ null_strcpy(buf, path, buf_size - 1);
+
+ char ident[MAX_PATH];
+ if (LoadStringA(hXStatusIconsDLL, IDS_IDENTIFY, ident, sizeof(ident)) == 0 || strcmpnull(ident, "# Custom Status Icons #"))
+ { // library is invalid
+ *buf = 0;
+ }
+ FreeLibrary(hXStatusIconsDLL);
+ }
+ else
+ *buf = 0;
+
+ return buf;
+}
+
+
+HICON CIcqProto::getXStatusIcon(int bStatus, UINT flags)
+{
+ HICON icon = NULL;
+
+ if (bStatus > 0 && bStatus <= XSTATUS_COUNT)
+ icon = hXStatusIcons[bStatus - 1]->GetIcon((flags & LR_BIGICON) != 0);
+
+ if (flags & LR_SHARED || !icon)
+ return icon;
+ else
+ return CopyIcon(icon);
+}
+
+
+void CIcqProto::releaseXStatusIcon(int bStatus, UINT flags)
+{
+ if (bStatus > 0 && bStatus <= XSTATUS_COUNT) {
+ IcqIconHandle p = hXStatusIcons[bStatus - 1];
+ if (p)
+ p->ReleaseIcon((flags & LR_BIGICON) != 0);
+ }
+}
+
+
+void CIcqProto::setContactExtraIcon(HANDLE hContact, int xstatus)
+{
+ HANDLE hIcon;
+
+ if (hExtraXStatus == NULL)
+ {
+ if (xstatus > 0 && bXStatusExtraIconsReady < 2)
+ CListMW_ExtraIconsRebuild(0, 0);
+
+ hIcon = (xstatus <= 0 ? (HANDLE)-1 : hXStatusExtraIcons[xstatus-1]);
+
+ IconExtraColumn iec;
+
+ iec.cbSize = sizeof(iec);
+ iec.hImage = hIcon;
+ iec.ColumnType = EXTRA_ICON_ADV1;
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)&iec);
+ }
+ else
+ {
+ hIcon = (HANDLE) -1;
+
+ if (xstatus <= 0)
+ {
+ ExtraIcon_SetIcon(hExtraXStatus, hContact, (char *) NULL);
+ }
+ else
+ {
+ char szTemp[MAX_PATH];
+ null_snprintf(szTemp, sizeof(szTemp), "%s_xstatus%d", m_szModuleName, xstatus-1);
+ ExtraIcon_SetIcon(hExtraXStatus, hContact, szTemp);
+ }
+ }
+
+ NotifyEventHooks(hxstatusiconchanged, (WPARAM)hContact, (LPARAM)hIcon);
+}
+
+
+int CIcqProto::CListMW_ExtraIconsRebuild(WPARAM wParam, LPARAM lParam)
+{
+ if ((m_bXStatusEnabled || m_bMoodsEnabled) && ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+ for (int i = 0; i < XSTATUS_COUNT; i++)
+ {
+ hXStatusExtraIcons[i] = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)getXStatusIcon(i + 1, LR_SHARED), 0);
+ releaseXStatusIcon(i + 1, 0);
+ }
+
+ if (!bXStatusExtraIconsReady)
+ { // try to hook the events again if they did not existed during init
+ HookProtoEvent(ME_CLIST_EXTRA_LIST_REBUILD, &CIcqProto::CListMW_ExtraIconsRebuild);
+ HookProtoEvent(ME_CLIST_EXTRA_IMAGE_APPLY, &CIcqProto::CListMW_ExtraIconsApply);
+ }
+
+ bXStatusExtraIconsReady = 2;
+ }
+ return 0;
+}
+
+
+int CIcqProto::CListMW_ExtraIconsApply(WPARAM wParam, LPARAM lParam)
+{
+ if ((m_bXStatusEnabled || m_bMoodsEnabled) && ServiceExists(MS_CLIST_EXTRA_SET_ICON))
+ {
+ if (IsICQContact((HANDLE)wParam))
+ {
+ // only apply icons to our contacts, do not mess others
+ DWORD bXStatus = getContactXStatus((HANDLE)wParam);
+
+ if ((m_bXStatusEnabled && CheckContactCapabilities((HANDLE)wParam, CAPF_XSTATUS)) ||
+ (m_bMoodsEnabled && CheckContactCapabilities((HANDLE)wParam, CAPF_STATUS_MOOD)))
+ setContactExtraIcon((HANDLE)wParam, bXStatus);
+ }
+ }
+ return 0;
+}
+
+#define NULLCAP {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+capstr capXStatus[XSTATUS_COUNT] = {
+ {0x01, 0xD8, 0xD7, 0xEE, 0xAC, 0x3B, 0x49, 0x2A, 0xA5, 0x8D, 0xD3, 0xD8, 0x77, 0xE6, 0x6B, 0x92},
+ {0x5A, 0x58, 0x1E, 0xA1, 0xE5, 0x80, 0x43, 0x0C, 0xA0, 0x6F, 0x61, 0x22, 0x98, 0xB7, 0xE4, 0xC7},
+ {0x83, 0xC9, 0xB7, 0x8E, 0x77, 0xE7, 0x43, 0x78, 0xB2, 0xC5, 0xFB, 0x6C, 0xFC, 0xC3, 0x5B, 0xEC},
+ {0xE6, 0x01, 0xE4, 0x1C, 0x33, 0x73, 0x4B, 0xD1, 0xBC, 0x06, 0x81, 0x1D, 0x6C, 0x32, 0x3D, 0x81},
+ {0x8C, 0x50, 0xDB, 0xAE, 0x81, 0xED, 0x47, 0x86, 0xAC, 0xCA, 0x16, 0xCC, 0x32, 0x13, 0xC7, 0xB7},
+ {0x3F, 0xB0, 0xBD, 0x36, 0xAF, 0x3B, 0x4A, 0x60, 0x9E, 0xEF, 0xCF, 0x19, 0x0F, 0x6A, 0x5A, 0x7F},
+ {0xF8, 0xE8, 0xD7, 0xB2, 0x82, 0xC4, 0x41, 0x42, 0x90, 0xF8, 0x10, 0xC6, 0xCE, 0x0A, 0x89, 0xA6},
+ {0x80, 0x53, 0x7D, 0xE2, 0xA4, 0x67, 0x4A, 0x76, 0xB3, 0x54, 0x6D, 0xFD, 0x07, 0x5F, 0x5E, 0xC6},
+ {0xF1, 0x8A, 0xB5, 0x2E, 0xDC, 0x57, 0x49, 0x1D, 0x99, 0xDC, 0x64, 0x44, 0x50, 0x24, 0x57, 0xAF},
+ {0x1B, 0x78, 0xAE, 0x31, 0xFA, 0x0B, 0x4D, 0x38, 0x93, 0xD1, 0x99, 0x7E, 0xEE, 0xAF, 0xB2, 0x18},
+ {0x61, 0xBE, 0xE0, 0xDD, 0x8B, 0xDD, 0x47, 0x5D, 0x8D, 0xEE, 0x5F, 0x4B, 0xAA, 0xCF, 0x19, 0xA7},
+ {0x48, 0x8E, 0x14, 0x89, 0x8A, 0xCA, 0x4A, 0x08, 0x82, 0xAA, 0x77, 0xCE, 0x7A, 0x16, 0x52, 0x08},
+ {0x10, 0x7A, 0x9A, 0x18, 0x12, 0x32, 0x4D, 0xA4, 0xB6, 0xCD, 0x08, 0x79, 0xDB, 0x78, 0x0F, 0x09},
+ {0x6F, 0x49, 0x30, 0x98, 0x4F, 0x7C, 0x4A, 0xFF, 0xA2, 0x76, 0x34, 0xA0, 0x3B, 0xCE, 0xAE, 0xA7},
+ {0x12, 0x92, 0xE5, 0x50, 0x1B, 0x64, 0x4F, 0x66, 0xB2, 0x06, 0xB2, 0x9A, 0xF3, 0x78, 0xE4, 0x8D},
+ {0xD4, 0xA6, 0x11, 0xD0, 0x8F, 0x01, 0x4E, 0xC0, 0x92, 0x23, 0xC5, 0xB6, 0xBE, 0xC6, 0xCC, 0xF0},
+ {0x60, 0x9D, 0x52, 0xF8, 0xA2, 0x9A, 0x49, 0xA6, 0xB2, 0xA0, 0x25, 0x24, 0xC5, 0xE9, 0xD2, 0x60},
+ {0x63, 0x62, 0x73, 0x37, 0xA0, 0x3F, 0x49, 0xFF, 0x80, 0xE5, 0xF7, 0x09, 0xCD, 0xE0, 0xA4, 0xEE},
+ {0x1F, 0x7A, 0x40, 0x71, 0xBF, 0x3B, 0x4E, 0x60, 0xBC, 0x32, 0x4C, 0x57, 0x87, 0xB0, 0x4C, 0xF1},
+ {0x78, 0x5E, 0x8C, 0x48, 0x40, 0xD3, 0x4C, 0x65, 0x88, 0x6F, 0x04, 0xCF, 0x3F, 0x3F, 0x43, 0xDF},
+ {0xA6, 0xED, 0x55, 0x7E, 0x6B, 0xF7, 0x44, 0xD4, 0xA5, 0xD4, 0xD2, 0xE7, 0xD9, 0x5C, 0xE8, 0x1F},
+ {0x12, 0xD0, 0x7E, 0x3E, 0xF8, 0x85, 0x48, 0x9E, 0x8E, 0x97, 0xA7, 0x2A, 0x65, 0x51, 0xE5, 0x8D},
+ {0xBA, 0x74, 0xDB, 0x3E, 0x9E, 0x24, 0x43, 0x4B, 0x87, 0xB6, 0x2F, 0x6B, 0x8D, 0xFE, 0xE5, 0x0F},
+ {0x63, 0x4F, 0x6B, 0xD8, 0xAD, 0xD2, 0x4A, 0xA1, 0xAA, 0xB9, 0x11, 0x5B, 0xC2, 0x6D, 0x05, 0xA1},
+ {0x2C, 0xE0, 0xE4, 0xE5, 0x7C, 0x64, 0x43, 0x70, 0x9C, 0x3A, 0x7A, 0x1C, 0xE8, 0x78, 0xA7, 0xDC},
+ {0x10, 0x11, 0x17, 0xC9, 0xA3, 0xB0, 0x40, 0xF9, 0x81, 0xAC, 0x49, 0xE1, 0x59, 0xFB, 0xD5, 0xD4},
+ {0x16, 0x0C, 0x60, 0xBB, 0xDD, 0x44, 0x43, 0xF3, 0x91, 0x40, 0x05, 0x0F, 0x00, 0xE6, 0xC0, 0x09},
+ {0x64, 0x43, 0xC6, 0xAF, 0x22, 0x60, 0x45, 0x17, 0xB5, 0x8C, 0xD7, 0xDF, 0x8E, 0x29, 0x03, 0x52},
+ {0x16, 0xF5, 0xB7, 0x6F, 0xA9, 0xD2, 0x40, 0x35, 0x8C, 0xC5, 0xC0, 0x84, 0x70, 0x3C, 0x98, 0xFA},
+ {0x63, 0x14, 0x36, 0xff, 0x3f, 0x8a, 0x40, 0xd0, 0xa5, 0xcb, 0x7b, 0x66, 0xe0, 0x51, 0xb3, 0x64},
+ {0xb7, 0x08, 0x67, 0xf5, 0x38, 0x25, 0x43, 0x27, 0xa1, 0xff, 0xcf, 0x4c, 0xc1, 0x93, 0x97, 0x97},
+ {0xdd, 0xcf, 0x0e, 0xa9, 0x71, 0x95, 0x40, 0x48, 0xa9, 0xc6, 0x41, 0x32, 0x06, 0xd6, 0xf2, 0x80},
+ NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP,
+ NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP,
+ NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP,
+ NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP,
+ NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP, NULLCAP,
+ NULLCAP, NULLCAP, NULLCAP, NULLCAP};
+
+const char *nameXStatus[XSTATUS_COUNT] = {
+ LPGEN("Angry"), // 23
+ LPGEN("Taking a bath"), // 1
+ LPGEN("Tired"), // 2
+ LPGEN("Birthday"), // 3
+ LPGEN("Drinking beer"), // 4
+ LPGEN("Thinking"), // 5
+ LPGEN("Eating"), // 80
+ 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("Internet"), // 20
+ LPGEN("Working"), // 21
+ LPGEN("Typing"), // 22
+ LPGEN("Picnic"), // 66
+ LPGEN("Cooking"),
+ LPGEN("Smoking"),
+ LPGEN("I'm high"),
+ LPGEN("On WC"), // 68
+ LPGEN("To be or not to be"),// 77
+ LPGEN("Watching pro7 on TV"),
+ LPGEN("Love"), // 61
+ LPGEN("Hot Dog"), //6
+ LPGEN("Rough"), //24
+ LPGEN("Rock On"), //25
+ LPGEN("Baby"), //26
+ LPGEN("Soccer"), //27
+ LPGEN("Pirate"), //28
+ LPGEN("Cyclop"), //29
+ LPGEN("Monkey"), //30
+ LPGEN("Birdie"), //31
+ LPGEN("Cool"), //32
+ LPGEN("Evil"), //33
+ LPGEN("Alien"), //34
+ LPGEN("Scooter"), //35
+ LPGEN("Mask"), //36
+ LPGEN("Money"), //37
+ LPGEN("Pilot"), //38
+ LPGEN("Afro"), //39
+ LPGEN("St. Patrick"), //40
+ LPGEN("Headmaster"), //41
+ LPGEN("Lips"), //42
+ LPGEN("Ice-Cream"), //43
+ LPGEN("Pink Lady"), //44
+ LPGEN("Up yours"), //45
+ LPGEN("Laughing"), //46
+ LPGEN("Dog"), //47
+ LPGEN("Candy"), //48
+ LPGEN("Crazy Professor"),//50
+ LPGEN("Ninja"), //51
+ LPGEN("Cocktail"), //52
+ LPGEN("Punch"), //53
+ LPGEN("Donut"), //54
+ LPGEN("Feeling Good"), //55
+ LPGEN("Lollypop"), //56
+ LPGEN("Oink Oink"), //57
+ LPGEN("Kitty"), //58
+ LPGEN("Sumo"), //59
+ LPGEN("Broken hearted"),//60
+ LPGEN("Free for Chat"), //62
+ LPGEN("@home"), //63
+ LPGEN("@work"), //64
+ LPGEN("Strawberry"), //65
+ LPGEN("Angel"), //67
+ LPGEN("Pizza"), //69
+ LPGEN("Snoring"), //70
+ LPGEN("On my mobile"), //71
+ LPGEN("Depressed"), //72
+ LPGEN("Beetle"), //73
+ LPGEN("Double Rainbow"),//74
+ LPGEN("Basketball"), //75
+ LPGEN("Cupid shot me"), //76
+ LPGEN("Celebrating"), //78
+ LPGEN("Sushi"), //79
+ LPGEN("Playing"), //81
+ LPGEN("Writing") //84
+ };
+
+const int moodXStatus[XSTATUS_COUNT] = {
+ 23,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 80,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 0,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 66,
+ -1,
+ -1,
+ -1,
+ 68,
+ 77,
+ -1,
+ 61,
+ 6,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 62,
+ 63,
+ 64,
+ 65,
+ 67,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 78,
+ 79,
+ 81,
+ 84};
+
+void CIcqProto::handleXStatusCaps(DWORD dwUIN, char *szUID, HANDLE hContact, BYTE *caps, int capsize, char *moods, int moodsize)
+{
+ int bChanged = FALSE;
+ int nCustomStatusID = 0, nMoodID = 0;
+
+ if (!m_bXStatusEnabled && !m_bMoodsEnabled)
+ {
+ ClearContactCapabilities(hContact, CAPF_STATUS_MOOD | CAPF_XSTATUS);
+ return;
+ }
+ int nOldXStatusID = getContactXStatus(hContact);
+
+ if (m_bXStatusEnabled)
+ {
+ if (caps)
+ { // detect custom status capabilities
+ if (capsize > 0)
+ for (int i = 0; i < XSTATUS_COUNT; i++)
+ {
+ if (MatchCapability(caps, capsize, (const capstr*)capXStatus[i], BINARY_CAP_SIZE))
+ {
+ BYTE bXStatusId = (BYTE)(i+1);
+ char str[MAX_PATH];
+
+ SetContactCapabilities(hContact, CAPF_XSTATUS);
+
+ if (nOldXStatusID != bXStatusId)
+ { // only write default name when it is really needed, i.e. on Custom Status change
+ setSettingByte(hContact, DBSETTING_XSTATUS_ID, bXStatusId);
+ setSettingStringUtf(hContact, DBSETTING_XSTATUS_NAME, ICQTranslateUtfStatic(nameXStatus[i], str, MAX_PATH));
+ deleteSetting(hContact, DBSETTING_XSTATUS_MSG);
+
+ NetLog_Server("%s changed custom status to %s.", strUID(dwUIN, szUID), ICQTranslateUtfStatic(nameXStatus[i], str, MAX_PATH));
+ bChanged = TRUE;
+ }
+#ifdef _DEBUG
+ else
+ NetLog_Server("%s has custom status %s.", strUID(dwUIN, szUID), ICQTranslateUtfStatic(nameXStatus[i], str, MAX_PATH));
+#endif
+
+ if (getSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO))
+ requestXStatusDetails(hContact, TRUE);
+
+ nCustomStatusID = bXStatusId;
+
+ break;
+ }
+ }
+
+ if (nCustomStatusID == 0)
+ {
+#ifdef _DEBUG
+ if (m_iStatus != ID_STATUS_OFFLINE && CheckContactCapabilities(hContact, CAPF_XSTATUS))
+ NetLog_Server("%s has removed custom status.", strUID(dwUIN, szUID));
+#endif
+ ClearContactCapabilities(hContact, CAPF_XSTATUS);
+ }
+ }
+#ifdef _DEBUG
+ else if (CheckContactCapabilities(hContact, CAPF_XSTATUS))
+ {
+ char str[MAX_PATH];
+ NetLog_Server("%s has custom status %s.", strUID(dwUIN, szUID), ICQTranslateUtfStatic(nameXStatus[nOldXStatusID-1], str, MAX_PATH));
+ }
+#endif
+ }
+ if (m_bMoodsEnabled)
+ {
+ if (moods && moodsize < 32)
+ { // process custom statuses (moods) from ICQ6
+ if (moodsize > 0)
+ for (int i = 0; i < XSTATUS_COUNT; i++)
+ {
+ char szMoodId[32], szMoodData[32];
+
+ null_strcpy(szMoodData, moods, moodsize);
+
+ if (moodXStatus[i] == -1) continue;
+ null_snprintf(szMoodId, SIZEOF(szMoodId), "0icqmood%d", moodXStatus[i]);
+ if (!strcmpnull(szMoodId, szMoodData))
+ {
+ BYTE bXStatusId = (BYTE)(i+1);
+ char str[MAX_PATH];
+
+ SetContactCapabilities(hContact, CAPF_STATUS_MOOD);
+
+ if (nCustomStatusID == 0 && nOldXStatusID != bXStatusId)
+ { // only write default name when it is really needed, i.e. on Custom Status change
+ setSettingByte(hContact, DBSETTING_XSTATUS_ID, bXStatusId);
+ setSettingStringUtf(hContact, DBSETTING_XSTATUS_NAME, ICQTranslateUtfStatic(nameXStatus[i], str, MAX_PATH));
+ deleteSetting(hContact, DBSETTING_XSTATUS_MSG);
+
+ NetLog_Server("%s changed mood to %s.", strUID(dwUIN, szUID), ICQTranslateUtfStatic(nameXStatus[i], str, MAX_PATH));
+ bChanged = TRUE;
+ }
+#ifdef _DEBUG
+ else if (nOldXStatusID != bXStatusId)
+ NetLog_Server("%s changed mood to %s.", strUID(dwUIN, szUID), ICQTranslateUtfStatic(nameXStatus[i], str, MAX_PATH));
+ else
+ NetLog_Server("%s has mood %s.", strUID(dwUIN, szUID), ICQTranslateUtfStatic(nameXStatus[i], str, MAX_PATH));
+#endif
+ // cannot retrieve mood details here - need to be processed with new user details
+ nMoodID = bXStatusId;
+
+ break;
+ }
+ }
+
+ if (nMoodID == 0 && moods)
+ {
+#ifdef _DEBUG
+ if (m_iStatus != ID_STATUS_OFFLINE && CheckContactCapabilities(hContact, CAPF_STATUS_MOOD))
+ NetLog_Server("%s has removed mood.", strUID(dwUIN, szUID));
+#endif
+ ClearContactCapabilities(hContact, CAPF_STATUS_MOOD);
+ }
+ }
+#ifdef _DEBUG
+ else if (CheckContactCapabilities(hContact, CAPF_STATUS_MOOD))
+ { // Mood was not changed, but contact has one, add a small log notice
+ char str[MAX_PATH];
+ NetLog_Server("%s has mood %s.", strUID(dwUIN, szUID), ICQTranslateUtfStatic(nameXStatus[nOldXStatusID-1], str, MAX_PATH));
+ }
+#endif
+ }
+
+ if (nCustomStatusID != 0 && nMoodID != 0 && nCustomStatusID != nMoodID)
+ NetLog_Server("Warning: Diverse custom statuses detected, using custom status.");
+
+ if ((nCustomStatusID == 0 && (caps || !m_bXStatusEnabled)) && (nMoodID == 0 && (moods || !m_bMoodsEnabled)))
+ {
+ if (getSettingByte(hContact, DBSETTING_XSTATUS_ID, -1) != -1)
+ bChanged = TRUE;
+ deleteSetting(hContact, DBSETTING_XSTATUS_ID);
+ deleteSetting(hContact, DBSETTING_XSTATUS_NAME);
+ deleteSetting(hContact, DBSETTING_XSTATUS_MSG);
+ }
+
+ if (m_bXStatusEnabled != 10 && m_bMoodsEnabled != 10)
+ {
+ setContactExtraIcon(hContact, nCustomStatusID ? nCustomStatusID : (nMoodID ? nMoodID : (moods ? 0 : nOldXStatusID)));
+
+ if (bChanged)
+ NotifyEventHooks(hxstatuschanged, (WPARAM)hContact, 0);
+ }
+}
+
+
+void CIcqProto::updateServerCustomStatus(int fullUpdate)
+{
+ BYTE bXStatus = getContactXStatus(NULL);
+
+ if (fullUpdate)
+ { // update client capabilities
+ if (m_bXStatusEnabled)
+ setUserInfo();
+
+ char szMoodData[32];
+
+ // prepare mood id
+ if (m_bMoodsEnabled && bXStatus && moodXStatus[bXStatus-1] != -1)
+ null_snprintf(szMoodData, SIZEOF(szMoodData), "0icqmood%d", moodXStatus[bXStatus-1]);
+ else
+ szMoodData[0] = '\0';
+
+ SetStatusMood(szMoodData, 1500);
+ }
+
+ char *szStatusNote = NULL;
+
+ if (bXStatus && (m_bXStatusEnabled || m_bMoodsEnabled))
+ { // use custom status message as status note
+ szStatusNote = getSettingStringUtf(NULL, DBSETTING_XSTATUS_MSG, "");
+ }
+ else
+ { // retrieve standard status message (e.g. custom status set to none)
+ char **pszMsg = MirandaStatusToAwayMsg(m_iStatus);
+
+ m_modeMsgsMutex->Enter();
+ if (pszMsg)
+ szStatusNote = null_strdup(*pszMsg);
+ m_modeMsgsMutex->Leave();
+ // no default status message, set empty
+ if (!szStatusNote)
+ szStatusNote = null_strdup("");
+ }
+
+ if (szStatusNote)
+ SetStatusNote(szStatusNote, 1500, FALSE);
+
+ SAFE_FREE(&szStatusNote);
+}
+
+
+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 *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) * (strlennull(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 CallWindowProc(OldMessageEditProc,hwnd,msg,wParam,lParam);
+}
+
+struct SetXStatusData
+{
+ CIcqProto* ppro;
+ BYTE bAction;
+ BYTE bXStatus;
+ HANDLE hContact;
+ HANDLE hEvent;
+ DWORD iEvent;
+ int countdown;
+ char* okButtonFormat;
+};
+
+struct InitXStatusData
+{
+ CIcqProto* ppro;
+ BYTE bAction;
+ BYTE bXStatus;
+ char* szXStatusName;
+ char* szXStatusMsg;
+ HANDLE hContact;
+};
+
+#define HM_PROTOACK (WM_USER+10)
+static INT_PTR CALLBACK SetXStatusDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam)
+{
+ SetXStatusData *dat = (SetXStatusData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ char str[MAX_PATH];
+
+ switch(message) {
+ case HM_PROTOACK:
+ {
+ ACKDATA *ack = (ACKDATA*)lParam;
+ if (ack->type != ICQACKTYPE_XSTATUS_RESPONSE) break;
+ if (ack->hContact != dat->hContact) break;
+ if ((DWORD)ack->hProcess != dat->iEvent) break;
+
+ ShowDlgItem(hwndDlg, IDC_RETRXSTATUS, SW_HIDE);
+ ShowDlgItem(hwndDlg, IDC_XMSG, SW_SHOW);
+ ShowDlgItem(hwndDlg, IDC_XTITLE, SW_SHOW);
+ SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic(LPGEN("Close"), str, MAX_PATH));
+ UnhookEvent(dat->hEvent); dat->hEvent = NULL;
+ char *szText = dat->ppro->getSettingStringUtf(dat->hContact, DBSETTING_XSTATUS_NAME, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, szText);
+ SAFE_FREE(&szText);
+ szText = dat->ppro->getSettingStringUtf(dat->hContact, DBSETTING_XSTATUS_MSG, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XMSG, szText);
+ SAFE_FREE(&szText);
+ }
+ break;
+
+ case WM_INITDIALOG:
+ {
+ InitXStatusData *init = (InitXStatusData*)lParam;
+
+ TranslateDialogDefault(hwndDlg);
+ dat = (SetXStatusData*)SAFE_MALLOC(sizeof(SetXStatusData));
+ dat->ppro = init->ppro;
+ SetWindowLongPtr(hwndDlg,GWLP_USERDATA,(LONG_PTR)dat);
+ dat->bAction = init->bAction;
+
+ if (!init->bAction)
+ { // set our xStatus
+ dat->bXStatus = init->bXStatus;
+ SendDlgItemMessage(hwndDlg, IDC_XMSG, EM_LIMITTEXT, 1024, 0);
+ OldMessageEditProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_XMSG),GWLP_WNDPROC,(LONG_PTR)MessageEditSubclassProc);
+ SetDlgItemTextUtf(hwndDlg, IDC_XMSG, init->szXStatusMsg);
+
+ if (dat->ppro->m_bXStatusEnabled)
+ { // custom status enabled, prepare title edit
+ SendDlgItemMessage(hwndDlg, IDC_XTITLE, EM_LIMITTEXT, 256, 0);
+ OldMessageEditProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_XTITLE),GWLP_WNDPROC,(LONG_PTR)MessageEditSubclassProc);
+ SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, init->szXStatusName);
+ }
+ else
+ { // only moods enabled, hide title, resize message edit control
+ ShowDlgItem(hwndDlg, IDC_XTITLE_STATIC, SW_HIDE);
+ ShowDlgItem(hwndDlg, IDC_XTITLE, SW_HIDE);
+ MoveDlgItem(hwndDlg, IDC_XMSG_STATIC, 5, 0, 179, 8);
+ MoveDlgItem(hwndDlg, IDC_XMSG, 5, 9, 179, 65);
+ }
+
+ dat->okButtonFormat = GetDlgItemTextUtf(hwndDlg,IDOK);
+ 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 = dat->ppro->getContactXStatus(dat->hContact);
+ dat->okButtonFormat = NULL;
+ SendMessage(GetDlgItem(hwndDlg, IDC_XTITLE), EM_SETREADONLY, 1, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_XMSG), EM_SETREADONLY, 1, 0);
+
+ if (dat->ppro->CheckContactCapabilities(dat->hContact, CAPF_XSTATUS) && !dat->ppro->getSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO))
+ {
+ SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic(LPGEN("Cancel"), str, MAX_PATH));
+ dat->hEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_PROTOACK);
+ ShowDlgItem(hwndDlg, IDC_RETRXSTATUS, SW_SHOW);
+ ShowDlgItem(hwndDlg, IDC_XMSG, SW_HIDE);
+ ShowDlgItem(hwndDlg, IDC_XTITLE, SW_HIDE);
+ dat->iEvent = dat->ppro->requestXStatusDetails(dat->hContact, FALSE);
+ }
+ else
+ {
+ SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic(LPGEN("Close"), str, MAX_PATH));
+ dat->hEvent = NULL;
+ char *szText = dat->ppro->getSettingStringUtf(dat->hContact, DBSETTING_XSTATUS_NAME, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, szText);
+ SAFE_FREE(&szText);
+
+ if (dat->ppro->CheckContactCapabilities(dat->hContact, CAPF_STATUS_MOOD) && !dat->ppro->CheckContactCapabilities(dat->hContact, CAPF_XSTATUS))
+ { // only for clients supporting just moods and not custom status
+ szText = dat->ppro->getSettingStringUtf(dat->hContact, DBSETTING_STATUS_NOTE, "");
+ // hide title, resize message edit control
+ ShowDlgItem(hwndDlg, IDC_XTITLE_STATIC, SW_HIDE);
+ ShowDlgItem(hwndDlg, IDC_XTITLE, SW_HIDE);
+ MoveDlgItem(hwndDlg, IDC_XMSG_STATIC, 5, 0, 179, 8);
+ MoveDlgItem(hwndDlg, IDC_XMSG, 5, 9, 179, 65);
+ }
+ else
+ szText = dat->ppro->getSettingStringUtf(dat->hContact, DBSETTING_XSTATUS_MSG, "");
+
+ SetDlgItemTextUtf(hwndDlg, IDC_XMSG, szText);
+ SAFE_FREE(&szText);
+ }
+ }
+
+ if (dat->bXStatus)
+ {
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)dat->ppro->getXStatusIcon(dat->bXStatus, LR_SHARED | LR_BIGICON));
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)dat->ppro->getXStatusIcon(dat->bXStatus, LR_SHARED));
+ }
+
+ char buf[MAX_PATH];
+ char *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(LPGEN("OK"), str, MAX_PATH));
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ if (!dat->bAction)
+ { // set our xStatus
+ char szSetting[64];
+ char *szValue;
+
+ dat->ppro->setSettingByte(NULL, DBSETTING_XSTATUS_ID, dat->bXStatus);
+ szValue = GetDlgItemTextUtf(hwndDlg,IDC_XMSG);
+ null_snprintf(szSetting, 64, "XStatus%dMsg", dat->bXStatus);
+ dat->ppro->setSettingStringUtf(NULL, szSetting, szValue);
+ dat->ppro->setSettingStringUtf(NULL, DBSETTING_XSTATUS_MSG, szValue);
+ SAFE_FREE(&szValue);
+
+ if (dat->ppro->m_bXStatusEnabled)
+ {
+ szValue = GetDlgItemTextUtf(hwndDlg,IDC_XTITLE);
+ null_snprintf(szSetting, 64, "XStatus%dName", dat->bXStatus);
+ dat->ppro->setSettingStringUtf(NULL, szSetting, szValue);
+ dat->ppro->setSettingStringUtf(NULL, DBSETTING_XSTATUS_NAME, szValue);
+ SAFE_FREE(&szValue);
+
+ if (dat->bXStatus)
+ {
+ dat->ppro->releaseXStatusIcon(dat->bXStatus, LR_BIGICON);
+ dat->ppro->releaseXStatusIcon(dat->bXStatus, 0);
+ }
+ }
+ dat->ppro->updateServerCustomStatus(TRUE);
+
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_XMSG),GWLP_WNDPROC,(LONG_PTR)OldMessageEditProc);
+ if (dat->ppro->m_bXStatusEnabled)
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_XTITLE),GWLP_WNDPROC,(LONG_PTR)OldMessageEditProc);
+ }
+ if (dat->hEvent) UnhookEvent(dat->hEvent);
+ SAFE_FREE(&dat->okButtonFormat);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, NULL);
+ SAFE_FREE((void**)&dat);
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ return FALSE;
+}
+
+
+void CIcqProto::setXStatusEx(BYTE bXStatus, BYTE bQuiet)
+{
+ CLISTMENUITEM mi = {0};
+ BYTE bOldXStatus = getSettingByte(NULL, DBSETTING_XSTATUS_ID, 0);
+
+ mi.cbSize = sizeof(mi);
+
+ if (!m_bHideXStatusUI)
+ {
+ if (bOldXStatus <= XSTATUS_COUNT)
+ {
+ 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 = NULL, *szMsg = NULL;
+
+ if (m_bXStatusEnabled)
+ {
+ null_snprintf(szSetting, 64, "XStatus%dName", bXStatus);
+ szName = getSettingStringUtf(NULL, szSetting, ICQTranslateUtfStatic(nameXStatus[bXStatus-1], str, MAX_PATH));
+ }
+ null_snprintf(szSetting, 64, "XStatus%dMsg", bXStatus);
+ szMsg = getSettingStringUtf(NULL, szSetting, "");
+
+ null_snprintf(szSetting, 64, "XStatus%dStat", bXStatus);
+ if (!bQuiet && !getSettingByte(NULL, szSetting, 0))
+ {
+ InitXStatusData init;
+ init.ppro = this;
+ init.bAction = 0; // set
+ init.bXStatus = bXStatus;
+ init.szXStatusName = szName;
+ init.szXStatusMsg = szMsg;
+ CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SETXSTATUS), NULL, SetXStatusDlgProc, (LPARAM)&init);
+ }
+ else
+ {
+ setSettingByte(NULL, DBSETTING_XSTATUS_ID, bXStatus);
+ if (m_bXStatusEnabled)
+ setSettingStringUtf(NULL, DBSETTING_XSTATUS_NAME, szName);
+ setSettingStringUtf(NULL, DBSETTING_XSTATUS_MSG, szMsg);
+
+ updateServerCustomStatus(TRUE);
+ }
+ SAFE_FREE(&szName);
+ SAFE_FREE(&szMsg);
+ }
+ else
+ {
+ setSettingByte(NULL, DBSETTING_XSTATUS_ID, bXStatus);
+ deleteSetting(NULL, DBSETTING_XSTATUS_NAME);
+ deleteSetting(NULL, DBSETTING_XSTATUS_MSG);
+
+ updateServerCustomStatus(TRUE);
+ }
+}
+
+
+INT_PTR CIcqProto::menuXStatus(WPARAM wParam,LPARAM lParam,LPARAM fParam)
+{
+ setXStatusEx((BYTE)fParam, 0);
+ return 0;
+}
+
+
+void CIcqProto::InitXStatusItems(BOOL bAllowStatus)
+{
+ CLISTMENUITEM mi;
+ int i = 0, len = strlennull(m_szModuleName);
+ char srvFce[MAX_PATH + 64];
+ char szItem[MAX_PATH + 64];
+ HANDLE hXStatusRoot;
+ int bXStatusMenuBuilt = 0;
+
+ BYTE bXStatus = getContactXStatus(NULL);
+
+ if (!m_bXStatusEnabled && !m_bMoodsEnabled) return;
+
+ if (!bAllowStatus) return;
+
+ // Custom Status UI is disabled, no need to continue items' init
+ if (m_bHideXStatusUI || m_bHideXStatusMenu) return;
+
+ null_snprintf(szItem, sizeof(szItem), Translate("%s Custom Status"), m_szModuleName);
+ mi.cbSize = sizeof(mi);
+ mi.pszPopupName = szItem;
+ mi.popupPosition= 500084000;
+ mi.position = 2000040000;
+
+ for (i = 0; i <= XSTATUS_COUNT; i++)
+ {
+ null_snprintf(srvFce, sizeof(srvFce), "%s/menuXStatus%d", m_szModuleName, i);
+
+ mi.position++;
+
+ if (!i)
+ bXStatusMenuBuilt = ServiceExists(srvFce);
+
+ if (!bXStatusMenuBuilt)
+ CreateProtoServiceParam(srvFce+len, &CIcqProto::menuXStatus, i);
+
+ mi.flags = (i ? CMIF_ICONFROMICOLIB : 0) | (bXStatus == i?CMIF_CHECKED:0);
+ mi.icolibItem = i ? hXStatusIcons[i-1]->Handle() : NULL;
+ mi.pszName = i ? (char*)nameXStatus[i-1] : (char *)LPGEN("None");
+ mi.pszService = srvFce;
+ mi.pszContactOwner = m_szModuleName;
+
+ hXStatusItems[i] = (HANDLE)CallService(MS_CLIST_ADDSTATUSMENUITEM, (WPARAM)&hXStatusRoot, (LPARAM)&mi);
+
+ // CMIF_HIDDEN does not work for adding services
+ CListShowMenuItem(hXStatusItems[i], !(m_bHideXStatusUI || m_bHideXStatusMenu));
+ }
+}
+
+
+void CIcqProto::InitXStatusIcons()
+{
+ if (!m_bXStatusEnabled && !m_bMoodsEnabled)
+ return;
+
+ TCHAR lib[2*MAX_PATH] = {0};
+ TCHAR *icon_lib = InitXStatusIconLibrary(lib, SIZEOF(lib));
+
+ char szSection[MAX_PATH + 64], *szAccountName = tchar_to_utf8(m_tszUserName);
+ null_snprintf(szSection, sizeof(szSection), "Status Icons/%s/Custom Status", szAccountName);
+ SAFE_FREE(&szAccountName);
+
+ for (int i = 0; i < XSTATUS_COUNT; i++)
+ {
+ char szTemp[64];
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", i);
+ hXStatusIcons[i] = IconLibDefine(nameXStatus[i], szSection, m_szModuleName, szTemp, icon_lib, -(IDI_XSTATUS1+i));
+ }
+
+ // initialize arrays for CList custom status icons
+ memset(bXStatusCListIconsValid, 0, sizeof(bXStatusCListIconsValid));
+ memset(hXStatusCListIcons, -1, sizeof(hXStatusCListIcons));
+}
+
+
+void CIcqProto::UninitXStatusIcons()
+{
+ for (int i = 0; i < XSTATUS_COUNT; i++)
+ IconLibRemove(&hXStatusIcons[i]);
+
+ // clear clist icon state indicators
+ memset(bXStatusCListIconsValid, 0, sizeof(bXStatusCListIconsValid));
+}
+
+
+INT_PTR CIcqProto::ShowXStatusDetails(WPARAM wParam, LPARAM lParam)
+{
+ InitXStatusData init;
+ init.ppro = this;
+ init.bAction = 1; // retrieve
+ init.hContact = (HANDLE)wParam;
+ CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SETXSTATUS), NULL, SetXStatusDlgProc, (LPARAM)&init);
+
+ return 0;
+}
+
+INT_PTR CIcqProto::SetXStatus(WPARAM wParam, LPARAM lParam)
+{ // obsolete (TODO: remove in next version)
+ if (!m_bXStatusEnabled && !m_bMoodsEnabled) return 0;
+
+ if (wParam >= 0 && wParam <= XSTATUS_COUNT)
+ {
+ setXStatusEx((BYTE)wParam, 1);
+ return wParam;
+ }
+ return 0;
+}
+
+
+INT_PTR CIcqProto::GetXStatus(WPARAM wParam, LPARAM lParam)
+{ // obsolete (TODO: remove in next version)
+ if (!m_bXStatusEnabled && !m_bMoodsEnabled) return 0;
+
+ if (!icqOnline()) return 0;
+
+ BYTE status = getContactXStatus(NULL);
+
+ if (wParam) *((char**)wParam) = m_bXStatusEnabled ? DBSETTING_XSTATUS_NAME : NULL;
+ if (lParam) *((char**)lParam) = DBSETTING_XSTATUS_MSG;
+
+ return status;
+}
+
+
+INT_PTR CIcqProto::SetXStatusEx(WPARAM wParam, LPARAM lParam)
+{
+ ICQ_CUSTOM_STATUS *pData = (ICQ_CUSTOM_STATUS*)lParam;
+
+ if (!m_bXStatusEnabled && !m_bMoodsEnabled) return 1;
+
+ if (pData->cbSize < sizeof(ICQ_CUSTOM_STATUS)) return 1; // Failure
+
+ if (pData->flags & CSSF_MASK_STATUS)
+ { // set custom status
+ int status = *pData->status;
+
+ if (status >= 0 && status <= XSTATUS_COUNT)
+ setXStatusEx((BYTE)status, 1);
+ else
+ return 1; // Failure
+ }
+
+ if (pData->flags & (CSSF_MASK_NAME | CSSF_MASK_MESSAGE))
+ {
+ BYTE status = getContactXStatus(NULL);
+
+ if (!status) return 1; // Failure
+
+ if (m_bXStatusEnabled && (pData->flags & CSSF_MASK_NAME))
+ { // set custom status name
+ if (pData->flags & CSSF_UNICODE)
+ setSettingStringW(NULL, DBSETTING_XSTATUS_NAME, pData->pwszName);
+ else
+ setSettingString(NULL, DBSETTING_XSTATUS_NAME, pData->pszName);
+ }
+ if (pData->flags & CSSF_MASK_MESSAGE)
+ { // set custom status message
+ if (pData->flags & CSSF_UNICODE)
+ setSettingStringW(NULL, DBSETTING_XSTATUS_MSG, pData->pwszMessage);
+ else
+ setSettingString(NULL, DBSETTING_XSTATUS_MSG, pData->pszMessage);
+
+ // update status note if used for custom status message
+ updateServerCustomStatus(FALSE);
+ }
+ }
+
+ if (pData->flags & CSSF_DISABLE_UI)
+ { // hide menu items + contact menu item
+ m_bHideXStatusUI = (*pData->wParam) ? 0 : 1;
+ }
+
+ if (pData->flags & CSSF_DISABLE_MENU)
+ { // hide menu items only
+ m_bHideXStatusMenu = (*pData->wParam) ? 0 : 1;
+ }
+
+ return 0; // Success
+}
+
+
+INT_PTR CIcqProto::GetXStatusEx(WPARAM wParam, LPARAM lParam)
+{
+ ICQ_CUSTOM_STATUS *pData = (ICQ_CUSTOM_STATUS*)lParam;
+ HANDLE hContact = (HANDLE)wParam;
+
+ if (!m_bXStatusEnabled && !m_bMoodsEnabled) return 1;
+
+ if (pData->cbSize < sizeof(ICQ_CUSTOM_STATUS)) return 1; // Failure
+
+ if (pData->flags & CSSF_MASK_STATUS)
+ { // fill status member
+ *pData->status = getContactXStatus(hContact);
+ }
+
+ if (pData->flags & CSSF_MASK_NAME)
+ { // fill status name member
+ if (pData->flags & CSSF_DEFAULT_NAME)
+ {
+ int status = *pData->wParam;
+
+ if (status < 1 || status > XSTATUS_COUNT) 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, (char*)nameXStatus[status - 1]);
+ }
+ else
+ { // moods does not support status title
+ if (!m_bXStatusEnabled) return 1;
+
+ if (pData->flags & CSSF_UNICODE)
+ {
+ char *str = getSettingStringUtf(hContact, DBSETTING_XSTATUS_NAME, "");
+ WCHAR *wstr = make_unicode_string(str);
+
+ wcscpy(pData->pwszName, wstr);
+ SAFE_FREE(&str);
+ SAFE_FREE(&wstr);
+ }
+ else
+ {
+ DBVARIANT dbv = {0};
+
+ if (!getSettingString(hContact, DBSETTING_XSTATUS_NAME, &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 = getSettingStringUtf(hContact, CheckContactCapabilities(hContact, CAPF_STATUS_MOOD) ? DBSETTING_STATUS_NOTE : DBSETTING_XSTATUS_MSG, "");
+ WCHAR *wstr = make_unicode_string(str);
+
+ wcscpy(pData->pwszMessage, wstr);
+ SAFE_FREE(&str);
+ SAFE_FREE(&wstr);
+ }
+ else
+ {
+ DBVARIANT dbv = {0};
+
+ if (!getSettingString(hContact, CheckContactCapabilities(hContact, CAPF_STATUS_MOOD) ? DBSETTING_STATUS_NOTE : DBSETTING_XSTATUS_MSG, &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 = !m_bHideXStatusUI;
+ }
+
+ if (pData->flags & CSSF_DISABLE_MENU)
+ {
+ if (pData->wParam) *pData->wParam = !m_bHideXStatusMenu;
+ }
+
+ if (pData->flags & CSSF_STATUSES_COUNT)
+ {
+ if (pData->wParam) *pData->wParam = XSTATUS_COUNT;
+ }
+
+ if (pData->flags & CSSF_STR_SIZES)
+ {
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ if (pData->wParam)
+ {
+ if (m_bXStatusEnabled && !getSettingString(hContact, DBSETTING_XSTATUS_NAME, &dbv))
+ *pData->wParam = strlennull(dbv.pszVal);
+ else
+ *pData->wParam = 0;
+ ICQFreeVariant(&dbv);
+ }
+ if (pData->lParam)
+ {
+ if (!getSettingString(hContact, CheckContactCapabilities(hContact, CAPF_STATUS_MOOD) ? DBSETTING_STATUS_NOTE : DBSETTING_XSTATUS_MSG, &dbv))
+ *pData->lParam = strlennull(dbv.pszVal);
+ else
+ *pData->lParam = 0;
+ ICQFreeVariant(&dbv);
+ }
+ }
+
+ return 0; // Success
+}
+
+
+INT_PTR CIcqProto::GetXStatusIcon(WPARAM wParam, LPARAM lParam)
+{
+ if (!m_bXStatusEnabled && !m_bMoodsEnabled) return 0;
+
+ if (!wParam)
+ wParam = getContactXStatus(NULL);
+
+ if (wParam >= 1 && wParam <= XSTATUS_COUNT)
+ {
+ return (INT_PTR)getXStatusIcon((BYTE)wParam, lParam);
+ }
+ return 0;
+}
+
+
+INT_PTR CIcqProto::RequestXStatusDetails(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+
+ if (!m_bXStatusEnabled) return 0;
+
+ if (hContact && !getSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO) &&
+ getContactXStatus(hContact) && CheckContactCapabilities(hContact, CAPF_XSTATUS))
+ { // user has xstatus, no auto-retrieve details, valid contact, request details
+ return requestXStatusDetails(hContact, TRUE);
+ }
+ return 0;
+}
+
+
+INT_PTR CIcqProto::RequestAdvStatusIconIdx(WPARAM wParam, LPARAM lParam)
+{
+ if (!m_bXStatusEnabled && !m_bMoodsEnabled) return -1;
+
+ BYTE bXStatus = getContactXStatus((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;
+
+ releaseXStatusIcon(bXStatus, 0);
+ }
+ }
+ idx = bXStatusCListIconsValid[bXStatus-1] ? hXStatusCListIcons[bXStatus-1] : -1;
+
+ if (idx > 0)
+ return (idx & 0xFFFF) << 16;
+ }
+ return -1;
+}
diff --git a/protocols/IcqOscarJ/icq_xtraz.cpp b/protocols/IcqOscarJ/icq_xtraz.cpp
new file mode 100644
index 0000000000..a4152fc5ea
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_xtraz.cpp
@@ -0,0 +1,473 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_xtraz.cpp $
+// Revision : $Revision: 13678 $
+// Last change on : $Date: 2011-07-04 00:53:23 +0300 (Пн, 04 июл 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Internal Xtraz API
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+void CIcqProto::handleXtrazNotify(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC)
+{
+ char *szNotify = strstrnull(szMsg, "<NOTIFY>");
+ char *szQuery = strstrnull(szMsg, "<QUERY>");
+
+ HANDLE hContact = HContactFromUIN(dwUin, NULL);
+ if (hContact) // user sent us xtraz, he supports it
+ SetContactCapabilities(hContact, CAPF_XTRAZ);
+
+ if (szNotify && szQuery)
+ { // valid request
+ char *szWork, *szEnd;
+ int nNotifyLen, nQueryLen;
+
+ szNotify += 8;
+ szQuery += 7;
+ szEnd = strstrnull(szMsg, "</NOTIFY>");
+ if (!szEnd) szEnd = szMsg + nMsgLen;
+ nNotifyLen = (szEnd - szNotify);
+ szEnd = strstrnull(szMsg, "</QUERY>");
+ if (!szEnd) szEnd = szNotify;
+ szNotify = DemangleXml(szNotify, nNotifyLen);
+ nQueryLen = (szEnd - szQuery);
+ szQuery = DemangleXml(szQuery, nQueryLen);
+ szWork = strstrnull(szQuery, "<PluginID>");
+ szEnd = strstrnull(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 (!stricmpnull(szWork, "srvMng") && strstrnull(szNotify, "AwayStat"))
+ {
+ char *szSender = strstrnull(szNotify, "<senderId>");
+ char *szEndSend = strstrnull(szNotify, "</senderId>");
+
+ if (szSender && szEndSend)
+ {
+ szSender += 10;
+ *szEndSend = '\0';
+
+ if ((DWORD)atoi(szSender) == dwUin)
+ {
+ BYTE dwXId = m_bXStatusEnabled ? getContactXStatus(NULL) : 0;
+
+ if (dwXId && validateStatusMessageRequest(hContact, MTYPE_SCRIPT_NOTIFY))
+ { // apply privacy rules
+ NotifyEventHooks(m_modeMsgsEvent, (WPARAM)MTYPE_SCRIPT_NOTIFY, (LPARAM)dwUin);
+
+ char *tmp = getSettingStringUtf(NULL, DBSETTING_XSTATUS_NAME, "");
+ char *szXName = MangleXml(tmp, strlennull(tmp));
+ SAFE_FREE(&tmp);
+
+ tmp = getSettingStringUtf(NULL, DBSETTING_XSTATUS_MSG, "");
+ char *szXMsg = MangleXml(tmp, strlennull(tmp));
+ SAFE_FREE(&tmp);
+
+ int nResponseLen = 212 + strlennull(szXName) + strlennull(szXMsg) + UINMAXLEN + 2;
+ char *szResponse = (char*)_alloca(nResponseLen + 1);
+ // send response
+ 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>",
+ m_dwLocalUIN, dwXId, szXName, szXMsg);
+
+ SAFE_FREE(&szXName);
+ SAFE_FREE(&szXMsg);
+
+ struct rates_xstatus_response: public rates_queue_item {
+ protected:
+ virtual rates_queue_item* copyItem(rates_queue_item *aDest = NULL) {
+ rates_xstatus_response *pDest = (rates_xstatus_response*)aDest;
+ if (!pDest)
+ pDest = new rates_xstatus_response(ppro, wGroup);
+
+ pDest->bThruDC = bThruDC;
+ pDest->dwMsgID1 = dwMsgID1;
+ pDest->dwMsgID2 = dwMsgID2;
+ pDest->wCookie = wCookie;
+ pDest->szResponse = null_strdup(szResponse);
+
+ return rates_queue_item::copyItem(pDest);
+ };
+ public:
+ rates_xstatus_response(CIcqProto *ppro, WORD wGroup): rates_queue_item(ppro, wGroup), szResponse(NULL) { };
+ virtual ~rates_xstatus_response() { if (bCreated) SAFE_FREE(&szResponse); };
+
+ virtual void execute() {
+ ppro->SendXtrazNotifyResponse(dwUin, dwMsgID1, dwMsgID2, wCookie, szResponse, strlennull(szResponse), bThruDC);
+ };
+
+ BOOL bThruDC;
+ DWORD dwMsgID1;
+ DWORD dwMsgID2;
+ WORD wCookie;
+ char *szResponse;
+ };
+
+ m_ratesMutex->Enter();
+ WORD wGroup = m_rates->getGroupFromSNAC(ICQ_MSG_FAMILY, ICQ_MSG_RESPONSE);
+ m_ratesMutex->Leave();
+
+ rates_xstatus_response rr(this, wGroup);
+ rr.hContact = hContact;
+ rr.dwUin = dwUin;
+ rr.bThruDC = bThruDC;
+ rr.dwMsgID1 = dwMID;
+ rr.dwMsgID2 = dwMID2;
+ rr.wCookie = wCookie;
+ rr.szResponse = szResponse;
+
+ handleRateItem(&rr, RQT_RESPONSE, 0, !bThruDC);
+ }
+ else if (dwXId)
+ NetLog_Server("Privacy: Ignoring XStatus request");
+ else
+ NetLog_Server("Error: We are not in XStatus, skipping");
+ }
+ else
+ NetLog_Server("Error: Invalid sender information");
+ }
+ else
+ NetLog_Server("Error: Missing sender information");
+ }
+ else
+ NetLog_Server("Error: Unknown plugin \"%s\" in Xtraz message", szWork);
+ }
+ else
+ NetLog_Server("Error: Missing PluginID in Xtraz message");
+
+ SAFE_FREE(&szNotify);
+ SAFE_FREE(&szQuery);
+ }
+ else
+ NetLog_Server("Error: Invalid Xtraz Notify message");
+}
+
+
+void CIcqProto::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 = strstrnull(szMsg, "<RES>");
+ szEnd = strstrnull(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
+
+ BroadcastAck(hContact, ICQACKTYPE_XTRAZNOTIFY_RESPONSE, ACKRESULT_SUCCESS, (HANDLE)wCookie, (LPARAM)szRes);
+
+NextVal:
+ szNode = strstrnull(szRes, "<val srv_id=");
+ if (szNode) szEnd = strstrnull(szNode, ">"); else szEnd = NULL;
+
+ if (szNode && szEnd)
+ {
+ *(szEnd-1) = '\0';
+ szNode += 13; //one more than the length of the string to skip ' or " too
+ szWork = szEnd + 1;
+
+ if (!stricmpnull(szNode, "cAwaySrv"))
+ {
+ int bChanged = FALSE;
+
+ *szEnd = ' ';
+ szNode = strstrnull(szWork, "<index>");
+ szEnd = strstrnull(szWork, "</index>");
+ if (szNode && szEnd)
+ {
+ szNode += 7;
+ *szEnd = '\0';
+ if (atoi(szNode) != getContactXStatus(hContact))
+ { // this is strange - but go on
+ NetLog_Server("Warning: XStatusIds do not match!");
+ }
+ *szEnd = ' ';
+ }
+ szNode = strstrnull(szWork, "<title>");
+ szEnd = strstrnull(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 = getSettingStringUtf(hContact, DBSETTING_XSTATUS_NAME, NULL);
+ if (strcmpnull(szOldXName, szXName))
+ bChanged = TRUE;
+ SAFE_FREE(&szOldXName);
+ setSettingStringUtf(hContact, DBSETTING_XSTATUS_NAME, szXName);
+ SAFE_FREE(&szXName);
+ *szEnd = ' ';
+ }
+ szNode = strstrnull(szWork, "<desc>");
+ szEnd = strstrnull(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 = getSettingStringUtf(hContact, DBSETTING_XSTATUS_NAME, NULL);
+ if (strcmpnull(szOldXMsg, szXMsg))
+ bChanged = TRUE;
+ SAFE_FREE(&szOldXMsg);
+ setSettingStringUtf(hContact, DBSETTING_XSTATUS_MSG, szXMsg);
+ SAFE_FREE(&szXMsg);
+ }
+ BroadcastAck(hContact, ICQACKTYPE_XSTATUS_RESPONSE, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
+ if (bChanged)
+ NotifyEventHooks(hxstatuschanged, (WPARAM)hContact, 0);
+ }
+ else
+ {
+ char *szSrvEnd = strstrnull(szEnd, "</srv>");
+
+ if (szSrvEnd && strstrnull(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)
+{
+ const char *szPid, *szEnd;
+
+ szPid = strstrnull(szData, "<PID>");
+ szEnd = strstrnull(szData, "</PID>");
+
+ if (szPid && szEnd)
+ {
+ szPid += 5;
+
+ return DemangleXml(szPid, szEnd - szPid);
+ }
+ return NULL;
+}
+
+
+void CIcqProto::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 CIcqProto::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 = strstrnull(szMsg, "<InD>");
+ szEnd = strstrnull(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 = strstrnull(szUrl, ".html");
+ if (szWork)
+ {
+ strcpy(szWork, ".php");
+ strcat(szWork, szWork+5);
+ }
+ while (szWork = strstrnull(szUrl, "&amp;"))
+ { // unescape &amp; code
+ strcpy(szWork+1, szWork+5);
+ }
+ szWork = (char*)SAFE_MALLOC(nDataLen + MAX_PATH);
+ ICQTranslateUtfStatic(LPGEN("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;
+ 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 CIcqProto::SendXtrazNotifyRequest(HANDLE hContact, char* szQuery, char* szNotify, int bForced)
+{
+ char *szQueryBody;
+ char *szNotifyBody;
+ DWORD dwUin;
+ int nBodyLen;
+ char *szBody;
+ DWORD dwCookie;
+
+ if (getContactUid(hContact, &dwUin, NULL))
+ return 0; // Invalid contact
+
+ if (!CheckContactCapabilities(hContact, CAPF_XTRAZ) && !bForced)
+ return 0; // Contact does not support xtraz, do not send anything
+
+ szQueryBody = MangleXml(szQuery, strlennull(szQuery));
+ szNotifyBody = MangleXml(szNotify, strlennull(szNotify));
+ nBodyLen = strlennull(szQueryBody) + strlennull(szNotifyBody) + 41;
+ szBody = (char*)_alloca(nBodyLen);
+ nBodyLen = null_snprintf(szBody, nBodyLen, "<N><QUERY>%s</QUERY><NOTIFY>%s</NOTIFY></N>", szQueryBody, szNotifyBody);
+ SAFE_FREE((void**)&szQueryBody);
+ SAFE_FREE((void**)&szNotifyBody);
+
+ // Set up the ack type
+ cookie_message_data *pCookieData = CreateMessageCookie(MTYPE_SCRIPT_NOTIFY, ACKTYPE_CLIENT);
+ dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (void*)pCookieData);
+
+ // have we a open DC, send through that
+ if (m_bDCMsgEnabled && 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 CIcqProto::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/protocols/IcqOscarJ/icq_xtraz.h b/protocols/IcqOscarJ/icq_xtraz.h
new file mode 100644
index 0000000000..8393e7b68f
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_xtraz.h
@@ -0,0 +1,43 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000-2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001-2002 Jon Keating, Richard Hughes
+// Copyright 2002-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_xtraz.h $
+// Revision : $Revision: 7484 $
+// Last change on : $Date: 2008-03-21 11:43:39 +0200 (Пт, 21 мар 2008) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_XTRAZ_H
+#define __ICQ_XTRAZ_H
+
+// custom status support
+void InitXStatusItems(BOOL bAllowStatus);
+
+#endif /* __ICQ_XTRAZ_H */
diff --git a/protocols/IcqOscarJ/icqosc_svcs.cpp b/protocols/IcqOscarJ/icqosc_svcs.cpp
new file mode 100644
index 0000000000..470f1f3030
--- /dev/null
+++ b/protocols/IcqOscarJ/icqosc_svcs.cpp
@@ -0,0 +1,788 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icqosc_svcs.cpp $
+// Revision : $Revision: 14152 $
+// Last change on : $Date: 2012-03-10 19:53:00 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// High-level code for exported API services
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+INT_PTR CIcqProto::AddServerContact(WPARAM wParam, LPARAM lParam)
+{
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (!m_bSsiEnabled) return 0;
+
+ // Does this contact have a UID?
+ if (!getContactUid((HANDLE)wParam, &dwUin, &szUid) && !getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_ID, 0) && !getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_IGNORE, 0))
+ { /// TODO: remove possible 0x6A TLV in contact server-list data!!!
+ // Read group from DB
+ char *pszGroup = getContactCListGroup((HANDLE)wParam);
+
+ servlistAddContact((HANDLE)wParam, pszGroup);
+ SAFE_FREE((void**)&pszGroup);
+ }
+ return 0;
+}
+
+
+static int LookupDatabaseSetting(const FieldNamesItem* table, int code, DBVARIANT *dbv, BYTE type)
+{
+ char *text = LookupFieldName(table, code);
+
+ if (!text)
+ {
+ dbv->type = DBVT_DELETED;
+ return 1;
+ }
+
+ if (type == DBVT_ASCIIZ)
+ {
+ dbv->pszVal = mir_strdup(Translate(text));
+ dbv->type = DBVT_ASCIIZ;
+ }
+ else if (type == DBVT_UTF8 || !type)
+ {
+ char tmp[MAX_PATH];
+
+ dbv->pszVal = mir_strdup(ICQTranslateUtfStatic(text, tmp, MAX_PATH));
+ dbv->type = DBVT_UTF8;
+ }
+ else if (type == DBVT_WCHAR)
+ {
+ WCHAR* wtext = make_unicode_string(text);
+
+ dbv->pwszVal = mir_wstrdup(TranslateW(wtext));
+ dbv->type = DBVT_WCHAR;
+
+ SAFE_FREE((void**)&wtext);
+ }
+ return 0; // Success
+}
+
+INT_PTR CIcqProto::GetInfoSetting(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTGETSETTING *cgs = (DBCONTACTGETSETTING*)lParam;
+ BYTE type = cgs->pValue->type;
+
+ cgs->pValue->type = 0; // original type without conversion
+ INT_PTR rc = CallService(MS_DB_CONTACT_GETSETTING_STR, wParam, lParam);
+
+ if (!rc)
+ { // Success
+ DBVARIANT dbv;
+
+ memcpy(&dbv, cgs->pValue, sizeof(DBVARIANT));
+
+ if (dbv.type == DBVT_BLOB)
+ {
+ cgs->pValue->pbVal = (BYTE*)mir_alloc(dbv.cpbVal);
+
+ memcpy(cgs->pValue->pbVal, dbv.pbVal, dbv.cpbVal);
+ }
+ else if (dbv.type == DBVT_ASCIIZ || dbv.type == DBVT_UTF8)
+ { // convert to the desired type
+ if (!type)
+ type = dbv.type;
+
+ if (dbv.type == type)
+ { // type is correct, only move it to miranda's heap
+ cgs->pValue->pszVal = mir_strdup(dbv.pszVal);
+ }
+ else if (type == DBVT_WCHAR)
+ {
+ if (dbv.type != DBVT_UTF8)
+ {
+ int len = MultiByteToWideChar(CP_ACP, 0, dbv.pszVal, -1, NULL, 0);
+ cgs->pValue->pwszVal = (WCHAR*)mir_alloc((len + 1)*sizeof(WCHAR));
+ if (cgs->pValue->pwszVal == NULL)
+ rc = 1;
+ else
+ {
+ MultiByteToWideChar(CP_ACP, 0, dbv.pszVal, -1, cgs->pValue->pwszVal, len);
+ cgs->pValue->pwszVal[len] = '\0';
+ }
+ }
+ else
+ {
+ char *savePtr = dbv.pszVal ? strcpy((char*)_alloca(strlennull(dbv.pszVal) + 1), dbv.pszVal) : NULL;
+ if (!mir_utf8decode(savePtr, &cgs->pValue->pwszVal))
+ rc = 1;
+ }
+ }
+ else if (type == DBVT_UTF8)
+ {
+ cgs->pValue->pszVal = mir_utf8encode(dbv.pszVal);
+ if (cgs->pValue->pszVal == NULL)
+ rc = 1;
+ }
+ else if (type == DBVT_ASCIIZ)
+ {
+ cgs->pValue->pszVal = mir_strdup(dbv.pszVal);
+ mir_utf8decode(cgs->pValue->pszVal, NULL);
+ }
+
+ cgs->pValue->type = type;
+ }
+ else if (!strcmpnull(cgs->szModule, m_szModuleName) && (dbv.type == DBVT_BYTE || dbv.type == DBVT_WORD || dbv.type == DBVT_DWORD))
+ {
+ int code = (dbv.type == DBVT_BYTE) ? dbv.bVal : ((dbv.type == DBVT_WORD) ? dbv.wVal : dbv.dVal);
+
+ if (!strcmpnull(cgs->szSetting, "Language1") || !strcmpnull(cgs->szSetting, "Language2") || !strcmpnull(cgs->szSetting, "Language3"))
+ rc = LookupDatabaseSetting(languageField, code, cgs->pValue, type);
+ else if (!strcmpnull(cgs->szSetting, "Country") || !strcmpnull(cgs->szSetting, "OriginCountry") || !strcmpnull(cgs->szSetting, "CompanyCountry"))
+ {
+ if (code == 420) code = 42; // conversion of obsolete codes (OMG!)
+ else if (code == 421) code = 4201;
+ else if (code == 102) code = 1201;
+ rc = LookupDatabaseSetting(countryField, code, cgs->pValue, type);
+ }
+ else if (!strcmpnull(cgs->szSetting, "Gender"))
+ rc = LookupDatabaseSetting(genderField, code, cgs->pValue, type);
+ else if (!strcmpnull(cgs->szSetting, "MaritalStatus"))
+ rc = LookupDatabaseSetting(maritalField, code, cgs->pValue, type);
+ else if (!strcmpnull(cgs->szSetting, "StudyLevel"))
+ rc = LookupDatabaseSetting(studyLevelField, code, cgs->pValue, type);
+ else if (!strcmpnull(cgs->szSetting, "CompanyIndustry"))
+ rc = LookupDatabaseSetting(industryField, code, cgs->pValue, type);
+ else if (!strcmpnull(cgs->szSetting, "Interest0Cat") || !strcmpnull(cgs->szSetting, "Interest1Cat") || !strcmpnull(cgs->szSetting, "Interest2Cat") || !strcmpnull(cgs->szSetting, "Interest3Cat"))
+ rc = LookupDatabaseSetting(interestsField, code, cgs->pValue, type);
+ }
+ // Release database memory
+ ICQFreeVariant(&dbv);
+ }
+
+ return rc;
+}
+
+
+INT_PTR CIcqProto::ChangeInfoEx(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline() && wParam)
+ {
+ PBYTE buf = NULL;
+ int buflen = 0;
+ BYTE b;
+
+ // userinfo
+ ppackTLVWord(&buf, &buflen, 0x1C2, (WORD)GetACP());
+
+ if (wParam & CIXT_CONTACT)
+ { // contact information
+ BYTE *pBlock = NULL;
+ int cbBlock = 0;
+ int nItems = 0;
+
+ // Emails
+ nItems += ppackTLVWordStringItemFromDB(&pBlock, &cbBlock, "e-mail0", 0x78, 0x64, 0x00);
+ nItems += ppackTLVWordStringItemFromDB(&pBlock, &cbBlock, "e-mail1", 0x78, 0x64, 0x00);
+ nItems += ppackTLVWordStringItemFromDB(&pBlock, &cbBlock, "e-mail2", 0x78, 0x64, 0x00);
+ ppackTLVBlockItems(&buf, &buflen, 0x8C, &nItems, &pBlock, (WORD*)&cbBlock, FALSE);
+
+ // Phones
+ nItems += ppackTLVWordStringItemFromDB(&pBlock, &cbBlock, "Phone", 0x6E, 0x64, 0x01);
+ nItems += ppackTLVWordStringItemFromDB(&pBlock, &cbBlock, "CompanyPhone", 0x6E, 0x64, 0x02);
+ nItems += ppackTLVWordStringItemFromDB(&pBlock, &cbBlock, "Cellular", 0x6E, 0x64, 0x03);
+ nItems += ppackTLVWordStringItemFromDB(&pBlock, &cbBlock, "Fax", 0x6E, 0x64, 0x04);
+ nItems += ppackTLVWordStringItemFromDB(&pBlock, &cbBlock, "CompanyFax", 0x6E, 0x64, 0x05);
+ ppackTLVBlockItems(&buf, &buflen, 0xC8, &nItems, &pBlock, (WORD*)&cbBlock, FALSE);
+
+ ppackTLVByte(&buf, &buflen, 0x1EA, getSettingByte(NULL, "AllowSpam", 0));
+ }
+
+ if (wParam & CIXT_BASIC)
+ { // upload basic user info
+ ppackTLVStringUtfFromDB(&buf, &buflen, "Nick", 0x78);
+ ppackTLVStringUtfFromDB(&buf, &buflen, "FirstName", 0x64);
+ ppackTLVStringUtfFromDB(&buf, &buflen, "LastName", 0x6E);
+ ppackTLVStringUtfFromDB(&buf, &buflen, "About", 0x186);
+ }
+
+ if (wParam & CIXT_MORE)
+ {
+ b = getSettingByte(NULL, "Gender", 0);
+ ppackTLVByte(&buf, &buflen, 0x82, (BYTE)(b ? (b == 'M' ? 2 : 1) : 0));
+
+ ppackTLVDateFromDB(&buf, &buflen, "BirthYear", "BirthMonth", "BirthDay", 0x1A4);
+
+ ppackTLVWord(&buf, &buflen, 0xAA, getSettingByte(NULL, "Language1", 0));
+ ppackTLVWord(&buf, &buflen, 0xB4, getSettingByte(NULL, "Language2", 0));
+ ppackTLVWord(&buf, &buflen, 0xBE, getSettingByte(NULL, "Language3", 0));
+
+ ppackTLVWord(&buf, &buflen, 0x12C, getSettingByte(NULL, "MaritalStatus", 0));
+ }
+
+ if (wParam & CIXT_WORK)
+ {
+ BYTE *pBlock = NULL;
+ int cbBlock = 0;
+ int nItems = 1;
+
+ // Jobs
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "CompanyPosition", 0x64);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "Company", 0x6E);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "CompanyDepartment", 0x7D);
+ ppackTLVStringFromDB(&pBlock, &cbBlock, "CompanyHomepage", 0x78);
+ ppackTLVWord(&pBlock, &cbBlock, 0x82, getSettingWord(NULL, "CompanyIndustry", 0));
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "CompanyStreet", 0xAA);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "CompanyCity", 0xB4);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "CompanyState", 0xBE);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "CompanyZIP", 0xC8);
+ ppackTLVDWord(&pBlock, &cbBlock, 0xD2, getSettingWord(NULL, "CompanyCountry", 0));
+ /// TODO: pack unknown data (need to preserve them in Block Items)
+ ppackTLVBlockItems(&buf, &buflen, 0x118, &nItems, &pBlock, (WORD*)&cbBlock, TRUE);
+
+ // ppackTLVWord(&buf, &buflen, getSettingWord(NULL, "CompanyOccupation", 0), TLV_OCUPATION, 1); // Lost In Conversion
+ }
+
+ if (wParam & CIXT_EDUCATION)
+ {
+ BYTE *pBlock = NULL;
+ int cbBlock = 0;
+ int nItems = 1;
+
+ // Studies
+ ppackTLVWord(&pBlock, &cbBlock, 0x64, getSettingWord(NULL, "StudyLevel", 0));
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "StudyInstitute", 0x6E);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "StudyDegree", 0x78);
+ ppackTLVWord(&pBlock, &cbBlock, 0x8C, getSettingWord(NULL, "StudyYear", 0));
+ ppackTLVBlockItems(&buf, &buflen, 0x10E, &nItems, &pBlock, (WORD*)&cbBlock, TRUE);
+ }
+
+ if (wParam & CIXT_LOCATION)
+ {
+ BYTE *pBlock = NULL;
+ int cbBlock = 0;
+ int nItems = 1;
+
+ // Home Address
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "Street", 0x64);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "City", 0x6E);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "State", 0x78);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "ZIP", 0x82);
+ ppackTLVDWord(&pBlock, &cbBlock, 0x8C, getSettingWord(NULL, "Country", 0));
+ ppackTLVBlockItems(&buf, &buflen, 0x96, &nItems, &pBlock, (WORD*)&cbBlock, TRUE);
+
+ nItems = 1;
+ // Origin Address
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "OriginStreet", 0x64);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "OriginCity", 0x6E);
+ ppackTLVStringUtfFromDB(&pBlock, &cbBlock, "OriginState", 0x78);
+ ppackTLVDWord(&pBlock, &cbBlock, 0x8C, getSettingWord(NULL, "OriginCountry", 0));
+ ppackTLVBlockItems(&buf, &buflen, 0xA0, &nItems, &pBlock, (WORD*)&cbBlock, TRUE);
+
+ ppackTLVStringFromDB(&buf, &buflen, "Homepage", 0xFA);
+
+ // Timezone
+ WORD wTimezone = getSettingByte(NULL, "Timezone", 0);
+ if ((wTimezone & 0x0080) == 0x80) wTimezone |= 0xFF00; // extend signed number
+ ppackTLVWord(&buf, &buflen, 0x17C, wTimezone);
+ }
+
+ if (wParam & CIXT_BACKGROUND)
+ {
+ BYTE *pBlock = NULL;
+ int cbBlock = 0;
+ int nItems = 0;
+
+ // Interests
+ nItems += ppackTLVWordStringUtfItemFromDB(&pBlock, &cbBlock, "Interest0Text", 0x6E, 0x64, getSettingWord(NULL, "Interest0Cat", 0));
+ nItems += ppackTLVWordStringUtfItemFromDB(&pBlock, &cbBlock, "Interest1Text", 0x6E, 0x64, getSettingWord(NULL, "Interest1Cat", 0));
+ nItems += ppackTLVWordStringUtfItemFromDB(&pBlock, &cbBlock, "Interest2Text", 0x6E, 0x64, getSettingWord(NULL, "Interest2Cat", 0));
+ nItems += ppackTLVWordStringUtfItemFromDB(&pBlock, &cbBlock, "Interest3Text", 0x6E, 0x64, getSettingWord(NULL, "Interest3Cat", 0));
+ ppackTLVBlockItems(&buf, &buflen, 0x122, &nItems, &pBlock, (WORD*)&cbBlock, FALSE);
+
+
+ /* WORD w; /// not supported anymore
+
+ 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);*/
+ }
+
+ DWORD dwCookie = icq_changeUserDirectoryInfoServ(buf, (WORD)buflen, DIRECTORYREQUEST_UPDATEOWNER);
+
+ SAFE_FREE((void**)&buf);
+
+ return dwCookie;
+ }
+
+ return 0; // Failure
+}
+
+
+INT_PTR CIcqProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam == AF_MAXSIZE)
+ {
+ POINT *size = (POINT*)lParam;
+
+ if (size)
+ {
+ 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 (m_bSsiEnabled && m_bAvatarsEnabled)
+ 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
+ }
+ else if (wParam == AF_FETCHALWAYS)
+ { // avatars can be fetched all the time (server only operation)
+ return 1;
+ }
+ return 0;
+}
+
+
+INT_PTR CIcqProto::GetAvatarInfo(WPARAM wParam, LPARAM lParam)
+{
+ PROTO_AVATAR_INFORMATIONT *pai = (PROTO_AVATAR_INFORMATIONT*)lParam;
+ DWORD dwUIN;
+ uid_str szUID;
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ if (!m_bAvatarsEnabled) return GAIR_NOAVATAR;
+
+ if (getSetting(pai->hContact, "AvatarHash", &dbv) || dbv.type != DBVT_BLOB || (dbv.cpbVal != 0x14 && dbv.cpbVal != 0x09))
+ {
+ ICQFreeVariant(&dbv);
+ return GAIR_NOAVATAR; // we did not found avatar hash or hash invalid - no avatar available
+ }
+
+ if (getContactUid(pai->hContact, &dwUIN, &szUID))
+ {
+ ICQFreeVariant(&dbv);
+ return GAIR_NOAVATAR; // we do not support avatars for invalid contacts
+ }
+
+ int dwPaFormat = getSettingByte(pai->hContact, "AvatarType", PA_FORMAT_UNKNOWN);
+
+ if (dwPaFormat != PA_FORMAT_UNKNOWN)
+ { // we know the format, test file
+ TCHAR tszFile[MAX_PATH * 2 + 4];
+
+ GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, tszFile, MAX_PATH * 2);
+
+ lstrcpyn(pai->filename, tszFile, SIZEOF(pai->filename)); // Avatar API does not support unicode :-(
+ pai->format = dwPaFormat;
+
+ if (!IsAvatarChanged(pai->hContact, dbv.pbVal, dbv.cpbVal))
+ { // hashes are the same
+ if (_taccess(tszFile, 0) == 0)
+ {
+ ICQFreeVariant(&dbv);
+
+ return GAIR_SUCCESS; // we have found the avatar file, whoala
+ }
+ }
+ }
+
+ if (IsAvatarChanged(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
+ TCHAR tszFile[MAX_PATH * 2 + 4];
+
+ GetAvatarFileName(dwUIN, szUID, tszFile, MAX_PATH * 2);
+ GetAvatarData(pai->hContact, dwUIN, szUID, dbv.pbVal, dbv.cpbVal, tszFile);
+ lstrcpyn(pai->filename, tszFile, SIZEOF(pai->filename)); // Avatar API does not support unicode :-(
+
+ ICQFreeVariant(&dbv);
+
+ return GAIR_WAITFOR;
+ }
+ }
+ ICQFreeVariant(&dbv);
+
+ return GAIR_NOAVATAR;
+}
+
+
+INT_PTR CIcqProto::GetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+ if (!m_bAvatarsEnabled) return -2;
+
+ if (!wParam) return -3;
+
+ TCHAR *tszFile = GetOwnAvatarFileName();
+ if (tszFile && !_taccess(tszFile, 0))
+ {
+ _tcsncpy((TCHAR*)wParam, tszFile, (int)lParam);
+ SAFE_FREE(&tszFile);
+ return 0;
+ }
+
+ SAFE_FREE(&tszFile);
+ return -1;
+}
+
+
+INT_PTR CIcqProto::GrantAuthorization(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline() && wParam != 0)
+ {
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (getContactUid((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
+ deleteSetting((HANDLE)wParam, "Grant");
+ }
+
+ return 0;
+}
+
+int CIcqProto::OnIdleChanged(WPARAM wParam, LPARAM lParam)
+{
+ int bIdle = (lParam&IDF_ISIDLE);
+ int bPrivacy = (lParam&IDF_PRIVACY);
+
+ if (bPrivacy) return 0;
+
+ setSettingDword(NULL, "IdleTS", bIdle ? time(0) : 0);
+
+ if (m_bTempVisListEnabled) // remove temporary visible users
+ sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_REMOVETEMPVISIBLE, BUL_TEMPVISIBLE);
+
+ icq_setidle(bIdle ? 1 : 0);
+
+ return 0;
+}
+
+INT_PTR CIcqProto::RevokeAuthorization(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline() && wParam != 0)
+ {
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (getContactUid((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_PTR CIcqProto::SendSms(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline() && wParam && lParam)
+ return icq_sendSMSServ((const char *)wParam, (const char *)lParam);
+
+ return 0; // Failure
+}
+
+INT_PTR CIcqProto::SendYouWereAdded(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam && icqOnline())
+ {
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ if (ccs->hContact)
+ {
+ DWORD dwUin, dwMyUin;
+
+ if (getContactUid(ccs->hContact, &dwUin, NULL))
+ return 1; // Invalid contact
+
+ dwMyUin = getContactUin(NULL);
+
+ if (dwUin)
+ {
+ icq_sendYouWereAddedServ(dwUin, dwMyUin);
+ return 0; // Success
+ }
+ }
+ }
+
+ return 1; // Failure
+}
+
+INT_PTR CIcqProto::SetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR* tszFile = (TCHAR*)lParam;
+ int iRet = -1;
+
+ if (!m_bAvatarsEnabled || !m_bSsiEnabled) return -2;
+
+ if (tszFile)
+ { // set file for avatar
+ int dwPaFormat = DetectAvatarFormat(tszFile);
+ if (dwPaFormat != PA_FORMAT_XML)
+ {
+ // if it should be image, check if it is valid
+ HBITMAP avt = (HBITMAP)CallService(MS_UTILS_LOADBITMAPT, 0, (WPARAM)tszFile);
+ if (!avt) return iRet;
+ DeleteObject(avt);
+ }
+
+ TCHAR tszMyFile[MAX_PATH+1];
+ GetFullAvatarFileName(0, NULL, dwPaFormat, tszMyFile, MAX_PATH);
+ // if not in our storage, copy
+ if (lstrcmp(tszFile, tszMyFile) && !CopyFile(tszFile, tszMyFile, FALSE))
+ {
+ NetLog_Server("Failed to copy our avatar to local storage.");
+ return iRet;
+ }
+
+ BYTE *hash = calcMD5HashOfFile(tszMyFile);
+ if (hash)
+ {
+ BYTE* ihash = (BYTE*)_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 (setSettingBlob(NULL, "AvatarHash", ihash, 0x14))
+ {
+ NetLog_Server("Failed to save avatar hash.");
+ }
+
+ TCHAR tmp[MAX_PATH];
+ CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)tszMyFile, (LPARAM)tmp);
+ setSettingStringT(NULL, "AvatarFile", tmp);
+
+ iRet = 0;
+
+ SAFE_FREE((void**)&hash);
+ }
+ }
+ else
+ { // delete user avatar
+ deleteSetting(NULL, "AvatarFile");
+ setSettingBlob(NULL, "AvatarHash", hashEmptyAvatar, 9);
+ updateServAvatarHash(hashEmptyAvatar, 9); // set blank avatar
+ iRet = 0;
+ }
+
+ return iRet;
+}
+
+INT_PTR CIcqProto::SetNickName(WPARAM wParam, LPARAM lParam)
+{
+ if (icqOnline())
+ {
+ setSettingString(NULL, "Nick", (char*)lParam);
+
+ return ChangeInfoEx(CIXT_BASIC, 0);
+ }
+
+ return 0; // Failure
+}
+
+INT_PTR CIcqProto::SetPassword(WPARAM wParam, LPARAM lParam)
+{
+ char *pwd = (char*)lParam;
+ int len = strlennull(pwd);
+
+ if (len && len < PASSWORDMAXLEN)
+ {
+ strcpy(m_szPassword, pwd);
+ m_bRememberPwd = TRUE;
+ }
+ return 0;
+}
+
+
+// TODO: Adding needs some more work in general
+
+HANDLE CIcqProto::AddToListByUIN(DWORD dwUin, DWORD dwFlags)
+{
+ int bAdded;
+ HANDLE hContact = HContactFromUIN(dwUin, &bAdded);
+ if (hContact)
+ {
+ if (!(dwFlags & PALF_TEMPORARY) && DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ {
+ setContactHidden(hContact, 0);
+ DBDeleteContactSetting(hContact, "CList", "NotOnList");
+ }
+
+ return hContact; // Success
+ }
+
+ return NULL; // Failure
+}
+
+
+HANDLE CIcqProto::AddToListByUID(const char *szUID, DWORD dwFlags)
+{
+ int bAdded;
+ HANDLE hContact = HContactFromUID(0, szUID, &bAdded);
+ if (hContact)
+ {
+ if (!(dwFlags & PALF_TEMPORARY) && DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ {
+ setContactHidden(hContact, 0);
+ DBDeleteContactSetting(hContact, "CList", "NotOnList");
+ }
+
+ return hContact; // Success
+ }
+
+ return NULL; // Failure
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CIcqProto::ICQAddRecvEvent(HANDLE hContact, WORD wType, PROTORECVEVENT* pre, DWORD cbBlob, PBYTE pBlob, DWORD flags)
+{
+ if (pre->flags & PREF_CREATEREAD)
+ flags |= DBEF_READ;
+
+ if (pre->flags & PREF_UTF)
+ flags |= DBEF_UTF;
+
+ 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 (!getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0) || getSettingByte(hContact, "Auth", 0))
+ {
+ getContactUid(hContact, &dwUin, &szUid);
+ icq_sendNewContact(dwUin, szUid); /// FIXME
+ }
+ }
+
+ AddEvent(hContact, wType, pre->timestamp, flags, cbBlob, pBlob);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR icq_getEventTextMissedMessage(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTGETTEXT *pEvent = (DBEVENTGETTEXT *)lParam;
+
+ INT_PTR nRetVal = 0;
+ char *pszText = NULL;
+
+ if (pEvent->dbei->cbBlob > 1)
+ {
+ switch (((WORD*)pEvent->dbei->pBlob)[0])
+ {
+ case 0:
+ pszText = LPGEN("** This message was blocked by the ICQ server ** The message was invalid.");
+ break;
+
+ case 1:
+ pszText = LPGEN("** This message was blocked by the ICQ server ** The message was too long.");
+ break;
+
+ case 2:
+ pszText = LPGEN("** This message was blocked by the ICQ server ** The sender has flooded the server.");
+ break;
+
+ case 4:
+ pszText = LPGEN("** This message was blocked by the ICQ server ** You are too evil.");
+ break;
+
+ default:
+ pszText = LPGEN("** Unknown missed message event.");
+ break;
+ }
+ if (pEvent->datatype == DBVT_WCHAR)
+ {
+ WCHAR *pwszText;
+ int wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszText, strlennull(pszText), NULL, 0);
+
+ pwszText = (WCHAR*)_alloca((wchars + 1) * sizeof(WCHAR));
+ pwszText[wchars] = 0;
+
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszText, strlennull(pszText), pwszText, wchars);
+
+ nRetVal = (INT_PTR)mir_wstrdup(TranslateW(pwszText));
+ }
+ else if (pEvent->datatype == DBVT_ASCIIZ)
+ nRetVal = (INT_PTR)mir_strdup(Translate(pszText));
+ }
+
+ return nRetVal;
+}
diff --git a/protocols/IcqOscarJ/icqosc_svcs.h b/protocols/IcqOscarJ/icqosc_svcs.h
new file mode 100644
index 0000000000..d2239f0e27
--- /dev/null
+++ b/protocols/IcqOscarJ/icqosc_svcs.h
@@ -0,0 +1,46 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icqosc_svcs.h $
+// Revision : $Revision: 9261 $
+// Last change on : $Date: 2009-03-28 22:16:39 +0300 (Сб, 28 мар 2009) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQOSC_SVCS_H
+#define __ICQOSC_SVCS_H
+
+
+#define ICQ_DB_GETEVENTTEXT_MISSEDMESSAGE "ICQ/GetEventTextMissedMessage"
+
+INT_PTR icq_getEventTextMissedMessage(WPARAM wParam, LPARAM lParam);
+
+
+#endif /* __ICQOSC_SVCS_H */
diff --git a/protocols/IcqOscarJ/icqoscar.cpp b/protocols/IcqOscarJ/icqoscar.cpp
new file mode 100644
index 0000000000..b7344437de
--- /dev/null
+++ b/protocols/IcqOscarJ/icqoscar.cpp
@@ -0,0 +1,42 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001,2002 Jon Keating, Richard Hughes
+// Copyright 2002,2003,2004 Martin berg, Sam Kothari, Robert Rainwater
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icqoscar.c,v $
+// Revision : $Revision: 7500 $
+// Last change on : $Date: 2008-03-24 20:07:37 +0200 (Пн, 24 мар 2008) $
+// Last change by : $Author: jokusoftware $
+//
+// 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/protocols/IcqOscarJ/icqoscar.h b/protocols/IcqOscarJ/icqoscar.h
new file mode 100644
index 0000000000..3a4291d1dc
--- /dev/null
+++ b/protocols/IcqOscarJ/icqoscar.h
@@ -0,0 +1,143 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icqoscar.h $
+// Revision : $Revision: 14085 $
+// Last change on : $Date: 2012-02-13 12:55:56 +0200 (Пн, 13 фев 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Includes all header files that should be precompiled to speed up compilation.
+//
+// -----------------------------------------------------------------------------
+
+#define MIRANDA_VER 0x0A00
+
+#define _WIN32_WINNT 0x0501
+#define _WIN32_IE 0x0501
+
+#include <m_stdhdr.h>
+
+// Windows includes
+#include <windows.h>
+#include <commctrl.h>
+#include <uxtheme.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>
+#include <process.h>
+#ifndef _DEBUG
+#ifdef _MSC_VER
+ #include <crtdbg.h>
+#endif
+#endif
+
+#ifndef AW_VER_POSITIVE
+#define AW_VER_POSITIVE 0x00000004
+#endif
+
+#ifndef _ASSERTE
+#define _ASSERTE(x)
+#endif
+
+// Miranda IM SDK includes
+#include <newpluginapi.h> // This must be included first
+#include <m_clc.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_message.h>
+#include <m_netlib.h>
+#include <m_protocols.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_options.h>
+#include <m_system.h>
+#include <m_userinfo.h>
+#include <m_utils.h>
+#include <m_idle.h>
+#include <m_popup.h>
+#include <m_clistint.h>
+#include <m_cluiframes.h>
+#include <m_ignore.h>
+#include <m_avatars.h>
+#include <win2k.h>
+
+// Project resources
+#include "resource.h"
+
+// ICQ plugin includes
+#include "version.h"
+#include "iconlib.h"
+#include "globals.h"
+#include "i18n.h"
+#include "icq_db.h"
+#include "cookies.h"
+#include "icq_packet.h"
+#include "utilities.h"
+#include "oscar_filetransfer.h"
+#include "icq_direct.h"
+#include "icq_server.h"
+#include "icqosc_svcs.h"
+#include "icq_xtraz.h"
+#include "icq_opts.h"
+#include "icq_servlist.h"
+#include "icq_http.h"
+#include "icq_fieldnames.h"
+#include "icq_constants.h"
+#include "capabilities.h"
+#include "guids.h"
+#include "icq_infoupdate.h"
+#include "init.h"
+#include "stdpackets.h"
+#include "directpackets.h"
+#include "tlv.h"
+#include "channels.h"
+#include "families.h"
+#include "m_icq.h"
+#include "icq_advsearch.h"
+#include "icq_uploadui.h"
+#include "log.h"
+#include "UI/askauthentication.h"
+#include "UI/userinfotab.h"
+#include "UI/loginpassword.h"
+
+#include "icq_rates.h"
+
+#include "icq_avatar.h"
+
+#include "changeinfo/changeinfo.h"
+#include "icq_popups.h"
+#include "icq_proto.h"
+
+extern LIST<CIcqProto> g_Instances;
diff --git a/protocols/IcqOscarJ/icqoscar8.dep b/protocols/IcqOscarJ/icqoscar8.dep
new file mode 100644
index 0000000000..a7866467bc
--- /dev/null
+++ b/protocols/IcqOscarJ/icqoscar8.dep
@@ -0,0 +1,4421 @@
+# Microsoft Developer Studio Generated Dependency File, included by icqoscar8.mak
+
+.\resources.rc : \
+ "..\..\include\m_version.h"\
+ ".\changeinfo\expandst.ico"\
+ ".\icos\auth_ask.ico"\
+ ".\icos\auth_grant.ico"\
+ ".\icos\auth_revoke.ico"\
+ ".\icos\icq.ico"\
+ ".\icos\srvlist_add.ico"\
+ ".\version.h"\
+
+
+.\chan_01login.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\chan_02data.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\chan_03error.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\chan_04close.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\chan_05ping.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\fam_01service.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\fam_02location.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\fam_03buddy.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\fam_04message.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\fam_09bos.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\fam_0alookup.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\fam_0bstatus.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\fam_13servclist.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\fam_15icqserver.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\fam_17signon.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\directpackets.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_direct.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_directmsg.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_filerequests.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_filetransfer.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_advsearch.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_db.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_proto.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icolib.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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_updater.h"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icqosc_svcs.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\init.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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_extraicons.h"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\log.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\UI\askauthentication.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\icqoscar.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_firstrun.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_menu.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_skin.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_opts.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_popups.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_uploadui.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\UI\loginpassword.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\icqoscar.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\UI\userinfotab.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\icqoscar.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\changeinfo\constants.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\changeinfo\icqoscar.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\changeinfo\db.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\changeinfo\icqoscar.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\changeinfo\dlgproc.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\changeinfo\icqoscar.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\changeinfo\editlist.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\changeinfo\icqoscar.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\changeinfo\editstring.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\changeinfo\icqoscar.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\changeinfo\main.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\changeinfo\icqoscar.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\changeinfo\upload.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\changeinfo\icqoscar.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\capabilities.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\cookies.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\i18n.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\iconlib.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icolib.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_avatar.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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_folders.h"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_clients.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_fieldnames.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_http.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_infoupdate.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_packet.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_rates.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_server.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_servlist.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_xstatus.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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_extraicons.h"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icq_xtraz.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\icqoscar.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\oscar_filetransfer.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\stdpackets.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\tlv.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
+
+.\utilities.cpp : \
+ "..\..\include\m_avatars.h"\
+ "..\..\include\m_clc.h"\
+ "..\..\include\m_clist.h"\
+ "..\..\include\m_clistint.h"\
+ "..\..\include\m_clui.h"\
+ "..\..\include\m_cluiframes.h"\
+ "..\..\include\m_database.h"\
+ "..\..\include\m_genmenu.h"\
+ "..\..\include\m_icq.h"\
+ "..\..\include\m_idle.h"\
+ "..\..\include\m_ignore.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_protoint.h"\
+ "..\..\include\m_protomod.h"\
+ "..\..\include\m_protosvc.h"\
+ "..\..\include\m_stdhdr.h"\
+ "..\..\include\m_system.h"\
+ "..\..\include\m_system_cpp.h"\
+ "..\..\include\m_userinfo.h"\
+ "..\..\include\m_utils.h"\
+ "..\..\include\m_version.h"\
+ "..\..\include\newpluginapi.h"\
+ "..\..\include\statusmodes.h"\
+ "..\..\include\win2k.h"\
+ ".\capabilities.h"\
+ ".\changeinfo\changeinfo.h"\
+ ".\channels.h"\
+ ".\cookies.h"\
+ ".\directpackets.h"\
+ ".\families.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_proto.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"\
+ ".\oscar_filetransfer.h"\
+ ".\stdpackets.h"\
+ ".\tlv.h"\
+ ".\UI\askauthentication.h"\
+ ".\UI\loginpassword.h"\
+ ".\UI\userinfotab.h"\
+ ".\utilities.h"\
+ ".\version.h"\
+
diff --git a/protocols/IcqOscarJ/icqoscar8.dsp b/protocols/IcqOscarJ/icqoscar8.dsp
new file mode 100644
index 0000000000..5b803ce2e5
--- /dev/null
+++ b/protocols/IcqOscarJ/icqoscar8.dsp
@@ -0,0 +1,768 @@
+# 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 Unicode
+!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 Unicode"
+!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 "icqoscar8 - Win32 Debug Unicode" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "icqoscar8 - Win32 Release Unicode" (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
+
+!IF "$(CFG)" == "icqoscar8 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /Zi /O1 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR /Yu"icqoscar.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x417 /i "../../include" /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /map /debug /machine:I386 /out:"../../bin/release/plugins/ICQ.dll" /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "icqoscar8 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR /Yu"icqoscar.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /i "../../include" /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
+
+!ELSEIF "$(CFG)" == "icqoscar8 - Win32 Debug Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "icqoscar8___Win32_Debug_Unicode"
+# PROP BASE Intermediate_Dir "icqoscar8___Win32_Debug_Unicode"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug_Unicode"
+# PROP Intermediate_Dir "Debug_Unicode"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE 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 CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "UNICODE" /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 /i "../../include" /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE 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 BASE LINK32 /pdb:none /incremental:no
+# 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 Unicode/plugins/ICQ.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none /incremental:no
+
+!ELSEIF "$(CFG)" == "icqoscar8 - Win32 Release Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "icqoscar8___Win32_Release_Unicode"
+# PROP BASE Intermediate_Dir "icqoscar8___Win32_Release_Unicode"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_Unicode"
+# PROP Intermediate_Dir "Release_Unicode"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /Zi /O1 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR /Yu"icqoscar.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /Zi /O1 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "UNICODE" /D "_USRDLL" /D "icqoscar8_EXPORTS" /FR /Yu"icqoscar.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x417 /d "NDEBUG"
+# ADD RSC /l 0x417 /i "../../include" /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 comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /map /debug /machine:I386 /out:"../../bin/release/plugins/ICQ.dll" /ALIGN:4096 /ignore:4108
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /map /debug /machine:I386 /out:"../../bin/release unicode/plugins/ICQ.dll" /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "icqoscar8 - Win32 Release"
+# Name "icqoscar8 - Win32 Debug"
+# Name "icqoscar8 - Win32 Debug Unicode"
+# Name "icqoscar8 - Win32 Release Unicode"
+# 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_proto.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_rates.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_server.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_servlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_uploadui.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_xtraz.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icqosc_svcs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\icqoscar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\init.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\UI\loginpassword.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\oscar_filetransfer.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
+# Begin Source File
+
+SOURCE=.\version.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=.\changeinfo\expandst.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\icq.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\resources.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\srvlist_add.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus01.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus02.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus03.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus04.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus05.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus06.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus07.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus08.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus09.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus10.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus11.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus12.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus13.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus14.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus15.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus16.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus17.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus18.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus19.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus20.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus21.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus22.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus23.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus24.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus25.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus26.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus27.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus28.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus29.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus30.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus31.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icos\xstatus32.ico
+# End Source File
+# End Group
+# Begin Group "FLAP Channels"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\chan_01login.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\chan_02data.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\chan_03error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\chan_04close.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\chan_05ping.cpp
+# End Source File
+# End Group
+# Begin Group "SNAC Families"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\fam_01service.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_02location.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_03buddy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_04message.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_09bos.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_0alookup.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_0bstatus.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_13servclist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_15icqserver.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fam_17signon.cpp
+# End Source File
+# End Group
+# Begin Group "Direct Connection"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\directpackets.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_direct.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_directmsg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_filerequests.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_filetransfer.cpp
+# End Source File
+# End Group
+# Begin Group "Miranda Bits"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\icq_advsearch.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_db.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_proto.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icqosc_svcs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\init.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\log.cpp
+# 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.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_firstrun.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_menu.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_opts.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_popups.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_uploadui.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\UI\loginpassword.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\UI\userinfotab.cpp
+# 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.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\db.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\dlgproc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\editlist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\editstring.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\changeinfo\upload.cpp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\capabilities.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\cookies.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\i18n.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\iconlib.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_avatar.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_clients.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_fieldnames.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_http.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_infoupdate.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_packet.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_rates.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_server.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_servlist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_xstatus.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icq_xtraz.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\icqoscar.cpp
+# ADD CPP /Yc"icqoscar.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\oscar_filetransfer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\stdpackets.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\tlv.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\utilities.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/protocols/IcqOscarJ/icqoscar8.dsw b/protocols/IcqOscarJ/icqoscar8.dsw
new file mode 100644
index 0000000000..233a2d673c
--- /dev/null
+++ b/protocols/IcqOscarJ/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/protocols/IcqOscarJ/icqoscar8.mak b/protocols/IcqOscarJ/icqoscar8.mak
new file mode 100644
index 0000000000..3b3fc51791
--- /dev/null
+++ b/protocols/IcqOscarJ/icqoscar8.mak
@@ -0,0 +1,1710 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on icqoscar8.dsp
+!IF "$(CFG)" == ""
+CFG=icqoscar8 - Win32 Release Unicode
+!MESSAGE No configuration specified. Defaulting to icqoscar8 - Win32 Release Unicode.
+!ENDIF
+
+!IF "$(CFG)" != "icqoscar8 - Win32 Release" && "$(CFG)" != "icqoscar8 - Win32 Debug" && "$(CFG)" != "icqoscar8 - Win32 Debug Unicode" && "$(CFG)" != "icqoscar8 - Win32 Release Unicode"
+!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 Unicode"
+!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 "icqoscar8 - Win32 Debug Unicode" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "icqoscar8 - Win32 Release Unicode" (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)\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_menu.obj"
+ -@erase "$(INTDIR)\icq_menu.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_proto.obj"
+ -@erase "$(INTDIR)\icq_proto.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)\oscar_filetransfer.obj"
+ -@erase "$(INTDIR)\oscar_filetransfer.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" /i "../../include" /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)\icq_proto.sbr" \
+ "$(INTDIR)\icqosc_svcs.sbr" \
+ "$(INTDIR)\init.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\askauthentication.sbr" \
+ "$(INTDIR)\icq_firstrun.sbr" \
+ "$(INTDIR)\icq_menu.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)\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)\oscar_filetransfer.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)\icq_proto.obj" \
+ "$(INTDIR)\icqosc_svcs.obj" \
+ "$(INTDIR)\init.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\askauthentication.obj" \
+ "$(INTDIR)\icq_firstrun.obj" \
+ "$(INTDIR)\icq_menu.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)\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)\oscar_filetransfer.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)\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_menu.obj"
+ -@erase "$(INTDIR)\icq_menu.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_proto.obj"
+ -@erase "$(INTDIR)\icq_proto.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)\oscar_filetransfer.obj"
+ -@erase "$(INTDIR)\oscar_filetransfer.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" /i "../../include" /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)\icq_proto.sbr" \
+ "$(INTDIR)\icqosc_svcs.sbr" \
+ "$(INTDIR)\init.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\askauthentication.sbr" \
+ "$(INTDIR)\icq_firstrun.sbr" \
+ "$(INTDIR)\icq_menu.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)\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)\oscar_filetransfer.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)\icq_proto.obj" \
+ "$(INTDIR)\icqosc_svcs.obj" \
+ "$(INTDIR)\init.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\askauthentication.obj" \
+ "$(INTDIR)\icq_firstrun.obj" \
+ "$(INTDIR)\icq_menu.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)\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)\oscar_filetransfer.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)
+<<
+
+!ELSEIF "$(CFG)" == "icqoscar8 - Win32 Debug Unicode"
+
+OUTDIR=.\Debug_Unicode
+INTDIR=.\Debug_Unicode
+# Begin Custom Macros
+OutDir=.\Debug_Unicode
+# End Custom Macros
+
+ALL : "..\..\bin\debug Unicode\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)\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_menu.obj"
+ -@erase "$(INTDIR)\icq_menu.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_proto.obj"
+ -@erase "$(INTDIR)\icq_proto.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)\oscar_filetransfer.obj"
+ -@erase "$(INTDIR)\oscar_filetransfer.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 Unicode\plugins\ICQ.dll"
+ -@erase "..\..\bin\debug Unicode\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 "UNICODE" /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" /i "../../include" /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)\icq_proto.sbr" \
+ "$(INTDIR)\icqosc_svcs.sbr" \
+ "$(INTDIR)\init.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\askauthentication.sbr" \
+ "$(INTDIR)\icq_firstrun.sbr" \
+ "$(INTDIR)\icq_menu.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)\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)\oscar_filetransfer.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 Unicode/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)\icq_proto.obj" \
+ "$(INTDIR)\icqosc_svcs.obj" \
+ "$(INTDIR)\init.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\askauthentication.obj" \
+ "$(INTDIR)\icq_firstrun.obj" \
+ "$(INTDIR)\icq_menu.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)\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)\oscar_filetransfer.obj" \
+ "$(INTDIR)\stdpackets.obj" \
+ "$(INTDIR)\tlv.obj" \
+ "$(INTDIR)\utilities.obj" \
+ "$(INTDIR)\resources.res"
+
+"..\..\bin\debug Unicode\plugins\ICQ.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "icqoscar8 - Win32 Release Unicode"
+
+OUTDIR=.\Release_Unicode
+INTDIR=.\Release_Unicode
+# Begin Custom Macros
+OutDir=.\Release_Unicode
+# End Custom Macros
+
+ALL : "..\..\bin\release unicode\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)\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_menu.obj"
+ -@erase "$(INTDIR)\icq_menu.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_proto.obj"
+ -@erase "$(INTDIR)\icq_proto.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)\oscar_filetransfer.obj"
+ -@erase "$(INTDIR)\oscar_filetransfer.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 unicode\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 "UNICODE" /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" /i "../../include" /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)\icq_proto.sbr" \
+ "$(INTDIR)\icqosc_svcs.sbr" \
+ "$(INTDIR)\init.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\askauthentication.sbr" \
+ "$(INTDIR)\icq_firstrun.sbr" \
+ "$(INTDIR)\icq_menu.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)\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)\oscar_filetransfer.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 unicode/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)\icq_proto.obj" \
+ "$(INTDIR)\icqosc_svcs.obj" \
+ "$(INTDIR)\init.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\askauthentication.obj" \
+ "$(INTDIR)\icq_firstrun.obj" \
+ "$(INTDIR)\icq_menu.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)\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)\oscar_filetransfer.obj" \
+ "$(INTDIR)\stdpackets.obj" \
+ "$(INTDIR)\tlv.obj" \
+ "$(INTDIR)\utilities.obj" \
+ "$(INTDIR)\resources.res"
+
+"..\..\bin\release unicode\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" || "$(CFG)" == "icqoscar8 - Win32 Debug Unicode" || "$(CFG)" == "icqoscar8 - Win32 Release Unicode"
+SOURCE=.\resources.rc
+
+"$(INTDIR)\resources.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+SOURCE=.\chan_01login.cpp
+
+"$(INTDIR)\chan_01login.obj" "$(INTDIR)\chan_01login.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\chan_02data.cpp
+
+"$(INTDIR)\chan_02data.obj" "$(INTDIR)\chan_02data.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\chan_03error.cpp
+
+"$(INTDIR)\chan_03error.obj" "$(INTDIR)\chan_03error.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\chan_04close.cpp
+
+"$(INTDIR)\chan_04close.obj" "$(INTDIR)\chan_04close.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\chan_05ping.cpp
+
+"$(INTDIR)\chan_05ping.obj" "$(INTDIR)\chan_05ping.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_01service.cpp
+
+"$(INTDIR)\fam_01service.obj" "$(INTDIR)\fam_01service.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_02location.cpp
+
+"$(INTDIR)\fam_02location.obj" "$(INTDIR)\fam_02location.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_03buddy.cpp
+
+"$(INTDIR)\fam_03buddy.obj" "$(INTDIR)\fam_03buddy.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_04message.cpp
+
+"$(INTDIR)\fam_04message.obj" "$(INTDIR)\fam_04message.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_09bos.cpp
+
+"$(INTDIR)\fam_09bos.obj" "$(INTDIR)\fam_09bos.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_0alookup.cpp
+
+"$(INTDIR)\fam_0alookup.obj" "$(INTDIR)\fam_0alookup.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_0bstatus.cpp
+
+"$(INTDIR)\fam_0bstatus.obj" "$(INTDIR)\fam_0bstatus.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_13servclist.cpp
+
+"$(INTDIR)\fam_13servclist.obj" "$(INTDIR)\fam_13servclist.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_15icqserver.cpp
+
+"$(INTDIR)\fam_15icqserver.obj" "$(INTDIR)\fam_15icqserver.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\fam_17signon.cpp
+
+"$(INTDIR)\fam_17signon.obj" "$(INTDIR)\fam_17signon.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\directpackets.cpp
+
+"$(INTDIR)\directpackets.obj" "$(INTDIR)\directpackets.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_direct.cpp
+
+"$(INTDIR)\icq_direct.obj" "$(INTDIR)\icq_direct.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_directmsg.cpp
+
+"$(INTDIR)\icq_directmsg.obj" "$(INTDIR)\icq_directmsg.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_filerequests.cpp
+
+"$(INTDIR)\icq_filerequests.obj" "$(INTDIR)\icq_filerequests.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_filetransfer.cpp
+
+"$(INTDIR)\icq_filetransfer.obj" "$(INTDIR)\icq_filetransfer.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_advsearch.cpp
+
+"$(INTDIR)\icq_advsearch.obj" "$(INTDIR)\icq_advsearch.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_db.cpp
+
+"$(INTDIR)\icq_db.obj" "$(INTDIR)\icq_db.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_proto.cpp
+
+"$(INTDIR)\icq_proto.obj" "$(INTDIR)\icq_proto.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icqosc_svcs.cpp
+
+"$(INTDIR)\icqosc_svcs.obj" "$(INTDIR)\icqosc_svcs.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\init.cpp
+
+"$(INTDIR)\init.obj" "$(INTDIR)\init.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\log.cpp
+
+"$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\UI\askauthentication.cpp
+
+"$(INTDIR)\askauthentication.obj" "$(INTDIR)\askauthentication.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\icq_firstrun.cpp
+
+"$(INTDIR)\icq_firstrun.obj" "$(INTDIR)\icq_firstrun.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_menu.cpp
+
+"$(INTDIR)\icq_menu.obj" "$(INTDIR)\icq_menu.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_opts.cpp
+
+"$(INTDIR)\icq_opts.obj" "$(INTDIR)\icq_opts.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_popups.cpp
+
+"$(INTDIR)\icq_popups.obj" "$(INTDIR)\icq_popups.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_uploadui.cpp
+
+"$(INTDIR)\icq_uploadui.obj" "$(INTDIR)\icq_uploadui.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\UI\loginpassword.cpp
+
+"$(INTDIR)\loginpassword.obj" "$(INTDIR)\loginpassword.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\UI\userinfotab.cpp
+
+"$(INTDIR)\userinfotab.obj" "$(INTDIR)\userinfotab.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\constants.cpp
+
+"$(INTDIR)\constants.obj" "$(INTDIR)\constants.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\db.cpp
+
+"$(INTDIR)\db.obj" "$(INTDIR)\db.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\dlgproc.cpp
+
+"$(INTDIR)\dlgproc.obj" "$(INTDIR)\dlgproc.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\editlist.cpp
+
+"$(INTDIR)\editlist.obj" "$(INTDIR)\editlist.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\editstring.cpp
+
+"$(INTDIR)\editstring.obj" "$(INTDIR)\editstring.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\main.cpp
+
+"$(INTDIR)\main.obj" "$(INTDIR)\main.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\changeinfo\upload.cpp
+
+"$(INTDIR)\upload.obj" "$(INTDIR)\upload.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\capabilities.cpp
+
+"$(INTDIR)\capabilities.obj" "$(INTDIR)\capabilities.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\cookies.cpp
+
+"$(INTDIR)\cookies.obj" "$(INTDIR)\cookies.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\i18n.cpp
+
+"$(INTDIR)\i18n.obj" "$(INTDIR)\i18n.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\iconlib.cpp
+
+"$(INTDIR)\iconlib.obj" "$(INTDIR)\iconlib.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_avatar.cpp
+
+"$(INTDIR)\icq_avatar.obj" "$(INTDIR)\icq_avatar.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_clients.cpp
+
+"$(INTDIR)\icq_clients.obj" "$(INTDIR)\icq_clients.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_fieldnames.cpp
+
+"$(INTDIR)\icq_fieldnames.obj" "$(INTDIR)\icq_fieldnames.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_http.cpp
+
+"$(INTDIR)\icq_http.obj" "$(INTDIR)\icq_http.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_infoupdate.cpp
+
+"$(INTDIR)\icq_infoupdate.obj" "$(INTDIR)\icq_infoupdate.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_packet.cpp
+
+"$(INTDIR)\icq_packet.obj" "$(INTDIR)\icq_packet.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_rates.cpp
+
+"$(INTDIR)\icq_rates.obj" "$(INTDIR)\icq_rates.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_server.cpp
+
+"$(INTDIR)\icq_server.obj" "$(INTDIR)\icq_server.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_servlist.cpp
+
+"$(INTDIR)\icq_servlist.obj" "$(INTDIR)\icq_servlist.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_xstatus.cpp
+
+"$(INTDIR)\icq_xstatus.obj" "$(INTDIR)\icq_xstatus.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icq_xtraz.cpp
+
+"$(INTDIR)\icq_xtraz.obj" "$(INTDIR)\icq_xtraz.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\icqoscar.cpp
+
+!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)
+<<
+
+
+!ELSEIF "$(CFG)" == "icqoscar8 - Win32 Debug Unicode"
+
+CPP_SWITCHES=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "UNICODE" /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)
+<<
+
+
+!ELSEIF "$(CFG)" == "icqoscar8 - Win32 Release Unicode"
+
+CPP_SWITCHES=/nologo /MD /W3 /GX /Zi /O1 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "UNICODE" /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)
+<<
+
+
+!ENDIF
+
+SOURCE=.\oscar_filetransfer.cpp
+
+"$(INTDIR)\oscar_filetransfer.obj" "$(INTDIR)\oscar_filetransfer.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\stdpackets.cpp
+
+"$(INTDIR)\stdpackets.obj" "$(INTDIR)\stdpackets.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\tlv.cpp
+
+"$(INTDIR)\tlv.obj" "$(INTDIR)\tlv.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+SOURCE=.\utilities.cpp
+
+"$(INTDIR)\utilities.obj" "$(INTDIR)\utilities.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\icqoscar8.pch"
+
+
+
+!ENDIF
diff --git a/protocols/IcqOscarJ/icqoscar8.vcproj b/protocols/IcqOscarJ/icqoscar8.vcproj
new file mode 100644
index 0000000000..73b1bb1c12
--- /dev/null
+++ b/protocols/IcqOscarJ/icqoscar8.vcproj
@@ -0,0 +1,1991 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="icqoscar8"
+ ProjectGUID="{01DDCB36-4DE2-405D-BC36-2C8BDEB86659}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2"
+ WholeProgramOptimization="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="1"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="FALSE"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="TRUE"
+ ExceptionHandling="FALSE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="icqoscar.h"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="TRUE"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="vc7to6.lib wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)/icq.dll"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="../../lib"
+ IgnoreAllDefaultLibraries="TRUE"
+ GenerateDebugInformation="TRUE"
+ GenerateMapFile="TRUE"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ OptimizeForWindows98="1"
+ ImportLibrary=""
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/icqoscar8.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="icqoscar.h"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)/icq.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ GenerateMapFile="TRUE"
+ BaseAddress="0x25000000"
+ ImportLibrary=""
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/icqoscar8.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug Unicode|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="1">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ BufferSecurityCheck="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="icqoscar.h"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="TRUE"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)/icq.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ GenerateMapFile="TRUE"
+ BaseAddress="0x25000000"
+ ImportLibrary=""
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/icqoscar8.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release Unicode|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="1"
+ WholeProgramOptimization="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ GlobalOptimizations="TRUE"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="FALSE"
+ OptimizeForProcessor="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="TRUE"
+ ExceptionHandling="FALSE"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="icqoscar.h"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="TRUE"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="vc7to6.lib wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)/icq.dll"
+ AdditionalLibraryDirectories="../../lib"
+ IgnoreAllDefaultLibraries="TRUE"
+ GenerateDebugInformation="TRUE"
+ GenerateMapFile="TRUE"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ OptimizeForWindows98="1"
+ ImportLibrary=""
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/icqoscar8.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="UI\askauthentication.h">
+ </File>
+ <File
+ RelativePath="capabilities.h">
+ </File>
+ <File
+ RelativePath="channels.h">
+ </File>
+ <File
+ RelativePath=".\cookies.h">
+ </File>
+ <File
+ RelativePath=".\directpackets.h">
+ </File>
+ <File
+ RelativePath="families.h">
+ </File>
+ <File
+ RelativePath="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_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_proto.h">
+ </File>
+ <File
+ RelativePath=".\icq_rates.h">
+ </File>
+ <File
+ RelativePath="icq_server.h">
+ </File>
+ <File
+ RelativePath="icq_servlist.h">
+ </File>
+ <File
+ RelativePath="icq_uploadui.h">
+ </File>
+ <File
+ RelativePath=".\icq_xtraz.h">
+ </File>
+ <File
+ RelativePath="icqosc_svcs.h">
+ </File>
+ <File
+ RelativePath="icqoscar.h">
+ </File>
+ <File
+ RelativePath="init.h">
+ </File>
+ <File
+ RelativePath="log.h">
+ </File>
+ <File
+ RelativePath="UI\loginpassword.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="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ <File
+ RelativePath=".\icos\auth_ask.ico">
+ </File>
+ <File
+ RelativePath=".\icos\auth_grant.ico">
+ </File>
+ <File
+ RelativePath=".\icos\auth_revoke.ico">
+ </File>
+ <File
+ RelativePath=".\changeinfo\expandst.ico">
+ </File>
+ <File
+ RelativePath="icos\icq.ico">
+ </File>
+ <File
+ RelativePath="resources.rc">
+ </File>
+ <File
+ RelativePath=".\icos\srvlist_add.ico">
+ </File>
+ </Filter>
+ <Filter
+ Name="FLAP Channels"
+ Filter="">
+ <File
+ RelativePath="chan_01login.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_02data.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_03error.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_04close.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_05ping.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="SNAC Families"
+ Filter="">
+ <File
+ RelativePath="fam_01service.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_02location.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_03buddy.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_04message.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_09bos.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\fam_0alookup.cpp">
+ </File>
+ <File
+ RelativePath="fam_0bstatus.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_13servclist.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_15icqserver.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Direct Connection"
+ Filter="">
+ <File
+ RelativePath="icq_direct.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_directmsg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_filerequests.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_filetransfer.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\oscar_filetransfer.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Miranda Bits"
+ Filter="">
+ <File
+ RelativePath=".\cookies.cpp">
+ </File>
+ <File
+ RelativePath="icq_advsearch.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_db.cpp">
+ </File>
+ <File
+ RelativePath=".\icq_menu.cpp">
+ </File>
+ <File
+ RelativePath=".\icq_popups.cpp">
+ </File>
+ <File
+ RelativePath=".\icq_proto.cpp">
+ </File>
+ <File
+ RelativePath=".\icq_xstatus.cpp">
+ </File>
+ <File
+ RelativePath="icqosc_svcs.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="init.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </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"
+ Filter="">
+ <File
+ RelativePath="UI\askauthentication.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_firstrun.cpp">
+ </File>
+ <File
+ RelativePath="icq_opts.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_uploadui.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="UI\loginpassword.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="UI\userinfotab.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Changeinfo"
+ Filter="">
+ <File
+ RelativePath=".\changeinfo\changeinfo.h">
+ </File>
+ <File
+ RelativePath=".\changeinfo\constants.cpp">
+ </File>
+ <File
+ RelativePath=".\changeinfo\db.cpp">
+ </File>
+ <File
+ RelativePath=".\changeinfo\dlgproc.cpp">
+ </File>
+ <File
+ RelativePath=".\changeinfo\editlist.cpp">
+ </File>
+ <File
+ RelativePath=".\changeinfo\editstring.cpp">
+ </File>
+ <File
+ RelativePath=".\changeinfo\main.cpp">
+ </File>
+ <File
+ RelativePath=".\changeinfo\upload.cpp">
+ </File>
+ </Filter>
+ <File
+ RelativePath="capabilities.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\directpackets.cpp">
+ </File>
+ <File
+ RelativePath=".\fam_17signon.cpp">
+ </File>
+ <File
+ RelativePath="i18n.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\iconlib.cpp">
+ </File>
+ <File
+ RelativePath="icq_avatar.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_clients.cpp">
+ </File>
+ <File
+ RelativePath="icq_fieldnames.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_http.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_infoupdate.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_packet.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_rates.cpp">
+ </File>
+ <File
+ RelativePath="icq_server.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_servlist.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_xtraz.cpp">
+ </File>
+ <File
+ RelativePath="icqoscar.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="stdpackets.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tlv.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="utilities.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/protocols/IcqOscarJ/icqoscar8_10.vcxproj b/protocols/IcqOscarJ/icqoscar8_10.vcxproj
new file mode 100644
index 0000000000..3820a5724e
--- /dev/null
+++ b/protocols/IcqOscarJ/icqoscar8_10.vcxproj
@@ -0,0 +1,690 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug Unicode|Win32">
+ <Configuration>Debug Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug Unicode|x64">
+ <Configuration>Debug Unicode</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|Win32">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|x64">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>icqoscar8</ProjectName>
+ <ProjectGuid>{01DDCB36-4DE2-405D-BC36-2C8BDEB86659}</ProjectGuid>
+ <RootNamespace>icqoscar8</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</IgnoreImportLibrary>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IgnoreImportLibrary>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">true</IgnoreImportLibrary>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">true</IgnoreImportLibrary>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">true</IgnoreImportLibrary>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">true</IgnoreImportLibrary>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">icq</TargetName>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">icq</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">icq</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">icq</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">icq</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">icq</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">icq</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">icq</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/icqoscar8.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>false</ExceptionHandling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>icqoscar.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>
+ </AssemblerListingLocation>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0417</Culture>
+ <AdditionalIncludeDirectories>./../../include/msapi/</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/ALIGN:4096 /ignore:4108 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>wsock32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27X86%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <GenerateMapFile>false</GenerateMapFile>
+ <MapFileName>
+ </MapFileName>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>.\Release/icqoscar8.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>false</ExceptionHandling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>icqoscar.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>
+ </AssemblerListingLocation>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0417</Culture>
+ <AdditionalIncludeDirectories>./../../include/msapi/</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/ALIGN:4096 /ignore:4108 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>wsock32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <GenerateMapFile>false</GenerateMapFile>
+ <MapFileName>
+ </MapFileName>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/icqoscar8.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>icqoscar.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>
+ </AssemblerListingLocation>
+ <BrowseInformationFile>
+ </BrowseInformationFile>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>./../../include/</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>wsock32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <GenerateMapFile>false</GenerateMapFile>
+ <MapFileName>
+ </MapFileName>
+ <BaseAddress>0x25000000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>.\Debug/icqoscar8.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>icqoscar.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>
+ </AssemblerListingLocation>
+ <BrowseInformationFile>
+ </BrowseInformationFile>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>./../../include/msapi/</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>wsock32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <GenerateMapFile>false</GenerateMapFile>
+ <MapFileName>
+ </MapFileName>
+ <BaseAddress>0x25000000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/icqoscar8.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>icqoscar.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>
+ </AssemblerListingLocation>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>./../../include/msapi/</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>wsock32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <GenerateMapFile>false</GenerateMapFile>
+ <MapFileName>
+ </MapFileName>
+ <BaseAddress>0x25000000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>.\Debug/icqoscar8.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>icqoscar.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>
+ </AssemblerListingLocation>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>./../../include/msapi/</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>wsock32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <GenerateMapFile>false</GenerateMapFile>
+ <MapFileName>
+ </MapFileName>
+ <BaseAddress>0x25000000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/icqoscar8.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>false</ExceptionHandling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>icqoscar.h</PrecompiledHeaderFile>
+ <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0417</Culture>
+ <AdditionalIncludeDirectories>./../../include/msapi/</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/ALIGN:4096 /ignore:4108 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>wsock32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27X86%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>.\Release/icqoscar8.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>false</ExceptionHandling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>icqoscar.h</PrecompiledHeaderFile>
+ <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0417</Culture>
+ <AdditionalIncludeDirectories>./../../include/msapi/</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/ALIGN:4096 /ignore:4108 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>wsock32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="UI\askauthentication.h" />
+ <ClInclude Include="capabilities.h" />
+ <ClInclude Include="channels.h" />
+ <ClInclude Include="cookies.h" />
+ <ClInclude Include="directpackets.h" />
+ <ClInclude Include="families.h" />
+ <ClInclude Include="guids.h" />
+ <ClInclude Include="i18n.h" />
+ <ClInclude Include="iconlib.h" />
+ <ClInclude Include="icq_advsearch.h" />
+ <ClInclude Include="icq_avatar.h" />
+ <ClInclude Include="icq_constants.h" />
+ <ClInclude Include="icq_direct.h" />
+ <ClInclude Include="icq_fieldnames.h" />
+ <ClInclude Include="icq_http.h" />
+ <ClInclude Include="icq_infoupdate.h" />
+ <ClInclude Include="icq_opts.h" />
+ <ClInclude Include="icq_packet.h" />
+ <ClInclude Include="icq_proto.h" />
+ <ClInclude Include="icq_rates.h" />
+ <ClInclude Include="icq_server.h" />
+ <ClInclude Include="icq_servlist.h" />
+ <ClInclude Include="icq_uploadui.h" />
+ <ClInclude Include="icq_xtraz.h" />
+ <ClInclude Include="icqosc_svcs.h" />
+ <ClInclude Include="icqoscar.h" />
+ <ClInclude Include="init.h" />
+ <ClInclude Include="log.h" />
+ <ClInclude Include="UI\loginpassword.h" />
+ <ClInclude Include="oscar_filetransfer.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="stdpackets.h" />
+ <ClInclude Include="tlv.h" />
+ <ClInclude Include="UI\userinfotab.h" />
+ <ClInclude Include="utilities.h" />
+ <ClInclude Include="changeinfo\changeinfo.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="icos\icq.ico" />
+ <None Include="docs\icq-readme.txt" />
+ <None Include="docs\IcqOscarJ-db settings.txt" />
+ <None Include="docs\IcqOscarJ-translation.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resources.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="chan_01login.cpp" />
+ <ClCompile Include="chan_02data.cpp" />
+ <ClCompile Include="chan_03error.cpp" />
+ <ClCompile Include="chan_04close.cpp" />
+ <ClCompile Include="chan_05ping.cpp" />
+ <ClCompile Include="fam_01service.cpp" />
+ <ClCompile Include="fam_02location.cpp" />
+ <ClCompile Include="fam_03buddy.cpp" />
+ <ClCompile Include="fam_04message.cpp" />
+ <ClCompile Include="fam_09bos.cpp" />
+ <ClCompile Include="fam_0alookup.cpp" />
+ <ClCompile Include="fam_0bstatus.cpp" />
+ <ClCompile Include="fam_13servclist.cpp" />
+ <ClCompile Include="fam_15icqserver.cpp" />
+ <ClCompile Include="fam_17signon.cpp" />
+ <ClCompile Include="icq_direct.cpp" />
+ <ClCompile Include="icq_directmsg.cpp" />
+ <ClCompile Include="icq_filerequests.cpp" />
+ <ClCompile Include="icq_filetransfer.cpp" />
+ <ClCompile Include="icq_menu.cpp" />
+ <ClCompile Include="oscar_filetransfer.cpp" />
+ <ClCompile Include="icq_advsearch.cpp" />
+ <ClCompile Include="icq_db.cpp" />
+ <ClCompile Include="icq_popups.cpp" />
+ <ClCompile Include="icq_proto.cpp" />
+ <ClCompile Include="icq_xstatus.cpp" />
+ <ClCompile Include="icqosc_svcs.cpp" />
+ <ClCompile Include="init.cpp" />
+ <ClCompile Include="log.cpp" />
+ <ClCompile Include="UI\askauthentication.cpp" />
+ <ClCompile Include="icq_firstrun.cpp" />
+ <ClCompile Include="icq_opts.cpp" />
+ <ClCompile Include="icq_uploadui.cpp" />
+ <ClCompile Include="UI\loginpassword.cpp" />
+ <ClCompile Include="UI\userinfotab.cpp" />
+ <ClCompile Include="changeinfo\constants.cpp" />
+ <ClCompile Include="changeinfo\db.cpp" />
+ <ClCompile Include="changeinfo\dlgproc.cpp" />
+ <ClCompile Include="changeinfo\editlist.cpp" />
+ <ClCompile Include="changeinfo\editstring.cpp" />
+ <ClCompile Include="changeinfo\main.cpp" />
+ <ClCompile Include="changeinfo\upload.cpp" />
+ <ClCompile Include="capabilities.cpp" />
+ <ClCompile Include="cookies.cpp" />
+ <ClCompile Include="directpackets.cpp" />
+ <ClCompile Include="i18n.cpp" />
+ <ClCompile Include="iconlib.cpp" />
+ <ClCompile Include="icq_avatar.cpp" />
+ <ClCompile Include="icq_clients.cpp" />
+ <ClCompile Include="icq_fieldnames.cpp" />
+ <ClCompile Include="icq_http.cpp" />
+ <ClCompile Include="icq_infoupdate.cpp" />
+ <ClCompile Include="icq_packet.cpp" />
+ <ClCompile Include="icq_rates.cpp" />
+ <ClCompile Include="icq_server.cpp" />
+ <ClCompile Include="icq_servlist.cpp" />
+ <ClCompile Include="icq_xtraz.cpp" />
+ <ClCompile Include="icqoscar.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="stdpackets.cpp" />
+ <ClCompile Include="tlv.cpp" />
+ <ClCompile Include="utilities.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/IcqOscarJ/icqoscar8_10.vcxproj.filters b/protocols/IcqOscarJ/icqoscar8_10.vcxproj.filters
new file mode 100644
index 0000000000..f6b34037b3
--- /dev/null
+++ b/protocols/IcqOscarJ/icqoscar8_10.vcxproj.filters
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{d8db2ef5-99b1-4927-b9dc-b915eeda857f}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{bd7e4337-1d6c-4e87-9406-2f853fb4bf7f}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ <Filter Include="FLAP Channels">
+ <UniqueIdentifier>{0bc28603-23fc-4a7b-8b14-c96119903bdb}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="SNAC Families">
+ <UniqueIdentifier>{e643d1b0-d2ef-4f24-b536-8f3b7bcb4cab}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Direct Connection">
+ <UniqueIdentifier>{731741ea-7d07-4c09-aa88-641a254b5f48}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Miranda Bits">
+ <UniqueIdentifier>{33754d1e-5911-4ebf-bbb2-f7f9ac930bb5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Documentation">
+ <UniqueIdentifier>{a21400e8-a7db-41a3-9bae-b2f9e0bde49a}</UniqueIdentifier>
+ <Extensions>.txt</Extensions>
+ </Filter>
+ <Filter Include="UI">
+ <UniqueIdentifier>{b50a315e-0455-4a42-8aa6-e73618237ff3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Changeinfo">
+ <UniqueIdentifier>{8380b888-17be-4a22-a3f2-36f8fd65b730}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="UI\askauthentication.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="capabilities.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="channels.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="cookies.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="directpackets.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="families.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="guids.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="i18n.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="iconlib.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_advsearch.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_avatar.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_constants.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_direct.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_fieldnames.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_http.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_infoupdate.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_opts.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_packet.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_proto.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_rates.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_server.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_servlist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_uploadui.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icq_xtraz.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icqosc_svcs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icqoscar.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="init.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="log.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="UI\loginpassword.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="oscar_filetransfer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="stdpackets.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="tlv.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="UI\userinfotab.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="utilities.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="changeinfo\changeinfo.h">
+ <Filter>Changeinfo</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="icos\icq.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="docs\icq-readme.txt">
+ <Filter>Documentation</Filter>
+ </None>
+ <None Include="docs\IcqOscarJ-db settings.txt">
+ <Filter>Documentation</Filter>
+ </None>
+ <None Include="docs\IcqOscarJ-translation.txt">
+ <Filter>Documentation</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resources.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="chan_01login.cpp">
+ <Filter>FLAP Channels</Filter>
+ </ClCompile>
+ <ClCompile Include="chan_02data.cpp">
+ <Filter>FLAP Channels</Filter>
+ </ClCompile>
+ <ClCompile Include="chan_03error.cpp">
+ <Filter>FLAP Channels</Filter>
+ </ClCompile>
+ <ClCompile Include="chan_04close.cpp">
+ <Filter>FLAP Channels</Filter>
+ </ClCompile>
+ <ClCompile Include="chan_05ping.cpp">
+ <Filter>FLAP Channels</Filter>
+ </ClCompile>
+ <ClCompile Include="fam_01service.cpp">
+ <Filter>SNAC Families</Filter>
+ </ClCompile>
+ <ClCompile Include="fam_02location.cpp">
+ <Filter>SNAC Families</Filter>
+ </ClCompile>
+ <ClCompile Include="fam_03buddy.cpp">
+ <Filter>SNAC Families</Filter>
+ </ClCompile>
+ <ClCompile Include="fam_04message.cpp">
+ <Filter>SNAC Families</Filter>
+ </ClCompile>
+ <ClCompile Include="fam_09bos.cpp">
+ <Filter>SNAC Families</Filter>
+ </ClCompile>
+ <ClCompile Include="fam_0alookup.cpp">
+ <Filter>SNAC Families</Filter>
+ </ClCompile>
+ <ClCompile Include="fam_0bstatus.cpp">
+ <Filter>SNAC Families</Filter>
+ </ClCompile>
+ <ClCompile Include="fam_13servclist.cpp">
+ <Filter>SNAC Families</Filter>
+ </ClCompile>
+ <ClCompile Include="fam_15icqserver.cpp">
+ <Filter>SNAC Families</Filter>
+ </ClCompile>
+ <ClCompile Include="fam_17signon.cpp">
+ <Filter>SNAC Families</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_direct.cpp">
+ <Filter>Direct Connection</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_directmsg.cpp">
+ <Filter>Direct Connection</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_filerequests.cpp">
+ <Filter>Direct Connection</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_filetransfer.cpp">
+ <Filter>Direct Connection</Filter>
+ </ClCompile>
+ <ClCompile Include="oscar_filetransfer.cpp">
+ <Filter>Direct Connection</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_advsearch.cpp">
+ <Filter>Miranda Bits</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_db.cpp">
+ <Filter>Miranda Bits</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_popups.cpp">
+ <Filter>Miranda Bits</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_proto.cpp">
+ <Filter>Miranda Bits</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_xstatus.cpp">
+ <Filter>Miranda Bits</Filter>
+ </ClCompile>
+ <ClCompile Include="icqosc_svcs.cpp">
+ <Filter>Miranda Bits</Filter>
+ </ClCompile>
+ <ClCompile Include="init.cpp">
+ <Filter>Miranda Bits</Filter>
+ </ClCompile>
+ <ClCompile Include="log.cpp">
+ <Filter>Miranda Bits</Filter>
+ </ClCompile>
+ <ClCompile Include="UI\askauthentication.cpp">
+ <Filter>UI</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_firstrun.cpp">
+ <Filter>UI</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_opts.cpp">
+ <Filter>UI</Filter>
+ </ClCompile>
+ <ClCompile Include="icq_uploadui.cpp">
+ <Filter>UI</Filter>
+ </ClCompile>
+ <ClCompile Include="UI\loginpassword.cpp">
+ <Filter>UI</Filter>
+ </ClCompile>
+ <ClCompile Include="UI\userinfotab.cpp">
+ <Filter>UI</Filter>
+ </ClCompile>
+ <ClCompile Include="changeinfo\constants.cpp">
+ <Filter>Changeinfo</Filter>
+ </ClCompile>
+ <ClCompile Include="changeinfo\db.cpp">
+ <Filter>Changeinfo</Filter>
+ </ClCompile>
+ <ClCompile Include="changeinfo\dlgproc.cpp">
+ <Filter>Changeinfo</Filter>
+ </ClCompile>
+ <ClCompile Include="changeinfo\editlist.cpp">
+ <Filter>Changeinfo</Filter>
+ </ClCompile>
+ <ClCompile Include="changeinfo\editstring.cpp">
+ <Filter>Changeinfo</Filter>
+ </ClCompile>
+ <ClCompile Include="changeinfo\main.cpp">
+ <Filter>Changeinfo</Filter>
+ </ClCompile>
+ <ClCompile Include="changeinfo\upload.cpp">
+ <Filter>Changeinfo</Filter>
+ </ClCompile>
+ <ClCompile Include="capabilities.cpp" />
+ <ClCompile Include="cookies.cpp" />
+ <ClCompile Include="directpackets.cpp" />
+ <ClCompile Include="i18n.cpp" />
+ <ClCompile Include="iconlib.cpp" />
+ <ClCompile Include="icq_avatar.cpp" />
+ <ClCompile Include="icq_clients.cpp" />
+ <ClCompile Include="icq_fieldnames.cpp" />
+ <ClCompile Include="icq_http.cpp" />
+ <ClCompile Include="icq_infoupdate.cpp" />
+ <ClCompile Include="icq_packet.cpp" />
+ <ClCompile Include="icq_rates.cpp" />
+ <ClCompile Include="icq_server.cpp" />
+ <ClCompile Include="icq_servlist.cpp" />
+ <ClCompile Include="icq_xtraz.cpp" />
+ <ClCompile Include="icqoscar.cpp" />
+ <ClCompile Include="stdpackets.cpp" />
+ <ClCompile Include="tlv.cpp" />
+ <ClCompile Include="utilities.cpp" />
+ <ClCompile Include="icq_menu.cpp">
+ <Filter>Miranda Bits</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/IcqOscarJ/icqoscar8_8.vcproj b/protocols/IcqOscarJ/icqoscar8_8.vcproj
new file mode 100644
index 0000000000..7cd7f06f7a
--- /dev/null
+++ b/protocols/IcqOscarJ/icqoscar8_8.vcproj
@@ -0,0 +1,2406 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="icqoscar8"
+ ProjectGUID="{01DDCB36-4DE2-405D-BC36-2C8BDEB86659}"
+ RootNamespace="icqoscar8"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="true"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ ExceptionHandling="0"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerListingLocation=""
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)/icq.dll"
+ SuppressStartupBanner="true"
+ AdditionalManifestDependencies="type=&apos;Win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;X86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ GenerateMapFile="false"
+ MapFileName=""
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ LinkTimeCodeGeneration="1"
+ ImportLibrary=""
+ 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="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerListingLocation=""
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)/icq.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ GenerateMapFile="false"
+ MapFileName=""
+ BaseAddress="0x25000000"
+ ImportLibrary=""
+ 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="Debug Unicode|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="false"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ EnableFunctionLevelLinking="true"
+ FloatingPointModel="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerListingLocation=""
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)/icq.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(TargetDir)$(TargetName).pdb"
+ GenerateMapFile="false"
+ MapFileName=""
+ BaseAddress="0x25000000"
+ ImportLibrary=""
+ 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 Unicode|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ 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="1"
+ FavorSizeOrSpeed="2"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ ExceptionHandling="0"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerListingLocation=""
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)/icq.dll"
+ SuppressStartupBanner="true"
+ AdditionalManifestDependencies="type=&apos;Win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;X86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(TargetDir)$(TargetName).pdb"
+ GenerateMapFile="false"
+ MapFileName=""
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ LinkTimeCodeGeneration="1"
+ ImportLibrary=""
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="UI\askauthentication.h"
+ >
+ </File>
+ <File
+ RelativePath="capabilities.h"
+ >
+ </File>
+ <File
+ RelativePath="channels.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cookies.h"
+ >
+ </File>
+ <File
+ RelativePath=".\directpackets.h"
+ >
+ </File>
+ <File
+ RelativePath="families.h"
+ >
+ </File>
+ <File
+ RelativePath="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_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_proto.h"
+ >
+ </File>
+ <File
+ RelativePath=".\icq_rates.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_server.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_servlist.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_uploadui.h"
+ >
+ </File>
+ <File
+ RelativePath=".\icq_xtraz.h"
+ >
+ </File>
+ <File
+ RelativePath="icqosc_svcs.h"
+ >
+ </File>
+ <File
+ RelativePath="icqoscar.h"
+ >
+ </File>
+ <File
+ RelativePath="init.h"
+ >
+ </File>
+ <File
+ RelativePath="log.h"
+ >
+ </File>
+ <File
+ RelativePath="UI\loginpassword.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="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ <File
+ RelativePath="icos\icq.ico"
+ >
+ </File>
+ <File
+ RelativePath="resources.rc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="FLAP Channels"
+ >
+ <File
+ RelativePath="chan_01login.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_02data.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_03error.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_04close.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="chan_05ping.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="SNAC Families"
+ >
+ <File
+ RelativePath="fam_01service.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_02location.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_03buddy.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_04message.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_09bos.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\fam_0alookup.cpp"
+ >
+ </File>
+ <File
+ RelativePath="fam_0bstatus.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_13servclist.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fam_15icqserver.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\fam_17signon.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Direct Connection"
+ >
+ <File
+ RelativePath="icq_direct.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_directmsg.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_filerequests.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_filetransfer.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\oscar_filetransfer.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Miranda Bits"
+ >
+ <File
+ RelativePath="icq_advsearch.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_db.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\icq_menu.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\icq_popups.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\icq_xstatus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icqosc_svcs.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="init.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </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.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_firstrun.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_opts.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_uploadui.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="UI\loginpassword.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="UI\userinfotab.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Changeinfo"
+ >
+ <File
+ RelativePath=".\changeinfo\changeinfo.h"
+ >
+ </File>
+ <File
+ RelativePath=".\changeinfo\constants.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\changeinfo\db.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\changeinfo\dlgproc.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\changeinfo\editlist.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\changeinfo\editstring.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\changeinfo\main.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\changeinfo\upload.cpp"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="capabilities.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\cookies.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\directpackets.cpp"
+ >
+ </File>
+ <File
+ RelativePath="i18n.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\iconlib.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_avatar.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_clients.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_fieldnames.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_http.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_infoupdate.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_packet.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_proto.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\icq_rates.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_server.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="icq_servlist.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icq_xtraz.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icqoscar.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="stdpackets.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tlv.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="utilities.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/protocols/IcqOscarJ/icqoscar8_9.vcproj b/protocols/IcqOscarJ/icqoscar8_9.vcproj
new file mode 100644
index 0000000000..dd7b39bc1e
--- /dev/null
+++ b/protocols/IcqOscarJ/icqoscar8_9.vcproj
@@ -0,0 +1,1381 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="icqoscar8"
+ ProjectGUID="{01DDCB36-4DE2-405D-BC36-2C8BDEB86659}"
+ RootNamespace="icqoscar8"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName="Release/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="1"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ ExceptionHandling="0"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="true"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerListingLocation=""
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ SuppressStartupBanner="true"
+ AdditionalManifestDependencies="type=&apos;Win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;X86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ GenerateMapFile="false"
+ MapFileName=""
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ LinkTimeCodeGeneration="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)/$(TargetName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)64/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)64/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ 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="3"
+ TypeLibraryName="Release/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="1"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ ExceptionHandling="0"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="true"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerListingLocation=""
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ SuppressStartupBanner="true"
+ AdditionalManifestDependencies="type=&apos;Win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;*&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ GenerateMapFile="false"
+ MapFileName=""
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ LinkTimeCodeGeneration="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)/$(TargetName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName="Debug/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerListingLocation=""
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ GenerateMapFile="false"
+ MapFileName=""
+ BaseAddress="0x25000000"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)/$(TargetName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)64/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)64/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ 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="3"
+ TypeLibraryName="Debug/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerListingLocation=""
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ SuppressStartupBanner="true"
+ AdditionalManifestDependencies="type=&apos;Win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;*&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ GenerateMapFile="false"
+ MapFileName=""
+ BaseAddress="0x25000000"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)/$(TargetName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug Unicode|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName="Debug/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="false"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ EnableFunctionLevelLinking="true"
+ FloatingPointModel="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerListingLocation=""
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(TargetDir)$(TargetName).pdb"
+ GenerateMapFile="false"
+ MapFileName=""
+ BaseAddress="0x25000000"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)/$(TargetName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug Unicode|x64"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)64/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)64/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="3"
+ TypeLibraryName="Debug/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="false"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ EnableFunctionLevelLinking="true"
+ FloatingPointModel="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerListingLocation=""
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ SuppressStartupBanner="true"
+ AdditionalManifestDependencies="type=&apos;Win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;*&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(TargetDir)$(TargetName).pdb"
+ GenerateMapFile="false"
+ MapFileName=""
+ BaseAddress="0x25000000"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)/$(TargetName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release Unicode|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ 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="1"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ ExceptionHandling="0"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="true"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerOutput="4"
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ AdditionalManifestDependencies="type=&apos;Win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;X86&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ LinkTimeCodeGeneration="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)/$(TargetName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release Unicode|x64"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)64/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)64/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="3"
+ TypeLibraryName="Release/icqoscar8.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="1"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;icqoscar8_EXPORTS"
+ StringPooling="true"
+ ExceptionHandling="0"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="true"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="icqoscar.h"
+ AssemblerOutput="4"
+ BrowseInformationFile=""
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="wsock32.lib comctl32.lib"
+ OutputFile="$(OutDir)\icq.dll"
+ AdditionalManifestDependencies="type=&apos;Win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;*&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
+ GenerateDebugInformation="true"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ LinkTimeCodeGeneration="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)/$(TargetName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="UI\askauthentication.h"
+ >
+ </File>
+ <File
+ RelativePath="capabilities.h"
+ >
+ </File>
+ <File
+ RelativePath="channels.h"
+ >
+ </File>
+ <File
+ RelativePath="cookies.h"
+ >
+ </File>
+ <File
+ RelativePath="directpackets.h"
+ >
+ </File>
+ <File
+ RelativePath="families.h"
+ >
+ </File>
+ <File
+ RelativePath="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_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_proto.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_rates.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_server.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_servlist.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_uploadui.h"
+ >
+ </File>
+ <File
+ RelativePath="icq_xtraz.h"
+ >
+ </File>
+ <File
+ RelativePath="icqosc_svcs.h"
+ >
+ </File>
+ <File
+ RelativePath="icqoscar.h"
+ >
+ </File>
+ <File
+ RelativePath="init.h"
+ >
+ </File>
+ <File
+ RelativePath="log.h"
+ >
+ </File>
+ <File
+ RelativePath="UI\loginpassword.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="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ <File
+ RelativePath="icos\auth_ask.ico"
+ >
+ </File>
+ <File
+ RelativePath="icos\auth_grant.ico"
+ >
+ </File>
+ <File
+ RelativePath="icos\auth_revoke.ico"
+ >
+ </File>
+ <File
+ RelativePath="changeinfo\expandst.ico"
+ >
+ </File>
+ <File
+ RelativePath="icos\icq.ico"
+ >
+ </File>
+ <File
+ RelativePath="resources.rc"
+ >
+ </File>
+ <File
+ RelativePath="icos\srvlist_add.ico"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="FLAP Channels"
+ >
+ <File
+ RelativePath="chan_01login.cpp"
+ >
+ </File>
+ <File
+ RelativePath="chan_02data.cpp"
+ >
+ </File>
+ <File
+ RelativePath="chan_03error.cpp"
+ >
+ </File>
+ <File
+ RelativePath="chan_04close.cpp"
+ >
+ </File>
+ <File
+ RelativePath="chan_05ping.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="SNAC Families"
+ >
+ <File
+ RelativePath="fam_01service.cpp"
+ >
+ </File>
+ <File
+ RelativePath="fam_02location.cpp"
+ >
+ </File>
+ <File
+ RelativePath="fam_03buddy.cpp"
+ >
+ </File>
+ <File
+ RelativePath="fam_04message.cpp"
+ >
+ </File>
+ <File
+ RelativePath="fam_09bos.cpp"
+ >
+ </File>
+ <File
+ RelativePath="fam_0alookup.cpp"
+ >
+ </File>
+ <File
+ RelativePath="fam_0bstatus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="fam_13servclist.cpp"
+ >
+ </File>
+ <File
+ RelativePath="fam_15icqserver.cpp"
+ >
+ </File>
+ <File
+ RelativePath="fam_17signon.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Direct Connection"
+ >
+ <File
+ RelativePath="icq_direct.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_directmsg.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_filerequests.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_filetransfer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="oscar_filetransfer.cpp"
+ >
+ </File>
+ <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>
+ <Filter
+ Name="Miranda Bits"
+ >
+ <File
+ RelativePath="icq_advsearch.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_db.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\icq_menu.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_popups.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_proto.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_xstatus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icqosc_svcs.cpp"
+ >
+ </File>
+ <File
+ RelativePath="init.cpp"
+ >
+ </File>
+ <File
+ RelativePath="log.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="UI"
+ >
+ <File
+ RelativePath="UI\askauthentication.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_firstrun.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_opts.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_uploadui.cpp"
+ >
+ </File>
+ <File
+ RelativePath="UI\loginpassword.cpp"
+ >
+ </File>
+ <File
+ RelativePath="UI\userinfotab.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Changeinfo"
+ >
+ <File
+ RelativePath="changeinfo\changeinfo.h"
+ >
+ </File>
+ <File
+ RelativePath="changeinfo\constants.cpp"
+ >
+ </File>
+ <File
+ RelativePath="changeinfo\db.cpp"
+ >
+ </File>
+ <File
+ RelativePath="changeinfo\dlgproc.cpp"
+ >
+ </File>
+ <File
+ RelativePath="changeinfo\editlist.cpp"
+ >
+ </File>
+ <File
+ RelativePath="changeinfo\editstring.cpp"
+ >
+ </File>
+ <File
+ RelativePath="changeinfo\main.cpp"
+ >
+ </File>
+ <File
+ RelativePath="changeinfo\upload.cpp"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="capabilities.cpp"
+ >
+ </File>
+ <File
+ RelativePath="cookies.cpp"
+ >
+ </File>
+ <File
+ RelativePath="directpackets.cpp"
+ >
+ </File>
+ <File
+ RelativePath="i18n.cpp"
+ >
+ </File>
+ <File
+ RelativePath="iconlib.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_avatar.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_clients.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_fieldnames.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_http.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_infoupdate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_packet.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_rates.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_server.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_servlist.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icq_xtraz.cpp"
+ >
+ </File>
+ <File
+ RelativePath="icqoscar.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="stdpackets.cpp"
+ >
+ </File>
+ <File
+ RelativePath="tlv.cpp"
+ >
+ </File>
+ <File
+ RelativePath="utilities.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/protocols/IcqOscarJ/init.cpp b/protocols/IcqOscarJ/init.cpp
new file mode 100644
index 0000000000..d7421c6c26
--- /dev/null
+++ b/protocols/IcqOscarJ/init.cpp
@@ -0,0 +1,320 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/init.cpp $
+// Revision : $Revision: 13596 $
+// Last change on : $Date: 2011-04-15 22:07:23 +0300 (Пт, 15 апр 2011) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+#include "m_extraicons.h"
+
+HINSTANCE hInst;
+PLUGINLINK* pluginLink;
+MM_INTERFACE mmi;
+UTF8_INTERFACE utfi;
+MD5_INTERFACE md5i;
+LIST_INTERFACE li;
+int hLangpack;
+
+DWORD MIRANDA_VERSION;
+
+HANDLE hStaticServices[1];
+IcqIconHandle hStaticIcons[4];
+HANDLE hStaticHooks[1];;
+HANDLE hExtraXStatus = NULL;
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "IcqOscarJ Protocol",
+ __VERSION_DWORD,
+ "Support for ICQ network, enhanced.",
+ "Joe Kucera, Bio, Martin berg, Richard Hughes, Jon Keating, etc",
+ "jokusoftware@miranda-im.org",
+ "(C) 2000-2010 M.berg, R.Hughes, J.Keating, Bio, Angeli-Ka, G.Hazan, J.Kucera",
+ "http://addons.miranda-im.org/details.php?action=viewfile&id=1683",
+ UNICODE_AWARE,
+ 0, //doesn't replace anything built-in
+#if defined( _UNICODE )
+ {0x73a9615c, 0x7d4e, 0x4555, {0xba, 0xdb, 0xee, 0x5, 0xdc, 0x92, 0x8e, 0xff}} // {73A9615C-7D4E-4555-BADB-EE05DC928EFF}
+#else
+ {0x89cf4c3d, 0x7014, 0x4658, {0xa1, 0x3b, 0x46, 0xdb, 0x49, 0x68, 0xc7, 0x3b}} // {89CF4C3D-7014-4658-A13B-46DB4968C73B}
+#endif
+};
+
+extern "C" PLUGININFOEX __declspec(dllexport) *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ // Only load for 0.9.0.8 or greater
+ // We need the new Unicode aware Contact Search API
+ if (mirandaVersion < MIRANDA_VERSION_CORE)
+ {
+ MessageBoxA( NULL, "ICQ plugin cannot be loaded. It requires Miranda IM " MIRANDA_VERSION_CORE_STRING " or later.", "ICQ Plugin",
+ MB_OK|MB_ICONWARNING|MB_SETFOREGROUND|MB_TOPMOST );
+ return NULL;
+ }
+
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_PROTOCOL, MIID_LAST};
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static PROTO_INTERFACE* icqProtoInit( const char* pszProtoName, const TCHAR* tszUserName )
+{
+ CIcqProto *ppro = new CIcqProto(pszProtoName, tszUserName);
+ g_Instances.insert(ppro);
+ return ppro;
+}
+
+
+static int icqProtoUninit( PROTO_INTERFACE* ppro )
+{
+ g_Instances.remove(( CIcqProto* )ppro);
+ delete ( CIcqProto* )ppro;
+ return 0;
+}
+
+
+static int OnModulesLoaded( WPARAM, LPARAM )
+{
+ hExtraXStatus = ExtraIcon_Register("xstatus", "ICQ XStatus");
+ return 0;
+}
+
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+ mir_getLI( &li );
+ mir_getMMI( &mmi );
+ mir_getUTFI( &utfi );
+ mir_getMD5I( &md5i );
+ mir_getLP( &pluginInfo );
+
+ // Get Miranda version
+ MIRANDA_VERSION = (DWORD)CallService(MS_SYSTEM_GETVERSION, 0, 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
+
+ if (strstrnull(szVer, "alpha") != NULL)
+ { // Are we running under Alpha Core
+ MIRANDA_VERSION |= 0x80000000;
+ }
+ else if (strstrnull(szVer, "preview") == NULL)
+ { // for Final Releases of Miranda 0.5+ clear build number
+ MIRANDA_VERSION &= 0xFFFFFF00;
+ }
+
+ // Check if _UNICODE matches Miranda's _UNICODE
+#if defined( _UNICODE )
+ if (strstrnull(szVer, "unicode") == NULL)
+ {
+ char szMsg[MAX_PATH], szCaption[100];
+
+ MessageBoxUtf(NULL, ICQTranslateUtfStatic("You cannot use Unicode version of ICQ Protocol plug-in with Ansi version of Miranda IM.", szMsg, MAX_PATH),
+ ICQTranslateUtfStatic("ICQ Plugin", szCaption, 100), MB_OK|MB_ICONWARNING|MB_SETFOREGROUND|MB_TOPMOST);
+ return 1; // Failure
+ }
+#else
+ if (strstrnull(szVer, "unicode") != NULL)
+ {
+ MessageBox(NULL, Translate("You cannot use Ansi version of ICQ Protocol plug-in with Unicode version of Miranda IM."), Translate("ICQ Plugin"),
+ MB_OK|MB_ICONWARNING|MB_SETFOREGROUND|MB_TOPMOST);
+ return 1; // Failure
+ }
+#endif
+ }
+
+ srand(time(NULL));
+ _tzset();
+
+ // Register the module
+ PROTOCOLDESCRIPTOR pd = {0};
+ pd.cbSize = sizeof(pd);
+ pd.szName = ICQ_PROTOCOL_NAME;
+ pd.type = PROTOTYPE_PROTOCOL;
+ pd.fnInit = icqProtoInit;
+ pd.fnUninit = icqProtoUninit;
+ CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
+
+ // Initialize charset conversion routines
+ InitI18N();
+
+ // Register static services
+ hStaticServices[0] = CreateServiceFunction(ICQ_DB_GETEVENTTEXT_MISSEDMESSAGE, icq_getEventTextMissedMessage);
+
+ {
+ // Define global icons
+ char szSectionName[MAX_PATH];
+ null_snprintf(szSectionName, sizeof(szSectionName), "Protocols/%s", ICQ_PROTOCOL_NAME);
+
+ TCHAR lib[MAX_PATH];
+ GetModuleFileName(hInst, lib, MAX_PATH);
+ hStaticIcons[ISI_AUTH_REQUEST] = IconLibDefine(LPGEN("Request authorization"), szSectionName, NULL, "req_auth", lib, -IDI_AUTH_ASK);
+ hStaticIcons[ISI_AUTH_GRANT] = IconLibDefine(LPGEN("Grant authorization"), szSectionName, NULL, "grant_auth", lib, -IDI_AUTH_GRANT);
+ hStaticIcons[ISI_AUTH_REVOKE] = IconLibDefine(LPGEN("Revoke authorization"), szSectionName, NULL, "revoke_auth", lib, -IDI_AUTH_REVOKE);
+ hStaticIcons[ISI_ADD_TO_SERVLIST] = IconLibDefine(LPGEN("Add to server list"), szSectionName, NULL, "add_to_server", lib, -IDI_SERVLIST_ADD);
+ }
+
+ hStaticHooks[0] = HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+
+ g_MenuInit();
+ return 0;
+}
+
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ int i;
+
+ // Release static icon handles
+ for (i = 0; i < SIZEOF(hStaticIcons); i++)
+ IconLibRemove(&hStaticIcons[i]);
+
+ // Release static event hooks
+ for (i = 0; i < SIZEOF(hStaticHooks); i++)
+ if (hStaticHooks[i])
+ UnhookEvent(hStaticHooks[i]);
+
+ // destroying contact menu
+ g_MenuUninit();
+
+ // Destroy static service functions
+ for (i = 0; i < SIZEOF(hStaticServices); i++)
+ if (hStaticServices[i])
+ DestroyServiceFunction(hStaticServices[i]);
+
+ g_Instances.destroy();
+
+ return 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// OnPrebuildContactMenu event
+
+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);
+}
+
+static 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);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// OnReloadIcons event
+
+int CIcqProto::OnReloadIcons(WPARAM wParam, LPARAM lParam)
+{
+ memset(bXStatusCListIconsValid, 0, sizeof(bXStatusCListIconsValid));
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// UpdateGlobalSettings event
+
+void CIcqProto::UpdateGlobalSettings()
+{
+ char szServer[MAX_PATH] = "";
+ getSettingStringStatic(NULL, "OscarServer", szServer, MAX_PATH);
+
+ m_bSecureConnection = getSettingByte(NULL, "SecureConnection", DEFAULT_SECURE_CONNECTION);
+ if (szServer[0])
+ {
+ if (strstr(szServer, "aol.com"))
+ setSettingString(NULL, "OscarServer", m_bSecureConnection ? DEFAULT_SERVER_HOST_SSL : DEFAULT_SERVER_HOST);
+
+ if (m_bSecureConnection && !_strnicmp(szServer, "login.", 6))
+ {
+ setSettingString(NULL, "OscarServer", DEFAULT_SERVER_HOST_SSL);
+ setSettingWord(NULL, "OscarPort", DEFAULT_SERVER_PORT_SSL);
+ }
+ }
+
+ if (m_hServerNetlibUser)
+ {
+ NETLIBUSERSETTINGS nlus = {0};
+
+ nlus.cbSize = sizeof(NETLIBUSERSETTINGS);
+ if (!m_bSecureConnection && CallService(MS_NETLIB_GETUSERSETTINGS, (WPARAM)m_hServerNetlibUser, (LPARAM)&nlus))
+ {
+ if (nlus.useProxy && nlus.proxyType == PROXYTYPE_HTTP)
+ m_bGatewayMode = 1;
+ else
+ m_bGatewayMode = 0;
+ }
+ else
+ m_bGatewayMode = 0;
+ }
+
+ m_bSecureLogin = getSettingByte(NULL, "SecureLogin", DEFAULT_SECURE_LOGIN);
+ m_bAimEnabled = getSettingByte(NULL, "AimEnabled", DEFAULT_AIM_ENABLED);
+ m_bUtfEnabled = getSettingByte(NULL, "UtfEnabled", DEFAULT_UTF_ENABLED);
+ m_wAnsiCodepage = getSettingWord(NULL, "AnsiCodePage", DEFAULT_ANSI_CODEPAGE);
+ m_bDCMsgEnabled = getSettingByte(NULL, "DirectMessaging", DEFAULT_DCMSG_ENABLED);
+ m_bTempVisListEnabled = getSettingByte(NULL, "TempVisListEnabled", DEFAULT_TEMPVIS_ENABLED);
+ m_bSsiEnabled = getSettingByte(NULL, "UseServerCList", DEFAULT_SS_ENABLED);
+ m_bSsiSimpleGroups = FALSE; /// TODO: enable, after server-list revolution is over
+ m_bAvatarsEnabled = getSettingByte(NULL, "AvatarsEnabled", DEFAULT_AVATARS_ENABLED);
+ m_bXStatusEnabled = getSettingByte(NULL, "XStatusEnabled", DEFAULT_XSTATUS_ENABLED);
+ m_bMoodsEnabled = getSettingByte(NULL, "MoodsEnabled", DEFAULT_MOODS_ENABLED);
+}
diff --git a/protocols/IcqOscarJ/init.h b/protocols/IcqOscarJ/init.h
new file mode 100644
index 0000000000..0f49a0bf22
--- /dev/null
+++ b/protocols/IcqOscarJ/init.h
@@ -0,0 +1,47 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/init.h $
+// Revision : $Revision: 13284 $
+// Last change on : $Date: 2011-01-17 00:42:01 +0200 (Пн, 17 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+// Debug defines
+#define DBG_CAPHTML
+#define DBG_CAPMTN
+#define DBG_CAPXTRAZ
+#undef DBG_CAPXTRAZ_MUC
+#define DBG_NEWCAPS
+#define DBG_OSCARFT
+#define DBG_AIMCONTACTSEND
+
+void g_MenuInit();
+void g_MenuUninit();
diff --git a/protocols/IcqOscarJ/log.cpp b/protocols/IcqOscarJ/log.cpp
new file mode 100644
index 0000000000..c6ff958f70
--- /dev/null
+++ b/protocols/IcqOscarJ/log.cpp
@@ -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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/log.cpp $
+// Revision : $Revision: 10574 $
+// Last change on : $Date: 2009-08-18 20:20:42 +0300 (Вт, 18 авг 2009) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+extern BOOL bPopUpService;
+
+static const char *szLevelDescr[] = {LPGEN("ICQ Note"), LPGEN("ICQ Warning"), LPGEN("ICQ Error"), LPGEN("ICQ Fatal")};
+
+struct LogMessageInfo {
+ const char *szMsg;
+ const char *szTitle;
+ BYTE bLevel;
+};
+
+
+void __cdecl CIcqProto::icq_LogMessageThread(void* arg)
+{
+ LogMessageInfo *err = (LogMessageInfo*)arg;
+ if (!err)
+ return;
+
+ if (bPopUpService && getSettingByte(NULL, "PopupsLogEnabled", DEFAULT_LOG_POPUPS_ENABLED))
+ {
+ ShowPopUpMsg(NULL, err->szTitle, err->szMsg, err->bLevel);
+
+ SAFE_FREE((void**)&err->szMsg);
+ SAFE_FREE((void**)&err);
+
+ return;
+ }
+
+ bErrorBoxVisible = TRUE;
+ if (err->szMsg && err->szTitle)
+ MessageBoxUtf(NULL, err->szMsg, err->szTitle, MB_OK);
+ SAFE_FREE((void**)&err->szMsg);
+ SAFE_FREE((void**)&err);
+ bErrorBoxVisible = FALSE;
+}
+
+
+void CIcqProto::icq_LogMessage(int level, const char *szMsg)
+{
+ NetLog_Server("%s", szMsg);
+
+ int displayLevel = getSettingByte(NULL, "ShowLogLevel", LOG_WARNING);
+ if (level >= displayLevel)
+ {
+ if (!bErrorBoxVisible || !getSettingByte(NULL, "IgnoreMultiErrorBox", 0))
+ {
+ // error not shown or allowed multi - show messagebox
+ LogMessageInfo *lmi = (LogMessageInfo*)SAFE_MALLOC(sizeof(LogMessageInfo));
+ lmi->bLevel = (BYTE)level;
+ lmi->szMsg = null_strdup(szMsg);
+ lmi->szTitle = szLevelDescr[level];
+ ForkThread( &CIcqProto::icq_LogMessageThread, lmi);
+ }
+ }
+}
+
+void CIcqProto::icq_LogUsingErrorCode(int level, DWORD dwError, const char *szMsg)
+{
+ char szBuf[1024];
+ char str[1024];
+ char str2[64];
+ char szErrorMsg[512];
+ char *pszErrorMsg = NULL;
+ int bNeedFree = FALSE;
+
+ switch(dwError) {
+ case ERROR_TIMEOUT:
+ case WSAETIMEDOUT:
+ pszErrorMsg = LPGEN("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 = LPGEN("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 = LPGEN("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 = LPGEN("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 = LPGEN("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 = LPGEN("The server to which you are trying to connect does not exist. Check your spelling in M->Options->Network->ICQ.");
+ break;
+
+ default:
+ {
+ TCHAR err[512];
+
+ if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, err, SIZEOF(err), NULL))
+ {
+#if defined( _UNICODE )
+ pszErrorMsg = make_utf8_string(err);
+#else
+ utf8_encode(err, &pszErrorMsg);
+#endif
+ bNeedFree = TRUE;
+ }
+ break;
+ }
+ }
+
+ null_snprintf(szBuf, sizeof(szBuf), "%s%s%s (%s %d)",
+ szMsg ? ICQTranslateUtfStatic(szMsg, str, 1024) : "",
+ szMsg ? "\r\n\r\n" : "",
+ ICQTranslateUtfStatic(pszErrorMsg, szErrorMsg, 512),
+ ICQTranslateUtfStatic(LPGEN("error"), str2, 64),
+ dwError);
+
+ if (bNeedFree)
+ SAFE_FREE(&pszErrorMsg);
+
+ icq_LogMessage(level, szBuf);
+}
+
+void CIcqProto::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/protocols/IcqOscarJ/log.h b/protocols/IcqOscarJ/log.h
new file mode 100644
index 0000000000..ef5079134b
--- /dev/null
+++ b/protocols/IcqOscarJ/log.h
@@ -0,0 +1,45 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/log.h $
+// Revision : $Revision: 7484 $
+// Last change on : $Date: 2008-03-21 11:43:39 +0200 (Пт, 21 мар 2008) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __LOG_H
+#define __LOG_H
+
+#define LOG_NOTE 0 //trivial problems or problems that will already have been reported elsewhere
+#define LOG_WARNING 1 //problems that may have caused data loss
+#define LOG_ERROR 2 //problems that cause a disconnection from the network
+#define LOG_FATAL 3 //problems requiring user intervention: password wrong, rate exceeded, etc.
+
+#endif /* __LOG_H */
diff --git a/protocols/IcqOscarJ/m_extraicons.h b/protocols/IcqOscarJ/m_extraicons.h
new file mode 100644
index 0000000000..589d040cef
--- /dev/null
+++ b/protocols/IcqOscarJ/m_extraicons.h
@@ -0,0 +1,158 @@
+/*
+ Copyright (C) 2009 Ricardo Pescuma Domenecci
+
+ This is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this file; see the file license.txt. If
+ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __M_EXTRAICONS_H__
+#define __M_EXTRAICONS_H__
+
+#define MIID_EXTRAICONSSERVICE { 0x62d80749, 0xf169, 0x4592, { 0xb4, 0x4d, 0x3d, 0xd6, 0xde, 0x9d, 0x50, 0xc5 } }
+
+
+#define EXTRAICON_TYPE_CALLBACK 0 // Similar to old clist callbacks, it fires 2 notifications
+#define EXTRAICON_TYPE_ICOLIB 1 // This extra icon will use only icons registered with icolib. No callbacks
+ // needed. Just call MS_EXTRAICON_SET_ICON passing the name of the extraicon to set one.
+
+
+typedef struct {
+ int cbSize;
+ int type; // One of EXTRAICON_TYPE_*
+ const char *name; // Internal name. More than one plugin can register extra icons with the same name
+ // if both have the same type. In this case, both will be handled as one.
+ // This is usefull for ex for extra status, where icq and jabber can share the same slot.
+ // If the types are different the second one will be denied.
+ const char *description; // [Translated by plugin] Description to be used in GUI
+ const char *descIcon; // [Optional] Name of an icon registered with icolib to be used in GUI.
+
+ // If type == EXTRAICON_TYPE_CALLBACK this two must be set
+
+ // Callback to add icons to clist, calling MS_CLIST_EXTRA_ADD_ICON
+ // wParam=lParam=0
+ MIRANDAHOOK RebuildIcons;
+
+ // Callback to set the icon to clist, calling MS_CLIST_EXTRA_SET_ICON or MS_EXTRAICON_SET_ICON
+ // wParam = HANDLE hContact
+ // lParam = int slot
+ MIRANDAHOOK ApplyIcon;
+
+ // Other optional callbacks
+
+ // [Optional] Callback called when extra icon was clicked
+ // wParam = HANDLE hContact
+ // lParam = int slot
+ // param = onClickParam
+ MIRANDAHOOKPARAM OnClick;
+
+ LPARAM onClickParam;
+
+} EXTRAICON_INFO;
+
+
+// Register an extra icon
+// wParam = (EXTRAICON_INFO *) Extra icon info
+// lParam = 0
+// Return: (HANDLE) id of extra icon on success, 0 on error
+#define MS_EXTRAICON_REGISTER "ExtraIcon/Register"
+
+
+typedef struct {
+ int cbSize;
+ HANDLE hExtraIcon; // Value returned by MS_EXTRAICON_REGISTER
+ HANDLE hContact; // Contact to set the extra icon
+ union { // The icon to be set. This depends on the type of the extra icon:
+ HANDLE hImage; // Value returned by MS_CLIST_EXTRA_ADD_ICON (if EXTRAICON_TYPE_CALLBACK)
+ const char *icoName; // Name of the icon registered with icolib (if EXTRAICON_TYPE_ICOLIB)
+ };
+} EXTRAICON;
+
+// Set an extra icon icon
+// wParam = (EXTRAICON *) Extra icon
+// Return: 0 on success
+#define MS_EXTRAICON_SET_ICON "ExtraIcon/SetIcon"
+
+
+
+#ifndef _NO_WRAPPERS
+#ifdef __cplusplus
+
+static HANDLE ExtraIcon_Register(const char *name, const char *description, const char *descIcon,
+ MIRANDAHOOK RebuildIcons,
+ MIRANDAHOOK ApplyIcon,
+ MIRANDAHOOKPARAM OnClick = NULL, LPARAM onClickParam = NULL)
+{
+ if (!ServiceExists(MS_EXTRAICON_REGISTER))
+ return NULL;
+
+ EXTRAICON_INFO ei = {0};
+ ei.cbSize = sizeof(ei);
+ ei.type = EXTRAICON_TYPE_CALLBACK;
+ ei.name = name;
+ ei.description = description;
+ ei.descIcon = descIcon;
+ ei.RebuildIcons = RebuildIcons;
+ ei.ApplyIcon = ApplyIcon;
+ ei.OnClick = OnClick;
+ ei.onClickParam = onClickParam;
+
+ return (HANDLE) CallService(MS_EXTRAICON_REGISTER, (WPARAM) &ei, 0);
+}
+
+static HANDLE ExtraIcon_Register(const char *name, const char *description, const char *descIcon = NULL,
+ MIRANDAHOOKPARAM OnClick = NULL, LPARAM onClickParam = NULL)
+{
+ if (!ServiceExists(MS_EXTRAICON_REGISTER))
+ return NULL;
+
+ EXTRAICON_INFO ei = {0};
+ ei.cbSize = sizeof(ei);
+ ei.type = EXTRAICON_TYPE_ICOLIB;
+ ei.name = name;
+ ei.description = description;
+ ei.descIcon = descIcon;
+ ei.OnClick = OnClick;
+ ei.onClickParam = onClickParam;
+
+ return (HANDLE) CallService(MS_EXTRAICON_REGISTER, (WPARAM) &ei, 0);
+}
+
+static int ExtraIcon_SetIcon(HANDLE hExtraIcon, HANDLE hContact, HANDLE hImage)
+{
+ EXTRAICON ei = {0};
+ ei.cbSize = sizeof(ei);
+ ei.hExtraIcon = hExtraIcon;
+ ei.hContact = hContact;
+ ei.hImage = hImage;
+
+ return CallService(MS_EXTRAICON_SET_ICON, (WPARAM) &ei, 0);
+}
+
+static int ExtraIcon_SetIcon(HANDLE hExtraIcon, HANDLE hContact, const char *icoName)
+{
+ EXTRAICON ei = {0};
+ ei.cbSize = sizeof(ei);
+ ei.hExtraIcon = hExtraIcon;
+ ei.hContact = hContact;
+ ei.icoName = icoName;
+
+ return CallService(MS_EXTRAICON_SET_ICON, (WPARAM) &ei, 0);
+}
+
+#endif
+#endif
+
+
+#endif // __M_EXTRAICONS_H__
diff --git a/protocols/IcqOscarJ/m_folders.h b/protocols/IcqOscarJ/m_folders.h
new file mode 100644
index 0000000000..c681074ed4
--- /dev/null
+++ b/protocols/IcqOscarJ/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_PTR FoldersGetCustomPath(HANDLE hFolderEntry, char *path, const int size, const char *notFound)
+{
+ FOLDERSGETDATA fgd = {0};
+ INT_PTR 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_PTR FoldersGetCustomPathW(HANDLE hFolderEntry, wchar_t *pathW, const int count, const wchar_t *notFoundW)
+{
+ FOLDERSGETDATA fgd = {0};
+ INT_PTR 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_PTR FoldersGetCustomPathEx(HANDLE hFolderEntry, char *path, const int size, char *notFound, char *fileName)
+{
+ FOLDERSGETDATA fgd = {0};
+ INT_PTR 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_PTR FoldersGetCustomPathExW(HANDLE hFolderEntry, wchar_t *pathW, const int count, wchar_t *notFoundW, wchar_t *fileNameW)
+{
+ FOLDERSGETDATA fgd = {0};
+ INT_PTR 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
diff --git a/protocols/IcqOscarJ/m_updater.h b/protocols/IcqOscarJ/m_updater.h
new file mode 100644
index 0000000000..c83b8a4600
--- /dev/null
+++ b/protocols/IcqOscarJ/m_updater.h
@@ -0,0 +1,117 @@
+#ifndef _M_UPDATER_H
+#define _M_UPDATER_H
+
+// if you set Update::szUpdateURL to the following value when registering, as well as setting your beta site and version data,
+// updater will ignore szVersionURL and pbVersionPrefix, and attempt to find the file listing URL's from the backend XML data.
+// for this to work, the plugin name in pluginInfo.shortName must match the file listing exactly (except for case)
+#define UPDATER_AUTOREGISTER "UpdaterAUTOREGISTER"
+
+typedef struct Update_tag {
+ int cbSize;
+ char *szComponentName; // component name as it will appear in the UI (will be translated before displaying)
+
+ char *szVersionURL; // URL where the current version can be found (NULL to disable)
+ BYTE *pbVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data
+ // (not that this URL could point at a binary file - dunno why, but it could :)
+ int cpbVersionPrefix; // number of bytes pionted to by pbVersionPrefix
+ char *szUpdateURL; // URL where dll/zip is located
+ // set to UPDATER_AUTOREGISTER if you want updater to find the file listing URLs (ensure plugin shortName matches file listing!)
+
+ char *szBetaVersionURL; // URL where the beta version can be found (NULL to disable betas)
+ BYTE *pbBetaVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data
+ int cpbBetaVersionPrefix; // number of bytes pionted to by pbVersionPrefix
+ char *szBetaUpdateURL; // URL where dll/zip is located
+
+ BYTE *pbVersion; // bytes of current version, used for comparison with those in VersionURL
+ int cpbVersion; // number of bytes pionted to by pbVersion
+
+ char *szBetaChangelogURL; // url for displaying changelog for beta versions
+} Update;
+
+// register a comonent with the updater
+//
+// wparam = 0
+// lparam = (LPARAM)&Update
+#define MS_UPDATE_REGISTER "Update/Register"
+
+// utility functions to create a version string from a DWORD or from pluginInfo
+// point buf at a buffer at least 16 chars wide - but note the version string returned may be shorter
+//
+__inline static char *CreateVersionString(DWORD version, char *buf) {
+ mir_snprintf(buf, 16, "%d.%d.%d.%d", (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF);
+ return buf;
+}
+
+__inline static char *CreateVersionStringPlugin(PLUGININFO *pluginInfo, char *buf) {
+ return CreateVersionString(pluginInfo->version, buf);
+}
+
+
+// register the 'easy' way - use this method if you have no beta URL and the plugin is on the miranda file listing
+// NOTE: the plugin 'short name' in pluginInfo must match the name of the plugin on the file listing, exactly (not including case)
+// AND the plugin version string on the file listing must be the string version of the version in pluginInfo (i.e. 0.0.0.1,
+// so no letters, brackets, etc.)
+//
+// wParam = (int)fileID - this is the file ID from the file listing (i.e. the number at the end of the download link)
+// lParam = (PLUGININFO*)&pluginInfo
+#define MS_UPDATE_REGISTERFL "Update/RegisterFL"
+
+// this event is fired when the startup process is complete, but NOT if a restart is imminent
+// it is designed for status managment plugins to use as a trigger for beggining their own startup process
+// wParam = lParam = 0 (unused)
+// (added in version 0.1.6.0)
+#define ME_UPDATE_STARTUPDONE "Update/StartupDone"
+
+// this service can be used to enable/disable Updater's global status control
+// it can be called from the StartupDone event handler
+// wParam = (BOOL)enable
+// lParam = 0
+// (added in version 0.1.6.0)
+#define MS_UPDATE_ENABLESTATUSCONTROL "Update/EnableStatusControl"
+
+// An description of usage of the above service and event:
+// Say you are a status control plugin that normally sets protocol or global statuses in your ModulesLoaded event handler.
+// In order to make yourself 'updater compatible', you would move the status control code from ModulesLoaded to another function,
+// say DoStartup. Then, in ModulesLoaded you would check for the existence of the MS_UPDATE_ENABLESTATUSCONTROL service.
+// If it does not exist, call DoStartup. If it does exist, hook the ME_UPDATE_STARTUPDONE event and call DoStartup from there. You may
+// also wish to call MS_UPDATE_ENABLESTATUSCONTROL with wParam == FALSE at this time, to disable Updater's own status control feature.
+
+#endif
+
+
+/////////////// Usage Example ///////////////
+
+#ifdef EXAMPLE_CODE
+
+// you need to #include "m_updater.h" and HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded) in your Load function...
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam) {
+
+ Update update = {0}; // for c you'd use memset or ZeroMemory...
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionString(&pluginInfo, szVersion);
+ update.cpbVersion = strlen((char *)update.pbVersion);
+
+ // these are the three lines that matter - the archive, the page containing the version string, and the text (or data)
+ // before the version that we use to locate it on the page
+ // (note that if the update URL and the version URL point to standard file listing entries, the backend xml
+ // data will be used to check for updates rather than the actual web page - this is not true for beta urls)
+ update.szUpdateURL = "http://scottellis.com.au:81/test/updater.zip";
+ update.szVersionURL = "http://scottellis.com.au:81/test/updater_test.html";
+ update.pbVersionPrefix = (BYTE *)"Updater version ";
+
+ update.cpbVersionPrefix = strlen((char *)update.pbVersionPrefix);
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+
+ // Alternatively, to register a plugin with e.g. file ID 2254 on the file listing...
+ // CallService(MS_UPDATE_REGISTERFL, (WPARAM)2254, (LPARAM)&pluginInfo);
+
+ return 0;
+}
+
+#endif
diff --git a/protocols/IcqOscarJ/oscar_filetransfer.cpp b/protocols/IcqOscarJ/oscar_filetransfer.cpp
new file mode 100644
index 0000000000..b6dd52cf5f
--- /dev/null
+++ b/protocols/IcqOscarJ/oscar_filetransfer.cpp
@@ -0,0 +1,2452 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/oscar_filetransfer.cpp $
+// Revision : $Revision: 14229 $
+// Last change on : $Date: 2012-05-14 03:26:21 +0300 (Пн, 14 май 2012) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// OSCAR File-Transfers implementation
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+struct oscarthreadstartinfo
+{
+ int type;
+ int incoming;
+ HANDLE hContact;
+ HANDLE hConnection;
+ DWORD dwRemoteIP;
+ oscar_filetransfer *ft;
+ oscar_listener *listener;
+};
+
+
+// small utility function
+extern void NormalizeBackslash(char* path);
+
+//
+// Common functions
+/////////////////////////////
+
+char *FindFilePathContainer(const char **files, int iFile, char *szContainer)
+{
+ const char *szThisFile = files[iFile];
+ char *szFileName = (char*)ExtractFileName(szThisFile);
+
+ szContainer[0] = '\0';
+
+ if (szThisFile != szFileName)
+ { // find an earlier subdirectory to be used as a container
+ for (int i = iFile - 1; i >= 0; i--)
+ {
+ int len = strlennull(files[i]);
+
+ if (!_strnicmp(files[i], szThisFile, len) && (szThisFile[len] == '\\' || szThisFile[len] == '/'))
+ {
+ const char *pszLastBackslash;
+
+ if (((pszLastBackslash = strrchr(files[i], '\\')) == NULL) &&
+ ((pszLastBackslash = strrchr(files[i], '/')) == NULL))
+ {
+ strcpy(szContainer, files[i]);
+ }
+ else
+ {
+ len = pszLastBackslash - files[i] + 1;
+ null_strcpy(szContainer, szThisFile + len, szFileName - szThisFile - len);
+ }
+ }
+ }
+ }
+ return szFileName;
+}
+
+
+//
+// Utility functions
+/////////////////////////////
+
+oscar_filetransfer* CIcqProto::CreateOscarTransfer()
+{
+ oscar_filetransfer* ft = (oscar_filetransfer*)SAFE_MALLOC(sizeof(oscar_filetransfer));
+
+ ft->ft_magic = FT_MAGIC_OSCAR; // Setup signature
+ // Init members
+ ft->fileId = -1;
+
+ icq_lock l(oftMutex);
+
+ fileTransferList = (basic_filetransfer**)SAFE_REALLOC(fileTransferList, sizeof(basic_filetransfer*)*(fileTransferCount + 1));
+ fileTransferList[fileTransferCount++] = ft;
+
+#ifdef _DEBUG
+ NetLog_Direct("OFT: FT struct 0x%x created", ft);
+#endif
+
+ return ft;
+}
+
+
+filetransfer *CIcqProto::CreateIcqFileTransfer()
+{
+ filetransfer *ft = (filetransfer*)SAFE_MALLOC(sizeof(filetransfer));
+
+ ft->ft_magic = FT_MAGIC_ICQ;
+
+ icq_lock l(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
+
+ return ft;
+}
+
+
+int CIcqProto::getFileTransferIndex(void *ft)
+{
+ for (int i = 0; i < fileTransferCount; i++)
+ {
+ if (fileTransferList[i] == ft)
+ return i;
+ }
+ return -1;
+}
+
+
+void CIcqProto::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 CIcqProto::IsValidFileTransfer(void *ft)
+{
+ icq_lock l(oftMutex);
+
+ if (getFileTransferIndex(ft) != -1) return 1;
+
+ return 0;
+}
+
+
+int CIcqProto::IsValidOscarTransfer(void *ft)
+{
+ icq_lock l(oftMutex);
+
+ if (getFileTransferIndex(ft) != -1 && ((basic_filetransfer*)ft)->ft_magic == FT_MAGIC_OSCAR)
+ return 1;
+
+ return 0;
+}
+
+
+oscar_filetransfer* CIcqProto::FindOscarTransfer(HANDLE hContact, DWORD dwID1, DWORD dwID2)
+{
+ icq_lock l(oftMutex);
+
+ for (int i = 0; i < fileTransferCount; i++)
+ {
+ if (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)
+ return oft;
+ }
+ }
+
+ return NULL;
+}
+
+
+// Release file transfer structure
+void CIcqProto::SafeReleaseFileTransfer(void **ft)
+{
+ basic_filetransfer **bft = (basic_filetransfer**)ft;
+
+ icq_lock l(oftMutex);
+
+ // Check for filetransfer validity
+ if (getFileTransferIndex(*ft) == -1)
+ 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->pszFiles)
+ {
+ for (int i = 0; i < (int)ift->dwFileCount; i++)
+ SAFE_FREE(&ift->pszFiles[i]);
+ SAFE_FREE((void**)&ift->pszFiles);
+ }
+ // Invalidate transfer
+ ReleaseFileTransfer(ift);
+#ifdef _DEBUG
+ NetLog_Direct("FT struct 0x%x released", ft);
+#endif
+ // Release memory
+ SAFE_FREE((void**)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);
+ SAFE_FREE(&oft->szDescription);
+ if (oft->files)
+ {
+ for (int i = 0; i < oft->wFilesCount; i++)
+ SAFE_FREE(&oft->files[i].szFile);
+ SAFE_FREE((void**)&oft->files);
+ }
+ if (oft->files_list)
+ {
+/* for (int i = 0; i < oft->wFilesCount; i++)
+ SAFE_FREE(&oft->files_list[i]);*/
+ SAFE_FREE((void**)&oft->files_list);
+ }
+ if (oft->file_containers)
+ {
+ for (int 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((void**)ft);
+ }
+ }
+}
+
+
+// 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 = (dwChecksum >> 16) & 0xffff;
+
+ for (int 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, (maxSize < sizeof(buf)) ? maxSize : (unsigned)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* CIcqProto::CreateOscarListener(oscar_filetransfer *ft, NETLIBNEWCONNECTIONPROC_V2 handler)
+{
+ oscar_listener *listener = (oscar_listener*)SAFE_MALLOC(sizeof(oscar_listener));
+
+ if (listener)
+ {
+ listener->ppro = this;
+ listener->ft = ft;
+ if (listener->hBoundPort = NetLib_BindPort(handler, listener, &listener->wPort, NULL))
+ return listener; // Success
+
+ SAFE_FREE((void**)&listener);
+ }
+
+ return NULL; // Failure
+}
+
+
+void CIcqProto::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((void**)pListener);
+}
+
+
+//
+// Miranda FT interface handlers & services
+/////////////////////////////
+
+void CIcqProto::handleRecvServMsgOFT(BYTE *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 = chain->getWord(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 = chain->getTLV(0x10, 1) ? 1 : 0;
+ ft->dwProxyIP = chain->getDWord(0x02, 1);
+ ft->dwRemoteInternalIP = chain->getDWord(0x03, 1);
+ ft->dwRemoteExternalIP = chain->getDWord(0x04, 1);
+ ft->wRemotePort = chain->getWord(0x05, 1);
+ ft->wReqNum = wAckType;
+
+ { // User Message
+ oscar_tlv* tlv = chain->getTLV(0x0C, 1);
+
+ if (tlv)
+ { // parse User Message
+ BYTE* tBuf = tlv->pData;
+
+ pszDescription = (char*)_alloca(tlv->wLen + 2);
+ unpackString(&tBuf, (char*)pszDescription, tlv->wLen);
+ pszDescription[tlv->wLen] = '\0';
+ pszDescription[tlv->wLen+1] = '\0';
+ { // apply User Message encoding
+ oscar_tlv *charset = chain->getTLV(0x0D, 1);
+ char *str = pszDescription;
+ char *bTag,*eTag;
+
+ if (charset)
+ { // decode charset
+ char *szEnc = (char*)_alloca(charset->wLen + 1);
+
+ null_strcpy(szEnc, (char*)charset->pData, charset->wLen);
+ str = ApplyEncoding((char*)pszDescription, szEnc);
+ }
+ else
+ str = null_strdup(str);
+ // eliminate HTML tags
+ pszDescription = EliminateHtml(str, strlennull(str));
+
+ bTag = strstrnull(pszDescription, "<DESC>");
+ if (bTag)
+ { // take special Description - ICQJ's extension
+ eTag = strstrnull(bTag, "</DESC>");
+ if (eTag)
+ {
+ *eTag = '\0';
+ str = null_strdup(bTag + 6);
+ SAFE_FREE(&pszDescription);
+ pszDescription = str;
+ }
+ }
+ else
+ {
+ bTag = strstrnull(pszDescription, "<FS>");
+ if (bTag)
+ { // take only <FS> - Description tag if present
+ eTag = strstrnull(bTag, "</FS>");
+ if (eTag)
+ {
+ *eTag = '\0';
+ str = null_strdup(bTag + 4);
+ SAFE_FREE(&pszDescription);
+ pszDescription = str;
+ }
+ }
+ }
+ }
+ }
+ if (!strlennull(pszDescription))
+ {
+ SAFE_FREE(&pszDescription);
+ pszDescription = ICQTranslateUtf(LPGEN("No description given"));
+ }
+ }
+ { // parse File Transfer Info block
+ oscar_tlv* tlv = chain->getTLV(0x2711, 1);
+
+ // sanity check
+ if (!tlv || tlv->wLen < 8)
+ {
+ NetLog_Server("Error: Malformed file request");
+ // release structures
+ SafeReleaseFileTransfer((void**)&ft);
+ SAFE_FREE(&pszDescription);
+ return;
+ }
+
+ 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
+ if (tLen)
+ { // some filename specified, unpack
+ wFilenameLength = tLen - 1;
+ pszFileName = (char*)_alloca(tLen);
+ unpackString(&tBuf, (char*)pszFileName, wFilenameLength);
+ pszFileName[wFilenameLength] = '\0';
+ }
+ else if (ft->wFilesCount == 1) // give some generic file name
+ pszFileName = "unnamed_file";
+ else // or empty directory name
+ pszFileName = "";
+
+ { // apply Filename / Directory Name encoding
+ oscar_tlv* charset = chain->getTLV(0x2712, 1);
+
+ if (charset)
+ {
+ char* szEnc = (char*)_alloca(charset->wLen + 1);
+
+ null_strcpy(szEnc, (char*)charset->pData, charset->wLen);
+ pszFileName = ApplyEncoding(pszFileName, szEnc);
+ }
+ else
+ pszFileName = ansi_to_utf8(pszFileName);
+ }
+ if (ft->wFilesCount == 1)
+ { // Filename - use for DB event
+ char *szFileName = (char*)_alloca(strlennull(pszFileName) + 1);
+
+ strcpy(szFileName, pszFileName);
+ SAFE_FREE(&pszFileName);
+ pszFileName = szFileName;
+ }
+ 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);
+
+ char tmp[64];
+ null_snprintf(pszFileName, 64, ICQTranslateUtfStatic(LPGEN("%d Files"), tmp, SIZEOF(tmp)), ft->wFilesCount);
+ }
+ }
+ // Total Size TLV (ICQ 6 and AIM 6)
+ {
+ oscar_tlv *tlv = chain->getTLV(0x2713, 1);
+
+ if (tlv && tlv->wLen >= 8)
+ {
+ BYTE *tBuf = tlv->pData;
+
+ unpackQWord(&tBuf, &ft->qwTotalSize);
+ }
+ }
+ int bAdded;
+ HANDLE hContact = HContactFromUID(dwUin, szUID, &bAdded);
+
+ ft->hContact = hContact;
+ ft->szDescription = pszDescription;
+ ft->fileId = -1;
+
+ // Send chain event
+ char *szBlob = (char*)_alloca(sizeof(DWORD) + strlennull(pszFileName) + strlennull(pszDescription) + 2);
+ *(PDWORD)szBlob = 0;
+ strcpy(szBlob + sizeof(DWORD), pszFileName);
+ strcpy(szBlob + sizeof(DWORD) + strlennull(pszFileName) + 1, pszDescription);
+
+ PROTORECVEVENT pre;
+ pre.flags = PREF_UTF;
+ pre.timestamp = time(NULL);
+ pre.szMessage = szBlob;
+ pre.lParam = (LPARAM)ft;
+
+ CCSDATA ccs;
+ ccs.szProtoService = PSR_FILE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)&pre;
+ 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->flags & OFTF_SENDING)
+ {
+ ReleaseOscarListener((oscar_listener**)&ft->listener);
+
+ ft->bUseProxy = chain->getTLV(0x10, 1) ? 1 : 0;
+ ft->dwProxyIP = chain->getDWord(0x02, 1);
+ ft->dwRemoteInternalIP = chain->getDWord(0x03, 1);
+ ft->dwRemoteExternalIP = chain->getDWord(0x04, 1);
+ ft->wRemotePort = chain->getWord(0x05, 1);
+
+ OpenOscarConnection(hContact, ft, ft->bUseProxy ? OCT_PROXY_RECV: OCT_REVERSE);
+ }
+ else
+ { // Just sanity
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&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 = chain->getTLV(0x10, 1) ? 1 : 0;
+ ft->dwProxyIP = chain->getDWord(0x02, 1);
+ ft->wRemotePort = chain->getWord(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 = chain->getTLV(0x10, 1) ? 1 : 0;
+ ft->dwProxyIP = chain->getDWord(0x02, 1);
+ ft->wRemotePort = chain->getWord(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));
+
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ft, 0);
+ // Notify user, that the FT was cancelled // TODO: new ACKRESULT_?
+ icq_LogMessage(LOG_ERROR, LPGEN("The file transfer was aborted by the other user."));
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&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->flags & OFTF_SENDING)
+ {
+ if (ft->connection && ft->connection->status == OCS_CONNECTED)
+ {
+ if (!(ft->flags & OFTF_FILE_REQUEST_SENT))
+ {
+ ft->flags |= OFTF_FILE_REQUEST_SENT;
+ // proceed with first file
+ oft_sendPeerInit(ft->connection);
+ }
+ }
+ ft->flags |= OFTF_INITIALIZED; // 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 CIcqProto::handleRecvServResponseOFT(BYTE *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));
+
+ BroadcastAck(oft->hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)oft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&oft);
+ }
+ break;
+
+ case 4: // Proxy error
+ {
+ icq_LogMessage(LOG_ERROR, LPGEN("The file transfer failed: Proxy error"));
+
+ BroadcastAck(oft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)oft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&oft);
+ }
+ break;
+
+ case 5: // Invalid request
+ {
+ icq_LogMessage(LOG_ERROR, LPGEN("The file transfer failed: Invalid request"));
+
+ BroadcastAck(oft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)oft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&oft);
+ }
+ break;
+
+ case 6: // Proxy Failed (IP = 0)
+ {
+ icq_LogMessage(LOG_ERROR, LPGEN("The file transfer failed: Proxy unavailable"));
+
+ BroadcastAck(oft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)oft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&oft);
+ }
+ break;
+
+ default:
+ {
+ NetLog_Server("OFT: Uknown request response code 0x%x", wStatus);
+
+ BroadcastAck(oft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)oft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&oft);
+ }
+ }
+ }
+}
+
+
+// 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->flags & OFTF_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
+ listener->ppro->ForkThread(( IcqThreadFunc )&CIcqProto::oft_connectionThread, otsi );
+}
+
+
+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 (!strcmpnull(szPathUtf, oft->file_containers[i]))
+ {
+ SAFE_FREE((void**)&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];
+}
+
+
+HANDLE CIcqProto::oftInitTransfer(HANDLE hContact, DWORD dwUin, char* szUid, const TCHAR** files, const TCHAR* pszDesc)
+{
+ oscar_filetransfer *ft;
+ int i, filesCount;
+ struct _stati64 statbuf;
+ char ** filesUtf;
+
+ // 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_list = (char**)SAFE_MALLOC(sizeof(TCHAR *) * filesCount);
+ ft->qwTotalSize = 0;
+
+ filesUtf = (char**)SAFE_MALLOC(sizeof(char *) * filesCount);
+ for(i = 0; i < filesCount; i++) filesUtf[i] = FileNameToUtf(files[i]);
+
+ // Prepare files arrays
+ for (i = 0; i < filesCount; i++)
+ {
+ if (_tstati64(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 = ft->files_list[ft->wFilesCount] = null_strdup(filesUtf[i]);
+ ft->files[ft->wFilesCount].szContainer = oftGetFileContainer(ft, (LPCSTR*) filesUtf, i);
+
+ ft->wFilesCount++;
+ ft->qwTotalSize += statbuf.st_size;
+ }
+ }
+ }
+
+ for (int i = 0; i < filesCount; i++)
+ SAFE_FREE(&filesUtf[i]);
+ SAFE_FREE((void**)&filesUtf);
+
+ 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
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&ft);
+
+ return 0; // Failure
+ }
+#ifdef __GNUC__
+#define OSCAR_MAX_SIZE 0x100000000ULL
+#else
+#define OSCAR_MAX_SIZE 0x100000000
+#endif
+ if (ft->qwTotalSize >= OSCAR_MAX_SIZE && ft->wFilesCount > 1)
+ { // file larger than 4GB can be send only as single
+ icq_LogMessage(LOG_ERROR, LPGEN("The files are too big to be sent at once. Files bigger than 4GB can be sent only separately."));
+ // Notify UI
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&ft);
+
+ return 0; // Failure
+ }
+
+ NetLog_Server("OFT: Found %d files.", ft->wFilesCount);
+
+ ft->szDescription = tchar_to_utf8(pszDesc);
+ ft->flags = OFTF_SENDING;
+ 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 = (char*)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 = strstrnull(szFirstDir, "\\")) || (szFirstDiv = strstrnull(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((char*)ft->file_containers[i], (char*)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, getSettingDword(NULL, "RealIP", 0));
+ }
+ else
+ { // try stage 1 proxy
+ ft->szThisFile = null_strdup(pszFiles);
+ OpenOscarConnection(hContact, ft, OCT_PROXY_INIT);
+ }
+ }
+
+ return ft; // Success
+}
+
+
+HANDLE CIcqProto::oftFileAllow(HANDLE hContact, HANDLE hTransfer, const TCHAR *szPath)
+{
+ oscar_filetransfer *ft = (oscar_filetransfer*)hTransfer;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (getContactUid(hContact, &dwUin, &szUid))
+ return 0; // Invalid contact
+
+ if (!IsValidOscarTransfer(ft))
+ return 0; // Invalid transfer
+
+ ft->szSavePath = tchar_to_utf8(szPath);
+
+ 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 hTransfer; // Success
+}
+
+
+DWORD CIcqProto::oftFileDeny(HANDLE hContact, HANDLE hTransfer, const TCHAR *szReason)
+{
+ oscar_filetransfer *ft = (oscar_filetransfer*)hTransfer;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (getContactUid(hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+ if (IsValidOscarTransfer(ft))
+ {
+ if (ft->hContact != hContact)
+ return 1; // Bad contact or hTransfer
+
+#ifdef _DEBUG
+ NetLog_Direct("OFT: Request denied.");
+#endif
+
+ oft_sendFileDeny(dwUin, szUid, ft);
+
+ // Release structure
+ SafeReleaseFileTransfer((void**)&ft);
+
+ return 0; // Success
+ }
+ return 1; // Invalid transfer
+}
+
+
+DWORD CIcqProto::oftFileCancel(HANDLE hContact, HANDLE hTransfer)
+{
+ oscar_filetransfer* ft = (oscar_filetransfer*)hTransfer;
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (getContactUid(hContact, &dwUin, &szUid))
+ return 1; // Invalid contact
+
+ if (IsValidOscarTransfer(ft))
+ {
+ if (ft->hContact != hContact)
+ return 1; // Bad contact or hTransfer
+
+#ifdef _DEBUG
+ NetLog_Direct("OFT: Transfer cancelled.");
+#endif
+
+ oft_sendFileCancel(dwUin, szUid, ft);
+
+ BroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+
+ // Release structure
+ SafeReleaseFileTransfer((void**)&ft);
+
+ return 0; // Success
+ }
+ return 1; // Invalid transfer
+}
+
+
+void CIcqProto::oftFileResume(oscar_filetransfer *ft, int action, const TCHAR *szFilename)
+{
+ int openFlags;
+
+ if (ft->connection == NULL)
+ return;
+
+ oscar_connection *oc = 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 = tchar_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, LPGEN("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."));
+
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&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 skipping the file, send "we are done"
+ oc->status = OCS_NEGOTIATION;
+ }
+ else
+ { // Send "we are ready"
+ oc->status = OCS_DATA;
+ ft->flags |= OFTF_FILE_RECEIVING;
+
+ sendOFT2FramePacket(oc, OFT_TYPE_READY);
+ }
+ BroadcastAck(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->flags = PFTS_UTF + ((ft->flags & OFTF_SENDING) ? PFTS_SENDING : PFTS_RECEIVING);
+ if (ft->flags & OFTF_SENDING)
+ pfts->pszFiles = ft->files_list;
+ else
+ pfts->pszFiles = NULL; /* FIXME */
+ pfts->totalFiles = ft->wFilesCount;
+ pfts->currentFileNumber = ft->iCurrentFile;
+ pfts->totalBytes = ft->qwTotalSize;
+ pfts->totalProgress = ft->qwBytesDone;
+ pfts->szWorkingDir = ft->szThisPath;
+ pfts->szCurrentFile = ft->szThisFile;
+ pfts->currentFileSize = ft->qwThisFileSize;
+ pfts->currentFileTime = ft->dwThisFileDate;
+ pfts->currentFileProgress = ft->qwFileBytesDone;
+}
+
+
+void CIcqProto::CloseOscarConnection(oscar_connection *oc)
+{
+ icq_lock l(oftMutex);
+
+ if (oc)
+ {
+ oc->type = OCT_CLOSING;
+
+ if (oc->hConnection)
+ { // we need this for Netlib handle consistency
+ NetLib_CloseConnection(&oc->hConnection, FALSE);
+ }
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CIcqProto::OpenOscarConnection(HANDLE hContact, oscar_filetransfer *ft, int type)
+{
+ oscarthreadstartinfo *otsi = (oscarthreadstartinfo*)SAFE_MALLOC(sizeof(oscarthreadstartinfo));
+
+ otsi->hContact = hContact;
+ otsi->type = type;
+ otsi->ft = ft;
+
+ ForkThread(( IcqThreadFunc )&CIcqProto::oft_connectionThread, otsi );
+}
+
+
+int CIcqProto::CreateOscarProxyConnection(oscar_connection *oc)
+{
+ NETLIBOPENCONNECTION nloc = {0};
+
+ // inform UI
+ BroadcastAck(oc->ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTPROXY, oc->ft, 0);
+
+ nloc.szHost = OSCAR_PROXY_HOST;
+ nloc.wPort = getSettingWord(NULL, "OscarPort", m_bSecureConnection ? DEFAULT_SERVER_PORT_SSL : DEFAULT_SERVER_PORT);
+ if (nloc.wPort == 0)
+ nloc.wPort = RandRange(1024, 65535);
+ if (m_bGatewayMode)
+ nloc.flags |= NLOCF_HTTPGATEWAY;
+
+ oc->hConnection = NetLib_OpenConnection(m_hServerNetlibUser, "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
+}
+
+
+void __cdecl CIcqProto::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;
+ }
+ else
+ { // FT is already over, kill listener
+ NetLog_Direct("Received unexpected connection, closing.");
+
+ CloseOscarConnection(&oc);
+ ReleaseOscarListener(&source);
+
+ SAFE_FREE((void**)&otsi);
+ return;
+ }
+ }
+ SAFE_FREE((void**)&otsi);
+
+ if (oc.hContact)
+ { // Load contact information
+ getContactUid(oc.hContact, &oc.dwUin, &oc.szUid);
+ }
+
+ // Load local IP information
+ oc.dwLocalExternalIP = getSettingDword(NULL, "IP", 0);
+ oc.dwLocalInternalIP = getSettingDword(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 if (oc.ft->dwRemoteExternalIP)
+ {
+ 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);
+ }
+ else // try LAN
+ addr.S_un.S_addr = htonl(oc.ft->dwRemoteInternalIP);
+
+ // Inform UI that we will attempt to connect
+ BroadcastAck(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
+ BroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_LISTENING, oc.ft, 0);
+
+ oft_sendFileRedirect(oc.dwUin, oc.szUid, oc.ft, oc.dwLocalInternalIP, listener->wPort, FALSE);
+ return;
+ }
+ 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;
+ }
+ }
+ 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(m_hDirectNetlibUser, 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(m_hDirectNetlibUser, 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
+ BroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_LISTENING, oc.ft, 0);
+
+ oft_sendFileRedirect(oc.dwUin, oc.szUid, oc.ft, oc.dwLocalInternalIP, listener->wPort, FALSE);
+ return;
+ }
+ }
+ 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;
+ }
+ }
+ 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
+ BroadcastAck(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;
+ }
+ }
+ }
+ 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
+ BroadcastAck(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 = getSettingWord(NULL, "OscarPort", m_bSecureConnection ? DEFAULT_SERVER_PORT_SSL : DEFAULT_SERVER_PORT);
+ if (nloc.wPort == 0)
+ nloc.wPort = RandRange(1024, 65535);
+ if (m_bGatewayMode)
+ nloc.flags |= NLOCF_HTTPGATEWAY;
+ oc.hConnection = NetLib_OpenConnection(m_hServerNetlibUser, "Proxy ", &nloc);
+ if (!oc.hConnection)
+ { // proxy connection failed, we are out of possibilities
+ BroadcastAck(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((void**)&oc.ft);
+ return;
+ }
+ 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
+ BroadcastAck(oc.ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc.ft, 0);
+ // Release structure
+ SafeReleaseFileTransfer((void**)&oc.ft);
+ return;
+ }
+ }
+ }
+ else if (oc.type == OCT_PROXY)
+ { // stage 4
+ if (!CreateOscarProxyConnection(&oc))
+ { // proxy connection failed, we are out of possibilities
+ BroadcastAck(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((void**)&oc.ft);
+ return;
+ }
+ }
+ else if (oc.type == OCT_PROXY_INIT)
+ { // stage 1
+ if (!CreateOscarProxyConnection(&oc))
+ { // We failed to init transfer, notify UI
+ icq_LogMessage(LOG_ERROR, LPGEN("Failed to Initialize File Transfer. Unable to bind local port and File proxy unavailable."));
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&oc.ft);
+ return;
+ }
+ else
+ oc.type = OCT_PROXY_INIT;
+ }
+ }
+ if (!oc.hConnection)
+ { // one more sanity check
+ NetLog_Direct("Error: No OFT connection.");
+ return;
+ }
+ if (oc.status != OCS_PROXY)
+ { // Connected, notify FT UI
+ BroadcastAck(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->flags & OFTF_SENDING) && ((oc.ft->flags & OFTF_INITIALIZED) || oc.type == OCT_REVERSE) && !(oc.ft->flags & OFTF_FILE_REQUEST_SENT))
+ {
+ oc.ft->flags |= OFTF_FILE_REQUEST_SENT;
+ // proceed with first file
+ oft_sendPeerInit(&oc);
+ }
+ }
+ 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
+ icq_lock l(oftMutex);
+
+ if (getFileTransferIndex(oc.ft) != -1)
+ oc.ft->connection = NULL; // release link
+ }
+ // Give server some time for abort/cancel to arrive
+ SleepEx(1000, TRUE);
+ // Error handling
+ if (IsValidOscarTransfer(oc.ft))
+ {
+ if (oc.status == OCS_DATA)
+ {
+ BroadcastAck(oc.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc.ft, 0);
+
+ icq_LogMessage(LOG_ERROR, LPGEN("Connection lost during file transfer."));
+ // Release structure
+ SafeReleaseFileTransfer((void**)&oc.ft);
+ }
+ else if (oc.status == OCS_NEGOTIATION)
+ {
+ BroadcastAck(oc.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc.ft, 0);
+
+ icq_LogMessage(LOG_ERROR, LPGEN("File transfer negotiation failed for unknown reason."));
+ // Release structure
+ SafeReleaseFileTransfer((void**)&oc.ft);
+ }
+ }
+}
+
+
+void CIcqProto::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((void**)&packet->pData);
+}
+
+
+int CIcqProto::oft_handlePackets(oscar_connection *oc, BYTE *buf, int len)
+{
+ int bytesUsed = 0;
+
+ while (len > 0)
+ {
+ if (oc->status == OCS_DATA && (oc->ft->flags & OFTF_FILE_RECEIVING))
+ {
+ return oft_handleFileData(oc, buf, len);
+ }
+ else if (oc->status == OCS_PROXY)
+ {
+ return oft_handleProxyData(oc, buf, len);
+ }
+ if (len < 6)
+ break;
+
+ BYTE *pBuf = buf;
+ DWORD dwHead;
+ unpackDWord(&pBuf, &dwHead);
+ if (dwHead != 0x4F465432)
+ { // bad packet
+ NetLog_Direct("OFT: Received invalid packet (dwHead = 0x%x).", dwHead);
+
+ CloseOscarConnection(oc);
+ break;
+ }
+
+ WORD datalen;
+ unpackWord(&pBuf, &datalen);
+
+ if (len < datalen) // wait for whole packet
+ break;
+
+ WORD datatype;
+ 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;
+}
+
+
+int CIcqProto::oft_handleProxyData(oscar_connection *oc, BYTE *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
+ BroadcastAck(oc->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, oc->ft, 0);
+ // Release structure
+ SafeReleaseFileTransfer((void**)&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
+ BroadcastAck(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
+ BroadcastAck(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->flags & OFTF_SENDING) // connection is ready for transfer (sending only)
+ ft->flags |= OFTF_INITIALIZED;
+ }
+
+ NetLog_Server("Proxy Tunnel established");
+
+ if ((ft->flags & OFTF_INITIALIZED) && (ft->flags & OFTF_SENDING) && !(ft->flags & OFTF_FILE_REQUEST_SENT))
+ {
+ ft->flags |= OFTF_FILE_REQUEST_SENT;
+ // proceed with first file
+ oft_sendPeerInit(ft->connection);
+ }
+ break;
+
+ default:
+ NetLog_Server("Unknown proxy command 0x%x", wCommand);
+ }
+
+ buf += datalen;
+ len -= datalen;
+ bytesUsed += datalen;
+ }
+
+ return bytesUsed;
+}
+
+
+int CIcqProto::oft_handleFileData(oscar_connection *oc, BYTE *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);
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&pfts);
+ ft->dwLastNotify = GetTickCount();
+ }
+ if (ft->qwFileBytesDone == ft->qwThisFileSize)
+ {
+ /* EOF */
+ ft->flags &= ~OFTF_FILE_RECEIVING;
+
+#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(LPGEN("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.");
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&ft);
+ }
+ else
+ { // ack received file
+ sendOFT2FramePacket(oc, OFT_TYPE_DONE);
+ oc->status = OCS_NEGOTIATION;
+ }
+
+ }
+ return bytesUsed;
+}
+
+
+void CIcqProto::handleOFT2FramePacket(oscar_connection *oc, WORD datatype, BYTE *pBuffer, WORD wLen)
+{
+ oscar_filetransfer *ft = oc->ft;
+ 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 && !(ft->flags & OFTF_FILE_REQUEST_RECEIVED))
+ { // first request does not contain MsgIDs we need to send them in ready packet
+ dwID1 = ft->pMessage.dwMsgID1;
+ dwID2 = ft->pMessage.dwMsgID2;
+ }
+
+ if (ft->pMessage.dwMsgID1 != dwID1 || 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
+ if (ft->flags & OFTF_SENDING)
+ { // just sanity check - this is only for receiving client
+ NetLog_Direct("Error: Invalid Packet, closing.");
+ CloseOscarConnection(oc);
+ return;
+ }
+
+ // Read Frame data
+ if (!(ft->flags & OFTF_FILE_REQUEST_RECEIVED))
+ {
+ unpackWord(&pBuffer, &ft->wEncrypt);
+ unpackWord(&pBuffer, &ft->wCompress);
+ unpackWord(&pBuffer, &ft->wFilesCount);
+ }
+ else
+ pBuffer += 6;
+ unpackWord(&pBuffer, &ft->wFilesLeft);
+ ft->iCurrentFile = ft->wFilesCount - ft->wFilesLeft;
+ if (!(ft->flags & OFTF_FILE_REQUEST_RECEIVED))
+ unpackWord(&pBuffer, &ft->wPartsCount);
+ else
+ pBuffer += 2;
+ unpackWord(&pBuffer, &ft->wPartsLeft);
+ if (!(ft->flags & OFTF_FILE_REQUEST_RECEIVED))
+ { // 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->flags & OFTF_FILE_REQUEST_RECEIVED))
+ unpackString(&pBuffer, ft->rawIDString, 32);
+ else
+ pBuffer += 32;
+ unpackByte(&pBuffer, &ft->bHeaderFlags);
+ unpackByte(&pBuffer, &ft->bNameOff);
+ unpackByte(&pBuffer, &ft->bSizeOff);
+ if (!(ft->flags & OFTF_FILE_REQUEST_RECEIVED))
+ {
+ unpackString(&pBuffer, (char*)ft->rawDummy, 69);
+ unpackString(&pBuffer, (char*)ft->rawMacInfo, 16);
+ }
+ else
+ pBuffer += 85;
+ unpackWord(&pBuffer, &ft->wEncoding);
+ unpackWord(&pBuffer, &ft->wSubEncoding);
+ ft->cbRawFileName = wLen - 176;
+ SAFE_FREE((void**)&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
+ int i;
+
+ for (i = 0; i < strlennull(ft->szThisFile); i++)
+ {
+ if (ft->szThisFile[i] == 0x01) ft->szThisFile[i] = '\\';
+ }
+ }
+
+ ft->flags |= OFTF_FILE_REQUEST_RECEIVED; // 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;
+ }
+ char *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 (BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, ft, (LPARAM)&pfts))
+ {
+ oc->status = OCS_WAITING;
+ break; /* UI supports resume: it will call PS_FILERESUME */
+ }
+
+ 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, LPGEN("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."));
+
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&oc->ft);
+ return;
+ }
+ }
+ // Send "we are ready"
+ oc->status = OCS_DATA;
+ ft->flags |= OFTF_FILE_RECEIVING;
+
+ sendOFT2FramePacket(oc, OFT_TYPE_READY);
+ BroadcastAck(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
+ oc->status = OCS_DATA;
+ oc->wantIdleTime = 1;
+ ft->flags |= OFTF_FILE_SENDING;
+
+ NetLog_Direct("OFT: Receiver ready.");
+ }
+ break;
+
+ case OFT_TYPE_RESUMEREQUEST:
+ { // Receiver wants to resume file transfer from point
+ DWORD dwResumeCheck, dwResumeOffset, dwFileCheck;
+
+ if (!(ft->flags & OFTF_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
+ DWORD dwResumeOffset, dwResumeCheck;
+
+ if (ft->flags & OFTF_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;
+ if (dwResumeOffset)
+ ft->dwRecvFileCheck = dwResumeCheck;
+ else // Restarted resume (data mismatch)
+ ft->dwRecvFileCheck = 0xFFFF0000;
+ }
+ _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;
+
+ BroadcastAck(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
+ oc->status = OCS_NEGOTIATION;
+ oc->wantIdleTime = 0;
+
+ ft->flags &= ~OFTF_FILE_SENDING;
+
+ 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
+/////////////////////////////
+
+void CIcqProto::proxy_sendInitTunnel(oscar_connection *oc)
+{
+ icq_packet packet;
+ WORD wLen = 39 + getUINLen(m_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, m_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);
+}
+
+void CIcqProto::proxy_sendJoinTunnel(oscar_connection *oc, WORD wPort)
+{
+ icq_packet packet;
+ WORD wLen = 41 + getUINLen(m_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, m_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
+/////////////////////////////
+
+void CIcqProto::oft_sendFileData(oscar_connection *oc)
+{
+ oscar_filetransfer *ft = oc->ft;
+ BYTE buf[OFT_BUFFER_SIZE];
+
+ if (ft->fileId == -1)
+ return;
+
+ int 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;
+ }
+
+ if (bytesRead)
+ {
+ icq_packet packet;
+
+ 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);
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&pfts);
+ ft->dwLastNotify = GetTickCount();
+ }
+}
+
+void CIcqProto::oft_sendPeerInit(oscar_connection *oc)
+{
+ icq_lock l(oftMutex);
+
+ oscar_filetransfer *ft = oc->ft;
+ struct _stati64 statbuf;
+ char *pszThisFileName;
+
+ // prepare init frame
+ if (ft->iCurrentFile >= (int)ft->wFilesCount)
+ { // All files done, great!
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&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, LPGEN("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."));
+
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&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
+ int i;
+ for (i = 0; i < strlennull(pszThisFileName); i++)
+ if (pszThisFileName[i] == '\\' || pszThisFileName[i] == '/')
+ pszThisFileName[i] = 0x01;
+ }
+
+ BroadcastAck(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((void**)&pszThisFileName);
+ icq_LogMessage(LOG_ERROR, LPGEN("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."));
+ //
+ BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ // Release transfer
+ SafeReleaseFileTransfer((void**)&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((void**)&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, (char*)pszThisFileName);
+ SAFE_FREE((void**)&pszThisFileName);
+ }
+ else
+ {
+ ft->wEncoding = 2; // ucs-2
+ WCHAR *pwsThisFile = make_unicode_string(pszThisFileName);
+ SAFE_FREE((void**)&pszThisFileName);
+ ft->cbRawFileName = strlennull(pwsThisFile) * (int)sizeof(WCHAR) + 2;
+ if (ft->cbRawFileName < 64) ft->cbRawFileName = 64;
+ ft->rawFileName = (char*)SAFE_MALLOC(ft->cbRawFileName);
+ // convert to LE ordered string
+ BYTE *pwsThisFileBuf = (BYTE*)pwsThisFile; // need this - unpackWideString moves the address!
+ unpackWideString(&pwsThisFileBuf, (WCHAR*)ft->rawFileName, (WORD)(strlennull(pwsThisFile) * sizeof(WCHAR)));
+ SAFE_FREE((void**)&pwsThisFile);
+ }
+ ft->wFilesLeft = (WORD)(ft->wFilesCount - ft->iCurrentFile);
+
+ sendOFT2FramePacket(oc, OFT_TYPE_REQUEST);
+}
+
+void CIcqProto::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, (LPBYTE)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, (LPBYTE)ft->rawFileName, ft->cbRawFileName);
+
+ sendOscarPacket(oc, &packet);
+}
diff --git a/protocols/IcqOscarJ/oscar_filetransfer.h b/protocols/IcqOscarJ/oscar_filetransfer.h
new file mode 100644
index 0000000000..a635f06e8f
--- /dev/null
+++ b/protocols/IcqOscarJ/oscar_filetransfer.h
@@ -0,0 +1,171 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000-2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001-2002 Jon Keating, Richard Hughes
+// Copyright 2002-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/oscar_filetransfer.h $
+// Revision : $Revision: 11353 $
+// Last change on : $Date: 2010-03-10 02:21:03 +0200 (Ср, 10 мар 2010) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// OSCAR File-Transfers headers
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __OSCAR_FILETRANSFER_H
+#define __OSCAR_FILETRANSFER_H
+
+
+#define FT_MAGIC_ICQ 0x00
+#define FT_MAGIC_OSCAR 0x4F
+
+struct basic_filetransfer
+{
+ cookie_message_data pMessage;
+ BYTE ft_magic;
+};
+
+#define OFT_BUFFER_SIZE 8192
+
+struct oft_file_record
+{
+ char *szContainer;
+ char *szFile;
+};
+
+char *FindFilePathContainer(const char **files, int iFile, char *szContainer);
+
+
+// file-transfer status flags
+#define OFTF_INITIALIZED 0x0001 // connection established (ack received)
+#define OFTF_SENDING 0x0002 // sending files (receiving otherwise)
+#define OFTF_FILE_REQUEST_SENT 0x0004 // request sent (sending only)
+#define OFTF_FILE_REQUEST_RECEIVED 0x0008 // first request processed (receiving only)
+#define OFTF_FILE_SENDING 0x0010 // sending file contents
+#define OFTF_FILE_RECEIVING 0x0020 // receiving file contents
+#define OFTF_FILE_DONE 0x0040 // file finished
+
+struct oscar_filetransfer: public basic_filetransfer
+{
+ HANDLE hContact;
+ int flags; // combination of OFTF_*
+ int containerCount;
+ char **file_containers;
+ oft_file_record *files;
+ char **files_list; // 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;
+ struct oscar_connection *connection;
+ struct oscar_listener *listener;
+ DWORD dwLastNotify;
+ int resumeAction;
+};
+
+#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);
+
+struct oscar_connection
+{
+ HANDLE hContact;
+ HANDLE hConnection;
+ int status;
+ DWORD dwUin;
+ uid_str szUid;
+ DWORD dwLocalInternalIP;
+ DWORD dwLocalExternalIP;
+ int type;
+ int incoming;
+ oscar_filetransfer *ft;
+ int wantIdleTime;
+};
+
+#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
+
+struct oscar_listener
+{
+ CIcqProto *ppro;
+ WORD wPort;
+ HANDLE hBoundPort;
+ oscar_filetransfer *ft;
+};
+
+
+#endif /* __OSCAR_FILETRANSFER_H */
+
diff --git a/protocols/IcqOscarJ/resource.h b/protocols/IcqOscarJ/resource.h
new file mode 100644
index 0000000000..5798642af2
--- /dev/null
+++ b/protocols/IcqOscarJ/resource.h
@@ -0,0 +1,260 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resources.rc
+//
+#define IDI_ICQ 101
+#define IDS_IDENTIFY 102
+#define IDD_ICQACCOUNT 103
+#define IDD_ASKAUTH 104
+#define IDD_LOGINPW 105
+#define IDD_OPT_ICQ 108
+#define IDD_OPT_ICQCONTACTS 109
+#define IDD_OPT_ICQFEATURES 110
+#define IDD_OPT_ICQPRIVACY 111
+#define IDI_AUTH_ASK 150
+#define IDI_AUTH_GRANT 151
+#define IDI_AUTH_REVOKE 152
+#define IDI_SERVLIST_ADD 160
+#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 235
+#define IDI_XSTATUS36 236
+#define IDI_XSTATUS37 237
+#define IDI_XSTATUS38 238
+#define IDI_XSTATUS39 239
+#define IDI_XSTATUS40 240
+#define IDI_XSTATUS41 241
+#define IDI_XSTATUS42 242
+#define IDI_XSTATUS43 243
+#define IDI_XSTATUS44 244
+#define IDI_XSTATUS45 245
+#define IDI_XSTATUS46 246
+#define IDI_XSTATUS47 247
+#define IDI_XSTATUS48 248
+#define IDI_XSTATUS49 249
+#define IDI_XSTATUS50 250
+#define IDI_XSTATUS51 251
+#define IDI_XSTATUS52 252
+#define IDI_XSTATUS53 253
+#define IDI_XSTATUS54 254
+#define IDI_XSTATUS55 255
+#define IDI_XSTATUS56 256
+#define IDI_XSTATUS57 257
+#define IDI_XSTATUS58 258
+#define IDI_XSTATUS59 259
+#define IDI_XSTATUS60 260
+#define IDI_XSTATUS61 261
+#define IDI_XSTATUS62 262
+#define IDI_XSTATUS63 263
+#define IDI_XSTATUS64 264
+#define IDI_XSTATUS65 265
+#define IDI_XSTATUS66 266
+#define IDI_XSTATUS67 267
+#define IDI_XSTATUS68 268
+#define IDI_XSTATUS69 269
+#define IDI_XSTATUS70 270
+#define IDI_XSTATUS71 271
+#define IDI_XSTATUS72 272
+#define IDI_XSTATUS73 273
+#define IDI_XSTATUS74 274
+#define IDI_XSTATUS75 275
+#define IDI_XSTATUS76 276
+#define IDI_XSTATUS77 277
+#define IDI_XSTATUS78 278
+#define IDI_XSTATUS79 279
+#define IDI_XSTATUS80 280
+#define IDI_XSTATUS81 281
+#define IDI_XSTATUS82 282
+#define IDI_XSTATUS83 283
+#define IDI_XSTATUS84 284
+#define IDI_XSTATUS85 285
+#define IDI_XSTATUS86 286
+#define IDD_INFO_ICQ 240
+#define IDD_ICQADVANCEDSEARCH 242
+#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_LOG 1001
+#define IDI_EXPANDSTRINGEDIT 1001
+#define IDC_SAVEPASS 1004
+#define IDC_RETRXSTATUS 1005
+#define IDC_XTITLE_STATIC 1006
+#define IDC_XMSG_STATIC 1007
+#define IDC_SSL 1008
+#define IDC_MD5LOGIN 1009
+#define IDC_UTFENABLE 1010
+#define IDC_XTITLE 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_AIMENABLE 1030
+#define IDC_CLIST 1035
+#define IDC_XSTATUSENABLE 1040
+#define IDC_XSTATUSAUTO 1041
+#define IDC_XSTATUSRESET 1042
+#define IDC_MOODSENABLE 1043
+#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_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_ADDSERVER 1532
+#define IDC_SAVETOSERVER 1533
+#define IDC_ENABLEAVATARS 1536
+#define IDC_AUTOLOADAVATARS 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_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 113
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1026
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/protocols/IcqOscarJ/resources.rc b/protocols/IcqOscarJ/resources.rc
new file mode 100644
index 0000000000..3422da7e54
--- /dev/null
+++ b/protocols/IcqOscarJ/resources.rc
@@ -0,0 +1,594 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+#include "version.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 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_ASK ICON "icos/auth_ask.ico"
+IDI_AUTH_GRANT ICON "icos/auth_grant.ico"
+IDI_AUTH_REVOKE ICON "icos/auth_revoke.ico"
+IDI_SERVLIST_ADD ICON "icos/srvlist_add.ico"
+IDI_EXPANDSTRINGEDIT ICON "changeinfo/expandst.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ICQACCOUNT DIALOGEX 0, 0, 186, 68
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "ICQ Number:",IDC_STATIC,0,0,53,12
+ EDITTEXT IDC_UIN,54,0,131,12,ES_AUTOHSCROLL
+ LTEXT "Password:",IDC_STATIC,0,16,53,12
+ EDITTEXT IDC_PW,54,16,131,12,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "Create a new ICQ account",IDC_REGISTER,"Hyperlink",WS_TABSTOP,0,49,174,12
+END
+
+IDD_ASKAUTH DIALOGEX 0, 0, 186, 95
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | 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_LOGINPW DIALOGEX 0, 0, 157, 87
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Enter ICQ Password"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Enter a password for UIN %d:",IDC_INSTRUCTION,7,7,142,8
+ EDITTEXT IDC_LOGINPW,17,16,122,14,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "Remember this session password",IDC_SAVEPASS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,54,120,10
+ DEFPUSHBUTTON "OK",IDOK,24,66,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,84,66,50,14
+END
+
+IDD_OPT_ICQ DIALOGEX 0, 0, 310, 234
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "ICQ",IDC_STICQGROUP,4,0,302,93
+ RTEXT "ICQ number:",IDC_STATIC11,12,14,51,8
+ EDITTEXT IDC_ICQNUM,68,12,106,12,ES_AUTOHSCROLL
+ RTEXT "Password:",IDC_STATIC12,12,28,51,8
+ EDITTEXT IDC_PASSWORD,68,26,106,12,ES_PASSWORD | ES_AUTOHSCROLL
+ LTEXT "Hint: If you don't enter your password here, Miranda will ask for the password everytime you try to go online.",IDC_STATIC,12,43,286,19
+ CONTROL "Retrieve a lost password or ICQ number",IDC_LOOKUPLINK,
+ "Hyperlink",WS_TABSTOP,12,78,286,8
+ CONTROL "Create a new ICQ account using the ICQ website",IDC_NEWUINLINK,
+ "Hyperlink",WS_TABSTOP,12,66,286,8
+ GROUPBOX "Connection settings",IDC_STATIC,4,94,302,136
+ LTEXT "Login Server:",IDC_STATIC,12,108,55,8
+ EDITTEXT IDC_ICQSERVER,68,106,106,12,ES_AUTOHSCROLL
+ LTEXT "Port:",IDC_STATIC,182,108,25,8
+ EDITTEXT IDC_ICQPORT,208,106,29,12,ES_AUTOHSCROLL
+ PUSHBUTTON "Default",IDC_RESETSERVER,244,106,50,12
+ LTEXT "Hint: Use port 0 to connect on a random port. Try port 80 or port 443 if you are having problems connecting through a http proxy server.",IDC_STATIC,12,123,286,19
+ CONTROL "Secure Connection (SSL)",IDC_SSL,"Button",BS_AUTOCHECKBOX | BS_TOP | WS_TABSTOP,12,143,286,10
+ CONTROL "Secure (MD5) login",IDC_MD5LOGIN,"Button",BS_AUTOCHECKBOX | BS_TOP | WS_TABSTOP,12,154,286,10
+ CONTROL "Send 'Keep-alives' (enable this if you use a proxy server and frequently get disconnected)",IDC_KEEPALIVE,
+ "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,12,166,286,18
+ CONTROL "Ignore concurrent error messages",IDC_NOERRMULTI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,190,286,10
+ LTEXT "Show connection error messages:",IDC_STATIC,12,204,238,8
+ CONTROL "Slider1",IDC_LOGLEVEL,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,18,214,52,10
+ LTEXT "",IDC_LEVELDESCR,72,214,226,8,SS_NOPREFIX
+END
+
+IDD_OPT_ICQCONTACTS DIALOGEX 0, 0, 310, 234
+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,302,97
+ PUSHBUTTON "Manage server's list...",IDC_UPLOADNOW,12,77,97,14
+ CONTROL "Enable server-side contact lists *",IDC_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,15,288,10
+ CONTROL "Add contacts to the server's list when I add them to mine",IDC_ADDSERVER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,33,288,10
+ CONTROL "Update my contacts' details from the server *",IDC_LOADFROMSERVER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,46,288,10
+ CONTROL "Update contacts' details on the server's list when I change them in mine",IDC_SAVETOSERVER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,59,290,10
+ GROUPBOX "ICQ avatars",IDC_STATIC,4,98,302,70
+ CONTROL "Enable avatar support",IDC_ENABLEAVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,110,288,10
+ CONTROL "Check avatar validity before saving *",IDC_STRICTAVATARCHECK,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,124,288,10
+ CONTROL "Load avatars automatically (like ICQ Lite)",IDC_AUTOLOADAVATARS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,138,288,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,10,172,290,16,NOT WS_VISIBLE
+ LTEXT "You cannot enable/disable the server-side contact list while you are connected to the ICQ network.",IDC_OFFLINETOENABLE,10,192,290,16,NOT WS_VISIBLE
+ CTEXT "Note: The options marked with an asterisk have important side-effects or caveats that may not be initially apparent documented in the help.",IDC_STATIC,10,212,290,16
+END
+
+IDD_OPT_ICQFEATURES DIALOGEX 0, 0, 310, 234
+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,302,94
+ CONTROL "Enable unicode messaging support",IDC_UTFENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,12,288,10
+ CONTROL "Send all messages in unicode if possible",IDC_UTFALL,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,24,288,10
+ RTEXT "Use this codepage for Ansi <-> Unicode translation :",IDC_UTFSTATIC,12,38,174,10
+ COMBOBOX IDC_UTFCODEPAGE,190,36,107,51,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Make me temporarily visible to contacts I send message to",IDC_TEMPVISIBLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,53,288,10
+ CONTROL "Notify me when a message delivery has failed (recommended)",IDC_SLOWSEND,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,65,288,10
+ CONTROL "Never use legacy messaging (server acknowledgements)",IDC_ONLYSERVERACKS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,77,288,10
+ GROUPBOX "Peer-to-peer Messaging",IDC_STATIC,4,95,302,41
+ CONTROL "Enable peer-to-peer message connections",IDC_DCENABLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,107,288,10
+ CONTROL "Passive mode, i.e. do not initiate new connections",IDC_DCPASSIVE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,119,288,10
+ GROUPBOX "Extra Features",IDC_STATIC,4,137,302,93
+ CONTROL "Enable Custom status support for xtraz",IDC_XSTATUSENABLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,149,288,10
+ CONTROL "Enable Custom status support for moods",IDC_MOODSENABLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,161,288,10
+ CONTROL "Reset Custom status on status change",IDC_XSTATUSRESET,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,175,288,10
+ CONTROL "Auto-retrieve Custom status details",IDC_XSTATUSAUTO,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,187,288,10
+ CONTROL "Block known Spam Bots",IDC_KILLSPAMBOTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,201,288,10
+ CONTROL "Enable AIM contacts support",IDC_AIMENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,12,215,288,10
+END
+
+IDD_OPT_ICQPRIVACY DIALOGEX 0, 0, 310, 234
+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,4,0,302,78
+ LTEXT "Allowing direct connections will expose your IP address but may be necessary for some ICQ features to work properly.",IDC_STATIC_DC2,10,12,292,17
+ CONTROL "Allow direct connections with any user",IDC_DCALLOW_ANY,
+ "Button",BS_AUTORADIOBUTTON,21,34,281,10
+ CONTROL "Allow direct connections with users on my contact list",IDC_DCALLOW_CLIST,
+ "Button",BS_AUTORADIOBUTTON,21,47,281,10
+ CONTROL "Allow direct connections only when I authorize or initiate them",IDC_DCALLOW_AUTH,
+ "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,21,60,281,10
+ GROUPBOX "Contact List Authorization",IDC_STATIC_CLIST,4,83,302,45,WS_GROUP
+ CONTROL "All users may add me to their Contact List",IDC_ADD_ANY,
+ "Button",BS_AUTORADIOBUTTON,21,97,281,10
+ CONTROL "I want to be asked when someone wants to add me to their Contact List",IDC_ADD_AUTH,
+ "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,21,111,281,10
+ GROUPBOX "Misc Settings",IDC_STATIC,4,131,302,78
+ CONTROL "Allow others to view my Online / Offline status from the web (Web Aware)",IDC_WEBAWARE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,144,281,10
+ CONTROL "Allow others to view my primary e-mail address",IDC_PUBLISHPRIMARY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,160,281,10
+ CONTROL "Only reply to status message requests from users on my contact list",IDC_STATUSMSG_CLIST,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,176,281,10
+ CONTROL "Only reply to status message request from visible contacts",IDC_STATUSMSG_VISIBLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,192,269,10
+ CTEXT "Some options are greyed out because they can only be changed when you are online.",IDC_STATIC_NOTONLINE,4,215,302,8
+END
+
+IDD_OPT_POPUPS DIALOGEX 0, 0, 314, 251
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Options",IDC_STATIC,4,4,305,81
+ CONTROL "Enable popup support",IDC_POPUPS_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,19,216,10
+ CONTROL "Display errors using popups",IDC_POPUPS_LOG_ENABLED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,37,216,10
+ CONTROL "Display popup when spambot is detected",IDC_POPUPS_SPAM_ENABLED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,50,216,10
+ GROUPBOX "Look && Feel",IDC_STATIC,4,91,305,143
+ LTEXT "Back Color",IDC_STATIC,80,104,42,8
+ LTEXT "Text Color",IDC_STATIC,130,104,40,8
+ LTEXT "Timeout (*)",IDC_STATIC,182,104,60,8
+ LTEXT "Note",IDC_STATIC,12,116,60,8
+ CONTROL "",IDC_POPUP_LOG0_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,115,39,10
+ CONTROL "",IDC_POPUP_LOG0_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,115,39,10
+ EDITTEXT IDC_POPUP_LOG0_TIMEOUT,182,114,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Warning",IDC_STATIC,12,131,60,8
+ CONTROL "",IDC_POPUP_LOG1_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,130,39,10
+ CONTROL "",IDC_POPUP_LOG1_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,130,39,10
+ EDITTEXT IDC_POPUP_LOG1_TIMEOUT,182,129,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Error",IDC_STATIC,12,146,60,8
+ CONTROL "",IDC_POPUP_LOG2_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,145,39,10
+ CONTROL "",IDC_POPUP_LOG2_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,145,39,10
+ EDITTEXT IDC_POPUP_LOG2_TIMEOUT,182,144,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Fatal",IDC_STATIC,12,161,60,8
+ CONTROL "",IDC_POPUP_LOG3_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,160,39,10
+ CONTROL "",IDC_POPUP_LOG3_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,160,39,10
+ EDITTEXT IDC_POPUP_LOG3_TIMEOUT,182,159,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Spam detected",IDC_STATIC,12,176,60,8
+ CONTROL "",IDC_POPUP_SPAM_BACKCOLOR,"ColourPicker",WS_TABSTOP,80,175,39,10
+ CONTROL "",IDC_POPUP_SPAM_TEXTCOLOR,"ColourPicker",WS_TABSTOP,130,175,39,10
+ EDITTEXT IDC_POPUP_SPAM_TIMEOUT,182,174,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "&Use Windows colors",IDC_USEWINCOLORS,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,12,194,220,8
+ CONTROL "Use system &icons",IDC_USESYSICONS,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,12,207,220,8
+ DEFPUSHBUTTON "Previe&w",IDC_PREVIEW,247,203,52,12
+ LTEXT "(*) Timeouts require Popup v. 1.0.1.9 or later",IDC_STATIC,12,221,232,8
+END
+
+IDD_INFO_ICQ 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
+ LTEXT "UIN:",IDC_UINSTATIC,5,5,71,8
+ EDITTEXT IDC_UIN,74,5,143,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "External IP:",IDC_STATIC,5,18,71,8
+ EDITTEXT IDC_IP,74,18,74,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "Internal IP:",IDC_STATIC,5,31,71,8
+ EDITTEXT IDC_REALIP,74,31,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "Port:",IDC_STATIC,5,44,71,8
+ EDITTEXT IDC_PORT,74,44,141,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "Protocol Version:",IDC_STATIC,5,57,71,8
+ EDITTEXT IDC_VERSION,74,57,142,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "User Client:",IDC_STATIC,5,70,71,8
+ EDITTEXT IDC_MIRVER,74,70,141,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "Online since:",IDC_STATIC,5,83,71,8
+ EDITTEXT IDC_ONLINESINCE,74,83,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "System up since:",IDC_SUPTIME,5,96,71,8
+ EDITTEXT IDC_SYSTEMUPTIME,74,96,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "Idle since:",IDC_STATIC,5,109,71,8
+ EDITTEXT IDC_IDLETIME,74,109,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "Status:",IDC_STATIC,5,122,71,8
+ EDITTEXT IDC_STATUS,74,122,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+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 info",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,142,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,226,222,68,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_XTITLE_STATIC,5,0,179,8
+ EDITTEXT IDC_XTITLE,5,9,179,13,ES_AUTOHSCROLL
+ LTEXT "Message:",IDC_XMSG_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
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_ICQACCOUNT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ TOPMARGIN, 7
+ END
+
+ IDD_ASKAUTH, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ END
+
+ IDD_LOGINPW, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 149
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 80
+ END
+
+ IDD_OPT_ICQ, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ VERTGUIDE, 12
+ VERTGUIDE, 174
+ VERTGUIDE, 302
+ TOPMARGIN, 4
+ HORZGUIDE, 120
+ END
+
+ IDD_OPT_ICQCONTACTS, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ VERTGUIDE, 12
+ VERTGUIDE, 302
+ TOPMARGIN, 4
+ BOTTOMMARGIN, 232
+ END
+
+ IDD_OPT_ICQFEATURES, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ VERTGUIDE, 12
+ TOPMARGIN, 7
+ END
+
+ IDD_OPT_ICQPRIVACY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 307
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 233
+ END
+
+ IDD_OPT_POPUPS, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ RIGHTMARGIN, 309
+ VERTGUIDE, 12
+ VERTGUIDE, 80
+ VERTGUIDE, 130
+ VERTGUIDE, 182
+ TOPMARGIN, 4
+ HORZGUIDE, 19
+ HORZGUIDE, 37
+ HORZGUIDE, 104
+ HORZGUIDE, 203
+ END
+
+ IDD_INFO_ICQ, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 217
+ VERTGUIDE, 61
+ TOPMARGIN, 5
+ BOTTOMMARGIN, 129
+ HORZGUIDE, 22
+ HORZGUIDE, 35
+ HORZGUIDE, 48
+ HORZGUIDE, 61
+ HORZGUIDE, 74
+ END
+
+ IDD_ICQADVANCEDSEARCH, DIALOG
+ BEGIN
+ LEFTMARGIN, 8
+ RIGHTMARGIN, 327
+ VERTGUIDE, 15
+ VERTGUIDE, 25
+ VERTGUIDE, 65
+ VERTGUIDE, 156
+ VERTGUIDE, 178
+ VERTGUIDE, 228
+ VERTGUIDE, 319
+ TOPMARGIN, 5
+ BOTTOMMARGIN, 239
+ END
+
+ IDD_ICQUPLOADLIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 353
+ TOPMARGIN, 5
+ BOTTOMMARGIN, 236
+ END
+
+ IDD_INFO_CHANGEINFO, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ RIGHTMARGIN, 220
+ TOPMARGIN, 2
+ BOTTOMMARGIN, 130
+ END
+
+ IDD_PWCONFIRM, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 162
+ TOPMARGIN, 5
+ BOTTOMMARGIN, 73
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\0"
+ "#include ""version.h""\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION __FILEVERSION_STRING
+ PRODUCTVERSION __FILEVERSION_STRING
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004e4"
+ BEGIN
+ VALUE "Comments", "Licensed under the terms of the GNU General Public License"
+ VALUE "FileDescription", "ICQ protocol plugin for Miranda IM, enhanced"
+ VALUE "FileVersion", __VERSION_STRING
+ VALUE "InternalName", "ICQJ protocol plugin for Miranda IM"
+ VALUE "LegalCopyright", "Copyright (C) 2000-2010 Joe Kucera, Angeli-Ka, Bio, Martin berg, Richard Hughes, Jon Keating"
+ VALUE "OriginalFilename", "ICQ.dll"
+ VALUE "ProductName", "ICQ Protocol Support"
+ VALUE "ProductVersion", __VERSION_STRING
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1252
+ END
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/protocols/IcqOscarJ/stdpackets.cpp b/protocols/IcqOscarJ/stdpackets.cpp
new file mode 100644
index 0000000000..c0bf42238d
--- /dev/null
+++ b/protocols/IcqOscarJ/stdpackets.cpp
@@ -0,0 +1,1902 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/stdpackets.cpp $
+// Revision : $Revision: 13915 $
+// Last change on : $Date: 2011-11-08 01:09:29 +0200 (Вт, 08 ноя 2011) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+extern const int moodXStatus[];
+
+/*****************************************************************************
+*
+* Some handy extra pack functions for basic message type headers
+*
+*/
+
+// This is the part of the message header that is common for all message channels
+static void packServMsgSendHeader(icq_packet *p, DWORD dwSequence, DWORD dwID1, DWORD dwID2, DWORD dwUin, const char *szUID, WORD wFmt, WORD wLen)
+{
+ serverPacketInit(p, (WORD)(21 + getUIDLen(dwUin, szUID) + wLen));
+ packFNACHeader(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, CIcqProto *ppro, WORD wLen, WORD wType, WORD wSeq, WORD wCmd = ICQ_META_CLI_REQUEST)
+{
+ serverPacketInit(p, (WORD)(24 + wLen));
+ packFNACHeader(p, ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQUEST, 0, wSeq | (wCmd<<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, ppro->m_dwLocalUIN); // My UIN
+ packLEWord(p, wType); // Request type
+ packWord(p, wSeq);
+}
+
+
+static void packServIcqDirectoryHeader(icq_packet *p, CIcqProto *ppro, WORD wLen, WORD wType, WORD wCommand, WORD wSeq, WORD wSubCommand = ICQ_META_CLI_REQUEST)
+{
+ packServIcqExtensionHeader(p, ppro, wLen + 0x1E, CLI_META_INFO_REQ, wSeq, wSubCommand);
+ packLEWord(p, wType);
+ packLEWord(p, wLen + 0x1A);
+ packFNACHeader(p, 0x5b9, wCommand, 0, 0, 2);
+ packWord(p, 0);
+ packWord(p, (WORD)GetACP());
+ packDWord(p, 2);
+}
+
+
+static void packServTLV5HeaderBasic(icq_packet *p, WORD wLen, DWORD ID1, DWORD ID2, WORD wCommand, const 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, CIcqProto* ppro, BOOL bEmpty)
+{
+ packTLVDWord(p, 0x03, bEmpty ? 0 : ppro->getSettingDword(NULL, "RealIP", 0)); // TLV: 0x03 DWORD IP
+ packTLVWord(p, 0x05, (WORD)(bEmpty ? 0 : ppro->wListenPort)); // TLV: 0x05 Listen port
+}
+
+
+static void packServChannel2Header(icq_packet *p, CIcqProto* ppro, 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, ppro, FALSE);
+
+ packDWord(p, 0x000F0000); // TLV: 0x0F empty
+
+ packServTLV2711Header(p, (WORD)dwCookie, wVersion, bMsgType, bMsgFlags, (WORD)MirandaStatusToIcq(ppro->m_iStatus), wPriority, wLen);
+}
+
+
+static void packServAdvancedReply(icq_packet *p, DWORD dwUin, const char *szUid, DWORD dwID1, DWORD dwID2, WORD wCookie, WORD wLen)
+{
+ serverPacketInit(p, (WORD)(getUIDLen(dwUin, szUid) + 23 + wLen));
+ packFNACHeader(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
+ packUID(p, dwUin, szUid); // Contact UID
+ packWord(p, 0x03); // Msg specific formating
+}
+
+
+static void packServAdvancedMsgReply(icq_packet *p, DWORD dwUin, const char *szUid, DWORD dwID1, DWORD dwID2, WORD wCookie, WORD wVersion, BYTE bMsgType, BYTE bMsgFlags, WORD wLen)
+{
+ packServAdvancedReply(p, dwUin, szUid, 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 CIcqProto::icq_sendCloseConnection()
+{
+ icq_packet packet;
+
+ packet.wLen = 0;
+ write_flap(&packet, ICQ_CLOSE_CHAN);
+ sendServPacket(&packet);
+}
+
+
+void CIcqProto::icq_requestnewfamily(WORD wFamily, void (CIcqProto::*familyhandler)(HANDLE hConn, char* cookie, WORD cookieLen))
+{
+ icq_packet packet;
+ cookie_family_request *request;
+ int bRequestSSL = m_bSecureConnection && (wFamily != ICQ_AVATAR_FAMILY); // Avatar servers does not support SSL
+
+ request = (cookie_family_request*)SAFE_MALLOC(sizeof(cookie_family_request));
+ request->wFamily = wFamily;
+ request->familyHandler = familyhandler;
+
+ DWORD dwCookie = AllocateCookie(CKT_SERVICEREQUEST, ICQ_CLIENT_NEW_SERVICE, 0, request); // generate and alloc cookie
+
+ serverPacketInit(&packet, 12 + (bRequestSSL ? 4 : 0));
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_NEW_SERVICE, 0, dwCookie);
+ packWord(&packet, wFamily);
+ if (bRequestSSL)
+ packDWord(&packet, 0x008C0000); // use SSL
+
+ sendServPacket(&packet);
+}
+
+
+void CIcqProto::icq_setidle(int bAllow)
+{
+ icq_packet packet;
+
+ if (bAllow != m_bIdleAllow)
+ {
+ /* 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);
+
+ m_bIdleAllow = bAllow;
+ sendServPacket(&packet);
+ }
+}
+
+
+void CIcqProto::icq_setstatus(WORD wStatus, const char *szStatusNote)
+{
+ icq_packet packet;
+ char *szCurrentStatusNote = szStatusNote ? getSettingStringUtf(NULL, DBSETTING_STATUS_NOTE, NULL) : NULL;
+ WORD wStatusMoodLen = 0, wStatusNoteLen = 0, wSessionDataLen = 0;
+ char *szMoodData = NULL;
+
+ if (szStatusNote && strcmpnull(szCurrentStatusNote, szStatusNote))
+ { // status note was changed, update now
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ if (m_bMoodsEnabled && !getSettingString(NULL, DBSETTING_STATUS_MOOD, &dbv))
+ szMoodData = null_strdup(dbv.pszVal);
+
+ ICQFreeVariant(&dbv);
+
+ wStatusNoteLen = strlennull(szStatusNote);
+ wStatusMoodLen = strlennull(szMoodData);
+
+ wSessionDataLen = (wStatusNoteLen ? wStatusNoteLen + 4 : 0) + 4 + wStatusMoodLen + 4;
+ }
+ SAFE_FREE(&szCurrentStatusNote);
+
+ // Pack data in packet
+ serverPacketInit(&packet, (WORD)(18 + (wSessionDataLen ? wSessionDataLen + 4 : 0)));
+ 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 (wSessionDataLen)
+ { // Pack session data
+ packWord(&packet, 0x1D); // TLV 1D
+ packWord(&packet, wSessionDataLen); // TLV length
+ packWord(&packet, 0x02); // Item Type
+ if (wStatusNoteLen)
+ {
+ packWord(&packet, 0x400 | (WORD)(wStatusNoteLen + 4)); // Flags + Item Length
+ packWord(&packet, wStatusNoteLen); // Text Length
+ packBuffer(&packet, (LPBYTE)szStatusNote, wStatusNoteLen);
+ packWord(&packet, 0); // Encoding not specified (utf-8 is default)
+ }
+ else
+ packWord(&packet, 0); // Flags + Item Length
+ packWord(&packet, 0x0E); // Item Type
+ packWord(&packet, wStatusMoodLen); // Flags + Item Length
+ if (wStatusMoodLen)
+ packBuffer(&packet, (LPBYTE)szMoodData, wStatusMoodLen); // Mood
+
+ // Save current status note
+ setSettingStringUtf(NULL, DBSETTING_STATUS_NOTE, szStatusNote);
+ }
+ // Release memory
+ SAFE_FREE(&szMoodData);
+
+ // Send packet
+ sendServPacket(&packet);
+}
+
+
+DWORD CIcqProto::icq_SendChannel1Message(DWORD dwUin, char *szUID, HANDLE hContact, char *pszText, cookie_message_data *pCookieData)
+{
+ icq_packet packet;
+ WORD wPacketLength;
+
+ WORD wMessageLen = strlennull(pszText);
+ DWORD 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, (LPBYTE)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 CIcqProto::icq_SendChannel1MessageW(DWORD dwUin, char *szUID, HANDLE hContact, WCHAR *pszText, cookie_message_data *pCookieData)
+{
+ icq_packet packet;
+ WORD wMessageLen;
+ DWORD dwCookie;
+ WORD wPacketLength;
+ WCHAR *ppText;
+ int i;
+
+ wMessageLen = strlennull(pszText) * (int)sizeof(WCHAR);
+ 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 CIcqProto::icq_SendChannel2Message(DWORD dwUin, HANDLE hContact, const char *szMessage, int nBodyLen, WORD wPriority, cookie_message_data *pCookieData, char *szCap)
+{
+ icq_packet packet;
+
+ DWORD dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (void*)pCookieData);
+
+ // Pack the standard header
+ packServChannel2Header(&packet, this, dwUin, (WORD)(nBodyLen + (szCap ? 53:11)), pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwCookie, ICQ_VERSION, (BYTE)pCookieData->bMessageType, 0,
+ wPriority, 0, 0, (BYTE)((pCookieData->nAckType == ACKTYPE_SERVER)?1:0));
+
+ packLEWord(&packet, (WORD)(nBodyLen+1)); // Length of message
+ packBuffer(&packet, (LPBYTE)szMessage, (WORD)(nBodyLen+1)); // Message
+ packMsgColorInfo(&packet);
+
+ if (szCap)
+ {
+ packLEDWord(&packet, 0x00000026); // length of GUID
+ packBuffer(&packet, (LPBYTE)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 CIcqProto::icq_SendChannel2Contacts(DWORD dwUin, char *szUid, HANDLE hContact, const char *pData, WORD wDataLen, const char *pNames, WORD wNamesLen, cookie_message_data *pCookieData)
+{
+ icq_packet packet;
+
+ DWORD dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, pCookieData);
+
+ WORD 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, (LPBYTE)pData); // TLV: 0x2711 Content (Contact UIDs)
+ packTLV(&packet, 0x2712, wNamesLen, (LPBYTE)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 CIcqProto::icq_SendChannel4Message(DWORD dwUin, HANDLE hContact, BYTE bMsgType, WORD wMsgLen, const char *szMsg, cookie_message_data *pCookieData)
+{
+ icq_packet packet;
+ WORD wPacketLength;
+ DWORD 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, m_dwLocalUIN); // My UIN
+ packByte(&packet, bMsgType); // Message type
+ packByte(&packet, 0); // Message flags
+ packLEWord(&packet, wMsgLen); // Message length
+ packBuffer(&packet, (LPBYTE)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 CIcqProto::sendOwnerInfoRequest(void)
+{
+ icq_packet packet;
+
+ cookie_directory_data *pCookieData = (cookie_directory_data*)SAFE_MALLOC(sizeof(cookie_directory_data));
+ pCookieData->bRequestType = DIRECTORYREQUEST_INFOOWNER;
+
+ DWORD dwCookie = AllocateCookie(CKT_DIRECTORY_QUERY, 0, NULL, (void*)pCookieData);
+ WORD wDataLen = getUINLen(m_dwLocalUIN) + 4;
+
+ packServIcqDirectoryHeader(&packet, this, wDataLen + 8, META_DIRECTORY_QUERY, DIRECTORY_QUERY_INFO, (WORD)dwCookie);
+ packWord(&packet, 0x03); // with interests (ICQ6 uses 2 at login)
+ packDWord(&packet, 0x01);
+ packWord(&packet, wDataLen);
+
+ packTLVUID(&packet, 0x32, m_dwLocalUIN, NULL);
+
+ sendServPacket(&packet);
+}
+
+
+DWORD CIcqProto::sendUserInfoMultiRequest(BYTE *pRequestData, WORD wDataLen, int nItems)
+{
+ icq_packet packet;
+
+ cookie_directory_data *pCookieData = (cookie_directory_data*)SAFE_MALLOC(sizeof(cookie_directory_data));
+ if (!pCookieData) return 0; // Failure
+ pCookieData->bRequestType = DIRECTORYREQUEST_INFOMULTI;
+
+ DWORD dwCookie = AllocateCookie(CKT_DIRECTORY_QUERY, 0, NULL, (void*)pCookieData);
+
+ packServIcqDirectoryHeader(&packet, this, wDataLen + 2, META_DIRECTORY_QUERY, DIRECTORY_QUERY_MULTI_INFO, (WORD)dwCookie);
+ packWord(&packet, nItems);
+ packBuffer(&packet, pRequestData, wDataLen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::icq_sendGetInfoServ(HANDLE hContact, DWORD dwUin, int bManual)
+{
+ icq_packet packet;
+ DWORD dwCookie = 0;
+
+ if (IsServerOverRate(ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQUEST, bManual ? RML_IDLE_10 : RML_IDLE_50))
+ return dwCookie;
+
+ DBVARIANT infoToken = {DBVT_DELETED};
+ BYTE *pToken = NULL;
+ WORD cbToken = 0;
+
+ if (!getSetting(hContact, DBSETTING_METAINFO_TOKEN, &infoToken))
+ { // retrieve user details using privacy token
+ cbToken = infoToken.cpbVal;
+ pToken = (BYTE*)_alloca(cbToken);
+ memcpy(pToken, infoToken.pbVal, cbToken);
+
+ ICQFreeVariant(&infoToken);
+ }
+
+ cookie_directory_data *pCookieData = (cookie_directory_data*)SAFE_MALLOC(sizeof(cookie_directory_data));
+ pCookieData->bRequestType = DIRECTORYREQUEST_INFOUSER;
+
+ dwCookie = AllocateCookie(CKT_DIRECTORY_QUERY, 0, hContact, (void*)pCookieData);
+ WORD wDataLen = cbToken + getUINLen(dwUin) + (cbToken ? 8 : 4);
+
+ packServIcqDirectoryHeader(&packet, this, wDataLen + 8, META_DIRECTORY_QUERY, DIRECTORY_QUERY_INFO, (WORD)dwCookie);
+ packWord(&packet, 0x03);
+ packDWord(&packet, 1);
+ packWord(&packet, wDataLen);
+ if (pToken)
+ packTLV(&packet, 0x3C, cbToken, pToken);
+ packTLVUID(&packet, 0x32, dwUin, NULL);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::icq_sendGetAimProfileServ(HANDLE hContact, char* szUid)
+{
+ icq_packet packet;
+ BYTE bUIDlen = strlennull(szUid);
+
+ if (IsServerOverRate(ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, RML_IDLE_10))
+ return 0;
+
+ cookie_fam15_data *pCookieData = (cookie_fam15_data*)SAFE_MALLOC(sizeof(cookie_fam15_data));
+ pCookieData->bRequestType = REQUESTTYPE_PROFILE;
+
+ DWORD dwCookie = AllocateCookie(CKT_FAMILYSPECIAL, ICQ_LOCATION_REQ_USER_INFO, hContact, (void*)pCookieData);
+
+ serverPacketInit(&packet, (WORD)(13 + bUIDlen));
+ packFNACHeader(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, 0, dwCookie);
+ packWord(&packet, 0x01); // request profile info
+ packByte(&packet, bUIDlen);
+ packBuffer(&packet, (LPBYTE)szUid, bUIDlen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::icq_sendGetAwayMsgServ(HANDLE hContact, DWORD dwUin, int type, WORD wVersion)
+{
+ icq_packet packet;
+
+ if (IsServerOverRate(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, RML_IDLE_30))
+ return 0;
+
+ cookie_message_data *pCookieData = CreateMessageCookie(MTYPE_AUTOAWAY, (BYTE)type);
+ DWORD dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (void*)pCookieData);
+
+ packServChannel2Header(&packet, this, dwUin, 3, pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwCookie, wVersion, (BYTE)type, 3, 1, 0, 0, 0);
+ packEmptyMsg(&packet); // Message
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::icq_sendGetAwayMsgServExt(HANDLE hContact, DWORD dwUin, char *szUID, int type, WORD wVersion)
+{
+ icq_packet packet;
+
+ if (IsServerOverRate(ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND, RML_IDLE_30))
+ return 0;
+
+ cookie_message_data *pCookieData = CreateMessageCookie(MTYPE_AUTOAWAY, (BYTE)type);
+ DWORD dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (void*)pCookieData);
+
+ packServMsgSendHeader(&packet, dwCookie, pCookieData->dwMsgID1, pCookieData->dwMsgID2, dwUin, szUID, 2, 122 + getPluginTypeIdLen(type));
+
+ // TLV(5) header
+ packServTLV5HeaderMsg(&packet, 82 + getPluginTypeIdLen(type), pCookieData->dwMsgID1, pCookieData->dwMsgID2, 1);
+
+ // TLV(0x2711) header
+ packServTLV2711Header(&packet, (WORD)dwCookie, wVersion, MTYPE_PLUGIN, 0, 0, 0x100, 27 + getPluginTypeIdLen(type));
+ //
+ packLEWord(&packet, 0); // Empty msg
+
+ packPluginTypeId(&packet, type);
+
+ packLEDWord(&packet, 0x15);
+ packLEDWord(&packet, 0);
+ packLEDWord(&packet, 0x0D);
+ packBuffer(&packet, (LPBYTE)"text/x-aolrtf", 0x0D);
+
+ // Send the monster
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::icq_sendGetAimAwayMsgServ(HANDLE hContact, char *szUID, int type)
+{
+ icq_packet packet;
+ BYTE bUIDlen = strlennull(szUID);
+
+ cookie_message_data *pCookieData = CreateMessageCookie(MTYPE_AUTOAWAY, (byte)type);
+ DWORD dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (void*)pCookieData);
+
+ serverPacketInit(&packet, (WORD)(13 + bUIDlen));
+ packFNACHeader(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, 0, dwCookie);
+ packWord(&packet, 0x03);
+ packUID(&packet, 0, szUID);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+void CIcqProto::icq_sendSetAimAwayMsgServ(const char *szMsg)
+{
+ icq_packet packet;
+ WORD wMsgLen = strlennull(szMsg);
+
+ DWORD dwCookie = GenerateCookie(ICQ_LOCATION_SET_USER_INFO);
+
+ if (wMsgLen)
+ {
+ if (wMsgLen > 0x1000) wMsgLen = 0x1000; // limit length
+
+ if (IsUSASCII(szMsg, wMsgLen))
+ {
+ const char* fmt = "text/x-aolrtf; charset=\"us-ascii\"";
+ const WORD fmtlen = (WORD)strlen(fmt);
+
+ serverPacketInit(&packet, 23 + wMsgLen + fmtlen);
+ packFNACHeader(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_SET_USER_INFO, 0, dwCookie);
+ packTLV(&packet, 0x0f, 1, (LPBYTE)"\x02");
+ packTLV(&packet, 0x03, fmtlen, (LPBYTE)fmt);
+ packTLV(&packet, 0x04, wMsgLen, (LPBYTE)szMsg);
+ }
+ else
+ {
+ const char* fmt = "text/x-aolrtf; charset=\"unicode-2-0\"";
+ const WORD fmtlen = (WORD)strlen(fmt);
+
+ WCHAR *szMsgW = make_unicode_string(szMsg);
+ wMsgLen = (WORD)strlennull(szMsgW) * sizeof(WCHAR);
+
+ WCHAR *szMsgW2 = (WCHAR*)alloca(wMsgLen), *szMsgW3 = szMsgW;
+ unpackWideString((BYTE**)&szMsgW3, szMsgW2, wMsgLen);
+ SAFE_FREE(&szMsgW);
+
+ serverPacketInit(&packet, 23 + wMsgLen + fmtlen);
+ packFNACHeader(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_SET_USER_INFO, 0, dwCookie);
+ packTLV(&packet, 0x0f, 1, (LPBYTE)"\x02");
+ packTLV(&packet, 0x03, fmtlen, (LPBYTE)fmt);
+ packTLV(&packet, 0x04, wMsgLen, (LPBYTE)szMsgW2);
+ }
+ }
+ else
+ {
+ serverPacketInit(&packet, 19);
+ packFNACHeader(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_SET_USER_INFO, 0, dwCookie);
+ packTLV(&packet, 0x0f, 1, (LPBYTE)"\x02");
+ packTLV(&packet, 0x04, 0, NULL);
+ }
+
+ sendServPacket(&packet);
+}
+
+
+void CIcqProto::icq_sendFileSendServv7(filetransfer* ft, const char *szFiles)
+{
+ icq_packet packet;
+ WORD wDescrLen = 0, wFilesLen = 0;
+ char *szFilesAnsi = NULL, *szDescrAnsi = NULL;
+
+ if (!utf8_decode(szFiles, &szFilesAnsi))
+ szFilesAnsi = NULL;
+ else
+ wFilesLen = strlennull(szFilesAnsi);
+
+ if (!utf8_decode(ft->szDescription, &szDescrAnsi))
+ szDescrAnsi = NULL;
+ else
+ wDescrLen = strlennull(szDescrAnsi);
+
+ packServChannel2Header(&packet, this, 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, (LPBYTE)szDescrAnsi, (WORD)(wDescrLen + 1));
+ packLEDWord(&packet, 0); // unknown
+ packLEWord(&packet, (WORD)(wFilesLen + 1));
+ packBuffer(&packet, (LPBYTE)szFilesAnsi, (WORD)(wFilesLen + 1));
+ packLEDWord(&packet, ft->dwTotalSize);
+ packLEDWord(&packet, 0); // unknown
+
+ SAFE_FREE(&szFilesAnsi);
+ SAFE_FREE(&szDescrAnsi);
+
+ sendServPacket(&packet);
+}
+
+
+void CIcqProto::icq_sendFileSendServv8(filetransfer* ft, const char *szFiles, int nAckType)
+{
+ icq_packet packet;
+ WORD wDescrLen = 0, wFilesLen = 0;
+ char *szFilesAnsi = NULL, *szDescrAnsi = NULL;
+
+ if (!utf8_decode(szFiles, &szFilesAnsi))
+ szFilesAnsi = NULL;
+ else
+ wFilesLen = strlennull(szFilesAnsi);
+
+ if (!utf8_decode(ft->szDescription, &szDescrAnsi))
+ szDescrAnsi = NULL;
+ else
+ wDescrLen = strlennull(szDescrAnsi);
+
+ // 202 + UIN len + file description (no null) + file name (null included)
+ // Packet size = Flap length + 4
+ WORD 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, this, FALSE);
+
+ // TLV(0x2711) header
+ packServTLV2711Header(&packet, (WORD)ft->dwCookie, ICQ_VERSION, MTYPE_PLUGIN, 0, (WORD)MirandaStatusToIcq(m_iStatus), 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, (LPBYTE)szDescrAnsi, wDescrLen);
+ packWord(&packet, 0x8c82); // Unknown (port?), seen 0x80F6
+ packWord(&packet, 0x0222); // Unknown, seen 0x2e01
+ packLEWord(&packet, (WORD)(wFilesLen + 1));
+ packBuffer(&packet, (LPBYTE)szFilesAnsi, (WORD)(wFilesLen + 1));
+ packLEDWord(&packet, ft->dwTotalSize);
+ packLEDWord(&packet, 0x0008c82); // Unknown, (seen 0xf680 ~33000)
+
+ SAFE_FREE(&szFilesAnsi);
+ SAFE_FREE(&szDescrAnsi);
+
+ // Pack request server ack TLV
+ if (nAckType == ACKTYPE_SERVER)
+ packDWord(&packet, 0x00030000); // TLV(3)
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+
+/* also sends rejections */
+void CIcqProto::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 wDescrLen, wFilesLen;
+ char *szFilesAnsi = NULL, *szDescrAnsi = NULL;
+
+ /* if !accepted, szDescr == szReason, szFiles = "" */
+
+ if (!accepted) szFiles = "";
+
+ if (!utf8_decode(szFiles, &szFilesAnsi))
+ szFilesAnsi = NULL;
+
+ if (!utf8_decode(szDescr, &szDescrAnsi))
+ szDescrAnsi = NULL;
+
+ wDescrLen = strlennull(szDescrAnsi);
+ wFilesLen = strlennull(szFilesAnsi);
+
+ // 202 + UIN len + file description (no null) + file name (null included)
+ // Packet size = Flap length + 4
+ WORD 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, this, !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, (LPBYTE)szDescrAnsi, wDescrLen);
+ packWord(&packet, wPort); // Port
+ packWord(&packet, 0x00); // Unknown
+ packLEWord(&packet, (WORD)(wFilesLen + 1));
+ packBuffer(&packet, (LPBYTE)szFilesAnsi, (WORD)(wFilesLen + 1));
+ packLEDWord(&packet, dwTotalSize);
+ packLEDWord(&packet, (DWORD)wPort); // Unknown
+
+ SAFE_FREE(&szFilesAnsi);
+ SAFE_FREE(&szDescrAnsi);
+
+ // Pack request server ack TLV
+ if (nAckType == ACKTYPE_SERVER)
+ {
+ packDWord(&packet, 0x00030000); // TLV(3)
+ }
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+
+void CIcqProto::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 wDescrLen, wFilesLen;
+ char *szFilesAnsi = NULL, *szDescrAnsi = NULL;
+
+ /* if !accepted, szDescr == szReason, szFiles = "" */
+
+ if (!accepted) szFiles = "";
+
+ if (!utf8_decode(szFiles, &szFilesAnsi))
+ szFilesAnsi = NULL;
+
+ if (!utf8_decode(szDescr, &szDescrAnsi))
+ szDescrAnsi = NULL;
+
+ wDescrLen = strlennull(szDescrAnsi);
+ wFilesLen = strlennull(szFilesAnsi);
+
+ // 150 + UIN len + file description (with null) + file name (2 nulls)
+ // Packet size = Flap length + 4
+ WORD 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, this, !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, (LPBYTE)szDescrAnsi, (WORD)(wDescrLen + 1));
+ packWord(&packet, wPort); // Port
+ packWord(&packet, 0x00); // Unknown
+ packLEWord(&packet, (WORD)(wFilesLen + 2));
+ packBuffer(&packet, (LPBYTE)szFilesAnsi, (WORD)(wFilesLen + 1));
+ packByte(&packet, 0);
+ packLEDWord(&packet, dwTotalSize);
+ packLEDWord(&packet, (DWORD)wPort); // Unknown
+
+ SAFE_FREE(&szFilesAnsi);
+ SAFE_FREE(&szDescrAnsi);
+
+ // Pack request server ack TLV
+ if (nAckType == ACKTYPE_SERVER)
+ {
+ packDWord(&packet, 0x00030000); // TLV(3)
+ }
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+
+void CIcqProto::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 CIcqProto::icq_sendFileDenyServ(DWORD dwUin, filetransfer *ft, const 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 CIcqProto::icq_sendAwayMsgReplyServ(DWORD dwUin, DWORD dwMsgID1, DWORD dwMsgID2, WORD wCookie, WORD wVersion, BYTE msgType, char** szMsg)
+{
+ HANDLE hContact = HContactFromUIN(dwUin, NULL);
+
+ if (validateStatusMessageRequest(hContact, msgType))
+ {
+ NotifyEventHooks(m_modeMsgsEvent, (WPARAM)msgType, (LPARAM)dwUin);
+
+ icq_lock l(m_modeMsgsMutex);
+
+ if (szMsg && *szMsg)
+ {
+ char *pszMsg = NULL;
+ WORD wReplyVersion = ICQ_VERSION;
+
+ if (wVersion == 9)
+ {
+ pszMsg = *szMsg;
+ wReplyVersion = 9;
+ }
+ else
+ { // only v9 protocol supports UTF-8 mode messagees
+ WORD wMsgLen = strlennull(*szMsg) + 1;
+ char *szAnsiMsg = (char*)_alloca(wMsgLen);
+
+ utf8_decode_static(*szMsg, szAnsiMsg, wMsgLen);
+ pszMsg = szAnsiMsg;
+ }
+
+ WORD wMsgLen = strlennull(pszMsg);
+
+ // limit msg len to max snac size - we get disconnected if exceeded
+ if (wMsgLen > MAX_MESSAGESNACSIZE)
+ wMsgLen = MAX_MESSAGESNACSIZE;
+
+ icq_packet packet;
+
+ packServAdvancedMsgReply(&packet, dwUin, NULL, dwMsgID1, dwMsgID2, wCookie, wReplyVersion, msgType, 3, (WORD)(wMsgLen + 3));
+ packLEWord(&packet, (WORD)(wMsgLen + 1));
+ packBuffer(&packet, (LPBYTE)pszMsg, wMsgLen);
+ packByte(&packet, 0);
+
+ sendServPacket(&packet);
+ }
+ }
+}
+
+
+void CIcqProto::icq_sendAwayMsgReplyServExt(DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, WORD wCookie, WORD wVersion, BYTE msgType, char **szMsg)
+{
+ HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
+
+ if (validateStatusMessageRequest(hContact, msgType))
+ {
+ NotifyEventHooks(m_modeMsgsEvent, (WPARAM)msgType, (LPARAM)dwUin);
+
+ icq_lock l(m_modeMsgsMutex);
+
+ if (szMsg && *szMsg)
+ {
+ char *pszMsg = NULL;
+ WORD wReplyVersion = ICQ_VERSION;
+
+ if (wVersion == 9)
+ {
+ pszMsg = *szMsg;
+ wReplyVersion = 9;
+ }
+ else
+ { // only v9 protocol supports UTF-8 mode messagees
+ WORD wMsgLen = strlennull(*szMsg) + 1;
+ char *szAnsiMsg = (char*)_alloca(wMsgLen);
+
+ utf8_decode_static(*szMsg, szAnsiMsg, wMsgLen);
+ pszMsg = szAnsiMsg;
+ }
+ // convert to HTML
+ char *mng = MangleXml(pszMsg, strlennull(pszMsg));
+ pszMsg = (char*)SAFE_MALLOC(strlennull(mng) + 28);
+ strcpy(pszMsg, "<HTML><BODY>"); /// TODO: add support for RTL & user customizable font
+ strcat(pszMsg, mng);
+ SAFE_FREE(&mng);
+ strcat(pszMsg, "</BODY></HTML>");
+
+ WORD wMsgLen = strlennull(pszMsg);
+
+ // limit msg len to max snac size - we get disconnected if exceeded /// FIXME: correct HTML cutting
+ if (wMsgLen > MAX_MESSAGESNACSIZE)
+ wMsgLen = MAX_MESSAGESNACSIZE;
+
+ icq_packet packet;
+
+ packServAdvancedMsgReply(&packet, dwUin, szUID, dwMsgID1, dwMsgID2, wCookie, wReplyVersion, MTYPE_PLUGIN, 0, wMsgLen + 27 + getPluginTypeIdLen(msgType));
+ packLEWord(&packet, 0); // Message size
+ packPluginTypeId(&packet, msgType);
+
+ packLEDWord(&packet, wMsgLen + 21);
+ packLEDWord(&packet, wMsgLen);
+ packBuffer(&packet, (LPBYTE)pszMsg, wMsgLen);
+
+ packLEDWord(&packet, 0x0D);
+ packBuffer(&packet, (LPBYTE)"text/x-aolrtf", 0x0D);
+
+ sendServPacket(&packet);
+ SAFE_FREE(&pszMsg);
+ }
+ }
+}
+
+
+void CIcqProto::icq_sendAdvancedMsgAck(DWORD dwUin, DWORD dwTimestamp, DWORD dwTimestamp2, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags)
+{
+ icq_packet packet;
+
+ packServAdvancedMsgReply(&packet, dwUin, NULL, dwTimestamp, dwTimestamp2, wCookie, ICQ_VERSION, bMsgType, bMsgFlags, 11);
+ packEmptyMsg(&packet); // Status message
+ packMsgColorInfo(&packet);
+
+ sendServPacket(&packet);
+}
+
+
+void CIcqProto::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 CIcqProto::SearchByUin(DWORD dwUin)
+{
+ WORD wInfoLen;
+ icq_packet pBuffer; // I reuse the ICQ packet type as a generic buffer
+ // I should be ashamed! ;)
+
+ // Calculate data size
+ wInfoLen = 4 + getUINLen(dwUin);
+
+ // Initialize our handy data buffer
+ pBuffer.wPlace = 0;
+ pBuffer.pData = (BYTE *)_alloca(wInfoLen);
+ pBuffer.wLen = wInfoLen;
+
+ // Initialize our handy data buffer
+ packTLVUID(&pBuffer, 0x32, dwUin, NULL);
+
+ // Send it off for further packing
+ return sendDirectorySearchPacket(pBuffer.pData, wInfoLen, 0, FALSE);
+}
+
+
+DWORD CIcqProto::SearchByNames(const char *pszNick, const char *pszFirstName, const char *pszLastName, WORD wPage)
+{ // use directory search like ICQ6 does
+ WORD wInfoLen = 0;
+ WORD wNickLen,wFirstLen,wLastLen;
+ icq_packet pBuffer; // I reuse the ICQ packet type as a generic buffer
+ // I should be ashamed! ;)
+
+ wNickLen = strlennull(pszNick);
+ wFirstLen = strlennull(pszFirstName);
+ wLastLen = strlennull(pszLastName);
+
+ _ASSERTE(wFirstLen || wLastLen || wNickLen);
+
+
+ // Calculate data size
+ if (wFirstLen)
+ wInfoLen = wFirstLen + 4;
+ if (wLastLen)
+ wInfoLen += wLastLen + 4;
+ if (wNickLen)
+ wInfoLen += wNickLen + 4;
+
+ // Initialize our handy data buffer
+ pBuffer.wPlace = 0;
+ pBuffer.pData = (BYTE *)_alloca(wInfoLen);
+ pBuffer.wLen = wInfoLen;
+
+ // Pack the search details
+ if (wNickLen)
+ packTLV(&pBuffer, 0x78, wNickLen, (PBYTE)pszNick);
+
+ if (wLastLen)
+ packTLV(&pBuffer, 0x6E, wLastLen, (PBYTE)pszLastName);
+
+ if (wFirstLen)
+ packTLV(&pBuffer, 0x64, wFirstLen, (PBYTE)pszFirstName);
+
+ // Send it off for further packing
+ if (wInfoLen)
+ return sendDirectorySearchPacket(pBuffer.pData, wInfoLen, wPage, FALSE);
+ else
+ return 0; // Failure
+}
+
+
+DWORD CIcqProto::SearchByMail(const char* pszEmail)
+{
+ DWORD dwCookie = 0;
+ 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
+ packLETLVLNTS(&pBuffer, &pBufferPos, pszEmail, TLV_EMAIL);
+
+ // Send it off for further packing
+ dwCookie = sendTLVSearchPacket(SEARCHTYPE_EMAIL, (char*)pBuffer, META_SEARCH_EMAIL, wInfoLen, FALSE);
+ }
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::sendDirectorySearchPacket(const BYTE *pSearchData, WORD wDataLen, WORD wPage, BOOL bOnlineUsersOnly)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+
+ _ASSERTE(pSearchData);
+ _ASSERTE(wDataLen >= 4);
+
+ cookie_directory_data *pCookieData = (cookie_directory_data*)SAFE_MALLOC(sizeof(cookie_directory_data));
+ if (pCookieData)
+ {
+ pCookieData->bRequestType = DIRECTORYREQUEST_SEARCH;
+ dwCookie = AllocateCookie(CKT_DIRECTORY_QUERY, 0, NULL, (void*)pCookieData);
+ }
+ else
+ return 0;
+
+ // Pack headers
+ packServIcqDirectoryHeader(&packet, this, wDataLen + (bOnlineUsersOnly ? 14 : 8), META_DIRECTORY_QUERY, DIRECTORY_QUERY_INFO, (WORD)dwCookie);
+ packWord(&packet, 0x02);
+
+ // Pack requested page number
+ packWord(&packet, wPage);
+
+ // Pack search data
+ packWord(&packet, 0x0001);
+ packWord(&packet, wDataLen + (bOnlineUsersOnly ? 6 : 0));
+ packBuffer(&packet, pSearchData, wDataLen);
+
+ if (bOnlineUsersOnly)
+ { // Pack "Online users only" flag
+ packTLVWord(&packet, 0x136, 1);
+ }
+
+ // Go!
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::sendTLVSearchPacket(BYTE bType, char* pSearchDataBuf, WORD wSearchType, WORD wInfoLen, BOOL bOnlineUsersOnly)
+{
+ icq_packet packet;
+ cookie_search* pCookie;
+
+ _ASSERTE(pSearchDataBuf);
+ _ASSERTE(wInfoLen >= 4);
+
+ pCookie = (cookie_search*)SAFE_MALLOC(sizeof(cookie_search));
+ if (!pCookie)
+ return 0;
+
+ pCookie->bSearchType = bType;
+ DWORD dwCookie = AllocateCookie(CKT_SEARCH, 0, 0, pCookie);
+
+ // Pack headers
+ packServIcqExtensionHeader(&packet, this, (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, (LPBYTE)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 CIcqProto::icq_sendAdvancedSearchServ(BYTE* fieldsBuffer,int bufferLen)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+
+ cookie_search *pCookie = (cookie_search*)SAFE_MALLOC(sizeof(cookie_search));
+ if (pCookie)
+ {
+ pCookie->bSearchType = SEARCHTYPE_DETAILS;
+ dwCookie = AllocateCookie(CKT_SEARCH, 0, 0, pCookie);
+ }
+ else
+ return 0;
+
+ packServIcqExtensionHeader(&packet, this, (WORD)bufferLen, CLI_META_INFO_REQ, (WORD)dwCookie);
+ packBuffer(&packet, (LPBYTE)fieldsBuffer, (WORD)bufferLen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::icq_searchAimByEmail(const char* pszEmail, DWORD dwSearchId)
+{
+ icq_packet packet;
+ DWORD dwCookie;
+ cookie_search* pCookie;
+ WORD wEmailLen;
+
+ if (!FindCookie(dwSearchId, NULL, (void**)&pCookie))
+ {
+ dwSearchId = 0;
+ pCookie = (cookie_search*)SAFE_MALLOC(sizeof(cookie_search));
+ 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));
+ packFNACHeader(&packet, ICQ_LOOKUP_FAMILY, ICQ_LOOKUP_REQUEST, 0, dwCookie);
+ packBuffer(&packet, (LPBYTE)pszEmail, wEmailLen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::icq_changeUserPasswordServ(const char *szPassword)
+{
+ icq_packet packet;
+ WORD wPasswordLen = strlennull(szPassword);
+ DWORD dwCookie = GenerateCookie(0);
+
+ packServIcqExtensionHeader(&packet, this, (WORD)(wPasswordLen + 4), CLI_META_INFO_REQ, (WORD)dwCookie, ICQ_META_SRV_UPDATE);
+ packLEWord(&packet, META_SET_PASSWORD_REQ);
+ packLEWord(&packet, wPasswordLen);
+ packBuffer(&packet, (BYTE*)szPassword, wPasswordLen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::icq_changeUserDirectoryInfoServ(const BYTE *pData, WORD wDataLen, BYTE bRequestType)
+{
+ icq_packet packet;
+ cookie_directory_data *pCookieData = (cookie_directory_data*)SAFE_MALLOC(sizeof(cookie_directory_data));
+ pCookieData->bRequestType = bRequestType;
+ DWORD dwCookie = AllocateCookie(CKT_DIRECTORY_UPDATE, 0, NULL, pCookieData);
+
+ packServIcqDirectoryHeader(&packet, this, wDataLen + 4, META_DIRECTORY_UPDATE, DIRECTORY_SET_INFO, (WORD)dwCookie, ICQ_META_SRV_UPDATE);
+ packWord(&packet, 0x0003);
+ packWord(&packet, wDataLen);
+ packBuffer(&packet, pData, wDataLen);
+
+ sendServPacket(&packet);
+
+ return dwCookie;
+}
+
+
+DWORD CIcqProto::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, m_dwLocalUIN, szMyNick, szTime);
+
+ dwCookie = GenerateCookie(0);
+
+ packServIcqExtensionHeader(&packet, this, (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, (LPBYTE)szBuffer, (WORD)(1 + wBufferLen));
+
+ sendServPacket(&packet);
+ }
+ else
+ {
+ dwCookie = 0;
+ }
+
+ SAFE_FREE((void**)&szMyNick);
+ return dwCookie;
+}
+
+void CIcqProto::icq_sendGenericContact(DWORD dwUin, const 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 CIcqProto::icq_sendNewContact(DWORD dwUin, const char *szUid)
+{
+ /* Try to add to temporary buddy list */
+ icq_sendGenericContact(dwUin, szUid, ICQ_BUDDY_FAMILY, ICQ_USER_ADDTOTEMPLIST);
+}
+
+
+void CIcqProto::icq_sendRemoveContact(DWORD dwUin, const char *szUid)
+{
+ /* Remove from temporary buddy list */
+ icq_sendGenericContact(dwUin, szUid, ICQ_BUDDY_FAMILY, ICQ_USER_REMOVEFROMTEMPLIST);
+}
+
+
+// list==0: visible list
+// list==1: invisible list
+void CIcqProto::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 (m_bSsiEnabled)
+ {
+ WORD wContactId;
+ char* szSetting;
+ WORD wType;
+
+ if (list == 0)
+ {
+ wType = SSI_ITEM_PERMIT;
+ szSetting = DBSETTING_SERVLIST_PERMIT;
+ }
+ else
+ {
+ wType = SSI_ITEM_DENY;
+ szSetting = DBSETTING_SERVLIST_DENY;
+ }
+
+ if (add)
+ {
+ // check if we should make the changes, this is 2nd level check
+ if (getSettingWord(hContact, szSetting, 0) != 0)
+ return;
+
+ // Add
+ wContactId = GenerateServerID(SSIT_ITEM, 0);
+
+ icq_addServerPrivacyItem(hContact, dwUin, szUID, wContactId, wType);
+
+ setSettingWord(hContact, szSetting, wContactId);
+ }
+ else
+ {
+ // Remove
+ wContactId = getSettingWord(hContact, szSetting, 0);
+
+ if (wContactId)
+ {
+ icq_removeServerPrivacyItem(hContact, dwUin, szUID, wContactId, wType);
+
+ deleteSetting(hContact, szSetting);
+ }
+ }
+ }
+
+ // Notify server that we have changed
+ // our client side visibility list
+ {
+ int nUinLen;
+ icq_packet packet;
+ WORD wSnac = 0;
+
+ if (list && m_iStatus == ID_STATUS_INVISIBLE)
+ return;
+
+ if (!list && m_iStatus != 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 CIcqProto::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 CIcqProto::icq_sendRevokeAuthServ(DWORD dwUin, char *szUid)
+{
+ icq_sendGenericContact(dwUin, szUid, ICQ_LISTS_FAMILY, ICQ_LISTS_REVOKEAUTH);
+}
+
+void CIcqProto::icq_sendGrantAuthServ(DWORD dwUin, const char *szUid, const char *szMsg)
+{
+ icq_packet packet;
+ BYTE 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, nMsglen);
+ packBuffer(&packet, (LPBYTE)szUtfMsg, nMsglen);
+ packWord(&packet, 0);
+
+ SAFE_FREE((void**)&szUtfMsg);
+
+ sendServPacket(&packet);
+}
+
+void CIcqProto::icq_sendAuthReqServ(DWORD dwUin, char *szUid, const char *szMsg)
+{
+ icq_packet packet;
+ BYTE 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, nMsglen);
+ packBuffer(&packet, (LPBYTE)szMsg, nMsglen);
+ packWord(&packet, 0);
+
+ sendServPacket(&packet);
+}
+
+void CIcqProto::icq_sendAuthResponseServ(DWORD dwUin, char* szUid, int auth, const TCHAR *szReason)
+{
+ icq_packet packet;
+ BYTE nUinLen = getUIDLen(dwUin, szUid);
+
+ // Prepare custom utf-8 reason
+ char *szUtfReason = tchar_to_utf8(szReason);
+ WORD nReasonLen = strlennull(szUtfReason);
+
+ serverPacketInit(&packet, (WORD)(16 + nUinLen + nReasonLen));
+ packFNACHeader(&packet, ICQ_LISTS_FAMILY, ICQ_LISTS_CLI_AUTHRESPONSE);
+ packUID(&packet, dwUin, szUid);
+ packByte(&packet, (BYTE)auth);
+ packWord(&packet, nReasonLen);
+ packBuffer(&packet, (LPBYTE)szUtfReason, nReasonLen);
+ packWord(&packet, 0);
+
+ SAFE_FREE(&szUtfReason);
+
+ sendServPacket(&packet);
+}
+
+void CIcqProto::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 CIcqProto::icq_sendXtrazRequestServ(DWORD dwUin, DWORD dwCookie, char* szBody, int nBodyLen, cookie_message_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, (LPBYTE)szBody, (WORD)nBodyLen);
+
+ // Pack request server ack TLV
+ packDWord(&packet, 0x00030000); // TLV(3)
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+void CIcqProto::icq_sendXtrazResponseServ(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szBody, int nBodyLen, int nType)
+{
+ icq_packet packet;
+
+ packServAdvancedMsgReply(&packet, dwUin, NULL, dwMID, dwMID2, wCookie, ICQ_VERSION, MTYPE_PLUGIN, 0, (WORD)(getPluginTypeIdLen(nType) + 11 + nBodyLen));
+ //
+ packEmptyMsg(&packet);
+
+ packPluginTypeId(&packet, nType);
+
+ packLEDWord(&packet, nBodyLen + 4);
+ packLEDWord(&packet, nBodyLen);
+ packBuffer(&packet, (LPBYTE)szBody, (WORD)nBodyLen);
+
+ // Send the monster
+ sendServPacket(&packet);
+}
+
+void CIcqProto::icq_sendReverseReq(directconnect *dc, DWORD dwCookie, cookie_message_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, m_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 CIcqProto::icq_sendReverseFailed(directconnect* dc, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwCookie)
+{
+ icq_packet packet;
+ int nUinLen = getUINLen(dc->dwRemoteUin);
+
+ serverPacketInit(&packet, (WORD)(nUinLen + 74));
+ packFNACHeader(&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 CIcqProto::oft_sendFileRequest(DWORD dwUin, char *szUid, oscar_filetransfer *ft, const char *pszFiles, DWORD dwLocalInternalIP)
+{
+ icq_packet packet;
+
+ char *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));
+
+ WORD 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, (LPBYTE)"utf-8"); // Charset
+ packTLV(&packet, 0x0C, (WORD)strlennull(szCoolStr), (LPBYTE)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, (LPBYTE)pszFiles, (WORD)(strlennull(pszFiles) + 1));
+ }
+ packTLV(&packet, 0x2712, 5, (LPBYTE)"utf-8");
+ { // TLV(0x2713)
+ packWord(&packet, 0x2713);
+ packWord(&packet, 8);
+ packQWord(&packet, ft->qwTotalSize);
+ }
+
+ sendServPacket(&packet); // Send the monster
+}
+
+
+void CIcqProto::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 CIcqProto::oft_sendFileAccept(DWORD dwUin, char *szUid, oscar_filetransfer *ft)
+{
+ oft_sendFileReply(dwUin, szUid, ft, 0x02);
+}
+
+
+void CIcqProto::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 CIcqProto::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 CIcqProto::oft_sendFileCancel(DWORD dwUin, char *szUid, oscar_filetransfer *ft)
+{
+ oft_sendFileReply(dwUin, szUid, ft, 0x01);
+}
+
+
+void CIcqProto::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);
+}
diff --git a/protocols/IcqOscarJ/stdpackets.h b/protocols/IcqOscarJ/stdpackets.h
new file mode 100644
index 0000000000..5d4903fc89
--- /dev/null
+++ b/protocols/IcqOscarJ/stdpackets.h
@@ -0,0 +1,50 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright 2000-2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright 2001-2002 Jon Keating, Richard Hughes
+// Copyright 2002-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/stdpackets.h $
+// Revision : $Revision: 7484 $
+// Last change on : $Date: 2008-03-21 11:43:39 +0200 (Пт, 21 мар 2008) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Low-level functions that really sends data to server
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __STDPACKETS_H
+#define __STDPACKETS_H
+
+struct icq_contactsend_s
+{
+ DWORD uin;
+ char *uid;
+ char *szNick;
+};
+
+
+void packMsgColorInfo(icq_packet *packet);
+
+#endif /* __STDPACKETS_H */
diff --git a/protocols/IcqOscarJ/tlv.cpp b/protocols/IcqOscarJ/tlv.cpp
new file mode 100644
index 0000000000..af6bde4fe7
--- /dev/null
+++ b/protocols/IcqOscarJ/tlv.cpp
@@ -0,0 +1,398 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2009 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/tlv.cpp $
+// Revision : $Revision: 13324 $
+// Last change on : $Date: 2011-01-23 17:58:59 +0200 (Вс, 23 янв 2011) $
+// Last change by : $Author: borkra $
+//
+// 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((void**)&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* oscar_tlv_chain::getTLV(WORD wType, WORD wIndex)
+{
+ int i = 0;
+ oscar_tlv_chain *list = this;
+
+ while (list)
+ {
+ if (list->tlv.wType == wType)
+ i++;
+ if (i >= wIndex)
+ return &list->tlv;
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+
+WORD oscar_tlv_chain::getChainLength()
+{
+ int len = 0;
+ oscar_tlv_chain *list = this;
+
+ while (list)
+ {
+ len += list->tlv.wLen + 4;
+ list = list->next;
+ }
+ return len;
+}
+
+
+oscar_tlv* oscar_tlv_chain::putTLV(WORD wType, WORD wLen, BYTE *pData, BOOL bReplace)
+{
+ oscar_tlv *tlv = getTLV(wType, 1);
+
+ if (tlv && bReplace)
+ {
+ SAFE_FREE((void**)&tlv->pData);
+ }
+ else
+ {
+ oscar_tlv_chain *last = this;
+
+ while (last && last->next)
+ last = last->next;
+
+ if (last)
+ {
+ last->next = (oscar_tlv_chain*)SAFE_MALLOC(sizeof(oscar_tlv_chain));
+ tlv = &last->next->tlv;
+ tlv->wType = wType;
+ }
+ }
+ if (tlv)
+ {
+ tlv->wLen = wLen;
+ tlv->pData = (PBYTE)SAFE_MALLOC(wLen);
+ memcpy(tlv->pData, pData, wLen);
+ }
+ return tlv;
+}
+
+
+oscar_tlv_chain* oscar_tlv_chain::removeTLV(oscar_tlv *tlv)
+{
+ oscar_tlv_chain *list = this, *prev = NULL, *chain = this;
+
+ while (list)
+ {
+ if (&list->tlv == tlv)
+ {
+ if (prev) // relink
+ prev->next = list->next;
+ else if (list->next)
+ { // move second item's tlv to the first item
+ list->tlv = list->next->tlv;
+ list = list->next;
+ }
+ else // result is an empty chain (NULL)
+ chain = NULL;
+ // release chain item memory
+ SAFE_FREE((void**)&list->tlv.pData);
+ SAFE_FREE((void**)&list);
+ }
+ prev = list;
+ list = list->next;
+ }
+
+ return chain;
+}
+
+
+WORD oscar_tlv_chain::getLength(WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv = getTLV(wType, wIndex);
+ if (tlv)
+ return tlv->wLen;
+
+ return 0;
+}
+
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* Values are returned in MSB format */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+DWORD oscar_tlv_chain::getDWord(WORD wType, WORD wIndex)
+{
+ DWORD dw = 0;
+
+ oscar_tlv *tlv = getTLV(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 oscar_tlv_chain::getWord(WORD wType, WORD wIndex)
+{
+ WORD w = 0;
+
+ oscar_tlv *tlv = getTLV(wType, wIndex);
+ if (tlv && tlv->wLen >= 2)
+ {
+ w |= (*((tlv->pData)+0) << 8);
+ w |= (*((tlv->pData)+1));
+ }
+
+ return w;
+}
+
+
+BYTE oscar_tlv_chain::getByte(WORD wType, WORD wIndex)
+{
+ BYTE b = 0;
+
+ oscar_tlv *tlv = getTLV(wType, wIndex);
+ if (tlv && tlv->wLen)
+ {
+ b = *(tlv->pData);
+ }
+
+ return b;
+}
+
+
+int oscar_tlv_chain::getNumber(WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv = getTLV(wType, wIndex);
+
+ if (tlv)
+ {
+ if (tlv->wLen == 1)
+ return getByte(wType, wIndex);
+ else if (tlv->wLen == 2)
+ return getWord(wType, wIndex);
+ else if (tlv->wLen == 4)
+ return getDWord(wType, wIndex);
+ }
+ return 0;
+}
+
+
+double oscar_tlv_chain::getDouble(WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv = getTLV(wType, wIndex);
+
+ if (tlv && tlv->wLen == 8)
+ {
+ BYTE *buf = tlv->pData;
+ double d = 0;
+
+ unpackQWord(&buf, (DWORD64*)&d);
+
+ return d;
+ }
+ return 0;
+}
+
+
+char* oscar_tlv_chain::getString(WORD wType, WORD wIndex)
+{
+ char *str = NULL;
+
+ oscar_tlv *tlv = getTLV(wType, wIndex);
+ if (tlv)
+ {
+ str = (char*)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 **chain)
+{
+ if (!chain || !*chain)
+ return;
+
+ oscar_tlv_chain *now = *chain;
+
+ while (now)
+ {
+ oscar_tlv_chain *next = now->next;
+
+ SAFE_FREE((void**)&now->tlv.pData);
+ SAFE_FREE((void**)&now);
+ now = next;
+ }
+
+ *chain = NULL;
+}
+
+
+oscar_tlv_record_list* readIntoTLVRecordList(BYTE **buf, WORD wLen, int nCount)
+{
+ oscar_tlv_record_list *list = NULL, *last;
+
+ while (wLen >= 2)
+ {
+ WORD wRecordSize;
+
+ unpackWord(buf, &wRecordSize);
+ wLen -= 2;
+ if (wRecordSize && wRecordSize <= wLen)
+ {
+ oscar_tlv_record_list *pRecord = (oscar_tlv_record_list*)SAFE_MALLOC(sizeof(oscar_tlv_record_list));
+ BYTE *pData = *buf;
+
+ *buf += wRecordSize;
+ wLen -= wRecordSize;
+
+ pRecord->item = readIntoTLVChain(&pData, wRecordSize, 0);
+ if (pRecord->item)
+ { // keep the order
+ if (list)
+ last->next = pRecord;
+ else
+ list = pRecord;
+
+ last = pRecord;
+ }
+ else
+ SAFE_FREE((void**)&pRecord);
+ }
+
+ if (--nCount == 0) break;
+ }
+ return list;
+}
+
+
+void disposeRecordList(oscar_tlv_record_list** list)
+{
+ if (!list || !*list)
+ return;
+
+ oscar_tlv_record_list *now = *list;
+
+ while (now)
+ {
+ oscar_tlv_record_list *next = now->next;
+
+ disposeChain(&now->item);
+ SAFE_FREE((void**)&now);
+ now = next;
+ }
+
+ *list = NULL;
+}
+
+
+oscar_tlv_chain* oscar_tlv_record_list::getRecordByTLV(WORD wType, int nValue)
+{
+ oscar_tlv_record_list *list = this;
+
+ while (list)
+ {
+ if (list->item && list->item->getTLV(wType, 1) && list->item->getNumber(wType, 1) == nValue)
+ return list->item;
+ list = list->next;
+ }
+
+ return NULL;
+}
diff --git a/protocols/IcqOscarJ/tlv.h b/protocols/IcqOscarJ/tlv.h
new file mode 100644
index 0000000000..12553bde49
--- /dev/null
+++ b/protocols/IcqOscarJ/tlv.h
@@ -0,0 +1,88 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2008 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: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/tlv.h $
+// Revision : $Revision: 8822 $
+// Last change on : $Date: 2009-01-11 19:17:05 +0200 (Вс, 11 янв 2009) $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __TLV_H
+#define __TLV_H
+
+/*---------* Structures *--------------*/
+
+struct oscar_tlv
+{
+ WORD wType;
+ WORD wLen;
+ BYTE *pData;
+};
+
+
+struct oscar_tlv_chain
+{
+ oscar_tlv tlv;
+ oscar_tlv_chain *next;
+
+ WORD getChainLength();
+
+ oscar_tlv* getTLV(WORD wType, WORD wIndex);
+ oscar_tlv* putTLV(WORD wType, WORD wLen, BYTE *pData, BOOL bReplace);
+ oscar_tlv_chain* removeTLV(oscar_tlv *tlv);
+ WORD getLength(WORD wType, WORD wIndex);
+
+ DWORD getDWord(WORD wType, WORD wIndex);
+ WORD getWord(WORD wType, WORD wIndex);
+ BYTE getByte(WORD wType, WORD wIndex);
+ int getNumber(WORD wType, WORD wIndex);
+ double getDouble(WORD wType, WORD wIndex);
+ char* getString(WORD wType, WORD wIndex);
+};
+
+
+struct oscar_tlv_record_list
+{
+ oscar_tlv_chain *item;
+ oscar_tlv_record_list *next;
+
+ oscar_tlv_chain* getRecordByTLV(WORD wType, int nValue);
+};
+
+/*---------* Functions *---------------*/
+
+oscar_tlv_chain* readIntoTLVChain(BYTE **buf, WORD wLen, int maxTlvs);
+void disposeChain(oscar_tlv_chain** chain);
+
+oscar_tlv_record_list* readIntoTLVRecordList(BYTE **buf, WORD wLen, int nCount);
+void disposeRecordList(oscar_tlv_record_list** list);
+
+
+#endif /* __TLV_H */
diff --git a/protocols/IcqOscarJ/utilities.cpp b/protocols/IcqOscarJ/utilities.cpp
new file mode 100644
index 0000000000..c9124a0aa1
--- /dev/null
+++ b/protocols/IcqOscarJ/utilities.cpp
@@ -0,0 +1,2243 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/utilities.cpp $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+struct gateway_index
+{
+ HANDLE hConn;
+ DWORD dwIndex;
+};
+
+static icq_critical_section *gatewayMutex = NULL;
+
+static gateway_index *gateways = NULL;
+static int gatewayCount = 0;
+
+static DWORD *spammerList = NULL;
+static int spammerListCount = 0;
+
+
+void MoveDlgItem(HWND hwndDlg, int iItem, int left, int top, int width, int height)
+{
+ RECT rc;
+
+ rc.left = left;
+ rc.top = top;
+ rc.right = left + width;
+ rc.bottom = top + height;
+ MapDialogRect(hwndDlg, &rc);
+ MoveWindow(GetDlgItem(hwndDlg, iItem), rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE);
+}
+
+
+void EnableDlgItem(HWND hwndDlg, UINT control, int state)
+{
+ EnableWindow(GetDlgItem(hwndDlg, control), state);
+}
+
+
+void ShowDlgItem(HWND hwndDlg, UINT control, int state)
+{
+ ShowWindow(GetDlgItem(hwndDlg, control), state);
+}
+
+
+void icq_EnableMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state)
+{
+ for (int i = 0; i < cControls; i++)
+ EnableDlgItem(hwndDlg, controls[i], state);
+}
+
+
+void icq_ShowMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state)
+{
+ for (int i = 0; i < cControls; i++)
+ ShowDlgItem(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_OFFLINE:
+ nSupportedStatus = nMirandaStatus;
+ break;
+
+case ID_STATUS_FREECHAT:
+ nSupportedStatus = ID_STATUS_ONLINE;
+ 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 tchar_to_utf8((TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, mirandaStatus, GSMDF_TCHAR));
+}
+
+char** CIcqProto::MirandaStatusToAwayMsg(int nStatus)
+{
+ switch (nStatus) {
+
+case ID_STATUS_ONLINE:
+ return &m_modeMsgs.szOnline;
+
+case ID_STATUS_AWAY:
+ return &m_modeMsgs.szAway;
+
+case ID_STATUS_NA:
+ return &m_modeMsgs.szNa;
+
+case ID_STATUS_OCCUPIED:
+ return &m_modeMsgs.szOccupied;
+
+case ID_STATUS_DND:
+ return &m_modeMsgs.szDnd;
+
+case ID_STATUS_FREECHAT:
+ return &m_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)
+{
+ icq_lock l(gatewayMutex);
+
+ for (int i = 0; i < gatewayCount; i++)
+ {
+ if (hConn == gateways[i].hConn)
+ {
+ gateways[i].dwIndex = dwIndex;
+ return;
+ }
+ }
+
+ gateways = (gateway_index *)SAFE_REALLOC(gateways, sizeof(gateway_index) * (gatewayCount + 1));
+ gateways[gatewayCount].hConn = hConn;
+ gateways[gatewayCount].dwIndex = dwIndex;
+ gatewayCount++;
+}
+
+
+DWORD GetGatewayIndex(HANDLE hConn)
+{
+ icq_lock l(gatewayMutex);
+
+ for (int i = 0; i < gatewayCount; i++)
+ {
+ if (hConn == gateways[i].hConn)
+ return gateways[i].dwIndex;
+ }
+
+ return 1; // this is default
+}
+
+
+void FreeGatewayIndex(HANDLE hConn)
+{
+ icq_lock l(gatewayMutex);
+
+ for (int 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;
+ }
+ }
+}
+
+
+void CIcqProto::AddToSpammerList(DWORD dwUIN)
+{
+ icq_lock l(gatewayMutex);
+
+ spammerList = (DWORD *)SAFE_REALLOC(spammerList, sizeof(DWORD) * (spammerListCount + 1));
+ spammerList[spammerListCount] = dwUIN;
+ spammerListCount++;
+}
+
+
+BOOL CIcqProto::IsOnSpammerList(DWORD dwUIN)
+{
+ icq_lock l(gatewayMutex);
+
+ for (int i = 0; i < spammerListCount; i++)
+ {
+ if (dwUIN == spammerList[i])
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+// ICQ contacts cache
+
+void CIcqProto::AddToContactsCache(HANDLE hContact, DWORD dwUin, const char *szUid)
+{
+ if (!hContact || (!dwUin && !szUid))
+ return;
+
+#ifdef _DEBUG
+ NetLog_Server("Adding contact to cache: %u%s%s", dwUin, dwUin ? "" : " - ", dwUin ? "" : szUid);
+#endif
+
+ icq_contacts_cache *cache_item = (icq_contacts_cache*)SAFE_MALLOC(sizeof(icq_contacts_cache));
+ cache_item->hContact = hContact;
+ cache_item->dwUin = dwUin;
+ if (!dwUin)
+ cache_item->szUid = null_strdup(szUid);
+
+ icq_lock l(contactsCacheMutex);
+ contactsCache.insert(cache_item);
+}
+
+
+void CIcqProto::InitContactsCache()
+{
+ if (!gatewayMutex)
+ gatewayMutex = new icq_critical_section();
+ else
+ gatewayMutex->_Lock();
+
+ contactsCacheMutex = new icq_critical_section();
+
+ // build cache
+ icq_lock l(contactsCacheMutex);
+
+ HANDLE hContact = FindFirstContact();
+
+ while (hContact)
+ {
+ DWORD dwUin;
+ uid_str szUid;
+
+ if (!getContactUid(hContact, &dwUin, &szUid))
+ AddToContactsCache(hContact, dwUin, szUid);
+
+ hContact = FindNextContact(hContact);
+ }
+}
+
+
+void CIcqProto::UninitContactsCache(void)
+{
+ contactsCacheMutex->Enter();
+
+ // cleanup the cache
+ for (int i = 0; i < contactsCache.getCount(); i++)
+ {
+ icq_contacts_cache *cache_item = contactsCache[i];
+
+ SAFE_FREE((void**)&cache_item->szUid);
+ SAFE_FREE((void**)&cache_item);
+ }
+
+ contactsCache.destroy();
+
+ contactsCacheMutex->Leave();
+
+ SAFE_DELETE(&contactsCacheMutex);
+
+ if (gatewayMutex && gatewayMutex->getLockCount() > 1)
+ gatewayMutex->_Release();
+ else
+ SAFE_DELETE(&gatewayMutex);
+}
+
+
+void CIcqProto::DeleteFromContactsCache(HANDLE hContact)
+{
+ icq_lock l(contactsCacheMutex);
+
+ for (int i = 0; i < contactsCache.getCount(); i++)
+ {
+ icq_contacts_cache *cache_item = contactsCache[i];
+
+ if (cache_item->hContact == hContact)
+ {
+#ifdef _DEBUG
+ NetLog_Server("Removing contact from cache: %u%s%s, position: %u", cache_item->dwUin, cache_item->dwUin ? "" : " - ", cache_item->dwUin ? "" : cache_item->szUid, i);
+#endif
+ contactsCache.remove(i);
+ // Release memory
+ SAFE_FREE((void**)&cache_item->szUid);
+ SAFE_FREE((void**)&cache_item);
+ break;
+ }
+ }
+}
+
+
+HANDLE CIcqProto::HandleFromCacheByUid(DWORD dwUin, const char *szUid)
+{
+ icq_contacts_cache cache_item = {NULL, dwUin, szUid};
+
+ icq_lock l(contactsCacheMutex);
+ // find in list
+ int i = contactsCache.getIndex(&cache_item);
+ if (i != -1)
+ return contactsCache[i]->hContact;
+
+ return NULL;
+}
+
+
+HANDLE CIcqProto::HContactFromUIN(DWORD dwUin, int *Added)
+{
+ if (Added) *Added = 0;
+
+ HANDLE hContact = HandleFromCacheByUid(dwUin, NULL);
+ if (hContact) return hContact;
+
+ hContact = FindFirstContact();
+ while (hContact)
+ {
+ DWORD dwContactUin;
+
+ dwContactUin = getContactUin(hContact);
+ if (dwContactUin == dwUin)
+ {
+ AddToContactsCache(hContact, dwUin, NULL);
+ return hContact;
+ }
+
+ hContact = FindNextContact(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", dwUin);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)m_szModuleName) != 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", dwUin);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ setSettingDword(hContact, UNIQUEIDSETTING, dwUin);
+
+ if (!bIsSyncingCL)
+ {
+ DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
+ setContactHidden(hContact, 1);
+
+ setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+
+ icq_QueueUser(hContact);
+
+ if (icqOnline())
+ icq_sendNewContact(dwUin, NULL);
+ }
+ AddToContactsCache(hContact, dwUin, NULL);
+ *Added = 1;
+
+ return hContact;
+ }
+
+ // not in list, check that uin do not belong to us
+ if (getContactUin(NULL) == dwUin)
+ return NULL;
+
+ return INVALID_HANDLE_VALUE;
+}
+
+
+HANDLE CIcqProto::HContactFromUID(DWORD dwUin, const char *szUid, int *Added)
+{
+ if (dwUin)
+ return HContactFromUIN(dwUin, Added);
+
+ if (Added) *Added = 0;
+
+ if (!m_bAimEnabled) return INVALID_HANDLE_VALUE;
+
+ HANDLE hContact = HandleFromCacheByUid(dwUin, szUid);
+ if (hContact) return hContact;
+
+ hContact = FindFirstContact();
+ while (hContact)
+ {
+ DWORD dwContactUin;
+ uid_str szContactUid;
+
+ if (!getContactUid(hContact, &dwContactUin, &szContactUid))
+ {
+ if (!dwContactUin && !stricmpnull(szContactUid, szUid))
+ {
+ if (strcmpnull(szContactUid, szUid))
+ { // fix case in SN
+ setSettingString(hContact, UNIQUEIDSETTING, szUid);
+ }
+ return hContact;
+ }
+ }
+ hContact = FindNextContact(hContact);
+ }
+
+ //not present: add
+ if (Added)
+ {
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0);
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)m_szModuleName);
+
+ setSettingString(hContact, UNIQUEIDSETTING, szUid);
+
+ if (!bIsSyncingCL)
+ {
+ DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
+ setContactHidden(hContact, 1);
+
+ setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+
+ if (icqOnline())
+ icq_sendNewContact(0, szUid);
+ }
+ AddToContactsCache(hContact, 0, szUid);
+ *Added = 1;
+
+ return hContact;
+ }
+
+ return INVALID_HANDLE_VALUE;
+}
+
+
+HANDLE CIcqProto::HContactFromAuthEvent(HANDLE hEvent)
+{
+ DBEVENTINFO dbei;
+ DWORD body[3];
+
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = sizeof(DWORD) + sizeof(HANDLE);
+ dbei.pBlob = (PBYTE)&body;
+
+ if (CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbei))
+ return INVALID_HANDLE_VALUE;
+
+ if (dbei.eventType != EVENTTYPE_AUTHREQUEST)
+ return INVALID_HANDLE_VALUE;
+
+ if (strcmpnull(dbei.szModule, m_szModuleName))
+ return INVALID_HANDLE_VALUE;
+
+ return *(HANDLE*)&body[1]; // this is bad - needs new auth system
+}
+
+char *NickFromHandle(HANDLE hContact)
+{
+ if (hContact == INVALID_HANDLE_VALUE)
+ return null_strdup(Translate("<invalid>"));
+
+ return null_strdup((char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0));
+}
+
+char *NickFromHandleUtf(HANDLE hContact)
+{
+ if (hContact == INVALID_HANDLE_VALUE)
+ return ICQTranslateUtf(LPGEN("<invalid>"));
+
+ return tchar_to_utf8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
+}
+
+char *strUID(DWORD dwUIN, char *pszUID)
+{
+ if (dwUIN && pszUID)
+ _ltoa(dwUIN, pszUID, 10);
+
+ return pszUID;
+}
+
+
+/* a strlen() that likes NULL */
+int __fastcall strlennull(const char *string)
+{
+ if (string)
+ return (int)strlen(string);
+
+ return 0;
+}
+
+
+/* a wcslen() that likes NULL */
+int __fastcall strlennull(const WCHAR *string)
+{
+ if (string)
+ return (int)wcslen(string);
+
+ return 0;
+}
+
+
+/* a strcmp() that likes NULL */
+int __fastcall strcmpnull(const char *str1, const char *str2)
+{
+ if (str1 && str2)
+ return strcmp(str1, str2);
+
+ if (!str1 && !str2)
+ return 0;
+
+ return 1;
+}
+
+/* a stricmp() that likes NULL */
+int __fastcall stricmpnull(const char *str1, const char *str2)
+{
+ if (str1 && str2)
+ return _stricmp(str1, str2);
+
+ if (!str1 && !str2)
+ return 0;
+
+ return 1;
+}
+
+char* __fastcall strstrnull(const char *str, const char *substr)
+{
+ if (str)
+ return (char*)strstr(str, substr);
+
+ return NULL;
+}
+
+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;
+}
+
+int null_snprintf(WCHAR *buffer, size_t count, const WCHAR *fmt, ...)
+{
+ va_list va;
+ int len;
+
+ ZeroMemory(buffer, count * sizeof(WCHAR));
+ va_start(va, fmt);
+ len = _vsnwprintf(buffer, count, fmt, va);
+ va_end(va);
+ return len;
+}
+
+
+char* __fastcall null_strdup(const char *string)
+{
+ if (string)
+ return _strdup(string);
+
+ return NULL;
+}
+
+
+WCHAR* __fastcall null_strdup(const WCHAR *string)
+{
+ if (string)
+ return wcsdup(string);
+
+ return NULL;
+}
+
+
+char* __fastcall null_strcpy(char *dest, const char *src, size_t maxlen)
+{
+ if (!dest)
+ return NULL;
+
+ if (src && src[0])
+ {
+ strncpy(dest, src, maxlen);
+ dest[maxlen] = '\0';
+ }
+ else
+ dest[0] = '\0';
+
+ return dest;
+}
+
+
+WCHAR* __fastcall null_strcpy(WCHAR *dest, const WCHAR *src, size_t maxlen)
+{
+ if (!dest)
+ return NULL;
+
+ if (src && src[0])
+ {
+ wcsncpy(dest, src, maxlen);
+ dest[maxlen] = '\0';
+ }
+ else
+ dest[0] = '\0';
+
+ return dest;
+}
+
+
+int __fastcall null_strcut(char *string, int maxlen)
+{ // limit the string to max length (null & utf-8 strings ready)
+ int len = (int)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, "&gt;", 4))
+ {
+ *szChar = '>';
+ szChar++;
+ i += 3;
+ }
+ else if (!_strnicmp(string+i, "&lt;", 4))
+ {
+ *szChar = '<';
+ szChar++;
+ i += 3;
+ }
+ else if (!_strnicmp(string+i, "&amp;", 5))
+ {
+ *szChar = '&';
+ szChar++;
+ i += 4;
+ }
+ else if (!_strnicmp(string+i, "&quot;", 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 if (string[i]=='"') l += 6; 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 if (string[i]=='"')
+ {
+ *(DWORD*)szChar = 'ouq&';
+ szChar += 4;
+ *(WORD*)szChar = ';t';
+ szChar += 2;
+ }
+ 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((void**)&tmp);
+
+ return res;
+}
+
+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);
+ }
+ if (!_strnicmp(pszEncoding, "unicode-2-0", 11))
+ { // it is UCS-2 encoded
+ int wLen = strlennull((WCHAR*)string) + 1;
+ WCHAR *szStr = (WCHAR*)_alloca(wLen*2);
+ BYTE *tmp = (BYTE*)string;
+
+ unpackWideString(&tmp, szStr, (WORD)(wLen*2));
+
+ return make_utf8_string(szStr);
+ }
+ 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 CIcqProto::ResetSettingsOnListReload()
+{
+ // Reset a bunch of session specific settings
+ setSettingWord(NULL, DBSETTING_SERVLIST_PRIVACY, 0);
+ setSettingWord(NULL, DBSETTING_SERVLIST_METAINFO, 0);
+ setSettingWord(NULL, DBSETTING_SERVLIST_AVATAR, 0);
+ setSettingWord(NULL, DBSETTING_SERVLIST_PHOTO, 0);
+ setSettingWord(NULL, "SrvRecordCount", 0);
+ deleteSetting(NULL, DBSETTING_SERVLIST_UNHANDLED);
+
+ HANDLE hContact = FindFirstContact();
+
+ while (hContact)
+ {
+ // All these values will be restored during the serv-list receive
+ setSettingWord(hContact, DBSETTING_SERVLIST_ID, 0);
+ setSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0);
+ setSettingWord(hContact, DBSETTING_SERVLIST_PERMIT, 0);
+ setSettingWord(hContact, DBSETTING_SERVLIST_DENY, 0);
+ deleteSetting(hContact, DBSETTING_SERVLIST_IGNORE);
+ setSettingByte(hContact, "Auth", 0);
+ deleteSetting(hContact, DBSETTING_SERVLIST_DATA);
+
+ hContact = FindNextContact(hContact);
+ }
+
+ FlushSrvGroupsCache();
+}
+
+void CIcqProto::ResetSettingsOnConnect()
+{
+ // Reset a bunch of session specific settings
+ setSettingByte(NULL, "SrvVisibility", 0);
+ setSettingDword(NULL, "IdleTS", 0);
+
+ HANDLE hContact = FindFirstContact();
+
+ while (hContact)
+ {
+ setSettingDword(hContact, "LogonTS", 0);
+ setSettingDword(hContact, "IdleTS", 0);
+ setSettingDword(hContact, "TickTS", 0);
+ setSettingByte(hContact, "TemporaryVisible", 0);
+
+ // All these values will be restored during the login
+ if (getContactStatus(hContact) != ID_STATUS_OFFLINE)
+ setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+
+ hContact = FindNextContact(hContact);
+ }
+}
+
+void CIcqProto::ResetSettingsOnLoad()
+{
+ setSettingDword(NULL, "IdleTS", 0);
+ setSettingDword(NULL, "LogonTS", 0);
+
+ HANDLE hContact = FindFirstContact();
+
+ while (hContact)
+ {
+ setSettingDword(hContact, "LogonTS", 0);
+ setSettingDword(hContact, "IdleTS", 0);
+ setSettingDword(hContact, "TickTS", 0);
+ if (getContactStatus(hContact) != ID_STATUS_OFFLINE)
+ {
+ setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
+
+ deleteSetting(hContact, DBSETTING_XSTATUS_ID);
+ deleteSetting(hContact, DBSETTING_XSTATUS_NAME);
+ deleteSetting(hContact, DBSETTING_XSTATUS_MSG);
+ }
+ setSettingByte(hContact, "DCStatus", 0);
+
+ hContact = FindNextContact(hContact);
+ }
+}
+
+int RandRange(int nLow, int nHigh)
+{
+ return nLow + (int)((nHigh-nLow+1)*rand()/(RAND_MAX+1.0));
+}
+
+
+BOOL IsStringUIN(const char *pszString)
+{
+ int i;
+ int nLen = strlennull(pszString);
+
+ if (nLen > 0 && pszString[0] != '0')
+ {
+ for (i=0; i<nLen; i++)
+ if ((pszString[i] < '0') || (pszString[i] > '9'))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+void __cdecl CIcqProto::ProtocolAckThread(icq_ack_args* pArguments)
+{
+ Sleep(150);
+
+ if (pArguments->nAckResult == ACKRESULT_SUCCESS)
+ NetLog_Server("Sent fake message ack");
+ else if (pArguments->nAckResult == ACKRESULT_FAILED)
+ NetLog_Server("Message delivery failed");
+
+ BroadcastAck(pArguments->hContact, pArguments->nAckType, pArguments->nAckResult, pArguments->hSequence, pArguments->pszMessage);
+
+ SAFE_FREE((void**)(char **)&pArguments->pszMessage);
+ SAFE_FREE((void**)&pArguments);
+}
+
+void CIcqProto::SendProtoAck(HANDLE hContact, DWORD dwCookie, int nAckResult, int nAckType, char* pszMessage)
+{
+ icq_ack_args* pArgs = (icq_ack_args*)SAFE_MALLOC(sizeof(icq_ack_args)); // This will be freed in the new thread
+ pArgs->hContact = hContact;
+ pArgs->hSequence = (HANDLE)dwCookie;
+ pArgs->nAckResult = nAckResult;
+ pArgs->nAckType = nAckType;
+ pArgs->pszMessage = (LPARAM)null_strdup(pszMessage);
+
+ ForkThread(( IcqThreadFunc )&CIcqProto::ProtocolAckThread, pArgs );
+}
+
+void CIcqProto::SetCurrentStatus(int nStatus)
+{
+ int nOldStatus = m_iStatus;
+
+ m_iStatus = nStatus;
+ BroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)nOldStatus, nStatus);
+}
+
+
+int CIcqProto::IsMetaInfoChanged(HANDLE hContact)
+{
+ DBVARIANT infoToken = {DBVT_DELETED};
+ int res = 0;
+
+ if (!getSetting(hContact, DBSETTING_METAINFO_TOKEN, &infoToken))
+ { // contact does have info from directory, check if it is not outdated
+ double dInfoTime = 0;
+ double dInfoSaved = 0;
+
+ if ((dInfoTime = getSettingDouble(hContact, DBSETTING_METAINFO_TIME, 0)) > 0)
+ {
+ if ((dInfoSaved = getSettingDouble(hContact, DBSETTING_METAINFO_SAVED, 0)) > 0)
+ {
+ if (dInfoSaved < dInfoTime)
+ res = 2; // directory info outdated
+ }
+ else
+ res = 1; // directory info not saved at all
+ }
+
+ ICQFreeVariant(&infoToken);
+ }
+ else
+ { // it cannot be detected if user info was not changed, so use a generic threshold
+ DBVARIANT infoSaved = {DBVT_DELETED};
+ DWORD dwInfoTime = 0;
+
+ if (!getSetting(hContact, DBSETTING_METAINFO_SAVED, &infoSaved))
+ {
+ if (infoSaved.type == DBVT_BLOB && infoSaved.cpbVal == 8)
+ {
+ double dwTime = *(double*)infoSaved.pbVal;
+
+ dwInfoTime = (dwTime - 25567) * 86400;
+ }
+ else if (infoSaved.type == DBVT_DWORD)
+ dwInfoTime = infoSaved.dVal;
+
+ ICQFreeVariant(&infoSaved);
+
+ if ((time(NULL) - dwInfoTime) > 14*3600*24)
+ {
+ res = 3; // threshold exceeded
+ }
+ }
+ else
+ res = 4; // no timestamp found
+ }
+
+ return res;
+}
+
+
+void __cdecl CIcqProto::SetStatusNoteThread(void *pDelay)
+{
+ if (pDelay)
+ SleepEx((DWORD)pDelay, TRUE);
+
+ cookieMutex->Enter();
+
+ if (icqOnline() && (setStatusNoteText || setStatusMoodData))
+ { // send status note change packets, write status note to database
+ if (setStatusNoteText)
+ { // change status note in directory
+ m_ratesMutex->Enter();
+ if (m_rates)
+ { // rate management
+ WORD wGroup = m_rates->getGroupFromSNAC(ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQUEST);
+
+ while (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(wGroup, RML_LIMIT))
+ { // we are over rate, need to wait before sending
+ int nDelay = m_rates->getDelayToLimitLevel(wGroup, RML_IDLE_10);
+
+ m_ratesMutex->Leave();
+ cookieMutex->Leave();
+#ifdef _DEBUG
+ NetLog_Server("Rates: SetStatusNote delayed %dms", nDelay);
+#endif
+ SleepEx(nDelay, TRUE); // do not keep things locked during sleep
+ cookieMutex->Enter();
+ m_ratesMutex->Enter();
+ if (!m_rates) // we lost connection when we slept, go away
+ break;
+ }
+ }
+ m_ratesMutex->Leave();
+
+ BYTE *pBuffer = NULL;
+ int cbBuffer = 0;
+
+ ppackTLV(&pBuffer, &cbBuffer, 0x226, strlennull(setStatusNoteText), (BYTE*)setStatusNoteText);
+ icq_changeUserDirectoryInfoServ(pBuffer, cbBuffer, DIRECTORYREQUEST_UPDATENOTE);
+
+ SAFE_FREE((void**)&pBuffer);
+ }
+
+ if (setStatusNoteText || setStatusMoodData)
+ { // change status note and mood in session data
+ m_ratesMutex->Enter();
+ if (m_rates)
+ { // rate management
+ WORD wGroup = m_rates->getGroupFromSNAC(ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_STATUS);
+
+ while (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(wGroup, RML_LIMIT))
+ { // we are over rate, need to wait before sending
+ int nDelay = m_rates->getDelayToLimitLevel(wGroup, RML_IDLE_10);
+
+ m_ratesMutex->Leave();
+ cookieMutex->Leave();
+#ifdef _DEBUG
+ NetLog_Server("Rates: SetStatusNote delayed %dms", nDelay);
+#endif
+ SleepEx(nDelay, TRUE); // do not keep things locked during sleep
+ cookieMutex->Enter();
+ m_ratesMutex->Enter();
+ if (!m_rates) // we lost connection when we slept, go away
+ break;
+ }
+ }
+ m_ratesMutex->Leave();
+
+ // check if the session data were not updated already
+ char *szCurrentStatusNote = getSettingStringUtf(NULL, DBSETTING_STATUS_NOTE, NULL);
+ char *szCurrentStatusMood = NULL;
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ if (m_bMoodsEnabled && !getSettingString(NULL, DBSETTING_STATUS_MOOD, &dbv))
+ szCurrentStatusMood = dbv.pszVal;
+
+ if (!setStatusNoteText && szCurrentStatusNote)
+ setStatusNoteText = null_strdup(szCurrentStatusNote);
+ if (m_bMoodsEnabled && !setStatusMoodData && szCurrentStatusMood)
+ setStatusMoodData = null_strdup(szCurrentStatusMood);
+
+ if (strcmpnull(szCurrentStatusNote, setStatusNoteText) || (m_bMoodsEnabled && strcmpnull(szCurrentStatusMood, setStatusMoodData)))
+ {
+ setSettingStringUtf(NULL, DBSETTING_STATUS_NOTE, setStatusNoteText);
+ if (m_bMoodsEnabled)
+ setSettingString(NULL, DBSETTING_STATUS_MOOD, setStatusMoodData);
+
+ WORD wStatusNoteLen = strlennull(setStatusNoteText);
+ WORD wStatusMoodLen = m_bMoodsEnabled ? strlennull(setStatusMoodData) : 0;
+ icq_packet packet;
+ WORD wDataLen = (wStatusNoteLen ? wStatusNoteLen + 4 : 0) + 4 + wStatusMoodLen + 4;
+
+ serverPacketInit(&packet, wDataLen + 14);
+ packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_STATUS);
+ // Change only session data
+ packWord(&packet, 0x1D); // TLV 1D
+ packWord(&packet, wDataLen); // TLV length
+ packWord(&packet, 0x02); // Item Type
+ if (wStatusNoteLen)
+ {
+ packWord(&packet, 0x400 | (WORD)(wStatusNoteLen + 4)); // Flags + Item Length
+ packWord(&packet, wStatusNoteLen); // Text Length
+ packBuffer(&packet, (LPBYTE)setStatusNoteText, wStatusNoteLen);
+ packWord(&packet, 0); // Encoding not specified (utf-8 is default)
+ }
+ else
+ packWord(&packet, 0); // Flags + Item Length
+ packWord(&packet, 0x0E); // Item Type
+ packWord(&packet, wStatusMoodLen); // Flags + Item Length
+ if (wStatusMoodLen)
+ packBuffer(&packet, (LPBYTE)setStatusMoodData, wStatusMoodLen); // Mood
+
+ sendServPacket(&packet);
+ }
+ SAFE_FREE(&szCurrentStatusNote);
+ ICQFreeVariant(&dbv);
+ }
+ }
+ SAFE_FREE(&setStatusNoteText);
+ SAFE_FREE(&setStatusMoodData);
+
+ cookieMutex->Leave();
+}
+
+
+int CIcqProto::SetStatusNote(const char *szStatusNote, DWORD dwDelay, int bForce)
+{
+ int bChanged = FALSE;
+
+ // bForce is intended for login sequence - need to call this earlier than icqOnline()
+ // the process is delayed and icqOnline() is ready when needed inside SetStatusNoteThread()
+ if (!bForce && !icqOnline()) return bChanged;
+
+ // reuse generic critical section (used for cookies list and object variables locks)
+ icq_lock l(cookieMutex);
+
+ if (!setStatusNoteText && (!m_bMoodsEnabled || !setStatusMoodData))
+ { // check if the status note was changed and if yes, create thread to change it
+ char *szCurrentStatusNote = getSettingStringUtf(NULL, DBSETTING_STATUS_NOTE, NULL);
+
+ if (strcmpnull(szCurrentStatusNote, szStatusNote))
+ { // status note was changed
+ // create thread to change status note on existing server connection
+ setStatusNoteText = null_strdup(szStatusNote);
+
+ if (dwDelay)
+ ForkThread(&CIcqProto::SetStatusNoteThread, (void*)dwDelay);
+ else // we cannot afford any delay, so do not run in separate thread
+ SetStatusNoteThread(NULL);
+
+ bChanged = TRUE;
+ }
+ SAFE_FREE(&szCurrentStatusNote);
+ }
+ else
+ { // only alter status note object with new status note, keep the thread waiting for execution
+ SAFE_FREE(&setStatusNoteText);
+ setStatusNoteText = null_strdup(szStatusNote);
+
+ bChanged = TRUE;
+ }
+
+ return bChanged;
+}
+
+
+int CIcqProto::SetStatusMood(const char *szMoodData, DWORD dwDelay)
+{
+ int bChanged = FALSE;
+
+ if (!icqOnline()) return bChanged;
+
+ // reuse generic critical section (used for cookies list and object variables locks)
+ icq_lock l(cookieMutex);
+
+ if (!setStatusNoteText && !setStatusMoodData)
+ { // check if the status mood was changed and if yes, create thread to change it
+ char *szCurrentStatusMood = NULL;
+ DBVARIANT dbv = {DBVT_DELETED};
+
+ if (!getSettingString(NULL, DBSETTING_STATUS_MOOD, &dbv))
+ szCurrentStatusMood = dbv.pszVal;
+
+ if (strcmpnull(szCurrentStatusMood, szMoodData))
+ { // status mood was changed
+ // create thread to change status mood on existing server connection
+ setStatusMoodData = null_strdup(szMoodData);
+ if (dwDelay)
+ ForkThread(&CIcqProto::SetStatusNoteThread, (void*)dwDelay);
+ else // we cannot afford any delay, so do not run in separate thread
+ SetStatusNoteThread(NULL);
+
+ bChanged = TRUE;
+ }
+ ICQFreeVariant(&dbv);
+ }
+ else
+ { // only alter status mood object with new status mood, keep the thread waiting for execution
+ SAFE_FREE(&setStatusMoodData);
+ setStatusMoodData = null_strdup(szMoodData);
+
+ bChanged = TRUE;
+ }
+
+ return bChanged;
+}
+
+
+void CIcqProto::writeDbInfoSettingTLVStringUtf(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
+{
+ oscar_tlv *pTLV = chain->getTLV(wTlv, 1);
+
+ if (pTLV && pTLV->wLen > 0)
+ {
+ char *str = (char*)_alloca(pTLV->wLen + 1);
+
+ memcpy(str, pTLV->pData, pTLV->wLen);
+ str[pTLV->wLen] = '\0';
+ setSettingStringUtf(hContact, szSetting, str);
+ }
+ else
+ deleteSetting(hContact, szSetting);
+}
+
+
+void CIcqProto::writeDbInfoSettingTLVString(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
+{
+ oscar_tlv *pTLV = chain->getTLV(wTlv, 1);
+
+ if (pTLV && pTLV->wLen > 0)
+ {
+ char *str = (char*)_alloca(pTLV->wLen + 1);
+
+ memcpy(str, pTLV->pData, pTLV->wLen);
+ str[pTLV->wLen] = '\0';
+ setSettingString(hContact, szSetting, str);
+ }
+ else
+ deleteSetting(hContact, szSetting);
+}
+
+
+void CIcqProto::writeDbInfoSettingTLVWord(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
+{
+ int num = chain->getNumber(wTlv, 1);
+
+ if (num > 0)
+ setSettingWord(hContact, szSetting, num);
+ else
+ deleteSetting(hContact, szSetting);
+}
+
+
+void CIcqProto::writeDbInfoSettingTLVByte(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
+{
+ int num = chain->getNumber(wTlv, 1);
+
+ if (num > 0)
+ setSettingByte(hContact, szSetting, num);
+ else
+ deleteSetting(hContact, szSetting);
+}
+
+
+void CIcqProto::writeDbInfoSettingTLVDouble(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
+{
+ double num = chain->getDouble(wTlv, 1);
+
+ if (num > 0)
+ setSettingDouble(hContact, szSetting, num);
+ else
+ deleteSetting(hContact, szSetting);
+}
+
+void CIcqProto::writeDbInfoSettingTLVDate(HANDLE hContact, const char* szSettingYear, const char* szSettingMonth, const char* szSettingDay, oscar_tlv_chain* chain, WORD wTlv)
+{
+ double time = chain->getDouble(wTlv, 1);
+
+ if (time > 0)
+ { // date is stored as double with unit equal to a day, incrementing since 1/1/1900 0:00 GMT
+ SYSTEMTIME sTime = {0};
+ if (VariantTimeToSystemTime(time + 2, &sTime))
+ {
+ setSettingWord(hContact, szSettingYear, sTime.wYear);
+ setSettingByte(hContact, szSettingMonth, (BYTE)sTime.wMonth);
+ setSettingByte(hContact, szSettingDay, (BYTE)sTime.wDay);
+ }
+ else
+ {
+ deleteSetting(hContact, szSettingYear);
+ deleteSetting(hContact, szSettingMonth);
+ deleteSetting(hContact, szSettingDay);
+ }
+ }
+ else
+ {
+ deleteSetting(hContact, szSettingYear);
+ deleteSetting(hContact, szSettingMonth);
+ deleteSetting(hContact, szSettingDay);
+ }
+}
+
+
+void CIcqProto::writeDbInfoSettingTLVBlob(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
+{
+ oscar_tlv *pTLV = chain->getTLV(wTlv, 1);
+
+ if (pTLV && pTLV->wLen > 0)
+ setSettingBlob(hContact, szSetting, pTLV->pData, pTLV->wLen);
+ else
+ deleteSetting(hContact, szSetting);
+}
+
+
+BOOL CIcqProto::writeDbInfoSettingString(HANDLE hContact, const char* szSetting, char** buf, WORD* pwLength)
+{
+ WORD wLen;
+
+ if (*pwLength < 2)
+ return FALSE;
+
+ unpackLEWord((LPBYTE*)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 = getSettingWord(hContact, "InfoCodePage", getSettingWord(hContact, "InfoCP", CP_ACP));
+
+ if (wCp != CP_ACP)
+ {
+ char *szUtf = ansi_to_utf8_codepage(*buf, wCp);
+
+ if (szUtf)
+ {
+ setSettingStringUtf(hContact, szSetting, szUtf);
+ SAFE_FREE((void**)&szUtf);
+ }
+ else
+ setSettingString(hContact, szSetting, *buf);
+ }
+ else
+ setSettingString(hContact, szSetting, *buf);
+ }
+ else
+ deleteSetting(hContact, szSetting);
+
+ *buf += wLen;
+ *pwLength -= wLen;
+
+ return TRUE;
+}
+
+BOOL CIcqProto::writeDbInfoSettingWord(HANDLE hContact, const char *szSetting, char **buf, WORD* pwLength)
+{
+ WORD wVal;
+
+
+ if (*pwLength < 2)
+ return FALSE;
+
+ unpackLEWord((LPBYTE*)buf, &wVal);
+ *pwLength -= 2;
+
+ if (wVal != 0)
+ setSettingWord(hContact, szSetting, wVal);
+ else
+ deleteSetting(hContact, szSetting);
+
+ return TRUE;
+}
+
+BOOL CIcqProto::writeDbInfoSettingWordWithTable(HANDLE hContact, const char *szSetting, const FieldNamesItem *table, char **buf, WORD* pwLength)
+{
+ WORD wVal;
+ char sbuf[MAX_PATH];
+ char *text;
+
+ if (*pwLength < 2)
+ return FALSE;
+
+ unpackLEWord((LPBYTE*)buf, &wVal);
+ *pwLength -= 2;
+
+ text = LookupFieldNameUtf(table, wVal, sbuf, MAX_PATH);
+ if (text)
+ setSettingStringUtf(hContact, szSetting, text);
+ else
+ deleteSetting(hContact, szSetting);
+
+ return TRUE;
+}
+
+BOOL CIcqProto::writeDbInfoSettingByte(HANDLE hContact, const char *pszSetting, char **buf, WORD* pwLength)
+{
+ BYTE byVal;
+
+ if (*pwLength < 1)
+ return FALSE;
+
+ unpackByte((LPBYTE*)buf, &byVal);
+ *pwLength -= 1;
+
+ if (byVal != 0)
+ setSettingByte(hContact, pszSetting, byVal);
+ else
+ deleteSetting(hContact, pszSetting);
+
+ return TRUE;
+}
+
+BOOL CIcqProto::writeDbInfoSettingByteWithTable(HANDLE hContact, const char *szSetting, const FieldNamesItem *table, char **buf, WORD* pwLength)
+{
+ BYTE byVal;
+ char sbuf[MAX_PATH];
+ char *text;
+
+ if (*pwLength < 1)
+ return FALSE;
+
+ unpackByte((LPBYTE*)buf, &byVal);
+ *pwLength -= 1;
+
+ text = LookupFieldNameUtf(table, byVal, sbuf, MAX_PATH);
+ if (text)
+ setSettingStringUtf(hContact, szSetting, text);
+ else
+ deleteSetting(hContact, szSetting);
+
+ return TRUE;
+}
+
+char* time2text(time_t time)
+{
+ tm *local = localtime(&time);
+
+ if (local)
+ {
+ char *str = asctime(local);
+ str[24] = '\0'; // remove new line
+ return str;
+ }
+ else
+ return "<invalid>";
+}
+
+
+BOOL CIcqProto::validateStatusMessageRequest(HANDLE hContact, WORD byMessageType)
+{
+ // Privacy control
+ if (getSettingByte(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 (getSettingByte(NULL, "StatusMsgReplyVisible", 0))
+ {
+ WORD wStatus = getContactStatus(hContact);
+ if (wStatus == ID_STATUS_OFFLINE)
+ return FALSE;
+ }
+ }
+
+ // Dont send messages to people you are hiding from
+ if (hContact != INVALID_HANDLE_VALUE &&
+ getSettingWord(hContact, "ApparentMode", 0) == ID_STATUS_OFFLINE)
+ {
+ return FALSE;
+ }
+
+ // Dont respond to request for other statuses than your current one
+ if ((byMessageType == MTYPE_AUTOONLINE && m_iStatus != ID_STATUS_ONLINE) ||
+ (byMessageType == MTYPE_AUTOAWAY && m_iStatus != ID_STATUS_AWAY) ||
+ (byMessageType == MTYPE_AUTOBUSY && m_iStatus != ID_STATUS_OCCUPIED) ||
+ (byMessageType == MTYPE_AUTONA && m_iStatus != ID_STATUS_NA) ||
+ (byMessageType == MTYPE_AUTODND && m_iStatus != ID_STATUS_DND) ||
+ (byMessageType == MTYPE_AUTOFFC && m_iStatus != ID_STATUS_FREECHAT))
+ {
+ return FALSE;
+ }
+
+ if (hContact != INVALID_HANDLE_VALUE && m_iStatus==ID_STATUS_INVISIBLE &&
+ getSettingWord(hContact, "ApparentMode", 0) != ID_STATUS_ONLINE)
+ {
+ if (!getSettingByte(hContact, "TemporaryVisible", 0))
+ { // Allow request to temporary visible contacts
+ return FALSE;
+ }
+ }
+
+ // All OK!
+ return TRUE;
+}
+
+
+void __fastcall SAFE_DELETE(void_struct **p)
+{
+ if (*p)
+ {
+ delete *p;
+ *p = NULL;
+ }
+}
+
+
+void __fastcall SAFE_DELETE(lockable_struct **p)
+{
+ if (*p)
+ {
+ (*p)->_Release();
+ *p = NULL;
+ }
+}
+
+
+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);
+}
+
+
+DWORD ICQWaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds, int bWaitAlways)
+{
+ DWORD dwResult;
+
+ do { // will get WAIT_IO_COMPLETION for QueueUserAPC(), ignore it unless terminating
+ dwResult = WaitForSingleObjectEx(hObject, dwMilliseconds, TRUE);
+ } while (dwResult == WAIT_IO_COMPLETION && (bWaitAlways || !Miranda_Terminated()));
+
+ return dwResult;
+}
+
+
+HANDLE NetLib_OpenConnection(HANDLE hUser, const char* szIdent, NETLIBOPENCONNECTION* nloc)
+{
+ Netlib_Logf(hUser, "%sConnecting to %s:%u", szIdent?szIdent:"", nloc->szHost, nloc->wPort);
+
+ nloc->cbSize = sizeof(NETLIBOPENCONNECTION);
+ nloc->flags |= NLOCF_V2;
+
+ return (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hUser, (LPARAM)nloc);
+}
+
+
+HANDLE CIcqProto::NetLib_BindPort(NETLIBNEWCONNECTIONPROC_V2 pFunc, void* lParam, WORD* pwPort, DWORD* pdwIntIP)
+{
+ NETLIBBIND nlb = {0};
+
+ nlb.cbSize = sizeof(NETLIBBIND);
+ nlb.pfnNewConnectionV2 = pFunc;
+ nlb.pExtra = lParam;
+ SetLastError(ERROR_INVALID_PARAMETER); // this must be here - NetLib does not set any error :((
+
+ HANDLE hBoundPort = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)m_hDirectNetlibUser, (LPARAM)&nlb);
+
+ if (pwPort) *pwPort = nlb.wPort;
+ if (pdwIntIP) *pdwIntIP = nlb.dwInternalIP;
+
+ return hBoundPort;
+}
+
+
+void NetLib_CloseConnection(HANDLE *hConnection, int bServerConn)
+{
+ if (*hConnection)
+ {
+ NetLib_SafeCloseHandle(hConnection);
+
+ if (bServerConn)
+ FreeGatewayIndex(*hConnection);
+ }
+}
+
+
+void NetLib_SafeCloseHandle(HANDLE *hConnection)
+{
+ if (*hConnection)
+ {
+ Netlib_CloseHandle(*hConnection);
+ *hConnection = NULL;
+ }
+}
+
+
+int CIcqProto::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)m_hServerNetlibUser,(LPARAM)szText);
+}
+
+int CIcqProto::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)m_hDirectNetlibUser,(LPARAM)szText);
+}
+
+int CIcqProto::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 = m_hDirectNetlibUser;
+ else
+ hNetlib = m_hServerNetlibUser;
+
+ return CallService(MS_NETLIB_LOG,(WPARAM)hNetlib,(LPARAM)szText);
+}
+
+int CIcqProto::BroadcastAck(HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam)
+{
+ ACKDATA ack={0};
+
+ ack.cbSize = sizeof(ACKDATA);
+ ack.szModule = m_szModuleName;
+ ack.hContact = hContact;
+ ack.type = type;
+ ack.result = result;
+ ack.hProcess = hProcess;
+ ack.lParam = lParam;
+ return CallService(MS_PROTO_BROADCASTACK,0,(LPARAM)&ack);
+}
+
+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((void**)&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((void**)&usrc);
+ }
+ else
+ buf[0] = '\0';
+
+ return buf;
+}
+
+void CIcqProto::ForkThread( IcqThreadFunc pFunc, void* arg )
+{
+ CloseHandle(( HANDLE )mir_forkthreadowner(( pThreadFuncOwner )*( void** )&pFunc, this, arg, NULL ));
+}
+
+HANDLE CIcqProto::ForkThreadEx( IcqThreadFunc pFunc, void* arg, UINT* threadID )
+{
+ return ( HANDLE )mir_forkthreadowner(( pThreadFuncOwner )*( void** )&pFunc, this, arg, threadID );
+}
+
+
+char* CIcqProto::GetUserStoredPassword(char *szBuffer, int cbSize)
+{
+ if (!getSettingStringStatic(NULL, "Password", szBuffer, cbSize))
+ {
+ CallService(MS_DB_CRYPT_DECODESTRING, strlennull(szBuffer) + 1, (LPARAM)szBuffer);
+
+ if (strlennull(szBuffer))
+ return szBuffer;
+ }
+ return NULL;
+}
+
+
+char* CIcqProto::GetUserPassword(BOOL bAlways)
+{
+ if (m_szPassword[0] != '\0' && (m_bRememberPwd || bAlways))
+ return m_szPassword;
+
+ if (GetUserStoredPassword(m_szPassword, sizeof(m_szPassword)))
+ {
+ m_bRememberPwd = TRUE;
+
+ return m_szPassword;
+ }
+
+ return NULL;
+}
+
+
+WORD CIcqProto::GetMyStatusFlags()
+{
+ WORD wFlags = 0;
+
+ // Webaware setting bit flag
+ if (getSettingByte(NULL, "WebAware", 0))
+ wFlags |= STATUS_WEBAWARE;
+
+ // DC setting bit flag
+ switch (getSettingByte(NULL, "DCType", 0))
+ {
+ case 0:
+ break;
+
+ case 1:
+ wFlags |= STATUS_DCCONT;
+ break;
+
+ case 2:
+ wFlags |= STATUS_DCAUTH;
+ break;
+
+ default:
+ wFlags |= STATUS_DCDISABLED;
+ break;
+ }
+ return wFlags;
+}
+
+
+int IsValidRelativePath(const char *filename)
+{
+ if (strstrnull(filename, "..\\") || strstrnull(filename, "../") ||
+ strstrnull(filename, ":\\") || strstrnull(filename, ":/") ||
+ filename[0] == '\\' || filename[0] == '/')
+ return 0; // Contains malicious chars, Failure
+
+ return 1; // Success
+}
+
+
+const char* ExtractFileName(const char *fullname)
+{
+ const char *szFileName;
+
+ // already is only filename
+ if (((szFileName = strrchr(fullname, '\\')) == NULL) && ((szFileName = strrchr(fullname, '/')) == NULL))
+ return fullname;
+
+ return szFileName + 1; // skip backslash
+}
+
+
+char* FileNameToUtf(const TCHAR *filename)
+{
+#if defined( _UNICODE )
+ // reasonable only on NT systems
+ HINSTANCE hKernel = GetModuleHandle(_T("KERNEL32"));
+ DWORD (CALLBACK *RealGetLongPathName)(LPCWSTR, LPWSTR, DWORD);
+
+ *(FARPROC *)&RealGetLongPathName = GetProcAddress(hKernel, "GetLongPathNameW");
+
+ if (RealGetLongPathName)
+ { // the function is available (it is not on old NT systems)
+ WCHAR *usFileName = NULL;
+ int wchars = RealGetLongPathName(filename, usFileName, 0);
+ usFileName = (WCHAR*)_alloca((wchars + 1) * sizeof(WCHAR));
+ RealGetLongPathName(filename, usFileName, wchars);
+
+ return make_utf8_string(usFileName);
+ }
+ return make_utf8_string(filename);
+#else
+ return ansi_to_utf8(filename);
+#endif
+}
+
+
+int FileAccessUtf(const char *path, int mode)
+{
+ int size = strlennull(path) + 2;
+ TCHAR *szPath = (TCHAR*)_alloca(size * sizeof(TCHAR));
+
+ if (utf8_to_tchar_static(path, szPath, size))
+ return _taccess(szPath, mode);
+
+ return -1;
+}
+
+
+int FileStatUtf(const char *path, struct _stati64 *buffer)
+{
+ int size = strlennull(path) + 2;
+ TCHAR *szPath = (TCHAR*)_alloca(size * sizeof(TCHAR));
+
+ if (utf8_to_tchar_static(path, szPath, size))
+ return _tstati64(szPath, buffer);
+
+ return -1;
+}
+
+
+int MakeDirUtf(const char *dir)
+{
+ int wRes = -1;
+ int size = strlennull(dir) + 2;
+ TCHAR *szDir = (TCHAR*)_alloca(size * sizeof(TCHAR));
+
+ if (utf8_to_tchar_static(dir, szDir, size))
+ { // _tmkdir can created only one dir at once
+ wRes = _tmkdir(szDir);
+ // 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
+ char *szLast = (char*)strrchr(dir, '\\');
+ if (!szLast) szLast = (char*)strrchr(dir, '/');
+ if (szLast)
+ {
+ char cOld = *szLast;
+
+ *szLast = '\0';
+ if (!MakeDirUtf(dir))
+ wRes = _tmkdir(szDir);
+
+ *szLast = cOld;
+ }
+ }
+ }
+
+ return wRes;
+}
+
+
+int OpenFileUtf(const char *filename, int oflag, int pmode)
+{
+ int size = strlennull(filename) + 2;
+ TCHAR *szFile = (TCHAR*)_alloca(size * sizeof(TCHAR));
+
+ if (utf8_to_tchar_static(filename, szFile, size))
+ return _topen(szFile, oflag, pmode);
+
+ return -1;
+}
+
+
+WCHAR *GetWindowTextUcs(HWND hWnd)
+{
+ WCHAR *utext;
+
+#if defined( _UNICODE )
+ 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);
+#endif
+ return utext;
+}
+
+
+void SetWindowTextUcs(HWND hWnd, WCHAR *text)
+{
+#if defined( _UNICODE )
+ SetWindowTextW(hWnd, text);
+#else
+ char *tmp = (char*)SAFE_MALLOC(strlennull(text) + 1);
+ WideCharToMultiByte(CP_ACP, 0, text, -1, tmp, strlennull(text)+1, NULL, NULL);
+ SetWindowTextA(hWnd, tmp);
+ SAFE_FREE((void**)&tmp);
+#endif
+}
+
+
+char* GetWindowTextUtf(HWND hWnd)
+{
+ int nLen = GetWindowTextLength(hWnd);
+ TCHAR *szText = (TCHAR*)_alloca((nLen + 2) * sizeof(TCHAR));
+
+ GetWindowText(hWnd, 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)
+{
+ int size = strlennull(szText) + 2;
+ TCHAR *tszText = (TCHAR*)_alloca(size * sizeof(TCHAR));
+
+ if (utf8_to_tchar_static(szText, tszText, size))
+ SetWindowText(hWnd, tszText);
+}
+
+
+void SetDlgItemTextUtf(HWND hwndDlg, int iItem, const char *szText)
+{
+ SetWindowTextUtf(GetDlgItem(hwndDlg, iItem), szText);
+}
+
+
+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 defined( _UNICODE )
+ WCHAR *wItem = make_unicode_string(szItem);
+ item = SendMessage(ctrl, msg, 0, (LPARAM)wItem);
+ SAFE_FREE((void**)&wItem);
+#else
+ int size = strlennull(szItem) + 2;
+ char *aItem = (char*)_alloca(size);
+
+ if (utf8_decode_static(szItem, aItem, size))
+ item = SendMessage(ctrl, msg, 0, (LPARAM)aItem);
+#endif
+
+ 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);
+}
+
+int MessageBoxUtf(HWND hWnd, const char *szText, const char *szCaption, UINT uType)
+{
+ int res;
+ char str[1024];
+ char cap[MAX_PATH];
+
+#if defined( _UNICODE )
+ 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((void**)&caption);
+ SAFE_FREE((void**)&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);
+#endif
+
+ return res;
+}
+
+char* CIcqProto::ConvertMsgToUserSpecificAnsi(HANDLE hContact, const char* szMsg)
+{ // this takes utf-8 encoded message
+ WORD wCP = getSettingWord(hContact, "CodePage", m_wAnsiCodepage);
+ char* szAnsi = NULL;
+
+ if (wCP != CP_ACP) // convert to proper codepage
+ if (!utf8_decode_codepage(szMsg, &szAnsi, wCP))
+ return NULL;
+
+ return szAnsi;
+}
+
+// just broadcast generic send error with dummy cookie and return that cookie
+DWORD CIcqProto::ReportGenericSendError(HANDLE hContact, int nType, const char* szErrorMsg)
+{
+ DWORD dwCookie = GenerateCookie(0);
+ SendProtoAck(hContact, dwCookie, ACKRESULT_FAILED, nType, Translate(szErrorMsg));
+ return dwCookie;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CIcqProto::CreateProtoService(const char* szService, IcqServiceFunc serviceProc)
+{
+ char temp[MAX_PATH*2];
+
+ null_snprintf(temp, sizeof(temp), "%s%s", m_szModuleName, szService);
+ CreateServiceFunctionObj( temp, ( MIRANDASERVICEOBJ )*( void** )&serviceProc, this );
+}
+
+void CIcqProto::CreateProtoServiceParam(const char* szService, IcqServiceFuncParam serviceProc, LPARAM lParam)
+{
+ char temp[MAX_PATH*2];
+
+ null_snprintf(temp, sizeof(temp), "%s%s", m_szModuleName, szService);
+ CreateServiceFunctionObjParam( temp, ( MIRANDASERVICEOBJPARAM )*( void** )&serviceProc, this, lParam );
+}
+
+
+HANDLE CIcqProto::HookProtoEvent(const char* szEvent, IcqEventFunc pFunc)
+{
+ return ::HookEventObj(szEvent, (MIRANDAHOOKOBJ)*(void**)&pFunc, this);
+}
+
+
+HANDLE CIcqProto::CreateProtoEvent(const char* szEvent)
+{
+ char str[MAX_PATH + 32];
+ strcpy(str, m_szModuleName);
+ strcat(str, szEvent);
+ return CreateHookableEvent(str);
+}
diff --git a/protocols/IcqOscarJ/utilities.h b/protocols/IcqOscarJ/utilities.h
new file mode 100644
index 0000000000..b469c9e4f4
--- /dev/null
+++ b/protocols/IcqOscarJ/utilities.h
@@ -0,0 +1,203 @@
+// ---------------------------------------------------------------------------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-2004 Martin berg, Sam Kothari, Robert Rainwater
+// Copyright 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/utilities.h $
+// Revision : $Revision: 14148 $
+// Last change on : $Date: 2012-03-10 00:01:01 +0200 (Сб, 10 мар 2012) $
+// Last change by : $Author: george.hazan $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __UTILITIES_H
+#define __UTILITIES_H
+
+
+struct icq_ack_args
+{
+ HANDLE hContact;
+ int nAckType;
+ int nAckResult;
+ HANDLE hSequence;
+ LPARAM pszMessage;
+};
+
+struct icq_contacts_cache
+{
+ HANDLE hContact;
+ DWORD dwUin;
+ const char *szUid;
+};
+
+
+/*---------* Functions *---------------*/
+
+void MoveDlgItem(HWND hwndDlg, int iItem, int left, int top, int width, int height);
+void EnableDlgItem(HWND hwndDlg, UINT control, int state);
+void ShowDlgItem(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);
+
+int AwayMsgTypeToStatus(int nMsgType);
+
+void SetGatewayIndex(HANDLE hConn, DWORD dwIndex);
+DWORD GetGatewayIndex(HANDLE hConn);
+void FreeGatewayIndex(HANDLE hConn);
+
+char *NickFromHandle(HANDLE hContact);
+char *NickFromHandleUtf(HANDLE hContact);
+char *strUID(DWORD dwUIN, char *pszUID);
+
+int __fastcall strlennull(const char *string);
+int __fastcall strcmpnull(const char *str1, const char *str2);
+int __fastcall stricmpnull(const char *str1, const char *str2);
+char* __fastcall strstrnull(const char *str, const char *substr);
+int null_snprintf(char *buffer, size_t count, const char *fmt, ...);
+char* __fastcall null_strdup(const char *string);
+char* __fastcall null_strcpy(char *dest, const char *src, size_t maxlen);
+int __fastcall null_strcut(char *string, int maxlen);
+
+int __fastcall strlennull(const WCHAR *string);
+int null_snprintf(WCHAR *buffer, size_t count, const WCHAR *fmt, ...);
+WCHAR* __fastcall null_strdup(const WCHAR *string);
+WCHAR* __fastcall null_strcpy(WCHAR *dest, const WCHAR *src, 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);
+
+int RandRange(int nLow, int nHigh);
+
+BOOL IsStringUIN(const char *pszString);
+
+char* time2text(time_t time);
+
+BOOL validateStatusMessageRequest(HANDLE hContact, WORD byMessageType);
+
+void __fastcall SAFE_FREE(void** p);
+void* __fastcall SAFE_MALLOC(size_t size);
+void* __fastcall SAFE_REALLOC(void* p, size_t size);
+
+__inline static void SAFE_FREE(char** str) { SAFE_FREE((void**)str); }
+__inline static void SAFE_FREE(WCHAR** str) { SAFE_FREE((void**)str); }
+
+struct void_struct
+{
+ __inline void* operator new(size_t size) { return SAFE_MALLOC(size); }
+ __inline void operator delete(void *p) { SAFE_FREE(&p); }
+
+ virtual ~void_struct() {};
+};
+
+struct lockable_struct: public void_struct
+{
+private:
+ int nLockCount;
+public:
+ lockable_struct(): void_struct() { _Lock(); };
+ virtual ~lockable_struct() {};
+
+ void _Lock() { nLockCount++; };
+ void _Release() { nLockCount--; if (!nLockCount) delete this; };
+
+ int getLockCount() { return nLockCount; };
+};
+
+void __fastcall SAFE_DELETE(void_struct **p);
+void __fastcall SAFE_DELETE(lockable_struct **p);
+
+DWORD ICQWaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds, int bWaitAlways = FALSE);
+
+
+struct icq_critical_section: public lockable_struct
+{
+private:
+ HANDLE hMutex;
+
+public:
+ icq_critical_section() { hMutex = CreateMutex(NULL, FALSE, NULL); }
+ ~icq_critical_section() { CloseHandle(hMutex); }
+
+ void Enter(void) { ICQWaitForSingleObject(hMutex, INFINITE, TRUE); }
+ void Leave(void) { ReleaseMutex(hMutex); }
+};
+
+__inline static void SAFE_DELETE(icq_critical_section **p) { SAFE_DELETE((lockable_struct**)p); }
+
+struct icq_lock
+{
+private:
+ icq_critical_section *pMutex;
+public:
+ icq_lock(icq_critical_section *mutex) { pMutex = mutex; pMutex->Enter(); };
+ ~icq_lock() { pMutex->Leave(); pMutex = NULL; };
+};
+
+
+HANDLE NetLib_OpenConnection(HANDLE hUser, const char* szIdent, NETLIBOPENCONNECTION* nloc);
+void NetLib_CloseConnection(HANDLE *hConnection, int bServerConn);
+void NetLib_SafeCloseHandle(HANDLE *hConnection);
+
+char* __fastcall ICQTranslateUtf(const char *src);
+char* __fastcall ICQTranslateUtfStatic(const char *src, char *buf, size_t bufsize);
+
+WORD GetMyStatusFlags();
+
+/* Unicode FS utility functions */
+
+int IsValidRelativePath(const char *filename);
+const char* ExtractFileName(const char *fullname);
+char* FileNameToUtf(const TCHAR *filename);
+
+int FileAccessUtf(const char *path, int mode);
+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);
+
+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);
+
+#endif /* __UTILITIES_H */
diff --git a/protocols/IcqOscarJ/version.h b/protocols/IcqOscarJ/version.h
new file mode 100644
index 0000000000..826d9fdefb
--- /dev/null
+++ b/protocols/IcqOscarJ/version.h
@@ -0,0 +1,5 @@
+#include "../../include/m_version.h"
+
+#define __FILEVERSION_STRING MIRANDA_VERSION_FILEVERSION
+#define __VERSION_STRING MIRANDA_VERSION_STRING
+#define __VERSION_DWORD MIRANDA_VERSION_DWORD