diff options
author | watcherhd <watcherhd@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb> | 2011-04-21 14:14:52 +0000 |
---|---|---|
committer | watcherhd <watcherhd@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb> | 2011-04-21 14:14:52 +0000 |
commit | cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c (patch) | |
tree | 30df260fdc5a1b5a7049c2f8cac8b7ef17513d6d /irc_mod | |
parent | 19b6f534d2e784a1e120bf52c4aa07004798f473 (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')
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 Binary files differnew file mode 100644 index 0000000..3fd5ef3 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Add.ico diff --git a/irc_mod/Icons/Angeli-Ka/Apply.ico b/irc_mod/Icons/Angeli-Ka/Apply.ico Binary files differnew file mode 100644 index 0000000..7e18dc4 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Apply.ico diff --git a/irc_mod/Icons/Angeli-Ka/Avatar.ico b/irc_mod/Icons/Angeli-Ka/Avatar.ico Binary files differnew file mode 100644 index 0000000..25d4ad7 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Avatar.ico diff --git a/irc_mod/Icons/Angeli-Ka/Cancel.ico b/irc_mod/Icons/Angeli-Ka/Cancel.ico Binary files differnew file mode 100644 index 0000000..710929d --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Cancel.ico diff --git a/irc_mod/Icons/Angeli-Ka/Dcc.ico b/irc_mod/Icons/Angeli-Ka/Dcc.ico Binary files differnew file mode 100644 index 0000000..e1421cb --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Dcc.ico diff --git a/irc_mod/Icons/Angeli-Ka/Delete.ico b/irc_mod/Icons/Angeli-Ka/Delete.ico Binary files differnew file mode 100644 index 0000000..9ba2221 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Delete.ico diff --git a/irc_mod/Icons/Angeli-Ka/Edit.ico b/irc_mod/Icons/Angeli-Ka/Edit.ico Binary files differnew file mode 100644 index 0000000..b85f53b --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Edit.ico diff --git a/irc_mod/Icons/Angeli-Ka/Ignore.ico b/irc_mod/Icons/Angeli-Ka/Ignore.ico Binary files differnew file mode 100644 index 0000000..91f176f --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Ignore.ico diff --git a/irc_mod/Icons/Angeli-Ka/Join.ico b/irc_mod/Icons/Angeli-Ka/Join.ico Binary files differnew file mode 100644 index 0000000..d533b2b --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Join.ico diff --git a/irc_mod/Icons/Angeli-Ka/Leave.ico b/irc_mod/Icons/Angeli-Ka/Leave.ico Binary files differnew file mode 100644 index 0000000..2a91b8a --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Leave.ico diff --git a/irc_mod/Icons/Angeli-Ka/List.ico b/irc_mod/Icons/Angeli-Ka/List.ico Binary files differnew file mode 100644 index 0000000..798c2c2 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/List.ico diff --git a/irc_mod/Icons/Angeli-Ka/Logo.bak b/irc_mod/Icons/Angeli-Ka/Logo.bak Binary files differnew file mode 100644 index 0000000..0bf8536 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Logo.bak diff --git a/irc_mod/Icons/Angeli-Ka/Logo.ico b/irc_mod/Icons/Angeli-Ka/Logo.ico Binary files differnew file mode 100644 index 0000000..919eccf --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Logo.ico diff --git a/irc_mod/Icons/Angeli-Ka/Main.ico b/irc_mod/Icons/Angeli-Ka/Main.ico Binary files differnew file mode 100644 index 0000000..fccffbc --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Main.ico diff --git a/irc_mod/Icons/Angeli-Ka/Manager.ico b/irc_mod/Icons/Angeli-Ka/Manager.ico Binary files differnew file mode 100644 index 0000000..5b065ff --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Manager.ico diff --git a/irc_mod/Icons/Angeli-Ka/Protopic.ico b/irc_mod/Icons/Angeli-Ka/Protopic.ico Binary files differnew file mode 100644 index 0000000..bdb8500 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Protopic.ico diff --git a/irc_mod/Icons/Angeli-Ka/Quest2.ico b/irc_mod/Icons/Angeli-Ka/Quest2.ico Binary files differnew file mode 100644 index 0000000..a6f23bc --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Quest2.ico diff --git a/irc_mod/Icons/Angeli-Ka/Question.ico b/irc_mod/Icons/Angeli-Ka/Question.ico Binary files differnew file mode 100644 index 0000000..2f11d7b --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Question.ico diff --git a/irc_mod/Icons/Angeli-Ka/Quick connect.ico b/irc_mod/Icons/Angeli-Ka/Quick connect.ico Binary files differnew file mode 100644 index 0000000..be271cb --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Quick connect.ico diff --git a/irc_mod/Icons/Angeli-Ka/Reading.ico b/irc_mod/Icons/Angeli-Ka/Reading.ico Binary files differnew file mode 100644 index 0000000..4f5ce84 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Reading.ico diff --git a/irc_mod/Icons/Angeli-Ka/Server.ico b/irc_mod/Icons/Angeli-Ka/Server.ico Binary files differnew file mode 100644 index 0000000..ae10690 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Server.ico diff --git a/irc_mod/Icons/Angeli-Ka/Show chanel.ico b/irc_mod/Icons/Angeli-Ka/Show chanel.ico Binary files differnew file mode 100644 index 0000000..ebfc573 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Show chanel.ico diff --git a/irc_mod/Icons/Angeli-Ka/Warning.ico b/irc_mod/Icons/Angeli-Ka/Warning.ico Binary files differnew file mode 100644 index 0000000..4bae248 --- /dev/null +++ b/irc_mod/Icons/Angeli-Ka/Warning.ico diff --git a/irc_mod/Icons/add.ico b/irc_mod/Icons/add.ico Binary files differnew file mode 100644 index 0000000..b61d733 --- /dev/null +++ b/irc_mod/Icons/add.ico diff --git a/irc_mod/Icons/avatar.ico b/irc_mod/Icons/avatar.ico Binary files differnew file mode 100644 index 0000000..eaf8c25 --- /dev/null +++ b/irc_mod/Icons/avatar.ico diff --git a/irc_mod/Icons/avatar_old.ico b/irc_mod/Icons/avatar_old.ico Binary files differnew file mode 100644 index 0000000..cc7fe7b --- /dev/null +++ b/irc_mod/Icons/avatar_old.ico diff --git a/irc_mod/Icons/block.ico b/irc_mod/Icons/block.ico Binary files differnew file mode 100644 index 0000000..bdc022e --- /dev/null +++ b/irc_mod/Icons/block.ico diff --git a/irc_mod/Icons/dcc.ico b/irc_mod/Icons/dcc.ico Binary files differnew file mode 100644 index 0000000..4668d95 --- /dev/null +++ b/irc_mod/Icons/dcc.ico diff --git a/irc_mod/Icons/delete.ico b/irc_mod/Icons/delete.ico Binary files differnew file mode 100644 index 0000000..a2134ca --- /dev/null +++ b/irc_mod/Icons/delete.ico diff --git a/irc_mod/Icons/error.ico b/irc_mod/Icons/error.ico Binary files differnew file mode 100644 index 0000000..8c2d8e8 --- /dev/null +++ b/irc_mod/Icons/error.ico diff --git a/irc_mod/Icons/fatal.ico b/irc_mod/Icons/fatal.ico Binary files differnew file mode 100644 index 0000000..5f6b307 --- /dev/null +++ b/irc_mod/Icons/fatal.ico diff --git a/irc_mod/Icons/go.ico b/irc_mod/Icons/go.ico Binary files differnew file mode 100644 index 0000000..8a58d47 --- /dev/null +++ b/irc_mod/Icons/go.ico diff --git a/irc_mod/Icons/help.ico b/irc_mod/Icons/help.ico Binary files differnew file mode 100644 index 0000000..bbed7c9 --- /dev/null +++ b/irc_mod/Icons/help.ico diff --git a/irc_mod/Icons/information.ico b/irc_mod/Icons/information.ico Binary files differnew file mode 100644 index 0000000..d6a8c50 --- /dev/null +++ b/irc_mod/Icons/information.ico diff --git a/irc_mod/Icons/irc.ico b/irc_mod/Icons/irc.ico Binary files differnew file mode 100644 index 0000000..acbbcba --- /dev/null +++ b/irc_mod/Icons/irc.ico diff --git a/irc_mod/Icons/list.ico b/irc_mod/Icons/list.ico Binary files differnew file mode 100644 index 0000000..046e7dc --- /dev/null +++ b/irc_mod/Icons/list.ico diff --git a/irc_mod/Icons/manager.ico b/irc_mod/Icons/manager.ico Binary files differnew file mode 100644 index 0000000..e4f6233 --- /dev/null +++ b/irc_mod/Icons/manager.ico diff --git a/irc_mod/Icons/part.ico b/irc_mod/Icons/part.ico Binary files differnew file mode 100644 index 0000000..4cd783a --- /dev/null +++ b/irc_mod/Icons/part.ico diff --git a/irc_mod/Icons/quick.ico b/irc_mod/Icons/quick.ico Binary files differnew file mode 100644 index 0000000..046544c --- /dev/null +++ b/irc_mod/Icons/quick.ico diff --git a/irc_mod/Icons/rename.ico b/irc_mod/Icons/rename.ico Binary files differnew file mode 100644 index 0000000..5bffc74 --- /dev/null +++ b/irc_mod/Icons/rename.ico diff --git a/irc_mod/Icons/server.ico b/irc_mod/Icons/server.ico Binary files differnew file mode 100644 index 0000000..e9db131 --- /dev/null +++ b/irc_mod/Icons/server.ico diff --git a/irc_mod/Icons/show.ico b/irc_mod/Icons/show.ico Binary files differnew file mode 100644 index 0000000..e883fcb --- /dev/null +++ b/irc_mod/Icons/show.ico diff --git a/irc_mod/Icons/warning.ico b/irc_mod/Icons/warning.ico Binary files differnew file mode 100644 index 0000000..9080ac7 --- /dev/null +++ b/irc_mod/Icons/warning.ico diff --git a/irc_mod/Icons/world.ico b/irc_mod/Icons/world.ico Binary files differnew file mode 100644 index 0000000..1ae508a --- /dev/null +++ b/irc_mod/Icons/world.ico diff --git a/irc_mod/Icons/world_old.ico b/irc_mod/Icons/world_old.ico Binary files differnew file mode 100644 index 0000000..2a86c3f --- /dev/null +++ b/irc_mod/Icons/world_old.ico diff --git a/irc_mod/Icons/xstatus01.ico b/irc_mod/Icons/xstatus01.ico Binary files differnew file mode 100644 index 0000000..b29cfd3 --- /dev/null +++ b/irc_mod/Icons/xstatus01.ico diff --git a/irc_mod/Icons/xstatus02.ico b/irc_mod/Icons/xstatus02.ico Binary files differnew file mode 100644 index 0000000..b43efbd --- /dev/null +++ b/irc_mod/Icons/xstatus02.ico diff --git a/irc_mod/Icons/xstatus03.ico b/irc_mod/Icons/xstatus03.ico Binary files differnew file mode 100644 index 0000000..819b070 --- /dev/null +++ b/irc_mod/Icons/xstatus03.ico diff --git a/irc_mod/Icons/xstatus04.ico b/irc_mod/Icons/xstatus04.ico Binary files differnew file mode 100644 index 0000000..946de46 --- /dev/null +++ b/irc_mod/Icons/xstatus04.ico diff --git a/irc_mod/Icons/xstatus05.ico b/irc_mod/Icons/xstatus05.ico Binary files differnew file mode 100644 index 0000000..762e104 --- /dev/null +++ b/irc_mod/Icons/xstatus05.ico diff --git a/irc_mod/Icons/xstatus06.ico b/irc_mod/Icons/xstatus06.ico Binary files differnew file mode 100644 index 0000000..d733952 --- /dev/null +++ b/irc_mod/Icons/xstatus06.ico diff --git a/irc_mod/Icons/xstatus07.ico b/irc_mod/Icons/xstatus07.ico Binary files differnew file mode 100644 index 0000000..801d231 --- /dev/null +++ b/irc_mod/Icons/xstatus07.ico diff --git a/irc_mod/Icons/xstatus08.ico b/irc_mod/Icons/xstatus08.ico Binary files differnew file mode 100644 index 0000000..68051e5 --- /dev/null +++ b/irc_mod/Icons/xstatus08.ico diff --git a/irc_mod/Icons/xstatus09.ico b/irc_mod/Icons/xstatus09.ico Binary files differnew file mode 100644 index 0000000..07cebb4 --- /dev/null +++ b/irc_mod/Icons/xstatus09.ico diff --git a/irc_mod/Icons/xstatus10.ico b/irc_mod/Icons/xstatus10.ico Binary files differnew file mode 100644 index 0000000..0c99c1c --- /dev/null +++ b/irc_mod/Icons/xstatus10.ico diff --git a/irc_mod/Icons/xstatus11.ico b/irc_mod/Icons/xstatus11.ico Binary files differnew file mode 100644 index 0000000..311c165 --- /dev/null +++ b/irc_mod/Icons/xstatus11.ico diff --git a/irc_mod/Icons/xstatus12.ico b/irc_mod/Icons/xstatus12.ico Binary files differnew file mode 100644 index 0000000..42adff4 --- /dev/null +++ b/irc_mod/Icons/xstatus12.ico diff --git a/irc_mod/Icons/xstatus13.ico b/irc_mod/Icons/xstatus13.ico Binary files differnew file mode 100644 index 0000000..05c5f67 --- /dev/null +++ b/irc_mod/Icons/xstatus13.ico diff --git a/irc_mod/Icons/xstatus14.ico b/irc_mod/Icons/xstatus14.ico Binary files differnew file mode 100644 index 0000000..4d98556 --- /dev/null +++ b/irc_mod/Icons/xstatus14.ico diff --git a/irc_mod/Icons/xstatus15.ico b/irc_mod/Icons/xstatus15.ico Binary files differnew file mode 100644 index 0000000..ef8040b --- /dev/null +++ b/irc_mod/Icons/xstatus15.ico diff --git a/irc_mod/Icons/xstatus16.ico b/irc_mod/Icons/xstatus16.ico Binary files differnew file mode 100644 index 0000000..dd0a602 --- /dev/null +++ b/irc_mod/Icons/xstatus16.ico diff --git a/irc_mod/Icons/xstatus17.ico b/irc_mod/Icons/xstatus17.ico Binary files differnew file mode 100644 index 0000000..2d7be75 --- /dev/null +++ b/irc_mod/Icons/xstatus17.ico diff --git a/irc_mod/Icons/xstatus18.ico b/irc_mod/Icons/xstatus18.ico Binary files differnew file mode 100644 index 0000000..b3d6dd1 --- /dev/null +++ b/irc_mod/Icons/xstatus18.ico diff --git a/irc_mod/Icons/xstatus19.ico b/irc_mod/Icons/xstatus19.ico Binary files differnew file mode 100644 index 0000000..db4d011 --- /dev/null +++ b/irc_mod/Icons/xstatus19.ico diff --git a/irc_mod/Icons/xstatus20.ico b/irc_mod/Icons/xstatus20.ico Binary files differnew file mode 100644 index 0000000..fd3ef57 --- /dev/null +++ b/irc_mod/Icons/xstatus20.ico diff --git a/irc_mod/Icons/xstatus21.ico b/irc_mod/Icons/xstatus21.ico Binary files differnew file mode 100644 index 0000000..2704aa7 --- /dev/null +++ b/irc_mod/Icons/xstatus21.ico diff --git a/irc_mod/Icons/xstatus22.ico b/irc_mod/Icons/xstatus22.ico Binary files differnew file mode 100644 index 0000000..96e7739 --- /dev/null +++ b/irc_mod/Icons/xstatus22.ico diff --git a/irc_mod/Icons/xstatus23.ico b/irc_mod/Icons/xstatus23.ico Binary files differnew file mode 100644 index 0000000..8a2ad77 --- /dev/null +++ b/irc_mod/Icons/xstatus23.ico diff --git a/irc_mod/Icons/xstatus24.ico b/irc_mod/Icons/xstatus24.ico Binary files differnew file mode 100644 index 0000000..8a01165 --- /dev/null +++ b/irc_mod/Icons/xstatus24.ico diff --git a/irc_mod/Icons/xstatus25.ico b/irc_mod/Icons/xstatus25.ico Binary files differnew file mode 100644 index 0000000..8e6d3f9 --- /dev/null +++ b/irc_mod/Icons/xstatus25.ico diff --git a/irc_mod/Icons/xstatus26.ico b/irc_mod/Icons/xstatus26.ico Binary files differnew file mode 100644 index 0000000..fe7114d --- /dev/null +++ b/irc_mod/Icons/xstatus26.ico diff --git a/irc_mod/Icons/xstatus27.ico b/irc_mod/Icons/xstatus27.ico Binary files differnew file mode 100644 index 0000000..6a84272 --- /dev/null +++ b/irc_mod/Icons/xstatus27.ico diff --git a/irc_mod/Icons/xstatus28.ico b/irc_mod/Icons/xstatus28.ico Binary files differnew file mode 100644 index 0000000..d78aadc --- /dev/null +++ b/irc_mod/Icons/xstatus28.ico diff --git a/irc_mod/Icons/xstatus29.ico b/irc_mod/Icons/xstatus29.ico Binary files differnew file mode 100644 index 0000000..4f2739c --- /dev/null +++ b/irc_mod/Icons/xstatus29.ico diff --git a/irc_mod/Icons/xstatus30.ico b/irc_mod/Icons/xstatus30.ico Binary files differnew file mode 100644 index 0000000..fe31759 --- /dev/null +++ b/irc_mod/Icons/xstatus30.ico diff --git a/irc_mod/Icons/xstatus31.ico b/irc_mod/Icons/xstatus31.ico Binary files differnew file mode 100644 index 0000000..4f5ce84 --- /dev/null +++ b/irc_mod/Icons/xstatus31.ico diff --git a/irc_mod/Icons/xstatus32.ico b/irc_mod/Icons/xstatus32.ico Binary files differnew file mode 100644 index 0000000..421856a --- /dev/null +++ b/irc_mod/Icons/xstatus32.ico 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.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 */
|