summaryrefslogtreecommitdiff
path: root/irc_mod
diff options
context:
space:
mode:
authorwatcherhd <watcherhd@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb>2011-04-21 14:14:52 +0000
committerwatcherhd <watcherhd@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb>2011-04-21 14:14:52 +0000
commitcb4a46e7fbe62d788e66ed6121c717a2d22a4d7c (patch)
tree30df260fdc5a1b5a7049c2f8cac8b7ef17513d6d /irc_mod
parent19b6f534d2e784a1e120bf52c4aa07004798f473 (diff)
svn.miranda.im is moving to a new home!
git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb
Diffstat (limited to 'irc_mod')
-rw-r--r--irc_mod/AggressiveOptimize.h166
-rw-r--r--irc_mod/Docs/IRC_Readme.txt47
-rw-r--r--irc_mod/Docs/IRC_Translate.txt335
-rw-r--r--irc_mod/Docs/IRC_license.txt340
-rw-r--r--irc_mod/Docs/rfc1459.txt3643
-rw-r--r--irc_mod/Docs/rfc2810.txt563
-rw-r--r--irc_mod/Docs/rfc2811.txt1067
-rw-r--r--irc_mod/Docs/rfc2812.txt3531
-rw-r--r--irc_mod/Docs/rfc2813.txt1459
-rw-r--r--irc_mod/IRC.rc887
-rw-r--r--irc_mod/IRC.sln30
-rw-r--r--irc_mod/IRC.vcproj1154
-rw-r--r--irc_mod/IRC7.sln55
-rw-r--r--irc_mod/IRC7.vcproj974
-rw-r--r--irc_mod/Icons/Angeli-Ka/Add.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Apply.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Avatar.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Cancel.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Dcc.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Delete.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Edit.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Ignore.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Join.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Leave.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/List.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Logo.bakbin0 -> 19046 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Logo.icobin0 -> 17014 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Main.icobin0 -> 1150 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Manager.icobin0 -> 1150 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Protopic.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Quest2.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Question.icobin0 -> 1150 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Quick connect.icobin0 -> 1150 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Reading.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Server.icobin0 -> 1150 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Show chanel.icobin0 -> 1150 bytes
-rw-r--r--irc_mod/Icons/Angeli-Ka/Warning.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/add.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/avatar.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/avatar_old.icobin0 -> 894 bytes
-rw-r--r--irc_mod/Icons/block.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/dcc.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/delete.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/error.icobin0 -> 894 bytes
-rw-r--r--irc_mod/Icons/fatal.icobin0 -> 894 bytes
-rw-r--r--irc_mod/Icons/go.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/help.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/information.icobin0 -> 894 bytes
-rw-r--r--irc_mod/Icons/irc.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/list.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/manager.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/part.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/quick.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/rename.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/server.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/show.icobin0 -> 2550 bytes
-rw-r--r--irc_mod/Icons/warning.icobin0 -> 1150 bytes
-rw-r--r--irc_mod/Icons/world.icobin0 -> 9662 bytes
-rw-r--r--irc_mod/Icons/world_old.icobin0 -> 3774 bytes
-rw-r--r--irc_mod/Icons/xstatus01.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus02.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus03.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus04.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus05.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus06.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus07.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus08.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus09.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus10.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus11.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus12.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus13.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus14.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus15.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus16.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus17.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus18.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus19.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus20.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus21.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus22.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus23.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus24.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus25.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus26.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus27.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus28.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus29.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus30.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus31.icobin0 -> 2038 bytes
-rw-r--r--irc_mod/Icons/xstatus32.icobin0 -> 1150 bytes
-rw-r--r--irc_mod/avatar.cpp273
-rw-r--r--irc_mod/avatar.h32
-rw-r--r--irc_mod/clist.cpp305
-rw-r--r--irc_mod/commandmonitor.cpp3460
-rw-r--r--irc_mod/commandmonitor.h105
-rw-r--r--irc_mod/i18n.cpp461
-rw-r--r--irc_mod/i18n.h55
-rw-r--r--irc_mod/iconlib.cpp118
-rw-r--r--irc_mod/iconlib.h37
-rw-r--r--irc_mod/icons_pack/ICONS.rc78
-rw-r--r--irc_mod/icons_pack/ICONS.sln17
-rw-r--r--irc_mod/icons_pack/ICONS.vcproj349
-rw-r--r--irc_mod/icons_pack/ICONS7.sln29
-rw-r--r--irc_mod/icons_pack/ICONS7.vcproj185
-rw-r--r--irc_mod/input.cpp953
-rw-r--r--irc_mod/irc.h510
-rw-r--r--irc_mod/irclib.cpp1865
-rw-r--r--irc_mod/irclib.h426
-rw-r--r--irc_mod/m_cluiframes.h255
-rw-r--r--irc_mod/m_icolib.h75
-rw-r--r--irc_mod/m_ircscript.h129
-rw-r--r--irc_mod/m_nudge.h5
-rw-r--r--irc_mod/m_popupw.h56
-rw-r--r--irc_mod/m_smileyadd.h78
-rw-r--r--irc_mod/m_uninstaller.h700
-rw-r--r--irc_mod/m_updater.h122
-rw-r--r--irc_mod/m_xstatus.h39
-rw-r--r--irc_mod/main.cpp248
-rw-r--r--irc_mod/md5.cpp352
-rw-r--r--irc_mod/md5.h82
-rw-r--r--irc_mod/options.cpp2576
-rw-r--r--irc_mod/output.cpp209
-rw-r--r--irc_mod/popups.cpp274
-rw-r--r--irc_mod/popups.h11
-rw-r--r--irc_mod/resource.h295
-rw-r--r--irc_mod/scripting.cpp295
-rw-r--r--irc_mod/services.cpp2515
-rw-r--r--irc_mod/tools.cpp925
-rw-r--r--irc_mod/utils.cpp548
-rw-r--r--irc_mod/utils.h67
-rw-r--r--irc_mod/windows.cpp1800
-rw-r--r--irc_mod/xstatus.cpp913
-rw-r--r--irc_mod/xstatus.h65
134 files changed, 36143 insertions, 0 deletions
diff --git a/irc_mod/AggressiveOptimize.h b/irc_mod/AggressiveOptimize.h
new file mode 100644
index 0000000..b579b0c
--- /dev/null
+++ b/irc_mod/AggressiveOptimize.h
@@ -0,0 +1,166 @@
+
+//////////////////////////////
+// Version 1.40
+// October 22nd, 2002 - .NET (VC7, _MSC_VER=1300) support!
+// Version 1.30
+// Nov 24th, 2000
+// Version 1.20
+// Jun 9th, 2000
+// Version 1.10
+// Jan 23rd, 2000
+// Version 1.00
+// May 20th, 1999
+// Todd C. Wilson, Fresh Ground Software
+// (todd@nopcode.com)
+// This header file will kick in settings for Visual C++ 5 and 6 that will (usually)
+// result in smaller exe's.
+// The "trick" is to tell the compiler to not pad out the function calls; this is done
+// by not using the /O1 or /O2 option - if you do, you implicitly use /Gy, which pads
+// out each and every function call. In one single 500k dll, I managed to cut out 120k
+// by this alone!
+// The other two "tricks" are telling the Linker to merge all data-type segments together
+// in the exe file. The relocation, read-only (constants) data, and code section (.text)
+// sections can almost always be merged. Each section merged can save 4k in exe space,
+// since each section is padded out to 4k chunks. This is very noticeable with smaller
+// exes, since you could have only 700 bytes of data, 300 bytes of code, 94 bytes of
+// strings - padded out, this could be 12k of runtime, for 1094 bytes of stuff! For larger
+// programs, this is less overall, but can save at least 4k.
+// Note that if you're using MFC static or some other 3rd party libs, you may get poor
+// results with merging the readonly (.rdata) section - the exe may grow larger.
+// To use this feature, define _MERGE_DATA_ in your project or before this header is used.
+// With Visual C++ 5, the program uses a file alignment of 512 bytes, which results
+// in a small exe. Under VC6, the program instead uses 4k, which is the same as the
+// section size. The reason (from what I understand) is that 4k is the chunk size of
+// the virtual memory manager, and that WinAlign (an end-user tuning tool for Win98)
+// will re-align the programs on this boundary. The problem with this is that all of
+// Microsoft's system exes and dlls are *NOT* tuned like this, and using 4k causes serious
+// exe bloat. This is very noticeable for smaller programs.
+// The "trick" for this is to use the undocumented FILEALIGN linker parm to change the
+// padding from 4k to 1/2k, which results in a much smaller exe - anywhere from 20%-75%
+// depending on the size. Note that this is the same as using /OPT:NOWIN98, which *is*
+// a previously documented switch, but was left out of the docs for some reason in VC6 and
+// all of the current MSDN's - see KB:Q235956 for more information.
+// Microsoft does say that using the 4k alignment will "speed up process loading",
+// but I've been unable to notice a difference, even on my P180, with a very large (4meg) exe.
+// Please note, however, that this will probably not change the size of the COMPRESSED
+// file (either in a .zip file or in an install archive), since this 4k is all zeroes and
+// gets compressed away.
+// Also, the /ALIGN:4096 switch will "magically" do the same thing, even though this is the
+// default setting for this switch. Apparently this sets the same values as the above two
+// switches do. We do not use this in this header, since it smacks of a bug and not a feature.
+// Thanks to Michael Geary <Mike@Geary.com> for some additional tips!
+//
+// Notes about using this header in .NET
+// First off, VC7 does not allow a lot of the linker command options in pragma's. There is no
+// honest or good reason why Microsoft decided to make this change, it just doesn't.
+// So that is why there are a lot of <1300 #if's in the header.
+// If you want to take full advantage of the VC7 linker options, you will need to do it on a
+// PER PROJECT BASIS; you can no longer use a global header file like this to make it better.
+// Items I strongly suggest putting in all your VC7 project linker options command line settings:
+// /ignore:4078 /RELEASE
+// Compiler options:
+// /GL (Whole Program Optimization)
+// If you're making an .EXE and not a .DLL, consider adding in:
+// /GA (Optimize for Windows Application)
+// Some items to consider using in your VC7 projects (not VC6):
+// Link-time Code Generation - whole code optimization. Put this in your exe/dll project link settings.
+// /LTCG:NOSTATUS
+// The classic no-padding and no-bloat compiler C/C++ switch:
+// /opt:nowin98
+//
+// (C++ command line options: /GL /opt:nowin98 and /GA for .exe files)
+// (Link command line options: /ignore:4078 /RELEASE /LTCG:NOSTATUS)
+//
+// Now, notes on using these options in VC7 vs VC6.
+// VC6 consistently, for me, produces smaller code from C++ the exact same sources,
+// with or without this header. On average, VC6 produces 5% smaller binaries compared
+// to VC7 compiling the exact same project, *without* this header. With this header, VC6
+// will make a 13k file, while VC7 will make a 64k one. VC7 is just bloaty, pure and
+// simple - all that managed/unmanaged C++ runtimes, and the CLR stuff must be getting
+// in the way of code generation. However, template support is better, so there.
+// Both VC6 and VC7 show the same end kind of end result savings - larger binary output
+// will shave about 2% off, where as smaller projects (support DLL's, cpl's,
+// activex controls, ATL libs, etc) get the best result, since the padding is usually
+// more than the actual usable code. But again, VC7 does not compile down as small as VC6.
+//
+// The argument can be made that doing this is a waste of time, since the "zero bytes"
+// will be compressed out in a zip file or install archive. Not really - it doesn't matter
+// if the data is a string of zeroes or ones or 85858585 - it will still take room (20 bytes
+// in a zip file, 29 bytes if only *4* of them 4k bytes are not the same) and time to
+// compress that data and decompress it. Also, 20k of zeros is NOT 20k on disk - it's the
+// size of the cluster slop- for Fat32 systems, 20k can be 32k, NTFS could make it 24k if you're
+// just 1 byte over (round up). Most end users do not have the dual P4 Xeon systems with
+// two gigs of RDram and a Raid 0+1 of Western Digital 120meg Special Editions that all
+// worthy developers have (all six of us), so they will need any space and LOADING TIME
+// savings they will need; taking an extra 32k or more out of your end user's 64megs of
+// ram on Windows 98 is Not a Good Thing.
+//
+// Now, as a ADDED BONUS at NO EXTRA COST TO YOU! Under VC6, using the /merge:.text=.data
+// pragma will cause the output file to be un-disassembleable! (is that a word?) At least,
+// with the normal tools - WinDisam, DumpBin, and the like will not work. Try it - use the
+// header, compile release, and then use DUMPBIN /DISASM filename.exe - no code!
+// Thanks to Gëzim Pani <gpani@siu.edu> for discovering this gem - for a full writeup on
+// this issue and the ramifactions of it, visit www.nopcode.com for the Aggressive Optimize
+// article.
+
+#ifndef _AGGRESSIVEOPTIMIZE_H_
+#define _AGGRESSIVEOPTIMIZE_H_
+
+#pragma warning(disable:4711)
+
+#ifdef NDEBUG
+// /Og (global optimizations), /Os (favor small code), /Oy (no frame pointers)
+#pragma optimize("gsy",on)
+
+#if (_MSC_VER<1300)
+ #pragma comment(linker,"/RELEASE")
+#endif
+
+// Note that merging the .rdata section will result in LARGER exe's if you using
+// MFC (esp. static link). If this is desirable, define _MERGE_RDATA_ in your project.
+//#ifdef _MERGE_RDATA_
+//#pragma comment(linker,"/merge:.rdata=.data")
+//#endif // _MERGE_RDATA_
+
+//#pragma comment(linker,"/merge:.text=.data")
+//#if (_MSC_VER<1300)
+ // In VC7, this causes problems with the relocation and data tables, so best to not merge them
+// #pragma comment(linker,"/merge:.reloc=.data")
+//#endif
+
+// Merging sections with different attributes causes a linker warning, so
+// turn off the warning. From Michael Geary. Undocumented, as usual!
+#if (_MSC_VER<1300)
+ // In VC7, you will need to put this in your project settings
+ #pragma comment(linker,"/ignore:4078")
+#endif
+
+// With Visual C++ 5, you already get the 512-byte alignment, so you will only need
+// it for VC6, and maybe later.
+#if _MSC_VER >= 1000
+
+// Option #1: use /filealign
+// Totally undocumented! And if you set it lower than 512 bytes, the program crashes.
+// Either leave at 0x200 or 0x1000
+//#pragma comment(linker,"/FILEALIGN:0x200")
+
+// Option #2: use /opt:nowin98
+// See KB:Q235956 or the READMEVC.htm in your VC directory for info on this one.
+// This is our currently preferred option, since it is fully documented and unlikely
+// to break in service packs and updates.
+#if (_MSC_VER<1300)
+ // In VC7, you will need to put this in your project settings
+ #pragma comment(linker,"/opt:nowin98")
+#else
+
+// Option #3: use /align:4096
+// A side effect of using the default align value is that it turns on the above switch.
+// Does nothing under Vc7 that /opt:nowin98 doesn't already give you
+// #pragma comment(linker,"/ALIGN:512")
+#endif
+
+#endif // _MSC_VER >= 1000
+
+#endif // NDEBUG
+
+#endif // _AGGRESSIVEOPTIMIZE_H_
diff --git a/irc_mod/Docs/IRC_Readme.txt b/irc_mod/Docs/IRC_Readme.txt
new file mode 100644
index 0000000..679365e
--- /dev/null
+++ b/irc_mod/Docs/IRC_Readme.txt
@@ -0,0 +1,47 @@
+----------------------------oOo----------------------------
+ IRC Protocol Plugin v 0.6.3.5
+
+ Implementation of IRC RFC-1459, RFC-2812 for Miranda IM
+
+ Released 2003-03-03, last updated 2005-08-19
+-----------------------------------------------------------
+
+
+Important information
+-----------
+
+#1 Please visit the online resource for the IRC plugin at:
+ http://members.chello.se/matrix/ for more information on usage etc.
+
+#2 To install OpenSSL if you need it, go here:
+ http://members.chello.se/matrix/openssl/Win32OpenSSL-v0.9.7f.exe
+
+#3 This protocol is dependant on the Chat plugin, get it here:
+ http://www.miranda-im.org/download/details.php?action=viewfile&id=1309
+
+
+
+Changelog
+---------
+
+Please visit:
+http://www.miranda-im.org/download/details.php?action=viewlog&id=550
+
+
+
+Copyright and license
+---------------------
+
+Copyright (C) 2003-2005 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \ No newline at end of file
diff --git a/irc_mod/Docs/IRC_Translate.txt b/irc_mod/Docs/IRC_Translate.txt
new file mode 100644
index 0000000..b810326
--- /dev/null
+++ b/irc_mod/Docs/IRC_Translate.txt
@@ -0,0 +1,335 @@
+;-----------------------------------------------------------
+;
+; IRC Protocol Plugin v 0.7.0.9
+;
+; Implementation of IRC RFC-1459, RFC-2812 for Miranda IM
+;
+;
+; TRANSLATION TEMPLATE
+;
+;-----------------------------------------------------------
+
+
+; clist.cpp
+;[CTCP chat request from %s]
+
+; commandmonitor.cpp
+;[CTCP ERROR: Malformed CTCP command received from %s!%s@%s. Possible attempt to take control of your irc client registered]
+;[CTCP FINGER requested by %s]
+;[CTCP VERSION requested by %s]
+;[CTCP SOURCE requested by %s]
+;[CTCP USERINFO requested by %s]
+;[CTCP PING requested by %s]
+;[CTCP TIME requested by %s]
+;[DCC: Chat request from %s denied]
+;[DCC: File transfer request from %s denied]
+;[DCC: Reverse file transfer request from %s denied [No local IP]]
+;[DCC ERROR: Malformed CTCP request from %s [%s]]
+;[DCC: File transfer resume request from %s denied]
+;[CTCP %s requested by %s]
+;[CTCP PING reply from %s: %u sec(s)]
+;[CTCP %s reply from %s: %s]
+;[Downloading list (%u%%) - %u channels]
+;[Downloading list - %u channels]
+;[%s sets mode %s]
+;[Done: %u channels]
+;[(probably truncated by server)]
+;[User information]
+;[Change nickname]
+;[IRC error]
+;[Unknown]
+;[Please enter the hostmask (nick!user@host) \nNOTE! Contacts on your contact list are never ignored]
+;[Ignore]
+;[Please enter the reason]
+;[Ban'n Kick]
+;[Jerk]
+;[Offline]
+;[*Disconnected*]
+;[The usage of /AWAY in your perform buffer is restricted\n as IRC sends this command automatically.]
+
+; input.cpp
+;[Ignore system is enabled]
+;[Ignore system is disabled]
+;[%s on %s is now ignored (+%s)]
+;[%s is not ignored now]
+;[%s was not ignored]
+;[Outgoing commands are shown]
+;[Outgoing commands are not shown]
+;[The buddy check function is enabled]
+;[The buddy check function is disabled]
+;[The time interval for the buddy check function is now at default setting]
+;[The time interval for the buddy check function is now %u seconds]
+;[Channel Manager]
+;[This command is not recommended on a network of this size!\r\nIt will probably cause high CPU usage and/or high bandwidth\r\nusage for around %u to %u minute(s).\r\n\r\nDo you want to continue?]
+;[IRC warning]
+;[Aborted]
+;[CTCP %s request sent to %s]
+;[DCC ERROR: Unable to automatically resolve external IP]
+;[DCC CHAT request sent to %s]
+;[DCC ERROR: Unable to bind port]
+;[Input command]
+;[Please enter the reply]
+
+; main.cpp
+;[The IRC protocol could not be loaded as it is dependant on Miranda IM version %s or later.\n\nDo you want to download an update from the Miranda website now?]
+;[Information]
+
+; options.cpp
+;[Please complete all fields]
+;[<Resolved IP: ]
+;[<Automatic>]
+;[<Local IP: ]
+;[Click to set commands that will be performed for this event]
+;[Click to delete the commands for this event]
+;[Add a new network]
+;[Edit this network]
+;[Delete this network]
+;[Off]
+;[Auto]
+;[On]
+;[N/A]
+;[Do you want to delete\r\n%s]
+;[Delete server]
+;[Edit server]
+;[Network]
+;[%s DCC 'n CTCP]
+;[%s Advanced]
+;[Main]
+;[Add]
+;[Apply]
+;[Edit]
+;[Cancel]
+;[Channel list]
+;[Server window]
+;[Show channel]
+;[Join channel]
+;[Leave Channel]
+;[Incoming DCC Chat]
+
+; output.cpp
+;[WallOps from %s: ]
+;[%s is away]
+;[%s invites you to %s]
+;[These are online: ]
+;[CTCP %s reply sent to %s]
+;[CTCP %s reply sent to %s: %s]
+;[Notice to %s: ]
+
+; services.cpp
+;[&Quick connect]
+;[&Join a channel]
+;[&Change your nickname]
+;[Show the &list of available channels]
+;[&Show the server window]
+;[&Leave the channel]
+;[&User details]
+;[&Ignore]
+;[DCC ERROR: No valid files specified]
+;[DCC reversed file transfer request sent to %s [%s]]
+;[DCC file transfer request sent to %s [%s]]
+;[DCC ERROR: Unable to bind local port]
+;[%s (%s) is requesting a client-to-client chat connection.]
+;[Join channel]
+;[Please enter a channel to join]
+;[Quick connect]
+;[Please select IRC network and enter the password if needed]
+;[Change nick name]
+;[Please enter a unique nickname]
+;[Kick]
+;[Channel &settings]
+;[Show the server &window]
+;[&WhoIs info]
+;[&Control]
+;[&Op]
+;[&Deop]
+;[&Voice]
+;[D&evoice]
+;[&Kick]
+;[Ki&ck (reason)]
+;[&Ban]
+;[Ban'&n kick]
+;[Ban'n kick (&reason)]
+;[&On]
+;[O&ff]
+;[&Direct Connection]
+;[Request &Chat]
+;[Send &File]
+;[&Add User]
+;[&Leave channel]
+;[&Show channel]
+;[&Show server]
+;[&WhoIs info]
+;[&Message]
+;[Di&sconnect]
+;[&Unignore user]
+;[Ignore user]
+;[Nickname]
+;[Connecting to]
+;[This protocol is dependent on another plugin named \'Chat\'\nPlease download it from the Miranda IM website!]
+;[Please choose an IRC-network to go online. This network will be the default.]
+;[Default network]
+;[Connection can not be established! You have not completed all necessary fields (Nickname, User ID and Name).]
+;[The protocol is not online]
+;[The dcc chat connection is not active]
+;[%s server connection]
+;[%s client-to-client connections]
+;[IRC Error]
+;[The IRC protocol depends on another plugin called \'Chat\'\n\nDo you want to download it from the Miranda IM web site now?]
+;[Reconnecting to]
+;[&Add to ignore list]
+;[Give &Op]
+;[Take O&p]
+;[Give &Halfop]
+;[Take H&alfop]
+;[Give &Voice]
+;[Take V&oice]
+
+; windows.cpp
+;[Please wait...]
+;[Channel]
+;[Mode]
+;[Topic]
+;[The \"Nick\" field must contain at least four characters, and also match the default nickname (incl. wildcards) for this contact.\n\nThe \"Nick\" field is not case-sensitive but \"User\" and \"Address\" are.\r\n\r\nThe default nickname for this contact is]
+;[Settings could not be saved!\n\nThe \"Nick\" field must contain at least four characters including wildcards,\n and it must also match the default nickname for this contact.]
+;[Add ban/invite/exception]
+;[Edit selected ban/invite/exception]
+;[Delete selected ban/invite/exception]
+;[Set this topic for the channel]
+;[Set these modes for the channel]
+;[Remove ban?]
+;[Remove invite?]
+;[Remove exception?]
+;[Edit ban]
+;[Edit invite?]
+;[Edit exception?]
+;[Please enter the hostmask (nick!user@host)]
+;[Add ban]
+;[Add invite]
+;[Add exception]
+;[You have not applied all changes!\n\nApply before exiting?]
+
+; IRC.rc
+;[&Add]
+;[&Edit]
+;[&Del]
+;[Enable]
+;[only while connecting]
+;[Update online statuses for users]
+;[Update statuses in channel nicklist]
+;[Don't check if more than (users):]
+;[Keep connection alive]
+;[Force visible (-i)]
+;[Rejoin channel if kicked]
+;[Disable tray balloon on error]
+;[Rejoin channels on reconnect]
+;[Internet address]
+;[Use server window]
+;[Show server window on startup]
+;[Automatically join on invite]
+;[Show addresses]
+;[&Set]
+;[SSL]
+;[Bans]
+;[Invites]
+;[Excepts]
+;[(*) blank to set this mask for all networks]
+;[Perform on event:]
+;[Only Ops set topic]
+;[No external messages]
+;[Invite only]
+;[Moderated]
+;[Key:]
+;[User limit:]
+;[Private]
+;[Secret]
+;[Hidden]
+;[Enable incoming requests]
+;[Normal]
+;[Send-ahead]
+;[Attempt reverse DCC (good if firewalled)]
+;[none]
+;[everyone on the contact list]
+;[everyone]
+;[everyone not on the contact list]
+;[Disconnect DCC chats when disconnecting from server]
+;[Manually set external IP:]
+;[Get IP address from server]
+;[&Refresh]
+;[&Close]
+;[&OK]
+;[&Join]
+;[C&onnect]
+;[&Deny]
+;[Ping]
+;[Version]
+;[Time]
+;[Userinfo]
+;[&Query]
+;[&Cancel]
+;[&Save]
+;[&Clear all]
+;[&Accept]
+;[Port range]
+;[Nick]
+;[User ID (Ident)]
+;[Full name (e-mail)]
+;[Password]
+;[Server name]
+;[Alternative nick]
+;[System]
+;[Port]
+;[Wait (s)]
+;[Retry count]
+;[Fear the monkeys!!!]
+;[Check every (s):]
+;[Name]
+;[Address]
+;[Channels]
+;[Auth]
+;[Server]
+;[User]
+;[Away Info]
+;[Other]
+;[The server returned the following information. Please note that this information might be misleading and/or falsified]
+;[Quit message]
+;[Use the options to set modes for this channel. You are usually required to be op. or higher to modify.]
+;[for choosing the IRC protocol for Miranda IM. Please enter your nickname and real name]
+;[Thank You...]
+;[Full name]
+;[Send mode:]
+;[Packet size (b):]
+;[Ident]
+;[User info - Required]
+;[Reconnect]
+;[CTCP information]
+;[Perform]
+;[Alias]
+;[Hostmask]
+;[User modes]
+;[Channel modes]
+;[Client-to-Client File Transfers]
+;[Auto-accept from:]
+;[Ignore chat requests from...]
+;[Client-to-Client Protocol]
+;[Client-to-Client Chats]
+;[Question]
+;[Add server]
+;[Channels on server]
+;[Miranda IRC]
+;[CTCP Chat Request]
+;[&Whois]
+;[Ki&ck (Reason)]
+;[Ban'&n Kick]
+;[Ban'n Kick (&Reason)]
+;[&Add contact]
+;[&Copy]
+;[Co&py All]
+;[Select &All]
+;[Leave channel]
+;[Clear log]
+;[Show/Hide server]
+;[Channel manager]
+;[Open in &new window]
+;[&Open in existing window]
+;[&Copy link]
+;[Scripting support]
diff --git a/irc_mod/Docs/IRC_license.txt b/irc_mod/Docs/IRC_license.txt
new file mode 100644
index 0000000..7f11610
--- /dev/null
+++ b/irc_mod/Docs/IRC_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/irc_mod/Docs/rfc1459.txt b/irc_mod/Docs/rfc1459.txt
new file mode 100644
index 0000000..09fbf34
--- /dev/null
+++ b/irc_mod/Docs/rfc1459.txt
@@ -0,0 +1,3643 @@
+
+
+
+
+
+
+Network Working Group J. Oikarinen
+Request for Comments: 1459 D. Reed
+ May 1993
+
+
+ Internet Relay Chat Protocol
+
+Status of This Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. Discussion and suggestions for improvement are requested.
+ Please refer to the current edition of the "IAB Official Protocol
+ Standards" for the standardization state and status of this protocol.
+ Distribution of this memo is unlimited.
+
+Abstract
+
+ The IRC protocol was developed over the last 4 years since it was
+ first implemented as a means for users on a BBS to chat amongst
+ themselves. Now it supports a world-wide network of servers and
+ clients, and is stringing to cope with growth. Over the past 2 years,
+ the average number of users connected to the main IRC network has
+ grown by a factor of 10.
+
+ The IRC protocol is a text-based protocol, with the simplest client
+ being any socket program capable of connecting to the server.
+
+Table of Contents
+
+ 1. INTRODUCTION ............................................... 4
+ 1.1 Servers ................................................ 4
+ 1.2 Clients ................................................ 5
+ 1.2.1 Operators .......................................... 5
+ 1.3 Channels ................................................ 5
+ 1.3.1 Channel Operators .................................... 6
+ 2. THE IRC SPECIFICATION ....................................... 7
+ 2.1 Overview ................................................ 7
+ 2.2 Character codes ......................................... 7
+ 2.3 Messages ................................................ 7
+ 2.3.1 Message format in 'pseudo' BNF .................... 8
+ 2.4 Numeric replies ......................................... 10
+ 3. IRC Concepts ................................................ 10
+ 3.1 One-to-one communication ................................ 10
+ 3.2 One-to-many ............................................. 11
+ 3.2.1 To a list .......................................... 11
+ 3.2.2 To a group (channel) ............................... 11
+ 3.2.3 To a host/server mask .............................. 12
+ 3.3 One to all .............................................. 12
+
+
+
+Oikarinen & Reed [Page 1]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ 3.3.1 Client to Client ................................... 12
+ 3.3.2 Clients to Server .................................. 12
+ 3.3.3 Server to Server ................................... 12
+ 4. MESSAGE DETAILS ............................................. 13
+ 4.1 Connection Registration ................................. 13
+ 4.1.1 Password message ................................... 14
+ 4.1.2 Nickname message ................................... 14
+ 4.1.3 User message ....................................... 15
+ 4.1.4 Server message ..................................... 16
+ 4.1.5 Operator message ................................... 17
+ 4.1.6 Quit message ....................................... 17
+ 4.1.7 Server Quit message ................................ 18
+ 4.2 Channel operations ...................................... 19
+ 4.2.1 Join message ....................................... 19
+ 4.2.2 Part message ....................................... 20
+ 4.2.3 Mode message ....................................... 21
+ 4.2.3.1 Channel modes ................................. 21
+ 4.2.3.2 User modes .................................... 22
+ 4.2.4 Topic message ...................................... 23
+ 4.2.5 Names message ...................................... 24
+ 4.2.6 List message ....................................... 24
+ 4.2.7 Invite message ..................................... 25
+ 4.2.8 Kick message ....................................... 25
+ 4.3 Server queries and commands ............................. 26
+ 4.3.1 Version message .................................... 26
+ 4.3.2 Stats message ...................................... 27
+ 4.3.3 Links message ...................................... 28
+ 4.3.4 Time message ....................................... 29
+ 4.3.5 Connect message .................................... 29
+ 4.3.6 Trace message ...................................... 30
+ 4.3.7 Admin message ...................................... 31
+ 4.3.8 Info message ....................................... 31
+ 4.4 Sending messages ........................................ 32
+ 4.4.1 Private messages ................................... 32
+ 4.4.2 Notice messages .................................... 33
+ 4.5 User-based queries ...................................... 33
+ 4.5.1 Who query .......................................... 33
+ 4.5.2 Whois query ........................................ 34
+ 4.5.3 Whowas message ..................................... 35
+ 4.6 Miscellaneous messages .................................. 35
+ 4.6.1 Kill message ....................................... 36
+ 4.6.2 Ping message ....................................... 37
+ 4.6.3 Pong message ....................................... 37
+ 4.6.4 Error message ...................................... 38
+ 5. OPTIONAL MESSAGES ........................................... 38
+ 5.1 Away message ............................................ 38
+ 5.2 Rehash command .......................................... 39
+ 5.3 Restart command ......................................... 39
+
+
+
+Oikarinen & Reed [Page 2]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ 5.4 Summon message .......................................... 40
+ 5.5 Users message ........................................... 40
+ 5.6 Operwall command ........................................ 41
+ 5.7 Userhost message ........................................ 42
+ 5.8 Ison message ............................................ 42
+ 6. REPLIES ..................................................... 43
+ 6.1 Error Replies ........................................... 43
+ 6.2 Command responses ....................................... 48
+ 6.3 Reserved numerics ....................................... 56
+ 7. Client and server authentication ............................ 56
+ 8. Current Implementations Details ............................. 56
+ 8.1 Network protocol: TCP ................................... 57
+ 8.1.1 Support of Unix sockets ............................ 57
+ 8.2 Command Parsing ......................................... 57
+ 8.3 Message delivery ........................................ 57
+ 8.4 Connection 'Liveness' ................................... 58
+ 8.5 Establishing a server-client connection ................. 58
+ 8.6 Establishing a server-server connection ................. 58
+ 8.6.1 State information exchange when connecting ......... 59
+ 8.7 Terminating server-client connections ................... 59
+ 8.8 Terminating server-server connections ................... 59
+ 8.9 Tracking nickname changes ............................... 60
+ 8.10 Flood control of clients ............................... 60
+ 8.11 Non-blocking lookups ................................... 61
+ 8.11.1 Hostname (DNS) lookups ............................ 61
+ 8.11.2 Username (Ident) lookups .......................... 61
+ 8.12 Configuration file ..................................... 61
+ 8.12.1 Allowing clients to connect ....................... 62
+ 8.12.2 Operators ......................................... 62
+ 8.12.3 Allowing servers to connect ....................... 62
+ 8.12.4 Administrivia ..................................... 63
+ 8.13 Channel membership ..................................... 63
+ 9. Current problems ............................................ 63
+ 9.1 Scalability ............................................. 63
+ 9.2 Labels .................................................. 63
+ 9.2.1 Nicknames .......................................... 63
+ 9.2.2 Channels ........................................... 64
+ 9.2.3 Servers ............................................ 64
+ 9.3 Algorithms .............................................. 64
+ 10. Support and availability ................................... 64
+ 11. Security Considerations .................................... 65
+ 12. Authors' Addresses ......................................... 65
+
+
+
+
+
+
+
+
+
+Oikarinen & Reed [Page 3]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+1. INTRODUCTION
+
+ The IRC (Internet Relay Chat) protocol has been designed over a
+ number of years for use with text based conferencing. This document
+ describes the current IRC protocol.
+
+ The IRC protocol has been developed on systems using the TCP/IP
+ network protocol, although there is no requirement that this remain
+ the only sphere in which it operates.
+
+ IRC itself is a teleconferencing system, which (through the use of
+ the client-server model) is well-suited to running on many machines
+ in a distributed fashion. A typical setup involves a single process
+ (the server) forming a central point for clients (or other servers)
+ to connect to, performing the required message delivery/multiplexing
+ and other functions.
+
+1.1 Servers
+
+ The server forms the backbone of IRC, providing a point to which
+ clients may connect to to talk to each other, and a point for other
+ servers to connect to, forming an IRC network. The only network
+ configuration allowed for IRC servers is that of a spanning tree [see
+ Fig. 1] where each server acts as a central node for the rest of the
+ net it sees.
+
+
+ [ Server 15 ] [ Server 13 ] [ Server 14]
+ / \ /
+ / \ /
+ [ Server 11 ] ------ [ Server 1 ] [ Server 12]
+ / \ /
+ / \ /
+ [ Server 2 ] [ Server 3 ]
+ / \ \
+ / \ \
+ [ Server 4 ] [ Server 5 ] [ Server 6 ]
+ / | \ /
+ / | \ /
+ / | \____ /
+ / | \ /
+ [ Server 7 ] [ Server 8 ] [ Server 9 ] [ Server 10 ]
+
+ :
+ [ etc. ]
+ :
+
+ [ Fig. 1. Format of IRC server network ]
+
+
+
+Oikarinen & Reed [Page 4]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+1.2 Clients
+
+ A client is anything connecting to a server that is not another
+ server. Each client is distinguished from other clients by a unique
+ nickname having a maximum length of nine (9) characters. See the
+ protocol grammar rules for what may and may not be used in a
+ nickname. In addition to the nickname, all servers must have the
+ following information about all clients: the real name of the host
+ that the client is running on, the username of the client on that
+ host, and the server to which the client is connected.
+
+1.2.1 Operators
+
+ To allow a reasonable amount of order to be kept within the IRC
+ network, a special class of clients (operators) is allowed to perform
+ general maintenance functions on the network. Although the powers
+ granted to an operator can be considered as 'dangerous', they are
+ nonetheless required. Operators should be able to perform basic
+ network tasks such as disconnecting and reconnecting servers as
+ needed to prevent long-term use of bad network routing. In
+ recognition of this need, the protocol discussed herein provides for
+ operators only to be able to perform such functions. See sections
+ 4.1.7 (SQUIT) and 4.3.5 (CONNECT).
+
+ A more controversial power of operators is the ability to remove a
+ user from the connected network by 'force', i.e. operators are able
+ to close the connection between any client and server. The
+ justification for this is delicate since its abuse is both
+ destructive and annoying. For further details on this type of
+ action, see section 4.6.1 (KILL).
+
+1.3 Channels
+
+ A channel is a named group of one or more clients which will all
+ receive messages addressed to that channel. The channel is created
+ implicitly when the first client joins it, and the channel ceases to
+ exist when the last client leaves it. While channel exists, any
+ client can reference the channel using the name of the channel.
+
+ Channels names are strings (beginning with a '&' or '#' character) of
+ length up to 200 characters. Apart from the the requirement that the
+ first character being either '&' or '#'; the only restriction on a
+ channel name is that it may not contain any spaces (' '), a control G
+ (^G or ASCII 7), or a comma (',' which is used as a list item
+ separator by the protocol).
+
+ There are two types of channels allowed by this protocol. One is a
+ distributed channel which is known to all the servers that are
+
+
+
+Oikarinen & Reed [Page 5]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ connected to the network. These channels are marked by the first
+ character being a only clients on the server where it exists may join
+ it. These are distinguished by a leading '&' character. On top of
+ these two types, there are the various channel modes available to
+ alter the characteristics of individual channels. See section 4.2.3
+ (MODE command) for more details on this.
+
+ To create a new channel or become part of an existing channel, a user
+ is required to JOIN the channel. If the channel doesn't exist prior
+ to joining, the channel is created and the creating user becomes a
+ channel operator. If the channel already exists, whether or not your
+ request to JOIN that channel is honoured depends on the current modes
+ of the channel. For example, if the channel is invite-only, (+i),
+ then you may only join if invited. As part of the protocol, a user
+ may be a part of several channels at once, but a limit of ten (10)
+ channels is recommended as being ample for both experienced and
+ novice users. See section 8.13 for more information on this.
+
+ If the IRC network becomes disjoint because of a split between two
+ servers, the channel on each side is only composed of those clients
+ which are connected to servers on the respective sides of the split,
+ possibly ceasing to exist on one side of the split. When the split
+ is healed, the connecting servers announce to each other who they
+ think is in each channel and the mode of that channel. If the
+ channel exists on both sides, the JOINs and MODEs are interpreted in
+ an inclusive manner so that both sides of the new connection will
+ agree about which clients are in the channel and what modes the
+ channel has.
+
+1.3.1 Channel Operators
+
+ The channel operator (also referred to as a "chop" or "chanop") on a
+ given channel is considered to 'own' that channel. In recognition of
+ this status, channel operators are endowed with certain powers which
+ enable them to keep control and some sort of sanity in their channel.
+ As an owner of a channel, a channel operator is not required to have
+ reasons for their actions, although if their actions are generally
+ antisocial or otherwise abusive, it might be reasonable to ask an IRC
+ operator to intervene, or for the usersjust leave and go elsewhere
+ and form their own channel.
+
+ The commands which may only be used by channel operators are:
+
+ KICK - Eject a client from the channel
+ MODE - Change the channel's mode
+ INVITE - Invite a client to an invite-only channel (mode +i)
+ TOPIC - Change the channel topic in a mode +t channel
+
+
+
+
+Oikarinen & Reed [Page 6]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ A channel operator is identified by the '@' symbol next to their
+ nickname whenever it is associated with a channel (ie replies to the
+ NAMES, WHO and WHOIS commands).
+
+2. The IRC Specification
+
+2.1 Overview
+
+ The protocol as described herein is for use both with server to
+ server and client to server connections. There are, however, more
+ restrictions on client connections (which are considered to be
+ untrustworthy) than on server connections.
+
+2.2 Character codes
+
+ No specific character set is specified. The protocol is based on a a
+ set of codes which are composed of eight (8) bits, making up an
+ octet. Each message may be composed of any number of these octets;
+ however, some octet values are used for control codes which act as
+ message delimiters.
+
+ Regardless of being an 8-bit protocol, the delimiters and keywords
+ are such that protocol is mostly usable from USASCII terminal and a
+ telnet connection.
+
+ Because of IRC's scandanavian origin, the characters {}| are
+ considered to be the lower case equivalents of the characters []\,
+ respectively. This is a critical issue when determining the
+ equivalence of two nicknames.
+
+2.3 Messages
+
+ Servers and clients send eachother messages which may or may not
+ generate a reply. If the message contains a valid command, as
+ described in later sections, the client should expect a reply as
+ specified but it is not advised to wait forever for the reply; client
+ to server and server to server communication is essentially
+ asynchronous in nature.
+
+ Each IRC message may consist of up to three main parts: the prefix
+ (optional), the command, and the command parameters (of which there
+ may be up to 15). The prefix, command, and all parameters are
+ separated by one (or more) ASCII space character(s) (0x20).
+
+ The presence of a prefix is indicated with a single leading ASCII
+ colon character (':', 0x3b), which must be the first character of the
+ message itself. There must be no gap (whitespace) between the colon
+ and the prefix. The prefix is used by servers to indicate the true
+
+
+
+Oikarinen & Reed [Page 7]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ origin of the message. If the prefix is missing from the message, it
+ is assumed to have originated from the connection from which it was
+ received. Clients should not use prefix when sending a message from
+ themselves; if they use a prefix, the only valid prefix is the
+ registered nickname associated with the client. If the source
+ identified by the prefix cannot be found from the server's internal
+ database, or if the source is registered from a different link than
+ from which the message arrived, the server must ignore the message
+ silently.
+
+ The command must either be a valid IRC command or a three (3) digit
+ number represented in ASCII text.
+
+ IRC messages are always lines of characters terminated with a CR-LF
+ (Carriage Return - Line Feed) pair, and these messages shall not
+ exceed 512 characters in length, counting all characters including
+ the trailing CR-LF. Thus, there are 510 characters maximum allowed
+ for the command and its parameters. There is no provision for
+ continuation message lines. See section 7 for more details about
+ current implementations.
+
+2.3.1 Message format in 'pseudo' BNF
+
+ The protocol messages must be extracted from the contiguous stream of
+ octets. The current solution is to designate two characters, CR and
+ LF, as message separators. Empty messages are silently ignored,
+ which permits use of the sequence CR-LF between messages
+ without extra problems.
+
+ The extracted message is parsed into the components <prefix>,
+ <command> and list of parameters matched either by <middle> or
+ <trailing> components.
+
+ The BNF representation for this is:
+
+
+<message> ::= [':' <prefix> <SPACE> ] <command> <params> <crlf>
+<prefix> ::= <servername> | <nick> [ '!' <user> ] [ '@' <host> ]
+<command> ::= <letter> { <letter> } | <number> <number> <number>
+<SPACE> ::= ' ' { ' ' }
+<params> ::= <SPACE> [ ':' <trailing> | <middle> <params> ]
+
+<middle> ::= <Any *non-empty* sequence of octets not including SPACE
+ or NUL or CR or LF, the first of which may not be ':'>
+<trailing> ::= <Any, possibly *empty*, sequence of octets not including
+ NUL or CR or LF>
+
+<crlf> ::= CR LF
+
+
+
+Oikarinen & Reed [Page 8]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+NOTES:
+
+ 1) <SPACE> is consists only of SPACE character(s) (0x20).
+ Specially notice that TABULATION, and all other control
+ characters are considered NON-WHITE-SPACE.
+
+ 2) After extracting the parameter list, all parameters are equal,
+ whether matched by <middle> or <trailing>. <Trailing> is just
+ a syntactic trick to allow SPACE within parameter.
+
+ 3) The fact that CR and LF cannot appear in parameter strings is
+ just artifact of the message framing. This might change later.
+
+ 4) The NUL character is not special in message framing, and
+ basically could end up inside a parameter, but as it would
+ cause extra complexities in normal C string handling. Therefore
+ NUL is not allowed within messages.
+
+ 5) The last parameter may be an empty string.
+
+ 6) Use of the extended prefix (['!' <user> ] ['@' <host> ]) must
+ not be used in server to server communications and is only
+ intended for server to client messages in order to provide
+ clients with more useful information about who a message is
+ from without the need for additional queries.
+
+ Most protocol messages specify additional semantics and syntax for
+ the extracted parameter strings dictated by their position in the
+ list. For example, many server commands will assume that the first
+ parameter after the command is the list of targets, which can be
+ described with:
+
+ <target> ::= <to> [ "," <target> ]
+ <to> ::= <channel> | <user> '@' <servername> | <nick> | <mask>
+ <channel> ::= ('#' | '&') <chstring>
+ <servername> ::= <host>
+ <host> ::= see RFC 952 [DNS:4] for details on allowed hostnames
+ <nick> ::= <letter> { <letter> | <number> | <special> }
+ <mask> ::= ('#' | '$') <chstring>
+ <chstring> ::= <any 8bit code except SPACE, BELL, NUL, CR, LF and
+ comma (',')>
+
+ Other parameter syntaxes are:
+
+ <user> ::= <nonwhite> { <nonwhite> }
+ <letter> ::= 'a' ... 'z' | 'A' ... 'Z'
+ <number> ::= '0' ... '9'
+ <special> ::= '-' | '[' | ']' | '\' | '`' | '^' | '{' | '}'
+
+
+
+Oikarinen & Reed [Page 9]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ <nonwhite> ::= <any 8bit code except SPACE (0x20), NUL (0x0), CR
+ (0xd), and LF (0xa)>
+
+2.4 Numeric replies
+
+ Most of the messages sent to the server generate a reply of some
+ sort. The most common reply is the numeric reply, used for both
+ errors and normal replies. The numeric reply must be sent as one
+ message consisting of the sender prefix, the three digit numeric, and
+ the target of the reply. A numeric reply is not allowed to originate
+ from a client; any such messages received by a server are silently
+ dropped. In all other respects, a numeric reply is just like a normal
+ message, except that the keyword is made up of 3 numeric digits
+ rather than a string of letters. A list of different replies is
+ supplied in section 6.
+
+3. IRC Concepts.
+
+ This section is devoted to describing the actual concepts behind the
+ organization of the IRC protocol and how the current
+ implementations deliver different classes of messages.
+
+
+
+ 1--\
+ A D---4
+ 2--/ \ /
+ B----C
+ / \
+ 3 E
+
+ Servers: A, B, C, D, E Clients: 1, 2, 3, 4
+
+ [ Fig. 2. Sample small IRC network ]
+
+3.1 One-to-one communication
+
+ Communication on a one-to-one basis is usually only performed by
+ clients, since most server-server traffic is not a result of servers
+ talking only to each other. To provide a secure means for clients to
+ talk to each other, it is required that all servers be able to send a
+ message in exactly one direction along the spanning tree in order to
+ reach any client. The path of a message being delivered is the
+ shortest path between any two points on the spanning tree.
+
+ The following examples all refer to Figure 2 above.
+
+
+
+
+
+Oikarinen & Reed [Page 10]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+Example 1:
+ A message between clients 1 and 2 is only seen by server A, which
+ sends it straight to client 2.
+
+Example 2:
+ A message between clients 1 and 3 is seen by servers A & B, and
+ client 3. No other clients or servers are allowed see the message.
+
+Example 3:
+ A message between clients 2 and 4 is seen by servers A, B, C & D
+ and client 4 only.
+
+3.2 One-to-many
+
+ The main goal of IRC is to provide a forum which allows easy and
+ efficient conferencing (one to many conversations). IRC offers
+ several means to achieve this, each serving its own purpose.
+
+3.2.1 To a list
+
+ The least efficient style of one-to-many conversation is through
+ clients talking to a 'list' of users. How this is done is almost
+ self explanatory: the client gives a list of destinations to which
+ the message is to be delivered and the server breaks it up and
+ dispatches a separate copy of the message to each given destination.
+ This isn't as efficient as using a group since the destination list
+ is broken up and the dispatch sent without checking to make sure
+ duplicates aren't sent down each path.
+
+3.2.2 To a group (channel)
+
+ In IRC the channel has a role equivalent to that of the multicast
+ group; their existence is dynamic (coming and going as people join
+ and leave channels) and the actual conversation carried out on a
+ channel is only sent to servers which are supporting users on a given
+ channel. If there are multiple users on a server in the same
+ channel, the message text is sent only once to that server and then
+ sent to each client on the channel. This action is then repeated for
+ each client-server combination until the original message has fanned
+ out and reached each member of the channel.
+
+ The following examples all refer to Figure 2.
+
+Example 4:
+ Any channel with 1 client in it. Messages to the channel go to the
+ server and then nowhere else.
+
+
+
+
+
+Oikarinen & Reed [Page 11]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+Example 5:
+ 2 clients in a channel. All messages traverse a path as if they
+ were private messages between the two clients outside a channel.
+
+Example 6:
+ Clients 1, 2 and 3 in a channel. All messages to the channel are
+ sent to all clients and only those servers which must be traversed
+ by the message if it were a private message to a single client. If
+ client 1 sends a message, it goes back to client 2 and then via
+ server B to client 3.
+
+3.2.3 To a host/server mask
+
+ To provide IRC operators with some mechanism to send messages to a
+ large body of related users, host and server mask messages are
+ provided. These messages are sent to users whose host or server
+ information match that of the mask. The messages are only sent to
+ locations where users are, in a fashion similar to that of channels.
+
+3.3 One-to-all
+
+ The one-to-all type of message is better described as a broadcast
+ message, sent to all clients or servers or both. On a large network
+ of users and servers, a single message can result in a lot of traffic
+ being sent over the network in an effort to reach all of the desired
+ destinations.
+
+ For some messages, there is no option but to broadcast it to all
+ servers so that the state information held by each server is
+ reasonably consistent between servers.
+
+3.3.1 Client-to-Client
+
+ There is no class of message which, from a single message, results in
+ a message being sent to every other client.
+
+3.3.2 Client-to-Server
+
+ Most of the commands which result in a change of state information
+ (such as channel membership, channel mode, user status, etc) must be
+ sent to all servers by default, and this distribution may not be
+ changed by the client.
+
+3.3.3 Server-to-Server.
+
+ While most messages between servers are distributed to all 'other'
+ servers, this is only required for any message that affects either a
+ user, channel or server. Since these are the basic items found in
+
+
+
+Oikarinen & Reed [Page 12]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ IRC, nearly all messages originating from a server are broadcast to
+ all other connected servers.
+
+4. Message details
+
+ On the following pages are descriptions of each message recognized by
+ the IRC server and client. All commands described in this section
+ must be implemented by any server for this protocol.
+
+ Where the reply ERR_NOSUCHSERVER is listed, it means that the
+ <server> parameter could not be found. The server must not send any
+ other replies after this for that command.
+
+ The server to which a client is connected is required to parse the
+ complete message, returning any appropriate errors. If the server
+ encounters a fatal error while parsing a message, an error must be
+ sent back to the client and the parsing terminated. A fatal error
+ may be considered to be incorrect command, a destination which is
+ otherwise unknown to the server (server, nick or channel names fit
+ this category), not enough parameters or incorrect privileges.
+
+ If a full set of parameters is presented, then each must be checked
+ for validity and appropriate responses sent back to the client. In
+ the case of messages which use parameter lists using the comma as an
+ item separator, a reply must be sent for each item.
+
+ In the examples below, some messages appear using the full format:
+
+ :Name COMMAND parameter list
+
+ Such examples represent a message from "Name" in transit between
+ servers, where it is essential to include the name of the original
+ sender of the message so remote servers may send back a reply along
+ the correct path.
+
+4.1 Connection Registration
+
+ The commands described here are used to register a connection with an
+ IRC server as either a user or a server as well as correctly
+ disconnect.
+
+ A "PASS" command is not required for either client or server
+ connection to be registered, but it must precede the server message
+ or the latter of the NICK/USER combination. It is strongly
+ recommended that all server connections have a password in order to
+ give some level of security to the actual connections. The
+ recommended order for a client to register is as follows:
+
+
+
+
+Oikarinen & Reed [Page 13]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ 1. Pass message
+ 2. Nick message
+ 3. User message
+
+4.1.1 Password message
+
+
+ Command: PASS
+ Parameters: <password>
+
+ The PASS command is used to set a 'connection password'. The
+ password can and must be set before any attempt to register the
+ connection is made. Currently this requires that clients send a PASS
+ command before sending the NICK/USER combination and servers *must*
+ send a PASS command before any SERVER command. The password supplied
+ must match the one contained in the C/N lines (for servers) or I
+ lines (for clients). It is possible to send multiple PASS commands
+ before registering but only the last one sent is used for
+ verification and it may not be changed once registered. Numeric
+ Replies:
+
+ ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
+
+ Example:
+
+ PASS secretpasswordhere
+
+4.1.2 Nick message
+
+ Command: NICK
+ Parameters: <nickname> [ <hopcount> ]
+
+ NICK message is used to give user a nickname or change the previous
+ one. The <hopcount> parameter is only used by servers to indicate
+ how far away a nick is from its home server. A local connection has
+ a hopcount of 0. If supplied by a client, it must be ignored.
+
+ If a NICK message arrives at a server which already knows about an
+ identical nickname for another client, a nickname collision occurs.
+ As a result of a nickname collision, all instances of the nickname
+ are removed from the server's database, and a KILL command is issued
+ to remove the nickname from all other server's database. If the NICK
+ message causing the collision was a nickname change, then the
+ original (old) nick must be removed as well.
+
+ If the server recieves an identical NICK from a client which is
+ directly connected, it may issue an ERR_NICKCOLLISION to the local
+ client, drop the NICK command, and not generate any kills.
+
+
+
+Oikarinen & Reed [Page 14]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ Numeric Replies:
+
+ ERR_NONICKNAMEGIVEN ERR_ERRONEUSNICKNAME
+ ERR_NICKNAMEINUSE ERR_NICKCOLLISION
+
+ Example:
+
+ NICK Wiz ; Introducing new nick "Wiz".
+
+ :WiZ NICK Kilroy ; WiZ changed his nickname to Kilroy.
+
+4.1.3 User message
+
+ Command: USER
+ Parameters: <username> <hostname> <servername> <realname>
+
+ The USER message is used at the beginning of connection to specify
+ the username, hostname, servername and realname of s new user. It is
+ also used in communication between servers to indicate new user
+ arriving on IRC, since only after both USER and NICK have been
+ received from a client does a user become registered.
+
+ Between servers USER must to be prefixed with client's NICKname.
+ Note that hostname and servername are normally ignored by the IRC
+ server when the USER command comes from a directly connected client
+ (for security reasons), but they are used in server to server
+ communication. This means that a NICK must always be sent to a
+ remote server when a new user is being introduced to the rest of the
+ network before the accompanying USER is sent.
+
+ It must be noted that realname parameter must be the last parameter,
+ because it may contain space characters and must be prefixed with a
+ colon (':') to make sure this is recognised as such.
+
+ Since it is easy for a client to lie about its username by relying
+ solely on the USER message, the use of an "Identity Server" is
+ recommended. If the host which a user connects from has such a
+ server enabled the username is set to that as in the reply from the
+ "Identity Server".
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
+
+ Examples:
+
+
+ USER guest tolmoon tolsun :Ronnie Reagan
+
+
+
+Oikarinen & Reed [Page 15]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ ; User registering themselves with a
+ username of "guest" and real name
+ "Ronnie Reagan".
+
+
+ :testnick USER guest tolmoon tolsun :Ronnie Reagan
+ ; message between servers with the
+ nickname for which the USER command
+ belongs to
+
+4.1.4 Server message
+
+ Command: SERVER
+ Parameters: <servername> <hopcount> <info>
+
+ The server message is used to tell a server that the other end of a
+ new connection is a server. This message is also used to pass server
+ data over whole net. When a new server is connected to net,
+ information about it be broadcast to the whole network. <hopcount>
+ is used to give all servers some internal information on how far away
+ all servers are. With a full server list, it would be possible to
+ construct a map of the entire server tree, but hostmasks prevent this
+ from being done.
+
+ The SERVER message must only be accepted from either (a) a connection
+ which is yet to be registered and is attempting to register as a
+ server, or (b) an existing connection to another server, in which
+ case the SERVER message is introducing a new server behind that
+ server.
+
+ Most errors that occur with the receipt of a SERVER command result in
+ the connection being terminated by the destination host (target
+ SERVER). Error replies are usually sent using the "ERROR" command
+ rather than the numeric since the ERROR command has several useful
+ properties which make it useful here.
+
+ If a SERVER message is parsed and attempts to introduce a server
+ which is already known to the receiving server, the connection from
+ which that message must be closed (following the correct procedures),
+ since a duplicate route to a server has formed and the acyclic nature
+ of the IRC tree broken.
+
+ Numeric Replies:
+
+ ERR_ALREADYREGISTRED
+
+ Example:
+
+
+
+
+Oikarinen & Reed [Page 16]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+SERVER test.oulu.fi 1 :[tolsun.oulu.fi] Experimental server
+ ; New server test.oulu.fi introducing
+ itself and attempting to register. The
+ name in []'s is the hostname for the
+ host running test.oulu.fi.
+
+
+:tolsun.oulu.fi SERVER csd.bu.edu 5 :BU Central Server
+ ; Server tolsun.oulu.fi is our uplink
+ for csd.bu.edu which is 5 hops away.
+
+4.1.5 Oper
+
+ Command: OPER
+ Parameters: <user> <password>
+
+ OPER message is used by a normal user to obtain operator privileges.
+ The combination of <user> and <password> are required to gain
+ Operator privileges.
+
+ If the client sending the OPER command supplies the correct password
+ for the given user, the server then informs the rest of the network
+ of the new operator by issuing a "MODE +o" for the clients nickname.
+
+ The OPER message is client-server only.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS RPL_YOUREOPER
+ ERR_NOOPERHOST ERR_PASSWDMISMATCH
+
+ Example:
+
+ OPER foo bar ; Attempt to register as an operator
+ using a username of "foo" and "bar" as
+ the password.
+
+4.1.6 Quit
+
+ Command: QUIT
+ Parameters: [<Quit message>]
+
+ A client session is ended with a quit message. The server must close
+ the connection to a client which sends a QUIT message. If a "Quit
+ Message" is given, this will be sent instead of the default message,
+ the nickname.
+
+ When netsplits (disconnecting of two servers) occur, the quit message
+
+
+
+Oikarinen & Reed [Page 17]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ is composed of the names of two servers involved, separated by a
+ space. The first name is that of the server which is still connected
+ and the second name is that of the server that has become
+ disconnected.
+
+ If, for some other reason, a client connection is closed without the
+ client issuing a QUIT command (e.g. client dies and EOF occurs
+ on socket), the server is required to fill in the quit message with
+ some sort of message reflecting the nature of the event which
+ caused it to happen.
+
+ Numeric Replies:
+
+ None.
+
+ Examples:
+
+ QUIT :Gone to have lunch ; Preferred message format.
+
+4.1.7 Server quit message
+
+ Command: SQUIT
+ Parameters: <server> <comment>
+
+ The SQUIT message is needed to tell about quitting or dead servers.
+ If a server wishes to break the connection to another server it must
+ send a SQUIT message to the other server, using the the name of the
+ other server as the server parameter, which then closes its
+ connection to the quitting server.
+
+ This command is also available operators to help keep a network of
+ IRC servers connected in an orderly fashion. Operators may also
+ issue an SQUIT message for a remote server connection. In this case,
+ the SQUIT must be parsed by each server inbetween the operator and
+ the remote server, updating the view of the network held by each
+ server as explained below.
+
+ The <comment> should be supplied by all operators who execute a SQUIT
+ for a remote server (that is not connected to the server they are
+ currently on) so that other operators are aware for the reason of
+ this action. The <comment> is also filled in by servers which may
+ place an error or similar message here.
+
+ Both of the servers which are on either side of the connection being
+ closed are required to to send out a SQUIT message (to all its other
+ server connections) for all other servers which are considered to be
+ behind that link.
+
+
+
+
+Oikarinen & Reed [Page 18]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ Similarly, a QUIT message must be sent to the other connected servers
+ rest of the network on behalf of all clients behind that link. In
+ addition to this, all channel members of a channel which lost a
+ member due to the split must be sent a QUIT message.
+
+ If a server connection is terminated prematurely (e.g. the server on
+ the other end of the link died), the server which detects
+ this disconnection is required to inform the rest of the network
+ that the connection has closed and fill in the comment field
+ with something appropriate.
+
+ Numeric replies:
+
+ ERR_NOPRIVILEGES ERR_NOSUCHSERVER
+
+ Example:
+
+ SQUIT tolsun.oulu.fi :Bad Link ? ; the server link tolson.oulu.fi has
+ been terminated because of "Bad Link".
+
+ :Trillian SQUIT cm22.eng.umd.edu :Server out of control
+ ; message from Trillian to disconnect
+ "cm22.eng.umd.edu" from the net
+ because "Server out of control".
+
+4.2 Channel operations
+
+ This group of messages is concerned with manipulating channels, their
+ properties (channel modes), and their contents (typically clients).
+ In implementing these, a number of race conditions are inevitable
+ when clients at opposing ends of a network send commands which will
+ ultimately clash. It is also required that servers keep a nickname
+ history to ensure that wherever a <nick> parameter is given, the
+ server check its history in case it has recently been changed.
+
+4.2.1 Join message
+
+ Command: JOIN
+ Parameters: <channel>{,<channel>} [<key>{,<key>}]
+
+ The JOIN command is used by client to start listening a specific
+ channel. Whether or not a client is allowed to join a channel is
+ checked only by the server the client is connected to; all other
+ servers automatically add the user to the channel when it is received
+ from other servers. The conditions which affect this are as follows:
+
+ 1. the user must be invited if the channel is invite-only;
+
+
+
+
+Oikarinen & Reed [Page 19]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ 2. the user's nick/username/hostname must not match any
+ active bans;
+
+ 3. the correct key (password) must be given if it is set.
+
+ These are discussed in more detail under the MODE command (see
+ section 4.2.3 for more details).
+
+ Once a user has joined a channel, they receive notice about all
+ commands their server receives which affect the channel. This
+ includes MODE, KICK, PART, QUIT and of course PRIVMSG/NOTICE. The
+ JOIN command needs to be broadcast to all servers so that each server
+ knows where to find the users who are on the channel. This allows
+ optimal delivery of PRIVMSG/NOTICE messages to the channel.
+
+ If a JOIN is successful, the user is then sent the channel's topic
+ (using RPL_TOPIC) and the list of users who are on the channel (using
+ RPL_NAMREPLY), which must include the user joining.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_BANNEDFROMCHAN
+ ERR_INVITEONLYCHAN ERR_BADCHANNELKEY
+ ERR_CHANNELISFULL ERR_BADCHANMASK
+ ERR_NOSUCHCHANNEL ERR_TOOMANYCHANNELS
+ RPL_TOPIC
+
+ Examples:
+
+ JOIN #foobar ; join channel #foobar.
+
+ JOIN &foo fubar ; join channel &foo using key "fubar".
+
+ JOIN #foo,&bar fubar ; join channel #foo using key "fubar"
+ and &bar using no key.
+
+ JOIN #foo,#bar fubar,foobar ; join channel #foo using key "fubar".
+ and channel #bar using key "foobar".
+
+ JOIN #foo,#bar ; join channels #foo and #bar.
+
+ :WiZ JOIN #Twilight_zone ; JOIN message from WiZ
+
+4.2.2 Part message
+
+ Command: PART
+ Parameters: <channel>{,<channel>}
+
+
+
+
+Oikarinen & Reed [Page 20]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ The PART message causes the client sending the message to be removed
+ from the list of active users for all given channels listed in the
+ parameter string.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_NOSUCHCHANNEL
+ ERR_NOTONCHANNEL
+
+ Examples:
+
+ PART #twilight_zone ; leave channel "#twilight_zone"
+
+ PART #oz-ops,&group5 ; leave both channels "&group5" and
+ "#oz-ops".
+
+4.2.3 Mode message
+
+ Command: MODE
+
+ The MODE command is a dual-purpose command in IRC. It allows both
+ usernames and channels to have their mode changed. The rationale for
+ this choice is that one day nicknames will be obsolete and the
+ equivalent property will be the channel.
+
+ When parsing MODE messages, it is recommended that the entire message
+ be parsed first and then the changes which resulted then passed on.
+
+4.2.3.1 Channel modes
+
+ Parameters: <channel> {[+|-]|o|p|s|i|t|n|b|v} [<limit>] [<user>]
+ [<ban mask>]
+
+ The MODE command is provided so that channel operators may change the
+ characteristics of `their' channel. It is also required that servers
+ be able to change channel modes so that channel operators may be
+ created.
+
+ The various modes available for channels are as follows:
+
+ o - give/take channel operator privileges;
+ p - private channel flag;
+ s - secret channel flag;
+ i - invite-only channel flag;
+ t - topic settable by channel operator only flag;
+ n - no messages to channel from clients on the outside;
+ m - moderated channel;
+ l - set the user limit to channel;
+
+
+
+Oikarinen & Reed [Page 21]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ b - set a ban mask to keep users out;
+ v - give/take the ability to speak on a moderated channel;
+ k - set a channel key (password).
+
+ When using the 'o' and 'b' options, a restriction on a total of three
+ per mode command has been imposed. That is, any combination of 'o'
+ and
+
+4.2.3.2 User modes
+
+ Parameters: <nickname> {[+|-]|i|w|s|o}
+
+ The user MODEs are typically changes which affect either how the
+ client is seen by others or what 'extra' messages the client is sent.
+ A user MODE command may only be accepted if both the sender of the
+ message and the nickname given as a parameter are both the same.
+
+ The available modes are as follows:
+
+ i - marks a users as invisible;
+ s - marks a user for receipt of server notices;
+ w - user receives wallops;
+ o - operator flag.
+
+ Additional modes may be available later on.
+
+ If a user attempts to make themselves an operator using the "+o"
+ flag, the attempt should be ignored. There is no restriction,
+ however, on anyone `deopping' themselves (using "-o"). Numeric
+ Replies:
+
+ ERR_NEEDMOREPARAMS RPL_CHANNELMODEIS
+ ERR_CHANOPRIVSNEEDED ERR_NOSUCHNICK
+ ERR_NOTONCHANNEL ERR_KEYSET
+ RPL_BANLIST RPL_ENDOFBANLIST
+ ERR_UNKNOWNMODE ERR_NOSUCHCHANNEL
+
+ ERR_USERSDONTMATCH RPL_UMODEIS
+ ERR_UMODEUNKNOWNFLAG
+
+ Examples:
+
+ Use of Channel Modes:
+
+MODE #Finnish +im ; Makes #Finnish channel moderated and
+ 'invite-only'.
+
+MODE #Finnish +o Kilroy ; Gives 'chanop' privileges to Kilroy on
+
+
+
+Oikarinen & Reed [Page 22]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ channel #Finnish.
+
+MODE #Finnish +v Wiz ; Allow WiZ to speak on #Finnish.
+
+MODE #Fins -s ; Removes 'secret' flag from channel
+ #Fins.
+
+MODE #42 +k oulu ; Set the channel key to "oulu".
+
+MODE #eu-opers +l 10 ; Set the limit for the number of users
+ on channel to 10.
+
+MODE &oulu +b ; list ban masks set for channel.
+
+MODE &oulu +b *!*@* ; prevent all users from joining.
+
+MODE &oulu +b *!*@*.edu ; prevent any user from a hostname
+ matching *.edu from joining.
+
+ Use of user Modes:
+
+:MODE WiZ -w ; turns reception of WALLOPS messages
+ off for WiZ.
+
+:Angel MODE Angel +i ; Message from Angel to make themselves
+ invisible.
+
+MODE WiZ -o ; WiZ 'deopping' (removing operator
+ status). The plain reverse of this
+ command ("MODE WiZ +o") must not be
+ allowed from users since would bypass
+ the OPER command.
+
+4.2.4 Topic message
+
+ Command: TOPIC
+ Parameters: <channel> [<topic>]
+
+ The TOPIC message is used to change or view the topic of a channel.
+ The topic for channel <channel> is returned if there is no <topic>
+ given. If the <topic> parameter is present, the topic for that
+ channel will be changed, if the channel modes permit this action.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_NOTONCHANNEL
+ RPL_NOTOPIC RPL_TOPIC
+ ERR_CHANOPRIVSNEEDED
+
+
+
+Oikarinen & Reed [Page 23]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ Examples:
+
+ :Wiz TOPIC #test :New topic ;User Wiz setting the topic.
+
+ TOPIC #test :another topic ;set the topic on #test to "another
+ topic".
+
+ TOPIC #test ; check the topic for #test.
+
+4.2.5 Names message
+
+ Command: NAMES
+ Parameters: [<channel>{,<channel>}]
+
+ By using the NAMES command, a user can list all nicknames that are
+ visible to them on any channel that they can see. Channel names
+ which they can see are those which aren't private (+p) or secret (+s)
+ or those which they are actually on. The <channel> parameter
+ specifies which channel(s) to return information about if valid.
+ There is no error reply for bad channel names.
+
+ If no <channel> parameter is given, a list of all channels and their
+ occupants is returned. At the end of this list, a list of users who
+ are visible but either not on any channel or not on a visible channel
+ are listed as being on `channel' "*".
+
+ Numerics:
+
+ RPL_NAMREPLY RPL_ENDOFNAMES
+
+ Examples:
+
+ NAMES #twilight_zone,#42 ; list visible users on #twilight_zone
+ and #42 if the channels are visible to
+ you.
+
+ NAMES ; list all visible channels and users
+
+4.2.6 List message
+
+ Command: LIST
+ Parameters: [<channel>{,<channel>} [<server>]]
+
+ The list message is used to list channels and their topics. If the
+ <channel> parameter is used, only the status of that channel
+ is displayed. Private channels are listed (without their
+ topics) as channel "Prv" unless the client generating the query is
+ actually on that channel. Likewise, secret channels are not listed
+
+
+
+Oikarinen & Reed [Page 24]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ at all unless the client is a member of the channel in question.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER RPL_LISTSTART
+ RPL_LIST RPL_LISTEND
+
+ Examples:
+
+ LIST ; List all channels.
+
+ LIST #twilight_zone,#42 ; List channels #twilight_zone and #42
+
+4.2.7 Invite message
+
+ Command: INVITE
+ Parameters: <nickname> <channel>
+
+ The INVITE message is used to invite users to a channel. The
+ parameter <nickname> is the nickname of the person to be invited to
+ the target channel <channel>. There is no requirement that the
+ channel the target user is being invited to must exist or be a valid
+ channel. To invite a user to a channel which is invite only (MODE
+ +i), the client sending the invite must be recognised as being a
+ channel operator on the given channel.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_NOSUCHNICK
+ ERR_NOTONCHANNEL ERR_USERONCHANNEL
+ ERR_CHANOPRIVSNEEDED
+ RPL_INVITING RPL_AWAY
+
+ Examples:
+
+ :Angel INVITE Wiz #Dust ; User Angel inviting WiZ to channel
+ #Dust
+
+ INVITE Wiz #Twilight_Zone ; Command to invite WiZ to
+ #Twilight_zone
+
+4.2.8 Kick command
+
+ Command: KICK
+ Parameters: <channel> <user> [<comment>]
+
+ The KICK command can be used to forcibly remove a user from a
+ channel. It 'kicks them out' of the channel (forced PART).
+
+
+
+Oikarinen & Reed [Page 25]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ Only a channel operator may kick another user out of a channel.
+ Each server that receives a KICK message checks that it is valid
+ (ie the sender is actually a channel operator) before removing
+ the victim from the channel.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_NOSUCHCHANNEL
+ ERR_BADCHANMASK ERR_CHANOPRIVSNEEDED
+ ERR_NOTONCHANNEL
+
+ Examples:
+
+KICK &Melbourne Matthew ; Kick Matthew from &Melbourne
+
+KICK #Finnish John :Speaking English
+ ; Kick John from #Finnish using
+ "Speaking English" as the reason
+ (comment).
+
+:WiZ KICK #Finnish John ; KICK message from WiZ to remove John
+ from channel #Finnish
+
+NOTE:
+ It is possible to extend the KICK command parameters to the
+following:
+
+<channel>{,<channel>} <user>{,<user>} [<comment>]
+
+4.3 Server queries and commands
+
+ The server query group of commands has been designed to return
+ information about any server which is connected to the network. All
+ servers connected must respond to these queries and respond
+ correctly. Any invalid response (or lack thereof) must be considered
+ a sign of a broken server and it must be disconnected/disabled as
+ soon as possible until the situation is remedied.
+
+ In these queries, where a parameter appears as "<server>", it will
+ usually mean it can be a nickname or a server or a wildcard name of
+ some sort. For each parameter, however, only one query and set of
+ replies is to be generated.
+
+4.3.1 Version message
+
+ Command: VERSION
+ Parameters: [<server>]
+
+
+
+
+Oikarinen & Reed [Page 26]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ The VERSION message is used to query the version of the server
+ program. An optional parameter <server> is used to query the version
+ of the server program which a client is not directly connected to.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER RPL_VERSION
+
+ Examples:
+
+ :Wiz VERSION *.se ; message from Wiz to check the version
+ of a server matching "*.se"
+
+ VERSION tolsun.oulu.fi ; check the version of server
+ "tolsun.oulu.fi".
+
+4.3.2 Stats message
+
+ Command: STATS
+ Parameters: [<query> [<server>]]
+
+ The stats message is used to query statistics of certain server. If
+ <server> parameter is omitted, only the end of stats reply is sent
+ back. The implementation of this command is highly dependent on the
+ server which replies, although the server must be able to supply
+ information as described by the queries below (or similar).
+
+ A query may be given by any single letter which is only checked by
+ the destination server (if given as the <server> parameter) and is
+ otherwise passed on by intermediate servers, ignored and unaltered.
+ The following queries are those found in the current IRC
+ implementation and provide a large portion of the setup information
+ for that server. Although these may not be supported in the same way
+ by other versions, all servers should be able to supply a valid reply
+ to a STATS query which is consistent with the reply formats currently
+ used and the purpose of the query.
+
+ The currently supported queries are:
+
+ c - returns a list of servers which the server may connect
+ to or allow connections from;
+ h - returns a list of servers which are either forced to be
+ treated as leaves or allowed to act as hubs;
+ i - returns a list of hosts which the server allows a client
+ to connect from;
+ k - returns a list of banned username/hostname combinations
+ for that server;
+ l - returns a list of the server's connections, showing how
+
+
+
+Oikarinen & Reed [Page 27]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ long each connection has been established and the traffic
+ over that connection in bytes and messages for each
+ direction;
+ m - returns a list of commands supported by the server and
+ the usage count for each if the usage count is non zero;
+ o - returns a list of hosts from which normal clients may
+ become operators;
+ y - show Y (Class) lines from server's configuration file;
+ u - returns a string showing how long the server has been up.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+ RPL_STATSCLINE RPL_STATSNLINE
+ RPL_STATSILINE RPL_STATSKLINE
+ RPL_STATSQLINE RPL_STATSLLINE
+ RPL_STATSLINKINFO RPL_STATSUPTIME
+ RPL_STATSCOMMANDS RPL_STATSOLINE
+ RPL_STATSHLINE RPL_ENDOFSTATS
+
+ Examples:
+
+STATS m ; check the command usage for the server
+ you are connected to
+
+:Wiz STATS c eff.org ; request by WiZ for C/N line
+ information from server eff.org
+
+4.3.3 Links message
+
+ Command: LINKS
+ Parameters: [[<remote server>] <server mask>]
+
+ With LINKS, a user can list all servers which are known by the server
+ answering the query. The returned list of servers must match the
+ mask, or if no mask is given, the full list is returned.
+
+ If <remote server> is given in addition to <server mask>, the LINKS
+ command is forwarded to the first server found that matches that name
+ (if any), and that server is then required to answer the query.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+ RPL_LINKS RPL_ENDOFLINKS
+
+ Examples:
+
+
+
+
+Oikarinen & Reed [Page 28]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+LINKS *.au ; list all servers which have a name
+ that matches *.au;
+
+:WiZ LINKS *.bu.edu *.edu ; LINKS message from WiZ to the first
+ server matching *.edu for a list of
+ servers matching *.bu.edu.
+
+4.3.4 Time message
+
+ Command: TIME
+ Parameters: [<server>]
+
+ The time message is used to query local time from the specified
+ server. If the server parameter is not given, the server handling the
+ command must reply to the query.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER RPL_TIME
+
+ Examples:
+
+ TIME tolsun.oulu.fi ; check the time on the server
+ "tolson.oulu.fi"
+
+ Angel TIME *.au ; user angel checking the time on a
+ server matching "*.au"
+
+4.3.5 Connect message
+
+ Command: CONNECT
+ Parameters: <target server> [<port> [<remote server>]]
+
+ The CONNECT command can be used to force a server to try to establish
+ a new connection to another server immediately. CONNECT is a
+ privileged command and is to be available only to IRC Operators. If
+ a remote server is given then the CONNECT attempt is made by that
+ server to <target server> and <port>.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER ERR_NOPRIVILEGES
+ ERR_NEEDMOREPARAMS
+
+ Examples:
+
+CONNECT tolsun.oulu.fi ; Attempt to connect a server to
+ tolsun.oulu.fi
+
+
+
+Oikarinen & Reed [Page 29]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+:WiZ CONNECT eff.org 6667 csd.bu.edu
+ ; CONNECT attempt by WiZ to get servers
+ eff.org and csd.bu.edu connected on port
+ 6667.
+
+4.3.6 Trace message
+
+ Command: TRACE
+ Parameters: [<server>]
+
+ TRACE command is used to find the route to specific server. Each
+ server that processes this message must tell the sender about it by
+ sending a reply indicating it is a pass-through link, forming a chain
+ of replies similar to that gained from using "traceroute". After
+ sending this reply back, it must then send the TRACE message to the
+ next server until given server is reached. If the <server> parameter
+ is omitted, it is recommended that TRACE command send a message to
+ the sender telling which servers the current server has direct
+ connection to.
+
+ If the destination given by "<server>" is an actual server, then the
+ destination server is required to report all servers and users which
+ are connected to it, although only operators are permitted to see
+ users present. If the destination given by <server> is a nickname,
+ they only a reply for that nickname is given.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+
+ If the TRACE message is destined for another server, all intermediate
+ servers must return a RPL_TRACELINK reply to indicate that the TRACE
+ passed through it and where its going next.
+
+ RPL_TRACELINK
+ A TRACE reply may be composed of any number of the following numeric
+ replies.
+
+ RPL_TRACECONNECTING RPL_TRACEHANDSHAKE
+ RPL_TRACEUNKNOWN RPL_TRACEOPERATOR
+ RPL_TRACEUSER RPL_TRACESERVER
+ RPL_TRACESERVICE RPL_TRACENEWTYPE
+ RPL_TRACECLASS
+
+ Examples:
+
+TRACE *.oulu.fi ; TRACE to a server matching *.oulu.fi
+
+
+
+
+Oikarinen & Reed [Page 30]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+:WiZ TRACE AngelDust ; TRACE issued by WiZ to nick AngelDust
+
+4.3.7 Admin command
+
+ Command: ADMIN
+ Parameters: [<server>]
+
+ The admin message is used to find the name of the administrator of
+ the given server, or current server if <server> parameter is omitted.
+ Each server must have the ability to forward ADMIN messages to other
+ servers.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+ RPL_ADMINME RPL_ADMINLOC1
+ RPL_ADMINLOC2 RPL_ADMINEMAIL
+
+ Examples:
+
+ ADMIN tolsun.oulu.fi ; request an ADMIN reply from
+ tolsun.oulu.fi
+
+ :WiZ ADMIN *.edu ; ADMIN request from WiZ for first
+ server found to match *.edu.
+
+4.3.8 Info command
+
+ Command: INFO
+ Parameters: [<server>]
+
+ The INFO command is required to return information which describes
+ the server: its version, when it was compiled, the patchlevel, when
+ it was started, and any other miscellaneous information which may be
+ considered to be relevant.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+ RPL_INFO RPL_ENDOFINFO
+
+ Examples:
+
+ INFO csd.bu.edu ; request an INFO reply from
+ csd.bu.edu
+
+ :Avalon INFO *.fi ; INFO request from Avalon for first
+ server found to match *.fi.
+
+
+
+Oikarinen & Reed [Page 31]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ INFO Angel ; request info from the server that
+ Angel is connected to.
+
+4.4 Sending messages
+
+ The main purpose of the IRC protocol is to provide a base for clients
+ to communicate with each other. PRIVMSG and NOTICE are the only
+ messages available which actually perform delivery of a text message
+ from one client to another - the rest just make it possible and try
+ to ensure it happens in a reliable and structured manner.
+
+4.4.1 Private messages
+
+ Command: PRIVMSG
+ Parameters: <receiver>{,<receiver>} <text to be sent>
+
+ PRIVMSG is used to send private messages between users. <receiver>
+ is the nickname of the receiver of the message. <receiver> can also
+ be a list of names or channels separated with commas.
+
+ The <receiver> parameter may also me a host mask (#mask) or server
+ mask ($mask). In both cases the server will only send the PRIVMSG
+ to those who have a server or host matching the mask. The mask must
+ have at least 1 (one) "." in it and no wildcards following the
+ last ".". This requirement exists to prevent people sending messages
+ to "#*" or "$*", which would broadcast to all users; from
+ experience, this is abused more than used responsibly and properly.
+ Wildcards are the '*' and '?' characters. This extension to
+ the PRIVMSG command is only available to Operators.
+
+ Numeric Replies:
+
+ ERR_NORECIPIENT ERR_NOTEXTTOSEND
+ ERR_CANNOTSENDTOCHAN ERR_NOTOPLEVEL
+ ERR_WILDTOPLEVEL ERR_TOOMANYTARGETS
+ ERR_NOSUCHNICK
+ RPL_AWAY
+
+ Examples:
+
+:Angel PRIVMSG Wiz :Hello are you receiving this message ?
+ ; Message from Angel to Wiz.
+
+PRIVMSG Angel :yes I'm receiving it !receiving it !'u>(768u+1n) .br ;
+ Message to Angel.
+
+PRIVMSG jto@tolsun.oulu.fi :Hello !
+ ; Message to a client on server
+
+
+
+Oikarinen & Reed [Page 32]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ tolsun.oulu.fi with username of "jto".
+
+PRIVMSG $*.fi :Server tolsun.oulu.fi rebooting.
+ ; Message to everyone on a server which
+ has a name matching *.fi.
+
+PRIVMSG #*.edu :NSFNet is undergoing work, expect interruptions
+ ; Message to all users who come from a
+ host which has a name matching *.edu.
+
+4.4.2 Notice
+
+ Command: NOTICE
+ Parameters: <nickname> <text>
+
+ The NOTICE message is used similarly to PRIVMSG. The difference
+ between NOTICE and PRIVMSG is that automatic replies must never be
+ sent in response to a NOTICE message. This rule applies to servers
+ too - they must not send any error reply back to the client on
+ receipt of a notice. The object of this rule is to avoid loops
+ between a client automatically sending something in response to
+ something it received. This is typically used by automatons (clients
+ with either an AI or other interactive program controlling their
+ actions) which are always seen to be replying lest they end up in a
+ loop with another automaton.
+
+ See PRIVMSG for more details on replies and examples.
+
+4.5 User based queries
+
+ User queries are a group of commands which are primarily concerned
+ with finding details on a particular user or group users. When using
+ wildcards with any of these commands, if they match, they will only
+ return information on users who are 'visible' to you. The visibility
+ of a user is determined as a combination of the user's mode and the
+ common set of channels you are both on.
+
+4.5.1 Who query
+
+ Command: WHO
+ Parameters: [<name> [<o>]]
+
+ The WHO message is used by a client to generate a query which returns
+ a list of information which 'matches' the <name> parameter given by
+ the client. In the absence of the <name> parameter, all visible
+ (users who aren't invisible (user mode +i) and who don't have a
+ common channel with the requesting client) are listed. The same
+ result can be achieved by using a <name> of "0" or any wildcard which
+
+
+
+Oikarinen & Reed [Page 33]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ will end up matching every entry possible.
+
+ The <name> passed to WHO is matched against users' host, server, real
+ name and nickname if the channel <name> cannot be found.
+
+ If the "o" parameter is passed only operators are returned according
+ to the name mask supplied.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+ RPL_WHOREPLY RPL_ENDOFWHO
+
+ Examples:
+
+ WHO *.fi ; List all users who match against
+ "*.fi".
+
+ WHO jto* o ; List all users with a match against
+ "jto*" if they are an operator.
+
+4.5.2 Whois query
+
+ Command: WHOIS
+ Parameters: [<server>] <nickmask>[,<nickmask>[,...]]
+
+ This message is used to query information about particular user. The
+ server will answer this message with several numeric messages
+ indicating different statuses of each user which matches the nickmask
+ (if you are entitled to see them). If no wildcard is present in the
+ <nickmask>, any information about that nick which you are allowed to
+ see is presented. A comma (',') separated list of nicknames may be
+ given.
+
+ The latter version sends the query to a specific server. It is
+ useful if you want to know how long the user in question has been
+ idle as only local server (ie. the server the user is directly
+ connected to) knows that information, while everything else is
+ globally known.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER ERR_NONICKNAMEGIVEN
+ RPL_WHOISUSER RPL_WHOISCHANNELS
+ RPL_WHOISCHANNELS RPL_WHOISSERVER
+ RPL_AWAY RPL_WHOISOPERATOR
+ RPL_WHOISIDLE ERR_NOSUCHNICK
+ RPL_ENDOFWHOIS
+
+
+
+Oikarinen & Reed [Page 34]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ Examples:
+
+ WHOIS wiz ; return available user information
+ about nick WiZ
+
+ WHOIS eff.org trillian ; ask server eff.org for user
+ information about trillian
+
+4.5.3 Whowas
+
+ Command: WHOWAS
+ Parameters: <nickname> [<count> [<server>]]
+
+ Whowas asks for information about a nickname which no longer exists.
+ This may either be due to a nickname change or the user leaving IRC.
+ In response to this query, the server searches through its nickname
+ history, looking for any nicks which are lexically the same (no wild
+ card matching here). The history is searched backward, returning the
+ most recent entry first. If there are multiple entries, up to
+ <count> replies will be returned (or all of them if no <count>
+ parameter is given). If a non-positive number is passed as being
+ <count>, then a full search is done.
+
+ Numeric Replies:
+
+ ERR_NONICKNAMEGIVEN ERR_WASNOSUCHNICK
+ RPL_WHOWASUSER RPL_WHOISSERVER
+ RPL_ENDOFWHOWAS
+
+ Examples:
+
+ WHOWAS Wiz ; return all information in the nick
+ history about nick "WiZ";
+
+ WHOWAS Mermaid 9 ; return at most, the 9 most recent
+ entries in the nick history for
+ "Mermaid";
+
+ WHOWAS Trillian 1 *.edu ; return the most recent history for
+ "Trillian" from the first server found
+ to match "*.edu".
+
+4.6 Miscellaneous messages
+
+ Messages in this category do not fit into any of the above categories
+ but are nonetheless still a part of and required by the protocol.
+
+
+
+
+
+Oikarinen & Reed [Page 35]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+4.6.1 Kill message
+
+ Command: KILL
+ Parameters: <nickname> <comment>
+
+ The KILL message is used to cause a client-server connection to be
+ closed by the server which has the actual connection. KILL is used
+ by servers when they encounter a duplicate entry in the list of valid
+ nicknames and is used to remove both entries. It is also available
+ to operators.
+
+ Clients which have automatic reconnect algorithms effectively make
+ this command useless since the disconnection is only brief. It does
+ however break the flow of data and can be used to stop large amounts
+ of being abused, any user may elect to receive KILL messages
+ generated for others to keep an 'eye' on would be trouble spots.
+
+ In an arena where nicknames are required to be globally unique at all
+ times, KILL messages are sent whenever 'duplicates' are detected
+ (that is an attempt to register two users with the same nickname) in
+ the hope that both of them will disappear and only 1 reappear.
+
+ The comment given must reflect the actual reason for the KILL. For
+ server-generated KILLs it usually is made up of details concerning
+ the origins of the two conflicting nicknames. For users it is left
+ up to them to provide an adequate reason to satisfy others who see
+ it. To prevent/discourage fake KILLs from being generated to hide
+ the identify of the KILLer, the comment also shows a 'kill-path'
+ which is updated by each server it passes through, each prepending
+ its name to the path.
+
+ Numeric Replies:
+
+ ERR_NOPRIVILEGES ERR_NEEDMOREPARAMS
+ ERR_NOSUCHNICK ERR_CANTKILLSERVER
+
+
+ KILL David (csd.bu.edu <- tolsun.oulu.fi)
+ ; Nickname collision between csd.bu.edu
+ and tolson.oulu.fi
+
+
+ NOTE:
+ It is recommended that only Operators be allowed to kill other users
+ with KILL message. In an ideal world not even operators would need
+ to do this and it would be left to servers to deal with.
+
+
+
+
+
+Oikarinen & Reed [Page 36]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+4.6.2 Ping message
+
+ Command: PING
+ Parameters: <server1> [<server2>]
+
+ The PING message is used to test the presence of an active client at
+ the other end of the connection. A PING message is sent at regular
+ intervals if no other activity detected coming from a connection. If
+ a connection fails to respond to a PING command within a set amount
+ of time, that connection is closed.
+
+ Any client which receives a PING message must respond to <server1>
+ (server which sent the PING message out) as quickly as possible with
+ an appropriate PONG message to indicate it is still there and alive.
+ Servers should not respond to PING commands but rely on PINGs from
+ the other end of the connection to indicate the connection is alive.
+ If the <server2> parameter is specified, the PING message gets
+ forwarded there.
+
+ Numeric Replies:
+
+ ERR_NOORIGIN ERR_NOSUCHSERVER
+
+ Examples:
+
+ PING tolsun.oulu.fi ; server sending a PING message to
+ another server to indicate it is still
+ alive.
+
+ PING WiZ ; PING message being sent to nick WiZ
+
+4.6.3 Pong message
+
+ Command: PONG
+ Parameters: <daemon> [<daemon2>]
+
+ PONG message is a reply to ping message. If parameter <daemon2> is
+ given this message must be forwarded to given daemon. The <daemon>
+ parameter is the name of the daemon who has responded to PING message
+ and generated this message.
+
+ Numeric Replies:
+
+ ERR_NOORIGIN ERR_NOSUCHSERVER
+
+ Examples:
+
+ PONG csd.bu.edu tolsun.oulu.fi ; PONG message from csd.bu.edu to
+
+
+
+Oikarinen & Reed [Page 37]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ tolsun.oulu.fi
+
+4.6.4 Error
+
+ Command: ERROR
+ Parameters: <error message>
+
+ The ERROR command is for use by servers when reporting a serious or
+ fatal error to its operators. It may also be sent from one server to
+ another but must not be accepted from any normal unknown clients.
+
+ An ERROR message is for use for reporting errors which occur with a
+ server-to-server link only. An ERROR message is sent to the server
+ at the other end (which sends it to all of its connected operators)
+ and to all operators currently connected. It is not to be passed
+ onto any other servers by a server if it is received from a server.
+
+ When a server sends a received ERROR message to its operators, the
+ message should be encapsulated inside a NOTICE message, indicating
+ that the client was not responsible for the error.
+
+ Numerics:
+
+ None.
+
+ Examples:
+
+ ERROR :Server *.fi already exists; ERROR message to the other server
+ which caused this error.
+
+ NOTICE WiZ :ERROR from csd.bu.edu -- Server *.fi already exists
+ ; Same ERROR message as above but sent
+ to user WiZ on the other server.
+
+5. OPTIONALS
+
+ This section describes OPTIONAL messages. They are not required in a
+ working server implementation of the protocol described herein. In
+ the absence of the option, an error reply message must be generated
+ or an unknown command error. If the message is destined for another
+ server to answer then it must be passed on (elementary parsing
+ required) The allocated numerics for this are listed with the
+ messages below.
+
+5.1 Away
+
+ Command: AWAY
+ Parameters: [message]
+
+
+
+Oikarinen & Reed [Page 38]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ With the AWAY message, clients can set an automatic reply string for
+ any PRIVMSG commands directed at them (not to a channel they are on).
+ The automatic reply is sent by the server to client sending the
+ PRIVMSG command. The only replying server is the one to which the
+ sending client is connected to.
+
+ The AWAY message is used either with one parameter (to set an AWAY
+ message) or with no parameters (to remove the AWAY message).
+
+ Numeric Replies:
+
+ RPL_UNAWAY RPL_NOWAWAY
+
+ Examples:
+
+ AWAY :Gone to lunch. Back in 5 ; set away message to "Gone to lunch.
+ Back in 5".
+
+ :WiZ AWAY ; unmark WiZ as being away.
+
+
+5.2 Rehash message
+
+ Command: REHASH
+ Parameters: None
+
+ The rehash message can be used by the operator to force the server to
+ re-read and process its configuration file.
+
+ Numeric Replies:
+
+ RPL_REHASHING ERR_NOPRIVILEGES
+
+Examples:
+
+REHASH ; message from client with operator
+ status to server asking it to reread its
+ configuration file.
+
+5.3 Restart message
+
+ Command: RESTART
+ Parameters: None
+
+ The restart message can only be used by an operator to force a server
+ restart itself. This message is optional since it may be viewed as a
+ risk to allow arbitrary people to connect to a server as an operator
+ and execute this command, causing (at least) a disruption to service.
+
+
+
+Oikarinen & Reed [Page 39]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ The RESTART command must always be fully processed by the server to
+ which the sending client is connected and not be passed onto other
+ connected servers.
+
+ Numeric Replies:
+
+ ERR_NOPRIVILEGES
+
+ Examples:
+
+ RESTART ; no parameters required.
+
+5.4 Summon message
+
+ Command: SUMMON
+ Parameters: <user> [<server>]
+
+ The SUMMON command can be used to give users who are on a host
+ running an IRC server a message asking them to please join IRC. This
+ message is only sent if the target server (a) has SUMMON enabled, (b)
+ the user is logged in and (c) the server process can write to the
+ user's tty (or similar).
+
+ If no <server> parameter is given it tries to summon <user> from the
+ server the client is connected to is assumed as the target.
+
+ If summon is not enabled in a server, it must return the
+ ERR_SUMMONDISABLED numeric and pass the summon message onwards.
+
+ Numeric Replies:
+
+ ERR_NORECIPIENT ERR_FILEERROR
+ ERR_NOLOGIN ERR_NOSUCHSERVER
+ RPL_SUMMONING
+
+ Examples:
+
+ SUMMON jto ; summon user jto on the server's host
+
+ SUMMON jto tolsun.oulu.fi ; summon user jto on the host which a
+ server named "tolsun.oulu.fi" is
+ running.
+
+
+5.5 Users
+
+ Command: USERS
+ Parameters: [<server>]
+
+
+
+Oikarinen & Reed [Page 40]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ The USERS command returns a list of users logged into the server in a
+ similar format to who(1), rusers(1) and finger(1). Some people
+ may disable this command on their server for security related
+ reasons. If disabled, the correct numeric must be returned to
+ indicate this.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER ERR_FILEERROR
+ RPL_USERSSTART RPL_USERS
+ RPL_NOUSERS RPL_ENDOFUSERS
+ ERR_USERSDISABLED
+
+ Disabled Reply:
+
+ ERR_USERSDISABLED
+
+ Examples:
+
+USERS eff.org ; request a list of users logged in on
+ server eff.org
+
+:John USERS tolsun.oulu.fi ; request from John for a list of users
+ logged in on server tolsun.oulu.fi
+
+5.6 Operwall message
+
+ Command: WALLOPS
+ Parameters: Text to be sent to all operators currently online
+
+ Sends a message to all operators currently online. After
+ implementing WALLOPS as a user command it was found that it was
+ often and commonly abused as a means of sending a message to a lot
+ of people (much similar to WALL). Due to this it is recommended
+ that the current implementation of WALLOPS be used as an
+ example by allowing and recognising only servers as the senders of
+ WALLOPS.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS
+
+ Examples:
+
+ :csd.bu.edu WALLOPS :Connect '*.uiuc.edu 6667' from Joshua; WALLOPS
+ message from csd.bu.edu announcing a
+ CONNECT message it received and acted
+ upon from Joshua.
+
+
+
+Oikarinen & Reed [Page 41]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+5.7 Userhost message
+
+ Command: USERHOST
+ Parameters: <nickname>{<space><nickname>}
+
+ The USERHOST command takes a list of up to 5 nicknames, each
+ separated by a space character and returns a list of information
+ about each nickname that it found. The returned list has each reply
+ separated by a space.
+
+ Numeric Replies:
+
+ RPL_USERHOST ERR_NEEDMOREPARAMS
+
+ Examples:
+
+ USERHOST Wiz Michael Marty p ;USERHOST request for information on
+ nicks "Wiz", "Michael", "Marty" and "p"
+
+5.8 Ison message
+
+ Command: ISON
+ Parameters: <nickname>{<space><nickname>}
+
+ The ISON command was implemented to provide a quick and efficient
+ means to get a response about whether a given nickname was currently
+ on IRC. ISON only takes one (1) parameter: a space-separated list of
+ nicks. For each nickname in the list that is present, the server
+ adds that to its reply string. Thus the reply string may return
+ empty (none of the given nicks are present), an exact copy of the
+ parameter string (all of them present) or as any other subset of the
+ set of nicks given in the parameter. The only limit on the number
+ of nicks that may be checked is that the combined length must not be
+ too large as to cause the server to chop it off so it fits in 512
+ characters.
+
+ ISON is only be processed by the server local to the client sending
+ the command and thus not passed onto other servers for further
+ processing.
+
+ Numeric Replies:
+
+ RPL_ISON ERR_NEEDMOREPARAMS
+
+ Examples:
+
+ ISON phone trillian WiZ jarlek Avalon Angel Monstah
+ ; Sample ISON request for 7 nicks.
+
+
+
+Oikarinen & Reed [Page 42]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+6. REPLIES
+
+ The following is a list of numeric replies which are generated in
+ response to the commands given above. Each numeric is given with its
+ number, name and reply string.
+
+6.1 Error Replies.
+
+ 401 ERR_NOSUCHNICK
+ "<nickname> :No such nick/channel"
+
+ - Used to indicate the nickname parameter supplied to a
+ command is currently unused.
+
+ 402 ERR_NOSUCHSERVER
+ "<server name> :No such server"
+
+ - Used to indicate the server name given currently
+ doesn't exist.
+
+ 403 ERR_NOSUCHCHANNEL
+ "<channel name> :No such channel"
+
+ - Used to indicate the given channel name is invalid.
+
+ 404 ERR_CANNOTSENDTOCHAN
+ "<channel name> :Cannot send to channel"
+
+ - Sent to a user who is either (a) not on a channel
+ which is mode +n or (b) not a chanop (or mode +v) on
+ a channel which has mode +m set and is trying to send
+ a PRIVMSG message to that channel.
+
+ 405 ERR_TOOMANYCHANNELS
+ "<channel name> :You have joined too many \
+ channels"
+ - Sent to a user when they have joined the maximum
+ number of allowed channels and they try to join
+ another channel.
+
+ 406 ERR_WASNOSUCHNICK
+ "<nickname> :There was no such nickname"
+
+ - Returned by WHOWAS to indicate there is no history
+ information for that nickname.
+
+ 407 ERR_TOOMANYTARGETS
+ "<target> :Duplicate recipients. No message \
+
+
+
+Oikarinen & Reed [Page 43]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ delivered"
+
+ - Returned to a client which is attempting to send a
+ PRIVMSG/NOTICE using the user@host destination format
+ and for a user@host which has several occurrences.
+
+ 409 ERR_NOORIGIN
+ ":No origin specified"
+
+ - PING or PONG message missing the originator parameter
+ which is required since these commands must work
+ without valid prefixes.
+
+ 411 ERR_NORECIPIENT
+ ":No recipient given (<command>)"
+ 412 ERR_NOTEXTTOSEND
+ ":No text to send"
+ 413 ERR_NOTOPLEVEL
+ "<mask> :No toplevel domain specified"
+ 414 ERR_WILDTOPLEVEL
+ "<mask> :Wildcard in toplevel domain"
+
+ - 412 - 414 are returned by PRIVMSG to indicate that
+ the message wasn't delivered for some reason.
+ ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
+ are returned when an invalid use of
+ "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted.
+
+ 421 ERR_UNKNOWNCOMMAND
+ "<command> :Unknown command"
+
+ - Returned to a registered client to indicate that the
+ command sent is unknown by the server.
+
+ 422 ERR_NOMOTD
+ ":MOTD File is missing"
+
+ - Server's MOTD file could not be opened by the server.
+
+ 423 ERR_NOADMININFO
+ "<server> :No administrative info available"
+
+ - Returned by a server in response to an ADMIN message
+ when there is an error in finding the appropriate
+ information.
+
+ 424 ERR_FILEERROR
+ ":File error doing <file op> on <file>"
+
+
+
+Oikarinen & Reed [Page 44]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ - Generic error message used to report a failed file
+ operation during the processing of a message.
+
+ 431 ERR_NONICKNAMEGIVEN
+ ":No nickname given"
+
+ - Returned when a nickname parameter expected for a
+ command and isn't found.
+
+ 432 ERR_ERRONEUSNICKNAME
+ "<nick> :Erroneus nickname"
+
+ - Returned after receiving a NICK message which contains
+ characters which do not fall in the defined set. See
+ section x.x.x for details on valid nicknames.
+
+ 433 ERR_NICKNAMEINUSE
+ "<nick> :Nickname is already in use"
+
+ - Returned when a NICK message is processed that results
+ in an attempt to change to a currently existing
+ nickname.
+
+ 436 ERR_NICKCOLLISION
+ "<nick> :Nickname collision KILL"
+
+ - Returned by a server to a client when it detects a
+ nickname collision (registered of a NICK that
+ already exists by another server).
+
+ 441 ERR_USERNOTINCHANNEL
+ "<nick> <channel> :They aren't on that channel"
+
+ - Returned by the server to indicate that the target
+ user of the command is not on the given channel.
+
+ 442 ERR_NOTONCHANNEL
+ "<channel> :You're not on that channel"
+
+ - Returned by the server whenever a client tries to
+ perform a channel effecting command for which the
+ client isn't a member.
+
+ 443 ERR_USERONCHANNEL
+ "<user> <channel> :is already on channel"
+
+ - Returned when a client tries to invite a user to a
+ channel they are already on.
+
+
+
+Oikarinen & Reed [Page 45]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ 444 ERR_NOLOGIN
+ "<user> :User not logged in"
+
+ - Returned by the summon after a SUMMON command for a
+ user was unable to be performed since they were not
+ logged in.
+
+ 445 ERR_SUMMONDISABLED
+ ":SUMMON has been disabled"
+
+ - Returned as a response to the SUMMON command. Must be
+ returned by any server which does not implement it.
+
+ 446 ERR_USERSDISABLED
+ ":USERS has been disabled"
+
+ - Returned as a response to the USERS command. Must be
+ returned by any server which does not implement it.
+
+ 451 ERR_NOTREGISTERED
+ ":You have not registered"
+
+ - Returned by the server to indicate that the client
+ must be registered before the server will allow it
+ to be parsed in detail.
+
+ 461 ERR_NEEDMOREPARAMS
+ "<command> :Not enough parameters"
+
+ - Returned by the server by numerous commands to
+ indicate to the client that it didn't supply enough
+ parameters.
+
+ 462 ERR_ALREADYREGISTRED
+ ":You may not reregister"
+
+ - Returned by the server to any link which tries to
+ change part of the registered details (such as
+ password or user details from second USER message).
+
+
+ 463 ERR_NOPERMFORHOST
+ ":Your host isn't among the privileged"
+
+ - Returned to a client which attempts to register with
+ a server which does not been setup to allow
+ connections from the host the attempted connection
+ is tried.
+
+
+
+Oikarinen & Reed [Page 46]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ 464 ERR_PASSWDMISMATCH
+ ":Password incorrect"
+
+ - Returned to indicate a failed attempt at registering
+ a connection for which a password was required and
+ was either not given or incorrect.
+
+ 465 ERR_YOUREBANNEDCREEP
+ ":You are banned from this server"
+
+ - Returned after an attempt to connect and register
+ yourself with a server which has been setup to
+ explicitly deny connections to you.
+
+ 467 ERR_KEYSET
+ "<channel> :Channel key already set"
+ 471 ERR_CHANNELISFULL
+ "<channel> :Cannot join channel (+l)"
+ 472 ERR_UNKNOWNMODE
+ "<char> :is unknown mode char to me"
+ 473 ERR_INVITEONLYCHAN
+ "<channel> :Cannot join channel (+i)"
+ 474 ERR_BANNEDFROMCHAN
+ "<channel> :Cannot join channel (+b)"
+ 475 ERR_BADCHANNELKEY
+ "<channel> :Cannot join channel (+k)"
+ 481 ERR_NOPRIVILEGES
+ ":Permission Denied- You're not an IRC operator"
+
+ - Any command requiring operator privileges to operate
+ must return this error to indicate the attempt was
+ unsuccessful.
+
+ 482 ERR_CHANOPRIVSNEEDED
+ "<channel> :You're not channel operator"
+
+ - Any command requiring 'chanop' privileges (such as
+ MODE messages) must return this error if the client
+ making the attempt is not a chanop on the specified
+ channel.
+
+ 483 ERR_CANTKILLSERVER
+ ":You cant kill a server!"
+
+ - Any attempts to use the KILL command on a server
+ are to be refused and this error returned directly
+ to the client.
+
+
+
+
+Oikarinen & Reed [Page 47]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ 491 ERR_NOOPERHOST
+ ":No O-lines for your host"
+
+ - If a client sends an OPER message and the server has
+ not been configured to allow connections from the
+ client's host as an operator, this error must be
+ returned.
+
+ 501 ERR_UMODEUNKNOWNFLAG
+ ":Unknown MODE flag"
+
+ - Returned by the server to indicate that a MODE
+ message was sent with a nickname parameter and that
+ the a mode flag sent was not recognized.
+
+ 502 ERR_USERSDONTMATCH
+ ":Cant change mode for other users"
+
+ - Error sent to any user trying to view or change the
+ user mode for a user other than themselves.
+
+6.2 Command responses.
+
+ 300 RPL_NONE
+ Dummy reply number. Not used.
+
+ 302 RPL_USERHOST
+ ":[<reply>{<space><reply>}]"
+
+ - Reply format used by USERHOST to list replies to
+ the query list. The reply string is composed as
+ follows:
+
+ <reply> ::= <nick>['*'] '=' <'+'|'-'><hostname>
+
+ The '*' indicates whether the client has registered
+ as an Operator. The '-' or '+' characters represent
+ whether the client has set an AWAY message or not
+ respectively.
+
+ 303 RPL_ISON
+ ":[<nick> {<space><nick>}]"
+
+ - Reply format used by ISON to list replies to the
+ query list.
+
+ 301 RPL_AWAY
+ "<nick> :<away message>"
+
+
+
+Oikarinen & Reed [Page 48]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ 305 RPL_UNAWAY
+ ":You are no longer marked as being away"
+ 306 RPL_NOWAWAY
+ ":You have been marked as being away"
+
+ - These replies are used with the AWAY command (if
+ allowed). RPL_AWAY is sent to any client sending a
+ PRIVMSG to a client which is away. RPL_AWAY is only
+ sent by the server to which the client is connected.
+ Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the
+ client removes and sets an AWAY message.
+
+ 311 RPL_WHOISUSER
+ "<nick> <user> <host> * :<real name>"
+ 312 RPL_WHOISSERVER
+ "<nick> <server> :<server info>"
+ 313 RPL_WHOISOPERATOR
+ "<nick> :is an IRC operator"
+ 317 RPL_WHOISIDLE
+ "<nick> <integer> :seconds idle"
+ 318 RPL_ENDOFWHOIS
+ "<nick> :End of /WHOIS list"
+ 319 RPL_WHOISCHANNELS
+ "<nick> :{[@|+]<channel><space>}"
+
+ - Replies 311 - 313, 317 - 319 are all replies
+ generated in response to a WHOIS message. Given that
+ there are enough parameters present, the answering
+ server must either formulate a reply out of the above
+ numerics (if the query nick is found) or return an
+ error reply. The '*' in RPL_WHOISUSER is there as
+ the literal character and not as a wild card. For
+ each reply set, only RPL_WHOISCHANNELS may appear
+ more than once (for long lists of channel names).
+ The '@' and '+' characters next to the channel name
+ indicate whether a client is a channel operator or
+ has been granted permission to speak on a moderated
+ channel. The RPL_ENDOFWHOIS reply is used to mark
+ the end of processing a WHOIS message.
+
+ 314 RPL_WHOWASUSER
+ "<nick> <user> <host> * :<real name>"
+ 369 RPL_ENDOFWHOWAS
+ "<nick> :End of WHOWAS"
+
+ - When replying to a WHOWAS message, a server must use
+ the replies RPL_WHOWASUSER, RPL_WHOISSERVER or
+ ERR_WASNOSUCHNICK for each nickname in the presented
+
+
+
+Oikarinen & Reed [Page 49]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ list. At the end of all reply batches, there must
+ be RPL_ENDOFWHOWAS (even if there was only one reply
+ and it was an error).
+
+ 321 RPL_LISTSTART
+ "Channel :Users Name"
+ 322 RPL_LIST
+ "<channel> <# visible> :<topic>"
+ 323 RPL_LISTEND
+ ":End of /LIST"
+
+ - Replies RPL_LISTSTART, RPL_LIST, RPL_LISTEND mark
+ the start, actual replies with data and end of the
+ server's response to a LIST command. If there are
+ no channels available to return, only the start
+ and end reply must be sent.
+
+ 324 RPL_CHANNELMODEIS
+ "<channel> <mode> <mode params>"
+
+ 331 RPL_NOTOPIC
+ "<channel> :No topic is set"
+ 332 RPL_TOPIC
+ "<channel> :<topic>"
+
+ - When sending a TOPIC message to determine the
+ channel topic, one of two replies is sent. If
+ the topic is set, RPL_TOPIC is sent back else
+ RPL_NOTOPIC.
+
+ 341 RPL_INVITING
+ "<channel> <nick>"
+
+ - Returned by the server to indicate that the
+ attempted INVITE message was successful and is
+ being passed onto the end client.
+
+ 342 RPL_SUMMONING
+ "<user> :Summoning user to IRC"
+
+ - Returned by a server answering a SUMMON message to
+ indicate that it is summoning that user.
+
+ 351 RPL_VERSION
+ "<version>.<debuglevel> <server> :<comments>"
+
+ - Reply by the server showing its version details.
+ The <version> is the version of the software being
+
+
+
+Oikarinen & Reed [Page 50]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ used (including any patchlevel revisions) and the
+ <debuglevel> is used to indicate if the server is
+ running in "debug mode".
+
+ The "comments" field may contain any comments about
+ the version or further version details.
+
+ 352 RPL_WHOREPLY
+ "<channel> <user> <host> <server> <nick> \
+ <H|G>[*][@|+] :<hopcount> <real name>"
+ 315 RPL_ENDOFWHO
+ "<name> :End of /WHO list"
+
+ - The RPL_WHOREPLY and RPL_ENDOFWHO pair are used
+ to answer a WHO message. The RPL_WHOREPLY is only
+ sent if there is an appropriate match to the WHO
+ query. If there is a list of parameters supplied
+ with a WHO message, a RPL_ENDOFWHO must be sent
+ after processing each list item with <name> being
+ the item.
+
+ 353 RPL_NAMREPLY
+ "<channel> :[[@|+]<nick> [[@|+]<nick> [...]]]"
+ 366 RPL_ENDOFNAMES
+ "<channel> :End of /NAMES list"
+
+ - To reply to a NAMES message, a reply pair consisting
+ of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
+ server back to the client. If there is no channel
+ found as in the query, then only RPL_ENDOFNAMES is
+ returned. The exception to this is when a NAMES
+ message is sent with no parameters and all visible
+ channels and contents are sent back in a series of
+ RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
+ the end.
+
+ 364 RPL_LINKS
+ "<mask> <server> :<hopcount> <server info>"
+ 365 RPL_ENDOFLINKS
+ "<mask> :End of /LINKS list"
+
+ - In replying to the LINKS message, a server must send
+ replies back using the RPL_LINKS numeric and mark the
+ end of the list using an RPL_ENDOFLINKS reply.
+
+ 367 RPL_BANLIST
+ "<channel> <banid>"
+ 368 RPL_ENDOFBANLIST
+
+
+
+Oikarinen & Reed [Page 51]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ "<channel> :End of channel ban list"
+
+ - When listing the active 'bans' for a given channel,
+ a server is required to send the list back using the
+ RPL_BANLIST and RPL_ENDOFBANLIST messages. A separate
+ RPL_BANLIST is sent for each active banid. After the
+ banids have been listed (or if none present) a
+ RPL_ENDOFBANLIST must be sent.
+
+ 371 RPL_INFO
+ ":<string>"
+ 374 RPL_ENDOFINFO
+ ":End of /INFO list"
+
+ - A server responding to an INFO message is required to
+ send all its 'info' in a series of RPL_INFO messages
+ with a RPL_ENDOFINFO reply to indicate the end of the
+ replies.
+
+ 375 RPL_MOTDSTART
+ ":- <server> Message of the day - "
+ 372 RPL_MOTD
+ ":- <text>"
+ 376 RPL_ENDOFMOTD
+ ":End of /MOTD command"
+
+ - When responding to the MOTD message and the MOTD file
+ is found, the file is displayed line by line, with
+ each line no longer than 80 characters, using
+ RPL_MOTD format replies. These should be surrounded
+ by a RPL_MOTDSTART (before the RPL_MOTDs) and an
+ RPL_ENDOFMOTD (after).
+
+ 381 RPL_YOUREOPER
+ ":You are now an IRC operator"
+
+ - RPL_YOUREOPER is sent back to a client which has
+ just successfully issued an OPER message and gained
+ operator status.
+
+ 382 RPL_REHASHING
+ "<config file> :Rehashing"
+
+ - If the REHASH option is used and an operator sends
+ a REHASH message, an RPL_REHASHING is sent back to
+ the operator.
+
+ 391 RPL_TIME
+
+
+
+Oikarinen & Reed [Page 52]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ "<server> :<string showing server's local time>"
+
+ - When replying to the TIME message, a server must send
+ the reply using the RPL_TIME format above. The string
+ showing the time need only contain the correct day and
+ time there. There is no further requirement for the
+ time string.
+
+ 392 RPL_USERSSTART
+ ":UserID Terminal Host"
+ 393 RPL_USERS
+ ":%-8s %-9s %-8s"
+ 394 RPL_ENDOFUSERS
+ ":End of users"
+ 395 RPL_NOUSERS
+ ":Nobody logged in"
+
+ - If the USERS message is handled by a server, the
+ replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
+ RPL_NOUSERS are used. RPL_USERSSTART must be sent
+ first, following by either a sequence of RPL_USERS
+ or a single RPL_NOUSER. Following this is
+ RPL_ENDOFUSERS.
+
+ 200 RPL_TRACELINK
+ "Link <version & debug level> <destination> \
+ <next server>"
+ 201 RPL_TRACECONNECTING
+ "Try. <class> <server>"
+ 202 RPL_TRACEHANDSHAKE
+ "H.S. <class> <server>"
+ 203 RPL_TRACEUNKNOWN
+ "???? <class> [<client IP address in dot form>]"
+ 204 RPL_TRACEOPERATOR
+ "Oper <class> <nick>"
+ 205 RPL_TRACEUSER
+ "User <class> <nick>"
+ 206 RPL_TRACESERVER
+ "Serv <class> <int>S <int>C <server> \
+ <nick!user|*!*>@<host|server>"
+ 208 RPL_TRACENEWTYPE
+ "<newtype> 0 <client name>"
+ 261 RPL_TRACELOG
+ "File <logfile> <debug level>"
+
+ - The RPL_TRACE* are all returned by the server in
+ response to the TRACE message. How many are
+ returned is dependent on the the TRACE message and
+
+
+
+Oikarinen & Reed [Page 53]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ whether it was sent by an operator or not. There
+ is no predefined order for which occurs first.
+ Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+ RPL_TRACEHANDSHAKE are all used for connections
+ which have not been fully established and are either
+ unknown, still attempting to connect or in the
+ process of completing the 'server handshake'.
+ RPL_TRACELINK is sent by any server which handles
+ a TRACE message and has to pass it on to another
+ server. The list of RPL_TRACELINKs sent in
+ response to a TRACE command traversing the IRC
+ network should reflect the actual connectivity of
+ the servers themselves along that path.
+ RPL_TRACENEWTYPE is to be used for any connection
+ which does not fit in the other categories but is
+ being displayed anyway.
+
+ 211 RPL_STATSLINKINFO
+ "<linkname> <sendq> <sent messages> \
+ <sent bytes> <received messages> \
+ <received bytes> <time open>"
+ 212 RPL_STATSCOMMANDS
+ "<command> <count>"
+ 213 RPL_STATSCLINE
+ "C <host> * <name> <port> <class>"
+ 214 RPL_STATSNLINE
+ "N <host> * <name> <port> <class>"
+ 215 RPL_STATSILINE
+ "I <host> * <host> <port> <class>"
+ 216 RPL_STATSKLINE
+ "K <host> * <username> <port> <class>"
+ 218 RPL_STATSYLINE
+ "Y <class> <ping frequency> <connect \
+ frequency> <max sendq>"
+ 219 RPL_ENDOFSTATS
+ "<stats letter> :End of /STATS report"
+ 241 RPL_STATSLLINE
+ "L <hostmask> * <servername> <maxdepth>"
+ 242 RPL_STATSUPTIME
+ ":Server Up %d days %d:%02d:%02d"
+ 243 RPL_STATSOLINE
+ "O <hostmask> * <name>"
+ 244 RPL_STATSHLINE
+ "H <hostmask> * <servername>"
+
+ 221 RPL_UMODEIS
+ "<user mode string>"
+
+
+
+
+Oikarinen & Reed [Page 54]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ - To answer a query about a client's own mode,
+ RPL_UMODEIS is sent back.
+
+ 251 RPL_LUSERCLIENT
+ ":There are <integer> users and <integer> \
+ invisible on <integer> servers"
+ 252 RPL_LUSEROP
+ "<integer> :operator(s) online"
+ 253 RPL_LUSERUNKNOWN
+ "<integer> :unknown connection(s)"
+ 254 RPL_LUSERCHANNELS
+ "<integer> :channels formed"
+ 255 RPL_LUSERME
+ ":I have <integer> clients and <integer> \
+ servers"
+
+ - In processing an LUSERS message, the server
+ sends a set of replies from RPL_LUSERCLIENT,
+ RPL_LUSEROP, RPL_USERUNKNOWN,
+ RPL_LUSERCHANNELS and RPL_LUSERME. When
+ replying, a server must send back
+ RPL_LUSERCLIENT and RPL_LUSERME. The other
+ replies are only sent back if a non-zero count
+ is found for them.
+
+ 256 RPL_ADMINME
+ "<server> :Administrative info"
+ 257 RPL_ADMINLOC1
+ ":<admin info>"
+ 258 RPL_ADMINLOC2
+ ":<admin info>"
+ 259 RPL_ADMINEMAIL
+ ":<admin info>"
+
+ - When replying to an ADMIN message, a server
+ is expected to use replies RLP_ADMINME
+ through to RPL_ADMINEMAIL and provide a text
+ message with each. For RPL_ADMINLOC1 a
+ description of what city, state and country
+ the server is in is expected, followed by
+ details of the university and department
+ (RPL_ADMINLOC2) and finally the administrative
+ contact for the server (an email address here
+ is required) in RPL_ADMINEMAIL.
+
+
+
+
+
+
+
+Oikarinen & Reed [Page 55]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+6.3 Reserved numerics.
+
+ These numerics are not described above since they fall into one of
+ the following categories:
+
+ 1. no longer in use;
+
+ 2. reserved for future planned use;
+
+ 3. in current use but are part of a non-generic 'feature' of
+ the current IRC server.
+
+ 209 RPL_TRACECLASS 217 RPL_STATSQLINE
+ 231 RPL_SERVICEINFO 232 RPL_ENDOFSERVICES
+ 233 RPL_SERVICE 234 RPL_SERVLIST
+ 235 RPL_SERVLISTEND
+ 316 RPL_WHOISCHANOP 361 RPL_KILLDONE
+ 362 RPL_CLOSING 363 RPL_CLOSEEND
+ 373 RPL_INFOSTART 384 RPL_MYPORTIS
+ 466 ERR_YOUWILLBEBANNED 476 ERR_BADCHANMASK
+ 492 ERR_NOSERVICEHOST
+
+7. Client and server authentication
+
+ Clients and servers are both subject to the same level of
+ authentication. For both, an IP number to hostname lookup (and
+ reverse check on this) is performed for all connections made to the
+ server. Both connections are then subject to a password check (if
+ there is a password set for that connection). These checks are
+ possible on all connections although the password check is only
+ commonly used with servers.
+
+ An additional check that is becoming of more and more common is that
+ of the username responsible for making the connection. Finding the
+ username of the other end of the connection typically involves
+ connecting to an authentication server such as IDENT as described in
+ RFC 1413.
+
+ Given that without passwords it is not easy to reliably determine who
+ is on the other end of a network connection, use of passwords is
+ strongly recommended on inter-server connections in addition to any
+ other measures such as using an ident server.
+
+8. Current implementations
+
+ The only current implementation of this protocol is the IRC server,
+ version 2.8. Earlier versions may implement some or all of the
+ commands described by this document with NOTICE messages replacing
+
+
+
+Oikarinen & Reed [Page 56]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ many of the numeric replies. Unfortunately, due to backward
+ compatibility requirements, the implementation of some parts of this
+ document varies with what is laid out. On notable difference is:
+
+ * recognition that any LF or CR anywhere in a message marks the
+ end of that message (instead of requiring CR-LF);
+
+ The rest of this section deals with issues that are mostly of
+ importance to those who wish to implement a server but some parts
+ also apply directly to clients as well.
+
+8.1 Network protocol: TCP - why it is best used here.
+
+ IRC has been implemented on top of TCP since TCP supplies a reliable
+ network protocol which is well suited to this scale of conferencing.
+ The use of multicast IP is an alternative, but it is not widely
+ available or supported at the present time.
+
+8.1.1 Support of Unix sockets
+
+ Given that Unix domain sockets allow listen/connect operations, the
+ current implementation can be configured to listen and accept both
+ client and server connections on a Unix domain socket. These are
+ recognized as sockets where the hostname starts with a '/'.
+
+ When providing any information about the connections on a Unix domain
+ socket, the server is required to supplant the actual hostname in
+ place of the pathname unless the actual socket name is being asked
+ for.
+
+8.2 Command Parsing
+
+ To provide useful 'non-buffered' network IO for clients and servers,
+ each connection is given its own private 'input buffer' in which the
+ results of the most recent read and parsing are kept. A buffer size
+ of 512 bytes is used so as to hold 1 full message, although, this
+ will usually hold several commands. The private buffer is parsed
+ after every read operation for valid messages. When dealing with
+ multiple messages from one client in the buffer, care should be taken
+ in case one happens to cause the client to be 'removed'.
+
+8.3 Message delivery
+
+ It is common to find network links saturated or hosts to which you
+ are sending data unable to send data. Although Unix typically
+ handles this through the TCP window and internal buffers, the server
+ often has large amounts of data to send (especially when a new
+ server-server link forms) and the small buffers provided in the
+
+
+
+Oikarinen & Reed [Page 57]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ kernel are not enough for the outgoing queue. To alleviate this
+ problem, a "send queue" is used as a FIFO queue for data to be sent.
+ A typical "send queue" may grow to 200 Kbytes on a large IRC network
+ with a slow network connection when a new server connects.
+
+ When polling its connections, a server will first read and parse all
+ incoming data, queuing any data to be sent out. When all available
+ input is processed, the queued data is sent. This reduces the number
+ of write() system calls and helps TCP make bigger packets.
+
+8.4 Connection 'Liveness'
+
+ To detect when a connection has died or become unresponsive, the
+ server must ping each of its connections that it doesn't get a
+ response from in a given amount of time.
+
+ If a connection doesn't respond in time, its connection is closed
+ using the appropriate procedures. A connection is also dropped if
+ its sendq grows beyond the maximum allowed, because it is better to
+ close a slow connection than have a server process block.
+
+8.5 Establishing a server to client connection
+
+ Upon connecting to an IRC server, a client is sent the MOTD (if
+ present) as well as the current user/server count (as per the LUSER
+ command). The server is also required to give an unambiguous message
+ to the client which states its name and version as well as any other
+ introductory messages which may be deemed appropriate.
+
+ After dealing with this, the server must then send out the new user's
+ nickname and other information as supplied by itself (USER command)
+ and as the server could discover (from DNS/authentication servers).
+ The server must send this information out with NICK first followed by
+ USER.
+
+8.6 Establishing a server-server connection.
+
+ The process of establishing of a server-to-server connection is
+ fraught with danger since there are many possible areas where
+ problems can occur - the least of which are race conditions.
+
+ After a server has received a connection following by a PASS/SERVER
+ pair which were recognised as being valid, the server should then
+ reply with its own PASS/SERVER information for that connection as
+ well as all of the other state information it knows about as
+ described below.
+
+ When the initiating server receives a PASS/SERVER pair, it too then
+
+
+
+Oikarinen & Reed [Page 58]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ checks that the server responding is authenticated properly before
+ accepting the connection to be that server.
+
+8.6.1 Server exchange of state information when connecting
+
+ The order of state information being exchanged between servers is
+ essential. The required order is as follows:
+
+ * all known other servers;
+
+ * all known user information;
+
+ * all known channel information.
+
+ Information regarding servers is sent via extra SERVER messages, user
+ information with NICK/USER/MODE/JOIN messages and channels with MODE
+ messages.
+
+ NOTE: channel topics are *NOT* exchanged here because the TOPIC
+ command overwrites any old topic information, so at best, the two
+ sides of the connection would exchange topics.
+
+ By passing the state information about servers first, any collisions
+ with servers that already exist occur before nickname collisions due
+ to a second server introducing a particular nickname. Due to the IRC
+ network only being able to exist as an acyclic graph, it may be
+ possible that the network has already reconnected in another
+ location, the place where the collision occurs indicating where the
+ net needs to split.
+
+8.7 Terminating server-client connections
+
+ When a client connection closes, a QUIT message is generated on
+ behalf of the client by the server to which the client connected. No
+ other message is to be generated or used.
+
+8.8 Terminating server-server connections
+
+ If a server-server connection is closed, either via a remotely
+ generated SQUIT or 'natural' causes, the rest of the connected IRC
+ network must have its information updated with by the server which
+ detected the closure. The server then sends a list of SQUITs (one
+ for each server behind that connection) and a list of QUITs (again,
+ one for each client behind that connection).
+
+
+
+
+
+
+
+Oikarinen & Reed [Page 59]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+8.9 Tracking nickname changes
+
+ All IRC servers are required to keep a history of recent nickname
+ changes. This is required to allow the server to have a chance of
+ keeping in touch of things when nick-change race conditions occur
+ with commands which manipulate them. Commands which must trace nick
+ changes are:
+
+ * KILL (the nick being killed)
+
+ * MODE (+/- o,v)
+
+ * KICK (the nick being kicked)
+
+ No other commands are to have nick changes checked for.
+
+ In the above cases, the server is required to first check for the
+ existence of the nickname, then check its history to see who that
+ nick currently belongs to (if anyone!). This reduces the chances of
+ race conditions but they can still occur with the server ending up
+ affecting the wrong client. When performing a change trace for an
+ above command it is recommended that a time range be given and
+ entries which are too old ignored.
+
+ For a reasonable history, a server should be able to keep previous
+ nickname for every client it knows about if they all decided to
+ change. This size is limited by other factors (such as memory, etc).
+
+8.10 Flood control of clients
+
+ With a large network of interconnected IRC servers, it is quite easy
+ for any single client attached to the network to supply a continuous
+ stream of messages that result in not only flooding the network, but
+ also degrading the level of service provided to others. Rather than
+ require every 'victim' to be provide their own protection, flood
+ protection was written into the server and is applied to all clients
+ except services. The current algorithm is as follows:
+
+ * check to see if client's `message timer' is less than
+ current time (set to be equal if it is);
+
+ * read any data present from the client;
+
+ * while the timer is less than ten seconds ahead of the current
+ time, parse any present messages and penalize the client by
+ 2 seconds for each message;
+
+ which in essence means that the client may send 1 message every 2
+
+
+
+Oikarinen & Reed [Page 60]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ seconds without being adversely affected.
+
+8.11 Non-blocking lookups
+
+ In a real-time environment, it is essential that a server process do
+ as little waiting as possible so that all the clients are serviced
+ fairly. Obviously this requires non-blocking IO on all network
+ read/write operations. For normal server connections, this was not
+ difficult, but there are other support operations that may cause the
+ server to block (such as disk reads). Where possible, such activity
+ should be performed with a short timeout.
+
+8.11.1 Hostname (DNS) lookups
+
+ Using the standard resolver libraries from Berkeley and others has
+ meant large delays in some cases where replies have timed out. To
+ avoid this, a separate set of DNS routines were written which were
+ setup for non-blocking IO operations and then polled from within the
+ main server IO loop.
+
+8.11.2 Username (Ident) lookups
+
+ Although there are numerous ident libraries for use and inclusion
+ into other programs, these caused problems since they operated in a
+ synchronous manner and resulted in frequent delays. Again the
+ solution was to write a set of routines which would cooperate with
+ the rest of the server and work using non-blocking IO.
+
+8.12 Configuration File
+
+ To provide a flexible way of setting up and running the server, it is
+ recommended that a configuration file be used which contains
+ instructions to the server on the following:
+
+ * which hosts to accept client connections from;
+
+ * which hosts to allow to connect as servers;
+
+ * which hosts to connect to (both actively and
+ passively);
+
+ * information about where the server is (university,
+ city/state, company are examples of this);
+
+ * who is responsible for the server and an email address
+ at which they can be contacted;
+
+ * hostnames and passwords for clients which wish to be given
+
+
+
+Oikarinen & Reed [Page 61]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ access to restricted operator commands.
+
+ In specifying hostnames, both domain names and use of the 'dot'
+ notation (127.0.0.1) should both be accepted. It must be possible to
+ specify the password to be used/accepted for all outgoing and
+ incoming connections (although the only outgoing connections are
+ those to other servers).
+
+ The above list is the minimum requirement for any server which wishes
+ to make a connection with another server. Other items which may be
+ of use are:
+
+ * specifying which servers other server may introduce;
+
+ * how deep a server branch is allowed to become;
+
+ * hours during which clients may connect.
+
+8.12.1 Allowing clients to connect
+
+ A server should use some sort of 'access control list' (either in the
+ configuration file or elsewhere) that is read at startup and used to
+ decide what hosts clients may use to connect to it.
+
+ Both 'deny' and 'allow' should be implemented to provide the required
+ flexibility for host access control.
+
+8.12.2 Operators
+
+ The granting of operator privileges to a disruptive person can have
+ dire consequences for the well-being of the IRC net in general due to
+ the powers given to them. Thus, the acquisition of such powers
+ should not be very easy. The current setup requires two 'passwords'
+ to be used although one of them is usually easy guessed. Storage of
+ oper passwords in configuration files is preferable to hard coding
+ them in and should be stored in a crypted format (ie using crypt(3)
+ from Unix) to prevent easy theft.
+
+8.12.3 Allowing servers to connect
+
+ The interconnection of server is not a trivial matter: a bad
+ connection can have a large impact on the usefulness of IRC. Thus,
+ each server should have a list of servers to which it may connect and
+ which servers may connect to it. Under no circumstances should a
+ server allow an arbitrary host to connect as a server. In addition
+ to which servers may and may not connect, the configuration file
+ should also store the password and other characteristics of that
+ link.
+
+
+
+Oikarinen & Reed [Page 62]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+8.12.4 Administrivia
+
+ To provide accurate and valid replies to the ADMIN command (see
+ section 4.3.7), the server should find the relevant details in the
+ configuration.
+
+8.13 Channel membership
+
+ The current server allows any registered local user to join upto 10
+ different channels. There is no limit imposed on non-local users so
+ that the server remains (reasonably) consistant with all others on a
+ channel membership basis
+
+9. Current problems
+
+ There are a number of recognized problems with this protocol, all of
+ which hope to be solved sometime in the near future during its
+ rewrite. Currently, work is underway to find working solutions to
+ these problems.
+
+9.1 Scalability
+
+ It is widely recognized that this protocol does not scale
+ sufficiently well when used in a large arena. The main problem comes
+ from the requirement that all servers know about all other servers
+ and users and that information regarding them be updated as soon as
+ it changes. It is also desirable to keep the number of servers low
+ so that the path length between any two points is kept minimal and
+ the spanning tree as strongly branched as possible.
+
+9.2 Labels
+
+ The current IRC protocol has 3 types of labels: the nickname, the
+ channel name and the server name. Each of the three types has its
+ own domain and no duplicates are allowed inside that domain.
+ Currently, it is possible for users to pick the label for any of the
+ three, resulting in collisions. It is widely recognized that this
+ needs reworking, with a plan for unique names for channels and nicks
+ that don't collide being desirable as well as a solution allowing a
+ cyclic tree.
+
+9.2.1 Nicknames
+
+ The idea of the nickname on IRC is very convenient for users to use
+ when talking to each other outside of a channel, but there is only a
+ finite nickname space and being what they are, its not uncommon for
+ several people to want to use the same nick. If a nickname is chosen
+ by two people using this protocol, either one will not succeed or
+
+
+
+Oikarinen & Reed [Page 63]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+ both will removed by use of KILL (4.6.1).
+
+9.2.2 Channels
+
+ The current channel layout requires that all servers know about all
+ channels, their inhabitants and properties. Besides not scaling
+ well, the issue of privacy is also a concern. A collision of
+ channels is treated as an inclusive event (both people who create the
+ new channel are considered to be members of it) rather than an
+ exclusive one such as used to solve nickname collisions.
+
+9.2.3 Servers
+
+ Although the number of servers is usually small relative to the
+ number of users and channels, they two currently required to be known
+ globally, either each one separately or hidden behind a mask.
+
+9.3 Algorithms
+
+ In some places within the server code, it has not been possible to
+ avoid N^2 algorithms such as checking the channel list of a set
+ of clients.
+
+ In current server versions, there are no database consistency checks,
+ each server assumes that a neighbouring server is correct. This
+ opens the door to large problems if a connecting server is buggy or
+ otherwise tries to introduce contradictions to the existing net.
+
+ Currently, because of the lack of unique internal and global labels,
+ there are a multitude of race conditions that exist. These race
+ conditions generally arise from the problem of it taking time for
+ messages to traverse and effect the IRC network. Even by changing to
+ unique labels, there are problems with channel-related commands being
+ disrupted.
+
+10. Current support and availability
+
+ Mailing lists for IRC related discussion:
+ Future protocol: ircd-three-request@eff.org
+ General discussion: operlist-request@eff.org
+
+ Software implemenations
+ cs.bu.edu:/irc
+ nic.funet.fi:/pub/irc
+ coombs.anu.edu.au:/pub/irc
+
+ Newsgroup: alt.irc
+
+
+
+
+Oikarinen & Reed [Page 64]
+
+RFC 1459 Internet Relay Chat Protocol May 1993
+
+
+Security Considerations
+
+ Security issues are discussed in sections 4.1, 4.1.1, 4.1.3, 5.5, and
+ 7.
+
+12. Authors' Addresses
+
+ Jarkko Oikarinen
+ Tuirantie 17 as 9
+ 90500 OULU
+ FINLAND
+
+ Email: jto@tolsun.oulu.fi
+
+
+ Darren Reed
+ 4 Pateman Street
+ Watsonia, Victoria 3087
+ Australia
+
+ Email: avalon@coombs.anu.edu.au
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Oikarinen & Reed [Page 65]
+ \ No newline at end of file
diff --git a/irc_mod/Docs/rfc2810.txt b/irc_mod/Docs/rfc2810.txt
new file mode 100644
index 0000000..e628a83
--- /dev/null
+++ b/irc_mod/Docs/rfc2810.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group C. Kalt
+Request for Comments: 2810 April 2000
+Updates: 1459
+Category: Informational
+
+
+ Internet Relay Chat: Architecture
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ The IRC (Internet Relay Chat) protocol is for use with text based
+ conferencing. It has been developed since 1989 when it was originally
+ implemented as a mean for users on a BBS to chat amongst themselves.
+
+ First formally documented in May 1993 by RFC 1459 [IRC], the protocol
+ has kept evolving. This document is an update describing the
+ architecture of the current IRC protocol and the role of its
+ different components. Other documents describe in detail the
+ protocol used between the various components defined here.
+
+Table of Contents
+
+ 1. Introduction ............................................... 2
+ 2. Components ................................................. 2
+ 2.1 Servers ................................................ 2
+ 2.2 Clients ................................................ 3
+ 2.2.1 User Clients ...................................... 3
+ 2.2.2 Service Clients ................................... 3
+ 3. Architecture ............................................... 3
+ 4. IRC Protocol Services ...................................... 4
+ 4.1 Client Locator ......................................... 4
+ 4.2 Message Relaying ....................................... 4
+ 4.3 Channel Hosting And Management ......................... 4
+ 5. IRC Concepts ............................................... 4
+ 5.1 One-To-One Communication ............................... 5
+ 5.2 One-To-Many ............................................ 5
+ 5.2.1 To A Channel ...................................... 5
+ 5.2.2 To A Host/Server Mask ............................. 6
+
+
+
+Kalt Informational [Page 1]
+
+RFC 2810 Internet Relay Chat: Architecture April 2000
+
+
+ 5.2.3 To A List ......................................... 6
+ 5.3 One-To-All ............................................. 6
+ 5.3.1 Client-to-Client .................................. 6
+ 5.3.2 Client-to-Server .................................. 7
+ 5.3.3 Server-to-Server .................................. 7
+ 6. Current Problems ........................................... 7
+ 6.1 Scalability ............................................ 7
+ 6.2 Reliability ............................................ 7
+ 6.3 Network Congestion ..................................... 7
+ 6.4 Privacy ................................................ 8
+ 7. Security Considerations .................................... 8
+ 8. Current Support And Availability ........................... 8
+ 9. Acknowledgements ........................................... 8
+ 10. References ................................................ 8
+ 11. Author's Address .......................................... 9
+ 12. Full Copyright Statement .................................. 10
+
+1. Introduction
+
+ The IRC (Internet Relay Chat) protocol has been designed over a
+ number of years for use with text based conferencing. This document
+ describes its current architecture.
+
+ The IRC Protocol is based on the client-server model, and is well
+ suited to running on many machines in a distributed fashion. A
+ typical setup involves a single process (the server) forming a
+ central point for clients (or other servers) to connect to,
+ performing the required message delivery/multiplexing and other
+ functions.
+
+ This distributed model, which requires each server to have a copy
+ of the global state information, is still the most flagrant problem
+ of the protocol as it is a serious handicap, which limits the maximum
+ size a network can reach. If the existing networks have been able to
+ keep growing at an incredible pace, we must thank hardware
+ manufacturers for giving us ever more powerful systems.
+
+2. Components
+
+ The following paragraphs define the basic components of the IRC
+ protocol.
+
+2.1 Servers
+
+ The server forms the backbone of IRC as it is the only component
+ of the protocol which is able to link all the other components
+ together: it provides a point to which clients may connect to talk to
+
+
+
+
+Kalt Informational [Page 2]
+
+RFC 2810 Internet Relay Chat: Architecture April 2000
+
+
+ each other [IRC-CLIENT], and a point for other servers to connect to
+ [IRC-SERVER]. The server is also responsible for providing the basic
+ services defined by the IRC protocol.
+
+2.2 Clients
+
+ A client is anything connecting to a server that is not another
+ server. There are two types of clients which both serve a different
+ purpose.
+
+2.2.1 User Clients
+
+ User clients are generally programs providing a text based
+ interface that is used to communicate interactively via IRC. This
+ particular type of clients is often referred as "users".
+
+2.2.2 Service Clients
+
+ Unlike users, service clients are not intended to be used manually
+ nor for talking. They have a more limited access to the chat
+ functions of the protocol, while optionally having access to more
+ private data from the servers.
+
+ Services are typically automatons used to provide some kind of
+ service (not necessarily related to IRC itself) to users. An example
+ is a service collecting statistics about the origin of users
+ connected on the IRC network.
+
+3. Architecture
+
+ An IRC network is defined by a group of servers connected to each
+ other. A single server forms the simplest IRC network.
+
+ The only network configuration allowed for IRC servers is that of
+ a spanning tree where each server acts as a central node for the rest
+ of the network it sees.
+
+ 1--\
+ A D---4
+ 2--/ \ /
+ B----C
+ / \
+ 3 E
+
+ Servers: A, B, C, D, E Clients: 1, 2, 3, 4
+
+ [ Fig. 1. Sample small IRC network ]
+
+
+
+
+Kalt Informational [Page 3]
+
+RFC 2810 Internet Relay Chat: Architecture April 2000
+
+
+ The IRC protocol provides no mean for two clients to directly
+ communicate. All communication between clients is relayed by the
+ server(s).
+
+4. IRC Protocol Services
+
+ This section describes the services offered by the IRC protocol. The
+ combination of these services allow real-time conferencing.
+
+4.1 Client Locator
+
+ To be able to exchange messages, two clients must be able to locate
+ each other.
+
+ Upon connecting to a server, a client registers using a label which
+ is then used by other servers and clients to know where the client is
+ located. Servers are responsible for keeping track of all the labels
+ being used.
+
+4.2 Message Relaying
+
+ The IRC protocol provides no mean for two clients to directly
+ communicate. All communication between clients is relayed by the
+ server(s).
+
+4.3 Channel Hosting And Management
+
+ A channel is a named group of one or more users which will all
+ receive messages addressed to that channel. A channel is
+ characterized by its name and current members, it also has a set of
+ properties which can be manipulated by (some of) its members.
+
+ Channels provide a mean for a message to be sent to several clients.
+ Servers host channels, providing the necessary message multiplexing.
+ Servers are also responsible for managing channels by keeping track
+ of the channel members. The exact role of servers is defined in
+ "Internet Relay Chat: Channel Management" [IRC-CHAN].
+
+5. IRC Concepts
+
+ This section is devoted to describing the actual concepts behind the
+ organization of the IRC protocol and how different classes of
+ messages are delivered.
+
+
+
+
+
+
+
+
+Kalt Informational [Page 4]
+
+RFC 2810 Internet Relay Chat: Architecture April 2000
+
+
+5.1 One-To-One Communication
+
+ Communication on a one-to-one basis is usually performed by clients,
+ since most server-server traffic is not a result of servers talking
+ only to each other. To provide a means for clients to talk to each
+ other, it is REQUIRED that all servers be able to send a message in
+ exactly one direction along the spanning tree in order to reach any
+ client. Thus the path of a message being delivered is the shortest
+ path between any two points on the spanning tree.
+
+ The following examples all refer to Figure 1 above.
+
+ Example 1: A message between clients 1 and 2 is only seen by server
+ A, which sends it straight to client 2.
+
+ Example 2: A message between clients 1 and 3 is seen by servers A &
+ B, and client 3. No other clients or servers are allowed see the
+ message.
+
+ Example 3: A message between clients 2 and 4 is seen by servers A, B,
+ C & D and client 4 only.
+
+5.2 One-To-Many
+
+ The main goal of IRC is to provide a forum which allows easy and
+ efficient conferencing (one to many conversations). IRC offers
+ several means to achieve this, each serving its own purpose.
+
+5.2.1 To A Channel
+
+ In IRC the channel has a role equivalent to that of the multicast
+ group; their existence is dynamic and the actual conversation carried
+ out on a channel MUST only be sent to servers which are supporting
+ users on a given channel. Moreover, the message SHALL only be sent
+ once to every local link as each server is responsible to fan the
+ original message to ensure that it will reach all the recipients.
+
+ The following examples all refer to Figure 2.
+
+ Example 4: Any channel with 1 client in it. Messages to the channel
+ go to the server and then nowhere else.
+
+ Example 5: 2 clients in a channel. All messages traverse a path as if
+ they were private messages between the two clients outside a
+ channel.
+
+
+
+
+
+
+Kalt Informational [Page 5]
+
+RFC 2810 Internet Relay Chat: Architecture April 2000
+
+
+ Example 6: Clients 1, 2 and 3 in a channel. All messages to the
+ channel are sent to all clients and only those servers which must
+ be traversed by the message if it were a private message to a
+ single client. If client 1 sends a message, it goes back to
+ client 2 and then via server B to client 3.
+
+5.2.2 To A Host/Server Mask
+
+ To provide with some mechanism to send messages to a large body of
+ related users, host and server mask messages are available. These
+ messages are sent to users whose host or server information match
+ that of the mask. The messages are only sent to locations where
+ users are, in a fashion similar to that of channels.
+
+5.2.3 To A List
+
+ The least efficient style of one-to-many conversation is through
+ clients talking to a 'list' of targets (client, channel, mask). How
+ this is done is almost self explanatory: the client gives a list of
+ destinations to which the message is to be delivered and the server
+ breaks it up and dispatches a separate copy of the message to each
+ given destination.
+
+ This is not as efficient as using a channel since the destination
+ list MAY be broken up and the dispatch sent without checking to make
+ sure duplicates aren't sent down each path.
+
+5.3 One-To-All
+
+ The one-to-all type of message is better described as a broadcast
+ message, sent to all clients or servers or both. On a large network
+ of users and servers, a single message can result in a lot of traffic
+ being sent over the network in an effort to reach all of the desired
+ destinations.
+
+ For some class of messages, there is no option but to broadcast it to
+ all servers so that the state information held by each server is
+ consistent between servers.
+
+5.3.1 Client-to-Client
+
+ There is no class of message which, from a single message, results in
+ a message being sent to every other client.
+
+
+
+
+
+
+
+
+Kalt Informational [Page 6]
+
+RFC 2810 Internet Relay Chat: Architecture April 2000
+
+
+5.3.2 Client-to-Server
+
+ Most of the commands which result in a change of state information
+ (such as channel membership, channel mode, user status, etc.) MUST be
+ sent to all servers by default, and this distribution SHALL NOT be
+ changed by the client.
+
+5.3.3 Server-to-Server
+
+ While most messages between servers are distributed to all 'other'
+ servers, this is only required for any message that affects a user,
+ channel or server. Since these are the basic items found in IRC,
+ nearly all messages originating from a server are broadcast to all
+ other connected servers.
+
+6. Current Problems
+
+ There are a number of recognized problems with this protocol, this
+ section only addresses the problems related to the architecture of
+ the protocol.
+
+6.1 Scalability
+
+ It is widely recognized that this protocol does not scale
+ sufficiently well when used in a large arena. The main problem comes
+ from the requirement that all servers know about all other servers,
+ clients and channels and that information regarding them be updated
+ as soon as it changes.
+
+6.2 Reliability
+
+ As the only network configuration allowed for IRC servers is that of
+ a spanning tree, each link between two servers is an obvious and
+ quite serious point of failure. This particular issue is addressed
+ more in detail in "Internet Relay Chat: Server Protocol" [IRC-
+ SERVER].
+
+6.3 Network Congestion
+
+ Another problem related to the scalability and reliability issues, as
+ well as the spanning tree architecture, is that the protocol and
+ architecture for IRC are extremely vulnerable to network congestions.
+ This problem is endemic, and should be solved for the next
+ generation: if congestion and high traffic volume cause a link
+ between two servers to fail, not only this failure generates more
+ network traffic, but the reconnection (eventually elsewhere) of two
+ servers also generates more traffic.
+
+
+
+
+Kalt Informational [Page 7]
+
+RFC 2810 Internet Relay Chat: Architecture April 2000
+
+
+ In an attempt to minimize the impact of these problems, it is
+ strongly RECOMMENDED that servers do not automatically try to
+ reconnect too fast, in order to avoid aggravating the situation.
+
+6.4 Privacy
+
+ Besides not scaling well, the fact that servers need to know all
+ information about other entities, the issue of privacy is also a
+ concern. This is in particular true for channels, as the related
+ information is quite a lot more revealing than whether a user is
+ online or not.
+
+7. Security Considerations
+
+ Asides from the privacy concerns mentioned in section 6.4 (Privacy),
+ security is believed to be irrelevant to this document.
+
+8. Current Support And Availability
+
+ Mailing lists for IRC related discussion:
+ General discussion: ircd-users@irc.org
+ Protocol development: ircd-dev@irc.org
+
+ Software implementations:
+ ftp://ftp.irc.org/irc/server
+ ftp://ftp.funet.fi/pub/unix/irc
+ ftp://coombs.anu.edu.au/pub/irc
+
+ Newsgroup: alt.irc
+
+9. Acknowledgements
+
+ Parts of this document were copied from the RFC 1459 [IRC] which
+ first formally documented the IRC Protocol. It has also benefited
+ from many rounds of review and comments. In particular, the
+ following people have made significant contributions to this
+ document:
+
+ Matthew Green, Michael Neumayer, Volker Paulsen, Kurt Roeckx, Vesa
+ Ruokonen, Magnus Tjernstrom, Stefan Zehl.
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 8]
+
+RFC 2810 Internet Relay Chat: Architecture April 2000
+
+
+10. References
+
+ [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [IRC] Oikarinen, J. and D. Reed, "Internet Relay Chat
+ Protocol", RFC 1459, May 1993.
+
+ [IRC-CLIENT] Kalt, C., "Internet Relay Chat: Client Protocol", RFC
+ 2812, April 2000.
+
+ [IRC-SERVER] Kalt, C., "Internet Relay Chat: Server Protocol", RFC
+ 2813, April 2000.
+
+ [IRC-CHAN] Kalt, C., "Internet Relay Chat: Channel Management", RFC
+ 2811, April 2000.
+
+11. Author's Address
+
+ Christophe Kalt
+ 99 Teaneck Rd, Apt #117
+ Ridgefield Park, NJ 07660
+ USA
+
+ EMail: kalt@stealth.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 9]
+
+RFC 2810 Internet Relay Chat: Architecture April 2000
+
+
+12. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 10]
+
diff --git a/irc_mod/Docs/rfc2811.txt b/irc_mod/Docs/rfc2811.txt
new file mode 100644
index 0000000..7c2c4ea
--- /dev/null
+++ b/irc_mod/Docs/rfc2811.txt
@@ -0,0 +1,1067 @@
+
+
+
+
+
+
+Network Working Group C. Kalt
+Request for Comments: 2811 April 2000
+Updates: 1459
+Category: Informational
+
+
+ Internet Relay Chat: Channel Management
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ One of the most notable characteristics of the IRC (Internet Relay
+ Chat) protocol is to allow for users to be grouped in forums, called
+ channels, providing a mean for multiple users to communicate
+ together.
+
+ There was originally a unique type of channels, but with the years,
+ new types appeared either as a response to a need, or for
+ experimental purposes.
+
+ This document specifies how channels, their characteristics and
+ properties are managed by IRC servers.
+
+Table of Contents
+
+ 1. Introduction ............................................... 2
+ 2. Channel Characteristics .................................... 3
+ 2.1 Namespace .............................................. 3
+ 2.2 Channel Scope .......................................... 3
+ 2.3 Channel Properties ..................................... 4
+ 2.4 Privileged Channel Members ............................. 4
+ 2.4.1 Channel Operators ................................. 5
+ 2.4.2 Channel Creator ................................... 5
+ 3. Channel lifetime ........................................... 5
+ 3.1 Standard channels ...................................... 5
+ 3.2 Safe Channels .......................................... 6
+ 4. Channel Modes .............................................. 7
+ 4.1 Member Status .......................................... 7
+ 4.1.1 "Channel Creator" Status .......................... 7
+
+
+
+Kalt Informational [Page 1]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ 4.1.2 Channel Operator Status ........................... 8
+ 4.1.3 Voice Privilege ................................... 8
+ 4.2 Channel Flags .......................................... 8
+ 4.2.1 Anonymous Flag .................................... 8
+ 4.2.2 Invite Only Flag .................................. 8
+ 4.2.3 Moderated Channel Flag ............................ 9
+ 4.2.4 No Messages To Channel From Clients On The Outside 9
+ 4.2.5 Quiet Channel ..................................... 9
+ 4.2.6 Private and Secret Channels ....................... 9
+ 4.2.7 Server Reop Flag .................................. 10
+ 4.2.8 Topic ............................................. 10
+ 4.2.9 User Limit ........................................ 10
+ 4.2.10 Channel Key ...................................... 10
+ 4.3 Channel Access Control ................................. 10
+ 4.3.1 Channel Ban and Exception ......................... 11
+ 4.3.2 Channel Invitation ................................ 11
+ 5. Current Implementations .................................... 11
+ 5.1 Tracking Recently Used Channels ........................ 11
+ 5.2 Safe Channels .......................................... 12
+ 5.2.1 Channel Identifier ................................ 12
+ 5.2.2 Channel Delay ..................................... 12
+ 5.2.3 Abuse Window ...................................... 13
+ 5.2.4 Preserving Sanity In The Name Space ............... 13
+ 5.2.5 Server Reop Mechanism ............................. 13
+ 6. Current problems ........................................... 14
+ 6.1 Labels ................................................. 14
+ 6.1.1 Channel Delay ..................................... 14
+ 6.1.2 Safe Channels ..................................... 15
+ 6.2 Mode Propagation Delays ................................ 15
+ 6.3 Collisions And Channel Modes ........................... 15
+ 6.4 Resource Exhaustion .................................... 16
+ 7. Security Considerations .................................... 16
+ 7.1 Access Control ......................................... 16
+ 7.2 Channel Privacy ........................................ 16
+ 7.3 Anonymity ............................................... 17
+ 8. Current support and availability ........................... 17
+ 9. Acknowledgements ........................................... 17
+ 10. References ................................................ 18
+ 11. Author's Address .......................................... 18
+ 12. Full Copyright Statement ................................... 19
+
+1. Introduction
+
+ This document defines in detail on how channels are managed by the
+ IRC servers and will be mostly useful to people working on
+ implementing an IRC server.
+
+
+
+
+
+Kalt Informational [Page 2]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ While the concepts defined here are an important part of IRC, they
+ remain non essential for implementing clients. While the trend seems
+ to be towards more and more complex and "intelligent" clients which
+ are able to take advantage of knowing the internal workings of
+ channels to provide the users with a more friendly interface, simple
+ clients can be implemented without reading this document.
+
+ Many of the concepts defined here were designed with the IRC
+ architecture [IRC-ARCH] in mind and mostly make sense in this
+ context. However, many others could be applied to other
+ architectures in order to provide forums for a conferencing system.
+
+ Finally, it is to be noted that IRC users may find some of the
+ following sections of interest, in particular sections 2 (Channel
+ Characteristics) and 4 (Channel Modes).
+
+2. Channel Characteristics
+
+ A channel is a named group of one or more users which will all
+ receive messages addressed to that channel. A channel is
+ characterized by its name, properties and current members.
+
+2.1 Namespace
+
+ Channels names are strings (beginning with a '&', '#', '+' or '!'
+ character) of length up to fifty (50) characters. Channel names are
+ case insensitive.
+
+ Apart from the the requirement that the first character being either
+ '&', '#', '+' or '!' (hereafter called "channel prefix"). The only
+ restriction on a channel name is that it SHALL NOT contain any spaces
+ (' '), a control G (^G or ASCII 7), a comma (',' which is used as a
+ list item separator by the protocol). Also, a colon (':') is used as
+ a delimiter for the channel mask. The exact syntax of a channel name
+ is defined in "IRC Server Protocol" [IRC-SERVER].
+
+ The use of different prefixes effectively creates four (4) distinct
+ namespaces for channel names. This is important because of the
+ protocol limitations regarding namespaces (in general). See section
+ 6.1 (Labels) for more details on these limitations.
+
+2.2 Channel Scope
+
+ A channel entity is known by one or more servers on the IRC network.
+ A user can only become member of a channel known by the server to
+ which the user is directly connected. The list of servers which know
+
+
+
+
+
+Kalt Informational [Page 3]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ of the existence of a particular channel MUST be a contiguous part of
+ the IRC network, in order for the messages addressed to the channel
+ to be sent to all the channel members.
+
+ Channels with '&' as prefix are local to the server where they are
+ created.
+
+ Other channels are known to one (1) or more servers that are
+ connected to the network, depending on the channel mask:
+
+ If there is no channel mask, then the channel is known to all
+ the servers.
+
+ If there is a channel mask, then the channel MUST only be known
+ to servers which has a local user on the channel, and to its
+ neighbours if the mask matches both the local and neighbouring
+ server names. Since other servers have absolutely no knowledge of
+ the existence of such a channel, the area formed by the servers
+ having a name matching the mask has to be contiguous for the
+ channel to be known by all these servers. Channel masks are best
+ used in conjunction with server hostmasking [IRC-SERVER].
+
+2.3 Channel Properties
+
+ Each channel has its own properties, which are defined by channel
+ modes. Channel modes can be manipulated by the channel members. The
+ modes affect the way servers manage the channels.
+
+ Channels with '+' as prefix do not support channel modes. This means
+ that all the modes are unset, with the exception of the 't' channel
+ flag which is set.
+
+2.4 Privileged Channel Members
+
+ In order for the channel members to keep some control over a channel,
+ and some kind of sanity, some channel members are privileged. Only
+ these members are allowed to perform the following actions on the
+ channel:
+
+ INVITE - Invite a client to an invite-only channel (mode +i)
+ KICK - Eject a client from the channel
+ MODE - Change the channel's mode, as well as
+ members' privileges
+ PRIVMSG - Sending messages to the channel (mode +n, +m, +v)
+ TOPIC - Change the channel topic in a mode +t channel
+
+
+
+
+
+
+Kalt Informational [Page 4]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+2.4.1 Channel Operators
+
+ The channel operators (also referred to as a "chop" or "chanop") on a
+ given channel are considered to 'own' that channel. Ownership of a
+ channel is shared among channel operators.
+
+ Channel operators are identified by the '@' symbol next to their
+ nickname whenever it is associated with a channel (i.e., replies to
+ the NAMES, WHO and WHOIS commands).
+
+ Since channels starting with the character '+' as prefix do not
+ support channel modes, no member can therefore have the status of
+ channel operator.
+
+2.4.2 Channel Creator
+
+ A user who creates a channel with the character '!' as prefix is
+ identified as the "channel creator". Upon creation of the channel,
+ this user is also given channel operator status.
+
+ In recognition of this status, the channel creators are endowed with
+ the ability to toggle certain modes of the channel which channel
+ operators may not manipulate.
+
+ A "channel creator" can be distinguished from a channel operator by
+ issuing the proper MODE command. See the "IRC Client Protocol"
+ [IRC-CLIENT] for more information on this topic.
+
+3. Channel lifetime
+
+ In regard to the lifetime of a channel, there are typically two
+ groups of channels: standard channels which prefix is either '&', '#'
+ or '+', and "safe channels" which prefix is '!'.
+
+3.1 Standard channels
+
+ These channels are created implicitly when the first user joins it,
+ and cease to exist when the last user leaves it. While the channel
+ exists, any client can reference the channel using the name of the
+ channel.
+
+ The user creating a channel automatically becomes channel operator
+ with the notable exception of channels which name is prefixed by the
+ character '+', see section 4 (Channel modes). See section 2.4.1
+ (Channel Operators) for more details on this title.
+
+
+
+
+
+
+Kalt Informational [Page 5]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ In order to avoid the creation of duplicate channels (typically when
+ the IRC network becomes disjoint because of a split between two
+ servers), channel names SHOULD NOT be allowed to be reused by a user
+ if a channel operator (See Section 2.4.1 (Channel Operators)) has
+ recently left the channel because of a network split. If this
+ happens, the channel name is temporarily unavailable. The duration
+ while a channel remains unavailable should be tuned on a per IRC
+ network basis. It is important to note that this prevents local
+ users from creating a channel using the same name, but does not
+ prevent the channel to be recreated by a remote user. The latter
+ typically happens when the IRC network rejoins. Obviously, this
+ mechanism only makes sense for channels which name begins with the
+ character '#', but MAY be used for channels which name begins with
+ the character '+'. This mechanism is commonly known as "Channel
+ Delay".
+
+3.2 Safe Channels
+
+ Unlike other channels, "safe channels" are not implicitly created. A
+ user wishing to create such a channel MUST request the creation by
+ sending a special JOIN command to the server in which the channel
+ identifier (then unknown) is replaced by the character '!'. The
+ creation process for this type of channel is strictly controlled.
+ The user only chooses part of the channel name (known as the channel
+ "short name"), the server automatically prepends the user provided
+ name with a channel identifier consisting of five (5) characters.
+ The channel name resulting from the combination of these two elements
+ is unique, making the channel safe from abuses based on network
+ splits.
+
+ The user who creates such a channel automatically becomes "channel
+ creator". See section 2.4.2 (Channel Creator) for more details on
+ this title.
+
+ A server MUST NOT allow the creation of a new channel if another
+ channel with the same short name exists; or if another channel with
+ the same short name existed recently AND any of its member(s) left
+ because of a network split. Such channel ceases to exist after last
+ user leaves AND no other member recently left the channel because of
+ a network split.
+
+ Unlike the mechanism described in section 5.2.2 (Channel Delay), in
+ this case, channel names do not become unavailable: these channels
+ may continue to exist after the last user left. Only the user
+ creating the channel becomes "channel creator", users joining an
+ existing empty channel do not automatically become "channel creator"
+ nor "channel operator".
+
+
+
+
+Kalt Informational [Page 6]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ To ensure the uniqueness of the channel names, the channel identifier
+ created by the server MUST follow specific rules. For more details
+ on this, see section 5.2.1 (Channel Identifier).
+
+4. Channel Modes
+
+ The various modes available for channels are as follows:
+
+ O - give "channel creator" status;
+ o - give/take channel operator privilege;
+ v - give/take the voice privilege;
+
+ a - toggle the anonymous channel flag;
+ i - toggle the invite-only channel flag;
+ m - toggle the moderated channel;
+ n - toggle the no messages to channel from clients on the
+ outside;
+ q - toggle the quiet channel flag;
+ p - toggle the private channel flag;
+ s - toggle the secret channel flag;
+ r - toggle the server reop channel flag;
+ t - toggle the topic settable by channel operator only flag;
+
+ k - set/remove the channel key (password);
+ l - set/remove the user limit to channel;
+
+ b - set/remove ban mask to keep users out;
+ e - set/remove an exception mask to override a ban mask;
+ I - set/remove an invitation mask to automatically override
+ the invite-only flag;
+
+ Unless mentioned otherwise below, all these modes can be manipulated
+ by "channel operators" by using the MODE command defined in "IRC
+ Client Protocol" [IRC-CLIENT].
+
+4.1 Member Status
+
+ The modes in this category take a channel member nickname as argument
+ and affect the privileges given to this user.
+
+4.1.1 "Channel Creator" Status
+
+ The mode 'O' is only used in conjunction with "safe channels" and
+ SHALL NOT be manipulated by users. Servers use it to give the user
+ creating the channel the status of "channel creator".
+
+
+
+
+
+
+Kalt Informational [Page 7]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+4.1.2 Channel Operator Status
+
+ The mode 'o' is used to toggle the operator status of a channel
+ member.
+
+4.1.3 Voice Privilege
+
+ The mode 'v' is used to give and take voice privilege to/from a
+ channel member. Users with this privilege can talk on moderated
+ channels. (See section 4.2.3 (Moderated Channel Flag).
+
+4.2 Channel Flags
+
+ The modes in this category are used to define properties which
+ affects how channels operate.
+
+4.2.1 Anonymous Flag
+
+ The channel flag 'a' defines an anonymous channel. This means that
+ when a message sent to the channel is sent by the server to users,
+ and the origin is a user, then it MUST be masked. To mask the
+ message, the origin is changed to "anonymous!anonymous@anonymous."
+ (e.g., a user with the nickname "anonymous", the username "anonymous"
+ and from a host called "anonymous."). Because of this, servers MUST
+ forbid users from using the nickname "anonymous". Servers MUST also
+ NOT send QUIT messages for users leaving such channels to the other
+ channel members but generate a PART message instead.
+
+ On channels with the character '&' as prefix, this flag MAY be
+ toggled by channel operators, but on channels with the character '!'
+ as prefix, this flag can be set (but SHALL NOT be unset) by the
+ "channel creator" only. This flag MUST NOT be made available on
+ other types of channels.
+
+ Replies to the WHOIS, WHO and NAMES commands MUST NOT reveal the
+ presence of other users on channels for which the anonymous flag is
+ set.
+
+4.2.2 Invite Only Flag
+
+ When the channel flag 'i' is set, new members are only accepted if
+ their mask matches Invite-list (See section 4.3.2) or they have been
+ invited by a channel operator. This flag also restricts the usage of
+ the INVITE command (See "IRC Client Protocol" [IRC-CLIENT]) to
+ channel operators.
+
+
+
+
+
+
+Kalt Informational [Page 8]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+4.2.3 Moderated Channel Flag
+
+ The channel flag 'm' is used to control who may speak on a channel.
+ When it is set, only channel operators, and members who have been
+ given the voice privilege may send messages to the channel.
+
+ This flag only affects users.
+
+4.2.4 No Messages To Channel From Clients On The Outside
+
+ When the channel flag 'n' is set, only channel members MAY send
+ messages to the channel.
+
+ This flag only affects users.
+
+4.2.5 Quiet Channel
+
+ The channel flag 'q' is for use by servers only. When set, it
+ restricts the type of data sent to users about the channel
+ operations: other user joins, parts and nick changes are not sent.
+ From a user's point of view, the channel contains only one user.
+
+ This is typically used to create special local channels on which the
+ server sends notices related to its operations. This was used as a
+ more efficient and flexible way to replace the user mode 's' defined
+ in RFC 1459 [IRC].
+
+4.2.6 Private and Secret Channels
+
+ The channel flag 'p' is used to mark a channel "private" and the
+ channel flag 's' to mark a channel "secret". Both properties are
+ similar and conceal the existence of the channel from other users.
+
+ This means that there is no way of getting this channel's name from
+ the server without being a member. In other words, these channels
+ MUST be omitted from replies to queries like the WHOIS command.
+
+ When a channel is "secret", in addition to the restriction above, the
+ server will act as if the channel does not exist for queries like the
+ TOPIC, LIST, NAMES commands. Note that there is one exception to
+ this rule: servers will correctly reply to the MODE command.
+ Finally, secret channels are not accounted for in the reply to the
+ LUSERS command (See "Internet Relay Chat: Client Protocol" [IRC-
+ CLIENT]) when the <mask> parameter is specified.
+
+
+
+
+
+
+
+Kalt Informational [Page 9]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ The channel flags 'p' and 's' MUST NOT both be set at the same time.
+ If a MODE message originating from a server sets the flag 'p' and the
+ flag 's' is already set for the channel, the change is silently
+ ignored. This should only happen during a split healing phase
+ (mentioned in the "IRC Server Protocol" document [IRC-SERVER]).
+
+4.2.7 Server Reop Flag
+
+ The channel flag 'r' is only available on channels which name begins
+ with the character '!' and MAY only be toggled by the "channel
+ creator".
+
+ This flag is used to prevent a channel from having no channel
+ operator for an extended period of time. When this flag is set, any
+ channel that has lost all its channel operators for longer than the
+ "reop delay" period triggers a mechanism in servers to reop some or
+ all of the channel inhabitants. This mechanism is described more in
+ detail in section 5.2.4 (Channel Reop Mechanism).
+
+4.2.8 Topic
+
+ The channel flag 't' is used to restrict the usage of the TOPIC
+ command to channel operators.
+
+4.2.9 User Limit
+
+ A user limit may be set on channels by using the channel flag 'l'.
+ When the limit is reached, servers MUST forbid their local users to
+ join the channel.
+
+ The value of the limit MUST only be made available to the channel
+ members in the reply sent by the server to a MODE query.
+
+4.2.10 Channel Key
+
+ When a channel key is set (by using the mode 'k'), servers MUST
+ reject their local users request to join the channel unless this key
+ is given.
+
+ The channel key MUST only be made visible to the channel members in
+ the reply sent by the server to a MODE query.
+
+4.3 Channel Access Control
+
+ The last category of modes is used to control access to the channel,
+ they take a mask as argument.
+
+
+
+
+
+Kalt Informational [Page 10]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ In order to reduce the size of the global database for control access
+ modes set for channels, servers MAY put a maximum limit on the number
+ of such modes set for a particular channel. If such restriction is
+ imposed, it MUST only affect user requests. The limit SHOULD be
+ homogeneous on a per IRC network basis.
+
+4.3.1 Channel Ban and Exception
+
+ When a user requests to join a channel, his local server checks if
+ the user's address matches any of the ban masks set for the channel.
+ If a match is found, the user request is denied unless the address
+ also matches an exception mask set for the channel.
+
+ Servers MUST NOT allow a channel member who is banned from the
+ channel to speak on the channel, unless this member is a channel
+ operator or has voice privilege. (See Section 4.1.3 (Voice
+ Privilege)).
+
+ A user who is banned from a channel and who carries an invitation
+ sent by a channel operator is allowed to join the channel.
+
+4.3.2 Channel Invitation
+
+ For channels which have the invite-only flag set (See Section 4.2.2
+ (Invite Only Flag)), users whose address matches an invitation mask
+ set for the channel are allowed to join the channel without any
+ invitation.
+
+5. Current Implementations
+
+ The only current implementation of these rules as part of the IRC
+ protocol is the IRC server, version 2.10.
+
+ The rest of this section deals with issues that are mostly of
+ importance to those who wish to implement a server but some parts may
+ also be of interest for client writers.
+
+5.1 Tracking Recently Used Channels
+
+ This mechanism is commonly known as "Channel Delay" and generally
+ only applies to channels which names is prefixed with the character
+ '#' (See Section 3.1 "Standard channels").
+
+ When a network split occurs, servers SHOULD keep track of which
+ channels lost a "channel operator" as the result of the break. These
+ channels are then in a special state which lasts for a certain period
+ of time. In this particular state, the channels cannot cease to
+
+
+
+
+Kalt Informational [Page 11]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ exist. If all the channel members leave the channel, the channel
+ becomes unavailable: the server local clients cannot join the channel
+ as long as it is empty.
+
+ Once a channel is unavailable, it will become available again either
+ because a remote user has joined the channel (most likely because the
+ network is healing), or because the delay period has expired (in
+ which case the channel ceases to exist and may be re-created).
+
+ The duration for which a channel death is delayed SHOULD be set
+ considering many factors among which are the size (user wise) of the
+ IRC network, and the usual duration of network splits. It SHOULD be
+ uniform on all servers for a given IRC network.
+
+5.2 Safe Channels
+
+ This document introduces the notion of "safe channels". These
+ channels have a name prefixed with the character '!' and great effort
+ is made to avoid collisions in this name space. Collisions are not
+ impossible, however they are very unlikely.
+
+5.2.1 Channel Identifier
+
+ The channel identifier is a function of the time. The current time
+ (as defined under UNIX by the number of seconds elapsed since
+ 00:00:00 GMT, January 1, 1970) is converted in a string of five (5)
+ characters using the following base:
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" (each character has a decimal
+ value starting from 0 for 'A' to 35 for '0').
+
+ The channel identifier therefore has a periodicity of 36^5 seconds
+ (about 700 days).
+
+5.2.2 Channel Delay
+
+ These channels MUST be subject to the "channel delay" mechanism
+ described in section 5.1 (Channel Delay). However, the mechanism is
+ slightly adapted to fit better.
+
+ Servers MUST keep track of all such channels which lose members as
+ the result of a network split, no matter whether the user is a
+ "channel operator" or not.
+
+ However, these channels do NOT ever become unavailable, it is always
+ possible to join them even when they are empty.
+
+
+
+
+
+
+Kalt Informational [Page 12]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+5.2.3 Abuse Window
+
+ Because the periodicity is so long, attacks on a particular channel
+ (name) may only occur once in a very long while. However, with luck
+ and patience, it is still possible for a user to cause a channel
+ collision. In order to avoid this, servers MUST "look in the future"
+ and keep a list of channel names which identifier is about to be used
+ (in the coming few days for example). Such list should remain small,
+ not be a burden for servers to maintain and be used to avoid channel
+ collisions by preventing the re-creation of such channel for a longer
+ period of time than channel delay does.
+
+ Eventually a server MAY choose to extend this procedure to forbid
+ creation of channels with the same shortname only (then ignoring the
+ channel identifier).
+
+5.2.4 Preserving Sanity In The Name Space
+
+ The combination of the mechanisms described in sections 5.2.2 and
+ 5.2.3 makes it quite difficult for a user to create a channel
+ collision. However, another type of abuse consists of creating many
+ channels having the same shortname, but different identifiers. To
+ prevent this from happening, servers MUST forbid the creation of a
+ new channel which has the same shortname of a channel currently
+ existing.
+
+5.2.5 Server Reop Mechanism
+
+ When a channel has been opless for longer than the "reop delay"
+ period and has the channel flag 'r' set (See Section 4.2.7 (Server
+ Reop Flag)), IRC servers are responsible for giving the channel
+ operator status randomly to some of the members.
+
+ The exact logic used for this mechanism by the current implementation
+ is described below. Servers MAY use a different logic, but that it
+ is strongly RECOMMENDED that all servers use the same logic on a
+ particular IRC network to maintain coherence as well as fairness.
+ For the same reason, the "reop delay" SHOULD be uniform on all
+ servers for a given IRC network. As for the "channel delay", the
+ value of the "reop delay" SHOULD be set considering many factors
+ among which are the size (user wise) of the IRC network, and the
+ usual duration of network splits.
+
+ a) the reop mechanism is triggered after a random time following the
+ expiration of the "reop delay". This should limit the eventuality
+ of the mechanism being triggered at the same time (for the same
+ channel) on two separate servers.
+
+
+
+
+Kalt Informational [Page 13]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ b) If the channel is small (five (5) users or less), and the "channel
+ delay" for this channel has expired,
+ Then reop all channel members if at least one member is local to
+ the server.
+
+ c) If the channel is small (five (5) users or less), and the "channel
+ delay" for this channel has expired, and the "reop delay" has
+ expired for longer than its value,
+ Then reop all channel members.
+
+ d) For other cases, reop at most one member on the channel, based on
+ some method build into the server. If you don't reop a member, the
+ method should be such that another server will probably op
+ someone. The method SHOULD be the same over the whole network. A
+ good heuristic could be just random reop.
+ (The current implementation actually tries to choose a member
+ local to the server who has not been idle for too long, eventually
+ postponing action, therefore letting other servers have a chance
+ to find a "not too idle" member. This is over complicated due to
+ the fact that servers only know the "idle" time of their local
+ users)
+
+6. Current problems
+
+ There are a number of recognized problems with the way IRC channels
+ are managed. Some of these can be directly attributed to the rules
+ defined in this document, while others are the result of the
+ underlying "IRC Server Protocol" [IRC-SERVER]. Although derived from
+ RFC 1459 [IRC], this document introduces several novelties in an
+ attempt to solve some of the known problems.
+
+6.1 Labels
+
+ This document defines one of the many labels used by the IRC
+ protocol. Although there are several distinct namespaces (based on
+ the channel name prefix), duplicates inside each of these are not
+ allowed. Currently, it is possible for users on different servers to
+ pick the label which may result in collisions (with the exception of
+ channels known to only one server where they can be averted).
+
+6.1.1 Channel Delay
+
+ The channel delay mechanism described in section 5.1 (Tracking
+ Recently Used Channels) and used for channels prefixed with the
+ character '#' is a simple attempt at preventing collisions from
+ happening. Experience has shown that, under normal circumstances, it
+
+
+
+
+
+Kalt Informational [Page 14]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ is very efficient; however, it obviously has severe limitations
+ keeping it from being an adequate solution to the problem discussed
+ here.
+
+6.1.2 Safe Channels
+
+ "Safe channels" described in section 3.2 (Safe Channels) are a better
+ way to prevent collisions from happening as it prevents users from
+ having total control over the label they choose. The obvious
+ drawback for such labels is that they are not user friendly.
+ However, it is fairly trivial for a client program to improve on
+ this.
+
+6.2 Mode Propagation Delays
+
+ Because of network delays induced by the network, and because each
+ server on the path is REQUIRED to check the validity of mode changes
+ (e.g., user exists and has the right privileges), it is not unusual
+ for a MODE message to only affect part of the network, often creating
+ a discrepancy between servers on the current state of a channel.
+
+ While this may seem easy to fix (by having only the original server
+ check the validity of mode changes), it was decided not to do so for
+ various reasons. One concern is that servers cannot trust each
+ other, and that a misbehaving servers can easily be detected. This
+ way of doing so also stops wave effects on channels which are out of
+ synch when mode changes are issued from different directions.
+
+6.3 Collisions And Channel Modes
+
+ The "Internet Relay Chat: Server Protocol" document [IRC-SERVER]
+ describes how channel data is exchanged when two servers connect to
+ each other. Channel collisions (either legitimate or not) are
+ treated as inclusive events, meaning that the resulting channel has
+ for members all the users who are members of the channel on either
+ server prior to the connection.
+
+ Similarly, each server sends the channel modes to the other one.
+ Therefore, each server also receives these channel modes. There are
+ three types of modes for a given channel: flags, masks, and data.
+ The first two types are easy to deal with as they are either set or
+ unset. If such a mode is set on one server, it MUST be set on the
+ other server as a result of the connection.
+
+
+
+
+
+
+
+
+Kalt Informational [Page 15]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+ As topics are not sent as part of this exchange, they are not a
+ problem. However, channel modes 'l' and 'k' are exchanged, and if
+ they are set on both servers prior to the connection, there is no
+ mechanism to decide which of the two values takes precedence. It is
+ left up to the users to fix the resulting discrepancy.
+
+6.4 Resource Exhaustion
+
+ The mode based on masks defined in section 4.3 make the IRC servers
+ (and network) vulnerable to a simple abuse of the system: a single
+ channel operator can set as many different masks as possible on a
+ particular channel. This can easily cause the server to waste
+ memory, as well as network bandwidth (since the info is propagated to
+ other servers). For this reason it is RECOMMENDED that a limit be
+ put on the number of such masks per channels as mentioned in section
+ 4.3.
+
+ Moreover, more complex mechanisms MAY be used to avoid having
+ redundant masks set for the same channel.
+
+7. Security Considerations
+
+7.1 Access Control
+
+ One of the main ways to control access to a channel is to use masks
+ which are based on the username and hostname of the user connections.
+ This mechanism can only be efficient and safe if the IRC servers have
+ an accurate way of authenticating user connections, and if users
+ cannot easily get around it. While it is in theory possible to
+ implement such a strict authentication mechanism, most IRC networks
+ (especially public networks) do not have anything like this in place
+ and provide little guaranty about the accuracy of the username and
+ hostname for a particular client connection.
+
+ Another way to control access is to use a channel key, but since this
+ key is sent in plaintext, it is vulnerable to traditional man in the
+ middle attacks.
+
+7.2 Channel Privacy
+
+ Because channel collisions are treated as inclusive events (See
+ Section 6.3), it is possible for users to join a channel overriding
+ its access control settings. This method has long been used by
+ individuals to "take over" channels by "illegitimately" gaining
+ channel operator status on the channel. The same method can be used
+ to find out the exact list of members of a channel, as well as to
+ eventually receive some of the messages sent to the channel.
+
+
+
+
+Kalt Informational [Page 16]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+7.3 Anonymity
+
+ The anonymous channel flag (See Section 4.2.1) can be used to render
+ all users on such channel "anonymous" by presenting all messages to
+ the channel as originating from a pseudo user which nickname is
+ "anonymous". This is done at the client-server level, and no
+ anonymity is provided at the server-server level.
+
+ It should be obvious to readers, that the level of anonymity offered
+ is quite poor and insecure, and that clients SHOULD display strong
+ warnings for users joining such channels.
+
+8. Current support and availability
+
+ Mailing lists for IRC related discussion:
+ General discussion: ircd-users@irc.org
+ Protocol development: ircd-dev@irc.org
+
+ Software implementations:
+ ftp://ftp.irc.org/irc/server
+ ftp://ftp.funet.fi/pub/unix/irc
+ ftp://coombs.anu.edu.au/pub/irc
+
+ Newsgroup: alt.irc
+
+9. Acknowledgements
+
+ Parts of this document were copied from the RFC 1459 [IRC] which
+ first formally documented the IRC Protocol. It has also benefited
+ from many rounds of review and comments. In particular, the
+ following people have made significant contributions to this
+ document:
+
+ Matthew Green, Michael Neumayer, Volker Paulsen, Kurt Roeckx, Vesa
+ Ruokonen, Magnus Tjernstrom, Stefan Zehl.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 17]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+10. References
+
+ [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [IRC] Oikarinen, J. and D. Reed, "Internet Relay Chat
+ Protocol", RFC 1459, May 1993.
+
+ [IRC-ARCH] Kalt, C., "Internet Relay Chat: Architecture", RFC 2810,
+ April 2000.
+
+ [IRC-CLIENT] Kalt, C., "Internet Relay Chat: Client Protocol", RFC
+ 2812, April 2000.
+
+ [IRC-SERVER] Kalt, C., "Internet Relay Chat: Server Protocol", RFC
+ 2813, April 2000.
+
+11. Author's Address
+
+ Christophe Kalt
+ 99 Teaneck Rd, Apt #117
+ Ridgefield Park, NJ 07660
+ USA
+
+ EMail: kalt@stealth.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 18]
+
+RFC 2811 Internet Relay Chat: Channel Management April 2000
+
+
+12. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 19]
+
diff --git a/irc_mod/Docs/rfc2812.txt b/irc_mod/Docs/rfc2812.txt
new file mode 100644
index 0000000..7f1b162
--- /dev/null
+++ b/irc_mod/Docs/rfc2812.txt
@@ -0,0 +1,3531 @@
+
+
+
+
+
+
+Network Working Group C. Kalt
+Request for Comments: 2812 April 2000
+Updates: 1459
+Category: Informational
+
+
+ Internet Relay Chat: Client Protocol
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+IESG NOTE:
+
+ The IRC protocol itself enables several possibilities of transferring
+ data between clients, and just like with other transfer mechanisms
+ like email, the receiver of the data has to be careful about how the
+ data is handled. For more information on security issues with the IRC
+ protocol, see for example http://www.irchelp.org/irchelp/security/.
+
+Abstract
+
+ The IRC (Internet Relay Chat) protocol is for use with text based
+ conferencing; the simplest client being any socket program capable of
+ connecting to the server.
+
+ This document defines the Client Protocol, and assumes that the
+ reader is familiar with the IRC Architecture [IRC-ARCH].
+
+Table of Contents
+
+ 1. Labels ..................................................... 3
+ 1.1 Servers ................................................ 3
+ 1.2 Clients ................................................ 3
+ 1.2.1 Users ............................................. 4
+ 1.2.1.1 Operators .................................... 4
+ 1.2.2 Services .......................................... 4
+ 1.3 Channels ............................................... 4
+ 2. The IRC Client Specification ............................... 5
+ 2.1 Overview ............................................... 5
+ 2.2 Character codes ........................................ 5
+ 2.3 Messages ............................................... 5
+
+
+
+Kalt Informational [Page 1]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 2.3.1 Message format in Augmented BNF ................... 6
+ 2.4 Numeric replies ........................................ 8
+ 2.5 Wildcard expressions ................................... 9
+ 3. Message Details ............................................ 9
+ 3.1 Connection Registration ................................ 10
+ 3.1.1 Password message .................................. 10
+ 3.1.2 Nick message ...................................... 10
+ 3.1.3 User message ...................................... 11
+ 3.1.4 Oper message ...................................... 12
+ 3.1.5 User mode message ................................. 12
+ 3.1.6 Service message ................................... 13
+ 3.1.7 Quit .............................................. 14
+ 3.1.8 Squit ............................................. 15
+ 3.2 Channel operations ..................................... 15
+ 3.2.1 Join message ...................................... 16
+ 3.2.2 Part message ...................................... 17
+ 3.2.3 Channel mode message .............................. 18
+ 3.2.4 Topic message ..................................... 19
+ 3.2.5 Names message ..................................... 20
+ 3.2.6 List message ...................................... 21
+ 3.2.7 Invite message .................................... 21
+ 3.2.8 Kick command ...................................... 22
+ 3.3 Sending messages ....................................... 23
+ 3.3.1 Private messages .................................. 23
+ 3.3.2 Notice ............................................ 24
+ 3.4 Server queries and commands ............................ 25
+ 3.4.1 Motd message ...................................... 25
+ 3.4.2 Lusers message .................................... 25
+ 3.4.3 Version message ................................... 26
+ 3.4.4 Stats message ..................................... 26
+ 3.4.5 Links message ..................................... 27
+ 3.4.6 Time message ...................................... 28
+ 3.4.7 Connect message ................................... 28
+ 3.4.8 Trace message ..................................... 29
+ 3.4.9 Admin command ..................................... 30
+ 3.4.10 Info command ...................................... 31
+ 3.5 Service Query and Commands ............................. 31
+ 3.5.1 Servlist message .................................. 31
+ 3.5.2 Squery ............................................ 32
+ 3.6 User based queries ..................................... 32
+ 3.6.1 Who query ......................................... 32
+ 3.6.2 Whois query ....................................... 33
+ 3.6.3 Whowas ............................................ 34
+ 3.7 Miscellaneous messages ................................. 34
+ 3.7.1 Kill message ...................................... 35
+ 3.7.2 Ping message ...................................... 36
+ 3.7.3 Pong message ...................................... 37
+ 3.7.4 Error ............................................. 37
+
+
+
+Kalt Informational [Page 2]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 4. Optional features .......................................... 38
+ 4.1 Away ................................................... 38
+ 4.2 Rehash message ......................................... 39
+ 4.3 Die message ............................................ 39
+ 4.4 Restart message ........................................ 40
+ 4.5 Summon message ......................................... 40
+ 4.6 Users .................................................. 41
+ 4.7 Operwall message ....................................... 41
+ 4.8 Userhost message ....................................... 42
+ 4.9 Ison message ........................................... 42
+ 5. Replies .................................................... 43
+ 5.1 Command responses ...................................... 43
+ 5.2 Error Replies .......................................... 53
+ 5.3 Reserved numerics ...................................... 59
+ 6. Current implementations .................................... 60
+ 7. Current problems ........................................... 60
+ 7.1 Nicknames .............................................. 60
+ 7.2 Limitation of wildcards ................................ 61
+ 7.3 Security considerations ................................ 61
+ 8. Current support and availability ........................... 61
+ 9. Acknowledgements ........................................... 61
+ 10. References ................................................ 62
+ 11. Author's Address .......................................... 62
+ 12. Full Copyright Statement .................................. 63
+
+1. Labels
+
+ This section defines the identifiers used for the various components
+ of the IRC protocol.
+
+1.1 Servers
+
+ Servers are uniquely identified by their name, which has a maximum
+ length of sixty three (63) characters. See the protocol grammar
+ rules (section 2.3.1) for what may and may not be used in a server
+ name.
+
+1.2 Clients
+
+ For each client all servers MUST have the following information: a
+ netwide unique identifier (whose format depends on the type of
+ client) and the server which introduced the client.
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 3]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+1.2.1 Users
+
+ Each user is distinguished from other users by a unique nickname
+ having a maximum length of nine (9) characters. See the protocol
+ grammar rules (section 2.3.1) for what may and may not be used in a
+ nickname.
+
+ While the maximum length is limited to nine characters, clients
+ SHOULD accept longer strings as they may become used in future
+ evolutions of the protocol.
+
+1.2.1.1 Operators
+
+ To allow a reasonable amount of order to be kept within the IRC
+ network, a special class of users (operators) is allowed to perform
+ general maintenance functions on the network. Although the powers
+ granted to an operator can be considered as 'dangerous', they are
+ nonetheless often necessary. Operators SHOULD be able to perform
+ basic network tasks such as disconnecting and reconnecting servers as
+ needed. In recognition of this need, the protocol discussed herein
+ provides for operators only to be able to perform such functions.
+ See sections 3.1.8 (SQUIT) and 3.4.7 (CONNECT).
+
+ A more controversial power of operators is the ability to remove a
+ user from the connected network by 'force', i.e., operators are able
+ to close the connection between any client and server. The
+ justification for this is very delicate since its abuse is both
+ destructive and annoying, and its benefits close to inexistent. For
+ further details on this type of action, see section 3.7.1 (KILL).
+
+1.2.2 Services
+
+ Each service is distinguished from other services by a service name
+ composed of a nickname and a server name. As for users, the nickname
+ has a maximum length of nine (9) characters. See the protocol
+ grammar rules (section 2.3.1) for what may and may not be used in a
+ nickname.
+
+1.3 Channels
+
+ Channels names are strings (beginning with a '&', '#', '+' or '!'
+ character) of length up to fifty (50) characters. Apart from the
+ requirement that the first character is either '&', '#', '+' or '!',
+ the only restriction on a channel name is that it SHALL NOT contain
+ any spaces (' '), a control G (^G or ASCII 7), a comma (','). Space
+ is used as parameter separator and command is used as a list item
+ separator by the protocol). A colon (':') can also be used as a
+ delimiter for the channel mask. Channel names are case insensitive.
+
+
+
+Kalt Informational [Page 4]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ See the protocol grammar rules (section 2.3.1) for the exact syntax
+ of a channel name.
+
+ Each prefix characterizes a different channel type. The definition
+ of the channel types is not relevant to the client-server protocol
+ and thus it is beyond the scope of this document. More details can
+ be found in "Internet Relay Chat: Channel Management" [IRC-CHAN].
+
+2. The IRC Client Specification
+
+2.1 Overview
+
+ The protocol as described herein is for use only with client to
+ server connections when the client registers as a user.
+
+2.2 Character codes
+
+ No specific character set is specified. The protocol is based on a
+ set of codes which are composed of eight (8) bits, making up an
+ octet. Each message may be composed of any number of these octets;
+ however, some octet values are used for control codes, which act as
+ message delimiters.
+
+ Regardless of being an 8-bit protocol, the delimiters and keywords
+ are such that protocol is mostly usable from US-ASCII terminal and a
+ telnet connection.
+
+ Because of IRC's Scandinavian origin, the characters {}|^ are
+ considered to be the lower case equivalents of the characters []\~,
+ respectively. This is a critical issue when determining the
+ equivalence of two nicknames or channel names.
+
+2.3 Messages
+
+ Servers and clients send each other messages, which may or may not
+ generate a reply. If the message contains a valid command, as
+ described in later sections, the client should expect a reply as
+ specified but it is not advised to wait forever for the reply; client
+ to server and server to server communication is essentially
+ asynchronous by nature.
+
+ Each IRC message may consist of up to three main parts: the prefix
+ (OPTIONAL), the command, and the command parameters (maximum of
+ fifteen (15)). The prefix, command, and all parameters are separated
+ by one ASCII space character (0x20) each.
+
+
+
+
+
+
+Kalt Informational [Page 5]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ The presence of a prefix is indicated with a single leading ASCII
+ colon character (':', 0x3b), which MUST be the first character of the
+ message itself. There MUST be NO gap (whitespace) between the colon
+ and the prefix. The prefix is used by servers to indicate the true
+ origin of the message. If the prefix is missing from the message, it
+ is assumed to have originated from the connection from which it was
+ received from. Clients SHOULD NOT use a prefix when sending a
+ message; if they use one, the only valid prefix is the registered
+ nickname associated with the client.
+
+ The command MUST either be a valid IRC command or a three (3) digit
+ number represented in ASCII text.
+
+ IRC messages are always lines of characters terminated with a CR-LF
+ (Carriage Return - Line Feed) pair, and these messages SHALL NOT
+ exceed 512 characters in length, counting all characters including
+ the trailing CR-LF. Thus, there are 510 characters maximum allowed
+ for the command and its parameters. There is no provision for
+ continuation of message lines. See section 6 for more details about
+ current implementations.
+
+2.3.1 Message format in Augmented BNF
+
+ The protocol messages must be extracted from the contiguous stream of
+ octets. The current solution is to designate two characters, CR and
+ LF, as message separators. Empty messages are silently ignored,
+ which permits use of the sequence CR-LF between messages without
+ extra problems.
+
+ The extracted message is parsed into the components <prefix>,
+ <command> and list of parameters (<params>).
+
+ The Augmented BNF representation for this is:
+
+ message = [ ":" prefix SPACE ] command [ params ] crlf
+ prefix = servername / ( nickname [ [ "!" user ] "@" host ] )
+ command = 1*letter / 3digit
+ params = *14( SPACE middle ) [ SPACE ":" trailing ]
+ =/ 14( SPACE middle ) [ SPACE [ ":" ] trailing ]
+
+ nospcrlfcl = %x01-09 / %x0B-0C / %x0E-1F / %x21-39 / %x3B-FF
+ ; any octet except NUL, CR, LF, " " and ":"
+ middle = nospcrlfcl *( ":" / nospcrlfcl )
+ trailing = *( ":" / " " / nospcrlfcl )
+
+ SPACE = %x20 ; space character
+ crlf = %x0D %x0A ; "carriage return" "linefeed"
+
+
+
+
+Kalt Informational [Page 6]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ NOTES:
+ 1) After extracting the parameter list, all parameters are equal
+ whether matched by <middle> or <trailing>. <trailing> is just a
+ syntactic trick to allow SPACE within the parameter.
+
+ 2) The NUL (%x00) character is not special in message framing, and
+ basically could end up inside a parameter, but it would cause
+ extra complexities in normal C string handling. Therefore, NUL
+ is not allowed within messages.
+
+ Most protocol messages specify additional semantics and syntax for
+ the extracted parameter strings dictated by their position in the
+ list. For example, many server commands will assume that the first
+ parameter after the command is the list of targets, which can be
+ described with:
+
+ target = nickname / server
+ msgtarget = msgto *( "," msgto )
+ msgto = channel / ( user [ "%" host ] "@" servername )
+ msgto =/ ( user "%" host ) / targetmask
+ msgto =/ nickname / ( nickname "!" user "@" host )
+ channel = ( "#" / "+" / ( "!" channelid ) / "&" ) chanstring
+ [ ":" chanstring ]
+ servername = hostname
+ host = hostname / hostaddr
+ hostname = shortname *( "." shortname )
+ shortname = ( letter / digit ) *( letter / digit / "-" )
+ *( letter / digit )
+ ; as specified in RFC 1123 [HNAME]
+ hostaddr = ip4addr / ip6addr
+ ip4addr = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit
+ ip6addr = 1*hexdigit 7( ":" 1*hexdigit )
+ ip6addr =/ "0:0:0:0:0:" ( "0" / "FFFF" ) ":" ip4addr
+ nickname = ( letter / special ) *8( letter / digit / special / "-" )
+ targetmask = ( "$" / "#" ) mask
+ ; see details on allowed masks in section 3.3.1
+ chanstring = %x01-07 / %x08-09 / %x0B-0C / %x0E-1F / %x21-2B
+ chanstring =/ %x2D-39 / %x3B-FF
+ ; any octet except NUL, BELL, CR, LF, " ", "," and ":"
+ channelid = 5( %x41-5A / digit ) ; 5( A-Z / 0-9 )
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 7]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Other parameter syntaxes are:
+
+ user = 1*( %x01-09 / %x0B-0C / %x0E-1F / %x21-3F / %x41-FF )
+ ; any octet except NUL, CR, LF, " " and "@"
+ key = 1*23( %x01-05 / %x07-08 / %x0C / %x0E-1F / %x21-7F )
+ ; any 7-bit US_ASCII character,
+ ; except NUL, CR, LF, FF, h/v TABs, and " "
+ letter = %x41-5A / %x61-7A ; A-Z / a-z
+ digit = %x30-39 ; 0-9
+ hexdigit = digit / "A" / "B" / "C" / "D" / "E" / "F"
+ special = %x5B-60 / %x7B-7D
+ ; "[", "]", "\", "`", "_", "^", "{", "|", "}"
+
+ NOTES:
+ 1) The <hostaddr> syntax is given here for the sole purpose of
+ indicating the format to follow for IP addresses. This
+ reflects the fact that the only available implementations of
+ this protocol uses TCP/IP as underlying network protocol but is
+ not meant to prevent other protocols to be used.
+
+ 2) <hostname> has a maximum length of 63 characters. This is a
+ limitation of the protocol as internet hostnames (in
+ particular) can be longer. Such restriction is necessary
+ because IRC messages are limited to 512 characters in length.
+ Clients connecting from a host which name is longer than 63
+ characters are registered using the host (numeric) address
+ instead of the host name.
+
+ 3) Some parameters used in the following sections of this
+ documents are not defined here as there is nothing specific
+ about them besides the name that is used for convenience.
+ These parameters follow the general syntax defined for
+ <params>.
+
+2.4 Numeric replies
+
+ Most of the messages sent to the server generate a reply of some
+ sort. The most common reply is the numeric reply, used for both
+ errors and normal replies. The numeric reply MUST be sent as one
+ message consisting of the sender prefix, the three-digit numeric, and
+ the target of the reply. A numeric reply is not allowed to originate
+ from a client. In all other respects, a numeric reply is just like a
+ normal message, except that the keyword is made up of 3 numeric
+ digits rather than a string of letters. A list of different replies
+ is supplied in section 5 (Replies).
+
+
+
+
+
+
+Kalt Informational [Page 8]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+2.5 Wildcard expressions
+
+ When wildcards are allowed in a string, it is referred as a "mask".
+
+ For string matching purposes, the protocol allows the use of two
+ special characters: '?' (%x3F) to match one and only one character,
+ and '*' (%x2A) to match any number of any characters. These two
+ characters can be escaped using the character '\' (%x5C).
+
+ The Augmented BNF syntax for this is:
+
+ mask = *( nowild / noesc wildone / noesc wildmany )
+ wildone = %x3F
+ wildmany = %x2A
+ nowild = %x01-29 / %x2B-3E / %x40-FF
+ ; any octet except NUL, "*", "?"
+ noesc = %x01-5B / %x5D-FF
+ ; any octet except NUL and "\"
+ matchone = %x01-FF
+ ; matches wildone
+ matchmany = *matchone
+ ; matches wildmany
+
+ Examples:
+
+ a?c ; Matches any string of 3 characters in length starting
+ with "a" and ending with "c"
+
+ a*c ; Matches any string of at least 2 characters in length
+ starting with "a" and ending with "c"
+
+3. Message Details
+
+ On the following pages there are descriptions of each message
+ recognized by the IRC server and client. All commands described in
+ this section MUST be implemented by any server for this protocol.
+
+ Where the reply ERR_NOSUCHSERVER is returned, it means that the
+ target of the message could not be found. The server MUST NOT send
+ any other replies after this error for that command.
+
+ The server to which a client is connected is required to parse the
+ complete message, and return any appropriate errors.
+
+ If multiple parameters is presented, then each MUST be checked for
+ validity and appropriate responses MUST be sent back to the client.
+ In the case of incorrect messages which use parameter lists with
+ comma as an item separator, a reply MUST be sent for each item.
+
+
+
+Kalt Informational [Page 9]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+3.1 Connection Registration
+
+ The commands described here are used to register a connection with an
+ IRC server as a user as well as to correctly disconnect.
+
+ A "PASS" command is not required for a client connection to be
+ registered, but it MUST precede the latter of the NICK/USER
+ combination (for a user connection) or the SERVICE command (for a
+ service connection). The RECOMMENDED order for a client to register
+ is as follows:
+
+ 1. Pass message
+ 2. Nick message 2. Service message
+ 3. User message
+
+ Upon success, the client will receive an RPL_WELCOME (for users) or
+ RPL_YOURESERVICE (for services) message indicating that the
+ connection is now registered and known the to the entire IRC network.
+ The reply message MUST contain the full client identifier upon which
+ it was registered.
+
+3.1.1 Password message
+
+ Command: PASS
+ Parameters: <password>
+
+ The PASS command is used to set a 'connection password'. The
+ optional password can and MUST be set before any attempt to register
+ the connection is made. Currently this requires that user send a
+ PASS command before sending the NICK/USER combination.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
+
+ Example:
+
+ PASS secretpasswordhere
+
+3.1.2 Nick message
+
+
+ Command: NICK
+ Parameters: <nickname>
+
+ NICK command is used to give user a nickname or change the existing
+ one.
+
+
+
+
+Kalt Informational [Page 10]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Numeric Replies:
+
+ ERR_NONICKNAMEGIVEN ERR_ERRONEUSNICKNAME
+ ERR_NICKNAMEINUSE ERR_NICKCOLLISION
+ ERR_UNAVAILRESOURCE ERR_RESTRICTED
+
+ Examples:
+
+ NICK Wiz ; Introducing new nick "Wiz" if session is
+ still unregistered, or user changing his
+ nickname to "Wiz"
+
+ :WiZ!jto@tolsun.oulu.fi NICK Kilroy
+ ; Server telling that WiZ changed his
+ nickname to Kilroy.
+
+3.1.3 User message
+
+ Command: USER
+ Parameters: <user> <mode> <unused> <realname>
+
+ The USER command is used at the beginning of connection to specify
+ the username, hostname and realname of a new user.
+
+ The <mode> parameter should be a numeric, and can be used to
+ automatically set user modes when registering with the server. This
+ parameter is a bitmask, with only 2 bits having any signification: if
+ the bit 2 is set, the user mode 'w' will be set and if the bit 3 is
+ set, the user mode 'i' will be set. (See Section 3.1.5 "User
+ Modes").
+
+ The <realname> may contain space characters.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
+
+ Example:
+
+ USER guest 0 * :Ronnie Reagan ; User registering themselves with a
+ username of "guest" and real name
+ "Ronnie Reagan".
+
+ USER guest 8 * :Ronnie Reagan ; User registering themselves with a
+ username of "guest" and real name
+ "Ronnie Reagan", and asking to be set
+ invisible.
+
+
+
+
+Kalt Informational [Page 11]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+3.1.4 Oper message
+
+ Command: OPER
+ Parameters: <name> <password>
+
+ A normal user uses the OPER command to obtain operator privileges.
+ The combination of <name> and <password> are REQUIRED to gain
+ Operator privileges. Upon success, the user will receive a MODE
+ message (see section 3.1.5) indicating the new user modes.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS RPL_YOUREOPER
+ ERR_NOOPERHOST ERR_PASSWDMISMATCH
+
+ Example:
+
+ OPER foo bar ; Attempt to register as an operator
+ using a username of "foo" and "bar"
+ as the password.
+
+3.1.5 User mode message
+
+ Command: MODE
+ Parameters: <nickname>
+ *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) )
+
+ The user MODE's are typically changes which affect either how the
+ client is seen by others or what 'extra' messages the client is sent.
+
+ A user MODE command MUST only be accepted if both the sender of the
+ message and the nickname given as a parameter are both the same. If
+ no other parameter is given, then the server will return the current
+ settings for the nick.
+
+ The available modes are as follows:
+
+ a - user is flagged as away;
+ i - marks a users as invisible;
+ w - user receives wallops;
+ r - restricted user connection;
+ o - operator flag;
+ O - local operator flag;
+ s - marks a user for receipt of server notices.
+
+ Additional modes may be available later on.
+
+
+
+
+
+Kalt Informational [Page 12]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ The flag 'a' SHALL NOT be toggled by the user using the MODE command,
+ instead use of the AWAY command is REQUIRED.
+
+ If a user attempts to make themselves an operator using the "+o" or
+ "+O" flag, the attempt SHOULD be ignored as users could bypass the
+ authentication mechanisms of the OPER command. There is no
+ restriction, however, on anyone `deopping' themselves (using "-o" or
+ "-O").
+
+ On the other hand, if a user attempts to make themselves unrestricted
+ using the "-r" flag, the attempt SHOULD be ignored. There is no
+ restriction, however, on anyone `deopping' themselves (using "+r").
+ This flag is typically set by the server upon connection for
+ administrative reasons. While the restrictions imposed are left up
+ to the implementation, it is typical that a restricted user not be
+ allowed to change nicknames, nor make use of the channel operator
+ status on channels.
+
+ The flag 's' is obsolete but MAY still be used.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_USERSDONTMATCH
+ ERR_UMODEUNKNOWNFLAG RPL_UMODEIS
+
+ Examples:
+
+ MODE WiZ -w ; Command by WiZ to turn off
+ reception of WALLOPS messages.
+
+ MODE Angel +i ; Command from Angel to make herself
+ invisible.
+
+ MODE WiZ -o ; WiZ 'deopping' (removing operator
+ status).
+
+3.1.6 Service message
+
+ Command: SERVICE
+ Parameters: <nickname> <reserved> <distribution> <type>
+ <reserved> <info>
+
+ The SERVICE command to register a new service. Command parameters
+ specify the service nickname, distribution, type and info of a new
+ service.
+
+
+
+
+
+
+Kalt Informational [Page 13]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ The <distribution> parameter is used to specify the visibility of a
+ service. The service may only be known to servers which have a name
+ matching the distribution. For a matching server to have knowledge
+ of the service, the network path between that server and the server
+ on which the service is connected MUST be composed of servers which
+ names all match the mask.
+
+ The <type> parameter is currently reserved for future usage.
+
+ Numeric Replies:
+
+ ERR_ALREADYREGISTRED ERR_NEEDMOREPARAMS
+ ERR_ERRONEUSNICKNAME
+ RPL_YOURESERVICE RPL_YOURHOST
+ RPL_MYINFO
+
+ Example:
+
+ SERVICE dict * *.fr 0 0 :French Dictionary ; Service registering
+ itself with a name of "dict". This
+ service will only be available on
+ servers which name matches "*.fr".
+
+3.1.7 Quit
+
+ Command: QUIT
+ Parameters: [ <Quit Message> ]
+
+ A client session is terminated with a quit message. The server
+ acknowledges this by sending an ERROR message to the client.
+
+ Numeric Replies:
+
+ None.
+
+ Example:
+
+ QUIT :Gone to have lunch ; Preferred message format.
+
+ :syrk!kalt@millennium.stealth.net QUIT :Gone to have lunch ; User
+ syrk has quit IRC to have lunch.
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 14]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+3.1.8 Squit
+
+ Command: SQUIT
+ Parameters: <server> <comment>
+
+ The SQUIT command is available only to operators. It is used to
+ disconnect server links. Also servers can generate SQUIT messages on
+ error conditions. A SQUIT message may also target a remote server
+ connection. In this case, the SQUIT message will simply be sent to
+ the remote server without affecting the servers in between the
+ operator and the remote server.
+
+ The <comment> SHOULD be supplied by all operators who execute a SQUIT
+ for a remote server. The server ordered to disconnect its peer
+ generates a WALLOPS message with <comment> included, so that other
+ users may be aware of the reason of this action.
+
+ Numeric replies:
+
+ ERR_NOPRIVILEGES ERR_NOSUCHSERVER
+ ERR_NEEDMOREPARAMS
+
+ Examples:
+
+ SQUIT tolsun.oulu.fi :Bad Link ? ; Command to uplink of the server
+ tolson.oulu.fi to terminate its
+ connection with comment "Bad Link".
+
+ :Trillian SQUIT cm22.eng.umd.edu :Server out of control ; Command
+ from Trillian from to disconnect
+ "cm22.eng.umd.edu" from the net with
+ comment "Server out of control".
+
+3.2 Channel operations
+
+ This group of messages is concerned with manipulating channels, their
+ properties (channel modes), and their contents (typically users).
+ For this reason, these messages SHALL NOT be made available to
+ services.
+
+ All of these messages are requests which will or will not be granted
+ by the server. The server MUST send a reply informing the user
+ whether the request was granted, denied or generated an error. When
+ the server grants the request, the message is typically sent back
+ (eventually reformatted) to the user with the prefix set to the user
+ itself.
+
+
+
+
+
+Kalt Informational [Page 15]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ The rules governing how channels are managed are enforced by the
+ servers. These rules are beyond the scope of this document. More
+ details are found in "Internet Relay Chat: Channel Management" [IRC-
+ CHAN].
+
+3.2.1 Join message
+
+ Command: JOIN
+ Parameters: ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] )
+ / "0"
+
+ The JOIN command is used by a user to request to start listening to
+ the specific channel. Servers MUST be able to parse arguments in the
+ form of a list of target, but SHOULD NOT use lists when sending JOIN
+ messages to clients.
+
+ Once a user has joined a channel, he receives information about
+ all commands his server receives affecting the channel. This
+ includes JOIN, MODE, KICK, PART, QUIT and of course PRIVMSG/NOTICE.
+ This allows channel members to keep track of the other channel
+ members, as well as channel modes.
+
+ If a JOIN is successful, the user receives a JOIN message as
+ confirmation and is then sent the channel's topic (using RPL_TOPIC) and
+ the list of users who are on the channel (using RPL_NAMREPLY), which
+ MUST include the user joining.
+
+ Note that this message accepts a special argument ("0"), which is
+ a special request to leave all channels the user is currently a member
+ of. The server will process this message as if the user had sent
+ a PART command (See Section 3.2.2) for each channel he is a member
+ of.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_BANNEDFROMCHAN
+ ERR_INVITEONLYCHAN ERR_BADCHANNELKEY
+ ERR_CHANNELISFULL ERR_BADCHANMASK
+ ERR_NOSUCHCHANNEL ERR_TOOMANYCHANNELS
+ ERR_TOOMANYTARGETS ERR_UNAVAILRESOURCE
+ RPL_TOPIC
+
+ Examples:
+
+ JOIN #foobar ; Command to join channel #foobar.
+
+ JOIN &foo fubar ; Command to join channel &foo using
+ key "fubar".
+
+
+
+Kalt Informational [Page 16]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ JOIN #foo,&bar fubar ; Command to join channel #foo using
+ key "fubar" and &bar using no key.
+
+ JOIN #foo,#bar fubar,foobar ; Command to join channel #foo using
+ key "fubar", and channel #bar using
+ key "foobar".
+
+ JOIN #foo,#bar ; Command to join channels #foo and
+ #bar.
+
+ JOIN 0 ; Leave all currently joined
+ channels.
+
+ :WiZ!jto@tolsun.oulu.fi JOIN #Twilight_zone ; JOIN message from WiZ
+ on channel #Twilight_zone
+
+3.2.2 Part message
+
+ Command: PART
+ Parameters: <channel> *( "," <channel> ) [ <Part Message> ]
+
+ The PART command causes the user sending the message to be removed
+ from the list of active members for all given channels listed in the
+ parameter string. If a "Part Message" is given, this will be sent
+ instead of the default message, the nickname. This request is always
+ granted by the server.
+
+ Servers MUST be able to parse arguments in the form of a list of
+ target, but SHOULD NOT use lists when sending PART messages to
+ clients.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_NOSUCHCHANNEL
+ ERR_NOTONCHANNEL
+
+ Examples:
+
+ PART #twilight_zone ; Command to leave channel
+ "#twilight_zone"
+
+ PART #oz-ops,&group5 ; Command to leave both channels
+ "&group5" and "#oz-ops".
+
+ :WiZ!jto@tolsun.oulu.fi PART #playzone :I lost
+ ; User WiZ leaving channel
+ "#playzone" with the message "I
+ lost".
+
+
+
+Kalt Informational [Page 17]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+3.2.3 Channel mode message
+
+ Command: MODE
+ Parameters: <channel> *( ( "-" / "+" ) *<modes> *<modeparams> )
+
+ The MODE command is provided so that users may query and change the
+ characteristics of a channel. For more details on available modes
+ and their uses, see "Internet Relay Chat: Channel Management" [IRC-
+ CHAN]. Note that there is a maximum limit of three (3) changes per
+ command for modes that take a parameter.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_KEYSET
+ ERR_NOCHANMODES ERR_CHANOPRIVSNEEDED
+ ERR_USERNOTINCHANNEL ERR_UNKNOWNMODE
+ RPL_CHANNELMODEIS
+ RPL_BANLIST RPL_ENDOFBANLIST
+ RPL_EXCEPTLIST RPL_ENDOFEXCEPTLIST
+ RPL_INVITELIST RPL_ENDOFINVITELIST
+ RPL_UNIQOPIS
+
+ The following examples are given to help understanding the syntax of
+ the MODE command, but refer to modes defined in "Internet Relay Chat:
+ Channel Management" [IRC-CHAN].
+
+ Examples:
+
+ MODE #Finnish +imI *!*@*.fi ; Command to make #Finnish channel
+ moderated and 'invite-only' with user
+ with a hostname matching *.fi
+ automatically invited.
+
+ MODE #Finnish +o Kilroy ; Command to give 'chanop' privileges
+ to Kilroy on channel #Finnish.
+
+ MODE #Finnish +v Wiz ; Command to allow WiZ to speak on
+ #Finnish.
+
+ MODE #Fins -s ; Command to remove 'secret' flag
+ from channel #Fins.
+
+ MODE #42 +k oulu ; Command to set the channel key to
+ "oulu".
+
+ MODE #42 -k oulu ; Command to remove the "oulu"
+ channel key on channel "#42".
+
+
+
+
+Kalt Informational [Page 18]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ MODE #eu-opers +l 10 ; Command to set the limit for the
+ number of users on channel
+ "#eu-opers" to 10.
+
+ :WiZ!jto@tolsun.oulu.fi MODE #eu-opers -l
+ ; User "WiZ" removing the limit for
+ the number of users on channel "#eu-
+ opers".
+
+ MODE &oulu +b ; Command to list ban masks set for
+ the channel "&oulu".
+
+ MODE &oulu +b *!*@* ; Command to prevent all users from
+ joining.
+
+ MODE &oulu +b *!*@*.edu +e *!*@*.bu.edu
+ ; Command to prevent any user from a
+ hostname matching *.edu from joining,
+ except if matching *.bu.edu
+
+ MODE #bu +be *!*@*.edu *!*@*.bu.edu
+ ; Comment to prevent any user from a
+ hostname matching *.edu from joining,
+ except if matching *.bu.edu
+
+ MODE #meditation e ; Command to list exception masks set
+ for the channel "#meditation".
+
+ MODE #meditation I ; Command to list invitations masks
+ set for the channel "#meditation".
+
+ MODE !12345ircd O ; Command to ask who the channel
+ creator for "!12345ircd" is
+
+3.2.4 Topic message
+
+ Command: TOPIC
+ Parameters: <channel> [ <topic> ]
+
+ The TOPIC command is used to change or view the topic of a channel.
+ The topic for channel <channel> is returned if there is no <topic>
+ given. If the <topic> parameter is present, the topic for that
+ channel will be changed, if this action is allowed for the user
+ requesting it. If the <topic> parameter is an empty string, the
+ topic for that channel will be removed.
+
+
+
+
+
+
+Kalt Informational [Page 19]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_NOTONCHANNEL
+ RPL_NOTOPIC RPL_TOPIC
+ ERR_CHANOPRIVSNEEDED ERR_NOCHANMODES
+
+ Examples:
+
+ :WiZ!jto@tolsun.oulu.fi TOPIC #test :New topic ; User Wiz setting the
+ topic.
+
+ TOPIC #test :another topic ; Command to set the topic on #test
+ to "another topic".
+
+ TOPIC #test : ; Command to clear the topic on
+ #test.
+
+ TOPIC #test ; Command to check the topic for
+ #test.
+
+3.2.5 Names message
+
+ Command: NAMES
+ Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
+
+ By using the NAMES command, a user can list all nicknames that are
+ visible to him. For more details on what is visible and what is not,
+ see "Internet Relay Chat: Channel Management" [IRC-CHAN]. The
+ <channel> parameter specifies which channel(s) to return information
+ about. There is no error reply for bad channel names.
+
+ If no <channel> parameter is given, a list of all channels and their
+ occupants is returned. At the end of this list, a list of users who
+ are visible but either not on any channel or not on a visible channel
+ are listed as being on `channel' "*".
+
+ If the <target> parameter is specified, the request is forwarded to
+ that server which will generate the reply.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numerics:
+
+ ERR_TOOMANYMATCHES ERR_NOSUCHSERVER
+ RPL_NAMREPLY RPL_ENDOFNAMES
+
+
+
+
+
+
+Kalt Informational [Page 20]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Examples:
+
+ NAMES #twilight_zone,#42 ; Command to list visible users on
+ #twilight_zone and #42
+
+ NAMES ; Command to list all visible
+ channels and users
+
+3.2.6 List message
+
+ Command: LIST
+ Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
+
+ The list command is used to list channels and their topics. If the
+ <channel> parameter is used, only the status of that channel is
+ displayed.
+
+ If the <target> parameter is specified, the request is forwarded to
+ that server which will generate the reply.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numeric Replies:
+
+ ERR_TOOMANYMATCHES ERR_NOSUCHSERVER
+ RPL_LIST RPL_LISTEND
+
+ Examples:
+
+ LIST ; Command to list all channels.
+
+ LIST #twilight_zone,#42 ; Command to list channels
+ #twilight_zone and #42
+
+3.2.7 Invite message
+
+ Command: INVITE
+ Parameters: <nickname> <channel>
+
+ The INVITE command is used to invite a user to a channel. The
+ parameter <nickname> is the nickname of the person to be invited to
+ the target channel <channel>. There is no requirement that the
+ channel the target user is being invited to must exist or be a valid
+ channel. However, if the channel exists, only members of the channel
+ are allowed to invite other users. When the channel has invite-only
+ flag set, only channel operators may issue INVITE command.
+
+
+
+
+
+Kalt Informational [Page 21]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Only the user inviting and the user being invited will receive
+ notification of the invitation. Other channel members are not
+ notified. (This is unlike the MODE changes, and is occasionally the
+ source of trouble for users.)
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_NOSUCHNICK
+ ERR_NOTONCHANNEL ERR_USERONCHANNEL
+ ERR_CHANOPRIVSNEEDED
+ RPL_INVITING RPL_AWAY
+
+ Examples:
+
+ :Angel!wings@irc.org INVITE Wiz #Dust
+
+ ; Message to WiZ when he has been
+ invited by user Angel to channel
+ #Dust
+
+ INVITE Wiz #Twilight_Zone ; Command to invite WiZ to
+ #Twilight_zone
+
+3.2.8 Kick command
+
+ Command: KICK
+ Parameters: <channel> *( "," <channel> ) <user> *( "," <user> )
+ [<comment>]
+
+ The KICK command can be used to request the forced removal of a user
+ from a channel. It causes the <user> to PART from the <channel> by
+ force. For the message to be syntactically correct, there MUST be
+ either one channel parameter and multiple user parameter, or as many
+ channel parameters as there are user parameters. If a "comment" is
+ given, this will be sent instead of the default message, the nickname
+ of the user issuing the KICK.
+
+ The server MUST NOT send KICK messages with multiple channels or
+ users to clients. This is necessarily to maintain backward
+ compatibility with old client software.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_NOSUCHCHANNEL
+ ERR_BADCHANMASK ERR_CHANOPRIVSNEEDED
+ ERR_USERNOTINCHANNEL ERR_NOTONCHANNEL
+
+
+
+
+
+Kalt Informational [Page 22]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Examples:
+
+ KICK &Melbourne Matthew ; Command to kick Matthew from
+ &Melbourne
+
+ KICK #Finnish John :Speaking English
+ ; Command to kick John from #Finnish
+ using "Speaking English" as the
+ reason (comment).
+
+ :WiZ!jto@tolsun.oulu.fi KICK #Finnish John
+ ; KICK message on channel #Finnish
+ from WiZ to remove John from channel
+
+3.3 Sending messages
+
+ The main purpose of the IRC protocol is to provide a base for clients
+ to communicate with each other. PRIVMSG, NOTICE and SQUERY
+ (described in Section 3.5 on Service Query and Commands) are the only
+ messages available which actually perform delivery of a text message
+ from one client to another - the rest just make it possible and try
+ to ensure it happens in a reliable and structured manner.
+
+3.3.1 Private messages
+
+ Command: PRIVMSG
+ Parameters: <msgtarget> <text to be sent>
+
+ PRIVMSG is used to send private messages between users, as well as to
+ send messages to channels. <msgtarget> is usually the nickname of
+ the recipient of the message, or a channel name.
+
+ The <msgtarget> parameter may also be a host mask (#<mask>) or server
+ mask ($<mask>). In both cases the server will only send the PRIVMSG
+ to those who have a server or host matching the mask. The mask MUST
+ have at least 1 (one) "." in it and no wildcards following the last
+ ".". This requirement exists to prevent people sending messages to
+ "#*" or "$*", which would broadcast to all users. Wildcards are the
+ '*' and '?' characters. This extension to the PRIVMSG command is
+ only available to operators.
+
+ Numeric Replies:
+
+ ERR_NORECIPIENT ERR_NOTEXTTOSEND
+ ERR_CANNOTSENDTOCHAN ERR_NOTOPLEVEL
+ ERR_WILDTOPLEVEL ERR_TOOMANYTARGETS
+ ERR_NOSUCHNICK
+ RPL_AWAY
+
+
+
+Kalt Informational [Page 23]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Examples:
+
+ :Angel!wings@irc.org PRIVMSG Wiz :Are you receiving this message ?
+ ; Message from Angel to Wiz.
+
+ PRIVMSG Angel :yes I'm receiving it !
+ ; Command to send a message to Angel.
+
+ PRIVMSG jto@tolsun.oulu.fi :Hello !
+ ; Command to send a message to a user
+ on server tolsun.oulu.fi with
+ username of "jto".
+
+ PRIVMSG kalt%millennium.stealth.net@irc.stealth.net :Are you a frog?
+ ; Message to a user on server
+ irc.stealth.net with username of
+ "kalt", and connected from the host
+ millennium.stealth.net.
+
+ PRIVMSG kalt%millennium.stealth.net :Do you like cheese?
+ ; Message to a user on the local
+ server with username of "kalt", and
+ connected from the host
+ millennium.stealth.net.
+
+ PRIVMSG Wiz!jto@tolsun.oulu.fi :Hello !
+ ; Message to the user with nickname
+ Wiz who is connected from the host
+ tolsun.oulu.fi and has the username
+ "jto".
+
+ PRIVMSG $*.fi :Server tolsun.oulu.fi rebooting.
+ ; Message to everyone on a server
+ which has a name matching *.fi.
+
+ PRIVMSG #*.edu :NSFNet is undergoing work, expect interruptions
+ ; Message to all users who come from
+ a host which has a name matching
+ *.edu.
+
+3.3.2 Notice
+
+ Command: NOTICE
+ Parameters: <msgtarget> <text>
+
+ The NOTICE command is used similarly to PRIVMSG. The difference
+ between NOTICE and PRIVMSG is that automatic replies MUST NEVER be
+ sent in response to a NOTICE message. This rule applies to servers
+
+
+
+Kalt Informational [Page 24]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ too - they MUST NOT send any error reply back to the client on
+ receipt of a notice. The object of this rule is to avoid loops
+ between clients automatically sending something in response to
+ something it received.
+
+ This command is available to services as well as users.
+
+ This is typically used by services, and automatons (clients with
+ either an AI or other interactive program controlling their actions).
+
+ See PRIVMSG for more details on replies and examples.
+
+3.4 Server queries and commands
+
+ The server query group of commands has been designed to return
+ information about any server which is connected to the network.
+
+ In these queries, where a parameter appears as <target>, wildcard
+ masks are usually valid. For each parameter, however, only one query
+ and set of replies is to be generated. In most cases, if a nickname
+ is given, it will mean the server to which the user is connected.
+
+ These messages typically have little value for services, it is
+ therefore RECOMMENDED to forbid services from using them.
+
+3.4.1 Motd message
+
+ Command: MOTD
+ Parameters: [ <target> ]
+
+ The MOTD command is used to get the "Message Of The Day" of the given
+ server, or current server if <target> is omitted.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numeric Replies:
+ RPL_MOTDSTART RPL_MOTD
+ RPL_ENDOFMOTD ERR_NOMOTD
+
+3.4.2 Lusers message
+
+ Command: LUSERS
+ Parameters: [ <mask> [ <target> ] ]
+
+ The LUSERS command is used to get statistics about the size of the
+ IRC network. If no parameter is given, the reply will be about the
+ whole net. If a <mask> is specified, then the reply will only
+
+
+
+
+Kalt Informational [Page 25]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ concern the part of the network formed by the servers matching the
+ mask. Finally, if the <target> parameter is specified, the request
+ is forwarded to that server which will generate the reply.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numeric Replies:
+
+ RPL_LUSERCLIENT RPL_LUSEROP
+ RPL_LUSERUNKOWN RPL_LUSERCHANNELS
+ RPL_LUSERME ERR_NOSUCHSERVER
+
+3.4.3 Version message
+
+ Command: VERSION
+ Parameters: [ <target> ]
+
+ The VERSION command is used to query the version of the server
+ program. An optional parameter <target> is used to query the version
+ of the server program which a client is not directly connected to.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER RPL_VERSION
+
+ Examples:
+
+ VERSION tolsun.oulu.fi ; Command to check the version of
+ server "tolsun.oulu.fi".
+
+3.4.4 Stats message
+
+ Command: STATS
+ Parameters: [ <query> [ <target> ] ]
+
+ The stats command is used to query statistics of certain server. If
+ <query> parameter is omitted, only the end of stats reply is sent
+ back.
+
+ A query may be given for any single letter which is only checked by
+ the destination server and is otherwise passed on by intermediate
+ servers, ignored and unaltered.
+
+ Wildcards are allowed in the <target> parameter.
+
+
+
+
+
+Kalt Informational [Page 26]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Except for the ones below, the list of valid queries is
+ implementation dependent. The standard queries below SHOULD be
+ supported by the server:
+
+ l - returns a list of the server's connections, showing how
+ long each connection has been established and the
+ traffic over that connection in Kbytes and messages for
+ each direction;
+ m - returns the usage count for each of commands supported
+ by the server; commands for which the usage count is
+ zero MAY be omitted;
+ o - returns a list of configured privileged users,
+ operators;
+ u - returns a string showing how long the server has been
+ up.
+
+ It is also RECOMMENDED that client and server access configuration be
+ published this way.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+ RPL_STATSLINKINFO RPL_STATSUPTIME
+ RPL_STATSCOMMANDS RPL_STATSOLINE
+ RPL_ENDOFSTATS
+
+ Examples:
+
+ STATS m ; Command to check the command usage
+ for the server you are connected to
+
+3.4.5 Links message
+
+ Command: LINKS
+ Parameters: [ [ <remote server> ] <server mask> ]
+
+ With LINKS, a user can list all servernames, which are known by the
+ server answering the query. The returned list of servers MUST match
+ the mask, or if no mask is given, the full list is returned.
+
+ If <remote server> is given in addition to <server mask>, the LINKS
+ command is forwarded to the first server found that matches that name
+ (if any), and that server is then required to answer the query.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+ RPL_LINKS RPL_ENDOFLINKS
+
+
+
+Kalt Informational [Page 27]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Examples:
+
+ LINKS *.au ; Command to list all servers which
+ have a name that matches *.au;
+
+ LINKS *.edu *.bu.edu ; Command to list servers matching
+ *.bu.edu as seen by the first server
+ matching *.edu.
+
+3.4.6 Time message
+
+ Command: TIME
+ Parameters: [ <target> ]
+
+ The time command is used to query local time from the specified
+ server. If the <target> parameter is not given, the server receiving
+ the command must reply to the query.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER RPL_TIME
+
+ Examples:
+ TIME tolsun.oulu.fi ; check the time on the server
+ "tolson.oulu.fi"
+
+3.4.7 Connect message
+
+ Command: CONNECT
+ Parameters: <target server> <port> [ <remote server> ]
+
+ The CONNECT command can be used to request a server to try to
+ establish a new connection to another server immediately. CONNECT is
+ a privileged command and SHOULD be available only to IRC Operators.
+ If a <remote server> is given and its mask doesn't match name of the
+ parsing server, the CONNECT attempt is sent to the first match of
+ remote server. Otherwise the CONNECT attempt is made by the server
+ processing the request.
+
+ The server receiving a remote CONNECT command SHOULD generate a
+ WALLOPS message describing the source and target of the request.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER ERR_NOPRIVILEGES
+ ERR_NEEDMOREPARAMS
+
+
+
+Kalt Informational [Page 28]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Examples:
+
+ CONNECT tolsun.oulu.fi 6667 ; Command to attempt to connect local
+ server to tolsun.oulu.fi on port 6667
+
+3.4.8 Trace message
+
+ Command: TRACE
+ Parameters: [ <target> ]
+
+ TRACE command is used to find the route to specific server and
+ information about its peers. Each server that processes this command
+ MUST report to the sender about it. The replies from pass-through
+ links form a chain, which shows route to destination. After sending
+ this reply back, the query MUST be sent to the next server until
+ given <target> server is reached.
+
+ TRACE command is used to find the route to specific server. Each
+ server that processes this message MUST tell the sender about it by
+ sending a reply indicating it is a pass-through link, forming a chain
+ of replies. After sending this reply back, it MUST then send the
+ TRACE message to the next server until given server is reached. If
+ the <target> parameter is omitted, it is RECOMMENDED that TRACE
+ command sends a message to the sender telling which servers the local
+ server has direct connection to.
+
+ If the destination given by <target> is an actual server, the
+ destination server is REQUIRED to report all servers, services and
+ operators which are connected to it; if the command was issued by an
+ operator, the server MAY also report all users which are connected to
+ it. If the destination given by <target> is a nickname, then only a
+ reply for that nickname is given. If the <target> parameter is
+ omitted, it is RECOMMENDED that the TRACE command is parsed as
+ targeted to the processing server.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+
+ If the TRACE message is destined for another server, all
+ intermediate servers must return a RPL_TRACELINK reply to indicate
+ that the TRACE passed through it and where it is going next.
+
+ RPL_TRACELINK
+
+
+
+
+
+Kalt Informational [Page 29]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ A TRACE reply may be composed of any number of the following
+ numeric replies.
+
+ RPL_TRACECONNECTING RPL_TRACEHANDSHAKE
+ RPL_TRACEUNKNOWN RPL_TRACEOPERATOR
+ RPL_TRACEUSER RPL_TRACESERVER
+ RPL_TRACESERVICE RPL_TRACENEWTYPE
+ RPL_TRACECLASS RPL_TRACELOG
+ RPL_TRACEEND
+
+ Examples:
+
+ TRACE *.oulu.fi ; TRACE to a server matching
+ *.oulu.fi
+
+3.4.9 Admin command
+
+ Command: ADMIN
+ Parameters: [ <target> ]
+
+ The admin command is used to find information about the administrator
+ of the given server, or current server if <target> parameter is
+ omitted. Each server MUST have the ability to forward ADMIN messages
+ to other servers.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+ RPL_ADMINME RPL_ADMINLOC1
+ RPL_ADMINLOC2 RPL_ADMINEMAIL
+
+ Examples:
+
+ ADMIN tolsun.oulu.fi ; request an ADMIN reply from
+ tolsun.oulu.fi
+
+ ADMIN syrk ; ADMIN request for the server to
+ which the user syrk is connected
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 30]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+3.4.10 Info command
+
+ Command: INFO
+ Parameters: [ <target> ]
+
+ The INFO command is REQUIRED to return information describing the
+ server: its version, when it was compiled, the patchlevel, when it
+ was started, and any other miscellaneous information which may be
+ considered to be relevant.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+ RPL_INFO RPL_ENDOFINFO
+
+ Examples:
+
+ INFO csd.bu.edu ; request an INFO reply from
+ csd.bu.edu
+
+ INFO Angel ; request info from the server that
+ Angel is connected to.
+
+3.5 Service Query and Commands
+
+ The service query group of commands has been designed to return
+ information about any service which is connected to the network.
+
+3.5.1 Servlist message
+
+ Command: SERVLIST
+ Parameters: [ <mask> [ <type> ] ]
+
+ The SERVLIST command is used to list services currently connected to
+ the network and visible to the user issuing the command. The
+ optional parameters may be used to restrict the result of the query
+ (to matching services names, and services type).
+
+ Numeric Replies:
+
+ RPL_SERVLIST RPL_SERVLISTEND
+
+
+
+
+
+
+
+
+Kalt Informational [Page 31]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+3.5.2 Squery
+
+ Command: SQUERY
+ Parameters: <servicename> <text>
+
+ The SQUERY command is used similarly to PRIVMSG. The only difference
+ is that the recipient MUST be a service. This is the only way for a
+ text message to be delivered to a service.
+
+ See PRIVMSG for more details on replies and example.
+
+ Examples:
+
+ SQUERY irchelp :HELP privmsg
+ ; Message to the service with
+ nickname irchelp.
+
+ SQUERY dict@irc.fr :fr2en blaireau
+ ; Message to the service with name
+ dict@irc.fr.
+
+3.6 User based queries
+
+ User queries are a group of commands which are primarily concerned
+ with finding details on a particular user or group users. When using
+ wildcards with any of these commands, if they match, they will only
+ return information on users who are 'visible' to you. The visibility
+ of a user is determined as a combination of the user's mode and the
+ common set of channels you are both on.
+
+ Although services SHOULD NOT be using this class of message, they are
+ allowed to.
+
+3.6.1 Who query
+
+ Command: WHO
+ Parameters: [ <mask> [ "o" ] ]
+
+ The WHO command is used by a client to generate a query which returns
+ a list of information which 'matches' the <mask> parameter given by
+ the client. In the absence of the <mask> parameter, all visible
+ (users who aren't invisible (user mode +i) and who don't have a
+ common channel with the requesting client) are listed. The same
+ result can be achieved by using a <mask> of "0" or any wildcard which
+ will end up matching every visible user.
+
+ The <mask> passed to WHO is matched against users' host, server, real
+ name and nickname if the channel <mask> cannot be found.
+
+
+
+Kalt Informational [Page 32]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ If the "o" parameter is passed only operators are returned according
+ to the <mask> supplied.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER
+ RPL_WHOREPLY RPL_ENDOFWHO
+
+ Examples:
+
+ WHO *.fi ; Command to list all users who match
+ against "*.fi".
+
+ WHO jto* o ; Command to list all users with a
+ match against "jto*" if they are an
+ operator.
+
+3.6.2 Whois query
+
+ Command: WHOIS
+ Parameters: [ <target> ] <mask> *( "," <mask> )
+
+ This command is used to query information about particular user.
+ The server will answer this command with several numeric messages
+ indicating different statuses of each user which matches the mask (if
+ you are entitled to see them). If no wildcard is present in the
+ <mask>, any information about that nick which you are allowed to see
+ is presented.
+
+ If the <target> parameter is specified, it sends the query to a
+ specific server. It is useful if you want to know how long the user
+ in question has been idle as only local server (i.e., the server the
+ user is directly connected to) knows that information, while
+ everything else is globally known.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER ERR_NONICKNAMEGIVEN
+ RPL_WHOISUSER RPL_WHOISCHANNELS
+ RPL_WHOISCHANNELS RPL_WHOISSERVER
+ RPL_AWAY RPL_WHOISOPERATOR
+ RPL_WHOISIDLE ERR_NOSUCHNICK
+ RPL_ENDOFWHOIS
+
+
+
+
+
+
+Kalt Informational [Page 33]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Examples:
+
+ WHOIS wiz ; return available user information
+ about nick WiZ
+
+ WHOIS eff.org trillian ; ask server eff.org for user
+ information about trillian
+
+3.6.3 Whowas
+
+ Command: WHOWAS
+ Parameters: <nickname> *( "," <nickname> ) [ <count> [ <target> ] ]
+
+ Whowas asks for information about a nickname which no longer exists.
+ This may either be due to a nickname change or the user leaving IRC.
+ In response to this query, the server searches through its nickname
+ history, looking for any nicks which are lexically the same (no wild
+ card matching here). The history is searched backward, returning the
+ most recent entry first. If there are multiple entries, up to
+ <count> replies will be returned (or all of them if no <count>
+ parameter is given). If a non-positive number is passed as being
+ <count>, then a full search is done.
+
+ Wildcards are allowed in the <target> parameter.
+
+ Numeric Replies:
+
+ ERR_NONICKNAMEGIVEN ERR_WASNOSUCHNICK
+ RPL_WHOWASUSER RPL_WHOISSERVER
+ RPL_ENDOFWHOWAS
+
+ Examples:
+
+ WHOWAS Wiz ; return all information in the nick
+ history about nick "WiZ";
+
+ WHOWAS Mermaid 9 ; return at most, the 9 most recent
+ entries in the nick history for
+ "Mermaid";
+
+ WHOWAS Trillian 1 *.edu ; return the most recent history for
+ "Trillian" from the first server
+ found to match "*.edu".
+
+3.7 Miscellaneous messages
+
+ Messages in this category do not fit into any of the above categories
+ but are nonetheless still a part of and REQUIRED by the protocol.
+
+
+
+Kalt Informational [Page 34]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+3.7.1 Kill message
+
+ Command: KILL
+ Parameters: <nickname> <comment>
+
+ The KILL command is used to cause a client-server connection to be
+ closed by the server which has the actual connection. Servers
+ generate KILL messages on nickname collisions. It MAY also be
+ available available to users who have the operator status.
+
+ Clients which have automatic reconnect algorithms effectively make
+ this command useless since the disconnection is only brief. It does
+ however break the flow of data and can be used to stop large amounts
+ of 'flooding' from abusive users or accidents. Abusive users usually
+ don't care as they will reconnect promptly and resume their abusive
+ behaviour. To prevent this command from being abused, any user may
+ elect to receive KILL messages generated for others to keep an 'eye'
+ on would be trouble spots.
+
+ In an arena where nicknames are REQUIRED to be globally unique at all
+ times, KILL messages are sent whenever 'duplicates' are detected
+ (that is an attempt to register two users with the same nickname) in
+ the hope that both of them will disappear and only 1 reappear.
+
+ When a client is removed as the result of a KILL message, the server
+ SHOULD add the nickname to the list of unavailable nicknames in an
+ attempt to avoid clients to reuse this name immediately which is
+ usually the pattern of abusive behaviour often leading to useless
+ "KILL loops". See the "IRC Server Protocol" document [IRC-SERVER]
+ for more information on this procedure.
+
+ The comment given MUST reflect the actual reason for the KILL. For
+ server-generated KILLs it usually is made up of details concerning
+ the origins of the two conflicting nicknames. For users it is left
+ up to them to provide an adequate reason to satisfy others who see
+ it. To prevent/discourage fake KILLs from being generated to hide
+ the identify of the KILLer, the comment also shows a 'kill-path'
+ which is updated by each server it passes through, each prepending
+ its name to the path.
+
+ Numeric Replies:
+
+ ERR_NOPRIVILEGES ERR_NEEDMOREPARAMS
+ ERR_NOSUCHNICK ERR_CANTKILLSERVER
+
+
+
+
+
+
+
+Kalt Informational [Page 35]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ NOTE:
+ It is RECOMMENDED that only Operators be allowed to kill other users
+ with KILL command. This command has been the subject of many
+ controversies over the years, and along with the above
+ recommendation, it is also widely recognized that not even operators
+ should be allowed to kill users on remote servers.
+
+3.7.2 Ping message
+
+ Command: PING
+ Parameters: <server1> [ <server2> ]
+
+ The PING command is used to test the presence of an active client or
+ server at the other end of the connection. Servers send a PING
+ message at regular intervals if no other activity detected coming
+ from a connection. If a connection fails to respond to a PING
+ message within a set amount of time, that connection is closed. A
+ PING message MAY be sent even if the connection is active.
+
+ When a PING message is received, the appropriate PONG message MUST be
+ sent as reply to <server1> (server which sent the PING message out)
+ as soon as possible. If the <server2> parameter is specified, it
+ represents the target of the ping, and the message gets forwarded
+ there.
+
+ Numeric Replies:
+
+ ERR_NOORIGIN ERR_NOSUCHSERVER
+
+ Examples:
+
+ PING tolsun.oulu.fi ; Command to send a PING message to
+ server
+
+ PING WiZ tolsun.oulu.fi ; Command from WiZ to send a PING
+ message to server "tolsun.oulu.fi"
+
+ PING :irc.funet.fi ; Ping message sent by server
+ "irc.funet.fi"
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 36]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+3.7.3 Pong message
+
+ Command: PONG
+ Parameters: <server> [ <server2> ]
+
+ PONG message is a reply to ping message. If parameter <server2> is
+ given, this message MUST be forwarded to given target. The <server>
+ parameter is the name of the entity who has responded to PING message
+ and generated this message.
+
+ Numeric Replies:
+
+ ERR_NOORIGIN ERR_NOSUCHSERVER
+
+ Example:
+
+ PONG csd.bu.edu tolsun.oulu.fi ; PONG message from csd.bu.edu to
+ tolsun.oulu.fi
+
+3.7.4 Error
+
+ Command: ERROR
+ Parameters: <error message>
+
+ The ERROR command is for use by servers when reporting a serious or
+ fatal error to its peers. It may also be sent from one server to
+ another but MUST NOT be accepted from any normal unknown clients.
+
+ Only an ERROR message SHOULD be used for reporting errors which occur
+ with a server-to-server link. An ERROR message is sent to the server
+ at the other end (which reports it to appropriate local users and
+ logs) and to appropriate local users and logs. It is not to be
+ passed onto any other servers by a server if it is received from a
+ server.
+
+ The ERROR message is also used before terminating a client
+ connection.
+
+ When a server sends a received ERROR message to its operators, the
+ message SHOULD be encapsulated inside a NOTICE message, indicating
+ that the client was not responsible for the error.
+
+ Numerics:
+
+ None.
+
+
+
+
+
+
+Kalt Informational [Page 37]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Examples:
+
+ ERROR :Server *.fi already exists ; ERROR message to the other server
+ which caused this error.
+
+ NOTICE WiZ :ERROR from csd.bu.edu -- Server *.fi already exists
+ ; Same ERROR message as above but
+ sent to user WiZ on the other server.
+
+4. Optional features
+
+ This section describes OPTIONAL messages. They are not required in a
+ working server implementation of the protocol described herein. In
+ the absence of the feature, an error reply message MUST be generated
+ or an unknown command error. If the message is destined for another
+ server to answer then it MUST be passed on (elementary parsing
+ REQUIRED) The allocated numerics for this are listed with the
+ messages below.
+
+ From this section, only the USERHOST and ISON messages are available
+ to services.
+
+4.1 Away
+
+ Command: AWAY
+ Parameters: [ <text> ]
+
+ With the AWAY command, clients can set an automatic reply string for
+ any PRIVMSG commands directed at them (not to a channel they are on).
+ The server sends an automatic reply to the client sending the PRIVMSG
+ command. The only replying server is the one to which the sending
+ client is connected to.
+
+ The AWAY command is used either with one parameter, to set an AWAY
+ message, or with no parameters, to remove the AWAY message.
+
+ Because of its high cost (memory and bandwidth wise), the AWAY
+ message SHOULD only be used for client-server communication. A
+ server MAY choose to silently ignore AWAY messages received from
+ other servers. To update the away status of a client across servers,
+ the user mode 'a' SHOULD be used instead. (See Section 3.1.5)
+
+ Numeric Replies:
+
+ RPL_UNAWAY RPL_NOWAWAY
+
+
+
+
+
+
+Kalt Informational [Page 38]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Example:
+
+ AWAY :Gone to lunch. Back in 5 ; Command to set away message to
+ "Gone to lunch. Back in 5".
+
+4.2 Rehash message
+
+ Command: REHASH
+ Parameters: None
+
+ The rehash command is an administrative command which can be used by
+ an operator to force the server to re-read and process its
+ configuration file.
+
+ Numeric Replies:
+
+ RPL_REHASHING ERR_NOPRIVILEGES
+
+
+ Example:
+
+ REHASH ; message from user with operator
+ status to server asking it to reread
+ its configuration file.
+
+4.3 Die message
+
+ Command: DIE
+ Parameters: None
+
+ An operator can use the DIE command to shutdown the server. This
+ message is optional since it may be viewed as a risk to allow
+ arbitrary people to connect to a server as an operator and execute
+ this command.
+
+ The DIE command MUST always be fully processed by the server to which
+ the sending client is connected and MUST NOT be passed onto other
+ connected servers.
+
+ Numeric Replies:
+
+ ERR_NOPRIVILEGES
+
+ Example:
+
+ DIE ; no parameters required.
+
+
+
+
+
+Kalt Informational [Page 39]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+4.4 Restart message
+
+ Command: RESTART
+ Parameters: None
+
+ An operator can use the restart command to force the server to
+ restart itself. This message is optional since it may be viewed as a
+ risk to allow arbitrary people to connect to a server as an operator
+ and execute this command, causing (at least) a disruption to service.
+
+ The RESTART command MUST always be fully processed by the server to
+ which the sending client is connected and MUST NOT be passed onto
+ other connected servers.
+
+ Numeric Replies:
+
+ ERR_NOPRIVILEGES
+
+ Example:
+
+ RESTART ; no parameters required.
+
+4.5 Summon message
+
+ Command: SUMMON
+ Parameters: <user> [ <target> [ <channel> ] ]
+
+ The SUMMON command can be used to give users who are on a host
+ running an IRC server a message asking them to please join IRC. This
+ message is only sent if the target server (a) has SUMMON enabled, (b)
+ the user is logged in and (c) the server process can write to the
+ user's tty (or similar).
+
+ If no <server> parameter is given it tries to summon <user> from the
+ server the client is connected to is assumed as the target.
+
+ If summon is not enabled in a server, it MUST return the
+ ERR_SUMMONDISABLED numeric.
+
+ Numeric Replies:
+
+ ERR_NORECIPIENT ERR_FILEERROR
+ ERR_NOLOGIN ERR_NOSUCHSERVER
+ ERR_SUMMONDISABLED RPL_SUMMONING
+
+
+
+
+
+
+
+Kalt Informational [Page 40]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ Examples:
+
+ SUMMON jto ; summon user jto on the server's
+ host
+
+ SUMMON jto tolsun.oulu.fi ; summon user jto on the host which a
+ server named "tolsun.oulu.fi" is
+ running.
+
+4.6 Users
+
+ Command: USERS
+ Parameters: [ <target> ]
+
+ The USERS command returns a list of users logged into the server in a
+ format similar to the UNIX commands who(1), rusers(1) and finger(1).
+ If disabled, the correct numeric MUST be returned to indicate this.
+
+ Because of the security implications of such a command, it SHOULD be
+ disabled by default in server implementations. Enabling it SHOULD
+ require recompiling the server or some equivalent change rather than
+ simply toggling an option and restarting the server. The procedure
+ to enable this command SHOULD also include suitable large comments.
+
+ Numeric Replies:
+
+ ERR_NOSUCHSERVER ERR_FILEERROR
+ RPL_USERSSTART RPL_USERS
+ RPL_NOUSERS RPL_ENDOFUSERS
+ ERR_USERSDISABLED
+
+ Disabled Reply:
+
+ ERR_USERSDISABLED
+
+ Example:
+
+ USERS eff.org ; request a list of users logged in
+ on server eff.org
+
+4.7 Operwall message
+
+ Command: WALLOPS
+ Parameters: <Text to be sent>
+
+ The WALLOPS command is used to send a message to all currently
+ connected users who have set the 'w' user mode for themselves. (See
+ Section 3.1.5 "User modes").
+
+
+
+Kalt Informational [Page 41]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ After implementing WALLOPS as a user command it was found that it was
+ often and commonly abused as a means of sending a message to a lot of
+ people. Due to this, it is RECOMMENDED that the implementation of
+ WALLOPS allows and recognizes only servers as the originators of
+ WALLOPS.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS
+
+ Example:
+
+ :csd.bu.edu WALLOPS :Connect '*.uiuc.edu 6667' from Joshua ; WALLOPS
+ message from csd.bu.edu announcing a
+ CONNECT message it received from
+ Joshua and acted upon.
+
+4.8 Userhost message
+
+ Command: USERHOST
+ Parameters: <nickname> *( SPACE <nickname> )
+
+ The USERHOST command takes a list of up to 5 nicknames, each
+ separated by a space character and returns a list of information
+ about each nickname that it found. The returned list has each reply
+ separated by a space.
+
+ Numeric Replies:
+
+ RPL_USERHOST ERR_NEEDMOREPARAMS
+
+ Example:
+
+ USERHOST Wiz Michael syrk ; USERHOST request for information on
+ nicks "Wiz", "Michael", and "syrk"
+
+ :ircd.stealth.net 302 yournick :syrk=+syrk@millennium.stealth.net
+ ; Reply for user syrk
+
+4.9 Ison message
+
+ Command: ISON
+ Parameters: <nickname> *( SPACE <nickname> )
+
+ The ISON command was implemented to provide a quick and efficient
+ means to get a response about whether a given nickname was currently
+ on IRC. ISON only takes one (1) type of parameter: a space-separated
+ list of nicks. For each nickname in the list that is present, the
+
+
+
+Kalt Informational [Page 42]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ server adds that to its reply string. Thus the reply string may
+ return empty (none of the given nicks are present), an exact copy of
+ the parameter string (all of them present) or any other subset of the
+ set of nicks given in the parameter. The only limit on the number of
+ nicks that may be checked is that the combined length MUST NOT be too
+ large as to cause the server to chop it off so it fits in 512
+ characters.
+
+ ISON is only processed by the server local to the client sending the
+ command and thus not passed onto other servers for further
+ processing.
+
+ Numeric Replies:
+
+ RPL_ISON ERR_NEEDMOREPARAMS
+
+ Example:
+
+ ISON phone trillian WiZ jarlek Avalon Angel Monstah syrk
+ ; Sample ISON request for 7 nicks.
+
+5. Replies
+
+ The following is a list of numeric replies which are generated in
+ response to the commands given above. Each numeric is given with its
+ number, name and reply string.
+
+5.1 Command responses
+
+ Numerics in the range from 001 to 099 are used for client-server
+ connections only and should never travel between servers. Replies
+ generated in the response to commands are found in the range from 200
+ to 399.
+
+ 001 RPL_WELCOME
+ "Welcome to the Internet Relay Network
+ <nick>!<user>@<host>"
+ 002 RPL_YOURHOST
+ "Your host is <servername>, running version <ver>"
+ 003 RPL_CREATED
+ "This server was created <date>"
+ 004 RPL_MYINFO
+ "<servername> <version> <available user modes>
+ <available channel modes>"
+
+ - The server sends Replies 001 to 004 to a user upon
+ successful registration.
+
+
+
+
+Kalt Informational [Page 43]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 005 RPL_BOUNCE
+ "Try server <server name>, port <port number>"
+
+ - Sent by the server to a user to suggest an alternative
+ server. This is often used when the connection is
+ refused because the server is already full.
+
+ 302 RPL_USERHOST
+ ":*1<reply> *( " " <reply> )"
+
+ - Reply format used by USERHOST to list replies to
+ the query list. The reply string is composed as
+ follows:
+
+ reply = nickname [ "*" ] "=" ( "+" / "-" ) hostname
+
+ The '*' indicates whether the client has registered
+ as an Operator. The '-' or '+' characters represent
+ whether the client has set an AWAY message or not
+ respectively.
+
+ 303 RPL_ISON
+ ":*1<nick> *( " " <nick> )"
+
+ - Reply format used by ISON to list replies to the
+ query list.
+
+ 301 RPL_AWAY
+ "<nick> :<away message>"
+ 305 RPL_UNAWAY
+ ":You are no longer marked as being away"
+ 306 RPL_NOWAWAY
+ ":You have been marked as being away"
+
+ - These replies are used with the AWAY command (if
+ allowed). RPL_AWAY is sent to any client sending a
+ PRIVMSG to a client which is away. RPL_AWAY is only
+ sent by the server to which the client is connected.
+ Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the
+ client removes and sets an AWAY message.
+
+ 311 RPL_WHOISUSER
+ "<nick> <user> <host> * :<real name>"
+ 312 RPL_WHOISSERVER
+ "<nick> <server> :<server info>"
+ 313 RPL_WHOISOPERATOR
+ "<nick> :is an IRC operator"
+
+
+
+
+Kalt Informational [Page 44]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 317 RPL_WHOISIDLE
+ "<nick> <integer> :seconds idle"
+ 318 RPL_ENDOFWHOIS
+ "<nick> :End of WHOIS list"
+ 319 RPL_WHOISCHANNELS
+ "<nick> :*( ( "@" / "+" ) <channel> " " )"
+
+ - Replies 311 - 313, 317 - 319 are all replies
+ generated in response to a WHOIS message. Given that
+ there are enough parameters present, the answering
+ server MUST either formulate a reply out of the above
+ numerics (if the query nick is found) or return an
+ error reply. The '*' in RPL_WHOISUSER is there as
+ the literal character and not as a wild card. For
+ each reply set, only RPL_WHOISCHANNELS may appear
+ more than once (for long lists of channel names).
+ The '@' and '+' characters next to the channel name
+ indicate whether a client is a channel operator or
+ has been granted permission to speak on a moderated
+ channel. The RPL_ENDOFWHOIS reply is used to mark
+ the end of processing a WHOIS message.
+
+ 314 RPL_WHOWASUSER
+ "<nick> <user> <host> * :<real name>"
+ 369 RPL_ENDOFWHOWAS
+ "<nick> :End of WHOWAS"
+
+ - When replying to a WHOWAS message, a server MUST use
+ the replies RPL_WHOWASUSER, RPL_WHOISSERVER or
+ ERR_WASNOSUCHNICK for each nickname in the presented
+ list. At the end of all reply batches, there MUST
+ be RPL_ENDOFWHOWAS (even if there was only one reply
+ and it was an error).
+
+ 321 RPL_LISTSTART
+ Obsolete. Not used.
+
+ 322 RPL_LIST
+ "<channel> <# visible> :<topic>"
+ 323 RPL_LISTEND
+ ":End of LIST"
+
+ - Replies RPL_LIST, RPL_LISTEND mark the actual replies
+ with data and end of the server's response to a LIST
+ command. If there are no channels available to return,
+ only the end reply MUST be sent.
+
+
+
+
+
+Kalt Informational [Page 45]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 325 RPL_UNIQOPIS
+ "<channel> <nickname>"
+
+ 324 RPL_CHANNELMODEIS
+ "<channel> <mode> <mode params>"
+
+ 331 RPL_NOTOPIC
+ "<channel> :No topic is set"
+ 332 RPL_TOPIC
+ "<channel> :<topic>"
+
+ - When sending a TOPIC message to determine the
+ channel topic, one of two replies is sent. If
+ the topic is set, RPL_TOPIC is sent back else
+ RPL_NOTOPIC.
+
+ 341 RPL_INVITING
+ "<channel> <nick>"
+
+ - Returned by the server to indicate that the
+ attempted INVITE message was successful and is
+ being passed onto the end client.
+
+ 342 RPL_SUMMONING
+ "<user> :Summoning user to IRC"
+
+ - Returned by a server answering a SUMMON message to
+ indicate that it is summoning that user.
+
+ 346 RPL_INVITELIST
+ "<channel> <invitemask>"
+ 347 RPL_ENDOFINVITELIST
+ "<channel> :End of channel invite list"
+
+ - When listing the 'invitations masks' for a given channel,
+ a server is required to send the list back using the
+ RPL_INVITELIST and RPL_ENDOFINVITELIST messages. A
+ separate RPL_INVITELIST is sent for each active mask.
+ After the masks have been listed (or if none present) a
+ RPL_ENDOFINVITELIST MUST be sent.
+
+ 348 RPL_EXCEPTLIST
+ "<channel> <exceptionmask>"
+ 349 RPL_ENDOFEXCEPTLIST
+ "<channel> :End of channel exception list"
+
+
+
+
+
+
+Kalt Informational [Page 46]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ - When listing the 'exception masks' for a given channel,
+ a server is required to send the list back using the
+ RPL_EXCEPTLIST and RPL_ENDOFEXCEPTLIST messages. A
+ separate RPL_EXCEPTLIST is sent for each active mask.
+ After the masks have been listed (or if none present)
+ a RPL_ENDOFEXCEPTLIST MUST be sent.
+
+ 351 RPL_VERSION
+ "<version>.<debuglevel> <server> :<comments>"
+
+ - Reply by the server showing its version details.
+ The <version> is the version of the software being
+ used (including any patchlevel revisions) and the
+ <debuglevel> is used to indicate if the server is
+ running in "debug mode".
+
+ The "comments" field may contain any comments about
+ the version or further version details.
+
+ 352 RPL_WHOREPLY
+ "<channel> <user> <host> <server> <nick>
+ ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
+ :<hopcount> <real name>"
+
+ 315 RPL_ENDOFWHO
+ "<name> :End of WHO list"
+
+ - The RPL_WHOREPLY and RPL_ENDOFWHO pair are used
+ to answer a WHO message. The RPL_WHOREPLY is only
+ sent if there is an appropriate match to the WHO
+ query. If there is a list of parameters supplied
+ with a WHO message, a RPL_ENDOFWHO MUST be sent
+ after processing each list item with <name> being
+ the item.
+
+ 353 RPL_NAMREPLY
+ "( "=" / "*" / "@" ) <channel>
+ :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
+ - "@" is used for secret channels, "*" for private
+ channels, and "=" for others (public channels).
+
+ 366 RPL_ENDOFNAMES
+ "<channel> :End of NAMES list"
+
+ - To reply to a NAMES message, a reply pair consisting
+ of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
+ server back to the client. If there is no channel
+ found as in the query, then only RPL_ENDOFNAMES is
+
+
+
+Kalt Informational [Page 47]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ returned. The exception to this is when a NAMES
+ message is sent with no parameters and all visible
+ channels and contents are sent back in a series of
+ RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
+ the end.
+
+ 364 RPL_LINKS
+ "<mask> <server> :<hopcount> <server info>"
+ 365 RPL_ENDOFLINKS
+ "<mask> :End of LINKS list"
+
+ - In replying to the LINKS message, a server MUST send
+ replies back using the RPL_LINKS numeric and mark the
+ end of the list using an RPL_ENDOFLINKS reply.
+
+ 367 RPL_BANLIST
+ "<channel> <banmask>"
+ 368 RPL_ENDOFBANLIST
+ "<channel> :End of channel ban list"
+
+ - When listing the active 'bans' for a given channel,
+ a server is required to send the list back using the
+ RPL_BANLIST and RPL_ENDOFBANLIST messages. A separate
+ RPL_BANLIST is sent for each active banmask. After the
+ banmasks have been listed (or if none present) a
+ RPL_ENDOFBANLIST MUST be sent.
+
+ 371 RPL_INFO
+ ":<string>"
+ 374 RPL_ENDOFINFO
+ ":End of INFO list"
+
+ - A server responding to an INFO message is required to
+ send all its 'info' in a series of RPL_INFO messages
+ with a RPL_ENDOFINFO reply to indicate the end of the
+ replies.
+
+ 375 RPL_MOTDSTART
+ ":- <server> Message of the day - "
+ 372 RPL_MOTD
+ ":- <text>"
+ 376 RPL_ENDOFMOTD
+ ":End of MOTD command"
+
+ - When responding to the MOTD message and the MOTD file
+ is found, the file is displayed line by line, with
+ each line no longer than 80 characters, using
+
+
+
+
+Kalt Informational [Page 48]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ RPL_MOTD format replies. These MUST be surrounded
+ by a RPL_MOTDSTART (before the RPL_MOTDs) and an
+ RPL_ENDOFMOTD (after).
+
+ 381 RPL_YOUREOPER
+ ":You are now an IRC operator"
+
+ - RPL_YOUREOPER is sent back to a client which has
+ just successfully issued an OPER message and gained
+ operator status.
+
+ 382 RPL_REHASHING
+ "<config file> :Rehashing"
+
+ - If the REHASH option is used and an operator sends
+ a REHASH message, an RPL_REHASHING is sent back to
+ the operator.
+
+ 383 RPL_YOURESERVICE
+ "You are service <servicename>"
+
+ - Sent by the server to a service upon successful
+ registration.
+
+ 391 RPL_TIME
+ "<server> :<string showing server's local time>"
+
+ - When replying to the TIME message, a server MUST send
+ the reply using the RPL_TIME format above. The string
+ showing the time need only contain the correct day and
+ time there. There is no further requirement for the
+ time string.
+
+ 392 RPL_USERSSTART
+ ":UserID Terminal Host"
+ 393 RPL_USERS
+ ":<username> <ttyline> <hostname>"
+ 394 RPL_ENDOFUSERS
+ ":End of users"
+ 395 RPL_NOUSERS
+ ":Nobody logged in"
+
+ - If the USERS message is handled by a server, the
+ replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
+ RPL_NOUSERS are used. RPL_USERSSTART MUST be sent
+ first, following by either a sequence of RPL_USERS
+ or a single RPL_NOUSER. Following this is
+ RPL_ENDOFUSERS.
+
+
+
+Kalt Informational [Page 49]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 200 RPL_TRACELINK
+ "Link <version & debug level> <destination>
+ <next server> V<protocol version>
+ <link uptime in seconds> <backstream sendq>
+ <upstream sendq>"
+ 201 RPL_TRACECONNECTING
+ "Try. <class> <server>"
+ 202 RPL_TRACEHANDSHAKE
+ "H.S. <class> <server>"
+ 203 RPL_TRACEUNKNOWN
+ "???? <class> [<client IP address in dot form>]"
+ 204 RPL_TRACEOPERATOR
+ "Oper <class> <nick>"
+ 205 RPL_TRACEUSER
+ "User <class> <nick>"
+ 206 RPL_TRACESERVER
+ "Serv <class> <int>S <int>C <server>
+ <nick!user|*!*>@<host|server> V<protocol version>"
+ 207 RPL_TRACESERVICE
+ "Service <class> <name> <type> <active type>"
+ 208 RPL_TRACENEWTYPE
+ "<newtype> 0 <client name>"
+ 209 RPL_TRACECLASS
+ "Class <class> <count>"
+ 210 RPL_TRACERECONNECT
+ Unused.
+ 261 RPL_TRACELOG
+ "File <logfile> <debug level>"
+ 262 RPL_TRACEEND
+ "<server name> <version & debug level> :End of TRACE"
+
+ - The RPL_TRACE* are all returned by the server in
+ response to the TRACE message. How many are
+ returned is dependent on the TRACE message and
+ whether it was sent by an operator or not. There
+ is no predefined order for which occurs first.
+ Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+ RPL_TRACEHANDSHAKE are all used for connections
+ which have not been fully established and are either
+ unknown, still attempting to connect or in the
+ process of completing the 'server handshake'.
+ RPL_TRACELINK is sent by any server which handles
+ a TRACE message and has to pass it on to another
+ server. The list of RPL_TRACELINKs sent in
+ response to a TRACE command traversing the IRC
+ network should reflect the actual connectivity of
+ the servers themselves along that path.
+
+
+
+
+Kalt Informational [Page 50]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ RPL_TRACENEWTYPE is to be used for any connection
+ which does not fit in the other categories but is
+ being displayed anyway.
+ RPL_TRACEEND is sent to indicate the end of the list.
+
+ 211 RPL_STATSLINKINFO
+ "<linkname> <sendq> <sent messages>
+ <sent Kbytes> <received messages>
+ <received Kbytes> <time open>"
+
+ - reports statistics on a connection. <linkname>
+ identifies the particular connection, <sendq> is
+ the amount of data that is queued and waiting to be
+ sent <sent messages> the number of messages sent,
+ and <sent Kbytes> the amount of data sent, in
+ Kbytes. <received messages> and <received Kbytes>
+ are the equivalent of <sent messages> and <sent
+ Kbytes> for received data, respectively. <time
+ open> indicates how long ago the connection was
+ opened, in seconds.
+
+ 212 RPL_STATSCOMMANDS
+ "<command> <count> <byte count> <remote count>"
+
+ - reports statistics on commands usage.
+
+ 219 RPL_ENDOFSTATS
+ "<stats letter> :End of STATS report"
+
+ 242 RPL_STATSUPTIME
+ ":Server Up %d days %d:%02d:%02d"
+
+ - reports the server uptime.
+
+ 243 RPL_STATSOLINE
+ "O <hostmask> * <name>"
+
+ - reports the allowed hosts from where user may become IRC
+ operators.
+
+ 221 RPL_UMODEIS
+ "<user mode string>"
+
+ - To answer a query about a client's own mode,
+ RPL_UMODEIS is sent back.
+
+ 234 RPL_SERVLIST
+ "<name> <server> <mask> <type> <hopcount> <info>"
+
+
+
+Kalt Informational [Page 51]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 235 RPL_SERVLISTEND
+ "<mask> <type> :End of service listing"
+
+ - When listing services in reply to a SERVLIST message,
+ a server is required to send the list back using the
+ RPL_SERVLIST and RPL_SERVLISTEND messages. A separate
+ RPL_SERVLIST is sent for each service. After the
+ services have been listed (or if none present) a
+ RPL_SERVLISTEND MUST be sent.
+
+ 251 RPL_LUSERCLIENT
+ ":There are <integer> users and <integer>
+ services on <integer> servers"
+ 252 RPL_LUSEROP
+ "<integer> :operator(s) online"
+ 253 RPL_LUSERUNKNOWN
+ "<integer> :unknown connection(s)"
+ 254 RPL_LUSERCHANNELS
+ "<integer> :channels formed"
+ 255 RPL_LUSERME
+ ":I have <integer> clients and <integer>
+ servers"
+
+ - In processing an LUSERS message, the server
+ sends a set of replies from RPL_LUSERCLIENT,
+ RPL_LUSEROP, RPL_USERUNKNOWN,
+ RPL_LUSERCHANNELS and RPL_LUSERME. When
+ replying, a server MUST send back
+ RPL_LUSERCLIENT and RPL_LUSERME. The other
+ replies are only sent back if a non-zero count
+ is found for them.
+
+ 256 RPL_ADMINME
+ "<server> :Administrative info"
+ 257 RPL_ADMINLOC1
+ ":<admin info>"
+ 258 RPL_ADMINLOC2
+ ":<admin info>"
+ 259 RPL_ADMINEMAIL
+ ":<admin info>"
+
+ - When replying to an ADMIN message, a server
+ is expected to use replies RPL_ADMINME
+ through to RPL_ADMINEMAIL and provide a text
+ message with each. For RPL_ADMINLOC1 a
+ description of what city, state and country
+ the server is in is expected, followed by
+ details of the institution (RPL_ADMINLOC2)
+
+
+
+Kalt Informational [Page 52]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ and finally the administrative contact for the
+ server (an email address here is REQUIRED)
+ in RPL_ADMINEMAIL.
+
+ 263 RPL_TRYAGAIN
+ "<command> :Please wait a while and try again."
+
+ - When a server drops a command without processing it,
+ it MUST use the reply RPL_TRYAGAIN to inform the
+ originating client.
+
+5.2 Error Replies
+
+ Error replies are found in the range from 400 to 599.
+
+ 401 ERR_NOSUCHNICK
+ "<nickname> :No such nick/channel"
+
+ - Used to indicate the nickname parameter supplied to a
+ command is currently unused.
+
+ 402 ERR_NOSUCHSERVER
+ "<server name> :No such server"
+
+ - Used to indicate the server name given currently
+ does not exist.
+
+ 403 ERR_NOSUCHCHANNEL
+ "<channel name> :No such channel"
+
+ - Used to indicate the given channel name is invalid.
+
+ 404 ERR_CANNOTSENDTOCHAN
+ "<channel name> :Cannot send to channel"
+
+ - Sent to a user who is either (a) not on a channel
+ which is mode +n or (b) not a chanop (or mode +v) on
+ a channel which has mode +m set or where the user is
+ banned and is trying to send a PRIVMSG message to
+ that channel.
+
+ 405 ERR_TOOMANYCHANNELS
+ "<channel name> :You have joined too many channels"
+
+ - Sent to a user when they have joined the maximum
+ number of allowed channels and they try to join
+ another channel.
+
+
+
+
+Kalt Informational [Page 53]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 406 ERR_WASNOSUCHNICK
+ "<nickname> :There was no such nickname"
+
+ - Returned by WHOWAS to indicate there is no history
+ information for that nickname.
+
+ 407 ERR_TOOMANYTARGETS
+ "<target> :<error code> recipients. <abort message>"
+
+ - Returned to a client which is attempting to send a
+ PRIVMSG/NOTICE using the user@host destination format
+ and for a user@host which has several occurrences.
+
+ - Returned to a client which trying to send a
+ PRIVMSG/NOTICE to too many recipients.
+
+ - Returned to a client which is attempting to JOIN a safe
+ channel using the shortname when there are more than one
+ such channel.
+
+ 408 ERR_NOSUCHSERVICE
+ "<service name> :No such service"
+
+ - Returned to a client which is attempting to send a SQUERY
+ to a service which does not exist.
+
+ 409 ERR_NOORIGIN
+ ":No origin specified"
+
+ - PING or PONG message missing the originator parameter.
+
+ 411 ERR_NORECIPIENT
+ ":No recipient given (<command>)"
+ 412 ERR_NOTEXTTOSEND
+ ":No text to send"
+ 413 ERR_NOTOPLEVEL
+ "<mask> :No toplevel domain specified"
+ 414 ERR_WILDTOPLEVEL
+ "<mask> :Wildcard in toplevel domain"
+ 415 ERR_BADMASK
+ "<mask> :Bad Server/host mask"
+
+ - 412 - 415 are returned by PRIVMSG to indicate that
+ the message wasn't delivered for some reason.
+ ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
+ are returned when an invalid use of
+ "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted.
+
+
+
+
+Kalt Informational [Page 54]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 421 ERR_UNKNOWNCOMMAND
+ "<command> :Unknown command"
+
+ - Returned to a registered client to indicate that the
+ command sent is unknown by the server.
+
+ 422 ERR_NOMOTD
+ ":MOTD File is missing"
+
+ - Server's MOTD file could not be opened by the server.
+
+ 423 ERR_NOADMININFO
+ "<server> :No administrative info available"
+
+ - Returned by a server in response to an ADMIN message
+ when there is an error in finding the appropriate
+ information.
+
+ 424 ERR_FILEERROR
+ ":File error doing <file op> on <file>"
+
+ - Generic error message used to report a failed file
+ operation during the processing of a message.
+
+ 431 ERR_NONICKNAMEGIVEN
+ ":No nickname given"
+
+ - Returned when a nickname parameter expected for a
+ command and isn't found.
+
+ 432 ERR_ERRONEUSNICKNAME
+ "<nick> :Erroneous nickname"
+
+ - Returned after receiving a NICK message which contains
+ characters which do not fall in the defined set. See
+ section 2.3.1 for details on valid nicknames.
+
+ 433 ERR_NICKNAMEINUSE
+ "<nick> :Nickname is already in use"
+
+ - Returned when a NICK message is processed that results
+ in an attempt to change to a currently existing
+ nickname.
+
+
+
+
+
+
+
+
+Kalt Informational [Page 55]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 436 ERR_NICKCOLLISION
+ "<nick> :Nickname collision KILL from <user>@<host>"
+
+ - Returned by a server to a client when it detects a
+ nickname collision (registered of a NICK that
+ already exists by another server).
+
+ 437 ERR_UNAVAILRESOURCE
+ "<nick/channel> :Nick/channel is temporarily unavailable"
+
+ - Returned by a server to a user trying to join a channel
+ currently blocked by the channel delay mechanism.
+
+ - Returned by a server to a user trying to change nickname
+ when the desired nickname is blocked by the nick delay
+ mechanism.
+
+ 441 ERR_USERNOTINCHANNEL
+ "<nick> <channel> :They aren't on that channel"
+
+ - Returned by the server to indicate that the target
+ user of the command is not on the given channel.
+
+ 442 ERR_NOTONCHANNEL
+ "<channel> :You're not on that channel"
+
+ - Returned by the server whenever a client tries to
+ perform a channel affecting command for which the
+ client isn't a member.
+
+ 443 ERR_USERONCHANNEL
+ "<user> <channel> :is already on channel"
+
+ - Returned when a client tries to invite a user to a
+ channel they are already on.
+
+ 444 ERR_NOLOGIN
+ "<user> :User not logged in"
+
+ - Returned by the summon after a SUMMON command for a
+ user was unable to be performed since they were not
+ logged in.
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 56]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 445 ERR_SUMMONDISABLED
+ ":SUMMON has been disabled"
+
+ - Returned as a response to the SUMMON command. MUST be
+ returned by any server which doesn't implement it.
+
+ 446 ERR_USERSDISABLED
+ ":USERS has been disabled"
+
+ - Returned as a response to the USERS command. MUST be
+ returned by any server which does not implement it.
+
+ 451 ERR_NOTREGISTERED
+ ":You have not registered"
+
+ - Returned by the server to indicate that the client
+ MUST be registered before the server will allow it
+ to be parsed in detail.
+
+ 461 ERR_NEEDMOREPARAMS
+ "<command> :Not enough parameters"
+
+ - Returned by the server by numerous commands to
+ indicate to the client that it didn't supply enough
+ parameters.
+
+ 462 ERR_ALREADYREGISTRED
+ ":Unauthorized command (already registered)"
+
+ - Returned by the server to any link which tries to
+ change part of the registered details (such as
+ password or user details from second USER message).
+
+ 463 ERR_NOPERMFORHOST
+ ":Your host isn't among the privileged"
+
+ - Returned to a client which attempts to register with
+ a server which does not been setup to allow
+ connections from the host the attempted connection
+ is tried.
+
+ 464 ERR_PASSWDMISMATCH
+ ":Password incorrect"
+
+ - Returned to indicate a failed attempt at registering
+ a connection for which a password was required and
+ was either not given or incorrect.
+
+
+
+
+Kalt Informational [Page 57]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 465 ERR_YOUREBANNEDCREEP
+ ":You are banned from this server"
+
+ - Returned after an attempt to connect and register
+ yourself with a server which has been setup to
+ explicitly deny connections to you.
+
+ 466 ERR_YOUWILLBEBANNED
+
+ - Sent by a server to a user to inform that access to the
+ server will soon be denied.
+
+ 467 ERR_KEYSET
+ "<channel> :Channel key already set"
+ 471 ERR_CHANNELISFULL
+ "<channel> :Cannot join channel (+l)"
+ 472 ERR_UNKNOWNMODE
+ "<char> :is unknown mode char to me for <channel>"
+ 473 ERR_INVITEONLYCHAN
+ "<channel> :Cannot join channel (+i)"
+ 474 ERR_BANNEDFROMCHAN
+ "<channel> :Cannot join channel (+b)"
+ 475 ERR_BADCHANNELKEY
+ "<channel> :Cannot join channel (+k)"
+ 476 ERR_BADCHANMASK
+ "<channel> :Bad Channel Mask"
+ 477 ERR_NOCHANMODES
+ "<channel> :Channel doesn't support modes"
+ 478 ERR_BANLISTFULL
+ "<channel> <char> :Channel list is full"
+
+ 481 ERR_NOPRIVILEGES
+ ":Permission Denied- You're not an IRC operator"
+
+ - Any command requiring operator privileges to operate
+ MUST return this error to indicate the attempt was
+ unsuccessful.
+
+ 482 ERR_CHANOPRIVSNEEDED
+ "<channel> :You're not channel operator"
+
+ - Any command requiring 'chanop' privileges (such as
+ MODE messages) MUST return this error if the client
+ making the attempt is not a chanop on the specified
+ channel.
+
+
+
+
+
+
+Kalt Informational [Page 58]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 483 ERR_CANTKILLSERVER
+ ":You can't kill a server!"
+
+ - Any attempts to use the KILL command on a server
+ are to be refused and this error returned directly
+ to the client.
+
+ 484 ERR_RESTRICTED
+ ":Your connection is restricted!"
+
+ - Sent by the server to a user upon connection to indicate
+ the restricted nature of the connection (user mode "+r").
+
+ 485 ERR_UNIQOPPRIVSNEEDED
+ ":You're not the original channel operator"
+
+ - Any MODE requiring "channel creator" privileges MUST
+ return this error if the client making the attempt is not
+ a chanop on the specified channel.
+
+ 491 ERR_NOOPERHOST
+ ":No O-lines for your host"
+
+ - If a client sends an OPER message and the server has
+ not been configured to allow connections from the
+ client's host as an operator, this error MUST be
+ returned.
+
+ 501 ERR_UMODEUNKNOWNFLAG
+ ":Unknown MODE flag"
+
+ - Returned by the server to indicate that a MODE
+ message was sent with a nickname parameter and that
+ the a mode flag sent was not recognized.
+
+ 502 ERR_USERSDONTMATCH
+ ":Cannot change mode for other users"
+
+ - Error sent to any user trying to view or change the
+ user mode for a user other than themselves.
+
+5.3 Reserved numerics
+
+ These numerics are not described above since they fall into one of
+ the following categories:
+
+ 1. no longer in use;
+
+
+
+
+Kalt Informational [Page 59]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+ 2. reserved for future planned use;
+
+ 3. in current use but are part of a non-generic 'feature' of
+ the current IRC server.
+
+ 231 RPL_SERVICEINFO 232 RPL_ENDOFSERVICES
+ 233 RPL_SERVICE
+ 300 RPL_NONE 316 RPL_WHOISCHANOP
+ 361 RPL_KILLDONE 362 RPL_CLOSING
+ 363 RPL_CLOSEEND 373 RPL_INFOSTART
+ 384 RPL_MYPORTIS
+
+ 213 RPL_STATSCLINE 214 RPL_STATSNLINE
+ 215 RPL_STATSILINE 216 RPL_STATSKLINE
+ 217 RPL_STATSQLINE 218 RPL_STATSYLINE
+ 240 RPL_STATSVLINE 241 RPL_STATSLLINE
+ 244 RPL_STATSHLINE 244 RPL_STATSSLINE
+ 246 RPL_STATSPING 247 RPL_STATSBLINE
+ 250 RPL_STATSDLINE
+
+ 492 ERR_NOSERVICEHOST
+
+6. Current implementations
+
+ The IRC software, version 2.10 is the only complete implementation of
+ the IRC protocol (client and server). Because of the small amount of
+ changes in the client protocol since the publication of RFC 1459
+ [IRC], implementations that follow it are likely to be compliant with
+ this protocol or to require a small amount of changes to reach
+ compliance.
+
+7. Current problems
+
+ There are a number of recognized problems with the IRC Client
+ Protocol, and more generally with the IRC Server Protocol. In order
+ to preserve backward compatibility with old clients, this protocol
+ has almost not evolved since the publication of RFC 1459 [IRC].
+
+7.1 Nicknames
+
+ The idea of the nickname on IRC is very convenient for users to use
+ when talking to each other outside of a channel, but there is only a
+ finite nickname space and being what they are, it's not uncommon for
+ several people to want to use the same nick. If a nickname is chosen
+ by two people using this protocol, either one will not succeed or
+ both will removed by use of a server KILL (See Section 3.7.1).
+
+
+
+
+
+Kalt Informational [Page 60]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+7.2 Limitation of wildcards
+
+ There is no way to escape the escape character "\" (%x5C). While
+ this isn't usually a problem, it makes it impossible to form a mask
+ with a backslash character ("\") preceding a wildcard.
+
+7.3 Security considerations
+
+ Security issues related to this protocol are discussed in the "IRC
+ Server Protocol" [IRC-SERVER] as they are mostly an issue for the
+ server side of the connection.
+
+8. Current support and availability
+
+ Mailing lists for IRC related discussion:
+ General discussion: ircd-users@irc.org
+ Protocol development: ircd-dev@irc.org
+
+ Software implementations:
+ ftp://ftp.irc.org/irc/server
+ ftp://ftp.funet.fi/pub/unix/irc
+ ftp://ftp.irc.org/irc/clients
+
+ Newsgroup: alt.irc
+
+9. Acknowledgements
+
+ Parts of this document were copied from the RFC 1459 [IRC] which
+ first formally documented the IRC Protocol. It has also benefited
+ from many rounds of review and comments. In particular, the
+ following people have made significant contributions to this
+ document:
+
+ Matthew Green, Michael Neumayer, Volker Paulsen, Kurt Roeckx, Vesa
+ Ruokonen, Magnus Tjernstrom, Stefan Zehl.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 61]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+10. References
+
+ [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [HNAME] Braden, R., "Requirements for Internet Hosts --
+ Application and Support", STD 3, RFC 1123, October 1989.
+
+ [IRC] Oikarinen, J. & D. Reed, "Internet Relay Chat Protocol",
+ RFC 1459, May 1993.
+
+ [IRC-ARCH] Kalt, C., "Internet Relay Chat: Architecture", RFC 2810,
+ April 2000.
+
+ [IRC-CHAN] Kalt, C., "Internet Relay Chat: Channel Management", RFC
+ 2811, April 2000.
+
+ [IRC-SERVER] Kalt, C., "Internet Relay Chat: Server Protocol", RFC
+ 2813, April 2000.
+
+11. Author's Address
+
+ Christophe Kalt
+ 99 Teaneck Rd, Apt #117
+ Ridgefield Park, NJ 07660
+ USA
+
+ EMail: kalt@stealth.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 62]
+
+RFC 2812 Internet Relay Chat: Client Protocol April 2000
+
+
+12. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 63]
+
diff --git a/irc_mod/Docs/rfc2813.txt b/irc_mod/Docs/rfc2813.txt
new file mode 100644
index 0000000..2da3de0
--- /dev/null
+++ b/irc_mod/Docs/rfc2813.txt
@@ -0,0 +1,1459 @@
+
+
+
+
+
+
+Network Working Group C. Kalt
+Request for Comments: 2813 April 2000
+Updates: 1459
+Category: Informational
+
+
+ Internet Relay Chat: Server Protocol
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ While based on the client-server model, the IRC (Internet Relay Chat)
+ protocol allows servers to connect to each other effectively forming
+ a network.
+
+ This document defines the protocol used by servers to talk to each
+ other. It was originally a superset of the client protocol but has
+ evolved differently.
+
+ First formally documented in May 1993 as part of RFC 1459 [IRC], most
+ of the changes brought since then can be found in this document as
+ development was focused on making the protocol scale better. Better
+ scalability has allowed existing world-wide networks to keep growing
+ and reach sizes which defy the old specification.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 1]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+Table of Contents
+
+ 1. Introduction ............................................... 3
+ 2. Global database ............................................ 3
+ 2.1 Servers ................................................ 3
+ 2.2 Clients ................................................ 4
+ 2.2.1 Users ............................................. 4
+ 2.2.2 Services .......................................... 4
+ 2.3 Channels ............................................... 4
+ 3. The IRC Server Specification ............................... 5
+ 3.1 Overview ............................................... 5
+ 3.2 Character codes ........................................ 5
+ 3.3 Messages ............................................... 5
+ 3.3.1 Message format in Augmented BNF ................... 6
+ 3.4 Numeric replies ........................................ 7
+ 4. Message Details ............................................ 7
+ 4.1 Connection Registration ................................ 8
+ 4.1.1 Password message .................................. 8
+ 4.1.2 Server message .................................... 9
+ 4.1.3 Nick .............................................. 10
+ 4.1.4 Service message ................................... 11
+ 4.1.5 Quit .............................................. 12
+ 4.1.6 Server quit message ............................... 13
+ 4.2 Channel operations ..................................... 14
+ 4.2.1 Join message ...................................... 14
+ 4.2.2 Njoin message ..................................... 15
+ 4.2.3 Mode message ...................................... 16
+ 5. Implementation details .................................... 16
+ 5.1 Connection 'Liveness' .................................. 16
+ 5.2 Accepting a client to server connection ................ 16
+ 5.2.1 Users ............................................. 16
+ 5.2.2 Services .......................................... 17
+ 5.3 Establishing a server-server connection. ............... 17
+ 5.3.1 Link options ...................................... 17
+ 5.3.1.1 Compressed server to server links ............ 18
+ 5.3.1.2 Anti abuse protections ....................... 18
+ 5.3.2 State information exchange when connecting ........ 18
+ 5.4 Terminating server-client connections .................. 19
+ 5.5 Terminating server-server connections .................. 19
+ 5.6 Tracking nickname changes .............................. 19
+ 5.7 Tracking recently used nicknames ....................... 20
+ 5.8 Flood control of clients ............................... 20
+ 5.9 Non-blocking lookups ................................... 21
+ 5.9.1 Hostname (DNS) lookups ............................ 21
+ 5.9.2 Username (Ident) lookups .......................... 21
+ 6. Current problems ........................................... 21
+ 6.1 Scalability ............................................ 21
+ 6.2 Labels ................................................. 22
+
+
+
+Kalt Informational [Page 2]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ 6.2.1 Nicknames ......................................... 22
+ 6.2.2 Channels .......................................... 22
+ 6.2.3 Servers ........................................... 22
+ 6.3 Algorithms ............................................. 22
+ 7. Security Considerations .................................... 23
+ 7.1 Authentication ......................................... 23
+ 7.2 Integrity .............................................. 23
+ 8. Current support and availability ........................... 24
+ 9. Acknowledgements ........................................... 24
+ 10. References ................................................ 24
+ 11. Author's Address .......................................... 25
+ 12. Full Copyright Statement ................................... 26
+
+1. Introduction
+
+ This document is intended for people working on implementing an IRC
+ server but will also be useful to anyone implementing an IRC service.
+
+ Servers provide the three basic services required for realtime
+ conferencing defined by the "Internet Relay Chat: Architecture"
+ [IRC-ARCH]: client locator (via the client protocol [IRC-CLIENT]),
+ message relaying (via the server protocol defined in this document)
+ and channel hosting and management (following specific rules [IRC-
+ CHAN]).
+
+2. Global database
+
+ Although the IRC Protocol defines a fairly distributed model, each
+ server maintains a "global state database" about the whole IRC
+ network. This database is, in theory, identical on all servers.
+
+2.1 Servers
+
+ Servers are uniquely identified by their name which has a maximum
+ length of sixty three (63) characters. See the protocol grammar
+ rules (section 3.3.1) for what may and may not be used in a server
+ name.
+
+ Each server is typically known by all other servers, however it is
+ possible to define a "hostmask" to group servers together according
+ to their name. Inside the hostmasked area, all the servers have a
+ name which matches the hostmask, and any other server with a name
+ matching the hostmask SHALL NOT be connected to the IRC network
+ outside the hostmasked area. Servers which are outside the area have
+ no knowledge of the individual servers present inside the area,
+ instead they are presented with a virtual server which has the
+ hostmask for name.
+
+
+
+
+Kalt Informational [Page 3]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+2.2 Clients
+
+ For each client, all servers MUST have the following information: a
+ netwide unique identifier (whose format depends on the type of
+ client) and the server to which the client is connected.
+
+2.2.1 Users
+
+ Each user is distinguished from other users by a unique nickname
+ having a maximum length of nine (9) characters. See the protocol
+ grammar rules (section 3.3.1) for what may and may not be used in a
+ nickname. In addition to the nickname, all servers MUST have the
+ following information about all users: the name of the host that the
+ user is running on, the username of the user on that host, and the
+ server to which the client is connected.
+
+2.2.2 Services
+
+ Each service is distinguished from other services by a service name
+ composed of a nickname and a server name. The nickname has a maximum
+ length of nine (9) characters. See the protocol grammar rules
+ (section 3.3.1) for what may and may not be used in a nickname. The
+ server name used to compose the service name is the name of the
+ server to which the service is connected. In addition to this
+ service name all servers MUST know the service type.
+
+ Services differ from users by the format of their identifier, but
+ more importantly services and users don't have the same type of
+ access to the server: services can request part or all of the global
+ state information that a server maintains, but have a more restricted
+ set of commands available to them (See "IRC Client Protocol" [IRC-
+ CLIENT] for details on which) and are not allowed to join channels.
+ Finally services are not usually subject to the "Flood control"
+ mechanism described in section 5.8.
+
+2.3 Channels
+
+ Alike services, channels have a scope [IRC-CHAN] and are not
+ necessarily known to all servers. When a channel existence is known
+ to a server, the server MUST keep track of the channel members, as
+ well as the channel modes.
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 4]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+3. The IRC Server Specification
+
+3.1 Overview
+
+ The protocol as described herein is for use with server to server
+ connections. For client to server connections, see the IRC Client
+ Protocol specification.
+
+ There are, however, more restrictions on client connections (which
+ are considered to be untrustworthy) than on server connections.
+
+3.2 Character codes
+
+ No specific character set is specified. The protocol is based on a a
+ set of codes which are composed of eight (8) bits, making up an
+ octet. Each message may be composed of any number of these octets;
+ however, some octet values are used for control codes which act as
+ message delimiters.
+
+ Regardless of being an 8-bit protocol, the delimiters and keywords
+ are such that protocol is mostly usable from US-ASCII terminal and a
+ telnet connection.
+
+ Because of IRC's Scandinavian origin, the characters {}|^ are
+ considered to be the lower case equivalents of the characters []\~,
+ respectively. This is a critical issue when determining the
+ equivalence of two nicknames, or channel names.
+
+3.3 Messages
+
+ Servers and clients send each other messages which may or may not
+ generate a reply. Most communication between servers do not generate
+ any reply, as servers mostly perform routing tasks for the clients.
+
+ Each IRC message may consist of up to three main parts: the prefix
+ (OPTIONAL), the command, and the command parameters (maximum of
+ fifteen (15)). The prefix, command, and all parameters are separated
+ by one ASCII space character (0x20) each.
+
+ The presence of a prefix is indicated with a single leading ASCII
+ colon character (':', 0x3b), which MUST be the first character of the
+ message itself. There MUST be NO gap (whitespace) between the colon
+ and the prefix. The prefix is used by servers to indicate the true
+ origin of the message. If the prefix is missing from the message, it
+ is assumed to have originated from the connection from which it was
+ received. Clients SHOULD not use a prefix when sending a message
+ from themselves; if they use one, the only valid prefix is the
+ registered nickname associated with the client.
+
+
+
+Kalt Informational [Page 5]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ When a server receives a message, it MUST identify its source using
+ the (eventually assumed) prefix. If the prefix cannot be found in
+ the server's internal database, it MUST be discarded, and if the
+ prefix indicates the message comes from an (unknown) server, the link
+ from which the message was received MUST be dropped. Dropping a link
+ in such circumstances is a little excessive but necessary to maintain
+ the integrity of the network and to prevent future problems. Another
+ common error condition is that the prefix found in the server's
+ internal database identifies a different source (typically a source
+ registered from a different link than from which the message
+ arrived). If the message was received from a server link and the
+ prefix identifies a client, a KILL message MUST be issued for the
+ client and sent to all servers. In other cases, the link from which
+ the message arrived SHOULD be dropped for clients, and MUST be
+ dropped for servers. In all cases, the message MUST be discarded.
+
+ The command MUST either be a valid IRC command or a three (3) digit
+ number represented in ASCII text.
+
+ IRC messages are always lines of characters terminated with a CR-LF
+ (Carriage Return - Line Feed) pair, and these messages SHALL NOT
+ exceed 512 characters in length, counting all characters including
+ the trailing CR-LF. Thus, there are 510 characters maximum allowed
+ for the command and its parameters. There is no provision for
+ continuation message lines. See section 5 for more details about
+ current implementations.
+
+3.3.1 Message format in Augmented BNF
+
+ The protocol messages must be extracted from the contiguous stream of
+ octets. The current solution is to designate two characters, CR and
+ LF, as message separators. Empty messages are silently ignored,
+ which permits use of the sequence CR-LF between messages without
+ extra problems.
+
+ The extracted message is parsed into the components <prefix>,
+ <command> and list of parameters (<params>).
+
+ The Augmented BNF representation for this is found in "IRC Client
+ Protocol" [IRC-CLIENT].
+
+ The extended prefix (["!" user "@" host ]) MUST NOT be used in server
+ to server communications and is only intended for server to client
+ messages in order to provide clients with more useful information
+ about who a message is from without the need for additional queries.
+
+
+
+
+
+
+Kalt Informational [Page 6]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+3.4 Numeric replies
+
+ Most of the messages sent to the server generate a reply of some
+ sort. The most common reply is the numeric reply, used for both
+ errors and normal replies. The numeric reply MUST be sent as one
+ message consisting of the sender prefix, the three digit numeric, and
+ the target of the reply. A numeric reply is not allowed to originate
+ from a client; any such messages received by a server are silently
+ dropped. In all other respects, a numeric reply is just like a normal
+ message, except that the keyword is made up of 3 numeric digits
+ rather than a string of letters. A list of different replies is
+ supplied in "IRC Client Protocol" [IRC-CLIENT].
+
+4. Message Details
+
+ All the messages recognized by the IRC server and client are
+ described in the IRC Client Protocol specification.
+
+ Where the reply ERR_NOSUCHSERVER is returned, it means that the
+ target of the message could not be found. The server MUST NOT send
+ any other replies after this error for that command.
+
+ The server to which a client is connected is required to parse the
+ complete message, returning any appropriate errors. If the server
+ encounters a fatal error while parsing a message, an error MUST be
+ sent back to the client and the parsing terminated. A fatal error
+ may follow from incorrect command, a destination which is otherwise
+ unknown to the server (server, client or channel names fit this
+ category), not enough parameters or incorrect privileges.
+
+ If a full set of parameters is presented, then each MUST be checked
+ for validity and appropriate responses sent back to the client. In
+ the case of messages which use parameter lists using the comma as an
+ item separator, a reply MUST be sent for each item.
+
+ In the examples below, some messages appear using the full format:
+
+ :Name COMMAND parameter list
+
+ Such examples represent a message from "Name" in transit between
+ servers, where it is essential to include the name of the original
+ sender of the message so remote servers may send back a reply along
+ the correct path.
+
+ The message details for client to server communication are described
+ in the "IRC Client Protocol" [IRC-CLIENT]. Some sections in the
+ following pages apply to some of these messages, they are additions
+ to the message specifications which are only relevant to server to
+
+
+
+Kalt Informational [Page 7]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ server communication, or to the server implementation. The messages
+ which are introduced here are only used for server to server
+ communication.
+
+4.1 Connection Registration
+
+ The commands described here are used to register a connection with
+ another IRC server.
+
+4.1.1 Password message
+
+ Command: PASS
+ Parameters: <password> <version> <flags> [<options>]
+
+ The PASS command is used to set a 'connection password'. The
+ password MUST be set before any attempt to register the connection is
+ made. Currently this means that servers MUST send a PASS command
+ before any SERVER command. Only one (1) PASS command SHALL be
+ accepted from a connection.
+
+ The last three (3) parameters MUST be ignored if received from a
+ client (e.g. a user or a service). They are only relevant when
+ received from a server.
+
+ The <version> parameter is a string of at least four (4) characters,
+ and up to fourteen (14) characters. The first four (4) characters
+ MUST be digits and indicate the protocol version known by the server
+ issuing the message. The protocol described by this document is
+ version 2.10 which is encoded as "0210". The remaining OPTIONAL
+ characters are implementation dependent and should describe the
+ software version number.
+
+ The <flags> parameter is a string of up to one hundred (100)
+ characters. It is composed of two substrings separated by the
+ character "|" (%x7C). If present, the first substring MUST be the
+ name of the implementation. The reference implementation (See
+ Section 8, "Current support and availability") uses the string "IRC".
+ If a different implementation is written, which needs an identifier,
+ then that identifier should be registered through publication of an
+ RFC. The second substring is implementation dependent. Both
+ substrings are OPTIONAL, but the character "|" is REQUIRED. The
+ character "|" MUST NOT appear in either substring.
+
+ Finally, the last parameter, <options>, is used for link options.
+ The only options defined by the protocol are link compression (using
+ the character "Z"), and an abuse protection flag (using the character
+
+
+
+
+
+Kalt Informational [Page 8]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ "P"). See sections 5.3.1.1 (Compressed server to server links) and
+ 5.3.1.2 (Anti abuse protections) respectively for more information on
+ these options.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
+
+ Example:
+
+ PASS moresecretpassword 0210010000 IRC|aBgH$ Z
+
+4.1.2 Server message
+
+ Command: SERVER
+ Parameters: <servername> <hopcount> <token> <info>
+
+ The SERVER command is used to register a new server. A new connection
+ introduces itself as a server to its peer. This message is also used
+ to pass server data over whole net. When a new server is connected
+ to net, information about it MUST be broadcasted to the whole
+ network.
+
+ The <info> parameter may contain space characters.
+
+ <hopcount> is used to give all servers some internal information on
+ how far away each server is. Local peers have a value of 0, and each
+ passed server increments the value. With a full server list, it
+ would be possible to construct a map of the entire server tree, but
+ hostmasks prevent this from being done.
+
+ The <token> parameter is an unsigned number used by servers as an
+ identifier. This identifier is subsequently used to reference a
+ server in the NICK and SERVICE messages sent between servers. Server
+ tokens only have a meaning for the point-to-point peering they are
+ used and MUST be unique for that connection. They are not global.
+
+ The SERVER message MUST only be accepted from either (a) a connection
+ which is yet to be registered and is attempting to register as a
+ server, or (b) an existing connection to another server, in which
+ case the SERVER message is introducing a new server behind that
+ server.
+
+ Most errors that occur with the receipt of a SERVER command result in
+ the connection being terminated by the destination host (target
+ SERVER). Because of the severity of such event, error replies are
+ usually sent using the "ERROR" command rather than a numeric.
+
+
+
+
+Kalt Informational [Page 9]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ If a SERVER message is parsed and it attempts to introduce a server
+ which is already known to the receiving server, the connection, from
+ which that message arrived, MUST be closed (following the correct
+ procedures), since a duplicate route to a server has been formed and
+ the acyclic nature of the IRC tree breaks. In some conditions, the
+ connection from which the already known server has registered MAY be
+ closed instead. It should be noted that this kind of error can also
+ be the result of a second running server, problem which cannot be
+ fixed within the protocol and typically requires human intervention.
+ This type of problem is particularly insidious, as it can quite
+ easily result in part of the IRC network to be isolated, with one of
+ the two servers connected to each partition therefore making it
+ impossible for the two parts to unite.
+
+ Numeric Replies:
+
+ ERR_ALREADYREGISTRED
+
+ Example:
+
+ SERVER test.oulu.fi 1 1 :Experimental server ; New server
+ test.oulu.fi introducing itself and
+ attempting to register.
+
+ :tolsun.oulu.fi SERVER csd.bu.edu 5 34 :BU Central Server ; Server
+ tolsun.oulu.fi is our uplink for
+ csd.bu.edu which is 5 hops away. The
+ token "34" will be used by
+ tolsun.oulu.fi when introducing new
+ users or services connected to
+ csd.bu.edu.
+
+4.1.3 Nick
+
+ Command: NICK
+ Parameters: <nickname> <hopcount> <username> <host> <servertoken>
+ <umode> <realname>
+
+ This form of the NICK message MUST NOT be allowed from user
+ connections. However, it MUST be used instead of the NICK/USER pair
+ to notify other servers of new users joining the IRC network.
+
+ This message is really the combination of three distinct messages:
+ NICK, USER and MODE [IRC-CLIENT].
+
+ The <hopcount> parameter is used by servers to indicate how far away
+ a user is from its home server. A local connection has a hopcount of
+ 0. The hopcount value is incremented by each passed server.
+
+
+
+Kalt Informational [Page 10]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ The <servertoken> parameter replaces the <servername> parameter of
+ the USER (See section 4.1.2 for more information on server tokens).
+
+ Examples:
+
+ NICK syrk 5 kalt millennium.stealth.net 34 +i :Christophe Kalt ; New
+ user with nickname "syrk", username
+ "kalt", connected from host
+ "millennium.stealth.net" to server
+ "34" ("csd.bu.edu" according to the
+ previous example).
+
+ :krys NICK syrk ; The other form of the NICK message,
+ as defined in "IRC Client Protocol"
+ [IRC-CLIENT] and used between
+ servers: krys changed his nickname to
+ syrk
+
+4.1.4 Service message
+
+ Command: SERVICE
+ Parameters: <servicename> <servertoken> <distribution> <type>
+ <hopcount> <info>
+
+ The SERVICE command is used to introduce a new service. This form of
+ the SERVICE message SHOULD NOT be allowed from client (unregistered,
+ or registered) connections. However, it MUST be used between servers
+ to notify other servers of new services joining the IRC network.
+
+ The <servertoken> is used to identify the server to which the service
+ is connected. (See section 4.1.2 for more information on server
+ tokens).
+
+ The <hopcount> parameter is used by servers to indicate how far away
+ a service is from its home server. A local connection has a hopcount
+ of 0. The hopcount value is incremented by each passed server.
+
+ The <distribution> parameter is used to specify the visibility of a
+ service. The service may only be known to servers which have a name
+ matching the distribution. For a matching server to have knowledge
+ of the service, the network path between that server and the server
+ to which the service is connected MUST be composed of servers whose
+ names all match the mask. Plain "*" is used when no restriction is
+ wished.
+
+ The <type> parameter is currently reserved for future usage.
+
+
+
+
+
+Kalt Informational [Page 11]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ Numeric Replies:
+
+ ERR_ALREADYREGISTRED ERR_NEEDMOREPARAMS
+ ERR_ERRONEUSNICKNAME
+ RPL_YOURESERVICE RPL_YOURHOST
+ RPL_MYINFO
+
+ Example:
+
+SERVICE dict@irc.fr 9 *.fr 0 1 :French Dictionary r" registered on
+ server "9" is being announced to
+ another server. This service will
+ only be available on servers whose
+ name matches "*.fr".
+
+4.1.5 Quit
+
+ Command: QUIT
+ Parameters: [<Quit Message>]
+
+ A client session ends with a quit message. The server MUST close the
+ connection to a client which sends a QUIT message. If a "Quit
+ Message" is given, this will be sent instead of the default message,
+ the nickname or service name.
+
+ When "netsplit" (See Section 4.1.6) occur, the "Quit Message" is
+ composed of the names of two servers involved, separated by a space.
+ The first name is that of the server which is still connected and the
+ second name is either that of the server which has become
+ disconnected or that of the server to which the leaving client was
+ connected:
+
+ <Quit Message> = ":" servername SPACE servername
+
+ Because the "Quit Message" has a special meaning for "netsplits",
+ servers SHOULD NOT allow a client to use a <Quit Message> in the
+ format described above.
+
+ If, for some other reason, a client connection is closed without the
+ client issuing a QUIT command (e.g. client dies and EOF occurs on
+ socket), the server is REQUIRED to fill in the quit message with some
+ sort of message reflecting the nature of the event which caused it to
+ happen. Typically, this is done by reporting a system specific
+ error.
+
+ Numeric Replies:
+
+ None.
+
+
+
+Kalt Informational [Page 12]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ Examples:
+
+ :WiZ QUIT :Gone to have lunch ; Preferred message format.
+
+4.1.6 Server quit message
+
+ Command: SQUIT
+ Parameters: <server> <comment>
+
+ The SQUIT message has two distinct uses.
+
+ The first one (described in "Internet Relay Chat: Client Protocol"
+ [IRC-CLIENT]) allows operators to break a local or remote server
+ link. This form of the message is also eventually used by servers to
+ break a remote server link.
+
+ The second use of this message is needed to inform other servers when
+ a "network split" (also known as "netsplit") occurs, in other words
+ to inform other servers about quitting or dead servers. If a server
+ wishes to break the connection to another server it MUST send a SQUIT
+ message to the other server, using the name of the other server as
+ the server parameter, which then closes its connection to the
+ quitting server.
+
+ The <comment> is filled in by servers which SHOULD place an error or
+ similar message here.
+
+ Both of the servers which are on either side of the connection being
+ closed are REQUIRED to send out a SQUIT message (to all its other
+ server connections) for all other servers which are considered to be
+ behind that link.
+
+ Similarly, a QUIT message MAY be sent to the other still connected
+ servers on behalf of all clients behind that quitting link. In
+ addition to this, all channel members of a channel which lost a
+ member due to the "split" MUST be sent a QUIT message. Messages to
+ channel members are generated by each client's local server.
+
+ If a server connection is terminated prematurely (e.g., the server on
+ the other end of the link died), the server which detects this
+ disconnection is REQUIRED to inform the rest of the network that the
+ connection has closed and fill in the comment field with something
+ appropriate.
+
+ When a client is removed as the result of a SQUIT message, the server
+ SHOULD add the nickname to the list of temporarily unavailable
+ nicknames in an attempt to prevent future nickname collisions. See
+
+
+
+
+Kalt Informational [Page 13]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ section 5.7 (Tracking recently used nicknames) for more information
+ on this procedure.
+
+ Numeric replies:
+
+ ERR_NOPRIVILEGES ERR_NOSUCHSERVER
+ ERR_NEEDMOREPARAMS
+
+ Example:
+
+ SQUIT tolsun.oulu.fi :Bad Link ? ; the server link tolson.oulu.fi
+ has been terminated because of "Bad
+ Link".
+
+ :Trillian SQUIT cm22.eng.umd.edu :Server out of control ; message
+ from Trillian to disconnect
+ "cm22.eng.umd.edu" from the net
+ because "Server out of control".
+
+4.2 Channel operations
+
+ This group of messages is concerned with manipulating channels, their
+ properties (channel modes), and their contents (typically users). In
+ implementing these, a number of race conditions are inevitable when
+ users at opposing ends of a network send commands which will
+ ultimately clash. It is also REQUIRED that servers keep a nickname
+ history to ensure that wherever a <nick> parameter is given, the
+ server check its history in case it has recently been changed.
+
+4.2.1 Join message
+
+ Command: JOIN
+ Parameters: <channel>[ %x7 <modes> ]
+ *( "," <channel>[ %x7 <modes> ] )
+
+ The JOIN command is used by client to start listening a specific
+ channel. Whether or not a client is allowed to join a channel is
+ checked only by the local server the client is connected to; all
+ other servers automatically add the user to the channel when the
+ command is received from other servers.
+
+ Optionally, the user status (channel modes 'O', 'o', and 'v') on the
+ channel may be appended to the channel name using a control G (^G or
+ ASCII 7) as separator. Such data MUST be ignored if the message
+ wasn't received from a server. This format MUST NOT be sent to
+ clients, it can only be used between servers and SHOULD be avoided.
+
+
+
+
+
+Kalt Informational [Page 14]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ The JOIN command MUST be broadcast to all servers so that each server
+ knows where to find the users who are on the channel. This allows
+ optimal delivery of PRIVMSG and NOTICE messages to the channel.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_BANNEDFROMCHAN
+ ERR_INVITEONLYCHAN ERR_BADCHANNELKEY
+ ERR_CHANNELISFULL ERR_BADCHANMASK
+ ERR_NOSUCHCHANNEL ERR_TOOMANYCHANNELS
+ ERR_TOOMANYTARGETS ERR_UNAVAILRESOURCE
+ RPL_TOPIC
+
+ Examples:
+
+ :WiZ JOIN #Twilight_zone ; JOIN message from WiZ
+
+4.2.2 Njoin message
+
+ Command: NJOIN
+ Parameters: <channel> [ "@@" / "@" ] [ "+" ] <nickname>
+ *( "," [ "@@" / "@" ] [ "+" ] <nickname> )
+
+ The NJOIN message is used between servers only. If such a message is
+ received from a client, it MUST be ignored. It is used when two
+ servers connect to each other to exchange the list of channel members
+ for each channel.
+
+ Even though the same function can be performed by using a succession
+ of JOIN, this message SHOULD be used instead as it is more efficient.
+ The prefix "@@" indicates that the user is the "channel creator", the
+ character "@" alone indicates a "channel operator", and the character
+ '+' indicates that the user has the voice privilege.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_NOSUCHCHANNEL
+ ERR_ALREADYREGISTRED
+
+ Examples:
+
+ :ircd.stealth.net NJOIN #Twilight_zone :@WiZ,+syrk,avalon ; NJOIN
+ message from ircd.stealth.net
+ announcing users joining the
+ #Twilight_zone channel: WiZ with
+ channel operator status, syrk with
+ voice privilege and avalon with no
+ privilege.
+
+
+
+Kalt Informational [Page 15]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+4.2.3 Mode message
+
+ The MODE message is a dual-purpose command in IRC. It allows both
+ usernames and channels to have their mode changed.
+
+ When parsing MODE messages, it is RECOMMENDED that the entire message
+ be parsed first, and then the changes which resulted passed on.
+
+ It is REQUIRED that servers are able to change channel modes so that
+ "channel creator" and "channel operators" may be created.
+
+5. Implementation details
+
+ A the time of writing, the only current implementation of this
+ protocol is the IRC server, version 2.10. Earlier versions may
+ implement some or all of the commands described by this document with
+ NOTICE messages replacing many of the numeric replies. Unfortunately,
+ due to backward compatibility requirements, the implementation of
+ some parts of this document varies with what is laid out. One
+ notable difference is:
+
+ * recognition that any LF or CR anywhere in a message marks
+ the end of that message (instead of requiring CR-LF);
+
+ The rest of this section deals with issues that are mostly of
+ importance to those who wish to implement a server but some parts
+ also apply directly to clients as well.
+
+5.1 Connection 'Liveness'
+
+ To detect when a connection has died or become unresponsive, the
+ server MUST poll each of its connections. The PING command (See "IRC
+ Client Protocol" [IRC-CLIENT]) is used if the server doesn't get a
+ response from its peer in a given amount of time.
+
+ If a connection doesn't respond in time, its connection is closed
+ using the appropriate procedures.
+
+5.2 Accepting a client to server connection
+
+5.2.1 Users
+
+ When a server successfully registers a new user connection, it is
+ REQUIRED to send to the user unambiguous messages stating: the user
+ identifiers upon which it was registered (RPL_WELCOME), the server
+ name and version (RPL_YOURHOST), the server birth information
+ (RPL_CREATED), available user and channel modes (RPL_MYINFO), and it
+ MAY send any introductory messages which may be deemed appropriate.
+
+
+
+Kalt Informational [Page 16]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ In particular the server SHALL send the current user/service/server
+ count (as per the LUSER reply) and finally the MOTD (if any, as per
+ the MOTD reply).
+
+ After dealing with registration, the server MUST then send out to
+ other servers the new user's nickname (NICK message), other
+ information as supplied by itself (USER message) and as the server
+ could discover (from DNS servers). The server MUST NOT send this
+ information out with a pair of NICK and USER messages as defined in
+ "IRC Client Protocol" [IRC-CLIENT], but MUST instead take advantage
+ of the extended NICK message defined in section 4.1.3.
+
+5.2.2 Services
+
+ Upon successfully registering a new service connection, the server is
+ subject to the same kind of REQUIREMENTS as for a user. Services
+ being somewhat different, only the following replies are sent:
+ RPL_YOURESERVICE, RPL_YOURHOST, RPL_MYINFO.
+
+ After dealing with this, the server MUST then send out to other
+ servers (SERVICE message) the new service's nickname and other
+ information as supplied by the service (SERVICE message) and as the
+ server could discover (from DNS servers).
+
+5.3 Establishing a server-server connection.
+
+ The process of establishing a server-to-server connection is fraught
+ with danger since there are many possible areas where problems can
+ occur - the least of which are race conditions.
+
+ After a server has received a connection following by a PASS/SERVER
+ pair which were recognized as being valid, the server SHOULD then
+ reply with its own PASS/SERVER information for that connection as
+ well as all of the other state information it knows about as
+ described below.
+
+ When the initiating server receives a PASS/SERVER pair, it too then
+ checks that the server responding is authenticated properly before
+ accepting the connection to be that server.
+
+5.3.1 Link options
+
+ Server links are based on a common protocol (defined by this
+ document) but a particular link MAY set specific options using the
+ PASS message (See Section 4.1.1).
+
+
+
+
+
+
+Kalt Informational [Page 17]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+5.3.1.1 Compressed server to server links
+
+ If a server wishes to establish a compressed link with its peer, it
+ MUST set the 'Z' flag in the options parameter to the PASS message.
+ If both servers request compression and both servers are able to
+ initialize the two compressed streams, then the remainder of the
+ communication is to be compressed. If any server fails to initialize
+ the stream, it will send an uncompressed ERROR message to its peer
+ and close the connection.
+
+ The data format used for the compression is described by RFC 1950
+ [ZLIB], RFC 1951 [DEFLATE] and RFC 1952 [GZIP].
+
+5.3.1.2 Anti abuse protections
+
+ Most servers implement various kinds of protections against possible
+ abusive behaviours from non trusted parties (typically users). On
+ some networks, such protections are indispensable, on others they are
+ superfluous. To require that all servers implement and enable such
+ features on a particular network, the 'P' flag is used when two
+ servers connect. If this flag is present, it means that the server
+ protections are enabled, and that the server REQUIRES all its server
+ links to enable them as well.
+
+ Commonly found protections are described in sections 5.7 (Tracking
+ recently used nicknames) and 5.8 (Flood control of clients).
+
+5.3.2 State information exchange when connecting
+
+ The order of state information being exchanged between servers is
+ essential. The REQUIRED order is as follows:
+
+ * all known servers;
+
+ * all known client information;
+
+ * all known channel information.
+
+ Information regarding servers is sent via extra SERVER messages,
+ client information with NICK and SERVICE messages and channels with
+ NJOIN/MODE messages.
+
+ NOTE: channel topics SHOULD NOT be exchanged here because the TOPIC
+ command overwrites any old topic information, so at best, the two
+ sides of the connection would exchange topics.
+
+
+
+
+
+
+Kalt Informational [Page 18]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ By passing the state information about servers first, any collisions
+ with servers that already exist occur before nickname collisions
+ caused by a second server introducing a particular nickname. Due to
+ the IRC network only being able to exist as an acyclic graph, it may
+ be possible that the network has already reconnected in another
+ location. In this event, the place where the server collision occurs
+ indicates where the net needs to split.
+
+5.4 Terminating server-client connections
+
+ When a client connection unexpectedly closes, a QUIT message is
+ generated on behalf of the client by the server to which the client
+ was connected. No other message is to be generated or used.
+
+5.5 Terminating server-server connections
+
+ If a server-server connection is closed, either via a SQUIT command
+ or "natural" causes, the rest of the connected IRC network MUST have
+ its information updated by the server which detected the closure.
+ The terminating server then sends a list of SQUITs (one for each
+ server behind that connection). (See Section 4.1.6 (SQUIT)).
+
+5.6 Tracking nickname changes
+
+ All IRC servers are REQUIRED to keep a history of recent nickname
+ changes. This is important to allow the server to have a chance of
+ keeping in touch of things when nick-change race conditions occur
+ with commands manipulating them. Messages which MUST trace nick
+ changes are:
+
+ * KILL (the nick being disconnected)
+
+ * MODE (+/- o,v on channels)
+
+ * KICK (the nick being removed from channel)
+
+ No other commands need to check nick changes.
+
+ In the above cases, the server is required to first check for the
+ existence of the nickname, then check its history to see who that
+ nick now belongs to (if anyone!). This reduces the chances of race
+ conditions but they can still occur with the server ending up
+ affecting the wrong client. When performing a change trace for an
+ above command it is RECOMMENDED that a time range be given and
+ entries which are too old ignored.
+
+
+
+
+
+
+Kalt Informational [Page 19]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ For a reasonable history, a server SHOULD be able to keep previous
+ nickname for every client it knows about if they all decided to
+ change. This size is limited by other factors (such as memory, etc).
+
+5.7 Tracking recently used nicknames
+
+ This mechanism is commonly known as "Nickname Delay", it has been
+ proven to significantly reduce the number of nickname collisions
+ resulting from "network splits"/reconnections as well as abuse.
+
+ In addition of keeping track of nickname changes, servers SHOULD keep
+ track of nicknames which were recently used and were released as the
+ result of a "network split" or a KILL message. These nicknames are
+ then unavailable to the server local clients and cannot be re-used
+ (even though they are not currently in use) for a certain period of
+ time.
+
+ The duration for which a nickname remains unavailable SHOULD be set
+ considering many factors among which are the size (user wise) of the
+ IRC network, and the usual duration of "network splits". It SHOULD
+ be uniform on all servers for a given IRC network.
+
+5.8 Flood control of clients
+
+ With a large network of interconnected IRC servers, it is quite easy
+ for any single client attached to the network to supply a continuous
+ stream of messages that result in not only flooding the network, but
+ also degrading the level of service provided to others. Rather than
+ require every 'victim' to provide their own protection, flood
+ protection was written into the server and is applied to all clients
+ except services. The current algorithm is as follows:
+
+ * check to see if client's `message timer' is less than current time
+ (set to be equal if it is);
+
+ * read any data present from the client;
+
+ * while the timer is less than ten (10) seconds ahead of the current
+ time, parse any present messages and penalize the client by two (2)
+ seconds for each message;
+
+ * additional penalties MAY be used for specific commands which
+ generate a lot of traffic across the network.
+
+ This in essence means that the client may send one (1) message every
+ two (2) seconds without being adversely affected. Services MAY also
+ be subject to this mechanism.
+
+
+
+
+Kalt Informational [Page 20]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+5.9 Non-blocking lookups
+
+ In a real-time environment, it is essential that a server process
+ does as little waiting as possible so that all the clients are
+ serviced fairly. Obviously this requires non-blocking IO on all
+ network read/write operations. For normal server connections, this
+ was not difficult, but there are other support operations that may
+ cause the server to block (such as disk reads). Where possible, such
+ activity SHOULD be performed with a short timeout.
+
+5.9.1 Hostname (DNS) lookups
+
+ Using the standard resolver libraries from Berkeley and others has
+ meant large delays in some cases where replies have timed out. To
+ avoid this, a separate set of DNS routines were written for the
+ current implementation. Routines were setup for non-blocking IO
+ operations with local cache, and then polled from within the main
+ server IO loop.
+
+5.9.2 Username (Ident) lookups
+
+ Although there are numerous ident libraries (implementing the
+ "Identification Protocol" [IDENT]) for use and inclusion into other
+ programs, these caused problems since they operated in a synchronous
+ manner and resulted in frequent delays. Again the solution was to
+ write a set of routines which would cooperate with the rest of the
+ server and work using non-blocking IO.
+
+6. Current problems
+
+ There are a number of recognized problems with this protocol, all of
+ which are hoped to be solved sometime in the near future during its
+ rewrite. Currently, work is underway to find working solutions to
+ these problems.
+
+6.1 Scalability
+
+ It is widely recognized that this protocol does not scale
+ sufficiently well when used in a large arena. The main problem comes
+ from the requirement that all servers know about all other servers
+ and clients and that information regarding them be updated as soon as
+ it changes. It is also desirable to keep the number of servers low
+ so that the path length between any two points is kept minimal and
+ the spanning tree as strongly branched as possible.
+
+
+
+
+
+
+
+Kalt Informational [Page 21]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+6.2 Labels
+
+ The current IRC protocol has 4 types of labels: the nickname, the
+ channel name, the server name and the service name. Each of the four
+ types has its own domain and no duplicates are allowed inside that
+ domain. Currently, it is possible for users to pick the label for
+ any of the first three, resulting in collisions. It is widely
+ recognized that this needs reworking, with a plan for unique names
+ for nicks that don't collide being desirable as well as a solution
+ allowing a cyclic tree.
+
+6.2.1 Nicknames
+
+ The idea of the nickname on IRC is very convenient for users to use
+ when talking to each other outside of a channel, but there is only a
+ finite nickname space and being what they are, it's not uncommon for
+ several people to want to use the same nick. If a nickname is chosen
+ by two people using this protocol, either one will not succeed or
+ both will be removed by use of KILL (See Section 3.7.1 of "IRC Client
+ Protocol" [IRC-CLIENT]).
+
+6.2.2 Channels
+
+ The current channel layout requires that all servers know about all
+ channels, their inhabitants and properties. Besides not scaling
+ well, the issue of privacy is also a concern. A collision of
+ channels is treated as an inclusive event (people from both nets on
+ channel with common name are considered to be members of it) rather
+ than an exclusive one such as used to solve nickname collisions.
+
+ This protocol defines "Safe Channels" which are very unlikely to be
+ the subject of a channel collision. Other channel types are kept for
+ backward compatibility.
+
+6.2.3 Servers
+
+ Although the number of servers is usually small relative to the
+ number of users and channels, they too are currently REQUIRED to be
+ known globally, either each one separately or hidden behind a mask.
+
+6.3 Algorithms
+
+ In some places within the server code, it has not been possible to
+ avoid N^2 algorithms such as checking the channel list of a set of
+ clients.
+
+
+
+
+
+
+Kalt Informational [Page 22]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ In current server versions, there are only few database consistency
+ checks, most of the time each server assumes that a neighbouring
+ server is correct. This opens the door to large problems if a
+ connecting server is buggy or otherwise tries to introduce
+ contradictions to the existing net.
+
+ Currently, because of the lack of unique internal and global labels,
+ there are a multitude of race conditions that exist. These race
+ conditions generally arise from the problem of it taking time for
+ messages to traverse and effect the IRC network. Even by changing to
+ unique labels, there are problems with channel-related commands being
+ disrupted.
+
+7. Security Considerations
+
+7.1 Authentication
+
+ Servers only have two means of authenticating incoming connections:
+ plain text password, and DNS lookups. While these methods are weak
+ and widely recognized as unsafe, their combination has proven to be
+ sufficient in the past:
+
+ * public networks typically allow user connections with only few
+ restrictions, without requiring accurate authentication.
+
+ * private networks which operate in a controlled environment often
+ use home-grown authentication mechanisms not available on the
+ internet: reliable ident servers [IDENT], or other proprietary
+ mechanisms.
+
+ The same comments apply to the authentication of IRC Operators.
+
+ It should also be noted that while there has been no real demand over
+ the years for stronger authentication, and no real effort to provide
+ better means to safely authenticate users, the current protocol
+ offers enough to be able to easily plug-in external authentication
+ methods based on the information that a client can submit to the
+ server upon connection: nickname, username, password.
+
+7.2 Integrity
+
+ Since the PASS and OPER messages of the IRC protocol are sent in
+ clear text, a stream layer encryption mechanism (like "The TLS
+ Protocol" [TLS]) could be used to protect these transactions.
+
+
+
+
+
+
+
+Kalt Informational [Page 23]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+8. Current support and availability
+
+ Mailing lists for IRC related discussion:
+ General discussion: ircd-users@irc.org
+ Protocol development: ircd-dev@irc.org
+
+ Software implementations:
+ ftp://ftp.irc.org/irc/server
+ ftp://ftp.funet.fi/pub/unix/irc
+ ftp://coombs.anu.edu.au/pub/irc
+
+ Newsgroup: alt.irc
+
+9. Acknowledgements
+
+ Parts of this document were copied from the RFC 1459 [IRC] which
+ first formally documented the IRC Protocol. It has also benefited
+ from many rounds of review and comments. In particular, the
+ following people have made significant contributions to this
+ document:
+
+ Matthew Green, Michael Neumayer, Volker Paulsen, Kurt Roeckx, Vesa
+ Ruokonen, Magnus Tjernstrom, Stefan Zehl.
+
+10. References
+
+ [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [IRC] Oikarinen, J. and D. Reed, "Internet Relay Chat
+ Protocol", RFC 1459, May 1993.
+
+ [IRC-ARCH] Kalt, C., "Internet Relay Chat: Architecture", RFC 2810,
+ April 2000.
+
+ [IRC-CLIENT] Kalt, C., "Internet Relay Chat: Client Protocol", RFC
+ 2812, April 2000.
+
+
+ [IRC-CHAN] Kalt, C., "Internet Relay Chat: Channel Management", RFC
+ 2811, April 2000.
+
+ [ZLIB] Deutsch, P. and J-L. Gailly, "ZLIB Compressed Data
+ Format Specification version 3.3", RFC 1950, May 1996.
+
+
+
+
+Kalt Informational [Page 24]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+ [DEFLATE] Deutsch, P., "DEFLATE Compressed Data Format
+ Specification version 1.3", RFC 1951, May 1996.
+
+ [GZIP] Deutsch, P., "GZIP file format specification version
+ 4.3", RFC 1952, May 1996.
+
+ [IDENT] St. Johns, M., "The Identification Protocol", RFC 1413,
+ February 1993.
+
+ [TLS] Dierks, T. and C. Allen, "The TLS Protocol", RFC 2246,
+ January 1999.
+
+11. Author's Address
+
+ Christophe Kalt
+ 99 Teaneck Rd, Apt #117
+ Ridgefield Park, NJ 07660
+ USA
+
+ EMail: kalt@stealth.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 25]
+
+RFC 2813 Internet Relay Chat: Server Protocol April 2000
+
+
+12. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kalt Informational [Page 26]
+
diff --git a/irc_mod/IRC.rc b/irc_mod/IRC.rc
new file mode 100644
index 0000000..ddd0308
--- /dev/null
+++ b/irc_mod/IRC.rc
@@ -0,0 +1,887 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_SETXSTATUS DIALOGEX 0, 0, 189, 99
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT
+CAPTION "Custom Status ""%s"" Details"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "Closing in %d",IDOK,62,79,65,14
+ LTEXT "Title:",IDC_STATIC,5,0,179,8
+ EDITTEXT IDC_XTITLE,5,9,179,13
+ LTEXT "Message:",IDC_STATIC,5,22,179,8
+ EDITTEXT IDC_XMSG,5,31,179,43,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ CTEXT "Retrieving custom status details...",IDC_RETRXSTATUS,5,0,179,75,SS_CENTERIMAGE | NOT WS_VISIBLE
+END
+
+IDD_PREFS_MAIN DIALOGEX 0, 0, 312, 247
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_OPTIONSTAB,"SysTabControl32",0x0,1,1,310,245,WS_EX_ACCEPTFILES
+END
+
+IDD_PREFS_CONNECT DIALOGEX 0, 0, 304, 230
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ COMBOBOX IDC_SERVERCOMBO,10,30,125,90,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_SERVER,10,53,88,12,ES_AUTOHSCROLL | ES_READONLY | WS_GROUP | NOT WS_TABSTOP
+ EDITTEXT IDC_PORT,10,75,50,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | NOT WS_TABSTOP,WS_EX_RIGHT
+ EDITTEXT IDC_PORT2,85,75,50,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | NOT WS_TABSTOP,WS_EX_RIGHT
+ EDITTEXT IDC_PASS,10,100,125,12,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "&Add",IDC_ADDSERVER,"MButtonClass",WS_DISABLED | WS_TABSTOP,16,116,27,14,0x18000000L
+ CONTROL "&Edit",IDC_EDITSERVER,"MButtonClass",WS_DISABLED | WS_TABSTOP,59,116,27,14,0x18000000L
+ CONTROL "&Del",IDC_DELETESERVER,"MButtonClass",WS_DISABLED | WS_TABSTOP,102,116,27,14,0x18000000L
+ EDITTEXT IDC_NICK,158,16,63,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_NICK2,231,16,63,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_NAME,158,40,63,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_USERID,231,40,63,13,ES_AUTOHSCROLL
+ CONTROL "Enable",IDC_IDENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158,73,46,15
+ EDITTEXT IDC_IDENTSYSTEM,210,73,39,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_IDENTPORT,256,73,39,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "only while connecting",IDC_IDENT_TIMED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,171,87,124,11
+ CONTROL "Enable",IDC_RETRY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158,118,42,10
+ EDITTEXT IDC_RETRYWAIT,210,116,39,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ EDITTEXT IDC_RETRYCOUNT,256,116,39,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "Force visible (-i)",IDC_FORCEVISIBLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,145,134,10
+ CONTROL "Rejoin channel if kicked",IDC_REJOINONKICK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,156,134,10
+ CONTROL "Rejoin channels on reconnect",IDC_REJOINCHANNELS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,167,134,10
+ CONTROL "Disable tray balloon on error",IDC_DISABLEERROR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,178,134,10
+ CONTROL "Show addresses",IDC_ADDRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,189,134,10
+ CONTROL "Use server window",IDC_USESERVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,200,134,10
+ CONTROL "Show server window on startup",IDC_SHOWSERVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,211,129,10
+ CONTROL "Keep connection alive",IDC_KEEPALIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,145,154,10
+ CONTROL "Automatically join on invite",IDC_AUTOJOIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,156,154,10
+ CONTROL "'Old style' mode changes",IDC_OLDSTYLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,167,153,10
+ CONTROL "Update online statuses for users",IDC_ONLINENOTIF,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,178,132,10
+ EDITTEXT IDC_ONLINETIMER,267,188,29,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "Spin1",IDC_SPIN1,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,284,188,12,14
+ CONTROL "Update statuses in channel nicklist",IDC_CHANNELAWAY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,200,131,10
+ EDITTEXT IDC_LIMIT,267,210,29,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "Spin2",IDC_SPIN2,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,284,209,11,14
+ CONTROL "Enable",IDC_STARTUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,11,73,10
+ CONTROL "Internet address",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,10,45,81,8,WS_EX_TRANSPARENT
+ LTEXT "Port range",IDC_STATIC,10,67,69,8,0,WS_EX_TRANSPARENT
+ LTEXT "Nick",IDC_STATIC,158,8,68,8,0,WS_EX_TRANSPARENT
+ LTEXT "User ID (Ident)",IDC_STATIC,231,31,68,9,0,WS_EX_TRANSPARENT
+ LTEXT "Full name (e-mail)",IDC_STATIC,158,31,68,9,0,WS_EX_TRANSPARENT
+ LTEXT "Password",IDC_STATIC,10,90,125,8,0,WS_EX_TRANSPARENT
+ LTEXT "Server name",IDC_STATIC,10,22,125,8,0,WS_EX_TRANSPARENT
+ LTEXT "->",IDC_STATIC,71,75,8,8
+ LTEXT "Alternative nick",IDC_STATIC,231,8,68,8,0,WS_EX_TRANSPARENT
+ GROUPBOX "Ident",IDC_STATIC,150,59,154,42
+ LTEXT "System",IDC_STATIC,210,65,39,8,0,WS_EX_TRANSPARENT
+ LTEXT "Port",IDC_STATIC,256,65,35,8,0,WS_EX_TRANSPARENT
+ GROUPBOX "Default network",IDC_STATIC,2,0,142,134
+ GROUPBOX "User info - Required",IDC_STATIC,150,0,154,59
+ GROUPBOX "Other",IDC_STATIC,2,134,302,92
+ GROUPBOX "Reconnect",IDC_STATIC,150,101,154,33
+ LTEXT "Wait (s)",IDC_STATIC,210,108,45,8,0,WS_EX_TRANSPARENT
+ LTEXT "Retry count",IDC_STATIC,256,108,36,8,0,WS_EX_TRANSPARENT
+ LTEXT "Fear the monkeys!!!",IDC_STATIC,72,4,63,8,NOT WS_VISIBLE
+ LTEXT "Check every (s):",IDC_STATIC,158,190,108,8
+ EDITTEXT IDC_SSL,107,53,28,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | NOT WS_TABSTOP,WS_EX_RIGHT
+ LTEXT "SSL",IDC_STATIC,107,45,28,8,0,WS_EX_TRANSPARENT
+ CONTROL "Don't check if more than (users):",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,158,212,108,8
+END
+
+IDD_INFO DIALOGEX 0, 0, 267, 193
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "User information"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ COMBOBOX IDC_INFO_NICK,6,49,60,97,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Ping",IDC_PING,12,128,50,14
+ PUSHBUTTON "Version",IDC_VERSION,76,128,50,14
+ PUSHBUTTON "Time",IDC_TIME,140,128,50,14
+ PUSHBUTTON "Userinfo",IDC_USERINFO,204,128,50,14
+ DEFPUSHBUTTON "&Refresh",ID_INFO_GO,93,174,50,14
+ PUSHBUTTON "&Query",ID_INFO_QUERY,152,174,50,14,WS_GROUP
+ DEFPUSHBUTTON "&Close",ID_INFO_OK,211,174,50,14,WS_GROUP
+ EDITTEXT IDC_INFO_NAME,71,49,60,12,ES_AUTOHSCROLL | NOT WS_TABSTOP
+ EDITTEXT IDC_INFO_ADDRESS,136,49,60,12,ES_AUTOHSCROLL | NOT WS_TABSTOP
+ EDITTEXT IDC_INFO_ID,201,49,60,12,ES_AUTOHSCROLL | NOT WS_TABSTOP
+ EDITTEXT IDC_INFO_AUTH,6,71,60,12,ES_AUTOHSCROLL | NOT WS_TABSTOP
+ EDITTEXT IDC_INFO_SERVER,71,71,60,12,ES_AUTOHSCROLL | NOT WS_TABSTOP
+ EDITTEXT IDC_INFO_AWAY2,136,71,125,12,ES_AUTOHSCROLL | NOT WS_TABSTOP
+ EDITTEXT IDC_INFO_CHANNELS,136,94,125,20,ES_MULTILINE | WS_VSCROLL | NOT WS_TABSTOP
+ EDITTEXT IDC_INFO_OTHER,6,94,125,20,ES_MULTILINE | WS_VSCROLL | NOT WS_TABSTOP
+ LTEXT "Nick",IDC_STATIC,6,41,60,8
+ LTEXT "Name",IDC_STATIC,71,41,59,8
+ LTEXT "Address",IDC_STATIC,136,41,59,8,SS_NOTIFY
+ LTEXT "Channels",IDC_STATIC,136,86,119,8
+ LTEXT "Auth",IDC_STATIC,6,63,59,8
+ LTEXT "Server",IDC_STATIC,71,63,59,8
+ LTEXT "User",IDC_STATIC,201,41,60,8
+ LTEXT "Away Info",IDC_STATIC,136,63,125,8
+ LTEXT "Other",IDC_STATIC,6,86,124,8
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,38,268,1
+ LTEXT "",IDC_WHITERECT,0,0,267,38
+ ICON "",IDC_LOGO,228,5,20,20,SS_REALSIZEIMAGE
+ LTEXT "The server returned the following information. Please note that this information might be misleading and/or falsified",IDC_TEXT,12,16,204,18
+ LTEXT "",IDC_CAPTION,6,5,201,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,167,268,1
+ GROUPBOX "CTCP information",IDC_STATIC,6,118,255,45
+ EDITTEXT IDC_REPLY,12,146,243,12,ES_READONLY | NOT WS_TABSTOP
+END
+
+IDD_NICK DIALOGEX 0, 0, 180, 90
+STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Question"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ COMBOBOX IDC_ENICK,5,47,170,71,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "&OK",IDNOK,65,71,50,14
+ PUSHBUTTON "&Cancel",IDNCANCEL,125,71,50,14,WS_GROUP
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,38,180,1
+ LTEXT "",IDC_WHITERECT,0,0,179,38
+ ICON "",IDC_LOGO,141,5,20,20,SS_REALSIZEIMAGE
+ LTEXT "",IDC_TEXT,13,16,121,18
+ LTEXT "",IDC_CAPTION,5,5,125,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,65,180,1
+END
+
+IDD_PREFS_OTHER DIALOGEX 0, 0, 304, 207
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Enable",IDC_PERFORM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,15,107,10
+ COMBOBOX IDC_PERFORMCOMBO,128,26,118,99,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_PERFORMEDIT,12,44,233,78,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL | WS_GROUP
+ CONTROL "&Set",IDC_ADD,"MButtonClass",WS_DISABLED | WS_TABSTOP,251,70,30,14,0x18000000L
+ CONTROL "&Del",IDC_DELETE,"MButtonClass",WS_DISABLED | WS_TABSTOP,251,90,30,14,0x18000000L
+ EDITTEXT IDC_ALIASEDIT,12,132,272,63,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL
+ GROUPBOX "Perform",IDC_STATIC,8,6,283,116
+ LTEXT "Perform on event:",IDC_STATIC,128,15,110,8,0,WS_EX_TRANSPARENT
+ GROUPBOX "Alias",IDC_STATIC,8,122,283,81
+END
+
+IDD_ADDSERVER DIALOGEX 0, 0, 182, 136
+STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT
+CAPTION "Add server"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ COMBOBOX IDC_ADD_COMBO,7,20,168,90,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_ADD_SERVER,7,44,120,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_ADD_ADDRESS,7,68,120,12,ES_AUTOHSCROLL | WS_GROUP
+ EDITTEXT IDC_ADD_PORT,7,92,47,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ EDITTEXT IDC_ADD_PORT2,80,92,47,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "On",IDC_ON,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,143,52,25,10
+ CONTROL "Auto",IDC_AUTO,"Button",BS_AUTORADIOBUTTON,143,69,30,10
+ CONTROL "Off",IDC_OFF,"Button",BS_AUTORADIOBUTTON,143,86,25,10
+ DEFPUSHBUTTON "&OK",IDN_ADD_OK,63,115,50,14
+ PUSHBUTTON "&Cancel",IDN_ADD_CANCEL,125,115,50,14
+ CONTROL "Internet address",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,7,60,108,8,WS_EX_TRANSPARENT
+ LTEXT "->",IDC_STATIC,64,94,8,8
+ LTEXT "Port range",IDC_STATIC,7,84,87,8,0,WS_EX_TRANSPARENT
+ LTEXT "Server name",IDC_STATIC,7,36,106,8,0,WS_EX_TRANSPARENT
+ LTEXT "Network",IDC_STATIC,7,12,107,8,0,WS_EX_TRANSPARENT
+ GROUPBOX "SSL",IDC_STATIC,136,38,39,67
+END
+
+IDD_LIST DIALOGEX 0, 0, 198, 172
+STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+CAPTION "Channels on server"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ PUSHBUTTON "&Close",IDC_CLOSE,141,151,50,14
+ DEFPUSHBUTTON "&Join",IDC_JOIN,78,151,50,14,WS_DISABLED
+ CONTROL "List1",IDC_INFO_LISTVIEW,"SysListView32",LVS_REPORT | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,7,7,184,139
+ CONTROL "Please wait...",IDC_TEXT,"Static",SS_LEFTNOWORDWRAP | SS_CENTERIMAGE | WS_GROUP,7,151,63,14
+END
+
+IDD_QUICKCONN DIALOGEX 0, 0, 201, 148
+STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ COMBOBOX IDC_SERVERCOMBO,12,54,177,69,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_SERVER,12,78,132,12,ES_AUTOHSCROLL | ES_READONLY | WS_GROUP | NOT WS_TABSTOP
+ EDITTEXT IDC_PORT,12,102,36,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | NOT WS_TABSTOP,WS_EX_RIGHT
+ EDITTEXT IDC_PORT2,63,102,36,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | NOT WS_TABSTOP,WS_EX_RIGHT
+ EDITTEXT IDC_PASS,116,102,73,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "C&onnect",IDNOK,83,129,50,14
+ PUSHBUTTON "&Cancel",IDNCANCEL,139,129,50,14
+ CONTROL "Internet address",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,12,70,130,8,WS_EX_TRANSPARENT
+ LTEXT "Port range",IDC_STATIC,12,94,63,8,0,WS_EX_TRANSPARENT
+ LTEXT "Password",IDC_STATIC,116,94,73,8,0,WS_EX_TRANSPARENT
+ LTEXT "Server name",IDC_STATIC,12,46,177,8,0,WS_EX_TRANSPARENT
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,123,201,1
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,38,201,1
+ LTEXT "",IDC_WHITERECT,0,0,201,38
+ ICON "",IDC_LOGO,159,5,20,20,SS_REALSIZEIMAGE
+ LTEXT "",IDC_TEXT,18,16,138,18
+ LTEXT "",IDC_CAPTION,12,5,143,11
+ LTEXT "->",IDC_STATIC,52,104,8,8,0,WS_EX_TRANSPARENT
+ EDITTEXT IDC_SSL,154,78,35,12,ES_AUTOHSCROLL | ES_READONLY | WS_GROUP | NOT WS_TABSTOP
+ CONTROL "SSL",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,154,70,35,8,WS_EX_TRANSPARENT
+END
+
+IDD_USERINFO DIALOGEX 0, 0, 222, 132
+STYLE DS_SETFONT | DS_CENTER | WS_CHILD | WS_VISIBLE
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_WILDCARD,12,91,40,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_USER,66,91,40,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_HOST,120,91,89,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Save",IDC_BUTTON,159,107,50,14,WS_DISABLED
+ LTEXT "Nick",IDC_STATIC,12,83,40,8
+ LTEXT "User",IDC_STATIC,66,83,40,8
+ LTEXT "Address",IDC_STATIC,120,83,89,8
+ LTEXT "@",IDC_STATIC,109,90,8,8
+ GROUPBOX "Hostmask",IDC_STATIC,6,73,209,52
+ LTEXT "",IDC_DEFAULT,12,30,197,37
+ LTEXT "!",IDC_STATIC,57,90,8,8
+ PUSHBUTTON "&Clear all",IDC_BUTTON2,96,107,50,14
+ GROUPBOX "Online detection mode",IDC_STATIC,6,7,209,66
+ CONTROL "Basic",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,23,17,33,10
+ CONTROL "Wildcard enabled network search",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,69,17,122,10
+END
+
+IDD_CHANMANAGER DIALOGEX 0, 0, 250, 250
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ COMBOBOX IDC_TOPIC,13,56,192,103,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ CONTROL "&Set",IDC_APPLYTOPIC,"MButtonClass",WS_DISABLED | WS_TABSTOP,209,55,28,14,0x18000000L
+ CONTROL "Bans",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_DISABLED | WS_GROUP | WS_TABSTOP,16,87,32,10
+ CONTROL "Invites",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,76,87,37,10
+ CONTROL "Excepts",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,141,87,41,10
+ LISTBOX IDC_LIST,13,100,192,47,LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL | WS_GROUP | WS_TABSTOP
+ CONTROL "&Add",IDC_ADD,"MButtonClass",WS_DISABLED | WS_TABSTOP,209,100,28,14,0x18000000L
+ CONTROL "&Edit",IDC_EDIT,"MButtonClass",WS_DISABLED | WS_TABSTOP,209,116,28,14,0x18000000L
+ CONTROL "&Del",IDC_REMOVE,"MButtonClass",WS_DISABLED | WS_TABSTOP,209,132,28,14,0x18000000L
+ CONTROL "Only Ops set topic",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,168,106,10
+ CONTROL "No external messages",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,181,106,10
+ CONTROL "Invite only",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,194,106,10
+ CONTROL "Moderated",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,207,106,10
+ CONTROL "Key:",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,119,168,45,10
+ EDITTEXT IDC_KEY,168,167,57,12,ES_AUTOHSCROLL | WS_DISABLED
+ CONTROL "User limit:",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,119,181,46,10
+ EDITTEXT IDC_LIMIT,168,181,25,12,ES_AUTOHSCROLL | ES_NUMBER | WS_DISABLED
+ CONTROL "Private",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,119,194,73,10
+ CONTROL "Secret",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,119,207,80,10
+ CONTROL "&Set",IDC_APPLYMODES,"MButtonClass",WS_DISABLED | WS_TABSTOP,209,202,28,14,0x18000000L
+ DEFPUSHBUTTON "&Close",IDCLOSE,194,231,50,14
+ GROUPBOX "Topic",IDC_STATIC,6,45,238,28
+ GROUPBOX "User modes",IDC_STATIC,6,74,238,80
+ GROUPBOX "Channel modes",IDC_STATIC,6,155,238,67
+ CONTROL "Hidden",IDC_NOTOP,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE,197,83,45,10
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,38,250,1
+ LTEXT "",IDC_WHITERECT,0,0,249,38
+ ICON "",IDC_LOGO,212,5,20,20,SS_REALSIZEIMAGE
+ LTEXT "Use the options to set modes for this channel. You are usually required to be op. or higher to modify.",IDC_TEXT,18,16,184,18
+ LTEXT "",IDC_CAPTION,12,5,184,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,225,255,1
+END
+
+IDD_QUESTION DIALOGEX 0, 0, 230, 97
+STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Question"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_EDIT,5,48,220,14,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "&OK",IDNOK,116,78,50,14
+ PUSHBUTTON "&Cancel",IDNCANCEL,175,78,50,14,WS_GROUP
+ EDITTEXT IDC_HIDDENEDIT,5,78,40,14,ES_AUTOHSCROLL | NOT WS_VISIBLE | NOT WS_BORDER | NOT WS_TABSTOP
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,38,230,1
+ LTEXT "",IDC_WHITERECT,0,0,229,38
+ ICON "",IDC_LOGO,193,5,20,20,SS_REALSIZEIMAGE
+ LTEXT "",IDC_TEXT,11,16,179,18
+ LTEXT "",IDC_CAPTION,5,5,184,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,71,230,1
+END
+
+IDD_INIT DIALOGEX 0, 0, 211, 102
+STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Miranda IRC"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_EDIT,5,52,65,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT2,88,52,118,14,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "&OK",IDNOK,96,83,50,14
+ PUSHBUTTON "&Cancel",IDNCANCEL,156,83,50,14,WS_GROUP
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,38,212,1
+ LTEXT "",IDC_WHITERECT,0,0,211,38
+ ICON "",IDC_LOGO,173,5,20,20,SS_REALSIZEIMAGE
+ LTEXT "for choosing the IRC protocol for Miranda IM. Please enter your nickname and real name",IDC_TEXT,11,16,157,18
+ LTEXT "Thank You...",IDC_CAPTION,5,5,154,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,76,211,1
+ LTEXT "Nick",IDC_STATIC,5,44,65,8
+ LTEXT "Full name",IDC_STATIC,88,44,117,8
+END
+
+IDD_PREFS_CTCP DIALOGEX 0, 0, 304, 207
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ COMBOBOX IDC_COMBO,104,40,52,85,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Normal",IDC_SLOW,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,104,24,76,10
+ CONTROL "Send-ahead",IDC_FAST,"Button",BS_AUTORADIOBUTTON,188,24,102,10
+ CONTROL "Attempt reverse DCC (good if firewalled)",IDC_PASSIVE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,62,273,10
+ CONTROL "none",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,104,94,162,10
+ CONTROL "everyone on the contact list",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,104,105,186,10
+ CONTROL "everyone",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,104,116,186,10
+ CONTROL "Disconnect DCC chats when disconnecting from server",IDC_DISC,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,135,257,10
+ CONTROL "Manually set external IP:",IDC_ENABLEIP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,164,130,10
+ EDITTEXT IDC_IP,146,162,144,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_USERINFO,16,196,274,14,ES_AUTOHSCROLL
+ GROUPBOX "Client-to-Client File Transfers",IDC_STATIC,8,6,289,75
+ LTEXT "User information",IDC_STATIC,16,188,144,8
+ GROUPBOX "Client-to-Client Protocol",IDC_STATIC,8,151,289,67
+ GROUPBOX "Client-to-Client Chats",IDC_STATIC,8,81,289,70
+ LTEXT "Send mode:",IDC_STATIC,16,25,79,8
+ LTEXT "Packet size (b):",IDC_STATIC,16,44,88,8
+ CONTROL "Get IP address from server",IDC_FROMSERVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,176,113,10
+ LTEXT "Auto-accept from:",IDC_STATIC,16,106,82,8
+ CONTROL "Send notice",IDC_SENDNOTICE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,188,43,101,10
+END
+
+IDD_MESSAGEBOX DIALOGEX 0, 0, 220, 68
+STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT
+CAPTION "CTCP Chat Request"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ PUSHBUTTON "&Accept",IDN_YES,50,47,50,14
+ DEFPUSHBUTTON "&Deny",IDN_NO,120,47,50,14
+ LTEXT "",IDC_TEXT,43,13,170,31,0,WS_EX_TRANSPARENT
+ ICON "",IDC_LOGO,7,13,21,20
+END
+
+IDD_PREFS_IGNORE DIALOGEX 0, 0, 304, 207
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Enable (*)",IDC_ENABLEIGNORE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,18,78,10
+ CONTROL "Ignore channel messages by default",IDC_IGNORECHANNEL,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,108,18,180,10
+ CONTROL "List1",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,16,33,240,104
+ CONTROL "&Add",IDC_ADD,"MButtonClass",WS_DISABLED | WS_TABSTOP,264,43,27,14,0x18000000L
+ CONTROL "&Edit",IDC_EDIT,"MButtonClass",WS_DISABLED | WS_TABSTOP,264,68,27,14,0x18000000L
+ CONTROL "&Del",IDC_DELETE,"MButtonClass",WS_DISABLED | WS_TABSTOP,264,93,27,14,0x18000000L
+ CONTROL "Ignore filetransfer requests",IDC_IGNOREFILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,170,240,10
+ CONTROL "Ignore DCC Chat requests",IDC_IGNORECHAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,185,240,10
+ CONTROL "Ignore DCC Chat requests from unknown contacts",IDC_IGNOREUNKNOWN,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,200,256,10
+ GROUPBOX "Ignore users",-1,8,6,289,150
+ GROUPBOX "Other",-1,8,156,289,62
+ CONTROL "(*) Queries from users on your contactlist are never ignored",IDC_CUSTOM,
+ "Hyperlink",WS_TABSTOP | 0x1,16,142,274,9
+END
+
+IDD_ADDIGNORE DIALOGEX 0, 0, 220, 126
+STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_MASK,7,15,137,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_NETWORK,150,15,63,14,ES_AUTOHSCROLL
+ CONTROL "Queries",IDC_Q,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,47,54,10
+ CONTROL "Messages",IDC_M,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,80,47,64,10
+ CONTROL "Notices",IDC_N,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,150,47,57,10
+ CONTROL "Invites",IDC_I,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,66,54,10
+ CONTROL "CTCP",IDC_C,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,80,66,64,10
+ CONTROL "DCC",IDC_D,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,150,66,57,10
+ DEFPUSHBUTTON "&Accept",IDN_YES,93,105,50,14
+ PUSHBUTTON "&Cancel",IDN_NO,163,105,50,14
+ LTEXT "Ignore mask ( nick!user@host )",IDC_STATIC,7,7,136,8
+ LTEXT "Network (*)",IDC_STATIC,150,7,63,8
+ GROUPBOX "Ignore events",IDC_STATIC,7,36,206,46
+ CTEXT "(*) blank to set this mask for all networks",IDC_STATIC,7,90,206,8
+END
+
+IDD_PREFS_POPUPS DIALOGEX 0, 0, 312, 247
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ PUSHBUTTON "Preview",IDC_PREVIEW,250,232,50,14
+ CONTROL "Enable popup support",IDC_POPUPS_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,18,288,10
+ CONTROL "Display popup when user is offline",IDC_POPUP_NOUSER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,38,278,10
+ CONTROL "Display errors using popups",IDC_POPUP_ERROR,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,22,28,278,10
+ CONTROL "Custom1",IDC_POPUP_LOG0_BACKCOLOR,"ColourPicker",WS_TABSTOP,84,114,40,10
+ CONTROL "Custom2",IDC_POPUP_LOG0_TEXTCOLOR,"ColourPicker",WS_TABSTOP,132,114,40,10
+ CONTROL "Custom3",IDC_POPUP_LOG1_BACKCOLOR,"ColourPicker",WS_TABSTOP,84,128,40,10
+ CONTROL "Custom4",IDC_POPUP_LOG1_TEXTCOLOR,"ColourPicker",WS_TABSTOP,132,128,40,10
+ CONTROL "Custom5",IDC_POPUP_LOG2_BACKCOLOR,"ColourPicker",WS_TABSTOP,84,142,40,10
+ CONTROL "Custom6",IDC_POPUP_LOG2_TEXTCOLOR,"ColourPicker",WS_TABSTOP,132,142,40,10
+ CONTROL "Custom7",IDC_POPUP_LOG3_BACKCOLOR,"ColourPicker",NOT WS_VISIBLE | WS_TABSTOP,84,156,40,10
+ CONTROL "Custom8",IDC_POPUP_LOG3_TEXTCOLOR,"ColourPicker",NOT WS_VISIBLE | WS_TABSTOP,132,156,40,10
+ EDITTEXT IDC_POPUP_LOG1_TIMEOUT,180,126,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ EDITTEXT IDC_POPUP_LOG2_TIMEOUT,180,140,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ EDITTEXT IDC_POPUP_LOG3_TIMEOUT,180,154,34,12,ES_AUTOHSCROLL | ES_NUMBER | NOT WS_VISIBLE
+ GROUPBOX "Look && Feel",IDC_STATIC,6,87,300,141
+ GROUPBOX "Options",IDC_STATIC,6,5,300,81
+ LTEXT "Note",IDC_STATIC,12,114,72,14
+ LTEXT "Warning",IDC_STATIC,12,128,72,14
+ LTEXT "Error",IDC_STATIC,12,142,72,14
+ LTEXT "Fatal",IDC_STATIC,12,156,72,12,NOT WS_VISIBLE
+ LTEXT "Back Color",IDC_STATIC,84,102,48,8
+ LTEXT "Text Color",IDC_STATIC,132,102,49,8
+ LTEXT "Timeout (*)",IDC_STATIC,181,102,60,8
+ LTEXT "(*) Timeouts require Popup v. 1.0.1.9 or later",IDC_STATIC,6,238,227,8
+ EDITTEXT IDC_POPUP_LOG0_TIMEOUT,180,112,34,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Display Whois using popups",IDC_POPUP_WHOIS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,48,278,10
+END
+
+IDD_PREFS_EXTRA DIALOGEX 0, 0, 304, 227
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "CTCP Extra",IDC_STATIC,0,0,302,130
+ CONTROL "Enable Nudge support",IDC_NUDGEENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,6,31,290,10
+ CONTROL "Enable Typing Notify support",IDC_TYPINGENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,21,290,10
+ CONTROL "Enable Custom status support",IDC_XSTATUSENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,12,45,148,10
+ CONTROL "Reset Custom status on status change",IDC_XSTATUSRESET,
+ "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,18,64,142,10
+ CONTROL "Auto-retrieve Custom status details",IDC_XSTATUSAUTO,
+ "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,18,55,142,10
+ GROUPBOX "Others",IDC_STATIC,0,137,302,75
+ CONTROL "Enable scripting support",IDC_SCRIPT,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,6,147,154,10
+ CONTROL "Go to the IRC protocol website for help and information",IDC_CUSTOM,
+ "Hyperlink",WS_TABSTOP | 0x1,6,216,290,9
+ LTEXT "Quit message",IDC_STATIC,6,186,290,8
+ EDITTEXT IDC_QUITMESSAGE,6,194,290,14,ES_AUTOHSCROLL
+ CONTROL "Enable avatar support",IDC_ENABLEAVATARS,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,12,83,284,10
+ CONTROL "Load avatars automatically",IDC_AUTOLOADAVATARS,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,18,93,278,10
+ CONTROL "Auto-retrieve version details",IDC_VERSIONAUTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,11,290,10
+ CONTROL "Link avatars as contact photos (mToolTip photos)",IDC_LINKAVATARS,
+ "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,18,103,278,10
+ CONTROL "Use MemoServ to send offline messages",IDC_MEMOSERV,
+ "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,6,158,154,10
+ EDITTEXT IDC_MEMOSERVNAME,160,156,136,12,ES_AUTOHSCROLL | WS_DISABLED
+ CONTROL "1",IDC_ADV1,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,182,55,16,8
+ CONTROL "2",IDC_ADV2,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,200,55,16,8
+ CONTROL "3",IDC_ADV3,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,218,55,16,8
+ CONTROL "4",IDC_ADV4,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,236,55,16,8
+ CONTROL "5",IDC_ADV5,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,254,55,16,8
+ CONTROL "6",IDC_ADV6,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,272,55,16,8
+ LTEXT "Contact List Icon",IDC_STATIC,182,45,80,8
+ GROUPBOX "",IDC_STATIC,6,38,290,39
+ GROUPBOX "",IDC_STATIC,6,76,290,39
+ CONTROL "Auto-retrieve MemoServ messages",IDC_MEMOSERV_AUTORETRIEVE,
+ "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,6,169,154,10
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MAIN ICON "Icons\\Angeli-Ka\\Main.ico"
+IDI_ADD ICON "Icons\\Angeli-Ka\\Add.ico"
+IDI_BLOCK ICON "Icons\\Angeli-Ka\\Ignore.ico"
+IDI_DELETE ICON "Icons\\Angeli-Ka\\Cancel.ico"
+IDI_GO ICON "Icons\\Angeli-Ka\\Apply.ico"
+IDI_WHOIS ICON "Icons\\Angeli-Ka\\Question.ico"
+IDI_LIST ICON "Icons\\Angeli-Ka\\List.ico"
+IDI_MANAGER ICON "Icons\\Angeli-Ka\\Manager.ico"
+IDI_QUICK ICON "Icons\\Angeli-Ka\\Quick connect.ico"
+IDI_RENAME ICON "Icons\\Angeli-Ka\\Edit.ico"
+IDI_SHOW ICON "Icons\\Angeli-Ka\\Show chanel.ico"
+IDI_LOGO ICON "Icons\\Angeli-Ka\\Logo.ico"
+IDI_DCC ICON "Icons\\Angeli-Ka\\Dcc.ico"
+IDI_SERVER ICON "Icons\\Angeli-Ka\\Server.ico"
+IDI_PART ICON "Icons\\Angeli-Ka\\Leave.ico"
+IDI_JOIN ICON "Icons\\Angeli-Ka\\Join.ico"
+IDI_ICON_INFORMATION ICON "Icons\\Angeli-Ka\\Quest2.ico"
+IDI_ICON_ERROR ICON "Icons\\Angeli-Ka\\Delete.ico"
+IDI_ICON_FATAL ICON "icons\\error.ico"
+IDI_ICON_WARNING ICON "Icons\\Angeli-Ka\\Warning.ico"
+IDI_AVATAR ICON "Icons\\Angeli-Ka\\Avatar.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_PREFS_CONNECT, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ VERTGUIDE, 10
+ VERTGUIDE, 135
+ VERTGUIDE, 144
+ VERTGUIDE, 158
+ VERTGUIDE, 210
+ VERTGUIDE, 229
+ HORZGUIDE, 16
+ HORZGUIDE, 30
+ HORZGUIDE, 39
+ HORZGUIDE, 53
+ HORZGUIDE, 61
+ HORZGUIDE, 73
+ HORZGUIDE, 75
+ HORZGUIDE, 116
+ HORZGUIDE, 134
+ HORZGUIDE, 145
+ END
+
+ IDD_INFO, DIALOG
+ BEGIN
+ VERTGUIDE, 6
+ VERTGUIDE, 261
+ BOTTOMMARGIN, 188
+ HORZGUIDE, 5
+ HORZGUIDE, 38
+ HORZGUIDE, 49
+ HORZGUIDE, 71
+ HORZGUIDE, 94
+ HORZGUIDE, 118
+ HORZGUIDE, 135
+ HORZGUIDE, 146
+ HORZGUIDE, 163
+ HORZGUIDE, 168
+ END
+
+ IDD_NICK, DIALOG
+ BEGIN
+ BOTTOMMARGIN, 85
+ HORZGUIDE, 5
+ HORZGUIDE, 65
+ END
+
+ IDD_PREFS_OTHER, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ RIGHTMARGIN, 291
+ VERTGUIDE, 8
+ VERTGUIDE, 12
+ VERTGUIDE, 128
+ HORZGUIDE, 15
+ HORZGUIDE, 38
+ HORZGUIDE, 44
+ HORZGUIDE, 122
+ HORZGUIDE, 203
+ END
+
+ IDD_ADDSERVER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 175
+ VERTGUIDE, 127
+ VERTGUIDE, 136
+ VERTGUIDE, 143
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 129
+ HORZGUIDE, 20
+ HORZGUIDE, 44
+ HORZGUIDE, 68
+ HORZGUIDE, 92
+ END
+
+ IDD_LIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 191
+ VERTGUIDE, 16
+ VERTGUIDE, 70
+ VERTGUIDE, 128
+ VERTGUIDE, 182
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 165
+ HORZGUIDE, 19
+ HORZGUIDE, 138
+ HORZGUIDE, 146
+ END
+
+ IDD_QUICKCONN, DIALOG
+ BEGIN
+ VERTGUIDE, 12
+ VERTGUIDE, 189
+ BOTTOMMARGIN, 143
+ HORZGUIDE, 5
+ HORZGUIDE, 38
+ HORZGUIDE, 54
+ HORZGUIDE, 78
+ HORZGUIDE, 102
+ HORZGUIDE, 123
+ END
+
+ IDD_USERINFO, DIALOG
+ BEGIN
+ LEFTMARGIN, 6
+ RIGHTMARGIN, 215
+ VERTGUIDE, 62
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 125
+ HORZGUIDE, 22
+ HORZGUIDE, 30
+ HORZGUIDE, 73
+ HORZGUIDE, 91
+ HORZGUIDE, 114
+ END
+
+ IDD_CHANMANAGER, DIALOG
+ BEGIN
+ VERTGUIDE, 6
+ VERTGUIDE, 119
+ BOTTOMMARGIN, 245
+ HORZGUIDE, 5
+ HORZGUIDE, 22
+ HORZGUIDE, 40
+ HORZGUIDE, 45
+ HORZGUIDE, 73
+ HORZGUIDE, 154
+ HORZGUIDE, 225
+ END
+
+ IDD_QUESTION, DIALOG
+ BEGIN
+ VERTGUIDE, 5
+ BOTTOMMARGIN, 92
+ HORZGUIDE, 5
+ HORZGUIDE, 72
+ END
+
+ IDD_INIT, DIALOG
+ BEGIN
+ VERTGUIDE, 5
+ BOTTOMMARGIN, 97
+ HORZGUIDE, 5
+ HORZGUIDE, 52
+ HORZGUIDE, 77
+ END
+
+ IDD_PREFS_CTCP, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ RIGHTMARGIN, 291
+ VERTGUIDE, 10
+ VERTGUIDE, 27
+ VERTGUIDE, 37
+ VERTGUIDE, 83
+ VERTGUIDE, 98
+ VERTGUIDE, 140
+ VERTGUIDE, 154
+ VERTGUIDE, 182
+ VERTGUIDE, 199
+ VERTGUIDE, 220
+ VERTGUIDE, 260
+ VERTGUIDE, 284
+ HORZGUIDE, 23
+ HORZGUIDE, 42
+ HORZGUIDE, 61
+ HORZGUIDE, 75
+ HORZGUIDE, 104
+ HORZGUIDE, 134
+ HORZGUIDE, 145
+ HORZGUIDE, 163
+ HORZGUIDE, 190
+ END
+
+ IDD_MESSAGEBOX, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 213
+ VERTGUIDE, 43
+ VERTGUIDE, 75
+ VERTGUIDE, 145
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 61
+ HORZGUIDE, 13
+ END
+
+ IDD_PREFS_IGNORE, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ RIGHTMARGIN, 291
+ VERTGUIDE, 10
+ VERTGUIDE, 250
+ VERTGUIDE, 258
+ HORZGUIDE, 17
+ HORZGUIDE, 27
+ HORZGUIDE, 140
+ HORZGUIDE, 150
+ END
+
+ IDD_ADDIGNORE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 213
+ VERTGUIDE, 20
+ VERTGUIDE, 80
+ VERTGUIDE, 150
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 119
+ HORZGUIDE, 15
+ HORZGUIDE, 36
+ HORZGUIDE, 52
+ HORZGUIDE, 71
+ END
+
+ IDD_PREFS_EXTRA, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ RIGHTMARGIN, 302
+ VERTGUIDE, 6
+ VERTGUIDE, 12
+ VERTGUIDE, 160
+ VERTGUIDE, 296
+ HORZGUIDE, 137
+ HORZGUIDE, 194
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU MENU
+BEGIN
+ POPUP "menu1"
+ BEGIN
+ MENUITEM "&Query", ID_MENU1_QUERY
+ MENUITEM "&Whois", ID_MENU1_WHOIS
+ MENUITEM SEPARATOR
+ POPUP "&Control"
+ BEGIN
+ MENUITEM "&Op", ID_MENU1_OP
+ MENUITEM "&Deop", ID_MENU1_DEOP
+ MENUITEM "&Voice", ID_MENU1_VOICE
+ MENUITEM "D&evoice", ID_MENU1_DEVOICE
+ MENUITEM SEPARATOR
+ MENUITEM "&Kick", ID_MENU1_KICK
+ MENUITEM "Ki&ck (Reason)", ID_MENU1_KICKREASON
+ MENUITEM "&Ban", ID_MENU1_BAN
+ MENUITEM "Ban'&n Kick", ID_MENU1_BANKICK
+ MENUITEM "Ban'n Kick (&Reason)", ID_MENU1_BANKICKREASON
+ END
+ MENUITEM SEPARATOR
+ POPUP "&Ignore"
+ BEGIN
+ MENUITEM "On", ID_MENU1_IGNORE_ON
+ MENUITEM "Off", ID_MENU1_IGNORE_OFF
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "&Add contact", ID_MENU1_ADDCONTACT
+ END
+ POPUP "Log"
+ BEGIN
+ MENUITEM "&Copy", IDM_COPY
+ MENUITEM "Co&py All", IDM_COPYALL
+ MENUITEM "Select &All", IDM_SELECTALL
+ MENUITEM SEPARATOR
+ MENUITEM "Leave channel", IDM_LEAVECHAN
+ MENUITEM SEPARATOR
+ MENUITEM "Clear log", IDM_CLEAR
+ MENUITEM SEPARATOR
+ MENUITEM "Join channel", IDM_JOIN
+ MENUITEM "Change nickname", IDM_CHANGENICK
+ MENUITEM "Show/Hide server", IDM_SHOWSERVER
+ MENUITEM SEPARATOR
+ MENUITEM "Channel manager", IDM_CHANMANAGER
+ END
+ POPUP "LogLink"
+ BEGIN
+ MENUITEM "Open in &new window", IDM_OPENNEW
+ MENUITEM "&Open in existing window", IDM_OPENEXISTING
+ MENUITEM "&Copy link", IDM_COPYLINK
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Swedish resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE)
+#ifdef _WIN32
+LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Swedish resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/irc_mod/IRC.sln b/irc_mod/IRC.sln
new file mode 100644
index 0000000..cfd8784
--- /dev/null
+++ b/irc_mod/IRC.sln
@@ -0,0 +1,30 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IRC", "IRC.vcproj", "{9DEF2913-AA5F-4925-A42B-11F203211052}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ICONS", "icons_pack\ICONS.vcproj", "{84471097-C974-45CD-845E-828B304195B8}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug Unicode|Win32 = Debug Unicode|Win32
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Debug|Win32.Build.0 = Debug|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Release|Win32.ActiveCfg = Release|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Release|Win32.Build.0 = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Debug|Win32.ActiveCfg = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Debug|Win32.Build.0 = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Release|Win32.ActiveCfg = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/irc_mod/IRC.vcproj b/irc_mod/IRC.vcproj
new file mode 100644
index 0000000..96e0a87
--- /dev/null
+++ b/irc_mod/IRC.vcproj
@@ -0,0 +1,1154 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="IRC"
+ ProjectGUID="{9DEF2913-AA5F-4925-A42B-11F203211052}"
+ RootNamespace="IRC"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../bin/debug/build"
+ IntermediateDirectory="../../bin/debug/build"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/IRC.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;IRC_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="../../bin/debug/build/IRC.pch"
+ AssemblerListingLocation="../../bin/debug/build/"
+ ObjectFile="../../bin/debug/build/"
+ ProgramDataBaseFileName="../../bin/debug/build/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1053"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib shlwapi.lib wsock32.lib"
+ OutputFile="../../bin/debug/plugins/IRC.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="../../bin/debug/build/IRC.pdb"
+ GenerateMapFile="true"
+ MapFileName="../../bin/debug/build/IRC.map"
+ BaseAddress="0x54010000"
+ ImportLibrary="../../bin/debug/build/IRC.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../bin/release/build"
+ IntermediateDirectory="../../bin/release/build"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/IRC.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IRC_EXPORTS"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="../../bin/release/build/IRC.pch"
+ AssemblerListingLocation="../../bin/release/build/"
+ ObjectFile="../../bin/release/build/"
+ ProgramDataBaseFileName="../../bin/release/build/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1053"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib shlwapi.lib wsock32.lib"
+ OutputFile="../../bin/release/plugins/IRC.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="../../bin/release/build/IRC.pdb"
+ GenerateMapFile="true"
+ MapFileName="../../bin/release/build/IRC.map"
+ BaseAddress="0x54010000"
+ ImportLibrary="../../bin/release/build/IRC.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release (static)|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/IRC.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IRC_EXPORTS"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="../../bin/release/build/IRC.pch"
+ AssemblerListingLocation="../../bin/release/build/"
+ ObjectFile="../../bin/release/build/"
+ ProgramDataBaseFileName="../../bin/release/build/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1053"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib shlwapi.lib wsock32.lib"
+ OutputFile="../../bin/release/plugins/IRC.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="../../bin/release/build/IRC.pdb"
+ GenerateMapFile="true"
+ MapFileName="../../bin/release/build/IRC.map"
+ BaseAddress="0x54010000"
+ ImportLibrary="../../bin/release/build/IRC.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug Unicode|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ 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/IRC.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;IRC_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="../../bin/debug/build/IRC.pch"
+ AssemblerListingLocation="../../bin/debug/build/"
+ ObjectFile="../../bin/debug/build/"
+ ProgramDataBaseFileName="../../bin/debug/build/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1053"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib shlwapi.lib wsock32.lib"
+ OutputFile="../../bin/debug/plugins/IRC.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="../../bin/debug/build/IRC.pdb"
+ GenerateMapFile="true"
+ MapFileName="../../bin/debug/build/IRC.map"
+ BaseAddress="0x54010000"
+ ImportLibrary="../../bin/debug/build/IRC.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\avatar.cpp"
+ >
+ </File>
+ <File
+ RelativePath="clist.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="commandmonitor.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\i18n.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\iconlib.cpp"
+ >
+ </File>
+ <File
+ RelativePath="input.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="irclib.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="main.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\md5.cpp"
+ >
+ </File>
+ <File
+ RelativePath="options.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="output.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\popups.cpp"
+ >
+ </File>
+ <File
+ RelativePath="scripting.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="services.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tools.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\utils.cpp"
+ >
+ </File>
+ <File
+ RelativePath="windows.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (static)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\xstatus.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath=".\avatar.h"
+ >
+ </File>
+ <File
+ RelativePath="commandmonitor.h"
+ >
+ </File>
+ <File
+ RelativePath="irc.h"
+ >
+ </File>
+ <File
+ RelativePath="irclib.h"
+ >
+ </File>
+ <File
+ RelativePath=".\m_nudge.h"
+ >
+ </File>
+ <File
+ RelativePath="resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\utils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\xstatus.h"
+ >
+ </File>
+ <Filter
+ Name="External"
+ >
+ <File
+ RelativePath="AggressiveOptimize.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\plugins\chat unstableTab\m_chat.h"
+ >
+ </File>
+ <File
+ RelativePath="m_ircscript.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ <File
+ RelativePath=".\Icons\error.ico"
+ >
+ </File>
+ <File
+ RelativePath="IRC.rc"
+ >
+ </File>
+ <Filter
+ Name="main"
+ >
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Add.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Apply.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Avatar.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Cancel.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Dcc.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Delete.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Edit.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Ignore.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Join.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Leave.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\List.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Logo.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Main.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Manager.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Quest2.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Question.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Quick connect.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Server.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Show chanel.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Warning.ico"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Documentation"
+ Filter=".txt"
+ >
+ <Filter
+ Name="docs"
+ >
+ <File
+ RelativePath=".\Docs\irc_license.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\Docs\irc_readme.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\Docs\irc_translate.txt"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="RFC"
+ >
+ <File
+ RelativePath=".\Docs\rfc1459.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\Docs\rfc2810.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\Docs\rfc2811.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\Docs\rfc2812.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\Docs\rfc2813.txt"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/irc_mod/IRC7.sln b/irc_mod/IRC7.sln
new file mode 100644
index 0000000..66f4c43
--- /dev/null
+++ b/irc_mod/IRC7.sln
@@ -0,0 +1,55 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IRC", "IRC7.vcproj", "{9DEF2913-AA5F-4925-A42B-11F203211052}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ICONS", "icons_pack\ICONS7.vcproj", "{84471097-C974-45CD-845E-828B304195B8}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Debug Unicode = Debug Unicode
+ Release = Release
+ Release Unicode = Release Unicode
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Debug.ActiveCfg = Debug|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Debug.Build.0 = Debug|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Debug Unicode.ActiveCfg = Debug Unicode|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Debug Unicode.Build.0 = Debug Unicode|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Release.ActiveCfg = Release Unicode|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Release.Build.0 = Release Unicode|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Release Unicode.ActiveCfg = Release Unicode|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Release Unicode.Build.0 = Release Unicode|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Debug.ActiveCfg = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Debug.Build.0 = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Debug Unicode.ActiveCfg = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Debug Unicode.Build.0 = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Release.ActiveCfg = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Release.Build.0 = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Release Unicode.ActiveCfg = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Release Unicode.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release (static)|Win32 = Release (static)|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Debug|Win32.Build.0 = Debug|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Release (static)|Win32.ActiveCfg = Release (static)|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Release (static)|Win32.Build.0 = Release (static)|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Release|Win32.ActiveCfg = Release|Win32
+ {9DEF2913-AA5F-4925-A42B-11F203211052}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/irc_mod/IRC7.vcproj b/irc_mod/IRC7.vcproj
new file mode 100644
index 0000000..8740215
--- /dev/null
+++ b/irc_mod/IRC7.vcproj
@@ -0,0 +1,974 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="IRC"
+ ProjectGUID="{9DEF2913-AA5F-4925-A42B-11F203211052}"
+ RootNamespace="IRC">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../bin/debug/build"
+ IntermediateDirectory="../../bin/debug/build"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;IRC_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="../../bin/debug/build/IRC.pch"
+ AssemblerListingLocation="../../bin/debug/build/"
+ ObjectFile="../../bin/debug/build/"
+ ProgramDataBaseFileName="../../bin/debug/build/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib shlwapi.lib wsock32.lib"
+ OutputFile="../../bin/debug/plugins/IRC.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="../../bin/debug/build/IRC.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName="../../bin/debug/build/IRC.map"
+ BaseAddress="0x54010000"
+ ImportLibrary="../../bin/debug/build/IRC.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/IRC.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1053"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../bin/release/build"
+ IntermediateDirectory="../../bin/release/build"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IRC_EXPORTS"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="../../bin/release/build/IRC.pch"
+ AssemblerListingLocation="../../bin/release/build/"
+ ObjectFile="../../bin/release/build/"
+ ProgramDataBaseFileName="../../bin/release/build/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib shlwapi.lib wsock32.lib"
+ OutputFile="../../bin/release/plugins/IRC.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="../../bin/release/build/IRC.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName="../../bin/release/build/IRC.map"
+ BaseAddress="0x54010000"
+ ImportLibrary="../../bin/release/build/IRC.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/IRC.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1053"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug Unicode|Win32"
+ OutputDirectory="../../bin/debugW/build"
+ IntermediateDirectory="../../bin/debugW/build"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="1">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;IRC_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="../../bin/debug/build/IRC.pch"
+ AssemblerListingLocation="../../bin/debug/build/"
+ ObjectFile="../../bin/debug/build/"
+ ProgramDataBaseFileName="../../bin/debug/build/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib shlwapi.lib wsock32.lib"
+ OutputFile="../../bin/debug/plugins/IRC.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="../../bin/debug/build/IRC.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName="../../bin/debug/build/IRC.map"
+ BaseAddress="0x54010000"
+ ImportLibrary="../../bin/debug/build/IRC.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/IRC.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1053"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release Unicode|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IRC_EXPORTS"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="../../bin/release/build/IRC.pch"
+ AssemblerListingLocation="../../bin/release/build/"
+ ObjectFile="../../bin/release/build/"
+ ProgramDataBaseFileName="../../bin/release/build/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib shlwapi.lib wsock32.lib"
+ OutputFile="../../bin/release/plugins/IRC.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="../../bin/release/build/IRC.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName="../../bin/release/build/IRC.map"
+ BaseAddress="0x54010000"
+ ImportLibrary="../../bin/release/build/IRC.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/IRC.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1053"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath=".\avatar.cpp">
+ </File>
+ <File
+ RelativePath="clist.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="commandmonitor.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\i18n.cpp">
+ </File>
+ <File
+ RelativePath=".\iconlib.cpp">
+ </File>
+ <File
+ RelativePath="input.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="irclib.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="main.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\md5.cpp">
+ </File>
+ <File
+ RelativePath="options.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="output.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\popups.cpp">
+ </File>
+ <File
+ RelativePath="scripting.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="services.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tools.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\utils.cpp">
+ </File>
+ <File
+ RelativePath="windows.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;IRC_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\xstatus.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath=".\avatar.h">
+ </File>
+ <File
+ RelativePath="commandmonitor.h">
+ </File>
+ <File
+ RelativePath="irc.h">
+ </File>
+ <File
+ RelativePath="irclib.h">
+ </File>
+ <File
+ RelativePath=".\m_nudge.h">
+ </File>
+ <File
+ RelativePath="resource.h">
+ </File>
+ <File
+ RelativePath=".\utils.h">
+ </File>
+ <File
+ RelativePath=".\xstatus.h">
+ </File>
+ <Filter
+ Name="External">
+ <File
+ RelativePath="AggressiveOptimize.h">
+ </File>
+ <File
+ RelativePath="..\..\plugins\chat unstableTab\m_chat.h">
+ </File>
+ <File
+ RelativePath="m_ircscript.h">
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ <File
+ RelativePath=".\Icons\error.ico">
+ </File>
+ <File
+ RelativePath="IRC.rc">
+ </File>
+ <Filter
+ Name="xstatus">
+ <File
+ RelativePath=".\Icons\xstatus01.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus02.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus03.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus04.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus05.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus06.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus07.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus08.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus09.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus10.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus11.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus12.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus13.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus14.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus15.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus16.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus17.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus18.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus19.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus20.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus21.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus22.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus23.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus24.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus25.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus26.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus27.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus28.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus29.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus30.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus31.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\xstatus32.ico">
+ </File>
+ </Filter>
+ <Filter
+ Name="main">
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Add.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Apply.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Avatar.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Cancel.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Dcc.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Delete.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Edit.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Ignore.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Join.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Leave.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\List.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Logo.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Main.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Manager.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Quest2.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Question.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Quick connect.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Server.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Show chanel.ico">
+ </File>
+ <File
+ RelativePath=".\Icons\Angeli-Ka\Warning.ico">
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Documentation"
+ Filter=".txt">
+ <Filter
+ Name="docs">
+ <File
+ RelativePath=".\Docs\irc_license.txt">
+ </File>
+ <File
+ RelativePath=".\Docs\irc_readme.txt">
+ </File>
+ <File
+ RelativePath=".\Docs\irc_translate.txt">
+ </File>
+ </Filter>
+ <Filter
+ Name="RFC">
+ <File
+ RelativePath=".\Docs\rfc1459.txt">
+ </File>
+ <File
+ RelativePath=".\Docs\rfc2810.txt">
+ </File>
+ <File
+ RelativePath=".\Docs\rfc2811.txt">
+ </File>
+ <File
+ RelativePath=".\Docs\rfc2812.txt">
+ </File>
+ <File
+ RelativePath=".\Docs\rfc2813.txt">
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/irc_mod/Icons/Angeli-Ka/Add.ico b/irc_mod/Icons/Angeli-Ka/Add.ico
new file mode 100644
index 0000000..3fd5ef3
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Add.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Apply.ico b/irc_mod/Icons/Angeli-Ka/Apply.ico
new file mode 100644
index 0000000..7e18dc4
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Apply.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Avatar.ico b/irc_mod/Icons/Angeli-Ka/Avatar.ico
new file mode 100644
index 0000000..25d4ad7
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Avatar.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Cancel.ico b/irc_mod/Icons/Angeli-Ka/Cancel.ico
new file mode 100644
index 0000000..710929d
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Cancel.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Dcc.ico b/irc_mod/Icons/Angeli-Ka/Dcc.ico
new file mode 100644
index 0000000..e1421cb
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Dcc.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Delete.ico b/irc_mod/Icons/Angeli-Ka/Delete.ico
new file mode 100644
index 0000000..9ba2221
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Delete.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Edit.ico b/irc_mod/Icons/Angeli-Ka/Edit.ico
new file mode 100644
index 0000000..b85f53b
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Edit.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Ignore.ico b/irc_mod/Icons/Angeli-Ka/Ignore.ico
new file mode 100644
index 0000000..91f176f
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Ignore.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Join.ico b/irc_mod/Icons/Angeli-Ka/Join.ico
new file mode 100644
index 0000000..d533b2b
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Join.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Leave.ico b/irc_mod/Icons/Angeli-Ka/Leave.ico
new file mode 100644
index 0000000..2a91b8a
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Leave.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/List.ico b/irc_mod/Icons/Angeli-Ka/List.ico
new file mode 100644
index 0000000..798c2c2
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/List.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Logo.bak b/irc_mod/Icons/Angeli-Ka/Logo.bak
new file mode 100644
index 0000000..0bf8536
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Logo.bak
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Logo.ico b/irc_mod/Icons/Angeli-Ka/Logo.ico
new file mode 100644
index 0000000..919eccf
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Logo.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Main.ico b/irc_mod/Icons/Angeli-Ka/Main.ico
new file mode 100644
index 0000000..fccffbc
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Main.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Manager.ico b/irc_mod/Icons/Angeli-Ka/Manager.ico
new file mode 100644
index 0000000..5b065ff
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Manager.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Protopic.ico b/irc_mod/Icons/Angeli-Ka/Protopic.ico
new file mode 100644
index 0000000..bdb8500
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Protopic.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Quest2.ico b/irc_mod/Icons/Angeli-Ka/Quest2.ico
new file mode 100644
index 0000000..a6f23bc
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Quest2.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Question.ico b/irc_mod/Icons/Angeli-Ka/Question.ico
new file mode 100644
index 0000000..2f11d7b
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Question.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Quick connect.ico b/irc_mod/Icons/Angeli-Ka/Quick connect.ico
new file mode 100644
index 0000000..be271cb
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Quick connect.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Reading.ico b/irc_mod/Icons/Angeli-Ka/Reading.ico
new file mode 100644
index 0000000..4f5ce84
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Reading.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Server.ico b/irc_mod/Icons/Angeli-Ka/Server.ico
new file mode 100644
index 0000000..ae10690
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Server.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Show chanel.ico b/irc_mod/Icons/Angeli-Ka/Show chanel.ico
new file mode 100644
index 0000000..ebfc573
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Show chanel.ico
Binary files differ
diff --git a/irc_mod/Icons/Angeli-Ka/Warning.ico b/irc_mod/Icons/Angeli-Ka/Warning.ico
new file mode 100644
index 0000000..4bae248
--- /dev/null
+++ b/irc_mod/Icons/Angeli-Ka/Warning.ico
Binary files differ
diff --git a/irc_mod/Icons/add.ico b/irc_mod/Icons/add.ico
new file mode 100644
index 0000000..b61d733
--- /dev/null
+++ b/irc_mod/Icons/add.ico
Binary files differ
diff --git a/irc_mod/Icons/avatar.ico b/irc_mod/Icons/avatar.ico
new file mode 100644
index 0000000..eaf8c25
--- /dev/null
+++ b/irc_mod/Icons/avatar.ico
Binary files differ
diff --git a/irc_mod/Icons/avatar_old.ico b/irc_mod/Icons/avatar_old.ico
new file mode 100644
index 0000000..cc7fe7b
--- /dev/null
+++ b/irc_mod/Icons/avatar_old.ico
Binary files differ
diff --git a/irc_mod/Icons/block.ico b/irc_mod/Icons/block.ico
new file mode 100644
index 0000000..bdc022e
--- /dev/null
+++ b/irc_mod/Icons/block.ico
Binary files differ
diff --git a/irc_mod/Icons/dcc.ico b/irc_mod/Icons/dcc.ico
new file mode 100644
index 0000000..4668d95
--- /dev/null
+++ b/irc_mod/Icons/dcc.ico
Binary files differ
diff --git a/irc_mod/Icons/delete.ico b/irc_mod/Icons/delete.ico
new file mode 100644
index 0000000..a2134ca
--- /dev/null
+++ b/irc_mod/Icons/delete.ico
Binary files differ
diff --git a/irc_mod/Icons/error.ico b/irc_mod/Icons/error.ico
new file mode 100644
index 0000000..8c2d8e8
--- /dev/null
+++ b/irc_mod/Icons/error.ico
Binary files differ
diff --git a/irc_mod/Icons/fatal.ico b/irc_mod/Icons/fatal.ico
new file mode 100644
index 0000000..5f6b307
--- /dev/null
+++ b/irc_mod/Icons/fatal.ico
Binary files differ
diff --git a/irc_mod/Icons/go.ico b/irc_mod/Icons/go.ico
new file mode 100644
index 0000000..8a58d47
--- /dev/null
+++ b/irc_mod/Icons/go.ico
Binary files differ
diff --git a/irc_mod/Icons/help.ico b/irc_mod/Icons/help.ico
new file mode 100644
index 0000000..bbed7c9
--- /dev/null
+++ b/irc_mod/Icons/help.ico
Binary files differ
diff --git a/irc_mod/Icons/information.ico b/irc_mod/Icons/information.ico
new file mode 100644
index 0000000..d6a8c50
--- /dev/null
+++ b/irc_mod/Icons/information.ico
Binary files differ
diff --git a/irc_mod/Icons/irc.ico b/irc_mod/Icons/irc.ico
new file mode 100644
index 0000000..acbbcba
--- /dev/null
+++ b/irc_mod/Icons/irc.ico
Binary files differ
diff --git a/irc_mod/Icons/list.ico b/irc_mod/Icons/list.ico
new file mode 100644
index 0000000..046e7dc
--- /dev/null
+++ b/irc_mod/Icons/list.ico
Binary files differ
diff --git a/irc_mod/Icons/manager.ico b/irc_mod/Icons/manager.ico
new file mode 100644
index 0000000..e4f6233
--- /dev/null
+++ b/irc_mod/Icons/manager.ico
Binary files differ
diff --git a/irc_mod/Icons/part.ico b/irc_mod/Icons/part.ico
new file mode 100644
index 0000000..4cd783a
--- /dev/null
+++ b/irc_mod/Icons/part.ico
Binary files differ
diff --git a/irc_mod/Icons/quick.ico b/irc_mod/Icons/quick.ico
new file mode 100644
index 0000000..046544c
--- /dev/null
+++ b/irc_mod/Icons/quick.ico
Binary files differ
diff --git a/irc_mod/Icons/rename.ico b/irc_mod/Icons/rename.ico
new file mode 100644
index 0000000..5bffc74
--- /dev/null
+++ b/irc_mod/Icons/rename.ico
Binary files differ
diff --git a/irc_mod/Icons/server.ico b/irc_mod/Icons/server.ico
new file mode 100644
index 0000000..e9db131
--- /dev/null
+++ b/irc_mod/Icons/server.ico
Binary files differ
diff --git a/irc_mod/Icons/show.ico b/irc_mod/Icons/show.ico
new file mode 100644
index 0000000..e883fcb
--- /dev/null
+++ b/irc_mod/Icons/show.ico
Binary files differ
diff --git a/irc_mod/Icons/warning.ico b/irc_mod/Icons/warning.ico
new file mode 100644
index 0000000..9080ac7
--- /dev/null
+++ b/irc_mod/Icons/warning.ico
Binary files differ
diff --git a/irc_mod/Icons/world.ico b/irc_mod/Icons/world.ico
new file mode 100644
index 0000000..1ae508a
--- /dev/null
+++ b/irc_mod/Icons/world.ico
Binary files differ
diff --git a/irc_mod/Icons/world_old.ico b/irc_mod/Icons/world_old.ico
new file mode 100644
index 0000000..2a86c3f
--- /dev/null
+++ b/irc_mod/Icons/world_old.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus01.ico b/irc_mod/Icons/xstatus01.ico
new file mode 100644
index 0000000..b29cfd3
--- /dev/null
+++ b/irc_mod/Icons/xstatus01.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus02.ico b/irc_mod/Icons/xstatus02.ico
new file mode 100644
index 0000000..b43efbd
--- /dev/null
+++ b/irc_mod/Icons/xstatus02.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus03.ico b/irc_mod/Icons/xstatus03.ico
new file mode 100644
index 0000000..819b070
--- /dev/null
+++ b/irc_mod/Icons/xstatus03.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus04.ico b/irc_mod/Icons/xstatus04.ico
new file mode 100644
index 0000000..946de46
--- /dev/null
+++ b/irc_mod/Icons/xstatus04.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus05.ico b/irc_mod/Icons/xstatus05.ico
new file mode 100644
index 0000000..762e104
--- /dev/null
+++ b/irc_mod/Icons/xstatus05.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus06.ico b/irc_mod/Icons/xstatus06.ico
new file mode 100644
index 0000000..d733952
--- /dev/null
+++ b/irc_mod/Icons/xstatus06.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus07.ico b/irc_mod/Icons/xstatus07.ico
new file mode 100644
index 0000000..801d231
--- /dev/null
+++ b/irc_mod/Icons/xstatus07.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus08.ico b/irc_mod/Icons/xstatus08.ico
new file mode 100644
index 0000000..68051e5
--- /dev/null
+++ b/irc_mod/Icons/xstatus08.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus09.ico b/irc_mod/Icons/xstatus09.ico
new file mode 100644
index 0000000..07cebb4
--- /dev/null
+++ b/irc_mod/Icons/xstatus09.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus10.ico b/irc_mod/Icons/xstatus10.ico
new file mode 100644
index 0000000..0c99c1c
--- /dev/null
+++ b/irc_mod/Icons/xstatus10.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus11.ico b/irc_mod/Icons/xstatus11.ico
new file mode 100644
index 0000000..311c165
--- /dev/null
+++ b/irc_mod/Icons/xstatus11.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus12.ico b/irc_mod/Icons/xstatus12.ico
new file mode 100644
index 0000000..42adff4
--- /dev/null
+++ b/irc_mod/Icons/xstatus12.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus13.ico b/irc_mod/Icons/xstatus13.ico
new file mode 100644
index 0000000..05c5f67
--- /dev/null
+++ b/irc_mod/Icons/xstatus13.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus14.ico b/irc_mod/Icons/xstatus14.ico
new file mode 100644
index 0000000..4d98556
--- /dev/null
+++ b/irc_mod/Icons/xstatus14.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus15.ico b/irc_mod/Icons/xstatus15.ico
new file mode 100644
index 0000000..ef8040b
--- /dev/null
+++ b/irc_mod/Icons/xstatus15.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus16.ico b/irc_mod/Icons/xstatus16.ico
new file mode 100644
index 0000000..dd0a602
--- /dev/null
+++ b/irc_mod/Icons/xstatus16.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus17.ico b/irc_mod/Icons/xstatus17.ico
new file mode 100644
index 0000000..2d7be75
--- /dev/null
+++ b/irc_mod/Icons/xstatus17.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus18.ico b/irc_mod/Icons/xstatus18.ico
new file mode 100644
index 0000000..b3d6dd1
--- /dev/null
+++ b/irc_mod/Icons/xstatus18.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus19.ico b/irc_mod/Icons/xstatus19.ico
new file mode 100644
index 0000000..db4d011
--- /dev/null
+++ b/irc_mod/Icons/xstatus19.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus20.ico b/irc_mod/Icons/xstatus20.ico
new file mode 100644
index 0000000..fd3ef57
--- /dev/null
+++ b/irc_mod/Icons/xstatus20.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus21.ico b/irc_mod/Icons/xstatus21.ico
new file mode 100644
index 0000000..2704aa7
--- /dev/null
+++ b/irc_mod/Icons/xstatus21.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus22.ico b/irc_mod/Icons/xstatus22.ico
new file mode 100644
index 0000000..96e7739
--- /dev/null
+++ b/irc_mod/Icons/xstatus22.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus23.ico b/irc_mod/Icons/xstatus23.ico
new file mode 100644
index 0000000..8a2ad77
--- /dev/null
+++ b/irc_mod/Icons/xstatus23.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus24.ico b/irc_mod/Icons/xstatus24.ico
new file mode 100644
index 0000000..8a01165
--- /dev/null
+++ b/irc_mod/Icons/xstatus24.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus25.ico b/irc_mod/Icons/xstatus25.ico
new file mode 100644
index 0000000..8e6d3f9
--- /dev/null
+++ b/irc_mod/Icons/xstatus25.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus26.ico b/irc_mod/Icons/xstatus26.ico
new file mode 100644
index 0000000..fe7114d
--- /dev/null
+++ b/irc_mod/Icons/xstatus26.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus27.ico b/irc_mod/Icons/xstatus27.ico
new file mode 100644
index 0000000..6a84272
--- /dev/null
+++ b/irc_mod/Icons/xstatus27.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus28.ico b/irc_mod/Icons/xstatus28.ico
new file mode 100644
index 0000000..d78aadc
--- /dev/null
+++ b/irc_mod/Icons/xstatus28.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus29.ico b/irc_mod/Icons/xstatus29.ico
new file mode 100644
index 0000000..4f2739c
--- /dev/null
+++ b/irc_mod/Icons/xstatus29.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus30.ico b/irc_mod/Icons/xstatus30.ico
new file mode 100644
index 0000000..fe31759
--- /dev/null
+++ b/irc_mod/Icons/xstatus30.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus31.ico b/irc_mod/Icons/xstatus31.ico
new file mode 100644
index 0000000..4f5ce84
--- /dev/null
+++ b/irc_mod/Icons/xstatus31.ico
Binary files differ
diff --git a/irc_mod/Icons/xstatus32.ico b/irc_mod/Icons/xstatus32.ico
new file mode 100644
index 0000000..421856a
--- /dev/null
+++ b/irc_mod/Icons/xstatus32.ico
Binary files differ
diff --git a/irc_mod/avatar.cpp b/irc_mod/avatar.cpp
new file mode 100644
index 0000000..a78297f
--- /dev/null
+++ b/irc_mod/avatar.cpp
@@ -0,0 +1,273 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+
+extern char * IRCPROTONAME;
+
+void GetFullAvatarFileName(int dwUin, char* szUid, int dwFormat, char* pszDest, int cbLen)
+{
+ GetAvatarFileName(dwUin, szUid, pszDest, cbLen);
+ AddAvatarExt(dwFormat, pszDest);
+}
+
+void GetAvatarFileName(int dwUin, char* szUid, char* pszDest, int cbLen)
+{
+ int tPathLen;
+
+ CallService(MS_DB_GETPROFILEPATH, cbLen, (LPARAM)pszDest);
+
+ tPathLen = strlennull(pszDest);
+ tPathLen += null_snprintf(pszDest + tPathLen, MAX_PATH-tPathLen, "\\%s\\", IRCPROTONAME);
+ #ifdef _UNICODE
+ CreateDirectory((LPCWSTR)pszDest, NULL);
+ #else
+ CreateDirectory(pszDest, NULL);
+ #endif
+
+ if (dwUin != 0)
+ {
+ ltoa(dwUin, pszDest + tPathLen, 10);
+ }
+ else if (szUid)
+ {
+ strcpy(pszDest + tPathLen, szUid);
+ }
+ else
+ {
+ char szBuf[MAX_PATH];
+
+ if (CallService(MS_DB_GETPROFILENAME, 250 - tPathLen, (LPARAM)szBuf))
+ strcpy(pszDest + tPathLen, "avatar" );
+ else
+ {
+ char* szLastDot = strstr(szBuf, ".");
+ if (szLastDot) while (strstr(szLastDot+1, ".")) szLastDot = strstr(szLastDot+1, ".");
+ if (szLastDot) szLastDot[0] = '\0';
+ strcpy(pszDest + tPathLen, szBuf);
+ strcat(pszDest + tPathLen, "_avt");
+ }
+ }
+}
+
+void AddAvatarExt(int dwFormat, char* pszDest)
+{
+ if (dwFormat == PA_FORMAT_JPEG)
+ strcat(pszDest, ".jpg");
+ else if (dwFormat == PA_FORMAT_GIF)
+ strcat(pszDest, ".gif");
+ else if (dwFormat == PA_FORMAT_PNG)
+ strcat(pszDest, ".png");
+ else if (dwFormat == PA_FORMAT_BMP)
+ strcat(pszDest, ".bmp");
+ else if (dwFormat == PA_FORMAT_XML)
+ strcat(pszDest, ".xml");
+ else
+ strcat(pszDest, ".dat");
+}
+
+int DetectAvatarFormatBuffer(char* pBuffer)
+{
+ if (!strncmp(pBuffer, "%PNG", 4))
+ {
+ return PA_FORMAT_PNG;
+ }
+ if (!strncmp(pBuffer, "GIF8", 4))
+ {
+ return PA_FORMAT_GIF;
+ }
+ if (!strnicmp(pBuffer, "<?xml", 5))
+ {
+ return PA_FORMAT_XML;
+ }
+ if ((((DWORD*)pBuffer)[0] == 0xE0FFD8FFul) || (((DWORD*)pBuffer)[0] == 0xE1FFD8FFul))
+ {
+ return PA_FORMAT_JPEG;
+ }
+ if (!strncmp(pBuffer, "BM", 2))
+ {
+ return PA_FORMAT_BMP;
+ }
+ return PA_FORMAT_UNKNOWN;
+}
+
+int DetectAvatarFormat(char* szFile)
+{
+ char pBuf[32];
+
+ int src = _open(szFile, _O_BINARY | _O_RDONLY);
+ _read(src, pBuf, 32);
+ _close(src);
+
+ return DetectAvatarFormatBuffer(pBuf);
+}
+
+int IsAvatarSaved(HANDLE hContact, char* pHash)
+{
+ DBVARIANT dbvSaved = {0};
+
+ if (!IRCGetContactSetting(hContact, "AvatarSaved", &dbvSaved))
+ {
+ if ((dbvSaved.cpbVal != 0x14) || memcmp(dbvSaved.pbVal, pHash, 0x14))
+ { // the hashes is different
+ IRCFreeVariant(&dbvSaved);
+
+ return 2;
+ }
+ IRCFreeVariant(&dbvSaved);
+
+ return 0; // hash is there and is the same - Success
+ }
+ return 1; // saved Avatar hash is missing
+}
+
+// request avatar data from server
+int GetAvatarData(HANDLE hContact, DWORD dwUin, char* szUid, char* hash, unsigned int hashlen, char* file)
+{
+/*
+ avatarthreadstartinfo* atsi;
+
+ atsi = currentAvatarThread; // we take avatar thread - horrible, but realiable
+ if (AvatarsReady && !atsi->paused) // check if we are ready
+
+ {
+ icq_packet packet;
+ BYTE nUinLen;
+ DWORD dwCookie;
+ avatarcookie* ack;
+ int i;
+ DWORD dwNow = GetTickCount();
+
+ EnterCriticalSection(&cookieMutex); // reused...
+ for(i = 0; i < atsi->runCount;)
+ { // look for timeouted requests
+ if (atsi->runTime[i] < dwNow)
+ { // found outdated, remove
+ atsi->runContact[i] = atsi->runContact[atsi->runCount - 1];
+ atsi->runTime[i] = atsi->runTime[atsi->runCount - 1];
+ atsi->runCount--;
+ }
+ else
+ i++;
+ }
+
+ for(i = 0; i < atsi->runCount; i++)
+ {
+ if (atsi->runContact[i] == hContact)
+ {
+ LeaveCriticalSection(&cookieMutex);
+ NetLog_Server("Ignoring duplicate get %d avatar request.", dwUin);
+
+ return 0;
+ }
+ }
+
+ if (atsi->runCount < 4)
+ { // 4 concurent requests at most
+ atsi->runContact[atsi->runCount] = hContact;
+ atsi->runTime[atsi->runCount] = GetTickCount() + 30000; // 30sec to complete request
+ atsi->runCount++;
+ LeaveCriticalSection(&cookieMutex);
+
+ nUinLen = getUIDLen(dwUin, szUid);
+
+ ack = (avatarcookie*)SAFE_MALLOC(sizeof(avatarcookie));
+ if (!ack) return 0; // out of memory, go away
+ ack->dwUin = 1; //dwUin; // I should be damned for this - only to identify get request
+ ack->hContact = hContact;
+ ack->hash = (char*)SAFE_MALLOC(hashlen);
+ memcpy(ack->hash, hash, hashlen); // copy the data
+ ack->hashlen = hashlen;
+ ack->szFile = null_strdup(file); // we duplicate the string
+ dwCookie = AllocateCookie(CKT_AVATAR, ICQ_AVATAR_GET_REQUEST, dwUin, ack);
+
+ serverPacketInit(&packet, (WORD)(12 + nUinLen + hashlen));
+ packFNACHeaderFull(&packet, ICQ_AVATAR_FAMILY, ICQ_AVATAR_GET_REQUEST, 0, dwCookie);
+ packUID(&packet, dwUin, szUid);
+ packByte(&packet, 1); // unknown, probably type of request: 1 = get icon :)
+ packBuffer(&packet, hash, (unsigned short)hashlen);
+
+ if (sendAvatarPacket(&packet, atsi))
+ {
+ NetLog_Server("Request to get %d avatar image sent.", dwUin);
+
+ return dwCookie;
+ }
+ FreeCookie(dwCookie); // sending failed, free resources
+ SAFE_FREE(&ack->szFile);
+ SAFE_FREE(&ack->hash);
+ SAFE_FREE(&ack);
+ }
+ else
+ LeaveCriticalSection(&cookieMutex);
+ }
+ // we failed to send request, or avatar thread not ready
+ EnterCriticalSection(&cookieMutex); // wait for ready queue, reused cs
+ { // check if any request for this user is not already in the queue
+ avatarrequest* ar;
+ int bYet = 0;
+ ar = pendingRequests;
+ while (ar)
+ {
+ if (ar->hContact == hContact)
+ { // we found it, return error
+ LeaveCriticalSection(&cookieMutex);
+ NetLog_Server("Ignoring duplicate get %d avatar request.", dwUin);
+
+ if (!AvatarsReady && !pendingAvatarsStart)
+ {
+ icq_requestnewfamily(ICQ_AVATAR_FAMILY, StartAvatarThread);
+ pendingAvatarsStart = 1;
+ }
+ return 0;
+ }
+ ar = ar->pNext;
+ }
+ // add request to queue, processed after successful login
+ ar = CreateAvatarRequest(1); // get avatar
+ if (!ar)
+ { // out of memory, go away
+ LeaveCriticalSection(&cookieMutex);
+ return 0;
+ }
+ ar->dwUin = dwUin;
+ ar->szUid = null_strdup(szUid);
+ ar->hContact = hContact;
+ ar->hash = (char*)SAFE_MALLOC(hashlen);
+ memcpy(ar->hash, hash, hashlen); // copy the data
+ ar->hashlen = hashlen;
+ ar->szFile = null_strdup(file); // duplicate the string
+ ar->pNext = pendingRequests;
+ pendingRequests = ar;
+ }
+ LeaveCriticalSection(&cookieMutex);
+
+ NetLog_Server("Request to get %d avatar image added to queue.", dwUin);
+
+ if (!AvatarsReady && !pendingAvatarsStart)
+ {
+ icq_requestnewfamily(0x10, StartAvatarThread);
+ pendingAvatarsStart = 1;
+ }
+
+ return -1; // we added to queue
+*/
+ return 0;
+} \ No newline at end of file
diff --git a/irc_mod/avatar.h b/irc_mod/avatar.h
new file mode 100644
index 0000000..4f9a21d
--- /dev/null
+++ b/irc_mod/avatar.h
@@ -0,0 +1,32 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define _O_TEXT 0x4000 /* file mode is text (translated) */
+#define _O_BINARY 0x8000 /* file mode is binary (untranslated) */
+
+void GetFullAvatarFileName(int dwUin, char* szUid, int dwFormat, char* pszDest, int cbLen);
+void GetAvatarFileName(int dwUin, char* szUid, char* pszDest, int cbLen);
+void AddAvatarExt(int dwFormat, char* pszDest);
+
+int DetectAvatarFormat(char* szFile);
+
+int IsAvatarSaved(HANDLE hContact, char* pHash);
+
+int GetAvatarData(HANDLE hContact, DWORD dwUin, char* szUid, char* hash, unsigned int hashlen, char* file); \ No newline at end of file
diff --git a/irc_mod/clist.cpp b/irc_mod/clist.cpp
new file mode 100644
index 0000000..13522f8
--- /dev/null
+++ b/irc_mod/clist.cpp
@@ -0,0 +1,305 @@
+
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+
+extern PREFERENCES *prefs;
+extern char * IRCPROTONAME;
+
+
+BOOL CList_AddDCCChat(String name, String hostmask, unsigned long adr, int port)
+{
+ CLISTEVENT cle = {0};
+ HANDLE hContact;
+ HANDLE hc;
+ char szNick[256];
+ char szService[256];
+ bool bFlag = false;
+
+ CONTACT usertemp ={(char *)name.c_str(), NULL, NULL, false, false, true};
+ hc = CList_FindContact(&usertemp);
+ if(hc && DBGetContactSettingByte(hc,"CList", "NotOnList", 0) == 0
+ && DBGetContactSettingByte(hc,"CList", "Hidden", 0) == 0)
+ {
+ bFlag = true;
+ }
+
+ String contactname = name + DCCSTRING;
+
+ CONTACT user ={(char *)contactname.c_str(), NULL, NULL, false, false, true};
+ hContact = CList_AddContact(&user, false, false);
+ DBWriteContactSettingByte(hContact, IRCPROTONAME, "DCC", 1);
+
+ DCCINFO * pdci = new DCCINFO;
+ ZeroMemory(pdci, sizeof(DCCINFO));
+ pdci->sHostmask = hostmask;
+ pdci->hContact = hContact;
+ pdci->dwAdr = (DWORD) adr;
+ pdci->iPort = port;
+ pdci->iType = DCC_CHAT;
+ pdci->bSender = false;
+ pdci->sContactName = name;
+
+ if(prefs->DCCChatAccept == 3 || prefs->DCCChatAccept == 2 && bFlag)
+ {
+ CDccSession * dcc = new CDccSession(pdci);
+
+ CDccSession * olddcc = g_ircSession.FindDCCSession(hContact);
+ if (olddcc)
+ olddcc->Disconnect();
+
+ g_ircSession.AddDCCSession(hContact, dcc);
+
+ dcc->Connect();
+
+ }
+ else
+ {
+ cle.cbSize=sizeof(cle);
+ cle.hContact=(HANDLE)hContact;
+ cle.hDbEvent=(HANDLE)"dccchat";
+ cle.flags = 0;
+ cle.hIcon=LoadIconEx(IDI_DCC,"dcc",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ mir_snprintf(szService, sizeof(szService),"%s/DblClickEvent", IRCPROTONAME);
+ cle.pszService= szService ;
+ mir_snprintf(szNick, sizeof(szNick), Translate("CTCP chat request from %s"), name.c_str());
+ cle.pszTooltip= szNick;
+ cle.lParam = (LPARAM)pdci;
+
+ if(CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)"dccchat");
+ CallService(MS_CLIST_ADDEVENT,(WPARAM) hContact,(LPARAM) &cle);
+ }
+ return TRUE;
+}
+
+HANDLE CList_AddContact(struct CONTACT_TYPE * user, bool InList, bool SetOnline)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: CList AddContact\n");
+// DBGprintf( "Nick -> %s\n", user->name);
+// #endif
+
+ if (user->name == NULL)
+ return 0;
+ HANDLE hContact = CList_FindContact(user);
+ if (hContact )
+ {
+ if (InList)
+ DBDeleteContactSetting(hContact, "CList", "NotOnList");
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Nick", user->name);
+ DBDeleteContactSetting(hContact, "CList", "Hidden");
+ if (SetOnline && DBGetContactSettingWord(hContact, IRCPROTONAME, "Status", ID_STATUS_OFFLINE)== ID_STATUS_OFFLINE)
+ DBWriteContactSettingWord(hContact, IRCPROTONAME, "Status", ID_STATUS_ONLINE);
+ return hContact;
+ }
+
+ // here we create a new one since no one is to be found
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
+ if (hContact)
+ {
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) IRCPROTONAME);
+
+ if (InList)
+ DBDeleteContactSetting(hContact, "CList", "NotOnList");
+ else
+ DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
+ DBDeleteContactSetting(hContact, "CList", "Hidden");
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Nick", user->name);
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Default", user->name);
+ DBWriteContactSettingWord(hContact, IRCPROTONAME, "Status", SetOnline ? ID_STATUS_ONLINE:ID_STATUS_OFFLINE);
+ return hContact;
+ }
+ return false;
+}
+
+HANDLE CList_SetOffline(struct CONTACT_TYPE * user)
+{
+ DBVARIANT dbv;
+ HANDLE hContact = CList_FindContact(user);
+ if (hContact )
+ {
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "User", "");
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Host", "");
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Nick", dbv.pszVal);
+ DBWriteContactSettingWord(hContact, IRCPROTONAME, "Status", ID_STATUS_OFFLINE);
+
+ //Addon
+// DBDeleteContactSetting(hContact, IRCPROTONAME, "MirVer");
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "Version");
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "XStatus");
+ DBDeleteContactSetting(hContact, IRCPROTONAME, DBSETTING_XSTATUSID);
+ DBDeleteContactSetting(hContact, IRCPROTONAME, DBSETTING_XSTATUSNAME);
+ DBDeleteContactSetting(hContact, IRCPROTONAME, DBSETTING_XSTATUSMSG);
+
+ DBFreeVariant(&dbv);
+ return hContact;
+ }
+ }
+
+ return 0;
+}
+bool CList_SetAllOffline(BYTE ChatsToo)
+{
+ HANDLE hContact;
+ char *szProto;
+ DBVARIANT dbv;
+
+
+ g_ircSession.DisconnectAllDCCSessions(false);
+
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto != NULL && !lstrcmpi(szProto, IRCPROTONAME))
+ {
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0) == 0)
+ {
+ if (DBGetContactSettingByte(hContact, IRCPROTONAME, "DCC", 0) != 0)
+ {
+ if(ChatsToo)
+ DBWriteContactSettingWord(hContact, IRCPROTONAME, "Status", ID_STATUS_OFFLINE);
+ }
+ else if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Nick", dbv.pszVal);
+ DBWriteContactSettingWord(hContact, IRCPROTONAME, "Status", ID_STATUS_OFFLINE);
+
+ //Addon
+// DBDeleteContactSetting(hContact, IRCPROTONAME, "MirVer");
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "Version");
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "XStatus");
+ DBDeleteContactSetting(hContact, IRCPROTONAME, DBSETTING_XSTATUSID);
+ DBDeleteContactSetting(hContact, IRCPROTONAME, DBSETTING_XSTATUSNAME);
+ DBDeleteContactSetting(hContact, IRCPROTONAME, DBSETTING_XSTATUSMSG);
+
+ DBFreeVariant(&dbv);
+ }
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "IP");
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "User", "");
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Host", "");
+ }
+ }
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ return true;
+}
+
+HANDLE CList_FindContact (struct CONTACT_TYPE * user)
+{
+ if (!user || !user->name)
+ return 0;
+ char * lowercasename = new char [lstrlen(user->name)+2];
+ lstrcpyn(lowercasename, user->name, lstrlen(user->name)+1);
+ CharLower(lowercasename);
+ HANDLE hContact;
+ char *szProto;
+ DBVARIANT dbv1;
+ DBVARIANT dbv2;
+ DBVARIANT dbv3;
+ DBVARIANT dbv4;
+ DBVARIANT dbv5;
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto != NULL && !lstrcmpi(szProto, IRCPROTONAME))
+ {
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0) == 0)
+ {
+ HANDLE hContact_temp =NULL;
+ char * DBDefault = NULL;
+ char * DBNick = NULL;
+ char * DBWildcard = NULL;
+ char * DBUser = NULL;
+ char * DBHost = NULL;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv1) && dbv1.type == DBVT_ASCIIZ) DBDefault = dbv1.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Nick", &dbv2)&& dbv2.type == DBVT_ASCIIZ) DBNick = dbv2.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv3)&& dbv3.type == DBVT_ASCIIZ) DBWildcard = dbv3.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UUser", &dbv4)&& dbv4.type == DBVT_ASCIIZ) DBUser = dbv4.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UHost", &dbv5)&& dbv5.type == DBVT_ASCIIZ) DBHost = dbv5.pszVal;
+
+ if (DBWildcard)
+ CharLower(DBWildcard);
+ if (IsChannel(user->name)){
+ if(DBDefault && !lstrcmpi(DBDefault, user->name))
+ hContact_temp = (HANDLE)-1;
+ }
+ else if (user->ExactNick && DBNick && !lstrcmpi(DBNick, user->name))
+ hContact_temp = hContact;
+
+ else if (user->ExactOnly && DBDefault && !lstrcmpi(DBDefault, user->name))
+ hContact_temp = hContact;
+
+ else if (user->ExactWCOnly)
+ {
+ if(DBWildcard && !lstrcmpi(DBWildcard, lowercasename)
+ || (DBWildcard && !lstrcmpi(DBNick, lowercasename) && !WCCmp(DBWildcard, lowercasename) )
+ || (!DBWildcard && !lstrcmpi(DBNick, lowercasename)) )
+ {
+ hContact_temp = hContact;
+ }
+ }
+ else if(strchr(user->name, ' ') == 0)
+ {
+ if ((DBDefault && !lstrcmpi(DBDefault, user->name) || DBNick && !lstrcmpi(DBNick, user->name) || DBWildcard && WCCmp(DBWildcard, lowercasename))
+ && (WCCmp(DBUser, user->user) && WCCmp(DBHost, user->host)))
+ {
+ hContact_temp = hContact;
+ }
+ }
+
+ if (DBDefault)
+ DBFreeVariant(&dbv1);
+ if (DBNick)
+ DBFreeVariant(&dbv2);
+ if (DBWildcard)
+ DBFreeVariant(&dbv3);
+ if (DBUser)
+ DBFreeVariant(&dbv4);
+ if (DBHost)
+ DBFreeVariant(&dbv5);
+
+ if (hContact_temp != NULL) {
+ delete [] lowercasename;
+ if(hContact_temp != (HANDLE)-1)
+ return hContact_temp;
+ return 0;
+ }
+ }
+
+ }
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ delete [] lowercasename;
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/irc_mod/commandmonitor.cpp b/irc_mod/commandmonitor.cpp
new file mode 100644
index 0000000..3498c67
--- /dev/null
+++ b/irc_mod/commandmonitor.cpp
@@ -0,0 +1,3460 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// This file holds functions that are called upon receiving
+// certain commands from the server.
+
+#include "irc.h"
+#include <algorithm>
+
+using namespace irc;
+
+int ChannelNumber =0;
+String WhoReply = "";
+bool nickflag;
+bool bPerformDone = false;
+int NoOfChannels = 0;
+HWND whois_hWnd = NULL;
+HWND list_hWnd = NULL;
+HWND nick_hWnd = NULL;
+HWND manager_hWnd = NULL;
+UINT_PTR InitTimer;
+UINT_PTR IdentTimer;
+int ManualWhoisCount = 0;
+String sNamesList;
+String sUserModes;
+String sUserModePrefixes;
+String sChannelPrefixes;
+String sChannelModes;
+String WhoisAwayReply;
+String sTopic;
+String sTopicName;
+String NamesToWho = "";
+String ChannelsToWho = "";
+String NamesToUserhost = "";
+
+extern char * pszIgnoreFile;
+extern String StatusMessage;
+extern char * pszPerformFile;
+extern char mirandapath[MAX_PATH];
+extern HANDLE hMenuQuick ;
+extern HANDLE hMenuServer ;
+extern HANDLE hMenuJoin ;
+extern HANDLE hMenuNick ;
+extern HANDLE hMenuList ;
+extern int ManualWhoisCount;
+extern bool bTempDisableCheck ;
+extern bool bTempForceCheck ;
+extern int iTempCheckTime ;
+extern int OldStatus;
+extern int GlobalStatus;
+extern PREFERENCES *prefs;
+extern CIrcSession g_ircSession;
+extern char * IRCPROTONAME;
+extern UINT_PTR OnlineNotifTimer;
+extern UINT_PTR OnlineNotifTimer3;
+extern UINT_PTR KeepAliveTimer = 0;
+extern CRITICAL_SECTION m_resolve;
+extern GETEVENTFUNC pfnAddEvent;
+HWND IgnoreWndHwnd = NULL;
+
+extern HANDLE hNetlib;
+
+extern bool whois_popup;
+WHOIS * whois;
+
+static VOID CALLBACK IdentTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
+{
+ KillChatTimer(IdentTimer);
+ if(OldStatus == ID_STATUS_OFFLINE || OldStatus == ID_STATUS_CONNECTING)
+ return;
+
+ if (g_ircSession && prefs->IdentTimer)
+ g_ircSession.KillIdent();
+
+ return;
+}
+
+
+static VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
+{
+ KillChatTimer(InitTimer);
+ if(OldStatus == ID_STATUS_OFFLINE || OldStatus == ID_STATUS_CONNECTING)
+ return;
+
+ if (prefs->ForceVisible)
+ PostIrcMessage("/MODE %s -i", g_ircSession.GetInfo().sNick.c_str());
+
+ if (lstrlen(prefs->MyHost)== 0 && g_ircSession)
+ {
+ DoUserhostWithReason(2, ("S"+ g_ircSession.GetInfo().sNick).c_str(), true, "%s", g_ircSession.GetInfo().sNick.c_str());
+ }
+
+ return;
+}
+
+
+VOID CALLBACK KeepAliveTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
+{
+ if(!prefs->SendKeepAlive || (OldStatus == ID_STATUS_OFFLINE || OldStatus == ID_STATUS_CONNECTING))
+ {
+ KillChatTimer(KeepAliveTimer);
+
+ return;
+ }
+
+ char temp2[270];
+ if(g_ircSession.GetInfo().sServerName != "")
+ mir_snprintf(temp2, 269, "PING %s", g_ircSession.GetInfo().sServerName.c_str());
+ else
+ mir_snprintf(temp2, 269, "PING %u", time(0));
+
+ if (g_ircSession)
+ g_ircSession << CIrcMessage(temp2, false, false);
+
+ return;
+}
+VOID CALLBACK OnlineNotifTimerProc3(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
+{
+ if(!prefs->ChannelAwayNotification || OldStatus == ID_STATUS_OFFLINE || OldStatus == ID_STATUS_CONNECTING || (!prefs->AutoOnlineNotification && !bTempForceCheck) || bTempDisableCheck)
+ {
+ KillChatTimer(OnlineNotifTimer3);
+ ChannelsToWho == "";
+ return;
+ }
+
+ String name = GetWord((char *)ChannelsToWho.c_str(), 0);
+
+ if (name == "" )
+ {
+ ChannelsToWho = "";
+ int count = (int)CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)IRCPROTONAME);
+ for (int i = 0; i < count ; i++)
+ {
+ GC_INFO gci = {0};
+ gci.Flags = BYINDEX|NAME|TYPE|COUNT;
+ gci.iItem = i;
+ gci.pszModule = IRCPROTONAME;
+ if(!CallService(MS_GC_GETINFO, 0, (LPARAM)&gci) && gci.iType == GCW_CHATROOM)
+ {
+ if(gci.iCount <= prefs->OnlineNotificationLimit)
+ ChannelsToWho += (String)gci.pszName + " ";
+ }
+ }
+ }
+
+ if(ChannelsToWho == "") {
+ SetChatTimer(OnlineNotifTimer3, 60*1000, OnlineNotifTimerProc3);
+ return;
+ }
+ name = GetWord((char *)ChannelsToWho.c_str(), 0);
+ DoUserhostWithReason(2, "S" + name, true, "%s", name.c_str());
+ String temp = GetWordAddress(ChannelsToWho.c_str(), 1);
+ ChannelsToWho = temp;
+ if (iTempCheckTime)
+ SetChatTimer(OnlineNotifTimer3, iTempCheckTime*1000, OnlineNotifTimerProc3);
+ else
+ SetChatTimer(OnlineNotifTimer3, prefs->OnlineNotificationTime*1000, OnlineNotifTimerProc3);
+ return;
+
+
+}
+
+VOID CALLBACK OnlineNotifTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
+{
+
+ if(OldStatus == ID_STATUS_OFFLINE || OldStatus == ID_STATUS_CONNECTING || (!prefs->AutoOnlineNotification && !bTempForceCheck) || bTempDisableCheck)
+ {
+ KillChatTimer(OnlineNotifTimer);
+ NamesToWho == "";
+
+ return;
+ }
+
+ String name = GetWord((char *)NamesToWho.c_str(), 0);
+ String name2 = GetWord((char *)NamesToUserhost.c_str(), 0);
+
+ if (name == "" && name2 == "")
+ {
+ HANDLE hContact;
+ DBVARIANT dbv;
+ char *szProto;
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto != NULL && !lstrcmpi(szProto, IRCPROTONAME))
+ {
+ BYTE bRoom = DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0);
+ if(bRoom == 0)
+ {
+ BYTE bDCC = DBGetContactSettingByte(hContact, IRCPROTONAME, "DCC", 0);
+ BYTE bHidden = DBGetContactSettingByte(hContact,"CList", "Hidden", 0);
+ if(bDCC == 0 && bHidden == 0)
+ {
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ BYTE bAdvanced = DBGetContactSettingByte(hContact,IRCPROTONAME, "AdvancedMode", 0) ;
+
+
+ if (!bAdvanced)
+ {
+ DBFreeVariant(&dbv);
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ NamesToUserhost += (String)dbv.pszVal + " ";
+ DBFreeVariant(&dbv);
+ }
+ }
+ else
+ {
+ DBFreeVariant(&dbv);
+ DBVARIANT dbv2;
+
+ char * DBNick = NULL;
+ char * DBWildcard = NULL;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ) DBNick = dbv.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv2) && dbv2.type == DBVT_ASCIIZ) DBWildcard = dbv2.pszVal;
+
+ if (DBNick && (!DBWildcard ||!WCCmp(CharLower(DBWildcard), CharLower(DBNick))))
+ NamesToWho += (String)DBNick + " ";
+ else if(DBWildcard)
+ NamesToWho += (String)DBWildcard + " ";
+
+ if(DBNick)
+ DBFreeVariant(&dbv);
+
+ if(DBWildcard)
+ DBFreeVariant(&dbv2);
+ }
+ }
+ }
+ }
+ }
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ }
+
+ if (NamesToWho == "" && NamesToUserhost == "")
+ {
+ SetChatTimer(OnlineNotifTimer, 60*1000, OnlineNotifTimerProc);
+ return;
+ }
+
+ name = GetWord((char *)NamesToWho.c_str(), 0);
+ name2 = GetWord((char *)NamesToUserhost.c_str(), 0);
+ String temp;
+ if(name != "")
+ {
+ DoUserhostWithReason(2, "S" + name, true, "%s", name.c_str());
+ temp = GetWordAddress(NamesToWho.c_str(), 1);
+ NamesToWho = temp;
+ }
+
+ if(name2 != "")
+ {
+ String params;
+ for(int i = 0; i < 2; i++)
+ {
+ params = "";
+ for(int j = 0; j < 5; j++)
+ {
+ params += GetWord(NamesToUserhost.c_str(), i *5 + j) + " ";
+ }
+ if(params[0] != ' ')
+ DoUserhostWithReason(1, (String)"S" + params, true, params);
+ }
+ temp = GetWordAddress(NamesToUserhost.c_str(), 15);
+ NamesToUserhost = temp;
+ }
+
+ if (iTempCheckTime)
+ SetChatTimer(OnlineNotifTimer, iTempCheckTime*1000, OnlineNotifTimerProc);
+ else
+ SetChatTimer(OnlineNotifTimer, prefs->OnlineNotificationTime*1000, OnlineNotifTimerProc);
+
+ return;
+
+
+}
+
+
+static int AddOutgoingMessageToDB(HANDLE hContact, char *msg)
+{
+ if (OldStatus == ID_STATUS_OFFLINE || OldStatus == ID_STATUS_CONNECTING)
+ return 0;
+
+ String S = msg;
+ S = DoColorCodes((char*)S.c_str(), TRUE, FALSE);
+ DBEVENTINFO dbei;
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = IRCPROTONAME;
+ dbei.timestamp = (DWORD)time(NULL);
+ dbei.flags = DBEF_SENT;
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.cbBlob = strlen(S.c_str()) + 1;
+ dbei.pBlob = (PBYTE) S.c_str();
+ CallService(MS_DB_EVENT_ADD, (WPARAM) hContact, (LPARAM) & dbei);
+
+ return 1;
+
+}
+
+void __cdecl ResolveIPThread(LPVOID di)
+{
+ EnterCriticalSection(&m_resolve);
+
+ IPRESOLVE * ipr = (IPRESOLVE *) di;
+
+ if ( ipr != NULL && (ipr->iType == IP_AUTO && lstrlen(prefs->MyHost) == 0 || ipr->iType == IP_MANUAL) )
+ {
+ IN_ADDR in;
+
+ struct hostent* myhost = gethostbyname( ipr->pszAdr );
+
+ if( myhost)
+ {
+ memcpy( &in, myhost->h_addr, 4 );
+ if(ipr->iType == IP_AUTO)
+ mir_snprintf( prefs->MyHost, sizeof( prefs->MyHost ), "%s", inet_ntoa( in ));
+ else
+ mir_snprintf( prefs->MySpecifiedHostIP, sizeof( prefs->MySpecifiedHostIP ), "%s", inet_ntoa( in ));
+ }
+ }
+ delete ipr;
+ LeaveCriticalSection(&m_resolve);
+
+}
+
+DECLARE_IRC_MAP(CMyMonitor, CIrcDefaultMonitor)
+
+CMyMonitor::CMyMonitor() : irc::CIrcDefaultMonitor(g_ircSession)
+{
+ IRC_MAP_ENTRY(CMyMonitor, "JOIN", OnIrc_JOIN)
+ IRC_MAP_ENTRY(CMyMonitor, "QUIT", OnIrc_QUIT)
+ IRC_MAP_ENTRY(CMyMonitor, "KICK", OnIrc_KICK)
+ IRC_MAP_ENTRY(CMyMonitor, "MODE", OnIrc_MODE)
+ IRC_MAP_ENTRY(CMyMonitor, "NICK", OnIrc_NICK)
+ IRC_MAP_ENTRY(CMyMonitor, "PART", OnIrc_PART)
+ IRC_MAP_ENTRY(CMyMonitor, "PRIVMSG", OnIrc_PRIVMSG)
+ IRC_MAP_ENTRY(CMyMonitor, "TOPIC", OnIrc_TOPIC)
+ IRC_MAP_ENTRY(CMyMonitor, "NOTICE", OnIrc_NOTICE)
+ IRC_MAP_ENTRY(CMyMonitor, "PING", OnIrc_PINGPONG)
+ IRC_MAP_ENTRY(CMyMonitor, "PONG", OnIrc_PINGPONG)
+ IRC_MAP_ENTRY(CMyMonitor, "INVITE", OnIrc_INVITE)
+ IRC_MAP_ENTRY(CMyMonitor, "ERROR", OnIrc_ERROR)
+ IRC_MAP_ENTRY(CMyMonitor, "001", OnIrc_WELCOME)
+ IRC_MAP_ENTRY(CMyMonitor, "002", OnIrc_YOURHOST)
+ IRC_MAP_ENTRY(CMyMonitor, "005", OnIrc_SUPPORT)
+ IRC_MAP_ENTRY(CMyMonitor, "254", OnIrc_NOOFCHANNELS)
+ IRC_MAP_ENTRY(CMyMonitor, "263", OnIrc_TRYAGAIN)
+ IRC_MAP_ENTRY(CMyMonitor, "301", OnIrc_WHOIS_AWAY)
+ IRC_MAP_ENTRY(CMyMonitor, "302", OnIrc_USERHOST_REPLY)
+ IRC_MAP_ENTRY(CMyMonitor, "305", OnIrc_BACKFROMAWAY)
+ IRC_MAP_ENTRY(CMyMonitor, "306", OnIrc_SETAWAY)
+ IRC_MAP_ENTRY(CMyMonitor, "307", OnIrc_WHOIS_AUTH)
+ IRC_MAP_ENTRY(CMyMonitor, "310", OnIrc_WHOIS_OTHER)
+ IRC_MAP_ENTRY(CMyMonitor, "311", OnIrc_WHOIS_NAME)
+ IRC_MAP_ENTRY(CMyMonitor, "312", OnIrc_WHOIS_SERVER)
+ IRC_MAP_ENTRY(CMyMonitor, "313", OnIrc_WHOIS_OTHER)
+ IRC_MAP_ENTRY(CMyMonitor, "315", OnIrc_WHO_END)
+ IRC_MAP_ENTRY(CMyMonitor, "317", OnIrc_WHOIS_IDLE)
+ IRC_MAP_ENTRY(CMyMonitor, "318", OnIrc_WHOIS_END)
+ IRC_MAP_ENTRY(CMyMonitor, "319", OnIrc_WHOIS_CHANNELS)
+ IRC_MAP_ENTRY(CMyMonitor, "320", OnIrc_WHOIS_AUTH)
+ IRC_MAP_ENTRY(CMyMonitor, "321", OnIrc_LISTSTART)
+ IRC_MAP_ENTRY(CMyMonitor, "322", OnIrc_LIST)
+ IRC_MAP_ENTRY(CMyMonitor, "323", OnIrc_LISTEND)
+ IRC_MAP_ENTRY(CMyMonitor, "324", OnIrc_MODEQUERY)
+ IRC_MAP_ENTRY(CMyMonitor, "330", OnIrc_WHOIS_AUTH)
+ IRC_MAP_ENTRY(CMyMonitor, "332", OnIrc_INITIALTOPIC)
+ IRC_MAP_ENTRY(CMyMonitor, "333", OnIrc_INITIALTOPICNAME)
+ IRC_MAP_ENTRY(CMyMonitor, "352", OnIrc_WHO_REPLY)
+ IRC_MAP_ENTRY(CMyMonitor, "353", OnIrc_NAMES)
+ IRC_MAP_ENTRY(CMyMonitor, "366", OnIrc_ENDNAMES)
+ IRC_MAP_ENTRY(CMyMonitor, "367", OnIrc_BANLIST)
+ IRC_MAP_ENTRY(CMyMonitor, "368", OnIrc_BANLISTEND)
+ IRC_MAP_ENTRY(CMyMonitor, "346", OnIrc_BANLIST)
+ IRC_MAP_ENTRY(CMyMonitor, "347", OnIrc_BANLISTEND)
+ IRC_MAP_ENTRY(CMyMonitor, "348", OnIrc_BANLIST)
+ IRC_MAP_ENTRY(CMyMonitor, "349", OnIrc_BANLISTEND)
+ IRC_MAP_ENTRY(CMyMonitor, "371", OnIrc_WHOIS_OTHER)
+ IRC_MAP_ENTRY(CMyMonitor, "376", OnIrc_ENDMOTD)
+ IRC_MAP_ENTRY(CMyMonitor, "401", OnIrc_WHOIS_NO_USER)
+ IRC_MAP_ENTRY(CMyMonitor, "403", OnIrc_JOINERROR)
+ IRC_MAP_ENTRY(CMyMonitor, "416", OnIrc_WHOTOOLONG)
+ IRC_MAP_ENTRY(CMyMonitor, "421", OnIrc_UNKNOWN)
+ IRC_MAP_ENTRY(CMyMonitor, "422", OnIrc_ENDMOTD)
+ IRC_MAP_ENTRY(CMyMonitor, "433", OnIrc_NICK_ERR)
+ IRC_MAP_ENTRY(CMyMonitor, "471", OnIrc_JOINERROR)
+ IRC_MAP_ENTRY(CMyMonitor, "473", OnIrc_JOINERROR)
+ IRC_MAP_ENTRY(CMyMonitor, "474", OnIrc_JOINERROR)
+ IRC_MAP_ENTRY(CMyMonitor, "475", OnIrc_JOINERROR)
+}
+
+CMyMonitor::~CMyMonitor()
+{
+}
+
+bool CMyMonitor::OnIrc_WELCOME(const CIrcMessage* pmsg)
+{
+ CIrcDefaultMonitor::OnIrc_WELCOME(pmsg);
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() > 1)
+ {
+ static char host[1024];
+ int i = 0;
+ String word = GetWord(pmsg->parameters[1].c_str(), i);
+ while(word != "")
+ {
+ if(strchr(word.c_str(), '!') && strchr(word.c_str(), '@'))
+ {
+ lstrcpyn(host, word.c_str(), 1024);
+ char * p1 = strchr(host, '@');
+ if(p1)
+ {
+ p1++;
+ IPRESOLVE * ipr = new IPRESOLVE;
+ ipr->iType = IP_AUTO;
+ ipr->pszAdr = p1;
+ forkthread(ResolveIPThread, NULL, ipr);
+ }
+
+ }
+ i++;
+ word = GetWord(pmsg->parameters[1].c_str(), i);
+
+
+ }
+ }
+
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_WHOTOOLONG(const CIrcMessage* pmsg)
+{
+ String command = GetNextUserhostReason(2);
+ if(command[0] == 'U')
+ ShowMessage(pmsg);
+
+ return true;
+}
+bool CMyMonitor::OnIrc_BACKFROMAWAY(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming)
+ {
+ int Temp = OldStatus;
+ OldStatus = ID_STATUS_ONLINE;
+ ProtoBroadcastAck(IRCPROTONAME,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)Temp,ID_STATUS_ONLINE);
+
+ if (prefs->Perform)
+ DoPerform("Event: Available");
+ }
+
+ ShowMessage(pmsg);
+ return true;
+}
+
+bool CMyMonitor::OnIrc_SETAWAY(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming)
+ {
+ int Temp = OldStatus;
+ OldStatus = ID_STATUS_AWAY;
+ ProtoBroadcastAck(IRCPROTONAME,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)Temp,ID_STATUS_AWAY);
+
+ if (prefs->Perform)
+ switch (GlobalStatus)
+ {
+ case ID_STATUS_AWAY :
+ {
+ DoPerform( "Event: Away" );
+ } break;
+ case ID_STATUS_NA :
+ {
+ DoPerform("Event: N/A" );
+ } break;
+ case ID_STATUS_DND :
+ {
+ DoPerform("Event: DND" );
+ } break;
+ case ID_STATUS_OCCUPIED :
+ {
+ DoPerform("Event: Occupied" );
+ } break;
+
+ default :
+ {
+ GlobalStatus = ID_STATUS_AWAY;
+ DoPerform("Event: Away" );
+ } break;
+ }
+ }
+
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_JOIN(const CIrcMessage* pmsg)
+{
+ if (pmsg->parameters.size() > 0 && pmsg->m_bIncoming && pmsg->prefix.sNick != g_ircSession.GetInfo().sNick) {
+ String host = pmsg->prefix.sUser + "@" + pmsg->prefix.sHost;
+ DoEvent(GC_EVENT_JOIN, pmsg->parameters[0].c_str(), pmsg->prefix.sNick.c_str(), NULL, "Normal", host.c_str(), NULL, true, false);
+ }
+ else
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+bool CMyMonitor::OnIrc_QUIT(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming)
+ {
+ String host = pmsg->prefix.sUser + "@" + pmsg->prefix.sHost;
+ DoEvent(GC_EVENT_QUIT, NULL, pmsg->prefix.sNick.c_str(), pmsg->parameters.size()>0?pmsg->parameters[0].c_str():NULL, NULL, host.c_str(), NULL, true, false);
+ struct CONTACT_TYPE user ={(char *)pmsg->prefix.sNick.c_str(), (char *)pmsg->prefix.sUser.c_str(), (char *)pmsg->prefix.sHost.c_str(), false, false, false};
+ CList_SetOffline(&user);
+ if (pmsg->prefix.sNick == g_ircSession.GetInfo().sNick)
+ {
+ GCDEST gcd = {0};
+ GCEVENT gce = {0};
+
+ gce.cbSize = sizeof(GCEVENT);
+ gcd.pszID = NULL;
+ gcd.pszModule = IRCPROTONAME;
+ gcd.iType = GC_EVENT_CONTROL;
+ gce.pDest = &gcd;
+ CallChatEvent( SESSION_OFFLINE, (LPARAM)&gce);
+
+ }
+
+ }
+ else
+ ShowMessage(pmsg);
+
+
+
+ return true;
+}
+
+bool CMyMonitor::OnIrc_PART(const CIrcMessage* pmsg)
+{
+ if (pmsg->parameters.size() > 0 && pmsg->m_bIncoming)
+ {
+ String host = pmsg->prefix.sUser + "@" + pmsg->prefix.sHost;
+ DoEvent(GC_EVENT_PART, pmsg->parameters[0].c_str(), pmsg->prefix.sNick.c_str(), pmsg->parameters.size()>1?pmsg->parameters[1].c_str():NULL, NULL, host.c_str(), NULL, true, false);
+ if (pmsg->prefix.sNick == g_ircSession.GetInfo().sNick)
+ {
+ GCDEST gcd = {0};
+ GCEVENT gce = {0};
+
+ String S = MakeWndID(pmsg->parameters[0]);
+ gce.cbSize = sizeof(GCEVENT);
+ gcd.pszID = (char *)S.c_str();
+ gcd.pszModule = IRCPROTONAME;
+ gcd.iType = GC_EVENT_CONTROL;
+ gce.pDest = &gcd;
+ CallChatEvent( SESSION_OFFLINE, (LPARAM)&gce);
+
+ }
+ }
+ else
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+bool CMyMonitor::OnIrc_KICK(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming && pmsg->parameters.size() > 1)
+ DoEvent(GC_EVENT_KICK, pmsg->parameters[0].c_str(), pmsg->parameters[1].c_str(), pmsg->parameters.size()>2?pmsg->parameters[2].c_str():NULL, pmsg->prefix.sNick.c_str(), NULL, NULL, true, false);
+ else
+ ShowMessage(pmsg);
+
+ if (pmsg->parameters[1] == g_ircSession.GetInfo().sNick)
+ {
+ GCDEST gcd = {0};
+ GCEVENT gce = {0};
+
+ String S = MakeWndID(pmsg->parameters[0]);
+ gce.cbSize = sizeof(GCEVENT);
+ gcd.pszID = (char *)S.c_str();
+ gcd.pszModule = IRCPROTONAME;
+ gcd.iType = GC_EVENT_CONTROL;
+ gce.pDest = &gcd;
+ CallChatEvent( SESSION_OFFLINE, (LPARAM)&gce);
+
+ if (prefs->RejoinIfKicked) {
+ CHANNELINFO* wi = (CHANNELINFO *)DoEvent(GC_EVENT_GETITEMDATA, pmsg->parameters[0].c_str(), NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, 0);
+ if (wi && wi->pszPassword)
+ PostIrcMessage("/JOIN %s %s", (char *)pmsg->parameters[0].c_str(), wi->pszPassword);
+ else
+ PostIrcMessage("/JOIN %s", (char *)pmsg->parameters[0].c_str());
+ }
+ }
+
+
+ return true;
+}
+bool CMyMonitor::OnIrc_MODEQUERY(const CIrcMessage* pmsg)
+{
+ if (pmsg->parameters.size() > 2 && pmsg->m_bIncoming && IsChannel(pmsg->parameters[1]))
+ {
+
+ String sPassword = "";
+ String sLimit = "";
+ bool bAdd =false;
+ int iParametercount = 3;
+ char* p1 = (char*)pmsg->parameters[2].c_str();
+
+ while (*p1 != '\0')
+ {
+ if (*p1 == '+')
+ bAdd = true;
+ if (*p1 == '-')
+ bAdd = false;
+ if (*p1 == 'l' && bAdd)
+ {
+ if ((int)pmsg->parameters.size() > iParametercount)
+ sLimit = pmsg->parameters[iParametercount];
+ iParametercount++;
+ }
+ if (*p1 == 'k' && bAdd)
+ {
+ if ((int)pmsg->parameters.size() > iParametercount)
+ sPassword = pmsg->parameters[iParametercount];
+ iParametercount++;
+ }
+
+ p1++;
+ }
+ AddWindowItemData(pmsg->parameters[1].c_str(), sLimit != ""?sLimit.c_str():0, pmsg->parameters[2].c_str(), sPassword != ""?sPassword.c_str():0, 0);
+
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_MODE(const CIrcMessage* pmsg)
+{
+ bool flag = false;
+ bool bContainsValidModes = false;
+ String sModes = "";
+ String sParams = "";
+
+ if (pmsg->parameters.size() > 1 && pmsg->m_bIncoming)
+ {
+
+ if(IsChannel(pmsg->parameters[0]))
+ {
+ bool bAdd =false;
+ int iParametercount = 2;
+ char* p1 = (char*)pmsg->parameters[1].c_str();
+
+ while (*p1 != '\0')
+ {
+ if (*p1 == '+')
+ {
+ bAdd = true;
+ sModes += "+";
+ }
+ if (*p1 == '-')
+ {
+ bAdd = false;
+ sModes += "-";
+ }
+ if (*p1 == 'l' && bAdd && iParametercount < (int)pmsg->parameters.size())
+ {
+ bContainsValidModes = true;
+ sModes += "l";
+ sParams += " " + pmsg->parameters[iParametercount];
+ iParametercount++;
+ }
+ if (*p1 == 'b' || *p1 == 'k' && iParametercount < (int)pmsg->parameters.size())
+ {
+ bContainsValidModes = true;
+ sModes += *p1;
+ sParams += " " + pmsg->parameters[iParametercount];
+ iParametercount++;
+ }
+
+ if(strchr(sUserModes.c_str(), *p1))
+ {
+ String sStatus = ModeToStatus(*p1);
+ if((int)pmsg->parameters.size() > iParametercount)
+ {
+ DoEvent(bAdd?GC_EVENT_ADDSTATUS:GC_EVENT_REMOVESTATUS, pmsg->parameters[0].c_str(), pmsg->parameters[iParametercount].c_str(), pmsg->prefix.sNick.c_str(), sStatus.c_str(), NULL, NULL, prefs->OldStyleModes?false:true, false);
+ iParametercount++;
+ }
+ }
+ else if (*p1 != 'b' && *p1 != ' ' && *p1 != '+' && *p1 != '-')
+ {
+ bContainsValidModes = true;
+ if(*p1 != 'l' && *p1 != 'k')
+ sModes += *p1;
+ flag = true;
+ }
+
+ p1++;
+ }
+
+ if(prefs->OldStyleModes)
+ {
+ String sMessage;
+ char temp[256]; *temp = '\0';
+ mir_snprintf(temp, 255, Translate( "%s sets mode %s" ), pmsg->prefix.sNick.c_str(), pmsg->parameters[1].c_str());
+ sMessage = temp;
+ for(int i=2; i < (int)pmsg->parameters.size(); i++)
+ {
+ sMessage = sMessage +" "+ pmsg->parameters[i];
+ }
+ DoEvent(GC_EVENT_INFORMATION, pmsg->parameters[0].c_str(), pmsg->prefix.sNick.c_str(), sMessage.c_str(), NULL, NULL, NULL, true, false);
+ }
+ else if(bContainsValidModes)
+ {
+ for(int i=iParametercount; i < (int)pmsg->parameters.size(); i++)
+ {
+ sParams += " "+ pmsg->parameters[i];
+ }
+
+
+ char temp[4000]; *temp = '\0';
+ mir_snprintf(temp, 3999, Translate( "%s sets mode %s%s" ), pmsg->prefix.sNick.c_str(), sModes.c_str(), sParams.c_str());
+ DoEvent(GC_EVENT_INFORMATION, pmsg->parameters[0].c_str(), pmsg->prefix.sNick.c_str(), temp, NULL, NULL, NULL, true, false);
+ }
+
+ if (flag)
+ PostIrcMessage("/MODE %s", pmsg->parameters[0].c_str());
+ }
+ else
+ {
+ String sMessage;
+ char temp[256]; *temp = '\0';
+ mir_snprintf(temp, 255, Translate( "%s sets mode %s" ), pmsg->prefix.sNick.c_str(), pmsg->parameters[1].c_str());
+ sMessage = temp;
+ for(int i=2; i < (int)pmsg->parameters.size(); i++)
+ {
+ sMessage = sMessage +" "+ pmsg->parameters[i];
+ }
+ DoEvent(GC_EVENT_INFORMATION, "Network Log", pmsg->prefix.sNick.c_str(), sMessage.c_str(), NULL, NULL, NULL, true, false);
+
+ }
+ }
+ else
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+bool CMyMonitor::OnIrc_NICK(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming && pmsg->parameters.size() > 0)
+ {
+ bool bIsMe = pmsg->prefix.sNick.c_str() == g_ircSession.GetInfo().sNick?true:false;
+ CIrcDefaultMonitor::OnIrc_NICK(pmsg);
+ String host = pmsg->prefix.sUser + "@" + pmsg->prefix.sHost;
+ DoEvent(GC_EVENT_NICK, NULL, pmsg->prefix.sNick.c_str(), pmsg->parameters[0].c_str(), NULL, host.c_str(), NULL, true, bIsMe);
+ DoEvent(GC_EVENT_CHUID, NULL, pmsg->prefix.sNick.c_str(), pmsg->parameters[0].c_str(), NULL, NULL, NULL, true, false);
+ struct CONTACT_TYPE user ={(char *)pmsg->prefix.sNick.c_str(), (char *)pmsg->prefix.sUser.c_str(), (char *)pmsg->prefix.sHost.c_str(), false, false, false};
+ HANDLE hContact = CList_FindContact(&user);
+ if (hContact)
+ {
+ if (DBGetContactSettingWord(hContact,IRCPROTONAME, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE)
+ DBWriteContactSettingWord(hContact, IRCPROTONAME, "Status", ID_STATUS_ONLINE);
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Nick", pmsg->parameters[0].c_str());
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "User", pmsg->prefix.sUser.c_str());
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Host", pmsg->prefix.sHost.c_str());
+ }
+ }
+ else
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+
+bool CMyMonitor::OnIrc_NOTICE(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: NOTICE\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value %d = %s\n", i, pmsg->parameters[i].c_str());
+// #endif
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() > 1)
+ {
+ if (IsCTCP(pmsg))
+ return true;
+
+ if(prefs->MemoServAuto && (strstr(pmsg->parameters[1].c_str(), "íîâîĺ ńîîáůĺíčĺ") || strstr(pmsg->parameters[1].c_str(), "âŕě ďđčřëî íîâîĺ ńîîáůĺíčĺ îň")))
+ {
+ HANDLE hContact = GetContactByName(pmsg->parameters[1].c_str());
+ if(prefs->PopupsEnabled)
+ ShowPopUpMsg(hContact, "MemoServ", ansi_to_utf8(pmsg->parameters[1].c_str()), LOG_NOTE);
+ PostIrcMessage("/MSG %s READ 1", prefs->MemoServName);
+ PostIrcMessage("/MSG %s DEL 1", prefs->MemoServName);
+// return true;
+ }
+
+ if(!prefs->Ignore || !IsIgnored(pmsg->prefix.sNick, pmsg->prefix.sUser, pmsg->prefix.sHost, 'n'))
+ {
+ String S;
+ String S2;
+ if(pmsg->prefix.sNick.length() > 0)
+ S = pmsg->prefix.sNick + " (" +m_session.GetInfo().sNetwork + ")";
+ else
+ S = m_session.GetInfo().sNetwork;
+
+ if(IsChannel(pmsg->parameters[0]))
+ {
+ S2 = pmsg->parameters[0].c_str();
+ }
+ else
+ {
+ String S3;
+ GC_INFO gci = {0};
+ gci.Flags = BYID|TYPE;
+ gci.pszModule = IRCPROTONAME;
+
+ S3 = GetWord(pmsg->parameters[1].c_str(), 0);
+
+ if(S3[0] == '[' && S3[1] == '#' && S3[S3.length()-1] == ']')
+ {
+ String Wnd;
+ S3.erase(S3.length()-1, 1);
+ S3.erase(0,1);
+ Wnd = MakeWndID(S3);
+ gci.pszID = (char *) Wnd.c_str();
+ if(!CallService(MS_GC_GETINFO, 0, (LPARAM)&gci) && gci.iType == GCW_CHATROOM)
+ S2 = GetWord(gci.pszID, 0);
+ else
+ S2 = "";
+ }
+ else
+ S2 = "";
+ }
+ DoEvent(GC_EVENT_NOTICE, S2 != "" ? S2.c_str() : NULL, S.c_str(), pmsg->parameters[1].c_str(), NULL, NULL, NULL, true, false);
+ }
+ }
+ else
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+bool CMyMonitor::OnIrc_YOURHOST(const CIrcMessage* pmsg)
+{
+ if(pmsg->m_bIncoming)
+ CIrcDefaultMonitor::OnIrc_YOURHOST(pmsg);
+
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+
+bool CMyMonitor::OnIrc_INVITE(const CIrcMessage* pmsg)
+{
+ if(pmsg->m_bIncoming && (prefs->Ignore && IsIgnored(pmsg->prefix.sNick, pmsg->prefix.sUser, pmsg->prefix.sHost, 'i')))
+ return true;
+
+ if(pmsg->m_bIncoming && prefs->JoinOnInvite && pmsg->parameters.size() >1 && lstrcmpi(pmsg->parameters[0].c_str(), m_session.GetInfo().sNick.c_str()) == 0)
+ PostIrcMessage( "/JOIN %s", pmsg->parameters[1].c_str());
+
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+
+bool CMyMonitor::OnIrc_PINGPONG(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming && pmsg->sCommand == "PING")
+ CIrcDefaultMonitor::OnIrc_PING(pmsg);
+
+ return true;
+}
+
+bool CMyMonitor::OnIrc_PRIVMSG(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: PRIVMSG\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ if (pmsg->parameters.size() > 1)
+ {
+ if (IsCTCP(pmsg))
+ return true;
+
+ String mess = pmsg->parameters[1];
+ bool bIsChannel = IsChannel(pmsg->parameters[0]);
+
+ if (pmsg->m_bIncoming &&!bIsChannel)
+ {
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+
+ mess = DoColorCodes((char*)mess.c_str(), TRUE, FALSE);
+ ccs.szProtoService = PSR_MESSAGE;
+
+ struct CONTACT_TYPE user ={(char *)pmsg->prefix.sNick.c_str(), (char *)pmsg->prefix.sUser.c_str(), (char *)pmsg->prefix.sHost.c_str(), false, false, false};
+
+ if (CallService(MS_IGNORE_ISIGNORED, NULL, IGNOREEVENT_MESSAGE))
+ {
+ if (!CList_FindContact(&user))
+ return true;
+ }
+
+ if((prefs->Ignore && IsIgnored(pmsg->prefix.sNick, pmsg->prefix.sUser, pmsg->prefix.sHost, 'q')))
+ {
+ HANDLE hContact = CList_FindContact(&user);
+ if (!hContact || (hContact && DBGetContactSettingByte(hContact,"CList", "Hidden", 0) == 1))
+ return true;
+ }
+
+ ccs.hContact = CList_AddContact(&user, false, true);
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM) & pre;
+ pre.flags = 0;
+ pre.timestamp = (DWORD)time(NULL);
+ pre.szMessage = (char *)mess.c_str();
+ pre.lParam = 0;
+ DBWriteContactSettingString(ccs.hContact, IRCPROTONAME, "User", pmsg->prefix.sUser.c_str());
+ DBWriteContactSettingString(ccs.hContact, IRCPROTONAME, "Host", pmsg->prefix.sHost.c_str());
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) & ccs);
+ return true;
+ }
+
+ if (bIsChannel)
+ {
+ if(!(pmsg->m_bIncoming && prefs->Ignore && IsIgnored(pmsg->prefix.sNick, pmsg->prefix.sUser, pmsg->prefix.sHost, 'm')))
+ {
+ if(!pmsg->m_bIncoming)
+ mess = ReplaceString(mess, "%%", "%");
+ DoEvent(GC_EVENT_MESSAGE, pmsg->parameters[0].c_str(), pmsg->m_bIncoming?pmsg->prefix.sNick.c_str():m_session.GetInfo().sNick.c_str(), mess.c_str(), NULL, NULL, NULL, true, pmsg->m_bIncoming?false:true);
+ }
+ return true;
+ }
+ }
+
+ ShowMessage(pmsg);
+
+ return true;
+
+}
+
+bool CMyMonitor::IsCTCP(const CIrcMessage* pmsg)
+{
+ // is it a ctcp command, i e is the first and last characer of a PRIVMSG or NOTICE text ASCII 1
+ if(pmsg->parameters[1].length() >3 && pmsg->parameters[1][0] == 1 && pmsg->parameters[1][pmsg->parameters[1].length()-1] == 1 )
+ {
+ // set mess to contain the ctcp command, excluding the leading and trailing ASCII 1
+ String mess = pmsg->parameters[1];
+ mess.erase(0,1);
+ mess.erase(mess.length()-1,1);
+
+ // exploit???
+ if(mess.find(1) != string::npos || mess.find("%newl") != string::npos )
+ {
+ char temp[4096];
+ mir_snprintf(temp, 4096, Translate("CTCP ERROR: Malformed CTCP command received from %s!%s@%s. Possible attempt to take control of your irc client registered"), pmsg->prefix.sNick.c_str(), pmsg->prefix.sUser.c_str(), pmsg->prefix.sHost.c_str());
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), temp, NULL, NULL, NULL, true, false);
+ return true;
+ }
+
+ // extract the type of ctcp command
+ String ocommand = GetWord(mess.c_str(), 0);
+ String command = GetWord(mess.c_str(), 0);
+ transform (command.begin(),command.end(), command.begin(), tolower);
+
+ // should it be ignored?
+ if(prefs->Ignore)
+ {
+ if(IsChannel(pmsg->parameters[0]))
+ {
+ if (command == "action" && IsIgnored(pmsg->prefix.sNick, pmsg->prefix.sUser, pmsg->prefix.sHost, 'm'))
+ return true;
+
+ }
+ else
+ {
+ if (command == "action")
+ {
+ if(IsIgnored(pmsg->prefix.sNick, pmsg->prefix.sUser, pmsg->prefix.sHost, 'q'))
+ return true;
+ }
+ else if (command == "dcc")
+ {
+ if( IsIgnored(pmsg->prefix.sNick, pmsg->prefix.sUser, pmsg->prefix.sHost, 'd'))
+ return true;
+ }
+ else if (IsIgnored(pmsg->prefix.sNick, pmsg->prefix.sUser, pmsg->prefix.sHost, 'c'))
+ return true;
+ }
+ }
+
+ if(pmsg->sCommand == "PRIVMSG")
+ {
+ // incoming ACTION
+ if (command == "action")
+ {
+ mess.erase(0,6);
+
+ if(IsChannel(pmsg->parameters[0]) )
+ {
+ if(mess.length() >1)
+ {
+ mess.erase(0,1);
+ if(!pmsg->m_bIncoming)
+ mess = ReplaceString(mess, "%%", "%");
+
+ DoEvent(GC_EVENT_ACTION, pmsg->parameters[0].c_str(), pmsg->m_bIncoming?pmsg->prefix.sNick.c_str():m_session.GetInfo().sNick.c_str(), mess.c_str(), NULL, NULL, NULL, true, pmsg->m_bIncoming?false:true);
+ }
+ }
+ else if (pmsg->m_bIncoming)
+ {
+ mess.insert(0, pmsg->prefix.sNick.c_str());
+ mess.insert(0, "* ");
+ mess.insert(mess.length(), " *");
+ CIrcMessage msg = *pmsg;
+ msg.parameters[1] = mess;
+ OnIrc_PRIVMSG(&msg);
+ }
+ }
+
+ // incoming FINGER
+ else if (pmsg->m_bIncoming && command == "finger")
+ {
+ PostIrcMessage("/NOTICE %s \001FINGER %s (%s)\001", pmsg->prefix.sNick.c_str(), prefs->Name, prefs->UserID);
+ char temp[300];
+ mir_snprintf(temp, sizeof(temp), Translate("CTCP FINGER requested by %s"), pmsg->prefix.sNick.c_str());
+ DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, temp, NULL, NULL, NULL, true, false);
+
+ }
+
+ // incoming VERSION
+ else if (pmsg->m_bIncoming && command == "version")
+ {
+ char szVer[260];
+ CallService(MS_SYSTEM_GETVERSIONTEXT, MAX_PATH, (LPARAM)szVer);
+ PostIrcMessage("/NOTICE %s \001VERSION Miranda IM %s (IRC v %s)\001", pmsg->prefix.sNick.c_str(), szVer, "%version");
+// char temp[300];
+// mir_snprintf(temp, sizeof(temp), Translate("CTCP VERSION requested by %s"), pmsg->prefix.sNick.c_str());
+// DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, temp, NULL, NULL, NULL, true, false);
+ }
+
+ // incoming SOURCE
+ else if (pmsg->m_bIncoming && command == "source")
+ {
+ PostIrcMessage("/NOTICE %s \001SOURCE http://miranda-im.org/ \001", pmsg->prefix.sNick.c_str());
+ char temp[300];
+ mir_snprintf(temp, sizeof(temp), Translate("CTCP SOURCE requested by %s"), pmsg->prefix.sNick.c_str());
+ DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, temp, NULL, NULL, NULL, true, false);
+ }
+
+ // incoming MODINFO
+ else if (pmsg->m_bIncoming && command == "modinfo")
+ {
+ PostIrcMessage("/NOTICE %s \001MODINFO %s\001", pmsg->prefix.sNick.c_str(), IRCGetContactSettingUtf(NULL, "ModInfo", "Miranda IRC modification"));
+// char temp[300];
+// mir_snprintf(temp, sizeof(temp), Translate("CTCP MODINFO requested by %s"), pmsg->prefix.sNick.c_str());
+// DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, temp, NULL, NULL, NULL, true, false);
+ }
+
+ // incoming MIRANDA
+ else if (pmsg->m_bIncoming && command == "miranda")
+ {
+ char szVer[260];
+ CallService(MS_SYSTEM_GETVERSIONTEXT, MAX_PATH, (LPARAM)szVer);
+ PostIrcMessage("/NOTICE %s \001MIRANDA Miranda IM %s\001", pmsg->prefix.sNick.c_str(), szVer);
+// char temp[300];
+// mir_snprintf(temp, sizeof(temp), Translate("CTCP MIRANDA requested by %s"), pmsg->prefix.sNick.c_str());
+// DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, temp, NULL, NULL, NULL, true, false);
+ }
+
+ // incoming XSTATUS
+ else if (pmsg->m_bIncoming && command == "xstatus")
+ {
+ handleXStatus(pmsg->prefix.sNick.c_str());
+ return true;
+ }
+
+ // incoming AVATAR
+ else if (pmsg->m_bIncoming && command == "avatar")
+ {
+ handleAvatarHash(pmsg->prefix.sNick.c_str());
+ }
+
+ // incoming AVATARDATA
+// else if (pmsg->m_bIncoming && command == "avatardata")
+// {
+// handleAvatarData(pmsg->prefix.sNick.c_str());
+// }
+
+ // incoming TYPING
+ else if (pmsg->m_bIncoming && command == "typingstart")
+ {
+ handleTypingNotification(pmsg->prefix.sNick.c_str(),MTN_BEGUN);
+ }
+ else if (pmsg->m_bIncoming && command == "typingstop")
+ {
+ handleTypingNotification(pmsg->prefix.sNick.c_str(),MTN_TYPED);
+ }
+
+ // incoming NUDGE
+ else if (pmsg->m_bIncoming && command == "nudge")
+ {
+ handleNudgeNotification(pmsg->prefix.sNick.c_str());
+ }
+
+ // incoming USERINFO
+ else if (pmsg->m_bIncoming && command == "userinfo")
+ {
+ PostIrcMessage("/NOTICE %s \001USERINFO %s\001", pmsg->prefix.sNick.c_str(), prefs->UserInfo);
+ char temp[300];
+ mir_snprintf(temp, sizeof(temp), Translate("CTCP USERINFO requested by %s") , pmsg->prefix.sNick.c_str());
+ DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, temp, NULL, NULL, NULL, true, false);
+ }
+
+ // incoming PING
+ else if (pmsg->m_bIncoming && command == "ping")
+ {
+ PostIrcMessage("/NOTICE %s \001%s\001", pmsg->prefix.sNick.c_str(), mess.c_str());
+ char temp[300];
+ mir_snprintf(temp, sizeof(temp), Translate("CTCP PING requested by %s"), pmsg->prefix.sNick.c_str());
+ DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, temp, NULL, NULL, NULL, true, false);
+ }
+
+ // incoming TIME
+ else if (pmsg->m_bIncoming && command == "time")
+ {
+ time_t tim;
+ tim = time(NULL);
+ char temp[300];
+ lstrcpyn(temp,ctime(&tim), 25);
+ PostIrcMessage("/NOTICE %s \001TIME %s\001", pmsg->prefix.sNick.c_str(), temp);
+ mir_snprintf(temp, sizeof(temp), Translate("CTCP TIME requested by %s"), pmsg->prefix.sNick.c_str());
+ DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, temp, NULL, NULL, NULL, true, false);
+ }
+
+ // incoming DCC request... lots of stuff happening here...
+ else if (pmsg->m_bIncoming && command == "dcc")
+ {
+ String type = GetWord(mess.c_str(), 1);
+ transform (type.begin(),type.end(), type.begin(), tolower);
+
+ // components of a dcc message
+ String sFile = "";
+ DWORD dwAdr = 0;
+ int iPort = 0;
+ DWORD dwSize = 0;
+ String sToken = "";
+
+ // 1. separate the dcc command into the correct pieces
+ if(type == "chat" || type == "send")
+ {
+ // if the filename is surrounded by quotes, do this
+ if(GetWord(mess.c_str(), 2)[0] == '\"')
+ {
+ int end = 0;
+ int begin = mess.find('\"', 0);
+ if(begin >= 0)
+ {
+ end = mess.find('\"', begin + 1);
+ if (end >= 0)
+ {
+ sFile = mess.substr(begin+1, end-begin-1);
+
+ begin = mess.find(' ', end);
+ if(begin >= 0)
+ {
+ String rest = mess.substr(begin, mess.length());
+ dwAdr = atoi(GetWord(rest.c_str(), 0).c_str());
+ iPort = atoi(GetWord(rest.c_str(), 1).c_str());
+ dwSize = atoi(GetWord(rest.c_str(), 2).c_str());
+ sToken = GetWord(rest.c_str(), 3);
+ }
+ }
+ }
+ }
+ else if (GetWord(mess.c_str(), type == "chat"?4:5) != "") // ... or try another method of separating the dcc command
+ {
+ int index = type == "chat"?4:5;
+ bool bFlag = false;
+
+ // look for the part of the ctcp command that contains adress, port and size
+ while (!bFlag && GetWord(mess.c_str(), index) != "")
+ {
+ String sTemp;
+
+ if(type == "chat")
+ sTemp = GetWord(mess.c_str(), index-1) + GetWord(mess.c_str(), index);
+ else
+ sTemp = GetWord(mess.c_str(), index-2) + GetWord(mess.c_str(), index-1) + GetWord(mess.c_str(), index);
+ // if all characters are number it indicates we have found the adress, port and size parameters
+ int ind = 0;
+
+ while (sTemp[ind] != '\0')
+ {
+ if(!isdigit(sTemp[ind]))
+ break;
+ ind++;
+ }
+ if(sTemp[ind] == '\0' && GetWord(mess.c_str(), index + ((type == "chat")?1:2)) == "")
+ bFlag = true;
+ index++;
+ }
+ if(bFlag)
+ {
+ char * p1 = strdup(GetWordAddress(mess.c_str(), 2));
+ char * p2 = GetWordAddress(p1, index-5);
+
+ if(type == "send")
+ {
+ if(p2 > p1)
+ {
+ p2--;
+ while( p2 != p1 && *p2 == ' ')
+ {
+ *p2 = '\0';
+ p2--;
+ }
+ sFile = p1;
+ }
+ }
+ else
+ sFile = "chat";
+
+ delete [] p1;
+
+ dwAdr = atoi(GetWord(mess.c_str(), index- (type == "chat"?2:3)).c_str());
+ iPort = atoi(GetWord(mess.c_str(), index-(type == "chat"?1:2)).c_str());
+ dwSize = atoi(GetWord(mess.c_str(), index-1).c_str());
+ sToken = GetWord(mess.c_str(), index);
+
+ }
+ }
+ }
+ else if (type == "accept" || type == "resume")
+ {
+ // if the filename is surrounded by quotes, do this
+ if(GetWord(mess.c_str(), 2)[0] == '\"')
+ {
+ int end = 0;
+ int begin = mess.find('\"', 0);
+ if(begin >= 0)
+ {
+ end = mess.find('\"', begin + 1);
+ if (end >= 0)
+ {
+ sFile = mess.substr(begin+1, end);
+
+ begin = mess.find(' ', end);
+ if(begin >= 0)
+ {
+ String rest = mess.substr(begin, mess.length());
+ iPort = atoi(GetWord(rest.c_str(), 0).c_str());
+ dwSize = atoi(GetWord(rest.c_str(), 1).c_str());
+ sToken = GetWord(rest.c_str(), 2);
+ }
+ }
+ }
+ }
+ else if (GetWord(mess.c_str(), 4) != "") // ... or try another method of separating the dcc command
+ {
+
+ int index = 4;
+ bool bFlag = false;
+
+ // look for the part of the ctcp command that contains adress, port and size
+ while (!bFlag && GetWord(mess.c_str(), index) != "")
+ {
+ String sTemp = GetWord(mess.c_str(), index-1) + GetWord(mess.c_str(), index);
+
+ // if all characters are number it indicates we have found the adress, port and size parameters
+ int ind = 0;
+
+ while (sTemp[ind] != '\0')
+ {
+ if(!isdigit(sTemp[ind]))
+ break;
+ ind++;
+ }
+ if(sTemp[ind] == '\0' && GetWord(mess.c_str(), index + 2) == "")
+ bFlag = true;
+ index++;
+ }
+ if(bFlag)
+ {
+ char * p1 = strdup(GetWordAddress(mess.c_str(), 2));
+ char * p2 = GetWordAddress(p1, index-4);
+
+ if(p2 > p1)
+ {
+ p2--;
+ while( p2 != p1 && *p2 == ' ')
+ {
+ *p2 = '\0';
+ p2--;
+ }
+ sFile = p1;
+ }
+
+ delete [] p1;
+
+ iPort = atoi(GetWord(mess.c_str(), index-2).c_str());
+ dwSize = atoi(GetWord(mess.c_str(), index-1).c_str());
+ sToken = GetWord(mess.c_str(), index);
+
+ }
+
+ }
+
+
+
+ } // /// end separating dcc commands
+
+ // 2. Check for malformed dcc commands or other errors
+ if(type == "chat" || type == "send")
+ {
+ char szTemp[256];
+ szTemp[0] = '\0';
+
+ unsigned long ulAdr = 0;
+ if (prefs->ManualHost)
+ ulAdr = ConvertIPToInteger(prefs->MySpecifiedHostIP);
+ else
+ ulAdr = ConvertIPToInteger(prefs->IPFromServer?prefs->MyHost:prefs->MyLocalHost);
+
+ if(type == "chat" && !prefs->DCCChatEnabled)
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC: Chat request from %s denied"),pmsg->prefix.sNick.c_str());
+
+ else if(type == "send" && !prefs->DCCFileEnabled)
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC: File transfer request from %s denied"),pmsg->prefix.sNick.c_str());
+
+ else if(type == "send" && !iPort && ulAdr == 0)
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC: Reverse file transfer request from %s denied [No local IP]"),pmsg->prefix.sNick.c_str());
+
+ if(sFile == "" || dwAdr == 0 || dwSize == 0 || iPort == 0 && sToken == "")
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC ERROR: Malformed CTCP request from %s [%s]"),pmsg->prefix.sNick.c_str(), mess.c_str());
+
+ if(lstrlen(szTemp))
+ {
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+ return true;
+ }
+
+ // remove path from the filename if the remote client (stupidly) sent it
+ String sFileCorrected = sFile;
+ int i = sFile.rfind("\\", sFile.length());
+ if (i != string::npos)
+ sFileCorrected = sFile.substr(i+1, sFile.length());
+ sFile = sFileCorrected;
+
+
+ }
+ else if(type == "accept" || type == "resume")
+ {
+ char szTemp[256];
+ szTemp[0] = '\0';
+
+ if(type == "resume" && !prefs->DCCFileEnabled)
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC: File transfer resume request from %s denied"),pmsg->prefix.sNick.c_str());
+
+ if(sToken == "" && iPort == 0 || sFile == "")
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC ERROR: Malformed CTCP request from %s [%s]"),pmsg->prefix.sNick.c_str(), mess.c_str());
+
+ if(lstrlen(szTemp))
+ {
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+ return true;
+ }
+
+ // remove path from the filename if the remote client (stupidly) sent it
+ String sFileCorrected = sFile;
+ int i = sFile.rfind("\\", sFile.length());
+ if (i != string::npos)
+ sFileCorrected = sFile.substr(i+1, sFile.length());
+ sFile = sFileCorrected;
+
+
+ }
+
+ // 3. Take proper actions considering type of command
+
+ // incoming chat request
+ if(type == "chat")
+ {
+ CONTACT user ={(char *)pmsg->prefix.sNick.c_str(), 0, 0, false, false, true};
+ HANDLE hContact = CList_FindContact(&user);
+
+ // check if it should be ignored
+ if(prefs->DCCChatIgnore == 1
+ || prefs->DCCChatIgnore == 2
+ && hContact && DBGetContactSettingByte(hContact,"CList", "NotOnList", 0) == 0
+ && DBGetContactSettingByte(hContact,"CList", "Hidden", 0) == 0)
+ {
+ String host = pmsg->prefix.sUser + "@" + pmsg->prefix.sHost;
+ CList_AddDCCChat(pmsg->prefix.sNick, host, dwAdr, iPort); // add a CHAT event to the clist
+ }
+ else
+ {
+ char szTemp[512];
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC: Chat request from %s denied"),pmsg->prefix.sNick.c_str());
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+ }
+
+ }
+
+ // remote requested that the file should be resumed
+ if(type == "resume")
+ {
+ CDccSession * dcc = NULL;
+
+ if (sToken =="")
+ dcc = g_ircSession.FindDCCSendByPort(iPort);
+ else
+ dcc = g_ircSession.FindPassiveDCCSend(atoi(sToken.c_str())); // reverse ft
+
+ if(dcc)
+ {
+ InterlockedExchange(&dcc->dwWhatNeedsDoing, (long)FILERESUME_RESUME);
+ InterlockedExchange(&dcc->dwResumePos, dwSize); // dwSize is the resume position
+ PostIrcMessage("/PRIVMSG %s \001DCC ACCEPT %s\001", pmsg->prefix.sNick.c_str(), GetWordAddress(mess.c_str(), 2));
+ }
+ }
+
+ // remote accepted your request for a file resume
+ if(type == "accept")
+ {
+ CDccSession * dcc = NULL;
+
+ if (sToken =="")
+ dcc = g_ircSession.FindDCCRecvByPortAndName(iPort, (char *)pmsg->prefix.sNick.c_str());
+ else
+ dcc = g_ircSession.FindPassiveDCCRecv(pmsg->prefix.sNick, sToken); // reverse ft
+
+ if(dcc)
+ {
+ InterlockedExchange(&dcc->dwWhatNeedsDoing, (long)FILERESUME_RESUME);
+ InterlockedExchange(&dcc->dwResumePos, dwSize); // dwSize is the resume position
+ SetEvent(dcc->hEvent);
+ }
+ }
+
+ if (type == "send")
+ {
+ String sTokenBackup = sToken;
+ bool bTurbo = false; // TDCC indicator
+
+ if(sToken != "" && sToken[sToken.length()-1] == 'T')
+ {
+ bTurbo = true;
+ sToken.erase(sToken.length()-1,1);
+ }
+
+ // if a token exists and the port is non-zero it is the remote
+ // computer telling us that is has accepted to act as server for
+ // a reverse filetransfer. The plugin should connect to that computer
+ // and start sedning the file (if the token is valid). Compare to DCC RECV
+ if(sToken != "" && iPort)
+ {
+ CDccSession * dcc = g_ircSession.FindPassiveDCCSend(atoi(sToken.c_str()));
+
+ if(dcc)
+ {
+ dcc->SetupPassive(dwAdr, iPort);
+ dcc->Connect();
+ }
+ }
+
+ else
+ {
+ struct CONTACT_TYPE user ={(char *)pmsg->prefix.sNick.c_str(), (char *)pmsg->prefix.sUser.c_str(), (char *)pmsg->prefix.sHost.c_str(), false, false, false};
+ if (CallService(MS_IGNORE_ISIGNORED, NULL, IGNOREEVENT_FILE))
+ {
+ if (!CList_FindContact(&user))
+ return true;
+ }
+
+ HANDLE hContact = CList_AddContact(&user, false, true);
+ if(hContact)
+ {
+ char * szBlob;
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ ccs.szProtoService = PSR_FILE;
+ DCCINFO * di = new DCCINFO;
+
+ ZeroMemory(di, sizeof(DCCINFO));
+ di->hContact = hContact;
+ di->sFile = sFile;
+ di->dwSize = dwSize;
+ di->sContactName = pmsg->prefix.sNick;
+ di->dwAdr = dwAdr;
+ di->iPort = iPort;
+ di->iType = DCC_SEND;
+ di->bSender = false;
+ di->bTurbo = bTurbo;
+ di->bSSL = false;
+ di->bReverse = (iPort == 0 && sToken !="")?true:false;
+ if(di->bReverse)
+ di->sToken = sTokenBackup;
+
+ pre.flags = 0;
+ pre.timestamp = (DWORD)time(NULL);
+
+ szBlob = (char *) malloc(sizeof(DWORD) + di->sFile.length() + 3);
+ *((PDWORD) szBlob) = (DWORD) di;
+ strcpy(szBlob + sizeof(DWORD), di->sFile.c_str());
+ strcpy(szBlob + sizeof(DWORD) + di->sFile.length() + 1, " ");
+
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "User", pmsg->prefix.sUser.c_str());
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Host", pmsg->prefix.sHost.c_str());
+
+ pre.szMessage = szBlob;
+ pre.lParam = 0;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM) & pre;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) & ccs);
+ }
+
+ }
+ } // end type == "send"
+
+ }
+ else if (pmsg->m_bIncoming)
+ {
+ char temp[300];
+ mir_snprintf(temp, sizeof(temp), Translate("CTCP %s requested by %s"), ocommand.c_str(), pmsg->prefix.sNick.c_str());
+ DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, temp, NULL, NULL, NULL, true, false);
+ }
+ }
+
+ // handle incoming ctcp in notices. This technique is used for replying to CTCP queries
+ else if(pmsg->sCommand == "NOTICE")
+ {
+ char szTemp[255];
+ szTemp[0] = '\0';
+
+ // if xstatus
+ if (pmsg->m_bIncoming && command == "xstatus" && DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusEnabled", 0))
+ {
+ HANDLE hContact = GetContactByName (pmsg->prefix.sNick.c_str());
+
+ char XSTATUSNAME[255], XSTATUSMSG[255], szResponse[255];
+ String StatusMsg;
+ int params,XSTATUSID;
+ strcpy(szResponse,pmsg->parameters[1].c_str());
+ XSTATUSNAME[0]=XSTATUSMSG[0]=0;
+
+ params=sscanf(szResponse,"\001XSTATUS %d %[^\004]\004%[^\001]",&XSTATUSID,XSTATUSNAME,XSTATUSMSG);
+// #ifdef _DEBUG
+// DBGprintf( ">> XSTATUS params = %d\n", params);
+// #endif
+
+ if(params)
+ {
+/*
+ #ifdef _DEBUG
+ DBGprintf( ">> XStatus response from %s\n", pmsg->prefix.sNick.c_str());
+ DBGprintf( ">> XSTATUSID = %d\n", XSTATUSID);
+ if(XSTATUSID!=0)
+ {
+ DBGprintf( ">> XSTATUSNAME = %s\n", XSTATUSNAME);
+ DBGprintf( ">> XSTATUSMSG = %s\n", XSTATUSMSG);
+ }
+ #endif
+*/
+ DBWriteContactSettingByte(hContact, IRCPROTONAME, "XStatus", 1);
+
+ extern HANDLE hXStatusIcons[32];
+
+ if(XSTATUSID!=0)
+ {
+ IRCWriteContactSettingByte(hContact, DBSETTING_XSTATUSID, XSTATUSID);
+ UniWriteContactSettingUtf(hContact, IRCPROTONAME, DBSETTING_XSTATUSNAME, XSTATUSNAME);
+ StatusMsg = XSTATUSMSG;
+ StatusMsg = ReplaceString( (char *)StatusMsg.c_str(), "\005", "\r\n");
+ UniWriteContactSettingUtf(hContact, IRCPROTONAME, DBSETTING_XSTATUSMSG, (char *)StatusMsg.c_str());
+ setContactExtraIcon(hContact, hXStatusIcons[XSTATUSID-1]);
+ }
+ else
+ {
+ DBDeleteContactSetting(hContact, IRCPROTONAME, DBSETTING_XSTATUSID);
+ DBDeleteContactSetting(hContact, IRCPROTONAME, DBSETTING_XSTATUSNAME);
+ DBDeleteContactSetting(hContact, IRCPROTONAME, DBSETTING_XSTATUSMSG);
+ setContactExtraIcon(hContact, (HANDLE)-1);
+ }
+ }
+
+ return true;
+ }
+
+ // if avatar
+ if (pmsg->m_bIncoming && command == "avatar")
+ {
+
+ HANDLE hContact = GetContactByName (pmsg->prefix.sNick.c_str());
+ if(!hContact)
+ return false;
+
+ char AVATARHASH[255], szResponse[255],hash[20];
+ strcpy(szResponse,pmsg->parameters[1].c_str());
+ AVATARHASH[0]=0;
+ sscanf(szResponse,"\001AVATAR %[^\001]",AVATARHASH);
+
+// #ifdef _DEBUG
+// DBGprintf( ">> AVATARHASH = %s\n", AVATARHASH);
+// #endif
+
+ int res;
+ for(int i=0;i<5;i++)
+ res=sscanf(AVATARHASH+i*8,"%8lX",(unsigned int *)(hash+i*4));
+
+ IRCWriteContactSettingBlob(hContact, "AvatarHash", hash,20);
+
+ return true;
+ }
+
+ if (pmsg->m_bIncoming && command == "version")
+ {
+ HANDLE hContact = GetContactByName(pmsg->prefix.sNick.c_str());
+ if(!DBGetContactSettingByte(hContact, IRCPROTONAME, "Version", 1))
+ {
+ IRCWriteContactSettingString(hContact, "MirVer", DoColorCodes(GetWordAddress(mess.c_str(), 1), TRUE, FALSE));
+ DBWriteContactSettingByte(hContact, IRCPROTONAME, "Version", 0);
+ }
+// #ifdef _DEBUG
+// DBGprintf("MirVer from %s = %s\n", pmsg->prefix.sNick.c_str(), UniGetContactSettingUtf( hContact, IRCPROTONAME, "MirVer", ""));
+// #endif
+ }
+
+ // if the whois window is visible and the ctcp reply belongs to the user in it, then show the reply in the whois window
+ if(whois_hWnd && IsWindowVisible(whois_hWnd))
+ {
+ SendMessage(GetDlgItem(whois_hWnd, IDC_INFO_NICK), WM_GETTEXT, 255, (LPARAM) szTemp);
+ if(lstrcmpi(szTemp, pmsg->prefix.sNick.c_str()) == 0)
+ {
+ if (pmsg->m_bIncoming && (command == "version" ||command == "userinfo" || command == "time"))
+ {
+ SetActiveWindow(whois_hWnd);
+ SetDlgItemText(whois_hWnd, IDC_REPLY, DoColorCodes(GetWordAddress(mess.c_str(), 1), TRUE, FALSE));
+ return true;
+ }
+ if (pmsg->m_bIncoming && command == "ping")
+ {
+ SetActiveWindow(whois_hWnd);
+ int s = (int)time(0) - (int)atol(GetWordAddress(mess.c_str(), 1));
+ char szTemp[30];
+ if (s==1)
+ mir_snprintf(szTemp, sizeof(szTemp), "%u second", s);
+ else
+ mir_snprintf(szTemp, sizeof(szTemp), "%u seconds", s);
+
+ SetDlgItemText(whois_hWnd, IDC_REPLY, DoColorCodes(szTemp, TRUE, FALSE));
+ return true;
+ }
+
+ }
+ }
+
+ char temp[300];
+
+ //... else show the reply in the current window
+ if (pmsg->m_bIncoming && command == "ping")
+ {
+ int s = (int)time(0) - (int)atol(GetWordAddress(mess.c_str(), 1));
+ mir_snprintf(temp, sizeof(temp), Translate("CTCP PING reply from %s: %u sec(s)"), pmsg->prefix.sNick.c_str(), s);
+ DoEvent(GC_EVENT_INFORMATION, NULL, NULL, temp, NULL, NULL, NULL, true, false);
+ }
+ else
+ {
+ mir_snprintf(temp, sizeof(temp), Translate("CTCP %s reply from %s: %s"), ocommand.c_str(), pmsg->prefix.sNick.c_str(), GetWordAddress(mess.c_str(), 1));
+ DoEvent(GC_EVENT_INFORMATION, NULL, NULL, temp, NULL, NULL, NULL, true, false);
+ }
+
+ }
+ return true;
+ }
+ return false;
+}
+
+bool CMyMonitor::OnIrc_NAMES(const CIrcMessage* pmsg)
+{
+
+ if(pmsg->m_bIncoming && pmsg->parameters.size()>3)
+ {
+ sNamesList += pmsg->parameters[3] + " ";
+ }
+
+ ShowMessage(pmsg);
+
+ return true;
+
+}
+
+bool CMyMonitor::OnIrc_ENDNAMES(const CIrcMessage* pmsg)
+{
+ HWND hActiveWindow = GetActiveWindow();
+ if(pmsg->m_bIncoming && pmsg->parameters.size()>1)
+ {
+ String name = "a";
+ int i = 0;
+ BOOL bFlag = false;
+
+ // Is the user on the names list?
+ while (name != "")
+ {
+ name = GetWord(sNamesList.c_str(), i);
+ i++;
+ if(name != "")
+ {
+ int index = 0;
+
+ while(strchr(sUserModePrefixes.c_str(), name[index]))
+ index++;
+
+ if(!lstrcmpi(name.substr(index, name.length()).c_str(), m_session.GetInfo().sNick.c_str()))
+ {
+ bFlag = true;
+ break;
+ }
+ }
+ }
+ if(bFlag)
+ {
+ String sChanName = pmsg->parameters[1];
+ if (sChanName[0] == '@' || sChanName[0] == '*' || sChanName[0] == '=')
+ sChanName.erase(0,1);
+
+
+ // Add a new chat window
+ GCSESSION gcw = {0};
+ String sID = MakeWndID(sChanName) ;
+
+ gcw.cbSize = sizeof(GCSESSION);
+ gcw.iType = GCW_CHATROOM;
+ gcw.pszID = sID.c_str();
+ gcw.pszModule = IRCPROTONAME;
+ gcw.pszName = sChanName.c_str();
+ if(!CallService(MS_GC_NEWSESSION, 0, (LPARAM)&gcw))
+
+ {
+ DBVARIANT dbv;
+ GCDEST gcd = {0};
+ GCEVENT gce = {0};
+ String sTemp;
+ int i = 0;
+
+ PostIrcMessage( "/MODE %s", sChanName.c_str());
+
+ gcd.pszID = (char*)sID.c_str();
+ gcd.pszModule = IRCPROTONAME;
+ gcd.iType = GC_EVENT_ADDGROUP;
+ gce.time = 0;
+
+ //register the statuses
+ gce.cbSize = sizeof(GCEVENT);
+ gce.pDest = &gcd;
+
+ gce.pszStatus = "Owner";
+ CallChatEvent(0, (LPARAM)&gce);
+ gce.pszStatus = "Admin";
+ CallChatEvent(0, (LPARAM)&gce);
+ gce.pszStatus = "Op";
+ CallChatEvent(0, (LPARAM)&gce);
+ gce.pszStatus = "Halfop";
+ CallChatEvent(0, (LPARAM)&gce);
+ gce.pszStatus = "Voice";
+ CallChatEvent(0, (LPARAM)&gce);
+ gce.pszStatus = "Normal";
+ CallChatEvent(0, (LPARAM)&gce);
+
+ i = 0;
+ sTemp = GetWord(sNamesList.c_str(), i);
+
+ // Fill the nicklist
+ while(sTemp != "")
+ {
+ String sStat;
+ String sTemp2 = sTemp;
+ sStat = PrefixToStatus(sTemp[0]);
+
+ // fix for networks like freshirc where they allow more than one prefix
+ while(PrefixToStatus(sTemp[0]) != "Normal")
+ sTemp.erase(0,1);
+
+ gcd.iType = GC_EVENT_JOIN;
+ gce.pszUID = sTemp.c_str();
+ gce.pszNick = sTemp.c_str();
+ gce.pszStatus = sStat.c_str();
+ BOOL bIsMe = (lstrcmpi(gce.pszNick, m_session.GetInfo().sNick.c_str()) == 0)?TRUE:FALSE;
+ gce.bAddToLog = false;
+ gce.bIsMe = bIsMe;
+ gce.time = bIsMe?time(0):0;
+
+ CallChatEvent(0, (LPARAM)&gce);
+
+ // fix for networks like freshirc where they allow more than one prefix
+ if(PrefixToStatus(sTemp2[0]) != "Normal")
+ {
+ sTemp2.erase(0,1);
+ sStat = PrefixToStatus(sTemp2[0]);
+ while(sStat != "Normal")
+ {
+ DoEvent(GC_EVENT_ADDSTATUS, (char*)sID.c_str(), sTemp.c_str(), "system", sStat.c_str(), NULL, NULL, false, false, 0);
+ sTemp2.erase(0,1);
+ sStat = PrefixToStatus(sTemp2[0]);
+ }
+
+ }
+
+ i++;
+ sTemp = GetWord(sNamesList.c_str(), i);
+ }
+ //Set the item data for the window
+ {
+ FreeWindowItemData(sChanName, NULL);
+
+ CHANNELINFO * wi = new CHANNELINFO;
+ wi->pszLimit = 0;
+ wi->pszMode = 0;
+ wi->pszPassword = 0;
+ wi->pszTopic = 0;
+ DoEvent(GC_EVENT_SETITEMDATA, sChanName.c_str(), NULL, NULL, NULL, NULL, (DWORD)wi, false, false, 0);
+
+ if(sTopic != "" && !lstrcmpi(GetWord(sTopic.c_str(), 0).c_str() , sChanName.c_str()))
+ {
+ DoEvent(GC_EVENT_TOPIC, sChanName.c_str(), sTopicName==""?NULL:sTopicName.c_str(), GetWordAddress(sTopic.c_str(), 1), NULL, NULL, NULL, true, false);
+ AddWindowItemData(sChanName, 0, 0, 0, GetWordAddress(sTopic.c_str(), 1));
+ sTopic = "";
+ sTopicName = "";
+ }
+ }
+
+ gcd.pszID = (char*)sID.c_str();
+ gcd.iType = GC_EVENT_CONTROL;
+ gce.cbSize = sizeof(GCEVENT);
+ gce.bAddToLog = false;
+ gce.bIsMe = false;
+ gce.dwItemData = false;
+ gce.pszNick = NULL;
+ gce.pszStatus = NULL;
+ gce.pszText = NULL;
+ gce.pszUID = NULL;
+ gce.pszUserInfo = NULL;
+ gce.time = time(0);
+ gce.pDest = &gcd;
+
+ if (!DBGetContactSetting(NULL, IRCPROTONAME, "JTemp", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ String command = "a";
+ String save = "";
+ int i = 0;
+
+ while(command != "")
+ {
+ command = GetWord(dbv.pszVal, i);
+ i++;
+ if(command != "")
+ {
+ String S = command.substr(1, command.length());
+ if( !lstrcmpi((char *)sChanName.c_str(), (char *)S.c_str()))
+ break;
+
+ save += command;
+ save += " ";
+ }
+ }
+
+ if (command != "")
+ {
+ save += GetWordAddress(dbv.pszVal, i);
+ switch (command[0])
+ {
+ case 'M':
+ CallChatEvent( WINDOW_HIDDEN, (LPARAM)&gce);
+ break;
+ case 'X':
+ CallChatEvent( WINDOW_MAXIMIZE, (LPARAM)&gce);
+ break;
+ default:
+ CallChatEvent( SESSION_INITDONE, (LPARAM)&gce);
+ break;
+ }
+
+ }
+ else
+ CallChatEvent( SESSION_INITDONE, (LPARAM)&gce);
+
+
+ if (save == "")
+ DBDeleteContactSetting(NULL, IRCPROTONAME, "JTemp");
+ else
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "JTemp", save.c_str());
+ DBFreeVariant(&dbv);
+ }
+ else
+ CallChatEvent( SESSION_INITDONE, (LPARAM)&gce);
+
+ {
+
+ gcd.iType = GC_EVENT_CONTROL;
+
+ gce.pDest = &gcd;
+ CallChatEvent( SESSION_ONLINE, (LPARAM)&gce);
+
+
+ }
+
+
+ }
+
+// if(prefs->AutoOnlineNotification && !bTempDisableCheck || bTempForceCheck)
+// DoUserhostWithReason(2, "S", true, "%s", sChanName.c_str());
+// SetChatTimer(OnlineNotifTimer3, prefs->OnlineNotificationTime*500, OnlineNotifTimerProc3);
+
+ }
+ }
+
+ sNamesList = "";
+
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+bool CMyMonitor::OnIrc_INITIALTOPIC(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming&& pmsg->parameters.size() >2)
+ {
+ AddWindowItemData(pmsg->parameters[1].c_str(), 0, 0, 0, (char*)pmsg->parameters[2].c_str());
+ sTopic = pmsg->parameters[1] + " " + pmsg->parameters[2];
+ sTopicName = "";
+ }
+ ShowMessage(pmsg);
+
+ return true;
+}
+bool CMyMonitor::OnIrc_INITIALTOPICNAME(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming&& pmsg->parameters.size() >2)
+ {
+ sTopicName = pmsg->parameters[2];
+ }
+ ShowMessage(pmsg);
+
+ return true;
+}
+bool CMyMonitor::OnIrc_TOPIC(const CIrcMessage* pmsg)
+{
+ if (pmsg->parameters.size() > 1 && pmsg->m_bIncoming)
+ {
+ DoEvent(GC_EVENT_TOPIC, pmsg->parameters[0].c_str(), pmsg->prefix.sNick.c_str(), pmsg->parameters[1].c_str(), NULL, NULL, NULL, true, false);
+ AddWindowItemData(pmsg->parameters[0].c_str(), 0, 0, 0, (char*)pmsg->parameters[1].c_str());
+ }
+
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+bool CMyMonitor::OnIrc_LISTSTART(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming) {
+ if( list_hWnd == NULL)
+ list_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_LIST),NULL,ListWndProc);
+ ChannelNumber = 0;
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_LIST(const CIrcMessage* pmsg)
+{
+
+ if (pmsg->m_bIncoming==1 && list_hWnd && pmsg->parameters.size() > 2)
+ {
+
+ ChannelNumber++;
+ LVITEM lvItem;
+ HWND hListView = GetDlgItem(list_hWnd, IDC_INFO_LISTVIEW);
+ lvItem.iItem = ListView_GetItemCount(hListView);
+ lvItem.mask = LVIF_TEXT |LVIF_PARAM;
+ lvItem.iSubItem = 0;
+ lvItem.pszText = (char *)pmsg->parameters[1].c_str();
+ lvItem.lParam = lvItem.iItem;
+ lvItem.iItem = ListView_InsertItem(hListView,&lvItem);
+ lvItem.mask = LVIF_TEXT;
+ lvItem.iSubItem =1;
+ lvItem.pszText = (char *)pmsg->parameters[pmsg->parameters.size()-2].c_str();
+ ListView_SetItem(hListView,&lvItem);
+
+ char * temp= new char [lstrlen(pmsg->parameters[pmsg->parameters.size()-1].c_str())+1];
+ strcpy(temp, (char *)pmsg->parameters[pmsg->parameters.size()-1].c_str());
+ char * find = strstr(temp , "[+");
+ char *find2 = strstr(temp , "]");
+ char * save = temp;
+ if (find == temp && find2 != NULL && find +8 >= find2)
+ {
+ temp = strstr(temp, "]");
+ if (lstrlen(temp) > 1)
+ {
+ temp++;
+ temp[0] = '\0';
+ lvItem.iSubItem =2;
+ lvItem.pszText = save;
+ ListView_SetItem(hListView,&lvItem);
+ temp[0] = ' ';
+ temp++;
+ }
+ else
+ temp =save;
+ }
+
+ lvItem.iSubItem =3;
+ String S = DoColorCodes(temp, TRUE, FALSE);
+ lvItem.pszText = (char *)S.c_str();
+ ListView_SetItem(hListView,&lvItem);
+ temp = save;
+ delete []temp;
+
+
+ int percent = 100;
+ if (NoOfChannels > 0)
+ percent = (int)(ChannelNumber*100) / NoOfChannels;
+ char text[50];
+ if ( percent < 100)
+ mir_snprintf(text, 49, Translate( "Downloading list (%u%%) - %u channels" ), percent, ChannelNumber);
+ else
+ mir_snprintf(text, 49, Translate( "Downloading list - %u channels" ), ChannelNumber);
+ SetDlgItemText(list_hWnd, IDC_TEXT, text);
+ }
+
+ return true;
+
+
+}
+bool CMyMonitor::OnIrc_LISTEND(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming && list_hWnd)
+ {
+
+ EnableWindow(GetDlgItem(list_hWnd, IDC_JOIN), true);
+ ListView_SetSelectionMark(GetDlgItem(list_hWnd, IDC_INFO_LISTVIEW), 0);
+ ListView_SetColumnWidth(GetDlgItem(list_hWnd, IDC_INFO_LISTVIEW), 1, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(GetDlgItem(list_hWnd, IDC_INFO_LISTVIEW), 2, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(GetDlgItem(list_hWnd, IDC_INFO_LISTVIEW), 3, LVSCW_AUTOSIZE);
+ SendMessage(list_hWnd, IRC_UPDATELIST, 0, 0);
+
+ char text[90];
+ mir_snprintf(text, 40, Translate( "Done: %u channels" ), ChannelNumber);
+ int percent = 100;
+ if (NoOfChannels > 0)
+ percent = (int)(ChannelNumber*100) / NoOfChannels;
+ if (percent <70) {
+ lstrcat(text, " ");
+ lstrcat(text, Translate( "(probably truncated by server)" ));
+ }
+ SetDlgItemText(list_hWnd, IDC_TEXT, text);
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_BANLIST(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >2)
+ {
+
+ if(manager_hWnd && (
+ IsDlgButtonChecked(manager_hWnd, IDC_RADIO1) && pmsg->sCommand == "367"
+ || IsDlgButtonChecked(manager_hWnd, IDC_RADIO2) && pmsg->sCommand == "346"
+ || IsDlgButtonChecked(manager_hWnd, IDC_RADIO3) && pmsg->sCommand == "348"
+ ) && !IsWindowEnabled(GetDlgItem(manager_hWnd, IDC_RADIO1)) && !IsWindowEnabled(GetDlgItem(manager_hWnd, IDC_RADIO2)) && !IsWindowEnabled(GetDlgItem(manager_hWnd, IDC_RADIO3))
+ )
+ {
+ String S = pmsg->parameters[2];
+ if(pmsg->parameters.size() > 3)
+ {
+ S += " - ";
+ S += pmsg->parameters[3];
+ if (pmsg->parameters.size() > 4)
+ {
+ S += " - ( ";
+ time_t time;
+ time = StrToInt(pmsg->parameters[4].c_str());
+ S += ctime(&time);
+ S = ReplaceString(S.c_str(), "\n", " ");
+ S += ")";
+ }
+ }
+
+ SendDlgItemMessage(manager_hWnd, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)S.c_str());
+ }
+
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_BANLISTEND(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >1)
+ {
+
+ if(manager_hWnd && (
+ IsDlgButtonChecked(manager_hWnd, IDC_RADIO1) && pmsg->sCommand == "368"
+ || IsDlgButtonChecked(manager_hWnd, IDC_RADIO2) && pmsg->sCommand == "347"
+ || IsDlgButtonChecked(manager_hWnd, IDC_RADIO3) && pmsg->sCommand == "349"
+ ) && !IsWindowEnabled(GetDlgItem(manager_hWnd, IDC_RADIO1)) && !IsWindowEnabled(GetDlgItem(manager_hWnd, IDC_RADIO2)) && !IsWindowEnabled(GetDlgItem(manager_hWnd, IDC_RADIO3))
+ )
+ {
+ if (strchr(sChannelModes.c_str(), 'b'))
+ EnableWindow(GetDlgItem(manager_hWnd, IDC_RADIO1), true);
+ if (strchr(sChannelModes.c_str(), 'I'))
+ EnableWindow(GetDlgItem(manager_hWnd, IDC_RADIO2), true);
+ if (strchr(sChannelModes.c_str(), 'e'))
+ EnableWindow(GetDlgItem(manager_hWnd, IDC_RADIO3), true);
+ if (!IsDlgButtonChecked(manager_hWnd, IDC_NOTOP))
+ EnableWindow(GetDlgItem(manager_hWnd, IDC_ADD), true);
+ }
+
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+
+bool CMyMonitor::OnIrc_WHOIS_NAME(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: WHOIS NAME\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() > 5 && ManualWhoisCount > 0)
+ {
+ if (prefs->PopupsEnabled && prefs->PopupWhois)
+ {
+ whois = new WHOIS;
+ strcpy(whois->_Name, DoColorCodes(pmsg->parameters[5].c_str(), TRUE, FALSE));
+ strcpy(whois->_Address, pmsg->parameters[3].c_str());
+ strcpy(whois->_ID, pmsg->parameters[2].c_str());
+ strcpy(whois->_Auth, "unregistered nick");
+ strcpy(whois->_Idle, "unknown");
+ }
+ if (!prefs->PopupsEnabled || !prefs->PopupWhois)
+ {
+ whois_popup = false;
+ if(whois_hWnd==NULL)
+ whois_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_INFO),NULL,InfoWndProc);
+ if (SendMessage(GetDlgItem(whois_hWnd, IDC_INFO_NICK), CB_FINDSTRINGEXACT, -1, (LPARAM) pmsg->parameters[1].c_str()) == CB_ERR)
+ SendMessage(GetDlgItem(whois_hWnd, IDC_INFO_NICK), CB_ADDSTRING, 0, (LPARAM) pmsg->parameters[1].c_str());
+ int i = SendMessage(GetDlgItem(whois_hWnd, IDC_INFO_NICK), CB_FINDSTRINGEXACT, -1, (LPARAM) pmsg->parameters[1].c_str());
+ SendMessage(GetDlgItem(whois_hWnd, IDC_INFO_NICK), CB_SETCURSEL, i, 0);
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_CAPTION), pmsg->parameters[1].c_str());
+
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_NAME), pmsg->parameters[5].c_str());
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_ADDRESS), pmsg->parameters[3].c_str());
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_ID), pmsg->parameters[2].c_str());
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_CHANNELS), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_SERVER), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_AWAY2), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_AUTH), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_OTHER), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_REPLY), '\0');
+ SetWindowText(whois_hWnd, Translate("User information"));
+ EnableWindow(GetDlgItem(whois_hWnd, ID_INFO_QUERY), true);
+ ShowWindow(whois_hWnd, SW_SHOW);
+ if (IsIconic(whois_hWnd))
+ ShowWindow(whois_hWnd, SW_SHOWNORMAL);
+ SendMessage(whois_hWnd, WM_SETREDRAW, TRUE, 0);
+ InvalidateRect(whois_hWnd, NULL, TRUE);
+ }
+ }
+
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+bool CMyMonitor::OnIrc_WHOIS_CHANNELS(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: WHOIS CHANNELS\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >2 && ManualWhoisCount > 0 && prefs->PopupsEnabled && prefs->PopupWhois)
+ {
+ strcpy(whois->_Channels, pmsg->parameters[2].c_str());
+ }
+
+ if (pmsg->m_bIncoming && whois_hWnd && pmsg->parameters.size() >2 && ManualWhoisCount > 0)
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_CHANNELS), pmsg->parameters[2].c_str());
+ ShowMessage(pmsg);
+ return true;
+}
+
+bool CMyMonitor::OnIrc_WHOIS_AWAY(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: WHOIS AWAY\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >2 && ManualWhoisCount > 0 && prefs->PopupsEnabled && prefs->PopupWhois)
+ {
+ strcpy(whois->_Away, pmsg->parameters[2].c_str());
+ }
+
+ if (pmsg->m_bIncoming && whois_hWnd && pmsg->parameters.size() >2 && ManualWhoisCount > 0)
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_AWAY2), pmsg->parameters[2].c_str());
+ if (ManualWhoisCount <1 && pmsg->m_bIncoming && pmsg->parameters.size() >2)
+ WhoisAwayReply = pmsg->parameters[2];
+ ShowMessage(pmsg);
+ return true;
+}
+
+bool CMyMonitor::OnIrc_WHOIS_OTHER(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: WHOIS OTHER\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >2 && ManualWhoisCount > 0 && prefs->PopupsEnabled && prefs->PopupWhois)
+ {
+ strcpy(whois->_Other, pmsg->parameters[2].c_str());
+ }
+
+ if (pmsg->m_bIncoming && whois_hWnd && pmsg->parameters.size() >2 && ManualWhoisCount > 0) {
+ char temp[1024];
+ char temp2[1024];
+ GetDlgItemText(whois_hWnd, IDC_INFO_OTHER, temp, 1000);
+ lstrcat(temp, "%s\r\n");
+ mir_snprintf(temp2, 1020, temp, pmsg->parameters[2].c_str());
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_OTHER), temp2);
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_WHOIS_END(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: WHOIS END\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ if (prefs->PopupsEnabled && prefs->PopupWhois && whois_popup)
+ {
+ if(whois_hWnd!=NULL)
+ ShowWindow(whois_hWnd, SW_HIDE);
+
+ HANDLE hContact = GetContactByName(pmsg->parameters[1].c_str());
+// char szTemp[MAX_PATH];
+ char szTemp[1000];
+
+ sprintf(szTemp, "[b]%s[/b]: %s\n[b]%s[/b]: %s\n[b]%s[/b]: %s\n[b]%s[/b]: %s\n[b]%s[/b]: %s\n[b]%s[/b]: %s\n",
+
+ IRCTranslateUtf("Nick"), ansi_to_utf8(pmsg->parameters[1].c_str()),
+ IRCTranslateUtf("Idle"), IRCTranslateUtf(whois->_Idle),
+ IRCTranslateUtf("Address"), whois->_Address,
+ IRCTranslateUtf("User"), ansi_to_utf8(whois->_ID),
+ IRCTranslateUtf("Name"), ansi_to_utf8(whois->_Name),
+ IRCTranslateUtf("Auth"), IRCTranslateUtf(whois->_Auth)
+ //IRCTranslateUtf("Server"), whois->_Server,
+ //IRCTranslateUtf("Channels"), whois->_Channels, // bug
+ //IRCTranslateUtf("Other"), whois->_Other, // bug
+ //IRCTranslateUtf("Away"), ansi_to_utf8(whois->_Away) // bug
+ );
+
+ ShowPopUpMsg(hContact, ansi_to_utf8(pmsg->parameters[1].c_str()), szTemp, LOG_NOTE);
+
+ whois_popup = true;
+ delete whois;
+ }
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >1 && ManualWhoisCount < 1) {
+ struct CONTACT_TYPE user ={(char *)pmsg->parameters[1].c_str(), NULL, NULL, false, false, true};
+ HANDLE hContact = CList_FindContact(&user);
+ if (hContact)
+ ProtoBroadcastAck(IRCPROTONAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE) 1, (LPARAM) WhoisAwayReply.c_str());
+
+ }
+ ManualWhoisCount--;
+ if (ManualWhoisCount < 0)
+ ManualWhoisCount = 0;
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_WHOIS_IDLE(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: WHOIS IDLE\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ int D = 0;
+ int H = 0;
+ int M = 0;
+ int S = 0;
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >2 && ManualWhoisCount > 0){
+ S = StrToInt(pmsg->parameters[2].c_str());
+ char temp[100];
+ if(S == 0)
+ mir_snprintf(temp ,99,"%us", S);
+ D = S/(60*60*24);
+ S -= (D * 60 * 60 *24);
+ H = S/(60*60);
+ S -= (H * 60 * 60);
+ M = S/60;
+ S -= (M * 60 );
+// char temp[100];
+ if (D)
+ mir_snprintf(temp ,99, "%ud, %uh, %um, %us", D, H, M, S);
+ else if (H)
+ mir_snprintf(temp ,99,"%uh, %um, %us", H, M, S);
+ else if (M)
+ mir_snprintf(temp ,99,"%um, %us", M, S);
+ else if (S)
+ mir_snprintf(temp ,99,"%us", S);
+
+ if(prefs->PopupsEnabled && prefs->PopupWhois)
+ strcpy(whois->_Idle, temp);
+
+ if(whois_hWnd)
+ {
+ char temp2[256];
+ GetWindowText(GetDlgItem(whois_hWnd, IDC_CAPTION), temp2, 255);
+ char temp3[256];
+ mir_snprintf(temp3, 255 ,"%s (idle %s)", temp2, temp);
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_CAPTION), temp3);
+ }
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+
+bool CMyMonitor::OnIrc_WHOIS_SERVER(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: WHOIS SERVER\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >2 && ManualWhoisCount > 0 && prefs->PopupsEnabled && prefs->PopupWhois)
+ {
+ strcpy(whois->_Server, pmsg->parameters[2].c_str());
+ }
+
+ if (pmsg->m_bIncoming && whois_hWnd && pmsg->parameters.size() >2 && ManualWhoisCount > 0)
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_SERVER), pmsg->parameters[2].c_str());
+ ShowMessage(pmsg);
+ return true;
+}
+
+bool CMyMonitor::OnIrc_WHOIS_AUTH(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: WHOIS AUTH\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >2 && ManualWhoisCount > 0 && prefs->PopupsEnabled && prefs->PopupWhois)
+ {
+ HANDLE hContact = GetContactByName(pmsg->parameters[1].c_str());
+ if (pmsg->sCommand == "330")
+ strcpy(whois->_Auth, pmsg->parameters[2].c_str());
+ else if (pmsg->parameters[2] == "is an identified user" || pmsg->parameters[2] == "is a registered nick" || pmsg->parameters[2] == "is identified to services ")
+ strcpy(whois->_Auth, pmsg->parameters[2].c_str());
+ }
+
+ if (pmsg->m_bIncoming && whois_hWnd && pmsg->parameters.size() >2 && ManualWhoisCount > 0)
+ if (pmsg->sCommand == "330")
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_AUTH), pmsg->parameters[2].c_str());
+ else if (pmsg->parameters[2] == "is an identified user" || pmsg->parameters[2] == "is a registered nick" || pmsg->parameters[2] == "is identified to services ")
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_AUTH), pmsg->parameters[2].c_str());
+ else
+ OnIrc_WHOIS_OTHER(pmsg);
+ ShowMessage(pmsg);
+ return true;
+}
+
+bool CMyMonitor::OnIrc_WHOIS_NO_USER(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: WHOIS NO USER\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >2 && !IsChannel(pmsg->parameters[1]) && prefs->UseMemoServ)
+ {
+ HANDLE hContact = GetContactByName(pmsg->parameters[1].c_str());
+// HANDLE hEvent = CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0);
+
+ PostIrcMessage("/msg %s send %s %s", prefs->MemoServName ,pmsg->parameters[1].c_str(), "test");
+ ShowPopUpMsg(hContact, pmsg->parameters[1].c_str(), IRCTranslateUtf("Message sent to MemoServ"), LOG_NOTE);
+ return true;
+ }
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >2 && !IsChannel(pmsg->parameters[1]) && prefs->PopupsEnabled && prefs->PopupsWhoisNoUser)
+ {
+ HANDLE hContact = GetContactByName(pmsg->parameters[1].c_str());
+ ShowPopUpMsg(hContact, pmsg->parameters[1].c_str(), IRCTranslateUtf(pmsg->parameters[2].c_str()), LOG_NOTE);
+ whois_popup = false;
+ return true;
+ }
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >2 && !IsChannel(pmsg->parameters[1]))
+ {
+ if (whois_hWnd) {
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_NICK), pmsg->parameters[2].c_str());
+ SendMessage(GetDlgItem(whois_hWnd, IDC_INFO_NICK), CB_SETEDITSEL, 0,MAKELPARAM(0,-1));
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_CAPTION), pmsg->parameters[2].c_str());
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_NAME), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_ADDRESS), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_ID), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_CHANNELS), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_SERVER), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_AWAY2), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_INFO_AUTH), '\0');
+ SetWindowText(GetDlgItem(whois_hWnd, IDC_REPLY), '\0');
+ EnableWindow(GetDlgItem(whois_hWnd, ID_INFO_QUERY), false);
+ }
+
+ struct CONTACT_TYPE user ={(char *)pmsg->parameters[1].c_str(), NULL, NULL, false, false, false};
+ HANDLE hContact = CList_FindContact(&user);
+ if (hContact)
+ {
+ AddOutgoingMessageToDB(hContact, (char*)((String)"> " + pmsg->parameters[2] + (String)": " + pmsg->parameters[1]).c_str() );
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv) && dbv.type == DBVT_ASCIIZ )
+ {
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Nick", dbv.pszVal);
+ DBVARIANT dbv2;
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 0)
+ DoUserhostWithReason(1, ((String)"S" + dbv.pszVal).c_str(), true, dbv.pszVal);
+ else
+ {
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv2) && dbv2.type == DBVT_ASCIIZ)
+ {
+ DoUserhostWithReason(2, ((String)"S" + dbv2.pszVal).c_str(), true, dbv2.pszVal);
+ DBFreeVariant(&dbv2);
+ }
+ else
+ {
+ DoUserhostWithReason(2, ((String)"S" + dbv.pszVal).c_str(), true, dbv.pszVal);
+ }
+ }
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "User", "");
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Host", "");
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_NICK_ERR(const CIrcMessage* pmsg)
+{
+ if ( (nickflag || lstrlen(prefs->AlternativeNick)== 0) && pmsg->m_bIncoming && pmsg->parameters.size() >2)
+ {
+ if (nick_hWnd == NULL)
+ {
+ nick_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_NICK),NULL,NickWndProc);
+ }
+ SetWindowText(GetDlgItem(nick_hWnd, IDC_CAPTION), Translate( "Change nickname" ));
+ SetWindowText(GetDlgItem(nick_hWnd, IDC_TEXT), pmsg->parameters[2].c_str());
+ SetWindowText(GetDlgItem(nick_hWnd, IDC_ENICK), pmsg->parameters[1].c_str());
+ SendMessage(GetDlgItem(nick_hWnd, IDC_ENICK), CB_SETEDITSEL, 0,MAKELPARAM(0,-1));
+ }
+ else if (pmsg->m_bIncoming )
+ {
+ char m[40];
+ mir_snprintf(m, 40, "NICK %s", prefs->AlternativeNick);
+ if( g_ircSession )
+ g_ircSession << irc::CIrcMessage(m);
+
+ nickflag =true;
+
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+
+bool CMyMonitor::OnIrc_JOINERROR(const CIrcMessage* pmsg)
+{
+
+ if(pmsg->m_bIncoming)
+ {
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, IRCPROTONAME, "JTemp", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ String command = "a";
+ String save = "";
+ int i = 0;
+
+ while(command != "")
+ {
+ command = GetWord(dbv.pszVal, i);
+ i++;
+
+ if(command != "" && pmsg->parameters[0] == command.substr(1, command.length()))
+ {
+ save += command;
+ save += " ";
+ }
+ }
+ DBFreeVariant(&dbv);
+
+ if (save == "")
+ DBDeleteContactSetting(NULL, IRCPROTONAME, "JTemp");
+ else
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "JTemp", save.c_str());
+ }
+ }
+
+ ShowMessage(pmsg);
+
+ return true;
+}
+bool CMyMonitor::OnIrc_UNKNOWN(const CIrcMessage* pmsg)
+{
+ if(pmsg->m_bIncoming && pmsg->parameters.size() > 0)
+ {
+ if(pmsg->parameters[0] == "WHO" && GetNextUserhostReason(2) !="U")
+ return true;
+ if(pmsg->parameters[0] == "USERHOST" && GetNextUserhostReason(1) !="U")
+ return true;
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_ENDMOTD(const CIrcMessage* pmsg)
+{
+ if(pmsg->m_bIncoming && !bPerformDone)
+ DoOnConnect(pmsg);
+ ShowMessage(pmsg);
+ return true;
+}
+
+bool CMyMonitor::OnIrc_NOOFCHANNELS(const CIrcMessage* pmsg)
+{
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >1)
+ NoOfChannels = StrToInt(pmsg->parameters[1].c_str());
+
+ if (pmsg->m_bIncoming && !bPerformDone) {
+ DoOnConnect(pmsg);
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+
+
+bool CMyMonitor::OnIrc_ERROR(const CIrcMessage* pmsg)
+{
+ #ifdef _DEBUG
+ DBGprintf( "Event: ERROR\n");
+ #endif
+
+// PopUp on ERROR
+ if(pmsg->m_bIncoming && prefs->PopupsEnabled && prefs->PopupsErrors)
+ {
+ if (pmsg->parameters.size() > 0)
+ ShowPopUpMsg(NULL, "Error", ansi_to_utf8(DoColorCodes(pmsg->parameters[0].c_str(), TRUE, FALSE)), LOG_ERROR);
+ else
+ ShowPopUpMsg(NULL, "Error", Translate("Unknown"), LOG_ERROR);
+ }
+
+ if(pmsg->m_bIncoming && !prefs->DisableErrorPopups ) {
+ MIRANDASYSTRAYNOTIFY msn;
+ msn.cbSize = sizeof(MIRANDASYSTRAYNOTIFY);
+ msn.szProto = IRCPROTONAME;
+ msn.szInfoTitle = Translate( "IRC error" );
+ String S;
+ if (pmsg->parameters.size() > 0)
+ S = DoColorCodes(pmsg->parameters[0].c_str(), TRUE, FALSE);
+ else
+ S = Translate( "Unknown" );
+ msn.szInfo = (char *)S.c_str();
+ msn.dwInfoFlags = NIIF_ERROR;
+ msn.uTimeout = 15000;
+ CallService(MS_CLIST_SYSTRAY_NOTIFY, (WPARAM)NULL,(LPARAM) &msn);
+ }
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_WHO_END(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: WHO END\n");
+// DBGprintf( "Nick -> %s\n", pmsg->parameters[1].c_str());
+// #endif
+
+ String command = GetNextUserhostReason(2);
+ if(command[0] == 'S')
+ {
+ if(pmsg->m_bIncoming && pmsg->parameters.size() > 1 )
+ {
+ // is it a channel?
+ if(IsChannel(pmsg->parameters[1]))
+ {
+ String S = "";
+ String SS = WhoReply;
+ String User = GetWord(WhoReply.c_str(), 0);
+ while (!User.empty())
+ {
+ if(GetWord(WhoReply.c_str(), 3)[0] == 'G')
+ {
+ S += User;
+ S += " ";
+ }
+ SS = GetWordAddress(WhoReply.c_str(), 4);
+ if(SS.empty())
+ break;
+ WhoReply = SS;
+ User = GetWord(WhoReply.c_str(), 0);
+ }
+ DoEvent(GC_EVENT_SETSTATUSEX, pmsg->parameters[1].c_str(), NULL, S == ""?NULL:S.c_str(), NULL, NULL, NULL, FALSE, FALSE);
+
+ return true;
+ }
+
+
+ /// if it is not a channel
+ char * UserList = new char [lstrlen(WhoReply.c_str())+2];
+ lstrcpyn(UserList, WhoReply.c_str(), lstrlen(WhoReply.c_str())+1);
+ char * p1= UserList;
+ WhoReply = "";
+ struct CONTACT_TYPE user ={(char *)pmsg->parameters[1].c_str(), NULL, NULL, false, true, false};
+ HANDLE hContact = CList_FindContact(&user);
+
+ if (hContact && DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 1)
+ {
+ char * DBDefault = NULL;
+ char * DBNick = NULL;
+ char * DBWildcard = NULL;
+ char * DBUser = NULL;
+ char * DBHost = NULL;
+ char * DBManUser = NULL;
+ char * DBManHost = NULL;
+ DBVARIANT dbv1;
+ DBVARIANT dbv2;
+ DBVARIANT dbv3;
+ DBVARIANT dbv4;
+ DBVARIANT dbv5;
+ DBVARIANT dbv6;
+ DBVARIANT dbv7;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv1) && dbv1.type == DBVT_ASCIIZ) DBDefault = dbv1.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Nick", &dbv2) && dbv2.type == DBVT_ASCIIZ) DBNick = dbv2.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv3) && dbv3.type == DBVT_ASCIIZ) DBWildcard = dbv3.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UUser", &dbv4) && dbv4.type == DBVT_ASCIIZ) DBUser = dbv4.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UHost", &dbv5) && dbv5.type == DBVT_ASCIIZ) DBHost = dbv5.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "User", &dbv6) && dbv6.type == DBVT_ASCIIZ) DBManUser = dbv6.pszVal;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Host", &dbv7) && dbv7.type == DBVT_ASCIIZ) DBManHost = dbv7.pszVal;
+ if (DBWildcard)
+ CharLower(DBWildcard);
+
+ String nick;
+ String user;
+ String host;
+ String away = GetWord(p1, 3);
+
+ while (away != "")
+ {
+ nick = GetWord(p1, 0);
+ user = GetWord(p1, 1);
+ host = GetWord(p1, 2);
+ if ((DBWildcard && WCCmp(DBWildcard, (char *)nick.c_str()) || DBNick && !lstrcmpi(DBNick, nick.c_str()) || DBDefault && !lstrcmpi(DBDefault, nick.c_str()))
+ && (WCCmp(DBUser, (char *)user.c_str()) &&WCCmp(DBHost, (char *)host.c_str())))
+ {
+ if (away[0] == 'G' && DBGetContactSettingWord(hContact,IRCPROTONAME, "Status", ID_STATUS_OFFLINE) != ID_STATUS_AWAY)
+ DBWriteContactSettingWord(hContact, IRCPROTONAME, "Status", ID_STATUS_AWAY);
+ else if (away[0] == 'H' && DBGetContactSettingWord(hContact,IRCPROTONAME, "Status", ID_STATUS_OFFLINE) != ID_STATUS_ONLINE)
+ DBWriteContactSettingWord(hContact, IRCPROTONAME, "Status", ID_STATUS_ONLINE);
+
+ if ((DBNick && lstrcmpi(nick.c_str(), DBNick)) || !DBNick)
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Nick", nick.c_str());
+ if ((DBManUser && lstrcmpi(user.c_str(), DBManUser)) || !DBManUser)
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "User", user.c_str());
+ if ((DBManHost &&lstrcmpi(host.c_str(), DBManHost)) || !DBManHost)
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Host", host.c_str());
+
+ if (DBDefault)
+ DBFreeVariant(&dbv1);
+ if (DBNick)
+ DBFreeVariant(&dbv2);
+ if (DBWildcard)
+ DBFreeVariant(&dbv3);
+ if (DBUser)
+ DBFreeVariant(&dbv4);
+ if (DBHost)
+ DBFreeVariant(&dbv5);
+ if (DBManUser)
+ DBFreeVariant(&dbv6);
+ if (DBManHost)
+ DBFreeVariant(&dbv7);
+
+ delete []UserList;
+
+ return true;
+
+ }
+ p1 = GetWordAddress(p1, 4);
+ away = GetWord(p1, 3);
+ }
+ if (DBWildcard && DBNick && !WCCmp(CharLower(DBWildcard), CharLower(DBNick)))
+ {
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Nick", DBDefault);
+
+
+ DoUserhostWithReason(2, ((String)"S" + DBWildcard).c_str(), true, DBWildcard);
+
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "User", "");
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Host", "");
+
+ if (DBDefault)
+ DBFreeVariant(&dbv1);
+ if (DBNick)
+ DBFreeVariant(&dbv2);
+ if (DBWildcard)
+ DBFreeVariant(&dbv3);
+ if (DBUser)
+ DBFreeVariant(&dbv4);
+ if (DBHost)
+ DBFreeVariant(&dbv5);
+ if (DBManUser)
+ DBFreeVariant(&dbv6);
+ if (DBManHost)
+ DBFreeVariant(&dbv7);
+
+ delete [] UserList;
+ return true;
+ }
+ if (DBGetContactSettingWord(hContact,IRCPROTONAME, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
+ {
+ DBWriteContactSettingWord(hContact, IRCPROTONAME, "Status", ID_STATUS_OFFLINE);
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Nick", DBDefault);
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "User", "");
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Host", "");
+ }
+
+ if (DBDefault)
+ DBFreeVariant(&dbv1);
+ if (DBNick)
+ DBFreeVariant(&dbv2);
+ if (DBWildcard)
+ DBFreeVariant(&dbv3);
+ if (DBUser)
+ DBFreeVariant(&dbv4);
+ if (DBHost)
+ DBFreeVariant(&dbv5);
+ if (DBManUser)
+ DBFreeVariant(&dbv6);
+ if (DBManHost)
+ DBFreeVariant(&dbv7);
+ }
+ delete []UserList;
+ }
+
+ }
+ else
+ ShowMessage(pmsg);
+
+ return true;
+}
+
+bool CMyMonitor::OnIrc_WHO_REPLY(const CIrcMessage* pmsg)
+{
+ String command = PeekAtReasons(2);
+ if(pmsg->m_bIncoming && pmsg->parameters.size() > 6 && command[0] == 'S') {
+ WhoReply += pmsg->parameters[5] + (String)" " +pmsg->parameters[2] + (String)" " + pmsg->parameters[3] + (String)" " + pmsg->parameters[6] + (String)" ";
+ if(lstrcmpi(pmsg->parameters[5].c_str(), m_session.GetInfo().sNick.c_str()) ==0)
+ {
+ static char host[1024];
+ lstrcpyn(host, pmsg->parameters[3].c_str(), 1024);
+ IPRESOLVE * ipr = new IPRESOLVE;
+ ipr->iType = IP_AUTO;
+ ipr->pszAdr = host;
+ forkthread(ResolveIPThread, NULL, ipr);
+ }
+ }
+
+ if (command[0] == 'U')
+ ShowMessage(pmsg);
+ return true;
+}
+bool CMyMonitor::OnIrc_TRYAGAIN(const CIrcMessage* pmsg)
+{
+ String command = "";
+ if(pmsg->m_bIncoming && pmsg->parameters.size() > 1 )
+ {
+ if(pmsg->parameters[1] == "WHO")
+ {
+ command = GetNextUserhostReason(2);
+ }
+ if(pmsg->parameters[1] == "USERHOST")
+ {
+ command = GetNextUserhostReason(1);
+ }
+ }
+ if (command[0] == 'U')
+ ShowMessage(pmsg);
+ return true;
+}
+
+bool CMyMonitor::OnIrc_USERHOST_REPLY(const CIrcMessage* pmsg)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: USERHOST REPLY\n");
+// DBGprintf( "Nick -> %s\n", pmsg->parameters[1].c_str());
+// #endif
+
+ String command = "";
+ if(pmsg->m_bIncoming)
+ {
+ // Get command
+ command = GetNextUserhostReason(1);
+ if(command != "" && command != "U" && pmsg->parameters.size() > 1)
+ {
+ CONTACT finduser = {NULL, NULL, NULL, false, false, false};
+ char * params = NULL;
+ char * next = NULL;
+ char * p1 = NULL;
+ char * p2 = NULL;
+ char awaystatus = 0;
+ String sTemp = "";
+ String host = "";
+ String user = "";
+ String nick = "";
+ String mask = "";
+ String mess = "";
+ String channel;
+ int i;
+ int j;
+
+ // Status-check pre-processing: Setup check-list
+ std::vector<String> checklist;
+ if(command[0] == 'S')
+ {
+ j = 0;
+ sTemp = GetWord(command.c_str(), 0);
+ sTemp.erase(0,1);
+ while(sTemp != "")
+ {
+ checklist.push_back(sTemp);
+ j++;
+ sTemp = GetWord(command.c_str(), j);
+ }
+
+ /*
+ params = new char[command.length()+1];
+ lstrcpyn(params, command.c_str() + 1, command.length());
+ for(p1 = GetWordAddress(params, 0); *p1; p1 = GetWordAddress(p1, 1)) {
+ p2 = next = GetWordAddress(p1, 1);
+ while(*(p2 - 1) == ' ')
+ p2--;
+ *p2 = '\0';
+ checklist.push_back(p1);
+ }
+ if(params)
+ delete [] params;
+ */
+ }
+
+ // Cycle through results
+// params = new char[pmsg->parameters[1].length()+2];
+// lstrcpyn(params, pmsg->parameters[1].c_str(), pmsg->parameters[1].length()+1);
+// for(p1 = GetWordAddress(params, 0); *p1; p1 = next)
+ j = 0;
+ sTemp = GetWord(pmsg->parameters[1].c_str(), j);
+ while (sTemp != "")
+ {
+// p2 = next = GetWordAddress(p1, 1);
+// while(*(p2 - 1) == ' ') p2--;
+// *p2 = '\0';
+ p1 = new char[sTemp.length()+1];
+ lstrcpyn(p1, sTemp.c_str(), sTemp.length()+1);
+ p2 = p1;
+
+ // Pull out host, user and nick
+ p2 = strchr(p1, '@');
+ if (p2)
+ {
+ *p2 = '\0';
+ p2++;
+ host = p2;
+ }
+ p2 = strchr(p1, '=');
+ if (p2)
+ {
+ *p2 = '\0';
+ p2++;
+ awaystatus = *p2;
+ p2++;
+ user = p2;
+ nick = p1;
+ }
+ mess = "";
+ mask = nick + "!" + user + "@" + host;
+ if(host == "" || user == "" || nick == "")
+ {
+ if(p1)
+ delete[] p1;
+ continue;
+ }
+
+ // Do command
+ switch (command[0])
+ {
+ case 'S': // Status check
+ HANDLE hContact;
+ finduser.name = (char *)nick.c_str();
+ finduser.host = (char *)host.c_str();
+ finduser.user = (char *)user.c_str();
+
+ hContact = CList_FindContact(&finduser);
+
+ if(hContact && DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 0)
+ {
+ DBWriteContactSettingWord(hContact, IRCPROTONAME, "Status", awaystatus == '-'? ID_STATUS_AWAY : ID_STATUS_ONLINE);
+
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "User", user.c_str());
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "Host", host.c_str());
+
+ if(DBGetContactSettingByte(NULL,IRCPROTONAME, "VersionAuto", 0) && DBGetContactSettingByte(hContact,IRCPROTONAME, "EnableVersion", 1) && DBGetContactSettingByte(hContact, IRCPROTONAME, "Version", 1))
+ {
+ PostIrcMessage( "/PRIVMSG %s \001VERSION\001", finduser.name);
+ DBWriteContactSettingByte(hContact, IRCPROTONAME, "Version", 0);
+ }
+
+ if(DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusEnabled", 0) && DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusAuto", 0) && DBGetContactSettingByte(hContact, IRCPROTONAME, "XStatus", 1))
+ {
+// #ifdef _DEBUG
+// DBGprintf("MirVer value = %s\n", IRCGetContactSettingString(hContact, "MirVer", "unknown"));
+// DBGprintf("MirVer compare = %d\n", strncmp(IRCGetContactSettingString(hContact, "MirVer", "unknown"), "Miranda IM", 10));
+// #endif
+ if(strstr(IRCGetContactSettingString(hContact, "MirVer", "unknown"), "Miranda IM"))
+ {
+// #ifdef _DEBUG
+// DBGprintf("XSTATUS REQUESTED from %s\n", finduser.name);
+// #endif
+ PostIrcMessage( "/PRIVMSG %s \001XSTATUS\001", finduser.name);
+ }
+ DBWriteContactSettingByte(hContact, IRCPROTONAME, "XStatus", 0);
+ }
+
+ // If user found, remove from checklist
+ for(i = 0; i < (int)checklist.size(); i++)
+ if(checklist[i] == nick)
+ checklist.erase(checklist.begin() + i);
+ }
+ break;
+
+ case 'I': // Ignore
+ mess = "/IGNORE %question=\"";
+ mess += Translate("Please enter the hostmask (nick!user@host)\nNOTE! Contacts on your contact list are never ignored");
+ mess += (String)"\",\"" + Translate("Ignore") + "\",\"*!*@" + host + "\"";
+ if(prefs->IgnoreChannelDefault)
+ mess += " +qnidcm";
+ else
+ mess += " +qnidc";
+ break;
+
+ case 'J': // Unignore
+ mess = "/UNIGNORE *!*@" + host;
+ break;
+
+ case 'B': // Ban
+ channel = (command.c_str() + 1);
+ mess = "/MODE " + channel + " +b *!*@" + host;
+ break;
+
+ case 'K': // Ban & Kick
+ channel = (command.c_str() + 1);
+ mess = "/MODE " + channel + " +b *!*@" + host + "%newl/KICK "+ channel + " " + nick;
+ break;
+
+ case 'L': // Ban & Kick with reason
+ channel = (command.c_str() + 1);
+ mess = "/MODE " + channel + " +b *!*@" + host + "%newl/KICK "+ channel + " " + nick + (String)" %question=\"";
+ mess += (String)Translate("Please enter the reason") + "\",\"" + Translate("Ban'n Kick") + "\",\"" + Translate("Jerk") + "\"";
+ break;
+ }
+
+ if(p1)
+ delete [] p1;
+
+ // Post message
+ if (mess != "")
+ PostIrcMessageWnd(NULL, NULL,(char *)mess.c_str());
+ j++;
+ sTemp = GetWord(pmsg->parameters[1].c_str(), j);
+ }
+
+ // Cleanup and exit
+// if(params) delete [] params;
+
+ // Status-check post-processing: make buddies in ckeck-list offline
+ if(command[0] == 'S')
+ {
+ for(i = 0; i < (int)checklist.size(); i++) {
+ finduser.name = (char *)checklist[i].c_str();
+ finduser.ExactNick = true;
+ CList_SetOffline(&finduser);
+ }
+ }
+ return true;
+ }
+ }
+ if(!pmsg->m_bIncoming || command =="U")
+ ShowMessage(pmsg);
+ return true;
+
+}
+bool CMyMonitor::OnIrc_SUPPORT(const CIrcMessage* pmsg)
+{
+ static const char* lpszFmt = "Try server %[^ ,], port %s";
+ char szAltServer[100];
+ char szAltPort[20];
+ if( pmsg->parameters.size() > 1 && sscanf(pmsg->parameters[1].c_str(), lpszFmt, &szAltServer, &szAltPort) == 2 )
+ {
+ ShowMessage(pmsg);
+ lstrcpyn(prefs->ServerName, szAltServer, 101);
+ lstrcpyn(prefs->PortStart, szAltPort, 9);
+
+ NoOfChannels = 0;
+ ConnectToServer();
+ return true;
+ }
+
+ if (pmsg->m_bIncoming && !bPerformDone) {
+ DoOnConnect(pmsg);
+ }
+
+
+ if (pmsg->m_bIncoming && pmsg->parameters.size() >0)
+ {
+ String S;
+ for( int i = 0; i < (int)pmsg->parameters.size();i++)
+ {
+ char * temp = new char[lstrlen(pmsg->parameters[i].c_str())+1];
+ strcpy(temp, pmsg->parameters[i].c_str());
+ if (strstr(temp, "CHANTYPES="))
+ {
+ char * p1 = strchr(temp, '=');
+ p1++;
+ if ( lstrlen(p1) > 0)
+ sChannelPrefixes = p1;
+ }
+ if (strstr(temp, "CHANMODES="))
+ {
+ char * p1 = strchr(temp, '=');
+ p1++;
+ if ( lstrlen(p1) > 0)
+ sChannelModes= p1;
+ }
+ if (strstr(temp, "PREFIX="))
+ {
+ char * p1 = strchr(temp, '(');
+ char * p2 = strchr(temp, ')');
+ if (p1 && p2)
+ {
+ p1++;
+ if (p1 != p2)
+ sUserModes = p1;
+ sUserModes = sUserModes.substr(0, p2-p1);
+ p2++;
+ if (*p2 != '\0')
+ sUserModePrefixes = p2;
+ }
+ else {
+ p1= strchr(temp, '=');
+ p1++;
+ sUserModePrefixes= p1;
+ for (int i =0; i < (int)sUserModePrefixes.length()+1; i++){
+ if (sUserModePrefixes[i] == '@')
+ sUserModes[i] = 'o';
+ else if (sUserModePrefixes[i] == '+')
+ sUserModes[i] = 'v';
+ else if (sUserModePrefixes[i] == '-')
+ sUserModes[i] = 'u';
+ else if (sUserModePrefixes[i] == '%')
+ sUserModes[i] = 'h';
+ else if (sUserModePrefixes[i] == '!')
+ sUserModes[i] = 'a';
+ else if (sUserModePrefixes[i] == '*')
+ sUserModes[i] = 'q';
+ else if (sUserModePrefixes[i] == '\0')
+ sUserModes[i] = '\0';
+ else
+ sUserModes[i] = '_';
+ }
+ }
+
+
+
+ }
+
+ delete[]temp;
+ }
+
+ }
+
+ ShowMessage(pmsg);
+ return true;
+}
+void CMyMonitor::OnIrcDefault(const CIrcMessage* pmsg)
+{
+ CIrcDefaultMonitor::OnIrcDefault(pmsg);
+ ShowMessage(pmsg);
+
+}
+
+void CMyMonitor::OnIrcDisconnected()
+{
+ CIrcDefaultMonitor::OnIrcDisconnected();
+ StatusMessage = "";
+ DBDeleteContactSetting(NULL, IRCPROTONAME, "JTemp");
+ bTempDisableCheck = false;
+ bTempForceCheck = false;
+ iTempCheckTime = 0;
+
+ prefs->MyHost[0] = '\0';
+
+ int Temp = OldStatus;
+ KillChatTimer(OnlineNotifTimer);
+ KillChatTimer(OnlineNotifTimer3);
+ KillChatTimer(KeepAliveTimer);
+ KillChatTimer(InitTimer);
+ KillChatTimer(IdentTimer);
+ OldStatus = ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(IRCPROTONAME,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)Temp, ID_STATUS_OFFLINE);
+ DoEvent(GC_EVENT_CHANGESESSIONAME, "Network log", NULL, Translate("Offline"), NULL, NULL, NULL, FALSE, TRUE);
+
+ String sDisconn = "\0035\002";
+ sDisconn += Translate("*Disconnected*");
+ DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, sDisconn.c_str(), NULL, NULL, NULL, true, false);
+
+ {
+ GCDEST gcd = {0};
+ GCEVENT gce = {0};
+
+ gce.cbSize = sizeof(GCEVENT);
+ gcd.pszID = NULL;
+ gcd.pszModule = IRCPROTONAME;
+ gcd.iType = GC_EVENT_CONTROL;
+ gce.pDest = &gcd;
+ CallChatEvent( SESSION_OFFLINE, (LPARAM)&gce);
+
+ }
+
+ if(!Miranda_Terminated())
+ CList_SetAllOffline(prefs->DisconnectDCCChats);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"Nick",prefs->Nick);
+
+ CLISTMENUITEM clmi;
+ memset( &clmi, 0, sizeof( clmi ));
+ clmi.cbSize = sizeof( clmi );
+ clmi.flags = CMIM_FLAGS|CMIF_GRAYED;
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuJoin, ( LPARAM )&clmi );
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuList, ( LPARAM )&clmi );
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuNick, ( LPARAM )&clmi );
+
+}
+
+
+bool DoOnConnect(const CIrcMessage *pmsg)
+{
+ bPerformDone= true;
+ nickflag = true;
+
+ CLISTMENUITEM clmi;
+ memset( &clmi, 0, sizeof( clmi ));
+ clmi.cbSize = sizeof( clmi );
+ clmi.flags = CMIM_FLAGS;
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuJoin, ( LPARAM )&clmi );
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuList, ( LPARAM )&clmi );
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuNick, ( LPARAM )&clmi );
+
+ int Temp = OldStatus;
+ OldStatus = ID_STATUS_ONLINE;
+ ProtoBroadcastAck(IRCPROTONAME,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)Temp,ID_STATUS_ONLINE);
+
+ if (StatusMessage != "")
+ {
+ String S = "/AWAY ";
+ S = S + StatusMessage;
+ S = ReplaceString( (char *)S.c_str(), "\r\n", " ");
+ PostIrcMessage((char *)S.c_str());
+ }
+ if(prefs->Perform)
+ {
+ DoPerform("ALL NETWORKS");
+ if (g_ircSession)
+ DoPerform((char*)g_ircSession.GetInfo().sNetwork.c_str());
+ }
+
+ if(prefs->RejoinChannels)
+ {
+ int count = (int)CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)IRCPROTONAME);
+
+ for (int i = 0; i < count ; i++)
+ {
+ GC_INFO gci = {0};
+ gci.Flags = BYINDEX|DATA|NAME|TYPE;
+ gci.iItem = i;
+ gci.pszModule = IRCPROTONAME;
+ if(!CallService(MS_GC_GETINFO, 0, (LPARAM)&gci) && gci.iType == GCW_CHATROOM)
+ {
+ CHANNELINFO* wi = (CHANNELINFO *)gci.dwItemData;
+ if (wi && wi->pszPassword)
+ PostIrcMessage("/JOIN %s %s", gci.pszName, wi->pszPassword);
+ else
+ PostIrcMessage("/JOIN %s", gci.pszName);
+ }
+ }
+ }
+
+ DoEvent(GC_EVENT_CHANGESESSIONAME, "Network log", NULL, g_ircSession.GetInfo().sNetwork.c_str(), NULL, NULL, NULL, FALSE, TRUE);
+ DoEvent(GC_EVENT_ADDGROUP, "Network log", NULL, NULL, "Normal", NULL, NULL, FALSE, TRUE);
+ {
+ GCDEST gcd = {0};
+ GCEVENT gce = {0};
+
+ gce.cbSize = sizeof(GCEVENT);
+ gcd.pszID = "Network log";
+ gcd.pszModule = IRCPROTONAME;
+ gcd.iType = GC_EVENT_CONTROL;
+ gce.pDest = &gcd;
+ CallChatEvent( SESSION_ONLINE, (LPARAM)&gce);
+
+ }
+ SetChatTimer(InitTimer, 1*1000, TimerProc);
+ if(prefs->IdentTimer)
+ SetChatTimer(IdentTimer, 60*1000, IdentTimerProc);
+ if (prefs->SendKeepAlive)
+ SetChatTimer(KeepAliveTimer, 60*1000, KeepAliveTimerProc);
+ if (prefs->AutoOnlineNotification && !bTempDisableCheck || bTempForceCheck)
+ {
+ SetChatTimer(OnlineNotifTimer, 1000, OnlineNotifTimerProc);
+ if(prefs->ChannelAwayNotification)
+ SetChatTimer(OnlineNotifTimer3, 3000, OnlineNotifTimerProc3);
+ }
+ return 0;
+
+}
+static void __cdecl AwayWarningThread(LPVOID di)
+{
+ MessageBox(NULL, Translate("The usage of /AWAY in your perform buffer is restricted\n as IRC sends this command automatically."), Translate("IRC Error"), MB_OK);
+}
+int DoPerform(char * event)
+{
+ if (!pszPerformFile)
+ return 0;
+ char * search = new char[lstrlen (event)+14];
+ mir_snprintf(search, lstrlen (event)+13, "NETWORK: %s", event);
+ char * p1 = my_strstri(pszPerformFile, search);
+ if (p1 != NULL)
+ {
+ char * p2 = strchr(p1, '\n');
+ if(!p2)
+ return 0;
+ p2 ++;
+ p1 = strstr(p2, "\nNETWORK: ");
+ if(!p1)
+ p1 = strchr(p2, '\0');
+ else
+ p1--;
+ while(p1 > p2 && ( p1[-1] == ' ' || p1[-1] == '\n' || p1[-1] == '\r' || p1[-1] == '\0'))
+ p1--;
+ if(p2 >= p1)
+ return 0;
+ char * DoThis = new char[p1-p2+1];
+ lstrcpyn(DoThis, p2, p1-p2+1);
+
+ if(!my_strstri(DoThis, "/away"))
+ PostIrcMessageWnd(NULL, NULL, (char *)DoThis);
+ else
+ forkthread(AwayWarningThread, NULL, NULL );
+ delete [] DoThis;
+ delete [] search;
+ return 1;
+ }
+ delete [] search;
+ return 0;
+}
+
+
+
+char * IsIgnored(String nick, String address, String host, char type)
+{
+ String user = nick + "!" + address + "@" + host;
+ return IsIgnored(user, type);
+}
+
+char * IsIgnored(String user, char type)
+{
+ if (pszIgnoreFile)
+ {
+ char * p1 = pszIgnoreFile;
+ char * p2 = p1;
+ char * pTemp = NULL;
+ while (*p1 != '\0')
+ {
+ while(*p1 == '\r' || *p1 == '\n')
+ p1++;
+ if (*p1 == '\0')
+ return 0;
+ p2 = strstr(p1, "\r\n");
+ if (!p2)
+ p2 = strchr(p1, '\0');
+ pTemp = p2;
+ while (pTemp > p1 && (*pTemp == '\r' || *pTemp == '\n' ||*pTemp == '\0' || *pTemp == ' '))
+ pTemp--;
+ pTemp++;
+
+ char * p3= new char[pTemp-p1+1];
+ lstrcpyn(p3, p1, pTemp-p1+1);
+
+ if(type == '\0')
+ {
+ if(!lstrcmpi(user.c_str(),(char *)GetWord(p3, 0).c_str()))
+ {
+ delete [] p3;
+ return p1;
+ }
+ }
+ bool bUserContainsWild = strchr(user.c_str(), '*') == NULL ?false:true || strchr(user.c_str(), '?') == NULL?false:true;
+
+ if( !bUserContainsWild && WCCmp((char *)GetWord(p3, 0).c_str(), (char *)user.c_str())
+ || bUserContainsWild && !lstrcmpi(user.c_str(),(char *)GetWord(p3, 0).c_str()))
+ {
+ if(GetWord(p3, 1) == "" || GetWord(p3, 1)[0] != '+')
+ {
+ goto IGNORELABEL;
+ }
+ if(!strchr(GetWord(p3, 1).c_str(), type))
+ {
+ goto IGNORELABEL;
+ }
+ if(GetWord(p3, 2) == "")
+ {
+ delete [] p3;
+ return p1;
+ }
+ if (g_ircSession && !lstrcmpi(GetWordAddress(p3, 2), g_ircSession.GetInfo().sNetwork.c_str()))
+ {
+ delete [] p3;
+ return p1;
+ }
+
+
+ }
+IGNORELABEL:
+ delete [] p3;
+ p1 = p2;
+
+ }
+
+ }
+ return NULL;
+}
+
+bool AddIgnore(String mask, String mode, String network)
+{
+ RemoveIgnore(mask);
+ String S = mask + " +" + mode + " " + network + "\r\n";
+ if (pszIgnoreFile)
+ S += pszIgnoreFile;
+
+ char filepath[MAX_PATH];
+ mir_snprintf(filepath, sizeof(filepath), "%s\\%s_ignore.ini", mirandapath, IRCPROTONAME);
+ FILE *hFile = fopen(filepath,"wb");
+ if (hFile)
+ {
+ fputs(S.c_str(), hFile);
+ fclose(hFile);
+
+ }
+ if (pszIgnoreFile)
+ delete [] pszIgnoreFile;
+ pszIgnoreFile = IrcLoadFile(filepath);
+ if(IgnoreWndHwnd)
+ SendMessage(IgnoreWndHwnd, IRC_REBUILDIGNORELIST, 0, 0);
+ return true;
+}
+
+bool RemoveIgnore(String mask)
+{
+ char * p1 = IsIgnored(mask, '\0');
+ if (!p1)
+ return false;
+ while (p1)
+ {
+ char * p2 = strstr(p1, "\r\n");
+ if (!p2)
+ p2 = strchr(p1, '\0');
+ else
+ p2 +=2;
+
+ for (int i=0;;i++)
+ {
+ p1[i] = p2[i];
+ if (p1[i] == '\0')
+ break;
+ }
+
+ char filepath[MAX_PATH];
+ mir_snprintf(filepath, sizeof(filepath), "%s\\%s_ignore.ini", mirandapath, IRCPROTONAME);
+ FILE *hFile = fopen(filepath,"wb");
+ if (hFile)
+ {
+ fputs(pszIgnoreFile, hFile);
+ fclose(hFile);
+
+ }
+ if (pszIgnoreFile)
+ delete [] pszIgnoreFile;
+ pszIgnoreFile = IrcLoadFile(filepath);
+ p1 = IsIgnored(mask, '\0');
+
+ }
+ if(IgnoreWndHwnd)
+ SendMessage(IgnoreWndHwnd, IRC_REBUILDIGNORELIST, 0, 0);
+ return true;
+}
+
+
+
+
diff --git a/irc_mod/commandmonitor.h b/irc_mod/commandmonitor.h
new file mode 100644
index 0000000..462dd70
--- /dev/null
+++ b/irc_mod/commandmonitor.h
@@ -0,0 +1,105 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+extern irc::CIrcSession g_ircSession;
+extern HINSTANCE g_hInstance;
+extern HWND server_hWnd;
+using namespace irc;
+
+bool DoOnConnect(const CIrcMessage *pmsg);
+int DoPerform(char * event);
+char * IsIgnored(String nick, String address, String host, char type) ;
+char * IsIgnored(String user, char type) ;
+bool AddIgnore(String mask, String mode, String network) ;
+bool RemoveIgnore(String mask) ;
+void __cdecl ResolveIPThread(LPVOID di);
+
+class CMyMonitor : public CIrcDefaultMonitor
+{
+protected:
+
+public:
+ CMyMonitor();
+ virtual ~CMyMonitor();
+
+ bool OnIrc_WELCOME(const CIrcMessage* pmsg);
+ bool OnIrc_YOURHOST(const CIrcMessage* pmsg);
+ bool OnIrc_NICK(const CIrcMessage* pmsg);
+ bool OnIrc_PRIVMSG(const CIrcMessage* pmsg);
+ bool OnIrc_JOIN(const CIrcMessage* pmsg);
+ bool OnIrc_QUIT(const CIrcMessage* pmsg);
+ bool OnIrc_PART(const CIrcMessage* pmsg);
+ bool OnIrc_KICK(const CIrcMessage* pmsg);
+ bool OnIrc_MODE(const CIrcMessage* pmsg);
+ bool OnIrc_USERHOST_REPLY(const CIrcMessage* pmsg);
+ bool OnIrc_MODEQUERY(const CIrcMessage* pmsg);
+ bool OnIrc_NAMES(const CIrcMessage* pmsg);
+ bool OnIrc_ENDNAMES(const CIrcMessage* pmsg);
+ bool OnIrc_INITIALTOPIC(const CIrcMessage* pmsg);
+ bool OnIrc_INITIALTOPICNAME(const CIrcMessage* pmsg);
+ bool OnIrc_TOPIC(const CIrcMessage* pmsg);
+ bool OnIrc_TRYAGAIN(const CIrcMessage* pmsg);
+ bool OnIrc_NOTICE(const CIrcMessage* pmsg);
+ bool OnIrc_WHOIS_NAME(const CIrcMessage* pmsg);
+ bool OnIrc_WHOIS_CHANNELS(const CIrcMessage* pmsg);
+ bool OnIrc_WHOIS_SERVER(const CIrcMessage* pmsg);
+ bool OnIrc_WHOIS_AWAY(const CIrcMessage* pmsg);
+ bool OnIrc_WHOIS_IDLE(const CIrcMessage* pmsg);
+ bool OnIrc_WHOIS_END(const CIrcMessage* pmsg);
+ bool OnIrc_WHOIS_OTHER(const CIrcMessage* pmsg);
+ bool OnIrc_WHOIS_AUTH(const CIrcMessage* pmsg);
+ bool OnIrc_WHOIS_NO_USER(const CIrcMessage* pmsg);
+ bool OnIrc_NICK_ERR(const CIrcMessage* pmsg);
+ bool OnIrc_ENDMOTD(const CIrcMessage* pmsg);
+ bool OnIrc_LISTSTART(const CIrcMessage* pmsg);
+ bool OnIrc_LIST(const CIrcMessage* pmsg);
+ bool OnIrc_LISTEND(const CIrcMessage* pmsg);
+ bool OnIrc_BANLIST(const CIrcMessage* pmsg);
+ bool OnIrc_BANLISTEND(const CIrcMessage* pmsg);
+ bool OnIrc_SUPPORT(const CIrcMessage* pmsg);
+ bool OnIrc_BACKFROMAWAY(const CIrcMessage* pmsg);
+ bool OnIrc_SETAWAY(const CIrcMessage* pmsg);
+ bool OnIrc_JOINERROR(const CIrcMessage* pmsg);
+ bool OnIrc_UNKNOWN(const CIrcMessage* pmsg);
+ bool OnIrc_ERROR(const CIrcMessage* pmsg);
+ bool OnIrc_NOOFCHANNELS(const CIrcMessage* pmsg);
+ bool OnIrc_PINGPONG(const CIrcMessage* pmsg);
+ bool OnIrc_INVITE(const CIrcMessage* pmsg);
+ bool OnIrc_WHO_END(const CIrcMessage* pmsg);
+ bool OnIrc_WHO_REPLY(const CIrcMessage* pmsg);
+ bool OnIrc_WHOTOOLONG(const CIrcMessage* pmsg);
+
+ bool IsCTCP(const CIrcMessage* pmsg);
+
+
+ virtual void OnIrcDefault(const CIrcMessage* pmsg);
+
+ virtual void OnIrcDisconnected();
+
+ DEFINE_IRC_MAP()
+
+
+private:
+
+
+;
+
+};
+
diff --git a/irc_mod/i18n.cpp b/irc_mod/i18n.cpp
new file mode 100644
index 0000000..71b39b8
--- /dev/null
+++ b/irc_mod/i18n.cpp
@@ -0,0 +1,461 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// Contains helper functions to convert text messages between different
+// character sets.
+
+#include "irc.h"
+
+static BOOL bHasCP_UTF8 = FALSE;
+
+void InitI18N(void)
+{
+ CPINFO CPInfo;
+ bHasCP_UTF8 = GetCPInfo(CP_UTF8, &CPInfo);
+ #ifdef _DEBUG
+ DBGprintf("HasCP_UTF8 = %d\n", bHasCP_UTF8);
+ #endif
+
+}
+
+// Returns true if the buffer only contains 7-bit characters.
+BOOL IsUSASCII(const unsigned char* pBuffer, int nSize)
+{
+ BOOL bResult = TRUE;
+ int nIndex;
+
+ for (nIndex = 0; nIndex < nSize; nIndex++)
+ {
+ if (pBuffer[nIndex] > 0x7F)
+ {
+ bResult = FALSE;
+ break;
+ }
+ }
+
+ return bResult;
+}
+
+// Returns true if the unicode buffer only contains 7-bit characters.
+BOOL IsUnicodeAscii(const wchar_t* pBuffer, int nSize)
+{
+ BOOL bResult = TRUE;
+ int nIndex;
+
+
+ for (nIndex = 0; nIndex < nSize; nIndex++)
+ {
+ if (pBuffer[nIndex] > 0x7F)
+ {
+ bResult = FALSE;
+ break;
+ }
+ }
+
+ return bResult;
+}
+
+
+// Scans a string encoded in UTF-8 to verify that it contains
+// only valid sequences. It will return 1 if the string contains
+// only legitimate encoding sequences; otherwise it will return 0;
+// From 'Secure Programming Cookbook', John Viega & Matt Messier, 2003
+int UTF8_IsValid(const unsigned char* pszInput)
+{
+ int nb, i;
+ const unsigned char* c = pszInput;
+
+
+ for (c = pszInput; *c; c += (nb + 1))
+ {
+ if (!(*c & 0x80))
+ nb = 0;
+ else if ((*c & 0xc0) == 0x80) return 0;
+ else if ((*c & 0xe0) == 0xc0) nb = 1;
+ else if ((*c & 0xf0) == 0xe0) nb = 2;
+ else if ((*c & 0xf8) == 0xf0) nb = 3;
+ else if ((*c & 0xfc) == 0xf8) nb = 4;
+ else if ((*c & 0xfe) == 0xfc) nb = 5;
+
+ for (i = 1; i<=nb; i++) // we this forward, do not cross end of string
+ if ((*(c + i) & 0xc0) != 0x80)
+ return 0;
+ }
+
+ return 1;
+}
+
+
+// returns ansi string in all cases
+char* detect_decode_utf8(const char *from)
+{
+ char* temp = NULL;
+
+ if (IsUSASCII((unsigned char *)from, strlennull(from)) || !UTF8_IsValid((const unsigned char *)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.
+ */
+unsigned char *make_utf8_string(const wchar_t *unicode)
+{
+ int size = 0;
+ int index = 0;
+ int out_index = 0;
+ unsigned char* out;
+ unsigned short c;
+
+
+ /* first calculate the size of the target string */
+ c = unicode[index++];
+ while (c)
+ {
+ if (c < 0x0080)
+ size += 1;
+ else if (c < 0x0800)
+ size += 2;
+ else
+ size += 3;
+ c = unicode[index++];
+ }
+
+ out = (unsigned char *)malloc(size + 1);
+ if (out == NULL)
+ return NULL;
+ index = 0;
+
+ c = unicode[index++];
+ while (c)
+ {
+ if (c < 0x080)
+ {
+ out[out_index++] = (unsigned char)c;
+ }
+ else if (c < 0x800)
+ {
+ out[out_index++] = 0xc0 | (c >> 6);
+ out[out_index++] = 0x80 | (c & 0x3f);
+ }
+ else
+ {
+ out[out_index++] = 0xe0 | (c >> 12);
+ out[out_index++] = 0x80 | ((c >> 6) & 0x3f);
+ out[out_index++] = 0x80 | (c & 0x3f);
+ }
+ c = unicode[index++];
+ }
+ out[out_index] = 0x00;
+
+ return out;
+}
+
+
+
+wchar_t *make_unicode_string(const unsigned char *utf8)
+{
+ int size = 0, index = 0, out_index = 0;
+ wchar_t *out;
+ unsigned char c;
+
+ /* first calculate the size of the target string */
+ c = utf8[index++];
+ while (c)
+ {
+ if ((c & 0x80) == 0)
+ {
+ index += 0;
+ }
+ else if ((c & 0xe0) == 0xe0)
+ {
+ index += 2;
+ }
+ else
+ {
+ index += 1;
+ }
+ size += 1;
+ c = utf8[index++];
+ }
+
+ out = (wchar_t *)malloc((size + 1) * sizeof(wchar_t));
+ if (out == NULL)
+ return NULL;
+ index = 0;
+
+ c = utf8[index++];
+ while (c)
+ {
+ if((c & 0x80) == 0)
+ {
+ out[out_index++] = c;
+ }
+ else if((c & 0xe0) == 0xe0)
+ {
+ out[out_index] = (c & 0x1F) << 12;
+ c = utf8[index++];
+ out[out_index] |= (c & 0x3F) << 6;
+ c = utf8[index++];
+ out[out_index++] |= (c & 0x3F);
+ }
+ else
+ {
+ out[out_index] = (c & 0x3F) << 6;
+ c = utf8[index++];
+ out[out_index++] |= (c & 0x3F);
+ }
+ c = utf8[index++];
+ }
+ out[out_index] = 0;
+
+ return out;
+}
+
+
+
+int utf8_encode(const char *from, char **to)
+{
+ wchar_t *unicode;
+ int wchars, err;
+
+
+ wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
+ strlennull(from), NULL, 0);
+
+ if (wchars == 0)
+ {
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+ return -1;
+ }
+
+ unicode = (wchar_t*)_alloca((wchars + 1) * sizeof(unsigned short));
+ unicode[wchars] = 0;
+
+ err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
+ strlennull(from), unicode, wchars);
+ if(err != wchars)
+ {
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+ return -1;
+ }
+
+ /* On NT-based windows systems, we could use WideCharToMultiByte(), but
+ * MS doesn't actually have a consistent API across win32.
+ */
+ *to = (char*)make_utf8_string(unicode);
+
+ return 0;
+}
+
+
+
+char *ansi_to_utf8(const char *szAnsi)
+{
+ char *szUtf;
+
+ if (strlennull(szAnsi))
+ {
+ utf8_encode(szAnsi, &szUtf);
+
+ return szUtf;
+ }
+ else
+ return null_strdup("");
+}
+
+
+
+char *ansi_to_utf8_codepage(const char *szAnsi, WORD wCp)
+{
+ wchar_t *unicode;
+ int wchars = strlennull(szAnsi);
+
+ unicode = (wchar_t*)_alloca((wchars + 1) * sizeof(wchar_t));
+ unicode[wchars] = 0;
+
+ MultiByteToWideChar(wCp, MB_PRECOMPOSED, szAnsi, wchars, unicode, wchars);
+
+ return (char*)make_utf8_string(unicode);
+}
+
+
+
+// Returns 0 on error, 1 on success
+int utf8_decode(const char *from, char **to)
+{
+ int nResult = 0;
+
+ _ASSERTE(!(*to)); // You passed a non-zero pointer, make sure it doesnt point to unfreed memory
+
+ // Validate the string
+ if (!UTF8_IsValid((const unsigned char *)from))
+ return 0;
+
+ // Use the native conversion routines when available
+ if (bHasCP_UTF8)
+ {
+ WCHAR *wszTemp = NULL;
+ int inlen = strlennull(from);
+
+ wszTemp = (WCHAR *)_alloca(sizeof(WCHAR) * (inlen + 1));
+
+ // Convert the UTF-8 string to UCS
+ if (MultiByteToWideChar(CP_UTF8, 0, from, -1, wszTemp, inlen + 1))
+ {
+ // Convert the UCS string to local ANSI codepage
+ *to = (char*)malloc(inlen+1);
+ if (WideCharToMultiByte(CP_ACP, 0, wszTemp, -1, *to, inlen+1, NULL, NULL))
+ {
+ nResult = 1;
+ }
+ else
+ {
+ SAFE_FREE((void **)&(*to));
+ }
+ }
+ }
+ else
+ {
+ wchar_t *unicode;
+ int chars;
+ int err;
+
+ unicode = make_unicode_string((const unsigned char *)from);
+ if(unicode == NULL)
+ {
+ fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n");
+ return 0;
+ }
+
+ chars = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL);
+
+ if(chars == 0)
+ {
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+ SAFE_FREE((void **)&unicode);
+ return 0;
+ }
+
+// *to = calloc(chars + 1, sizeof(unsigned char));
+ if(*to == NULL)
+ {
+ fprintf(stderr, "Out of memory processing string to local charset\n");
+ SAFE_FREE((void **)&unicode);
+ return 0;
+ }
+
+ err = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL);
+ if (err != chars)
+ {
+ fprintf(stderr, "Unicode translation error %d\n", GetLastError());
+ SAFE_FREE((void **)&unicode);
+ SAFE_FREE((void **)to);
+ return 0;
+ }
+
+ SAFE_FREE((void **)&unicode);
+
+ nResult = 1;
+ }
+
+ return nResult;
+}
+
+
+
+// Returns 0 on error, 1 on success
+int utf8_decode_static(const char *from, char *to, int to_size)
+{
+ int nResult = 0;
+
+ _ASSERTE(to); // You passed a zero pointer
+
+ // Validate the string
+ if (!UTF8_IsValid((const unsigned char *)from))
+ return 0;
+
+ // Use the native conversion routines when available
+ if (bHasCP_UTF8)
+ {
+ WCHAR *wszTemp = NULL;
+ int inlen = strlennull(from);
+
+ wszTemp = (WCHAR *)_alloca(sizeof(WCHAR) * (inlen + 1));
+
+ // Convert the UTF-8 string to UCS
+ if (MultiByteToWideChar(CP_UTF8, 0, from, -1, wszTemp, inlen + 1))
+ {
+ // Convert the UCS string to local ANSI codepage
+ if (WideCharToMultiByte(CP_ACP, 0, wszTemp, -1, to, to_size, NULL, NULL))
+ {
+ nResult = 1;
+ }
+ }
+ }
+ else
+ {
+ wchar_t *unicode = make_unicode_string((const unsigned char *)from);
+
+ if (unicode == NULL)
+ {
+ fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n");
+ return 0;
+ }
+
+ WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, to, to_size, NULL, NULL);
+
+ SAFE_FREE((void **)&unicode);
+
+ nResult = 1;
+ }
+
+ return nResult;
+}
diff --git a/irc_mod/i18n.h b/irc_mod/i18n.h
new file mode 100644
index 0000000..e408083
--- /dev/null
+++ b/irc_mod/i18n.h
@@ -0,0 +1,55 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/i18n.h,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-17 01:38:00 +0400 (Ср, 17 май 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Helper functions to convert text messages between different character sets.
+//
+// -----------------------------------------------------------------------------
+
+
+
+BOOL IsUSASCII(const unsigned char *pBuffer, int nSize);
+BOOL IsUnicodeAscii(const wchar_t *pBuffer, int nSize);
+int UTF8_IsValid(const unsigned char* pszInput);
+
+char* detect_decode_utf8(const char *from);
+
+wchar_t *make_unicode_string(const unsigned char *utf8);
+
+unsigned char *make_utf8_string(const wchar_t *unicode);
+
+int utf8_encode(const char *from, char **to);
+char *ansi_to_utf8(const char *szAnsi);
+char *ansi_to_utf8_codepage(const char *szAnsi, WORD wCp);
+int utf8_decode(const char *from, char **to);
+int utf8_decode_static(const char *from, char *to, int to_size);
+
+void InitI18N(void);
diff --git a/irc_mod/iconlib.cpp b/irc_mod/iconlib.cpp
new file mode 100644
index 0000000..b85838b
--- /dev/null
+++ b/irc_mod/iconlib.cpp
@@ -0,0 +1,118 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/iconlib.c,v $
+// Revision : $Revision: 1.6 $
+// Last change on : $Date: 2006/03/23 23:32:15 $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Support for IcoLib plug-in
+//
+// -----------------------------------------------------------------------------
+
+#include "irc.h"
+
+static int bIcoReady = 0;
+static int bIcoUtf = 0;
+
+extern char * IRCPROTONAME;
+
+void InitIconLib()
+{ // check plugin presence, init variables
+ bIcoReady = ServiceExists(MS_SKIN2_GETICON);
+ if (bIcoReady)
+ {
+ SKINICONDESC sid = {0};
+
+ if (CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid) >= PLUGIN_MAKE_VERSION(0,0,1,0))
+ bIcoUtf = 1;
+ }
+}
+
+int IconLibInstalled()
+{
+ return bIcoReady;
+}
+
+void IconLibDefine(const char* desc, const char* section, const char* ident, HICON icon)
+{
+ if (bIcoReady)
+ {
+ SKINICONDESC sid = {0};
+ char szTemp[MAX_PATH + 128];
+
+ if (bIcoUtf)
+ {
+ sid.cbSize = SKINICONDESC_SIZE;
+ sid.pwszSection = make_unicode_string((const unsigned char *)section);
+ sid.pwszDescription = make_unicode_string((const unsigned char *)desc);
+ sid.flags = SIDF_UNICODE;
+ }
+ else
+ {
+ sid.cbSize = SKINICONDESC_SIZE_V3;
+ utf8_decode(section, &sid.pszSection);
+ utf8_decode(desc, &sid.pszDescription);
+ }
+
+ sid.pszDefaultFile = NULL;
+ null_snprintf(szTemp, sizeof(szTemp), "%s_%s", IRCPROTONAME, ident);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = 0;
+ sid.hDefaultIcon = icon;
+ sid.cx = sid.cy = 16;
+
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ SAFE_FREE((void **)&sid.pwszSection);
+ SAFE_FREE((void **)&sid.pwszDescription);
+ }
+}
+
+HICON IconLibProcess(HICON icon, const char* ident)
+{
+ if (bIcoReady)
+ {
+ char szTemp[MAX_PATH + 128];
+ HICON hNew;
+
+ null_snprintf(szTemp, sizeof(szTemp), "%s_%s", IRCPROTONAME, ident);
+ hNew = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szTemp);
+ if (hNew) return hNew;
+ }
+
+ return icon;
+}
+
+HANDLE IconLibHookIconsChanged(MIRANDAHOOK hook)
+{
+ if (bIcoReady)
+ {
+ return HookEvent(ME_SKIN2_ICONSCHANGED, hook);
+ }
+ return NULL;
+} \ No newline at end of file
diff --git a/irc_mod/iconlib.h b/irc_mod/iconlib.h
new file mode 100644
index 0000000..dac7825
--- /dev/null
+++ b/irc_mod/iconlib.h
@@ -0,0 +1,37 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//
+// Headers for IconLib Plugin support
+//
+
+#ifndef __ICONLIB_H
+#define __ICONLIB_H
+
+void InitIconLib();
+
+int IconLibInstalled();
+
+void IconLibDefine(const char* desc, const char* section, const char* ident, HICON icon);
+HICON IconLibProcess(HICON icon, const char* ident);
+HANDLE IconLibHookIconsChanged(MIRANDAHOOK hook);
+
+
+#endif /* __ICONLIB_H */
diff --git a/irc_mod/icons_pack/ICONS.rc b/irc_mod/icons_pack/ICONS.rc
new file mode 100644
index 0000000..a8902a7
--- /dev/null
+++ b/irc_mod/icons_pack/ICONS.rc
@@ -0,0 +1,78 @@
+//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 "..\\icons\\xstatus01.ico"
+IDI_XSTATUS2 ICON DISCARDABLE "..\\icons\\xstatus02.ico"
+IDI_XSTATUS3 ICON DISCARDABLE "..\\icons\\xstatus03.ico"
+IDI_XSTATUS4 ICON DISCARDABLE "..\\icons\\xstatus04.ico"
+IDI_XSTATUS5 ICON DISCARDABLE "..\\icons\\xstatus05.ico"
+IDI_XSTATUS6 ICON DISCARDABLE "..\\icons\\xstatus06.ico"
+IDI_XSTATUS7 ICON DISCARDABLE "..\\icons\\xstatus07.ico"
+IDI_XSTATUS8 ICON DISCARDABLE "..\\icons\\xstatus08.ico"
+IDI_XSTATUS9 ICON DISCARDABLE "..\\icons\\xstatus09.ico"
+IDI_XSTATUS10 ICON DISCARDABLE "..\\icons\\xstatus10.ico"
+IDI_XSTATUS11 ICON DISCARDABLE "..\\icons\\xstatus11.ico"
+IDI_XSTATUS12 ICON DISCARDABLE "..\\icons\\xstatus12.ico"
+IDI_XSTATUS13 ICON DISCARDABLE "..\\icons\\xstatus13.ico"
+IDI_XSTATUS14 ICON DISCARDABLE "..\\icons\\xstatus14.ico"
+IDI_XSTATUS15 ICON DISCARDABLE "..\\icons\\xstatus15.ico"
+IDI_XSTATUS16 ICON DISCARDABLE "..\\icons\\xstatus16.ico"
+IDI_XSTATUS17 ICON DISCARDABLE "..\\icons\\xstatus17.ico"
+IDI_XSTATUS18 ICON DISCARDABLE "..\\icons\\xstatus18.ico"
+IDI_XSTATUS19 ICON DISCARDABLE "..\\icons\\xstatus19.ico"
+IDI_XSTATUS20 ICON DISCARDABLE "..\\icons\\xstatus20.ico"
+IDI_XSTATUS21 ICON DISCARDABLE "..\\icons\\xstatus21.ico"
+IDI_XSTATUS22 ICON DISCARDABLE "..\\icons\\xstatus22.ico"
+IDI_XSTATUS23 ICON DISCARDABLE "..\\icons\\xstatus23.ico"
+IDI_XSTATUS24 ICON DISCARDABLE "..\\icons\\xstatus24.ico"
+IDI_XSTATUS25 ICON DISCARDABLE "..\\icons\\xstatus25.ico"
+IDI_XSTATUS26 ICON DISCARDABLE "..\\icons\\xstatus26.ico"
+IDI_XSTATUS27 ICON DISCARDABLE "..\\icons\\xstatus27.ico"
+IDI_XSTATUS28 ICON DISCARDABLE "..\\icons\\xstatus28.ico"
+IDI_XSTATUS29 ICON DISCARDABLE "..\\icons\\xstatus29.ico"
+IDI_XSTATUS30 ICON DISCARDABLE "..\\icons\\xstatus30.ico"
+IDI_XSTATUS31 ICON DISCARDABLE "..\\icons\\xstatus31.ico"
+IDI_XSTATUS32 ICON DISCARDABLE "..\\icons\\xstatus32.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_IDENTIFY "# Custom Status Icons #"
+END
+
+
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
diff --git a/irc_mod/icons_pack/ICONS.sln b/irc_mod/icons_pack/ICONS.sln
new file mode 100644
index 0000000..96a605b
--- /dev/null
+++ b/irc_mod/icons_pack/ICONS.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ICONS", "ICONS.vcproj", "{84471097-C974-45CD-845E-828B304195B8}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {84471097-C974-45CD-845E-828B304195B8}.Release|Win32.ActiveCfg = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/irc_mod/icons_pack/ICONS.vcproj b/irc_mod/icons_pack/ICONS.vcproj
new file mode 100644
index 0000000..67b49e0
--- /dev/null
+++ b/irc_mod/icons_pack/ICONS.vcproj
@@ -0,0 +1,349 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="ICONS"
+ ProjectGUID="{84471097-C974-45CD-845E-828B304195B8}"
+ RootNamespace="ICONS"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../bin/release/icons/"
+ IntermediateDirectory="../../bin/release/icons/"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/ICONS.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="4"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ICONS_EXPORTS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="stdafx.h"
+ PrecompiledHeaderFile=".\Release/ICONS.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="odbc32.lib odbccp32.lib"
+ OutputFile="..\..\..\bin\release\plugins\xstatus_icons.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="../../bin/release/icons/ICQ_icons.pdb"
+ ResourceOnlyDLL="true"
+ ImportLibrary="../../bin/release/icons/ICQ_icons.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile="../../bin/release/icons/ICONS.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug Unicode|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/ICONS.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="4"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ICONS_EXPORTS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="stdafx.h"
+ PrecompiledHeaderFile=".\Release/ICONS.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="odbc32.lib odbccp32.lib"
+ OutputFile="..\..\..\bin\release\plugins\xstatus_icons.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="../../bin/release/icons/ICQ_icons.pdb"
+ ResourceOnlyDLL="true"
+ ImportLibrary="../../bin/release/icons/ICQ_icons.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile="../../bin/release/icons/ICONS.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ >
+ <File
+ RelativePath="ICONS.rc"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus01.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus02.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus03.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus04.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus05.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus06.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus07.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus08.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus09.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus10.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus11.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus12.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus13.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus14.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus15.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus16.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus17.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus18.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus19.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus20.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus21.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus22.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus23.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus24.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus25.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus26.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus27.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus28.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus29.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus30.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus31.ico"
+ >
+ </File>
+ <File
+ RelativePath="..\icons\xstatus32.ico"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/irc_mod/icons_pack/ICONS7.sln b/irc_mod/icons_pack/ICONS7.sln
new file mode 100644
index 0000000..eb2b3ef
--- /dev/null
+++ b/irc_mod/icons_pack/ICONS7.sln
@@ -0,0 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ICONS", "ICONS7.vcproj", "{84471097-C974-45CD-845E-828B304195B8}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {84471097-C974-45CD-845E-828B304195B8}.Release.ActiveCfg = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {84471097-C974-45CD-845E-828B304195B8}.Release|Win32.ActiveCfg = Release|Win32
+ {84471097-C974-45CD-845E-828B304195B8}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/irc_mod/icons_pack/ICONS7.vcproj b/irc_mod/icons_pack/ICONS7.vcproj
new file mode 100644
index 0000000..718b56d
--- /dev/null
+++ b/irc_mod/icons_pack/ICONS7.vcproj
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="ICONS"
+ ProjectGUID="{84471097-C974-45CD-845E-828B304195B8}"
+ RootNamespace="ICONS">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../../bin/release/icons/"
+ IntermediateDirectory="../../../bin/release/icons/"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="4"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ICONS_EXPORTS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="stdafx.h"
+ PrecompiledHeaderFile=".\Release/ICONS.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/ALIGN:4096 /ignore:4108"
+ AdditionalDependencies="odbc32.lib odbccp32.lib"
+ OutputFile="..\..\..\bin\release\plugins\xstatus_icons.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="../../bin/release/icons/ICQ_icons.pdb"
+ ResourceOnlyDLL="TRUE"
+ ImportLibrary="../../bin/release/icons/ICQ_icons.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/ICONS.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx">
+ <File
+ RelativePath="ICONS.rc">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus01.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus02.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus03.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus04.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus05.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus06.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus07.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus08.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus09.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus10.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus11.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus12.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus13.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus14.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus15.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus16.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus17.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus18.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus19.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus20.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus21.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus22.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus23.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus24.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus25.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus26.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus27.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus28.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus29.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus30.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus31.ico">
+ </File>
+ <File
+ RelativePath="..\icons\xstatus32.ico">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/irc_mod/input.cpp b/irc_mod/input.cpp
new file mode 100644
index 0000000..c617460
--- /dev/null
+++ b/irc_mod/input.cpp
@@ -0,0 +1,953 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+extern PREFERENCES * prefs;
+extern String StatusMessage;
+extern char * IRCPROTONAME;
+extern PLUGININFO pluginInfo;
+extern HWND list_hWnd;
+extern int NoOfChannels;
+bool bEcho = true;
+extern int ManualWhoisCount ;
+bool bTempDisableCheck = false;
+bool bTempForceCheck = false;
+extern int iTempCheckTime ;
+extern UINT_PTR OnlineNotifTimer;
+extern UINT_PTR OnlineNotifTimer3;
+extern HWND manager_hWnd;
+
+static String FormatMsg(String text)
+{
+ char temp[30];
+ lstrcpyn(temp, GetWord(text.c_str(), 0).c_str(), 29);
+ CharLower(temp);
+ String command =temp;
+ String S = "";
+ if (command == "/quit" || command == "/away")
+ S =GetWord(text.c_str(), 0) + (String) " :" + GetWordAddress(text.c_str(), 1);
+ else if (command == "/privmsg" || command == "/part" || command == "/topic" || command == "/notice") {
+ S =GetWord(text.c_str(), 0) + (String)" " + GetWord(text.c_str(), 1) ;
+ if (!GetWord(text.c_str(), 2).empty())
+ S += (String) " :" + (String)(GetWordAddress(text.c_str(), 1) +1 + lstrlen (GetWord(text.c_str(), 1).c_str()));
+ }
+ else if (command == "/kick")
+ S =GetWord(text.c_str(), 0) + (String)" " + GetWord(text.c_str(), 1) + (String)" " + GetWord(text.c_str(), 2)+ (String) " :" + GetWordAddress(text.c_str(), 3);
+ else
+ S = GetWordAddress(text.c_str(), 0);
+ S.erase(0,1);
+ return S;
+}
+
+static String AddCR(String text)
+{
+
+ text = ReplaceString(text, "\n", "\r\n");
+ text = ReplaceString(text, "\r\r", "\r");
+
+ return text;
+}
+
+static String DoAlias(char *text, char *window)
+{
+ String Messageout = "";
+ char * p1 = text;
+ char * p2 = text;
+ bool LinebreakFlag = false;
+ p2 = strstr(p1, "\r\n");
+ if (!p2)
+ p2 = strchr(p1, '\0');
+ if (p1 == p2)
+ return (String)text;
+ do {
+ if (LinebreakFlag )
+ Messageout += "\r\n";
+ char * line = new char[p2-p1 +1];
+ lstrcpyn(line, p1, p2-p1+1);
+ char *test = line;
+ while (*test == ' ')
+ test++;
+ if ( *test == '/')
+ {
+ lstrcpyn(line, GetWordAddress(line, 0), p2-p1+1);
+ String S = line ;
+ delete [] line;
+ line = new char[S.length() +2];
+ lstrcpyn(line, S.c_str(), S.length()+1);
+ char * p3 = strstr(prefs->Alias, (GetWord(line, 0)+ " ").c_str());
+ if( p3 != prefs->Alias) {
+ p3 = strstr(prefs->Alias, ((String)"\r\n" + GetWord(line, 0)+ " ").c_str());
+ if (p3) p3 +=2;
+ }
+ if (p3 != NULL) {
+ char * p4 = strstr(p3, "\r\n");
+ if (!p4)
+ p4 = strchr(p3, '\0');
+ char * alias = new char[p4-p3 +1] ;
+ lstrcpyn(alias, p3, p4-p3+1);
+ String S = ReplaceString(alias, "##", window);
+ S = ReplaceString(S.c_str(), "$?", "%question");
+
+ for (int index = 1; index <8; index++){
+ char str[5];
+ mir_snprintf(str, sizeof(str), "#$%u", index);
+ if (!GetWord(line, index).empty() && IsChannel(GetWord(line, index)))
+ S = ReplaceString(S, str, (char *)GetWord(line, index).c_str());
+ else
+ S = ReplaceString(S, str, (char *)((String)"#" +GetWord(line, index)).c_str());
+ }
+ for (int index2 = 1; index2 <8; index2++){
+ char str[5];
+ mir_snprintf(str, sizeof(str), "$%u-", index2);
+ S = ReplaceString(S, str, GetWordAddress(line, index2));
+ }
+ for (int index3 = 1; index3 <8; index3++){
+ char str[5];
+ mir_snprintf(str, sizeof(str), "$%u", index3);
+ S = ReplaceString(S, str, (char *)GetWord(line, index3).c_str());
+ }
+ Messageout += GetWordAddress((char *)S.c_str(), 1);
+ delete []alias;
+ } else {
+ Messageout += line;
+ }
+ } else {
+ Messageout += line;
+ }
+ p1 = p2;
+ if (*p1 == '\r')
+ p1 += 2;
+ p2 = strstr(p1, "\r\n");
+ if (!p2)
+ p2 = strchr(p1, '\0');
+ delete [] line;
+ LinebreakFlag = true;
+ } while ( *p1 != '\0');
+ return Messageout;
+}
+
+
+static String DoIdentifiers (String text, const char * window)
+{
+ SYSTEMTIME time;
+ char str[800];
+ int i = 0;
+
+ GetLocalTime(&time);
+ text = ReplaceString(text, "%mnick", prefs->Nick);
+ text = ReplaceString(text, "%anick", prefs->AlternativeNick);
+ text = ReplaceString(text, "%awaymsg", (char *)StatusMessage.c_str());
+ text = ReplaceString(text, "%module", IRCPROTONAME);
+ text = ReplaceString(text, "%name", prefs->Name);
+ text = ReplaceString(text, "%newl", "\r\n");
+ text = ReplaceString(text, "%network", (char*)g_ircSession.GetInfo().sNetwork.c_str());
+ text = ReplaceString(text, "%me", (char *)g_ircSession.GetInfo().sNick.c_str());
+ mir_snprintf(str,511,"%d.%d.%d.%d",(pluginInfo.version>>24)&0xFF,(pluginInfo.version>>16)&0xFF,(pluginInfo.version>>8)&0xFF,pluginInfo.version&0xFF);
+ text = ReplaceString(text, "%version", str);
+ str[0] = (char)3; str[1] = '\0' ;
+ text = ReplaceString(text, "%color", str);
+ str[0] = (char)2;
+ text = ReplaceString(text, "%bold", str);
+ str[0] = (char)31;
+ text = ReplaceString(text, "%underline", str);
+ str[0] = (char)22;
+ text = ReplaceString(text, "%italics", str);
+
+
+ return text;
+}
+
+static BOOL DoHardcodedCommand(String text, char * window, HANDLE hContact)
+{
+
+ char temp[30];
+ lstrcpyn(temp, GetWord(text.c_str(), 0).c_str(), 29);
+ CharLower(temp);
+ String command =temp;
+ String one =GetWord(text.c_str(), 1);
+ String two =GetWord(text.c_str(), 2);
+ String three =GetWord(text.c_str(), 3);
+ String therest =GetWordAddress(text.c_str(), 4);
+
+ if (command == "/servershow" || command == "/serverhide")
+ {
+ if(prefs->UseServer)
+ {
+ GCEVENT gce = {0};
+ GCDEST gcd = {0};
+ gcd.iType = GC_EVENT_CONTROL;
+ gcd.pszID = "Network log";
+ gcd.pszModule = IRCPROTONAME;
+ gce.cbSize = sizeof(GCEVENT);
+ gce.pDest = &gcd;
+ CallChatEvent( command == "/servershow"?WINDOW_VISIBLE:WINDOW_HIDDEN, (LPARAM)&gce);
+ }
+ return true;
+ }
+
+ else if (command == "/clear" )
+ {
+ GCEVENT gce = {0};
+ GCDEST gcd = {0};
+ String S;
+ if (one != "")
+ {
+ if(one == "server")
+ S = "Network log";
+ else
+ S = MakeWndID(one);
+ }
+ else if(lstrcmpi(window, "Network log") == 0)
+ S = window;
+ else
+ S = MakeWndID(window);
+ gce.cbSize = sizeof(GCEVENT);
+ gcd.iType = GC_EVENT_CONTROL;
+ gcd.pszModule = IRCPROTONAME;
+ gce.pDest = &gcd;
+ gcd.pszID = (char *)S.c_str();
+ CallChatEvent( WINDOW_CLEARLOG, (LPARAM)&gce);
+
+ return true;
+ }
+ else if (command == "/ignore" )
+ {
+ if (g_ircSession)
+ {
+ String IgnoreFlags = "";
+ char temp[500];
+ if (one == "")
+ {
+ if (prefs->Ignore)
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate( "Ignore system is enabled" ), NULL, NULL, NULL, true, false);
+ else
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate( "Ignore system is disabled" ), NULL, NULL, NULL, true, false);
+ return true;
+ }
+ if (!lstrcmpi(one.c_str(),"on"))
+ {
+ prefs->Ignore = 1;
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate( "Ignore system is enabled" ), NULL, NULL, NULL, true, false);
+ return true;
+ }
+ if (!lstrcmpi(one.c_str(), "off"))
+ {
+ prefs->Ignore = 0;
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate( "Ignore system is disabled" ), NULL, NULL, NULL, true, false);
+ return true;
+ }
+ if (!strchr(one.c_str(), '!') && !strchr(one.c_str(), '@'))
+ one += "!*@*";
+ if(two != "" && two[0] == '+')
+ {
+ if (strchr(two.c_str(), 'q'))
+ IgnoreFlags += "q";
+ if (strchr(two.c_str(), 'n'))
+ IgnoreFlags += "n";
+ if (strchr(two.c_str(), 'i'))
+ IgnoreFlags += "i";
+ if (strchr(two.c_str(), 'd'))
+ IgnoreFlags += "d";
+ if (strchr(two.c_str(), 'c'))
+ IgnoreFlags += "c";
+ if (strchr(two.c_str(), 'm'))
+ IgnoreFlags += "m";
+ }
+ else
+ IgnoreFlags = "qnidc";
+
+ String Network;
+ if(three == "")
+ Network = g_ircSession.GetInfo().sNetwork;
+ else
+ Network = three;
+
+ AddIgnore(one, IgnoreFlags.c_str(), Network);
+ mir_snprintf(temp, 499, Translate( "%s on %s is now ignored (+%s)" ), one.c_str(), Network.c_str(), IgnoreFlags.c_str());
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), temp, NULL, NULL, NULL, true, false);
+ }
+ return true;
+ }
+ else if (command == "/unignore" )
+ {
+ if (!strchr(one.c_str(), '!') && !strchr(one.c_str(), '@'))
+ one += "!*@*";
+ char temp[500];
+ if (RemoveIgnore(one))
+ mir_snprintf(temp, 499, Translate( "%s is not ignored now" ), one.c_str());
+ else
+ mir_snprintf(temp, 499, Translate( "%s was not ignored" ), one.c_str());
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), temp, NULL, NULL, NULL, true, false);
+ return true;
+ }
+
+ else if(command == "/userhost")
+ {
+ if (one.empty())
+ return true;
+
+ DoUserhostWithReason(1, "U", false, temp);
+ return false;
+ }
+
+ else if (command == "/joinx")
+ {
+ if (one.empty())
+ return true;
+
+ AddToJTemp("X"+one);
+
+ PostIrcMessage( "/JOIN %s", GetWordAddress(text.c_str(), 1));
+ return true;
+ }
+
+ else if (command == "/joinm")
+ {
+ if (one.empty())
+ return true;
+
+ AddToJTemp("M"+one);
+
+ PostIrcMessage( "/JOIN %s", GetWordAddress(text.c_str(), 1));
+ return true;
+ }
+ else if (command == "/nusers")
+ {
+ char szTemp[40];
+ String S = MakeWndID(window);
+ GC_INFO gci = {0};
+ gci.Flags = BYID|NAME|COUNT;
+ gci.pszModule = IRCPROTONAME;
+ gci.pszID = (char *)S.c_str();
+ if(!CallService(MS_GC_GETINFO, 0, (LPARAM)&gci))
+ {
+ _snprintf(szTemp, 35, "users: %u", gci.iCount);
+ }
+
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+ return true;
+ }
+ else if (command == "/echo")
+ {
+ if (one.empty())
+ return true;
+
+ if (!lstrcmpi(one.c_str(), "on"))
+ {
+ bEcho = TRUE;
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate("Outgoing commands are shown"), NULL, NULL, NULL, true, false);
+ }
+
+ if (!lstrcmpi(one.c_str(), "off"))
+ {
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate("Outgoing commands are not shown"), NULL, NULL, NULL, true, false);
+ bEcho = FALSE;
+ }
+
+ return true;
+ }
+
+ else if (command == "/buddycheck")
+ {
+ if (one.empty())
+ {
+ if ((prefs->AutoOnlineNotification && !bTempDisableCheck) || bTempForceCheck)
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate( "The buddy check function is enabled" ), NULL, NULL, NULL, true, false);
+ else
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate( "The buddy check function is disabled" ), NULL, NULL, NULL, true, false);
+ return true;
+ }
+ if (!lstrcmpi(one.c_str(), "on"))
+ {
+ bTempForceCheck = true;
+ bTempDisableCheck = false;
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate( "The buddy check function is enabled" ), NULL, NULL, NULL, true, false);
+ SetChatTimer(OnlineNotifTimer, 500, OnlineNotifTimerProc);
+ if(prefs->ChannelAwayNotification)
+ SetChatTimer(OnlineNotifTimer3, 1500, OnlineNotifTimerProc3);
+ }
+ if (!lstrcmpi(one.c_str(), "off"))
+ {
+ bTempForceCheck = false;
+ bTempDisableCheck = true;
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate( "The buddy check function is disabled" ), NULL, NULL, NULL, true, false);
+ KillChatTimer(OnlineNotifTimer);
+ KillChatTimer(OnlineNotifTimer3);
+ }
+ if (!lstrcmpi(one.c_str(), "time") && !two.empty())
+ {
+ iTempCheckTime = StrToInt(two.c_str());
+ if (iTempCheckTime < 10 && iTempCheckTime != 0)
+ iTempCheckTime = 10;
+
+ if (iTempCheckTime == 0)
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), Translate( "The time interval for the buddy check function is now at default setting" ), NULL, NULL, NULL, true, false);
+ else
+ {
+ char temp[200];
+ mir_snprintf(temp, 199, Translate( "The time interval for the buddy check function is now %u seconds" ), iTempCheckTime);
+ DoEvent(GC_EVENT_INFORMATION, NULL, g_ircSession.GetInfo().sNick.c_str(), temp, NULL, NULL, NULL, true, false);
+ }
+ }
+ return true;
+
+ }
+ else if (command == "/whois")
+ {
+ if (one.empty())
+ return false;
+ ManualWhoisCount++;
+ return false;
+ }
+
+ else if (command == "/channelmanager")
+ {
+ if (window && !hContact && IsChannel(window))
+ {
+ if (g_ircSession)
+ {
+ if(manager_hWnd != NULL)
+ {
+ SetActiveWindow(manager_hWnd);
+ SendMessage(manager_hWnd, WM_CLOSE, 0, 0);
+ }
+ if(manager_hWnd == NULL)
+ {
+ manager_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_CHANMANAGER),NULL,ManagerWndProc);
+ SetWindowText(manager_hWnd, Translate("Channel Manager"));
+ SetWindowText(GetDlgItem(manager_hWnd, IDC_CAPTION), window);
+ SendMessage(manager_hWnd, IRC_INITMANAGER, 1, (LPARAM)window);
+ }
+ }
+ }
+ return true;
+ }
+
+ else if (command == "/who")
+ {
+ if (one.empty())
+ return true;
+ DoUserhostWithReason(2, "U", false, "%s", one.c_str());
+ return false;
+ }
+
+ else if (command == "/hop")
+ {
+ if (!IsChannel(window))
+ return true;
+
+ PostIrcMessage( "/PART %s", window);
+
+ if ((one.empty() || !IsChannel(one)))
+ {
+
+ CHANNELINFO* wi = (CHANNELINFO *)DoEvent(GC_EVENT_GETITEMDATA, window, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, 0);
+ if (wi && wi->pszPassword)
+ PostIrcMessage( "/JOIN %s %s", window, wi->pszPassword);
+ else
+ PostIrcMessage( "/JOIN %s", window);
+
+ return true;
+ }
+ GCEVENT gce = {0};
+ GCDEST gcd = {0};
+ gcd.iType = GC_EVENT_CONTROL;
+ String S = MakeWndID(window);
+ gcd.pszID = (char*) S.c_str();
+ gcd.pszModule = IRCPROTONAME;
+ gce.cbSize = sizeof(GCEVENT);
+ gce.pDest = &gcd;
+
+ CallChatEvent( SESSION_TERMINATE, (LPARAM)&gce);
+
+ PostIrcMessage( "/JOIN %s", GetWordAddress(text.c_str(), 1));
+
+ return true;
+ }
+
+ else if (command == "/list")
+ {
+ if (list_hWnd == NULL)
+ list_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_LIST),NULL,ListWndProc);
+ SetActiveWindow(list_hWnd);
+ int minutes = (int)NoOfChannels/4000;
+ int minutes2 = (int)NoOfChannels/9000;
+ char text[250];
+ mir_snprintf(text, 249, Translate( "This command is not recommended on a network of this size!\r\nIt will probably cause high CPU usage and/or high bandwidth\r\nusage for around %u to %u minute(s).\r\n\r\nDo you want to continue?" ), minutes2, minutes);
+ if (NoOfChannels < 4000 || (NoOfChannels >= 4000 && MessageBox(NULL, text, Translate("IRC warning") , MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) == IDYES)) {
+ ListView_DeleteAllItems (GetDlgItem(list_hWnd, IDC_INFO_LISTVIEW));
+ PostIrcMessage( "/lusers");
+ return false;
+ }
+ SetDlgItemText(list_hWnd, IDC_TEXT, Translate( "Aborted" ));
+ return true;
+ }
+
+ else if (command == "/me")
+ {
+ if (one.empty())
+ return true;
+ char szTemp[4000];
+ mir_snprintf(szTemp, sizeof(szTemp), "\1ACTION %s\1", GetWordAddress(text.c_str(), 1));
+ PostIrcMessageWnd(window, hContact, szTemp);
+ return true;
+ }
+
+ else if (command == "/ame")
+ {
+ if (one.empty())
+ return true;
+
+ String S ;
+ S = "/ME " + DoIdentifiers((String)GetWordAddress(text.c_str(), 1), window);
+ S = ReplaceString(S, "%", "%%");
+ DoEvent(GC_EVENT_SENDMESSAGE, NULL, NULL, S.c_str(), NULL, NULL, NULL, FALSE, FALSE);
+ return true;
+ }
+
+ else if (command == "/amsg")
+ {
+ if (one.empty())
+ return true;
+ String S ;
+ S = DoIdentifiers((String)GetWordAddress(text.c_str(), 1), window);
+ S = ReplaceString(S, "%", "%%");
+ DoEvent(GC_EVENT_SENDMESSAGE, NULL, NULL, S.c_str(), NULL, NULL, NULL, FALSE, FALSE);
+ return true;
+ }
+
+ else if (command == "/msg")
+ {
+ if (one.empty() || two.empty())
+ return true;
+
+ char szTemp[4000];
+ mir_snprintf(szTemp, sizeof(szTemp), "/PRIVMSG %s", GetWordAddress(text.c_str(), 1));
+
+ PostIrcMessageWnd(window, hContact, szTemp);
+ return true;
+ }
+
+ else if (command == "/query")
+ {
+ if (one.empty() || IsChannel(one.c_str()))
+ return true;
+
+ struct CONTACT_TYPE user ={(char *)one.c_str(), NULL, NULL, false, false, false};
+ HANDLE hContact2 = CList_AddContact(&user, false, false);
+
+ if (hContact2){
+
+ DBVARIANT dbv1;
+
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 0)
+ DoUserhostWithReason(1, ("S" + one).c_str(), true, one.c_str());
+ else
+ {
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv1) && dbv1.type == DBVT_ASCIIZ)
+ {
+ DoUserhostWithReason(2, ((String)"S" + dbv1.pszVal).c_str(), true, dbv1.pszVal);
+ DBFreeVariant(&dbv1);
+ }
+ else
+ {
+ DoUserhostWithReason(2, ((String)"S" + one).c_str(), true, one.c_str());
+ }
+ }
+
+ CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact2,0);
+
+ }
+
+ if (!two.empty())
+ {
+ char szTemp[4000];
+ mir_snprintf(szTemp, sizeof(szTemp), "/PRIVMSG %s", GetWordAddress(text.c_str(), 1));
+ PostIrcMessageWnd(window, hContact, szTemp);
+ }
+ return true;
+ }
+ else if (command == "/ctcp")
+ {
+ if (one.empty() || two.empty())
+ return true;
+
+ char szTemp[1000];
+
+ unsigned long ulAdr = 0;
+ if (prefs->ManualHost)
+ ulAdr = ConvertIPToInteger(prefs->MySpecifiedHostIP);
+ else
+ ulAdr = ConvertIPToInteger(prefs->IPFromServer?prefs->MyHost:prefs->MyLocalHost);
+
+ if(lstrcmpi(two.c_str(), "dcc") != 0 || ulAdr) // if it is not dcc or if it is dcc and a local ip exist
+ {
+ if(lstrcmpi(two.c_str(), "ping") == 0)
+ mir_snprintf(szTemp, sizeof(szTemp), "/PRIVMSG %s \001%s %u\001", one.c_str(), two.c_str(), time(0));
+ else
+ mir_snprintf(szTemp, sizeof(szTemp), "/PRIVMSG %s \001%s\001", one.c_str(), GetWordAddress(text.c_str(), 2));
+ PostIrcMessageWnd(window, hContact, szTemp);
+ }
+
+ if(lstrcmpi(two.c_str(), "dcc") != 0)
+ {
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("CTCP %s request sent to %s"), two.c_str(), one.c_str());
+ DoEvent(GC_EVENT_INFORMATION, "Network Log", g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+ }
+
+ return true;
+ }
+ else if (command == "/dcc")
+ {
+ if (one.empty() || two.empty())
+ return true;
+ if(lstrcmpi(one.c_str(), "send") == 0)
+ {
+ char szTemp[1000];
+
+ unsigned long ulAdr = 0;
+ if (prefs->ManualHost)
+ ulAdr = ConvertIPToInteger(prefs->MySpecifiedHostIP);
+ else
+ ulAdr = ConvertIPToInteger(prefs->IPFromServer?prefs->MyHost:prefs->MyLocalHost);
+
+ if(ulAdr)
+ {
+ struct CONTACT_TYPE user ={(char *)two.c_str(), NULL, NULL, false, false, true};
+ HANDLE hContact = CList_AddContact(&user, false, false);
+
+ if(hContact)
+ {
+ DBVARIANT dbv1;
+ String s;
+
+
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 0)
+ DoUserhostWithReason(1, ("S" + two).c_str(), true, two.c_str());
+ else
+ {
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv1) && dbv1.type == DBVT_ASCIIZ)
+ {
+ DoUserhostWithReason(2, ((String)"S" + dbv1.pszVal).c_str(), true, dbv1.pszVal);
+ DBFreeVariant(&dbv1);
+ }
+ else
+ {
+ DoUserhostWithReason(2, ((String)"S" + two).c_str(), true, two.c_str());
+ }
+ }
+
+ if(three == "")
+ CallService(MS_FILE_SENDFILE, (WPARAM)hContact, 0);
+ else
+ {
+ String temp = GetWordAddress(text.c_str(), 3);
+ char * pp[2];
+ char * p = (char *)temp.c_str();
+ pp[0] = p;
+ pp[1] = NULL;
+ CallService(MS_FILE_SENDSPECIFICFILES, (WPARAM)hContact, (LPARAM)pp);
+ }
+ }
+ }
+ else
+ {
+
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC ERROR: Unable to automatically resolve external IP"));
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+ }
+ return true;
+ }
+ if(lstrcmpi(one.c_str(), "chat") == 0)
+ {
+ char szTemp[1000];
+
+ unsigned long ulAdr = 0;
+ if (prefs->ManualHost)
+ ulAdr = ConvertIPToInteger(prefs->MySpecifiedHostIP);
+ else
+ ulAdr = ConvertIPToInteger(prefs->IPFromServer?prefs->MyHost:prefs->MyLocalHost);
+
+ if(ulAdr)
+ {
+ String contact = two + DCCSTRING;
+ struct CONTACT_TYPE user ={(char *)contact.c_str(), NULL, NULL, false, false, true};
+ HANDLE hContact = CList_AddContact(&user, false, false);
+ DBWriteContactSettingByte(hContact, IRCPROTONAME, "DCC", 1);
+
+ int iPort = 0;
+
+ if(hContact)
+ {
+ DCCINFO * dci = new DCCINFO;
+ ZeroMemory(dci, sizeof(DCCINFO));
+ dci->hContact = hContact;
+ dci->sContactName = two;
+ dci->iType = DCC_CHAT;
+ dci->bSender = true;
+
+ CDccSession * dcc = new CDccSession(dci);
+
+ CDccSession * olddcc = g_ircSession.FindDCCSession(hContact);
+ if (olddcc)
+ olddcc->Disconnect();
+ g_ircSession.AddDCCSession(hContact, dcc);
+ iPort = dcc->Connect();
+ }
+
+ if (iPort != 0)
+ {
+ PostIrcMessage("/CTCP %s DCC CHAT chat %u %u", two.c_str(), ulAdr, iPort);
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC CHAT request sent to %s"), two.c_str(), one.c_str());
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+ }
+ else
+ {
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC ERROR: Unable to bind port"));
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+ }
+
+ }
+ else
+ {
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC ERROR: Unable to automatically resolve external IP"));
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+ }
+
+ }
+ return true;
+ }
+ return false;
+}
+
+
+
+
+static bool DoInputRequestAlias(char * text)
+{
+ char * p1 = strstr(text, "%question");
+ if(p1)
+ {
+ char * infotext = NULL;
+ char * title = NULL;
+ char * defaulttext = NULL;
+ String command = text;
+ if(p1[9] == '=' && p1[10] == '\"')
+ {
+ infotext = &p1[11];
+ p1 = strchr(infotext, '\"');
+ if (p1)
+ {
+ *p1 = '\0';
+ p1++;
+ if (*p1 == ',' && p1[1] == '\"')
+ {
+ p1++; p1++;
+ title = p1;
+ p1 = strchr(title, '\"');
+ if (p1)
+ {
+ *p1 = '\0';
+ p1++;
+ if (*p1 == ',' && p1[1] == '\"')
+ {
+ p1++; p1++;
+ defaulttext = p1;
+ p1 = strchr(defaulttext, '\"');
+ if (p1)
+ {
+ *p1 = '\0';
+ }
+
+ }
+
+ }
+ }
+
+ }
+ }
+
+ HWND question_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_QUESTION),NULL, QuestionWndProc);
+
+ if(title)
+ SetDlgItemText(question_hWnd, IDC_CAPTION, title);
+ else
+ SetDlgItemText(question_hWnd, IDC_CAPTION, Translate( "Input command" ));
+
+ if(infotext)
+ SetWindowText(GetDlgItem(question_hWnd, IDC_TEXT), infotext);
+ else
+ SetWindowText(GetDlgItem(question_hWnd, IDC_TEXT), Translate( "Please enter the reply" ));
+
+ if(defaulttext)
+ SetWindowText(GetDlgItem(question_hWnd, IDC_EDIT), defaulttext);
+
+ SetDlgItemText(question_hWnd, IDC_HIDDENEDIT, command.c_str());
+ PostMessage(question_hWnd, IRC_ACTIVATE, 0, 0);
+ return true;
+ }
+ return false;
+}
+bool PostIrcMessage(const char * fmt, ...)
+{
+ if (!fmt || lstrlen(fmt) < 1 || lstrlen(fmt) > 4000)
+ return 0;
+
+ va_list marker;
+ va_start(marker, fmt);
+ static char szBuf[4*1024];
+ vsprintf(szBuf, fmt, marker);
+ va_end(marker);
+
+ return PostIrcMessageWnd(NULL, NULL, szBuf);
+}
+
+bool PostIrcMessageWnd(char* window, HANDLE hContact, const char * szBuf)
+{
+ DBVARIANT dbv;
+ char windowname[256];
+
+ BYTE bDCC = 0;
+
+ if(hContact)
+ bDCC = DBGetContactSettingByte(hContact, IRCPROTONAME, "DCC", 0);
+
+ if (!g_ircSession && !bDCC || !szBuf || lstrlen(szBuf) < 1)
+ return 0;
+
+ if (hContact && !DBGetContactSetting(hContact, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ lstrcpyn(windowname, dbv.pszVal, 255);
+ DBFreeVariant(&dbv);
+ }
+ else if(window)
+ {
+ lstrcpyn(windowname, window, 255);
+ }
+ else
+ {
+ lstrcpyn(windowname, "Network log", 255);
+ }
+ if(lstrcmpi(window, "Network log") != 0)
+ {
+ char * p1 = strchr(windowname, ' ');
+ if (p1)
+ *p1 = '\0';
+ }
+
+ // remove unecessary linebreaks, and do the aliases
+ String Message = szBuf;
+ Message = AddCR(Message);
+ Message = RemoveLinebreaks(Message);
+ if(!hContact && g_ircSession)
+ {
+ Message = DoAlias((char *)Message.c_str(), windowname);
+ if (DoInputRequestAlias((char *)Message.c_str()))
+ return 1;
+ Message = ReplaceString(Message, "%newl", "\r\n");
+ Message = RemoveLinebreaks(Message);
+ }
+
+ if (Message.empty())
+ return 0;
+ int index = 0;
+
+ // process the message
+ while (!Message.empty()) {
+ // split the text into lines, and do an automatic textsplit on long lies as well
+ bool flag = false;
+ String DoThis = "";
+ index = Message.find("\r\n",0);
+ if (index == string::npos) {
+ index = Message.length();
+ }
+ if (index >480)
+ index = 480;
+ DoThis = Message.substr(0, index);
+ Message.erase(0, index);
+ if (Message.find("\r\n", 0) == 0)
+ Message.erase(0,2);
+
+ //do this if it's a /raw
+ if (g_ircSession && (GetWord(DoThis.c_str(), 0) == "/raw" || GetWord(DoThis.c_str(), 0) == "/quote"))
+ {
+ if (GetWord(DoThis.c_str(), 1).empty())
+ continue;
+ DoThis = ReplaceString(DoThis, "%", "%%");
+ String S = GetWordAddress(DoThis.c_str(), 1);
+ g_ircSession << irc::CIrcMessage(S.c_str());
+ continue;
+ }
+
+ // Do this if the message is not a command
+ if (GetWord(DoThis.c_str(), 0)[0] != '/' || hContact) {
+ if(lstrcmpi(window, "Network log") == 0 && g_ircSession.GetInfo().sServerName != "")
+ DoThis = (String)"/PRIVMSG " + g_ircSession.GetInfo().sServerName + (String)" "+ DoThis;
+ else
+ DoThis = (String)"/PRIVMSG " + (String)windowname + (String)" "+ DoThis;
+ flag = true;
+ }
+
+ // and here we send it unless the command was a hardcoded one that should not be sent
+ if (!DoHardcodedCommand(DoThis, windowname, hContact)){
+ if( g_ircSession || bDCC)
+ {
+ if (!flag && g_ircSession )
+ DoThis = DoIdentifiers(DoThis, windowname);
+ if (hContact)
+ {
+ if(flag && bDCC)
+ {
+ CDccSession * dcc = g_ircSession.FindDCCSession(hContact);
+ if(dcc)
+ {
+ DoThis = FormatMsg(DoThis);
+ String mess = GetWordAddress(DoThis.c_str(), 2);
+ if(mess[0] == ':')
+ mess.erase(0,1);
+ mess += '\n';
+ dcc->SendStuff((const char*) mess.c_str());
+
+ }
+ else if(g_ircSession)
+ {
+
+
+ }
+ }
+ else if(g_ircSession)
+ {
+ DoThis = ReplaceString(DoThis, "%", "%%");
+ DoThis = FormatMsg(DoThis);
+ g_ircSession << irc::CIrcMessage(DoThis.c_str(), false, false);
+
+ }
+ }
+ else
+ {
+ DoThis = ReplaceString(DoThis, "%", "%%");
+ DoThis = FormatMsg(DoThis);
+ g_ircSession << irc::CIrcMessage(DoThis.c_str(), false, true);
+ }
+ }
+ }
+ }
+ return 1;
+}
diff --git a/irc_mod/irc.h b/irc_mod/irc.h
new file mode 100644
index 0000000..9b790ed
--- /dev/null
+++ b/irc_mod/irc.h
@@ -0,0 +1,510 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public 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 _IRCWIN_H_
+#define _IRCWIN_H_
+
+// disable a lot of warnings. It should comppile on VS 6 also
+#pragma warning( disable : 4076 )
+#pragma warning( disable : 4786 )
+#pragma warning( disable : 4996 )
+
+#define WIN32_LEAN_AND_MEAN
+
+//#if defined(_UNICODE)
+//#endif
+
+//#include "AggressiveOptimize.h"
+
+/*
+#include <windows.h>
+#include <shlwapi.h>
+#include <shlobj.h>
+#include <objbase.h>
+#include <shellapi.h>
+#include <stdio.h>
+#include <process.h>
+#include <math.h>
+#include <winsock.h>
+#include <time.h>
+#include "newpluginapi.h"
+#include "m_system.h"
+#include "m_protocols.h"
+#include "m_protomod.h"
+#include "m_protosvc.h"
+#include "m_clist.h"
+#include "m_options.h"
+#include "m_database.h"
+#include "m_utils.h"
+#include "m_skin.h"
+#include "m_netlib.h"
+#include "m_clui.h"
+#include "m_langpack.h"
+#include "m_message.h"
+#include "m_userinfo.h"
+#include "m_addcontact.h"
+#include "m_button.h"
+#include "m_file.h"
+#include "m_ignore.h"
+#include "m_chat.h"
+#include "m_ircscript.h"
+#include "resource.h"
+#include "irclib.h"
+#include "commandmonitor.h"
+#include "IcoLib.h"
+*/
+
+#include <tchar.h>
+
+// Windows includes
+#include <windows.h>
+#include <commctrl.h> // ADDED
+#include <commdlg.h> // ADDED
+
+// Standard includes
+#include <shlwapi.h>
+#include <shlobj.h>
+#include <objbase.h>
+#include <shellapi.h>
+#include <stdio.h>
+#include <process.h>
+#include <math.h>
+#include <winsock.h>
+#include <time.h>
+
+// ADDED
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <direct.h>
+#include <fcntl.h>
+#include <crtdbg.h>
+#include <malloc.h>
+
+// Miranda IM SDK includes
+#include "newpluginapi.h"
+#include "m_system.h"
+#include "m_protocols.h"
+#include "m_protomod.h"
+#include "m_protosvc.h"
+#include "m_clist.h"
+#include "m_options.h"
+#include "m_database.h"
+#include "m_utils.h"
+#include "m_skin.h"
+#include "m_netlib.h"
+#include "m_clui.h"
+#include "m_langpack.h"
+#include "m_message.h"
+#include "m_userinfo.h"
+#include "m_addcontact.h"
+#include "m_button.h"
+#include "m_file.h"
+#include "m_ignore.h"
+#include "m_chat.h"
+#include "m_popup.h"
+#include "m_popupw.h"
+#include "m_icolib.h"
+
+#include "m_updater.h"
+#include "m_nudge.h"
+#include "m_xstatus.h"
+#include "m_cluiframes.h"
+
+// Need FIX
+#include "i18n.h"
+#include "md5.h"
+
+#include "utils.h"
+#include "popups.h"
+
+#include "iconlib.h"
+#include "avatar.h"
+#include "xstatus.h"
+
+#include "m_ircscript.h"
+#include "resource.h"
+#include "irclib.h"
+#include "commandmonitor.h"
+
+
+#ifndef NDEBUG
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#ifdef _DEBUG
+#define DBGprintf printf
+#endif
+
+#define IRC_UPDATELIST (WM_USER+1)
+#define IRC_QUESTIONAPPLY (WM_USER+2)
+#define IRC_QUESTIONCLOSE (WM_USER+3)
+#define IRC_ACTIVATE (WM_USER+4)
+#define IRC_INITMANAGER (WM_USER+5)
+#define IRC_REBUILDIGNORELIST (WM_USER+6)
+#define IRC_UPDATEIGNORELIST (WM_USER+7)
+#define IRC_FIXIGNOREBUTTONS (WM_USER+8)
+
+#define STR_QUITMESSAGE "\002Miranda IM!\002"
+#define STR_USERINFO "© 2000-2006 Miranda-IM project"
+#define STR_AWAYMESSAGE "I'm away from the computer." // Default away
+#define DCCSTRING " (DCC)"
+
+#define DCC_CHAT 1
+#define DCC_SEND 2
+
+#define FILERESUME_CANCEL 11
+
+// Defaults
+#define DEFAULT_VERSION_AUTO 0
+#define DEFAULT_TYPING 0
+#define DEFAULT_XSTATUS_ENABLED 0
+#define DEFAULT_XSTATUS_AUTO 0
+#define DEFAULT_XSTATUS_RESET 0
+#define DEFAULT_XSTATUS_ADV 1
+
+#define ADV_CNT 6
+
+// Database setting names
+// #define DBSETTING_CAPABILITIES "caps"
+#define DBSETTING_XSTATUSID "XStatusId"
+#define DBSETTING_XSTATUSNAME "XStatusName"
+#define DBSETTING_XSTATUSMSG "XStatusMsg"
+
+// capabilities
+// typedef unsigned char capstr[0x10];
+
+// Nudge
+#define PS_SEND_NUDGE "/SendNudge"
+
+// Typing notification statuses
+#define MTN_FINISHED 0x0000
+#define MTN_TYPED 0x0001
+#define MTN_BEGUN 0x0002
+
+// Avatars
+#define DEFAULT_AVATARS_ENABLED 1
+
+//set owner avatar
+//wParam=0
+//lParam=(const char *)Avatar file name
+//return=0 for sucess
+#define PS_IRC_SETMYAVATAR "/SetMyAvatar"
+
+//get current owner avatar
+//wParam=(char *)Buffer to file name
+//lParam=(int)Buffer size
+//return=0 for sucess
+#define PS_IRC_GETMYAVATAR "/GetMyAvatar"
+
+//get size limit for avatar image
+//wParam=(int *)max width of avatar - will be set
+//lParam=(int *)max height of avatar - will be set
+//return=0 for sucess
+#define PS_IRC_GETMYAVATARMAXSIZE "/GetMyAvatarMaxSize"
+
+//check if image format supported for avatars
+//wParam = 0
+//lParam = PA_FORMAT_* // avatar format
+//return = 1 (supported) or 0 (not supported)
+#define PS_IRC_ISAVATARFORMATSUPPORTED "/IsAvatarFormatSupported"
+
+//PopUp
+#define DEFAULT_POPUPS_ENABLED 1
+
+#define LOG_NOTE 0 //trivial problems or problems that will already have been reported elsewhere
+#define LOG_WARNING 1 //problems that may have caused data loss
+#define LOG_ERROR 2 //problems that cause a disconnection from the network
+#define LOG_FATAL 3 //problems requiring user intervention: password wrong, rate exceeded, etc.
+
+#define DEFAULT_LOG0_TEXT_COLORS RGB(0,0,0) // LOG_NOTE
+#define DEFAULT_LOG0_BACK_COLORS RGB(255,255,128)
+#define DEFAULT_LOG0_TIMEOUT 5
+#define DEFAULT_LOG1_TEXT_COLORS RGB(0,0,0) // LOG_WARNING
+#define DEFAULT_LOG1_BACK_COLORS RGB(128,128,128)
+#define DEFAULT_LOG1_TIMEOUT 5
+#define DEFAULT_LOG2_TEXT_COLORS RGB(0,0,0) // LOG_ERROR
+#define DEFAULT_LOG2_BACK_COLORS RGB(255,128,64)
+#define DEFAULT_LOG2_TIMEOUT 5
+#define DEFAULT_LOG3_TEXT_COLORS RGB(0,0,0) // LOG_FATAL
+#define DEFAULT_LOG3_BACK_COLORS RGB(255,0,0)
+#define DEFAULT_LOG3_TIMEOUT 5
+
+using namespace std;
+using namespace irc;
+
+// special service for tweaking performance, implemented in chat.dll
+#define MS_GC_GETEVENTPTR "GChat/GetNewEventPtr"
+typedef int (*GETEVENTFUNC)(WPARAM wParam, LPARAM lParam);
+typedef struct {
+ GETEVENTFUNC pfnAddEvent;
+}GCPTRS;
+
+#define IP_AUTO 1
+#define IP_MANUAL 2
+
+typedef struct IPRESOLVE_INFO_TYPE // Contains info about the channels
+{
+ int iType;
+ char * pszAdr;
+} IPRESOLVE;
+
+typedef struct WINDOW_INFO_TYPE // Contains info about the channels
+{
+ char * pszTopic;
+ char * pszMode;
+ char * pszPassword;
+ char * pszLimit;
+} CHANNELINFO;
+
+typedef struct SERVER_INFO_TYPE // Contains info about different servers
+{
+ char * Group;
+ char * Address;
+ char * Name;
+ char * PortStart;
+ char * PortEnd;
+ int iSSL;
+} SERVER_INFO;
+
+typedef struct PERFORM_INFO_TYPE // Contains 'Perform buffer' for different networks
+{
+ char * Perform;
+
+} PERFORM_INFO;
+
+typedef struct CONTACT_TYPE // Contains info about users
+{
+ char * name;
+ char * user;
+ char * host;
+ bool ExactOnly;
+ bool ExactWCOnly;
+ bool ExactNick;
+} CONTACT;
+
+typedef struct PREFERENCES_TYPE // Preferences structure
+{
+ char ServerName[100];
+ char Password [500];
+ char IdentSystem[10];
+ char Network[30];
+ char PortStart[10];
+ char PortEnd[10];
+ int IdentTimer;
+ int iSSL;
+ char IdentPort[10];
+ char RetryWait[10];
+ char RetryCount[10];
+
+ char Nick[30];
+ char AlternativeNick[30];
+ char Name[200];
+ char UserID[200];
+ char QuitMessage[400];
+ char UserInfo[500];
+ char MyHost[50];
+ char MySpecifiedHost[500];
+ char MySpecifiedHostIP[50];
+ char MyLocalHost[50];
+ char * Alias;
+ int ServerComboSelection;
+ int QuickComboSelection;
+ int OnlineNotificationTime;
+ int OnlineNotificationLimit;
+ BYTE ScriptingEnabled;
+
+ BYTE VersionAuto;
+ BYTE NudgeEnabled;
+ BYTE TypingEnabled;
+ BYTE XStatusEnabled;
+ BYTE XStatusReset;
+ BYTE XStatusAuto;
+ BYTE XStatusAdv;
+
+ BYTE AvatarsEnabled;
+ BYTE AvatarsAutoLoad;
+ BYTE AvatarsAutoLink;
+
+ BYTE UseMemoServ;
+ char MemoServName[30];
+ BYTE MemoServAuto;
+
+ BYTE PopupsEnabled;
+ BYTE PopupsErrors;
+ BYTE PopupWhois;
+ BYTE PopupsWhoisNoUser;
+
+ BYTE IPFromServer;
+ BYTE ShowAddresses;
+ BYTE DisconnectDCCChats;
+ BYTE DisableErrorPopups;
+ BYTE RejoinChannels;
+ BYTE RejoinIfKicked;
+ BYTE HideServerWindow;
+ BYTE Ident;
+ BYTE Retry;
+ BYTE DisableDefaultServer;
+ BYTE AutoOnlineNotification;
+ BYTE SendKeepAlive;
+ BYTE JoinOnInvite;
+ BYTE Perform;
+ BYTE ForceVisible;
+ BYTE Ignore;
+ BYTE IgnoreChannelDefault;
+ BYTE UseServer;
+ BYTE DCCFileEnabled;
+ BYTE DCCChatEnabled;
+ BYTE DCCChatAccept;
+ BYTE DCCChatIgnore;
+ BYTE DCCPassive;
+ BYTE ManualHost;
+ BYTE OldStyleModes;
+ BYTE ChannelAwayNotification;
+ BYTE SendNotice;
+ POINT ListSize;
+ COLORREF colors[16];
+ HICON hIcon[13];
+
+} PREFERENCES;
+
+typedef struct WHOIS_TYPE // Whois structure
+{
+ char _Name[100];
+ char _ID[100];
+ char _Server[100];
+ char _Address[100];
+ char _Auth[100];
+ char _Channels[100];
+ char _Other[100];
+ char _Idle[100];
+ char _Away[100];
+} WHOIS;
+
+//main.cpp
+void UpgradeCheck(void);
+
+//services.cpp
+void HookEvents(void);
+void UnhookEvents(void);
+void CreateServiceFunctions(void);
+void ConnectToServer(void);
+void DisconnectFromServer(void);
+int Service_GCEventHook(WPARAM wParam,LPARAM lParam);
+void sendTypingNotification(HANDLE hContact, WORD wMTNCode);
+void handleNudgeNotification(const char* NickName);
+void handleTypingNotification(const char* NickName, WORD wMTNCode);
+void handleXStatus(const char* NickName);
+void handleAvatarHash(const char* NickName);
+
+//options.cpp
+void InitPrefs(void);
+void UnInitOptions(void);
+int InitOptionsPages(WPARAM wParam,LPARAM lParam);
+void InitIcons(void);
+HICON LoadIconEx(int iIndex, char * pszIcoLibName, int iX, int iY);
+
+//tools.cpp
+int WCCmp(char* wild, char *string);
+char * IrcLoadFile(char * szPath);
+void AddToJTemp(String sCommand);
+void __cdecl forkthread_r(void *param);
+unsigned long forkthread ( void (__cdecl *threadcode)(void*),unsigned long stacksize,void *arg);
+String GetWord(const char * text, int index);
+String ReplaceString (String text, char * replaceme, char * newword);
+bool IsChannel(String sName);
+char * GetWordAddress(const char * text, int index);
+String RemoveLinebreaks(String Message);
+char* my_strstri(char *s1, char *s2) ;
+char * DoColorCodes (const char * text, bool bStrip, bool bReplacePercent);
+int DoEvent(int iEvent, const char* pszWindow, const char * pszNick, const char* pszText, const char* pszStatus, const char* pszUserInfo, DWORD dwItemData, bool bAddToLog, bool bIsMe,time_t timestamp = 1);
+int CallChatEvent(WPARAM wParam, LPARAM lParam);
+String ModeToStatus(char sMode) ;
+String PrefixToStatus(char cPrefix) ;
+void SetChatTimer(UINT_PTR &nIDEvent,UINT uElapse,TIMERPROC lpTimerFunc);
+void KillChatTimer(UINT_PTR &nIDEvent);
+int SetChannelSBText(String sWindow, CHANNELINFO * wi);
+String MakeWndID(String sWindow);
+bool FreeWindowItemData(String window, CHANNELINFO* wis);
+bool AddWindowItemData(String window, const char * pszLimit, const char * pszMode, const char * pszPassword, const char * pszTopic);
+void FindLocalIP(HANDLE con);
+void DoUserhostWithReason(int type, String reason, bool bSendCommand, String userhostparams, ...);
+String GetNextUserhostReason(int type);
+void ClearUserhostReasons(int type);
+String PeekAtReasons(int type);
+//clist.cpp
+HANDLE CList_AddContact(struct CONTACT_TYPE * user, bool InList, bool SetOnline);
+bool CList_SetAllOffline(BYTE ChatsToo);
+HANDLE CList_SetOffline(struct CONTACT_TYPE * user);
+
+bool CList_AddEvent(struct CONTACT_TYPE * user, HICON Icon, HANDLE event, const char * tooltip, int type ) ;
+HANDLE CList_FindContact (struct CONTACT_TYPE * user);
+int WCCmp(char* wild, char *string);
+BOOL CList_AddDCCChat(String name, String hostmask, unsigned long adr, int port) ;
+
+//input.cpp
+bool PostIrcMessageWnd(char * pszWindow, HANDLE hContact,const char * szBuf);
+bool PostIrcMessage( const char * fmt, ...);
+
+//output
+BOOL ShowMessage (const CIrcMessage* pmsg);
+
+//windows.cpp
+BOOL CALLBACK MessageboxWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+BOOL CALLBACK InfoWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+BOOL CALLBACK NickWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+BOOL CALLBACK JoinWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+BOOL CALLBACK InitWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+BOOL CALLBACK ListWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+BOOL CALLBACK QuickWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+BOOL CALLBACK UserDetailsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK ManagerWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+BOOL CALLBACK QuestionWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+int CALLBACK ListViewSort(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
+LRESULT CALLBACK MgrEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) ;
+
+//commandmonitor.cpp
+VOID CALLBACK KeepAliveTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);
+VOID CALLBACK OnlineNotifTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);
+VOID CALLBACK OnlineNotifTimerProc3(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);
+
+//scripting.cpp
+int Scripting_InsertRawIn(WPARAM wParam,LPARAM lParam);
+int Scripting_InsertRawOut(WPARAM wParam,LPARAM lParam);
+int Scripting_InsertGuiIn(WPARAM wParam,LPARAM lParam);
+int Scripting_InsertGuiOut(WPARAM wParam,LPARAM lParam);
+int Scripting_GetIrcData(WPARAM wparam, LPARAM lparam);
+BOOL Scripting_TriggerMSPRawIn(char ** pszRaw);
+BOOL Scripting_TriggerMSPRawOut(char ** pszRaw);
+BOOL Scripting_TriggerMSPGuiIn(WPARAM * wparam, GCEVENT * gce);
+BOOL Scripting_TriggerMSPGuiOut(GCHOOK * gch);
+
+#ifndef NDEBUG
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#pragma comment(lib,"comctl32.lib")
+
+#endif
+
diff --git a/irc_mod/irclib.cpp b/irc_mod/irclib.cpp
new file mode 100644
index 0000000..59eaffc
--- /dev/null
+++ b/irc_mod/irclib.cpp
@@ -0,0 +1,1865 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "irc.h"
+#include "tchar.h"
+#include <stdio.h>
+extern char * IRCPROTONAME;
+extern HANDLE hNetlib;
+extern HANDLE hNetlibDCC;
+extern UINT_PTR OnlineNotifTimer;
+extern UINT_PTR OnlineNotifTimer3;
+extern HMODULE m_ssleay32;
+extern PREFERENCES * prefs;
+extern MM_INTERFACE mmi;
+extern bool bMbotInstalled;
+UINT_PTR DCCTimer;
+CRITICAL_SECTION m_resolve;
+int i = 0;
+#define DCCCHATTIMEOUT 300
+#define DCCSENDTIMEOUT 120
+
+using namespace irc;
+
+int CDccSession::nDcc = 0;
+
+
+////////////////////////////////////////////////////////////////////
+
+CIrcMessage::CIrcMessage(const char* lpszCmdLine, bool bIncoming, bool bNotify)
+ : m_bIncoming(bIncoming), m_bNotify(bNotify)
+{
+ ParseIrcCommand(lpszCmdLine);
+}
+
+CIrcMessage::CIrcMessage(const CIrcMessage& m)
+ : sCommand(m.sCommand),
+ parameters(m.parameters),
+ m_bIncoming(m.m_bIncoming),
+ m_bNotify(m.m_bNotify)
+{
+ prefix.sNick = m.prefix.sNick;
+ prefix.sUser = m.prefix.sUser;
+ prefix.sHost = m.prefix.sHost;
+}
+
+void CIrcMessage::Reset()
+{
+ prefix.sNick = prefix.sUser = prefix.sHost = sCommand = "";
+ m_bIncoming = false;
+ m_bNotify = true;
+ parameters.clear();
+}
+
+CIrcMessage& CIrcMessage::operator = (const CIrcMessage& m)
+{
+ if( &m != this )
+ {
+ sCommand = m.sCommand;
+ parameters = m.parameters;
+ prefix.sNick = m.prefix.sNick;
+ prefix.sUser = m.prefix.sUser;
+ prefix.sHost = m.prefix.sHost;
+ m_bIncoming = m.m_bIncoming;
+ m_bNotify = m.m_bNotify;
+ }
+ return *this;
+}
+
+CIrcMessage& CIrcMessage::operator = (const char* lpszCmdLine)
+{
+ Reset();
+ ParseIrcCommand(lpszCmdLine);
+ return *this;
+}
+
+void CIrcMessage::ParseIrcCommand(const char* lpszCmdLine)
+{
+ const char* p1 = lpszCmdLine;
+ const char* p2 = lpszCmdLine;
+
+// ASSERT(lpszCmdLine != NULL);
+// ASSERT(*lpszCmdLine);
+
+ // prefix exists ?
+ if( *p1 == ':' )
+ { // break prefix into its components (nick!user@host)
+ p2 = ++p1;
+ while( *p2 && !strchr(" !", *p2) )
+ ++p2;
+ prefix.sNick.assign(p1, p2 - p1);
+ if( *p2 != '!' )
+ goto end_of_prefix;
+ p1 = ++p2;
+ while( *p2 && !strchr(" @", *p2) )
+ ++p2;
+ prefix.sUser.assign(p1, p2 - p1);
+ if( *p2 != '@' )
+ goto end_of_prefix;
+ p1 = ++p2;
+ while( *p2 && *p2 != ' ' )
+ ++p2;
+ prefix.sHost.assign(p1, p2 - p1);
+end_of_prefix :
+ while( *p2 && *p2 == ' ' )
+ ++p2;
+ p1 = p2;
+ }
+
+ // get command
+// ASSERT(*p1 != '\0');
+ p2 = p1;
+ while( *p2 && *p2 != ' ' )
+ ++p2;
+ sCommand.assign(p1, p2 - p1);
+ _strupr((char*)sCommand.c_str());
+ while( *p2 && *p2 == ' ' )
+ ++p2;
+ p1 = p2;
+
+ // get parameters
+ while( *p1 )
+ {
+ if( *p1 == ':')
+ {
+ ++p1;
+// if (*p1 == '\0')
+// break;
+ // seek end-of-message
+ while( *p2 )
+ ++p2;
+ parameters.push_back(String(p1, p2 - p1));
+ break;
+ }
+ else
+ {
+ // seek end of parameter
+ while( *p2 && *p2 != ' ' )
+ ++p2;
+ parameters.push_back(String(p1, p2 - p1));
+ // see next parameter
+ while( *p2 && *p2 == ' ' )
+ ++p2;
+ p1 = p2;
+ }
+ } // end parameters loop
+}
+
+String CIrcMessage::AsString() const
+{
+ String s;
+
+ if( prefix.sNick.length() )
+ {
+ s += ":" + prefix.sNick;
+ if( prefix.sUser.length() && prefix.sHost.length() )
+ s += "!" + prefix.sUser + "@" + prefix.sHost;
+ s += " ";
+ }
+
+ s += sCommand;
+
+ for(int i=0; i < (int)parameters.size(); i++)
+ {
+ s += " ";
+ if( i == parameters.size() - 1 && (strchr(parameters[i].c_str(), ' ') || parameters[i][0] == ':' ) )// is last parameter ?
+ s += ":";
+ s += parameters[i];
+ }
+
+ s += endl;
+
+ return s;
+}
+
+////////////////////////////////////////////////////////////////////
+//#ifdef IRC_SSL
+
+int CSSLSession::SSLInit()
+{
+ if(m_ssl_ctx) return true;
+ if(!m_ssleay32) return false;
+
+ pSSL_library_init = (tSSL_library_init) GetProcAddress(m_ssleay32, "SSL_library_init");
+ pSSL_CTX_new = (tSSL_CTX_new) GetProcAddress(m_ssleay32, "SSL_CTX_new");
+ pSSL_new = (tSSL_new) GetProcAddress(m_ssleay32, "SSL_new");
+ pSSL_set_fd = (tSSL_set_fd) GetProcAddress(m_ssleay32, "SSL_set_fd");
+ pSSL_connect = (tSSL_connect) GetProcAddress(m_ssleay32, "SSL_connect");
+ pSSL_read = (tSSL_read) GetProcAddress(m_ssleay32, "SSL_read");
+ pSSL_write = (tSSL_write) GetProcAddress(m_ssleay32, "SSL_write");
+ pSSLv23_method = (tSSLv23_method) GetProcAddress(m_ssleay32, "SSLv23_method");
+ pSSL_get_error = (tSSL_get_error) GetProcAddress(m_ssleay32, "SSL_get_error");
+ pSSL_load_error_strings = (tSSL_load_error_strings) GetProcAddress(m_ssleay32, "SSL_load_error_strings");
+ pSSL_shutdown = (tSSL_shutdown) GetProcAddress(m_ssleay32, "SSL_shutdown");
+ pSSL_CTX_free = (tSSL_CTX_free) GetProcAddress(m_ssleay32, "SSL_CTX_free");
+ pSSL_free = (tSSL_free) GetProcAddress(m_ssleay32, "SSL_free");
+
+ if( !pSSL_library_init ||
+ !pSSL_CTX_new ||
+ !pSSL_new ||
+ !pSSL_set_fd ||
+ !pSSL_connect ||
+ !pSSL_read ||
+ !pSSL_write ||
+ !pSSLv23_method ||
+ !pSSL_get_error ||
+ !pSSL_load_error_strings ||
+ !pSSL_shutdown ||
+ !pSSL_CTX_free ||
+ !pSSL_free //||
+ )
+ {
+ return false;
+ }
+
+ if(!pSSL_library_init())
+ {
+ return false;
+ }
+ m_ssl_ctx=pSSL_CTX_new(pSSLv23_method());
+
+ if (!m_ssl_ctx) {
+ return false;
+ }
+
+ pSSL_load_error_strings();
+ return true;
+}
+
+CSSLSession::~CSSLSession() {
+ if(m_ssl_ctx)
+ pSSL_CTX_free(m_ssl_ctx);
+ m_ssl_ctx = 0;
+
+}
+
+
+int CSSLSession::SSLConnect(HANDLE con) {
+ if(!SSLInit())
+ return false;
+
+ SOCKET s = (SOCKET) CallService(MS_NETLIB_GETSOCKET, (WPARAM) con, (LPARAM) 0);
+
+ if(s == INVALID_SOCKET)
+ return false;
+
+ m_ssl = pSSL_new(m_ssl_ctx);
+
+ if(!m_ssl)
+ return false;
+
+ if(m_ssl) pSSL_set_fd(m_ssl, s);
+ nSSLConnected = pSSL_connect(m_ssl);
+ if(nSSLConnected != 1) {
+ return false;
+ }
+ return true;
+}
+
+int CSSLSession::SSLDisconnect(void) {
+ if(nSSLConnected != 1) return true;
+
+ int nSSLret = pSSL_shutdown(m_ssl);
+ if(nSSLret == 0) nSSLret = pSSL_shutdown(m_ssl);
+
+ pSSL_free(m_ssl);
+ m_ssl = 0;
+ nSSLConnected = 0;
+
+ return nSSLret;
+}
+//#endif
+////////////////////////////////////////////////////////////////////
+
+CIrcSession::CIrcSession(IIrcSessionMonitor* pMonitor)
+{
+ InitializeCriticalSection(&m_cs);
+ InitializeCriticalSection(&m_resolve);
+ InitializeCriticalSection(&m_dcc);
+
+}
+
+CIrcSession::~CIrcSession()
+{
+ // Disconnect();
+ DeleteCriticalSection(&m_cs);
+ DeleteCriticalSection(&m_resolve);
+ DeleteCriticalSection(&m_dcc);
+ KillChatTimer(OnlineNotifTimer);
+ KillChatTimer(OnlineNotifTimer3);
+}
+
+
+bool CIrcSession::Connect(const CIrcSessionInfo& info)
+{
+ try
+ {
+ NETLIBOPENCONNECTION ncon;
+ ncon.cbSize = sizeof(ncon);
+ ncon.szHost = info.sServer.c_str();
+ ncon.wPort = info.iPort;
+ con = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) hNetlib, (LPARAM) & ncon);
+
+ if (con == NULL)
+ return false;
+
+ FindLocalIP(con); // get the local ip used for filetransfers etc
+
+//#ifdef IRC_SSL
+
+ if(info.iSSL > 0)
+ {
+ sslSession.SSLConnect(con); // Establish SSL connection
+ if(sslSession.nSSLConnected != 1 && info.iSSL == 2)
+ {
+ Netlib_CloseHandle(con);
+ con = NULL;
+ m_info.Reset();
+
+ return false;
+ }
+ }
+//#endif
+
+ if(Miranda_Terminated())
+ {
+ Disconnect();
+ return false;
+ }
+
+ m_info = info;
+
+ // start receiving messages from host
+ forkthread(ThreadProc, 0, this );
+ Sleep(100);
+ if( info.sPassword.length() )
+ NLSend("PASS %s\r\n", info.sPassword.c_str());
+ NLSend("NICK %s\r\n", info.sNick.c_str());
+
+ String UserID = GetWord(info.sUserID.c_str(), 0);
+ TCHAR szHostName[MAX_PATH];
+ DWORD cbHostName = sizeof(szHostName);
+ GetComputerName(szHostName, &cbHostName);
+ String HostName = GetWord(szHostName, 0);
+ if (UserID.empty())
+ UserID= "Miranda";
+ if (HostName.empty())
+ HostName= "host";
+ NLSend("USER %s %s %s :%s\r\n", UserID.c_str(), HostName.c_str(), "server", info.sFullName.c_str());
+ }
+ catch( const char* )
+ {
+ Disconnect();
+ }
+ catch( ... )
+ {
+ Disconnect();
+ }
+
+ return con!=NULL;
+}
+
+void CIrcSession::Disconnect(void)
+{
+ static const DWORD dwServerTimeout = 5 * 1000;
+
+ if( con == NULL )
+ return;
+
+ if(prefs->QuitMessage && lstrlen(prefs->QuitMessage)>0)
+ NLSend("QUIT :%s\r\n", prefs->QuitMessage);
+ else
+ NLSend("QUIT \r\n", prefs->QuitMessage);
+
+
+
+ int i = 0;
+ while(
+//#ifdef IRC_SSL
+
+ sslSession.nSSLConnected && sslSession.m_ssl || !sslSession.nSSLConnected &&
+//#endif
+ con)
+ {
+ Sleep(50);
+ if (i == 20)
+ break;
+ i++;
+ }
+//#ifdef IRC_SSL
+ sslSession.SSLDisconnect(); // Close SSL connection
+//#endif
+
+ if(con)
+ Netlib_CloseHandle(con);
+
+ con = NULL;
+
+ m_info.Reset();
+ return;
+}
+
+void CIrcSession::Notify(const CIrcMessage* pmsg)
+{
+ // forward message to monitor objects
+ EnterCriticalSection(&m_cs);
+ for(std::set<IIrcSessionMonitor*>::iterator it = m_monitors.begin();
+ it != m_monitors.end();
+ it++
+ )
+ {
+ (*it)->OnIrcMessage(pmsg);
+ }
+ LeaveCriticalSection(&m_cs);
+}
+
+int CIrcSession::NLSend( const unsigned char* buf, int cbBuf)
+{
+ if(bMbotInstalled && prefs->ScriptingEnabled)
+ {
+ int iVal = NULL;
+ char * pszTemp = 0;
+ pszTemp = (char *) mmi.mmi_malloc( lstrlen((const char *) buf ) + 1);
+ lstrcpyn(pszTemp, (const char *)buf, lstrlen ((const char *)buf) + 1);
+
+ if( Scripting_TriggerMSPRawOut(&pszTemp) && pszTemp )
+ {
+//#ifdef IRC_SSL
+ if(sslSession.nSSLConnected == 1)
+ {
+ iVal = pSSL_write(sslSession.m_ssl, pszTemp, lstrlen(pszTemp));
+ }
+ else
+//#endif
+ if (con)
+ iVal = Netlib_Send(con, (const char*)pszTemp, lstrlen(pszTemp), MSG_DUMPASTEXT);
+ }
+ if(pszTemp)
+ mmi.mmi_free ( pszTemp );
+
+ return iVal;
+ }
+ else
+ {
+
+//#ifdef IRC_SSL
+ if(sslSession.nSSLConnected == 1)
+ {
+ return pSSL_write(sslSession.m_ssl, buf, cbBuf);
+ }
+ else
+//#endif
+ if (con)
+ return Netlib_Send(con, (const char*)buf, cbBuf, MSG_DUMPASTEXT);
+ }
+ return 0;
+
+}
+
+int CIrcSession::NLSend( const char* fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+
+ char szBuf[1024*4];
+ vsprintf(szBuf, fmt, marker);
+
+ va_end(marker);
+
+ return NLSend((unsigned char*)szBuf, strlen(szBuf));
+}
+int CIrcSession::NLSendNoScript( const unsigned char* buf, int cbBuf)
+{
+
+//#ifdef IRC_SSL
+ if(sslSession.nSSLConnected == 1)
+ {
+ return pSSL_write(sslSession.m_ssl, buf, cbBuf);
+ }
+ else
+//#endif
+ if (con)
+ return Netlib_Send(con, (const char*)buf, cbBuf, MSG_DUMPASTEXT);
+
+ return 0;
+
+}
+int CIrcSession::NLReceive(unsigned char* buf, int cbBuf)
+{
+ int n = 0;
+//#ifdef IRC_SSL
+ if(sslSession.nSSLConnected == 1)
+ n = pSSL_read(sslSession.m_ssl, buf, cbBuf);
+ else
+//#endif
+ n = Netlib_Recv(con, (char*)buf, cbBuf, MSG_DUMPASTEXT);
+
+ return n;
+}
+
+void CIrcSession::KillIdent()
+{
+ if (hBindPort)
+ Netlib_CloseHandle(hBindPort);
+ return;
+}
+
+void CIrcSession::InsertIncomingEvent(char * pszRaw)
+{
+ CIrcMessage msg(pszRaw, true);
+ Notify(&msg);
+ return;
+}
+
+void CIrcSession::DoReceive()
+{
+ char chBuf[1024*4+1];
+ int cbInBuf = 0;
+
+
+ if (m_info.bIdentServer && m_info.iIdentServerPort != NULL )
+ {
+ NETLIBBIND nb = {0};
+ nb.cbSize = sizeof(NETLIBBIND);
+ nb.pfnNewConnectionV2 = DoIdent;
+ nb.wPort = m_info.iIdentServerPort;
+ hBindPort= (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)hNetlib,(LPARAM) &nb);
+ if (!hBindPort || nb.wPort != m_info.iIdentServerPort)
+ {
+ char szTemp[200];
+ mir_snprintf(szTemp, sizeof(szTemp), "Error: unable to bind local port %u", m_info.iIdentServerPort);
+ CallService(MS_NETLIB_LOG, (WPARAM) hNetlib , (LPARAM) szTemp );
+ KillIdent();
+ }
+ }
+
+ while( con )
+ {
+ int cbRead;
+ int nLinesProcessed = 0;
+
+ cbRead = NLReceive((unsigned char*)chBuf+cbInBuf, sizeof(chBuf)-cbInBuf-1);
+ if( cbRead <= 0 )
+ break;
+ cbInBuf += cbRead;
+ chBuf[cbInBuf] = '\0';
+
+ char* pStart = chBuf;
+ while( *pStart )
+ {
+ char* pEnd;
+
+ // seek end-of-line
+ for(pEnd=pStart; *pEnd && *pEnd != '\r' && *pEnd != '\n'; ++pEnd)
+ ;
+ if( *pEnd == '\0' )
+ break; // uncomplete message. stop parsing.
+
+ ++nLinesProcessed;
+
+ // replace end-of-line with NULLs and skip
+ while( *pEnd == '\r' || *pEnd == '\n' )
+ *pEnd++ = '\0';
+
+ // process single message by monitor objects
+ if( *pStart )
+ {
+ if(bMbotInstalled && prefs->ScriptingEnabled)
+ {
+
+ char * pszTemp = NULL;
+ pszTemp = (char *) mmi.mmi_malloc(lstrlen(pStart) + 1);
+ lstrcpyn(pszTemp, pStart, lstrlen (pStart) + 1);
+
+ if( Scripting_TriggerMSPRawIn(&pszTemp) && pszTemp)
+ {
+ char* p1 = pszTemp;
+ // replace end-of-line with NULLs
+ while( *p1 != '\0')
+ {
+ if( *p1 == '\r' || *p1 == '\n')
+ *p1 = '\0';
+ *p1++;
+ }
+
+ CIrcMessage msg(pszTemp, true);
+ Notify(&msg);
+ }
+
+ if(pszTemp)
+ mmi.mmi_free( pszTemp );
+ }
+ else
+ {
+ CIrcMessage msg(pStart, true);
+ Notify(&msg);
+ }
+ }
+
+ cbInBuf -= pEnd - pStart;
+// ASSERT(cbInBuf >= 0);
+
+ pStart = pEnd;
+ }
+
+ // discard processed messages
+ if( nLinesProcessed != 0 )
+ memmove(chBuf, pStart, cbInBuf+1);
+ }
+ if( con )
+ {
+ Netlib_CloseHandle(con);
+ con = NULL;
+ }
+
+ KillIdent();
+
+ // notify monitor objects that the connection has been closed
+ Notify(NULL);
+}
+
+
+void __cdecl CIrcSession::ThreadProc(void *pparam)
+{
+// CallService(MS_SYSTEM_THREAD_PUSH, 0, 0);
+ CIrcSession* pThis = (CIrcSession*)pparam;
+ try { pThis->DoReceive(); } catch( ... ) {}
+ pThis->m_info.Reset();
+ // CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+ return;
+}
+
+void CIrcSession::AddDCCSession(HANDLE hContact, CDccSession * dcc)
+{
+ EnterCriticalSection(&m_dcc);
+
+ DccSessionMap::iterator it = m_dcc_chats.find(hContact);
+ if(it != m_dcc_chats.end())
+ {
+ m_dcc_chats.erase(it);
+ }
+ g_ircSession.m_dcc_chats.insert(DccSessionPair(hContact, dcc));
+
+ LeaveCriticalSection(&m_dcc);
+}
+void CIrcSession::AddDCCSession(DCCINFO * pdci, CDccSession * dcc)
+{
+ EnterCriticalSection(&m_dcc);
+
+ g_ircSession.m_dcc_xfers.insert(DccSessionPair(pdci, dcc));
+
+ LeaveCriticalSection(&m_dcc);
+}
+void CIrcSession::RemoveDCCSession(HANDLE hContact)
+{
+ EnterCriticalSection(&m_dcc);
+
+ DccSessionMap::iterator it = m_dcc_chats.find(hContact);
+ if(it != m_dcc_chats.end())
+ {
+ m_dcc_chats.erase(it);
+ }
+
+ LeaveCriticalSection(&m_dcc);
+}
+void CIrcSession::RemoveDCCSession(DCCINFO * pdci)
+{
+ EnterCriticalSection(&m_dcc);
+
+ DccSessionMap::iterator it = m_dcc_xfers.find(pdci);
+ if(it != m_dcc_xfers.end())
+ {
+ m_dcc_xfers.erase(it);
+ }
+
+ LeaveCriticalSection(&m_dcc);
+}
+CDccSession * CIrcSession::FindDCCSession(HANDLE hContact)
+{
+ EnterCriticalSection(&m_dcc);
+
+ DccSessionMap::iterator it = m_dcc_chats.find(hContact);
+ if(it != m_dcc_chats.end())
+ {
+ LeaveCriticalSection(&m_dcc);
+ return (CDccSession *)it->second;
+ }
+ LeaveCriticalSection(&m_dcc);
+ return 0;
+}
+CDccSession * CIrcSession::FindDCCSession(DCCINFO * pdci)
+{
+ EnterCriticalSection(&m_dcc);
+
+ DccSessionMap::iterator it = m_dcc_xfers.find(pdci);
+ if(it != m_dcc_xfers.end())
+ {
+ LeaveCriticalSection(&m_dcc);
+ return (CDccSession *)it->second;
+ }
+ LeaveCriticalSection(&m_dcc);
+ return 0;
+}
+
+CDccSession * CIrcSession::FindDCCSendByPort(int iPort)
+{
+ EnterCriticalSection(&m_dcc);
+ CDccSession * dcc = NULL;
+
+ DccSessionMap::iterator it = m_dcc_xfers.begin();
+ while(it != m_dcc_xfers.end())
+ {
+ dcc = it->second;
+ if(dcc->di->iType == DCC_SEND && dcc->di->bSender && iPort == dcc->di->iPort)
+ {
+ LeaveCriticalSection(&m_dcc);
+ return (CDccSession *)it->second;
+ }
+ it++;
+ }
+ LeaveCriticalSection(&m_dcc);
+ return 0;
+}
+CDccSession * CIrcSession::FindDCCRecvByPortAndName(int iPort, char * szName)
+{
+ EnterCriticalSection(&m_dcc);
+ CDccSession * dcc = NULL;
+
+ DccSessionMap::iterator it = m_dcc_xfers.begin();
+ while(it != m_dcc_xfers.end())
+ {
+ dcc = it->second;
+ DBVARIANT dbv;
+
+ if (!DBGetContactSetting(dcc->di->hContact, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ )
+ {
+
+ if(dcc->di->iType == DCC_SEND && !dcc->di->bSender && !lstrcmpi(szName, dbv.pszVal) && iPort == dcc->di->iPort)
+ {
+ DBFreeVariant(&dbv);
+ LeaveCriticalSection(&m_dcc);
+ return (CDccSession *)it->second;
+ }
+ DBFreeVariant(&dbv);
+ }
+ it++;
+ }
+ LeaveCriticalSection(&m_dcc);
+ return 0;
+}
+
+CDccSession * CIrcSession::FindPassiveDCCSend(int iToken)
+{
+ EnterCriticalSection(&m_dcc);
+ CDccSession * dcc = NULL;
+
+ DccSessionMap::iterator it = m_dcc_xfers.begin();
+ while(it != m_dcc_xfers.end())
+ {
+ dcc = it->second;
+
+ if (iToken == dcc->iToken)
+ {
+ LeaveCriticalSection(&m_dcc);
+ return (CDccSession *)it->second;
+ }
+ it++;
+ }
+ LeaveCriticalSection(&m_dcc);
+ return 0;
+}
+
+CDccSession * CIrcSession::FindPassiveDCCRecv(String sName, String sToken)
+{
+ EnterCriticalSection(&m_dcc);
+ CDccSession * dcc = NULL;
+
+ DccSessionMap::iterator it = m_dcc_xfers.begin();
+ while(it != m_dcc_xfers.end())
+ {
+ dcc = it->second;
+
+ if (sToken == dcc->di->sToken && sName == dcc->di->sContactName)
+ {
+ LeaveCriticalSection(&m_dcc);
+ return (CDccSession *)it->second;
+ }
+ it++;
+ }
+ LeaveCriticalSection(&m_dcc);
+ return 0;
+}
+
+void CIrcSession::DisconnectAllDCCSessions(bool Shutdown)
+{
+ EnterCriticalSection(&m_dcc);
+
+ DccSessionMap::iterator it = m_dcc_chats.begin();
+ CDccSession * dcc;
+
+ while(it != m_dcc_chats.end())
+ {
+ dcc = it->second;
+ it++;
+ if(prefs->DisconnectDCCChats || Shutdown)
+ dcc->Disconnect();
+ }
+
+ LeaveCriticalSection(&m_dcc);
+ return;
+
+}
+void CIrcSession::CheckDCCTimeout(void)
+{
+ EnterCriticalSection(&m_dcc);
+
+ DccSessionMap::iterator it = m_dcc_chats.begin();
+ CDccSession * dcc;
+
+ while(it != m_dcc_chats.end())
+ {
+ dcc = it->second;
+ it++;
+ if(time(0) > dcc->tLastActivity + DCCCHATTIMEOUT)
+ dcc->Disconnect();
+ }
+
+ it = m_dcc_xfers.begin();
+ while(it != m_dcc_xfers.end())
+ {
+ dcc = it->second;
+ it++;
+ if(time(0) > dcc->tLastActivity + DCCSENDTIMEOUT)
+ dcc->Disconnect();
+ }
+
+ LeaveCriticalSection(&m_dcc);
+ return;
+}
+
+void CIrcSession::AddIrcMonitor(IIrcSessionMonitor* pMonitor)
+{
+// ASSERT(pMonitor != NULL);
+ EnterCriticalSection(&m_cs);
+ m_monitors.insert(pMonitor);
+ LeaveCriticalSection(&m_cs);
+}
+
+void CIrcSession::RemoveMonitor(IIrcSessionMonitor* pMonitor)
+{
+// ASSERT(pMonitor != NULL);
+ EnterCriticalSection(&m_cs);
+ m_monitors.erase(pMonitor);
+ LeaveCriticalSection(&m_cs);
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+
+CIrcSessionInfo::CIrcSessionInfo()
+ : iPort(0), bIdentServer(false), iIdentServerPort(0)
+{
+}
+
+CIrcSessionInfo::CIrcSessionInfo(const CIrcSessionInfo& si)
+ : sServer(si.sServer),
+ sServerName(si.sServerName),
+ iPort(si.iPort),
+ sNick(si.sNick),
+ sUserID(si.sUserID),
+ sFullName(si.sFullName),
+ sPassword(si.sPassword),
+ bIdentServer(si.bIdentServer),
+ iSSL(si.iSSL),
+ sIdentServerType(si.sIdentServerType),
+ sNetwork(si.sNetwork),
+ iIdentServerPort(si.iIdentServerPort)
+{
+}
+
+void CIrcSessionInfo::Reset()
+{
+ sServer = "";
+ sServerName = "";
+ iPort = 0;
+ sNick = "";
+ sUserID = "";
+ sFullName = "";
+ sPassword = "";
+ bIdentServer = false;
+ bNickFlag = false;
+ iSSL = 0;
+ sIdentServerType = "";
+ iIdentServerPort = 0;
+ sNetwork = "";
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+CIrcMonitor::HandlersMap CIrcMonitor::m_handlers;
+CIrcMonitor::IrcCommandsMapsListEntry CIrcMonitor::m_handlersMapsListEntry
+ = { &CIrcMonitor::m_handlers, NULL };
+
+
+CIrcMonitor::CIrcMonitor(CIrcSession& session)
+ : m_session(session)
+{
+}
+
+CIrcMonitor::~CIrcMonitor()
+{
+}
+
+void CIrcMonitor::OnIrcMessage(const CIrcMessage* pmsg)
+{
+ XTHREADS * xthread = NULL;
+ xthread = new XTHREADS;
+ xthread->pthis = (void *)this;
+ xthread->pmsg = NULL;
+
+ if( pmsg )
+ {
+ xthread->pmsg = new CIrcMessage(*pmsg);
+ }
+ CallFunctionAsync(OnCrossThreadsMessage, (void *)xthread);
+}
+
+void CIrcMonitor::OnCrossThreadsMessage(void * p)
+{
+ XTHREADS * xthread = (XTHREADS *)p;
+ if (xthread)
+ {
+ CIrcMonitor * pmon = (CIrcMonitor *)xthread->pthis;
+
+ if(xthread->pmsg)
+ {
+ pmon->OnIrcAll(xthread->pmsg);
+
+ PfnIrcMessageHandler pfn = pmon->FindMethod(xthread->pmsg->sCommand.c_str());
+ if( pfn )
+ {
+ // call member function. if it returns 'false',
+ // call the default handling
+ if( !(pmon->*pfn)(xthread->pmsg) )
+ pmon->OnIrcDefault(xthread->pmsg);
+ }
+ else // handler not found. call default handler
+ pmon->OnIrcDefault(xthread->pmsg);
+
+ delete xthread->pmsg;
+ }
+ else
+ pmon->OnIrcDisconnected();
+ delete xthread;
+ }
+}
+
+CIrcMonitor::PfnIrcMessageHandler CIrcMonitor::FindMethod(const char* lpszName)
+{
+ // call the recursive version with the most derived map
+ return FindMethod(GetIrcCommandsMap(), lpszName);
+}
+
+CIrcMonitor::PfnIrcMessageHandler CIrcMonitor::FindMethod(IrcCommandsMapsListEntry* pMapsList, const char* lpszName)
+{
+ HandlersMap::iterator it = pMapsList->pHandlersMap->find(lpszName);
+ if( it != pMapsList->pHandlersMap->end() )
+ return it->second; // found !
+ else if( pMapsList->pBaseHandlersMap )
+ return FindMethod(pMapsList->pBaseHandlersMap, lpszName); // try at base class
+ return NULL; // not found in any map
+}
+
+////////////////////////////////////////////////////////////////////
+
+DECLARE_IRC_MAP(CIrcDefaultMonitor, CIrcMonitor)
+
+CIrcDefaultMonitor::CIrcDefaultMonitor(CIrcSession& session)
+ : CIrcMonitor(session)
+{
+ IRC_MAP_ENTRY(CIrcDefaultMonitor, "NICK", OnIrc_NICK)
+ IRC_MAP_ENTRY(CIrcDefaultMonitor, "PING", OnIrc_PING)
+ IRC_MAP_ENTRY(CIrcDefaultMonitor, "002", OnIrc_YOURHOST)
+ IRC_MAP_ENTRY(CIrcDefaultMonitor, "001", OnIrc_WELCOME)
+}
+
+bool CIrcDefaultMonitor::OnIrc_NICK(const CIrcMessage* pmsg)
+{
+ if( (m_session.GetInfo().sNick == pmsg->prefix.sNick) && (pmsg->parameters.size() > 0) )
+ {
+ m_session.m_info.sNick = pmsg->parameters[0];
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"Nick",m_session.m_info.sNick.c_str());
+ }
+ return false;
+}
+
+bool CIrcDefaultMonitor::OnIrc_PING(const CIrcMessage* pmsg)
+{
+ char szResponse[100];
+ sprintf(szResponse, "PONG %s", pmsg->parameters[0].c_str());
+ m_session << CIrcMessage(szResponse);
+ return false;
+}
+
+bool CIrcDefaultMonitor::OnIrc_YOURHOST(const CIrcMessage* pmsg)
+{
+ static const char* lpszFmt = "Your host is %[^ \x5b,], running version %s";
+ char szHostName[100], szVersion[100];
+ if( sscanf(pmsg->parameters[1].c_str(), lpszFmt, &szHostName, &szVersion) > 0 )
+ m_session.m_info.sServerName = szHostName;
+ if (pmsg->parameters[0] != m_session.GetInfo().sNick)
+ m_session.m_info.sNick = pmsg->parameters[0];
+ return false;
+}
+bool CIrcDefaultMonitor::OnIrc_WELCOME(const CIrcMessage* pmsg)
+{
+ if (pmsg->parameters[0] != m_session.GetInfo().sNick)
+ m_session.m_info.sNick = pmsg->parameters[0];
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////
+
+#define IPC_ADDR_SIZE 4 /* Size of IP address, change for IPv6. */
+
+char* ConvertIntegerToIP(unsigned long int_ip_addr) {
+ IN_ADDR intemp;
+ IN_ADDR in;
+ intemp.S_un.S_addr = int_ip_addr;
+
+ in.S_un.S_un_b.s_b1 = intemp.S_un.S_un_b.s_b4;
+ in.S_un.S_un_b.s_b2 = intemp.S_un.S_un_b.s_b3;
+ in.S_un.S_un_b.s_b3 = intemp.S_un.S_un_b.s_b2;
+ in.S_un.S_un_b.s_b4 = intemp.S_un.S_un_b.s_b1;
+
+ return inet_ntoa( in );
+
+}
+unsigned long ConvertIPToInteger(char * IP) {
+ IN_ADDR in;
+ IN_ADDR intemp;
+
+ if( IP == 0 || lstrlen(IP) == 0)
+ return 0;
+
+ intemp.S_un.S_addr = inet_addr(IP);
+
+ in.S_un.S_un_b.s_b1 = intemp.S_un.S_un_b.s_b4;
+ in.S_un.S_un_b.s_b2 = intemp.S_un.S_un_b.s_b3;
+ in.S_un.S_un_b.s_b3 = intemp.S_un.S_un_b.s_b2;
+ in.S_un.S_un_b.s_b4 = intemp.S_un.S_un_b.s_b1;
+
+ return in.S_un.S_addr;
+
+}
+
+
+////////////////////////////////////////////////////////////////////
+
+// initialize basic stuff needed for the dcc objects, also start a timer for checking the status of connections (timeouts)
+CDccSession::CDccSession(DCCINFO * pdci) : NewFileName(0), dwWhatNeedsDoing(0), tLastPercentageUpdate(0), iTotal(0), iGlobalToken(), dwResumePos(0), hEvent(0), con(0), hBindPort(0)
+{
+ tLastActivity = time(0);
+
+ di = pdci; // Setup values passed to the constructor
+
+ ZeroMemory(&pfts, sizeof(PROTOFILETRANSFERSTATUS));
+ pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
+
+ if(di->iType == DCC_SEND && di->bSender == false)
+ hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if(nDcc == 0)
+ SetChatTimer(DCCTimer, 20*1000, DCCTimerProc);
+
+ nDcc++; // increase the count of existing objects
+
+ iGlobalToken++;
+ if(iGlobalToken == 1000)
+ iGlobalToken = 1;
+ iToken = iGlobalToken;
+
+ iPacketSize = DBGetContactSettingWord(NULL,IRCPROTONAME, "PacketSize", 4096);
+
+ if (di->dwAdr)
+ DBWriteContactSettingDword(di->hContact, IRCPROTONAME, "IP", di->dwAdr); // mtooltip stuff
+
+}
+
+CDccSession::~CDccSession() // destroy all that needs destroying
+{
+ if(di->iType == DCC_SEND)
+ {
+ // ack SUCCESS or FAILURE
+ if (iTotal == di->dwSize )
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, (void *)di, 0);
+ else
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (void *)di, 0);
+ }
+
+ if(di->iType == DCC_CHAT)
+ {
+ CDccSession * dcc = g_ircSession.FindDCCSession(di->hContact);
+ if(dcc && this == dcc)
+ {
+ g_ircSession.RemoveDCCSession(di->hContact); // objects automatically remove themselves from the list of objects
+ DBWriteContactSettingWord(di->hContact, IRCPROTONAME, "Status", ID_STATUS_OFFLINE);
+ }
+ }
+
+ if(di->iType == DCC_SEND)
+ g_ircSession.RemoveDCCSession(di);
+
+ if (hEvent != NULL)
+ {
+ SetEvent(hEvent);
+ CloseHandle(hEvent);
+ hEvent=NULL;
+ }
+
+ delete di;
+
+
+ nDcc--;
+
+ if(nDcc < 0)
+ nDcc = 0;
+ if(nDcc == 0)
+ KillChatTimer(DCCTimer); // destroy the timer when no dcc objects remain
+
+}
+
+int CDccSession::NLSend(const unsigned char* buf, int cbBuf)
+{
+ tLastActivity = time(0);
+
+ if (con)
+ return Netlib_Send(con, (const char*)buf, cbBuf, di->iType == DCC_CHAT?MSG_DUMPASTEXT:MSG_NODUMP);
+
+ return 0;
+}
+
+int CDccSession::NLReceive(const unsigned char* buf, int cbBuf) {
+ int n = 0;
+
+ if(con)
+ n = Netlib_Recv(con, (char*)buf, cbBuf, di->iType == DCC_CHAT?MSG_DUMPASTEXT:MSG_NODUMP);
+
+ tLastActivity = time(0);
+
+ return n;
+}
+
+int CDccSession::SendStuff(const char* fmt)
+{
+ return NLSend((unsigned char*)fmt, strlen(fmt));
+}
+
+// called when the user wants to connect/create a new connection given the parameters in the constructor.
+int CDccSession::Connect() {
+ if(!di->bSender || di->bReverse)
+ {
+ if(!con)
+ forkthread(ConnectProc, 0, this ); // spawn a new thread for time consuming activities, ie when connecting to a remote computer
+ return true;
+ }
+ else
+ {
+ if(!con)
+ return SetupConnection(); // no need to spawn thread for setting up a listening port locally
+ }
+
+ return false;
+}
+
+void __cdecl CDccSession::ConnectProc(void *pparam) {
+ CDccSession* pThis = (CDccSession*)pparam;
+ if(!pThis->con)
+ pThis->SetupConnection();
+ return;
+}
+// small function to setup the address and port of the remote computer fror passive filetransfers
+void CDccSession::SetupPassive(DWORD adress, DWORD port) {
+
+ di->dwAdr = adress;
+ di->iPort = (int)port;
+
+ DBWriteContactSettingDword(di->hContact, IRCPROTONAME, "IP", di->dwAdr); // mtooltip stuff
+
+ return;
+}
+int CDccSession::SetupConnection() {
+ //sets up the connection
+ try
+ {
+
+ // if it is a dcc chat connection make sure it is "offline" to begoin with, since no connection exists still
+ if(di->iType == DCC_CHAT )
+ DBWriteContactSettingWord(di->hContact, IRCPROTONAME, "Status", ID_STATUS_OFFLINE);
+
+ // Set up stuff needed for the filetransfer dialog (if it is a filetransfer)
+ if(di->iType == DCC_SEND)
+ {
+
+ file[0] = (char *)di->sFileAndPath.c_str();
+ file[1] = 0;
+
+ pfts.hContact = di->hContact;
+ pfts.sending = di->bSender?true:false;
+ pfts.totalFiles = 1;
+ pfts.currentFileNumber = 0;
+ pfts.currentFile = (char *)di->sFileAndPath.c_str();
+ pfts.totalBytes = di->dwSize;
+ pfts.currentFileSize = pfts.totalBytes;
+ pfts.workingDir = (char *)di->sPath.c_str();
+ pfts.files = file;
+ pfts.totalProgress = 0;
+ pfts.currentFileProgress = 0;
+ pfts.currentFileTime = (unsigned long)time(0);
+
+ }
+
+
+
+ // create a listening socket for outgoing chat/send requests. The remote computer connects to this computer. Used for both chat and filetransfer.
+ if(di->bSender && !di->bReverse)
+ {
+ NETLIBBIND nb = {0};
+ nb.cbSize = sizeof(NETLIBBIND);
+ nb.pfnNewConnectionV2 = DoIncomingDcc; // this is the (helper) function to be called once an incoming connection is made. The 'real' function that is called is IncomingConnection()
+ nb.pExtra = (void *)this;
+ nb.wPort = 0;
+ hBindPort = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)hNetlibDCC,(LPARAM) &nb);
+
+ if(hBindPort == NULL)
+ {
+ delete this; // dcc objects destroy themselves when the connection has been closed or failed for some reasson.
+ return 0;
+ }
+
+ di->iPort = nb.wPort; // store the port internally so it is possible to search for it (for resuming of filetransfers purposes)
+
+ return nb.wPort; // return the created port so it can be sent to the remote computer in a ctcp/dcc command
+ }
+
+
+ // If a remote computer initiates a chat session this is used to connect to the remote computer (user already accepted at this point).
+ // also used for connecting to a remote computer for remote file transfers
+ if(di->iType == DCC_CHAT && !di->bSender || di->iType == DCC_SEND && di->bSender && di->bReverse)
+ {
+
+ NETLIBOPENCONNECTION ncon;
+ ncon.cbSize = sizeof(ncon);
+ ncon.szHost = ConvertIntegerToIP(di->dwAdr);
+ ncon.wPort = (WORD) di->iPort;
+ con = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) hNetlibDCC, (LPARAM) & ncon);
+ }
+
+
+ // If a remote computer initiates a filetransfer this is used to connect to that computer (the user has chosen to accept but it is possible the file exists/needs to be resumed etc still)
+ if(di->iType == DCC_SEND && !di->bSender)
+ {
+
+ // this following code is for miranda to be able to show the resume/overwrite etc dialog if the file that we are receiving already exists.
+ // It must be done before we create the connection or else the other party will begin sending packets while the user is still deciding if
+ // s/he wants to resume/cancel or whatever. Just the way dcc is...
+
+ // if the file exists (dialog is shown) WaitForSingleObject() till the dialog is closed and PS_FILERESUME has been processed.
+ // dwWhatNeedsDoing will be set using InterlockedExchange() (from other parts of the code depending on action) before SetEvent() is called.
+ // If the user has chosen rename then InterlockedExchange() will be used for setting NewFileName to a string containing the new name.
+ // Furthermore dwResumePos will be set using InterlockedExchange() to indicate what the file position to start from is.
+ if(ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, (void *)di, (long)&pfts))
+ {
+ WaitForSingleObject(hEvent, INFINITE);
+ switch(dwWhatNeedsDoing)
+ {
+ case FILERESUME_RENAME :
+ {
+ // If the user has chosen to rename the file we need to change variables accordingly. NewFileName has been set using
+ // InterlockedExchange()
+ if( NewFileName) // the user has chosen to rename the new incoming file.
+ {
+ di->sFileAndPath = NewFileName;
+
+ int i = di->sFileAndPath.rfind("\\", di->sFileAndPath.length());
+ if (i != string::npos)
+ {
+ di->sPath = di->sFileAndPath.substr(0, i+1);
+ di->sFile = di->sFileAndPath.substr(i+1, di->sFileAndPath.length());
+ }
+
+ pfts.currentFile = (char *)di->sFileAndPath.c_str();
+ pfts.totalBytes = di->dwSize;
+ pfts.currentFileSize = pfts.totalBytes;
+ pfts.workingDir = (char *)di->sPath.c_str();
+ file[0] = (char *)di->sFileAndPath.c_str();
+
+ delete []NewFileName;
+ NewFileName = NULL;
+ }
+ } break;
+
+ case FILERESUME_OVERWRITE:
+ case FILERESUME_RESUME :
+ // no action needed at this point, just break out of the switch statement
+ break;
+
+ case FILERESUME_CANCEL :
+ return FALSE;
+ break;
+
+ case FILERESUME_SKIP :
+ default:
+ delete this; // per usual dcc objects destroy themselves when they fail or when connection is closed
+ return FALSE;
+ break;
+ }
+
+ }
+
+ // hack for passive filetransfers
+ if(di->iType == DCC_SEND && !di->bSender && di->bReverse)
+ {
+ NETLIBBIND nb = {0};
+ nb.cbSize = sizeof(NETLIBBIND);
+ nb.pfnNewConnectionV2 = DoIncomingDcc; // this is the (helper) function to be called once an incoming connection is made. The 'real' function that is called is IncomingConnection()
+ nb.pExtra = (void *)this;
+ nb.wPort = 0;
+ hBindPort = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)hNetlibDCC,(LPARAM) &nb);
+
+ if(hBindPort == NULL)
+ {
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), "DCC ERROR: Unable to bind local port for passive filetransfer", NULL, NULL, NULL, true, false);
+ delete this; // dcc objects destroy themselves when the connection has been closed or failed for some reasson.
+ return 0;
+ }
+
+ di->iPort = nb.wPort; // store the port internally so it is possible to search for it (for resuming of filetransfers purposes)
+
+ String sFileWithQuotes = di->sFile;
+
+ // if spaces in the filename surround with quotes
+ if (sFileWithQuotes.find(' ', 0) != string::npos)
+ {
+ sFileWithQuotes.insert(0, "\"");
+ sFileWithQuotes.insert(sFileWithQuotes.length(), "\"");
+ }
+
+ // send out DCC RECV command for passive filetransfers
+ unsigned long ulAdr = 0;
+ if (prefs->ManualHost)
+ ulAdr = ConvertIPToInteger(prefs->MySpecifiedHostIP);
+ else
+ ulAdr = ConvertIPToInteger(prefs->IPFromServer?prefs->MyHost:prefs->MyLocalHost);
+
+
+ if(di->iPort && ulAdr)
+ PostIrcMessage("/CTCP %s DCC SEND %s %u %u %u %s", di->sContactName.c_str(), sFileWithQuotes.c_str(), ulAdr, di->iPort, di->dwSize, di->sToken.c_str());
+
+ return TRUE;
+ }
+
+
+ // connect to the remote computer from which you are receiving the file (now all actions to take (resume/overwrite etc) have been decided
+ NETLIBOPENCONNECTION ncon;
+ ncon.cbSize = sizeof(ncon);
+ ncon.szHost = ConvertIntegerToIP(di->dwAdr);
+ ncon.wPort = (WORD) di->iPort;
+
+ con = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) hNetlibDCC, (LPARAM) & ncon);
+ }
+
+ // if for some reason the plugin has failed to connect to the remote computer the object is destroyed.
+ if (con == NULL)
+ {
+ delete this;
+ return FALSE; // failed to connect
+ }
+
+ // if it is a chat connection set the user to online now since we now know there is a connection
+ if(di->iType == DCC_CHAT)
+ DBWriteContactSettingWord(di->hContact, IRCPROTONAME, "Status", ID_STATUS_ONLINE);
+
+ // spawn a new thread to handle receiving/sending of data for the new chat/filetransfer connection to the remote computer
+ forkthread(ThreadProc, 0, this );
+
+ } catch( const char* ){
+ Disconnect();
+ } catch( ... ) {
+ Disconnect();
+ }
+
+ return (int)con;
+}
+
+// called by netlib for incoming connections on a listening socket (chat/filetransfer)
+int CDccSession::IncomingConnection(HANDLE hConnection, DWORD dwIP)
+{
+ con = hConnection;
+
+ if (con == NULL)
+ {
+ delete this;
+ return false; // failed to connect
+ }
+
+ DBWriteContactSettingDword(di->hContact, IRCPROTONAME, "IP", dwIP); // mToolTip stuff
+
+ if(di->iType == DCC_CHAT)
+ DBWriteContactSettingWord(di->hContact, IRCPROTONAME, "Status", ID_STATUS_ONLINE); // set chat to online
+
+ // same as above, spawn a new thread to handle receiving/sending of data for the new incoming chat/filetransfer connection
+ forkthread(ThreadProc, 0, this );
+ return true;
+
+
+}
+// here we decide which function to use for communicating with the remote computer, depending on connection type
+void __cdecl CDccSession::ThreadProc(void *pparam)
+{
+
+ CDccSession* pThis = (CDccSession*)pparam;
+
+ // if it is an incoming connection on a listening port, then we should close the listenting port so only one can connect (the one you offered
+ // the connection to) can connect and not evil IRCopers with haxxored IRCDs
+ if(pThis->hBindPort)
+ {
+ Netlib_CloseHandle(pThis->hBindPort);
+ pThis->hBindPort = NULL;
+ }
+
+ try
+ {
+
+ if(pThis->di->iType == DCC_CHAT)
+ pThis->DoChatReceive(); // dcc chat
+
+ else if(!pThis->di->bSender)
+ pThis->DoReceiveFile(); // receive a file
+
+ else if(pThis->di->bSender)
+ pThis->DoSendFile(); // send a file
+
+ } catch( ... ) {}
+
+ return;
+}
+
+// this is done when the user is initiating a filetransfer to a remote computer
+void CDccSession::DoSendFile()
+{
+ // initialize the filetransfer dialog
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, (void *)di, 0);
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, (void *)di, 0);
+
+ BYTE DCCMode = DBGetContactSettingByte(NULL, IRCPROTONAME, "DCCMode", 0);
+ WORD wPacketSize = DBGetContactSettingWord(NULL, IRCPROTONAME, "DCCPacketSize", 1024*4);
+
+ if(wPacketSize <256)
+ wPacketSize = 256;
+
+ if(wPacketSize > 32 * 1024)
+ wPacketSize = 32 * 1024;
+
+ BYTE * chBuf = new BYTE[wPacketSize+1];
+
+ // is there a connection?
+ if(con)
+ {
+
+ // open the file for reading
+ FILE * hFile = fopen(di->sFileAndPath.c_str(),"rb");
+ if(hFile)
+ {
+ DWORD iLastAck = 0;
+
+ // if the user has chosen to resume a file, dwResumePos will contain a value (set using InterlockedExchange())
+ // and then the variables and the file pointer are changed accordingly.
+ if(dwResumePos && dwWhatNeedsDoing == FILERESUME_RESUME)
+ {
+ fseek (hFile,dwResumePos,SEEK_SET);
+ iTotal = dwResumePos;
+ iLastAck = dwResumePos;
+ pfts.totalProgress = dwResumePos;
+ pfts.currentFileProgress = dwResumePos;
+ }
+
+ // initial ack to set the 'percentage-ready meter' to the correct value
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_DATA, (void *)di, (LPARAM) &pfts);
+
+ tLastActivity = time(0);
+
+ // create a packet receiver to handle receiving ack's from the remote computer.
+ HANDLE hPackrcver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)con, (LPARAM)sizeof(DWORD));
+ NETLIBPACKETRECVER npr;
+ npr.cbSize = sizeof(NETLIBPACKETRECVER);
+ npr.dwTimeout = 60*1000;
+ npr.bufferSize = sizeof(DWORD);
+ npr.bytesUsed = 0;
+
+ // until the connection is dropped it will spin around in this while() loop
+ while( con )
+ {
+
+ // read a packet
+ DWORD iRead = fread(chBuf, 1, wPacketSize, hFile);
+ if( iRead <= 0 )
+ break; // break out if everything has already been read
+
+ // send the package
+ DWORD cbSent = NLSend((unsigned char*)chBuf, iRead);
+ if (cbSent <= 0)
+ break; // break out if connection is lost or a transmission error has occured
+
+ if(!con)
+ break;
+
+ iTotal += cbSent;
+
+ // block connection and receive ack's from remote computer (if applicable)
+ if(DCCMode == 0 )
+ {
+ DWORD dwRead = 0;
+ DWORD dwPacket = NULL;
+
+ do
+ {
+
+ dwRead = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPackrcver, (LPARAM)&npr);
+ npr.bytesUsed = sizeof(DWORD);
+
+ if( dwRead <= 0)
+ break; // connection closed, or a timeout occurred.
+
+ memcpy(&dwPacket, npr.buffer, 4);
+ iLastAck = ntohl((u_long)dwPacket);
+
+ } while(con && iTotal != iLastAck);
+
+ if(!con || dwRead <= 0)
+ goto DCC_STOP;
+
+
+ }
+ if(DCCMode == 1)
+ {
+ DWORD dwRead = 0;
+ DWORD dwPacket = NULL;
+
+ do
+ {
+ dwRead = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPackrcver, (LPARAM)&npr);
+ npr.bytesUsed = sizeof(DWORD);
+ if( dwRead <= 0)
+ break; // connection closed, or a timeout occurred.
+
+ memcpy(&dwPacket, npr.buffer, 4);
+ iLastAck = ntohl((u_long)dwPacket);
+
+ } while(con && (di->dwSize != iTotal
+ && iTotal - iLastAck >= 100*1024
+ || di->dwSize == iTotal // get the last packets when the whole file has been sent
+ && iTotal != iLastAck));
+
+ if(!con || dwRead <= 0)
+ goto DCC_STOP;
+ }
+
+ // update the filetransfer dialog's 'percentage-ready meter' once per second only to save cpu
+ if(tLastPercentageUpdate < time(0))
+ {
+ tLastPercentageUpdate = time(0);
+ pfts.totalProgress = iTotal;
+ pfts.currentFileProgress = iTotal;
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_DATA, (void *)di, (LPARAM) &pfts);
+ }
+
+ // close the connection once the whole file has been sent an completely ack'ed
+ if(iLastAck >= di->dwSize)
+ {
+ Netlib_CloseHandle(con);
+ con = NULL;
+ }
+
+
+ }
+
+DCC_STOP:
+ // need to close the connection if it isn't allready
+ if(con)
+ {
+ Netlib_CloseHandle(con);
+ con = NULL;
+ }
+
+ // ack the progress one final time
+ tLastActivity = time(0);
+ pfts.totalProgress = iTotal;
+ pfts.currentFileProgress = iTotal;
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_DATA, (void *)di, (LPARAM) &pfts);
+
+ fclose(hFile);
+ }
+ else // file was not possible to open for reading
+ {
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (void *)di, 0);
+ if( con )
+ {
+ Netlib_CloseHandle(con);
+ con = NULL;
+ }
+ }
+ }
+
+ delete []chBuf;
+ delete this; // ... and hopefully all went right, cuz here the object is deleted in any case
+
+
+}
+
+
+// This is called when receiving a file from a remote computer.
+void CDccSession::DoReceiveFile()
+{
+ // initialize the filetransfer dialog
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, (void *)di, 0);
+
+ BYTE chBuf[1024*32+1];
+ BYTE DCCMode = DBGetContactSettingByte(NULL, IRCPROTONAME, "DCCMode", 0); // type of dcc: normal, send-ahead
+ WORD wAckRate = DBGetContactSettingWord(NULL, IRCPROTONAME, "DCCAckRate", 1024*4);
+
+ // do some stupid thing so the filetransfer dialog shows the right thing
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, (void *)di, 0);
+
+ // open the file for writing (and reading in case it is a resume)
+ FILE * hFile = fopen(di->sFileAndPath.c_str(),dwWhatNeedsDoing == FILERESUME_RESUME?"rb+":"wb");
+
+ if(hFile)
+ {
+ DWORD iLastAck = 0;
+
+ // dwResumePos and dwWhatNeedsDoing has possibly been set using InterlockedExchange()
+ // if set it is a resume and we adjust variables and the file pointer accordingly.
+ if(dwResumePos && dwWhatNeedsDoing == FILERESUME_RESUME)
+ {
+ fseek (hFile,dwResumePos,SEEK_SET);
+ iTotal = dwResumePos;
+ iLastAck = dwResumePos;
+ pfts.totalProgress = dwResumePos;
+ pfts.currentFileProgress = dwResumePos;
+ }
+
+ // send an initial ack for the percentage-ready meter
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_DATA, (void *)di, (LPARAM) &pfts);
+
+ // the while loop will spin around till the connection is dropped, locally or by the remote computer.
+ while( con )
+ {
+ // read
+ DWORD cbRead = NLReceive((unsigned char*)chBuf, sizeof(chBuf));
+ if( cbRead <= 0 )
+ break;
+
+ // write it to the file
+ fwrite(chBuf, 1, cbRead, hFile);
+
+ iTotal += cbRead;
+
+ // this snippet sends out an ack for every 4 kb received in send ahead
+ // or every packet for normal mode
+ if(!di->bTurbo)
+ {
+ DWORD no = htonl(iTotal);
+ NLSend((const unsigned char *)&no, sizeof(DWORD));
+ iLastAck = iTotal;
+ }
+ else
+ iLastAck = iTotal;
+
+ // sets the 'last update time' to check for timed out connections, and also make sure we only
+ // ack the 'percentage-ready meter' only once a second to save CPU.
+ if(tLastPercentageUpdate < time(0))
+ {
+ tLastPercentageUpdate = time (0);
+ pfts.totalProgress = iTotal;
+ pfts.currentFileProgress = iTotal;
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_DATA, (void *)di, (LPARAM) &pfts);
+ }
+
+ // if file size is known and everything is received then disconnect
+ if(di->dwSize && di->dwSize == iTotal)
+ {
+ Netlib_CloseHandle(con);
+ con = NULL;
+ }
+ } // receiving loop broken locally or by remote computer, just some cleaning up left....
+
+
+ pfts.totalProgress = iTotal;
+ pfts.currentFileProgress = iTotal;
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_DATA, (void *)di, (LPARAM) &pfts);
+
+
+ fclose(hFile);
+ }
+ else
+ {
+ ProtoBroadcastAck(IRCPROTONAME, di->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (void *)di, 0);
+ if( con ) // file not possible to open for writing so we ack FAILURE and close the handle
+ {
+ Netlib_CloseHandle(con);
+ con = NULL;
+ }
+ }
+
+
+ delete this; // and finally the object is deleted
+
+}
+
+// this function handles receiving text in dcc chats and then send it in the protochain. very uncomplicated...
+// For sending text the SendStuff() function is called (with the help of some function in CIrcSession to find the right
+// Dcc object). See CIrcSession for info on how the dcc objects are stored, retreived and deleted.
+void CDccSession::DoChatReceive() {
+
+ char chBuf[1024*4+1];
+ int cbInBuf = 0;
+
+ // loop to spin around while there is a connection
+ while( con )
+ {
+ int cbRead;
+ int nLinesProcessed = 0;
+
+ cbRead = NLReceive((unsigned char*)chBuf+cbInBuf, sizeof(chBuf)-cbInBuf-1);
+ if( cbRead <= 0 )
+ break;
+ cbInBuf += cbRead;
+ chBuf[cbInBuf] = '\0';
+
+ char* pStart = chBuf;
+ while( *pStart )
+ {
+ char* pEnd;
+
+ // seek end-of-line
+ for(pEnd=pStart; *pEnd && *pEnd != '\r' && *pEnd != '\n'; ++pEnd)
+ ;
+ if( *pEnd == '\0' )
+ break; // uncomplete message. stop parsing.
+
+ ++nLinesProcessed;
+
+ // replace end-of-line with NULLs and skip
+ while( *pEnd == '\r' || *pEnd == '\n' )
+ *pEnd++ = '\0';
+
+ if( *pStart ) {
+ // send it off to some messaging module
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ ccs.szProtoService = PSR_MESSAGE;
+
+ ccs.hContact = di->hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM) &pre;
+ pre.flags = 0;
+ pre.timestamp = (DWORD)time(NULL);
+ pre.szMessage = DoColorCodes(pStart, true, false); // remove color codes
+ pre.lParam = 0;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) & ccs);
+
+ }
+
+ cbInBuf -= pEnd - pStart;
+ pStart = pEnd;
+ }
+
+ // discard processed messages
+ if( nLinesProcessed != 0 )
+ memmove(chBuf, pStart, cbInBuf+1);
+ }
+
+ delete this; // delete the object when the connection is dropped
+}
+
+// disconnect the stuff
+int CDccSession::Disconnect()
+{
+ if(hBindPort)
+ {
+ Netlib_CloseHandle(hBindPort);
+ hBindPort = NULL;
+ }
+
+ // if 'con' exists it is cuz a connection exists.
+ // Terminating 'con' will cause any spawned threads to die and then the object will destroy itself.
+ if(con)
+ {
+ Netlib_CloseHandle(con);
+ con = NULL;
+ }
+ else
+ delete this; // if 'con' do not exist (no connection made so far from the object) the object is destroyed
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////
+
+// check if the dcc chats should disconnect ( default 5 minute timeout )
+VOID CALLBACK DCCTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
+{
+ g_ircSession.CheckDCCTimeout();
+}
+
+// helper function for incoming dcc connections.
+void DoIncomingDcc(HANDLE hConnection, DWORD dwRemoteIP, void * p1)
+{
+
+ CDccSession * dcc = (CDccSession *)p1;
+ dcc->IncomingConnection(hConnection, dwRemoteIP);
+ return ;
+}
+
+// ident server
+void DoIdent(HANDLE hConnection, DWORD dwRemoteIP, void* extra)
+{
+ char szBuf[1024];
+ char* p;
+ int cbRead = Netlib_Recv(hConnection, szBuf, sizeof(szBuf)-1, 0);
+ if( cbRead == SOCKET_ERROR || cbRead == 0)
+ return ;
+ szBuf[cbRead] = '\0';
+
+ // strip CRLF from query
+ for(p = szBuf; *p && *p != '\r' && *p != '\n'; ++p)
+ ;
+ *p = '\0';
+
+ char buf[1024*4];
+ wsprintf(buf,"%s : USERID : %s : %s\r\n", szBuf, g_ircSession.GetInfo().sIdentServerType.c_str() , g_ircSession.GetInfo().sUserID.c_str());
+ Netlib_Send(hConnection, (const char*)buf, strlen(buf), 0);
+ Netlib_CloseHandle(hConnection);
+
+ return ;
+}
+
diff --git a/irc_mod/irclib.h b/irc_mod/irclib.h
new file mode 100644
index 0000000..376bf5c
--- /dev/null
+++ b/irc_mod/irclib.h
@@ -0,0 +1,426 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public 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 _IRC_H_
+#define _IRC_H_
+
+#pragma warning (disable: 4786)
+
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+
+//#ifdef IRC_SSL
+#include <openssl/ssl.h>
+//#include "../../openssl-0.9.7d/include/openssl/err.h"
+//#endif
+
+void DoIdent(HANDLE hConnection, DWORD dwRemoteIP, void* extra);
+void DoIncomingDcc(HANDLE hConnection, DWORD dwRemoteIP, void* extra);
+VOID CALLBACK DCCTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);
+unsigned long ConvertIPToInteger(char * IP);
+char* ConvertIntegerToIP(unsigned long int_ip_addr);
+
+////////////////////////////////////////////////////////////////////
+namespace irc {
+////////////////////////////////////////////////////////////////////
+
+typedef std::string String;
+
+
+typedef struct {
+ DWORD dwAdr;
+ DWORD dwSize;
+ DWORD iType;
+ String sToken;
+ int iPort;
+ BOOL bTurbo;
+ BOOL bSSL;
+ BOOL bSender;
+ BOOL bReverse;
+ String sPath;
+ String sFile;
+ String sFileAndPath;
+ String sContactName;
+ String sHostmask;
+ HANDLE hContact;
+} DCCINFO;
+
+//#ifdef IRC_SSL
+// OpenSSL stuff
+typedef int (*tSSL_library_init) (void);
+typedef SSL_CTX* (*tSSL_CTX_new) (SSL_METHOD *meth);
+typedef SSL* (*tSSL_new) (SSL_CTX *ctx);
+typedef int (*tSSL_set_fd) (SSL *ssl, int fd);
+typedef int (*tSSL_connect) (SSL *ssl);
+typedef int (*tSSL_read) (SSL *ssl, void *buf, int num);
+typedef int (*tSSL_write) (SSL *ssl, const void *buf, int num);
+typedef SSL_METHOD* (*tSSLv23_method) (void);
+typedef int (*tSSL_get_error) (SSL *s, int retcode);
+typedef void (*tSSL_load_error_strings) (void);
+typedef int (*tSSL_shutdown) (SSL *ssl);
+typedef void (*tSSL_CTX_free) (SSL_CTX *ctx);
+typedef void (*tSSL_free) (SSL *ssl);
+
+//typedef char (*tERR_error_string) (unsigned long e, char *buf);
+//typedef const char* (*tERR_lib_error_string) (unsigned long e);
+//typedef const char* (*tERR_func_error_string) (unsigned long e);
+//typedef const char* (*tERR_reason_error_string) (unsigned long e);
+
+static tSSL_library_init pSSL_library_init;
+static tSSL_CTX_new pSSL_CTX_new;
+static tSSL_new pSSL_new;
+static tSSL_set_fd pSSL_set_fd;
+static tSSL_connect pSSL_connect;
+static tSSL_read pSSL_read;
+static tSSL_write pSSL_write;
+static tSSLv23_method pSSLv23_method;
+static tSSL_get_error pSSL_get_error;
+static tSSL_load_error_strings pSSL_load_error_strings;
+static tSSL_shutdown pSSL_shutdown;
+static tSSL_CTX_free pSSL_CTX_free;
+static tSSL_free pSSL_free;
+
+//static tERR_error_string pERR_error_string;
+//static tERR_lib_error_string pERR_lib_error_string;
+//static tERR_func_error_string pERR_func_error_string;
+//static tERR_reason_error_string pERR_reason_error_string;
+//#endif
+
+static const char* endl = "\r\n";
+
+class CIrcMessage
+{
+public :
+ struct Prefix
+ {
+ String sNick, sUser, sHost;
+ } prefix;
+ String sCommand;
+ std::vector<String> parameters;
+ bool m_bIncoming;
+ bool m_bNotify;
+ CIrcMessage() : m_bIncoming(false), m_bNotify(true) {} // default constructor
+ CIrcMessage(const char* lpszCmdLine, bool bIncoming=false, bool bNotify = true); // parser constructor
+ CIrcMessage(const CIrcMessage& m); // copy constructor
+
+ void Reset();
+
+ CIrcMessage& operator = (const CIrcMessage& m);
+ CIrcMessage& operator = (const char* lpszCmdLine);
+
+ String AsString() const;
+
+private :
+ void ParseIrcCommand(const char* lpszCmdLine);
+};
+
+////////////////////////////////////////////////////////////////////
+
+struct IIrcSessionMonitor
+{
+ virtual void OnIrcMessage(const CIrcMessage* pmsg) = 0;
+};
+
+////////////////////////////////////////////////////////////////////
+
+struct CIrcSessionInfo
+{
+ String sServer;
+ String sServerName;
+ String sNick;
+ String sUserID;
+ String sFullName;
+ String sPassword;
+ String sIdentServerType;
+ String sNetwork;
+ bool bIdentServer;
+ bool bNickFlag;
+ int iSSL;
+ unsigned int iIdentServerPort;
+ unsigned int iPort;
+
+ CIrcSessionInfo();
+ CIrcSessionInfo(const CIrcSessionInfo& si);
+
+ void Reset();
+};
+
+////////////////////////////////////////////////////////////////////
+
+//#ifdef IRC_SSL
+// Handles to the SSL libraries
+static SSL_CTX* m_ssl_ctx; // SSL context, valid for all threads
+
+class CSSLSession { // OpenSSL
+
+public:
+ SSL* m_ssl;
+ int nSSLConnected;
+ CSSLSession(void) : nSSLConnected(0) {
+ m_ssl_ctx = 0;
+ }
+ ~CSSLSession();
+ int SSLInit();
+ int SSLConnect(HANDLE con);
+ int SSLDisconnect(void);
+
+};
+
+//#endif
+////////////////////////////////////////////////////////////////////
+
+class CIrcDefaultMonitor; // foreward
+class CDccSession; // forward
+
+//#include <string.h>
+
+typedef std::map<HANDLE, CDccSession*> DccSessionMap;
+typedef std::pair<HANDLE, CDccSession*> DccSessionPair;
+
+class CIrcSession
+{
+public :
+ friend class CIrcDefaultMonitor;
+
+ CIrcSession(IIrcSessionMonitor* pMonitor = NULL);
+ virtual ~CIrcSession();
+
+ void AddIrcMonitor(IIrcSessionMonitor* pMonitor);
+ void RemoveMonitor(IIrcSessionMonitor* pMonitor);
+
+ void AddDCCSession(HANDLE hContact, CDccSession * dcc);
+ void AddDCCSession(DCCINFO* pdci, CDccSession * dcc);
+ void RemoveDCCSession(HANDLE hContact);
+ void RemoveDCCSession(DCCINFO* pdci);
+ CDccSession * FindDCCSession(HANDLE hContact);
+ CDccSession * FindDCCSession(DCCINFO * pdci);
+ CDccSession * FindDCCSendByPort(int iPort);
+ CDccSession * FindDCCRecvByPortAndName(int iPort, char * szName);
+ CDccSession * FindPassiveDCCSend(int iToken);
+ CDccSession * FindPassiveDCCRecv(String sName, String sToken);
+ void DisconnectAllDCCSessions(bool Shutdown);
+ void CheckDCCTimeout(void);
+
+ bool Connect(const CIrcSessionInfo& info);
+ void Disconnect(void);
+ void KillIdent(void);
+
+ CIrcSessionInfo& GetInfo() const
+ { return (CIrcSessionInfo&)m_info; }
+
+ int NLSend(const unsigned char* buf, int cbBuf);
+ int NLSend(const char* fmt, ...);
+ int NLSendNoScript( const unsigned char* buf, int cbBuf);
+ int NLReceive(unsigned char* buf, int cbBuf);
+ void InsertIncomingEvent(char * pszRaw);
+
+ operator bool() const { return con!= NULL; }
+
+ // send-to-stream operators
+ friend CIrcSession& operator << (CIrcSession& os, const CIrcMessage& m);
+
+
+protected :
+// Socket m_socket;
+ CIrcSessionInfo m_info;
+//#ifdef IRC_SSL
+ CSSLSession sslSession;
+//#endif
+ HANDLE con;
+ HANDLE hBindPort;
+ void DoReceive();
+ DccSessionMap m_dcc_chats;
+ DccSessionMap m_dcc_xfers;
+
+
+private :
+ std::set<IIrcSessionMonitor*> m_monitors;
+// HANDLE m_hThread;
+ CRITICAL_SECTION m_cs; // protect m_monitors
+ CRITICAL_SECTION m_dcc; // protect the dcc objects
+
+ void Notify(const CIrcMessage* pmsg);
+ static void __cdecl ThreadProc(void *pparam);
+};
+
+
+__inline CIrcSession& operator << (CIrcSession& os, const CIrcMessage& m)
+{
+ if( os )
+ {
+ os.NLSend(m.AsString().c_str());
+ if (!m.sCommand.empty() && m.sCommand != "QUIT" && m.m_bNotify)
+ os.Notify(&m);
+ }
+ return os;
+}
+
+////////////////////////////////////////////////////////////////////
+typedef struct
+{
+ void * pthis;
+ CIrcMessage * pmsg;
+} XTHREADS;
+
+class CIrcMonitor :
+ public IIrcSessionMonitor
+{
+public :
+ typedef bool (CIrcMonitor::*PfnIrcMessageHandler)(const CIrcMessage* pmsg);
+ struct LessString
+ {
+ bool operator()(const char* s1, const char* s2) const
+ { return stricmp(s1, s2) < 0; }
+ };
+ typedef std::map<const char*, PfnIrcMessageHandler, LessString> HandlersMap;
+ struct IrcCommandsMapsListEntry
+ {
+ HandlersMap* pHandlersMap;
+ IrcCommandsMapsListEntry* pBaseHandlersMap;
+ };
+
+ CIrcMonitor(CIrcSession& session);
+ virtual ~CIrcMonitor();
+ static IrcCommandsMapsListEntry m_handlersMapsListEntry;
+ static HandlersMap m_handlers;
+
+ PfnIrcMessageHandler FindMethod(const char* lpszName);
+ PfnIrcMessageHandler FindMethod(IrcCommandsMapsListEntry* pMapsList, const char* lpszName);
+
+ static void __stdcall OnCrossThreadsMessage(void * p);
+ virtual void OnIrcMessage(const CIrcMessage* pmsg);
+ CIrcSession& m_session;
+
+ virtual IrcCommandsMapsListEntry* GetIrcCommandsMap()
+ { return &m_handlersMapsListEntry; }
+
+ virtual void OnIrcAll(const CIrcMessage* pmsg) {}
+ virtual void OnIrcDefault(const CIrcMessage* pmsg) {}
+ virtual void OnIrcDisconnected() {}
+protected :
+
+
+private :
+
+};
+
+// define an IRC command-to-member map.
+// put that macro inside the class definition (.H file)
+#define DEFINE_IRC_MAP() \
+protected : \
+ virtual IrcCommandsMapsListEntry* GetIrcCommandsMap() \
+ { return &m_handlersMapsListEntry; } \
+ static CIrcMonitor::IrcCommandsMapsListEntry m_handlersMapsListEntry; \
+ static CIrcMonitor::HandlersMap m_handlers; \
+private : \
+protected :
+
+// IRC command-to-member map's declaration.
+// add this macro to the class's .CPP file
+#define DECLARE_IRC_MAP(this_class, base_class) \
+ CIrcMonitor::HandlersMap this_class##::m_handlers; \
+ CIrcMonitor::IrcCommandsMapsListEntry this_class##::m_handlersMapsListEntry \
+ = { &this_class##::m_handlers, &base_class##::m_handlersMapsListEntry };
+
+// map actual member functions to their associated IRC command.
+// put any number of this macro in the class's constructor.
+#define IRC_MAP_ENTRY(class_name, name, member) \
+ m_handlers[(name)] = (PfnIrcMessageHandler)&class_name##::member;
+
+////////////////////////////////////////////////////////////////////
+
+class CIrcDefaultMonitor : public CIrcMonitor
+{
+public :
+ CIrcDefaultMonitor(CIrcSession& session);
+
+ DEFINE_IRC_MAP()
+
+protected :
+ bool OnIrc_NICK(const CIrcMessage* pmsg);
+ bool OnIrc_PING(const CIrcMessage* pmsg);
+ bool OnIrc_YOURHOST(const CIrcMessage* pmsg);
+ bool OnIrc_WELCOME(const CIrcMessage* pmsg);
+};
+
+////////////////////////////////////////////////////////////////////
+
+
+class CDccSession{
+protected:
+ HANDLE con; // connection handle
+ HANDLE hBindPort; // handle for listening port
+
+
+ static int nDcc; // number of dcc objects
+ DWORD iTotal; // total bytes sent/received
+
+ int iPacketSize; // size of outgoing packets
+ int iGlobalToken;
+
+ PROTOFILETRANSFERSTATUS pfts; // structure used to setup and update the filetransfer dialogs of miranda
+ char * file[2]; // used with the PROTOFILETRANSFER struct
+
+ int SetupConnection();
+ void DoSendFile();
+ void DoReceiveFile();
+ void DoChatReceive();
+ int NLSend( const unsigned char* buf, int cbBuf);
+ int NLReceive(const unsigned char* buf, int cbBuf);
+ static void __cdecl ThreadProc(void *pparam);
+ static void __cdecl ConnectProc(void *pparam);
+
+public:
+
+ CDccSession(DCCINFO * pdci); // constructor
+ ~CDccSession(); // destructor
+
+ time_t tLastPercentageUpdate; // time of last update of the filetransfer dialog
+ time_t tLastActivity; // time of last in/out activity of the object
+ time_t tLastAck; // last acked filesize
+
+ HANDLE hEvent; // Manual object
+ volatile long dwWhatNeedsDoing; // Set to indicate what FILERESUME_ action is chosen by the user
+ char * NewFileName; // contains new file name if FILERESUME_RENAME chosen
+ volatile long dwResumePos; // position to resume from if FILERESUME_RESUME
+
+ int iToken; // used to identify (find) objects in reverse dcc filetransfers
+
+ DCCINFO * di; // details regarding the filetrasnfer
+
+ int Connect();
+ void SetupPassive(DWORD adr, DWORD port);
+ int SendStuff(const char* fmt);
+ int IncomingConnection(HANDLE hConnection, DWORD dwIP);
+ int Disconnect();
+
+
+};
+////////////////////////////////////////////////////////////////////
+}; // end of namespace irc
+////////////////////////////////////////////////////////////////////
+
+
+
+#endif // _IRC_H_
+
+
diff --git a/irc_mod/m_cluiframes.h b/irc_mod/m_cluiframes.h
new file mode 100644
index 0000000..ebb89ef
--- /dev/null
+++ b/irc_mod/m_cluiframes.h
@@ -0,0 +1,255 @@
+/*
+Miranda ICQ: the free icq client for MS Windows
+Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//#pragma hdrstop
+
+////////////////////////////////////
+//Extra Image Column Support +0.5.0.0
+
+//Extra columns type.
+//column arranged in this way
+//
+// [statusicon] ContactName [ADV1][ADV2][SMS][EMAIL][PROTO]
+//
+#define EXTRA_ICON_EMAIL 1
+#define EXTRA_ICON_PROTO 2
+#define EXTRA_ICON_SMS 3
+#define EXTRA_ICON_ADV1 4
+#define EXTRA_ICON_ADV2 5
+
+typedef struct
+{
+int cbSize; //must be sizeof(IconExtraColumn)
+int ColumnType;
+HANDLE hImage; //return value from MS_CLIST_EXTRA_ADD_ICON
+}IconExtraColumn,*pIconExtraColumn;
+
+
+//Set icon for contact at needed column
+//wparam=hContact
+//lparam=pIconExtraColumn
+//return 0 on success,-1 on failure
+//
+//See above for supported columns
+#define MS_CLIST_EXTRA_SET_ICON "CListFrames/SetIconForExraColumn"
+
+//Adding icon to extra image list.
+//Call this in ME_CLIST_EXTRA_LIST_REBUILD event
+//
+//wparam=hIcon
+//lparam=0
+//return hImage on success,-1 on failure
+#define MS_CLIST_EXTRA_ADD_ICON "CListFrames/AddIconToExtraImageList"
+
+
+
+#define ME_CLIST_EXTRA_LIST_REBUILD "CListFrames/OnExtraListRebuild"
+
+//called with wparam=hContact
+#define ME_CLIST_EXTRA_IMAGE_APPLY "CListFrames/OnExtraImageApply"
+
+
+///////////////////////////////////
+
+
+
+
+//
+//want show tooltip for statusbar
+//wparam=(char *)protocolname
+//lparam=0
+#define ME_CLIST_FRAMES_SB_SHOW_TOOLTIP "CListFrames/StatusBarShowToolTip"
+
+
+//want hide tooltip for statusbar
+//wparam=lparam=0
+
+#define ME_CLIST_FRAMES_SB_HIDE_TOOLTIP "CListFrames/StatusBarHideToolTip"
+
+//
+
+
+
+//adds a frame window
+//wParam=(CLISTFrame*)
+//lParam=0
+//returns an integer, the frame id.
+typedef struct tagCLISTFrame {
+ DWORD cbSize;
+ HWND hWnd ;
+ HICON hIcon;
+ int align; //al flags below
+ int height;
+ int Flags; //F_flags below
+ char *name; //frame window name,will be shown in menu
+ char *TBname; //titlebar caption
+ //COLORREF TBBackColour; //titlebar background colour
+} CLISTFrame;
+#define F_VISIBLE 1 //Frame visible
+#define F_SHOWTB 2 //Show TitleBar
+#define F_UNCOLLAPSED 4 //UnCollapse frame
+#define F_LOCKED 8 //Lock Frame
+#define F_NOBORDER 16 //Dont apply WS_BORDER style for window
+#define F_SHOWTBTIP 32 //Show titlebar tooltip
+
+
+// frame alignment
+#define alTop 0x00000001
+#define alBottom 0x00000002
+#define alClient 0x00000004 //only one alClient frame
+#define MS_CLIST_FRAMES_ADDFRAME "CListFrames/AddFrame"
+
+#define MS_CLIST_FRAMES_REMOVEFRAME "CListFrames/RemoveFrame"
+
+//shows all frames
+//wParam=lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHOWALLFRAMES "CListFrames/ShowALLFrames"
+
+//shows the titlebars of all frames
+//wParam=lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHOWALLFRAMESTB "CListFrames/ShowALLFramesTB"
+
+//hides the titlebars of all frames
+//wParam=lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_HIDEALLFRAMESTB "CListFrames/HideALLFramesTB"
+
+//shows the frame if it is hidden,
+//hides the frame if it is shown
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHFRAME "CListFrames/SHFrame"
+
+//shows the frame titlebar if it is hidden,
+//hides the frame titlebar if it is shown
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHFRAMETITLEBAR "CListFrame/SHFrameTitleBar"
+
+//locks the frame if it is unlocked,
+//unlock the frame if it is locked
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_ULFRAME "CListFrame/ULFrame"
+
+//collapses the frame if it is uncollapsed,
+//uncollapses the frame if it is collapsed
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_UCOLLFRAME "CListFrame/UCOLLFrame"
+
+//trigger border flags
+//wparam=frameid
+//lparam=0
+#define MS_CLIST_FRAMES_SETUNBORDER "CListFrame/SetUnBorder"
+
+//redraws the frame
+//wParam=FrameId, -1 for all frames
+//lparam=FU_flags
+//returns a pointer to option, -1 on failure
+#define FU_TBREDRAW 1 //redraw titlebar
+#define FU_FMREDRAW 2 //redraw Frame
+#define FU_FMPOS 4 //update Frame position
+#define MS_CLIST_FRAMES_UPDATEFRAME "CListFrame/UpdateFrame"
+
+//gets the frame options
+//(HIWORD)wParam=FrameId
+//(LOWORD)wParam=FO_flag
+//lParam=0
+//returns a pointer to option, -1 on failure
+#define FO_FLAGS 0x0001 //return set of F_VISIBLE,F_SHOWTB,F_UNCOLLAPSED,F_LOCKED,F_NOBORDER,F_SHOWTBTIP
+#define FO_NAME 0x0002 //Change name
+#define FO_TBNAME 0x0003 //Change TB caption
+#define FO_TBSTYLE 0x0004 //Change TB style
+#define FO_TBEXSTYLE 0x0005 //Change TB exstyle
+#define FO_ICON 0x0006 //Change icon
+#define FO_HEIGHT 0x0007 //Change height
+#define FO_ALIGN 0x0008 //Change align
+#define FO_TBTIPNAME 0x0009 //Change TB tooltip
+#define FO_FLOATING 0x000a //Change floating mode
+
+#define MS_CLIST_FRAMES_GETFRAMEOPTIONS "CListFrame/GetFrameOptions"
+
+//sets the frame options
+//(HIWORLD)wParam=FrameId
+//(LOWORD)wParam=FO_flag
+//lParam=value
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SETFRAMEOPTIONS "CListFrame/SetFrameOptions"
+
+
+//menu stuff
+
+//add a new item to the context frame menu
+//wParam=0
+//lParam=(LPARAM)(CLISTMENUITEM*)&mi
+//returns a handle to the new item
+//popupposition=frameid
+//contactowner=advanced parameter
+#define MS_CLIST_ADDCONTEXTFRAMEMENUITEM "CList/AddContextFrameMenuItem"
+
+//remove a item from context frame menu
+//wParam=hMenuItem returned by MS_CLIST_ADDCONTACTMENUITEM
+//lParam=0
+//returns 0 on success, nonzero on failure
+#define MS_CLIST_REMOVECONTEXTFRAMEMENUITEM "CList/RemoveContextFrameMenuItem"
+
+//builds the context menu for a frame
+//wparam=frameid
+//lParam=0
+//returns a HMENU on success, or NULL on failure
+#define MS_CLIST_MENUBUILDFRAMECONTEXT "CList/BuildContextFrameMenu"
+
+/*
+//the frame menu is about to be built
+wparam=frameid
+lparam=
+-1 for build from titlebar,
+ use
+ MS_CLIST_ADDCONTEXTFRAMEMENUITEM
+ MS_CLIST_REMOVECONTEXTFRAMEMENUITEM
+
+>0 for build in main menu,
+must be popupname=lparam to place your items in right popup of main menu.
+ use
+ MS_CLIST_ADDMAINMENUITEM
+ MS_CLIST_REMOVEMAINMENUITEM
+
+*/
+#define ME_CLIST_PREBUILDFRAMEMENU "CList/PreBuildFrameMenu"
+
+//needed by cluiframes module to add frames menu to main menu.
+//it just calls NotifyEventHooks(hPreBuildFrameMenuEvent,wParam,lParam);
+#define MS_CLIST_FRAMEMENUNOTIFY "CList/ContextFrameMenuNotify"
+
+
+//#define FONTID_STATUS 8
+//#define FONTID_FRAMETITLE 9
+
+//#undef FONTID_MAX
+//#define FONTID_MAX 9
+
+#define ME_CLIST_PREBUILDSTATUSMENU "CList/PreBuildStatusMenu"
+#define MS_CLIST_ADDSTATUSMENUITEM "CList/AddStatusMenuItem"
diff --git a/irc_mod/m_icolib.h b/irc_mod/m_icolib.h
new file mode 100644
index 0000000..a31abe2
--- /dev/null
+++ b/irc_mod/m_icolib.h
@@ -0,0 +1,75 @@
+// ---------------------------------------------------------------------------80
+// Icons Library Manager plugin for Miranda Instant Messenger
+// __________________________________________________________
+//
+// Copyright © 2005 Denis Stanishevskiy // StDenis
+// Copyright © 2006 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+
+#define SKINICONDESC_SIZE sizeof(SKINICONDESC)
+#define SKINICONDESC_SIZE_V1 0x18
+#define SKINICONDESC_SIZE_V2 0x1C
+#define SKINICONDESC_SIZE_V3 0x24
+
+typedef struct {
+ int cbSize;
+ union {
+ char *pszSection; // section name used to group icons
+ TCHAR *ptszSection;
+ wchar_t *pwszSection;
+ };
+ union {
+ char *pszDescription; // description for options dialog
+ TCHAR *ptszDescription;
+ wchar_t *pwszDescription;
+ };
+ char *pszName; // name to refer to icon when playing and in db
+ char *pszDefaultFile; // default icon file to use
+ int iDefaultIndex; // index of icon in default file
+ HICON hDefaultIcon; // handle to default icon
+ int cx,cy; // dimensions of icon
+ int flags;
+} SKINICONDESC;
+
+#define SIDF_UNICODE 0x100 // Section and Description are in UCS-2
+
+#if defined(_UNICODE)
+ #define SIDF_TCHAR SIDF_UNICODE
+#else
+ #define SIDF_TCHAR 0
+#endif
+
+//
+// Add a icon into options UI
+//
+// wParam = (WPARAM)0
+// lParam = (LPARAM)(SKINICONDESC*)sid;
+//
+#define MS_SKIN2_ADDICON "Skin2/Icons/AddIcon"
+
+//
+// Retrieve HICON with name specified in lParam
+// Returned HICON SHOULDN'T be destroyed, it is managed by IcoLib
+//
+
+#define MS_SKIN2_GETICON "Skin2/Icons/GetIcon"
+
+//
+// Icons change notification
+//
+#define ME_SKIN2_ICONSCHANGED "Skin2/IconsChanged"
diff --git a/irc_mod/m_ircscript.h b/irc_mod/m_ircscript.h
new file mode 100644
index 0000000..e12dcf4
--- /dev/null
+++ b/irc_mod/m_ircscript.h
@@ -0,0 +1,129 @@
+
+/*
+ This file is a description of the interface between the Miranda Scripting
+ Plugin (MSP) and IRC. It is mainly an internal draft.
+
+ The MSP is a powerful PHP based scripting engine
+ which can automate many tasks in Miranda IM. With the implementation of
+ this interface IRC can also benefit from the advantages MSP brings. The
+ interface has been constructed by the respective authors of IRC and MSP.
+
+ The idea is that MSP and IRC should communicate via the interface outlined herein,
+ but MSP should "package" the data in attractive functions that can be easily
+ used by eager scripters.
+
+ Note that m_chat.h should be #included as the events defined therein is used in this interface
+
+ The IRC plugin communicates with MSP mainly through 8 (2 x 4) services which are
+ illustrated by the following matrix (MSP has 4 services and IRC 4 services):
+
+
+ --------------------------------------------------
+ | | |
+ | Incoming raw data | Data going |
+ | from server | to GUI |
+ | (before processing) | (after processing) |
+ | | |
+ --------------------------------------------------
+ | | |
+ | Outgoing raw data | Data going |
+ | to server | from GUI |
+ | (after processing) | (before processing) |
+ | | |
+ --------------------------------------------------
+
+ (processing refers to the IRC plugin reacting to different commands)
+
+*/
+
+
+//------------------------- HANDLING RAW MESSAGES ------------------------
+/*
+
+ The two leftmost boxes are related to data sent to and from the server in RAW form.
+ (a typical RAW message looks like this: ":nick!user@host COMMAND PARAMETERS")
+
+ It is very useful for scripters to be able to manipulate and add RAW streams of data.
+
+ The below structure is used when RAW data is generated and IRC must trigger an
+ event in MSP so the scripts can do their magic.
+
+ If the data is modified make sure to use MS_SYSTEM_GET_MMI and then mmi_realloc() to
+ allocate from the same heap. Do not free the data.
+
+ wParam= Module name
+ lParam= (LPARAM)(char *)pszRaw
+ returns nonzero if the message should be dropped
+*/
+
+/*
+ NOTE! IRC will implement two services which also uses the same parameters:
+
+ "<Module Name>/InsertRawIn" //used for inserting a "fake" incoming RAW event
+ "<Module Name>/InsertRawOut" //used for inserting a "fake" outgoing RAW event
+
+*/
+
+
+#define MS_MBOT_IRC_RAW_IN "MBot/IrcRawIn"
+#define MS_MBOT_IRC_RAW_OUT "MBot/IrcRawOut"
+
+
+//------------------------- HANDLING GUI MESSAGES 1 ------------------------
+/*
+
+ The top rightmost box is related to data sent to the gui
+ (currently chat.dll) in the form of GCEVENT's. (see m_chat.h)
+
+ While maybe not as useful to the scripter, it can be useful to be able to
+ "tap into" messages to the GUI from the IRC plugin.
+
+ If the data is modified make sure to realloc() or similar.
+
+ wParam= (WPARAM) (WPARAM_GUI_IN) &wgi
+ lParam= (LPARAM)(GCEVENT *)&gce // see m_chat.h
+ returns nonzero if the message should be dropped
+*/
+
+/*
+ NOTE! IRC will implement a service which also uses the same parameters:
+
+ "<Module Name>/InsertGuiIn" //used for inserting a "fake" event to the GUI
+
+*/
+typedef struct MBOT_GUI_WPARAM_IN_STRUCT
+{
+ const char* pszModule;
+ WPARAM wParam;
+}WPARAM_GUI_IN;
+
+#define MS_MBOT_IRC_GUI_IN "MBot/IrcGuiIn"
+
+
+//------------------------- HANDLING GUI MESSAGES 2 ------------------------
+/*
+
+ The bottom rightmost box is related to data sent from the gui
+ (currently chat.dll) in the form of GCHOOKS's. Originally this is carried out in a hook,
+ but for MSP this is done via a service instead.
+
+ It can be useful for scripters to simulate user actions, like entering text, closing the window etc
+
+ If the data is modified make sure to realloc() or similar.
+
+ wParam= Module name
+ lParam= (LPARAM)(GCHOOK *)gch // see m_chat.h
+ returns nonzero if the message should be dropped
+*/
+
+/*
+ NOTE! IRC will implement a service which also uses the same parameters:
+
+ "<Module Name>/InsertGuiOut" //used for inserting a "fake" outgoing event to the GUI
+
+*/
+
+#define MS_MBOT_IRC_GUI_OUT "MBot/IrcGuiOut"
+
+#define MS_MBOT_REGISTERIRC "MBot/RegisterIRCModule"
+
diff --git a/irc_mod/m_nudge.h b/irc_mod/m_nudge.h
new file mode 100644
index 0000000..e87e410
--- /dev/null
+++ b/irc_mod/m_nudge.h
@@ -0,0 +1,5 @@
+#define MS_SHAKE_CLIST "SHAKE/Service/ShakeClist"
+#define MS_SHAKE_CHAT "SHAKE/Service/ShakeChat"
+#define MS_SHAKE_CLIST_TRIGGER "SHAKE/Service/TriggerShakeClist"
+#define MS_SHAKE_CHAT_TRIGGER "SHAKE/Service/TirggerShakeChat"
+#define MS_NUDGE_SEND "NUDGE/Send"
diff --git a/irc_mod/m_popupw.h b/irc_mod/m_popupw.h
new file mode 100644
index 0000000..c0cac41
--- /dev/null
+++ b/irc_mod/m_popupw.h
@@ -0,0 +1,56 @@
+/*
+===============================================================================
+ PopUp plugin
+Plugin Name: PopUp
+Plugin authors: Luca Santarelli aka hrk (hrk@users.sourceforge.net)
+ Victor Pavlychko aka zazoo (nullbie@gmail.com)
+===============================================================================
+The purpose of this plugin is to give developers a common "platform/interface"
+to show PopUps. It is born from the source code of NewStatusNotify, another
+plugin I've made.
+
+Remember that users *must* have this plugin enabled, or they won't get any
+popup. Write this in the requirements, do whatever you wish ;-)... but tell
+them!
+===============================================================================
+*/
+#ifndef M_POPUPW_H
+#define M_POPUPW_H
+
+#ifndef MAX_CONTACTNAME
+ #define MAX_CONTACTNAME 2048
+#endif
+
+#ifndef MAX_SECONDLINE
+ #define MAX_SECONDLINE 2048
+#endif
+
+// Unicode Popup Info
+typedef struct {
+ HANDLE lchContact;
+ HICON lchIcon;
+ WCHAR lpwzContactName[MAX_CONTACTNAME];
+ WCHAR lpwzText[MAX_SECONDLINE];
+ COLORREF colorBack;
+ COLORREF colorText;
+ WNDPROC PluginWindowProc;
+ void * PluginData;
+ int iSeconds; //Custom delay time in seconds. -1 means "forever", 0 means "default time".
+ char cZero[16]; //some unused bytes which may come useful in the future.
+} POPUPDATAW, *LPPOPUPDATAW;
+
+// Create Popup
+#define MS_POPUP_ADDPOPUPW "PopUp/AddPopUpW"
+
+static int __inline PUAddPopUpW(POPUPDATAW* ppdp) {
+ return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)ppdp,0);
+}
+
+// Change Text
+#define MS_POPUP_CHANGETEXTW "PopUp/ChangetextW"
+
+static int __inline PUChangeTextW(HWND hWndPopUp, LPCWSTR lpwzNewText) {
+ return (int)CallService(MS_POPUP_CHANGETEXTW, (WPARAM)hWndPopUp, (LPARAM)lpwzNewText);
+}
+
+#endif
diff --git a/irc_mod/m_smileyadd.h b/irc_mod/m_smileyadd.h
new file mode 100644
index 0000000..508c6e8
--- /dev/null
+++ b/irc_mod/m_smileyadd.h
@@ -0,0 +1,78 @@
+/*
+Miranda SmileyAdd Plugin
+Plugin support header file
+Copyright (C) 2003 Rein-Peter de Boer (peacow)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+//replace smiley tags in a rich edit control...
+//wParam = (WPARAM) 0; not used
+//lParam = (LPARAM) (SMADD_RICHEDIT*) &smre; //pointer to SmAddRicheditStructure
+//return: TRUE if replacement succeeded, FALSE if not (disable by user?).
+typedef struct
+{
+ int cbSize; //size of the structure
+ HWND hwndRichEditControl; //handle to the rich edit control
+ CHARRANGE* rangeToReplace; //same meaning as for normal Richedit use (NULL = replaceall)
+ char* Protocolname; //protocol to use... if you have defined a protocol, u can
+ //use your own protocol name. Smiley add wil automatically
+ //select the smileypack that is defined for your protocol.
+ //Or, use "Standard" for standard smiley set. Or "ICQ", "MSN"
+ //if you prefer those icons.
+ //If not found or NULL: "Standard" will be used
+ } SMADD_RICHEDIT;
+
+//new version from smileyadd 1.2
+typedef struct
+{
+ int cbSize; //size of the structure
+ HWND hwndRichEditControl; //handle to the rich edit control
+ CHARRANGE* rangeToReplace; //same meaning as for normal Richedit use (NULL = replaceall)
+ char* Protocolname; //protocol to use... if you have defined a protocol, u can
+ //use your own protocol name. Smiley add wil automatically
+ //select the smileypack that is defined for your protocol.
+ //Or, use "Standard" for standard smiley set. Or "ICQ", "MSN"
+ //if you prefer those icons.
+ //If not found or NULL: "Standard" will be used
+ BOOL useSounds; //NOT IMPLEMENTED YET, set to FALSE
+ BOOL disableRedraw; //If true then you have to restore scrollbars, selection
+ //etc and redraw yourself
+ //everything will be screwed up and not restored.
+
+} SMADD_RICHEDIT2;
+
+#define MS_SMILEYADD_REPLACESMILEYS "SmileyAdd/ReplaceSmileys"
+
+
+
+
+//replace smiley tags in a rich edit control...
+//wParam = (WPARAM) 0; not used
+//lParam = (LPARAM) (SMADD_GETICON*) &smgi; //pointer to SmAddRicheditStructure
+//return: TRUE if found, FALSE if not
+//NOTE: the
+typedef struct
+{
+ int cbSize; //same as in SMADD_RICHEDIT
+ char* Protocolname; // " "
+ char* SmileySequence; //character string containing the smiley
+ HICON SmileyIcon; //RETURN VALUE: this is filled with the icon handle...
+ //do not destroy!
+ int Smileylength; //length of the smiley that is found.
+} SMADD_GETICON;
+#define MS_SMILEYADD_GETSMILEYICON "SmileyAdd/GetSmileyIcon"
+
diff --git a/irc_mod/m_uninstaller.h b/irc_mod/m_uninstaller.h
new file mode 100644
index 0000000..e26f55c
--- /dev/null
+++ b/irc_mod/m_uninstaller.h
@@ -0,0 +1,700 @@
+/*
+
+ PluginUninstaller 1.1.2.1 for Miranda IM 0.3.3a and +
+ ------------------------------------------------------------------------
+ Developers - C/C++ Header File
+
+ Plugin Info: ----------------------------
+ | Version: 1.1.2.1
+ | Filename: uninstaller.dll
+ | Author: H. Herkenrath (hrathh@users.sourceforge.net)
+ | Description: Extends the plugin options and offers the possibility
+ | to directly remove plugins and delete all associated
+ | settings and files.
+
+ Contents: -------------------------------
+ | > General Info:
+ | - Uninstall Example/Template
+ | - Changing displayed icon
+ | - Changing displayed docs
+ | - Message boxes on uninstall
+ | - Service Accesibility
+ | - Including this file
+ |
+ | > Structs:
+ | - Uninstall Params (PLUGINUNINSTALLPARAMS)
+ |
+ | > Helpers:
+ | - Macro: Run service while uninstalling (PUICallService)
+ | - Function: Remove some files in directory (PUIRemoveFilesInDirectory)
+ |
+ | > Events:
+ | - Allow to uninstall a plugin (ME_PLUGINUNINSTALLER_OKTOUNINSTALL)
+ | - Plugin gets uninstalled (ME_PLUGINUNINSTALLER_UNINSTALL)
+ |
+ | > Services:
+ | - Remove database module (MS_PLUGINUNINSTALLER_REMOVEDBMODULE)
+ | - Remove a setting globally (MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY)
+ | - Remove skinned sound (MS_PLUGINUNINSTALLER_REMOVESKINSOUND)
+ | - Uninstall a plugin (MS_PLUGINUNISTALLER_UNISTALLPLUGIN)
+ | - Getting handles (MS_PLUGINUNINSTALLER_GETHANDLE)
+ |
+
+
+ This file is only thought for plugin developers.
+ If you only want to use "PluginUninstaller" and don't want to develop a plugin
+ or something with it you don't need this file.
+
+ If there are any problems or bugs with or in this file or something else
+ please mail me. My e-mail address is: hrathh@users.sourceforge.net
+ For more documentation you can use this address, too. :-)
+
+ If you have any whishes on some plugin uninstalling for your
+ plugin you can mail me, too. :-)
+
+*/
+#ifndef M_UNINSTALLER_H
+#define M_UNINSTALLER_H
+
+#ifndef CallService
+ #pragma message("Mistake Alert!: "m_uninstaller.h" needs to be included after "newpluginapi.h"!\n The following errors are resulting of this mistake.\n")
+#endif
+
+
+// | General Info
+// -----------------------------
+
+// Uninstall Example/Template
+// ---------------------------
+// Making your plugin uninstallable is very easy.
+// Just add the following "Uninstall" function near the "Unload" function
+// in your plugin.
+// A template plugin is available in the source code package.
+
+// Old:
+// int __declspec(dllexport) Uninstall(BOOL bIsMirandaRunning, BOOL bDoDeleteSettings, char* pszPluginPath);
+
+// New:
+//int __declspec(dllexport) UninstallEx(PLUGINUNINSTALLPARAMS* ppup)
+//{
+ // Available Variables:
+ // -----------------------------
+ // ppup->bIsMirandaRunning:
+ // Contains if Miranda is running
+ // (Currently this is always TRUE).
+
+ // ppup->bDoDeleteSettings:
+ // Contains if the users selected
+ // that he wants all settings be deleted.
+
+ // ppup->pszPluginsPath:
+ // Contains the plugins directory name.
+
+
+ // Notes:
+ // -----------------------------
+
+ // Run before "Unload" function:
+ // -> IMPORTANT: Be careful not to write to the database or to files in "Unload" again!!!
+ // -> Perhaps create a global BOOL variable which is set to TRUE when your plugin gets uninstalled
+ // or check of a database setting "IsInstalled" in Unload() or sth. like that
+
+ // All Miranda is still loaded
+
+ // Here you can do:
+ // - Delete settings group in database
+ // - Delete registry items
+ // - Delete ini-files and other settings files
+ // - Delete other files
+
+ // Your plugin dll gets automatically deleted
+
+ // Services to remove are offered:
+ // MS_PLUGINUNINSTALLER_REMOVEDBMODULE
+ // MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY
+ // MS_PLUGINUNINSTALLER_REMOVESKINSOUND
+
+
+ // Getting other useful paths:
+ // -----------------------------
+
+ // System directory:
+
+ //char szSysPath[MAX_PATH];
+ //GetSystemDirectory(szSysPath, MAX_PATH);
+
+
+ // Windows directory:
+
+ //char szWinPath[MAX_PATH];
+ //GetWindowsDirectory(szWinPath, MAX_PATH);
+
+
+ // Other directories:
+
+ // char szPath[MAX_PATH];
+ // SHGetSpecialFolderPath(NULL, szPath, CSIDL_* , FALSE);
+
+ // Some available dirs:
+ // CSIDL_APPDATA CSIDL_SENDTO CSIDL_FAVORITES
+ // CSIDL_STARTUP CSIDL_PROFILE CSIDL_DESKTOPDIRECTORY
+
+
+ // Delete Files
+ //const char* apszFiles[] = {"MyPlugin_Readme.txt", "MyPlugin_License.txt", "MyPlugin_Developer.txt", "MyPlugin_Translation.txt"};
+ //PUIRemoveFilesInPath(ppup->pszPluginsPath, apszFiles);
+
+ // Delete Settings
+ //if(ppup->bDoDeleteSettings == TRUE)
+ //{
+ //if (ppup->bIsMirandaRunning == TRUE) // Check if it is possible to access services
+ //{
+ // Remove plugin's module
+ //PUIRemoveDbModule("MyPlugin");
+
+ // Remove plugin's sounds
+ //PUIRemoveSkinSound("MySoundSetting1");
+ //PUIRemoveSkinSound("MySoundSetting2");
+ //}
+ //}
+
+ // Remember:
+ // Do not forget to remove your (eventually) created registry items here, too.
+
+
+ // The plugin's dll file gets deleted after returning.
+
+ // Remember:
+ // If your DLL file is additionally in use by another application (eg. Windows)
+ // you need to free the DLL *here* completely. Otherwise it can't be deleted.
+
+// return 0;
+//}
+
+
+
+// Changing displayed icon
+// ---------------------------
+// The icon that gets displayed on the options page is always the "first"
+// icon in your DLL file.
+// An icon in your DLL file is the first icon when it has the lowest recource ID.
+// If you would like to have an other icon shown in the options please change your
+// icon resource IDs so that the icon you would like to have has the lowest one.
+// For example if you use MS Visual C++, open "resource.h" and change the resource define
+// of your prefered icon to the lowest icon number.
+
+
+// Changing displayed docs
+// ---------------------------
+// The items "License" and "More Information" on the plugin details page
+// are created when the a license and/or a readme file for the plugin exists.
+// The files get detected automatically and need a special name
+// so that they get detected.
+// The text files need to be either placed in the "Plugins" directory or
+// in the "Docs" directory. Whereof the last one is the better one :-)
+//
+// For the license file the following file name formatings are possible:
+// PluginName-License.txt (I personally think that this is the best naming solution... :-) )
+// PluginName_License.txt,
+//
+// For the readme file the following ones are possible:
+// PluginName-Readme.txt (Again...I like this one :-D ),
+// PluginName_Readme.txt,
+
+// Message boxes on uninstall
+// ---------------------------
+// If you would like to ask the user for something to remove/uninstall
+// please hook the event ME_PLUGINUNINSTALLER_UNINSTALL and show your
+// message box there. Save the action the user chose in a
+// global BOOL variable and do the chosen action in "UninstallEx".
+// You can get the plugins options window handle with MS_PLUGINUNINSTALLER_GETHANDLE.
+
+
+// Service Accessibility
+// ---------------------------
+// Remember that you only can use these functions after the event ME_SYSTEM_MODULESLOADED
+// or later because "PluginUninstaller" needs to be loaded first.
+// Normally you only use them in your "UninstallEx" function.
+//
+// IMPORTANT!:
+// Please make sure that you always use the macro PUICallService
+// in the "UninstallEx" function instead of the CallService function.
+
+
+// Including this file
+// ---------------------------
+// To use some of the uninstalling functionality you have to include this file
+// into your project.
+//
+// IMPORTANT!:
+// Please make sure that you include the file "newpluginapi.h" before this one.
+// If this isn't the case there may some compile errors come up.
+
+ // -> Example:
+ // If your plugin is in the directory "Plugins/MyPlugin/" and
+ // this include file is in the directory "Plugins/PluginUninstaller"
+ // you can use the following:
+
+ //#include "../PluginUninstaller/m_uninstaller.h"
+
+ // If your plugin is in an directory that is different to that one just
+ // change the include path to the one you want.
+
+
+
+
+
+// | Structs
+// -----------------------------
+
+// ---------------------------------------------
+// -- Struct: Uninstall Params -----------------
+// ---------------------------------------------
+
+// Struct: PLUGINUNINSTALLPARAMS
+// (Gets passed to "UninstallEx" function)
+
+typedef int (*HELPERPROC)(const char*, WPARAM, LPARAM); // Used internally (for pHelperProcAddress)
+
+typedef struct {
+ BOOL bIsMirandaRunning; // Is TRUE when Miranda is loaded and services are available (Please use PUICallService instead of CallService)
+ BOOL bDoDeleteSettings; // Is TRUE when user wants to delete settings (If this is FALSE, please only delete your files)
+ char* pszPluginsPath; // Contains the plugin directory path
+ char* pszDocsPath; // Contains the document directory for plugins documentation (Added in version 1.1.1.0)
+ char* pszIconsPath; // Contains the icon directory for icon dlls (Added in version 1.1.2.0)
+ HELPERPROC pHelperProcAddress; // Used internally (Contains proc address for PUICallService)
+} PLUGINUNINSTALLPARAMS;
+
+
+
+
+
+// | Helper
+// -----------------------------
+
+
+// ---------------------------------------------
+// -- Macro: Run service while uninstalling ----
+// ---------------------------------------------
+
+// Macro: PUICallService
+
+#define PUICallService(service, wParam, lParam) (ppup->pHelperProcAddress) (service, wParam, lParam);
+
+// Description:
+// -------------
+// This service provides the possibility to call a Miranda
+// service in the "UninstallEx" function.
+// Important!: Use this macro always instead of "CallService",
+// because else a crash occurs when the plugin was decativated
+// and gets uninstalled
+
+// Parameters:
+// -------------
+// Same parameters as CallService of Miranda Core.
+
+// Return Values:
+// --------------
+// Return values are the same as the CallService function of Miranda Core.
+// Additionaly returns CALLSERVICE_NOTFOUND if Miranda is not loaded
+// which means the services are not accessable.
+
+
+ // Example:
+ // ----------------------------------
+
+ //if ( (bIsMirandaRunning == TRUE) && (bDoDeleteSettings == TRUE) )
+ //{
+ // Remove plugin's module
+ //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)"MyPlugin", 0);
+ //}
+
+
+
+
+// ---------------------------------------------
+// -- Function: Remove some files in directory -
+// ---------------------------------------------
+
+// Function: PUIRemoveFilesInDirectory
+
+static BOOL __inline PUIRemoveFilesInDirectory(char* pszPath, const char* apszFiles[]);
+
+// Description:
+// -------------
+// This helper provides the possibility to easily
+// remove specified files in a specified directory.
+
+// Note: The last version of this helper (PUIRemoveFilesInPath)
+// did not work correctly.
+// Please do now always append a NULL slot to the end of your array.
+
+// Parameters:
+// -------------
+// char* pszPath = Path to the files in array
+// const LPCSTR apszFiles[] = NULL-terminated array of files to be deleted.
+
+// Return Values:
+// --------------
+// Returns TRUE if the files could be deleted.
+// FALSE if the files could not be deleted or did not exist.
+
+
+static BOOL __inline PUIRemoveFilesInDirectory(char* pszPath, const char* apszFiles[])
+{
+ char szFile[MAX_PATH];
+ BOOL bReturn = FALSE;
+ int iFile = 0;
+
+ while (apszFiles[iFile] != NULL)
+ {
+ strncpy(szFile, pszPath, sizeof(szFile));
+ strncat(szFile, apszFiles[iFile], sizeof(szFile)-strlen(szFile));
+
+ if ((BOOL)DeleteFile(szFile) == TRUE) bReturn = TRUE;
+ iFile++;
+ }
+
+ return bReturn;
+}
+
+ // Example:
+ // ----------------------------------
+
+ //const char* apszFiles[] = {"File1.txt", "File2.txt", "File3.txt", NULL};
+ //PUIRemoveFilesInDirectory(ppup->pszPluginsPath, apszFiles);
+
+
+
+
+// | Events
+// -----------------------------
+
+
+// ---------------------------------------------
+// -- Event: Allow to uninstall a plugin -------
+// ---------------------------------------------
+
+// Event: ME_PLUGINUNINSTALLER_OKTOUNINSTALL
+
+#define ME_PLUGINUNINSTALLER_OKTOUNINSTALL "PluginUninstaller/OkToUninstall"
+
+// Submitted Values:
+// -----------------
+// wParam = pszPluginName (String containing the translated plugin name)
+// lParam = pszPluginFile (String containing the plugin dll file name in lower case)
+
+// Return Values:
+// -----------------
+// Returning 1 on this event causes the "Remove Plugin" button to be disabled.
+
+
+
+// ---------------------------------------------
+// -- Event: Plugin gets uninstalled -----------
+// ---------------------------------------------
+
+// Event: ME_PLUGINUNINSTALLER_UNINSTALL
+
+#define ME_PLUGINUNINSTALLER_UNINSTALL "PluginUninstaller/Uninstall"
+
+// Submitted Values:
+// -----------------
+// wParam = pszPluginName (String containing the translated plugin name)
+// lParam = pszPluginFile (String containing the plugin dll file name in lower case)
+
+// Return Values:
+// -----------------
+// Returning 1 on this event causes the uninstall process to be canceled.
+
+// Notice:
+// Hook this event if you would like to ask the user for something to remove/uninstall
+// and show your message box on this event. Save the action the user chose in a
+// global BOOL variable and do the chosen action in "UninstallEx".
+// You can get the plugins options window handle with MS_PLUGINUNINSTALLER_GETHANDLE.
+
+// Other plugins can use this event to be noticed that another plugin isn't installed anylonger.
+
+
+
+
+// | Services
+// -----------------------------
+
+
+// ---------------------------------------------
+// -- Service: Remove database module ----------
+// ---------------------------------------------
+
+// Service: MS_PLUGINUNINSTALLER_REMOVEDBMODULE
+
+#define MS_PLUGINUNINSTALLER_REMOVEDBMODULE "PluginUninstaller/RemoveDbModule"
+
+// Description:
+// -------------
+// This service provides the possibility to delete all database modules
+// associated to your plugin.
+// The specified database module will be removed in all contacts
+// including the NULL contact.
+// Remember to call it always with PUICallService in "UninstallEx" function.
+
+// Parameters:
+// -------------
+// wParam = (char*)pszModule // Pointer to a string containd module name. Can't be NULL
+// lParam = (const char*)apszIgnoreSettings // NULL terminated array of strings. Can be 0 if no settings should be ignored.
+ // See example 3 for more details
+
+// Return Values:
+// --------------
+// Returns 0 on success.
+// Nonzero if the module was not present in database.
+
+
+#ifndef UNINSTALLER_NOHELPERS
+
+// Can only be used in "UninstallEx" function
+#define PUIRemoveDbModule(pszModule) PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)pszModule, 0);
+
+#endif
+
+
+ // Example 1:
+ // ----------------------------------
+
+ //PUIRemoveDbModule("MyPlugin");
+
+
+ // Example 2:
+ // ----------------------------------
+
+ //char szModule[] = "MyModule";
+ //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szModule, 0);
+
+
+ // Example 3:
+ // ----------------------------------
+
+ // This deletes all settings in the specified module exept
+ // the specified settings: "Setting1",..."Setting4"
+
+ // char szModule[] = "MyModule";
+ // const char* apszIgnoreSettings[] = {"Setting1", "Setting2", "Setting3", "Setting4", NULL};
+ // PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szModule, (LPARAM)&apszIgnoreSettings);
+
+
+
+// ---------------------------------------------
+// -- Service: Remove a setting globally -------
+// ---------------------------------------------
+
+// Service: MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY
+
+#define MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY "PluginUninstaller/RemoveDbSettingGlobally"
+
+// Description:
+// -------------
+// This service provides the possibility to delete a specific
+// setting in database in all contacts including the NULL contact.
+// Remember to call it always with PUICallService in "UninstallEx" function.
+
+// Parameters:
+// -------------
+// wParam = (char*)pszModule
+// lParam = (char*)pszSetting
+
+// Return Values:
+// --------------
+// Returns 0 on success.
+// Nonzero if the setting was not present in database.
+
+
+#ifndef UNINSTALLER_NOHELPERS
+
+// Can only be used in "UninstallEx" function
+#define PUIRemoveDbSettingGlobally(pszModule, pszSetting) PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY, (WPARAM)pszModule, (LPARAM)pszSetting);
+
+
+#endif
+
+
+ // Example 1:
+ // ----------------------------------
+
+ //PUIRemoveDbSettingGlobally("MyPlugin", "MySetting");
+
+
+ // Example 2:
+ // ----------------------------------
+
+ //szModule[] = "MyPlugin";
+ //szSetting[] = "MySetting";
+ //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY, (WPARAM)szModule, (LPARAM)szSetting);
+
+
+
+
+
+
+// ---------------------------------------------
+// -- Service: Remove skinned sound ------------
+// ---------------------------------------------
+
+// Service: MS_PLUGINUNINSTALLER_REMOVESKINSOUND
+
+#define MS_PLUGINUNINSTALLER_REMOVESKINSOUND "PluginUninstaller/RemoveSkinSound"
+
+// Description:
+// -------------
+// This service provides the possibility to delete all your sound settings
+// associated to your plugin.
+// The specified sound will be be removed.
+// Remember to call it always with PUICallService in "UninstallEx" function.
+
+// Parameters:
+// -------------
+// wParam = (char*)pszSoundSetting
+// lParam = 0
+
+// Return Values:
+// --------------
+// Returns 0 on success.
+// Nonzero if the sound was not present in database.
+
+
+#ifndef UNINSTALLER_NOHELPERS
+
+// Can only be used in "UninstallEx" function
+#define PUIRemoveSkinSound(pszSoundSetting) PUICallService(MS_PLUGINUNINSTALLER_REMOVESKINSOUND, (WPARAM)pszSoundSetting, 0);
+
+#endif
+
+
+ // Example 1:
+ // ----------------------------------
+
+ //PUIRemoveSkinSound("MySoundSetting");
+
+
+ // Example 2:
+ // ----------------------------------
+
+ //szSoundModule[] = "MySoundSetting";
+ //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szSoundSetting, 0);
+
+
+
+
+
+// ---------------------------------------------
+// -- Service: Uninstall a plugin --------------
+// ---------------------------------------------
+
+// Service: MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN
+
+#define MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN "PluginUninstaller/UninstallPlugin"
+
+// Description:
+// -------------
+// This service marks a plugin to be uninstalled at next restart of Miranda IM.
+// It uses the default value for "Delete all settings".
+// You can use this service for example when you want that your sub-plugin gets
+// also removed when your main-plugin is uninstalled.
+// Note: This service is not needed for the normal uninstalling functionality.
+
+// Parameters:
+// -------------
+// wParam = (char*)pszPluginName // do not translate this!
+// lParam = (char*)pszPluginFile // without path, only file name!
+
+// Return Values:
+// --------------
+// Returns always 0.
+
+
+#ifndef UNINSTALLER_NOHELPERS
+
+int __inline PUIUninstallPlugin(char* pszPluginName, char* pszPluginFile)
+{
+ return CallService(MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN, (WPARAM)pszPluginName, (LPARAM)pszPluginFile);
+}
+
+#endif
+
+
+ // Example 1:
+ // ----------------------------------
+
+ //PUIUninstallPlugin("PluginName", "plugin.dll");
+
+
+ // Example 2:
+ // ----------------------------------
+
+ // hInst => Handle of a specific (your?) plugin
+ // char szPluginName[] = "YourPluginName";
+
+ //char* pFileName;
+ //char szPath[MAX_PATH];
+
+ //GetModuleFileName(hInst, szPath, sizeof(szPath));
+ //pFileName = strrchr(szPath, '\\');
+ //pFileName = pFileName+1; // Pointer arithmetic
+
+ //CallService(MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN, (WPARAM)szPluginName, (LPARAM)pFileName);
+
+
+
+
+// ---------------------------------------------
+// -- Service: Getting handles -----------------
+// ---------------------------------------------
+
+// Service: MS_PLUGINUNINSTALLER_GETHANDLE
+
+#define MS_PLUGINUNINSTALLER_GETHANDLE "PluginUninstaller/GetHandle"
+
+// Description:
+// -------------
+// This service gets a specified window/instance handle.
+
+// Note: This service must not be used in "UninstallEx" function.
+// It is mainly thought for being used in ME_PLUGINUNINSTALLER_UNINSTALL event
+// to give out a MessageBox or something like that.
+
+// Parameters:
+// -------------
+// wParam = UINT uHandleType;
+// lParam = 0
+
+// Possible values for wParam:
+#define PUIHT_HINST_PLUGIN_INSTANCE 0 // HINSTANCE of the PluginUninstaller plugin
+#define PUIHT_HWND_PLUGIN_OPTIONS 1 // HWND of the plugin options dialog (if it is loaded; else NULL)
+
+// Return Values:
+// --------------
+// Returns the specified handle value.
+// If no handle type is specified it returns NULL.
+// The handle doesn't need to be destroyed.
+
+
+#ifndef UNINSTALLER_NOHELPERS
+
+HANDLE __inline PUIGetHandle(UINT uHandleType)
+{
+ return (HANDLE)CallService(MS_PLUGINUNINSTALLER_GETHANDLE, uHandleType, 0);
+}
+
+#endif
+
+
+ // Example
+ // ----------------------------------
+
+ //HWND hwndDlg;
+ //hwndDlg = (HWND)PUIGetHandle(PUIHT_HWND_PLUGIN_OPTIONS);
+
+
+
+
+
+#endif // M_UNINSTALLER_H
diff --git a/irc_mod/m_updater.h b/irc_mod/m_updater.h
new file mode 100644
index 0000000..a5081a4
--- /dev/null
+++ b/irc_mod/m_updater.h
@@ -0,0 +1,122 @@
+#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 function can be used to 'unregister' components - useful for plugins that register non-plugin/langpack components and
+// may need to change those components on the fly
+// lParam = (char *)szComponentName
+#define MS_UPDATE_UNREGISTER "Update/Unregister"
+
+// this event is fired when the startup process is complete, but NOT if a restart is imminent
+// it is designed for status managment plugins to use as a trigger for beggining their own startup process
+// wParam = lParam = 0 (unused)
+// (added in version 0.1.6.0)
+#define ME_UPDATE_STARTUPDONE "Update/StartupDone"
+
+// this service can be used to enable/disable Updater's global status control
+// it can be called from the StartupDone event handler
+// wParam = (BOOL)enable
+// lParam = 0
+// (added in version 0.1.6.0)
+#define MS_UPDATE_ENABLESTATUSCONTROL "Update/EnableStatusControl"
+
+// An description of usage of the above service and event:
+// Say you are a status control plugin that normally sets protocol or global statuses in your ModulesLoaded event handler.
+// In order to make yourself 'updater compatible', you would move the status control code from ModulesLoaded to another function,
+// say DoStartup. Then, in ModulesLoaded you would check for the existence of the MS_UPDATE_ENABLESTATUSCONTROL service.
+// If it does not exist, call DoStartup. If it does exist, hook the ME_UPDATE_STARTUPDONE event and call DoStartup from there. You may
+// also wish to call MS_UPDATE_ENABLESTATUSCONTROL with wParam == FALSE at this time, to disable Updater's own status control feature.
+
+#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/irc_mod/m_xstatus.h b/irc_mod/m_xstatus.h
new file mode 100644
index 0000000..82237ad
--- /dev/null
+++ b/irc_mod/m_xstatus.h
@@ -0,0 +1,39 @@
+// Display XStatus detail (internal use only)
+// wParam=(WPARAM)hContact;
+#define MS_XSTATUS_SHOWDETAILS "/ShowXStatusDetails"
+
+//received Custom Status details response
+//hProcess=dwSequence
+//lParam=0
+#define ACKTYPE_XSTATUS_RESPONSE 1006
+
+/* Custom Status helper API *
+ - to set custom status message & title use PS_ICQ_GETCUSTOMSTATUS to obtain
+ DB settings and write values to them (UTF-8 strings best).
+ - custom messages for each user supported - ME_ICQ_STATUSMSGREQ with type MTYPE_SCRIPT_NOTIFY
+ */
+// Sets owner current custom status
+//wParam = (int)N // custom status id (1-32)
+//lParam = 0
+//return = N (id of status set) or 0 (failed - probably bad params)
+#define PS_SETCUSTOMSTATUS "/SetXStatus"
+
+// Retrieves specified custom status icon
+//wParam = (int)N // custom status id (1-32), 0 = my current custom status
+//lParam = 0
+//return = HICON // custom status icon (use DestroyIcon to release resources)
+#define PS_GETCUSTOMSTATUSICON "/GetXStatusIcon"
+
+// Get Custom status DB field names & current owner custom status
+//wParam = (char**)szDBTitle // will receive title DB setting name (do not free)
+//lParam = (char**)szDBMsg // will receive message DB setting name
+//return = N // current custom status id if successful, 0 otherwise
+#define PS_GETCUSTOMSTATUS "/GetXStatus"
+
+// Request Custom status details (messages) for specified contact
+//wParam = hContact // request custom status details for this contact
+//lParam = 0
+//return = (int)dwSequence // if successful it is sequence for ICQACKTYPE_XSTATUS_RESPONSE
+ // 0 failed to request (e.g. auto-request enabled)
+ // -1 delayed (rate control) - sequence unknown
+#define PS_REQUESTCUSTOMSTATUS "/RequestXStatusDetails"
diff --git a/irc_mod/main.cpp b/irc_mod/main.cpp
new file mode 100644
index 0000000..1f57f01
--- /dev/null
+++ b/irc_mod/main.cpp
@@ -0,0 +1,248 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+
+CIrcSession g_ircSession=NULL; // Representation of the IRC-connection
+CMyMonitor *monitor; // Object that processes data from the IRC server
+MM_INTERFACE mmi = {0}; // structure which keeps pointers to mirandas alloc, free and realloc
+char * IRCPROTONAME = NULL;
+char * ALTIRCPROTONAME = NULL;
+char * pszServerFile = NULL;
+char * pszPerformFile = NULL;
+char * pszIgnoreFile = NULL;
+char mirandapath[MAX_PATH];
+DWORD mirVersion = NULL;
+CRITICAL_SECTION cs;
+CRITICAL_SECTION m_gchook;
+PLUGINLINK * pluginLink;
+HINSTANCE g_hInstance = NULL;
+PREFERENCES * prefs;
+
+//static HMODULE m_libeay32;
+HMODULE m_ssleay32 = NULL;
+
+// NUDGE
+HANDLE hIRCNudge = NULL;
+
+// Unicode
+BYTE gbUnicodeAPI;
+BYTE gbUnicodeCore;
+BYTE gbUtfLangpack;
+
+PLUGININFO pluginInfo=
+{ // Information about the plugin
+ sizeof( PLUGININFO ),
+ #ifdef _UNICODE
+ "IRC Protocol (Unicode)",
+ #else
+ "IRC Protocol",
+ #endif
+ PLUGIN_MAKE_VERSION( 0,7,0,11 ),
+ "IRC protocol for Miranda IM. (Nudge, Typing Notify, xStatus, Avatars)",
+ "MatriX, Angeli-Ka, prog, IRoN, etc",
+ "wortex@users.sourceforge.net",
+ "© 2003 - 2005 Jörgen Persson, © 2006 Miranda IM Community",
+ "http://dev.mirandaim.ru/iron/",
+ 0,
+ 0
+};
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ g_hInstance=hinstDLL;
+
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ mirVersion = mirandaVersion;
+ return &pluginInfo;
+}
+
+static void GetModuleName( void ) // ripped from msn
+{
+ char * p = NULL;
+ char * p1 = NULL;
+
+ GetModuleFileName(g_hInstance, mirandapath, MAX_PATH);
+ p = strrchr( mirandapath, '\\' );
+ if(p)
+ {
+ char * p2;
+ *p = '\0';
+ p++;
+ p1 = strrchr( p, '.' );
+ *p1 = '\0';
+ p2 = p;
+ while( *p2 )
+ {
+ if(*p2 == ' ')
+ *p2 = '_';
+ p2++;
+ }
+ IRCPROTONAME = strdup( p );
+ ALTIRCPROTONAME = new char[lstrlen( IRCPROTONAME ) + 7 ];
+ CharUpper(IRCPROTONAME);
+
+ if (lstrcmpi(IRCPROTONAME, "IRC"))
+ mir_snprintf(ALTIRCPROTONAME, lstrlen( IRCPROTONAME ) + 7 , "IRC (%s)", IRCPROTONAME);
+ else
+ mir_snprintf(ALTIRCPROTONAME, lstrlen( IRCPROTONAME ) + 7 , "%s", IRCPROTONAME);
+ }
+}
+
+static void RegisterProtocol( void )
+{
+ PROTOCOLDESCRIPTOR pd;
+ ZeroMemory( &pd, sizeof( pd ) );
+ pd.cbSize = sizeof( pd );
+ pd.szName = IRCPROTONAME;
+ pd.type = PROTOTYPE_PROTOCOL;
+ CallService( MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd );
+}
+
+extern "C" int __declspec(dllexport) Load( PLUGINLINK *link )
+{
+ #ifndef NDEBUG //mem leak detector :-) Thanks Tornado!
+ int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); // Get current flag
+ flag |= _CRTDBG_LEAK_CHECK_DF; // Turn on leak-checking bit
+ _CrtSetDbgFlag(flag); // Set flag to the new value
+ #endif
+
+ pluginLink=link;
+
+ // Are we running under Unicode Windows version ?
+ gbUnicodeAPI = (GetVersion() & 0x80000000) == 0;
+ #ifdef _DEBUG
+ DBGprintf("UnicodeAPI = %d\n", gbUnicodeAPI);
+ #endif
+
+ // Do we have new LangPack module ready ?
+ gbUtfLangpack = ServiceExists(MS_LANGPACK_GETCODEPAGE);
+ { // Are we running under unicode Miranda core ?
+ char szVer[MAX_PATH];
+ CallService(MS_SYSTEM_GETVERSIONTEXT, MAX_PATH, (LPARAM)szVer);
+ gbUnicodeCore = (strstr(szVer, "Unicode") != NULL);
+ }
+ #ifdef _DEBUG
+ DBGprintf("UnicodeCore = %d\n", gbUnicodeCore);
+ #endif
+
+ // Initialize charset conversion routines
+ InitI18N();
+
+ // Initialize core modules
+ InitDB(); // DB interface
+
+ if( !mirVersion || mirVersion<PLUGIN_MAKE_VERSION( 0, 4, 0 ,0 ) )
+ {
+ char szVersion[] = "0.4"; // minimum required version
+ char szText[] = "The IRC protocol could not be loaded as it is dependant on Miranda IM version %s or later.\n\nDo you want to download an update from the Miranda website now?";
+ char * szTemp = new char[lstrlen (szVersion) + lstrlen(szText) + 10];
+ mir_snprintf(szTemp, lstrlen (szVersion) + lstrlen(szText) + 10, szText, szVersion);
+ if(IDYES == MessageBoxA(0,Translate(szTemp),Translate("Information"),MB_YESNO|MB_ICONINFORMATION))
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM) "http://miranda-im.org/");
+ delete[] szTemp;
+ return 1;
+ }
+
+ GetModuleName();
+ UpgradeCheck();
+ CallService(MS_SYSTEM_GET_MMI, 0, (LPARAM) &mmi);
+
+ InitializeCriticalSection(&cs);
+ InitializeCriticalSection(&m_gchook);
+
+//#ifdef IRC_SSL
+ m_ssleay32 = LoadLibrary("ssleay32.dll");
+//#endif
+
+ monitor = new CMyMonitor;
+ g_ircSession.AddIrcMonitor(monitor);
+
+// Nudge
+ char nudge[250];
+ sprintf(nudge,"%s/Nudge",IRCPROTONAME);
+ hIRCNudge = CreateHookableEvent(nudge);
+
+ RegisterProtocol();
+ HookEvents();
+ CreateServiceFunctions();
+ InitPrefs();
+ CList_SetAllOffline(true);
+
+// This must be here - the events are called too early, WTF?
+ InitXStatusEvents();
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ CList_SetAllOffline(TRUE);
+
+ DeleteCriticalSection(&cs);
+ DeleteCriticalSection(&m_gchook);
+
+ if(m_ssleay32)
+ FreeLibrary(m_ssleay32);
+
+ UnhookEvents();
+ UnInitOptions();
+ free( IRCPROTONAME );
+ delete [] ALTIRCPROTONAME;
+ delete monitor;
+
+ return 0;
+}
+
+void UpgradeCheck(void)
+{
+ DWORD dwVersion = DBGetContactSettingDword(NULL, IRCPROTONAME, "OldVersion", PLUGIN_MAKE_VERSION(0,6,0,0));
+ if( pluginInfo.version > dwVersion)
+ {
+ if(dwVersion < PLUGIN_MAKE_VERSION(0,6,1,0))
+ {
+ DBDeleteContactSetting(NULL, IRCPROTONAME, "OnlineNotificationTime");
+ DBDeleteContactSetting(NULL, IRCPROTONAME, "AutoOnlineNotifTempAlso");
+
+ }
+ if(dwVersion < PLUGIN_MAKE_VERSION(0,6,3,7))
+ {
+ DBVARIANT dbv;
+ char pw[600] = {0};
+ if(!DBGetContactSetting(NULL, IRCPROTONAME, "Password", &dbv) && dbv.type==DBVT_ASCIIZ)
+ {
+ lstrcpyn(pw, dbv.pszVal, 599);
+ DBFreeVariant(&dbv);
+ }
+ if(lstrlenA(pw) > 0)
+ {
+ CallService(MS_DB_CRYPT_ENCODESTRING, 499, (LPARAM)pw);
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "Password", pw);
+ MessageBoxA(NULL, Translate("To increase security the saved password for your\n default network is now encrypted."), IRCPROTONAME, MB_OK|MB_ICONINFORMATION);
+ }
+ }
+ }
+ DBWriteContactSettingDword(NULL, IRCPROTONAME, "OldVersion", pluginInfo.version);
+ return;
+} \ No newline at end of file
diff --git a/irc_mod/md5.cpp b/irc_mod/md5.cpp
new file mode 100644
index 0000000..eaf2d80
--- /dev/null
+++ b/irc_mod/md5.cpp
@@ -0,0 +1,352 @@
+/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.c 2874 2006-05-16 21:38:00Z ghazan $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+ either statically or dynamically; added missing #include <string.h>
+ in library.
+ 2002-03-11 lpd Corrected argument list for main(), and added int return
+ type, in test program and T value program.
+ 2002-02-21 lpd Added missing #include <stdio.h> in test program.
+ 2000-07-03 lpd Patched to eliminate warnings about "constant is
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+// (C) 2005 Joe @ Whale - changed to compile with Miranda
+
+#include "irc.h"
+
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+//gfd*
+static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+
+ {
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+ else /* dynamic big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
+
+ X = xbuf; /* (dynamic only) */
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+ }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET1(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET1(a, b, c, d, 0, 7, T1);
+ SET1(d, a, b, c, 1, 12, T2);
+ SET1(c, d, a, b, 2, 17, T3);
+ SET1(b, c, d, a, 3, 22, T4);
+ SET1(a, b, c, d, 4, 7, T5);
+ SET1(d, a, b, c, 5, 12, T6);
+ SET1(c, d, a, b, 6, 17, T7);
+ SET1(b, c, d, a, 7, 22, T8);
+ SET1(a, b, c, d, 8, 7, T9);
+ SET1(d, a, b, c, 9, 12, T10);
+ SET1(c, d, a, b, 10, 17, T11);
+ SET1(b, c, d, a, 11, 22, T12);
+ SET1(a, b, c, d, 12, 7, T13);
+ SET1(d, a, b, c, 13, 12, T14);
+ SET1(c, d, a, b, 14, 17, T15);
+ SET1(b, c, d, a, 15, 22, T16);
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET2(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET2(a, b, c, d, 1, 5, T17);
+ SET2(d, a, b, c, 6, 9, T18);
+ SET2(c, d, a, b, 11, 14, T19);
+ SET2(b, c, d, a, 0, 20, T20);
+ SET2(a, b, c, d, 5, 5, T21);
+ SET2(d, a, b, c, 10, 9, T22);
+ SET2(c, d, a, b, 15, 14, T23);
+ SET2(b, c, d, a, 4, 20, T24);
+ SET2(a, b, c, d, 9, 5, T25);
+ SET2(d, a, b, c, 14, 9, T26);
+ SET2(c, d, a, b, 3, 14, T27);
+ SET2(b, c, d, a, 8, 20, T28);
+ SET2(a, b, c, d, 13, 5, T29);
+ SET2(d, a, b, c, 2, 9, T30);
+ SET2(c, d, a, b, 7, 14, T31);
+ SET2(b, c, d, a, 12, 20, T32);
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET3(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET3(a, b, c, d, 5, 4, T33);
+ SET3(d, a, b, c, 8, 11, T34);
+ SET3(c, d, a, b, 11, 16, T35);
+ SET3(b, c, d, a, 14, 23, T36);
+ SET3(a, b, c, d, 1, 4, T37);
+ SET3(d, a, b, c, 4, 11, T38);
+ SET3(c, d, a, b, 7, 16, T39);
+ SET3(b, c, d, a, 10, 23, T40);
+ SET3(a, b, c, d, 13, 4, T41);
+ SET3(d, a, b, c, 0, 11, T42);
+ SET3(c, d, a, b, 3, 16, T43);
+ SET3(b, c, d, a, 6, 23, T44);
+ SET3(a, b, c, d, 9, 4, T45);
+ SET3(d, a, b, c, 12, 11, T46);
+ SET3(c, d, a, b, 15, 16, T47);
+ SET3(b, c, d, a, 2, 23, T48);
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET4(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET4(a, b, c, d, 0, 6, T49);
+ SET4(d, a, b, c, 7, 10, T50);
+ SET4(c, d, a, b, 14, 15, T51);
+ SET4(b, c, d, a, 5, 21, T52);
+ SET4(a, b, c, d, 12, 6, T53);
+ SET4(d, a, b, c, 3, 10, T54);
+ SET4(c, d, a, b, 10, 15, T55);
+ SET4(b, c, d, a, 1, 21, T56);
+ SET4(a, b, c, d, 8, 6, T57);
+ SET4(d, a, b, c, 15, 10, T58);
+ SET4(c, d, a, b, 6, 15, T59);
+ SET4(b, c, d, a, 13, 21, T60);
+ SET4(a, b, c, d, 4, 6, T61);
+ SET4(d, a, b, c, 11, 10, T62);
+ SET4(c, d, a, b, 2, 15, T63);
+ SET4(b, c, d, a, 9, 21, T64);
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset)
+ {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/irc_mod/md5.h b/irc_mod/md5.h
new file mode 100644
index 0000000..d3fd8bb
--- /dev/null
+++ b/irc_mod/md5.h
@@ -0,0 +1,82 @@
+/*
+ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.h 2874 2006-05-16 21:38:00Z ghazan $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Removed support for non-ANSI compilers; removed
+ references to Ghostscript; clarified derivation from RFC 1321;
+ now handles byte order either statically or dynamically.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#endif /* md5_INCLUDED */
diff --git a/irc_mod/options.cpp b/irc_mod/options.cpp
new file mode 100644
index 0000000..abec632
--- /dev/null
+++ b/irc_mod/options.cpp
@@ -0,0 +1,2576 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+#include <uxtheme.h>
+#include <win2k.h>
+
+HANDLE OptionsInitHook = NULL;
+extern UINT_PTR KeepAliveTimer;
+UINT_PTR OnlineNotifTimer = 0;
+UINT_PTR OnlineNotifTimer3 = 0;
+
+
+extern PREFERENCES * prefs;
+extern char * IRCPROTONAME;
+extern char * ALTIRCPROTONAME;
+extern char * pszServerFile;
+extern char * pszIgnoreFile;
+extern char * pszPerformFile;
+extern char mirandapath[MAX_PATH];
+HWND connect_hWnd = NULL;
+HWND addserver_hWnd = NULL;
+extern HWND IgnoreWndHwnd;
+bool ServerlistModified = false;
+bool PerformlistModified = false;
+extern bool bMbotInstalled;
+extern bool bTempDisableCheck ;
+extern bool bTempForceCheck ;
+extern int iTempCheckTime ;
+extern HMODULE m_ssleay32;
+extern HANDLE hMenuServer;
+static WNDPROC OldProc;
+static WNDPROC OldListViewProc;
+
+static BOOL (WINAPI *pfnEnableThemeDialogTexture)(HANDLE, DWORD) = 0;
+
+static int GetPrefsString(const char *szSetting, char * prefstoset, int n, char * defaulttext)
+{
+ DBVARIANT dbv;
+ int rv;
+ rv = !DBGetContactSetting(NULL, IRCPROTONAME,szSetting, &dbv) && dbv.type==DBVT_ASCIIZ;
+ if(rv)
+ lstrcpyn(prefstoset, dbv.pszVal, n);
+ else
+ lstrcpyn(prefstoset, defaulttext, n);
+ if (rv)
+ DBFreeVariant(&dbv);
+ return rv;
+}
+
+static int GetSetting(const char *szSetting, DBVARIANT *dbv)
+{
+ int rv;
+ rv = !DBGetContactSetting(NULL, IRCPROTONAME,szSetting,dbv) && dbv->type==DBVT_ASCIIZ;
+ return rv;
+}
+void InitPrefs(void)
+{
+ DBVARIANT dbv;
+
+ prefs = new PREFERENCES;
+ GetPrefsString("ServerName", prefs->ServerName, 101, "");
+ GetPrefsString("PortStart", prefs->PortStart, 6, "");
+ GetPrefsString("PortEnd", prefs->PortEnd, 6, "");
+ GetPrefsString("Password", prefs->Password, 499, "");
+ CallService(MS_DB_CRYPT_DECODESTRING, 499, (LPARAM)prefs->Password);
+ if(!GetPrefsString("PNick", prefs->Nick, 30, ""))
+ {
+ GetPrefsString("Nick", prefs->Nick, 30, "");
+ if (lstrlen(prefs->Nick) > 0)
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "PNick", prefs->Nick);
+ }
+ GetPrefsString("AlernativeNick", prefs->AlternativeNick, 31, "");
+ GetPrefsString("Name", prefs->Name, 199, "");
+ GetPrefsString("UserID", prefs->UserID, 199, "Miranda");
+ GetPrefsString("IdentSystem", prefs->IdentSystem, 10, "UNIX");
+ GetPrefsString("IdentPort", prefs->IdentPort, 6, "113");
+ GetPrefsString("RetryWait", prefs->RetryWait, 4, "30");
+ GetPrefsString("RetryCount", prefs->RetryCount, 4, "10");
+ GetPrefsString("Network", prefs->Network, 31, "");
+ GetPrefsString("QuitMessage", prefs->QuitMessage, 399, STR_QUITMESSAGE);
+ GetPrefsString("UserInfo", prefs->UserInfo, 499, STR_USERINFO);
+ GetPrefsString("SpecHost", prefs->MySpecifiedHost, 499, "");
+ GetPrefsString("MyLocalHost", prefs->MyLocalHost, 49, "");
+
+ lstrcpy(prefs->MySpecifiedHostIP, "");
+
+ if (GetSetting("Alias", &dbv)) {
+ prefs->Alias = new char[lstrlen(dbv.pszVal)+1];
+ lstrcpyn(prefs->Alias, dbv.pszVal, lstrlen(dbv.pszVal)+1);
+ DBFreeVariant(&dbv);
+ }
+ else
+ {
+ prefs->Alias = new char[350];
+ lstrcpy(prefs->Alias, "/op /mode ## +ooo $1 $2 $3\r\n/dop /mode ## -ooo $1 $2 $3\r\n/voice /mode ## +vvv $1 $2 $3\r\n/dvoice /mode ## -vvv $1 $2 $3\r\n/j /join #$1 $2-\r\n/p /part ## $1-\r\n/w /whois $1\r\n/k /kick ## $1 $2-\r\n/q /query $1\r\n/logon /log on ##\r\n/logoff /log off ##\r\n/save /log buffer $1\r\n/slap /me slaps $1 around a bit with a large trout" );
+// DBFreeVariant(&dbv);
+ }
+
+ prefs->ScriptingEnabled = DBGetContactSettingByte(NULL,IRCPROTONAME, "ScriptingEnabled", 0);
+
+ prefs->PopupsEnabled = DBGetContactSettingByte(NULL,IRCPROTONAME, "PopupsEnabled", 1);
+ prefs->PopupsErrors = DBGetContactSettingByte(NULL,IRCPROTONAME, "PopupsErrors", 0);
+ prefs->PopupWhois = DBGetContactSettingByte(NULL,IRCPROTONAME, "PopupWhois", 0);
+ prefs->PopupsWhoisNoUser = DBGetContactSettingByte(NULL,IRCPROTONAME, "PopupsWhoisNoUser", 1);
+
+ prefs->VersionAuto = DBGetContactSettingByte(NULL,IRCPROTONAME, "VersionAuto", DEFAULT_VERSION_AUTO);
+ prefs->NudgeEnabled = DBGetContactSettingByte(NULL,IRCPROTONAME, "NudgeEnabled", ServiceExists(MS_NUDGE_SEND));
+ prefs->TypingEnabled = DBGetContactSettingByte(NULL,IRCPROTONAME, "TypingEnabled", DEFAULT_TYPING);
+
+ prefs->XStatusEnabled = DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusEnabled", DEFAULT_XSTATUS_ENABLED);
+ prefs->XStatusAuto = DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusAuto", DEFAULT_XSTATUS_AUTO);
+ prefs->XStatusReset = DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusReset", DEFAULT_XSTATUS_RESET);
+ prefs->XStatusAdv = DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusAdv", DEFAULT_XSTATUS_ADV);
+
+ prefs->AvatarsEnabled = DBGetContactSettingByte(NULL,IRCPROTONAME, "AvatarsEnabled", 0);
+ prefs->AvatarsAutoLoad = DBGetContactSettingByte(NULL,IRCPROTONAME, "AvatarsAutoLoad", 0);
+ prefs->AvatarsAutoLink = DBGetContactSettingByte(NULL,IRCPROTONAME, "AvatarsAutoLink", 0);
+
+ prefs->UseMemoServ = DBGetContactSettingByte(NULL,IRCPROTONAME, "UseMemoServ", 0);
+ prefs->MemoServAuto = DBGetContactSettingByte(NULL,IRCPROTONAME, "MemoServAuto", 0);
+ GetPrefsString("MemoServName", prefs->MemoServName, 199, "memoserv");
+
+ prefs->ForceVisible = DBGetContactSettingByte(NULL,IRCPROTONAME, "ForceVisible", 0);
+ prefs->DisableErrorPopups = DBGetContactSettingByte(NULL,IRCPROTONAME, "DisableErrorPopups", 0);
+ prefs->RejoinChannels = DBGetContactSettingByte(NULL,IRCPROTONAME, "RejoinChannels", 0);
+ prefs->RejoinIfKicked = DBGetContactSettingByte(NULL,IRCPROTONAME, "RejoinIfKicked", 1);
+ prefs->Ident = DBGetContactSettingByte(NULL,IRCPROTONAME, "Ident", 0);
+ prefs->IdentTimer = (int)DBGetContactSettingByte(NULL,IRCPROTONAME, "IdentTimer", 0);
+ prefs->Retry = DBGetContactSettingByte(NULL,IRCPROTONAME, "Retry", 0);
+ prefs->DisableDefaultServer = DBGetContactSettingByte(NULL,IRCPROTONAME, "DisableDefaultServer", 0);
+ prefs->HideServerWindow = DBGetContactSettingByte(NULL,IRCPROTONAME, "HideServerWindow", 1);
+ prefs->UseServer = DBGetContactSettingByte(NULL,IRCPROTONAME, "UseServer", 1);
+ prefs->JoinOnInvite = DBGetContactSettingByte(NULL,IRCPROTONAME, "JoinOnInvite", 0);
+ prefs->Perform = DBGetContactSettingByte(NULL,IRCPROTONAME, "Perform", 0);
+ prefs->ShowAddresses = DBGetContactSettingByte(NULL,IRCPROTONAME, "ShowAddresses", 0);
+ prefs->AutoOnlineNotification = DBGetContactSettingByte(NULL,IRCPROTONAME, "AutoOnlineNotification", 1);
+ prefs->Ignore = DBGetContactSettingByte(NULL,IRCPROTONAME, "Ignore", 0);;
+ prefs->IgnoreChannelDefault = DBGetContactSettingByte(NULL,IRCPROTONAME, "IgnoreChannelDefault", 0);;
+ prefs->ServerComboSelection = DBGetContactSettingDword(NULL,IRCPROTONAME, "ServerComboSelection", -1);
+ prefs->QuickComboSelection = DBGetContactSettingDword(NULL,IRCPROTONAME, "QuickComboSelection", prefs->ServerComboSelection);
+ prefs->SendKeepAlive = (int)DBGetContactSettingByte(NULL,IRCPROTONAME, "SendKeepAlive", 0);
+ prefs->ListSize.y = DBGetContactSettingDword(NULL,IRCPROTONAME, "SizeOfListBottom", 400);
+ prefs->ListSize.x = DBGetContactSettingDword(NULL,IRCPROTONAME, "SizeOfListRight", 600);
+ prefs->iSSL = DBGetContactSettingByte(NULL,IRCPROTONAME, "UseSSL", 0);
+ prefs->DCCFileEnabled = DBGetContactSettingByte(NULL,IRCPROTONAME, "EnableCtcpFile", 1);
+ prefs->DCCChatEnabled = DBGetContactSettingByte(NULL,IRCPROTONAME, "EnableCtcpChat", 1);
+ prefs->DCCChatAccept = DBGetContactSettingByte(NULL,IRCPROTONAME, "CtcpChatAccept", 1);
+ prefs->DCCChatIgnore = DBGetContactSettingByte(NULL,IRCPROTONAME, "CtcpChatIgnore", 1);
+ prefs->DCCPassive = DBGetContactSettingByte(NULL,IRCPROTONAME, "DccPassive", 0);
+ prefs->ManualHost = DBGetContactSettingByte(NULL,IRCPROTONAME, "ManualHost", 0);
+ prefs->IPFromServer = DBGetContactSettingByte(NULL,IRCPROTONAME, "IPFromServer", 0);
+ prefs->DisconnectDCCChats = DBGetContactSettingByte(NULL,IRCPROTONAME, "DisconnectDCCChats", 1);
+ prefs->OldStyleModes = DBGetContactSettingByte(NULL,IRCPROTONAME, "OldStyleModes", 0);
+ prefs->SendNotice = DBGetContactSettingByte(NULL,IRCPROTONAME, "SendNotice", 1);
+ prefs->MyHost[0] = '\0';
+ prefs->colors[0] = RGB(255,255,255);
+ prefs->colors[1] = RGB(0,0,0);
+ prefs->colors[2] = RGB(0,0,127);
+ prefs->colors[3] = RGB(0,147,0);
+ prefs->colors[4] = RGB(255,0,0);
+ prefs->colors[5] = RGB(127,0,0);
+ prefs->colors[6] = RGB(156,0,156);
+ prefs->colors[7] = RGB(252,127,0);
+ prefs->colors[8] = RGB(255,255,0);
+ prefs->colors[9] = RGB(0,252,0);
+ prefs->colors[10] = RGB(0,147,147);
+ prefs->colors[11] = RGB(0,255,255);
+ prefs->colors[12] = RGB(0,0,252);
+ prefs->colors[13] = RGB(255,0,255);
+ prefs->colors[14] = RGB(127,127,127);
+ prefs->colors[15] = RGB(210,210,210);
+ prefs->OnlineNotificationTime = DBGetContactSettingWord(NULL, IRCPROTONAME, "OnlineNotificationTime", 30);
+ prefs->OnlineNotificationLimit = DBGetContactSettingWord(NULL, IRCPROTONAME, "OnlineNotificationLimit", 50);
+ prefs->ChannelAwayNotification = DBGetContactSettingByte(NULL,IRCPROTONAME, "ChannelAwayNotification", 1);
+
+// DBFreeVariant(&dbv);
+ return;
+}
+
+// add icons to the skinning module
+void InitIcons(void)
+{
+/*
+ if(ServiceExists(MS_SKIN2_ADDICON))
+ {
+ SKINICONDESC sid = {0};
+ char szTemp[255];
+ char szFile[MAX_PATH];
+
+ sid.cx = sid.cy = 16;
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.pszSection = ALTIRCPROTONAME;
+ GetModuleFileName(g_hInstance, szFile, MAX_PATH);
+ sid.pszDefaultFile = szFile;
+
+ // add them one by one
+ sid.pszDescription = Translate("Main");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_main", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_MAIN;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Add");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_add", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_ADD;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Apply");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_go", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_GO;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Edit");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_rename", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_RENAME;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Cancel");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_delete", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_DELETE;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Ignore");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_block", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_BLOCK;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Channel list");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_list", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_LIST;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Channel manager");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_manager", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_MANAGER;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Quick connect");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_quick", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_QUICK;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Server window");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_server", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_SERVER;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Avatar");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_avatar", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_AVATAR;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Show channel");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_show", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_SHOW;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Join channel");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_join", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_JOIN;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Leave Channel");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_part", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_PART;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Question");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_whois", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_WHOIS;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Incoming DCC Chat");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_dcc", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_DCC;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.cx = sid.cy = 48;
+ sid.pszDescription = Translate("Logo (48x48)");
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_logo", IRCPROTONAME);
+ sid.pszName = szTemp;
+ sid.iDefaultIndex = -IDI_LOGO;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+}
+*/
+ char szSection[MAX_PATH + 64];
+ null_snprintf(szSection, sizeof(szSection), IRCTranslateUtf(IRCPROTONAME));
+
+ IconLibDefine(IRCTranslateUtf("Main"), szSection, "main", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_MAIN), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Add"), szSection, "add", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_ADD), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Apply"), szSection, "go", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_GO), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Edit"), szSection, "rename", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_RENAME), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Cancel"), szSection, "delete", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_DELETE), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Ignore"), szSection, "block", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_BLOCK), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Channel list"), szSection, "list", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_LIST), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Channel manager"), szSection, "manager", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_MANAGER), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Quick connect"), szSection, "quick", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_QUICK), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Server window"), szSection, "server", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_SERVER), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Avatar"), szSection, "avatar", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_AVATAR), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Show channel"), szSection, "show", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_SHOW), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Join channel"), szSection, "join", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_JOIN), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Leave Channel"), szSection, "part", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_PART), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Question"), szSection, "whois", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_WHOIS), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Incoming DCC Chat"), szSection, "dcc", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_DCC), IMAGE_ICON, 0, 0, 0));
+ IconLibDefine(IRCTranslateUtf("Logo (48x48)"), szSection, "logo", (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_LOGO), IMAGE_ICON, 0, 0, 0));
+
+ return;
+}
+
+// load icons from the skinning module if available
+HICON LoadIconEx(int iIndex, char * pszIcoLibName, int iX, int iY)
+{
+ if(ServiceExists(MS_SKIN2_GETICON))
+ {
+ char szTemp[256];
+ mir_snprintf(szTemp, sizeof(szTemp), "%s_%s", IRCPROTONAME, pszIcoLibName);
+ return (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM)szTemp);
+ }
+ else
+ return (HICON)LoadImage(g_hInstance,MAKEINTRESOURCE(iIndex),IMAGE_ICON,iX,iY,LR_SHARED);
+ return 0;
+}
+
+// Callback for the 'Add server' dialog
+BOOL CALLBACK AddServerProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ int i = SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), CB_GETCOUNT, 0, 0);
+ for (int index = 0; index <i; index++)
+ {
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), CB_GETITEMDATA, index, 0);
+ if (SendMessage(GetDlgItem(hwndDlg, IDC_ADD_COMBO), CB_FINDSTRINGEXACT, -1,(LPARAM) pData->Group) == CB_ERR)
+ SendMessage(GetDlgItem(hwndDlg, IDC_ADD_COMBO), CB_ADDSTRING, 0, (LPARAM) pData->Group);
+ }
+
+ if(m_ssleay32)
+ CheckDlgButton(hwndDlg, IDC_OFF, BST_CHECKED);
+ else
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ON), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OFF), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_AUTO), FALSE);
+ }
+
+ SetWindowText(GetDlgItem(hwndDlg, IDC_ADD_PORT), "6667");
+ SetWindowText(GetDlgItem(hwndDlg, IDC_ADD_PORT2), "6667");
+ SetFocus(GetDlgItem(hwndDlg, IDC_ADD_COMBO));
+
+ }break;
+
+
+ case WM_COMMAND:
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ switch (LOWORD(wParam))
+ {
+ case IDN_ADD_OK:
+ {
+ if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_SERVER)) && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_ADDRESS)) && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT)) && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT2)) && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_COMBO)))
+ {
+ SERVER_INFO * pData = new SERVER_INFO;
+ pData->iSSL = 0;
+ if(IsDlgButtonChecked(hwndDlg, IDC_ON))
+ pData->iSSL = 2;
+ if(IsDlgButtonChecked(hwndDlg, IDC_AUTO))
+ pData->iSSL = 1;
+ pData->Address=new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_ADDRESS))+1];
+ GetDlgItemText(hwndDlg,IDC_ADD_ADDRESS, pData->Address, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_ADDRESS))+1);
+ pData->Group=new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_COMBO))+1];
+ GetDlgItemText(hwndDlg,IDC_ADD_COMBO, pData->Group, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_COMBO))+1);
+ pData->Name=new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_SERVER))+GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_COMBO))+3];
+ lstrcpy(pData->Name, pData->Group);
+ lstrcat(pData->Name, ": ");
+ char temp[255];
+ GetDlgItemText(hwndDlg,IDC_ADD_SERVER, temp, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_SERVER))+1);
+ lstrcat(pData->Name, temp);
+ pData->PortEnd=new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT2))+1];
+ GetDlgItemText(hwndDlg,IDC_ADD_PORT2, pData->PortEnd, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT2))+1);
+ pData->PortStart=new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT))+1];
+ GetDlgItemText(hwndDlg,IDC_ADD_PORT, pData->PortStart, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT))+1);
+ int iItem = SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO),CB_ADDSTRING,0,(LPARAM) pData->Name);
+ SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO),CB_SETITEMDATA,iItem,(LPARAM) pData);
+ SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO),CB_SETCURSEL,iItem,0);
+ SendMessage(connect_hWnd, WM_COMMAND, MAKEWPARAM(IDC_SERVERCOMBO,CBN_SELCHANGE), 0);
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ if ( SendMessage(GetDlgItem(connect_hWnd, IDC_PERFORMCOMBO),CB_FINDSTRINGEXACT,-1, (LPARAM)pData->Group) == CB_ERR)
+ {
+ int m = SendMessage(GetDlgItem(connect_hWnd, IDC_PERFORMCOMBO),CB_ADDSTRING,0,(LPARAM) pData->Group);
+ SendMessage(GetDlgItem(connect_hWnd, IDC_PERFORMCOMBO),CB_SETITEMDATA,m,0);
+ }
+ ServerlistModified = true;
+ }
+ else
+ MessageBox(hwndDlg, Translate( "Please complete all fields" ), Translate( "IRC error" ), MB_OK|MB_ICONERROR);
+ }break;
+
+ case IDN_ADD_CANCEL:
+ {
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }break;
+ default:break;
+ }
+
+ }break;
+
+
+ case WM_CLOSE:
+ {
+ EnableWindow(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), true);
+ EnableWindow(GetDlgItem(connect_hWnd, IDC_ADDSERVER), true);
+ EnableWindow(GetDlgItem(connect_hWnd, IDC_EDITSERVER), true);
+ EnableWindow(GetDlgItem(connect_hWnd, IDC_DELETESERVER), true);
+ DestroyWindow(hwndDlg);
+ return(true);
+ } break;
+
+ case WM_DESTROY:
+ {
+ return (true);
+ } break;
+ default:break;
+ }
+
+ return false;
+}
+
+// Callback for the 'Edit server' dialog
+BOOL CALLBACK EditServerProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ int i = SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), CB_GETCOUNT, 0, 0);
+ for (int index = 0; index <i; index++)
+ {
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), CB_GETITEMDATA, index, 0);
+ if (SendMessage(GetDlgItem(hwndDlg, IDC_ADD_COMBO), CB_FINDSTRINGEXACT, -1,(LPARAM) pData->Group) == CB_ERR)
+ SendMessage(GetDlgItem(hwndDlg, IDC_ADD_COMBO), CB_ADDSTRING, 0, (LPARAM) pData->Group);
+ }
+ int j = SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), CB_GETITEMDATA, j, 0);
+ SetDlgItemText(hwndDlg, IDC_ADD_ADDRESS, pData->Address);
+ SetDlgItemText(hwndDlg, IDC_ADD_COMBO, pData->Group);
+ SetDlgItemText(hwndDlg, IDC_ADD_PORT, pData->PortStart);
+ SetDlgItemText(hwndDlg, IDC_ADD_PORT2, pData->PortEnd);
+ char tempchar[255];
+ strcpy (tempchar, pData->Name);
+ int temp = strchr(tempchar, ' ') -tempchar;
+ for (int index2 = temp+1; index2 < lstrlen(tempchar)+1;index2++)
+ tempchar[index2-temp-1] = tempchar[index2];
+ if(m_ssleay32)
+ {
+ if(pData->iSSL == 0)
+ CheckDlgButton(hwndDlg, IDC_OFF, BST_CHECKED);
+ if(pData->iSSL == 1)
+ CheckDlgButton(hwndDlg, IDC_AUTO, BST_CHECKED);
+ if(pData->iSSL == 2)
+ CheckDlgButton(hwndDlg, IDC_ON, BST_CHECKED);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ON), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OFF), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_AUTO), FALSE);
+
+ }
+
+
+ SetDlgItemText(hwndDlg, IDC_ADD_SERVER, tempchar);
+ SetFocus(GetDlgItem(hwndDlg, IDC_ADD_COMBO));
+
+ }break;
+
+
+ case WM_COMMAND:
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ switch (LOWORD(wParam))
+ {
+ case IDN_ADD_OK:
+ {
+ if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_SERVER)) && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_ADDRESS)) && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT)) && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT2)) && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_COMBO)))
+ {
+ int i = SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+
+ SERVER_INFO * pData1 = (SERVER_INFO *)SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), CB_GETITEMDATA, i, 0);
+ delete []pData1->Name;
+ delete []pData1->Address;
+ delete []pData1->PortStart;
+ delete []pData1->PortEnd;
+ delete []pData1->Group;
+ delete pData1;
+ SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), CB_DELETESTRING, i, 0);
+// if (i >= SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCOUNT, 0, 0))
+// i--;
+// SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_SETCURSEL, i, 0);
+// SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_SERVERCOMBO,CBN_SELCHANGE), 0);
+
+
+ SERVER_INFO * pData = new SERVER_INFO;
+ pData->iSSL = 0;
+ if(IsDlgButtonChecked(hwndDlg, IDC_ON))
+ pData->iSSL = 2;
+ if(IsDlgButtonChecked(hwndDlg, IDC_AUTO))
+ pData->iSSL = 1;
+ pData->Address=new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_ADDRESS))+1];
+ GetDlgItemText(hwndDlg,IDC_ADD_ADDRESS, pData->Address, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_ADDRESS))+1);
+ pData->Group=new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_COMBO))+1];
+ GetDlgItemText(hwndDlg,IDC_ADD_COMBO, pData->Group, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_COMBO))+1);
+ pData->Name=new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_SERVER))+GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_COMBO))+3];
+ lstrcpy(pData->Name, pData->Group);
+ lstrcat(pData->Name, ": ");
+ char temp[255];
+ GetDlgItemText(hwndDlg,IDC_ADD_SERVER, temp, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_SERVER))+1);
+ lstrcat(pData->Name, temp);
+ pData->PortEnd=new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT2))+1];
+ GetDlgItemText(hwndDlg,IDC_ADD_PORT2, pData->PortEnd, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT2))+1);
+ pData->PortStart=new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT))+1];
+ GetDlgItemText(hwndDlg,IDC_ADD_PORT, pData->PortStart, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ADD_PORT))+1);
+ int iItem = SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO),CB_ADDSTRING,0,(LPARAM) pData->Name);
+ SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO),CB_SETITEMDATA,iItem,(LPARAM) pData);
+ SendMessage(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO),CB_SETCURSEL,iItem,0);
+ SendMessage(connect_hWnd, WM_COMMAND, MAKEWPARAM(IDC_SERVERCOMBO,CBN_SELCHANGE), 0);
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ if ( SendMessage(GetDlgItem(connect_hWnd, IDC_PERFORMCOMBO),CB_FINDSTRINGEXACT,-1, (LPARAM)pData->Group) == CB_ERR)
+ {
+ int m = SendMessage(GetDlgItem(connect_hWnd, IDC_PERFORMCOMBO),CB_ADDSTRING,0,(LPARAM) pData->Group);
+ SendMessage(GetDlgItem(connect_hWnd, IDC_PERFORMCOMBO),CB_SETITEMDATA,m,0);
+ }
+ ServerlistModified = true;
+ }
+ else
+ MessageBox(hwndDlg, Translate( "Please complete all fields" ), Translate( "IRC error" ), MB_OK|MB_ICONERROR);
+ }break;
+
+ case IDN_ADD_CANCEL:
+ {
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }break;
+ default:break;
+ }
+
+ }break;
+ case WM_CLOSE:
+ {
+ EnableWindow(GetDlgItem(connect_hWnd, IDC_SERVERCOMBO), true);
+ EnableWindow(GetDlgItem(connect_hWnd, IDC_ADDSERVER), true);
+ EnableWindow(GetDlgItem(connect_hWnd, IDC_EDITSERVER), true);
+ EnableWindow(GetDlgItem(connect_hWnd, IDC_DELETESERVER), true);
+ DestroyWindow(hwndDlg);
+ return(true);
+ } break;
+
+ case WM_DESTROY:
+ {
+ return (true);
+ } break;
+ default:break;
+ }
+
+ return false;
+}
+
+static LRESULT CALLBACK EditSubclassProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+ switch(msg)
+ {
+ case WM_CHAR :
+ {
+ if (wParam == 21 || wParam == 11 || wParam == 2)
+ {
+ char w[2];
+ w[1] = '\0';
+ if (wParam == 11)
+ w[0] = 3;
+ if (wParam == 2)
+ w[0] = 2;
+ if (wParam == 21)
+ w[0] = 31;
+ SendMessage(hwndDlg, EM_REPLACESEL, false, (LPARAM) w);
+ SendMessage(hwndDlg, EM_SCROLLCARET, 0,0);
+ return 0;
+ }
+
+ } break;
+ default: break;
+
+ }
+ return CallWindowProc(OldProc, hwndDlg, msg, wParam, lParam);
+
+}
+
+// Callback for the 'CTCP preferences' dialog
+BOOL CALLBACK CtcpPrefsProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ SetDlgItemText(hwndDlg,IDC_USERINFO,prefs->UserInfo);
+
+
+
+ CheckDlgButton(hwndDlg, IDC_SLOW, DBGetContactSettingByte(NULL, IRCPROTONAME, "DCCMode", 0)==0?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_FAST, DBGetContactSettingByte(NULL, IRCPROTONAME, "DCCMode", 0)==1?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DISC, prefs->DisconnectDCCChats?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_PASSIVE, prefs->DCCPassive?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SENDNOTICE, prefs->SendNotice?BST_CHECKED:BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg, IDC_COMBO, CB_ADDSTRING, (WPARAM)0,(LPARAM) "256");
+ SendDlgItemMessage(hwndDlg, IDC_COMBO, CB_ADDSTRING, (WPARAM)0,(LPARAM) "512");
+ SendDlgItemMessage(hwndDlg, IDC_COMBO, CB_ADDSTRING, (WPARAM)0,(LPARAM) "1024");
+ SendDlgItemMessage(hwndDlg, IDC_COMBO, CB_ADDSTRING, (WPARAM)0,(LPARAM) "2048");
+ SendDlgItemMessage(hwndDlg, IDC_COMBO, CB_ADDSTRING, (WPARAM)0,(LPARAM) "4096");
+ SendDlgItemMessage(hwndDlg, IDC_COMBO, CB_ADDSTRING, (WPARAM)0,(LPARAM) "8192");
+ int j = DBGetContactSettingWord(NULL, IRCPROTONAME, "DCCPacketSize", 1024*4);
+ char szTemp[10];
+ mir_snprintf(szTemp, sizeof(szTemp), "%u", j);
+ int i = SendDlgItemMessage(hwndDlg, IDC_COMBO, CB_SELECTSTRING, (WPARAM)-1,(LPARAM) szTemp);
+ if(i== CB_ERR)
+ int i = SendDlgItemMessage(hwndDlg, IDC_COMBO, CB_SELECTSTRING, (WPARAM)-1,(LPARAM) "4096");
+
+
+ if(prefs->DCCChatAccept == 1)
+ CheckDlgButton(hwndDlg, IDC_RADIO1, BST_CHECKED);
+ if(prefs->DCCChatAccept == 2)
+ CheckDlgButton(hwndDlg, IDC_RADIO2, BST_CHECKED);
+ if(prefs->DCCChatAccept == 3)
+ CheckDlgButton(hwndDlg, IDC_RADIO3, BST_CHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_FROMSERVER, prefs->IPFromServer?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ENABLEIP, prefs->ManualHost?BST_CHECKED:BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IP), prefs->ManualHost);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FROMSERVER), !prefs->ManualHost);
+ if(prefs->ManualHost)
+ {
+ SetDlgItemText(hwndDlg,IDC_IP,prefs->MySpecifiedHost);
+ }else
+ {
+ if(prefs->IPFromServer)
+ {
+ if(lstrlen(prefs->MyHost))
+ {
+ String s = (String)Translate("<Resolved IP: ") + (String)prefs->MyHost+ (String)">";
+ SetDlgItemText(hwndDlg,IDC_IP,s.c_str());
+ }
+ else
+ SetDlgItemText(hwndDlg,IDC_IP,Translate("<Automatic>"));
+ }
+ else
+ {
+ if(lstrlen(prefs->MyLocalHost))
+ {
+ String s = (String)Translate("<Local IP: ") + (String)prefs->MyLocalHost+ (String)">";
+ SetDlgItemText(hwndDlg,IDC_IP,s.c_str());
+ }
+ else
+ SetDlgItemText(hwndDlg,IDC_IP,Translate("<Automatic>"));
+
+ }
+
+ }
+
+
+ }break;
+
+ case WM_COMMAND:
+ {
+
+ if(( LOWORD(wParam) == IDC_USERINFO
+ || LOWORD(wParam) == IDC_IP
+ || LOWORD(wParam) == IDC_COMBO && HIWORD(wParam) != CBN_SELCHANGE)
+ && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return true;
+
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0);
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ switch (LOWORD(wParam))
+ {
+ case ( IDC_FROMSERVER):
+ case ( IDC_ENABLEIP):
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IP), IsDlgButtonChecked(hwndDlg, IDC_ENABLEIP)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FROMSERVER), IsDlgButtonChecked(hwndDlg, IDC_ENABLEIP)== BST_UNCHECKED);
+
+ if(IsDlgButtonChecked(hwndDlg, IDC_ENABLEIP)== BST_CHECKED)
+ {
+ SetDlgItemText(hwndDlg,IDC_IP,prefs->MySpecifiedHost);
+ }else
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_FROMSERVER)== BST_CHECKED)
+ {
+ if(lstrlen(prefs->MyHost))
+ {
+ String s = (String)Translate("<Resolved IP: ") + (String)prefs->MyHost+ (String)">";
+ SetDlgItemText(hwndDlg,IDC_IP,s.c_str());
+ }
+ else
+ SetDlgItemText(hwndDlg,IDC_IP,Translate("<Automatic>"));
+ }
+ else
+ {
+ if(lstrlen(prefs->MyLocalHost))
+ {
+ String s = (String)Translate("<Local IP: ") + (String)prefs->MyLocalHost+ (String)">";
+ SetDlgItemText(hwndDlg,IDC_IP,s.c_str());
+ }
+ else
+ SetDlgItemText(hwndDlg,IDC_IP,Translate("<Automatic>"));
+
+ }
+
+ }
+
+ }break;
+ default:break;
+ }
+ }
+ }break;
+ case WM_NOTIFY:
+ {
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+
+ GetDlgItemText(hwndDlg,IDC_USERINFO,prefs->UserInfo, 499);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"UserInfo",prefs->UserInfo);
+
+ char szTemp[10];
+ GetWindowText(GetDlgItem(hwndDlg, IDC_COMBO), szTemp, 10);
+ DBWriteContactSettingWord(NULL,IRCPROTONAME,"DCCPacketSize", (WORD)atoi(szTemp));
+
+
+
+ prefs->DCCPassive = IsDlgButtonChecked(hwndDlg,IDC_PASSIVE)== BST_CHECKED?1:0;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"DccPassive",prefs->DCCPassive);
+
+ prefs->SendNotice = IsDlgButtonChecked(hwndDlg,IDC_SENDNOTICE)== BST_CHECKED?1:0;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"SendNotice",prefs->SendNotice);
+
+ if(IsDlgButtonChecked(hwndDlg,IDC_SLOW)== BST_CHECKED)
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"DCCMode",0);
+ else
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"DCCMode",1);
+
+ prefs->ManualHost = IsDlgButtonChecked(hwndDlg,IDC_ENABLEIP)== BST_CHECKED?1:0;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"ManualHost",prefs->ManualHost);
+
+ prefs->IPFromServer = IsDlgButtonChecked(hwndDlg,IDC_FROMSERVER)== BST_CHECKED?1:0;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"IPFromServer",prefs->IPFromServer);
+
+ prefs->DisconnectDCCChats = IsDlgButtonChecked(hwndDlg,IDC_DISC)== BST_CHECKED?1:0;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"DisconnectDCCChats",prefs->DisconnectDCCChats);
+
+ if(IsDlgButtonChecked(hwndDlg, IDC_ENABLEIP) == BST_CHECKED)
+ {
+ char szTemp[500];
+ GetDlgItemText(hwndDlg,IDC_IP,szTemp, 499);
+ lstrcpyn(prefs->MySpecifiedHost, GetWord(szTemp, 0).c_str(), 499);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"SpecHost",prefs->MySpecifiedHost);
+ if(lstrlen(prefs->MySpecifiedHost))
+ {
+ IPRESOLVE * ipr = new IPRESOLVE;
+ ipr->iType = IP_MANUAL;
+ ipr->pszAdr = prefs->MySpecifiedHost;
+ forkthread(ResolveIPThread, NULL, ipr);
+ }
+
+ }
+
+ if(IsDlgButtonChecked(hwndDlg, IDC_RADIO1) == BST_CHECKED)
+ prefs->DCCChatAccept = 1;
+ if(IsDlgButtonChecked(hwndDlg, IDC_RADIO2) == BST_CHECKED)
+ prefs->DCCChatAccept = 2;
+ if(IsDlgButtonChecked(hwndDlg, IDC_RADIO3) == BST_CHECKED)
+ prefs->DCCChatAccept = 3;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"CtcpChatAccept",prefs->DCCChatAccept);
+ }
+ default:break;
+ return TRUE;
+ }
+ }
+ }break;
+
+ default:break;
+ }
+
+ return false;
+}
+
+// Callback for the 'Advanced preferences' dialog
+BOOL CALLBACK OtherPrefsProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ OldProc = (WNDPROC)SetWindowLong(GetDlgItem(hwndDlg, IDC_ALIASEDIT), GWL_WNDPROC,(LONG)EditSubclassProc);
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_QUITMESSAGE), GWL_WNDPROC,(LONG)EditSubclassProc);
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_PERFORMEDIT), GWL_WNDPROC,(LONG)EditSubclassProc);
+
+ SendDlgItemMessage(hwndDlg,IDC_ADD,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_ADD,"add",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendDlgItemMessage(hwndDlg,IDC_DELETE,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_DELETE,"delete",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendMessage(GetDlgItem(hwndDlg,IDC_ADD), BUTTONADDTOOLTIP, (WPARAM)Translate("Click to set commands that will be performed for this event"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_DELETE), BUTTONADDTOOLTIP, (WPARAM)Translate("Click to delete the commands for this event"), 0);
+
+ SetDlgItemText(hwndDlg,IDC_ALIASEDIT,prefs->Alias);
+ SetDlgItemText(hwndDlg,IDC_QUITMESSAGE,prefs->QuitMessage);
+ CheckDlgButton(hwndDlg,IDC_PERFORM, ((prefs->Perform) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_SCRIPT, ((prefs->ScriptingEnabled) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SCRIPT), bMbotInstalled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), prefs->Perform);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PERFORMEDIT), prefs->Perform);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), prefs->Perform);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), prefs->Perform);
+ char * p1 = pszServerFile;
+ char * p2 = pszServerFile;
+ if (pszServerFile)
+ while(strchr(p2, 'n'))
+ {
+ p1 = strstr(p2, "GROUP:");
+ p1 =p1+ 6;
+ p2 = strchr(p1, '\r');
+ if (!p2)
+ p2 = strchr(p1, '\n');
+ if (!p2)
+ p2 = strchr(p1, '\0');
+
+ char * Group = new char[p2-p1+1];
+ lstrcpyn(Group, p1, p2-p1+1);
+ int i = SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Group);
+ if (i ==CB_ERR) {
+ int index = SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_ADDSTRING, 0, (LPARAM) Group);
+// SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_SETITEMDATA, index, 0);
+ }
+ delete []Group;
+
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_INSERTSTRING, 0, (LPARAM)"Event: Available" );
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_INSERTSTRING, 1, (LPARAM)"Event: Away" );
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_INSERTSTRING, 2, (LPARAM)"Event: N/A" );
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_INSERTSTRING, 3, (LPARAM)"Event: Occupied" );
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_INSERTSTRING, 4, (LPARAM)"Event: DND" );
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_INSERTSTRING, 5, (LPARAM)"Event: Free for chat" );
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_INSERTSTRING, 6, (LPARAM)"Event: On the phone" );
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_INSERTSTRING, 7, (LPARAM)"Event: Out for lunch" );
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_INSERTSTRING, 8, (LPARAM)"Event: Disconnect" );
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_INSERTSTRING, 9, (LPARAM)"ALL NETWORKS" );
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_SETITEMDATA, -1, 0);
+ p1 = pszPerformFile;
+ p2 = pszPerformFile;
+ if(pszPerformFile)
+ while(strstr(p2, "NETWORK: ")) {
+ p1 = strstr(p2, "NETWORK: ");
+ p1 = p1+9;
+ p2 = strchr(p1, '\n');
+ char * szNetwork = new char[p2-p1];
+ lstrcpyn(szNetwork, p1, p2-p1);
+ p1 = p2;
+ p1++;
+ p2 = strstr(p1, "\nNETWORK: ");
+ if (!p2)
+ p2= p1 + lstrlen(p1)-1;
+ if(p1 != p2) {
+ int index = SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_FINDSTRINGEXACT, -1, (LPARAM) szNetwork);
+ if (index != CB_ERR) {
+ PERFORM_INFO * pPref = new PERFORM_INFO;
+ pPref->Perform = new char[p2-p1];
+ lstrcpyn(pPref->Perform, p1, p2-p1);
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_SETITEMDATA, index, (LPARAM)pPref);
+ }
+ }
+ else
+ break;
+ delete [] szNetwork;
+ }
+ SendDlgItemMessage(hwndDlg, IDC_PERFORMCOMBO, CB_SETCURSEL, 0, 0);
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_PERFORMCOMBO, CBN_SELCHANGE), 0);
+ PerformlistModified = false;
+
+ }break;
+
+ case WM_COMMAND:
+ {
+
+ if(( LOWORD(wParam) == IDC_ALIASEDIT
+ || LOWORD(wParam) == IDC_PERFORMEDIT
+ || LOWORD(wParam) == IDC_QUITMESSAGE
+ || LOWORD(wParam) == IDC_PERFORMCOMBO && HIWORD(wParam) != CBN_SELCHANGE
+ )
+ && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return true;
+
+
+ if ( HIWORD(wParam) == STN_CLICKED )
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CUSTOM:
+ {
+ CallService(MS_UTILS_OPENURL,0,(LPARAM) "http://members.chello.se/matrix/index.html" );
+ }break;
+ default:break;
+ } // switch
+ }
+ if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_PERFORMCOMBO)
+ {
+
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETCURSEL, 0, 0);
+ PERFORM_INFO * pPerf = (PERFORM_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETITEMDATA, i, 0);
+ if (pPerf == 0)
+ SetDlgItemText(hwndDlg, IDC_PERFORMEDIT, "");
+ else
+ SetDlgItemText(hwndDlg, IDC_PERFORMEDIT, pPerf->Perform);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), false);
+ if ( GetWindowTextLength(GetDlgItem(hwndDlg, IDC_PERFORMEDIT)) != 0)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), true);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), false);
+ }
+ return false;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0);
+
+ if (HIWORD(wParam) == EN_CHANGE && LOWORD(wParam) == IDC_PERFORMEDIT)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), true);
+
+ if ( GetWindowTextLength(GetDlgItem(hwndDlg, IDC_PERFORMEDIT)) != 0)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), true);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), false);
+ }
+ }
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ switch (LOWORD(wParam))
+ {
+ case ( IDC_PERFORM):
+ {
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), IsDlgButtonChecked(hwndDlg, IDC_PERFORM)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PERFORMEDIT), IsDlgButtonChecked(hwndDlg, IDC_PERFORM)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), IsDlgButtonChecked(hwndDlg, IDC_PERFORM)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), IsDlgButtonChecked(hwndDlg, IDC_PERFORM)== BST_CHECKED);
+
+ }break;
+
+
+ case ( IDC_ADD):
+ {
+
+ int j = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_PERFORMEDIT));
+ char * temp = new char[j+1];
+ GetWindowText(GetDlgItem(hwndDlg, IDC_PERFORMEDIT), temp, j+1);
+
+ if(my_strstri(temp, "/away"))
+ MessageBox(NULL, Translate("The usage of /AWAY in your perform buffer is restricted\n as IRC sends this command automatically."), Translate("IRC Error"), MB_OK);
+ else
+ {
+ int i = (int) SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETCURSEL, 0, 0);
+ PERFORM_INFO * pPerf = (PERFORM_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETITEMDATA, i, 0);
+ if (pPerf != 0)
+ {
+ delete []pPerf->Perform;
+ delete pPerf;
+ }
+ pPerf = new PERFORM_INFO;
+ pPerf->Perform = new char[j+1];
+ lstrcpy(pPerf->Perform, temp);
+ SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_SETITEMDATA, i, (LPARAM) pPerf);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), false);
+
+ PerformlistModified = true;
+ }
+ delete []temp;
+
+
+ }break;
+
+ case ( IDC_DELETE):
+ {
+ int i = (int) SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETCURSEL, 0, 0);
+ PERFORM_INFO * pPerf = (PERFORM_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETITEMDATA, i, 0);
+ if (pPerf != 0)
+ {
+ delete []pPerf->Perform;
+ delete pPerf;
+ }
+ SetDlgItemText(hwndDlg, IDC_PERFORMEDIT, "");
+ SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_SETITEMDATA, i, 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), false);
+
+
+ PerformlistModified = true;
+
+ }break;
+ default:break;
+ }
+ }
+ }break;
+ case WM_DESTROY:
+ {
+ PerformlistModified = false;
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETCOUNT, 0, 0);
+ if (i != CB_ERR && i !=0)
+ {
+ for (int index = 0; index < i; index++)
+ {
+ PERFORM_INFO * pPerf = (PERFORM_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETITEMDATA, index, 0);
+ if ( (const int)pPerf != CB_ERR && pPerf != 0)
+ {
+ delete []pPerf->Perform;
+ delete pPerf;
+ }
+
+ }
+ }
+
+ } break;
+ case WM_NOTIFY:
+ {
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+
+ delete [] prefs->Alias;
+ prefs->Alias = new char[GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ALIASEDIT))+1];
+ GetDlgItemText(hwndDlg,IDC_ALIASEDIT,prefs->Alias, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ALIASEDIT))+1);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"Alias",prefs->Alias);
+
+ GetDlgItemText(hwndDlg,IDC_QUITMESSAGE,prefs->QuitMessage, 399);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"QuitMessage",prefs->QuitMessage);
+
+ prefs->Perform = IsDlgButtonChecked(hwndDlg,IDC_PERFORM)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"Perform",prefs->Perform);
+ prefs->ScriptingEnabled = IsDlgButtonChecked(hwndDlg,IDC_SCRIPT)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"ScriptingEnabled",prefs->ScriptingEnabled);
+ if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_ADD)))
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ADD, BN_CLICKED), 0);
+
+ if (PerformlistModified) {
+ PerformlistModified = false;
+ char filepath[MAX_PATH];
+ mir_snprintf(filepath, sizeof(filepath), "%s\\%s_perform.ini", mirandapath, IRCPROTONAME);
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETCOUNT, 0, 0);
+ FILE *hFile = fopen(filepath,"wb");
+ if (hFile && i != CB_ERR && i !=0)
+ {
+ for (int index = 0; index < i; index++)
+ {
+ PERFORM_INFO * pPerf = (PERFORM_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETITEMDATA, index, 0);
+ if ( (const int)pPerf != CB_ERR && pPerf != 0)
+ {
+ int k = SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETLBTEXTLEN, index, 0);
+ char * temp = new char[k+1];
+ SendMessage(GetDlgItem(hwndDlg, IDC_PERFORMCOMBO), CB_GETLBTEXT, index, (LPARAM)temp);
+ fputs("NETWORK: ", hFile);
+ fputs(temp, hFile);
+ fputs("\r\n", hFile);
+ fputs(pPerf->Perform, hFile);
+ fputs("\r\n", hFile);
+ delete []temp;
+
+ }
+
+ }
+ fclose(hFile);
+ delete [] pszPerformFile;
+ pszPerformFile = IrcLoadFile(filepath);
+
+ }
+ }
+
+ }
+ return TRUE;
+ }
+ }
+ }break;
+
+ default:break;
+ }
+
+ return false;
+}
+
+static const UINT IRCExtraAvatarsControls[] = {IDC_ENABLEAVATARS, IDC_AUTOLOADAVATARS/*,IDC_LINKAVATARS*/};
+static const UINT IRCExtraXStatusControls[] = {IDC_XSTATUSRESET,IDC_XSTATUSAUTO};
+static const UINT IRCAdvXStatusControls[] = {IDC_ADV1,IDC_ADV2,IDC_ADV3,IDC_ADV4,IDC_ADV5,IDC_ADV6};
+
+BOOL CALLBACK ExtraPrefsProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ UINT i;
+// UINT data;
+
+ switch (uMsg)
+ {
+ case WM_CHAR:
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0);
+ }break;
+
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_QUITMESSAGE), GWL_WNDPROC,(LONG)EditSubclassProc);
+ SetDlgItemText(hwndDlg,IDC_QUITMESSAGE,prefs->QuitMessage);
+
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_MEMOSERVNAME), GWL_WNDPROC,(LONG)EditSubclassProc);
+ SetDlgItemText(hwndDlg,IDC_MEMOSERVNAME,prefs->MemoServName);
+
+ CheckDlgButton(hwndDlg,IDC_VERSIONAUTO, ((prefs->VersionAuto) ? (BST_CHECKED) : (BST_UNCHECKED)));
+
+ CheckDlgButton(hwndDlg,IDC_NUDGEENABLE, ((prefs->NudgeEnabled) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NUDGEENABLE), ServiceExists(MS_NUDGE_SEND));
+
+ CheckDlgButton(hwndDlg,IDC_TYPINGENABLE, ((prefs->TypingEnabled) ? (BST_CHECKED) : (BST_UNCHECKED)));
+
+ CheckDlgButton(hwndDlg,IDC_XSTATUSENABLE, ((prefs->XStatusEnabled) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_XSTATUSRESET, ((prefs->XStatusReset) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_XSTATUSAUTO, ((prefs->XStatusAuto) ? (BST_CHECKED) : (BST_UNCHECKED)));
+
+ for(i=0;i<ADV_CNT;i++)
+ SendMessage(GetDlgItem(hwndDlg,IDC_ADV1+i),BM_SETCHECK,(i==prefs->XStatusAdv)?BST_CHECKED:BST_UNCHECKED,0L);
+
+ CheckDlgButton(hwndDlg,IDC_ENABLEAVATARS, ((prefs->AvatarsEnabled) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_AUTOLOADAVATARS, ((prefs->AvatarsAutoLoad) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_LINKAVATARS, ((prefs->AvatarsAutoLink) ? (BST_CHECKED) : (BST_UNCHECKED)));
+
+ CheckDlgButton(hwndDlg,IDC_SCRIPT, ((prefs->ScriptingEnabled) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SCRIPT), bMbotInstalled);
+
+ CheckDlgButton(hwndDlg,IDC_MEMOSERV, ((prefs->UseMemoServ) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_MEMOSERV_AUTORETRIEVE, ((prefs->MemoServAuto) ? (BST_CHECKED) : (BST_UNCHECKED)));
+
+ if(DBGetContactSettingByte(NULL,IRCPROTONAME, "Developer", 0))
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_XSTATUSENABLE), TRUE);
+ IRC_EnableMultipleControls(hwndDlg, IRCExtraXStatusControls, sizeof(IRCExtraXStatusControls)/sizeof(IRCExtraXStatusControls[0]), prefs->XStatusEnabled);
+
+ IRC_EnableMultipleControls(hwndDlg, IRCAdvXStatusControls, sizeof(IRCAdvXStatusControls)/sizeof(IRCAdvXStatusControls[0]), 1);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEAVATARS), TRUE);
+ IRC_EnableMultipleControls(hwndDlg, IRCExtraAvatarsControls, sizeof(IRCExtraAvatarsControls)/sizeof(IRCExtraAvatarsControls[0]), prefs->AvatarsEnabled);
+
+ #ifdef _DEBUG
+ EnableWindow(GetDlgItem(hwndDlg, IDC_MEMOSERV), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_MEMOSERVNAME), prefs->UseMemoServ);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_MEMOSERV_AUTORETRIEVE), TRUE);
+ #endif
+ }
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ if(( LOWORD(wParam) == IDC_QUITMESSAGE || LOWORD(wParam) == IDC_MEMOSERVNAME) && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return true;
+
+ if ( HIWORD(wParam) == STN_CLICKED )
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CUSTOM:
+ {
+ CallService(MS_UTILS_OPENURL,0,(LPARAM) "http://dev.mirandaim.ru/iron/" );
+ return true;
+ }break;
+ default:break;
+ } // switch
+ }
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_MEMOSERV:
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_MEMOSERVNAME), IsDlgButtonChecked(hwndDlg, IDC_MEMOSERV)== BST_CHECKED);
+ }break;
+
+ case IDC_XSTATUSENABLE:
+ {
+ IRC_EnableMultipleControls(hwndDlg, IRCExtraXStatusControls, sizeof(IRCExtraXStatusControls)/sizeof(IRCExtraXStatusControls[0]), IsDlgButtonChecked(hwndDlg,IDC_XSTATUSENABLE));
+ }
+ break;
+
+ case IDC_ENABLEAVATARS:
+ {
+ IRC_EnableMultipleControls(hwndDlg, IRCExtraAvatarsControls, sizeof(IRCExtraAvatarsControls)/sizeof(IRCExtraAvatarsControls[0]), IsDlgButtonChecked(hwndDlg,IDC_ENABLEAVATARS));
+ }
+ break;
+
+// case IDC_ADV8:
+// case IDC_ADV7:
+ case IDC_ADV6:
+ case IDC_ADV5:
+ case IDC_ADV4:
+ case IDC_ADV3:
+ case IDC_ADV2:
+ case IDC_ADV1:
+ {
+ for(int i=0;i<ADV_CNT;i++)
+ SendMessage(GetDlgItem(hwndDlg,IDC_ADV1+i),BM_SETCHECK,BST_UNCHECKED,0L);
+ SendMessage(GetDlgItem(hwndDlg,LOWORD(wParam)),BM_SETCHECK,BST_CHECKED,0L);
+ }
+ break;
+
+ default:break;
+ }
+ }
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0);
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ GetDlgItemText(hwndDlg,IDC_QUITMESSAGE,prefs->QuitMessage, 399);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"QuitMessage",prefs->QuitMessage);
+
+ GetDlgItemText(hwndDlg,IDC_MEMOSERVNAME,prefs->MemoServName, 29);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"MemoServName",prefs->MemoServName);
+
+ prefs->ScriptingEnabled = IsDlgButtonChecked(hwndDlg,IDC_SCRIPT)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"ScriptingEnabled",prefs->ScriptingEnabled);
+
+ prefs->VersionAuto = IsDlgButtonChecked(hwndDlg,IDC_VERSIONAUTO)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"VersionAuto",prefs->VersionAuto);
+ prefs->NudgeEnabled = IsDlgButtonChecked(hwndDlg,IDC_NUDGEENABLE)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"NudgeEnabled",prefs->NudgeEnabled);
+ prefs->TypingEnabled = IsDlgButtonChecked(hwndDlg,IDC_TYPINGENABLE)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"TypingEnabled",prefs->TypingEnabled);
+
+ prefs->XStatusEnabled = IsDlgButtonChecked(hwndDlg,IDC_XSTATUSENABLE)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"XStatusEnabled",prefs->XStatusEnabled);
+ prefs->XStatusReset = IsDlgButtonChecked(hwndDlg,IDC_XSTATUSRESET)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"XStatusReset",prefs->XStatusReset);
+ prefs->XStatusAuto = IsDlgButtonChecked(hwndDlg,IDC_XSTATUSAUTO)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"XStatusAuto",prefs->XStatusAuto);
+
+ for(i=0;i<ADV_CNT;i++)
+ if(SendMessage(GetDlgItem(hwndDlg, IDC_ADV1+i),BM_GETCHECK,0L,0L)==BST_CHECKED)
+ {
+ DBWriteContactSettingByte(NULL,IRCPROTONAME, "XStatusAdv", i);
+ break;
+ }
+
+ prefs->AvatarsEnabled = IsDlgButtonChecked(hwndDlg,IDC_ENABLEAVATARS)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"AvatarsEnabled",prefs->AvatarsEnabled);
+ prefs->AvatarsAutoLoad = IsDlgButtonChecked(hwndDlg,IDC_AUTOLOADAVATARS)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"AvatarsAutoLoad",prefs->AvatarsAutoLoad);
+ prefs->AvatarsAutoLink = IsDlgButtonChecked(hwndDlg,IDC_LINKAVATARS)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"AvatarsAutoLink",prefs->AvatarsAutoLink);
+
+ prefs->UseMemoServ = IsDlgButtonChecked(hwndDlg,IDC_MEMOSERV)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"UseMemoServ",prefs->UseMemoServ);
+ prefs->MemoServAuto = IsDlgButtonChecked(hwndDlg,IDC_MEMOSERV_AUTORETRIEVE)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"MemoServAuto",prefs->MemoServAuto);
+
+ return TRUE;
+ }
+ }
+ }
+ }break;
+
+ default:break;
+ }
+ return FALSE;
+}
+
+// Callback for the 'Connect preferences' dialog
+BOOL CALLBACK ConnectPrefsProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_CHAR:
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0);
+ }break;
+ case WM_INITDIALOG:
+ {
+
+ TranslateDialogDefault(hwndDlg);
+
+ SendDlgItemMessage(hwndDlg,IDC_ADDSERVER,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_ADD,"add",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendDlgItemMessage(hwndDlg,IDC_DELETESERVER,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_DELETE,"delete",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendDlgItemMessage(hwndDlg,IDC_EDITSERVER,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_RENAME,"rename",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendMessage(GetDlgItem(hwndDlg,IDC_ADDSERVER), BUTTONADDTOOLTIP, (WPARAM)Translate("Add a new network"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_EDITSERVER), BUTTONADDTOOLTIP, (WPARAM)Translate("Edit this network"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_DELETESERVER), BUTTONADDTOOLTIP, (WPARAM)Translate("Delete this network"), 0);
+
+
+ connect_hWnd = hwndDlg;
+
+ // Fill the servers combo box and create SERVER_INFO structures
+ char * p1 = pszServerFile;
+ char * p2 = pszServerFile;
+ if(pszServerFile)
+ while (strchr(p2, 'n'))
+ {
+ SERVER_INFO * pData = new SERVER_INFO;
+ p1 = strchr(p2, '=');
+ ++p1;
+ p2 = strstr(p1, "SERVER:");
+ pData->Name=new char[p2-p1+1];
+ lstrcpyn(pData->Name, p1, p2-p1+1);
+
+ p1 = strchr(p2, ':');
+ ++p1;
+ pData->iSSL = 0;
+ if(strstr(p1, "SSL") == p1)
+ {
+ p1 +=3;
+ if(*p1 == '1')
+ pData->iSSL = 1;
+ else if(*p1 == '2')
+ pData->iSSL = 2;
+ p1++;
+ }
+ p2 = strchr(p1, ':');
+ pData->Address=new char[p2-p1+1];
+ lstrcpyn(pData->Address, p1, p2-p1+1);
+
+ p1 = p2;
+ p1++;
+ while (*p2 !='G' && *p2 != '-')
+ p2++;
+ pData->PortStart = new char[p2-p1+1];
+ lstrcpyn(pData->PortStart, p1, p2-p1+1);
+
+ if (*p2 == 'G'){
+ pData->PortEnd = new char[p2-p1+1];
+ lstrcpy(pData->PortEnd, pData->PortStart);
+ } else {
+ p1 = p2;
+ p1++;
+ p2 = strchr(p1, 'G');
+ pData->PortEnd = new char[p2-p1+1];
+ lstrcpyn(pData->PortEnd, p1, p2-p1+1);
+ }
+
+ p1 = strchr(p2, ':');
+ p1++;
+ p2 = strchr(p1, '\r');
+ if (!p2)
+ p2 = strchr(p1, '\n');
+ if (!p2)
+ p2 = strchr(p1, '\0');
+ pData->Group = new char[p2-p1+1];
+ lstrcpyn(pData->Group, p1, p2-p1+1);
+ int iItem = SendDlgItemMessage(hwndDlg, IDC_SERVERCOMBO, CB_ADDSTRING,0,(LPARAM) pData->Name);
+ SendDlgItemMessage(hwndDlg, IDC_SERVERCOMBO, CB_SETITEMDATA, iItem,(LPARAM) pData);
+
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_SERVERCOMBO, CB_SETCURSEL, prefs->ServerComboSelection,0);
+ SetDlgItemText(hwndDlg,IDC_SERVER, prefs->ServerName);
+ SetDlgItemText(hwndDlg,IDC_PORT, prefs->PortStart);
+ SetDlgItemText(hwndDlg,IDC_PORT2, prefs->PortEnd);
+ if(m_ssleay32)
+ {
+ if(prefs->iSSL == 0)
+ SetDlgItemText(hwndDlg,IDC_SSL,Translate("Off") );
+ if(prefs->iSSL == 1)
+ SetDlgItemText(hwndDlg,IDC_SSL,Translate("Auto") );
+ if(prefs->iSSL == 2)
+ SetDlgItemText(hwndDlg,IDC_SSL,Translate("On") );
+ }
+ else
+ SetDlgItemText(hwndDlg,IDC_SSL, Translate("N/A"));
+
+
+
+ if (prefs->ServerComboSelection != -1)
+ {
+ SERVER_INFO * pData = (SERVER_INFO *)SendDlgItemMessage(hwndDlg, IDC_SERVERCOMBO, CB_GETITEMDATA, prefs->ServerComboSelection, 0);
+ if ((int)pData != CB_ERR)
+ {
+ SetDlgItemText(hwndDlg,IDC_SERVER,pData->Address);
+ SetDlgItemText(hwndDlg,IDC_PORT,pData->PortStart);
+ SetDlgItemText(hwndDlg,IDC_PORT2,pData->PortEnd);
+ }
+ }
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN1,UDM_SETRANGE,0,MAKELONG(999,20));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN1,UDM_SETPOS,0,MAKELONG(prefs->OnlineNotificationTime,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN2,UDM_SETRANGE,0,MAKELONG(200,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN2,UDM_SETPOS,0,MAKELONG(prefs->OnlineNotificationLimit,0));
+ SetDlgItemText(hwndDlg,IDC_NICK,prefs->Nick);
+ SetDlgItemText(hwndDlg,IDC_NICK2,prefs->AlternativeNick);
+ SetDlgItemText(hwndDlg,IDC_USERID,prefs->UserID);
+ SetDlgItemText(hwndDlg,IDC_NAME,prefs->Name);
+ SetDlgItemText(hwndDlg,IDC_PASS,prefs->Password);
+ SetDlgItemText(hwndDlg,IDC_IDENTSYSTEM,prefs->IdentSystem);
+ SetDlgItemText(hwndDlg,IDC_IDENTPORT,prefs->IdentPort);
+ SetDlgItemText(hwndDlg,IDC_RETRYWAIT,prefs->RetryWait);
+ SetDlgItemText(hwndDlg,IDC_RETRYCOUNT,prefs->RetryCount);
+ CheckDlgButton(hwndDlg,IDC_ADDRESS, ((prefs->ShowAddresses) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_OLDSTYLE, ((prefs->OldStyleModes) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_CHANNELAWAY, ((prefs->ChannelAwayNotification) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_ONLINENOTIF, ((prefs->AutoOnlineNotification) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ONLINETIMER), prefs->AutoOnlineNotification);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANNELAWAY), prefs->AutoOnlineNotification);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SPIN1), prefs->AutoOnlineNotification);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SPIN2), prefs->AutoOnlineNotification && prefs->ChannelAwayNotification);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), prefs->AutoOnlineNotification && prefs->ChannelAwayNotification);
+ CheckDlgButton(hwndDlg,IDC_IDENT, ((prefs->Ident) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IDENTSYSTEM), prefs->Ident);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IDENTPORT), prefs->Ident);
+ CheckDlgButton(hwndDlg,IDC_DISABLEERROR, ((prefs->DisableErrorPopups) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_FORCEVISIBLE, ((prefs->ForceVisible) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_REJOINCHANNELS, ((prefs->RejoinChannels) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_REJOINONKICK, ((prefs->RejoinIfKicked) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_RETRY, ((prefs->Retry) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RETRYWAIT), prefs->Retry);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RETRYCOUNT), prefs->Retry);
+ CheckDlgButton(hwndDlg,IDC_STARTUP, ((!prefs->DisableDefaultServer) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_KEEPALIVE, ((prefs->SendKeepAlive) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_IDENT_TIMED, ((prefs->IdentTimer) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_USESERVER, ((prefs->UseServer) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_SHOWSERVER, ((!prefs->HideServerWindow) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_AUTOJOIN, ((prefs->JoinOnInvite) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSERVER), prefs->UseServer);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), !prefs->DisableDefaultServer);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDSERVER), !prefs->DisableDefaultServer);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDITSERVER), !prefs->DisableDefaultServer);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETESERVER), !prefs->DisableDefaultServer);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SERVER), !prefs->DisableDefaultServer);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PORT), !prefs->DisableDefaultServer);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PORT2), !prefs->DisableDefaultServer);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PASS), !prefs->DisableDefaultServer);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IDENT_TIMED), prefs->Ident);
+ ServerlistModified = false;
+ } break;
+
+ case WM_COMMAND:
+ {
+ if( (LOWORD(wParam) == IDC_SERVER
+ || LOWORD(wParam) == IDC_PORT
+ || LOWORD(wParam) == IDC_PORT2
+ || LOWORD(wParam) == IDC_PASS
+ || LOWORD(wParam) == IDC_NICK
+ || LOWORD(wParam) == IDC_NICK2
+ || LOWORD(wParam) == IDC_NAME
+ || LOWORD(wParam) == IDC_USERID
+ || LOWORD(wParam) == IDC_IDENTSYSTEM
+ || LOWORD(wParam) == IDC_IDENTPORT
+ || LOWORD(wParam) == IDC_ONLINETIMER
+ || LOWORD(wParam) == IDC_LIMIT
+ || LOWORD(wParam) == IDC_RETRYWAIT
+ || LOWORD(wParam) == IDC_RETRYCOUNT
+ || LOWORD(wParam) == IDC_SSL
+ || LOWORD(wParam) == IDC_SERVERCOMBO && HIWORD(wParam) != CBN_SELCHANGE
+ )
+ && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return true;
+ if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_SERVERCOMBO)
+ {
+
+
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETITEMDATA, i, 0);
+ if (pData && (int)pData !=CB_ERR)
+ {
+ SetDlgItemText(hwndDlg,IDC_SERVER,pData->Address);
+ SetDlgItemText(hwndDlg,IDC_PORT,pData->PortStart);
+ SetDlgItemText(hwndDlg,IDC_PORT2,pData->PortEnd);
+ SetDlgItemText(hwndDlg,IDC_PASS,"");
+ if(m_ssleay32)
+ {
+ if(pData->iSSL == 0)
+ SetDlgItemText(hwndDlg,IDC_SSL,Translate("Off") );
+ if(pData->iSSL == 1)
+ SetDlgItemText(hwndDlg,IDC_SSL,Translate("Auto") );
+ if(pData->iSSL == 2)
+ SetDlgItemText(hwndDlg,IDC_SSL,Translate("On") );
+ }
+ else
+ SetDlgItemText(hwndDlg,IDC_SSL, Translate("N/A"));
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0);
+ }
+ return false;
+
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0);
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ switch (LOWORD(wParam))
+ {
+ case ( IDC_DELETESERVER):
+ {
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+ if (i != CB_ERR)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDSERVER), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDITSERVER), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETESERVER), false);
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETITEMDATA, i, 0);
+ char * temp = new char [lstrlen(pData->Name)+24];
+ wsprintf(temp,Translate( "Do you want to delete\r\n%s" ), pData->Name);
+ if (MessageBox(hwndDlg, temp, Translate( "Delete server" ), MB_YESNO|MB_ICONQUESTION) == IDYES)
+ {
+ delete []pData->Name;
+ delete []pData->Address;
+ delete []pData->PortStart;
+ delete []pData->PortEnd;
+ delete []pData->Group;
+ delete pData;
+ SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_DELETESTRING, i, 0);
+ if (i >= SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCOUNT, 0, 0))
+ i--;
+ SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_SETCURSEL, i, 0);
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_SERVERCOMBO,CBN_SELCHANGE), 0);
+ ServerlistModified = true;
+ }
+ delete []temp;
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), true);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDSERVER), true);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDITSERVER), true);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETESERVER), true);
+ }
+
+ }break;
+
+ case ( IDC_ADDSERVER):
+ {
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDSERVER), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDITSERVER), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETESERVER), false);
+ addserver_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_ADDSERVER),hwndDlg,AddServerProc);
+
+ }break;
+ case ( IDC_EDITSERVER):
+ {
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+ if (i != CB_ERR)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDSERVER), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDITSERVER), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETESERVER), false);
+ addserver_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_ADDSERVER),hwndDlg,EditServerProc);
+ SetWindowText(addserver_hWnd, Translate("Edit server"));
+ }
+
+ }break;
+ case ( IDC_STARTUP):
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDSERVER), IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDITSERVER), IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETESERVER), IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SERVER), IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PORT), IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PORT2), IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PASS), IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SSL), IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED);
+
+ }break;
+
+ case ( IDC_IDENT):
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IDENTSYSTEM), IsDlgButtonChecked(hwndDlg, IDC_IDENT)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IDENTPORT), IsDlgButtonChecked(hwndDlg, IDC_IDENT)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IDENT_TIMED), IsDlgButtonChecked(hwndDlg, IDC_IDENT)== BST_CHECKED);
+ }break;
+ case ( IDC_USESERVER):
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSERVER), IsDlgButtonChecked(hwndDlg, IDC_USESERVER)== BST_CHECKED);
+ }break;
+ case ( IDC_ONLINENOTIF):
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANNELAWAY), IsDlgButtonChecked(hwndDlg, IDC_ONLINENOTIF)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ONLINETIMER), IsDlgButtonChecked(hwndDlg, IDC_ONLINENOTIF)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SPIN1), IsDlgButtonChecked(hwndDlg, IDC_ONLINENOTIF)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SPIN2), IsDlgButtonChecked(hwndDlg, IDC_ONLINENOTIF)== BST_CHECKED && IsDlgButtonChecked(hwndDlg, IDC_CHANNELAWAY)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), IsDlgButtonChecked(hwndDlg, IDC_ONLINENOTIF)== BST_CHECKED && IsDlgButtonChecked(hwndDlg, IDC_CHANNELAWAY)== BST_CHECKED);
+
+ }break;
+ case ( IDC_CHANNELAWAY):
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SPIN2), IsDlgButtonChecked(hwndDlg, IDC_ONLINENOTIF)== BST_CHECKED && IsDlgButtonChecked(hwndDlg, IDC_CHANNELAWAY)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), IsDlgButtonChecked(hwndDlg, IDC_ONLINENOTIF)== BST_CHECKED && IsDlgButtonChecked(hwndDlg, IDC_CHANNELAWAY)== BST_CHECKED);
+
+ }break;
+
+ case ( IDC_RETRY):
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RETRYWAIT), IsDlgButtonChecked(hwndDlg, IDC_RETRY)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RETRYCOUNT), IsDlgButtonChecked(hwndDlg, IDC_RETRY)== BST_CHECKED);
+ }break;
+
+ default:break;
+ }
+ }
+ } break;
+
+ case WM_NOTIFY:
+ {
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ //Save the setting in the CONNECT dialog
+ if(IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED)
+ {
+ GetDlgItemText(hwndDlg,IDC_SERVER, prefs->ServerName, 101);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"ServerName",prefs->ServerName);
+ GetDlgItemText(hwndDlg,IDC_PORT, prefs->PortStart, 6);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"PortStart",prefs->PortStart);
+ GetDlgItemText(hwndDlg,IDC_PORT2, prefs->PortEnd, 6);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"PortEnd",prefs->PortEnd);
+ GetDlgItemText(hwndDlg,IDC_PASS, prefs->Password, 500);
+ CallService(MS_DB_CRYPT_ENCODESTRING, 499, (LPARAM)prefs->Password);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"Password",prefs->Password);
+ CallService(MS_DB_CRYPT_DECODESTRING, 499, (LPARAM)prefs->Password);
+ }
+ else
+ {
+ lstrcpy(prefs->ServerName, "");
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"ServerName",prefs->ServerName);
+ lstrcpy(prefs->PortStart, "");
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"PortStart",prefs->PortStart);
+ lstrcpy(prefs->PortEnd, "");
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"PortEnd",prefs->PortEnd);
+ lstrcpy( prefs->Password, "");
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"Password",prefs->Password);
+ }
+
+ prefs->OnlineNotificationTime = SendDlgItemMessage(hwndDlg,IDC_SPIN1,UDM_GETPOS,0,0);
+ DBWriteContactSettingWord(NULL, IRCPROTONAME, "OnlineNotificationTime", (BYTE)prefs->OnlineNotificationTime);
+
+ prefs->OnlineNotificationLimit = SendDlgItemMessage(hwndDlg,IDC_SPIN2,UDM_GETPOS,0,0);
+ DBWriteContactSettingWord(NULL, IRCPROTONAME, "OnlineNotificationLimit", (BYTE)prefs->OnlineNotificationLimit);
+
+ prefs->ChannelAwayNotification = IsDlgButtonChecked(hwndDlg, IDC_CHANNELAWAY )== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"ChannelAwayNotification",prefs->ChannelAwayNotification);
+
+ GetDlgItemText(hwndDlg,IDC_NICK, prefs->Nick, 30);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"PNick",prefs->Nick);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"Nick",prefs->Nick);
+ GetDlgItemText(hwndDlg,IDC_NICK2, prefs->AlternativeNick, 30);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"AlernativeNick",prefs->AlternativeNick);
+ GetDlgItemText(hwndDlg,IDC_USERID, prefs->UserID, 199);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"UserID",prefs->UserID);
+ GetDlgItemText(hwndDlg,IDC_NAME, prefs->Name, 199);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"Name",prefs->Name);
+ GetDlgItemText(hwndDlg,IDC_IDENTSYSTEM, prefs->IdentSystem, 10);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"IdentSystem",prefs->IdentSystem);
+ GetDlgItemText(hwndDlg,IDC_IDENTPORT, prefs->IdentPort, 6);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"IdentPort",prefs->IdentPort);
+ GetDlgItemText(hwndDlg,IDC_RETRYWAIT, prefs->RetryWait, 4);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"RetryWait",prefs->RetryWait);
+ GetDlgItemText(hwndDlg,IDC_RETRYCOUNT, prefs->RetryCount, 4);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"RetryCount",prefs->RetryCount);
+ prefs->DisableDefaultServer = !IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"DisableDefaultServer",prefs->DisableDefaultServer);
+ prefs->Ident = IsDlgButtonChecked(hwndDlg, IDC_IDENT)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"Ident",prefs->Ident);
+ prefs->IdentTimer = IsDlgButtonChecked(hwndDlg, IDC_IDENT_TIMED)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"IdentTimer",prefs->IdentTimer);
+ prefs->ForceVisible = IsDlgButtonChecked(hwndDlg, IDC_FORCEVISIBLE)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"ForceVisible",prefs->ForceVisible);
+ prefs->DisableErrorPopups = IsDlgButtonChecked(hwndDlg, IDC_DISABLEERROR)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"DisableErrorPopups",prefs->DisableErrorPopups);
+ prefs->RejoinChannels = IsDlgButtonChecked(hwndDlg, IDC_REJOINCHANNELS)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"RejoinChannels",prefs->RejoinChannels);
+ prefs->RejoinIfKicked = IsDlgButtonChecked(hwndDlg, IDC_REJOINONKICK)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"RejoinIfKicked",prefs->RejoinIfKicked);
+ prefs->Retry = IsDlgButtonChecked(hwndDlg, IDC_RETRY)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"Retry",prefs->Retry);
+ prefs->ShowAddresses = IsDlgButtonChecked(hwndDlg, IDC_ADDRESS)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"ShowAddresses",prefs->ShowAddresses);
+ prefs->OldStyleModes = IsDlgButtonChecked(hwndDlg, IDC_OLDSTYLE)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"OldStyleModes",prefs->OldStyleModes);
+
+ prefs->UseServer = IsDlgButtonChecked(hwndDlg, IDC_USESERVER )== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"UseServer",prefs->UseServer);
+
+ CLISTMENUITEM clmi;
+ memset( &clmi, 0, sizeof( clmi ));
+ clmi.cbSize = sizeof( clmi );
+ if(prefs->UseServer)
+ {
+ clmi.flags = CMIM_FLAGS;
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuServer, ( LPARAM )&clmi );
+ }
+ else
+ {
+ clmi.flags = CMIM_FLAGS|CMIF_GRAYED;
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuServer, ( LPARAM )&clmi );
+ }
+
+ prefs->JoinOnInvite = IsDlgButtonChecked(hwndDlg, IDC_AUTOJOIN )== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"JoinOnInvite",prefs->JoinOnInvite);
+ prefs->HideServerWindow = IsDlgButtonChecked(hwndDlg, IDC_SHOWSERVER )== BST_UNCHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"HideServerWindow",prefs->HideServerWindow);
+ prefs->ServerComboSelection = SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+ DBWriteContactSettingDword(NULL,IRCPROTONAME,"ServerComboSelection",prefs->ServerComboSelection);
+ prefs->SendKeepAlive = IsDlgButtonChecked(hwndDlg, IDC_KEEPALIVE )== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"SendKeepAlive",prefs->SendKeepAlive);
+ if (prefs->SendKeepAlive)
+ SetChatTimer(KeepAliveTimer, 60*1000, KeepAliveTimerProc);
+ else
+ KillChatTimer(KeepAliveTimer);
+
+ prefs->AutoOnlineNotification = IsDlgButtonChecked(hwndDlg, IDC_ONLINENOTIF )== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"AutoOnlineNotification",prefs->AutoOnlineNotification);
+ if (prefs->AutoOnlineNotification)
+ {
+ if(!bTempDisableCheck)
+ {
+ SetChatTimer(OnlineNotifTimer, 500, OnlineNotifTimerProc);
+ if(prefs->ChannelAwayNotification)
+ SetChatTimer(OnlineNotifTimer3, 1500, OnlineNotifTimerProc3);
+ }
+ }
+ else
+ {
+ if (!bTempForceCheck)
+ {
+ KillChatTimer(OnlineNotifTimer);
+ KillChatTimer(OnlineNotifTimer3);
+ }
+ }
+
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETITEMDATA, i, 0);
+ if (pData && (int)pData !=CB_ERR)
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_STARTUP)== BST_CHECKED)
+ lstrcpy(prefs->Network, pData->Group);
+ else
+ lstrcpy(prefs->Network, "");
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"Network",prefs->Network);
+ prefs->iSSL = pData->iSSL;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"UseSSL",pData->iSSL);
+ }
+
+ if (ServerlistModified) {
+ ServerlistModified = false;
+ char filepath[MAX_PATH];
+ mir_snprintf(filepath, sizeof(filepath), "%s\\%s_servers.ini", mirandapath, IRCPROTONAME);
+ FILE *hFile2 = fopen(filepath,"w");
+ if (hFile2)
+ {
+ int j = (int) SendDlgItemMessage(hwndDlg, IDC_SERVERCOMBO, CB_GETCOUNT, 0, 0);
+ if (j !=CB_ERR && j !=0){
+ for (int index2 = 0; index2 < j; index2++)
+ {
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETITEMDATA, index2, 0);
+ if (pData != NULL && (int)pData != CB_ERR)
+ {
+ char TextLine[512];
+ if(pData->iSSL > 0)
+ mir_snprintf(TextLine, sizeof(TextLine), "n%u=%sSERVER:SSL%u%s:%s-%sGROUP:%s\n", index2, pData->Name, pData->iSSL, pData->Address, pData->PortStart, pData->PortEnd, pData->Group);
+ else
+ mir_snprintf(TextLine, sizeof(TextLine), "n%u=%sSERVER:%s:%s-%sGROUP:%s\n", index2, pData->Name, pData->Address, pData->PortStart, pData->PortEnd, pData->Group);
+ fputs(TextLine, hFile2);
+
+ }
+
+ }
+ }
+ fclose(hFile2);
+ delete [] pszServerFile;
+ pszServerFile = IrcLoadFile(filepath);
+
+ }
+ }
+
+
+ }
+ return TRUE;
+ }
+ }
+ }break;
+ case WM_DESTROY:
+ {
+ ServerlistModified = false;
+ int j = (int) SendDlgItemMessage(hwndDlg, IDC_SERVERCOMBO, CB_GETCOUNT, 0, 0);
+ if (j !=CB_ERR && j !=0){
+ for (int index2 = 0; index2 < j; index2++)
+ {
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETITEMDATA, index2, 0);
+ if (pData != NULL && (int)pData != CB_ERR)
+ {
+ delete []pData->Name;
+ delete []pData->Address;
+ delete []pData->PortStart;
+ delete []pData->PortEnd;
+ delete []pData->Group;
+ delete pData;
+ }
+
+ }
+ }
+
+ } break;
+
+ default:break;
+ }
+return (false);
+}
+
+
+
+
+
+
+
+
+
+
+
+static int CALLBACK IgnoreListSort(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+ if(!IgnoreWndHwnd)
+ return 1;
+ char temp1[512];
+ char temp2[512];
+ LVITEM lvm;
+ lvm.mask = LVIF_TEXT;
+ lvm.iItem = lParam1;
+ lvm.iSubItem = lParamSort;
+ lvm.pszText = temp1;
+ lvm.cchTextMax = 511;
+ SendMessage(GetDlgItem(IgnoreWndHwnd, IDC_INFO_LISTVIEW), LVM_GETITEM, 0, (LPARAM)&lvm);
+ lvm.iItem = lParam2;
+ lvm.pszText = temp2;
+ SendMessage(GetDlgItem(IgnoreWndHwnd, IDC_INFO_LISTVIEW), LVM_GETITEM, 0, (LPARAM)&lvm);
+ if (lstrlen(temp1) !=0 && lstrlen(temp2) !=0)
+ return lstrcmpi(temp1, temp2);
+ else
+ {
+ if(lstrlen(temp1) ==0 )
+ return 1;
+ else
+ return -1;
+ }
+
+}
+static LRESULT CALLBACK ListviewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_KEYUP :
+ {
+ if( ListView_GetSelectionMark(GetDlgItem(GetParent(hwnd), IDC_LIST)) != -1)
+ {
+ EnableWindow(GetDlgItem(GetParent(hwnd), IDC_EDIT), true);
+ EnableWindow(GetDlgItem(GetParent(hwnd), IDC_DELETE), true);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(GetParent(hwnd), IDC_EDIT), false);
+ EnableWindow(GetDlgItem(GetParent(hwnd), IDC_DELETE), false);
+ }
+ if (wParam == VK_DELETE)
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_DELETE, BN_CLICKED), 0);
+
+ if (wParam == VK_SPACE)
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_EDIT, BN_CLICKED), 0);
+
+
+ }break;
+
+ default:break;
+ }
+
+ return CallWindowProc(OldListViewProc, hwnd, msg, wParam, lParam);
+
+}
+// Callback for the 'Add server' dialog
+BOOL CALLBACK AddIgnoreWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ static char szOldMask[500];
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ if(lParam == 0)
+ {
+ if(g_ircSession)
+ SetWindowText(GetDlgItem(hwndDlg, IDC_NETWORK), g_ircSession.GetInfo().sNetwork.c_str());
+ CheckDlgButton(hwndDlg, IDC_Q, BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_N, BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_I, BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_D, BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_C, BST_CHECKED);
+ lstrcpyn(szOldMask, (char *) "\0", 499);
+ }
+ else
+ lstrcpyn(szOldMask, (char *) lParam, 499);
+
+ }break;
+
+
+ case WM_COMMAND:
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ switch (LOWORD(wParam))
+ {
+ case IDN_YES:
+ {
+ char szMask[500];
+ char szNetwork[500];
+ String flags = "";
+ if(IsDlgButtonChecked(hwndDlg, IDC_Q) == BST_CHECKED)
+ flags += "q";
+ if(IsDlgButtonChecked(hwndDlg, IDC_N) == BST_CHECKED)
+ flags += "n";
+ if(IsDlgButtonChecked(hwndDlg, IDC_I) == BST_CHECKED)
+ flags += "i";
+ if(IsDlgButtonChecked(hwndDlg, IDC_D) == BST_CHECKED)
+ flags += "d";
+ if(IsDlgButtonChecked(hwndDlg, IDC_C) == BST_CHECKED)
+ flags += "c";
+ if(IsDlgButtonChecked(hwndDlg, IDC_M) == BST_CHECKED)
+ flags += "m";
+
+ GetWindowText(GetDlgItem(hwndDlg, IDC_MASK), szMask, 499);
+ GetWindowText(GetDlgItem(hwndDlg, IDC_NETWORK), szNetwork, 499);
+
+ String Mask = GetWord(szMask, 0);
+ if(Mask.length() != 0)
+ {
+ if (!strchr(Mask.c_str(), '!') && !strchr(Mask.c_str(), '@'))
+ Mask += "!*@*";
+
+ if(flags != "")
+ {
+ if(*szOldMask)
+ RemoveIgnore(szOldMask);
+ AddIgnore(Mask, flags, szNetwork);
+ }
+ }
+
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+
+ }break;
+
+ case IDN_NO:
+ {
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }break;
+ default:break;
+ }
+
+ }break;
+
+
+ case WM_CLOSE:
+ {
+ PostMessage(IgnoreWndHwnd, IRC_FIXIGNOREBUTTONS, 0, 0);
+ DestroyWindow(hwndDlg);
+ return(true);
+ } break;
+
+ default:break;
+ }
+
+ return false;
+}
+
+// Callback for the 'Connect preferences' dialog
+BOOL CALLBACK IgnorePrefsProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+
+ TranslateDialogDefault(hwndDlg);
+ OldListViewProc = (WNDPROC)SetWindowLong(GetDlgItem(hwndDlg,IDC_LIST),GWL_WNDPROC,(LONG)ListviewSubclassProc);
+
+ CheckDlgButton(hwndDlg, IDC_ENABLEIGNORE, prefs->Ignore?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_IGNOREFILE, prefs->DCCFileEnabled?BST_UNCHECKED:BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_IGNORECHAT, prefs->DCCChatEnabled?BST_UNCHECKED:BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_IGNORECHANNEL, prefs->IgnoreChannelDefault?BST_CHECKED:BST_UNCHECKED);
+ if(prefs->DCCChatIgnore == 2)
+ CheckDlgButton(hwndDlg, IDC_IGNOREUNKNOWN, BST_CHECKED);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IGNOREUNKNOWN), prefs->DCCChatEnabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LIST), prefs->Ignore);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IGNORECHANNEL), prefs->Ignore);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), prefs->Ignore);
+
+ SendDlgItemMessage(hwndDlg,IDC_ADD,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_ADD,"add",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendDlgItemMessage(hwndDlg,IDC_DELETE,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_DELETE,"delete",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendDlgItemMessage(hwndDlg,IDC_EDIT,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_RENAME,"rename",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendMessage(GetDlgItem(hwndDlg,IDC_ADD), BUTTONADDTOOLTIP, (WPARAM)Translate("Add new ignore"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_EDIT), BUTTONADDTOOLTIP, (WPARAM)Translate("Edit this ignore"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_DELETE), BUTTONADDTOOLTIP, (WPARAM)Translate("Delete this ignore"), 0);
+
+ LV_COLUMN lvC;
+ int COLUMNS_SIZES[3] ={195, 60,80};
+ char szBuffer[32];
+
+ lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvC.fmt = LVCFMT_LEFT;
+ for (int index=0;index < 3;index++)
+ {
+ lvC.iSubItem = index;
+ lvC.cx = COLUMNS_SIZES[index];
+
+ switch (index)
+ {
+ case 0: lstrcpy(szBuffer,Translate("Ignore mask")); break;
+ case 1: lstrcpy(szBuffer,"Flags"); break;
+ case 2: lstrcpy(szBuffer,Translate("Network")); break;
+ }
+ lvC.pszText = szBuffer;
+ ListView_InsertColumn(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW),index,&lvC);
+ }
+
+ ListView_SetExtendedListViewStyle(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW), LVS_EX_FULLROWSELECT);
+ PostMessage(hwndDlg, IRC_REBUILDIGNORELIST, 0, 0);
+
+
+ } break;
+
+ case IRC_UPDATEIGNORELIST:
+ {
+ int j = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_LIST));
+ if (j >0)
+ {
+ LVITEM lvm;
+ lvm.mask= LVIF_PARAM;
+ lvm.iSubItem = 0;
+ for( int i =0; i < j; i++)
+ {
+ lvm.iItem = i;
+ lvm.lParam = i;
+ ListView_SetItem(GetDlgItem(hwndDlg, IDC_LIST),&lvm);
+ }
+ }
+ } break;
+ case IRC_REBUILDIGNORELIST:
+ {
+ IgnoreWndHwnd = hwndDlg;
+
+ ListView_DeleteAllItems (GetDlgItem(hwndDlg, IDC_LIST));
+
+
+ if (pszIgnoreFile)
+ {
+ char * p1 = pszIgnoreFile;
+ char * p2 = NULL;
+ char * p3 = NULL;
+ char * pTemp = NULL;
+ while(*p1 != '\0')
+ {
+ while(*p1 == '\r' || *p1 == '\n')
+ p1++;
+ if (*p1 == '\0')
+ break;
+ p2 = strstr(p1, "\r\n");
+ if (!p2)
+ p2 = strchr(p1, '\0');
+
+ pTemp = p2;
+
+ while (pTemp > p1 && (*pTemp == '\r' || *pTemp == '\n' ||*pTemp == '\0' || *pTemp == ' '))
+ pTemp--;
+ pTemp++;
+
+ p3= new char[pTemp-p1+1];
+ lstrcpyn(p3, p1, pTemp-p1+1);
+ if(GetWord(p3, 0) != "" && GetWord(p3, 0) != "")
+ {
+ String mask = GetWord(p3, 0);
+ String flags = GetWord(p3, 1);
+ String network = GetWordAddress(p3, 2);
+ if(flags[0] == '+')
+ {
+ LVITEM lvItem;
+ HWND hListView = GetDlgItem(hwndDlg, IDC_LIST);
+ lvItem.iItem = ListView_GetItemCount(hListView);
+ lvItem.mask = LVIF_TEXT|LVIF_PARAM ;
+ lvItem.iSubItem = 0;
+ lvItem.lParam = lvItem.iItem;
+ lvItem.pszText = (char *)mask.c_str();
+ lvItem.iItem = ListView_InsertItem(hListView,&lvItem);
+
+ lvItem.mask = LVIF_TEXT;
+ lvItem.iSubItem =1;
+ lvItem.pszText = (char *)flags.c_str();
+ ListView_SetItem(hListView,&lvItem);
+
+ lvItem.mask = LVIF_TEXT;
+ lvItem.iSubItem =2;
+ lvItem.pszText = (char *)network.c_str();
+ ListView_SetItem(hListView,&lvItem);
+ }
+ }
+ delete []p3;
+ p1 = p2;
+ }
+
+ }
+
+ SendMessage(hwndDlg, IRC_UPDATEIGNORELIST, 0, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LVM_SORTITEMS, (WPARAM)0, (LPARAM)IgnoreListSort);
+ SendMessage(hwndDlg, IRC_UPDATEIGNORELIST, 0, 0);
+
+ PostMessage(hwndDlg, IRC_FIXIGNOREBUTTONS, 0, 0);
+
+
+ }break;
+ case IRC_FIXIGNOREBUTTONS:
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), true);
+ if(ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LIST)) != -1)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), true);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), true);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), false);
+
+ }
+ }break;
+
+ case WM_COMMAND:
+ {
+// if( (LOWORD(wParam) == IDC_SERVER
+// || LOWORD(wParam) == IDC_PORT
+// && HIWORD(wParam) != CBN_SELCHANGE
+// )
+// && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return true;
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED,0,0);
+
+ if ( HIWORD(wParam) == STN_CLICKED )
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CUSTOM:
+ {
+ CallService(MS_UTILS_OPENURL,0,(LPARAM) "http://members.chello.se/matrix/troubleshooting.html" );
+ }break;
+ default:break;
+ } // switch
+ }
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ switch (LOWORD(wParam))
+ {
+ case ( IDC_ENABLEIGNORE):
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IGNORECHANNEL), IsDlgButtonChecked(hwndDlg, IDC_ENABLEIGNORE) == BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LIST), IsDlgButtonChecked(hwndDlg, IDC_ENABLEIGNORE) == BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), IsDlgButtonChecked(hwndDlg, IDC_ENABLEIGNORE) == BST_CHECKED);
+
+ }break;
+ case ( IDC_IGNORECHAT):
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IGNOREUNKNOWN), IsDlgButtonChecked(hwndDlg, IDC_IGNORECHAT) == BST_UNCHECKED);
+
+ }break;
+ case ( IDC_ADD):
+ {
+ HWND hWnd = CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_ADDIGNORE), hwndDlg,AddIgnoreWndProc, 0);
+ SetWindowText(hWnd, Translate("Add Ignore"));
+ EnableWindow(GetDlgItem((hwndDlg), IDC_ADD), false);
+ EnableWindow(GetDlgItem((hwndDlg), IDC_EDIT), false);
+ EnableWindow(GetDlgItem((hwndDlg), IDC_DELETE), false);
+
+ }break;
+ case ( IDC_EDIT):
+ {
+ if(!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_ADD)))
+ break;
+ char szMask[512];
+ char szFlags[512];
+ char szNetwork[512];
+ int i = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LIST));
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LIST), i, 0, szMask, 511);
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LIST), i, 1, szFlags, 511);
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LIST), i, 2, szNetwork, 511);
+ HWND hWnd = CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_ADDIGNORE), hwndDlg,AddIgnoreWndProc, (LPARAM)&szMask);
+ SetWindowText(hWnd, Translate("Edit Ignore"));
+ if(szFlags)
+ {
+ if(strchr(szFlags, 'q'))
+ CheckDlgButton(hWnd, IDC_Q, BST_CHECKED);
+ if(strchr(szFlags, 'n'))
+ CheckDlgButton(hWnd, IDC_N, BST_CHECKED);
+ if(strchr(szFlags, 'i'))
+ CheckDlgButton(hWnd, IDC_I, BST_CHECKED);
+ if(strchr(szFlags, 'd'))
+ CheckDlgButton(hWnd, IDC_D, BST_CHECKED);
+ if(strchr(szFlags, 'c'))
+ CheckDlgButton(hWnd, IDC_C, BST_CHECKED);
+ if(strchr(szFlags, 'm'))
+ CheckDlgButton(hWnd, IDC_M, BST_CHECKED);
+ }
+ SetWindowText(GetDlgItem(hWnd, IDC_MASK), szMask);
+ SetWindowText(GetDlgItem(hWnd, IDC_NETWORK), szNetwork);
+ EnableWindow(GetDlgItem((hwndDlg), IDC_ADD), false);
+ EnableWindow(GetDlgItem((hwndDlg), IDC_EDIT), false);
+ EnableWindow(GetDlgItem((hwndDlg), IDC_DELETE), false);
+
+ }break;
+ case ( IDC_DELETE):
+ {
+ if(!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_DELETE)))
+ break;
+ char szMask[512];
+ int i = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LIST));
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LIST), i, 0, szMask, 511);
+ RemoveIgnore(szMask);
+ }break;
+
+ default:break;
+ }
+ }
+ } break;
+ case WM_NOTIFY :
+ {
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case IDC_LIST:
+ {
+ switch (((NMHDR*)lParam)->code)
+ {
+ case NM_CLICK:
+ case NM_RCLICK:
+ {
+ if(ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LIST)) != -1)
+ {
+ SendMessage(hwndDlg, IRC_FIXIGNOREBUTTONS, 0, 0);
+ }
+
+ } break;
+ case NM_DBLCLK:
+ {
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDIT, BN_CLICKED), 0);
+
+ } break;
+ case LVN_COLUMNCLICK :
+ {
+ LPNMLISTVIEW lv;
+ lv = (LPNMLISTVIEW)lParam;
+ SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LVM_SORTITEMS, (WPARAM)lv->iSubItem, (LPARAM)IgnoreListSort);
+ SendMessage(hwndDlg, IRC_UPDATEIGNORELIST, 0, 0);
+ } break;
+ default:break;
+ }
+ }
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ prefs->DCCFileEnabled = IsDlgButtonChecked(hwndDlg,IDC_IGNOREFILE)== BST_UNCHECKED?1:0;
+ prefs->DCCChatEnabled = IsDlgButtonChecked(hwndDlg,IDC_IGNORECHAT)== BST_UNCHECKED?1:0;
+ prefs->Ignore = IsDlgButtonChecked(hwndDlg,IDC_ENABLEIGNORE)== BST_CHECKED?1:0;
+ prefs->IgnoreChannelDefault = IsDlgButtonChecked(hwndDlg,IDC_IGNORECHANNEL)== BST_CHECKED?1:0;
+ prefs->DCCChatIgnore = IsDlgButtonChecked(hwndDlg, IDC_IGNOREUNKNOWN) == BST_CHECKED?2:1;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"EnableCtcpFile",prefs->DCCFileEnabled);
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"EnableCtcpChat",prefs->DCCChatEnabled);
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"Ignore",prefs->Ignore);
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"IgnoreChannelDefault",prefs->IgnoreChannelDefault);
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"CtcpChatIgnore",prefs->DCCChatIgnore);
+ }
+ default:break;
+ }
+ return TRUE;
+ }break;
+ default:break;
+ }
+ }break;
+ case WM_DESTROY:
+ {
+ int i = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_LIST));
+ String S = "";
+ for(int j = 0; j<i; j++)
+ {
+ char szItem[512];
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LIST), j, 0, szItem, 511);
+ S += szItem;
+ S += " ";
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LIST), j, 1, szItem, 511);
+ S += szItem;
+ S += " ";
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LIST), j, 2, szItem, 511);
+ S += szItem;
+ S += "\r\n";
+ }
+ char filepath[MAX_PATH];
+ mir_snprintf(filepath, sizeof(filepath), "%s\\%s_ignore.ini", mirandapath, IRCPROTONAME);
+ FILE *hFile = fopen(filepath,"wb");
+ if (hFile)
+ {
+ fputs(S.c_str(), hFile);
+ fclose(hFile);
+ }
+ if (pszIgnoreFile)
+ delete [] pszIgnoreFile;
+ pszIgnoreFile = IrcLoadFile(filepath);
+
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_LIST),GWL_WNDPROC,(LONG)OldListViewProc);
+ IgnoreWndHwnd = NULL;
+
+ } break;
+
+ default:break;
+ }
+return (false);
+}
+
+static HWND hwndConn = 0, hwndCtcp = 0, hwndOther = 0, hwndIgnore = 0, hwndExtra = 0;
+
+static void SetOptionsDlgToType(HWND hwnd, int iExpert)
+{
+ TCITEM tci;
+ RECT rcClient;
+ HWND hwndTab = GetDlgItem(hwnd, IDC_OPTIONSTAB);
+ int iPages = 0;
+
+ if(!hwndConn)
+ hwndConn = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_PREFS_CONNECT), hwnd, ConnectPrefsProc);
+
+ GetClientRect(hwnd, &rcClient);
+ TabCtrl_DeleteAllItems(hwndTab);
+
+ tci.mask = TCIF_PARAM|TCIF_TEXT;
+ tci.lParam = (LPARAM)hwndConn;
+ tci.pszText = Translate("Account");
+ TabCtrl_InsertItem(hwndTab, 0, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 26, rcClient.right-8, rcClient.bottom-29, 1);
+ iPages++;
+
+ if(!hwndCtcp)
+ hwndCtcp = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_PREFS_CTCP), hwnd, CtcpPrefsProc);
+
+ if(!hwndOther)
+ hwndOther = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_PREFS_OTHER), hwnd, OtherPrefsProc);
+
+ if(!hwndIgnore)
+ hwndIgnore = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_PREFS_IGNORE), hwnd, IgnorePrefsProc);
+
+ if(!hwndExtra)
+ hwndExtra = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_PREFS_EXTRA), hwnd, ExtraPrefsProc);
+
+ if(pfnEnableThemeDialogTexture) {
+ if(hwndConn)
+ pfnEnableThemeDialogTexture(hwndConn, ETDT_ENABLETAB);
+ if(hwndCtcp)
+ pfnEnableThemeDialogTexture(hwndCtcp, ETDT_ENABLETAB);
+ if(hwndIgnore)
+ pfnEnableThemeDialogTexture(hwndIgnore, ETDT_ENABLETAB);
+ if(hwndOther)
+ pfnEnableThemeDialogTexture(hwndOther, ETDT_ENABLETAB);
+ if(hwndExtra)
+ pfnEnableThemeDialogTexture(hwndExtra, ETDT_ENABLETAB);
+ }
+
+ ShowWindow(hwndCtcp, SW_HIDE);
+ ShowWindow(hwndOther, SW_HIDE);
+ ShowWindow(hwndIgnore, SW_HIDE);
+ ShowWindow(hwndExtra, SW_HIDE);
+ ShowWindow(hwndConn, SW_SHOW);
+
+ if(iExpert) {
+ tci.lParam = (LPARAM)hwndCtcp;
+ tci.pszText = Translate("DCC 'n CTCP");
+ TabCtrl_InsertItem(hwndTab, iPages++, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 26, rcClient.right-8, rcClient.bottom-29, 1);
+
+ tci.lParam = (LPARAM)hwndOther;
+ tci.pszText = Translate("Other");
+ TabCtrl_InsertItem(hwndTab, iPages++, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 26, rcClient.right-8, rcClient.bottom-29, 1);
+
+ tci.lParam = (LPARAM)hwndIgnore;
+ tci.pszText = Translate("Ignore");
+ TabCtrl_InsertItem(hwndTab, iPages++, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 26, rcClient.right-8, rcClient.bottom-29, 1);
+
+ tci.lParam = (LPARAM)hwndExtra;
+ tci.pszText = Translate("Advanced");
+ TabCtrl_InsertItem(hwndTab, iPages++, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 26, rcClient.right-8, rcClient.bottom-29, 1);
+ }
+ TabCtrl_SetCurSel(hwndTab, 0);
+}
+
+// handle tabbed options dialog
+static BOOL CALLBACK TabsPrefsProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int iInit = TRUE;
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ iInit = TRUE;
+ int iExpert = SendMessage(GetParent(hwnd), PSM_ISEXPERT, 0, 0);
+ SetOptionsDlgToType(hwnd, iExpert);
+ iInit = FALSE;
+ return FALSE;
+ }
+ case WM_DESTROY:
+ hwndConn = hwndCtcp = hwndOther = hwndIgnore = hwndExtra = 0;
+ break;
+ case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0);
+ if(!iInit)
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ {
+ TCITEM tci;
+ int i, count = TabCtrl_GetItemCount(GetDlgItem(hwnd, IDC_OPTIONSTAB));
+ tci.mask = TCIF_PARAM;
+ for (i=0;i<count;i++) {
+ TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB), i, &tci);
+ SendMessage((HWND)tci.lParam, WM_NOTIFY, 0, lParam);
+ } }
+ break;
+ case PSN_EXPERTCHANGED:
+ {
+ int iExpert = SendMessage(GetParent(hwnd), PSM_ISEXPERT, 0, 0);
+ SetOptionsDlgToType(hwnd, iExpert);
+ break;
+ } }
+ break;
+ case IDC_OPTIONSTAB:
+ switch (((LPNMHDR)lParam)->code) {
+ case TCN_SELCHANGING:
+ {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB), TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)), &tci);
+ ShowWindow((HWND)tci.lParam, SW_HIDE);
+ break;
+ }
+ case TCN_SELCHANGE:
+ {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB), TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)), &tci);
+ ShowWindow((HWND)tci.lParam, SW_SHOW);
+ break;
+ } }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+int InitOptionsPages(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ HMODULE hUxTheme = 0;
+
+ if(IsWinVerXPPlus()) {
+ hUxTheme = GetModuleHandle(_T("uxtheme.dll"));
+
+ if(hUxTheme)
+ pfnEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
+ }
+
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = g_hInstance;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_PREFS_MAIN);
+ odp.pszTitle = ALTIRCPROTONAME;
+ odp.pszGroup = Translate("Network");
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = TabsPrefsProc;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+ InitPopupOpts(wParam);
+
+ return 0;
+}
+
+void UnInitOptions(void)
+{
+ delete [] prefs->Alias;
+ delete prefs;
+ delete []pszServerFile;
+ delete []pszPerformFile;
+ delete []pszIgnoreFile;
+
+}
diff --git a/irc_mod/output.cpp b/irc_mod/output.cpp
new file mode 100644
index 0000000..3a1f3c2
--- /dev/null
+++ b/irc_mod/output.cpp
@@ -0,0 +1,209 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+extern PREFERENCES* prefs;
+extern char * IRCPROTONAME;
+extern bool bEcho;
+
+
+static String FormatOutput (const CIrcMessage* pmsg)
+{
+ String sMessage ="";
+
+ if (pmsg->m_bIncoming) // Is it an incoming message?
+ {
+ if (pmsg->sCommand=="WALLOPS" && pmsg->parameters.size() >0)
+ {
+ char temp[200]; *temp = '\0';
+ mir_snprintf(temp, 499, Translate( "WallOps from %s: " ), pmsg->prefix.sNick.c_str());
+ sMessage = temp;
+ for(int i=0; i < (int)pmsg->parameters.size(); i++)
+ {
+ sMessage = sMessage + pmsg->parameters[i];
+ if (i != pmsg->parameters.size()-1)
+ sMessage = sMessage + " ";
+ }
+ goto THE_END;
+ }
+
+ if (pmsg->sCommand=="301" && pmsg->parameters.size() >0)
+ {
+ char temp[500]; *temp = '\0';
+ mir_snprintf(temp, sizeof(temp), Translate( "%s is away" ), pmsg->parameters[1].c_str());
+ sMessage = temp;
+ for(int i=2; i < (int)pmsg->parameters.size(); i++)
+ {
+ sMessage = sMessage + ": " + pmsg->parameters[i];
+ if (i != pmsg->parameters.size()-1)
+ sMessage = sMessage + " ";
+ }
+ goto THE_END;
+ }
+ if (pmsg->sCommand=="INVITE" && pmsg->parameters.size() >1)
+ {
+ char temp[256]; *temp = '\0';
+ mir_snprintf(temp, 255, Translate( "%s invites you to %s" ), pmsg->prefix.sNick.c_str(), pmsg->parameters[1].c_str());
+ sMessage = temp;
+ for(int i=2; i < (int)pmsg->parameters.size(); i++)
+ {
+ sMessage = sMessage +": "+ pmsg->parameters[i];
+ if (i != pmsg->parameters.size()-1)
+ sMessage = sMessage + " ";
+ }
+ goto THE_END;
+ }
+ if ((pmsg->sCommand == "443"
+ || pmsg->sCommand == "441") && pmsg->parameters.size() > 3)
+ {
+ sMessage= pmsg->parameters[1] + (String)" " + pmsg->parameters[3] + ": " + pmsg->parameters[2].c_str();
+ goto THE_END;
+ }
+ if (pmsg->sCommand=="303") // ISON command
+ {
+ sMessage= Translate("These are online: ");
+ for(int i=1; i < (int)pmsg->parameters.size(); i++)
+ {
+ sMessage = sMessage + pmsg->parameters[i];
+ if (i != pmsg->parameters.size()-1)
+ sMessage = sMessage + ", ";
+ }
+ goto THE_END;
+ }
+ int index = StrToInt(pmsg->sCommand.c_str());
+ if ((index >400
+ || index < 500) && pmsg->parameters.size() > 2 && pmsg->sCommand[0] =='4') //all error messages
+ {
+ sMessage = pmsg->parameters[2] + (String)": " + pmsg->parameters[1].c_str();
+ goto THE_END;
+ }
+
+ }
+ else
+ {
+ if (pmsg->sCommand=="NOTICE" && pmsg->parameters.size() >1)
+ {
+ char temp[500]; *temp = '\0';
+
+ if(pmsg->parameters[1].length() >3 && pmsg->parameters[1][0] == 1 && pmsg->parameters[1][pmsg->parameters[1].length()-1] == 1 )
+ {
+// #ifdef _DEBUG
+// DBGprintf( "Event: CTCP NOTICE\n");
+// for(unsigned int i=0; i<pmsg->parameters.size(); i++)
+// DBGprintf( "value = %s\n", pmsg->parameters[i].c_str());
+// #endif
+
+ // CTCP reply
+ String tempstr = pmsg->parameters[1];
+ tempstr.erase(0,1);
+ tempstr.erase(tempstr.length()-1,1);
+ String type = GetWord(tempstr.c_str(), 0);
+// Hide channel events
+ if(lstrcmpi(type.c_str(), "version") == 0 || lstrcmpi(type.c_str(), "xstatus") == 0)
+ {
+ sMessage="";
+ goto THE_END;
+ }
+ if(lstrcmpi(type.c_str(), "ping") == 0)
+ mir_snprintf(temp, 499, Translate( "CTCP %s reply sent to %s" ), type.c_str(), pmsg->parameters[0].c_str());
+ else
+ mir_snprintf(temp, 499, Translate( "CTCP %s reply sent to %s: %s" ), type.c_str(), pmsg->parameters[0].c_str(), GetWordAddress(tempstr.c_str(), 1));
+ sMessage = temp;
+ goto THE_END;
+ }
+
+ mir_snprintf(temp, 499, Translate( "Notice to %s: " ), pmsg->parameters[0].c_str());
+ sMessage = temp;
+ for(int i=1; i < (int)pmsg->parameters.size(); i++)
+ {
+ sMessage = sMessage + pmsg->parameters[i];
+ if (i != pmsg->parameters.size()-1)
+ sMessage = sMessage + " ";
+ }
+ goto THE_END;
+ }
+
+ }
+
+// Default Message handler.
+
+ if(pmsg->m_bIncoming)
+ {
+ if (pmsg->parameters.size() <2 && pmsg->parameters.size() >0)
+ {
+ sMessage = pmsg->sCommand +" : " + pmsg->parameters[0] ;
+ return sMessage;
+ }
+ if (pmsg->parameters.size() >1)
+ for(int i=1; i < (int)pmsg->parameters.size(); i++)
+ {
+ sMessage = sMessage+pmsg->parameters[i] + " ";
+ }
+ }
+ else
+ {
+ if( pmsg->prefix.sNick.length() )
+ sMessage= pmsg->prefix.sNick + " ";
+ sMessage =sMessage + pmsg->sCommand + " ";
+ for(int i=0; i < (int)pmsg->parameters.size(); i++)
+ {
+ sMessage = sMessage + pmsg->parameters[i] + " ";
+ }
+ }
+
+THE_END:
+ return sMessage;
+}
+
+BOOL ShowMessage (const CIrcMessage* pmsg)
+{
+ String mess = FormatOutput(pmsg);
+
+ if(mess=="")
+ return false;
+
+ if(!pmsg->m_bIncoming)
+ mess = ReplaceString(mess, "%%", "%");
+
+ int iTemp = StrToInt(pmsg->sCommand.c_str());
+
+ //To active window
+ if ((iTemp >400 //all error messages
+ || iTemp <500) && pmsg->sCommand[0] =='4'
+ || pmsg->sCommand == "303" //ISON command
+ || pmsg->sCommand == "INVITE"
+ || pmsg->sCommand == "NOTICE"
+ || pmsg->sCommand == "515") //chanserv error
+ {
+ DoEvent(GC_EVENT_INFORMATION, NULL, pmsg->m_bIncoming?pmsg->prefix.sNick.c_str():g_ircSession.GetInfo().sNick.c_str(), mess.c_str(), NULL, NULL, NULL, true, pmsg->m_bIncoming?false:true);
+ return TRUE;
+ }
+
+ if (prefs->UseServer)
+ {
+ DoEvent(GC_EVENT_INFORMATION, "Network log", pmsg->m_bIncoming?pmsg->prefix.sNick.c_str():g_ircSession.GetInfo().sNick.c_str(), mess.c_str(), NULL, NULL, NULL, true, pmsg->m_bIncoming?false:true);
+ return true;
+ }
+ return false;
+
+}
+
+
+
diff --git a/irc_mod/popups.cpp b/irc_mod/popups.cpp
new file mode 100644
index 0000000..9d3966b
--- /dev/null
+++ b/irc_mod/popups.cpp
@@ -0,0 +1,274 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+
+extern PREFERENCES * prefs;
+extern char * IRCPROTONAME;
+extern char * ALTIRCPROTONAME;
+
+static BOOL bPopUpService = FALSE;
+
+void InitPopUps()
+{
+ if (ServiceExists(MS_POPUP_ADDPOPUPEX))
+ {
+ bPopUpService = TRUE;
+ }
+}
+
+static const UINT IRCPopupsControls[] = {IDC_POPUP_ERROR,IDC_POPUP_NOUSER,IDC_POPUP_WHOIS,IDC_PREVIEW,IDC_POPUP_LOG0_TIMEOUT,IDC_POPUP_LOG1_TIMEOUT,IDC_POPUP_LOG2_TIMEOUT,IDC_POPUP_LOG3_TIMEOUT};
+static const UINT IRCPopupColorControls[] = {IDC_POPUP_LOG0_TEXTCOLOR,IDC_POPUP_LOG1_TEXTCOLOR,IDC_POPUP_LOG2_TEXTCOLOR,IDC_POPUP_LOG3_TEXTCOLOR, IDC_POPUP_LOG0_BACKCOLOR,IDC_POPUP_LOG1_BACKCOLOR,IDC_POPUP_LOG2_BACKCOLOR,IDC_POPUP_LOG3_BACKCOLOR};
+
+static BOOL CALLBACK DlgProcIRCPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BYTE bEnabled;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ CheckDlgButton(hwndDlg,IDC_POPUPS_ENABLED, ((prefs->PopupsEnabled) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_POPUP_ERROR, ((prefs->PopupsErrors) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_POPUP_WHOIS, ((prefs->PopupWhois) ? (BST_CHECKED) : (BST_UNCHECKED)));
+ CheckDlgButton(hwndDlg,IDC_POPUP_NOUSER, ((prefs->PopupsWhoisNoUser) ? (BST_CHECKED) : (BST_UNCHECKED)));
+
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG0_TEXTCOLOR, CPM_SETCOLOUR, 0, IRCGetContactSettingDword(NULL,"Popups0TextColor",DEFAULT_LOG0_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG0_BACKCOLOR, CPM_SETCOLOUR, 0, IRCGetContactSettingDword(NULL,"Popups0BackColor",DEFAULT_LOG0_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG0_TIMEOUT, IRCGetContactSettingDword(NULL,"Popups0Timeout",DEFAULT_LOG0_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG1_TEXTCOLOR, CPM_SETCOLOUR, 0, IRCGetContactSettingDword(NULL,"Popups1TextColor",DEFAULT_LOG1_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG1_BACKCOLOR, CPM_SETCOLOUR, 0, IRCGetContactSettingDword(NULL,"Popups1BackColor",DEFAULT_LOG1_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG1_TIMEOUT, IRCGetContactSettingDword(NULL,"Popups1Timeout",DEFAULT_LOG1_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG2_TEXTCOLOR, CPM_SETCOLOUR, 0, IRCGetContactSettingDword(NULL,"Popups2TextColor",DEFAULT_LOG2_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG2_BACKCOLOR, CPM_SETCOLOUR, 0, IRCGetContactSettingDword(NULL,"Popups2BackColor",DEFAULT_LOG2_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG2_TIMEOUT, IRCGetContactSettingDword(NULL,"Popups2Timeout",DEFAULT_LOG2_TIMEOUT),FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG3_TEXTCOLOR, CPM_SETCOLOUR, 0, IRCGetContactSettingDword(NULL,"Popups3TextColor",DEFAULT_LOG3_TEXT_COLORS));
+ SendDlgItemMessage(hwndDlg, IDC_POPUP_LOG3_BACKCOLOR, CPM_SETCOLOUR, 0, IRCGetContactSettingDword(NULL,"Popups3BackColor",DEFAULT_LOG3_BACK_COLORS));
+ SetDlgItemInt(hwndDlg, IDC_POPUP_LOG3_TIMEOUT, IRCGetContactSettingDword(NULL,"Popups3Timeout",DEFAULT_LOG3_TIMEOUT),FALSE);
+
+ bEnabled = IRCGetContactSettingByte(NULL,"PopupsEnabled",DEFAULT_POPUPS_ENABLED);
+ CheckDlgButton(hwndDlg, IDC_POPUPS_ENABLED, bEnabled);
+ IRC_EnableMultipleControls(hwndDlg, IRCPopupsControls, sizeof(IRCPopupsControls)/sizeof(IRCPopupsControls[0]), bEnabled);
+ IRC_EnableMultipleControls(hwndDlg, IRCPopupColorControls, sizeof(IRCPopupColorControls)/sizeof(IRCPopupColorControls[0]), bEnabled);
+
+ } break;
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_PREVIEW:
+ {
+ ShowPopUpMsg(NULL, "Popup Title", "Sample Note", LOG_NOTE);
+ ShowPopUpMsg(NULL, "Popup Title", "Sample Warning", LOG_WARNING);
+ ShowPopUpMsg(NULL, "Popup Title", "Sample Error", LOG_ERROR);
+// ShowPopUpMsg(NULL, "Popup Title", "Sample Fatal", LOG_FATAL);
+ return TRUE;
+ }
+ break;
+
+ case IDC_POPUPS_ENABLED:
+ {
+ bEnabled = IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED);
+ IRC_EnableMultipleControls(hwndDlg, IRCPopupsControls, sizeof(IRCPopupsControls)/sizeof(IRCPopupsControls[0]), bEnabled);
+ IRC_EnableMultipleControls(hwndDlg, IRCPopupColorControls, sizeof(IRCPopupColorControls)/sizeof(IRCPopupColorControls[0]), bEnabled & IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED));
+ }
+ break;
+
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ prefs->PopupsEnabled = IsDlgButtonChecked(hwndDlg,IDC_POPUPS_ENABLED)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"PopupsEnabled",prefs->PopupsEnabled);
+ prefs->PopupsErrors = IsDlgButtonChecked(hwndDlg,IDC_POPUP_ERROR)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"PopupsErrors",prefs->PopupsErrors);
+ prefs->PopupWhois = IsDlgButtonChecked(hwndDlg,IDC_POPUP_WHOIS)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"PopupWhois",prefs->PopupWhois);
+ prefs->PopupsWhoisNoUser = IsDlgButtonChecked(hwndDlg,IDC_POPUP_NOUSER)== BST_CHECKED;
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"PopupsWhoisNoUser",prefs->PopupsWhoisNoUser);
+
+ IRCWriteContactSettingDword(NULL,"Popups0TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG0_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ IRCWriteContactSettingDword(NULL,"Popups0BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG0_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ IRCWriteContactSettingDword(NULL,"Popups0Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG0_TIMEOUT, NULL, FALSE));
+ IRCWriteContactSettingDword(NULL,"Popups1TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG1_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ IRCWriteContactSettingDword(NULL,"Popups1BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG1_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ IRCWriteContactSettingDword(NULL,"Popups1Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG1_TIMEOUT, NULL, FALSE));
+ IRCWriteContactSettingDword(NULL,"Popups2TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG2_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ IRCWriteContactSettingDword(NULL,"Popups2BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG2_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ IRCWriteContactSettingDword(NULL,"Popups2Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG2_TIMEOUT, NULL, FALSE));
+ IRCWriteContactSettingDword(NULL,"Popups3TextColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG3_TEXTCOLOR,CPM_GETCOLOUR,0,0));
+ IRCWriteContactSettingDword(NULL,"Popups3BackColor",SendDlgItemMessage(hwndDlg,IDC_POPUP_LOG3_BACKCOLOR,CPM_GETCOLOUR,0,0));
+ IRCWriteContactSettingDword(NULL,"Popups3Timeout",GetDlgItemInt(hwndDlg, IDC_POPUP_LOG3_TIMEOUT, NULL, FALSE));
+
+ return TRUE;
+ }
+ }
+ }
+ }break;
+
+ default:break;
+
+ }
+ return FALSE;
+}
+
+void InitPopupOpts(WPARAM wParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+
+ if (bPopUpService)
+ {
+/*
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = g_hInstance;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_POPUPS);
+ odp.groupPosition = 900000000;
+ odp.pfnDlgProc = DlgProcIRCPopupOpts;
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.nIDBottomSimpleControl = 0;
+ AddOptionsPageUtf(&odp, wParam, "Popups", ALTIRCPROTONAME);
+*/
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = g_hInstance;
+ #ifdef _UNICODE
+ odp.pszTemplate = (char *)MAKEINTRESOURCE(IDD_PREFS_POPUPS);
+ #else
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_PREFS_POPUPS);
+ #endif
+
+ odp.pszTitle = ALTIRCPROTONAME;
+ odp.pszGroup = Translate("Popups");
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = DlgProcIRCPopupOpts;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+ }
+}
+
+int ShowPopUpMsg(HANDLE hContact, const char* szTitle, const char* szMsg, BYTE bType)
+{
+ if (bPopUpService && IRCGetContactSettingByte(NULL, "PopupsEnabled", DEFAULT_POPUPS_ENABLED))
+ {
+ POPUPDATAEX ppd = {0};
+ POPUPDATAW ppdw = {0};
+ LPCTSTR rsIcon;
+ HINSTANCE hIcons = NULL;
+ char szPrefix[32], szSetting[32];
+
+ strcpy(szPrefix, "Popups");
+ ppd.iSeconds = 0;
+
+ hIcons = g_hInstance;
+
+ switch(bType)
+ {
+ case LOG_NOTE:
+ rsIcon = MAKEINTRESOURCE(IDI_ICON_INFORMATION);
+ ppd.colorBack = DEFAULT_LOG0_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG0_TEXT_COLORS;
+ strcat(szPrefix, "0");
+ break;
+
+ case LOG_WARNING:
+ rsIcon = MAKEINTRESOURCE(IDI_ICON_WARNING);
+ ppd.colorBack = DEFAULT_LOG1_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG1_TEXT_COLORS;
+ strcat(szPrefix, "1");
+ break;
+
+ case LOG_ERROR:
+ rsIcon = MAKEINTRESOURCE(IDI_ICON_ERROR);
+ ppd.colorBack = DEFAULT_LOG2_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG2_TEXT_COLORS;
+ strcat(szPrefix, "2");
+ break;
+
+ case LOG_FATAL:
+ rsIcon = MAKEINTRESOURCE(IDI_ICON_FATAL);
+ ppd.colorBack = DEFAULT_LOG3_BACK_COLORS;
+ ppd.colorText = DEFAULT_LOG3_TEXT_COLORS;
+ strcat(szPrefix, "3");
+ break;
+
+ default:
+ return -1;
+ }
+
+ ppd.lchIcon = (HICON)LoadImage(hIcons, rsIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ strcpy(szSetting, szPrefix);
+ strcat(szSetting, "TextColor");
+ ppd.colorText = IRCGetContactSettingDword(NULL, szSetting, ppd.colorText);
+ strcpy(szSetting, szPrefix);
+ strcat(szSetting, "BackColor");
+ ppd.colorBack = IRCGetContactSettingDword(NULL, szSetting, ppd.colorBack);
+ strcpy(szSetting, szPrefix);
+ strcat(szSetting, "Timeout");
+ ppd.iSeconds = IRCGetContactSettingDword(NULL, szSetting, ppd.iSeconds);
+
+ if (ServiceExists(MS_POPUP_ADDPOPUPW))
+ { // call unicode popup module
+ wchar_t *tmp;
+ char str[MAX_SECONDLINE];
+
+ tmp = make_unicode_string((const unsigned char*)IRCTranslateUtfStatic(szTitle, str));
+ memmove(ppdw.lpwzContactName, tmp, wcslen(tmp)*sizeof(wchar_t));
+ SAFE_FREE((void **)&tmp);
+ tmp = make_unicode_string((const unsigned char*)IRCTranslateUtfStatic(szMsg, str));
+ memmove(ppdw.lpwzText, tmp, wcslen(tmp)*sizeof(wchar_t));
+ SAFE_FREE((void **)&tmp);
+ ppdw.lchContact = hContact;
+ ppdw.lchIcon = ppd.lchIcon;
+ ppdw.colorBack = ppd.colorBack;
+ ppdw.colorText = ppd.colorText;
+ ppdw.PluginWindowProc = NULL;
+ ppdw.PluginData = NULL;
+ ppdw.iSeconds = ppd.iSeconds;
+
+ return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&ppdw, 0);
+ }
+ else
+ {
+ char str[MAX_SECONDLINE];
+
+ utf8_decode_static(IRCTranslateUtfStatic(szTitle, str), ppd.lpzContactName, MAX_CONTACTNAME);
+ utf8_decode_static(IRCTranslateUtfStatic(szMsg, str), ppd.lpzText, MAX_SECONDLINE);
+ ppd.lchContact = hContact;
+ ppd.PluginWindowProc = NULL;
+ ppd.PluginData = NULL;
+
+ return CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+ }
+ }
+ return -1; // Failure
+} \ No newline at end of file
diff --git a/irc_mod/popups.h b/irc_mod/popups.h
new file mode 100644
index 0000000..148e8ba
--- /dev/null
+++ b/irc_mod/popups.h
@@ -0,0 +1,11 @@
+#ifndef __IRC_POPUPS_H
+#define __IRC_POPUPS_H
+
+#define POPTYPE_SPAM 254 // this is for spambots
+
+void InitPopUps();
+void InitPopupOpts(WPARAM wParam);
+
+int ShowPopUpMsg(HANDLE hContact, const char* szTitle, const char* szMsg, BYTE bType);
+
+#endif /* __IRC_POPUPS_H */
diff --git a/irc_mod/resource.h b/irc_mod/resource.h
new file mode 100644
index 0000000..4da2217
--- /dev/null
+++ b/irc_mod/resource.h
@@ -0,0 +1,295 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by IRC.rc
+//
+#define ID_INFO_QUERY 3
+#define IDS_IDENTIFY 102
+#define IDD_PREFS_MAIN 110
+#define IDD_PREFS_MAIN1 111
+#define IDD_PREFS_CONNECT 112
+#define IDD_PREFS_CTCP 113
+#define IDD_PREFS_IGNORE 114
+#define IDD_PREFS_POPUPS 115
+#define IDD_PREFS_EXTRA 116
+#define IDD_PREFS_OTHER 117
+#define IDD_INFO 120
+#define IDD_NICK 121
+#define IDD_ADDSERVER 122
+#define IDD_LIST 123
+#define IDR_MENU 124
+#define IDD_QUICKCONN 125
+#define IDD_USERINFO 126
+#define IDD_CHANMANAGER 127
+#define IDD_QUESTION 128
+#define IDD_INIT 129
+#define IDD_MESSAGEBOX 130
+#define IDD_ADDIGNORE 131
+#define IDI_MAIN 136
+#define IDD_SETXSTATUS 150
+#define IDC_OPTIONSTAB 160
+#define IDI_ADD 175
+#define IDI_BLOCK 176
+#define IDI_DELETE 177
+#define IDI_WHOIS 179
+#define IDI_LIST 181
+#define IDI_MANAGER 182
+#define IDI_QUICK 184
+#define IDI_GO 185
+#define IDI_SHOW 186
+#define IDI_LOGO 187
+#define IDI_RENAME 188
+#define IDI_SERVER 189
+#define IDI_DCC 196
+#define IDI_PART 197
+#define IDI_JOIN 198
+#define IDI_ICON_INFORMATION 199
+#define IDI_XSTATUS1 201
+#define IDI_XSTATUS2 202
+#define IDI_XSTATUS3 203
+#define IDI_XSTATUS4 204
+#define IDI_XSTATUS5 205
+#define IDI_XSTATUS6 206
+#define IDI_XSTATUS7 207
+#define IDI_XSTATUS8 208
+#define IDI_XSTATUS9 209
+#define IDI_XSTATUS10 210
+#define IDI_XSTATUS11 211
+#define IDI_XSTATUS12 212
+#define IDI_XSTATUS13 213
+#define IDI_XSTATUS14 214
+#define IDI_XSTATUS15 215
+#define IDI_XSTATUS16 216
+#define IDI_XSTATUS17 217
+#define IDI_XSTATUS18 218
+#define IDI_XSTATUS19 219
+#define IDI_XSTATUS20 220
+#define IDI_XSTATUS21 221
+#define IDI_XSTATUS22 222
+#define IDI_XSTATUS23 223
+#define IDI_XSTATUS24 224
+#define IDI_XSTATUS25 225
+#define IDI_XSTATUS26 226
+#define IDI_XSTATUS27 227
+#define IDI_XSTATUS28 228
+#define IDI_XSTATUS29 229
+#define IDI_XSTATUS30 230
+#define IDI_XSTATUS31 231
+#define IDI_XSTATUS32 232
+#define IDI_ICON_ERROR 300
+#define IDI_ICON_FATAL 301
+#define IDI_ICON_WARNING 302
+#define IDI_AVATAR 303
+#define IDC_ENICK 1000
+#define IDC_USERID 1001
+#define IDC_INFO_NAME 1001
+#define IDC_NICK 1002
+#define IDC_LIST 1002
+#define IDC_INFO_AUTH 1002
+#define IDC_INFO_LISTVIEW 1002
+#define IDC_PORT 1003
+#define IDC_INFO_CHANNELS 1003
+#define IDC_NAME 1004
+#define IDC_INFO_ADDRESS 1004
+#define IDC_PASS 1005
+#define IDC_INFO_SERVER 1005
+#define IDC_SERVER 1006
+#define IDC_INFO_ID 1006
+#define IDC_PERFORMEDIT 1007
+#define IDC_PORT2 1008
+#define IDC_INFO_AWAY2 1008
+#define IDC_NICK2 1009
+#define IDC_REPLY 1009
+#define IDC_SSL 1010
+#define IDC_INFO_OTHER 1011
+#define IDC_EDIT 1012
+#define IDC_RETRYCOUNT 1013
+#define IDC_INFO_NICK 1013
+#define IDC_EDIT2 1013
+#define IDC_XTITLE 1014
+#define IDC_XMSG 1015
+#define ID_INFO_GO 1017
+#define IDNOK 1019
+#define IDNCANCEL 1020
+#define IDC_SERVERCOMBO 1022
+#define IDC_IDENT 1023
+#define IDC_IDENT_TIMED 1024
+#define IDC_RETRY 1029
+#define IDC_ADDSERVER 1031
+#define IDC_EDITSERVER 1032
+#define IDC_RETRYWAIT 1035
+#define IDC_IDENTSYSTEM 1036
+#define IDC_IDENTPORT 1037
+#define IDC_ONLINETIMER 1038
+#define IDC_FORCEVISIBLE 1039
+#define IDC_REJOINCHANNELS 1041
+#define IDC_REJOINONKICK 1042
+#define IDC_PERFORM 1043
+#define IDC_PERFORMCOMBO 1044
+#define IDC_DISABLEERROR 1044
+#define IDC_KEEPALIVE 1045
+#define IDC_ENABLEIP 1045
+#define IDC_ONLINENOTIF 1046
+#define IDC_CHANNELAWAY 1047
+#define IDC_USESERVER 1048
+#define IDC_SHOWSERVER 1049
+#define IDC_ADDRESS 1050
+#define IDC_AUTOJOIN 1051
+#define IDC_OLDSTYLE 1052
+#define IDC_ADD 1090
+#define IDC_DELETE 1091
+#define IDC_ALIASEDIT 1094
+#define IDC_REMOVE 1094
+#define IDC_APPLYTOPIC 1095
+#define IDC_APPLYMODES 1096
+#define IDC_DELETESERVER 1097
+#define IDC_ADD_COMBO 1100
+#define IDC_ADD_SERVER 1101
+#define IDC_ADD_ADDRESS 1102
+#define IDC_ADD_PORT 1103
+#define IDC_ADD_PORT2 1104
+#define IDN_ADD_OK 1105
+#define IDN_ADD_CANCEL 1106
+#define IDC_CLOSE 1108
+#define IDC_JOIN 1109
+#define ID_INFO_OK 1110
+#define IDC_STARTUP 1133
+#define IDC_TEXT 1134
+#define IDC_DEFAULT 1139
+#define IDC_WILDCARD 1140
+#define IDC_USER 1141
+#define IDC_HOST 1142
+#define IDC_BUTTON 1143
+#define IDC_BUTTON2 1144
+#define IDC_CHECK1 1147
+#define IDC_CHECK2 1148
+#define IDC_CHECK3 1149
+#define IDC_CHECK4 1150
+#define IDC_CHECK5 1151
+#define IDC_CHECK6 1152
+#define IDC_CHECK7 1153
+#define IDC_CHECK8 1154
+#define IDC_KEY 1159
+#define IDC_LIMIT 1160
+#define IDC_TOPIC 1161
+#define IDC_RADIO1 1170
+#define IDC_RADIO2 1171
+#define IDC_RADIO3 1172
+#define IDC_HIDDENEDIT 1175
+#define IDC_NOTOP 1176
+#define IDC_WHITERECT 1179
+#define IDC_RADIO4 1179
+#define IDC_LOGO 1180
+#define IDC_RADIO5 1180
+#define IDC_CAPTION 1181
+#define IDC_RADIO6 1181
+#define IDC_RADIO7 1182
+#define IDC_RADIO8 1183
+#define IDC_OFF 1184
+#define IDC_AUTO 1185
+#define IDC_ON 1186
+#define IDC_QUITMESSAGE 1187
+#define IDC_MEMOSERVNAME 1188
+#define IDC_USERINFO 1189
+#define IDC_PING 1190
+#define IDC_IP 1190
+#define IDC_VERSION 1191
+#define IDN_YES 1191
+#define IDC_PASSIVE 1191
+#define IDC_TIME 1192
+#define IDN_NO 1192
+#define IDC_PASSIVE2 1192
+#define IDC_SENDNOTICE 1192
+#define IDC_SLOW 1193
+#define IDC_FAST 1194
+#define IDC_COMBO 1196
+#define IDC_DISC 1197
+#define IDC_FROMSERVER 1201
+#define IDC_SCRIPT 1202
+#define IDC_MASK 1204
+#define IDC_Q 1205
+#define IDC_M 1206
+#define IDC_N 1207
+#define IDC_I 1208
+#define IDC_C 1209
+#define IDC_D 1210
+#define IDC_NETWORK 1211
+#define IDC_IGNORECHANNEL 1212
+#define IDC_ENABLEIGNORE 1213
+#define IDC_IGNOREFILE 1214
+#define IDC_IGNORECHAT 1215
+#define IDC_IGNOREUNKNOWN 1216
+#define IDC_CUSTOM 1218
+#define IDC_SPIN1 1219
+#define IDC_SPIN2 1220
+#define IDC_MEMOSERV 1221
+#define IDC_MEMOSERV_AUTORETRIEVE 1224
+#define IDC_PREVIEW 1239
+#define IDC_POPUP_LOG0_TIMEOUT 1240
+#define IDC_XSTATUSENABLE 1241
+#define IDC_XSTATUSRESET 1242
+#define IDC_XSTATUSAUTO 1243
+#define IDC_NUDGEENABLE 1244
+#define IDC_RETRXSTATUS 1244
+#define IDC_TYPINGENABLE 1245
+#define IDC_ENABLEAVATARS 1246
+#define IDC_AUTOLOADAVATARS 1247
+#define IDC_VERSIONAUTO 1249
+#define IDC_POPUPS_ENABLED 1252
+#define IDC_POPUP_NOUSER 1253
+#define IDC_POPUP_ERROR 1254
+#define IDC_POPUP_LOG0_BACKCOLOR 1255
+#define IDC_POPUP_LOG0_TEXTCOLOR 1256
+#define IDC_POPUP_LOG1_BACKCOLOR 1257
+#define IDC_POPUP_LOG1_TEXTCOLOR 1258
+#define IDC_POPUP_LOG2_BACKCOLOR 1259
+#define IDC_POPUP_LOG2_TEXTCOLOR 1260
+#define IDC_POPUP_LOG3_BACKCOLOR 1261
+#define IDC_POPUP_LOG3_TEXTCOLOR 1262
+#define IDC_POPUP_LOG2_TIMEOUT 1263
+#define IDC_POPUP_LOG3_TIMEOUT 1264
+#define IDC_POPUP_LOG1_TIMEOUT 1265
+#define IDC_POPUP_WHOIS 1266
+#define IDC_LINKAVATARS 1267
+#define IDC_ADV1 2001
+#define IDC_ADV2 2002
+#define IDC_ADV3 2003
+#define IDC_ADV4 2004
+#define IDC_ADV5 2005
+#define IDC_ADV6 2006
+#define ID_MENU1_OP 40013
+#define ID_MENU1_DEOP 40014
+#define ID_MENU1_VOICE 40015
+#define ID_MENU1_DEVOICE 40016
+#define ID_MENU1_KICK 40017
+#define ID_MENU1_QUERY 40018
+#define ID_MENU1_WHOIS 40019
+#define IDM_COPYALL 40020
+#define IDM_SELECTALL 40022
+#define IDM_CLEAR 40023
+#define IDM_OPENNEW 40024
+#define IDM_OPENEXISTING 40025
+#define IDM_COPYLINK 40026
+#define IDM_COPY 40027
+#define IDM_JOIN 40028
+#define IDM_CHANGENICK 40029
+#define IDM_SHOWSERVER 40030
+#define IDM_LEAVECHAN 40031
+#define ID_MENU1_ADDCONTACT 40032
+#define IDM_CHANMANAGER 40033
+#define ID_MENU1_KICKREASON 40034
+#define ID_MENU1_BAN 40035
+#define ID_MENU1_BANKICK 40036
+#define ID_MENU1_BANKICKREASON 40037
+#define ID_MENU1_IGNORE_ON 40038
+#define ID_MENU1_IGNORE_OFF 40039
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 240
+#define _APS_NEXT_COMMAND_VALUE 40040
+#define _APS_NEXT_CONTROL_VALUE 1225
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/irc_mod/scripting.cpp b/irc_mod/scripting.cpp
new file mode 100644
index 0000000..6ba591d
--- /dev/null
+++ b/irc_mod/scripting.cpp
@@ -0,0 +1,295 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+#include <algorithm>
+extern MM_INTERFACE mmi;
+
+extern char * IRCPROTONAME;
+extern bool bMbotInstalled;
+extern PREFERENCES* prefs;
+
+int Scripting_InsertRawIn(WPARAM wParam,LPARAM lParam)
+{
+ char * pszRaw = (char *) lParam;
+
+ if(bMbotInstalled && prefs->ScriptingEnabled && pszRaw && g_ircSession)
+ {
+ g_ircSession.InsertIncomingEvent(pszRaw);
+ return 0;
+ }
+
+ return 1;
+}
+
+int Scripting_InsertRawOut(WPARAM wParam,LPARAM lParam)
+{
+ char * pszRaw = (char *) lParam;
+ if(bMbotInstalled && prefs->ScriptingEnabled && pszRaw && g_ircSession)
+ {
+ String S = ReplaceString(pszRaw, "%", "%%%%");
+ g_ircSession.NLSendNoScript((const unsigned char *)S.c_str(), lstrlen(S.c_str()));
+ return 0;
+ }
+
+ return 1;
+}
+
+int Scripting_InsertGuiIn(WPARAM wParam,LPARAM lParam)
+{
+ GCEVENT * gce = (GCEVENT *) lParam;
+ WPARAM_GUI_IN * wgi = (WPARAM_GUI_IN *) wParam;
+
+
+ if(bMbotInstalled && prefs->ScriptingEnabled && gce)
+ {
+ char * p1 = NULL;
+ String S;
+ if(gce->pDest && gce->pDest->pszID)
+ {
+ p1 = gce->pDest->pszID;
+ S = MakeWndID(gce->pDest->pszID);
+ gce->pDest->pszID = (char *)S.c_str();
+ }
+ gce->cbSize = sizeof(GCEVENT);
+
+ CallService(MS_GC_EVENT, wgi?wgi->wParam:0, (LPARAM)gce);
+
+ if(p1)
+ gce->pDest->pszID = p1;
+ return 0;
+ }
+
+ return 1;
+}
+
+//helper functions
+static void __stdcall OnHook(void * pi)
+{
+ GCHOOK * gch = (GCHOOK *) pi;
+
+ Service_GCEventHook(1, (LPARAM) gch);
+
+ if(gch->pszUID)
+ free(gch->pszUID);
+ if(gch->pszText)
+ free(gch->pszText);
+ if(gch->pDest->pszID)
+ free(gch->pDest->pszID);
+ if(gch->pDest->pszModule)
+ free(gch->pDest->pszModule);
+ delete gch->pDest;
+ delete gch;
+}
+static void __cdecl GuiOutThread(LPVOID di)
+{
+ GCHOOK * gch = (GCHOOK *) di;
+ CallFunctionAsync(OnHook, (void *)gch);
+}
+
+int Scripting_InsertGuiOut(WPARAM wParam,LPARAM lParam)
+{
+
+ GCHOOK * gch = (GCHOOK *) lParam;
+
+ if(bMbotInstalled && prefs->ScriptingEnabled && gch)
+ {
+ GCHOOK * gchook = new GCHOOK;
+ gchook->pDest = new GCDEST;
+
+ gchook->dwData = gch->dwData;
+ gchook->pDest->iType = gch->pDest->iType;
+ if(gch->pszText)
+ gchook->pszText = strdup(gch->pszText);
+ else gchook->pszText = NULL;
+
+ if(gch->pszUID)
+ gchook->pszUID = strdup(gch->pszUID);
+ else gchook->pszUID = NULL;
+
+ if(gch->pDest->pszID)
+ {
+ String S = MakeWndID(gch->pDest->pszID);
+ gchook->pDest->pszID = strdup(S.c_str());
+ }
+ else gchook->pDest->pszID = NULL;
+
+ if(gch->pDest->pszModule)
+ gchook->pDest->pszModule = strdup(gch->pDest->pszModule);
+ else gchook->pDest->pszModule = NULL;
+
+ forkthread(GuiOutThread, NULL, gchook);
+
+ return 0;
+ }
+
+ return 1;
+}
+
+
+BOOL Scripting_TriggerMSPRawIn(char ** pszRaw)
+{
+ int iVal = CallService(MS_MBOT_IRC_RAW_IN, (WPARAM)IRCPROTONAME, (LPARAM)pszRaw);
+ if (iVal == 0)
+ return TRUE;
+ return iVal > 0?FALSE:TRUE;
+
+}
+
+BOOL Scripting_TriggerMSPRawOut(char ** pszRaw)
+{
+
+ int iVal = CallService(MS_MBOT_IRC_RAW_OUT, (WPARAM)IRCPROTONAME, (LPARAM)pszRaw);
+ if (iVal == 0)
+ return TRUE;
+ return iVal > 0?FALSE:TRUE;
+}
+
+BOOL Scripting_TriggerMSPGuiIn(WPARAM * wparam, GCEVENT * gce)
+{
+ WPARAM_GUI_IN wgi = {0};
+
+ wgi.pszModule = IRCPROTONAME;
+ wgi.wParam = *wparam;
+ if (gce->time == 0)
+ gce->time = time(0);
+
+ int iVal = CallService(MS_MBOT_IRC_GUI_IN, (WPARAM)&wgi, (LPARAM)gce);
+ if (iVal == 0)
+ {
+ *wparam = wgi.wParam;
+ return TRUE;
+ }
+
+ return iVal > 0?FALSE:TRUE;
+}
+
+BOOL Scripting_TriggerMSPGuiOut(GCHOOK * gch)
+{
+
+ int iVal = CallService(MS_MBOT_IRC_GUI_OUT, (WPARAM)IRCPROTONAME, (LPARAM)gch);
+ if (iVal == 0)
+ return TRUE;
+ return iVal > 0?FALSE:TRUE;
+}
+
+int Scripting_GetIrcData(WPARAM wparam, LPARAM lparam)
+{
+
+ if(bMbotInstalled && prefs->ScriptingEnabled && lparam)
+ {
+ String sString = (char *) lparam;
+ String sRequest, sOutput, sChannel;
+ int i = sString.find("|",0);
+
+ if(i != string::npos)
+ {
+ sRequest = sString.substr(0, i);
+ sChannel = sString.substr(i+1, sString.length());
+
+ }
+ else
+ sRequest = sString;
+
+
+ transform (sRequest.begin(),sRequest.end(), sRequest.begin(), tolower);
+
+ if (sRequest == "ownnick" && g_ircSession)
+ sOutput = g_ircSession.GetInfo().sNick;
+
+ else if (sRequest == "network" && g_ircSession)
+ sOutput = g_ircSession.GetInfo().sNetwork;
+
+ else if (sRequest == "primarynick")
+ sOutput = prefs->Nick;
+
+ else if (sRequest == "secondarynick")
+ sOutput = prefs->AlternativeNick;
+
+ else if (sRequest == "myip")
+ sOutput = prefs->ManualHost?prefs->MySpecifiedHostIP:prefs->IPFromServer?prefs->MyHost:prefs->MyLocalHost;
+
+ else if (sRequest == "usercount" && sChannel != "")
+ {
+ String S = MakeWndID(sChannel);
+ GC_INFO gci = {0};
+ gci.Flags = BYID|COUNT;
+ gci.pszModule = IRCPROTONAME;
+ gci.pszID = (char *)S.c_str();
+ if(!CallService(MS_GC_GETINFO, 0, (LPARAM)&gci))
+ {
+ char szTemp[40];
+ _snprintf(szTemp, 35, "%u", gci.iCount);
+ sOutput = szTemp;
+ }
+ }
+ else if (sRequest == "userlist" && sChannel != "")
+ {
+ String S = MakeWndID(sChannel);
+ GC_INFO gci = {0};
+ gci.Flags = BYID|USERS;
+ gci.pszModule = IRCPROTONAME;
+ gci.pszID = (char *)S.c_str();
+ if(!CallService(MS_GC_GETINFO, 0, (LPARAM)&gci))
+ sOutput = gci.pszUsers;
+ }
+ else if (sRequest == "channellist")
+ {
+ String S = "";
+ int i = CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)IRCPROTONAME);
+ if(i >= 0)
+ {
+ int j = 0;
+ while (j < i)
+ {
+ GC_INFO gci = {0};
+ gci.Flags = BYINDEX|ID;
+ gci.pszModule = IRCPROTONAME;
+ gci.iItem = j;
+ if(!CallService(MS_GC_GETINFO, 0, (LPARAM)&gci))
+ {
+ if(lstrcmpi(gci.pszID, "network log"))
+ {
+ int k;
+ String S1 = gci.pszID;
+ k = S1.find(" ", 0);
+ if(k != string::npos)
+ S1 = S1.substr(0, k);
+ S += S1;
+ S += " ";
+ }
+ }
+ j++;
+ }
+ }
+ if (S != "")
+ sOutput = S;
+ }
+ // send it to mbot
+ if(sOutput != "")
+ {
+ char * pTemp = (char *)mmi.mmi_malloc(sOutput.length() + 1);
+ lstrcpyn(pTemp, sOutput.c_str(), sOutput.length() + 1);
+ return (int) pTemp;
+ }
+ }
+ return 0;
+
+}
diff --git a/irc_mod/services.cpp b/irc_mod/services.cpp
new file mode 100644
index 0000000..3953e80
--- /dev/null
+++ b/irc_mod/services.cpp
@@ -0,0 +1,2515 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+
+CIrcSessionInfo si;
+HANDLE g_hModulesLoaded = NULL;
+HANDLE g_hSystemPreShutdown = NULL;
+HANDLE g_hContactDblClick = NULL;
+HANDLE g_hEventDblClick = NULL;
+HANDLE g_hContactDeleted = NULL;
+HANDLE g_hIconsChanged = NULL;
+HANDLE g_hUserInfoInit = NULL;
+HANDLE g_hMenuCreation = NULL;
+HANDLE g_hGCUserEvent = NULL;
+HANDLE g_hGCMenuBuild = NULL;
+HANDLE g_hOptionsInit = NULL;
+HANDLE hContactMenu1 = NULL;
+HANDLE hContactMenu2 = NULL;
+HANDLE hContactMenu3 = NULL;
+HANDLE hMenuQuick = NULL;
+HANDLE hMenuJoin = NULL;
+HANDLE hMenuNick = NULL;
+HANDLE hMenuList = NULL;
+HANDLE hMenuServer = NULL;
+HANDLE hMenuAvatar = NULL;
+HANDLE hMenuConsole = NULL;
+HANDLE hNetlib = NULL;
+HANDLE hNetlibDCC = NULL;
+HWND join_hWnd = NULL;
+HWND quickconn_hWnd = NULL;
+volatile bool bChatInstalled = FALSE;
+bool bMbotInstalled = FALSE;
+extern HWND nick_hWnd;
+extern HWND list_hWnd ;
+int RetryCount =0;
+int PortCount =0;
+DWORD bConnectRequested = 0;
+DWORD bConnectThreadRunning = 0;
+extern bool bTempDisableCheck ;
+extern bool bTempForceCheck ;
+extern bool bPerformDone;
+int iTempCheckTime = 0;
+int OldStatus= ID_STATUS_OFFLINE;
+int GlobalStatus = ID_STATUS_OFFLINE;
+UINT_PTR RetryTimer = 0;
+String StatusMessage ="";
+
+extern CIrcSession g_ircSession;
+extern char * IRCPROTONAME;
+extern char * ALTIRCPROTONAME;
+extern char * pszServerFile;
+extern char * pszPerformFile;
+extern char * pszIgnoreFile;
+extern PREFERENCES* prefs;
+extern CRITICAL_SECTION cs;
+extern CRITICAL_SECTION m_gchook;
+extern bool nickflag;
+extern String sUserModes;
+extern String sUserModePrefixes;
+extern String sChannelPrefixes;
+extern String sChannelModes;
+extern String WhoisAwayReply ;
+extern char mirandapath[MAX_PATH];
+extern MM_INTERFACE mmi;
+GETEVENTFUNC pfnAddEvent = 0;
+
+// Nudge
+extern HANDLE hIRCNudge;
+
+// PopUp
+bool whois_popup=true;
+
+// Updater
+extern PLUGININFO pluginInfo;
+
+// xStatus
+HANDLE hHookUserMenu = NULL;
+HANDLE hUserMenuXStatus = NULL;
+
+// IcoLib
+HANDLE hHookIconsChanged = NULL;
+
+VOID CALLBACK RetryTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);
+int Service_SetMyAvatar(WPARAM wParam, LPARAM lParam);
+
+static void InitMenus(void)
+{
+ CLISTMENUITEM mi = { 0 };
+ char temp[MAXMODULELABELLENGTH];
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ if (bChatInstalled)
+ {
+ mi.pszName = Translate("&Quick connect");
+ mi.hIcon = LoadIconEx(IDI_QUICK,"quick",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ wsprintf(temp,"%s/QuickConnectMenu", IRCPROTONAME);
+ mi.pszService = temp;
+ mi.popupPosition = 500090000;
+ mi.pszPopupName = ALTIRCPROTONAME;
+ hMenuQuick= (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi);
+
+ mi.pszName = Translate("&Join a channel");
+ mi.hIcon = LoadIconEx(IDI_JOIN,"join",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ wsprintf(temp,"%s/JoinChannelMenu", IRCPROTONAME);
+ mi.pszService = temp;
+ mi.popupPosition = 500090001;
+ mi.pszPopupName = ALTIRCPROTONAME;
+ hMenuJoin = (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi);
+
+ mi.pszName = Translate("&Change your nickname");
+ mi.hIcon = LoadIconEx(IDI_WHOIS,"whois",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ wsprintf(temp,"%s/ChangeNickMenu", IRCPROTONAME);
+ mi.pszService = temp;
+ mi.popupPosition = 500090002;
+ mi.pszPopupName = ALTIRCPROTONAME;
+ hMenuNick = (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi);
+
+ mi.pszName = Translate("Show the &list of available channels");
+ mi.hIcon = LoadIconEx(IDI_LIST,"list",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ wsprintf(temp,"%s/ShowListMenu", IRCPROTONAME);
+ mi.pszService = temp;
+ mi.popupPosition = 500090003;
+ mi.pszPopupName = ALTIRCPROTONAME;
+ hMenuList = (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi);
+
+ mi.pszName = Translate("&Show the server window");
+ mi.hIcon = LoadIconEx(IDI_SERVER,"server",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ wsprintf(temp,"%s/ShowServerMenu", IRCPROTONAME);
+ mi.pszService = temp;
+ mi.popupPosition = 500090004;
+ mi.pszPopupName = ALTIRCPROTONAME;
+ hMenuServer = (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi);
+
+ if(prefs->AvatarsEnabled)
+ {
+ mi.pszName = Translate("Set proto picture");
+ mi.hIcon = LoadIconEx(IDI_AVATAR,"avatar",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ wsprintf(temp,"%s/SetAvatarMenu", IRCPROTONAME);
+ mi.pszService = temp;
+ mi.popupPosition = 500090005;
+ mi.pszPopupName = ALTIRCPROTONAME;
+ hMenuAvatar = (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi);
+ }
+ }
+
+ mi.pszName = Translate("&Leave the channel");
+ mi.hIcon = LoadIconEx(IDI_DELETE,"delete",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ wsprintf(temp,"%s/Menu1ChannelMenu", IRCPROTONAME);
+ mi.pszService = temp;
+ mi.pszContactOwner = IRCPROTONAME;
+ mi.popupPosition = 500090000;
+ hContactMenu1 = (void *)CallService(MS_CLIST_ADDCONTACTMENUITEM, (WPARAM)0, (LPARAM)&mi);
+
+ mi.pszName = Translate("&User details");
+ mi.hIcon = LoadIconEx(IDI_WHOIS,"whois",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ wsprintf(temp,"%s/Menu2ChannelMenu", IRCPROTONAME);
+ mi.pszService = temp;
+ mi.pszContactOwner = IRCPROTONAME;
+ mi.popupPosition = 500090001;
+ hContactMenu2 = (void *)CallService(MS_CLIST_ADDCONTACTMENUITEM, (WPARAM)0, (LPARAM)&mi);
+
+ mi.pszName = Translate("&Ignore");
+ mi.hIcon = LoadIconEx(IDI_BLOCK,"block",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ wsprintf(temp,"%s/Menu3ChannelMenu", IRCPROTONAME);
+ mi.pszService = temp;
+ mi.pszContactOwner = IRCPROTONAME;
+ mi.popupPosition = 500090002;
+ hContactMenu3 = (void *)CallService(MS_CLIST_ADDCONTACTMENUITEM, (WPARAM)0, (LPARAM)&mi);
+
+ mi.pszName = IRCTranslate("Show custom status details");
+ mi.hIcon = NULL; // dynamically updated
+ wsprintf(temp,"%s%s", IRCPROTONAME, MS_XSTATUS_SHOWDETAILS);
+ mi.pszService = temp;
+ mi.flags=CMIF_NOTOFFLINE;
+ mi.popupPosition = 500090003;
+ hUserMenuXStatus = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+ CLISTMENUITEM clmi;
+ memset( &clmi, 0, sizeof( clmi ));
+ clmi.cbSize = sizeof( clmi );
+ clmi.flags = CMIM_FLAGS|CMIF_GRAYED;
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuJoin, ( LPARAM )&clmi );
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuList, ( LPARAM )&clmi );
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuNick, ( LPARAM )&clmi );
+ if(!prefs->UseServer)
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuServer, ( LPARAM )&clmi );
+ return;
+}
+
+static int Service_FileAllow(WPARAM wParam,LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ DCCINFO * di = (DCCINFO *) ccs->wParam;;
+
+ if (g_ircSession)
+ {
+ String sFile = (String)(char *)ccs->lParam + di->sFile;
+ di->sFileAndPath = sFile;
+ di->sPath = (char *)ccs->lParam;
+
+ CDccSession * dcc = new CDccSession(di);
+
+ g_ircSession.AddDCCSession(di, dcc);
+
+ dcc->Connect();
+
+ }
+ else
+ delete di;
+ return ccs->wParam;
+
+}
+
+static int Service_FileDeny(WPARAM wParam,LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ DCCINFO * di = (DCCINFO *) ccs->wParam;
+
+ delete di;
+
+ return 0;
+}
+
+static int Service_FileCancel(WPARAM wParam,LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ DCCINFO *di = (DCCINFO *) ccs->wParam;
+
+ CDccSession * dcc = g_ircSession.FindDCCSession(di);
+
+ if (dcc)
+ {
+ InterlockedExchange(&dcc->dwWhatNeedsDoing, (long)FILERESUME_CANCEL);
+ SetEvent(dcc->hEvent);
+ dcc->Disconnect();
+ }
+
+ return 0;
+}
+
+static int Service_FileSend(WPARAM wParam,LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char **files = (char **) ccs->lParam;
+ DCCINFO * dci = NULL;
+ int iPort = 0;
+ int index= 0;
+ DWORD size = 0;
+
+ // do not send to channels :-P
+ if(DBGetContactSettingByte(ccs->hContact, IRCPROTONAME, "ChatRoom", 0) != 0)
+ return 0;
+
+ // stop if it is an active type filetransfer and the user's IP is not known
+ unsigned long ulAdr = 0;
+ if (prefs->ManualHost)
+ ulAdr = ConvertIPToInteger(prefs->MySpecifiedHostIP);
+ else
+ ulAdr = ConvertIPToInteger(prefs->IPFromServer?prefs->MyHost:prefs->MyLocalHost);
+
+ if(!prefs->DCCPassive && !ulAdr)
+ {
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), Translate("DCC ERROR: Unable to automatically resolve external IP"), NULL, NULL, NULL, true, false);
+ return 0;
+ }
+
+ if(files[index])
+ {
+
+ //get file size
+ FILE * hFile = NULL;
+ while (files[index] && hFile == 0)
+ {
+ hFile = fopen ( files[index] , "rb" );
+ if(hFile)
+ {
+ fseek (hFile , 0 , SEEK_END);
+ size = ftell (hFile);
+ rewind (hFile);
+ fclose(hFile);
+ break;
+ }
+ index++;
+ }
+
+ if(size == 0)
+ {
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), Translate("DCC ERROR: No valid files specified"), NULL, NULL, NULL, true, false);
+ return 0;
+ }
+
+
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(ccs->hContact, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ // set up a basic DCCINFO struct and pass it to a DCC object
+ dci = new DCCINFO;
+ dci->sFileAndPath = files[index];
+
+ int i = dci->sFileAndPath.rfind("\\", dci->sFileAndPath.length());
+ if (i != string::npos)
+ {
+ dci->sPath = dci->sFileAndPath.substr(0, i+1);
+ dci->sFile = dci->sFileAndPath.substr(i+1, dci->sFileAndPath.length());
+ }
+
+ String sFileWithQuotes = dci->sFile;
+
+ // if spaces in the filename surround witrh quotes
+ if (sFileWithQuotes.find(' ', 0) != string::npos)
+ {
+ sFileWithQuotes.insert(0, "\"");
+ sFileWithQuotes.insert(sFileWithQuotes.length(), "\"");
+ }
+
+ dci->hContact = ccs->hContact;
+ dci->sContactName = dbv.pszVal;
+ dci->iType = DCC_SEND;
+ dci->bReverse = prefs->DCCPassive?true:false;
+ dci->bSender = true;
+ dci->dwSize = size;
+
+ // create new dcc object
+ CDccSession * dcc = new CDccSession(dci);
+
+ // keep track of all objects created
+ g_ircSession.AddDCCSession(dci, dcc);
+
+ // need to make sure that %'s are doubled to avoid having chat interpret as color codes
+ String sFileCorrect = ReplaceString(dci->sFile, "%", "%%");
+
+ // is it an reverse filetransfer (receiver acts as server)
+ if(dci->bReverse)
+ {
+ char szTemp[256];
+ PostIrcMessage("/CTCP %s DCC SEND %s 200 0 %u %u", dci->sContactName.c_str(), sFileWithQuotes.c_str(), dci->dwSize, dcc->iToken);
+
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC reversed file transfer request sent to %s [%s]"), dci->sContactName.c_str(), sFileCorrect.c_str());
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+
+ mir_snprintf(szTemp, sizeof(szTemp), "/NOTICE %s I am sending the file \'\002%s\002\' (%u kB) to you, please accept it. [Reverse transfer]", dci->sContactName.c_str(), sFileCorrect.c_str(), dci->dwSize/1024);
+ if(prefs->SendNotice)
+ PostIrcMessage(szTemp);
+
+ }
+ else // ... normal filetransfer.
+ {
+
+ iPort = dcc->Connect();
+
+ if(iPort)
+ {
+ char szTemp[256];
+ PostIrcMessage("/CTCP %s DCC SEND %s %u %u %u", dci->sContactName.c_str(), sFileWithQuotes.c_str(), ulAdr, iPort, dci->dwSize);
+
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC file transfer request sent to %s [%s]"), dci->sContactName.c_str(), sFileCorrect.c_str());
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false);
+
+ mir_snprintf(szTemp, sizeof(szTemp), "/NOTICE %s I am sending the file \'\002%s\002\' (%u kB) to you, please accept it. [IP: %s]", dci->sContactName.c_str(), sFileCorrect.c_str(), dci->dwSize/1024, ConvertIntegerToIP(ulAdr));
+
+ if(prefs->SendNotice)
+ PostIrcMessage(szTemp);
+ }
+ else
+ DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), Translate("DCC ERROR: Unable to bind local port"), NULL, NULL, NULL, true, false);
+ }
+
+ // fix for sending multiple files
+ index++;
+ while(files[index])
+ {
+ hFile = NULL;
+ hFile = fopen ( files[index] , "rb" );
+ if(hFile)
+ {
+ fclose(hFile);
+ PostIrcMessage("/DCC SEND %s %s", dci->sContactName.c_str(), files[index]);
+ }
+ index++;
+ }
+
+
+ DBFreeVariant(&dbv);
+
+ }
+ }
+
+ if(dci)
+ return (int)(HANDLE) dci;
+ return NULL;
+}
+
+static int Service_FileReceive(WPARAM wParam,LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam;
+ char *szDesc, *szFile;
+
+ DBDeleteContactSetting(ccs->hContact, "CList", "Hidden");
+ szFile = pre->szMessage + sizeof(DWORD);
+ szDesc = szFile + strlen(szFile) + 1;
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = IRCPROTONAME;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = pre->flags & (PREF_CREATEREAD ? DBEF_READ : 0);
+ dbei.eventType = EVENTTYPE_FILE;
+ dbei.cbBlob = sizeof(DWORD) + strlen(szFile) + strlen(szDesc) + 2;
+ dbei.pBlob = (PBYTE) pre->szMessage;
+ CallService(MS_DB_EVENT_ADD, (WPARAM) ccs->hContact, (LPARAM) &dbei);
+
+ return 0;
+}
+
+static int Service_FileResume(WPARAM wParam,LPARAM lParam)
+{
+ DCCINFO * di = (DCCINFO *) wParam;
+ PROTOFILERESUME * pfr = (PROTOFILERESUME *) lParam;
+
+ long i = (long)pfr->action;
+
+ CDccSession * dcc = g_ircSession.FindDCCSession(di);
+ if(dcc)
+ {
+ InterlockedExchange(&dcc->dwWhatNeedsDoing, i);
+ if(pfr->action == FILERESUME_RENAME)
+ {
+ char * szTemp = strdup(pfr->szFilename);
+ InterlockedExchange((volatile long*)&dcc->NewFileName, (long)szTemp);
+ }
+ if(pfr->action == FILERESUME_RESUME)
+ {
+ DWORD dwPos = 0;
+ String sFile;
+ char * pszTemp = NULL;;
+ FILE * hFile = NULL;
+
+ hFile = fopen(di->sFileAndPath.c_str(), "rb");
+ if(hFile)
+ {
+ fseek(hFile,0,SEEK_END);
+ dwPos = ftell(hFile);
+ rewind (hFile);
+ fclose(hFile); hFile = NULL;
+ }
+
+ String sFileWithQuotes = di->sFile;
+
+ // if spaces in the filename surround witrh quotes
+ if (sFileWithQuotes.find(' ', 0) != string::npos)
+ {
+ sFileWithQuotes.insert(0, "\"");
+ sFileWithQuotes.insert(sFileWithQuotes.length(), "\"");
+ }
+
+
+ if (di->bReverse)
+ PostIrcMessage("/PRIVMSG %s \001DCC RESUME %s 0 %u %s\001", di->sContactName.c_str(), sFileWithQuotes.c_str(), dwPos, dcc->di->sToken.c_str());
+ else
+ PostIrcMessage("/PRIVMSG %s \001DCC RESUME %s %u %u\001", di->sContactName.c_str(), sFileWithQuotes.c_str(), di->iPort, dwPos);
+
+ return 0;
+ }
+
+
+ SetEvent(dcc->hEvent);
+ }
+ return 0;
+}
+
+static int Service_EventDoubleclicked(WPARAM wParam,LPARAM lParam)
+{
+ if (!lParam)
+ return 0;
+
+ CLISTEVENT* pcle = (CLISTEVENT*)lParam;
+
+ if(DBGetContactSettingByte((HANDLE) pcle->hContact, IRCPROTONAME, "DCC", 0) != 0)
+ {
+ char szTemp[500];
+ DCCINFO * pdci = (DCCINFO *) pcle->lParam;
+ HWND hWnd = CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_MESSAGEBOX),NULL,MessageboxWndProc, (LPARAM)pdci);
+ mir_snprintf(szTemp, sizeof(szTemp), Translate("%s (%s) is requesting a client-to-client chat connection."), pdci->sContactName.c_str(), pdci->sHostmask.c_str() );
+ SetDlgItemText(hWnd,IDC_TEXT, szTemp);
+ ShowWindow(hWnd, SW_SHOW);
+ return 1;
+ }
+ return 0;
+}
+
+int Service_UserDeletedContact(WPARAM wp, LPARAM lp)
+{
+ DBVARIANT dbv;
+ HANDLE hContact = (HANDLE) wp;
+
+ if (!hContact)
+ return 0;
+ if (!DBGetContactSetting((HANDLE)wp, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ )
+ {
+ int type = DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0);
+ if ( type != 0)
+ {
+
+ GCEVENT gce = {0};
+ GCDEST gcd = {0};
+ String S = "";
+ if(type == GCW_CHATROOM)
+ S = MakeWndID(dbv.pszVal);
+ if(type == GCW_SERVER)
+ S = "Network log";
+ gce.cbSize = sizeof(GCEVENT);
+ gce.dwItemData = 0;
+ gcd.iType = GC_EVENT_CONTROL;
+ gcd.pszModule = IRCPROTONAME;
+ gce.pDest = &gcd;
+ gcd.pszID = (char *)S.c_str();
+ int i = CallChatEvent( SESSION_TERMINATE, (LPARAM)&gce);
+ if (i && type == GCW_CHATROOM)
+ PostIrcMessage( "/PART %s", dbv.pszVal);
+ }
+ else
+ {
+ BYTE bDCC = DBGetContactSettingByte((HANDLE)wp, IRCPROTONAME, "DCC", 0) ;
+ if(bDCC)
+ {
+ CDccSession * dcc = g_ircSession.FindDCCSession((HANDLE)wp);
+ if(dcc)
+ dcc->Disconnect();
+ }
+ }
+
+
+
+ DBFreeVariant(&dbv);
+ }
+ return 0;
+}
+
+static int Service_Menu1Command(WPARAM wp, LPARAM lp)
+{
+ DBVARIANT dbv;
+
+ if (!wp )
+ return 0;
+ if (!DBGetContactSetting((HANDLE)wp, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ )
+ {
+ int type = DBGetContactSettingByte((HANDLE)wp, IRCPROTONAME, "ChatRoom", 0);
+ if ( type != 0)
+ {
+ GCEVENT gce = {0};
+ GCDEST gcd = {0};
+ String S = "";
+ if(type == GCW_CHATROOM)
+ S = MakeWndID(dbv.pszVal);
+ if(type == GCW_SERVER)
+ S = "Network log";
+ gcd.iType = GC_EVENT_CONTROL;
+ gcd.pszID = (char *)S.c_str();
+ gcd.pszModule = IRCPROTONAME;
+ gce.cbSize = sizeof(GCEVENT);
+ gce.pDest = &gcd;
+ CallChatEvent( WINDOW_VISIBLE, (LPARAM)&gce);
+ }
+ else
+ CallService(MS_MSG_SENDMESSAGE, (WPARAM)wp, 0);
+ }
+ return 0;
+}
+
+static int Service_Menu2Command(WPARAM wp, LPARAM lp)
+{
+ DBVARIANT dbv;
+
+ if (!wp )
+ return 0;
+ if (!DBGetContactSetting((HANDLE)wp, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ )
+ {
+ int type = DBGetContactSettingByte((HANDLE)wp, IRCPROTONAME, "ChatRoom", 0);
+ if ( type != 0)
+ {
+ if (type == GCW_CHATROOM)
+ PostIrcMessage( "/PART %s", dbv.pszVal);
+
+ GCEVENT gce = {0};
+ GCDEST gcd = {0};
+ String S = "";
+ if(type == GCW_CHATROOM)
+ S = MakeWndID(dbv.pszVal);
+ if(type == GCW_SERVER)
+ S = "Network log";
+ gce.cbSize = sizeof(GCEVENT);
+ gcd.iType = GC_EVENT_CONTROL;
+ gcd.pszModule = IRCPROTONAME;
+ gce.pDest = &gcd;
+ gcd.pszID = (char *)S.c_str();
+ CallChatEvent( SESSION_TERMINATE, (LPARAM)&gce);
+ }
+ else
+ {
+ BYTE bDCC = DBGetContactSettingByte((HANDLE)wp, IRCPROTONAME, "DCC", 0) ;
+ if(bDCC)
+ {
+ CDccSession * dcc = g_ircSession.FindDCCSession((HANDLE)wp);
+ if(dcc)
+ dcc->Disconnect();
+ }
+ else
+ {
+ PostIrcMessage( "/WHOIS %s", dbv.pszVal);
+ whois_popup = true;
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ return 0;
+}
+
+static int Service_Menu3Command(WPARAM wp, LPARAM lp)
+{
+ if (!wp )
+ return 0;
+ HANDLE hContact = (HANDLE) wp;
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ )
+ {
+ if (DBGetContactSettingByte((HANDLE)wp, IRCPROTONAME, "ChatRoom", 0) ==0)
+ {
+ char * host = NULL;
+ DBVARIANT dbv1;
+ if (!DBGetContactSetting((HANDLE) wp, IRCPROTONAME, "Host", &dbv1) && dbv1.type == DBVT_ASCIIZ) host = dbv1.pszVal;
+
+ if (host)
+ {
+ String S;
+ if(prefs->IgnoreChannelDefault)
+ S = "+qnidcm";
+ else
+ S = "+qnidc";
+ PostIrcMessage( "/IGNORE %%question=\"%s\",\"%s\",\"*!*@%s\" %s",Translate("Please enter the hostmask (nick!user@host) \nNOTE! Contacts on your contact list are never ignored"), Translate("Ignore"), host, S.c_str());
+
+ }
+
+ if (host)
+ DBFreeVariant(&dbv1);
+ }
+ else
+ {
+ PostIrcMessageWnd(dbv.pszVal, NULL, "/CHANNELMANAGER");
+ }
+ DBFreeVariant(&dbv);
+ }
+ return 0;
+}
+
+static int Service_JoinMenuCommand(WPARAM wp, LPARAM lp)
+{
+ if (!join_hWnd)
+ join_hWnd = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_NICK), NULL, JoinWndProc);
+ SetDlgItemText(join_hWnd, IDC_CAPTION, Translate("Join channel"));
+ SetWindowText(GetDlgItem(join_hWnd, IDC_TEXT), Translate("Please enter a channel to join"));
+ SendMessage(GetDlgItem(join_hWnd, IDC_ENICK), EM_SETSEL, 0,MAKELPARAM(0,-1));
+ ShowWindow(join_hWnd, SW_SHOW);
+ SetActiveWindow(join_hWnd);
+ return 0;
+}
+
+static int Service_QuickConnectMenuCommand(WPARAM wp, LPARAM lp)
+{
+ if (!quickconn_hWnd)
+ quickconn_hWnd = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_QUICKCONN), NULL, QuickWndProc);
+
+ SetWindowText(quickconn_hWnd, Translate("Quick connect"));
+ SetWindowText(GetDlgItem(quickconn_hWnd, IDC_TEXT), Translate("Please select IRC network and enter the password if needed"));
+ SetWindowText(GetDlgItem(quickconn_hWnd, IDC_CAPTION), Translate("Quick connect"));
+ SendMessage(quickconn_hWnd, WM_SETICON, ICON_BIG,(LPARAM)LoadIconEx(IDI_QUICK,"quick",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ ShowWindow(quickconn_hWnd, SW_SHOW);
+ SetActiveWindow(quickconn_hWnd);
+ return 0;
+}
+
+static int Service_ShowListMenuCommand(WPARAM wp, LPARAM lp)
+{
+ PostIrcMessage( "/LIST");
+ return 0;
+}
+
+static int Service_ShowServerMenuCommand(WPARAM wp, LPARAM lp)
+{
+ GCEVENT gce = {0};
+ GCDEST gcd = {0};
+ gcd.iType = GC_EVENT_CONTROL;
+ gcd.pszID = "Network log";
+ gcd.pszModule = IRCPROTONAME;
+ gce.cbSize = sizeof(GCEVENT);
+ gce.pDest = &gcd;
+ CallChatEvent( WINDOW_VISIBLE, (LPARAM)&gce);
+
+ return 0;
+}
+
+static int Service_ChangeNickMenuCommand(WPARAM wp, LPARAM lp)
+{
+ if (!nick_hWnd)
+ nick_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_NICK), NULL, NickWndProc);
+
+ SetDlgItemText(nick_hWnd, IDC_CAPTION, Translate("Change nick name"));
+ SetWindowText(GetDlgItem(nick_hWnd, IDC_TEXT), Translate("Please enter a unique nickname"));
+ SetWindowText(GetDlgItem(nick_hWnd, IDC_ENICK), g_ircSession.GetInfo().sNick.c_str());
+ SendMessage(GetDlgItem(nick_hWnd, IDC_ENICK), CB_SETEDITSEL, 0,MAKELPARAM(0,-1));
+ ShowWindow(nick_hWnd, SW_SHOW);
+ SetActiveWindow(nick_hWnd);
+
+ return 0;
+}
+
+static int Service_SetAvatarMenuCommand(WPARAM wp, LPARAM lp)
+{
+ char* szDest = (char*)SAFE_MALLOC(MAX_PATH+0x10);
+ char str[MAX_PATH];
+ char szFilter[512];
+ OPENFILENAME ofn = {0};
+
+ str[0] = 0;
+ CallService(MS_UTILS_GETBITMAPFILTERSTRINGS,sizeof(szFilter),(LPARAM)szFilter);
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.lpstrFilter = szFilter;
+ ofn.lpstrFile = szDest;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = "jpg";
+ if(GetOpenFileName(&ofn))
+ Service_SetMyAvatar(NULL, (LPARAM)szDest);
+ else
+ Service_SetMyAvatar(NULL, NULL);
+
+ return 0;
+}
+
+static void DoChatFormatting(char * pszText)
+{
+ char * p1 = pszText;
+ int iFG = -1;
+ int iRemoveChars;
+ char InsertThis[50];
+
+ while(*p1 != '\0')
+ {
+ iRemoveChars = 0;
+ mir_snprintf(InsertThis, sizeof(InsertThis), "");
+
+ if (*p1 == '%')
+ {
+ switch (p1[1])
+ {
+ case 'B':
+ case 'b':
+ mir_snprintf(InsertThis, sizeof(InsertThis), "\002");
+ iRemoveChars = 2;
+ break;
+ case 'I':
+ case 'i':
+ mir_snprintf(InsertThis, sizeof(InsertThis), "\026");
+ iRemoveChars = 2;
+ break;
+ case 'U':
+ case 'u':
+ mir_snprintf(InsertThis, sizeof(InsertThis), "\037");
+ iRemoveChars = 2;
+ break;
+ case 'c':
+ {
+ char szTemp[3];
+ mir_snprintf(InsertThis, sizeof(InsertThis), "\003");
+
+ iRemoveChars = 2;
+
+ lstrcpyn(szTemp, p1 + 2, 3);
+ iFG = atoi(szTemp);
+ }break;
+ case 'C':
+ if(p1[2] =='%' && p1[3] == 'F')
+ {
+ mir_snprintf(InsertThis, sizeof(InsertThis), "\00399,99");
+ iRemoveChars = 4;
+ }
+ else
+ {
+ mir_snprintf(InsertThis, sizeof(InsertThis), "\00399");
+ iRemoveChars = 2;
+ }
+ iFG = -1;
+ break;
+ case 'f':
+ {
+ char szTemp[3];
+ if(p1 - 3 >= pszText && p1[-3] == '\003')
+ mir_snprintf(InsertThis, sizeof(InsertThis), ",");
+ else if( iFG >= 0 )
+ mir_snprintf(InsertThis, sizeof(InsertThis), "\003%u,", iFG);
+ else
+ mir_snprintf(InsertThis, sizeof(InsertThis), "\00399,");
+
+ iRemoveChars = 2;
+
+ lstrcpyn(szTemp, p1 + 2, 3);
+ }break;
+
+ case 'F':
+ if(iFG >= 0)
+ mir_snprintf(InsertThis, sizeof(InsertThis), "\003%u,99", iFG);
+ else
+ mir_snprintf(InsertThis, sizeof(InsertThis), "\00399,99");
+ iRemoveChars = 2;
+ break;
+
+ case '%':
+ mir_snprintf(InsertThis, sizeof(InsertThis), "%%");
+ iRemoveChars = 2;
+ break;
+ default:
+ iRemoveChars = 2;
+ break;
+
+ }
+ MoveMemory(p1 + lstrlen(InsertThis) , p1 + iRemoveChars, lstrlen(p1) - iRemoveChars +1);
+ CopyMemory(p1, InsertThis, lstrlen(InsertThis));
+ if(iRemoveChars || lstrlen(InsertThis))
+ p1 += lstrlen(InsertThis);
+ else
+ p1++;
+
+ }
+ else
+ p1++;
+
+ }
+
+
+}
+
+int Service_SendUserIsTyping(WPARAM wParam, LPARAM lParam)
+{
+ int nResult = 1;
+ HANDLE hContact = (HANDLE)wParam;
+
+ if (hContact && GlobalStatus != ID_STATUS_OFFLINE && DBGetContactSettingWord(hContact,IRCPROTONAME, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE && DBGetContactSettingByte(NULL,IRCPROTONAME, "TypingEnabled", 0))
+ {
+ switch (lParam)
+ {
+ case PROTOTYPE_SELFTYPING_ON:
+ sendTypingNotification(hContact, MTN_BEGUN);
+ nResult = 0;
+ break;
+
+ case PROTOTYPE_SELFTYPING_OFF:
+ sendTypingNotification(hContact, MTN_FINISHED);
+ nResult = 0;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return nResult;
+}
+
+static int Service_SendNudge( WPARAM wParam, LPARAM lParam )
+{
+/*
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING dcs;
+ dcs.szModule=IRCPROTONAME;
+ dcs.szSetting="Nick";
+ dcs.pValue=&dbv;
+ dbv.type=DBVT_ASCIIZ;
+ CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)wParam,(LPARAM)&dcs);
+ if(ServiceExists(MS_NUDGE_SEND))
+ PostIrcMessage( "/PRIVMSG %s \001NUDGE\001", dbv.pszVal);
+ DBFreeVariant(&dbv);
+*/
+
+ if(ServiceExists(MS_NUDGE_SEND))
+ PostIrcMessage( "/PRIVMSG %s \001NUDGE\001", IRCGetContactSettingString((HANDLE)wParam, "Nick", ""));
+ return 0;
+}
+
+int Service_GCEventHook(WPARAM wParam,LPARAM lParam)
+{
+ GCHOOK *gchook= (GCHOOK*) lParam;
+ GCHOOK *gchtemp = NULL;
+ GCHOOK *gch = NULL;
+ String S = "";
+
+ EnterCriticalSection(&m_gchook);
+
+ // handle the hook
+ if(gchook)
+ {
+ if (!lstrcmpi(gchook->pDest->pszModule, IRCPROTONAME))
+ {
+
+ // first see if the scripting module should modify or stop this event
+ if(bMbotInstalled && prefs->ScriptingEnabled && wParam == NULL)
+ {
+ gchtemp = (GCHOOK *)mmi.mmi_malloc(sizeof(GCHOOK));
+ gchtemp->pDest = (GCDEST *)mmi.mmi_malloc(sizeof(GCDEST));
+ gchtemp->pDest->iType = gchook->pDest->iType;
+ gchtemp->dwData = gchook->dwData;
+
+ if(gchook->pDest->pszID)
+ {
+ char * pTemp = NULL;
+ gchtemp->pDest->pszID = (char *)mmi.mmi_malloc(lstrlen(gchook->pDest->pszID) + 1);
+ lstrcpyn(gchtemp->pDest->pszID, gchook->pDest->pszID, lstrlen(gchook->pDest->pszID) + 1);
+ pTemp = strchr(gchtemp->pDest->pszID, ' ');
+ if(pTemp)
+ *pTemp = '\0';
+
+ }else gchtemp->pDest->pszID = NULL;
+
+ if(gchook->pDest->pszModule)
+ {
+ gchtemp->pDest->pszModule = (char *)mmi.mmi_malloc(lstrlen(gchook->pDest->pszModule) + 1);
+ lstrcpyn(gchtemp->pDest->pszModule, gchook->pDest->pszModule, lstrlen(gchook->pDest->pszModule) + 1);
+ }else gchtemp->pDest->pszModule = NULL;
+
+ if(gchook->pszText)
+ {
+ gchtemp->pszText = (char *)mmi.mmi_malloc(lstrlen(gchook->pszText) + 1);
+ lstrcpyn(gchtemp->pszText, gchook->pszText, lstrlen(gchook->pszText) + 1);
+ }else gchtemp->pszText = NULL;
+
+ if(gchook->pszUID)
+ {
+ gchtemp->pszUID = (char *)mmi.mmi_malloc(lstrlen(gchook->pszUID) + 1);
+ lstrcpyn(gchtemp->pszUID, gchook->pszUID, lstrlen(gchook->pszUID) + 1);
+ }else gchtemp->pszUID = NULL;
+
+ if( Scripting_TriggerMSPGuiOut(gchtemp) && gchtemp)
+ gch = gchtemp;
+ else
+ gch = NULL;
+
+ }
+ else
+ gch = gchook;
+
+ if(gch)
+ {
+ char * p1 = new char[lstrlen(gch->pDest->pszID)+1];
+ lstrcpy(p1, gch->pDest->pszID);
+ char * p2 = strstr(p1, " - ");
+ if(p2)
+ {
+ *p2 = '\0';
+ }
+ switch (gch->pDest->iType)
+ {
+ case GC_SESSION_TERMINATE:
+ FreeWindowItemData(p1, (CHANNELINFO*)gch->dwData);
+ break;
+ case GC_USER_MESSAGE:
+ if(gch && gch->pszText && lstrlen(gch->pszText)> 0)
+ {
+ char * pszText = new char[lstrlen(gch->pszText)+1000];
+ lstrcpy(pszText, gch->pszText);
+ DoChatFormatting(pszText);
+ PostIrcMessageWnd(p1, NULL, pszText);
+ delete []pszText;
+ }
+ break;
+ case GC_USER_CHANMGR:
+ PostIrcMessageWnd(p1, NULL, "/CHANNELMANAGER");
+ break;
+ case GC_USER_PRIVMESS:
+ char szTemp[4000];
+ mir_snprintf(szTemp, sizeof(szTemp), "/QUERY %s", gch->pszUID);
+ PostIrcMessageWnd(p1, NULL, szTemp);
+ break;
+ case GC_USER_LOGMENU:
+ switch(gch->dwData)
+ {
+ case 1:
+ PostIrcMessageWnd(p1, NULL, "/CHANNELMANAGER");
+ break;
+ case 2:
+ {
+ PostIrcMessage( "/PART %s", p1);
+ GCEVENT gce = {0};
+ GCDEST gcd = {0};
+ S = MakeWndID(p1);
+ gce.cbSize = sizeof(GCEVENT);
+ gcd.iType = GC_EVENT_CONTROL;
+ gcd.pszModule = IRCPROTONAME;
+ gce.pDest = &gcd;
+ gcd.pszID = (char *)S.c_str();
+ CallChatEvent( SESSION_TERMINATE, (LPARAM)&gce);
+ }break;
+ case 3:
+ PostIrcMessageWnd(p1, NULL, "/SERVERSHOW");
+ break;
+ default:break;
+ }break;
+ case GC_USER_NICKLISTMENU:
+ switch(gch->dwData)
+ {
+ case 1:
+ PostIrcMessage( "/MODE %s +o %s", p1, gch->pszUID);
+ break;
+ case 2:
+ PostIrcMessage( "/MODE %s -o %s", p1, gch->pszUID);
+ break;
+ case 3:
+ PostIrcMessage( "/MODE %s +v %s", p1, gch->pszUID);
+ break;
+ case 4:
+ PostIrcMessage( "/MODE %s -v %s", p1, gch->pszUID);
+ break;
+ case 5:
+ PostIrcMessage( "/KICK %s %s", p1, gch->pszUID);
+ break;
+ case 6:
+ PostIrcMessage( "/KICK %s %s %%question=\"%s\",\"%s\",\"%s\"", p1, gch->pszUID, Translate("Please enter the reason"), Translate("Kick"), Translate("Jerk") );
+ break;
+ case 7:
+ DoUserhostWithReason(1, "B" + (String)p1, true, "%s", gch->pszUID);
+ break;
+ case 8:
+ DoUserhostWithReason(1, "K" + (String)p1, true, "%s", gch->pszUID);
+ break;
+ case 9:
+ DoUserhostWithReason(1, "L" + (String)p1, true, "%s", gch->pszUID);
+ break;
+ case 10:
+ PostIrcMessage( "/WHOIS %s", gch->pszUID);
+ break;
+// case 11:
+// DoUserhostWithReason(1, "I", true, "%s", gch->pszUID);
+// break;
+// case 12:
+// DoUserhostWithReason(1, "J", true, "%s", gch->pszUID);
+// break;
+ case 13:
+ PostIrcMessage( "/DCC CHAT %s", gch->pszUID);
+ break;
+ case 14:
+ PostIrcMessage( "/DCC SEND %s", gch->pszUID);
+ break;
+ case 15:
+ DoUserhostWithReason(1, "I", true, "%s", gch->pszUID);
+ break;
+ case 16:
+ PostIrcMessage( "/MODE %s +h %s", p1, gch->pszUID);
+ break;
+ case 17:
+ PostIrcMessage( "/MODE %s -h %s", p1, gch->pszUID);
+ break;
+ case 30:
+ {
+ PROTOSEARCHRESULT psr;
+ ZeroMemory(&psr, sizeof(psr));
+ psr.cbSize = sizeof(psr);
+ psr.nick = (char *)gch->pszUID;
+ ADDCONTACTSTRUCT acs;
+ ZeroMemory(&acs, sizeof(acs));
+ acs.handleType =HANDLE_SEARCHRESULT;
+ acs.szProto = IRCPROTONAME;
+ acs.psr = &psr;
+ CallService(MS_ADDCONTACT_SHOW, (WPARAM)NULL, (LPARAM)&acs);
+ }break;
+ break;
+ default:break;
+ }break;
+ default:break;
+ }
+
+ delete[]p1;
+ }
+ }
+
+ }
+ if (gchtemp)
+ {
+ if(gchtemp->pszUID)
+ mmi.mmi_free(gchtemp->pszUID);
+ if(gchtemp->pszText)
+ mmi.mmi_free(gchtemp->pszText);
+ if(gchtemp->pDest->pszID)
+ mmi.mmi_free(gchtemp->pDest->pszID);
+ if(gchtemp->pDest->pszModule)
+ mmi.mmi_free(gchtemp->pDest->pszModule);
+ mmi.mmi_free(gchtemp->pDest);
+ mmi.mmi_free(gchtemp);
+ }
+ LeaveCriticalSection(&m_gchook);
+ return 0;
+}
+
+static int Service_GCMenuHook(WPARAM wParam,LPARAM lParam)
+{
+ GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam;
+ if(gcmi)
+ {
+ if (!lstrcmpi(gcmi->pszModule, IRCPROTONAME))
+ {
+ if(gcmi->Type == MENU_ON_LOG)
+ {
+ if(lstrcmpi(gcmi->pszID, "Network log"))
+ {
+ static struct gc_item Item[] = {
+ {Translate("Channel &settings"), 1, MENU_ITEM, FALSE},
+ {Translate("&Leave the channel"), 2, MENU_ITEM, FALSE},
+ {Translate("Show the server &window"), 3, MENU_ITEM, FALSE}};
+ gcmi->nItems = sizeof(Item)/sizeof(Item[0]);
+ gcmi->Item = &Item[0];
+ }
+ else
+ gcmi->nItems = 0;
+ }
+ if(gcmi->Type == MENU_ON_NICKLIST)
+ {
+ struct CONTACT_TYPE user ={(char *)gcmi->pszUID, NULL, NULL, false, false, false};
+ HANDLE hContact = CList_FindContact(&user);
+ BOOL bFlag = FALSE;
+
+ if (hContact && DBGetContactSettingByte(hContact,"CList", "NotOnList", 0) == 0)
+ bFlag = TRUE;
+
+ static struct gc_item Item[] = {
+ {Translate("&WhoIs info"), 10, MENU_ITEM, FALSE},
+ {Translate("&Control"), 0, MENU_NEWPOPUP, FALSE},
+ {Translate("Give &Op"), 1, MENU_POPUPITEM, FALSE},
+ {Translate("Take O&p"), 2, MENU_POPUPITEM, FALSE},
+ {Translate("Give &Halfop"), 16, MENU_POPUPITEM, FALSE},
+ {Translate("Take H&alfop"), 17, MENU_POPUPITEM, FALSE},
+ {Translate("Give &Voice"), 3, MENU_POPUPITEM, FALSE},
+ {Translate("Take V&oice"), 4, MENU_POPUPITEM, FALSE},
+ {"", 0, MENU_POPUPSEPARATOR, FALSE},
+ {Translate("&Kick"), 5, MENU_POPUPITEM, FALSE},
+ {Translate("Ki&ck (reason)"), 6, MENU_POPUPITEM, FALSE},
+ {Translate("&Ban"), 7, MENU_POPUPITEM, FALSE},
+ {Translate("Ban'&n kick"), 8, MENU_POPUPITEM, FALSE},
+ {Translate("Ban'n kick (&reason)"), 9, MENU_POPUPITEM, FALSE},
+ {Translate("&Direct Connection"), 0, MENU_NEWPOPUP, FALSE},
+ {Translate("Request &Chat"), 13, MENU_POPUPITEM, FALSE},
+ {Translate("Send &File"), 14, MENU_POPUPITEM, FALSE},
+ {Translate("Add to &ignore list"), 15, MENU_ITEM, FALSE},
+ {"", 12, MENU_SEPARATOR, FALSE},
+ {Translate("&Add User"), 30, MENU_ITEM, bFlag}
+ };
+ gcmi->nItems = sizeof(Item)/sizeof(Item[0]);
+ gcmi->Item = &Item[0];
+ gcmi->Item[gcmi->nItems-1].bDisabled = bFlag;
+
+ unsigned long ulAdr = 0;
+ if (prefs->ManualHost)
+ ulAdr = ConvertIPToInteger(prefs->MySpecifiedHostIP);
+ else
+ ulAdr = ConvertIPToInteger(prefs->IPFromServer?prefs->MyHost:prefs->MyLocalHost);
+
+ bool bDcc = ulAdr == 0 ?false:true;
+
+ gcmi->Item[14].bDisabled = !bDcc;
+ gcmi->Item[15].bDisabled = !bDcc;
+ gcmi->Item[16].bDisabled = !bDcc;
+
+ bool bHalfop = strchr(sUserModes.c_str(), 'h') == NULL?false:true;
+ gcmi->Item[5].bDisabled = !bHalfop;
+ gcmi->Item[4].bDisabled = !bHalfop;
+
+ }
+ }
+ }
+ return 0;
+}
+
+static int Service_SystemPreShutdown(WPARAM wParam,LPARAM lParam)
+{
+
+ EnterCriticalSection(&cs);
+
+ if (prefs->Perform && g_ircSession)
+ {
+ if(DoPerform("Event: Disconnect"))
+ Sleep(200);
+ }
+
+ g_ircSession.DisconnectAllDCCSessions(true);
+
+ if (g_ircSession)
+ g_ircSession.Disconnect();
+ if (list_hWnd)
+ SendMessage(list_hWnd, WM_CLOSE, 0, 0);
+ if (nick_hWnd)
+ SendMessage(nick_hWnd, WM_CLOSE, 0, 0);
+ if (join_hWnd)
+ SendMessage(join_hWnd, WM_CLOSE, 0, 0);
+ LeaveCriticalSection(&cs);
+
+ return 0;
+}
+
+static int Service_MenuPreBuild(WPARAM wParam,LPARAM lParam)
+{
+ DBVARIANT dbv;
+ char *szProto;
+ CLISTMENUITEM clmi;
+ HANDLE hContact = (HANDLE) wParam;
+
+ if (!hContact)
+ return 0;
+ memset( &clmi, 0, sizeof( clmi ));
+ clmi.cbSize = sizeof( clmi );
+ clmi.flags = CMIM_FLAGS|CMIM_NAME|CMIM_ICON;
+
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) wParam, 0);
+ if (szProto && !lstrcmpi(szProto, IRCPROTONAME))
+ {
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0) == GCW_CHATROOM)
+ {
+ clmi.hIcon = LoadIconEx(IDI_PART,"part",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ clmi.pszName = Translate("&Leave channel");
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu2, ( LPARAM )&clmi );
+
+ clmi.hIcon = LoadIconEx(IDI_MANAGER,"manager",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ clmi.pszName = Translate("Channel &settings");
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu3, ( LPARAM )&clmi );
+
+ clmi.hIcon = LoadIconEx(IDI_SHOW,"show",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ clmi.pszName = Translate("&Show channel");
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu1, ( LPARAM )&clmi );
+
+ }
+ else if(DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0) == GCW_SERVER)
+ {
+ clmi.hIcon = LoadIconEx(IDI_SERVER,"server",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ clmi.pszName = Translate("&Show server");
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu1, ( LPARAM )&clmi );
+
+ clmi.flags = CMIM_FLAGS|CMIF_HIDDEN;
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu2, ( LPARAM )&clmi );
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu3, ( LPARAM )&clmi );
+
+
+ }
+ else if (!DBGetContactSetting((void *)wParam, IRCPROTONAME, "Default", &dbv)&& dbv.type == DBVT_ASCIIZ)
+ {
+ BYTE bDcc = DBGetContactSettingByte((HANDLE) wParam, IRCPROTONAME, "DCC", 0) ;
+
+ clmi.flags = CMIM_FLAGS|CMIF_HIDDEN;
+
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu1, ( LPARAM )&clmi );
+ clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS;
+
+ if(bDcc)
+ {
+ if(DBGetContactSettingWord((void *)wParam, IRCPROTONAME, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE)
+ clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS |CMIF_HIDDEN;
+ clmi.hIcon = LoadIconEx(IDI_DELETE,"delete",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ clmi.pszName = Translate("Di&sconnect");
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu2, ( LPARAM )&clmi );
+ }
+ else
+ {
+ if(!g_ircSession)
+ clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS |CMIF_HIDDEN;
+ clmi.hIcon = LoadIconEx(IDI_WHOIS,"whois",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ clmi.pszName = Translate("&WhoIs info");
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu2, ( LPARAM )&clmi );
+
+ }
+
+ if(!g_ircSession || bDcc)
+ clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS |CMIF_HIDDEN;
+ else
+ clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS;
+
+ clmi.hIcon = LoadIconEx(IDI_BLOCK,"block",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ if (DBGetContactSettingWord((HANDLE)wParam, IRCPROTONAME, "Status", ID_STATUS_OFFLINE) !=ID_STATUS_OFFLINE)
+ {
+ char * host = NULL;
+ DBVARIANT dbv3;
+ if (!DBGetContactSetting((HANDLE) wParam, IRCPROTONAME, "Host", &dbv3) && dbv3.type == DBVT_ASCIIZ) host = dbv3.pszVal;
+
+ if (host)
+ {
+ clmi.pszName = Translate("&Add to ignore list");
+ }
+ else
+ clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS |CMIF_HIDDEN;
+
+ if (host)
+ DBFreeVariant(&dbv3);
+
+ }
+ else
+ clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS |CMIF_HIDDEN;
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu3, ( LPARAM )&clmi );
+ DBFreeVariant(&dbv);
+ }
+
+ }
+
+ return 0;
+}
+
+static int Service_GetCaps(WPARAM wParam,LPARAM lParam)
+{
+ if(wParam==PFLAGNUM_1)
+ return PF1_BASICSEARCH | PF1_MODEMSG | PF1_FILE |PF1_CANRENAMEFILE | PF1_PEER2PEER | PF1_IM;
+ if(wParam==PFLAGNUM_2)
+ return PF2_ONLINE|PF2_SHORTAWAY;
+ if(wParam==PFLAGNUM_3)
+ return PF2_SHORTAWAY;
+ if(wParam==PFLAGNUM_4)
+ return PF4_NOCUSTOMAUTH | PF4_SUPPORTTYPING;
+ if(wParam==PFLAG_UNIQUEIDTEXT)
+ return (int) Translate("Nickname");
+ if(wParam==PFLAG_MAXLENOFMESSAGE)
+ return 400;
+ if(wParam==PFLAG_UNIQUEIDSETTING)
+ return (int) "Default";
+return 0;
+}
+
+static int Service_GetName(WPARAM wParam,LPARAM lParam)
+{
+ lstrcpyn((char *) lParam, ALTIRCPROTONAME, wParam);
+ return 0;
+}
+
+static int Service_LoadIcon(WPARAM wParam,LPARAM lParam)
+{
+
+ switch(wParam&0xFFFF) {
+ case PLI_PROTOCOL:
+ return (int)LoadImage(g_hInstance,MAKEINTRESOURCE(IDI_MAIN),IMAGE_ICON,16,16,LR_SHARED);
+ default: return (int)(HICON)NULL;
+ }
+ return 0;
+}
+
+static void __cdecl AckBasicSearch(void * pszNick)
+{
+ PROTOSEARCHRESULT psr;
+ ZeroMemory(&psr, sizeof(psr));
+ psr.cbSize = sizeof(psr);
+ psr.nick = (char *)pszNick;
+ ProtoBroadcastAck(IRCPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE) 1, (LPARAM) & psr);
+ ProtoBroadcastAck(IRCPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
+}
+
+static int Service_BasicSearch(WPARAM wParam,LPARAM lParam)
+{
+ static char buf[50];
+ if (lParam) {
+ lstrcpyn(buf, (const char *)lParam, 50);
+ if (OldStatus != ID_STATUS_OFFLINE && OldStatus != ID_STATUS_CONNECTING
+ && lstrlen(buf) >0 && !IsChannel(buf))
+ {
+ forkthread(AckBasicSearch, 0, &buf );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int Service_AddToList(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact;
+ PROTOSEARCHRESULT *psr = (PROTOSEARCHRESULT *) lParam;
+ CONTACT user ={(char *)psr->nick, NULL, NULL, true, false, false};
+
+ if (OldStatus == ID_STATUS_OFFLINE || OldStatus == ID_STATUS_CONNECTING)
+ return 0;
+ hContact = CList_AddContact(&user, true, false);
+
+ if (hContact)
+ {
+ DBVARIANT dbv1;
+
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 0)
+ DoUserhostWithReason(1, ((String)"S" + psr->nick).c_str(), true, psr->nick);
+ else
+ {
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv1) && dbv1.type == DBVT_ASCIIZ)
+ {
+ DoUserhostWithReason(2, ((String)"S" + dbv1.pszVal).c_str(), true, dbv1.pszVal);
+ DBFreeVariant(&dbv1);
+ }
+ else
+ {
+ DoUserhostWithReason(2, ((String)"S" + psr->nick).c_str(), true, psr->nick);
+ }
+ }
+
+ }
+ return (int) hContact;
+}
+
+static void __cdecl ConnectServerThread(LPVOID di)
+{
+ EnterCriticalSection(&cs);
+ InterlockedIncrement((volatile long *) &bConnectThreadRunning);
+ InterlockedIncrement((volatile long *) &bConnectRequested);
+ while ( !Miranda_Terminated() && bConnectRequested > 0 )
+ {
+ while(bConnectRequested > 0)
+ InterlockedDecrement((volatile long *) &bConnectRequested);
+ if (g_ircSession)
+ {
+ Sleep(200);
+ g_ircSession.Disconnect();
+ }
+ g_ircSession.GetInfo().bNickFlag = false;
+ int Temp = OldStatus;
+ OldStatus = ID_STATUS_CONNECTING;
+ nickflag = false;
+ ProtoBroadcastAck(IRCPROTONAME,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)Temp,ID_STATUS_CONNECTING);
+ Sleep(100);
+ g_ircSession.Connect(si);
+ if (g_ircSession)
+ {
+
+ KillChatTimer(RetryTimer);
+
+ if(lstrlen(prefs->MySpecifiedHost))
+ {
+ IPRESOLVE * ipr = new IPRESOLVE;
+ ipr->iType = IP_MANUAL;
+ ipr->pszAdr = prefs->MySpecifiedHost;
+ forkthread(ResolveIPThread, NULL, ipr);
+ }
+ }
+ else
+ {
+ Temp = OldStatus;
+ OldStatus = ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(IRCPROTONAME,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)Temp,ID_STATUS_OFFLINE);
+ Sleep(100);
+ }
+ }
+ InterlockedDecrement((volatile long *) &bConnectThreadRunning);
+ LeaveCriticalSection(&cs);
+ return;
+}
+
+static void __cdecl DisconnectServerThread(LPVOID di)
+{
+ EnterCriticalSection(&cs);
+ KillChatTimer(RetryTimer);
+ if (g_ircSession)
+ g_ircSession.Disconnect();
+ LeaveCriticalSection(&cs);
+ return;
+}
+
+void ConnectToServer(void)
+{
+ PortCount= StrToInt(prefs->PortStart);
+ si.sServer = GetWord(prefs->ServerName, 0);
+ si.iPort = PortCount;
+ si.sNick = prefs->Nick;
+ si.sUserID = prefs->UserID;
+ si.sFullName = prefs->Name;
+ si.sPassword = prefs->Password;
+ si.bIdentServer = ((prefs->Ident) ? (true) : (false));
+ si.iIdentServerPort = StrToInt(prefs->IdentPort);
+ si.sIdentServerType = prefs->IdentSystem;
+ si.sNetwork = prefs->Network;
+ si.iSSL = prefs->iSSL;
+ RetryCount = 1;
+ KillChatTimer(RetryTimer);
+ if (prefs->Retry)
+ {
+ if (StrToInt(prefs->RetryWait)<10)
+ lstrcpy(prefs->RetryWait, "10");
+ SetChatTimer(RetryTimer, StrToInt(prefs->RetryWait)*1000, RetryTimerProc);
+ }
+ bPerformDone = false;
+ bTempDisableCheck = false;
+ bTempForceCheck = false;
+ iTempCheckTime = 0;
+ sChannelPrefixes = "&#";
+ sUserModes = "ov";
+ sUserModePrefixes = "@+";
+ sChannelModes = "btnimklps";
+
+
+ if (!bConnectThreadRunning)
+ {
+ forkthread(ConnectServerThread, 0, NULL );
+ }
+ else if (bConnectRequested < 1)
+ InterlockedIncrement((volatile long *) &bConnectRequested);
+
+ char szTemp[300];
+ mir_snprintf(szTemp, sizeof(szTemp), "\0033%s \002%s\002 (%s: %u)", Translate("Connecting to"), si.sNetwork.c_str(), si.sServer.c_str(), si.iPort);
+ DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, szTemp, NULL, NULL, NULL, true, false);
+
+ return;
+}
+
+void DisconnectFromServer(void)
+{
+ GCEVENT gce = {0};
+ GCDEST gcd = {0};
+
+ if (prefs->Perform && g_ircSession) {
+ DoPerform("Event: Disconnect");
+ }
+
+ gcd.iType = GC_EVENT_CONTROL;
+ gcd.pszID = NULL; // all windows
+ gcd.pszModule = IRCPROTONAME;
+ gce.cbSize = sizeof(GCEVENT);
+ gce.pDest = &gcd;
+
+ CallChatEvent( SESSION_TERMINATE, (LPARAM)&gce);
+ forkthread(DisconnectServerThread, 0, NULL );
+
+ return;
+}
+
+static int Service_SetStatus(WPARAM wParam,LPARAM lParam)
+{
+
+ if (!bChatInstalled)
+ {
+ MIRANDASYSTRAYNOTIFY msn;
+ msn.cbSize = sizeof(MIRANDASYSTRAYNOTIFY);
+ msn.szProto = IRCPROTONAME;
+ msn.szInfoTitle = Translate("Information");
+ msn.szInfo = Translate("This protocol is dependent on another plugin named \'Chat\'\nPlease download it from the Miranda IM website!");
+ msn.dwInfoFlags = NIIF_ERROR;
+ msn.uTimeout = 15000;
+ CallService(MS_CLIST_SYSTRAY_NOTIFY, (WPARAM)NULL,(LPARAM) &msn);
+ return 0;
+ }
+ if (wParam != ID_STATUS_OFFLINE && lstrlen(prefs->Network) <1)
+ {
+ if (lstrlen(prefs->Nick) > 0 && !prefs->DisableDefaultServer)
+ {
+ HWND hwnd=CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_QUICKCONN),NULL,QuickWndProc);
+ SetWindowText(hwnd, "Miranda IRC");
+ SetWindowText(GetDlgItem(hwnd, IDC_TEXT), Translate("Please choose an IRC-network to go online. This network will be the default."));
+ SetWindowText(GetDlgItem(hwnd, IDC_CAPTION), Translate("Default network"));
+ HICON hIcon = LoadIconEx(IDI_MAIN,"main",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON));
+ SendMessage(hwnd, WM_SETICON, ICON_BIG,(LPARAM)hIcon);
+ ShowWindow(hwnd, SW_SHOW);
+ SetActiveWindow(hwnd);
+ }
+ return 0;
+ }
+ if (wParam != ID_STATUS_OFFLINE && (lstrlen(prefs->Nick) <1 || lstrlen(prefs->UserID) < 1 || lstrlen(prefs->Name) < 1))
+ {
+ MIRANDASYSTRAYNOTIFY msn;
+ msn.cbSize = sizeof(MIRANDASYSTRAYNOTIFY);
+ msn.szProto = IRCPROTONAME;
+ msn.szInfoTitle = Translate("IRC error");
+ msn.szInfo = Translate("Connection can not be established! You have not completed all necessary fields (Nickname, User ID and Name)." );
+ msn.dwInfoFlags = NIIF_ERROR;
+ msn.uTimeout = 15000;
+ CallService(MS_CLIST_SYSTRAY_NOTIFY, (WPARAM)NULL,(LPARAM) &msn);
+ return 0;
+ }
+ if (wParam == ID_STATUS_FREECHAT && prefs->Perform && g_ircSession)
+ DoPerform("Event: Free for chat" );
+ if (wParam == ID_STATUS_ONTHEPHONE && prefs->Perform && g_ircSession)
+ DoPerform("Event: On the phone");
+ if (wParam == ID_STATUS_OUTTOLUNCH && prefs->Perform && g_ircSession)
+ DoPerform("Event: Out for lunch");
+ if (wParam == ID_STATUS_ONLINE && prefs->Perform && g_ircSession && (GlobalStatus ==ID_STATUS_ONTHEPHONE ||GlobalStatus ==ID_STATUS_OUTTOLUNCH) && OldStatus !=ID_STATUS_AWAY)
+ DoPerform("Event: Available" );
+ if (lParam != 1)
+ GlobalStatus = wParam;
+
+ // clear custom status on status change
+ if (wParam != OldStatus)
+ if (IRCGetContactSettingByte(NULL, "XStatusReset", DEFAULT_XSTATUS_RESET))
+ IRCSetXStatus(0, 0);
+
+ if ((wParam == ID_STATUS_ONLINE || wParam == ID_STATUS_AWAY || wParam == ID_STATUS_FREECHAT) && !g_ircSession ) //go from offline to online
+ ConnectToServer();
+ else if ((wParam == ID_STATUS_ONLINE || wParam == ID_STATUS_FREECHAT) && g_ircSession && OldStatus == ID_STATUS_AWAY) //go to online while connected
+ {
+ StatusMessage = "";
+ PostIrcMessage( "/AWAY");
+ return 0;
+ }
+ else if (wParam == ID_STATUS_OFFLINE && g_ircSession) //go from online/away to offline
+ DisconnectFromServer();
+ else if (wParam == ID_STATUS_OFFLINE && !g_ircSession) //offline to offline
+ {
+ KillChatTimer( RetryTimer);
+ return 0;
+ }
+ else if (wParam == ID_STATUS_AWAY && g_ircSession) //go to away while connected
+ return 0;
+ else if (wParam == ID_STATUS_ONLINE && g_ircSession) //already online
+ return 0;
+ else
+ Service_SetStatus(ID_STATUS_AWAY, 1);
+ return 0;
+}
+
+static int Service_GetStatus(WPARAM wParam,LPARAM lParam)
+{
+ if (OldStatus == ID_STATUS_CONNECTING)
+ return ID_STATUS_CONNECTING;
+ else if (g_ircSession && OldStatus == ID_STATUS_ONLINE)
+ return ID_STATUS_ONLINE;
+ else if (g_ircSession && OldStatus == ID_STATUS_AWAY)
+ return ID_STATUS_AWAY;
+ else
+ return ID_STATUS_OFFLINE;
+}
+
+static int Service_SetAwayMsg(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam != ID_STATUS_ONLINE && wParam != ID_STATUS_INVISIBLE && wParam != ID_STATUS_FREECHAT && wParam != ID_STATUS_CONNECTING && wParam != ID_STATUS_OFFLINE)
+ {
+ if (StatusMessage == "" || lParam == NULL || StatusMessage != ReplaceString((char *)lParam, "\r\n", " ") )
+ {
+ if(lParam == NULL || *(char*)lParam == '\0')
+ StatusMessage = STR_AWAYMESSAGE;
+ else
+ StatusMessage = ReplaceString((char *)lParam, "\r\n", " ");
+
+ PostIrcMessage( "/AWAY %s", (StatusMessage.substr(0,450)).c_str());
+ }
+ }
+ return 0;
+}
+
+static int Service_AddIncMessToDB(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam;
+
+ DBDeleteContactSetting(ccs->hContact, "CList", "Hidden");
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = IRCPROTONAME;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = pre->flags & (PREF_CREATEREAD ? DBEF_READ : 0);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.cbBlob = strlen(pre->szMessage) + 1;
+ dbei.pBlob = (PBYTE) pre->szMessage;
+ CallService(MS_DB_EVENT_ADD, (WPARAM) ccs->hContact, (LPARAM) & dbei);
+ return 0;
+}
+
+static void __cdecl AckMessageFail(void * lParam)
+{
+ ProtoBroadcastAck(IRCPROTONAME, (void*)lParam, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE) 1, (LONG)Translate("The protocol is not online"));
+}
+
+static void __cdecl AckMessageFailDcc(void * lParam)
+{
+ ProtoBroadcastAck(IRCPROTONAME, (void*)lParam, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE) 1, (LONG)Translate("The dcc chat connection is not active"));
+}
+
+static void __cdecl AckMessageSuccess(void * lParam)
+{
+ ProtoBroadcastAck(IRCPROTONAME, (void*)lParam, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
+}
+
+static int Service_GetMessFromSRMM(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *) lParam;
+
+ BYTE bDcc = DBGetContactSettingByte(ccs->hContact, IRCPROTONAME, "DCC", 0) ;
+ WORD wStatus = DBGetContactSettingWord(ccs->hContact, IRCPROTONAME, "Status", ID_STATUS_OFFLINE) ;
+ if (OldStatus !=ID_STATUS_OFFLINE && OldStatus !=ID_STATUS_CONNECTING && !bDcc || bDcc && wStatus == ID_STATUS_ONLINE) {
+ PostIrcMessageWnd(NULL, ccs->hContact, (char *) ccs->lParam);
+ forkthread(AckMessageSuccess, 0, ccs->hContact);
+ }
+ else
+ {
+ if(bDcc)
+ forkthread(AckMessageFailDcc, 0, ccs->hContact);
+ else
+ forkthread(AckMessageFail, 0, ccs->hContact);
+ }
+
+ return 1;
+}
+
+static int Service_GetAwayMessage(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ WhoisAwayReply = "";
+ DBVARIANT dbv;
+
+ // bypass chat contacts.
+ if(DBGetContactSettingByte(ccs->hContact, IRCPROTONAME, "ChatRoom", 0) == 0)
+
+ if (ccs->hContact && !DBGetContactSetting(ccs->hContact, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ )
+ {
+ int i = DBGetContactSettingWord(ccs->hContact,IRCPROTONAME, "Status", ID_STATUS_OFFLINE);
+
+// if ( i != ID_STATUS_OFFLINE)
+// {
+// if(DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusEnabled", 0) && DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusAuto", 0))
+// if(strcmp(UniGetContactSettingUtf(ccs->hContact,IRCPROTONAME, "MirVer", ""), "Miranda"))
+// {
+// #ifdef _DEBUG
+// DBGprintf("XSTATUS REQUESTED from %s\n", dbv.pszVal);
+// #endif
+// PostIrcMessage( "/PRIVMSG %s \001XSTATUS\001", dbv.pszVal);
+// }
+// }
+
+ if ( i != ID_STATUS_AWAY)
+ {
+ DBFreeVariant( &dbv);
+ return 0;
+ }
+
+ whois_popup = false;
+ String S="WHOIS " + (String)dbv.pszVal ;
+ if (g_ircSession)
+ g_ircSession << CIrcMessage(S.c_str(), false, false);
+ DBFreeVariant( &dbv);
+ }
+
+ return 1;
+}
+
+static int Service_InitUserInfo(WPARAM wParam, LPARAM lParam)
+{
+ char *szProto;
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, lParam, 0);
+ DBVARIANT dbv;
+ HANDLE hContact = (HANDLE) lParam;
+ if (!hContact || !szProto || lstrcmpi(szProto, IRCPROTONAME))
+ {
+ return 0;
+ }
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0) != 0)
+ return 0;
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "DCC", 0) != 0)
+ return 0;
+
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ if (IsChannel(dbv.pszVal))
+ {
+ DBFreeVariant(&dbv);
+ return 0;
+ }
+ DBFreeVariant(&dbv);
+ }
+
+ OPTIONSDIALOGPAGE odp;
+ odp.cbSize = sizeof(odp);
+ odp.pszTitle = ALTIRCPROTONAME;
+ odp.hIcon = NULL;
+ odp.hInstance = g_hInstance;
+ odp.position = -1900000000;
+ odp.pfnDlgProc = UserDetailsDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_USERINFO);
+ odp.pszTitle = ALTIRCPROTONAME;
+ CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM) & odp);
+ return 0;
+}
+
+static void CListShowMenuItem(HANDLE hMenuItem, BYTE bShow)
+{
+ CLISTMENUITEM mi = {0};
+
+ mi.cbSize = sizeof(mi);
+// Menu modification
+ if (bShow || !prefs->XStatusAuto)
+ 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);
+}
+
+static int PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
+{
+ BYTE bXStatus;
+
+// if(IRCGetContactSettingByte((HANDLE)wParam, "ChatRoom", 0) != 0)
+// {
+// CListShowMenuItem(hUserMenuXStatus, 0);
+// return 0;
+// }
+
+ bXStatus = IRCGetContactSettingByte((HANDLE)wParam, DBSETTING_XSTATUSID, 0);
+ CListShowMenuItem(hUserMenuXStatus, bXStatus);
+ if (bXStatus)
+ {
+ HICON iXStatus = GetXStatusIcon(bXStatus);
+ CListSetMenuItemIcon(hUserMenuXStatus, iXStatus);
+
+ if (iXStatus && !IconLibInstalled())
+ DestroyIcon(iXStatus); // release icon
+ }
+
+ return 0;
+}
+
+static int IconLibIconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ CListSetMenuItemIcon(hMenuQuick, IconLibProcess(LoadIconEx(IDI_QUICK,"quick",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "quick"));
+ CListSetMenuItemIcon(hMenuJoin, IconLibProcess(LoadIconEx(IDI_JOIN,"join",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "join"));
+ CListSetMenuItemIcon(hMenuNick, IconLibProcess(LoadIconEx(IDI_WHOIS,"whois",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "whois"));
+ CListSetMenuItemIcon(hMenuList, IconLibProcess(LoadIconEx(IDI_LIST,"list",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "list"));
+ CListSetMenuItemIcon(hMenuServer, IconLibProcess(LoadIconEx(IDI_SERVER,"server",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "server"));
+ CListSetMenuItemIcon(hMenuAvatar, IconLibProcess(LoadIconEx(IDI_AVATAR,"avatar",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "avatar"));
+
+ ChangedIconsXStatus();
+ return 0;
+}
+
+static int Service_ModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ char szTemp[MAX_PATH];
+ char szTemp3[256];
+ NETLIBUSER nlu = {0};
+
+ DBDeleteContactSetting(NULL, IRCPROTONAME, "JTemp");
+
+ InitIconLib();
+ hHookUserMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu);
+ hHookIconsChanged = IconLibHookIconsChanged(IconLibIconsChanged);
+
+ // Initialize IconLib icons
+ InitIcons();
+
+ InitXStatusIcons();
+ InitXStatusEvents();
+ InitXStatusItems(FALSE);
+
+ // Init extra optional modules
+ InitPopUps();
+
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_OUTGOING|NUF_INCOMING|NUF_HTTPCONNS;
+ nlu.szSettingsModule = IRCPROTONAME;
+ wsprintf(szTemp, Translate("%s server connection"), ALTIRCPROTONAME);
+ nlu.szDescriptiveName = szTemp;
+ hNetlib=(HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+
+ char szTemp2[256];
+ nlu.flags = NUF_OUTGOING|NUF_INCOMING|NUF_HTTPCONNS;
+ mir_snprintf(szTemp2, sizeof(szTemp2), "%s DCC", IRCPROTONAME);
+ nlu.szSettingsModule = szTemp2;
+ wsprintf(szTemp, Translate("%s client-to-client connections"), ALTIRCPROTONAME);
+ nlu.szDescriptiveName = szTemp;
+ hNetlibDCC=(HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+
+ //add as a known module in DB Editor ++
+ CallService("DBEditorpp/RegisterSingleModule",(WPARAM)IRCPROTONAME,0);
+ mir_snprintf(szTemp3, sizeof(szTemp3), "%s DCC", IRCPROTONAME);
+ CallService("DBEditorpp/RegisterSingleModule",(WPARAM)szTemp3,0);
+
+ // updater plugin support
+ if(ServiceExists(MS_UPDATE_REGISTER))
+ {
+ Update upd = {0};
+ char szCurrentVersion[30];
+ char *szVersionUrl = "http://dev.mirandaim.ru/iron/IRC/version.txt";
+ char *szUpdateUrl = "http://dev.mirandaim.ru/iron/files/IRC.zip";
+// char *szFLVersionUrl = "http://addons.miranda-im.org/details.php?action=viewfile&id=2951";
+// char *szFLUpdateurl = "http://addons.miranda-im.org/feed.php?dlfile=2951";
+ char *szPrefix = "IRC ";
+
+ upd.cbSize = sizeof(upd);
+ upd.szComponentName = pluginInfo.shortName;
+ upd.pbVersion = (BYTE *)CreateVersionStringPlugin(&pluginInfo, szCurrentVersion);
+ upd.cpbVersion = strlen((char *)upd.pbVersion);
+// upd.szVersionURL = szFLVersionUrl;
+// upd.szUpdateURL = szFLUpdateurl;
+// upd.pbVersionPrefix = (BYTE *)"<span class=\"fileNameHeader\">Updater ";
+
+ upd.szBetaUpdateURL = szUpdateUrl;
+ upd.szBetaVersionURL = szVersionUrl;
+ upd.pbBetaVersionPrefix = (BYTE *)szPrefix;
+ upd.pbVersion = (PBYTE)szCurrentVersion;
+ upd.cpbVersion = lstrlenA(szCurrentVersion);
+
+// upd.cpbVersionPrefix = strlen((char *)upd.pbVersionPrefix);
+ upd.cpbBetaVersionPrefix = strlen((char *)upd.pbBetaVersionPrefix);
+
+ CallService(MS_UPDATE_REGISTER, 0, (LPARAM)&upd);
+ }
+
+ if(ServiceExists("MBot/GetFcnTable"))
+ {
+ CallService(MS_MBOT_REGISTERIRC, 0, (LPARAM)IRCPROTONAME);
+ bMbotInstalled = TRUE;
+ }
+
+ if(ServiceExists(MS_GC_REGISTER))
+ {
+ GCREGISTER gcr = {0};
+
+ GCPTRS gp = {0};
+ CallService(MS_GC_GETEVENTPTR, 0, (LPARAM)&gp);
+ pfnAddEvent = gp.pfnAddEvent;
+
+ gcr.cbSize = sizeof(GCREGISTER);
+ gcr.dwFlags = GC_CHANMGR|GC_BOLD|GC_ITALICS|GC_UNDERLINE|GC_COLOR|GC_BKGCOLOR;
+ gcr.iMaxText = 0;
+ gcr.nColors = 16;
+ gcr.pColors = prefs->colors;
+ gcr.pszModuleDispName = IRCPROTONAME;
+ gcr.pszModule = IRCPROTONAME;
+ CallService(MS_GC_REGISTER, NULL, (LPARAM)&gcr);
+ g_hGCUserEvent = HookEvent(ME_GC_EVENT, Service_GCEventHook);
+ g_hGCMenuBuild = HookEvent(ME_GC_BUILDMENU, Service_GCMenuHook );
+
+ GCSESSION gcw = {0};
+ GCDEST gcd = {0};
+ GCEVENT gce = {0};
+
+ gcw.cbSize = sizeof(GCSESSION);
+ gcw.iType = GCW_SERVER;
+ gcw.pszID = "Network log";
+ gcw.pszModule = IRCPROTONAME;
+ gcw.pszName = Translate("Offline");
+ CallService(MS_GC_NEWSESSION, 0, (LPARAM)&gcw);
+
+ gce.cbSize = sizeof(GCEVENT);
+ gce.pDest = &gcd;
+ gcd.pszID = "Network log";
+ gcd.pszModule = IRCPROTONAME;
+ gcd.iType = GC_EVENT_CONTROL;
+
+ gce.pDest = &gcd;
+ if (prefs->UseServer && !prefs->HideServerWindow)
+ CallChatEvent( WINDOW_VISIBLE, (LPARAM)&gce);
+ else
+ CallChatEvent( WINDOW_HIDDEN, (LPARAM)&gce);
+ bChatInstalled = TRUE;
+
+ }
+ else
+ {
+ if(IDYES == MessageBoxA(0,Translate("The IRC protocol depends on another plugin called \'Chat\'\n\nDo you want to download it from the Miranda IM web site now?"),Translate("Information"),MB_YESNO|MB_ICONINFORMATION))
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM) "http://www.miranda-im.org/download/details.php?action=viewfile&id=1309");
+ }
+
+ mir_snprintf(szTemp, sizeof(szTemp), "%s\\%s_servers.ini", mirandapath, IRCPROTONAME);
+ pszServerFile = IrcLoadFile(szTemp);
+
+ mir_snprintf(szTemp, sizeof(szTemp), "%s\\%s_perform.ini", mirandapath, IRCPROTONAME);
+ pszPerformFile = IrcLoadFile(szTemp);
+
+ mir_snprintf(szTemp, sizeof(szTemp), "%s\\%s_ignore.ini", mirandapath, IRCPROTONAME);
+ pszIgnoreFile = IrcLoadFile(szTemp);
+
+ InitMenus();
+
+ g_hUserInfoInit = HookEvent(ME_USERINFO_INITIALISE, Service_InitUserInfo);
+ g_hMenuCreation = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, Service_MenuPreBuild );
+ g_hOptionsInit = HookEvent(ME_OPT_INITIALISE, InitOptionsPages);
+
+ if (lstrlen(prefs->Nick) == 0)
+ CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_INIT),NULL, InitWndProc);
+ else
+ {
+ if (lstrlen(prefs->AlternativeNick) == 0)
+ {
+ mir_snprintf(szTemp, 30, "%s%u", prefs->Nick, rand()%9999);
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "AlernativeNick", szTemp);
+ lstrcpyn(prefs->AlternativeNick, szTemp, 30);
+ }
+ if (lstrlen(prefs->Name) == 0)
+ {
+ mir_snprintf(szTemp, 30, "Miranda%u", rand()%9999);
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "Name", szTemp);
+ lstrcpyn(prefs->Name, szTemp, 200);
+ }
+ }
+ return 0;
+}
+
+void HookEvents(void)
+{
+ g_hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, Service_ModulesLoaded);
+// g_hContactDblClick= HookEvent(ME_CLIST_DOUBLECLICKED, Service_ContactDoubleclicked);
+ g_hSystemPreShutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, Service_SystemPreShutdown);
+ g_hContactDeleted = HookEvent(ME_DB_CONTACT_DELETED, Service_UserDeletedContact );
+// g_hIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, Service_IconsChanged );
+
+ return;
+}
+
+void UnhookEvents(void)
+{
+ UnhookEvent(g_hModulesLoaded);
+ UnhookEvent(g_hSystemPreShutdown);
+// UnhookEvent(g_hContactDblClick);
+ UnhookEvent(g_hContactDeleted);
+ UnhookEvent(g_hUserInfoInit);
+ UnhookEvent(g_hMenuCreation);
+ UnhookEvent(g_hGCUserEvent);
+ UnhookEvent(g_hGCMenuBuild);
+ UnhookEvent(g_hIconsChanged);
+ Netlib_CloseHandle(hNetlib);
+ Netlib_CloseHandle(hNetlibDCC);
+ return;
+}
+
+int Service_GetAvatarInfo(WPARAM wParam, LPARAM lParam)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: Service_GetAvatarInfo\n");
+// #endif
+
+ PROTO_AVATAR_INFORMATION* pai = (PROTO_AVATAR_INFORMATION*)lParam;
+// DWORD dwUIN;
+// uid_str szUID;
+ DBVARIANT dbv;
+ int dwPaFormat;
+
+ if (!prefs->AvatarsEnabled) return GAIR_NOAVATAR;
+
+ if (IRCGetContactSetting(pai->hContact, "AvatarHash", &dbv) || dbv.cpbVal != 0x14)
+ return GAIR_NOAVATAR; // we did not found avatar hash or hash invalid - no avatar available
+
+// if (ICQGetContactSettingUID(pai->hContact, &dwUIN, &szUID))
+// {
+// ICQFreeVariant(&dbv);
+// return GAIR_NOAVATAR; // we do not support avatars for invalid contacts
+// }
+
+ dwPaFormat = IRCGetContactSettingByte(pai->hContact, "AvatarType", PA_FORMAT_UNKNOWN);
+ if (dwPaFormat != PA_FORMAT_UNKNOWN)
+ { // we know the format, test file
+// GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, pai->filename, MAX_PATH);
+
+ pai->format = dwPaFormat;
+
+ if (!IsAvatarSaved(pai->hContact, (char *)dbv.pbVal))
+ { // hashes are the same
+ if (access(pai->filename, 0) == 0)
+ {
+ IRCFreeVariant(&dbv);
+ return GAIR_SUCCESS; // we have found the avatar file, whoala
+ }
+ }
+ }
+
+ if (IsAvatarSaved(pai->hContact, (char *)dbv.pbVal))
+ { // we didn't received the avatar before - this ensures we will not request avatar again and again
+ if ((wParam & GAIF_FORCE) != 0 && pai->hContact != 0)
+ { // request avatar data
+// GetAvatarFileName(dwUIN, szUID, pai->filename, MAX_PATH);
+// GetAvatarData(pai->hContact, dwUIN, szUID, dbv.pbVal, dbv.cpbVal, pai->filename);
+ IRCFreeVariant(&dbv);
+ return GAIR_WAITFOR;
+ }
+ }
+ IRCFreeVariant(&dbv);
+
+ return GAIR_NOAVATAR;
+}
+
+int Service_GetMaxAvatarSize(WPARAM wParam, LPARAM lParam)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: Service_GetMaxAvatarSize\n");
+// #endif
+
+ if (wParam) *((int*)wParam) = 64;
+ if (lParam) *((int*)lParam) = 64;
+ return 0;
+}
+
+int Service_AvatarFormatSupported(WPARAM wParam, LPARAM lParam)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: Service_AvatarFormatSupported\n");
+// #endif
+
+ if (lParam == PA_FORMAT_JPEG || lParam == PA_FORMAT_GIF)
+ return -2;
+ else
+ return 0;
+}
+
+int Service_GetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: Service_GetMyAvatar\n");
+// #endif
+
+ if (!prefs->AvatarsEnabled) return -2;
+
+ if (!wParam) return -3;
+
+ if (!IRCGetContactStaticString(NULL, "AvatarFile", (char*)wParam, (int)lParam))
+ {
+ if (!access((char*)wParam, 0)) return 0;
+ }
+ return -1;
+}
+
+int Service_SetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+// #ifdef _DEBUG
+// DBGprintf( "Event: Service_SetMyAvatar\n");
+// #endif
+
+ char* szFile = (char*)lParam;
+ int iRet = -1;
+
+ if (!prefs->AvatarsEnabled) return -2;
+
+ if (szFile)
+ { // set file for avatar
+ char szMyFile[MAX_PATH+1];
+ int dwPaFormat = DetectAvatarFormat(szFile);
+ char* hash;
+ HBITMAP avt;
+
+ avt = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szFile);
+ if (!avt) return iRet;
+ DeleteObject(avt);
+
+ GetFullAvatarFileName(0, NULL, dwPaFormat, szMyFile, MAX_PATH);
+ if (!CopyFile(szFile, szMyFile, FALSE))
+ return iRet;
+
+ hash = calcMD5Hash(szMyFile);
+ if (hash)
+ {
+ char* ihash = (char*)_alloca(0x14);
+ // upload hash to server
+ ihash[0] = 0; //unknown
+ ihash[1] = 1; //hash type
+ ihash[2] = 1; //hash status
+ ihash[3] = 0x10; //hash len
+ memcpy(ihash+4, hash, 0x10);
+
+ IRCWriteContactSettingBlob(NULL, "AvatarHash", ihash, 0x14);
+ IRCWriteContactSettingString(NULL, "AvatarFile", szMyFile);
+
+ iRet = 0;
+ SAFE_FREE((void **)&hash);
+ }
+ }
+ else
+ { // delete user avatar
+ IRCDeleteContactSetting(NULL, "AvatarFile");
+ IRCDeleteContactSetting(NULL, "AvatarHash");
+ iRet = 0;
+ }
+
+ return iRet;
+}
+
+void CreateServiceFunctions(void)
+{
+ char temp[MAXMODULELABELLENGTH];
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PS_GETCAPS);
+ CreateServiceFunction(temp, Service_GetCaps);
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PS_GETNAME);
+ CreateServiceFunction(temp,Service_GetName);
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PS_LOADICON);
+ CreateServiceFunction(temp,Service_LoadIcon);
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PS_SETSTATUS);
+ CreateServiceFunction(temp,Service_SetStatus);
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PS_GETSTATUS);
+ CreateServiceFunction(temp,Service_GetStatus);
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PS_SETAWAYMSG);
+ CreateServiceFunction(temp, Service_SetAwayMsg);
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PS_BASICSEARCH);
+ CreateServiceFunction(temp, Service_BasicSearch);
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PS_ADDTOLIST);
+ CreateServiceFunction(temp, Service_AddToList);
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PSR_MESSAGE);
+ CreateServiceFunction(temp,Service_AddIncMessToDB);
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PSS_MESSAGE);
+ CreateServiceFunction(temp, Service_GetMessFromSRMM);
+
+ wsprintf(temp, "%s%s", IRCPROTONAME, PSS_GETAWAYMSG);
+ CreateServiceFunction(temp, Service_GetAwayMessage);
+
+ wsprintf(temp,"%s/JoinChannelMenu", IRCPROTONAME);
+ CreateServiceFunction(temp,Service_JoinMenuCommand);
+
+ wsprintf(temp,"%s/QuickConnectMenu", IRCPROTONAME);
+ CreateServiceFunction(temp,Service_QuickConnectMenuCommand);
+
+ wsprintf(temp,"%s/ChangeNickMenu", IRCPROTONAME);
+ CreateServiceFunction(temp,Service_ChangeNickMenuCommand);
+
+ wsprintf(temp,"%s/ShowListMenu", IRCPROTONAME);
+ CreateServiceFunction(temp,Service_ShowListMenuCommand);
+
+ wsprintf(temp,"%s/ShowServerMenu", IRCPROTONAME);
+ CreateServiceFunction(temp,Service_ShowServerMenuCommand);
+
+ wsprintf(temp,"%s/SetAvatarMenu", IRCPROTONAME);
+ CreateServiceFunction(temp, Service_SetAvatarMenuCommand);
+
+ wsprintf(temp,"%s/Menu1ChannelMenu", IRCPROTONAME);
+ CreateServiceFunction(temp,Service_Menu1Command);
+
+ wsprintf(temp,"%s/Menu2ChannelMenu", IRCPROTONAME);
+ CreateServiceFunction(temp,Service_Menu2Command);
+
+ wsprintf(temp,"%s/Menu3ChannelMenu", IRCPROTONAME);
+ CreateServiceFunction(temp,Service_Menu3Command);
+
+ wsprintf(temp,"%s/DblClickEvent", IRCPROTONAME);
+ CreateServiceFunction(temp, Service_EventDoubleclicked);
+
+ wsprintf(temp,"%s/InsertRawIn", IRCPROTONAME);
+ CreateServiceFunction(temp, Scripting_InsertRawIn);
+
+ wsprintf(temp,"%s/InsertRawOut", IRCPROTONAME);
+ CreateServiceFunction(temp, Scripting_InsertRawOut);
+
+ wsprintf(temp,"%s/InsertGuiIn", IRCPROTONAME);
+ CreateServiceFunction(temp, Scripting_InsertGuiIn);
+
+ wsprintf(temp,"%s/InsertGuiOut", IRCPROTONAME);
+ CreateServiceFunction(temp, Scripting_InsertGuiOut);
+
+ wsprintf(temp,"%s/GetIrcData", IRCPROTONAME);
+ CreateServiceFunction(temp, Scripting_GetIrcData);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PSS_FILEALLOW);
+ CreateServiceFunction(temp, Service_FileAllow);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PSS_FILEDENY);
+ CreateServiceFunction(temp, Service_FileDeny);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PSS_FILECANCEL);
+ CreateServiceFunction(temp, Service_FileCancel);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PSS_FILE);
+ CreateServiceFunction(temp, Service_FileSend);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PSR_FILE);
+ CreateServiceFunction(temp, Service_FileReceive);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_FILERESUME);
+ CreateServiceFunction(temp, Service_FileResume);
+
+// Typing Notify
+ wsprintf(temp,"%s%s", IRCPROTONAME, PSS_USERISTYPING);
+ CreateServiceFunction(temp, Service_SendUserIsTyping);
+
+// Nudge
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_SEND_NUDGE);
+ CreateServiceFunction(temp, Service_SendNudge);
+
+//Begin Custom Status API
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_SETCUSTOMSTATUS);
+ CreateServiceFunction(temp, IRCSetXStatus);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_GETCUSTOMSTATUSICON);
+ CreateServiceFunction(temp, IRCGetXStatusIcon);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_GETCUSTOMSTATUS);
+ CreateServiceFunction(temp, IRCGetXStatus);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_REQUESTCUSTOMSTATUS);
+ CreateServiceFunction(temp, IRCRequestXStatusDetails);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, MS_XSTATUS_SHOWDETAILS);
+ CreateServiceFunction(temp, IRCShowXStatusDetails);
+//End Custom Status API
+
+// Begin Avatar API
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_IRC_GETMYAVATARMAXSIZE);
+ CreateServiceFunction(temp, Service_GetMaxAvatarSize);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_IRC_ISAVATARFORMATSUPPORTED);
+ CreateServiceFunction(temp, Service_AvatarFormatSupported);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_IRC_GETMYAVATAR);
+ CreateServiceFunction(temp, Service_GetMyAvatar);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_IRC_SETMYAVATAR);
+ CreateServiceFunction(temp, Service_SetMyAvatar);
+
+ wsprintf(temp,"%s%s", IRCPROTONAME, PS_GETAVATARINFO);
+ CreateServiceFunction(temp, Service_GetAvatarInfo);
+// End Avatar API
+
+ return;
+}
+
+void handleNudgeNotification(const char* NickName)
+{
+ if(ServiceExists(MS_NUDGE_SEND))
+ {
+ HANDLE hContact = GetContactByName(NickName);
+ if(hContact)
+ {
+ #ifdef _DEBUG
+ DBGprintf( "Event: NudgeNotification (TRUE)\n");
+ #endif
+
+ DBVARIANT dbv1;
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 0)
+ DoUserhostWithReason(1, ((String)"S" + NickName).c_str(), true, NickName);
+ else
+ {
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv1) && dbv1.type == DBVT_ASCIIZ)
+ {
+ DoUserhostWithReason(2, ((String)"S" + dbv1.pszVal).c_str(), true, dbv1.pszVal);
+ DBFreeVariant(&dbv1);
+ }
+ else
+ {
+ DoUserhostWithReason(2, ((String)"S" + NickName).c_str(), true, NickName);
+ }
+ }
+
+ NotifyEventHooks(hIRCNudge,WPARAM(hContact),0);
+ }
+ else
+ {
+ #ifdef _DEBUG
+ DBGprintf( "Event: NudgeNotification (FALSE)\n");
+ #endif
+
+ }
+ }
+}
+
+void handleTypingNotification(const char* NickName, WORD wMTNCode)
+{
+ LPARAM lParam;
+
+ if(prefs->TypingEnabled)
+ {
+ switch (wMTNCode)
+ {
+ case MTN_TYPED:
+ lParam = PROTOTYPE_CONTACTTYPING_OFF;
+ break;
+ case MTN_BEGUN:
+ lParam = (LPARAM)60;
+ break;
+ default:
+ break;
+ }
+
+ HANDLE hContact = GetContactByName(NickName);
+ DBWriteContactSettingByte(hContact,"SRMsg", "SupportTyping", 1);
+ if (hContact)
+ {
+ DBVARIANT dbv1;
+
+ if(DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 0)
+ DoUserhostWithReason(1, ((String)"S" + NickName).c_str(), true, NickName);
+ else
+ {
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv1) && dbv1.type == DBVT_ASCIIZ)
+ {
+ DoUserhostWithReason(2, ((String)"S" + dbv1.pszVal).c_str(), true, dbv1.pszVal);
+ DBFreeVariant(&dbv1);
+ }
+ else
+ {
+ DoUserhostWithReason(2, ((String)"S" + NickName).c_str(), true, NickName);
+ }
+ }
+
+ }
+
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, lParam);
+ }
+}
+
+void handleXStatus(const char* NickName)
+{
+ BYTE bXStatus = NULL;
+ char *szName;
+
+ if(DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusEnabled", 0))
+ {
+ bXStatus = IRCGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+ szName = UniGetContactSettingUtf(NULL, ALTIRCPROTONAME, DBSETTING_XSTATUSNAME, "");
+ String szText = UniGetContactSettingUtf(NULL, ALTIRCPROTONAME, DBSETTING_XSTATUSMSG, "");
+ szText = ReplaceString( (char *)szText.c_str(), "\r\n", "\005");
+ PostIrcMessage("/NOTICE %s \001XSTATUS %d %s\004%s\001", NickName, bXStatus, szName, szText.c_str());
+ }
+ else
+ PostIrcMessage("/NOTICE %s \001XSTATUS OFF\001", NickName);
+}
+
+void handleAvatarHash(const char* NickName)
+{
+ DBVARIANT dbvHash;
+
+ if(!IRCGetContactSetting(NULL, "AvatarHash", &dbvHash))
+ {
+ char hash[50]="",h[9],path[255];
+ for(int i=0;i<20;i+=4)
+ {
+ sprintf(h,"%.8X",*((unsigned int*)(dbvHash.pbVal+i)));
+ strcat(hash,h);
+ }
+ IRCFreeVariant(&dbvHash);
+ IRCGetContactSettingString(NULL,"AvatarPath",path);
+// #ifdef _DEBUG
+// DBGprintf("AvatarHash = %s\n", hash);
+// #endif
+ PostIrcMessage("/NOTICE %s \001AVATAR %s %s\001", NickName, hash, path);
+ }
+}
+
+void sendTypingNotification(HANDLE hContact, WORD wMTNCode)
+{
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING dcs;
+
+ dcs.szModule=IRCPROTONAME;
+ dcs.szSetting="Nick";
+ dcs.pValue=&dbv;
+ dbv.type=DBVT_ASCIIZ;
+ CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&dcs);
+
+ switch (wMTNCode)
+ {
+ case MTN_BEGUN:
+ PostIrcMessage( "/PRIVMSG %s \001TYPINGSTART\001", dbv.pszVal);
+ break;
+ case MTN_FINISHED:
+ PostIrcMessage( "/PRIVMSG %s \001TYPINGSTOP\001", dbv.pszVal);
+ break;
+ default:
+ break;
+ }
+
+ DBFreeVariant(&dbv);
+
+ return;
+}
+
+
+VOID CALLBACK RetryTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
+{
+ if (RetryCount <= StrToInt(prefs->RetryCount) && prefs->Retry)
+ {
+ char szTemp[300];
+ PortCount++;
+ if (PortCount > StrToInt(prefs->PortEnd) || StrToInt(prefs->PortEnd) ==0)
+ PortCount = StrToInt(prefs->PortStart);
+ si.iPort = PortCount;
+
+ mir_snprintf(szTemp, sizeof(szTemp), "\0033%s \002%s\002 (%s: %u, try %u)", Translate("Reconnecting to"), si.sNetwork.c_str(), si.sServer.c_str(), si.iPort, RetryCount);
+
+ DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, szTemp, NULL, NULL, NULL, true, false);
+
+ if (!bConnectThreadRunning)
+ {
+ forkthread(ConnectServerThread, 0, NULL );
+ }
+ else
+ bConnectRequested = true;
+
+ RetryCount++;
+ }
+ else
+ KillChatTimer(RetryTimer);
+}
+
diff --git a/irc_mod/tools.cpp b/irc_mod/tools.cpp
new file mode 100644
index 0000000..846da87
--- /dev/null
+++ b/irc_mod/tools.cpp
@@ -0,0 +1,925 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+extern char * IRCPROTONAME;
+extern String sChannelPrefixes;
+extern String sUserModes;
+extern String sUserModePrefixes;
+extern PREFERENCES * prefs;
+extern GETEVENTFUNC pfnAddEvent;
+extern bool bMbotInstalled;
+extern MM_INTERFACE mmi;
+
+std::vector<String> vUserhostReasons;
+std::vector<String> vWhoInProgress;
+
+
+struct FORK_ARG {
+ HANDLE hEvent;
+ void (__cdecl *threadcode)(void*);
+ unsigned (__stdcall *threadcodeex)(void*);
+ void *arg;
+};
+
+
+void AddToJTemp(String sCommand)
+{
+ DBVARIANT dbv;
+
+ if (!DBGetContactSetting(NULL, IRCPROTONAME, "JTemp", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ sCommand = (String)dbv.pszVal + (String)" " + sCommand;
+ DBFreeVariant(&dbv);
+ }
+
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "JTemp", sCommand.c_str());
+
+ return;
+}
+
+
+
+
+void __cdecl forkthread_r(void *param)
+{
+ struct FORK_ARG *fa=(struct FORK_ARG*)param;
+ void (*callercode)(void*)=fa->threadcode;
+ void *arg=fa->arg;
+
+ CallService(MS_SYSTEM_THREAD_PUSH,0,0);
+
+ SetEvent(fa->hEvent);
+
+ __try {
+ callercode(arg);
+ } __finally {
+ CallService(MS_SYSTEM_THREAD_POP,0,0);
+ }
+
+ return;
+}
+
+unsigned long forkthread ( void (__cdecl *threadcode)(void*),unsigned long stacksize,void *arg)
+{
+ unsigned long rc;
+ struct FORK_ARG fa;
+
+ fa.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
+ fa.threadcode=threadcode;
+ fa.arg=arg;
+
+ rc=_beginthread(forkthread_r,stacksize,&fa);
+
+ if ((unsigned long)-1L != rc) {
+ WaitForSingleObject(fa.hEvent,INFINITE);
+ }
+ CloseHandle(fa.hEvent);
+
+ return rc;
+}
+
+
+
+
+String GetWord(const char * text, int index)
+{
+ if(!text || !lstrlen(text))
+ return (String)"";
+
+ char * p1 = (char *)text;
+ char * p2 = NULL;
+ String S = "";
+
+ while (*p1 == ' ')
+ p1++;
+
+ if (*p1 != '\0')
+ {
+
+ for (int i =0; i < index; i++)
+ {
+ p2 = strchr(p1, ' ');
+
+ if (!p2)
+ p2 = strchr (p1, '\0');
+ else
+ while (*p2 == ' ')
+ p2++;
+
+ p1 = p2;
+ }
+
+
+
+ p2 = strchr(p1, ' ');
+ if(!p2)
+ p2 = strchr(p1, '\0');
+
+ if (p1 != p2)
+ {
+ char * pszTemp = new char[p2-p1+1];
+ lstrcpyn(pszTemp, p1, p2-p1+1);
+
+ S = pszTemp;
+ delete [] pszTemp;
+ }
+
+ }
+
+ return S;
+
+
+}
+
+
+
+char * GetWordAddress(const char * text, int index)
+{
+ if(!text || !lstrlen(text))
+ return (char *)text;
+
+ char *temp = (char*)text;
+
+ while (*temp == ' ')
+ temp++;
+
+ if (index == 0)
+ return (char *)temp;
+
+
+ for (int i =0; i < index; i++) {
+ temp = strchr(temp, ' ');
+ if (!temp)
+ temp = (char *)strchr (text, '\0');
+ else
+ while (*temp == ' ')
+ temp++;
+ text = temp;
+ }
+
+ return temp;
+}
+
+
+
+
+String RemoveLinebreaks(String Message)
+{
+
+ while (Message.find("\r\n\r\n", 0) != string::npos)
+ Message = ReplaceString(Message, "\r\n\r\n", "\r\n");
+
+ if (Message.find("\r\n", 0) == 0)
+ Message.erase(0,2);
+
+ if (Message.length() >1 && Message.rfind("\r\n", Message.length()) == Message.length()-2)
+ Message.erase(Message.length()-2, 2);
+
+ return Message;
+}
+
+
+
+String ReplaceString (String text, char * replaceme, char * newword)
+{
+ if (text != "" && replaceme != NULL)
+ {
+ int i = 0;
+
+ while (text.find(replaceme, i) != string::npos )
+ {
+ i = text.find(replaceme, i);
+ text.erase(i,lstrlen(replaceme));
+ text.insert(i, newword);
+ i = i + lstrlen(newword);
+ }
+
+ }
+
+ return text;
+}
+
+char * IrcLoadFile(char * szPath){
+ char * szContainer = NULL;
+ DWORD dwSiz = 0;
+ FILE *hFile = fopen(szPath,"rb");
+
+ if (hFile != NULL )
+ {
+ fseek(hFile,0,SEEK_END); // seek to end
+ dwSiz = ftell(hFile); // size
+ fseek(hFile,0,SEEK_SET); // seek back to original pos
+ szContainer = new char [dwSiz+1];
+ fread(szContainer, 1, dwSiz, hFile);
+ szContainer[dwSiz] = '\0';
+ fclose(hFile);
+
+ return szContainer;
+ }
+
+ return 0;
+}
+
+
+
+
+int WCCmp(char* wild, char *string)
+{
+ if ( wild == NULL || !lstrlen(wild) || string == NULL || !lstrlen(string))
+ return 1;
+ char *cp, *mp;
+
+ while ((*string) && (*wild != '*'))
+ {
+ if ((*wild != *string) && (*wild != '?')) {
+ return 0;
+ }
+ wild++;
+ string++;
+ }
+
+ while (*string)
+ {
+ if (*wild == '*') {
+ if (!*++wild) {
+ return 1;
+ }
+ mp = wild;
+ cp = string+1;
+ } else if ((*wild == *string) || (*wild == '?')) {
+ wild++;
+ string++;
+ } else {
+ wild = mp;
+ string = cp++;
+ }
+ }
+
+ while (*wild == '*') {
+ wild++;
+ }
+ return !*wild;
+}
+
+bool IsChannel(String sName)
+{
+ if(strchr(sChannelPrefixes.c_str(), sName[0]))
+ return true;
+
+ return false;
+}
+
+char* my_strstri(char *s1, char *s2)
+{
+ int i,j,k;
+ for(i=0;s1[i];i++)
+ for(j=i,k=0;tolower(s1[j])==tolower(s2[k]);j++,k++)
+ if(!s2[k+1])
+ return (s1+i);
+
+ return NULL;
+}
+
+char * DoColorCodes (const char * text, bool bStrip, bool bReplacePercent)
+{
+ static char szTemp[4000];
+ szTemp[0] = '\0';
+ char * p = &szTemp[0];
+ bool bBold = false;
+ bool bUnderline = false;
+ bool bItalics = false;
+
+ if(!text)
+ return szTemp;
+
+ while (*text != '\0')
+ {
+ int iFG = -1;
+ int iBG = -1;
+
+ switch(*text)
+ {
+ case '%': //escape
+ *p = '%';
+ p++;
+ if(bReplacePercent)
+ {
+ *p = '%';
+ p++;
+ }
+ text++;
+ break;
+
+ case 2: //bold
+ if(!bStrip)
+ {
+ *p = '%';
+ p++;
+ *p = bBold?'B':'b';
+ p++;
+ }
+ bBold = !bBold;
+ text++;
+ break;
+
+ case 15: //reset
+ if(!bStrip)
+ {
+ *p = '%';
+ p++;
+ *p = 'r';
+ p++;
+ }
+ bUnderline = false;
+ bBold = false;
+ text++;
+ break;
+
+ case 22: //italics
+ if(!bStrip)
+ {
+ *p = '%';
+ p++;
+ *p = bItalics?'I':'i';
+ p++;
+ }
+ bItalics = !bItalics;
+ text++;
+ break;
+
+ case 31: //underlined
+ if(!bStrip)
+ {
+ *p = '%';
+ p++;
+ *p = bUnderline?'U':'u';
+ p++;
+ }
+ bUnderline = !bUnderline;
+ text++;
+ break;
+
+ case 3: //colors
+ text++;
+
+ // do this if the colors should be reset to default
+ if(*text <= 47 || *text >= 58 || *text == '\0')
+ {
+ if(!bStrip)
+ {
+ *p = '%'; p++;
+ *p = 'C'; p++;
+ *p = '%'; p++;
+ *p = 'F'; p++;
+ }
+ break;
+ }
+ else // some colors should be set... need to find out who
+ {
+ char szTemp[3];
+
+ // fix foreground index
+ if(text[1] > 47 && text[1] < 58 && text[1] != '\0')
+ lstrcpyn(szTemp, text, 3);
+ else
+ lstrcpyn(szTemp, text, 2);
+ text += lstrlen(szTemp);
+ iFG = atoi(szTemp);
+
+ // fix background color
+ if(*text == ',' && text[1] > 47 && text[1] < 58 && text[1] != '\0')
+ {
+ text++;
+
+ if(text[1] > 47 && text[1] < 58 && text[1] != '\0')
+ lstrcpyn(szTemp, text, 3);
+ else
+ lstrcpyn(szTemp, text, 2);
+ text += lstrlen(szTemp);
+ iBG = atoi(szTemp);
+ }
+
+
+ }
+
+ if( iFG >= 0 && iFG != 99)
+ while( iFG > 15)
+ iFG -= 16;
+ if( iBG >= 0 && iBG != 99)
+ while( iBG > 15 )
+ iBG -= 16;
+
+ // create tag for chat.dll
+ if(!bStrip)
+ {
+ char szTemp[10];
+ if(iFG >= 0 && iFG != 99)
+ {
+ *p = '%'; p++;
+ *p = 'c';p++;
+
+ mir_snprintf(szTemp, sizeof(szTemp), "%02u", iFG);
+ for (int i = 0; i<2; i++)
+ {
+ *p = szTemp[i]; p++;
+ }
+ }
+ else if (iFG == 99)
+ {
+ *p = '%'; p++;
+ *p = 'C';p++;
+ }
+ if(iBG >= 0 && iBG != 99)
+ {
+ *p = '%'; p++;
+ *p = 'f';p++;
+
+ mir_snprintf(szTemp, sizeof(szTemp), "%02u", iBG);
+ for (int i = 0; i<2; i++)
+ {
+ *p = szTemp[i]; p++;
+ }
+ }
+ else if (iBG == 99)
+ {
+ *p = '%'; p++;
+ *p = 'F';p++;
+ }
+ }
+
+ break;
+
+ default:
+ *p = *text;
+ p++;
+ text++;
+ break;
+
+ }
+ char * o = szTemp;
+ }
+ *p = '\0';
+
+ return szTemp;
+
+}
+
+
+int CallChatEvent(WPARAM wParam, LPARAM lParam)
+{
+
+ GCEVENT * gce = (GCEVENT *)lParam;
+ int iVal = 0;
+
+ // first see if the scripting module should modify or stop this event
+ if(bMbotInstalled && prefs->ScriptingEnabled && gce
+ && gce->time != 0 && (gce->pDest->pszID == NULL
+ || lstrlen(gce->pDest->pszID) != 0 && lstrcmpi(gce->pDest->pszID , "Network Log")) )
+ {
+ GCEVENT *gcevent= (GCEVENT*) lParam;
+ GCEVENT *gcetemp = NULL;
+ WPARAM wp = wParam;
+ gcetemp = (GCEVENT *)mmi.mmi_malloc(sizeof(GCEVENT));
+ gcetemp->pDest = (GCDEST *)mmi.mmi_malloc(sizeof(GCDEST));
+ gcetemp->pDest->iType = gcevent->pDest->iType;
+ gcetemp->bAddToLog = gcevent->bAddToLog;
+ gcetemp->bIsMe = gcevent->bIsMe;
+ gcetemp->cbSize = sizeof(GCEVENT);
+ gcetemp->dwItemData = gcevent->dwItemData;
+ gcetemp->time = gcevent->time;
+ if(gcevent->pDest->pszID)
+ {
+ char * pTemp = NULL;
+ gcetemp->pDest->pszID = (char *)mmi.mmi_malloc(lstrlen(gcevent->pDest->pszID) + 1);
+ lstrcpyn(gcetemp->pDest->pszID, gcevent->pDest->pszID, lstrlen(gcevent->pDest->pszID) + 1);
+ pTemp = strchr(gcetemp->pDest->pszID, ' ');
+ if(pTemp)
+ *pTemp = '\0';
+ }else gcetemp->pDest->pszID = NULL;
+
+ if(gcevent->pDest->pszModule)
+ {
+ gcetemp->pDest->pszModule = (char *)mmi.mmi_malloc(lstrlen(gcevent->pDest->pszModule) + 1);
+ lstrcpyn(gcetemp->pDest->pszModule, gcevent->pDest->pszModule, lstrlen(gcevent->pDest->pszModule) + 1);
+ }else gcetemp->pDest->pszModule = NULL;
+
+ if(gcevent->pszText)
+ {
+ gcetemp->pszText = (char *)mmi.mmi_malloc(lstrlen(gcevent->pszText) + 1);
+ lstrcpyn((char *)gcetemp->pszText, gcevent->pszText, lstrlen(gcevent->pszText) + 1);
+ }else gcetemp->pszText = NULL;
+
+ if(gcevent->pszUID)
+ {
+ gcetemp->pszUID = (char *)mmi.mmi_malloc(lstrlen(gcevent->pszUID) + 1);
+ lstrcpyn((char *)gcetemp->pszUID, gcevent->pszUID, lstrlen(gcevent->pszUID) + 1);
+ }else gcetemp->pszUID = NULL;
+
+ if(gcevent->pszNick)
+ {
+ gcetemp->pszNick = (char *)mmi.mmi_malloc(lstrlen(gcevent->pszNick) + 1);
+ lstrcpyn((char *)gcetemp->pszNick, gcevent->pszNick, lstrlen(gcevent->pszNick) + 1);
+ }else gcetemp->pszNick = NULL;
+
+ if(gcevent->pszStatus)
+ {
+ gcetemp->pszStatus = (char *)mmi.mmi_malloc(lstrlen(gcevent->pszStatus) + 1);
+ lstrcpyn((char *)gcetemp->pszStatus, gcevent->pszStatus, lstrlen(gcevent->pszStatus) + 1);
+ }else gcetemp->pszStatus = NULL;
+
+ if(gcevent->pszUserInfo)
+ {
+ gcetemp->pszUserInfo = (char *)mmi.mmi_malloc(lstrlen(gcevent->pszUserInfo) + 1);
+ lstrcpyn((char *)gcetemp->pszUserInfo, gcevent->pszUserInfo, lstrlen(gcevent->pszUserInfo) + 1);
+ }else gcetemp->pszUserInfo = NULL;
+
+ if( Scripting_TriggerMSPGuiIn(&wp, gcetemp) && gcetemp)
+ {
+ if(gcetemp && gcetemp->pDest && gcetemp->pDest->pszID)
+ {
+ String sTempId = MakeWndID(gcetemp->pDest->pszID);
+ mmi.mmi_realloc(gcetemp->pDest->pszID, sTempId.length() + 1);
+ lstrcpyn(gcetemp->pDest->pszID, sTempId.c_str(), sTempId.length()+1);
+ }
+ if(pfnAddEvent)
+ iVal = pfnAddEvent(wp, (LPARAM) gcetemp);
+ else
+ iVal = CallService(MS_GC_EVENT, wp, (LPARAM) gcetemp);
+ }
+ if (gcetemp)
+ {
+ if(gcetemp->pszNick)
+ mmi.mmi_free((void *)gcetemp->pszNick);
+ if(gcetemp->pszUID)
+ mmi.mmi_free((void *)gcetemp->pszUID);
+ if(gcetemp->pszStatus)
+ mmi.mmi_free((void *)gcetemp->pszStatus);
+ if(gcetemp->pszUserInfo)
+ mmi.mmi_free((void *)gcetemp->pszUserInfo);
+ if(gcetemp->pszText)
+ mmi.mmi_free((void *)gcetemp->pszText);
+ if(gcetemp->pDest->pszID)
+ mmi.mmi_free((void *)gcetemp->pDest->pszID);
+ if(gcetemp->pDest->pszModule)
+ mmi.mmi_free((void *)gcetemp->pDest->pszModule);
+ mmi.mmi_free((void *)gcetemp->pDest);
+ mmi.mmi_free((void *)gcetemp);
+ }
+
+ return iVal;
+ }
+
+ if(pfnAddEvent)
+ iVal = pfnAddEvent(wParam, (LPARAM) gce);
+ else
+ iVal = CallService(MS_GC_EVENT, wParam, (LPARAM) gce);
+
+ return iVal;
+}
+
+int DoEvent(int iEvent, const char* pszWindow, const char * pszNick,
+ const char* pszText, const char* pszStatus, const char* pszUserInfo,
+ DWORD dwItemData, bool bAddToLog, bool bIsMe, time_t timestamp)
+{
+ GCDEST gcd = {0};
+ GCEVENT gce = {0};
+ String sID;
+ String sText = "";
+ extern bool bEcho;
+
+ if(iEvent == GC_EVENT_INFORMATION && bIsMe && !bEcho)
+ return false;
+
+ if(pszText)
+ {
+ if (iEvent != GC_EVENT_SENDMESSAGE)
+ sText = DoColorCodes(pszText, FALSE, TRUE);
+ else
+ sText = pszText;
+ }
+
+ if (pszWindow)
+ {
+ if(lstrcmpi(pszWindow, "Network log"))
+ sID = pszWindow + (String)" - " + g_ircSession.GetInfo().sNetwork;
+ else
+ sID = pszWindow;
+ gcd.pszID = (char *)sID.c_str();
+ }
+ else
+ gcd.pszID = NULL;
+
+
+ gcd.pszModule = IRCPROTONAME;
+ gcd.iType = iEvent;
+
+ gce.cbSize = sizeof(GCEVENT);
+ gce.pDest = &gcd;
+ gce.pszStatus = (char *)pszStatus;
+ gce.bAddToLog = bAddToLog;
+ gce.pszNick = (char *)pszNick;
+ gce.pszUID = (char *)pszNick;
+ gce.pszUserInfo = prefs->ShowAddresses?(char *)pszUserInfo:NULL;
+
+ if(sText != "")
+ gce.pszText = (char *)sText.c_str();
+
+ gce.dwItemData = dwItemData;
+ if(timestamp == 1)
+ gce.time = time(NULL);
+ else
+ gce.time = timestamp;
+ gce.bIsMe = bIsMe;
+ return CallChatEvent((WPARAM)0, (LPARAM)&gce);
+
+
+}
+
+
+
+
+String ModeToStatus(char sMode)
+{
+ if(strchr(sUserModes.c_str(), sMode))
+ {
+
+ switch(sMode)
+ {
+ case 'q':
+ return (String)"Owner";
+ case 'o':
+ return (String)"Op";
+ case 'v':
+ return (String)"Voice";
+ case 'h':
+ return (String)"Halfop";
+ case 'a':
+ return (String)"Admin";
+ default:
+ return (String)"Unknown";
+ }
+
+ }
+
+ return (String)"Normal";
+}
+String PrefixToStatus(char cPrefix)
+{
+ int i = (int)strchr(sUserModePrefixes.c_str(), cPrefix);
+ if(i)
+ {
+ int index = i - (int)sUserModePrefixes.c_str();
+ return ModeToStatus(sUserModes[index]);
+ }
+
+ return (String)"Normal";
+}
+
+void SetChatTimer(UINT_PTR &nIDEvent,UINT uElapse,TIMERPROC lpTimerFunc)
+{
+ if (nIDEvent)
+ KillChatTimer(nIDEvent);
+
+ nIDEvent = SetTimer(NULL, NULL, uElapse, lpTimerFunc);
+
+ return;
+}
+
+void KillChatTimer(UINT_PTR &nIDEvent)
+{
+ if (nIDEvent)
+ KillTimer(NULL, nIDEvent);
+
+ nIDEvent = NULL;
+
+ return;
+}
+
+
+
+int SetChannelSBText(String sWindow, CHANNELINFO * wi)
+{
+ String sTemp = "";
+ if(wi->pszMode)
+ {
+ sTemp += "[";
+ sTemp += wi->pszMode;
+ sTemp += "]" ;
+ sTemp += " ";
+ }
+ if(wi->pszTopic)
+ sTemp += wi->pszTopic;
+ sTemp = DoColorCodes(sTemp.c_str(), TRUE, FALSE);
+ return DoEvent(GC_EVENT_SETSBTEXT, sWindow.c_str(), NULL, sTemp.c_str(), NULL, NULL, NULL, FALSE, FALSE, 0);
+
+
+}
+
+
+
+String MakeWndID(String sWindow)
+{
+ String sTemp = sWindow;
+ sTemp += " - ";
+ if(g_ircSession)
+ sTemp += g_ircSession.GetInfo().sNetwork;
+ else
+ sTemp += Translate("Offline");
+
+ return sTemp;
+
+
+}
+
+
+
+bool FreeWindowItemData(String window, CHANNELINFO* wis)
+{
+ CHANNELINFO* wi;
+ if(!wis)
+ wi = (CHANNELINFO *)DoEvent(GC_EVENT_GETITEMDATA, window.c_str(), NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, 0);
+ else
+ wi = wis;
+ if(wi)
+ {
+ if(wi->pszLimit)
+ delete[]wi->pszLimit;
+ if(wi->pszMode)
+ delete[]wi->pszMode;
+ if(wi->pszPassword)
+ delete[]wi->pszPassword;
+ if(wi->pszTopic)
+ delete[]wi->pszTopic;
+ delete wi;
+
+ return true;
+ }
+ return false;
+}
+
+
+
+bool AddWindowItemData(String window, const char * pszLimit, const char * pszMode, const char * pszPassword, const char * pszTopic)
+{
+ CHANNELINFO* wi;
+
+ wi = (CHANNELINFO *)DoEvent(GC_EVENT_GETITEMDATA, window.c_str(), NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, 0);
+ if(wi)
+ {
+ if(pszLimit)
+ {
+ wi->pszLimit = (char *)realloc(wi->pszLimit, lstrlen(pszLimit)+1);
+ lstrcpy(wi->pszLimit, pszLimit);
+ }
+ if(pszMode)
+ {
+ wi->pszMode = (char *)realloc(wi->pszMode, lstrlen(pszMode)+1);
+ lstrcpy(wi->pszMode, pszMode);
+ }
+ if(pszPassword)
+ {
+ wi->pszPassword = (char *)realloc(wi->pszPassword, lstrlen(pszPassword)+1);
+ lstrcpy(wi->pszPassword, pszPassword);
+ }
+ if(pszTopic)
+ {
+ wi->pszTopic = (char *)realloc(wi->pszTopic, lstrlen(pszTopic)+1);
+ lstrcpy(wi->pszTopic, pszTopic);
+ }
+
+ SetChannelSBText(window, wi);
+
+ return true;
+ }
+ return false;
+}
+
+void FindLocalIP(HANDLE con) // inspiration from jabber
+{
+ // Determine local IP
+ int socket = CallService(MS_NETLIB_GETSOCKET, (WPARAM) con, 0);
+ if (socket!=INVALID_SOCKET)
+ {
+ struct sockaddr_in saddr;
+ int len;
+
+ len = sizeof(saddr);
+ getsockname(socket, (struct sockaddr *) &saddr, &len);
+
+ lstrcpyn(prefs->MyLocalHost, inet_ntoa(saddr.sin_addr), 49);
+
+ }
+
+}
+
+void DoUserhostWithReason(int type, String reason, bool bSendCommand, String userhostparams, ...)
+{
+ char temp[4096];
+ String S = "";
+ switch(type)
+ {
+ case 1:
+ S = "USERHOST";
+ break;
+ case 2:
+ S = "WHO";
+ break;
+ default:
+ S= "USERHOST";
+ break;
+ }
+
+ va_list ap;
+ va_start(ap, userhostparams);
+ mir_vsnprintf(temp, sizeof(temp), (S + (String)" " + userhostparams).c_str(), ap);
+ va_end(ap);
+
+ // Add reason
+ if (type ==1)
+ vUserhostReasons.push_back(reason);
+ else if (type == 2)
+ vWhoInProgress.push_back(reason);
+
+ // Do command
+ if (g_ircSession && bSendCommand)
+ g_ircSession << CIrcMessage(temp, false, false);
+}
+
+String GetNextUserhostReason(int type)
+{
+ String reason = "";
+ switch(type)
+ {
+ case 1:
+ if(!vUserhostReasons.size())
+ return (String)"";
+
+ // Get reason
+ reason = vUserhostReasons.front();
+ vUserhostReasons.erase(vUserhostReasons.begin());
+ break;
+ case 2:
+ if(!vWhoInProgress.size())
+ return (String)"";
+
+ // Get reason
+ reason = vWhoInProgress.front();
+ vWhoInProgress.erase(vWhoInProgress.begin());
+ break;
+ default:break;
+ }
+
+ return reason;
+}
+String PeekAtReasons(int type)
+{
+ switch (type)
+ {
+ case 1:
+ if(!vUserhostReasons.size())
+ return (String)"";
+ return vUserhostReasons.front();
+ break;
+ case 2:
+ if(!vWhoInProgress.size())
+ return (String)"";
+ return vWhoInProgress.front();
+ break;
+ default:break;
+ }
+ return (String)"";
+
+}
+
+void ClearUserhostReasons(int type)
+{
+ switch (type)
+ {
+ case 1:
+ vUserhostReasons.clear();
+ break;
+ case 2:
+ vWhoInProgress.clear();
+ break;
+ default:break;
+ }
+ return;
+}
diff --git a/irc_mod/utils.cpp b/irc_mod/utils.cpp
new file mode 100644
index 0000000..f9a7459
--- /dev/null
+++ b/irc_mod/utils.cpp
@@ -0,0 +1,548 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+
+extern char * IRCPROTONAME;
+extern BYTE gbUtfLangpack;
+extern BYTE gbUnicodeAPI;
+
+static BOOL bUtfReadyDB = FALSE;
+
+void InitDB()
+{
+ bUtfReadyDB = ServiceExists(MS_DB_CONTACT_GETSETTING_STR);
+ #ifdef _DEBUG
+ if (!bUtfReadyDB)
+ DBGprintf("Warning: DB module does not support Unicode\n");
+ #endif
+}
+
+HANDLE GetContactByName(const char* NickName)
+{
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING dcs;
+ HANDLE f=hContact;
+
+ while (hContact)
+ {
+ char*szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+
+//HACK: here just replaced by lstrcmpiA
+ if (szProto != NULL && !lstrcmpiA(szProto, IRCPROTONAME))
+ {
+ dcs.szModule=IRCPROTONAME;
+ dcs.szSetting="Nick";
+ dcs.pValue=&dbv;
+ dbv.type=DBVT_ASCIIZ;
+ CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&dcs);
+ if(!strcmp(NickName,dbv.pszVal))
+ {
+ return hContact;
+ f=0;
+ }
+ CallService(MS_DB_CONTACT_FREEVARIANT,0,(LPARAM)(DBVARIANT*)&dbv);
+ DBFreeVariant(&dbv);
+ }
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ if(f)
+ {
+ return hContact;
+ }
+ return NULL;
+}
+
+//HANDLE GetHandleFromNick(char *displayname)
+//{
+// HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+// char *nick, *nickfind;
+// nick = (char *) malloc (strlen(displayname) + 1);
+// nick = _strupr(_strdup(displayname));
+// while (hContact != NULL) {
+// nickfind = (char *) malloc (strlen(GetNickFromHandle(hContact)) + 1);
+// nickfind = _strupr(_strdup(GetNickFromHandle(hContact)));
+// if (!strcmp(nickfind, nick))
+// break;
+// free(nickfind);
+// hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+// }
+// free(nickfind);
+// free(nick);
+// return hContact;
+//}
+
+char* calcMD5Hash(char* szFile)
+{
+ md5_state_t state;
+ md5_byte_t digest[16];
+
+ if (szFile)
+ {
+ HANDLE hFile = NULL, hMap = NULL;
+ BYTE* ppMap = NULL;
+ long cbFileSize = 0;
+ char* res;
+
+ if ((hFile =
+ #ifdef _UNICODE
+ CreateFile((LPCWSTR)szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL )) != INVALID_HANDLE_VALUE)
+ #else
+ CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL )) != INVALID_HANDLE_VALUE)
+ #endif
+ if ((hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL)
+ if ((ppMap = (BYTE*)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
+ cbFileSize = GetFileSize( hFile, NULL );
+
+ res = (char *)malloc(16*sizeof(char));
+ if (cbFileSize != 0 && res)
+ {
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)ppMap, cbFileSize);
+ md5_finish(&state, digest);
+ memcpy(res, digest, 16);
+ }
+
+ if (ppMap != NULL) UnmapViewOfFile(ppMap);
+ if (hMap != NULL) CloseHandle(hMap);
+ if (hFile != NULL) CloseHandle(hFile);
+
+ if (res) return res;
+ }
+
+ return NULL;
+}
+
+void EnableDlgItem(HWND hwndDlg, UINT control, int state)
+{
+ EnableWindow(GetDlgItem(hwndDlg, control), state);
+}
+
+void IRC_EnableMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state)
+{
+ int i;
+
+ for (i = 0; i < cControls; i++)
+ EnableDlgItem(hwndDlg, controls[i], state);
+}
+
+
+int IRCGetContactSetting(HANDLE hContact, const char* szSetting, DBVARIANT *dbv)
+{
+ return DBGetContactSetting(hContact, IRCPROTONAME, szSetting, dbv);
+}
+
+BYTE IRCGetContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bDef)
+{
+ return DBGetContactSettingByte(hContact, IRCPROTONAME, szSetting, bDef);
+}
+
+int IRCWriteContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bValue)
+{
+ return DBWriteContactSettingByte(hContact, IRCPROTONAME, szSetting, bValue);
+}
+
+DWORD IRCGetContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwDef)
+{
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING cgs;
+ DWORD dwRes;
+
+ cgs.szModule = IRCPROTONAME;
+ cgs.szSetting = szSetting;
+ cgs.pValue = &dbv;
+ if (CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs))
+ return dwDef; // not found, give default
+
+ if (dbv.type != DBVT_DWORD)
+ dwRes = dwDef; // invalid type, give default
+ else // found and valid, give result
+ dwRes = dbv.dVal;
+
+ IRCFreeVariant(&dbv);
+ return dwRes;
+}
+
+int IRCWriteContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwValue)
+{
+ return DBWriteContactSettingDword(hContact, IRCPROTONAME, szSetting, dwValue);
+}
+
+
+char* IRCGetContactSettingString(HANDLE hContact, const char* szSetting, char* szValue)
+{
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING dcs;
+ char* szRes;
+
+ dcs.szModule=IRCPROTONAME;
+ dcs.szSetting=szSetting;
+ dcs.pValue=&dbv;
+ dbv.type=DBVT_ASCIIZ;
+ if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&dcs) != 0)
+ szRes = szValue;
+ else
+ szRes = dbv.pszVal;
+
+ DBFreeVariant(&dbv);
+ return szRes;
+}
+
+int IRCWriteContactSettingString(HANDLE hContact, const char* szSetting, char* szValue)
+{
+ return DBWriteContactSettingString(hContact, IRCPROTONAME, szSetting, szValue);
+}
+
+int IRCDeleteContactSetting(HANDLE hContact, const char* szSetting)
+{
+ return DBDeleteContactSetting(hContact, IRCPROTONAME, szSetting);
+}
+
+char* UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szDef)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ char* szRes;
+
+ if (bUtfReadyDB)
+ {
+ if (DBGetContactSettingStringUtf(hContact, szModule, szSetting, &dbv))
+ return null_strdup(szDef);
+
+ szRes = null_strdup(dbv.pszVal);
+ IRCFreeVariant(&dbv);
+ }
+ else
+ { // old DB, we need to convert the string to UTF-8
+ if (DBGetContactSetting(hContact, szModule, szSetting, &dbv))
+ return null_strdup(szDef);
+
+ szRes = ansi_to_utf8(dbv.pszVal);
+
+ IRCFreeVariant(&dbv);
+ }
+ return szRes;
+}
+
+int UniWriteContactSettingUtf(HANDLE hContact, const char *szModule, const char* szSetting, char* szValue)
+{
+ if (bUtfReadyDB)
+ return DBWriteContactSettingStringUtf(hContact, szModule, szSetting, szValue);
+ else
+ { // old DB, we need to convert the string to Ansi
+ int size = strlennull(szValue) + 2;
+ char* szAnsi = (char*)_alloca(size);
+
+ if (utf8_decode_static(szValue, szAnsi, size))
+ return DBWriteContactSettingString(hContact, szModule, szSetting, szAnsi);
+ // failed to convert - give error
+ return 1;
+ }
+}
+
+char* IRCGetContactSettingUtf(HANDLE hContact, const char* szSetting, char* szDef)
+{
+ return UniGetContactSettingUtf(hContact, IRCPROTONAME, szSetting, szDef);
+}
+
+int IRCWriteContactSettingUtf(HANDLE hContact, const char* szSetting, char* szValue)
+{
+ return UniWriteContactSettingUtf(hContact, IRCPROTONAME, szSetting, szValue);
+}
+
+int IRCGetContactStaticString(HANDLE hContact, const char* valueName, char* dest, int dest_len)
+{
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING sVal;
+
+ dbv.pszVal = dest;
+ dbv.cchVal = dest_len;
+ dbv.type = DBVT_ASCIIZ;
+
+ sVal.pValue = &dbv;
+ sVal.szModule = IRCPROTONAME;
+ sVal.szSetting = valueName;
+
+ if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&sVal) != 0)
+ {
+ dbv.pszVal = dest;
+ dbv.cchVal = dest_len;
+ dbv.type = DBVT_UTF8;
+
+ if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&sVal) != 0)
+ return 1; // this is here due to DB module bug...
+ }
+
+ return (dbv.type != DBVT_ASCIIZ);
+}
+
+int IRCWriteContactSettingBlob(HANDLE hContact,const char *szSetting,const char *val, const int cbVal)
+{
+ DBCONTACTWRITESETTING cws;
+
+/* if (!bdCacheTested) TestDBBlobIssue();
+
+ if (bdWorkaroundRequired)
+ { // this is workaround for DB blob caching problems - nasty isn't it
+ DBWriteContactSettingByte(hContact, gpszICQProtoName, szSetting, 1);
+ DBDeleteContactSetting(hContact, gpszICQProtoName, szSetting);
+ }*/
+
+ cws.szModule=IRCPROTONAME;
+ cws.szSetting=szSetting;
+ cws.value.type=DBVT_BLOB;
+ cws.value.pbVal=(BYTE *)val;
+ cws.value.cpbVal = cbVal;
+ return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws);
+}
+
+int IRCFreeVariant(DBVARIANT* dbv)
+{
+ return DBFreeVariant(dbv);
+}
+
+char* __fastcall IRCTranslate(const char* src)
+{
+ return (char*)CallService(MS_LANGPACK_TRANSLATESTRING,0,(LPARAM)src);
+}
+
+char* __fastcall IRCTranslateUtf(const char* src)
+{ // this takes UTF-8 strings only!!!
+ char* szRes = NULL;
+
+ if (!strlennull(src))
+ { // for the case of empty strings
+ return null_strdup(src);
+ }
+
+ if (gbUtfLangpack)
+ { // we can use unicode translate
+ wchar_t* usrc = make_unicode_string((const unsigned char *)src);
+
+ szRes = (char *)make_utf8_string(TranslateW(usrc));
+
+ SAFE_FREE((void **)&usrc);
+ }
+ else
+ {
+ int size = strlennull(src)+2;
+ char* asrc = (char*)_alloca(size);
+
+ utf8_decode_static(src, asrc, size);
+ utf8_encode(Translate(asrc), &szRes);
+ }
+ return szRes;
+}
+
+char* __fastcall IRCTranslateUtfStatic(const char* src, char* buf)
+{ // this takes UTF-8 strings only!!!
+ char* t;
+
+ if (strlennull(src))
+ {
+ t = IRCTranslateUtf(src);
+ strcpy(buf, t);
+ SAFE_FREE((void **)&t);
+ }
+ else
+ buf[0] = '\0';
+
+ return buf;
+}
+
+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;
+}
+
+/* a strlennull() that likes NULL */
+size_t __fastcall strlennull(const char *string)
+{
+ if (string)
+ return strlen(string);
+
+ return 0;
+}
+
+char* __fastcall null_strdup(const char *string)
+{
+ if (string)
+ return strdup(string);
+
+ return NULL;
+}
+
+void __fastcall SAFE_FREE(void** p)
+{
+ if (*p)
+ {
+ free(*p);
+ *p = NULL;
+ }
+}
+
+void* __fastcall SAFE_MALLOC(size_t size)
+{
+ void* p = malloc(size);
+
+ if (p)
+ ZeroMemory(p, size);
+
+ return p;
+}
+
+wchar_t *GetWindowTextUcs(HWND hWnd)
+{
+ wchar_t *utext;
+
+ if (gbUnicodeAPI)
+ {
+ int nLen = GetWindowTextLengthW(hWnd);
+
+ utext = (wchar_t*)malloc((nLen+2)*sizeof(wchar_t));
+ GetWindowTextW(hWnd, utext, nLen + 1);
+ }
+ else
+ {
+ char *text;
+ int wchars, nLen = GetWindowTextLengthA(hWnd);
+
+ text = (char*)_alloca(nLen+2);
+ GetWindowTextA(hWnd, text, nLen + 1);
+
+ wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text,
+ strlennull(text), NULL, 0);
+
+ utext = (wchar_t *)calloc(wchars + 1, sizeof(unsigned short));
+
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text,
+ strlennull(text), utext, wchars);
+ }
+ return utext;
+}
+
+void SetWindowTextUcs(HWND hWnd, wchar_t *text)
+{
+ if (gbUnicodeAPI)
+ {
+ SetWindowTextW(hWnd, text);
+ }
+ else
+ {
+ char *tmp = (char*)malloc(wcslen(text) + 1);
+
+ tmp[0] = '\0';
+ WideCharToMultiByte(CP_ACP, 0, text, -1, tmp, wcslen(text)+1, NULL, NULL);
+ SetWindowTextA(hWnd, tmp);
+ SAFE_FREE((void **)&tmp);
+ }
+}
+
+char* GetWindowTextUtf(HWND hWnd)
+{
+ if (gbUnicodeAPI)
+ {
+ wchar_t* usText;
+ int nLen = GetWindowTextLengthW(hWnd);
+
+ usText = (wchar_t*)_alloca((nLen+2)*sizeof(wchar_t));
+ GetWindowTextW(hWnd, usText, nLen + 1);
+ return (char *)make_utf8_string(usText);
+ }
+ else
+ {
+ char* szAnsi;
+ int nLen = GetWindowTextLengthA(hWnd);
+
+ szAnsi = (char*)_alloca(nLen+2);
+ GetWindowTextA(hWnd, szAnsi, nLen + 1);
+ return ansi_to_utf8(szAnsi);
+ }
+}
+
+char* GetDlgItemTextUtf(HWND hwndDlg, int iItem)
+{
+ return GetWindowTextUtf(GetDlgItem(hwndDlg, iItem));
+}
+
+void SetWindowTextUtf(HWND hWnd, const char* szText)
+{
+ if (gbUnicodeAPI)
+ {
+ wchar_t* usText = make_unicode_string((const unsigned char *)szText);
+
+ SetWindowTextW(hWnd, usText);
+ SAFE_FREE((void **)&usText);
+ }
+ else
+ {
+ int size = strlennull(szText)+2;
+ char* szAnsi = (char*)_alloca(size);
+
+ if (utf8_decode_static(szText, szAnsi, size))
+ SetWindowTextA(hWnd, szAnsi);
+ }
+}
+
+void SetDlgItemTextUtf(HWND hwndDlg, int iItem, const char* szText)
+{
+ SetWindowTextUtf(GetDlgItem(hwndDlg, iItem), szText);
+}
+
+LONG SetWindowLongUtf(HWND hWnd, int nIndex, LONG dwNewLong)
+{
+ if (gbUnicodeAPI)
+ return SetWindowLongW(hWnd, nIndex, dwNewLong);
+ else
+ return SetWindowLongA(hWnd, nIndex, dwNewLong);
+}
+
+LRESULT CallWindowProcUtf(WNDPROC OldProc, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (gbUnicodeAPI)
+ return CallWindowProcW(OldProc,hWnd,msg,wParam,lParam);
+ else
+ return CallWindowProcA(OldProc,hWnd,msg,wParam,lParam);
+}
+
+HWND DialogBoxUtf(BOOL bModal, HINSTANCE hInstance, const char* szTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
+{ // Unicode pump ready dialog box
+ if (gbUnicodeAPI)
+ {
+ if (bModal)
+ return (HWND)DialogBoxParamW(hInstance, (LPCWSTR)szTemplate, hWndParent, lpDialogFunc, dwInitParam);
+ else
+ return CreateDialogParamW(hInstance, (LPCWSTR)szTemplate, hWndParent, lpDialogFunc, dwInitParam);
+ }
+ else
+ {
+ if (bModal)
+ return (HWND)DialogBoxParamA(hInstance, szTemplate, hWndParent, lpDialogFunc, dwInitParam);
+ else
+ return CreateDialogParamA(hInstance, szTemplate, hWndParent, lpDialogFunc, dwInitParam);
+ }
+}
diff --git a/irc_mod/utils.h b/irc_mod/utils.h
new file mode 100644
index 0000000..ef903b3
--- /dev/null
+++ b/irc_mod/utils.h
@@ -0,0 +1,67 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+void InitDB();
+
+HANDLE GetContactByName(const char* NickName);
+
+char* calcMD5Hash(char* szFile);
+
+void EnableDlgItem(HWND hwndDlg, UINT control, int state);
+void IRC_EnableMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state);
+
+int IRCGetContactSetting(HANDLE hContact, const char* szSetting, DBVARIANT *dbv);
+BYTE IRCGetContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bDef);
+int IRCWriteContactSettingByte(HANDLE hContact, const char* szSetting, BYTE bValue);
+DWORD IRCGetContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwDef);
+int IRCWriteContactSettingDword(HANDLE hContact, const char* szSetting, DWORD dwValue);
+char* IRCGetContactSettingString(HANDLE hContact, const char* szSetting, char* szValue);
+int IRCWriteContactSettingString(HANDLE hContact, const char* szSetting, char* szValue);
+int IRCDeleteContactSetting(HANDLE hContact, const char* szSetting);
+char* UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szDef);
+int UniWriteContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szValue);
+char* IRCGetContactSettingUtf(HANDLE hContact, const char* szSetting, char* szDef);
+int IRCWriteContactSettingUtf(HANDLE hContact, const char* szSetting, char* szValue);
+int IRCGetContactStaticString(HANDLE hContact, const char* valueName, char* dest, int dest_len);
+int IRCWriteContactSettingBlob(HANDLE hContact,const char *szSetting,const char *val, const int cbVal);
+
+int IRCFreeVariant(DBVARIANT* dbv);
+
+char* __fastcall IRCTranslate(const char* src);
+char* __fastcall IRCTranslateUtf(const char* src);
+char* __fastcall IRCTranslateUtfStatic(const char* src, char* buf);
+
+int null_snprintf(char *buffer, size_t count, const char* fmt, ...);
+size_t __fastcall strlennull(const char *string);
+char* __fastcall null_strdup(const char *string);
+void __fastcall SAFE_FREE(void** p);
+void* __fastcall SAFE_MALLOC(size_t size);
+
+/* Unicode UI utility functions */
+wchar_t* GetWindowTextUcs(HWND hWnd);
+void SetWindowTextUcs(HWND hWnd, wchar_t *text);
+char* GetWindowTextUtf(HWND hWnd);
+char* GetDlgItemTextUtf(HWND hwndDlg, int iItem);
+void SetWindowTextUtf(HWND hWnd, const char* szText);
+void SetDlgItemTextUtf(HWND hwndDlg, int iItem, const char* szText);
+LONG SetWindowLongUtf(HWND hWnd, int nIndex, LONG dwNewLong);
+LRESULT CallWindowProcUtf(WNDPROC OldProc, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+HWND DialogBoxUtf(BOOL bModal, HINSTANCE hInstance, const char* szTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); \ No newline at end of file
diff --git a/irc_mod/windows.cpp b/irc_mod/windows.cpp
new file mode 100644
index 0000000..99dca8f
--- /dev/null
+++ b/irc_mod/windows.cpp
@@ -0,0 +1,1800 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+
+extern PREFERENCES *prefs;
+extern HWND nick_hWnd;
+extern HWND list_hWnd;
+extern HWND whois_hWnd;
+extern HWND join_hWnd;
+extern HWND quickconn_hWnd;
+extern char * IRCPROTONAME;
+extern char * pszServerFile;
+extern String sChannelModes;
+static WNDPROC OldMgrEditProc;
+extern HWND manager_hWnd;
+extern HMODULE m_ssleay32;
+
+extern bool whois_popup;
+
+// Callback for the 'CTCP accept' dialog
+BOOL CALLBACK MessageboxWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ static DCCINFO * pdci = NULL;
+ switch (uMsg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ pdci = (DCCINFO *) lParam;
+ SendMessage(GetDlgItem(hwndDlg, IDC_LOGO),STM_SETICON,(LPARAM)(HICON)LoadImage(NULL,IDI_QUESTION,IMAGE_ICON,48, 48,LR_SHARED), 0);
+
+ } break;
+
+ case WM_COMMAND:
+ {
+ if(HIWORD(wParam) == BN_CLICKED)
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDN_YES:
+ {
+ CDccSession * dcc = new CDccSession(pdci);
+
+ CDccSession * olddcc = g_ircSession.FindDCCSession(pdci->hContact);
+ if (olddcc)
+ olddcc->Disconnect();
+ g_ircSession.AddDCCSession(pdci->hContact, dcc);
+
+ dcc->Connect();
+
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }break;
+ case IDN_NO:
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ break;
+
+ default:break;
+ }
+
+ }
+ } break;
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+ } break;
+
+ default:break;
+ }
+ return(false);
+}
+
+// Callback for the /WHOIS dialog
+BOOL CALLBACK InfoWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+
+ case WM_INITDIALOG:
+ {
+
+ TranslateDialogDefault(hwndDlg);
+ HFONT hFont;
+ LOGFONT lf;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ GetObject(hFont,sizeof(lf),&lf);
+ lf.lfHeight=(int)(lf.lfHeight*1.2);
+ lf.lfWeight=FW_BOLD;
+ hFont=CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,(WPARAM)hFont,0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LOGO),STM_SETICON,(LPARAM)(HICON)LoadIconEx(IDI_LOGO,"logo",48,48), 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_INFO_NAME), EM_SETREADONLY, true, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_INFO_ID), EM_SETREADONLY, true, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_INFO_ADDRESS), EM_SETREADONLY, true, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_INFO_CHANNELS), EM_SETREADONLY, true, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_INFO_AUTH), EM_SETREADONLY, true, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_INFO_SERVER), EM_SETREADONLY, true, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_INFO_AWAY2), EM_SETREADONLY, true, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_INFO_OTHER), EM_SETREADONLY, true, 0);
+ SendMessage(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM)LoadIconEx(IDI_WHOIS,"whois",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON))); // Tell the dialog to use it
+
+ } break;
+
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ {
+ if((HWND)lParam==GetDlgItem(hwndDlg,IDC_WHITERECT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_TEXT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_CAPTION)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_LOGO))
+ {
+ SetTextColor((HDC)wParam,RGB(0,0,0));
+ SetBkColor((HDC)wParam,RGB(255,255,255));
+ return (BOOL)GetStockObject(WHITE_BRUSH);
+ }
+ }break;
+ case WM_COMMAND:
+ {
+ if(HIWORD(wParam) == BN_CLICKED)
+ {
+ char szTemp[255];
+ SendMessage(GetDlgItem(hwndDlg, IDC_INFO_NICK), WM_GETTEXT, 255, (LPARAM) szTemp);
+ switch (LOWORD(wParam))
+ {
+ case ID_INFO_OK:
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ break;
+
+ case ID_INFO_GO:
+ PostIrcMessage( "/WHOIS %s", szTemp);
+ whois_popup = true;
+ break;
+
+ case ID_INFO_QUERY:
+ PostIrcMessage( "/QUERY %s", szTemp);
+ break;
+ case IDC_PING:
+ SetDlgItemText(hwndDlg, IDC_REPLY, Translate("Please wait..."));
+ PostIrcMessage( "/PRIVMSG %s \001PING %u\001", szTemp, time(0));
+ break;
+ case IDC_USERINFO:
+ SetDlgItemText(hwndDlg, IDC_REPLY, Translate("Please wait..."));
+ PostIrcMessage( "/PRIVMSG %s \001USERINFO\001", szTemp);
+ break;
+ case IDC_TIME:
+ SetDlgItemText(hwndDlg, IDC_REPLY, Translate("Please wait..."));
+ PostIrcMessage( "/PRIVMSG %s \001TIME\001", szTemp);
+ break;
+ case IDC_VERSION:
+ SetDlgItemText(hwndDlg, IDC_REPLY, Translate("Please wait..."));
+ PostIrcMessage( "/PRIVMSG %s \001VERSION\001", szTemp);
+ break;
+ default:break;
+ }
+
+ }
+
+ } break;
+
+ case WM_CLOSE:
+ {
+ ShowWindow(hwndDlg, SW_HIDE);
+ SendMessage(hwndDlg, WM_SETREDRAW, FALSE, 0);
+ } break;
+
+ case WM_DESTROY:
+ {
+ HFONT hFont;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,SendDlgItemMessage(hwndDlg,IDNOK,WM_GETFONT,0,0),0);
+ DeleteObject(hFont);
+ whois_hWnd = NULL;
+ } break;
+
+
+ default:break;
+ }
+ return(false);
+}
+
+// Callback for the 'Change nickname' dialog
+BOOL CALLBACK NickWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ HFONT hFont;
+ LOGFONT lf;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ GetObject(hFont,sizeof(lf),&lf);
+ lf.lfHeight=(int)(lf.lfHeight*1.2);
+ lf.lfWeight=FW_BOLD;
+ hFont=CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,(WPARAM)hFont,0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LOGO),STM_SETICON,(LPARAM)(HICON)LoadIconEx(IDI_LOGO,"logo",48,48), 0);
+
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, IRCPROTONAME, "RecentNicks", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ for (int i = 0; i<10; i++) {
+ if (!GetWord(dbv.pszVal, i).empty())
+ SendDlgItemMessage(hwndDlg, IDC_ENICK, CB_ADDSTRING, 0, (LPARAM)GetWord(dbv.pszVal, i).c_str());
+ }
+ DBFreeVariant(&dbv);
+ }
+ } break;
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ {
+ if((HWND)lParam==GetDlgItem(hwndDlg,IDC_WHITERECT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_TEXT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_CAPTION)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_LOGO))
+ {
+ SetTextColor((HDC)wParam,RGB(0,0,0));
+ SetBkColor((HDC)wParam,RGB(255,255,255));
+ return (BOOL)GetStockObject(WHITE_BRUSH);
+ }
+ }break;
+
+ case WM_COMMAND:
+ {
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDNCANCEL)
+ {
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDNOK)
+ {
+ char szTemp[255];
+ SendMessage(GetDlgItem(hwndDlg, IDC_ENICK), WM_GETTEXT, 255, (LPARAM) szTemp);
+ PostIrcMessage( "/NICK %s", szTemp);
+
+ String S = szTemp;
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, IRCPROTONAME, "RecentNicks", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ for (int i = 0; i<10; i++) {
+ if (!GetWord(dbv.pszVal, i).empty() && GetWord(dbv.pszVal, i) != szTemp) {
+ S += " ";
+ S += GetWord(dbv.pszVal, i);
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "RecentNicks", S.c_str());
+ SendMessage (hwndDlg, WM_CLOSE, 0,0);
+
+ }
+
+ } break;
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+ } break;
+
+ case WM_DESTROY:
+ {
+ HFONT hFont;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,SendDlgItemMessage(hwndDlg,IDNOK,WM_GETFONT,0,0),0);
+ DeleteObject(hFont);
+ nick_hWnd = NULL;
+ } break;
+
+
+ default:break;
+ }
+ return(false);
+}
+
+BOOL CALLBACK ListWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case IRC_UPDATELIST:
+ {
+ int j = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW));
+ if (j >0) {
+ LVITEM lvm;
+ lvm.mask= LVIF_PARAM;
+ lvm.iSubItem = 0;
+ for( int i =0; i < j; i++)
+ {
+ lvm.iItem = i;
+ lvm.lParam = i;
+ ListView_SetItem(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW),&lvm);
+ }
+ }
+ } break;
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ RECT screen;
+
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0);
+ LV_COLUMN lvC;
+ int COLUMNS_SIZES[4] ={200, 50,50,2000};
+ char szBuffer[32];
+
+ lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvC.fmt = LVCFMT_LEFT;
+ for (int index=0;index < 4;index++)
+ {
+ lvC.iSubItem = index;
+ lvC.cx = COLUMNS_SIZES[index];
+
+ switch (index)
+ {
+ case 0: lstrcpy(szBuffer,Translate("Channel")); break;
+ case 1: lstrcpy(szBuffer,"#"); break;
+ case 2: lstrcpy(szBuffer,Translate("Mode")); break;
+ case 3: lstrcpy(szBuffer,Translate("Topic")); break;
+
+ }
+ lvC.pszText = szBuffer;
+ ListView_InsertColumn(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW),index,&lvC);
+ }
+
+ SetWindowPos(hwndDlg, HWND_TOP, (screen.right-screen.left)/2- (prefs->ListSize.x)/2,(screen.bottom-screen.top)/2- (prefs->ListSize.y)/2, (prefs->ListSize.x), (prefs->ListSize.y), 0);
+ SendMessage(hwndDlg, WM_SIZE, SIZE_RESTORED, MAKELPARAM(prefs->ListSize.x, prefs->ListSize.y));
+ ListView_SetExtendedListViewStyle(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW), LVS_EX_FULLROWSELECT);
+ SendMessage(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM)LoadIconEx(IDI_LIST,"list",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON))); // Tell the dialog to use it
+ } break;
+
+ case WM_SIZE:
+ {
+
+ RECT winRect;
+ GetClientRect(hwndDlg, &winRect);
+ RECT buttRect;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_JOIN), &buttRect);
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW), HWND_TOP, 4, 4, winRect.right-8, winRect.bottom-36, 0 );
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_CLOSE), HWND_TOP, winRect.right-84, winRect.bottom-28, buttRect.right- buttRect.left, buttRect.bottom- buttRect.top, 0 );
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_JOIN), HWND_TOP, winRect.right-174, winRect.bottom-28, buttRect.right- buttRect.left, buttRect.bottom- buttRect.top, 0 );
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_TEXT), HWND_TOP, 4, winRect.bottom-28, winRect.right-200, buttRect.bottom- buttRect.top, 0 );
+
+ GetWindowRect(hwndDlg, &winRect);
+ prefs->ListSize.x = winRect.right-winRect.left;
+ prefs->ListSize.y = winRect.bottom-winRect.top;
+ DBWriteContactSettingDword(NULL,IRCPROTONAME, "SizeOfListBottom", prefs->ListSize.y);
+ DBWriteContactSettingDword(NULL,IRCPROTONAME, "SizeOfListRight", prefs->ListSize.x);
+ return 0;
+
+ } break;
+
+ case WM_COMMAND:
+ {
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_CLOSE)
+ {
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_JOIN)
+ {
+ char szTemp[255];
+ int i = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW));
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW), i, 0, szTemp, 255);
+ PostIrcMessage( "/JOIN %s", szTemp);
+ }
+ }break;
+ case WM_NOTIFY :
+ {
+ switch (((NMHDR*)lParam)->code)
+ {
+ case NM_DBLCLK:
+ {
+ char szTemp[255];
+ int i = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW));
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW), i, 0, szTemp, 255);
+ PostIrcMessage( "/JOIN %s", szTemp);
+
+ } break;
+ case LVN_COLUMNCLICK :
+ {
+ LPNMLISTVIEW lv;
+ lv = (LPNMLISTVIEW)lParam;
+ SendMessage(GetDlgItem(hwndDlg, IDC_INFO_LISTVIEW), LVM_SORTITEMS, (WPARAM)lv->iSubItem, (LPARAM)ListViewSort);
+ SendMessage(list_hWnd, IRC_UPDATELIST, 0, 0);
+ } break;
+ }
+ } break;
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+
+ } break;
+
+
+ case WM_DESTROY:
+ {
+ list_hWnd = NULL;
+ } break;
+
+ default:break;
+ }
+ return(false);
+}
+
+BOOL CALLBACK JoinWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ HFONT hFont;
+ LOGFONT lf;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ GetObject(hFont,sizeof(lf),&lf);
+ lf.lfHeight=(int)(lf.lfHeight*1.2);
+ lf.lfWeight=FW_BOLD;
+ hFont=CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,(WPARAM)hFont,0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LOGO),STM_SETICON,(LPARAM)(HICON)LoadIconEx(IDI_LOGO,"logo",48,48), 0);
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, IRCPROTONAME, "RecentChannels", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ for (int i = 0; i<20; i++) {
+ if (!GetWord(dbv.pszVal, i).empty()) {
+ String S = ReplaceString(GetWord(dbv.pszVal, i) ,"%newl" , " ");
+ SendDlgItemMessage(hwndDlg, IDC_ENICK, CB_ADDSTRING, 0, (LPARAM)S.c_str());
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ } break;
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ {
+ if((HWND)lParam==GetDlgItem(hwndDlg,IDC_WHITERECT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_TEXT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_CAPTION)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_LOGO))
+ {
+ SetTextColor((HDC)wParam,RGB(0,0,0));
+ SetBkColor((HDC)wParam,RGB(255,255,255));
+ return (BOOL)GetStockObject(WHITE_BRUSH);
+ }
+ }break;
+
+ case WM_COMMAND:
+ {
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDNCANCEL)
+ {
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDNOK)
+ {
+ char szTemp[255];
+ SendMessage(GetDlgItem(hwndDlg, IDC_ENICK), WM_GETTEXT, 255, (LPARAM) szTemp);
+ if (IsChannel(szTemp))
+ PostIrcMessage( "/JOIN %s", szTemp);
+ else
+ PostIrcMessage( "/JOIN #%s", szTemp);
+
+ String S = ReplaceString(szTemp, " ", "%newl");
+ String SL = S;
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, IRCPROTONAME, "RecentChannels", &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ for (int i = 0; i<20; i++) {
+ if (!GetWord(dbv.pszVal, i).empty() && GetWord(dbv.pszVal, i) != SL) {
+ S += " ";
+ S += GetWord(dbv.pszVal, i);
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "RecentChannels", S.c_str());
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }
+ } break;
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+
+ } break;
+ case WM_DESTROY:
+ {
+ HFONT hFont;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,SendDlgItemMessage(hwndDlg,IDNOK,WM_GETFONT,0,0),0);
+ DeleteObject(hFont);
+ join_hWnd = NULL;
+ } break;
+ default:break;
+ }
+ return(false);
+}
+BOOL CALLBACK InitWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ HFONT hFont;
+ LOGFONT lf;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ GetObject(hFont,sizeof(lf),&lf);
+ lf.lfHeight=(int)(lf.lfHeight*1.2);
+ lf.lfWeight=FW_BOLD;
+ hFont=CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,(WPARAM)hFont,0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LOGO),STM_SETICON,(LPARAM)(HICON)LoadIconEx(IDI_LOGO,"logo",48,48), 0);
+ } break;
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ {
+ if((HWND)lParam==GetDlgItem(hwndDlg,IDC_WHITERECT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_TEXT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_CAPTION)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_LOGO))
+ {
+ SetTextColor((HDC)wParam,RGB(0,0,0));
+ SetBkColor((HDC)wParam,RGB(255,255,255));
+ return (BOOL)GetStockObject(WHITE_BRUSH);
+ }
+ }break;
+
+ case WM_COMMAND:
+ {
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDNCANCEL)
+ {
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDNOK)
+ {
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_EDIT), WM_GETTEXTLENGTH, 0, 0);
+ int j = SendMessage(GetDlgItem(hwndDlg, IDC_EDIT2), WM_GETTEXTLENGTH, 0, 0);
+ if (i >0 && j > 0)
+ {
+ char l [30];
+ char m [200];
+ SendMessage(GetDlgItem(hwndDlg, IDC_EDIT), WM_GETTEXT, 30, (LPARAM) l);
+ SendMessage(GetDlgItem(hwndDlg, IDC_EDIT2), WM_GETTEXT, 200, (LPARAM) m);
+
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "PNick", l);
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "Nick", l);
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "Name", m);
+ lstrcpyn(prefs->Nick, l, 30);
+ lstrcpyn(prefs->Name, m, 200);
+ if (lstrlen(prefs->AlternativeNick) == 0)
+ {
+ char szTemp[30];
+ mir_snprintf(szTemp, sizeof(szTemp), "%s%u", l, rand()%9999);
+ DBWriteContactSettingString(NULL, IRCPROTONAME, "AlernativeNick", szTemp);
+ lstrcpyn(prefs->AlternativeNick, szTemp, 30);
+ }
+ }
+
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+
+ }
+
+
+
+ } break;
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+
+ } break;
+ case WM_DESTROY:
+ {
+ HFONT hFont;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,SendDlgItemMessage(hwndDlg,IDNOK,WM_GETFONT,0,0),0);
+ DeleteObject(hFont);
+ } break;
+ default:break;
+ }
+ return(false);
+}
+BOOL CALLBACK QuickWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ HFONT hFont;
+ LOGFONT lf;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ GetObject(hFont,sizeof(lf),&lf);
+ lf.lfHeight=(int)(lf.lfHeight*1.2);
+ lf.lfWeight=FW_BOLD;
+ hFont=CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,(WPARAM)hFont,0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LOGO),STM_SETICON,(LPARAM)(HICON)LoadIconEx(IDI_LOGO,"logo",48,48), 0);
+
+ char * p1 = pszServerFile;
+ char * p2 = pszServerFile;
+ if(pszServerFile)
+ while (strchr(p2, 'n'))
+ {
+ SERVER_INFO * pData = new SERVER_INFO;
+ p1 = strchr(p2, '=');
+ ++p1;
+ p2 = strstr(p1, "SERVER:");
+ pData->Name=new char[p2-p1+1];
+ lstrcpyn(pData->Name, p1, p2-p1+1);
+
+ p1 = strchr(p2, ':');
+ ++p1;
+ pData->iSSL = 0;
+ if(strstr(p1, "SSL") == p1)
+ {
+ p1 +=3;
+ if(*p1 == '1')
+ pData->iSSL = 1;
+ else if(*p1 == '2')
+ pData->iSSL = 2;
+ p1++;
+ }
+
+ p2 = strchr(p1, ':');
+ pData->Address=new char[p2-p1+1];
+ lstrcpyn(pData->Address, p1, p2-p1+1);
+
+ p1 = p2;
+ p1++;
+ while (*p2 !='G' && *p2 != '-')
+ p2++;
+ pData->PortStart = new char[p2-p1+1];
+ lstrcpyn(pData->PortStart, p1, p2-p1+1);
+
+ if (*p2 == 'G'){
+ pData->PortEnd = new char[p2-p1+1];
+ lstrcpy(pData->PortEnd, pData->PortStart);
+ } else {
+ p1 = p2;
+ p1++;
+ p2 = strchr(p1, 'G');
+ pData->PortEnd = new char[p2-p1+1];
+ lstrcpyn(pData->PortEnd, p1, p2-p1+1);
+ }
+
+ p1 = strchr(p2, ':');
+ p1++;
+ p2 = strchr(p1, '\r');
+ if (!p2)
+ p2 = strchr(p1, '\n');
+ if (!p2)
+ p2 = strchr(p1, '\0');
+ pData->Group = new char[p2-p1+1];
+ lstrcpyn(pData->Group, p1, p2-p1+1);
+ int iItem = SendDlgItemMessage(hwndDlg, IDC_SERVERCOMBO, CB_ADDSTRING,0,(LPARAM) pData->Name);
+ SendDlgItemMessage(hwndDlg, IDC_SERVERCOMBO, CB_SETITEMDATA, iItem,(LPARAM) pData);
+
+ }
+ else
+ EnableWindow(GetDlgItem(hwndDlg, IDNOK), false);
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_SERVER), EM_SETREADONLY, true, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_PORT), EM_SETREADONLY, true, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_PORT2), EM_SETREADONLY, true, 0);
+
+ if (prefs->QuickComboSelection != -1)
+ {
+ SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_SETCURSEL, prefs->QuickComboSelection,0);
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_SERVERCOMBO, CBN_SELCHANGE), 0);
+ }
+ else
+ EnableWindow(GetDlgItem(hwndDlg, IDNOK), false);
+
+ } break;
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ {
+ if((HWND)lParam==GetDlgItem(hwndDlg,IDC_WHITERECT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_TEXT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_CAPTION)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_LOGO))
+ {
+ SetTextColor((HDC)wParam,RGB(0,0,0));
+ SetBkColor((HDC)wParam,RGB(255,255,255));
+ return (BOOL)GetStockObject(WHITE_BRUSH);
+ }
+ }break;
+
+
+ case WM_COMMAND:
+ {
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDNCANCEL)
+ {
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDNOK)
+ {
+ GetDlgItemText(hwndDlg,IDC_SERVER, prefs->ServerName, 100);
+ GetDlgItemText(hwndDlg,IDC_PORT, prefs->PortStart, 7);
+ GetDlgItemText(hwndDlg,IDC_PORT2, prefs->PortEnd , 7);
+ GetDlgItemText(hwndDlg,IDC_PASS, prefs->Password, 500);
+
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETITEMDATA, i, 0);
+ if (pData && (int)pData != CB_ERR)
+ {
+ lstrcpy(prefs->Network, pData->Group);
+ if(m_ssleay32)
+ prefs->iSSL = pData->iSSL;
+ else
+ prefs->iSSL = 0;
+ }
+
+ char windowname[20];
+ GetWindowText(hwndDlg, windowname, 20);
+ if (lstrcmpi(windowname, "Miranda IRC") == 0)
+ {
+ prefs->ServerComboSelection = SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+ DBWriteContactSettingDword(NULL,IRCPROTONAME,"ServerComboSelection",prefs->ServerComboSelection);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"ServerName",prefs->ServerName);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"PortStart",prefs->PortStart);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"PortEnd",prefs->PortEnd);
+ CallService(MS_DB_CRYPT_ENCODESTRING, 499, (LPARAM)prefs->Password);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"Password",prefs->Password);
+ CallService(MS_DB_CRYPT_DECODESTRING, 499, (LPARAM)prefs->Password);
+ DBWriteContactSettingString(NULL,IRCPROTONAME,"Network",prefs->Network);
+ DBWriteContactSettingByte(NULL,IRCPROTONAME,"UseSSL",prefs->iSSL);
+
+ }
+ prefs->QuickComboSelection = SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+ DBWriteContactSettingDword(NULL,IRCPROTONAME,"QuickComboSelection",prefs->QuickComboSelection);
+ DisconnectFromServer();
+ ConnectToServer();
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }
+
+
+ if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_SERVERCOMBO)
+ {
+
+
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCURSEL, 0, 0);
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETITEMDATA, i, 0);
+ if (i !=CB_ERR)
+ {
+ SetDlgItemText(hwndDlg,IDC_SERVER,pData->Address);
+ SetDlgItemText(hwndDlg,IDC_PORT,pData->PortStart);
+ SetDlgItemText(hwndDlg,IDC_PORT2,pData->PortEnd);
+ SetDlgItemText(hwndDlg,IDC_PASS,"");
+ if(m_ssleay32)
+ {
+ if(pData->iSSL == 0)
+ SetDlgItemText(hwndDlg,IDC_SSL,Translate("Off") );
+ if(pData->iSSL == 1)
+ SetDlgItemText(hwndDlg,IDC_SSL,Translate("Auto") );
+ if(pData->iSSL == 2)
+ SetDlgItemText(hwndDlg,IDC_SSL,Translate("On") );
+ }
+ else
+ SetDlgItemText(hwndDlg,IDC_SSL, Translate("N/A"));
+ EnableWindow(GetDlgItem(hwndDlg, IDNOK), true);
+
+ }
+
+ }
+
+
+ } break;
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+
+ } break;
+
+ case WM_DESTROY:
+ {
+ HFONT hFont;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,SendDlgItemMessage(hwndDlg,IDNOK,WM_GETFONT,0,0),0);
+ DeleteObject(hFont);
+
+ int j = (int) SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETCOUNT, 0, 0);
+ for (int index2 = 0; index2 < j; index2++)
+ {
+ SERVER_INFO * pData = (SERVER_INFO *)SendMessage(GetDlgItem(hwndDlg, IDC_SERVERCOMBO), CB_GETITEMDATA, index2, 0);
+ delete []pData->Name;
+ delete []pData->Address;
+ delete []pData->PortStart;
+ delete []pData->PortEnd;
+ delete []pData->Group;
+ delete pData;
+
+ }
+
+ quickconn_hWnd = NULL;
+ } break;
+
+
+ default:break;
+ }
+ return(false);
+}
+
+int CALLBACK ListViewSort(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+ if (!list_hWnd)
+ return 0;
+ char temp1[512];
+ char temp2[512];
+ LVITEM lvm;
+ lvm.mask = LVIF_TEXT;
+ lvm.iItem = lParam1;
+ lvm.iSubItem = lParamSort;
+ lvm.pszText = temp1;
+ lvm.cchTextMax = 511;
+ SendMessage(GetDlgItem(list_hWnd, IDC_INFO_LISTVIEW), LVM_GETITEM, 0, (LPARAM)&lvm);
+ lvm.iItem = lParam2;
+ lvm.pszText = temp2;
+ SendMessage(GetDlgItem(list_hWnd, IDC_INFO_LISTVIEW), LVM_GETITEM, 0, (LPARAM)&lvm);
+ if (lParamSort != 1){
+ if (lstrlen(temp1) !=0 && lstrlen(temp2) !=0)
+ return lstrcmpi(temp1, temp2);
+ else
+ {
+ if(lstrlen(temp1) ==0 )
+ return 1;
+ else
+ return -1;
+ }
+ }
+ else {
+ if(StrToInt(temp1) < StrToInt(temp2))
+ return 1;
+ else
+ return -1;
+ }
+}
+static void __cdecl AckUserInfoSearch(void * lParam)
+{
+ ProtoBroadcastAck(IRCPROTONAME, (void*)lParam, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
+}
+
+#define STR_BASIC "Faster! Searches the network for an exact match of the nickname only. The hostmask is optional and provides further security if used. Wildcards (? and *) are allowed."
+#define STR_ADVANCED "Slower! Searches the network for nicknames matching a wildcard string. The hostmask is mandatory and a minimum of 4 characters is necessary in the \"Nick\" field. Wildcards (? and *) are allowed."
+#define STR_ERROR "Settings could not be saved!\n\nThe \"Nick\" field must contain at least four characters including wildcards,\n and it must also match the default nickname for this contact."
+#define STR_ERROR2 "Settings could not be saved!\n\nA full hostmask must be set for this online detection mode to work."
+
+BOOL CALLBACK UserDetailsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact;
+ hContact = (HANDLE) GetWindowLong(hwndDlg, GWL_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ DBVARIANT dbv;
+ hContact = (HANDLE) lParam;
+ BYTE bAdvanced = DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0);
+
+ TranslateDialogDefault(hwndDlg);
+
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) hContact);
+
+ CheckDlgButton(hwndDlg, IDC_RADIO1, bAdvanced?BST_UNCHECKED:BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_RADIO2, bAdvanced?BST_CHECKED:BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_WILDCARD), bAdvanced);
+
+ if(!bAdvanced)
+ {
+ SetDlgItemText(hwndDlg, IDC_DEFAULT, STR_BASIC);
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv) && dbv.type == DBVT_ASCIIZ) {
+ SetDlgItemText(hwndDlg, IDC_WILDCARD, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ else
+ {
+ SetDlgItemText(hwndDlg, IDC_DEFAULT, STR_ADVANCED);
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv) && dbv.type == DBVT_ASCIIZ) {
+ SetDlgItemText(hwndDlg, IDC_WILDCARD, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UUser", &dbv) && dbv.type == DBVT_ASCIIZ) {
+ SetDlgItemText(hwndDlg, IDC_USER, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UHost", &dbv) && dbv.type == DBVT_ASCIIZ) {
+ SetDlgItemText(hwndDlg, IDC_HOST, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ forkthread(AckUserInfoSearch, 0, hContact);
+
+ }break;
+ case WM_COMMAND:
+ {
+
+ if( (LOWORD(wParam)==IDC_WILDCARD
+ || LOWORD(wParam)==IDC_USER
+ || LOWORD(wParam) == IDC_HOST
+ )
+ && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return true;
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON), true);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON2), true);
+
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_BUTTON)
+ {
+ char temp[500];
+ GetDlgItemText(hwndDlg, IDC_WILDCARD, temp, 500);
+ DBVARIANT dbv;
+ BYTE bAdvanced = IsDlgButtonChecked(hwndDlg, IDC_RADIO1)?0:1;
+
+
+
+ if(bAdvanced)
+ {
+ if(GetWindowTextLength(GetDlgItem(hwndDlg, IDC_WILDCARD)) == 0
+ || GetWindowTextLength(GetDlgItem(hwndDlg, IDC_USER)) == 0
+ || GetWindowTextLength(GetDlgItem(hwndDlg, IDC_HOST)) == 0)
+ {
+ MessageBox(NULL, Translate( STR_ERROR2 ), Translate("IRC error"), MB_OK|MB_ICONERROR);
+ return false;
+ }
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv) && dbv.type == DBVT_ASCIIZ )
+ {
+ String S = STR_ERROR + (String)" (" + dbv.pszVal + (String)")";
+ if((lstrlen(temp) <4 && lstrlen(temp)) || !WCCmp(CharLower(temp), CharLower(dbv.pszVal)))
+ {
+ MessageBox(NULL, Translate( S.c_str() ), Translate("IRC error"), MB_OK|MB_ICONERROR);
+ DBFreeVariant(&dbv);
+ return false;
+ }
+ DBFreeVariant(&dbv);
+ }
+ GetDlgItemText(hwndDlg, IDC_WILDCARD, temp, 500);
+ if (lstrlen(GetWord(temp, 0).c_str()))
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "UWildcard", GetWord(temp, 0).c_str());
+ else
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "UWildcard");
+ }
+
+ DBWriteContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", bAdvanced);
+
+ GetDlgItemText(hwndDlg, IDC_USER, temp, 500);
+ if (lstrlen(GetWord(temp, 0).c_str()))
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "UUser", GetWord(temp, 0).c_str());
+ else
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "UUser");
+
+ GetDlgItemText(hwndDlg, IDC_HOST, temp, 500);
+ if (lstrlen(GetWord(temp, 0).c_str()))
+ DBWriteContactSettingString(hContact, IRCPROTONAME, "UHost", GetWord(temp, 0).c_str());
+ else
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "UHost");
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON), false);
+
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_BUTTON2)
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_RADIO2))
+ SetDlgItemText(hwndDlg, IDC_WILDCARD, "");
+ SetDlgItemText(hwndDlg, IDC_HOST, "");
+ SetDlgItemText(hwndDlg, IDC_USER, "");
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "UWildcard");
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "UUser");
+ DBDeleteContactSetting(hContact, IRCPROTONAME, "UHost");
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON2), false);
+
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_RADIO1)
+ {
+ DBVARIANT dbv;
+ SetDlgItemText(hwndDlg, IDC_DEFAULT, STR_BASIC);
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv) && dbv.type == DBVT_ASCIIZ) {
+ SetDlgItemText(hwndDlg, IDC_WILDCARD, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_WILDCARD), false);
+
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_RADIO2)
+ {
+ DBVARIANT dbv;
+ SetDlgItemText(hwndDlg, IDC_DEFAULT, STR_ADVANCED);
+ if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv) && dbv.type == DBVT_ASCIIZ) {
+ SetDlgItemText(hwndDlg, IDC_WILDCARD, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_WILDCARD), true);
+
+ }
+
+ }break;
+ }
+ return FALSE;
+}
+BOOL CALLBACK QuestionWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ HFONT hFont;
+ LOGFONT lf;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ GetObject(hFont,sizeof(lf),&lf);
+ lf.lfHeight=(int)(lf.lfHeight*1.2);
+ lf.lfWeight=FW_BOLD;
+ hFont=CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,(WPARAM)hFont,0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LOGO),STM_SETICON,(LPARAM)(HICON)LoadIconEx(IDI_LOGO,"logo",48,48), 0);
+
+ } break;
+
+ case WM_COMMAND:
+ {
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDNCANCEL)
+ {
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDNOK)
+ {
+ int i = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_EDIT));
+ if (i > 0)
+ {
+ char * l= new char[i +2];
+ GetDlgItemText(hwndDlg, IDC_EDIT, l, 200);
+
+ int j = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_HIDDENEDIT));
+ char * m;
+ m = new char[j+2];
+ GetDlgItemText(hwndDlg, IDC_HIDDENEDIT, m, j+1);
+
+ char * text = strstr(m, "%question");
+ char * p1 = text;
+ char * p2 = NULL;
+ if (p1)
+ {
+ p1 += 9;
+ if (*p1 == '=' && p1[1] == '\"')
+ {
+ p1 += 2;
+ for (int k =0; k< 3;k++)
+ {
+ p2 = strchr(p1, '\"');
+ if (p2)
+ {
+ p2++;
+ if (k == 2 || (*p2 != ',' || (*p2 == ',' && p2[1] != '\"')))
+ {
+ *p2 = '\0';
+
+ }
+ else
+ p2 +=2;
+ p1 = p2;
+ }
+ }
+
+ }
+ else
+ *p1 = '\0';
+
+ }
+
+ char * n;
+ n = new char[j+2];
+ GetDlgItemText(hwndDlg, IDC_HIDDENEDIT, n, j+1);
+
+ String S = ReplaceString(n, text, l);
+
+ PostIrcMessageWnd( NULL, NULL, (char*)S.c_str());
+
+ delete []m;
+ delete []l;
+ delete []n;
+ HWND hwnd = GetParent(hwndDlg);
+ if(hwnd)
+ SendMessage(hwnd, IRC_QUESTIONAPPLY, 0, 0);
+
+ }
+ SendMessage (hwndDlg, WM_CLOSE, 0,0);
+
+ }
+
+
+
+ } break;
+ case IRC_ACTIVATE:
+ {
+ ShowWindow(hwndDlg, SW_SHOW);
+ SetActiveWindow(hwndDlg);
+ }break;
+ case WM_CLOSE:
+ {
+ HWND hwnd = GetParent(hwndDlg);
+ if(hwnd)
+ SendMessage(GetParent(hwndDlg), IRC_QUESTIONCLOSE, 0, 0);
+ DestroyWindow(hwndDlg);
+
+ } break;
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ {
+ if((HWND)lParam==GetDlgItem(hwndDlg,IDC_WHITERECT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_TEXT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_CAPTION)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_LOGO))
+ {
+ SetTextColor((HDC)wParam,RGB(0,0,0));
+ SetBkColor((HDC)wParam,RGB(255,255,255));
+ return (BOOL)GetStockObject(WHITE_BRUSH);
+ }
+ }break;
+ case WM_DESTROY:
+ {
+ HFONT hFont;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,SendDlgItemMessage(hwndDlg,IDNOK,WM_GETFONT,0,0),0);
+ DeleteObject(hFont);
+
+ } break;
+
+ default:break;
+ }
+ return(false);
+}
+
+BOOL CALLBACK ManagerWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ HFONT hFont;
+ LOGFONT lf;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ GetObject(hFont,sizeof(lf),&lf);
+ lf.lfHeight=(int)(lf.lfHeight*1.2);
+ lf.lfWeight=FW_BOLD;
+ hFont=CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,(WPARAM)hFont,0);
+
+ POINT pt;
+ pt.x = 3;
+ pt.y = 3;
+ HWND hwndEdit = ChildWindowFromPoint(GetDlgItem(hwndDlg, IDC_TOPIC), pt);
+
+ OldMgrEditProc = (WNDPROC)SetWindowLong(hwndEdit, GWL_WNDPROC,(LONG)MgrEditSubclassProc);
+
+ SendDlgItemMessage(hwndDlg,IDC_ADD,BM_SETIMAGE,IMAGE_ICON,(LPARAM)(HICON)LoadIconEx(IDI_ADD,"add",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendDlgItemMessage(hwndDlg,IDC_REMOVE,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_DELETE,"delete",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendDlgItemMessage(hwndDlg,IDC_EDIT,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_RENAME,"rename",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendMessage(GetDlgItem(hwndDlg,IDC_ADD), BUTTONADDTOOLTIP, (WPARAM)Translate("Add ban/invite/exception"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_EDIT), BUTTONADDTOOLTIP, (WPARAM)Translate("Edit selected ban/invite/exception"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_REMOVE), BUTTONADDTOOLTIP, (WPARAM)Translate("Delete selected ban/invite/exception"), 0);
+
+ SendMessage(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM)LoadIconEx(IDI_MANAGER,"manager",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendMessage(GetDlgItem(hwndDlg, IDC_LOGO),STM_SETICON,(LPARAM)(HICON)LoadIconEx(IDI_LOGO,"logo",48,48), 0);
+ SendDlgItemMessage(hwndDlg,IDC_APPLYTOPIC,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_GO,"go",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendDlgItemMessage(hwndDlg,IDC_APPLYMODES,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx(IDI_GO,"go",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)));
+ SendMessage(GetDlgItem(hwndDlg,IDC_APPLYTOPIC), BUTTONADDTOOLTIP, (WPARAM)Translate("Set this topic for the channel"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_APPLYMODES), BUTTONADDTOOLTIP, (WPARAM)Translate("Set these modes for the channel"), 0);
+
+ SendDlgItemMessage(hwndDlg,IDC_LIST,LB_SETHORIZONTALEXTENT,750,NULL);
+ CheckDlgButton(hwndDlg, IDC_RADIO1, BST_CHECKED);
+ if (!strchr(sChannelModes.c_str(), 't'))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK1), false);
+ if (!strchr(sChannelModes.c_str(), 'n'))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK2), false);
+ if (!strchr(sChannelModes.c_str(), 'i'))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK3), false);
+ if (!strchr(sChannelModes.c_str(), 'm'))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK4), false);
+ if (!strchr(sChannelModes.c_str(), 'k'))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK5), false);
+ if (!strchr(sChannelModes.c_str(), 'l'))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK6), false);
+ if (!strchr(sChannelModes.c_str(), 'p'))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK7), false);
+ if (!strchr(sChannelModes.c_str(), 's'))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK8), false);
+ } break;
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ {
+ if((HWND)lParam==GetDlgItem(hwndDlg,IDC_WHITERECT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_TEXT)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_CAPTION)
+ || (HWND)lParam==GetDlgItem(hwndDlg,IDC_LOGO))
+ {
+ SetTextColor((HDC)wParam,RGB(0,0,0));
+ SetBkColor((HDC)wParam,RGB(255,255,255));
+ return (BOOL)GetStockObject(WHITE_BRUSH);
+ }
+ }break;
+ case IRC_INITMANAGER:
+ {
+ char * window = (char *) lParam;
+ CHANNELINFO* wi = (CHANNELINFO *)DoEvent(GC_EVENT_GETITEMDATA, window, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, 0);
+
+ if(wi)
+ {
+ if (g_ircSession)
+ {
+ char temp[1000];
+ mir_snprintf(temp, sizeof(temp), "Topic%s%s", window, g_ircSession.GetInfo().sNetwork.c_str());
+
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, IRCPROTONAME, temp, &dbv) && dbv.type == DBVT_ASCIIZ)
+ {
+ for (int i = 0; i<5; i++) {
+ if (!GetWord(dbv.pszVal, i).empty()) {
+ String S = ReplaceString(GetWord(dbv.pszVal, i) ,"%¤" , " ");
+ SendDlgItemMessage(hwndDlg, IDC_TOPIC, CB_ADDSTRING, 0, (LPARAM)S.c_str());
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ if(wi->pszTopic)
+ SetDlgItemText(hwndDlg, IDC_TOPIC, wi->pszTopic);
+
+ if (!IsDlgButtonChecked(manager_hWnd, IDC_NOTOP))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), true);
+
+
+ bool add =false;
+ char * p1= wi->pszMode;
+ if(p1)
+ {
+ while (*p1 != '\0' && *p1 != ' ')
+ {
+ if (*p1 == '+')
+ add = true;
+ if (*p1 == '-')
+ add = false;
+ if (*p1 == 't')
+ CheckDlgButton(hwndDlg, IDC_CHECK1, add?(BST_CHECKED) : (BST_UNCHECKED));
+ if (*p1 == 'n')
+ CheckDlgButton(hwndDlg, IDC_CHECK2, add?(BST_CHECKED) : (BST_UNCHECKED));
+ if (*p1 == 'i')
+ CheckDlgButton(hwndDlg, IDC_CHECK3, add?(BST_CHECKED) : (BST_UNCHECKED));
+ if (*p1 == 'm')
+ CheckDlgButton(hwndDlg, IDC_CHECK4, add?(BST_CHECKED) : (BST_UNCHECKED));
+ if (*p1 == 'p')
+ CheckDlgButton(hwndDlg, IDC_CHECK7, add?(BST_CHECKED) : (BST_UNCHECKED));
+ if (*p1 == 's')
+ CheckDlgButton(hwndDlg, IDC_CHECK8, add?(BST_CHECKED) : (BST_UNCHECKED));
+ if (*p1 == 'k' && add) {
+ CheckDlgButton(hwndDlg, IDC_CHECK5, add?(BST_CHECKED) : (BST_UNCHECKED));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY), add?(true) : (false));
+ if(wi->pszPassword)
+ SetDlgItemText(hwndDlg, IDC_KEY, wi->pszPassword);
+ }
+ if (*p1 == 'l' && add) {
+ CheckDlgButton(hwndDlg, IDC_CHECK6, add?(BST_CHECKED) : (BST_UNCHECKED));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), add?(true) : (false));
+ if(wi->pszLimit)
+ SetDlgItemText(hwndDlg, IDC_LIMIT, wi->pszLimit);
+ }
+ p1++;
+ if (wParam ==0)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), (false));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY), (false));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK1), (false));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK2), (false));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK3), (false));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK4), (false));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK5), (false));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK6), (false));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK7), (false));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK8), (false));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), (false));
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHECK1))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TOPIC), (false));
+ CheckDlgButton(hwndDlg, IDC_NOTOP, BST_CHECKED);
+
+ }
+ ShowWindow(hwndDlg, SW_SHOW);
+
+ }
+ }
+ }
+ if (strchr(sChannelModes.c_str(), 'b'))
+ {
+ CheckDlgButton(hwndDlg, IDC_RADIO1, BST_CHECKED);
+ PostIrcMessage( "/MODE %s +b", window);
+ }
+
+ } break;
+ case WM_COMMAND:
+ {
+ if(
+ ( LOWORD(wParam)==IDC_LIMIT
+ || LOWORD(wParam)==IDC_KEY
+ )
+ && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return true;
+ char window[256];
+ GetDlgItemText(hwndDlg, IDC_CAPTION, window, 255);
+
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCLOSE)
+ {
+ PostMessage (hwndDlg, WM_CLOSE, 0,0);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_REMOVE)
+ {
+ int i = SendDlgItemMessage(hwndDlg, IDC_LIST, LB_GETCURSEL, 0, 0);
+ if (i != LB_ERR)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), false);
+ char * m = new char[SendDlgItemMessage(hwndDlg, IDC_LIST, LB_GETTEXTLEN, i, 0)+2];
+ SendDlgItemMessage(hwndDlg, IDC_LIST, LB_GETTEXT, i, (LPARAM)m);
+ String user = GetWord(m, 0);
+ delete[]m;
+ char temp[100];
+ char mode[3];
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO1))
+ {
+ lstrcpy(mode, "-b");
+ lstrcpyn(temp, Translate( "Remove ban?" ), 100);
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO2))
+ {
+ lstrcpy(mode, "-I");
+ lstrcpyn(temp, Translate( "Remove invite?" ), 100);
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO3))
+ {
+ lstrcpy(mode, "-e");
+ lstrcpyn(temp, Translate( "Remove exception?" ), 100);
+ }
+
+ if (MessageBox(hwndDlg,user.c_str(), temp, MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDYES)
+ {
+ PostIrcMessage( "/MODE %s %s %s", window, mode, user.c_str());
+ SendMessage(hwndDlg, IRC_QUESTIONAPPLY, 0, 0);
+
+ }
+ SendMessage(hwndDlg, IRC_QUESTIONCLOSE, 0, 0);
+ }
+ }
+
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_EDIT)
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_NOTOP))
+ break;
+
+ int i = SendDlgItemMessage(hwndDlg, IDC_LIST, LB_GETCURSEL, 0, 0);
+ if (i != LB_ERR)
+ {
+ char * m = new char[SendDlgItemMessage(hwndDlg, IDC_LIST, LB_GETTEXTLEN, i, 0)+2];
+ SendDlgItemMessage(hwndDlg, IDC_LIST, LB_GETTEXT, i, (LPARAM)m);
+ String user = GetWord(m, 0);
+ delete[]m;
+ char temp[100];
+ char mode[3];
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO1))
+ {
+ lstrcpy(mode, "b");
+ lstrcpyn(temp, Translate( "Edit ban" ), 100);
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO2))
+ {
+ lstrcpy(mode, "I");
+ lstrcpyn(temp, Translate( "Edit invite?" ), 100);
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO3))
+ {
+ lstrcpy(mode, "e");
+ lstrcpyn(temp, Translate( "Edit exception?" ), 100);
+ }
+
+ HWND addban_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_QUESTION),hwndDlg, QuestionWndProc);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), false);
+ SetDlgItemText(addban_hWnd, IDC_CAPTION, temp);
+ SetWindowText(GetDlgItem(addban_hWnd, IDC_TEXT), Translate( "Please enter the hostmask (nick!user@host)" ));
+ SetWindowText(GetDlgItem(addban_hWnd, IDC_EDIT), user.c_str());
+ char temp2[450];
+ mir_snprintf(temp2, 450, "/MODE %s -%s %s%s/MODE %s +%s %s", window, mode, user.c_str(), "%newl", window, mode, "%question");
+ SetDlgItemText(addban_hWnd, IDC_HIDDENEDIT, temp2);
+ PostMessage(addban_hWnd, IRC_ACTIVATE, 0, 0);
+ }
+ }
+ if(HIWORD(wParam) == LBN_SELCHANGE && LOWORD(wParam) == IDC_LIST)
+ {
+ if(!IsDlgButtonChecked(hwndDlg, IDC_NOTOP))
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), true);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), true);
+ }
+ }
+ if(HIWORD(wParam) == LBN_DBLCLK && LOWORD(wParam) == IDC_LIST)
+ {
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDIT, BN_CLICKED), 0);
+ }
+
+ if(HIWORD(wParam) == EN_CHANGE && (LOWORD(wParam) == IDC_LIMIT || LOWORD(wParam) == IDC_KEY))
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLYMODES), true);
+ }
+
+ if ((HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE) && LOWORD(wParam) == IDC_TOPIC)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLYTOPIC), true);
+
+ return false;
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_APPLYTOPIC)
+ {
+ char temp[470];
+ GetDlgItemText(hwndDlg, IDC_TOPIC, temp, 470);
+ PostIrcMessage ( "/TOPIC %s %s", window, temp);
+ int i = SendDlgItemMessage(hwndDlg, IDC_TOPIC, CB_FINDSTRINGEXACT, -1, (LPARAM)temp);
+ if(i!=LB_ERR)
+ SendDlgItemMessage(hwndDlg, IDC_TOPIC, CB_DELETESTRING, i, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TOPIC, CB_INSERTSTRING, 0, (LPARAM)temp);
+ SetDlgItemText(hwndDlg, IDC_TOPIC, temp);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLYTOPIC), false);
+
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_CHECK5)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY), IsDlgButtonChecked(hwndDlg, IDC_CHECK5)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLYMODES), true);
+
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_ADD)
+ {
+ char temp[100];
+ char mode[3];
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO1))
+ {
+ lstrcpy(mode, "+b");
+ lstrcpyn(temp, Translate( "Add ban" ), 100);
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO2))
+ {
+ lstrcpy(mode, "+I");
+ lstrcpyn(temp, Translate( "Add invite" ), 100);
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO3))
+ {
+ lstrcpy(mode, "+e");
+ lstrcpyn(temp, Translate( "Add exception" ), 100);
+ }
+ HWND addban_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_QUESTION),hwndDlg, QuestionWndProc);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), false);
+ SetDlgItemText(addban_hWnd, IDC_CAPTION, temp);
+ SetWindowText(GetDlgItem(addban_hWnd, IDC_TEXT), Translate( "Please enter the hostmask (nick!user@host)" ));
+ char temp2[450];
+ mir_snprintf(temp2, 450, "/MODE %s %s %s", window, mode, "%question");
+ SetDlgItemText(addban_hWnd, IDC_HIDDENEDIT, temp2);
+ PostMessage(addban_hWnd, IRC_ACTIVATE, 0, 0);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_CHECK6)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), IsDlgButtonChecked(hwndDlg, IDC_CHECK6)== BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLYMODES), true);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDC_RADIO1 || LOWORD(wParam) == IDC_RADIO3 || LOWORD(wParam) == IDC_RADIO2))
+ {
+ SendMessage(hwndDlg, IRC_QUESTIONAPPLY, 0, 0);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDC_CHECK1
+ || LOWORD(wParam) == IDC_CHECK2
+ || LOWORD(wParam) == IDC_CHECK3
+ || LOWORD(wParam) == IDC_CHECK4
+ || LOWORD(wParam) == IDC_CHECK7
+ || LOWORD(wParam) == IDC_CHECK8))
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLYMODES), true);
+ }
+ if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_APPLYMODES)
+ {
+ CHANNELINFO* wi = (CHANNELINFO *)DoEvent(GC_EVENT_GETITEMDATA, window, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, 0);
+ if (wi )
+ {
+ char toadd[10]; *toadd = '\0';
+ char toremove[10]; *toremove = '\0';
+ String appendixadd = "";
+ String appendixremove = "";
+ if(wi->pszMode && strchr(wi->pszMode, 't'))
+ {
+ if(!IsDlgButtonChecked(hwndDlg, IDC_CHECK1))
+ lstrcat(toremove, "t");
+ }
+ else
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHECK1))
+ lstrcat(toadd, "t");
+ }
+
+ if(wi->pszMode && strchr(wi->pszMode, 'n'))
+ {
+ if(!IsDlgButtonChecked(hwndDlg, IDC_CHECK2))
+ lstrcat(toremove, "n");
+ }
+ else
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHECK2))
+ lstrcat(toadd, "n");
+ }
+
+ if(wi->pszMode && strchr(wi->pszMode, 'i'))
+ {
+ if(!IsDlgButtonChecked(hwndDlg, IDC_CHECK3))
+ lstrcat(toremove, "i");
+ }
+ else
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHECK3))
+ lstrcat(toadd, "i");
+ }
+
+ if(wi->pszMode && strchr(wi->pszMode, 'm'))
+ {
+ if(!IsDlgButtonChecked(hwndDlg, IDC_CHECK4))
+ lstrcat(toremove, "m");
+ }
+ else
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHECK4))
+ lstrcat(toadd, "m");
+ }
+
+ if(wi->pszMode && strchr(wi->pszMode, 'p'))
+ {
+ if(!IsDlgButtonChecked(hwndDlg, IDC_CHECK7))
+ lstrcat(toremove, "p");
+ }
+ else
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHECK7))
+ lstrcat(toadd, "p");
+ }
+
+ if(wi->pszMode && strchr(wi->pszMode, 's'))
+ {
+ if(!IsDlgButtonChecked(hwndDlg, IDC_CHECK8))
+ lstrcat(toremove, "s");
+ }
+ else
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHECK8))
+ lstrcat(toadd, "s");
+ }
+ String Key = "";
+ String Limit = "";
+ if(wi->pszMode && wi->pszPassword && strchr(wi->pszMode, 'k'))
+ {
+ if(!IsDlgButtonChecked(hwndDlg, IDC_CHECK5) )
+ {
+ lstrcat(toremove, "k");
+ appendixremove += " ";
+ appendixremove += wi->pszPassword;
+ }
+ else if(GetWindowTextLength(GetDlgItem(hwndDlg, IDC_KEY)))
+ {
+ char temp[400];
+ GetDlgItemText(hwndDlg, IDC_KEY, temp, 14);
+
+ if(Key != temp) {
+ lstrcat(toremove, "k");
+ lstrcat(toadd, "k");
+ appendixadd += " ";
+ appendixadd += temp;
+ appendixremove += " ";
+ appendixremove += wi->pszPassword;
+ }
+ }
+ }
+ else
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHECK5) && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_KEY)))
+ {
+ lstrcat(toadd, "k");
+ appendixadd +=" ";
+ char temp[400];
+ GetDlgItemText(hwndDlg, IDC_KEY, temp, 399);
+ appendixadd += temp;
+ }
+
+ }
+
+ if(strchr(wi->pszMode, 'l'))
+ {
+ if(!IsDlgButtonChecked(hwndDlg, IDC_CHECK6) )
+ lstrcat(toremove, "l");
+ else if(GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LIMIT)))
+ {
+ char temp[15];
+ GetDlgItemText(hwndDlg, IDC_LIMIT, temp, 14);
+ if(wi->pszLimit && lstrcmpi(wi->pszLimit, temp))
+ {
+ lstrcat(toadd, "l");
+ appendixadd += " ";
+ appendixadd += temp;
+
+ }
+
+
+ }
+ }
+ else
+ {
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHECK6) && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LIMIT)))
+ {
+ lstrcat(toadd, "l");
+ appendixadd +=" ";
+ char temp[15];
+ GetDlgItemText(hwndDlg, IDC_LIMIT, temp, 14);
+ appendixadd += temp;
+ }
+
+ }
+
+
+ if (lstrlen(toadd) || lstrlen(toremove))
+ {
+ char temp[500];
+ lstrcpy(temp, "/mode ");
+ lstrcat(temp, window);
+ lstrcat(temp, " ");
+ if(lstrlen(toremove))
+ mir_snprintf(temp, 499, "%s-%s", temp, toremove);
+ if(lstrlen(toadd))
+ mir_snprintf(temp, 499, "%s+%s", temp, toadd);
+ if (!appendixremove.empty())
+ lstrcat(temp, appendixremove.c_str());
+ if (!appendixadd.empty())
+ lstrcat(temp, appendixadd.c_str());
+ PostIrcMessage ( temp);
+ }
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLYMODES), false);
+
+ }
+
+ } break;
+ case IRC_QUESTIONCLOSE:
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), true);
+ if(SendDlgItemMessage(hwndDlg, IDC_LIST, LB_GETCURSEL, 0, 0) != LB_ERR)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), true);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), true);
+ }
+
+ }break;
+ case IRC_QUESTIONAPPLY:
+ {
+ char window[256];
+ GetDlgItemText(hwndDlg, IDC_CAPTION, window, 255);
+
+ char mode[3];
+ lstrcpy(mode, "+b");
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO2))
+ lstrcpy(mode, "+I");
+ if (IsDlgButtonChecked(hwndDlg, IDC_RADIO3))
+ lstrcpy(mode, "+e");
+ SendDlgItemMessage(hwndDlg, IDC_LIST, LB_RESETCONTENT, 0, 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO1), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO2), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO3), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), false);
+ PostIrcMessage( "%s %s %s", "/MODE", window, mode); //wrong overloaded operator if three args
+
+ }break;
+ case WM_CLOSE:
+ {
+ if (lParam != 3)
+ {
+ if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_APPLYMODES)) || IsWindowEnabled(GetDlgItem(hwndDlg, IDC_APPLYTOPIC)))
+ {
+ int i = MessageBox(hwndDlg, Translate( "You have not applied all changes!\n\nApply before exiting?" ), Translate( "IRC warning" ), MB_YESNOCANCEL|MB_ICONWARNING|MB_DEFBUTTON3);
+ if( i== IDCANCEL)
+ return false;
+
+ if (i == IDYES)
+ {
+ if(IsWindowEnabled(GetDlgItem(hwndDlg, IDC_APPLYMODES)))
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_APPLYMODES, BN_CLICKED), 0);
+ if(IsWindowEnabled(GetDlgItem(hwndDlg, IDC_APPLYTOPIC)))
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_APPLYTOPIC, BN_CLICKED), 0);
+ }
+ }
+ }
+
+ char window[256];
+ GetDlgItemText(hwndDlg, IDC_CAPTION, window, 255);
+ String S = "";
+ char temp[1000];
+ for (int i = 0; i<5; i++)
+ {
+ if (SendDlgItemMessage(hwndDlg, IDC_TOPIC, CB_GETLBTEXT, i, (LPARAM)temp) != LB_ERR)
+ {
+ S += " ";
+ S += ReplaceString(temp ," " , "%¤");
+ }
+ }
+
+ if (S != "" && g_ircSession)
+ {
+ mir_snprintf(temp, sizeof(temp), "Topic%s%s", window, g_ircSession.GetInfo().sNetwork.c_str());
+ DBWriteContactSettingString(NULL, IRCPROTONAME, temp, S.c_str());
+ }
+ DestroyWindow(hwndDlg);
+
+ } break;
+ case WM_DESTROY:
+ {
+ HFONT hFont;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_GETFONT,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_CAPTION,WM_SETFONT,SendDlgItemMessage(hwndDlg,IDNOK,WM_GETFONT,0,0),0);
+ DeleteObject(hFont);
+ manager_hWnd = NULL;
+
+ } break;
+ default:break;
+ }
+ return(false);
+}
+
+LRESULT CALLBACK MgrEditSubclassProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+ switch(msg)
+ {
+ case WM_CHAR :
+ {
+ if (wParam == 21 || wParam == 11 || wParam == 2)
+ {
+ char w[2];
+ if (wParam == 11)
+ {
+ w[0] = 3;
+ w[1] = '\0';
+ }
+ if (wParam == 2)
+ {
+ w[0] = 2;
+ w[1] = '\0';
+ }
+ if (wParam == 21)
+ {
+ w[0] = 31;
+ w[1] = '\0';
+ }
+ SendMessage(hwndDlg, EM_REPLACESEL, false, (LPARAM) w);
+ SendMessage(hwndDlg, EM_SCROLLCARET, 0,0);
+ return 0;
+ }
+
+ } break;
+ default: break;
+
+ }
+ return CallWindowProc(OldMgrEditProc, hwndDlg, msg, wParam, lParam);
+
+}
diff --git a/irc_mod/xstatus.cpp b/irc_mod/xstatus.cpp
new file mode 100644
index 0000000..4a4138e
--- /dev/null
+++ b/irc_mod/xstatus.cpp
@@ -0,0 +1,913 @@
+/*
+IRC plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "irc.h"
+
+extern char * IRCPROTONAME;
+extern char * ALTIRCPROTONAME;
+extern int GlobalStatus;
+
+static int bStatusMenu = 0;
+static int bXStatusMenuBuilt = 0;
+static HANDLE hHookExtraIconsRebuild = NULL;
+static HANDLE hHookStatusBuild = NULL;
+static HANDLE hHookExtraIconsApply = NULL;
+static HMODULE hXStatusIconsDLL = NULL;
+//static HANDLE hXStatusIcons[32];
+HANDLE hXStatusIcons[32];
+static HANDLE hXStatusItems[33];
+
+extern PREFERENCES * prefs;
+
+static DWORD requestXStatusDetails(HANDLE hContact, BOOL bAllowDelay)
+{
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING dcs;
+
+ dcs.szModule=IRCPROTONAME;
+ dcs.szSetting="Nick";
+ dcs.pValue=&dbv;
+ dbv.type=DBVT_ASCIIZ;
+ CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&dcs);
+
+ PostIrcMessage( "/PRIVMSG %s \001XSTATUS\001", dbv.pszVal);
+
+ DBFreeVariant(&dbv);
+
+ return 1;
+}
+
+static void InitXStatusIconLibrary()
+{
+ char path[2*MAX_PATH];
+ char* p;
+
+ // get miranda's exe path
+ GetModuleFileNameA(NULL, path, MAX_PATH);
+ // find the last \ and null it out, this leaves no trailing slash
+ p = strrchr(path, '\\');
+ strcpy(p, "\\plugins");
+ strcat(p, "\\xstatus_icons.dll");
+ hXStatusIconsDLL = LoadLibraryA(path);
+
+ if (!hXStatusIconsDLL)
+ {
+ strcpy(p, "\\icons");
+ strcat(p, "\\xstatus_icons.dll");
+ hXStatusIconsDLL = LoadLibraryA(path);
+ if (!hXStatusIconsDLL)
+ {
+ MessageBoxA(0, "Critical: cannot init IcoLib, no resource DLL found.", "IRC", MB_OK | MB_ICONEXCLAMATION);
+ return;
+ }
+ }
+
+ if (hXStatusIconsDLL)
+ {
+ if (LoadStringA(hXStatusIconsDLL, IDS_IDENTIFY, path, sizeof(path)) == 0 || strcmp(path, "# Custom Status Icons #"))
+ {
+ MessageBoxA(0, "Critical: cannot init IcoLib, wrong resource DLL found.", "IRC", MB_OK | MB_ICONEXCLAMATION);
+ FreeLibrary(hXStatusIconsDLL);
+ hXStatusIconsDLL = NULL;
+ }
+ }
+}
+
+HICON LoadDefaultXStatusIcon(int bStatus)
+{
+ if (hXStatusIconsDLL)
+ return (HICON)LoadImage(hXStatusIconsDLL, MAKEINTRESOURCE(IDI_XSTATUS1 + bStatus - 1), IMAGE_ICON, 0, 0, 0);
+ else
+ return (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_ICON_INFORMATION), IMAGE_ICON, 0, 0, 0);
+}
+
+HICON GetXStatusIcon(int bStatus)
+{
+ char szTemp[64];
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", bStatus - 1);
+
+ if (IconLibInstalled())
+ return IconLibProcess(NULL, szTemp);
+
+ return LoadDefaultXStatusIcon(bStatus);
+}
+
+//static void setContactExtraIcon(HANDLE hContact, HANDLE hIcon)
+void setContactExtraIcon(HANDLE hContact, HANDLE hIcon)
+{
+ IconExtraColumn iec;
+
+ iec.cbSize = sizeof(iec);
+ iec.hImage = hIcon;
+ iec.ColumnType = EXTRA_ICON_ADV1 + DBGetContactSettingByte(NULL,ALTIRCPROTONAME,"XStatusAdv",0);
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)&iec);
+}
+
+static int CListMW_ExtraIconsRebuild(WPARAM wParam, LPARAM lParam)
+{
+ int i;
+
+ if (IRCGetContactSettingByte(NULL, "XStatusEnabled", 0) && ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+ for (i = 0; i < 32; i++)
+ {
+ HICON hXIcon = LoadDefaultXStatusIcon(i + 1);
+ char szTemp[64];
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", i);
+ hXStatusIcons[i] = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)IconLibProcess(hXIcon, szTemp), 0);
+ DestroyIcon(hXIcon);
+ }
+ }
+ return 0;
+}
+
+static int CListMW_ExtraIconsApply(WPARAM wParam, LPARAM lParam)
+{
+if (IRCGetContactSettingByte(NULL, "XStatusEnabled", 0) && ServiceExists(MS_CLIST_EXTRA_SET_ICON))
+ {
+ DWORD bXStatus = IRCGetContactSettingByte((HANDLE)wParam, DBSETTING_XSTATUSID, 0);
+
+ if (bXStatus > 0 && bXStatus < 33)
+ {
+ setContactExtraIcon((HANDLE)wParam, hXStatusIcons[bXStatus-1]);
+ }
+ else
+ {
+ setContactExtraIcon((HANDLE)wParam, (HANDLE)-1);
+ }
+ }
+ return 0;
+}
+
+
+static int CListMW_BuildStatusItems(WPARAM wParam, LPARAM lParam)
+{
+ InitXStatusItems(TRUE);
+ return 0;
+}
+
+
+void InitXStatusEvents()
+{
+ if (!hHookStatusBuild)
+ if (bStatusMenu = ServiceExists(MS_CLIST_ADDSTATUSMENUITEM))
+ hHookStatusBuild = HookEvent(ME_CLIST_PREBUILDSTATUSMENU, CListMW_BuildStatusItems);
+
+ if (!hHookExtraIconsRebuild)
+ hHookExtraIconsRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, CListMW_ExtraIconsRebuild);
+
+ if (!hHookExtraIconsApply)
+ hHookExtraIconsApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, CListMW_ExtraIconsApply);
+}
+
+
+void UninitXStatusEvents()
+{
+ if (hHookStatusBuild)
+ UnhookEvent(hHookStatusBuild);
+
+ if (hHookExtraIconsRebuild)
+ UnhookEvent(hHookExtraIconsRebuild);
+
+ if (hHookExtraIconsApply)
+ UnhookEvent(hHookExtraIconsApply);
+}
+
+const char* nameXStatus[32] = {
+ "Angry",
+ "Taking a bath",
+ "Tired",
+ "Party",
+ "Drinking beer",
+ "Thinking",
+ "Eating",
+ "Watching TV",
+ "Meeting",
+ "Coffee",
+ "Listening to music",
+ "Business",
+ "Shooting",
+ "Having fun",
+ "On the phone",
+ "Gaming",
+ "Studying",
+ "Shopping",
+ "Feeling sick",
+ "Sleeping",
+ "Surfing",
+ "Browsing",
+ "Working",
+ "Typing",
+ "Picnic",
+ "Cooking",
+ "Smoking",
+ "I'm high",
+ "On WC",
+ "To be or not to be",
+ "Reading",
+ "Love"};
+
+/*
+
+void handleXStatusCaps(HANDLE hContact, char* caps, int capsize)
+{
+ HANDLE hIcon = (HANDLE)-1;
+
+// if (!gbXStatusEnabled) return;
+
+ if (caps)
+ {
+ int i;
+
+ for (i = 0; i<32; i++)
+ {
+ if (MatchCap(caps, capsize, (const capstr*)capXStatus[i], 0x10))
+ {
+ char str[MAX_PATH];
+
+ ICQWriteContactSettingByte(hContact, DBSETTING_XSTATUSID, (BYTE)(i+1));
+ ICQWriteContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, ICQTranslateUtfStatic(nameXStatus[i], str));
+
+ if (ICQGetContactSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO))
+ requestXStatusDetails(hContact, TRUE);
+
+ hIcon = hXStatusIcons[i];
+
+ break;
+ }
+ }
+ }
+ if (hIcon == (HANDLE)-1)
+ {
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSID);
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSNAME);
+ ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSMSG);
+ }
+
+ if (gbXStatusEnabled != 10)
+ {
+ setContactExtraIcon(hContact, hIcon);
+ }
+}
+*/
+
+static WNDPROC OldMessageEditProc;
+
+static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_CHAR:
+ if(wParam=='\n' && GetKeyState(VK_CONTROL)&0x8000)
+ {
+ PostMessage(GetParent(hwnd),WM_COMMAND,IDOK,0);
+ return 0;
+ }
+ if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000)
+ { // ctrl-a
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ return 0;
+ }
+ if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000)
+ { // ctrl-w
+ SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0);
+ return 0;
+ }
+ if (wParam == 127 && GetKeyState(VK_CONTROL) & 0x8000)
+ { // ctrl-backspace
+ DWORD start, end;
+ wchar_t *text;
+
+ SendMessage(hwnd, EM_GETSEL, (WPARAM) & end, (LPARAM) (PDWORD) NULL);
+ SendMessage(hwnd, WM_KEYDOWN, VK_LEFT, 0);
+ SendMessage(hwnd, EM_GETSEL, (WPARAM) & start, (LPARAM) (PDWORD) NULL);
+ text = GetWindowTextUcs(hwnd);
+ MoveMemory(text + start, text + end, sizeof(wchar_t) * (wcslen(text) + 1 - end));
+ SetWindowTextUcs(hwnd, text);
+ SAFE_FREE((void **)&text);
+ SendMessage(hwnd, EM_SETSEL, start, start);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM) hwnd);
+ return 0;
+ }
+ break;
+ }
+ return CallWindowProcUtf(OldMessageEditProc,hwnd,msg,wParam,lParam);
+}
+
+typedef struct SetXStatusData_s {
+ BYTE bAction;
+ BYTE bXStatus;
+ HANDLE hContact;
+ HANDLE hEvent;
+ DWORD iEvent;
+ int countdown;
+ char *okButtonFormat;
+} SetXStatusData;
+
+typedef struct InitXStatusData_s {
+ BYTE bAction;
+ BYTE bXStatus;
+ HANDLE hContact;
+} InitXStatusData;
+
+
+#define HM_PROTOACK (WM_USER+10)
+
+static BOOL CALLBACK SetXStatusDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam)
+{
+ SetXStatusData *dat = (SetXStatusData*)GetWindowLong(hwndDlg,GWL_USERDATA);
+ char str[MAX_PATH];
+
+ switch(message)
+ {
+ case HM_PROTOACK:
+ {
+ ACKDATA *ack = (ACKDATA*)lParam;
+ char *szText;
+
+ if (ack->hContact != dat->hContact) break;
+ if ((DWORD)ack->hProcess != dat->iEvent) break;
+
+ ShowWindow(GetDlgItem(hwndDlg, IDC_RETRXSTATUS), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_XMSG), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_XTITLE), SW_SHOW);
+ SetDlgItemTextUtf(hwndDlg,IDOK,IRCTranslateUtfStatic("Close", str));
+ UnhookEvent(dat->hEvent); dat->hEvent = NULL;
+ szText = IRCGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSNAME, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, szText);
+ SAFE_FREE((void **)&szText);
+ szText = IRCGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSMSG, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XMSG, szText);
+ SAFE_FREE((void **)&szText);
+
+ break;
+ }
+ case WM_INITDIALOG:
+ {
+ InitXStatusData *init = (InitXStatusData*)lParam;
+
+ TranslateDialogDefault(hwndDlg);
+ dat = (SetXStatusData*)malloc(sizeof(SetXStatusData));
+ SetWindowLong(hwndDlg,GWL_USERDATA,(LONG)dat);
+ dat->bAction = init->bAction;
+ if (!init->bAction)
+ { // set our xStatus
+ char szSetting[64];
+ char* szValue;
+
+ dat->bXStatus = init->bXStatus;
+ SendDlgItemMessage(hwndDlg, IDC_XTITLE, EM_LIMITTEXT, 256, 0);
+ SendDlgItemMessage(hwndDlg, IDC_XMSG, EM_LIMITTEXT, 1024, 0);
+ OldMessageEditProc = (WNDPROC)SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XTITLE),GWL_WNDPROC,(LONG)MessageEditSubclassProc);
+ OldMessageEditProc = (WNDPROC)SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XMSG),GWL_WNDPROC,(LONG)MessageEditSubclassProc);
+ dat->okButtonFormat = GetDlgItemTextUtf(hwndDlg,IDOK);
+
+ dat->countdown=5;
+ SendMessage(hwndDlg, WM_TIMER, 0, 0);
+ SetTimer(hwndDlg,1,1000,0);
+
+ sprintf(szSetting, "XStatus%dName", dat->bXStatus);
+ szValue = IRCGetContactSettingUtf(NULL, szSetting, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, szValue);
+ SAFE_FREE((void **)&szValue);
+
+ sprintf(szSetting, "XStatus%dMsg", dat->bXStatus);
+ szValue = IRCGetContactSettingUtf(NULL, szSetting, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XMSG, szValue);
+ SAFE_FREE((void **)&szValue);
+ }
+ else
+ { // retrieve contact's xStatus
+ dat->hContact = init->hContact;
+ dat->bXStatus = IRCGetContactSettingByte(dat->hContact, DBSETTING_XSTATUSID, 0);
+ dat->okButtonFormat = NULL;
+ SendMessage(GetDlgItem(hwndDlg, IDC_XTITLE), EM_SETREADONLY, 1, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_XMSG), EM_SETREADONLY, 1, 0);
+ if (!IRCGetContactSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO))
+ {
+ SetDlgItemTextUtf(hwndDlg,IDOK,IRCTranslateUtfStatic("Cancel", str));
+ dat->hEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_PROTOACK);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_RETRXSTATUS), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_XMSG), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_XTITLE), SW_HIDE);
+ dat->iEvent = requestXStatusDetails(dat->hContact, FALSE);
+ }
+ else
+ {
+ char *szText;
+
+ SetDlgItemTextUtf(hwndDlg,IDOK,IRCTranslateUtfStatic("Close", str));
+ dat->hEvent = NULL;
+ szText = IRCGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSNAME, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, szText);
+ SAFE_FREE((void **)&szText);
+ szText = IRCGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSMSG, "");
+ SetDlgItemTextUtf(hwndDlg, IDC_XMSG, szText);
+ SAFE_FREE((void **)&szText);
+ }
+ }
+ {
+ char *format;
+ char buf[MAX_PATH];
+
+ format = GetWindowTextUtf(hwndDlg);
+ null_snprintf(str, sizeof(str), format, dat->bXStatus?IRCTranslateUtfStatic(nameXStatus[dat->bXStatus-1], buf):"");
+ SetWindowTextUtf(hwndDlg, str);
+ SAFE_FREE((void **)&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,IRCTranslateUtfStatic("OK", str));
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ if (!dat->bAction)
+ { // set our xStatus
+ char szSetting[64];
+ char* szValue;
+
+ szValue = GetDlgItemTextUtf(hwndDlg,IDC_XMSG);
+ sprintf(szSetting, "XStatus%dMsg", dat->bXStatus);
+ IRCWriteContactSettingUtf(NULL, szSetting, szValue);
+ IRCWriteContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, szValue);
+ SAFE_FREE((void **)&szValue);
+ szValue = GetDlgItemTextUtf(hwndDlg,IDC_XTITLE);
+ sprintf(szSetting, "XStatus%dName", dat->bXStatus);
+ IRCWriteContactSettingUtf(NULL, szSetting, szValue);
+ IRCWriteContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, szValue);
+ SAFE_FREE((void **)&szValue);
+
+ SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XMSG),GWL_WNDPROC,(LONG)OldMessageEditProc);
+ SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XTITLE),GWL_WNDPROC,(LONG)OldMessageEditProc);
+ }
+ if (dat->hEvent) UnhookEvent(dat->hEvent);
+ SAFE_FREE((void **)&dat->okButtonFormat);
+ SAFE_FREE((void **)&dat);
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ return FALSE;
+}
+
+static void setXStatusEx(BYTE bXStatus, BYTE bQuiet)
+{
+ CLISTMENUITEM mi = {0};
+ BYTE bOldXStatus = IRCGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+
+ mi.cbSize = sizeof(mi);
+
+ if (bOldXStatus <= 32)
+ {
+ mi.flags = CMIM_FLAGS;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[bOldXStatus], (LPARAM)&mi);
+ }
+
+ IRCWriteContactSettingByte(NULL, DBSETTING_XSTATUSID, bXStatus);
+ mi.flags = CMIM_FLAGS | (bXStatus?CMIF_CHECKED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[bXStatus], (LPARAM)&mi);
+
+ if (bXStatus)
+ {
+ char szSetting[64];
+ char str[MAX_PATH];
+ char* szUtf;
+
+ sprintf(szSetting, "XStatus%dName", bXStatus);
+ szUtf = IRCGetContactSettingUtf(NULL, szSetting, IRCTranslateUtfStatic(nameXStatus[bXStatus-1], str));
+ IRCWriteContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, szUtf);
+ SAFE_FREE((void **)&szUtf);
+
+ sprintf(szSetting, "XStatus%dMsg", bXStatus);
+ szUtf = IRCGetContactSettingUtf(NULL, szSetting, "");
+ IRCWriteContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, szUtf);
+ SAFE_FREE((void **)&szUtf);
+
+ sprintf(szSetting, "XStatus%dStat", bXStatus);
+ if (!bQuiet && !IRCGetContactSettingByte(NULL, szSetting, 0))
+ {
+ InitXStatusData init;
+
+ init.bAction = 0; // set
+ init.bXStatus = bXStatus;
+ DialogBoxUtf(FALSE, g_hInstance, MAKEINTRESOURCEA(IDD_SETXSTATUS),NULL,SetXStatusDlgProc,(LPARAM)&init);
+ }
+ }
+ else
+ {
+ IRCDeleteContactSetting(NULL, DBSETTING_XSTATUSNAME);
+ IRCDeleteContactSetting(NULL, DBSETTING_XSTATUSMSG);
+ }
+}
+
+static void __fastcall setXStatus(BYTE bXStatus)
+{ // for menu commands
+ setXStatusEx(bXStatus, 0);
+}
+
+static int menuXStatus0(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(0); return 0;
+}
+
+static int menuXStatus1(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(1); return 0;
+}
+
+static int menuXStatus2(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(2); return 0;
+}
+
+static int menuXStatus3(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(3); return 0;
+}
+
+static int menuXStatus4(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(4); return 0;
+}
+
+static int menuXStatus5(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(5); return 0;
+}
+
+static int menuXStatus6(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(6); return 0;
+}
+
+static int menuXStatus7(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(7); return 0;
+}
+
+static int menuXStatus8(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(8); return 0;
+}
+
+static int menuXStatus9(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(9); return 0;
+}
+
+static int menuXStatus10(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(10); return 0;
+}
+
+static int menuXStatus11(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(11); return 0;
+}
+
+static int menuXStatus12(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(12); return 0;
+}
+
+static int menuXStatus13(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(13); return 0;
+}
+
+static int menuXStatus14(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(14); return 0;
+}
+
+static int menuXStatus15(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(15); return 0;
+}
+
+static int menuXStatus16(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(16); return 0;
+}
+
+static int menuXStatus17(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(17); return 0;
+}
+
+static int menuXStatus18(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(18); return 0;
+}
+
+static int menuXStatus19(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(19); return 0;
+}
+
+static int menuXStatus20(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(20); return 0;
+}
+
+static int menuXStatus21(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(21); return 0;
+}
+
+static int menuXStatus22(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(22); return 0;
+}
+
+static int menuXStatus23(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(23); return 0;
+}
+
+static int menuXStatus24(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(24); return 0;
+}
+
+static int menuXStatus25(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(25); return 0;
+}
+
+static int menuXStatus26(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(26); return 0;
+}
+
+static int menuXStatus27(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(27); return 0;
+}
+
+static int menuXStatus28(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(28); return 0;
+}
+
+static int menuXStatus29(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(29); return 0;
+}
+
+static int menuXStatus30(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(30); return 0;
+}
+static int menuXStatus31(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(31); return 0;
+}
+static int menuXStatus32(WPARAM wParam,LPARAM lParam)
+{
+ setXStatus(32); return 0;
+}
+
+void InitXStatusItems(BOOL bAllowStatus)
+{
+ CLISTMENUITEM mi;
+ int i = 0;
+ char srvFce[MAX_PATH + 64];
+ char szItem[MAX_PATH + 64];
+ HANDLE hXStatusRoot;
+
+ BYTE bXStatus = IRCGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+
+ if (!IRCGetContactSettingByte(NULL, "XStatusEnabled", 0)) return;
+
+ if (bStatusMenu && !bAllowStatus) return;
+
+ null_snprintf(szItem, sizeof(szItem), Translate("%s Custom Status"), ALTIRCPROTONAME);
+ mi.cbSize = sizeof(mi);
+ mi.pszPopupName = szItem;
+ mi.popupPosition= 500084000;
+ mi.position = 2000040000;
+
+ for(i = 0; i <= 32; i++)
+ {
+ char szTemp[64];
+ HICON hIIcon = (i > 0) ? LoadDefaultXStatusIcon(i) : NULL;
+
+ null_snprintf(srvFce, sizeof(srvFce), "%s/menuXStatus%d", ALTIRCPROTONAME, i);
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", i-1);
+ mi.hIcon = IconLibProcess(hIIcon, szTemp);
+ mi.position++;
+
+ if (!bXStatusMenuBuilt)
+ {
+ switch(i)
+ {
+ case 0: CreateServiceFunction(srvFce, menuXStatus0); break;
+ case 1: CreateServiceFunction(srvFce, menuXStatus1); break;
+ case 2: CreateServiceFunction(srvFce, menuXStatus2); break;
+ case 3: CreateServiceFunction(srvFce, menuXStatus3); break;
+ case 4: CreateServiceFunction(srvFce, menuXStatus4); break;
+ case 5: CreateServiceFunction(srvFce, menuXStatus5); break;
+ case 6: CreateServiceFunction(srvFce, menuXStatus6); break;
+ case 7: CreateServiceFunction(srvFce, menuXStatus7); break;
+ case 8: CreateServiceFunction(srvFce, menuXStatus8); break;
+ case 9: CreateServiceFunction(srvFce, menuXStatus9); break;
+ case 10: CreateServiceFunction(srvFce, menuXStatus10); break;
+ case 11: CreateServiceFunction(srvFce, menuXStatus11); break;
+ case 12: CreateServiceFunction(srvFce, menuXStatus12); break;
+ case 13: CreateServiceFunction(srvFce, menuXStatus13); break;
+ case 14: CreateServiceFunction(srvFce, menuXStatus14); break;
+ case 15: CreateServiceFunction(srvFce, menuXStatus15); break;
+ case 16: CreateServiceFunction(srvFce, menuXStatus16); break;
+ case 17: CreateServiceFunction(srvFce, menuXStatus17); break;
+ case 18: CreateServiceFunction(srvFce, menuXStatus18); break;
+ case 19: CreateServiceFunction(srvFce, menuXStatus19); break;
+ case 20: CreateServiceFunction(srvFce, menuXStatus20); break;
+ case 21: CreateServiceFunction(srvFce, menuXStatus21); break;
+ case 22: CreateServiceFunction(srvFce, menuXStatus22); break;
+ case 23: CreateServiceFunction(srvFce, menuXStatus23); break;
+ case 24: CreateServiceFunction(srvFce, menuXStatus24); break;
+ case 25: CreateServiceFunction(srvFce, menuXStatus25); break;
+ case 26: CreateServiceFunction(srvFce, menuXStatus26); break;
+ case 27: CreateServiceFunction(srvFce, menuXStatus27); break;
+ case 28: CreateServiceFunction(srvFce, menuXStatus28); break;
+ case 29: CreateServiceFunction(srvFce, menuXStatus29); break;
+ case 30: CreateServiceFunction(srvFce, menuXStatus30); break;
+ case 31: CreateServiceFunction(srvFce, menuXStatus31); break;
+ case 32: CreateServiceFunction(srvFce, menuXStatus32); break;
+ }
+ }
+
+ mi.flags = bXStatus == i?CMIF_CHECKED:0;
+ mi.pszName = IRCTranslate(i?nameXStatus[i-1]:"None");
+ mi.pszService = srvFce;
+ mi.pszContactOwner = ALTIRCPROTONAME;
+
+ if (bStatusMenu)
+ hXStatusItems[i] = (HANDLE)CallService(MS_CLIST_ADDSTATUSMENUITEM, (WPARAM)&hXStatusRoot, (LPARAM)&mi);
+ else
+ hXStatusItems[i] = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi);
+ if (i) DestroyIcon(hIIcon);
+ }
+
+ bXStatusMenuBuilt = 1;
+}
+
+void InitXStatusIcons()
+{
+ char szSection[MAX_PATH + 64];
+ char str[MAX_PATH], prt[MAX_PATH];
+ int i;
+
+ if (!prefs->XStatusEnabled) return;
+
+ InitXStatusIconLibrary();
+
+ null_snprintf(szSection, sizeof(szSection), IRCTranslateUtfStatic("%s/Custom Status", str), IRCTranslateUtfStatic(IRCPROTONAME, prt));
+
+ for (i = 0; i < 32; i++)
+ {
+ HICON hXIcon = LoadDefaultXStatusIcon(i + 1);
+ char szTemp[64];
+
+ null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", i);
+ IconLibDefine(IRCTranslateUtfStatic(nameXStatus[i], str), szSection, szTemp, hXIcon);
+ DestroyIcon(hXIcon);
+ }
+
+ if (bXStatusMenuBuilt)
+ ChangedIconsXStatus();
+}
+
+void ChangedIconsXStatus()
+{ // reload icons
+ CLISTMENUITEM mi;
+ int i;
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+
+ mi.flags = CMIM_FLAGS | CMIM_ICON;
+
+ for (i = 1; i < 33; i++)
+ {
+ mi.hIcon = GetXStatusIcon(i);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[i], (LPARAM)&mi);
+ if (!IconLibInstalled())
+ DestroyIcon(mi.hIcon); // if not IconLib resource release
+ }
+}
+
+int IRCShowXStatusDetails(WPARAM wParam, LPARAM lParam)
+{
+ InitXStatusData init;
+
+ init.bAction = 1; // retrieve
+ init.hContact = (HANDLE)wParam;
+ DialogBoxUtf(FALSE, g_hInstance, MAKEINTRESOURCEA(IDD_SETXSTATUS), NULL, SetXStatusDlgProc, (LPARAM)&init);
+
+ return 0;
+}
+
+int IRCSetXStatus(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam >= 0 && wParam <= 32)
+ {
+ setXStatusEx((BYTE)wParam, 1);
+ return wParam;
+ }
+ return 0;
+}
+
+int IRCGetXStatusIcon(WPARAM wParam, LPARAM lParam)
+{
+ if (!wParam)
+ wParam = IRCGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+
+ if (wParam >= 1 && wParam <= 32)
+ {
+ HICON icon = GetXStatusIcon((BYTE)wParam);
+
+ if (IconLibInstalled())
+ icon = CopyIcon(icon);
+
+ return (int)icon;
+ }
+ return 0;
+}
+
+int IRCGetXStatus(WPARAM wParam, LPARAM lParam)
+{
+ BYTE status = IRCGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
+
+ if (GlobalStatus == ID_STATUS_OFFLINE)
+ return 0;
+
+ if (status < 1 || status > 32) status = 0;
+
+ if (wParam) *((char**)wParam) = DBSETTING_XSTATUSNAME;
+ if (lParam) *((char**)lParam) = DBSETTING_XSTATUSMSG;
+
+ return status;
+}
+
+int IRCRequestXStatusDetails(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+
+ if (hContact && !IRCGetContactSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO) && IRCGetContactSettingByte(hContact, DBSETTING_XSTATUSID, 0))
+ { // user has xstatus, no auto-retrieve details, valid contact, request details
+ return requestXStatusDetails(hContact, TRUE);
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/irc_mod/xstatus.h b/irc_mod/xstatus.h
new file mode 100644
index 0000000..53c0ed3
--- /dev/null
+++ b/irc_mod/xstatus.h
@@ -0,0 +1,65 @@
+// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_xtraz.h,v $
+// Revision : $Revision: 1.6 $
+// Last change on : $Date: 2006/01/25 20:20:41 $
+// Last change by : $Author: jokusoftware $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#ifndef __ICQ_XTRAZ_H
+#define __ICQ_XTRAZ_H
+
+void handleXtrazNotify(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC);
+void handleXtrazNotifyResponse(DWORD dwUin, HANDLE hContact, WORD wCookie, char* szMsg, int nMsgLen);
+
+DWORD SendXtrazNotifyRequest(HANDLE hContact, char* szQuery, char* szNotify);
+void SendXtrazNotifyResponse(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szResponse, int nResponseLen, BOOL bThruDC);
+
+// custom status support
+void InitXStatusItems(BOOL bAllowStatus);
+void InitXStatusEvents();
+void UninitXStatusEvents();
+
+void InitXStatusIcons();
+void ChangedIconsXStatus();
+HICON GetXStatusIcon(int bStatus);
+
+void setContactExtraIcon(HANDLE hContact, HANDLE hIcon);
+
+int IRCShowXStatusDetails(WPARAM wParam, LPARAM lParam);
+
+// custom status public services
+int IRCSetXStatus(WPARAM wParam, LPARAM lParam);
+int IRCGetXStatusIcon(WPARAM wParam, LPARAM lParam);
+int IRCGetXStatus(WPARAM wParam, LPARAM lParam);
+int IRCRequestXStatusDetails(WPARAM wParam, LPARAM lParam);
+
+#endif /* __ICQ_XTRAZ_H */