summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Docs/PCRE-License.txt84
-rw-r--r--Docs/SpamFilter-Developer.txt116
-rw-r--r--Docs/SpamFilter-License.txt556
-rw-r--r--Docs/SpamFilter-Readme.txt1952
-rw-r--r--Docs/SpamFilter-Translation.txt1728
-rw-r--r--SpamFilter.dsp1604
-rw-r--r--SpamFilter.dsw58
-rw-r--r--SpamFilter.rc1112
-rw-r--r--SpamFilter.sln52
-rw-r--r--SpamFilter.vcproj4486
-rw-r--r--Utilities/DebugHelper.h676
-rw-r--r--common.h566
-rw-r--r--contact.c1636
-rw-r--r--contact.h82
-rw-r--r--dlg.c768
-rw-r--r--dlg.h74
-rw-r--r--extraimg.c234
-rw-r--r--extraimg.h60
-rw-r--r--folders.c200
-rw-r--r--folders.h66
-rw-r--r--forkthread.c222
-rw-r--r--forkthread.h128
-rw-r--r--logfile.c954
-rw-r--r--logfile.h56
-rw-r--r--m_popup.h676
-rw-r--r--m_spamfilter.h1650
-rw-r--r--m_trigger.h696
-rw-r--r--main.c1190
-rw-r--r--menuitems.c270
-rw-r--r--menuitems.h58
-rw-r--r--options.c7396
-rw-r--r--options.h120
-rw-r--r--path.c1080
-rw-r--r--path.h102
-rw-r--r--popup.c568
-rw-r--r--popup.h78
-rw-r--r--regexp.c448
-rw-r--r--regexp.h68
-rw-r--r--resource.h278
-rw-r--r--services.c4074
-rw-r--r--services.h78
-rw-r--r--spamcheck.c1364
-rw-r--r--spamcheck.h66
-rw-r--r--spamcheckdata.c544
-rw-r--r--spamcheckdata.h70
-rw-r--r--spamdefinitions.c1698
-rw-r--r--spamdefinitions.h118
-rw-r--r--string.c618
-rw-r--r--string.h82
-rw-r--r--stringlist.c2012
-rw-r--r--stringlist.h160
-rw-r--r--trigger.c124
-rw-r--r--trigger.h64
-rw-r--r--utilities.c1256
-rw-r--r--utilities.h90
-rw-r--r--variables.c128
-rw-r--r--variables.h60
-rw-r--r--version.h70
58 files changed, 22412 insertions, 22412 deletions
diff --git a/Docs/PCRE-License.txt b/Docs/PCRE-License.txt
index f1cbefd..72def16 100644
--- a/Docs/PCRE-License.txt
+++ b/Docs/PCRE-License.txt
@@ -1,42 +1,42 @@
-PCRE LICENCE
-------------
-
-PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
-Release 5 of PCRE is distributed under the terms of the "BSD" licence, as
-specified below.
-
-Written by: Philip Hazel <ph10@cam.ac.uk>
-
-University of Cambridge Computing Service,
-Cambridge, England. Phone: +44 1223 334714.
-
-Copyright (c) 1997-2004 University of Cambridge
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+PCRE LICENCE
+------------
+
+PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+Release 5 of PCRE is distributed under the terms of the "BSD" licence, as
+specified below.
+
+Written by: Philip Hazel <ph10@cam.ac.uk>
+
+University of Cambridge Computing Service,
+Cambridge, England. Phone: +44 1223 334714.
+
+Copyright (c) 1997-2004 University of Cambridge
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/Docs/SpamFilter-Developer.txt b/Docs/SpamFilter-Developer.txt
index a7a2b66..8e7e4b2 100644
--- a/Docs/SpamFilter-Developer.txt
+++ b/Docs/SpamFilter-Developer.txt
@@ -1,59 +1,59 @@
-
-Spam Filter 2.5.2.3 for Miranda IM 0.4.3+
-------------------------------------------------------------------------
- Developer Information
-
- Contents: -------------------------------
- | Translation, Services and Events (API),
- | Debug Symbols, Coding Language, Rebase Info
-
-
-Translation
------------------
- Translation strings and available bad words can be found in
- "SpamFilter-Translation.txt".
-
-
-Services and Events (API)
------------------
- For more information about which service functions are provided by
- "Spam Filter" and about how they can be used by your plugin please
- refer to "m_spamfilter.h".
- If you would like to use Delphi/Pascal please refer to m_spamfilter.inc.
-
- For example code on how to do a spam check in your plugin see "spamcheck.c" file
- of the source code package.
- If you need help with it, just send me an e-mail.
-
- The functionality and the API of Spam Filter is quite complex
- and not easy to describe or explain.
- If you have any questions or extension whishes please send me an e-mail:
- hrathh at users.sourceforge.net
-
-
-Debug Symbols
------------------
- Debug symbols are also available for debugging purposes.
- Copy the PDB-files into the same directory as the
- corresponding DLL-files.
-
-
-Coding Language
------------------
- "Spam Filter" is written with Microsoft Visual C++ 6.0 SP6.
- Used Microsoft Platform SDK: 5.2.3790.1830.15 (Svr2003 SP1).
-
-
-Rebase Info
------------------
- 'Spam Filter' has set its base address to:
- 0x24000000
-
- Please avoid using this base address for your plugins because it will
- slow down the start of Miranda IM.
-
- With Microsoft Visual C++ the Base Address can be configured at:
- "Project" -> "Settings" -> "Linker" -> "Output" -> "Base Address"
-
-
+
+Spam Filter 2.5.2.3 for Miranda IM 0.4.3+
+------------------------------------------------------------------------
+ Developer Information
+
+ Contents: -------------------------------
+ | Translation, Services and Events (API),
+ | Debug Symbols, Coding Language, Rebase Info
+
+
+Translation
+-----------------
+ Translation strings and available bad words can be found in
+ "SpamFilter-Translation.txt".
+
+
+Services and Events (API)
+-----------------
+ For more information about which service functions are provided by
+ "Spam Filter" and about how they can be used by your plugin please
+ refer to "m_spamfilter.h".
+ If you would like to use Delphi/Pascal please refer to m_spamfilter.inc.
+
+ For example code on how to do a spam check in your plugin see "spamcheck.c" file
+ of the source code package.
+ If you need help with it, just send me an e-mail.
+
+ The functionality and the API of Spam Filter is quite complex
+ and not easy to describe or explain.
+ If you have any questions or extension whishes please send me an e-mail:
+ hrathh at users.sourceforge.net
+
+
+Debug Symbols
+-----------------
+ Debug symbols are also available for debugging purposes.
+ Copy the PDB-files into the same directory as the
+ corresponding DLL-files.
+
+
+Coding Language
+-----------------
+ "Spam Filter" is written with Microsoft Visual C++ 6.0 SP6.
+ Used Microsoft Platform SDK: 5.2.3790.1830.15 (Svr2003 SP1).
+
+
+Rebase Info
+-----------------
+ 'Spam Filter' has set its base address to:
+ 0x24000000
+
+ Please avoid using this base address for your plugins because it will
+ slow down the start of Miranda IM.
+
+ With Microsoft Visual C++ the Base Address can be configured at:
+ "Project" -> "Settings" -> "Linker" -> "Output" -> "Base Address"
+
+
H. Herkenrath (hrathh at users.sourceforge.net) \ No newline at end of file
diff --git a/Docs/SpamFilter-License.txt b/Docs/SpamFilter-License.txt
index a726a52..ae71b67 100644
--- a/Docs/SpamFilter-License.txt
+++ b/Docs/SpamFilter-License.txt
@@ -1,278 +1,278 @@
- 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.
+ 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.
diff --git a/Docs/SpamFilter-Readme.txt b/Docs/SpamFilter-Readme.txt
index 6316589..5c185b9 100644
--- a/Docs/SpamFilter-Readme.txt
+++ b/Docs/SpamFilter-Readme.txt
@@ -1,977 +1,977 @@
-
-Spam Filter 2.5.2.3
-------------------------------------------------------------------------
- Plugin for Miranda IM 0.4.3 and +
-
- Plugin Info: ----------------------------
- | Version: 2.5.2.3
- | Filename: spamfilter.dll / spamfilterW.dll
- | Author: H. Herkenrath (hrathh at users.sourceforge.net)
- | Description: Filters out advertisments, robot messages and disliked messages
- | such as hoax messages.Filters out spam messages from contacts
-
- Contents: -------------------------------
- | Filter Improvement, Features, Requirements, Usage,
- | Spam Definitions, Installation, Bugs and Wishes, Filtering Tips,
- | To-Do List, Version History, Thanks, Translation, License and Copyright
-
-
-Filter Improvement
-----------------------
- -> Still receiving spam?
- If you receive spam messages after installing this plugin
- which are not filtered out just mail the text of the spam message
- to me and I will integrate some bad phrases out of it immediately.
- If the filtering of that message can't be done via bad phrases I
- will try to find another way and integrate that way, too.
-
- -> New filtering ideas?
- If you have some other spam filtering ideas please mail me.
-
- -> Bugs?
- If you find any bugs please tell them to me via mail.
- So I don't have to look everywhere around to find them. ;-)
-
- -> Patches or Extensions?
- If you are a developer and/or know how to code
- feel free to send me patches or extensions to the code.
- The best way is via e-mail.
- I really appreciate it. :-)
- If you need extensions to the API please contact me, too.
-
- -> Filtering in all languages?!
- There are already bad phrases for the following languages:
- English, German, French, Russian, Portuguese (Brazil), Chinese (Traditional)
- I would love it if this list could be extended further.
- It is a little difficult to speak and understand all languages of this
- world at the same time ;-) ...and if you speak a language that I don't...
- (and I think that are very much ;-)...) please send some bad phrases in
- your language to me.
- It would be nice if spam could be filtered in all languages,
- but I need some help... please... :-)
- Also feel encouraged to release your own Spam Definitions on the File Listing.
-
- -> Reporting spam log file?!
- You can also help me via sending your spam log file to me.
- So I can look for new/better bad phrases.
- Such a log file can be created with the spam logging feature.
- It doesn't include any data beside the spam messages sent to you.
- I will look at it and intergrate some more bad phrases out of it to
- improve the filter quality.
-
- -> New bad phrases?
- If you have some bad phrases to add to the existing lists
- please mail them to me, too.
- I will check the bad phrases and integrate them immediately.
-
-
-Features
-----------------------
- + Filters out incoming spam messages
- + Spam filtering with all protocols
- + Which messages are declared as spam is changeable
- + Improved spam filter (pretty accurate)
- + Recognizes also URLs with spaces
- + Supports Regular Expressions (RegExp) in its word filter (really powerful!)
- + Spam handling: either mark read or delete messages
- + Spaming contacts get automatically removed if there are no items in history
- + Spammer name/id auto ignoring
- + Easy adding of customized bad phrases
- + Spam alert via Sound or Popup (Popup plugin is needed for this feature)
- + Spam message logging to file
- Supported file formats: TXT, LOG, CSV, XML (including XSL stylesheet)
- + Supports "ballon tips" for error display
- + Press control key to avoid messages to be checked for spam
- + Fully configurable with many options
- + Filter can be disabled temporarily on the options page
- + Large list of default bad phrases (about 80 well chosen english phrases at the moment)
- + Full translation support (default bad phrases, too)
- + Available dialog languages: English, German
- + Available Spam Definition languages:
- English, German, French, Russian, Portuguese (Brazil), Chinese (Traditional)
- + Provides spam checking service functions for other plugins
- + Auto-Updates for Spam Definitions using Updater plugin
- + Full Unicode support
- + Automatic installation of all files, just unzip into Plugins directory
- + Supported plugins/tools:
- Miranda Installer, Popup/PopupPlus/YAPP, DatabaseEditor++, Updater,
- Variables Plugin (http://www.cs.vu.nl/~pboon/projects.htm),
- Trigger Plugin (http://www.cs.vu.nl/~pboon/projects.htm),
- Icons Library Manager (IcoLib), Colour Picker, OSD Plugin/WannaBe OSD,
- Custom Profile Folder Plugin, MultiWindow Contact List (extra icon)
-
-
-Requirements
-----------------------
- -> Miranda IM 0.4.3+:
- Miranda IM is needed in the version 0.4.3 or greater.
-
- -> Popup Plugin 1.0.1.9+ (optional):
- For using the popup function when a spam message
- arrives it is necessary to have the popup plugin installed,
- At least version 1.0.1.9 or greater.
- PopupPlus is supported, too.
- You need PopupPlus 2.0.3.97 or later.
-
- -> Variables Plugin 0.2.0.23+ (optional):
- For using variables in outgoing reply messages
- you need to have the Variables Plugin installed,
- At least version 0.2.0.23 or greater.
-
-
-Usage
-----------------------
- "Spam Filter" options can be found here:
- "Options" -> "Events" -> "Spam Filter"
-
- The sound file which is played when spam arrives can be changed in:
- "Options" -> "Events" -> "Sounds"
-
- Mark-Read feature:
- If you chose "mark spam messages as read" in the options recommended option)
- the spammer shows up in a half-visible way on your contact list.
- However, the incoming message notification is blocked.
- When you close Miranda IM all half-visible (not-on-list) contacts get removed automatically!
-
- To avoid the online notification go to the Ignore options and activate "suppress online notification" for unknown contacts.
-
- If you dislike this behaviour choose "delete spam" (but be aware that you might loose messages).
-
- Un-Ignoring spammers:
- Recognized spammers can be easily unignored usinf the options.
- Just go to "Options" -> "Events" -> "Spam Filter" and click on the "Spammers" button.
-
- If a unknown user sent you a message and you want to be sure he is no longer watched by the filter, just click
- on "Add user to contact list" in the contact's menu. (This only works if you chose "mark spam as read".)
-
-
-Spam Definitions
-----------------------
- "Spam Definitions" are a set of files which Spam Filter uses to detect spam.
- The files contain well selected words/phrases etc. which a common in spam messages.
- The Spam Definitions are mostly used by the "Advertisment Filter".
-
- The Spam Definitions make up the default filter behaviour of Spam Filter.
- You normally should not need to modify these files. Instead you should use
- "Options" -> "Events" -> "Spam Filter" to configure your personal filter words.
-
- You can install as many Spam Definitions as you like, but you should at least
- install one package in your language.
- The filter will not work as it should without any Spam Definitions.
- For each languge package you install the plugin can filter spam messages.
- For example, if you install the "German" and the "English" packages,
- most German and English spam can be filtered.
- Spam Filter can only filter for those languages it has data sets available.
-
- Spam Filter loads all Spam Definition Files it can find in the directories.
- All contents of all files are considered when a message is checked for spam.
- Spam Filter does not know which language the message is, it simply compares its contents.
-
- The exactness and accuracy of Spam Filter depends on its Spam Definitions.
- If the Spam Definitions are not good, the filter is not exact.
-
- The current Spam Definitions can be viewed in
- the "Spam Filter" subdirectory of the Miranda IM folder.
-
- How it works:
- There are different Spam Definition languages available because Spam Filter needs different data sets
- (e.g. bad words) for the different languages. This is necessary, because bad word filtering consits
- only of testing if a word exists in the message or not.
- When there are enough bad words in the message it will be seen as spam.
- If Spam Filter would only have a list of English bad words (like "earn money",...)
- it would only be able to filter English spam, since the words "earn money", etc do only exist in English messages.
- To filter German spam another data set is needed for the filter with e.g. "Sonderangebot",
- which again probably never will exist in English spam messages.
- The more Spam Definition languages you have installed, the more spam you can filter.
-
- Spam Filter does not detect the language of a message. It simply loads all bad words it can find
- in the directoriy and checks if any of the contained bad words do match with the message.
- If they match it is spam, if they do not, it is no spam.
-
- The file names are not important for the filter (only extension and subdirectory is considered).
- They are named "English", "German", etc so that it is easier to determine what they contain.
-
- Spam Filter checks if any contained word of the Spam Definitions matches with the message.
- It counts how many matches it can find and then checks if the matches are enough to consider the message as spam.
-
- If you get a spam message in a language for which you don't have Spam Definitions installed, it won't be a problem.
- It won't break anything, nor will your PC be blown up, or sth. like this... ;-)
- Spam Filter simple won't be able to filter this message. The message will be detected as no spam,
- because there are no data sets available.
-
- Example:
- If you receive, for example, French spam and you don't have the French Spam Definitions installed.
- Spam Filter will then load all bad words it can find in the Definitions to detect if it is spam.
- But, no matches will be found, because French spam does normally not contain English or German words.
- French spam typically contains French words... ;-)
-
- Spam for which you don't have any Spam Definitions installed can
- only be blocked by the Robot Filter (if enabled additionally)
- or if (by chance) the message contains some English bad words, or some common URLs (like .org, .com), etc.
-
-
-Installation
-----------------------
- The easiest way to install this plugin is to use the
- installation tool "Miranda Installer" (sadly not available anymore).
-
- If you don't want to use that tool you can install this plugin
- manually, too.
- Just copy all the contents of the zip-file as they are into the "Plugins" directory
- in the Miranda IM folder.
- "Spam Filter" will detect the files and move them into the appropriate directories
- on it's first run.
-
- You can also do all the installation by hand, if you want to:
-
- Main Plugin: Copy the file "spamfilter.dll" into the "Plugins" directory
- in the Miranda IM folder.
- If you would like to use Unicode you need to copy the file "spamfilterW.dll"
- instead. Using Unicode will only work for Windows NT4/2000+.
-
- Support for Regular Expressions:
- If you would like to use Regular Expressions with Spam Filter (recommended)
- then you should copy the file "pcre.dll" (RegExp DLL) into the Miranda IM directory.
-
- Spam Definitions: The contents of the "Spam Filter" folder from the zip file,
- including its subdirectories, need to be placed into a new created
- "Spam Filter" subdirectory in the Miranda IM main directory.
- The filter will not work as it should without any Spam Definitions.
-
- Documentation: The txt-files should be moved along with the sdk-zip into the
- "Docs" directory in the Miranda IM folder.
-
- Sounds: The wav-files should be moved into the "Sounds"
- directory. They will get recognized automatically and be added to the sounds list.
-
- That's it!
-
-
-Bugs and Wishes
-----------------------
- Feel free to mail me your wishes about "Spam Filter" and tell
- me all the bugs you may find.
- Please tell them to me via mail so I don't have to look
- everywhere around to find them. ;-)
- My email address is: hrathh at users.sourceforge.net
-
- # I would love it if you could mail me your translated bad phrases
- in your language. I would be nice if spam could be filtered in
- all languages, but I need some help, please... :-)
- ... Or perhaps you want to add some bad phrases to an existing list?
- That's also possible... ;-)
-
- # If you have any bad phrases that you want to be integrated into
- the standard bad phrases of the next release of "Spam Filter"
- please mail them to me.
-
- # If you think a string is not grammatically correct or something
- please mail me, too. (English is not my first language.)
-
-
-Filtering Tips
-----------------------
- #1:
- WebAware is often used by ICQ spambots,
- if you disable it, you'll not get as many spam as before.
- Goto: Options -> Network -> ICQ Privacy
-
- #2:
- Perhaps the following tip is useful for users that don't use latin letters
- on the system due to their language:
-
- Tip by ZaNuDa: (thanks very much!)
- "I have a good idea to filter out some of the spam messages sent to me by robots.
- These programs are plain enough and insert in their messages my nick from ICQ registration
- data regardless of my country and native language. My nickname and name is written
- on the ICQ site in transliteration, with latin letters.
- Russian ICQ users writing to me never use these phrases in Latin transcription.
- So I know, that when I receive message beginning with one of these phrases, it is probably
- spam sent to me by a robot. So I've added both phrases to customized the bad phrases list. And it works for me."
-
-
-To-Do List (random ideas)
-----------------------
- - Some events in are not yet Unicode enabled in spam filter (Miranda unicode event documentaion is quite crappy...not existant)
-
- ? Add a main menu item "Show spam log" (initially deactivated) or "Show Spammers", user can enable it
- on MenuOrder options (currently not possible using menu API of miranda)
-
- ? Button "Recognize this message as a spam" on message dialog
- so that it will be easier to add patterns to the list without going to the options (suggested by PanTzeR)
- >> this could show a editbox containing the message content
- >> after clicking OK the editbox content is added as new bad word/disliked word
- -> not a good idea IMHO, since bad words should not be taken out of one single message
- Instead: the option "Mark this contact as spammer" should be used
- -> MS_SPAMFILTER_SHOWFILTERDIALOG does much of this (show spam filter options)
- -> message dialog should/could offer support for this
-
- ? Extend the Popup message text to contain more information than just "Advertisment Alert!"
- -> similar to log file items
- -> making it customizable (suggested by Dominik Sebald)
- -> I don't know if this is really necessary...
- -> Problem: If the popup contains the mesage text the behaviour is almost the same as without spam filter :-)
-
- ? "Filtered Spam" Window where all filtered messages are displayed (similar to log file, but no separate file)
- >> The user can choose which one he would like to delete
- >> and which ones he would like to be put back into the contacts history
- (better than a "show log file" menu item)
-
- ? Filtering based on user info data, contact details (really necessary?)
- -> quite difficult, because user details are first available
- after the first message was received and added to db (for new temporary contacts), only UIN is first available
- -> Solution: need to watch Nick setting, or wait for proto acks
-
- ? Add filter for SMS Plugin(s)
- >> (Spam Filter offers spam checking services...
- >> so the better way would be if the SMS Plugins would support Spam Filter)
-
- ? Add filter for YAMN plugin (e-mail)
- >> (Spam Filter offers spam checking services...
- >> so the better way would be if YAMN supports Spam Filter)
-
- ? Bayesian method: -> will probably be "Spam Filter v3" (really necessary? I think it's too much...)
- >> This feature will be added additionally to the phrase filtering method (-> functioning as expert option)
- >> Perhaps as an half bayesian filter, which means that spam database will be shared
- >> and only few people (around 100) are allowed to maintain it
- - Integrate Bayesian filtering (http://www.paulgraham.com/antispam.html) (thanks to InvisiBill)
- - Change to percent (%) spam detection: messages declared as
- spam at 75% spam probability
- >> Save spam database on server to share the training data
-
-
-Version History
-----------------------
- 2.5.2.3: - Some internal improvements
- - Fixed: temp file sometimes resulting from VerInstallFile API was not deleted
- - Removed: reply sending delay (caused problems)
-
- 2.5.2.2: - Bug-Fix: Check for unicode core was wrong (spamfilterW.dll)
- - Some other minor changes
-
- 2.5.2.1: - Minor fixes and improvements
- - Fixed automatic installation routine for
- easy installation and Updater support
- (just extract everything out of the zip-file into the Plugins folder,
- all files will get moved accordingly)
- - Bug-Fix: Unicode calls to VariablesPlugin were wrong
- - Bug-Fix: Corrected some problems with spammer info dialog
- - Removed spammer group delete question
- - Improved: handling of users awaiting security code
- - Added debug symbols (PDB) into SDK package
-
- 2.5.2.0: - Robot Filter improvements
- - Also allows quotes in securitycode reply
- - Some minor internal improvements
- - Revised default message texts
- - Some unicode fixes
- - Fixed ColourPicker support
- - Message send delayed by short time to allow nick to be retrieved
- - Enabled workaround for YouWereAdded event recv
- - Added %triesleft% variable for message texts
-
- 2.5.1.2: - Some minor improvements
- - Fixed unicode message sending (and receiving)
- - Revisited string functions (probably introducted new bugs...)
- - Fixed possible mem leak in string lists
- - Fixed possible memory corruption in string lists
- - Fixed crash on exit
-
- 2.5.1.1: - Improved: Invalid RegExp error to be a bit more informative
- - Some minor internal changes to robustness
- - Fixed some visual glitches on Spam Definitions window on WinXP
- - Fixed a critical-section corruption
- - Fixed/Updated Custom Folders Plugin support (new version needed)
- - Added checks for new IcoLib version
-
- 2.5.1.0 - Packaged with unicode DLL (spamfilterw.dll) -> highly experimental!!!
- - Auto-Updates for Spam Definitions using Updater (uses file listing)
- - minor improvements
- - fixed version resource
- - shows error when miranda version is not supported or db3x too old
- - remembers original NotOnList-state of spammers
- - Bug-Fix using MS_PROTO_ADDTOCONTACT (workaround for problem in core)
- -> fixes Quick Search incompatibility
- - Updated icolib support for latest version (requires 0.0.1.0)
- - "Mark as spammer" not shown for chatrooms
- - The bug that YouWereAdded messages were sent to marked spammers was
- a problem in ICQ.dll this should be fixed in newer versions of the ICQ protocol
- (newer than 0.3.6.14)
- - Fixed: Invalid Regular Expressions in Spam Definitions are now notified
- - Bug-Fix: Auto-Ignore spammers were not shown on the spammers list
- - Bug-Fix: Sometimes short messages were considered as multiple received messages
- - Bug-Fix: Memory corruption problems with the log file (and some other minor logging fixes)
- - Bug-Fix: Auto-Replies were sometimes not sent out when "Delete Spam" was enabled
-
- 2.5.0.0 NEW FEATURE: Real Unicode Support!
- -> two DLL files: spamfilter.dll and spamfilterw.dll
- -> spamfilterW.dll will only load if Unicode *is* supported (e.g. Win2000 and higher...)
- -> spamfilter.dll will only load if Unicode *is not* supported (Win95/98/ME)
- -> spamfilterW9x.dll uses the unicode layer for Win95/98/ME (highly experimental version)
- It needs unicows.dll in Miranda IM directory.
- -> Spam Definition files are saved/loaded as UTF8 (auto-converting at first-run)
- - Updated: Variables Plugin support (now supports Variables v0.2.0.0)
- - Added: Support for help dialog of Variables Plugin
- - Added: The "Missing Spam Definitions"-Warning can be
- deactivated for the future by pressung the Ctrl-Key whn the message occurs
- (requested by kopec)
- (Be careful!: Should normally not be used)
- - Enhanced: Functionality of MS_SPAMFILTER_REGISTERMESSAGETYPE
- - Bug-Fix: tiny memory leak with the regexp help button icon
- - Bug-Fix: "Variables" Plugin text was not always freed (mem leak)
- - Bug-Fix: fixed possible memory leaks with realloc when low memory
- - Improved: spammers file format
- - Fixed: fixed a typing mistake without any effect
- - Bug-Fix: fixed error handling for calls to GetWindowRect
- (did not have any effect)
- - Bug-Fix: Corrected wronmg calling of TreeView state (however no effects)
- - Bug-Fix: fixed large spam icon (res id was wrong)
- - Bug-Fix: OSD support did not work yet..commented out...oups :-)
- - Bug-Fix: Option "Allowed Spam per User" on Advertisment Filter dialog
- was not synced correctly
- - Bug-Fix: OpenFile-Dialog was not shown correctly on WinNT4 (I hope it does now)
- - Bug-Fix: Restored full support for Win95 (GetLongFileName is now run-time linked)
- - Bug-Fix: special chars in XML logging header were sometimes not replaced correctly
- - Bug-Fix: samll memory leak in XL logging logic
- - Bug-Fix: Read/Sent flags got corrupted when making events as unread
- - Fixed: Updated old part in the docs (reported by PanTzeR)
- - Added: Note is shown in options when not all SpamDefinitions are available
- - Improved: some other internal tweaks
- - Extended: english teaser definitions
- - Modified: translation strings (see SpamFilter-Translation.txt)
- - Improved: Made it more robost against database curruption
- - Improved: Removed 256 sized text buffer for MsgType box (possibility of buffer overrun)
- - Improved: Internal stringlist handling on low memory conditions (string pairs)
- - Improved: revisited log file code
- - Bug-Fix: robot filter instruction and answer text could not be changed
- - Added/Fixed: MBCS and surrogates support for far east (improved locale handling, too)
- - Fixed some issues with pointer arithmetic
- - Code robustness updates
- - Impreoved: further increased filtering performance by caching
- - Cleaned up SetSpammerManually code
- - Strings modified (see SpamFilter-Translation.txt)
- - Corrected some typos in strings
- - Minor Bug-Fix: horizontal extent of list box was sometimes miscalculated
- - Added: Auto-Import feature to convert old ANSI files of old Spam Filter 2.x
- into the new UTF-8 format (needed to support Unicode properly)
- IMPORTANT!: be sure to make a backup of any self-defined Spam Definitions.
- - Improved: removed static variables in DlgProcs/WindowProcs
- - Added: bad words cache to further improve performance
- - Added: Real Unicode support (separate files: spamfilterW.dll is unicode,
- no Win9x/ME supported on Unicode)
- including BOM support for text files
- - Added: LogFile write UTF-16LE BOM into txt/log files to indicate
- correct Unicode format for Rraders as Notepad (only in Unicode mode)
- - Improved: Spam Definitions are only validated when Advertisment Filter or
- Disliked Messages Filter is enabled
- - Added some documenation about Regular Expressions (RegExp),
- how to use them and a code table (quick guide for beginners)
- (accessable via a button on the add to list dialog)
- More info: http://perldoc.perl.org/perlrequick.html
- - Added: Now shows a error message when the reply messages can't be sent
- (due to network errors etc.)
- - Added: Support for Custom Folder Plugin
- - new service: write log file
- - new service: send_automated_contact_message (including rec, error output)
- - new service: show generic error_message (out of memory?, message not sent)
- - Added: now uses Miranda's simple memory problems catcher
- - Updated: PluginInfo of Plugins options
- - got rid of AgressiveOptimize.h:
- (reason: http://forums.miranda-im.org/showthread.php?t=4863)
- does not work on DEP systems (= data execution prevention).
- As for optimizing. Use /O1 (optimize for size), disable global optimizing and disable the
- "optimize for Windows 98" feature of the linker (/opt:nowin98).
- This can considerably bloat the resulting DLL/EXE for (a small) performance gain on Win 9x,
- but does nothing on NT based systems.
- - support new variable in Variables Plugin: %number_of_auto_ignore_users%
- - Repackaged: in default zip is only english spam language
- - Added: Trigger Plugin support
- - Added: Support for extra icon on contact list (indicating spammer)
- - Added: Spammers list manager
- - Added: Auto-Import of old spammers of v2.0.1.0
-
-
- 2.1.0.0 - Added: pending auth requests are automatically denied if contact is ignored
- - Added: preparation for taken YouWereAdded events into spam detection
- - Added: Support for OSD Plugins beside Popup Plugin support (requested by Schommel)
- - Bug-Fix: Configure dialogs were not closed properly when created not as modal
- - Bug-Fix: memory leak in the string lists, the stringlist main object was never freed
- - Bug-Fix: stringlist converting to string did not work correctly (not zero terminated)
- - Bug-Fix: internal stringlists are now thread safe (using CriticalSections)
- - Bug-Fix: pcre.dll is now copied/installed correctly (path was wrong formated)
- - Bug-Fix: Regular Expressions were not compiled correctly
- -> Regular Expressions should now really work in default installation :-)
- - Bug-Fix: possible crash in recv chain filtering
- -> empty contact was deleted before ICQ could have the chance to add its message
- (bug only occured when "delete spam messages" was enabled)
- - Bug-Fix: contact that were set on the spammer list were never really hidden
- -> ICQ did always reset the Hidden attribute; this is now fixed
- - Bug-Fix: small memory leak in AutoIgnore settings loading
- - Bug-Fix: Now question message will not be sent when spammer just reached it spam limit
- - Bug-Fix: reply messages are ordered correctly in db/history
- - Bug-Fix: No longer sending "YouWereAdded" notification when a spammer is added to ignore list
- (reported by PanTzeR)
- -> ICQ sent a confirmation automatically when a user was made permanent; now this is prevented
- - Bug-Fix: Spam Log did not always mention "user ignored" (log written too early)
- - Bug-Fix: contacts event was never filtered
- - Bug-Fix: tiny problem with hContact of auth requests
- - Bug-Fix: Corrected some hidden Access Violations in MessageTypes box
- - Bug-Fix: "Disliked Messages Filter" now really works (reported by zk, Tomaso, PanTzeR)
- * message text never got allocated
- * did not work for contacts that passed the robot filter previously
- * some wrong setting names were used
- * hoax texs were checked wrongly
- * hoax texts were not loaded (corrected file ext: .sfw -> .sft)
- >> Ouch....quite crappy thing...did I really code that? :-o
- Anyway...now it's finally fixed :-D
- - Bug-Fix: Filter strings of Log-Browse dialog were not allocated correctly
- (stringlist access violation)
- - Bug-Fix: AddToHistory option of DislikedMessagesFilter did not get disabled
- when other options got disabled
- - Bug-Fix: If "Add the reply to contact history" was selected, the history showed the reply
- before the spam message (reported by Tomaso)
- - Bug-Fix: "Show log" button did never get activated (broken in v2.0.1.0)
- - Bug-Fix: relative paths for spam log were broken
- - Bug-Fix: some minor UI improvements
- - Bug-Fix: memory leak in the DislikedMessages options (bold font was not destroyed)
- - Bug-Fix: when a filter window was opened using the SF-API without parent then the window
- would not be destroyed on exit of Miranda (extended/modified SF-API)
- - Bug-Fix: added some NULL checking where I forgot it
- - Bug-Fix: added checking for correct db setting type
- - Bug-Fix: "Apply" button was sometimes enabled although no options
- were changed for message types
- - Improved: now the robot filter only workd for normal sending and receiving contacts
- - Improved: stringlist loading speed (just a bit)
- - Improved: spam detection speed when "show popup" is disabled (just a bit)
- - Fixed/Improved: some small internal tweaks and resource cleanup
- - Fixed: now uses UniqueID instead when renaming a contact to set it on the spammers list
- -> this fixes: spammers added as "'Unknown Contact' (Spammer)" (reported by PanTzeR)
- - Modified: "Random" button in robot filter options now creates always the same length
- - Improved: SPAMCHECKDATA strcuture to be more cleanly implemented
- => Code is now fully tested on different situations
- => Code was additionally fully checked for memory leaks and/or memory access violations
-
- 2.0.2.0 - FEATURE!: Support for Regular Expressions (using pcre.dll; included)
- -> Support for Regular Expressions is disabled when the DLL (pcre.dll) is not present
- -> Word filter is now much, much, much more powerful!
- - Added: RegExp DLL (pcre.dll) is installed automatically on first run (In Miranda directory)
- -> including DLL version checking
- - Added: some little more documentation about the Spam Definitions (readme and in the files)
- - Added: now the UniqueID of a protocol is appended to the nickname in the spam log
- (reported by Lastwebpage)
- - Added: support for Updater to update the SpamFilter plugin
- - Bug-Fix: Making use of EnterCriticalSection to gain thread safety
- - Bug-Fix: avoiding of some string buffer overruns in some rare situations (if ever)
- - Bug-Fix: Message Types box gets sorted properly
- - Bug-Fix: popups did not work (broken in 2.0.1.0)
- - Bug-Fix: menu item icon was not updated when icons were changed (IcoLib support)
- - Bug-Fix: fixed some memory leaks of contact name strings
- - Extended: Documentation of Spam Definitions and how they work
- - Fixed: corrected some strings (see SpamFilter-Translation.txt)
- - Fixed: corrected wrong naming of teaser text files (.sfw -> .sft)
- - Fixed: known spammer file now allows proto|uniqueid and proto|nick (if available)
- - Modified: few changes in the strings (see SpamFilter-Translation.txt)
-
- 2.0.1.0 - Bug-Fix: "Allowed spam per User" could not be changed (reported by ATom)
- - Bug-Fix: problems with RTL support (:text)
- -> I thought RTL support would only work on Arabic/Hebrew versions of windows, so I enabled it..
- In fact it works on most Win2000/XP versions as I found out
- (not really good documented :-/... they only speak of "RTL enabled windows versions")
- - Bug-Fix: minor memory leak with the message type icons
- - Bug-Fix: layout confusion with Spam Logging group (reported by Romx)
- - Bug-Fix: auth requests were not handled correctly when setting a spammer manually
- - Bug-Fix: "Allowed bad phrases until spam" was ignored (ATom)
- -> caused just by a small typo in the code :-/
- - Bug-Fix: line breaks and spaces were not cleared correctly in
- incoming messages (silly typo in code :-/)
- -> this fixes the following:
- * normal words as security code were not recognized as right answers
- (reported by Steffen Kaufmann)
- * sometimes the reply for a good answer was not sent (reported by ATom)
- - Bug-Fix: using mir_snprintf to avoid string buffer overruns
- - Bug-Fix: first message from NotOnList user was from "(Unknown contact)"
- - Bug-Fix: PreSpammers were not unique, now they are saved as "Proto|Address"
- - Modified: Removed SFFreeMemory, replaced with miranda_sys_free (m_spamfilter.h)
- - Modified: pszSection in MESSAGETYPEDESC can now really be NULL (m_spamfilter.h updated)
- - Modified: AutoIgnore feature now uses real unique user ID
- - Added: IcoLib support
- - Added: Support for "ColourPicker" to choose Colors of Popups
- - Added: Support for Netlib logging (Netlib_Logf) -> spam filter actions on messages are now listed
- in the network activity log
- - Added: ability to reset the AutoIgnore feature
- - Improved: Better looking "Mark as spammer" dialog
- - Improved: minor performance improvements, code cleaning, DB settings cleaned up.
- - Changed: services for message types (no backward compatibility to 2.0.0.0, sorry
- -> devs, please update "m_spamfilter.h")
- -> detecting default settings for checked protocols/events is now possible (might be useful for IRC?)
- - Added: New event for protocols to determine if they want to be checked for spam by default:
- ME_SPAMFILTER_PREADDNEWMESSAGETYPE
- - Modified: Functionality of MS_SPAMFILTER_SETSPAMMANUALLY and
- MS_SPAMFILTER_GETHANDLE ("m_spamfilter.h")
- - Fixed: phone number default definitions (all large numbers were detected as phnone codes)
- - Fixed/Extended: translation strings (Translattor see "SpamFilter-Translation.txt")
- => all known bugs should now be fixed :-)
-
- 2.0.0.0 - Almost all got changed/fixed/improved/extended/... :-)
- - Added support for logging in XML format (including XSL stylesheet)
- -> Very clean XML format used
- -> Characters replaced: < with &lt; , > with &gt; , & with &amp; , " with &quot; , ' with &apos;
- - Fixed: Layout mistake on options page
- - Added: Recognition of CAPITALIZED messages (thanks to InvisiBill)
- - Some other small changes and cleaned up code
- - Added possibility to change spammers (on ignore list)
- - Added extra buttons for "filter settings"
- - Added error handling for log file edit box and removed read only flag
- - Fixed: "Select log file" dialog was shown sometimes on re-activating filter
- - Removed unnecessary error message ("Please select bad phrase to delete")
- - Added (better) error handling for "Allowed bad phrases" box
- - Improved/Changed German translation completely
- - Added more Russian bad phrases
- -> Many thanks to ZaNuDa
- - Added new section "Filtering Tips" to readme file
- - Added recognition support for phone numbers (Idea by ZaNuDa)
- - Spam Filter now behaves as a filter protocol
- -> This makes the filter more faster than before
- - Moved together the filter behaviour "delete message" and "delete contact"
- -> The contact now gets automatically deleted if it has no other messages in history
- - Fixed: Apply button got always enabled when options were loaded
- - Now uses better/newer LoadImage function instead of LoadIcon function to save memory
- -> Icons now get unloaded to save memory
- - Added Spam Definitions instead of using a langpack string
- - Bold heading for groups in "Configure..." options, too
- - Added automatic adjustment of "Ignore" settings
- - Improved: Icons in spam popups are now skinned icons of Miranda IM for message and URL icon
- (with layered spam icon on it)
- - Improved file size
- - Dropped "one phrase message" recognition
- -> Was not a good indicator for spam
- -> Did not work with languages which do not have (or use) spaces
- - Added support for "PluginUninstaller"
- - Added "Allowed spam messages" feature
- - Complete new phrase list algorithms for easy phrase list
- loading/saving and checking
- - Changed formating of sounds (Added: "Spam Filter: " prefix)
- - Added "empty message" detection
- - Added "Multiple message with same content" detection (Idea by Popovn)
- - Recognition of bad phrases that are formated differently (like "\/!@gr@")
- and have kinds of things in them (thanks to InvisiBill)
- - Added disliked messages filter
- Filter out something like: "Please send this message to all of your friends" or
- "please forward") (Idea by Johannes)
- - Added button "Show log" to make opening the log file more easier
- - Changed "Select log file" dialog to use the standard "Save as" dialog instead of the "Open" dialog
- - Improved log file format
- - Also looking for "good phrase(s)"
- - Recognition support for phrases with s p a c e s (included in "different formated phrases" check)
- - Added: Position of configure dialogs gets saved
- - Added: Now also checks for auth requests
- - Some resource improvements
- - Added the possibility to manually avoid spam check via pressing the control key
- when recieving a message
- - The Spam Filter now is implemented as a proper protocol filter plugin
- - Improved filtering speed
- - Added: Automatic installation of docs and sound files on first run
- - Added: Auto-Import feature for bad phrases used with v1.0.4.0
- - Added: DatabaseEditor++ support
- - Extended: Phrase list editing; the list boxes now support
- horizontal scrolls if needed, drag and drop for rearranging the phrases,
- context menu for fast editing, possibility to input long phrases, etc...
- - Added: "Variables" plugin support
- - Added a second default sound file
- - Added: Log file control now makes use of the auto complete feature
- - Added: Relative paths can be used in the log file edit control
- - Added: Comma Separated Values format logging
- - Added: Robot Block functionality similar to "StopSpam" plugin:
- Further enhanced technic and cleaner implementation.
- - Translators: There are a lot of changes in the strings ;-)
- - Doubly recieved messages can be removed
- For plugin developers: (Only ;-) )
- - Updated "m_spamfilter.h" (Almost all is new)
- - Added "m_spamfilter.inc" for Delphi developers
-
- 1.0.4.0 - Two entries with the same words in the customized bad words list
- are no longer possible
- - Added Feature: Spammer name/id remembering and blocking
- - Added Feature: Spammers who are not recognized can be added to the spammers list via right click
- (thanks to Rudi)
- - Added version information to DLL file
- - Changed logging output
- - Added txt file item on select log file dialog
- - Improved conrolling of the options page via keyboard
- - Improved layout of the options page
- - Extended URL-recognition: Now recognizes also URLs with returns in between (thanks to Rudi)
- - Extended/Improved default bad words very much (strings, too) -> now 78
- -> Please update your language pack (if you use one)
- - Extended German bad words (see "SpamFilter_Translation.txt")
- - Extended Potuguese (Brazil) bad words (thanks to Paulo)
- - Updated German and Chinese (Traditional) dialog translations
- (thanks to Wongsen for the Chinese one)
- - Fixed: The string "Log spam messages to file:" was displayed in
- German (thanks to Wongsen)
- - Fixed: Crash on selecting logging file (thanks to Genionhandy2 and Bumper1)
- - Fixed: URL-Recognition and one word message recognition didn't work
- currently (thanks to Wongsen and Rudi)
- - Fixed: Small bug with the open file dialog
- - Fixed: URLs are now completely checked and saved to log file
- - Updated service functions for plugin developers
- - Improved error checking of "Add bad word" dialog
- - Improved error checking for "Select log file" dialog
- - New/Improved icons (smaller file size, too)
- - Improved default settings
- - Some other small changes
- - Updated screenshot on website
-
- 1.0.3.1 - Changed/Improved icons for spam popups
- - Nearly complete rewrite of the spam recognition
- - Fixed: Log file wasn't written if selected directory didn't exist anylonger
- - Fixed: Log file option got always unchecked (also if enabled)
- - Fixed: Sometimes the wrong bad word got selected on inserting a
- customized bad word
- - Added bad words are now checked for occurence in default list
- - Changed some strings
- - Changed some German translation strings
- - Updated Chinese (Traditional) strings (thanks to Wongsen)
- - Updated Chinese (Traditional) bad words (thanks to Wongsen)
- - Extended English default bad words (strings, too)
- -> Please update your language pack (if you use one)
- - Changed/Improved included sound file and new file name
- -> Please update your sound settings (thanks to Wongsen)
- - Extended German bad words
- - Added "Activate/Deactivate" item in "PopUps" submenu
- - Improved URL filtering: URLs with spaces (h t t p :) are now
- included in the filter, too (thanks to Rudi)
- - Some preparing for contact name/id collecting/blocking (coming in v1.0.4.0)
- - Changed/Improved documentation and removed some mistypings
- - Some other small/big internal changes/improvements
- - FOR PLUGIN DEVELOPERS!: Added more service functions!
- -> Activation service functions
- -> General spam checking service (with hContact)
- (For details see "m_spamfilter.h")
-
- 1.0.3.0 - Improved error checking for "allowed bad words" control
- - Fixed: Customized bad words sometimes got messed up due to wrong
- pointers (thanks to Lúcio and Wongsen)
- - Fixed: Customized bad words now get correctly allocated
- and released
- - Fixed: Default settings did not now fit for all languages
- (thanks to Wongsen)
- - Improved performance and bad words count loader
- - Improved spam filter
- - Merged "Is URL" and "Contains URL" part
- - Improved log file output
- - Extended default bad words (Updated strings, too)
- - Added Chinese (Traditional) bad words (thanks to Wongsen)
- - Changed some English strings (Updated strings, too)
- - Changed some German translation strings
- - Added Chinese (Traditional) dialog strings (thanks to Wongsen)
- - Improved/Changed documentation
- - NEW FOR DEVELOPERS: Added service function for bad words
- checking in other plugins (For details see "m_spamfilter.h")
- - Some other small changes
- - Updated screenshot on website
-
- 1.0.2.4 - Fixed: Non-spamming contacts sometimes got hidden while sending
- messages to them (thanks to Javier and Tomaso)
- - Changed some strings in German translation
-
- 1.0.2.3 - Fixed: Button "Cancel" in "Add bad word" dialog showed always the
- German variant "Abbrechen" (thanks to Jef)
- - Fixed: Database values now get freed (Oups, I forgot that...)
- - Fixed: Auto-Deleting message and auto-deleting contact now works
- without outputing empty message dialogs! (Nobody noticed?)
- - Changed "Add bad word" dialog for people who don't read documentation
- files ;-)
- - Changed some translation strings
- - Improved filter performance
- - Small changes in translation documentation
-
- 1.0.2.2 - Improved: Smaller file size (improved compiler settings)
- - Changed documentation files
- - Reprogrammed error checking for "Add bad word" dialog
- - Reprogrammed key support for customized bad words list box
- (Now uses subclass procedure)
- - Extended recognized keys in list box:
- Now supports "del", "-", "+", up and down keys
- - Changed Portuguese (Brazil) bad words (thanks to Lúcio)
- - Improved dates/times in logging:
- -> Now uses system (language) default format for formatting dates/times
- -> Removed translation strings for this
- - Fixed: Corrected small checking bug with "Allowed bad words until spam"
- (thanks to Lúcio)
- - Fixed: Options items are now correctly grouped
- - Fixed: Spam logging didn't work without Path plugin
- - Some internal improvements/performance optimizations
- - Some changes with the German translation
- - Improved spam logging output: more detailed and cleaned up
- - Optimized/Faster spam logging
- - Improved/Changed documentation
- - Some other small/minor changes
-
- 1.0.2.1 - Improved behaviour of "Allowed bad words in messages" spin control
- - Changed dialog font to same as in Miranda IM core
- - Added expert options support for logging options
- - Changed Path Plugin dependency (Path plugin is now optional)
- -> You do not need to have the Path plugin for logging any longer
- -> It is only needed if you would like to use relative paths
- - Included a fix for an issue with the Path plugin
- (kind of bug in Path plugin)
- - Changed option group headings to bold (finally found out how to
- switch this... ;-) )
- - Removed positioning of options group
- - Cleaned up/Improved resources
- - Added button for "Select log file" dialog
- - Changed log file box
- - Improved spam logging: Now messages are now longer saved as only
- lower case
- - Added error checking for add bad word dialog
- - Fixed: Some error box strings were not translatable
- - Fixed: Selection of "What to do" got sometimes not set
- - Changed the path to default sound file to the included sound file
- - Forgot to switch the version number shown on plugins page (Oups...)
- - Improved German translation
- - Some other small changes
- - Updated screenshot on website
-
- 1.0.2.0 - Added spam message/sender logging to file (fully translatable)
- - Added some language pack string for spam logging
- - Added Portuguese (Brazil) bad words (thanks to Lúcio)
- - Improved comma recognition in default bad words list in language pack
- - Added "del" key support in customized bad words box
- - Small changes in German translation
- - Added some default bad words (Changed strings, too)
- - Use of new header files
- - Updated screenshot on website
-
- 1.0.1.0 - Added spamming contacts handling
- - Improved option page layout
- - Moved translation strings out of "SpamFilter_Developers.txt" to
- separate file
- - Added some default bad words (Changed strings, too)
- - Added French bad words (thanks to Poischack)
- - Added Russian bad words (thanks to NeptunE)
- - "SpamFilter" speaks German!
- (Completed German standard translation in "SpamFilter_Translation.txt")
- - Rearranged and optimized code
- - Some other small changes
- - Updated screenshot on website
-
- 1.0.0.2 - Changed selection style of customized bad words box
- - Fixed: I forgot to mark some strings translatable...
- - Changed some texts (Changed strings, too)
- - Better position for "Add Bad Word" dialog
- - Customized bad words list gets now sorted
- - Added "Fast delete": Improved and faster deleting of customized
- bad words in list
- - Improved adding of customized bad words (small change)
- - Added sound file
- - Cleaned up code a bit
- - Some other minor changes
-
- 1.0.0.1 - Removed some debug output messages (Oups...)
- - Extended default bad words
- - Fixed: Customized bad words list doubled itself every time it
- got loaded
- - Smaller file size
- - Some other tiny changes
-
- 1.0.0.0 - Initial release
-
-
-Thanks
-----------------------
- * To Roland Rabien the author of "SpamBlock" for the
- first idea of spam recognition by bad words
-
- * To Daniel Walter who improved "SpamBlock" to "SpamBlock+"
- for the idea of an extensible bad words list
-
- * To romamik the author of "StopSpam" for the
- idea to block robots via reply messages
-
- * To Lúcio for the Portuguese (Brazil) bad words
- and his much feedback ;-)
-
- * To Wongsen for the Chinese (Traditional) bad words and dialog translation,
- his much feedback, his idea for an sound file and his helpful "beta testing" ;-)
-
- * To NeptunE for the Russian bad words
-
- * To Poischack for the French bad words
-
- * To Paulo for some more Portuguese (Brazil) bad words
-
- * To cyesto for creating a great bug-fix for the crash-on-ignore issue
- in version 2.1.0.0. Thanks a lot!
-
- * To Rudi for his many reported spam messages
-
- * To Javier, Jef, Lúcio, Tomaso, Wongsen, Rudi, Genionhandy2, Bumper1,
- ATom, Lastwebpage, Steffen Kaufmann, Romx, zk, Sarcago, sh8an, PanTzeR,
- DaSilva, TioDuke, kurd, gerk, Vosoni, Avalanche, adderek, Schommel,
- PsychodelEKS, Petr and pro100_tak for their bug reports
-
- * To Johannes, Pickle Pete, Popovn, PanTzeR for their improvement ideas
-
- * To Genionhandy2 for advertising this plugin ;-)
-
- * To InvisiBill for his much feedback and his improvement ideas
-
- * To Tigerix for his massive feature suggestions and bug-reporting :-)
-
- * To ZaNuDa for some more Russian bad words and the filtering tips
- and especially for his much effort in beta testing version 2.0.0.0.
-
-
-Translation
-----------------------
- Translation strings and available bad words strings can be found
- in "SpamFilter-Translation.txt" of the SDK package.
-
-
-License and Copyright
-----------------------
-
- "Spam Filter" is released under the terms of the GNU General Public License.
- See "SpamFilter-License.txt" for more details.
-
- "Spam Filter" is copyright (c) 2003-2006 by Heiko Herkenrath.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the copyright
- notice, this list of conditions and the following disclaimer.
- 2. 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.
- 3. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
- 4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- RegExp Library:
- PCRE (pcre.dll) is a library of functions to support regular expressions whose syntax
- and semantics are as close as possible to those of the Perl 5 language.
-
- "Perl Compatible Regular Expressions" (PCRE) is distributed under the terms of
- the "BSD" license. See "PCRE-License.txt" for more details.
-
- "PCRE" is copyright (c) 1997-2004 University of Cambridge
-
-
+
+Spam Filter 2.5.2.3
+------------------------------------------------------------------------
+ Plugin for Miranda IM 0.4.3 and +
+
+ Plugin Info: ----------------------------
+ | Version: 2.5.2.3
+ | Filename: spamfilter.dll / spamfilterW.dll
+ | Author: H. Herkenrath (hrathh at users.sourceforge.net)
+ | Description: Filters out advertisments, robot messages and disliked messages
+ | such as hoax messages.Filters out spam messages from contacts
+
+ Contents: -------------------------------
+ | Filter Improvement, Features, Requirements, Usage,
+ | Spam Definitions, Installation, Bugs and Wishes, Filtering Tips,
+ | To-Do List, Version History, Thanks, Translation, License and Copyright
+
+
+Filter Improvement
+----------------------
+ -> Still receiving spam?
+ If you receive spam messages after installing this plugin
+ which are not filtered out just mail the text of the spam message
+ to me and I will integrate some bad phrases out of it immediately.
+ If the filtering of that message can't be done via bad phrases I
+ will try to find another way and integrate that way, too.
+
+ -> New filtering ideas?
+ If you have some other spam filtering ideas please mail me.
+
+ -> Bugs?
+ If you find any bugs please tell them to me via mail.
+ So I don't have to look everywhere around to find them. ;-)
+
+ -> Patches or Extensions?
+ If you are a developer and/or know how to code
+ feel free to send me patches or extensions to the code.
+ The best way is via e-mail.
+ I really appreciate it. :-)
+ If you need extensions to the API please contact me, too.
+
+ -> Filtering in all languages?!
+ There are already bad phrases for the following languages:
+ English, German, French, Russian, Portuguese (Brazil), Chinese (Traditional)
+ I would love it if this list could be extended further.
+ It is a little difficult to speak and understand all languages of this
+ world at the same time ;-) ...and if you speak a language that I don't...
+ (and I think that are very much ;-)...) please send some bad phrases in
+ your language to me.
+ It would be nice if spam could be filtered in all languages,
+ but I need some help... please... :-)
+ Also feel encouraged to release your own Spam Definitions on the File Listing.
+
+ -> Reporting spam log file?!
+ You can also help me via sending your spam log file to me.
+ So I can look for new/better bad phrases.
+ Such a log file can be created with the spam logging feature.
+ It doesn't include any data beside the spam messages sent to you.
+ I will look at it and intergrate some more bad phrases out of it to
+ improve the filter quality.
+
+ -> New bad phrases?
+ If you have some bad phrases to add to the existing lists
+ please mail them to me, too.
+ I will check the bad phrases and integrate them immediately.
+
+
+Features
+----------------------
+ + Filters out incoming spam messages
+ + Spam filtering with all protocols
+ + Which messages are declared as spam is changeable
+ + Improved spam filter (pretty accurate)
+ + Recognizes also URLs with spaces
+ + Supports Regular Expressions (RegExp) in its word filter (really powerful!)
+ + Spam handling: either mark read or delete messages
+ + Spaming contacts get automatically removed if there are no items in history
+ + Spammer name/id auto ignoring
+ + Easy adding of customized bad phrases
+ + Spam alert via Sound or Popup (Popup plugin is needed for this feature)
+ + Spam message logging to file
+ Supported file formats: TXT, LOG, CSV, XML (including XSL stylesheet)
+ + Supports "ballon tips" for error display
+ + Press control key to avoid messages to be checked for spam
+ + Fully configurable with many options
+ + Filter can be disabled temporarily on the options page
+ + Large list of default bad phrases (about 80 well chosen english phrases at the moment)
+ + Full translation support (default bad phrases, too)
+ + Available dialog languages: English, German
+ + Available Spam Definition languages:
+ English, German, French, Russian, Portuguese (Brazil), Chinese (Traditional)
+ + Provides spam checking service functions for other plugins
+ + Auto-Updates for Spam Definitions using Updater plugin
+ + Full Unicode support
+ + Automatic installation of all files, just unzip into Plugins directory
+ + Supported plugins/tools:
+ Miranda Installer, Popup/PopupPlus/YAPP, DatabaseEditor++, Updater,
+ Variables Plugin (http://www.cs.vu.nl/~pboon/projects.htm),
+ Trigger Plugin (http://www.cs.vu.nl/~pboon/projects.htm),
+ Icons Library Manager (IcoLib), Colour Picker, OSD Plugin/WannaBe OSD,
+ Custom Profile Folder Plugin, MultiWindow Contact List (extra icon)
+
+
+Requirements
+----------------------
+ -> Miranda IM 0.4.3+:
+ Miranda IM is needed in the version 0.4.3 or greater.
+
+ -> Popup Plugin 1.0.1.9+ (optional):
+ For using the popup function when a spam message
+ arrives it is necessary to have the popup plugin installed,
+ At least version 1.0.1.9 or greater.
+ PopupPlus is supported, too.
+ You need PopupPlus 2.0.3.97 or later.
+
+ -> Variables Plugin 0.2.0.23+ (optional):
+ For using variables in outgoing reply messages
+ you need to have the Variables Plugin installed,
+ At least version 0.2.0.23 or greater.
+
+
+Usage
+----------------------
+ "Spam Filter" options can be found here:
+ "Options" -> "Events" -> "Spam Filter"
+
+ The sound file which is played when spam arrives can be changed in:
+ "Options" -> "Events" -> "Sounds"
+
+ Mark-Read feature:
+ If you chose "mark spam messages as read" in the options recommended option)
+ the spammer shows up in a half-visible way on your contact list.
+ However, the incoming message notification is blocked.
+ When you close Miranda IM all half-visible (not-on-list) contacts get removed automatically!
+
+ To avoid the online notification go to the Ignore options and activate "suppress online notification" for unknown contacts.
+
+ If you dislike this behaviour choose "delete spam" (but be aware that you might loose messages).
+
+ Un-Ignoring spammers:
+ Recognized spammers can be easily unignored usinf the options.
+ Just go to "Options" -> "Events" -> "Spam Filter" and click on the "Spammers" button.
+
+ If a unknown user sent you a message and you want to be sure he is no longer watched by the filter, just click
+ on "Add user to contact list" in the contact's menu. (This only works if you chose "mark spam as read".)
+
+
+Spam Definitions
+----------------------
+ "Spam Definitions" are a set of files which Spam Filter uses to detect spam.
+ The files contain well selected words/phrases etc. which a common in spam messages.
+ The Spam Definitions are mostly used by the "Advertisment Filter".
+
+ The Spam Definitions make up the default filter behaviour of Spam Filter.
+ You normally should not need to modify these files. Instead you should use
+ "Options" -> "Events" -> "Spam Filter" to configure your personal filter words.
+
+ You can install as many Spam Definitions as you like, but you should at least
+ install one package in your language.
+ The filter will not work as it should without any Spam Definitions.
+ For each languge package you install the plugin can filter spam messages.
+ For example, if you install the "German" and the "English" packages,
+ most German and English spam can be filtered.
+ Spam Filter can only filter for those languages it has data sets available.
+
+ Spam Filter loads all Spam Definition Files it can find in the directories.
+ All contents of all files are considered when a message is checked for spam.
+ Spam Filter does not know which language the message is, it simply compares its contents.
+
+ The exactness and accuracy of Spam Filter depends on its Spam Definitions.
+ If the Spam Definitions are not good, the filter is not exact.
+
+ The current Spam Definitions can be viewed in
+ the "Spam Filter" subdirectory of the Miranda IM folder.
+
+ How it works:
+ There are different Spam Definition languages available because Spam Filter needs different data sets
+ (e.g. bad words) for the different languages. This is necessary, because bad word filtering consits
+ only of testing if a word exists in the message or not.
+ When there are enough bad words in the message it will be seen as spam.
+ If Spam Filter would only have a list of English bad words (like "earn money",...)
+ it would only be able to filter English spam, since the words "earn money", etc do only exist in English messages.
+ To filter German spam another data set is needed for the filter with e.g. "Sonderangebot",
+ which again probably never will exist in English spam messages.
+ The more Spam Definition languages you have installed, the more spam you can filter.
+
+ Spam Filter does not detect the language of a message. It simply loads all bad words it can find
+ in the directoriy and checks if any of the contained bad words do match with the message.
+ If they match it is spam, if they do not, it is no spam.
+
+ The file names are not important for the filter (only extension and subdirectory is considered).
+ They are named "English", "German", etc so that it is easier to determine what they contain.
+
+ Spam Filter checks if any contained word of the Spam Definitions matches with the message.
+ It counts how many matches it can find and then checks if the matches are enough to consider the message as spam.
+
+ If you get a spam message in a language for which you don't have Spam Definitions installed, it won't be a problem.
+ It won't break anything, nor will your PC be blown up, or sth. like this... ;-)
+ Spam Filter simple won't be able to filter this message. The message will be detected as no spam,
+ because there are no data sets available.
+
+ Example:
+ If you receive, for example, French spam and you don't have the French Spam Definitions installed.
+ Spam Filter will then load all bad words it can find in the Definitions to detect if it is spam.
+ But, no matches will be found, because French spam does normally not contain English or German words.
+ French spam typically contains French words... ;-)
+
+ Spam for which you don't have any Spam Definitions installed can
+ only be blocked by the Robot Filter (if enabled additionally)
+ or if (by chance) the message contains some English bad words, or some common URLs (like .org, .com), etc.
+
+
+Installation
+----------------------
+ The easiest way to install this plugin is to use the
+ installation tool "Miranda Installer" (sadly not available anymore).
+
+ If you don't want to use that tool you can install this plugin
+ manually, too.
+ Just copy all the contents of the zip-file as they are into the "Plugins" directory
+ in the Miranda IM folder.
+ "Spam Filter" will detect the files and move them into the appropriate directories
+ on it's first run.
+
+ You can also do all the installation by hand, if you want to:
+
+ Main Plugin: Copy the file "spamfilter.dll" into the "Plugins" directory
+ in the Miranda IM folder.
+ If you would like to use Unicode you need to copy the file "spamfilterW.dll"
+ instead. Using Unicode will only work for Windows NT4/2000+.
+
+ Support for Regular Expressions:
+ If you would like to use Regular Expressions with Spam Filter (recommended)
+ then you should copy the file "pcre.dll" (RegExp DLL) into the Miranda IM directory.
+
+ Spam Definitions: The contents of the "Spam Filter" folder from the zip file,
+ including its subdirectories, need to be placed into a new created
+ "Spam Filter" subdirectory in the Miranda IM main directory.
+ The filter will not work as it should without any Spam Definitions.
+
+ Documentation: The txt-files should be moved along with the sdk-zip into the
+ "Docs" directory in the Miranda IM folder.
+
+ Sounds: The wav-files should be moved into the "Sounds"
+ directory. They will get recognized automatically and be added to the sounds list.
+
+ That's it!
+
+
+Bugs and Wishes
+----------------------
+ Feel free to mail me your wishes about "Spam Filter" and tell
+ me all the bugs you may find.
+ Please tell them to me via mail so I don't have to look
+ everywhere around to find them. ;-)
+ My email address is: hrathh at users.sourceforge.net
+
+ # I would love it if you could mail me your translated bad phrases
+ in your language. I would be nice if spam could be filtered in
+ all languages, but I need some help, please... :-)
+ ... Or perhaps you want to add some bad phrases to an existing list?
+ That's also possible... ;-)
+
+ # If you have any bad phrases that you want to be integrated into
+ the standard bad phrases of the next release of "Spam Filter"
+ please mail them to me.
+
+ # If you think a string is not grammatically correct or something
+ please mail me, too. (English is not my first language.)
+
+
+Filtering Tips
+----------------------
+ #1:
+ WebAware is often used by ICQ spambots,
+ if you disable it, you'll not get as many spam as before.
+ Goto: Options -> Network -> ICQ Privacy
+
+ #2:
+ Perhaps the following tip is useful for users that don't use latin letters
+ on the system due to their language:
+
+ Tip by ZaNuDa: (thanks very much!)
+ "I have a good idea to filter out some of the spam messages sent to me by robots.
+ These programs are plain enough and insert in their messages my nick from ICQ registration
+ data regardless of my country and native language. My nickname and name is written
+ on the ICQ site in transliteration, with latin letters.
+ Russian ICQ users writing to me never use these phrases in Latin transcription.
+ So I know, that when I receive message beginning with one of these phrases, it is probably
+ spam sent to me by a robot. So I've added both phrases to customized the bad phrases list. And it works for me."
+
+
+To-Do List (random ideas)
+----------------------
+ - Some events in are not yet Unicode enabled in spam filter (Miranda unicode event documentaion is quite crappy...not existant)
+
+ ? Add a main menu item "Show spam log" (initially deactivated) or "Show Spammers", user can enable it
+ on MenuOrder options (currently not possible using menu API of miranda)
+
+ ? Button "Recognize this message as a spam" on message dialog
+ so that it will be easier to add patterns to the list without going to the options (suggested by PanTzeR)
+ >> this could show a editbox containing the message content
+ >> after clicking OK the editbox content is added as new bad word/disliked word
+ -> not a good idea IMHO, since bad words should not be taken out of one single message
+ Instead: the option "Mark this contact as spammer" should be used
+ -> MS_SPAMFILTER_SHOWFILTERDIALOG does much of this (show spam filter options)
+ -> message dialog should/could offer support for this
+
+ ? Extend the Popup message text to contain more information than just "Advertisment Alert!"
+ -> similar to log file items
+ -> making it customizable (suggested by Dominik Sebald)
+ -> I don't know if this is really necessary...
+ -> Problem: If the popup contains the mesage text the behaviour is almost the same as without spam filter :-)
+
+ ? "Filtered Spam" Window where all filtered messages are displayed (similar to log file, but no separate file)
+ >> The user can choose which one he would like to delete
+ >> and which ones he would like to be put back into the contacts history
+ (better than a "show log file" menu item)
+
+ ? Filtering based on user info data, contact details (really necessary?)
+ -> quite difficult, because user details are first available
+ after the first message was received and added to db (for new temporary contacts), only UIN is first available
+ -> Solution: need to watch Nick setting, or wait for proto acks
+
+ ? Add filter for SMS Plugin(s)
+ >> (Spam Filter offers spam checking services...
+ >> so the better way would be if the SMS Plugins would support Spam Filter)
+
+ ? Add filter for YAMN plugin (e-mail)
+ >> (Spam Filter offers spam checking services...
+ >> so the better way would be if YAMN supports Spam Filter)
+
+ ? Bayesian method: -> will probably be "Spam Filter v3" (really necessary? I think it's too much...)
+ >> This feature will be added additionally to the phrase filtering method (-> functioning as expert option)
+ >> Perhaps as an half bayesian filter, which means that spam database will be shared
+ >> and only few people (around 100) are allowed to maintain it
+ - Integrate Bayesian filtering (http://www.paulgraham.com/antispam.html) (thanks to InvisiBill)
+ - Change to percent (%) spam detection: messages declared as
+ spam at 75% spam probability
+ >> Save spam database on server to share the training data
+
+
+Version History
+----------------------
+ 2.5.2.3: - Some internal improvements
+ - Fixed: temp file sometimes resulting from VerInstallFile API was not deleted
+ - Removed: reply sending delay (caused problems)
+
+ 2.5.2.2: - Bug-Fix: Check for unicode core was wrong (spamfilterW.dll)
+ - Some other minor changes
+
+ 2.5.2.1: - Minor fixes and improvements
+ - Fixed automatic installation routine for
+ easy installation and Updater support
+ (just extract everything out of the zip-file into the Plugins folder,
+ all files will get moved accordingly)
+ - Bug-Fix: Unicode calls to VariablesPlugin were wrong
+ - Bug-Fix: Corrected some problems with spammer info dialog
+ - Removed spammer group delete question
+ - Improved: handling of users awaiting security code
+ - Added debug symbols (PDB) into SDK package
+
+ 2.5.2.0: - Robot Filter improvements
+ - Also allows quotes in securitycode reply
+ - Some minor internal improvements
+ - Revised default message texts
+ - Some unicode fixes
+ - Fixed ColourPicker support
+ - Message send delayed by short time to allow nick to be retrieved
+ - Enabled workaround for YouWereAdded event recv
+ - Added %triesleft% variable for message texts
+
+ 2.5.1.2: - Some minor improvements
+ - Fixed unicode message sending (and receiving)
+ - Revisited string functions (probably introducted new bugs...)
+ - Fixed possible mem leak in string lists
+ - Fixed possible memory corruption in string lists
+ - Fixed crash on exit
+
+ 2.5.1.1: - Improved: Invalid RegExp error to be a bit more informative
+ - Some minor internal changes to robustness
+ - Fixed some visual glitches on Spam Definitions window on WinXP
+ - Fixed a critical-section corruption
+ - Fixed/Updated Custom Folders Plugin support (new version needed)
+ - Added checks for new IcoLib version
+
+ 2.5.1.0 - Packaged with unicode DLL (spamfilterw.dll) -> highly experimental!!!
+ - Auto-Updates for Spam Definitions using Updater (uses file listing)
+ - minor improvements
+ - fixed version resource
+ - shows error when miranda version is not supported or db3x too old
+ - remembers original NotOnList-state of spammers
+ - Bug-Fix using MS_PROTO_ADDTOCONTACT (workaround for problem in core)
+ -> fixes Quick Search incompatibility
+ - Updated icolib support for latest version (requires 0.0.1.0)
+ - "Mark as spammer" not shown for chatrooms
+ - The bug that YouWereAdded messages were sent to marked spammers was
+ a problem in ICQ.dll this should be fixed in newer versions of the ICQ protocol
+ (newer than 0.3.6.14)
+ - Fixed: Invalid Regular Expressions in Spam Definitions are now notified
+ - Bug-Fix: Auto-Ignore spammers were not shown on the spammers list
+ - Bug-Fix: Sometimes short messages were considered as multiple received messages
+ - Bug-Fix: Memory corruption problems with the log file (and some other minor logging fixes)
+ - Bug-Fix: Auto-Replies were sometimes not sent out when "Delete Spam" was enabled
+
+ 2.5.0.0 NEW FEATURE: Real Unicode Support!
+ -> two DLL files: spamfilter.dll and spamfilterw.dll
+ -> spamfilterW.dll will only load if Unicode *is* supported (e.g. Win2000 and higher...)
+ -> spamfilter.dll will only load if Unicode *is not* supported (Win95/98/ME)
+ -> spamfilterW9x.dll uses the unicode layer for Win95/98/ME (highly experimental version)
+ It needs unicows.dll in Miranda IM directory.
+ -> Spam Definition files are saved/loaded as UTF8 (auto-converting at first-run)
+ - Updated: Variables Plugin support (now supports Variables v0.2.0.0)
+ - Added: Support for help dialog of Variables Plugin
+ - Added: The "Missing Spam Definitions"-Warning can be
+ deactivated for the future by pressung the Ctrl-Key whn the message occurs
+ (requested by kopec)
+ (Be careful!: Should normally not be used)
+ - Enhanced: Functionality of MS_SPAMFILTER_REGISTERMESSAGETYPE
+ - Bug-Fix: tiny memory leak with the regexp help button icon
+ - Bug-Fix: "Variables" Plugin text was not always freed (mem leak)
+ - Bug-Fix: fixed possible memory leaks with realloc when low memory
+ - Improved: spammers file format
+ - Fixed: fixed a typing mistake without any effect
+ - Bug-Fix: fixed error handling for calls to GetWindowRect
+ (did not have any effect)
+ - Bug-Fix: Corrected wronmg calling of TreeView state (however no effects)
+ - Bug-Fix: fixed large spam icon (res id was wrong)
+ - Bug-Fix: OSD support did not work yet..commented out...oups :-)
+ - Bug-Fix: Option "Allowed Spam per User" on Advertisment Filter dialog
+ was not synced correctly
+ - Bug-Fix: OpenFile-Dialog was not shown correctly on WinNT4 (I hope it does now)
+ - Bug-Fix: Restored full support for Win95 (GetLongFileName is now run-time linked)
+ - Bug-Fix: special chars in XML logging header were sometimes not replaced correctly
+ - Bug-Fix: samll memory leak in XL logging logic
+ - Bug-Fix: Read/Sent flags got corrupted when making events as unread
+ - Fixed: Updated old part in the docs (reported by PanTzeR)
+ - Added: Note is shown in options when not all SpamDefinitions are available
+ - Improved: some other internal tweaks
+ - Extended: english teaser definitions
+ - Modified: translation strings (see SpamFilter-Translation.txt)
+ - Improved: Made it more robost against database curruption
+ - Improved: Removed 256 sized text buffer for MsgType box (possibility of buffer overrun)
+ - Improved: Internal stringlist handling on low memory conditions (string pairs)
+ - Improved: revisited log file code
+ - Bug-Fix: robot filter instruction and answer text could not be changed
+ - Added/Fixed: MBCS and surrogates support for far east (improved locale handling, too)
+ - Fixed some issues with pointer arithmetic
+ - Code robustness updates
+ - Impreoved: further increased filtering performance by caching
+ - Cleaned up SetSpammerManually code
+ - Strings modified (see SpamFilter-Translation.txt)
+ - Corrected some typos in strings
+ - Minor Bug-Fix: horizontal extent of list box was sometimes miscalculated
+ - Added: Auto-Import feature to convert old ANSI files of old Spam Filter 2.x
+ into the new UTF-8 format (needed to support Unicode properly)
+ IMPORTANT!: be sure to make a backup of any self-defined Spam Definitions.
+ - Improved: removed static variables in DlgProcs/WindowProcs
+ - Added: bad words cache to further improve performance
+ - Added: Real Unicode support (separate files: spamfilterW.dll is unicode,
+ no Win9x/ME supported on Unicode)
+ including BOM support for text files
+ - Added: LogFile write UTF-16LE BOM into txt/log files to indicate
+ correct Unicode format for Rraders as Notepad (only in Unicode mode)
+ - Improved: Spam Definitions are only validated when Advertisment Filter or
+ Disliked Messages Filter is enabled
+ - Added some documenation about Regular Expressions (RegExp),
+ how to use them and a code table (quick guide for beginners)
+ (accessable via a button on the add to list dialog)
+ More info: http://perldoc.perl.org/perlrequick.html
+ - Added: Now shows a error message when the reply messages can't be sent
+ (due to network errors etc.)
+ - Added: Support for Custom Folder Plugin
+ - new service: write log file
+ - new service: send_automated_contact_message (including rec, error output)
+ - new service: show generic error_message (out of memory?, message not sent)
+ - Added: now uses Miranda's simple memory problems catcher
+ - Updated: PluginInfo of Plugins options
+ - got rid of AgressiveOptimize.h:
+ (reason: http://forums.miranda-im.org/showthread.php?t=4863)
+ does not work on DEP systems (= data execution prevention).
+ As for optimizing. Use /O1 (optimize for size), disable global optimizing and disable the
+ "optimize for Windows 98" feature of the linker (/opt:nowin98).
+ This can considerably bloat the resulting DLL/EXE for (a small) performance gain on Win 9x,
+ but does nothing on NT based systems.
+ - support new variable in Variables Plugin: %number_of_auto_ignore_users%
+ - Repackaged: in default zip is only english spam language
+ - Added: Trigger Plugin support
+ - Added: Support for extra icon on contact list (indicating spammer)
+ - Added: Spammers list manager
+ - Added: Auto-Import of old spammers of v2.0.1.0
+
+
+ 2.1.0.0 - Added: pending auth requests are automatically denied if contact is ignored
+ - Added: preparation for taken YouWereAdded events into spam detection
+ - Added: Support for OSD Plugins beside Popup Plugin support (requested by Schommel)
+ - Bug-Fix: Configure dialogs were not closed properly when created not as modal
+ - Bug-Fix: memory leak in the string lists, the stringlist main object was never freed
+ - Bug-Fix: stringlist converting to string did not work correctly (not zero terminated)
+ - Bug-Fix: internal stringlists are now thread safe (using CriticalSections)
+ - Bug-Fix: pcre.dll is now copied/installed correctly (path was wrong formated)
+ - Bug-Fix: Regular Expressions were not compiled correctly
+ -> Regular Expressions should now really work in default installation :-)
+ - Bug-Fix: possible crash in recv chain filtering
+ -> empty contact was deleted before ICQ could have the chance to add its message
+ (bug only occured when "delete spam messages" was enabled)
+ - Bug-Fix: contact that were set on the spammer list were never really hidden
+ -> ICQ did always reset the Hidden attribute; this is now fixed
+ - Bug-Fix: small memory leak in AutoIgnore settings loading
+ - Bug-Fix: Now question message will not be sent when spammer just reached it spam limit
+ - Bug-Fix: reply messages are ordered correctly in db/history
+ - Bug-Fix: No longer sending "YouWereAdded" notification when a spammer is added to ignore list
+ (reported by PanTzeR)
+ -> ICQ sent a confirmation automatically when a user was made permanent; now this is prevented
+ - Bug-Fix: Spam Log did not always mention "user ignored" (log written too early)
+ - Bug-Fix: contacts event was never filtered
+ - Bug-Fix: tiny problem with hContact of auth requests
+ - Bug-Fix: Corrected some hidden Access Violations in MessageTypes box
+ - Bug-Fix: "Disliked Messages Filter" now really works (reported by zk, Tomaso, PanTzeR)
+ * message text never got allocated
+ * did not work for contacts that passed the robot filter previously
+ * some wrong setting names were used
+ * hoax texs were checked wrongly
+ * hoax texts were not loaded (corrected file ext: .sfw -> .sft)
+ >> Ouch....quite crappy thing...did I really code that? :-o
+ Anyway...now it's finally fixed :-D
+ - Bug-Fix: Filter strings of Log-Browse dialog were not allocated correctly
+ (stringlist access violation)
+ - Bug-Fix: AddToHistory option of DislikedMessagesFilter did not get disabled
+ when other options got disabled
+ - Bug-Fix: If "Add the reply to contact history" was selected, the history showed the reply
+ before the spam message (reported by Tomaso)
+ - Bug-Fix: "Show log" button did never get activated (broken in v2.0.1.0)
+ - Bug-Fix: relative paths for spam log were broken
+ - Bug-Fix: some minor UI improvements
+ - Bug-Fix: memory leak in the DislikedMessages options (bold font was not destroyed)
+ - Bug-Fix: when a filter window was opened using the SF-API without parent then the window
+ would not be destroyed on exit of Miranda (extended/modified SF-API)
+ - Bug-Fix: added some NULL checking where I forgot it
+ - Bug-Fix: added checking for correct db setting type
+ - Bug-Fix: "Apply" button was sometimes enabled although no options
+ were changed for message types
+ - Improved: now the robot filter only workd for normal sending and receiving contacts
+ - Improved: stringlist loading speed (just a bit)
+ - Improved: spam detection speed when "show popup" is disabled (just a bit)
+ - Fixed/Improved: some small internal tweaks and resource cleanup
+ - Fixed: now uses UniqueID instead when renaming a contact to set it on the spammers list
+ -> this fixes: spammers added as "'Unknown Contact' (Spammer)" (reported by PanTzeR)
+ - Modified: "Random" button in robot filter options now creates always the same length
+ - Improved: SPAMCHECKDATA strcuture to be more cleanly implemented
+ => Code is now fully tested on different situations
+ => Code was additionally fully checked for memory leaks and/or memory access violations
+
+ 2.0.2.0 - FEATURE!: Support for Regular Expressions (using pcre.dll; included)
+ -> Support for Regular Expressions is disabled when the DLL (pcre.dll) is not present
+ -> Word filter is now much, much, much more powerful!
+ - Added: RegExp DLL (pcre.dll) is installed automatically on first run (In Miranda directory)
+ -> including DLL version checking
+ - Added: some little more documentation about the Spam Definitions (readme and in the files)
+ - Added: now the UniqueID of a protocol is appended to the nickname in the spam log
+ (reported by Lastwebpage)
+ - Added: support for Updater to update the SpamFilter plugin
+ - Bug-Fix: Making use of EnterCriticalSection to gain thread safety
+ - Bug-Fix: avoiding of some string buffer overruns in some rare situations (if ever)
+ - Bug-Fix: Message Types box gets sorted properly
+ - Bug-Fix: popups did not work (broken in 2.0.1.0)
+ - Bug-Fix: menu item icon was not updated when icons were changed (IcoLib support)
+ - Bug-Fix: fixed some memory leaks of contact name strings
+ - Extended: Documentation of Spam Definitions and how they work
+ - Fixed: corrected some strings (see SpamFilter-Translation.txt)
+ - Fixed: corrected wrong naming of teaser text files (.sfw -> .sft)
+ - Fixed: known spammer file now allows proto|uniqueid and proto|nick (if available)
+ - Modified: few changes in the strings (see SpamFilter-Translation.txt)
+
+ 2.0.1.0 - Bug-Fix: "Allowed spam per User" could not be changed (reported by ATom)
+ - Bug-Fix: problems with RTL support (:text)
+ -> I thought RTL support would only work on Arabic/Hebrew versions of windows, so I enabled it..
+ In fact it works on most Win2000/XP versions as I found out
+ (not really good documented :-/... they only speak of "RTL enabled windows versions")
+ - Bug-Fix: minor memory leak with the message type icons
+ - Bug-Fix: layout confusion with Spam Logging group (reported by Romx)
+ - Bug-Fix: auth requests were not handled correctly when setting a spammer manually
+ - Bug-Fix: "Allowed bad phrases until spam" was ignored (ATom)
+ -> caused just by a small typo in the code :-/
+ - Bug-Fix: line breaks and spaces were not cleared correctly in
+ incoming messages (silly typo in code :-/)
+ -> this fixes the following:
+ * normal words as security code were not recognized as right answers
+ (reported by Steffen Kaufmann)
+ * sometimes the reply for a good answer was not sent (reported by ATom)
+ - Bug-Fix: using mir_snprintf to avoid string buffer overruns
+ - Bug-Fix: first message from NotOnList user was from "(Unknown contact)"
+ - Bug-Fix: PreSpammers were not unique, now they are saved as "Proto|Address"
+ - Modified: Removed SFFreeMemory, replaced with miranda_sys_free (m_spamfilter.h)
+ - Modified: pszSection in MESSAGETYPEDESC can now really be NULL (m_spamfilter.h updated)
+ - Modified: AutoIgnore feature now uses real unique user ID
+ - Added: IcoLib support
+ - Added: Support for "ColourPicker" to choose Colors of Popups
+ - Added: Support for Netlib logging (Netlib_Logf) -> spam filter actions on messages are now listed
+ in the network activity log
+ - Added: ability to reset the AutoIgnore feature
+ - Improved: Better looking "Mark as spammer" dialog
+ - Improved: minor performance improvements, code cleaning, DB settings cleaned up.
+ - Changed: services for message types (no backward compatibility to 2.0.0.0, sorry
+ -> devs, please update "m_spamfilter.h")
+ -> detecting default settings for checked protocols/events is now possible (might be useful for IRC?)
+ - Added: New event for protocols to determine if they want to be checked for spam by default:
+ ME_SPAMFILTER_PREADDNEWMESSAGETYPE
+ - Modified: Functionality of MS_SPAMFILTER_SETSPAMMANUALLY and
+ MS_SPAMFILTER_GETHANDLE ("m_spamfilter.h")
+ - Fixed: phone number default definitions (all large numbers were detected as phnone codes)
+ - Fixed/Extended: translation strings (Translattor see "SpamFilter-Translation.txt")
+ => all known bugs should now be fixed :-)
+
+ 2.0.0.0 - Almost all got changed/fixed/improved/extended/... :-)
+ - Added support for logging in XML format (including XSL stylesheet)
+ -> Very clean XML format used
+ -> Characters replaced: < with &lt; , > with &gt; , & with &amp; , " with &quot; , ' with &apos;
+ - Fixed: Layout mistake on options page
+ - Added: Recognition of CAPITALIZED messages (thanks to InvisiBill)
+ - Some other small changes and cleaned up code
+ - Added possibility to change spammers (on ignore list)
+ - Added extra buttons for "filter settings"
+ - Added error handling for log file edit box and removed read only flag
+ - Fixed: "Select log file" dialog was shown sometimes on re-activating filter
+ - Removed unnecessary error message ("Please select bad phrase to delete")
+ - Added (better) error handling for "Allowed bad phrases" box
+ - Improved/Changed German translation completely
+ - Added more Russian bad phrases
+ -> Many thanks to ZaNuDa
+ - Added new section "Filtering Tips" to readme file
+ - Added recognition support for phone numbers (Idea by ZaNuDa)
+ - Spam Filter now behaves as a filter protocol
+ -> This makes the filter more faster than before
+ - Moved together the filter behaviour "delete message" and "delete contact"
+ -> The contact now gets automatically deleted if it has no other messages in history
+ - Fixed: Apply button got always enabled when options were loaded
+ - Now uses better/newer LoadImage function instead of LoadIcon function to save memory
+ -> Icons now get unloaded to save memory
+ - Added Spam Definitions instead of using a langpack string
+ - Bold heading for groups in "Configure..." options, too
+ - Added automatic adjustment of "Ignore" settings
+ - Improved: Icons in spam popups are now skinned icons of Miranda IM for message and URL icon
+ (with layered spam icon on it)
+ - Improved file size
+ - Dropped "one phrase message" recognition
+ -> Was not a good indicator for spam
+ -> Did not work with languages which do not have (or use) spaces
+ - Added support for "PluginUninstaller"
+ - Added "Allowed spam messages" feature
+ - Complete new phrase list algorithms for easy phrase list
+ loading/saving and checking
+ - Changed formating of sounds (Added: "Spam Filter: " prefix)
+ - Added "empty message" detection
+ - Added "Multiple message with same content" detection (Idea by Popovn)
+ - Recognition of bad phrases that are formated differently (like "\/!@gr@")
+ and have kinds of things in them (thanks to InvisiBill)
+ - Added disliked messages filter
+ Filter out something like: "Please send this message to all of your friends" or
+ "please forward") (Idea by Johannes)
+ - Added button "Show log" to make opening the log file more easier
+ - Changed "Select log file" dialog to use the standard "Save as" dialog instead of the "Open" dialog
+ - Improved log file format
+ - Also looking for "good phrase(s)"
+ - Recognition support for phrases with s p a c e s (included in "different formated phrases" check)
+ - Added: Position of configure dialogs gets saved
+ - Added: Now also checks for auth requests
+ - Some resource improvements
+ - Added the possibility to manually avoid spam check via pressing the control key
+ when recieving a message
+ - The Spam Filter now is implemented as a proper protocol filter plugin
+ - Improved filtering speed
+ - Added: Automatic installation of docs and sound files on first run
+ - Added: Auto-Import feature for bad phrases used with v1.0.4.0
+ - Added: DatabaseEditor++ support
+ - Extended: Phrase list editing; the list boxes now support
+ horizontal scrolls if needed, drag and drop for rearranging the phrases,
+ context menu for fast editing, possibility to input long phrases, etc...
+ - Added: "Variables" plugin support
+ - Added a second default sound file
+ - Added: Log file control now makes use of the auto complete feature
+ - Added: Relative paths can be used in the log file edit control
+ - Added: Comma Separated Values format logging
+ - Added: Robot Block functionality similar to "StopSpam" plugin:
+ Further enhanced technic and cleaner implementation.
+ - Translators: There are a lot of changes in the strings ;-)
+ - Doubly recieved messages can be removed
+ For plugin developers: (Only ;-) )
+ - Updated "m_spamfilter.h" (Almost all is new)
+ - Added "m_spamfilter.inc" for Delphi developers
+
+ 1.0.4.0 - Two entries with the same words in the customized bad words list
+ are no longer possible
+ - Added Feature: Spammer name/id remembering and blocking
+ - Added Feature: Spammers who are not recognized can be added to the spammers list via right click
+ (thanks to Rudi)
+ - Added version information to DLL file
+ - Changed logging output
+ - Added txt file item on select log file dialog
+ - Improved conrolling of the options page via keyboard
+ - Improved layout of the options page
+ - Extended URL-recognition: Now recognizes also URLs with returns in between (thanks to Rudi)
+ - Extended/Improved default bad words very much (strings, too) -> now 78
+ -> Please update your language pack (if you use one)
+ - Extended German bad words (see "SpamFilter_Translation.txt")
+ - Extended Potuguese (Brazil) bad words (thanks to Paulo)
+ - Updated German and Chinese (Traditional) dialog translations
+ (thanks to Wongsen for the Chinese one)
+ - Fixed: The string "Log spam messages to file:" was displayed in
+ German (thanks to Wongsen)
+ - Fixed: Crash on selecting logging file (thanks to Genionhandy2 and Bumper1)
+ - Fixed: URL-Recognition and one word message recognition didn't work
+ currently (thanks to Wongsen and Rudi)
+ - Fixed: Small bug with the open file dialog
+ - Fixed: URLs are now completely checked and saved to log file
+ - Updated service functions for plugin developers
+ - Improved error checking of "Add bad word" dialog
+ - Improved error checking for "Select log file" dialog
+ - New/Improved icons (smaller file size, too)
+ - Improved default settings
+ - Some other small changes
+ - Updated screenshot on website
+
+ 1.0.3.1 - Changed/Improved icons for spam popups
+ - Nearly complete rewrite of the spam recognition
+ - Fixed: Log file wasn't written if selected directory didn't exist anylonger
+ - Fixed: Log file option got always unchecked (also if enabled)
+ - Fixed: Sometimes the wrong bad word got selected on inserting a
+ customized bad word
+ - Added bad words are now checked for occurence in default list
+ - Changed some strings
+ - Changed some German translation strings
+ - Updated Chinese (Traditional) strings (thanks to Wongsen)
+ - Updated Chinese (Traditional) bad words (thanks to Wongsen)
+ - Extended English default bad words (strings, too)
+ -> Please update your language pack (if you use one)
+ - Changed/Improved included sound file and new file name
+ -> Please update your sound settings (thanks to Wongsen)
+ - Extended German bad words
+ - Added "Activate/Deactivate" item in "PopUps" submenu
+ - Improved URL filtering: URLs with spaces (h t t p :) are now
+ included in the filter, too (thanks to Rudi)
+ - Some preparing for contact name/id collecting/blocking (coming in v1.0.4.0)
+ - Changed/Improved documentation and removed some mistypings
+ - Some other small/big internal changes/improvements
+ - FOR PLUGIN DEVELOPERS!: Added more service functions!
+ -> Activation service functions
+ -> General spam checking service (with hContact)
+ (For details see "m_spamfilter.h")
+
+ 1.0.3.0 - Improved error checking for "allowed bad words" control
+ - Fixed: Customized bad words sometimes got messed up due to wrong
+ pointers (thanks to Lúcio and Wongsen)
+ - Fixed: Customized bad words now get correctly allocated
+ and released
+ - Fixed: Default settings did not now fit for all languages
+ (thanks to Wongsen)
+ - Improved performance and bad words count loader
+ - Improved spam filter
+ - Merged "Is URL" and "Contains URL" part
+ - Improved log file output
+ - Extended default bad words (Updated strings, too)
+ - Added Chinese (Traditional) bad words (thanks to Wongsen)
+ - Changed some English strings (Updated strings, too)
+ - Changed some German translation strings
+ - Added Chinese (Traditional) dialog strings (thanks to Wongsen)
+ - Improved/Changed documentation
+ - NEW FOR DEVELOPERS: Added service function for bad words
+ checking in other plugins (For details see "m_spamfilter.h")
+ - Some other small changes
+ - Updated screenshot on website
+
+ 1.0.2.4 - Fixed: Non-spamming contacts sometimes got hidden while sending
+ messages to them (thanks to Javier and Tomaso)
+ - Changed some strings in German translation
+
+ 1.0.2.3 - Fixed: Button "Cancel" in "Add bad word" dialog showed always the
+ German variant "Abbrechen" (thanks to Jef)
+ - Fixed: Database values now get freed (Oups, I forgot that...)
+ - Fixed: Auto-Deleting message and auto-deleting contact now works
+ without outputing empty message dialogs! (Nobody noticed?)
+ - Changed "Add bad word" dialog for people who don't read documentation
+ files ;-)
+ - Changed some translation strings
+ - Improved filter performance
+ - Small changes in translation documentation
+
+ 1.0.2.2 - Improved: Smaller file size (improved compiler settings)
+ - Changed documentation files
+ - Reprogrammed error checking for "Add bad word" dialog
+ - Reprogrammed key support for customized bad words list box
+ (Now uses subclass procedure)
+ - Extended recognized keys in list box:
+ Now supports "del", "-", "+", up and down keys
+ - Changed Portuguese (Brazil) bad words (thanks to Lúcio)
+ - Improved dates/times in logging:
+ -> Now uses system (language) default format for formatting dates/times
+ -> Removed translation strings for this
+ - Fixed: Corrected small checking bug with "Allowed bad words until spam"
+ (thanks to Lúcio)
+ - Fixed: Options items are now correctly grouped
+ - Fixed: Spam logging didn't work without Path plugin
+ - Some internal improvements/performance optimizations
+ - Some changes with the German translation
+ - Improved spam logging output: more detailed and cleaned up
+ - Optimized/Faster spam logging
+ - Improved/Changed documentation
+ - Some other small/minor changes
+
+ 1.0.2.1 - Improved behaviour of "Allowed bad words in messages" spin control
+ - Changed dialog font to same as in Miranda IM core
+ - Added expert options support for logging options
+ - Changed Path Plugin dependency (Path plugin is now optional)
+ -> You do not need to have the Path plugin for logging any longer
+ -> It is only needed if you would like to use relative paths
+ - Included a fix for an issue with the Path plugin
+ (kind of bug in Path plugin)
+ - Changed option group headings to bold (finally found out how to
+ switch this... ;-) )
+ - Removed positioning of options group
+ - Cleaned up/Improved resources
+ - Added button for "Select log file" dialog
+ - Changed log file box
+ - Improved spam logging: Now messages are now longer saved as only
+ lower case
+ - Added error checking for add bad word dialog
+ - Fixed: Some error box strings were not translatable
+ - Fixed: Selection of "What to do" got sometimes not set
+ - Changed the path to default sound file to the included sound file
+ - Forgot to switch the version number shown on plugins page (Oups...)
+ - Improved German translation
+ - Some other small changes
+ - Updated screenshot on website
+
+ 1.0.2.0 - Added spam message/sender logging to file (fully translatable)
+ - Added some language pack string for spam logging
+ - Added Portuguese (Brazil) bad words (thanks to Lúcio)
+ - Improved comma recognition in default bad words list in language pack
+ - Added "del" key support in customized bad words box
+ - Small changes in German translation
+ - Added some default bad words (Changed strings, too)
+ - Use of new header files
+ - Updated screenshot on website
+
+ 1.0.1.0 - Added spamming contacts handling
+ - Improved option page layout
+ - Moved translation strings out of "SpamFilter_Developers.txt" to
+ separate file
+ - Added some default bad words (Changed strings, too)
+ - Added French bad words (thanks to Poischack)
+ - Added Russian bad words (thanks to NeptunE)
+ - "SpamFilter" speaks German!
+ (Completed German standard translation in "SpamFilter_Translation.txt")
+ - Rearranged and optimized code
+ - Some other small changes
+ - Updated screenshot on website
+
+ 1.0.0.2 - Changed selection style of customized bad words box
+ - Fixed: I forgot to mark some strings translatable...
+ - Changed some texts (Changed strings, too)
+ - Better position for "Add Bad Word" dialog
+ - Customized bad words list gets now sorted
+ - Added "Fast delete": Improved and faster deleting of customized
+ bad words in list
+ - Improved adding of customized bad words (small change)
+ - Added sound file
+ - Cleaned up code a bit
+ - Some other minor changes
+
+ 1.0.0.1 - Removed some debug output messages (Oups...)
+ - Extended default bad words
+ - Fixed: Customized bad words list doubled itself every time it
+ got loaded
+ - Smaller file size
+ - Some other tiny changes
+
+ 1.0.0.0 - Initial release
+
+
+Thanks
+----------------------
+ * To Roland Rabien the author of "SpamBlock" for the
+ first idea of spam recognition by bad words
+
+ * To Daniel Walter who improved "SpamBlock" to "SpamBlock+"
+ for the idea of an extensible bad words list
+
+ * To romamik the author of "StopSpam" for the
+ idea to block robots via reply messages
+
+ * To Lúcio for the Portuguese (Brazil) bad words
+ and his much feedback ;-)
+
+ * To Wongsen for the Chinese (Traditional) bad words and dialog translation,
+ his much feedback, his idea for an sound file and his helpful "beta testing" ;-)
+
+ * To NeptunE for the Russian bad words
+
+ * To Poischack for the French bad words
+
+ * To Paulo for some more Portuguese (Brazil) bad words
+
+ * To cyesto for creating a great bug-fix for the crash-on-ignore issue
+ in version 2.1.0.0. Thanks a lot!
+
+ * To Rudi for his many reported spam messages
+
+ * To Javier, Jef, Lúcio, Tomaso, Wongsen, Rudi, Genionhandy2, Bumper1,
+ ATom, Lastwebpage, Steffen Kaufmann, Romx, zk, Sarcago, sh8an, PanTzeR,
+ DaSilva, TioDuke, kurd, gerk, Vosoni, Avalanche, adderek, Schommel,
+ PsychodelEKS, Petr and pro100_tak for their bug reports
+
+ * To Johannes, Pickle Pete, Popovn, PanTzeR for their improvement ideas
+
+ * To Genionhandy2 for advertising this plugin ;-)
+
+ * To InvisiBill for his much feedback and his improvement ideas
+
+ * To Tigerix for his massive feature suggestions and bug-reporting :-)
+
+ * To ZaNuDa for some more Russian bad words and the filtering tips
+ and especially for his much effort in beta testing version 2.0.0.0.
+
+
+Translation
+----------------------
+ Translation strings and available bad words strings can be found
+ in "SpamFilter-Translation.txt" of the SDK package.
+
+
+License and Copyright
+----------------------
+
+ "Spam Filter" is released under the terms of the GNU General Public License.
+ See "SpamFilter-License.txt" for more details.
+
+ "Spam Filter" is copyright (c) 2003-2006 by Heiko Herkenrath.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. 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.
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ RegExp Library:
+ PCRE (pcre.dll) is a library of functions to support regular expressions whose syntax
+ and semantics are as close as possible to those of the Perl 5 language.
+
+ "Perl Compatible Regular Expressions" (PCRE) is distributed under the terms of
+ the "BSD" license. See "PCRE-License.txt" for more details.
+
+ "PCRE" is copyright (c) 1997-2004 University of Cambridge
+
+
H. Herkenrath (hrathh at users.sourceforge.net) \ No newline at end of file
diff --git a/Docs/SpamFilter-Translation.txt b/Docs/SpamFilter-Translation.txt
index b9a1e1c..569e481 100644
--- a/Docs/SpamFilter-Translation.txt
+++ b/Docs/SpamFilter-Translation.txt
@@ -1,865 +1,865 @@
-
-Spam Filter 2.5.2.3 for Miranda IM 0.4.3+
-------------------------------------------------------------------------
- Translator Information
-
- Contents: -------------------------------
- | General Info, Default Bad Phrases/Patterns, German Strings,
- | Chinese (Traditional) Strings, String History
-
-
-General Info
------------------------------
- "Spam Filter" can be translated with the Miranda IM
- language files.
-
- Put the following strings in a file called "langpack_<language>.txt"
- in the Miranda IM directory and translate them into your
- language or take the German ones... ;-)
-
- If you need more info on Miranda IM language files visit:
- http://cvs.sourceforge.net/viewcvs.py/*checkout*/miranda/miranda/i18n/readme.txt
-
-
-Default Bad Phrases/Patterns
------------------------------
- If you think a string has to be added to the translated bad phrases
- please mail me.
-
- If you notice some bad phrases that are
- missing in the lists, please mail them to me. this would be very nice.
- And..ehm...If it is another language than German, English or French
- then a translation would be nice, so that I can look if all bad phrases
- are usable and perhaps I can take some over into the english ones...
-
- More bad phrase languages will (hopefully) come soon... please help me :-)
-
-
-German Strings
------------------------------
-
-; --- Plugin: Spam Filter 2.5.2.3 (German) ---
-
-; Translation by H. Herkenrath (hrathh at users.sourceforge.net)
-; Please report any mistakes or missing strings in here.
-
-[Spam Filter]
-Spam-Filter
-[Filters out advertisment messages, messages sent by robots and other disliked messages such as hoax messages.]
-Dieses Plugin filtert Werbe-Nachrichten, automatisch versandte Nachrichten und unerwünschte Nachrichten, wie Kettennachrichten, heraus.
-
-; Message Types (same as "Options->Contact List->Icons")
-[Authorization Request]
-Erlaubnisanfrage
-[Added Notification]
-Hinzufügungsmeldung
-[Message]
-Nachricht
-[URL]
-URL-Adresse
-[File]
-Dateiübertragung
-[Contacts]
-Kontakte
-
-; Menu Items
-[Enable &spam popups]
-&Spam-Meldungen aktivieren
-[Disable &spam popups]
-&Spam-Meldungen deaktivieren
-[&Unmark spammer]
-&Kein Spam-Versender
-[&Mark as spammer]
-&Als Spam-Versender markieren...
-[Mark Contact as Spammer]
-Kontakt als Spam-Versender markieren
-[Are you sure that the contact \"%s\" shall be marked as spammer?\r\n\r\nMarking a contact as spammer means that all associated messages will be recognized as spam and the contact will be completely ignored in the future.\r\n\r\nA contact that was marked as spammer can be restored using the options dialog.]
-Soll der Kontakt \"%s\" wirklich als Spam-Versender markiert werden?\r\n\r\nEinen Kontakt als Spam-Versender markieren bedeutet, dass alle seine bisherigen Nachrichten als Spam erkannt werden und der Kontakt für die Zukunft komplett ignoriert wird.\r\nSpam-Versender können in den Einstellungen wieder reaktiviert werden.
-
-; Popups
-[Disliked Message Alert!]
-Unerwünschte Nachricht-Alarm!
-[Advertisment Alert!]
-Werbung-Alarm!
-[Robot Alert!]
-Automatische Nachricht-Alarm!
-
-; Balloon Tips
-[Spam Filter Error]
-Spam-Filter Fehler
-[Spam Filter Error"), TranslateT("The log file \"%s\"\r\ncan not be written.\r\n\r\nProblem:\r\n%s\r\nPlease check the settings.]
-Die Protokollierdatei\r\n\"%s\" kann nicht geschrieben werden.\r\n\r\nProblem:%s\r\nBitte überprüfen Sie die Einstellungen.
-[You did not install any Spam Definition files! Spam Filter can not work as powerful as it could.\r\n\r\nPlease install at least one language of the Spam Definitions.]
-Es wurden keine Spam-Definitionen installiert! Der Spam-Filter kann nicht so ausgeprägt funktionieren, wie er könnte.\r\n\r\nBitte installieren Sie mindestens eine Sprache der Spam-Definitionen.
-[Spam Filter Critical Error]
-Kritischer Fehler im Spam-Filter
-[A very critical internal error was detected!\r\nProbably the filter will not work at all.\r\n\r\nPlease update to the most current version if this problem persists.]
-Ein sehr schwerwiegender interner Fehler wurde festgestellt!\r\nWahrscheinlich wird der Filter überhaupt nicht funktionieren.\r\n\r\nWenn das Problem fortbesteht bitte auf eine neuere Version aktualisieren.
-[Spam Filter was not able to send an automated message to the user \"%s\".]
-[Spam Filter Warning]
-Spam-Filter Warnung
-[The filter has detected %u incorrect Regular Expression(s) in the default bad words!\r\n\r\nPlease update your installed Spam Definitions to the latest versions to resolve this problem.\r\nThis problem might also be caused by Spam Definitions that are not compatible with your system codepage.]
-In den Standard-Spam-Wörtern wurde ein inkorrekter Regulärer Ausdruck gefunden (%u Stück)!.\r\n\r\nDie Spam-Definitionen müssen auf die neustenn Versionen aktualisiert werden um dieses Problemn zu beheben.\r\nEs kann auch sein, dass Spam-Definitionen installiert sind, die nicht kompatibel mit der verwendeten Windows-Codepage sind.
-
-; Sounds
-;[Spam]
-[Advertisment Alert]
-Werbung eingegangen
-[Disliked Message Alert]
-Unerwünschte Nachicht eingegangen
-[Robot Alert]
-Automatische Nachricht eingegangen
-
-; Icons
-[Spam Message Overlay]
-Spam-Nachricht Indikator
-;[Mark Contact as Spammer]
-[Spammer Indicator]
-Spam-Versender
-
-; Variables Plugin
-; %autoignore_count%
-[Number of users currently being in danger of being ignored.]
-Anzahl der Benutzer die gefährdet sind automatisch ignoriert zu werden.
-
-; Trigger Plugin
-[Spam Filter: Incoming Spam]
-Spam-Filter: Eingehende Spam-Nachricht
-
-; Custom Folders Plugin
-[Spam Definitions]
-Spam-Definitionen
-[Customized Words]
-Selbstdefinierte Wörter
-
-; Logging
-[Contact set as spammer]
-Kontakt ist Spam-Versender
-[Contains only spaces]
-Enthält keinen Text
-[Is multiple]
-Ist mehrfach empfangene Nachricht
-[Is capitalized]
-Enthält nur große Buchstaben
-[Contains URL address]
-Enthält URL-Adresse
-[Contains phone number]
-Enthält Telefonnummer
-[Is teaser]
-Ist Locknachricht
-[User is known as spammer]
-Benutzer ist als Spam-Versender bekannt
-[Robot message]
-Automatisch versendete Nachricht
-[Contains %u bad phrase(s)/pattern(s)]
-Enthält %u Spam-Worte
-[Contains %u differently formated bad phrase(s)/pattern(s)]
-Enthält %u abweichend formatierte Spam-Wörter
-[Contains %u good phrase(s)/pattern(s)]
-Enthält %u positive Wörter
-[Is hoax text]
-Ist Kettennachricht
-[Contains %u disliked indicating phrase(s)/pattern(s)]
-Enthält %u unerwünschte Wortkombinationen
-; Separator:
-;[, ]
-[Message deleted]
-Nachricht gelöscht
-[Message marked read]
-Nachricht als gelesen markiert
-[User ignored]
-Benutzer ignoriert
-; %log_user% format: Nick (UniqueID)
-;[%s (%s)]
-
-; Logging: Plain Text Format
-[[%log_date% %log_time%, User: %log_user%, Type: %log_type%]\r\nRecognition: %log_recognition%\t\r\nResult: %log_result%\r\n%log_message%\r\n\r\n]
-[%log_date% %log_time%, Benutzer: %log_user%, Typ: %log_type%]\r\nErkennung: %log_recognition%\t\r\nErgebnis: %log_result%\r\n%log_message%\r\n\r\n]
-
-; Logging: CSV Format
-;[\"%log_date%\";\"%log_time%\";\"%log_user%\";\"%log_type%\";\"%log_recognition%\";\"%log_result%\";\"%log_message%\"\r\n]
-["Date";"Time";"User";"Type";"Recognition";"Result";"Message"\r\n]
-"Datum";"Uhrzeit";"Benutzer";"Typ";"Erkennung";"Ergebnis";"Nachricht"\r\n
-
-; Logging: XML Format
-[Received Spam]
-Empfangene Spam-Nachrichten
-[Logged since]
-Protokolliert seit
-[Date/Time:]
-Datum/Uhrzeit:
-[User:]
-Benutzer:
-[Type:]
-Typ:
-[Recognition:]
-Erkennung:
-[Result:]
-Ergebnis:
-
-
-; Options: Main
-[&Advertisment Filter (recommended)]
-&Werbung-Filter (empfohlen)
-[Filters out advertisments from unknown users that are not on the contact list.]
-Filtert Werbe-Nachrichten von Benutzern, die nicht in der Kontaktliste aufgeführt sind, heraus.
-[C&onfigure...]
-K&onfigurieren...
-[&Robot Filter]
-&Automatische Nachrichten-Filter
-[Filters out all automated messages from unknown contacts via requesting a correct answer from the sender.]
-Filtert alle automatisch versandten Nachrichten heraus, durch Anforderung einer korrekten Antwort von unbekannten Versendern.
-[Co&nfigure...]
-Ko&nfigurieren...
-[&Disliked Messages Filter]
-&Unerwünschte Nachrichten-Filter
-[Filters out disliked messages such as hoax messages from known contacts that are on your contact list.]
-Filtert unerwünschte Nachrichten, wie Kettennachrichten, von Kontakten, die in der Kontaktliste aufgeführt sind, heraus.
-[Con&figure...]
-Kon&figurieren...
-[Behaviour]
-Filterverhalten
-[Mar&k spam messages as read]
-Spam als &gelesen markieren
-[D&elete spam messages]
-Spam-Nachrichten &löschen
-[Auto Ignore]
-Automatisch Ignorieren
-[Automatically &ignore spamming users]
-Spam-Versender automatisch &ignorieren
-[Allowed spam per &user:]
-&Erlaubte Spam-Nachrichten:
-[&Rese&t...]
-Zurückse&tzen...
-[Spa&mmers]
-Spa&m-Versender
-[Reset Auto Ignore]
-Automatisches Ignorieren zurücksetzen
-[Are you sure that the Auto Ignore counters shall really be reset?\r\n\r\nSpammers that are not already ignored will then not be remembered any longer.]
-Sollen die Zähler für das Automatische Ignorieren wirklich zurückgesetzt werden?\r\nSpam-Versender die noch nicht ignoriert sind werden dann nicht mehr vorgemerkt sein.
-[Message Types]
-Nachrichtentypen
-[Types of incoming e&vents which shall be checked for spam:]
-Eingehende Nachrichtent&ypen die überprüft werden sollen:
-[Spam Notification]
-Meldungen
-[Show &popup when a spam message is received]
-&Popup-Fenster anzeigen, wenn eine Spam-Nachricht eingeht
-[&Log spam messages to file:]
-Spam in Datei &speichern:
-; Default Log file name:
-;[Spam.xml]
-;[&...]
-[&Show]
-&Anzeigen
-
-; Options: Spammers Info
-[Ignored Spammers]
-Ignorierte Spam-Versender
-[The following contacts were recognized as spammers:]
-Die folgenden Kontakte wurde als Spam-Versender erkannt:
-[Spammer]
-Spam-Versender
-[Accept]
-Akzeptieren
-[Delete]
-Löschen
-[Store spammers in special &group:]
-Spam-Versender in folgender &Gruppe aufbewahren:
-[Spammers]
-Spam-Versender
-
-; Options: Advertisment Filter
-[Configure Advertisment Filter]
-Werbung-Filter konfigurieren
-[Bad Phrases/Patterns]
-Spam-Wortkombinationen
-[Look for standard &bad phrases in received messages]
-Auf &Standard Spam-Wörter in empfangenen Nachrichten prüfen
-[Also watch for following &customized bad phrases:]
-Auch nach &folgenden Spam-Wörtern suchen:
-[Automated message]
-Automatisch generierte Nachricht
-[All&owed bad phrases until spam:]
-Erlaubte &Anzahl an Spam-Wörtern:
-[Recogni&ze different formating]
-Abweichende &Formatierung erkennen
-[Allowed &formated bad phrases:]
-Erlaubte formatierte &Wörter:
-[Known Spammers]
-Spam-Versender
-[Filter out messages from standard &known spammers]
-Nachrichten von standardmäßigen Spam-Versendern herausfiltern
-[Bad Contents]
-Spam-Inhalte
-[&URL addresses]
-&URL-Adressen
-[&Phone numbers]
-&Telefonnummern
-[C&apitalized messages]
-&Großgeschriebene Nachrichten
-[Messages containing &spaces only]
-&Leere Nachrichten
-[&Multiple messages with same content]
-&Mehrere Nachrichten mit gleichem Inhalt
-[&Teaser messages]
-&Locknachrichten
-[Good Phrases/Patterns]
-Positive Wortkombinationen
-[Messages are &no spam when containing some of the following phrases:]
-Nachrichten &nicht als Spam ansehen, wenn folgende Wörter enthalten sind:
-;[Miranda IM]
-[Allo&wed phrases until no spam:]
-Erlaubte positive Wörter:
-
-; Options: Robot Filter
-[Configure Robot Filter]
-Filter für automatich versendete Nachrichten konfigurieren
-[Message Texts]
-Nachrichtentexte
-[&Instruction:]
-&Anleitung:
-[Hello %sender%,\r\nPlease reply \"%securitycode%\" if you want to contact me. If you don't reply correctly your messages will be ignored. Sorry for the inconvenience.\r\nThis spam check quarantees that you are a real person.\r\nYou have %triesleft% tries left.\r\nThanks in advance!\r\n\r\n(Automated message)]
-Hallo %sender%,\r\nBitte antworte mit \"%securitycode%\", um mit mit mir in Kontakt zu treten. Alle anderen Nachrichten werden zunächst ignoriert.\r\nEs verbleiben noch %triesleft% Versuche.\r\nDanke im Voraus!\r\n(Automatisch generierte Nachricht)
-[&Confirmation:]
-&Bestätigung:
-[Thank you for your help!\r\nAll your previous messages were delivered. New messages do now reach me directly without an additional spam check.\r\n\r\n(Automated message)]
-Danke für die Hilfe!\r\nAlle bisherigen Nachrichten wurden zugestellt. Weitere Nachrichten unterliegen keiner erneuten Spam-Prüfung.\r\n\r\n(Automatisch generierte Nachricht)
-[(You can use the substitute symbols %sender%, %message%, %securitycode% and %triesleft% for the appropriate contents.)]
-(Die Platzhalter %sender%, %message%, %securitycode% and %triesleft% können für die jeweiligen Inhalte verwendet werden.)
-; Value of %triesleft% when auto ignore feature disabled
-[unlimited]
-unbegrenzte
-[Add the message texts to contact &history]
-Zum &Nachrichtenverlauf des Kontakts hinzufügen
-[Security Code]
-Richtige Antwort
-[The following text needs to be replied by the contact to confirm that the message was not sent automatically:]
-Der folgende Text muss vom Benutzer zurückgesendet werden um zu bestätigen, dass seine Nachricht nicht automatisch versandt wurde:
-[&Random]
-&Zufall
-; Random chars base (Note: misunderstandable chars removed)
-;[abcdefghkmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWXYZ23456789]
-[(You can use readable words, too.)]
-(Normale Wörter sind auch möglich.)
-[&Hide users until they identified themselves]
-Absender &verstecken bis sie bestätigt wurden
-[Note: This filter gets invoked after the Advertisment Filter.\r\nThus, no instruction message will be sent in reply to advertisment messages.]
-Hinweis: Dieser Filter wird nach dem Werbung-Filter angewendet,\r\nd.h. es wird nicht mit einer Anleitungsnachricht auf Werbenachrichten geantwortet.
-
-; Options: Disliked Messages Filter
-[Configure Disliked Messages Filter]
-Filter für unerwünschte Nachrichten konfigurieren
-[Disliked Contents]
-Unerwünschte Inhalte
-[Messages containing &known hoax message texts]
-Auf &bekannte Texte von Kettennachrichten prüfen
-[Indicating Phrases/Patterns]
-Wortkombinationen
-[Look for the following indicating &phrases:]
-Auf folgende &Worte prüfen:
-[Please forward]
-Bitte weiterleiten
-[Auto Reply]
-Automatische Antwort
-[Auto &reply to disliked messages using the following text:]
-Automatisch auf unerwünschte Nachrichten mit dem folgenden Text &antworten:
-[Hello %sender%,\r\nI don't like such messages. Please don't send them to me anymore.\r\nThanks.\r\n\r\n(Automated message)]
-Hallo %sender%\r\nIch kann solche Nachrichten nicht ausstehen. Bitte nicht mehr senden!\r\nDanke.\r\n\r\n(Automatisch generierte Nachricht)
-[(You can use the substitute symbols %sender% and %message% for the appropriate contents.)]
-(Die Platzhalter %sender% und %message% können für die jeweiligen Inhalte verwendet werden.)
-[Add the reply to contact &history]
-Zum &Nachrichtenverlauf hinzufügen
-
-; Options: Select Log File
-[Select Log File]
-Protokollierdatei festlegen
-[Text Files (*.txt)]
-Textdokumente (*.txt)
-[Log Files (*.log)]
-Log-Dateien (*.log)
-[Comma Separated Values Files (*.csv)]
-CSV (Trenzeichen-getrennt) (*.csv)
-[XML Files (*.xml; *.xsl)]
-XML-Dateien (*.xml; *.xsl)
-[All Logging Files (*.log; *.txt; *.csv; *.xml)]
-Alle Protokollierdateien (*.log; *.txt; *.csv; *.xml)
-[All Files (*.*)]
-Alle Dateien (*.*)
-
-; Options: Add/Remove List Item
-[&Add...]
-&Hinzufügen..
-[&Remove]
-&Entfernen
-[&New indicating phrase/pattern:]
-&Neue Wortkombination:
-[Add bad phrase/pattern]
-Spam-Wort hinzufügen
-[Remove bad phrase/pattern]
-Spam-Wort entfernen
-[The entered bad phrase \"%s\" already exists in the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the bad phrase be added anyway?]
-Das soeben eingegebene Spam-Wort \"%s\" existiert bereits in der Liste.\r\n\r\nDer Filter unterscheidet nicht zwischen Groß- und Kleinschreibung\nin den Wörtern, deshalb sind zwei Einträge mit demselben Wort nicht notwendig\nund würden die Filterqualität negativ beeinflussen.\r\n\r\nSoll das Spam-Wort dennoch hinzugefügt werden?
-[The entered bad phrase \"%s\" already exists in the default bad phrases lists.\r\n\r\nAllowing the same bad phrase in the customized bad phrases lists will\npull down the filter quality.\r\n\r\nShall the bad phrase be added anyway?]
-Das soeben eingegebene Spam-Wort \"%s\" existiert bereits in den Standard-Wörtern.\r\n\r\nEin selbsteingegebenes Spam-Wort sollte jedoch nicht in den Standard-Wörtern\nvorkommen, da dadurch die Filter-Qualität negativ beeinflusst werden könnte.\r\n\r\nSoll das Spam-Wort dennoch hinzugefügt werden?
-[Add good phrase/pattern]
-Positives Wort hinzufügen
-[Remove good phrase/pattern]
-Positives Wort entfernen
-[The entered good phrase \"%s\" already exists in the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the good phrase be added anyway?]
-Das soeben eingegebene positive Wort \"%s\" existiert bereits in der Liste.\r\n\r\nDer Filter unterscheidet nicht zwischen Groß- und Kleinschreibung\nin den Wörtern, deshalb sind zwei Einträge mit demselben Wort nicht notwendig\nund würden die Filterqualität negativ beeinflussen.\r\n\r\nSoll das positive Wort dennoch hinzugefügt werden?
-[Add indicating phrase/pattern]
-Wortkombination hinzufügen
-[Remove indicating phrase/pattern]
-Wortkombination entfernen
-[The entered indicating phrase \"%s\" already exists in the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the chain indicating phrase be added anyway?]
-Die soeben eingegebene Wortkombination \"%s\" existiert bereits in der Liste.\r\n\r\nDer Filter unterscheidet nicht zwischen Groß- und Kleinschreibung\nin den Wörtern, deshalb sind zwei Einträge mit demselben Wort nicht notwendig\nund würden die Filterqualität negativ beeinflussen.\r\n\r\nSoll die Wortkombination dennoch hinzugefügt werden?
-[(You can use normal words and Regular Expressions)]
-(Reguläre Ausdrücke und normale Wörter sind möglich)
-[(Regular Expressions disabled)]
-(Reguläre Ausdrucke sind deaktiviert)
-[Syntax Error in Regular Expression]
-Syntaxfehler in Regulärem Ausdruck (RegExp)
-[The entered phrase \"%s\" consists of a Regular Expression containing a syntax error!\r\n\r\nAdding an malformed Regular Expression will cause the filter\r\nto treat the expression as a normal phrase.\r\n\r\nShall the malformed Regular Expression be added anyway?]
-Die eingegebene Wortkombination enthält einen ungültigen Regulären Ausdruck (RegExp)!\r\nEin ungültiger Regulärer Ausruck wird vom Filter als normale Wortkombination angesehen.\r\n\r\nSoll der ungültige Reguläre Ausruck trotzdem hinzugefügt werden?
-
-; Options: Regular Expressions Help Section
-[Quick Quide to Regular Expressions:]
-Schnellanleitung für Reguläre Ausdrücke:
-[Alternatives:]
-Alternativen:
-[gilbert|sullivan finds \"gilbert\" or \"sullivan\"]
-gilbert|sullivan findet \"gilbert\" oder \"sullivan\"
-[Subpatterns]
-Unterausdrücke:
-[cat(aract|erpillar) finds "cataract\" or \"caterpillar\"]
-cat(aract|erpillar) findet "cataract\" oder \"caterpillar\"
-[Repetitions]
-Wiederholungen:
-[z{2,4} matches \"zz\", \"zzz\" or \"zzzz\"\r\n* is equivalent to {0,}\r\n+ is equivalent to {1,}\r\n? is equivalent to {0,1}]
-z{2,4} findet \"zz\", \"zzz\" oder \"zzzz\"\r\n* ist gleichbedeutend mit {0,}\r\n+ ist gleichbedeutend mit {1,}\r\n? ist gleichbedeutend mit {0,1}
-[Generic Types:]
-Allgemeine Typen:
-[\\d represents any decimal digit\r\n\\D represents any character that is not a decimal digit]
-\\d steht für irgendeine Dezimalzahl\r\n\\D steht für irgendein nicht-numerisches Zeichen
-[Assertions:]
-Zusicherungen:
-[(?<!foo)bar finds an occurrence of \"bar\" that is not preceded by \"foo\"\r\n(?<= for positive lookahead assertions\r\n(?<! for negative lookahead assertions\r\n(?= for positive lookbehind assertions\r\n(?! for negative lookbehind assertions]
-(?<!foo)bar findet ein Vorkommen von \"bar\" dem nicht \"foo\" vorangestellt ist\r\n(?<= steht für postiv vorausblickend\r\n(?<! steht für negativ vorausblickend\r\n(?= steht für positiv rückblickend\r\n(?! steht für negativ rückblickend
-[Back References:]
-Rückverweise:
-[(sens|respons)e and \\1ibility matches \"sense and sensibility\" and \"response and responsibility\", but not \"sense and responsibility\"]
-(sens|respons)e and \\1ibility findet \"sense and sensibility\" und \"response and responsibility\", jedoch nicht \"sense and responsibility\"
-[All syntax elements can be combined or nested using subpatterns.]
-Syntaxelemente können mithilfe von Unterausdrücken kombiniert werden.
-
-; Options: Spam Definitions Info Dialog
-[Spam Definitions: Advertisment Filter]
-Spam-Definitionen: Werbung-Filter
-[Advertisment Filter]
-Werbung-Filter
-[Spam Definitions: Disliked Messages Filter]
-Spam-Definitionen: Unerwünschte Nachrichten-Filter
-[Disliked Messages Filter]
-Unerwünschte Nachrichten-Filter
-[Installed Spam Definitions for filter:]
-Installierte Spam-Definitionen für den Filter:
-[Not Available]
-Nicht verfügbar
-[Packet]
-Paket
-;[Version]
-[Type]
-Typ
-[Default Bad Words]
-Standard Spam-Wörter
-[Known Spammers]
-Bekannte Spam-Versender
-[Known Teaser Texts]
-Bekannte Lock-Texte
-[URL Recognition]
-[URL-Erkennung
-[Phone Number Recognition]
-Telefonnummer-Erkennung
-[Different Format Recognition: Text]
-Format-Erkennung: Text
-[Different Format Recognition: Numbers]
-Format-Erkennung: Nummern
-[Different Format Recognition: Separators]
-Format-Erkennung: Trennzeichen
-[Known Hoax Texts]
-Bekannte Hoax-Texte
-[Download more Spam Definitions]
-Weitere Spam-Definitionen herunterladen
-;[http://addons.miranda-im.org/index.php?action=display&id=92]
-[&Remove...]
-&Entfernen...
-
-; Options: Spam Definitions Info
-[Spam &Definitions]
-Spam-&Definitionen
-[Warning: Not all Spam Definitions are available!\r\nSome features are disabled.]
-Achtung: Nicht alle Spam-Definitionen sind verfügbar!\r\nEinige Optionen sind deaktiviert.
-
-; Spam Definitions Info File Names
-; (Strings prepended by "Spam Definitions:" are used by Updater plugin)
-[Common]
-Allgemein
-[English]
-Englisch
-[Spam Definitions: English]
-Spam-Definitionen: Englisch
-[Chinese]
-Chinesisch
-[Spam Definitions: Chinese]
-Spam-Definitionen: Chinesisch
-[French]
-Französisch
-[Spam Definitions: French]
-Spam-Definitionen: Französisch
-[Portuguese]
-Portugiesisch
-[Spam Definitions: Portuguese]
-Spam-Definitionen: Portugiesisch
-[Russian]
-Russisch
-[Spam Definitions: Russian]
-Spam-Definitionen: Russisch
-
-; Options: Variables Button
-[Use variables in the message text]
-Variablen im Nachrichtentext verwenden
-
-; Options: Ignore Options Extension
-[You chose to ignore all kind of messages from contacts that are not on your contact list although the spam filter is activated.\r\n\r\nShall the spam filter be deactivated?]
-Nachrichten von Benutzern, die nicht auf der Kontaktliste sind, werden im Moment ignoriert.\r\nJedoch ist der Spam-Filter aktiviert, der unerwünschte Nachrichten von solchen Benutzern herausfiltert.\r\n\r\nSoll der Spam-Filter deaktiviert werden?
-
-; ---
-
-
-
-String History:
------------------------------
- 2.5.2.1: Added: [&Hide users until they identified themselves]
- Changed: [The filter has detected %u malformed Regular Expression(s) in the default bad words!\r\n\r\n
- Please update your installed Spam Definitions to the latest versions to resolve this problem.\r\n
- This problem might also be caused by Spam Definitions that are not compatible
- with your system codepage.]
- To: [The filter has detected %u malformed Regular Expression(s) in the default bad words!\r\n\r\n
- Please update your installed Spam Definitions to the latest versions to resolve this problem.\r\n
- This problem might also be caused by Spam Definitions that are not compatible
- with your system codepage.
- Changed: [The entered phrase \"%s\" consists of a Regular Expression which is invalid!\r\n\r\n
- Adding an invalid Regular Expression will cause the filter\r\nto treat the expression as a normal
- phrase.\r\n\r\nShall the invalid Regular Expression be added anyway?]
- To: [The entered phrase \"%s\" consists of a Regular Expression containing a syntax error!\r\n\r\n
- Adding an malformed Regular Expression will cause the filter\r\nto treat the expression as a normal
- phrase.\r\n\r\nShall the malformed Regular Expression be added anyway?]
- Changed: [(You can use the substitute symbols %sender%, %message%, %triesleft% and
- %securitycode% for the appropriate contents.)]
- To: [(You can use the substitute symbols %sender%, %message%, %securitycode% and
- %triesleft% for the appropriate contents.)]
- Changed: [Hello %sender%,\r\nPlease reply \"%securitycode%\" if you want to contact me.
- If you don't reply correctly your messages will be ignored. Sorry for the inconvenience.\r\n
- This spam check quarantees that you are a real person.\r\nYou have %triesleft% tries left.\r\n
- Thanks in advance!\r\n\r\n(Automated message)]
- To: [Hello %sender%,\r\nPlease reply \"%securitycode%\" if you want to contact me.
- If you don't reply correctly your messages will be ignored. Sorry for the inconvenience.\r\n
- This spam check guarantees that you are a real person.\r\nYou have %triesleft% tries left.\r\n
- Thanks in advance!\r\n\r\n(Automated message)]
-
- 2.5.2.0:
- Added: [unlimited]
- Changed: [Please reply \"%securitycode%\" if you want to contact me. If you don't reply correctly your
- messages will be ignored. Sorry for the inconvenience.\r\n\r\n(Automated message)]
- To: [Hello %sender%,\r\nPlease reply \"%securitycode%\" if you want to contact me.
- If you don't reply correctly your messages will be ignored. Sorry for the inconvenience.\r\n
- This spam check quarantees that you are a real person.\r\nYou have %triesleft% tries left.\r\n
- Thanks in advance!\r\n\r\n(Automated message)]
- Changed: [Hi %sender%,\r\nI don't like such messages. Please don't send them to me
- anymore.\r\nThanks.\r\n\r\n(Automated message)]
- To: [Hello %sender%,\r\nI don't like such messages. Please don't send them to me anymore.\r\n
- Thanks.\r\n\r\n(Automated message)]
- Changed: [Thank you for your help!\r\nAll your previous messages were delivered.
- New messages do now reach me directly without an additional spam check.\r\n\r\n
- (Automated message)]
- To: [Thank you for your help!\r\nAll your previous messages were delivered. New messages do reach
- me directly, without an additional spam check.\r\n\r\n(Automated message)]
- Changed: [Automatically &ignore spammers]
- To: [Automatically &ignore spamming users]
- Changed: [&Empty messages]
- To: [Messages containing &spaces only]
- Changed: [Contains spaces only]
- To: [Is empty]
- Changed: [Allowed &bad phrases until spam:]
- To: [All&owed bad phrases until spam:]
- Changed: [Recognize &different formating]
- To: [Recogni&ze different formating]
- Changed: [&Spammers]
- To: [Spa&mmers]
- Changed: [&Reset...]
- To: [Rese&t...]
- Changed: [&Mark spam messages as read]
- To: [Mar&k spam messages as read]
- Changed: [&Types of incoming events which shall be checked for spam:]
- To: [Types of incoming e&vents which shall be checked for spam:]
- Changed: [(You can use the substitute symbols %sender%, %message%and %securitycode%
- for the appropriate contents.)]
- To: [(You can use the substitute symbols %sender%, %message%, %triesleft% and %securitycode% for the appropriate contents.)]
-
- * corrected some typos
-
- 2.5.1.2:
- Added: [Store spammers in special &group:]
- Added: [Spammers]
- Added: [&Unmark spammer]
- Changed: [Normal]
- To: [Accept]
-
- 2.5.1.1:
- Changed: [Spam Filter has detected %u incorrect Regular Expression(s) in the default bad words!\r\n\r\n
- Please update your installed Spam Definitions to the latest versions to resolve this problem.]
- To: [The filter has detected %u incorrect Regular Expression(s) in the default bad words!\r\n\r\n
- Please update your installed Spam Definitions to the latest versions to resolve this problem.\r\n
- This problem might also be caused by Spam Definitions that are not compatible
- with your system codepage.]
-
- 2.5.1.0:
- Added: [Spammer Indicator]
- Changed: [Spam Filter has detected a incorrect Regular Expression in the default bad words!\r\n\r\n
- Please update your installed Spam Definitions to the latest versions to resolve this problem.]
- To: [Spam Filter has detected %u incorrect Regular Expression(s) in the default bad words!\r\n\r\n
- Please update your installed Spam Definitions to the latest versions to resolve this problem.]
-
- * Corrected some typos
-
- 2.5.0.0:
- Added: [Use variables in the message text]
- Added: [Disliked Contents]
- Added: [Number of users currently being in danger of being ignored.]
- Added: [Spam Filter Critical Error]
- Added: [A very critical internal error was detected!\r\nProbably the filter will not work at all.\r\n\r\n
- Please update to the most current version if this problem persists.]
- Added: [Spam Filter was not able to send an automated message to the user \"%s\".]
- Added: [Spam Filter Warning]
- Added: [Spam Filter has detected a incorrect Regular Expression in the default bad words!\r\n\r\n
- Please update your installed Spam Definitions to the latest versions to resolve this problem.]
- Added: [(Regular Expressions disabled)]
- Added [Spam &Definitions]
- Added: [Warning: Not all Spam Definitions are available!\r\nSome features are disabled.]
- Added: [Spam Definitions]
- Added: [Installed Spam Definitions for filter:]
- Added: [Download more Spam Definitions]
- Added: [http://www.miranda-im.org/download/index.php?action=display&id=92]
- Added: [Not available]
- Added: [Packet]
- Added: [Version]
- Added: [Type]
- Added: [Default Bad Words]
- Added: [Known Spammers]
- Added: [Known Teaser Texts]
- Added: [URL Recognition]
- Added: [Phone Number Recognition]
- Added: [Different Format Recognition: Text]
- Added: [Different Format Recognition: Numbers]
- Added: [Different Format Recognition: Separators]
- Added: [Known Hoax Texts]
- Added: [Quick Quide to Regular Expressions:]
- Added: [Alternatives:]
- Added: [gilbert|sullivan finds \"gilbert\" or \"sullivan\"]
- Added: [Subpatterns]
- Added: [cat(aract|erpillar) finds "cataract\" or \"caterpillar\"]
- Added: [Repetitions]
- Added: [z{2,4} matches \"zz\", \"zzz\" or \"zzzz\"\r\n* is equivalent to {0,}\r\n
- + is equivalent to {1,}\r\n? is equivalent to {0,1}]
- Added: [Generic Types:]
- Added: [\\d represents any decimal digit\r\n\\D represents any character that is not a decimal digit]
- Added: [Assertions:]
- Added: [(?<!foo)bar finds an occurrence of \"bar\" that is not preceded by \"foo\"\r\n
- (?<= for positive lookahead assertions\r\n(?<! for negative lookahead assertions\r\n
- (?= for positive lookbehind assertions\r\n(?! for negative lookbehind assertions]
- Added: [Back References:]
- Added: [(sens|respons)e and \\1ibility matches \"sense and sensibility\" and \"response and responsibility\",
- but not \"sense and responsibility\"]
- Added: [All syntax elements can be combined or nested using subpatterns.]
- Added: [Spam Definitions]
- Added: [Customized Words]
- Added: [Spam Filter: Incoming Spam]
- Added: [&Remove...]
- Added: [Note: The filter gets invoked after the Advertisment Filter.\n
- Thus, no instruction message will be sent in reply to advertisment messages.]
- Added: [Spammers]
- Added: [Ignored Spammers]
- Added: [The following contacts were recognized as spammers:]
- Added: [Spammer]
- Added: [Normal]
- Added: [Delete]
- Removed: [ (Spammer)]
- Removed: [Hoax Messages]
- Removed: [Contains 1 disliked indicating phrase/pattern]
- Removed: [Contains 1 bad phrase/pattern]
- Removed: [Contains 1 differently formated bad phrase/pattern]
- Removed: [Contains 1 good phrase/pattern]
- Changed: [Contains %u disliked indicating phrases/patterns]
- To: [Contains %u disliked indicating phrase(s)/pattern(s)]
- Changed: [Contains %u bad phrases/patterns]
- To: [Contains %u bad phrase(s)/pattern(s)]
- Changed: [Contains %u differently formated bad phrases/patterns]
- To: [Contains %u differently formated bad phrase(s)/pattern(s)]
- Changed: [Date;Time;User;Type;Recognition;Result;Message\r\n]
- To: ["Date";"Time";"User";"Type";"Recognition";"Result";"Message"\r\n]
- Changed: [Contains %u good phrases/patterns]
- To: [Contains %u good phrase(s)/pattern(s)]
- Changed: [The log file \"%s\"\r\ncan not be written.\r\n\r\nPlease check the settings.]
- To: [The log file \"%s\"\r\ncan not be written.\r\n\r\nProblem:\r\n%s\r\nPlease check the settings.]
- Changed: [Manually set as spam]
- To: [Contact set as spammer]
- Changed: [Look for &known hoax message texts]
- To: [Messages containing &known hoax message texts]
-
- * Corrected some typos
-
- 2.1.0.0:
- Changed: [&Scramble]
- To: [&Random]
- Added: [Added Notification]
- Added: [Is hoax text]
-
- 2.0.2.0:
- Added: [Syntax Error in Regular Expression]
- Added: [The entered phrase \"%s\" consists of a Regular Expression which is invalid!\r\n\r\n
- Adding an invalid Regular Expression will cause the filter\r\nto treat the expression as a normal
- phrase.\r\n\r\nShall the invalid Regular Expression be added anyway?]
- Added: [Robot message]
- Changed: [ (spammer)]
- To: [ (Spammer)]
-
- * Renamed most occurences of "phrase" to "phrase/pattern" (only in captions): Compare with German strings.
- * Changed all occurences of a simple "\n" to "\r\n": Compare with German strings.
-
- 2.0.1.0:
- Added: [Spam Message Overlay]
- Added: [&Reset]
- Added: [(You can use readable words, too.)]
- Added: [abcdefghkmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWXYZ23456789]
- Added: [Reset Auto Ignore]
- Added: [Are you sure that the Auto Ignore counters shall really be reset?\r\n\r\n
- Spammers that are not already ignored will then not be remembered any longer.]
- Changed: [A&llowed phrases until no spam:]
- To: [Allo&wed phrases until no spam:]
- Changed: [Allo&wed bad phrases until spam:]
- To: [Allowed &bad phrases until spam:]
- Changed: [&Mark contact as spammer]
- To: [&Mark as spammer]
- Changed: [Filters out advertisments, robot messages and disliked messages such as hoax messages..]
- To: [Filters out advertisment messages, messages sent by robots and
- other disliked messages such as hoax messages.]
- Changed: [Are you sure that the contact \"%s\" shall be marked as spammer?]
- To: [Are you sure that the contact \"%s\" shall be marked as spammer?\r\n\r\n
- Marking a contact as spammer means that all associated messages will be recognized as spam
- and the contact will be completely ignored in the future.\r\n\r\nA contact that was marked as
- spammer can be unignored using the options dialog.]
-
- 2.0.0.0:
- * The strings have been changed almost completely.
- Please compare with German strings.
-
- 1.0.4.0:
- Added: [User is known as spammer]
- Added: [The entered bad word \"%s\" already exists in the list.\r\n\r\n
- The filter doesn't differentiate between lower and upper case.\n
- Two entries with the same word are not neccessary\nand would decrease the filter quality.]
- Added: [Add contact to spammer list...]
- Added: [Spamer Remembering]
- Added: [Filter out all messages from users who once sent spam]
- Added: [Notify users that they are blocked]
- Added: [Hey %s, I don't like spam!\nYou are now put onto the spammers list to stop
- you from sending me such things.\r\n\r\nHere is your message back:\n%s\r\n\r\n\n
- (Automated message)]
- Added: [Text Files]
- Removed: [Contact kept]
-
-
- 1.0.3.1:
- Added: [The entered bad word \"%s\" already exists in the default bad words list.\r\n\r\n
- Allowing the same bad words in the customized bad words list would\n
- pull down the filter quality.\r\n\r\nShould the bad word be added anyway?]
- Added: [Enable &spam popups]
- Added: [Disable &spam popups]
- Added: [Type:]
- Changed: [Website adresses are bad]
- To: [Website addresses are bad]
- Changed: [(URL)]
- To: [URL]
- Changed: [(Message)]
- To: [Message]
-
-
- 1.0.3.0:
- Added: [(URL)]
- Added: [(Message)]
- Removed: [Is URL]
- Removed: [Spam Contacts]
- Changed: [Result:\t]
- To: [Result:]
- Changed: [Recognition:\t]
- To: [Recognition:]
- Changed: [Bad words (%u)]
- To: [Contains &u bad words]
- Changed: [Urls are bad]
- To: [Website addresses are bad]
- Changed: [Bad Messages]
- To: [Bad Contents]
- Changed: [Additionally look for standard bad words in bad messages]
- To: [Look for standard bad words in received messages]
-
- 1.0.2.3:
- Added: [If you have any bad words that could be added to the default list please mail them to me.\n
- So that the filter can be further improved. This would be very nice.]
- Added: [User:]
- Added: [Result:\t]
- Changed: [Recognition:]
- To: [Recognition:\t]
-
- 1.0.2.2:
- Added: [Recognition:]
- Added: [Contains only one word]
- Added: [Contains URL]
- Added: [Is URL]
- Added: [Bad words (%u)]
- Added: [Message deleted]
- Added: [Message marked read]
- Added: [Contact deleted]
- Added: [Contact kept]
- Removed: [(Found Bad Words: %u)]
- Removed: [HH:mm]
- Removed: [dd/MM/yyyy]
-
- 1.0.2.1:
- Added: [Select Log File]
- Added: [Log Files]
- Added: [All Files]
- Changed: [Logs\\Spam.log]
- To: [Spam.log]
-
- 1.0.2.0:
- Added: [Spam Logging]
- Added: [Log spam messages to file:]
- Added: [Logs\\Spam.log]
- Added: [HH:mm]
- Added: [dd/MM/yyyy]
- Added: [(Found Bad Words: %u)]
-
- 1.0.1.0:
- Added: [No spam filter]
- Added: [Filter out spam messages from users that are not on the contact list (recommended)]
- Added: [Spam Contacts]
- Added: [Delete spamming contacts]
- Removed: [Activate spam checking for users that are not on the contact list]
-
- 1.0.0.1:
- Changed: [Number of words until spam:]
- To: [Allowed bad words until spam:]
-
-
+
+Spam Filter 2.5.2.3 for Miranda IM 0.4.3+
+------------------------------------------------------------------------
+ Translator Information
+
+ Contents: -------------------------------
+ | General Info, Default Bad Phrases/Patterns, German Strings,
+ | Chinese (Traditional) Strings, String History
+
+
+General Info
+-----------------------------
+ "Spam Filter" can be translated with the Miranda IM
+ language files.
+
+ Put the following strings in a file called "langpack_<language>.txt"
+ in the Miranda IM directory and translate them into your
+ language or take the German ones... ;-)
+
+ If you need more info on Miranda IM language files visit:
+ http://cvs.sourceforge.net/viewcvs.py/*checkout*/miranda/miranda/i18n/readme.txt
+
+
+Default Bad Phrases/Patterns
+-----------------------------
+ If you think a string has to be added to the translated bad phrases
+ please mail me.
+
+ If you notice some bad phrases that are
+ missing in the lists, please mail them to me. this would be very nice.
+ And..ehm...If it is another language than German, English or French
+ then a translation would be nice, so that I can look if all bad phrases
+ are usable and perhaps I can take some over into the english ones...
+
+ More bad phrase languages will (hopefully) come soon... please help me :-)
+
+
+German Strings
+-----------------------------
+
+; --- Plugin: Spam Filter 2.5.2.3 (German) ---
+
+; Translation by H. Herkenrath (hrathh at users.sourceforge.net)
+; Please report any mistakes or missing strings in here.
+
+[Spam Filter]
+Spam-Filter
+[Filters out advertisment messages, messages sent by robots and other disliked messages such as hoax messages.]
+Dieses Plugin filtert Werbe-Nachrichten, automatisch versandte Nachrichten und unerwünschte Nachrichten, wie Kettennachrichten, heraus.
+
+; Message Types (same as "Options->Contact List->Icons")
+[Authorization Request]
+Erlaubnisanfrage
+[Added Notification]
+Hinzufügungsmeldung
+[Message]
+Nachricht
+[URL]
+URL-Adresse
+[File]
+Dateiübertragung
+[Contacts]
+Kontakte
+
+; Menu Items
+[Enable &spam popups]
+&Spam-Meldungen aktivieren
+[Disable &spam popups]
+&Spam-Meldungen deaktivieren
+[&Unmark spammer]
+&Kein Spam-Versender
+[&Mark as spammer]
+&Als Spam-Versender markieren...
+[Mark Contact as Spammer]
+Kontakt als Spam-Versender markieren
+[Are you sure that the contact \"%s\" shall be marked as spammer?\r\n\r\nMarking a contact as spammer means that all associated messages will be recognized as spam and the contact will be completely ignored in the future.\r\n\r\nA contact that was marked as spammer can be restored using the options dialog.]
+Soll der Kontakt \"%s\" wirklich als Spam-Versender markiert werden?\r\n\r\nEinen Kontakt als Spam-Versender markieren bedeutet, dass alle seine bisherigen Nachrichten als Spam erkannt werden und der Kontakt für die Zukunft komplett ignoriert wird.\r\nSpam-Versender können in den Einstellungen wieder reaktiviert werden.
+
+; Popups
+[Disliked Message Alert!]
+Unerwünschte Nachricht-Alarm!
+[Advertisment Alert!]
+Werbung-Alarm!
+[Robot Alert!]
+Automatische Nachricht-Alarm!
+
+; Balloon Tips
+[Spam Filter Error]
+Spam-Filter Fehler
+[Spam Filter Error"), TranslateT("The log file \"%s\"\r\ncan not be written.\r\n\r\nProblem:\r\n%s\r\nPlease check the settings.]
+Die Protokollierdatei\r\n\"%s\" kann nicht geschrieben werden.\r\n\r\nProblem:%s\r\nBitte überprüfen Sie die Einstellungen.
+[You did not install any Spam Definition files! Spam Filter can not work as powerful as it could.\r\n\r\nPlease install at least one language of the Spam Definitions.]
+Es wurden keine Spam-Definitionen installiert! Der Spam-Filter kann nicht so ausgeprägt funktionieren, wie er könnte.\r\n\r\nBitte installieren Sie mindestens eine Sprache der Spam-Definitionen.
+[Spam Filter Critical Error]
+Kritischer Fehler im Spam-Filter
+[A very critical internal error was detected!\r\nProbably the filter will not work at all.\r\n\r\nPlease update to the most current version if this problem persists.]
+Ein sehr schwerwiegender interner Fehler wurde festgestellt!\r\nWahrscheinlich wird der Filter überhaupt nicht funktionieren.\r\n\r\nWenn das Problem fortbesteht bitte auf eine neuere Version aktualisieren.
+[Spam Filter was not able to send an automated message to the user \"%s\".]
+[Spam Filter Warning]
+Spam-Filter Warnung
+[The filter has detected %u incorrect Regular Expression(s) in the default bad words!\r\n\r\nPlease update your installed Spam Definitions to the latest versions to resolve this problem.\r\nThis problem might also be caused by Spam Definitions that are not compatible with your system codepage.]
+In den Standard-Spam-Wörtern wurde ein inkorrekter Regulärer Ausdruck gefunden (%u Stück)!.\r\n\r\nDie Spam-Definitionen müssen auf die neustenn Versionen aktualisiert werden um dieses Problemn zu beheben.\r\nEs kann auch sein, dass Spam-Definitionen installiert sind, die nicht kompatibel mit der verwendeten Windows-Codepage sind.
+
+; Sounds
+;[Spam]
+[Advertisment Alert]
+Werbung eingegangen
+[Disliked Message Alert]
+Unerwünschte Nachicht eingegangen
+[Robot Alert]
+Automatische Nachricht eingegangen
+
+; Icons
+[Spam Message Overlay]
+Spam-Nachricht Indikator
+;[Mark Contact as Spammer]
+[Spammer Indicator]
+Spam-Versender
+
+; Variables Plugin
+; %autoignore_count%
+[Number of users currently being in danger of being ignored.]
+Anzahl der Benutzer die gefährdet sind automatisch ignoriert zu werden.
+
+; Trigger Plugin
+[Spam Filter: Incoming Spam]
+Spam-Filter: Eingehende Spam-Nachricht
+
+; Custom Folders Plugin
+[Spam Definitions]
+Spam-Definitionen
+[Customized Words]
+Selbstdefinierte Wörter
+
+; Logging
+[Contact set as spammer]
+Kontakt ist Spam-Versender
+[Contains only spaces]
+Enthält keinen Text
+[Is multiple]
+Ist mehrfach empfangene Nachricht
+[Is capitalized]
+Enthält nur große Buchstaben
+[Contains URL address]
+Enthält URL-Adresse
+[Contains phone number]
+Enthält Telefonnummer
+[Is teaser]
+Ist Locknachricht
+[User is known as spammer]
+Benutzer ist als Spam-Versender bekannt
+[Robot message]
+Automatisch versendete Nachricht
+[Contains %u bad phrase(s)/pattern(s)]
+Enthält %u Spam-Worte
+[Contains %u differently formated bad phrase(s)/pattern(s)]
+Enthält %u abweichend formatierte Spam-Wörter
+[Contains %u good phrase(s)/pattern(s)]
+Enthält %u positive Wörter
+[Is hoax text]
+Ist Kettennachricht
+[Contains %u disliked indicating phrase(s)/pattern(s)]
+Enthält %u unerwünschte Wortkombinationen
+; Separator:
+;[, ]
+[Message deleted]
+Nachricht gelöscht
+[Message marked read]
+Nachricht als gelesen markiert
+[User ignored]
+Benutzer ignoriert
+; %log_user% format: Nick (UniqueID)
+;[%s (%s)]
+
+; Logging: Plain Text Format
+[[%log_date% %log_time%, User: %log_user%, Type: %log_type%]\r\nRecognition: %log_recognition%\t\r\nResult: %log_result%\r\n%log_message%\r\n\r\n]
+[%log_date% %log_time%, Benutzer: %log_user%, Typ: %log_type%]\r\nErkennung: %log_recognition%\t\r\nErgebnis: %log_result%\r\n%log_message%\r\n\r\n]
+
+; Logging: CSV Format
+;[\"%log_date%\";\"%log_time%\";\"%log_user%\";\"%log_type%\";\"%log_recognition%\";\"%log_result%\";\"%log_message%\"\r\n]
+["Date";"Time";"User";"Type";"Recognition";"Result";"Message"\r\n]
+"Datum";"Uhrzeit";"Benutzer";"Typ";"Erkennung";"Ergebnis";"Nachricht"\r\n
+
+; Logging: XML Format
+[Received Spam]
+Empfangene Spam-Nachrichten
+[Logged since]
+Protokolliert seit
+[Date/Time:]
+Datum/Uhrzeit:
+[User:]
+Benutzer:
+[Type:]
+Typ:
+[Recognition:]
+Erkennung:
+[Result:]
+Ergebnis:
+
+
+; Options: Main
+[&Advertisment Filter (recommended)]
+&Werbung-Filter (empfohlen)
+[Filters out advertisments from unknown users that are not on the contact list.]
+Filtert Werbe-Nachrichten von Benutzern, die nicht in der Kontaktliste aufgeführt sind, heraus.
+[C&onfigure...]
+K&onfigurieren...
+[&Robot Filter]
+&Automatische Nachrichten-Filter
+[Filters out all automated messages from unknown contacts via requesting a correct answer from the sender.]
+Filtert alle automatisch versandten Nachrichten heraus, durch Anforderung einer korrekten Antwort von unbekannten Versendern.
+[Co&nfigure...]
+Ko&nfigurieren...
+[&Disliked Messages Filter]
+&Unerwünschte Nachrichten-Filter
+[Filters out disliked messages such as hoax messages from known contacts that are on your contact list.]
+Filtert unerwünschte Nachrichten, wie Kettennachrichten, von Kontakten, die in der Kontaktliste aufgeführt sind, heraus.
+[Con&figure...]
+Kon&figurieren...
+[Behaviour]
+Filterverhalten
+[Mar&k spam messages as read]
+Spam als &gelesen markieren
+[D&elete spam messages]
+Spam-Nachrichten &löschen
+[Auto Ignore]
+Automatisch Ignorieren
+[Automatically &ignore spamming users]
+Spam-Versender automatisch &ignorieren
+[Allowed spam per &user:]
+&Erlaubte Spam-Nachrichten:
+[&Rese&t...]
+Zurückse&tzen...
+[Spa&mmers]
+Spa&m-Versender
+[Reset Auto Ignore]
+Automatisches Ignorieren zurücksetzen
+[Are you sure that the Auto Ignore counters shall really be reset?\r\n\r\nSpammers that are not already ignored will then not be remembered any longer.]
+Sollen die Zähler für das Automatische Ignorieren wirklich zurückgesetzt werden?\r\nSpam-Versender die noch nicht ignoriert sind werden dann nicht mehr vorgemerkt sein.
+[Message Types]
+Nachrichtentypen
+[Types of incoming e&vents which shall be checked for spam:]
+Eingehende Nachrichtent&ypen die überprüft werden sollen:
+[Spam Notification]
+Meldungen
+[Show &popup when a spam message is received]
+&Popup-Fenster anzeigen, wenn eine Spam-Nachricht eingeht
+[&Log spam messages to file:]
+Spam in Datei &speichern:
+; Default Log file name:
+;[Spam.xml]
+;[&...]
+[&Show]
+&Anzeigen
+
+; Options: Spammers Info
+[Ignored Spammers]
+Ignorierte Spam-Versender
+[The following contacts were recognized as spammers:]
+Die folgenden Kontakte wurde als Spam-Versender erkannt:
+[Spammer]
+Spam-Versender
+[Accept]
+Akzeptieren
+[Delete]
+Löschen
+[Store spammers in special &group:]
+Spam-Versender in folgender &Gruppe aufbewahren:
+[Spammers]
+Spam-Versender
+
+; Options: Advertisment Filter
+[Configure Advertisment Filter]
+Werbung-Filter konfigurieren
+[Bad Phrases/Patterns]
+Spam-Wortkombinationen
+[Look for standard &bad phrases in received messages]
+Auf &Standard Spam-Wörter in empfangenen Nachrichten prüfen
+[Also watch for following &customized bad phrases:]
+Auch nach &folgenden Spam-Wörtern suchen:
+[Automated message]
+Automatisch generierte Nachricht
+[All&owed bad phrases until spam:]
+Erlaubte &Anzahl an Spam-Wörtern:
+[Recogni&ze different formating]
+Abweichende &Formatierung erkennen
+[Allowed &formated bad phrases:]
+Erlaubte formatierte &Wörter:
+[Known Spammers]
+Spam-Versender
+[Filter out messages from standard &known spammers]
+Nachrichten von standardmäßigen Spam-Versendern herausfiltern
+[Bad Contents]
+Spam-Inhalte
+[&URL addresses]
+&URL-Adressen
+[&Phone numbers]
+&Telefonnummern
+[C&apitalized messages]
+&Großgeschriebene Nachrichten
+[Messages containing &spaces only]
+&Leere Nachrichten
+[&Multiple messages with same content]
+&Mehrere Nachrichten mit gleichem Inhalt
+[&Teaser messages]
+&Locknachrichten
+[Good Phrases/Patterns]
+Positive Wortkombinationen
+[Messages are &no spam when containing some of the following phrases:]
+Nachrichten &nicht als Spam ansehen, wenn folgende Wörter enthalten sind:
+;[Miranda IM]
+[Allo&wed phrases until no spam:]
+Erlaubte positive Wörter:
+
+; Options: Robot Filter
+[Configure Robot Filter]
+Filter für automatich versendete Nachrichten konfigurieren
+[Message Texts]
+Nachrichtentexte
+[&Instruction:]
+&Anleitung:
+[Hello %sender%,\r\nPlease reply \"%securitycode%\" if you want to contact me. If you don't reply correctly your messages will be ignored. Sorry for the inconvenience.\r\nThis spam check quarantees that you are a real person.\r\nYou have %triesleft% tries left.\r\nThanks in advance!\r\n\r\n(Automated message)]
+Hallo %sender%,\r\nBitte antworte mit \"%securitycode%\", um mit mit mir in Kontakt zu treten. Alle anderen Nachrichten werden zunächst ignoriert.\r\nEs verbleiben noch %triesleft% Versuche.\r\nDanke im Voraus!\r\n(Automatisch generierte Nachricht)
+[&Confirmation:]
+&Bestätigung:
+[Thank you for your help!\r\nAll your previous messages were delivered. New messages do now reach me directly without an additional spam check.\r\n\r\n(Automated message)]
+Danke für die Hilfe!\r\nAlle bisherigen Nachrichten wurden zugestellt. Weitere Nachrichten unterliegen keiner erneuten Spam-Prüfung.\r\n\r\n(Automatisch generierte Nachricht)
+[(You can use the substitute symbols %sender%, %message%, %securitycode% and %triesleft% for the appropriate contents.)]
+(Die Platzhalter %sender%, %message%, %securitycode% and %triesleft% können für die jeweiligen Inhalte verwendet werden.)
+; Value of %triesleft% when auto ignore feature disabled
+[unlimited]
+unbegrenzte
+[Add the message texts to contact &history]
+Zum &Nachrichtenverlauf des Kontakts hinzufügen
+[Security Code]
+Richtige Antwort
+[The following text needs to be replied by the contact to confirm that the message was not sent automatically:]
+Der folgende Text muss vom Benutzer zurückgesendet werden um zu bestätigen, dass seine Nachricht nicht automatisch versandt wurde:
+[&Random]
+&Zufall
+; Random chars base (Note: misunderstandable chars removed)
+;[abcdefghkmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWXYZ23456789]
+[(You can use readable words, too.)]
+(Normale Wörter sind auch möglich.)
+[&Hide users until they identified themselves]
+Absender &verstecken bis sie bestätigt wurden
+[Note: This filter gets invoked after the Advertisment Filter.\r\nThus, no instruction message will be sent in reply to advertisment messages.]
+Hinweis: Dieser Filter wird nach dem Werbung-Filter angewendet,\r\nd.h. es wird nicht mit einer Anleitungsnachricht auf Werbenachrichten geantwortet.
+
+; Options: Disliked Messages Filter
+[Configure Disliked Messages Filter]
+Filter für unerwünschte Nachrichten konfigurieren
+[Disliked Contents]
+Unerwünschte Inhalte
+[Messages containing &known hoax message texts]
+Auf &bekannte Texte von Kettennachrichten prüfen
+[Indicating Phrases/Patterns]
+Wortkombinationen
+[Look for the following indicating &phrases:]
+Auf folgende &Worte prüfen:
+[Please forward]
+Bitte weiterleiten
+[Auto Reply]
+Automatische Antwort
+[Auto &reply to disliked messages using the following text:]
+Automatisch auf unerwünschte Nachrichten mit dem folgenden Text &antworten:
+[Hello %sender%,\r\nI don't like such messages. Please don't send them to me anymore.\r\nThanks.\r\n\r\n(Automated message)]
+Hallo %sender%\r\nIch kann solche Nachrichten nicht ausstehen. Bitte nicht mehr senden!\r\nDanke.\r\n\r\n(Automatisch generierte Nachricht)
+[(You can use the substitute symbols %sender% and %message% for the appropriate contents.)]
+(Die Platzhalter %sender% und %message% können für die jeweiligen Inhalte verwendet werden.)
+[Add the reply to contact &history]
+Zum &Nachrichtenverlauf hinzufügen
+
+; Options: Select Log File
+[Select Log File]
+Protokollierdatei festlegen
+[Text Files (*.txt)]
+Textdokumente (*.txt)
+[Log Files (*.log)]
+Log-Dateien (*.log)
+[Comma Separated Values Files (*.csv)]
+CSV (Trenzeichen-getrennt) (*.csv)
+[XML Files (*.xml; *.xsl)]
+XML-Dateien (*.xml; *.xsl)
+[All Logging Files (*.log; *.txt; *.csv; *.xml)]
+Alle Protokollierdateien (*.log; *.txt; *.csv; *.xml)
+[All Files (*.*)]
+Alle Dateien (*.*)
+
+; Options: Add/Remove List Item
+[&Add...]
+&Hinzufügen..
+[&Remove]
+&Entfernen
+[&New indicating phrase/pattern:]
+&Neue Wortkombination:
+[Add bad phrase/pattern]
+Spam-Wort hinzufügen
+[Remove bad phrase/pattern]
+Spam-Wort entfernen
+[The entered bad phrase \"%s\" already exists in the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the bad phrase be added anyway?]
+Das soeben eingegebene Spam-Wort \"%s\" existiert bereits in der Liste.\r\n\r\nDer Filter unterscheidet nicht zwischen Groß- und Kleinschreibung\nin den Wörtern, deshalb sind zwei Einträge mit demselben Wort nicht notwendig\nund würden die Filterqualität negativ beeinflussen.\r\n\r\nSoll das Spam-Wort dennoch hinzugefügt werden?
+[The entered bad phrase \"%s\" already exists in the default bad phrases lists.\r\n\r\nAllowing the same bad phrase in the customized bad phrases lists will\npull down the filter quality.\r\n\r\nShall the bad phrase be added anyway?]
+Das soeben eingegebene Spam-Wort \"%s\" existiert bereits in den Standard-Wörtern.\r\n\r\nEin selbsteingegebenes Spam-Wort sollte jedoch nicht in den Standard-Wörtern\nvorkommen, da dadurch die Filter-Qualität negativ beeinflusst werden könnte.\r\n\r\nSoll das Spam-Wort dennoch hinzugefügt werden?
+[Add good phrase/pattern]
+Positives Wort hinzufügen
+[Remove good phrase/pattern]
+Positives Wort entfernen
+[The entered good phrase \"%s\" already exists in the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the good phrase be added anyway?]
+Das soeben eingegebene positive Wort \"%s\" existiert bereits in der Liste.\r\n\r\nDer Filter unterscheidet nicht zwischen Groß- und Kleinschreibung\nin den Wörtern, deshalb sind zwei Einträge mit demselben Wort nicht notwendig\nund würden die Filterqualität negativ beeinflussen.\r\n\r\nSoll das positive Wort dennoch hinzugefügt werden?
+[Add indicating phrase/pattern]
+Wortkombination hinzufügen
+[Remove indicating phrase/pattern]
+Wortkombination entfernen
+[The entered indicating phrase \"%s\" already exists in the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the chain indicating phrase be added anyway?]
+Die soeben eingegebene Wortkombination \"%s\" existiert bereits in der Liste.\r\n\r\nDer Filter unterscheidet nicht zwischen Groß- und Kleinschreibung\nin den Wörtern, deshalb sind zwei Einträge mit demselben Wort nicht notwendig\nund würden die Filterqualität negativ beeinflussen.\r\n\r\nSoll die Wortkombination dennoch hinzugefügt werden?
+[(You can use normal words and Regular Expressions)]
+(Reguläre Ausdrücke und normale Wörter sind möglich)
+[(Regular Expressions disabled)]
+(Reguläre Ausdrucke sind deaktiviert)
+[Syntax Error in Regular Expression]
+Syntaxfehler in Regulärem Ausdruck (RegExp)
+[The entered phrase \"%s\" consists of a Regular Expression containing a syntax error!\r\n\r\nAdding an malformed Regular Expression will cause the filter\r\nto treat the expression as a normal phrase.\r\n\r\nShall the malformed Regular Expression be added anyway?]
+Die eingegebene Wortkombination enthält einen ungültigen Regulären Ausdruck (RegExp)!\r\nEin ungültiger Regulärer Ausruck wird vom Filter als normale Wortkombination angesehen.\r\n\r\nSoll der ungültige Reguläre Ausruck trotzdem hinzugefügt werden?
+
+; Options: Regular Expressions Help Section
+[Quick Quide to Regular Expressions:]
+Schnellanleitung für Reguläre Ausdrücke:
+[Alternatives:]
+Alternativen:
+[gilbert|sullivan finds \"gilbert\" or \"sullivan\"]
+gilbert|sullivan findet \"gilbert\" oder \"sullivan\"
+[Subpatterns]
+Unterausdrücke:
+[cat(aract|erpillar) finds "cataract\" or \"caterpillar\"]
+cat(aract|erpillar) findet "cataract\" oder \"caterpillar\"
+[Repetitions]
+Wiederholungen:
+[z{2,4} matches \"zz\", \"zzz\" or \"zzzz\"\r\n* is equivalent to {0,}\r\n+ is equivalent to {1,}\r\n? is equivalent to {0,1}]
+z{2,4} findet \"zz\", \"zzz\" oder \"zzzz\"\r\n* ist gleichbedeutend mit {0,}\r\n+ ist gleichbedeutend mit {1,}\r\n? ist gleichbedeutend mit {0,1}
+[Generic Types:]
+Allgemeine Typen:
+[\\d represents any decimal digit\r\n\\D represents any character that is not a decimal digit]
+\\d steht für irgendeine Dezimalzahl\r\n\\D steht für irgendein nicht-numerisches Zeichen
+[Assertions:]
+Zusicherungen:
+[(?<!foo)bar finds an occurrence of \"bar\" that is not preceded by \"foo\"\r\n(?<= for positive lookahead assertions\r\n(?<! for negative lookahead assertions\r\n(?= for positive lookbehind assertions\r\n(?! for negative lookbehind assertions]
+(?<!foo)bar findet ein Vorkommen von \"bar\" dem nicht \"foo\" vorangestellt ist\r\n(?<= steht für postiv vorausblickend\r\n(?<! steht für negativ vorausblickend\r\n(?= steht für positiv rückblickend\r\n(?! steht für negativ rückblickend
+[Back References:]
+Rückverweise:
+[(sens|respons)e and \\1ibility matches \"sense and sensibility\" and \"response and responsibility\", but not \"sense and responsibility\"]
+(sens|respons)e and \\1ibility findet \"sense and sensibility\" und \"response and responsibility\", jedoch nicht \"sense and responsibility\"
+[All syntax elements can be combined or nested using subpatterns.]
+Syntaxelemente können mithilfe von Unterausdrücken kombiniert werden.
+
+; Options: Spam Definitions Info Dialog
+[Spam Definitions: Advertisment Filter]
+Spam-Definitionen: Werbung-Filter
+[Advertisment Filter]
+Werbung-Filter
+[Spam Definitions: Disliked Messages Filter]
+Spam-Definitionen: Unerwünschte Nachrichten-Filter
+[Disliked Messages Filter]
+Unerwünschte Nachrichten-Filter
+[Installed Spam Definitions for filter:]
+Installierte Spam-Definitionen für den Filter:
+[Not Available]
+Nicht verfügbar
+[Packet]
+Paket
+;[Version]
+[Type]
+Typ
+[Default Bad Words]
+Standard Spam-Wörter
+[Known Spammers]
+Bekannte Spam-Versender
+[Known Teaser Texts]
+Bekannte Lock-Texte
+[URL Recognition]
+[URL-Erkennung
+[Phone Number Recognition]
+Telefonnummer-Erkennung
+[Different Format Recognition: Text]
+Format-Erkennung: Text
+[Different Format Recognition: Numbers]
+Format-Erkennung: Nummern
+[Different Format Recognition: Separators]
+Format-Erkennung: Trennzeichen
+[Known Hoax Texts]
+Bekannte Hoax-Texte
+[Download more Spam Definitions]
+Weitere Spam-Definitionen herunterladen
+;[http://addons.miranda-im.org/index.php?action=display&id=92]
+[&Remove...]
+&Entfernen...
+
+; Options: Spam Definitions Info
+[Spam &Definitions]
+Spam-&Definitionen
+[Warning: Not all Spam Definitions are available!\r\nSome features are disabled.]
+Achtung: Nicht alle Spam-Definitionen sind verfügbar!\r\nEinige Optionen sind deaktiviert.
+
+; Spam Definitions Info File Names
+; (Strings prepended by "Spam Definitions:" are used by Updater plugin)
+[Common]
+Allgemein
+[English]
+Englisch
+[Spam Definitions: English]
+Spam-Definitionen: Englisch
+[Chinese]
+Chinesisch
+[Spam Definitions: Chinese]
+Spam-Definitionen: Chinesisch
+[French]
+Französisch
+[Spam Definitions: French]
+Spam-Definitionen: Französisch
+[Portuguese]
+Portugiesisch
+[Spam Definitions: Portuguese]
+Spam-Definitionen: Portugiesisch
+[Russian]
+Russisch
+[Spam Definitions: Russian]
+Spam-Definitionen: Russisch
+
+; Options: Variables Button
+[Use variables in the message text]
+Variablen im Nachrichtentext verwenden
+
+; Options: Ignore Options Extension
+[You chose to ignore all kind of messages from contacts that are not on your contact list although the spam filter is activated.\r\n\r\nShall the spam filter be deactivated?]
+Nachrichten von Benutzern, die nicht auf der Kontaktliste sind, werden im Moment ignoriert.\r\nJedoch ist der Spam-Filter aktiviert, der unerwünschte Nachrichten von solchen Benutzern herausfiltert.\r\n\r\nSoll der Spam-Filter deaktiviert werden?
+
+; ---
+
+
+
+String History:
+-----------------------------
+ 2.5.2.1: Added: [&Hide users until they identified themselves]
+ Changed: [The filter has detected %u malformed Regular Expression(s) in the default bad words!\r\n\r\n
+ Please update your installed Spam Definitions to the latest versions to resolve this problem.\r\n
+ This problem might also be caused by Spam Definitions that are not compatible
+ with your system codepage.]
+ To: [The filter has detected %u malformed Regular Expression(s) in the default bad words!\r\n\r\n
+ Please update your installed Spam Definitions to the latest versions to resolve this problem.\r\n
+ This problem might also be caused by Spam Definitions that are not compatible
+ with your system codepage.
+ Changed: [The entered phrase \"%s\" consists of a Regular Expression which is invalid!\r\n\r\n
+ Adding an invalid Regular Expression will cause the filter\r\nto treat the expression as a normal
+ phrase.\r\n\r\nShall the invalid Regular Expression be added anyway?]
+ To: [The entered phrase \"%s\" consists of a Regular Expression containing a syntax error!\r\n\r\n
+ Adding an malformed Regular Expression will cause the filter\r\nto treat the expression as a normal
+ phrase.\r\n\r\nShall the malformed Regular Expression be added anyway?]
+ Changed: [(You can use the substitute symbols %sender%, %message%, %triesleft% and
+ %securitycode% for the appropriate contents.)]
+ To: [(You can use the substitute symbols %sender%, %message%, %securitycode% and
+ %triesleft% for the appropriate contents.)]
+ Changed: [Hello %sender%,\r\nPlease reply \"%securitycode%\" if you want to contact me.
+ If you don't reply correctly your messages will be ignored. Sorry for the inconvenience.\r\n
+ This spam check quarantees that you are a real person.\r\nYou have %triesleft% tries left.\r\n
+ Thanks in advance!\r\n\r\n(Automated message)]
+ To: [Hello %sender%,\r\nPlease reply \"%securitycode%\" if you want to contact me.
+ If you don't reply correctly your messages will be ignored. Sorry for the inconvenience.\r\n
+ This spam check guarantees that you are a real person.\r\nYou have %triesleft% tries left.\r\n
+ Thanks in advance!\r\n\r\n(Automated message)]
+
+ 2.5.2.0:
+ Added: [unlimited]
+ Changed: [Please reply \"%securitycode%\" if you want to contact me. If you don't reply correctly your
+ messages will be ignored. Sorry for the inconvenience.\r\n\r\n(Automated message)]
+ To: [Hello %sender%,\r\nPlease reply \"%securitycode%\" if you want to contact me.
+ If you don't reply correctly your messages will be ignored. Sorry for the inconvenience.\r\n
+ This spam check quarantees that you are a real person.\r\nYou have %triesleft% tries left.\r\n
+ Thanks in advance!\r\n\r\n(Automated message)]
+ Changed: [Hi %sender%,\r\nI don't like such messages. Please don't send them to me
+ anymore.\r\nThanks.\r\n\r\n(Automated message)]
+ To: [Hello %sender%,\r\nI don't like such messages. Please don't send them to me anymore.\r\n
+ Thanks.\r\n\r\n(Automated message)]
+ Changed: [Thank you for your help!\r\nAll your previous messages were delivered.
+ New messages do now reach me directly without an additional spam check.\r\n\r\n
+ (Automated message)]
+ To: [Thank you for your help!\r\nAll your previous messages were delivered. New messages do reach
+ me directly, without an additional spam check.\r\n\r\n(Automated message)]
+ Changed: [Automatically &ignore spammers]
+ To: [Automatically &ignore spamming users]
+ Changed: [&Empty messages]
+ To: [Messages containing &spaces only]
+ Changed: [Contains spaces only]
+ To: [Is empty]
+ Changed: [Allowed &bad phrases until spam:]
+ To: [All&owed bad phrases until spam:]
+ Changed: [Recognize &different formating]
+ To: [Recogni&ze different formating]
+ Changed: [&Spammers]
+ To: [Spa&mmers]
+ Changed: [&Reset...]
+ To: [Rese&t...]
+ Changed: [&Mark spam messages as read]
+ To: [Mar&k spam messages as read]
+ Changed: [&Types of incoming events which shall be checked for spam:]
+ To: [Types of incoming e&vents which shall be checked for spam:]
+ Changed: [(You can use the substitute symbols %sender%, %message%and %securitycode%
+ for the appropriate contents.)]
+ To: [(You can use the substitute symbols %sender%, %message%, %triesleft% and %securitycode% for the appropriate contents.)]
+
+ * corrected some typos
+
+ 2.5.1.2:
+ Added: [Store spammers in special &group:]
+ Added: [Spammers]
+ Added: [&Unmark spammer]
+ Changed: [Normal]
+ To: [Accept]
+
+ 2.5.1.1:
+ Changed: [Spam Filter has detected %u incorrect Regular Expression(s) in the default bad words!\r\n\r\n
+ Please update your installed Spam Definitions to the latest versions to resolve this problem.]
+ To: [The filter has detected %u incorrect Regular Expression(s) in the default bad words!\r\n\r\n
+ Please update your installed Spam Definitions to the latest versions to resolve this problem.\r\n
+ This problem might also be caused by Spam Definitions that are not compatible
+ with your system codepage.]
+
+ 2.5.1.0:
+ Added: [Spammer Indicator]
+ Changed: [Spam Filter has detected a incorrect Regular Expression in the default bad words!\r\n\r\n
+ Please update your installed Spam Definitions to the latest versions to resolve this problem.]
+ To: [Spam Filter has detected %u incorrect Regular Expression(s) in the default bad words!\r\n\r\n
+ Please update your installed Spam Definitions to the latest versions to resolve this problem.]
+
+ * Corrected some typos
+
+ 2.5.0.0:
+ Added: [Use variables in the message text]
+ Added: [Disliked Contents]
+ Added: [Number of users currently being in danger of being ignored.]
+ Added: [Spam Filter Critical Error]
+ Added: [A very critical internal error was detected!\r\nProbably the filter will not work at all.\r\n\r\n
+ Please update to the most current version if this problem persists.]
+ Added: [Spam Filter was not able to send an automated message to the user \"%s\".]
+ Added: [Spam Filter Warning]
+ Added: [Spam Filter has detected a incorrect Regular Expression in the default bad words!\r\n\r\n
+ Please update your installed Spam Definitions to the latest versions to resolve this problem.]
+ Added: [(Regular Expressions disabled)]
+ Added [Spam &Definitions]
+ Added: [Warning: Not all Spam Definitions are available!\r\nSome features are disabled.]
+ Added: [Spam Definitions]
+ Added: [Installed Spam Definitions for filter:]
+ Added: [Download more Spam Definitions]
+ Added: [http://www.miranda-im.org/download/index.php?action=display&id=92]
+ Added: [Not available]
+ Added: [Packet]
+ Added: [Version]
+ Added: [Type]
+ Added: [Default Bad Words]
+ Added: [Known Spammers]
+ Added: [Known Teaser Texts]
+ Added: [URL Recognition]
+ Added: [Phone Number Recognition]
+ Added: [Different Format Recognition: Text]
+ Added: [Different Format Recognition: Numbers]
+ Added: [Different Format Recognition: Separators]
+ Added: [Known Hoax Texts]
+ Added: [Quick Quide to Regular Expressions:]
+ Added: [Alternatives:]
+ Added: [gilbert|sullivan finds \"gilbert\" or \"sullivan\"]
+ Added: [Subpatterns]
+ Added: [cat(aract|erpillar) finds "cataract\" or \"caterpillar\"]
+ Added: [Repetitions]
+ Added: [z{2,4} matches \"zz\", \"zzz\" or \"zzzz\"\r\n* is equivalent to {0,}\r\n
+ + is equivalent to {1,}\r\n? is equivalent to {0,1}]
+ Added: [Generic Types:]
+ Added: [\\d represents any decimal digit\r\n\\D represents any character that is not a decimal digit]
+ Added: [Assertions:]
+ Added: [(?<!foo)bar finds an occurrence of \"bar\" that is not preceded by \"foo\"\r\n
+ (?<= for positive lookahead assertions\r\n(?<! for negative lookahead assertions\r\n
+ (?= for positive lookbehind assertions\r\n(?! for negative lookbehind assertions]
+ Added: [Back References:]
+ Added: [(sens|respons)e and \\1ibility matches \"sense and sensibility\" and \"response and responsibility\",
+ but not \"sense and responsibility\"]
+ Added: [All syntax elements can be combined or nested using subpatterns.]
+ Added: [Spam Definitions]
+ Added: [Customized Words]
+ Added: [Spam Filter: Incoming Spam]
+ Added: [&Remove...]
+ Added: [Note: The filter gets invoked after the Advertisment Filter.\n
+ Thus, no instruction message will be sent in reply to advertisment messages.]
+ Added: [Spammers]
+ Added: [Ignored Spammers]
+ Added: [The following contacts were recognized as spammers:]
+ Added: [Spammer]
+ Added: [Normal]
+ Added: [Delete]
+ Removed: [ (Spammer)]
+ Removed: [Hoax Messages]
+ Removed: [Contains 1 disliked indicating phrase/pattern]
+ Removed: [Contains 1 bad phrase/pattern]
+ Removed: [Contains 1 differently formated bad phrase/pattern]
+ Removed: [Contains 1 good phrase/pattern]
+ Changed: [Contains %u disliked indicating phrases/patterns]
+ To: [Contains %u disliked indicating phrase(s)/pattern(s)]
+ Changed: [Contains %u bad phrases/patterns]
+ To: [Contains %u bad phrase(s)/pattern(s)]
+ Changed: [Contains %u differently formated bad phrases/patterns]
+ To: [Contains %u differently formated bad phrase(s)/pattern(s)]
+ Changed: [Date;Time;User;Type;Recognition;Result;Message\r\n]
+ To: ["Date";"Time";"User";"Type";"Recognition";"Result";"Message"\r\n]
+ Changed: [Contains %u good phrases/patterns]
+ To: [Contains %u good phrase(s)/pattern(s)]
+ Changed: [The log file \"%s\"\r\ncan not be written.\r\n\r\nPlease check the settings.]
+ To: [The log file \"%s\"\r\ncan not be written.\r\n\r\nProblem:\r\n%s\r\nPlease check the settings.]
+ Changed: [Manually set as spam]
+ To: [Contact set as spammer]
+ Changed: [Look for &known hoax message texts]
+ To: [Messages containing &known hoax message texts]
+
+ * Corrected some typos
+
+ 2.1.0.0:
+ Changed: [&Scramble]
+ To: [&Random]
+ Added: [Added Notification]
+ Added: [Is hoax text]
+
+ 2.0.2.0:
+ Added: [Syntax Error in Regular Expression]
+ Added: [The entered phrase \"%s\" consists of a Regular Expression which is invalid!\r\n\r\n
+ Adding an invalid Regular Expression will cause the filter\r\nto treat the expression as a normal
+ phrase.\r\n\r\nShall the invalid Regular Expression be added anyway?]
+ Added: [Robot message]
+ Changed: [ (spammer)]
+ To: [ (Spammer)]
+
+ * Renamed most occurences of "phrase" to "phrase/pattern" (only in captions): Compare with German strings.
+ * Changed all occurences of a simple "\n" to "\r\n": Compare with German strings.
+
+ 2.0.1.0:
+ Added: [Spam Message Overlay]
+ Added: [&Reset]
+ Added: [(You can use readable words, too.)]
+ Added: [abcdefghkmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWXYZ23456789]
+ Added: [Reset Auto Ignore]
+ Added: [Are you sure that the Auto Ignore counters shall really be reset?\r\n\r\n
+ Spammers that are not already ignored will then not be remembered any longer.]
+ Changed: [A&llowed phrases until no spam:]
+ To: [Allo&wed phrases until no spam:]
+ Changed: [Allo&wed bad phrases until spam:]
+ To: [Allowed &bad phrases until spam:]
+ Changed: [&Mark contact as spammer]
+ To: [&Mark as spammer]
+ Changed: [Filters out advertisments, robot messages and disliked messages such as hoax messages..]
+ To: [Filters out advertisment messages, messages sent by robots and
+ other disliked messages such as hoax messages.]
+ Changed: [Are you sure that the contact \"%s\" shall be marked as spammer?]
+ To: [Are you sure that the contact \"%s\" shall be marked as spammer?\r\n\r\n
+ Marking a contact as spammer means that all associated messages will be recognized as spam
+ and the contact will be completely ignored in the future.\r\n\r\nA contact that was marked as
+ spammer can be unignored using the options dialog.]
+
+ 2.0.0.0:
+ * The strings have been changed almost completely.
+ Please compare with German strings.
+
+ 1.0.4.0:
+ Added: [User is known as spammer]
+ Added: [The entered bad word \"%s\" already exists in the list.\r\n\r\n
+ The filter doesn't differentiate between lower and upper case.\n
+ Two entries with the same word are not neccessary\nand would decrease the filter quality.]
+ Added: [Add contact to spammer list...]
+ Added: [Spamer Remembering]
+ Added: [Filter out all messages from users who once sent spam]
+ Added: [Notify users that they are blocked]
+ Added: [Hey %s, I don't like spam!\nYou are now put onto the spammers list to stop
+ you from sending me such things.\r\n\r\nHere is your message back:\n%s\r\n\r\n\n
+ (Automated message)]
+ Added: [Text Files]
+ Removed: [Contact kept]
+
+
+ 1.0.3.1:
+ Added: [The entered bad word \"%s\" already exists in the default bad words list.\r\n\r\n
+ Allowing the same bad words in the customized bad words list would\n
+ pull down the filter quality.\r\n\r\nShould the bad word be added anyway?]
+ Added: [Enable &spam popups]
+ Added: [Disable &spam popups]
+ Added: [Type:]
+ Changed: [Website adresses are bad]
+ To: [Website addresses are bad]
+ Changed: [(URL)]
+ To: [URL]
+ Changed: [(Message)]
+ To: [Message]
+
+
+ 1.0.3.0:
+ Added: [(URL)]
+ Added: [(Message)]
+ Removed: [Is URL]
+ Removed: [Spam Contacts]
+ Changed: [Result:\t]
+ To: [Result:]
+ Changed: [Recognition:\t]
+ To: [Recognition:]
+ Changed: [Bad words (%u)]
+ To: [Contains &u bad words]
+ Changed: [Urls are bad]
+ To: [Website addresses are bad]
+ Changed: [Bad Messages]
+ To: [Bad Contents]
+ Changed: [Additionally look for standard bad words in bad messages]
+ To: [Look for standard bad words in received messages]
+
+ 1.0.2.3:
+ Added: [If you have any bad words that could be added to the default list please mail them to me.\n
+ So that the filter can be further improved. This would be very nice.]
+ Added: [User:]
+ Added: [Result:\t]
+ Changed: [Recognition:]
+ To: [Recognition:\t]
+
+ 1.0.2.2:
+ Added: [Recognition:]
+ Added: [Contains only one word]
+ Added: [Contains URL]
+ Added: [Is URL]
+ Added: [Bad words (%u)]
+ Added: [Message deleted]
+ Added: [Message marked read]
+ Added: [Contact deleted]
+ Added: [Contact kept]
+ Removed: [(Found Bad Words: %u)]
+ Removed: [HH:mm]
+ Removed: [dd/MM/yyyy]
+
+ 1.0.2.1:
+ Added: [Select Log File]
+ Added: [Log Files]
+ Added: [All Files]
+ Changed: [Logs\\Spam.log]
+ To: [Spam.log]
+
+ 1.0.2.0:
+ Added: [Spam Logging]
+ Added: [Log spam messages to file:]
+ Added: [Logs\\Spam.log]
+ Added: [HH:mm]
+ Added: [dd/MM/yyyy]
+ Added: [(Found Bad Words: %u)]
+
+ 1.0.1.0:
+ Added: [No spam filter]
+ Added: [Filter out spam messages from users that are not on the contact list (recommended)]
+ Added: [Spam Contacts]
+ Added: [Delete spamming contacts]
+ Removed: [Activate spam checking for users that are not on the contact list]
+
+ 1.0.0.1:
+ Changed: [Number of words until spam:]
+ To: [Allowed bad words until spam:]
+
+
H. Herkenrath (hrathh at users.sourceforge.net) \ No newline at end of file
diff --git a/SpamFilter.dsp b/SpamFilter.dsp
index 7c67382..ab9d55e 100644
--- a/SpamFilter.dsp
+++ b/SpamFilter.dsp
@@ -1,802 +1,802 @@
-# Microsoft Developer Studio Project File - Name="SpamFilter" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** NICHT BEARBEITEN **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=SpamFilter - Win32 Debug Unicode
-!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
-!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
-!MESSAGE
-!MESSAGE NMAKE /f "SpamFilter.mak".
-!MESSAGE
-!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
-!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
-!MESSAGE
-!MESSAGE NMAKE /f "SpamFilter.mak" CFG="SpamFilter - Win32 Debug Unicode"
-!MESSAGE
-!MESSAGE Für die Konfiguration stehen zur Auswahl:
-!MESSAGE
-!MESSAGE "SpamFilter - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "SpamFilter - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "SpamFilter - Win32 Release Unicode" (basierend auf "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "SpamFilter - Win32 Debug Unicode" (basierend auf "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "SpamFilter - Win32 Release Unicode 9x/ME" (basierend auf "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "SpamFilter - Win32 Debug Unicode 9x/ME" (basierend auf "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "SpamFilter - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Temp\Release"
-# PROP BASE Target_Dir "Release"
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Temp\Release"
-# PROP Intermediate_Dir "Temp\Release"
-# PROP Ignore_Export_Lib 1
-# PROP Target_Dir "Release"
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W4 /GX /O2 /I ".\Include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "NO_STRICT" /FR /YX /FD /opt:nowin98 /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /win32
-# SUBTRACT MTL /mktyplib203 /Oicf
-# ADD BASE RSC /l 0x1009 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:".\Release\spamfilter.pdb" /debug /machine:I386 /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:".\Release\spamfilter.dll" /opt:nowin98 /ignore:4078 /RELEASE
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF "$(CFG)" == "SpamFilter - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Temp\Debug"
-# PROP BASE Intermediate_Dir "Temp\Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Temp\Debug"
-# PROP Intermediate_Dir "Temp\Debug"
-# PROP Ignore_Export_Lib 1
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W4 /Gm /Gi /GX /ZI /Od /I ".\Include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "NO_STRICT" /FR /YX /FD /GZ /c
-# SUBTRACT CPP /WX
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# SUBTRACT MTL /Oicf
-# ADD BASE RSC /l 0x1009 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilter.pdb" /map /debug /machine:I386 /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilter.dll" /pdbtype:sept
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF "$(CFG)" == "SpamFilter - Win32 Release Unicode"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Temp\ReleaseW"
-# PROP BASE Target_Dir "ReleaseW"
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Temp\ReleaseW"
-# PROP Intermediate_Dir "Temp\ReleaseW"
-# PROP Ignore_Export_Lib 1
-# PROP Target_Dir "Release"
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W4 /GX /O2 /I ".\Include" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "_MBCS" /U "NO_STRICT" /FR /YX /FD /opt:nowin98 /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /win32
-# SUBTRACT MTL /mktyplib203 /Oicf
-# ADD BASE RSC /l 0x1009 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:".\Release\spamfilterW.pdb" /debug /machine:I386 /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:".\Release\spamfilterW.dll" /opt:nowin98 /ignore:4078 /RELEASE
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF "$(CFG)" == "SpamFilter - Win32 Debug Unicode"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Temp\DebugW"
-# PROP BASE Intermediate_Dir "Temp\DebugW"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Temp\DebugW"
-# PROP Intermediate_Dir "Temp\DebugW"
-# PROP Ignore_Export_Lib 1
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W4 /Gm /Gi /GX /ZI /Od /I ".\Include" /D "_DEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "_MBCS" /U "NO_STRICT" /FR /YX /FD /GZ /c
-# SUBTRACT CPP /WX
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# SUBTRACT MTL /Oicf
-# ADD BASE RSC /l 0x1009 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW.pdb" /map /debug /machine:I386 /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW.dll" /pdbtype:sept
-# SUBTRACT LINK32 /pdb:none /nodefaultlib
-
-!ELSEIF "$(CFG)" == "SpamFilter - Win32 Release Unicode 9x/ME"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Temp\ReleaseW9x"
-# PROP BASE Target_Dir "ReleaseW9x"
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Temp\ReleaseW9x"
-# PROP Intermediate_Dir "Temp\ReleaseW9x"
-# PROP Ignore_Export_Lib 1
-# PROP Target_Dir "ReleaseW9x"
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W4 /GX /O2 /I ".\Include" /D "NDEBUG" /D "UNICOWS" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "_MBCS" /U "NO_STRICT" /FR /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /win32
-# SUBTRACT MTL /mktyplib203 /Oicf
-# ADD BASE RSC /l 0x1009 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 unicows.lib kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:".\Release\spamfilterW9x.pdb" /debug /machine:I386 /nodefaultlib:"kernel32.lib" /nodefaultlib:"advapi32.lib" /nodefaultlib:"user32.lib" /nodefaultlib:"gdi32.lib" /nodefaultlib:"shell32.lib" /nodefaultlib:"comdlg32.lib" /nodefaultlib:"version.lib" /nodefaultlib:"mpr.lib" /nodefaultlib:"rasapi32.lib" /nodefaultlib:"winmm.lib" /nodefaultlib:"winspool.lib" /nodefaultlib:"vfw32.lib" /nodefaultlib:"secur32.lib" /nodefaultlib:"oleacc.lib" /nodefaultlib:"oledlg.lib" /nodefaultlib:"sensapi.lib" /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:".\Release\spamfilterW9x.dll" /ignore:4078 /RELEASE
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF "$(CFG)" == "SpamFilter - Win32 Debug Unicode 9x/ME"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Temp\DebugW9x"
-# PROP BASE Intermediate_Dir "Temp\DebugW9x"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Temp\DebugW9x"
-# PROP Intermediate_Dir "Temp\DebugW9x"
-# PROP Ignore_Export_Lib 1
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W4 /Gm /Gi /GX /ZI /Od /I ".\Include" /D "_DEBUG" /D "UNICOWS" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "_MBCS" /U "NO_STRICT" /FR /YX /FD /GZ /c
-# SUBTRACT CPP /WX
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# SUBTRACT MTL /Oicf
-# ADD BASE RSC /l 0x1009 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 unicows.lib kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW9x.pdb" /map /debug /machine:I386 /nodefaultlib:"kernel32.lib" /nodefaultlib:"advapi32.lib" /nodefaultlib:"user32.lib" /nodefaultlib:"gdi32.lib" /nodefaultlib:"shell32.lib" /nodefaultlib:"comdlg32.lib" /nodefaultlib:"version.lib" /nodefaultlib:"mpr.lib" /nodefaultlib:"rasapi32.lib" /nodefaultlib:"winmm.lib" /nodefaultlib:"winspool.lib" /nodefaultlib:"vfw32.lib" /nodefaultlib:"secur32.lib" /nodefaultlib:"oleacc.lib" /nodefaultlib:"oledlg.lib" /nodefaultlib:"sensapi.lib" /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW9x.dll" /pdbtype:sept
-# SUBTRACT LINK32 /pdb:none
-
-!ENDIF
-
-# Begin Target
-
-# Name "SpamFilter - Win32 Release"
-# Name "SpamFilter - Win32 Debug"
-# Name "SpamFilter - Win32 Release Unicode"
-# Name "SpamFilter - Win32 Debug Unicode"
-# Name "SpamFilter - Win32 Release Unicode 9x/ME"
-# Name "SpamFilter - Win32 Debug Unicode 9x/ME"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\contact.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\dlg.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\extraimg.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\folders.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\forkthread.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\logfile.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\main.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\menuitems.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\options.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\path.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\popup.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\regexp.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\services.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\spamcheck.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\spamcheckdata.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\spamdefinitions.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\string.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\stringlist.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\trigger.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\unicode.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\update.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\utilities.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\variables.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\common.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\contact.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\dlg.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\extraimg.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\folders.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\forkthread.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\logfile.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\menuitems.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\options.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\path.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\popup.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\regexp.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\services.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\spamcheck.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\spamcheckdata.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\spamdefinitions.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\string.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\stringlist.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\trigger.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\unicode.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\update.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\utilities.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\variables.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\version.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# Begin Source File
-
-SOURCE=.\Resources\add_button_16x16_256.ico
-# End Source File
-# Begin Source File
-
-SOURCE=.\Resources\delete_button_16x16_256.ico
-# End Source File
-# Begin Source File
-
-SOURCE=.\Resources\log_item.xml
-# End Source File
-# Begin Source File
-
-SOURCE=.\Resources\log_layout.xsl
-# End Source File
-# Begin Source File
-
-SOURCE=.\Resources\log_main.xml
-# End Source File
-# Begin Source File
-
-SOURCE=.\resource.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Resources\spam_16x16_256.ico
-# End Source File
-# Begin Source File
-
-SOURCE=.\Resources\spam_32x32_256.ico
-# End Source File
-# Begin Source File
-
-SOURCE=.\Resources\spam_definitions_16x16_256.ico
-# End Source File
-# Begin Source File
-
-SOURCE=.\Resources\spam_layer_16x16_256.ico
-# End Source File
-# Begin Source File
-
-SOURCE=.\SpamFilter.rc
-# End Source File
-# End Group
-# Begin Group "Documentation"
-
-# PROP Default_Filter "*.txt"
-# Begin Source File
-
-SOURCE=".\Docs\PCRE-License.txt"
-# End Source File
-# Begin Source File
-
-SOURCE=".\Docs\SpamFilter-Developer.txt"
-# End Source File
-# Begin Source File
-
-SOURCE=".\Docs\SpamFilter-License.txt"
-# End Source File
-# Begin Source File
-
-SOURCE=".\Docs\SpamFilter-Readme.txt"
-# End Source File
-# Begin Source File
-
-SOURCE=".\Docs\SpamFilter-Translation.txt"
-# End Source File
-# End Group
-# Begin Group "Extensions"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\Extensions\filtered1.wav
-# End Source File
-# Begin Source File
-
-SOURCE=.\Extensions\filtered2.wav
-# End Source File
-# Begin Source File
-
-SOURCE=.\Extensions\filtered3.wav
-# End Source File
-# Begin Source File
-
-SOURCE=.\Extensions\InstallScript.xml
-# End Source File
-# Begin Source File
-
-SOURCE=.\m_spamfilter.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\m_spamfilter.inc
-# End Source File
-# End Group
-# Begin Group "Utilities"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\Utilities\DebugHelper.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Utilities\Pcre\include\pcre.h
-# End Source File
-# End Group
-# Begin Group "Include"
-
-# PROP Default_Filter "c;h"
-# Begin Source File
-
-SOURCE=.\Include\m_addcontact.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_alarms.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_autoshutdown.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_avatars.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_awaymsg.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_bkgrcfg.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_button.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_chat.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_clc.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_clist.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_clistint.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_clui.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_cluiframes.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_colourpicker.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_contactdir.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_contacts.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_contactsex.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_contactstransfer.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_database.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_email.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_file.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_findadd.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_folders.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_fontservice.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_fuse.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_genmenu.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_history.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_httpserver.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_icolib.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_icq.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_idle.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_ieview.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_ignore.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_langpack.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_mathmodule.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_message.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_metacontacts.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_netlib.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_options.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_plugins.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_png.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_popup.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_popupw.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_protocols.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_protomod.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_protosvc.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_sessions.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_skin.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_skin_eng.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_smileyadd.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_snapping_windows.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_spamfilter.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_statusplugins.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_system.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_toptoolbar.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_trigger.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_uninstaller.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_updater.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_url.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_userinfo.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_utils.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_variables.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\m_weather.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\newpluginapi.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\statusmodes.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Include\win2k.h
-# End Source File
-# End Group
-# Begin Source File
-
-SOURCE=.\Info_Src.txt
-# End Source File
-# Begin Source File
-
-SOURCE=.\License_Appendix.txt
-# End Source File
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="SpamFilter" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=SpamFilter - Win32 Debug Unicode
+!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
+!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
+!MESSAGE
+!MESSAGE NMAKE /f "SpamFilter.mak".
+!MESSAGE
+!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
+!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
+!MESSAGE
+!MESSAGE NMAKE /f "SpamFilter.mak" CFG="SpamFilter - Win32 Debug Unicode"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "SpamFilter - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "SpamFilter - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "SpamFilter - Win32 Release Unicode" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "SpamFilter - Win32 Debug Unicode" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "SpamFilter - Win32 Release Unicode 9x/ME" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "SpamFilter - Win32 Debug Unicode 9x/ME" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "SpamFilter - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Temp\Release"
+# PROP BASE Target_Dir "Release"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Temp\Release"
+# PROP Intermediate_Dir "Temp\Release"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir "Release"
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W4 /GX /O2 /I ".\Include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "NO_STRICT" /FR /YX /FD /opt:nowin98 /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+# SUBTRACT MTL /mktyplib203 /Oicf
+# ADD BASE RSC /l 0x1009 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:".\Release\spamfilter.pdb" /debug /machine:I386 /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:".\Release\spamfilter.dll" /opt:nowin98 /ignore:4078 /RELEASE
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "SpamFilter - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Temp\Debug"
+# PROP BASE Intermediate_Dir "Temp\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Temp\Debug"
+# PROP Intermediate_Dir "Temp\Debug"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W4 /Gm /Gi /GX /ZI /Od /I ".\Include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "NO_STRICT" /FR /YX /FD /GZ /c
+# SUBTRACT CPP /WX
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# SUBTRACT MTL /Oicf
+# ADD BASE RSC /l 0x1009 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilter.pdb" /map /debug /machine:I386 /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilter.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "SpamFilter - Win32 Release Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Temp\ReleaseW"
+# PROP BASE Target_Dir "ReleaseW"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Temp\ReleaseW"
+# PROP Intermediate_Dir "Temp\ReleaseW"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir "Release"
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W4 /GX /O2 /I ".\Include" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "_MBCS" /U "NO_STRICT" /FR /YX /FD /opt:nowin98 /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+# SUBTRACT MTL /mktyplib203 /Oicf
+# ADD BASE RSC /l 0x1009 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:".\Release\spamfilterW.pdb" /debug /machine:I386 /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:".\Release\spamfilterW.dll" /opt:nowin98 /ignore:4078 /RELEASE
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "SpamFilter - Win32 Debug Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Temp\DebugW"
+# PROP BASE Intermediate_Dir "Temp\DebugW"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Temp\DebugW"
+# PROP Intermediate_Dir "Temp\DebugW"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W4 /Gm /Gi /GX /ZI /Od /I ".\Include" /D "_DEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "_MBCS" /U "NO_STRICT" /FR /YX /FD /GZ /c
+# SUBTRACT CPP /WX
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# SUBTRACT MTL /Oicf
+# ADD BASE RSC /l 0x1009 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW.pdb" /map /debug /machine:I386 /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none /nodefaultlib
+
+!ELSEIF "$(CFG)" == "SpamFilter - Win32 Release Unicode 9x/ME"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Temp\ReleaseW9x"
+# PROP BASE Target_Dir "ReleaseW9x"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Temp\ReleaseW9x"
+# PROP Intermediate_Dir "Temp\ReleaseW9x"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir "ReleaseW9x"
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W4 /GX /O2 /I ".\Include" /D "NDEBUG" /D "UNICOWS" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "_MBCS" /U "NO_STRICT" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+# SUBTRACT MTL /mktyplib203 /Oicf
+# ADD BASE RSC /l 0x1009 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 unicows.lib kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:".\Release\spamfilterW9x.pdb" /debug /machine:I386 /nodefaultlib:"kernel32.lib" /nodefaultlib:"advapi32.lib" /nodefaultlib:"user32.lib" /nodefaultlib:"gdi32.lib" /nodefaultlib:"shell32.lib" /nodefaultlib:"comdlg32.lib" /nodefaultlib:"version.lib" /nodefaultlib:"mpr.lib" /nodefaultlib:"rasapi32.lib" /nodefaultlib:"winmm.lib" /nodefaultlib:"winspool.lib" /nodefaultlib:"vfw32.lib" /nodefaultlib:"secur32.lib" /nodefaultlib:"oleacc.lib" /nodefaultlib:"oledlg.lib" /nodefaultlib:"sensapi.lib" /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:".\Release\spamfilterW9x.dll" /ignore:4078 /RELEASE
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "SpamFilter - Win32 Debug Unicode 9x/ME"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Temp\DebugW9x"
+# PROP BASE Intermediate_Dir "Temp\DebugW9x"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Temp\DebugW9x"
+# PROP Intermediate_Dir "Temp\DebugW9x"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAMFILTER_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W4 /Gm /Gi /GX /ZI /Od /I ".\Include" /D "_DEBUG" /D "UNICOWS" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "STRICT" /D "SPAMFILTER_EXPORTS" /U "_MBCS" /U "NO_STRICT" /FR /YX /FD /GZ /c
+# SUBTRACT CPP /WX
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# SUBTRACT MTL /Oicf
+# ADD BASE RSC /l 0x1009 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 unicows.lib kernel32.lib comctl32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib shlwapi.lib ole32.lib version.lib /nologo /base:"" /dll /pdb:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW9x.pdb" /map /debug /machine:I386 /nodefaultlib:"kernel32.lib" /nodefaultlib:"advapi32.lib" /nodefaultlib:"user32.lib" /nodefaultlib:"gdi32.lib" /nodefaultlib:"shell32.lib" /nodefaultlib:"comdlg32.lib" /nodefaultlib:"version.lib" /nodefaultlib:"mpr.lib" /nodefaultlib:"rasapi32.lib" /nodefaultlib:"winmm.lib" /nodefaultlib:"winspool.lib" /nodefaultlib:"vfw32.lib" /nodefaultlib:"secur32.lib" /nodefaultlib:"oleacc.lib" /nodefaultlib:"oledlg.lib" /nodefaultlib:"sensapi.lib" /nodefaultlib:"uuid.lib" /nodefaultlib:"OLDNAMES" /out:"C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW9x.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "SpamFilter - Win32 Release"
+# Name "SpamFilter - Win32 Debug"
+# Name "SpamFilter - Win32 Release Unicode"
+# Name "SpamFilter - Win32 Debug Unicode"
+# Name "SpamFilter - Win32 Release Unicode 9x/ME"
+# Name "SpamFilter - Win32 Debug Unicode 9x/ME"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\contact.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dlg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\extraimg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\folders.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\forkthread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\logfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\menuitems.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\options.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\path.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\popup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\regexp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\services.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\spamcheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\spamcheckdata.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\spamdefinitions.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\string.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\stringlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\trigger.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\unicode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\update.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\utilities.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\variables.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\common.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\contact.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\extraimg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\folders.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\forkthread.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\logfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\menuitems.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\options.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\path.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\popup.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\regexp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\services.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\spamcheck.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\spamcheckdata.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\spamdefinitions.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\string.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\stringlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\trigger.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\unicode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\update.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\utilities.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\variables.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\Resources\add_button_16x16_256.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resources\delete_button_16x16_256.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resources\log_item.xml
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resources\log_layout.xsl
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resources\log_main.xml
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resources\spam_16x16_256.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resources\spam_32x32_256.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resources\spam_definitions_16x16_256.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resources\spam_layer_16x16_256.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\SpamFilter.rc
+# End Source File
+# End Group
+# Begin Group "Documentation"
+
+# PROP Default_Filter "*.txt"
+# Begin Source File
+
+SOURCE=".\Docs\PCRE-License.txt"
+# End Source File
+# Begin Source File
+
+SOURCE=".\Docs\SpamFilter-Developer.txt"
+# End Source File
+# Begin Source File
+
+SOURCE=".\Docs\SpamFilter-License.txt"
+# End Source File
+# Begin Source File
+
+SOURCE=".\Docs\SpamFilter-Readme.txt"
+# End Source File
+# Begin Source File
+
+SOURCE=".\Docs\SpamFilter-Translation.txt"
+# End Source File
+# End Group
+# Begin Group "Extensions"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\Extensions\filtered1.wav
+# End Source File
+# Begin Source File
+
+SOURCE=.\Extensions\filtered2.wav
+# End Source File
+# Begin Source File
+
+SOURCE=.\Extensions\filtered3.wav
+# End Source File
+# Begin Source File
+
+SOURCE=.\Extensions\InstallScript.xml
+# End Source File
+# Begin Source File
+
+SOURCE=.\m_spamfilter.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\m_spamfilter.inc
+# End Source File
+# End Group
+# Begin Group "Utilities"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\Utilities\DebugHelper.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Utilities\Pcre\include\pcre.h
+# End Source File
+# End Group
+# Begin Group "Include"
+
+# PROP Default_Filter "c;h"
+# Begin Source File
+
+SOURCE=.\Include\m_addcontact.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_alarms.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_autoshutdown.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_avatars.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_awaymsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_bkgrcfg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_button.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_chat.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_clc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_clist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_clistint.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_clui.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_cluiframes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_colourpicker.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_contactdir.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_contacts.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_contactsex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_contactstransfer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_database.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_email.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_file.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_findadd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_folders.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_fontservice.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_fuse.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_genmenu.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_history.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_httpserver.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_icolib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_icq.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_idle.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_ieview.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_ignore.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_langpack.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_mathmodule.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_message.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_metacontacts.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_netlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_options.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_plugins.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_png.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_popup.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_popupw.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_protocols.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_protomod.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_protosvc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_sessions.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_skin.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_skin_eng.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_smileyadd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_snapping_windows.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_spamfilter.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_statusplugins.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_system.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_toptoolbar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_trigger.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_uninstaller.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_updater.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_url.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_userinfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_utils.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_variables.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\m_weather.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\newpluginapi.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\statusmodes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Include\win2k.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\Info_Src.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\License_Appendix.txt
+# End Source File
+# End Target
+# End Project
diff --git a/SpamFilter.dsw b/SpamFilter.dsw
index 99809ac..759a8e8 100644
--- a/SpamFilter.dsw
+++ b/SpamFilter.dsw
@@ -1,29 +1,29 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "SpamFilter"=".\SpamFilter.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "SpamFilter"=".\SpamFilter.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/SpamFilter.rc b/SpamFilter.rc
index 2f7f7cb..7867f14 100644
--- a/SpamFilter.rc
+++ b/SpamFilter.rc
@@ -1,556 +1,556 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include <windows.h>
-#include <winres.h>
-#include <m_utils.h>
-#include <m_button.h>
-#include <m_clc.h>
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// Englisch (USA) 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_LISTBOX_ADD_ITEM DIALOGEX 0, 0, 240, 230
-STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_NOFAILCREATE |
- WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Add %s"
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- LTEXT "&New phrase/pattern:",IDC_TEXT_DESCRIPTION,5,5,120,8
- EDITTEXT IDC_EDITBOX_NEWITEM,5,15,158,12,ES_AUTOHSCROLL |
- ES_NOHIDESEL | WS_GROUP
- CONTROL "",IDC_BUTTON_REGEXP,"MButtonClass",WS_TABSTOP,165,15,13,
- 12,0x18000000L
- LTEXT "(You can use normal words or Regular Expressions)",
- IDC_TEXT_REGEXP,7,29,176,8
- DEFPUSHBUTTON "OK",IDOK,185,6,50,14,WS_DISABLED
- PUSHBUTTON "Cancel",IDCANCEL,185,23,50,14
- CONTROL "",IDC_RECT_SEPARATOR,"Static",SS_ETCHEDHORZ,0,43,246,1,
- WS_EX_STATICEDGE
- LTEXT "Quick Quide to Regular Expressions:",IDC_TEXT_QUICKHELP,
- 5,48,223,10
- LTEXT "Alternatives:",IDC_STATIC,5,60,60,8
- LTEXT "gilbert|sullivan finds ""gilbert"" or ""sullivan""",
- IDC_STATIC,72,60,163,10
- LTEXT "Subpatterns:",IDC_STATIC,5,70,60,8
- LTEXT "cat(aract|erpillar) finds ""cataract"" or ""caterpillar""",
- IDC_STATIC,72,70,163,8
- LTEXT "Repetitions:",IDC_STATIC,5,80,60,8
- LTEXT "z{2,4} matches ""zz"", ""zzz"" or ""zzzz""\r\n* is equivalent to {0,}\r\n+ is equivalent to {1,}\r\n? is equivalent to {0,1}",
- IDC_STATIC,72,80,163,34
- LTEXT "Generic Types:",IDC_STATIC,5,114,60,8
- LTEXT "\\d represents any decimal digit\r\n\\D represents any character that is not a decimal digit",
- IDC_STATIC,72,114,163,26
- LTEXT "Assertions:",IDC_STATIC,5,140,60,8
- LTEXT "(?<!foo)bar finds an occurrence of ""bar"" that is not preceded by ""foo""\r\n(?<= for positive lookahead assertions\r\n(?<! for negative lookahead assertions\r\n(?= for positive lookbehind assertions\r\n(?! for negative lookbehind assertions",
- IDC_STATIC,72,140,163,51
- LTEXT "Back References:",IDC_STATIC,5,191,60,8
- LTEXT "(sens|respons)e and \\1ibility matches ""sense and sensibility"" and ""response and responsibility"", but not ""sense and responsibility""",
- IDC_STATIC,72,191,163,26
- LTEXT "All syntax elements can be combined or nested using subpatterns.",
- IDC_TEXT_HELPNESTED,5,218,230,8
-END
-
-IDD_OPTIONS_CONFIGURE_ADVERTISMENTFILTER DIALOG DISCARDABLE 0, 0, 345, 264
-STYLE DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER | WS_POPUP | WS_VISIBLE |
- WS_CAPTION | WS_SYSMENU
-CAPTION "Configure Advertisment Filter"
-FONT 8, "MS Shell Dlg"
-BEGIN
- GROUPBOX "Bad Phrases/Patterns",IDC_GROUP_BADWORDS,7,7,160,173
- CONTROL "Look for standard &bad phrases in received messages",
- IDC_CHECKBOX_DEFAULTBADWORDS,"Button",BS_AUTOCHECKBOX |
- BS_TOP | BS_MULTILINE | WS_GROUP | WS_TABSTOP,17,19,142,
- 18
- CONTROL "Also watch for following &customized bad phrases:",
- IDC_CHECKBOX_CUSTOMIZEDBADWORDS,"Button",BS_AUTOCHECKBOX |
- BS_TOP | BS_MULTILINE | WS_TABSTOP,17,39,142,16
- LISTBOX IDC_LISTBOX_CUSTOMIZEDBADWORDS,29,59,112,69,NOT
- LBS_NOTIFY | LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT |
- LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL
- CONTROL "",IDC_BUTTON_ADDBADWORD,"MButtonClass",WS_TABSTOP,145,
- 59,14,13,0x18000000L
- CONTROL "",IDC_BUTTON_DELETEBADWORD,"MButtonClass",WS_TABSTOP,
- 145,75,14,13,0x18000000L
- LTEXT "All&owed bad phrases until spam:",
- IDC_TEXT_ALLOWEDBADWORDS,18,136,112,8,NOT WS_GROUP
- EDITTEXT IDC_EDITBOX_ALLOWEDBADWORDS,133,135,27,12,ES_AUTOHSCROLL |
- ES_NUMBER
- CONTROL "",IDC_SPIN_ALLOWEDBADWORDS,"msctls_updown32",
- UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
- UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,155,135,9,
- 11
- CONTROL "Recogni&ze different formating",IDC_CHECKBOX_FORMATING,
- "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,17,151,
- 146,8
- CONTROL "Allowed &formated bad phrases:",
- IDC_TEXT_ALLOWEDFORMATEDWORDS,"Static",SS_LEFTNOWORDWRAP,
- 30,163,102,8
- EDITTEXT IDC_EDITBOX_ALLOWEDFORMATEDWORDS,133,162,27,12,
- ES_AUTOHSCROLL | ES_NUMBER
- CONTROL "",IDC_SPIN_ALLOWEDFORMATEDWORDS,"msctls_updown32",
- UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
- UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,155,162,9,
- 11
- GROUPBOX "Known Spammers",IDC_GROUP_SPAMMERS,7,187,160,38
- CONTROL "Filter out messages from standard &known spammers",
- IDC_CHECKBOX_DEFAULTSPAMMERS,"Button",BS_AUTOCHECKBOX |
- BS_TOP | BS_MULTILINE | WS_GROUP | WS_TABSTOP,17,199,142,
- 18
- GROUPBOX "Bad Contents",IDC_GROUP_OTHERCONTENTS,177,7,160,86
- CONTROL "&URL addresses",IDC_CHECKBOX_URL,"Button",
- BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,187,21,148,8
- CONTROL "&Phone numbers",IDC_CHECKBOX_PHONENUMBERS,"Button",
- BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,187,32,148,8
- CONTROL "C&apitalized messages",IDC_CHECKBOX_CAPITALIZED,"Button",
- BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,187,43,148,8
- CONTROL "Messages containing &spaces only",IDC_CHECKBOX_EMPTY,
- "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,187,54,
- 148,8
- CONTROL "&Multiple messages with same content",
- IDC_CHECKBOX_MULTIPLEMESSAGES,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,187,65,147,8
- CONTROL "&Teaser messages",IDC_CHECKBOX_TEASERMESSAGES,"Button",
- BS_AUTOCHECKBOX | WS_TABSTOP,187,76,147,8
- GROUPBOX "Good Phrases/Patterns",IDC_GROUP_GOODWORDS,177,100,160,
- 125
- CONTROL "Messages are &no spam when containing some of the following phrases:",
- IDC_CHECKBOX_CUSTOMIZEDGOODWORDS,"Button",
- BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,187,
- 112,142,17
- LISTBOX IDC_LISTBOX_CUSTOMIZEDGOODWORDS,199,132,112,70,NOT
- LBS_NOTIFY | LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT |
- LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL
- CONTROL "",IDC_BUTTON_ADDGOODWORD,"MButtonClass",WS_TABSTOP,315,
- 132,14,13,0x18000000L
- CONTROL "",IDC_BUTTON_DELETEGOODWORD,"MButtonClass",WS_TABSTOP,
- 315,148,14,13,0x18000000L
- CONTROL "Allo&wed phrases until no spam:",
- IDC_TEXT_ALLOWEDGOODWORDS,"Static",SS_LEFTNOWORDWRAP,188,
- 208,112,8
- EDITTEXT IDC_EDITBOX_ALLOWEDGOODWORDS,303,206,27,12,
- ES_AUTOHSCROLL | ES_NUMBER
- CONTROL "",IDC_SPIN_ALLOWEDGOODWORDS,"msctls_updown32",
- UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
- UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,325,206,9,
- 11
- LTEXT "Warning: Not all Spam Definitions are available! Some features are disabled.",
- IDC_TEXT_WARNING,18,229,318,10,NOT WS_VISIBLE
- PUSHBUTTON "Spam &Definitions",IDC_BUTTON_SPAMDEFINITIONS,17,240,84,
- 14
- DEFPUSHBUTTON "OK",IDOK,221,240,50,14
- PUSHBUTTON "Cancel",IDCANCEL,279,240,50,14
-END
-
-IDD_OPTIONS_MAIN DIALOGEX 0, 0, 314, 240
-STYLE DS_FIXEDSYS | DS_NOFAILCREATE | WS_CHILD | WS_VISIBLE
-EXSTYLE WS_EX_CONTROLPARENT
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- GROUPBOX "Spam Filter",IDC_STATIC,0,0,314,112
- CONTROL "&Advertisment Filter (recommended)",
- IDC_CHECKBOX_ADVERTISMENTFILTER,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,10,14,213,8
- LTEXT "Filters out advertisments from unknown users that are not on the contact list.",
- IDC_TEXT_ADVERTISMENTFILTER,22,24,201,17
- PUSHBUTTON "C&onfigure...",IDC_BUTTON_ADVERTISMENTFILTER,237,22,61,
- 14
- CONTROL "&Robot Filter",IDC_CHECKBOX_ROBOTFILTER,"Button",
- BS_AUTOCHECKBOX | WS_TABSTOP,10,45,213,8
- LTEXT "Filters out all automated messages from unknown contacts via requesting a correct answer from the sender.",
- IDC_TEXT_ROBOTFILTER,22,55,201,17
- PUSHBUTTON "Co&nfigure...",IDC_BUTTON_ROBOTFILTER,237,53,61,14
- CONTROL "&Disliked Messages Filter",
- IDC_CHECKBOX_DISLIKEDMESSAGEFILTER,"Button",
- BS_AUTOCHECKBOX | WS_TABSTOP,10,76,213,8
- LTEXT "Filters out disliked messages such as hoax messages from known contacts that are on your contact list.",
- IDC_TEXT_DISLIKEDMESSAGEFILTER,22,86,201,17
- PUSHBUTTON "Con&figure...",IDC_BUTTON_DISLIKEDMESSAGEFILTER,237,84,
- 61,14
- GROUPBOX "Auto Ignore",IDC_GROUP_IGNORE,0,117,171,64
- CONTROL "Automatically &ignore spamming users",
- IDC_CHECKBOX_AUTOADDSPAMMERS,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,7,129,158,10
- CONTROL "Allowed spam per &user:",IDC_TEXT_ALLOWEDSPAMMESSAGES,
- "Static",SS_LEFTNOWORDWRAP,20,142,108,8
- EDITTEXT IDC_EDITBOX_ALLOWEDSPAMMESSAGES,131,140,32,12,
- ES_AUTOHSCROLL | ES_NUMBER
- CONTROL "",IDC_SPIN_ALLOWEDSPAMMESSAGES,"msctls_updown32",
- UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
- UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,157,140,8,
- 11
- PUSHBUTTON "Rese&t...",IDC_BUTTON_RESETAUTOIGNORE,19,159,70,14,
- WS_DISABLED
- PUSHBUTTON "Spa&mmers",IDC_BUTTON_SHOWSPAMMERS,93,159,70,14
- GROUPBOX "Spam Notification",IDC_GROUP_LOGGING,0,185,171,55
- CONTROL "Show &popup on spam message",IDC_CHECKBOX_POPUP,"Button",
- BS_AUTOCHECKBOX | BS_TOP | WS_GROUP | WS_TABSTOP,7,197,
- 158,9
- CONTROL "&Log spam messages to file:",IDC_CHECKBOX_LOGGING,
- "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,7,210,
- 157,8
- EDITTEXT IDC_EDITBOX_LOGFILE,19,220,102,13,ES_AUTOHSCROLL
- PUSHBUTTON "&...",IDC_BUTTON_LOGBROWSE,107,220,15,13,BS_ICON |
- BS_CENTER | BS_VCENTER
- PUSHBUTTON "&Show",IDC_BUTTON_OPENLOG,124,220,41,13,WS_DISABLED
- GROUPBOX "Behaviour",IDC_GROUP_BEHAVIOUR,178,117,135,40
- CONTROL "Mar&k spam messages as read",IDC_RADIO_MARKREADMSG,
- "Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,186,
- 130,121,8
- CONTROL "D&elete spam messages",IDC_RADIO_DELETEMSG,"Button",
- BS_AUTORADIOBUTTON | WS_TABSTOP,186,142,121,8
- GROUPBOX "Message Types",IDC_GROUP_MESSAGETYPES,178,161,135,79
- LTEXT "Types of incoming e&vents which shall be checked for spam:",
- IDC_TEXT_MESSAGETYPES,183,171,124,17
- CONTROL "",IDC_TREEVIEW_MESSAGETYPES,"SysTreeView32",
- TVS_DISABLEDRAGDROP | WS_BORDER | WS_TABSTOP | 0x8000,
- 184,189,123,45
-END
-
-IDD_OPTIONS_CONFIGURE_DISLIKEDMESSAGEFILTER DIALOGEX 0, 0, 353, 227
-STYLE DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER | WS_POPUP | WS_VISIBLE |
- WS_CAPTION | WS_SYSMENU
-CAPTION "Configure Disliked Messages Filter"
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- GROUPBOX "Disliked Contents",IDC_GROUP_OTHERCONTENTS,7,7,160,53
- CONTROL "&Multiple messages with same content",
- IDC_CHECKBOX_MULTIPLEMESSAGES,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,18,20,147,8
- CONTROL "Messages containing &known hoax message texts",
- IDC_CHECKBOX_HOAXTEXTS,"Button",BS_AUTOCHECKBOX | BS_TOP |
- BS_MULTILINE | WS_GROUP | WS_TABSTOP,18,34,146,19
- GROUPBOX "Indicating Phrases/Patterns",IDC_GROUP_WORDS,7,67,160,
- 122
- CONTROL "Look for the following indicating &phrases:",
- IDC_CHECKBOX_CUSTOMIZEDWORDS,"Button",BS_AUTOCHECKBOX |
- BS_TOP | BS_MULTILINE | WS_TABSTOP,18,79,142,16
- LISTBOX IDC_LISTBOX_CUSTOMIZEDWORDS,30,99,112,78,NOT LBS_NOTIFY |
- LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT |
- LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL
- CONTROL "",IDC_BUTTON_ADDWORD,"MButtonClass",WS_TABSTOP,145,98,
- 14,13,0x18000000L
- CONTROL "",IDC_BUTTON_DELETEWORD,"MButtonClass",WS_TABSTOP,145,
- 114,14,13,0x18000000L
- GROUPBOX "Auto Reply",IDC_GROUP_NOTIFYSENDER,177,7,168,182
- CONTROL "Auto &reply to disliked messages using the following text:",
- IDC_CHECKBOX_NOTIFYSENDER,"Button",BS_AUTOCHECKBOX |
- BS_TOP | BS_MULTILINE | WS_TABSTOP,187,20,153,17
- EDITTEXT IDC_EDITBOX_NOTIFYSENDER,200,39,137,92,ES_MULTILINE |
- ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
- LTEXT "(You can use the substitute symbols %sender% and %message% for the appropriate contents.)",
- IDC_TEXT_NOTIFYSENDER,200,134,122,26
- CONTROL "",IDC_BUTTON_NOTIFYSENDER_VARIABLES,"MButtonClass",
- WS_TABSTOP,323,134,14,13,0x18000000L
- CONTROL "Add the reply to contact &history",
- IDC_CHECKBOX_ADDTOHISTORY,"Button",BS_AUTOCHECKBOX |
- BS_TOP | BS_MULTILINE | WS_TABSTOP,187,163,153,18
- LTEXT "Warning: Not all Spam Definitions are available! Some features are disabled.",
- IDC_TEXT_WARNING,18,192,327,10,NOT WS_VISIBLE
- PUSHBUTTON "Spam &Definitions",IDC_BUTTON_SPAMDEFINITIONS,17,203,84,
- 14
- DEFPUSHBUTTON "OK",IDOK,225,203,50,14
- PUSHBUTTON "Cancel",IDCANCEL,283,203,50,14
-END
-
-IDD_OPTIONS_CONFIGURE_ROBOTFILTER DIALOG DISCARDABLE 0, 0, 329, 287
-STYLE DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER | WS_POPUP | WS_VISIBLE |
- WS_CAPTION | WS_SYSMENU
-CAPTION "Configure Robot Filter"
-FONT 8, "MS Shell Dlg"
-BEGIN
- GROUPBOX "Message Texts",IDC_GROUP_MESSAGETEXTS,7,7,314,161
- LTEXT "&Instruction:",IDC_STATIC,20,20,290,8
- EDITTEXT IDC_EDITBOX_INSTRUCTION,20,29,290,40,ES_MULTILINE |
- ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
- CONTROL "",IDC_BUTTON_INSTRUCTION_VARIABLES,"MButtonClass",
- WS_TABSTOP,296,70,14,13,0x18000000L
- LTEXT "&Confirmation:",IDC_STATIC,20,75,271,8
- EDITTEXT IDC_EDITBOX_CONFIRMATION,20,85,290,40,ES_MULTILINE |
- ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
- CONTROL "",IDC_BUTTON_CONFIRMATION_VARIABLES,"MButtonClass",
- WS_TABSTOP,296,127,14,13,0x18000000L
- LTEXT "(You can use the substitute symbols %sender%, %message%, %securitycode% and %triesleft% for the appropriate contents.)",
- IDC_TEXT_VARS,20,130,271,18
- CONTROL "Add the message texts to contact &history",
- IDC_CHECKBOX_ADDTOHISTORY,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,20,149,290,10
- GROUPBOX "Security Code",IDC_GROUP_ANSWER,7,177,314,59
- LTEXT "The following text needs to be replied by the contact to confirm that the message was not sent automatically:",
- IDC_STATIC,20,188,163,32
- EDITTEXT IDC_EDITBOX_ANSWER,187,195,79,12,ES_AUTOHSCROLL
- PUSHBUTTON "&Random",IDC_BUTTON_ANSWER,268,195,42,12
- LTEXT "(You can use readable words, too.)",IDC_STATIC,187,210,
- 123,8
- CONTROL "&Hide users until they identified themselves",
- IDC_CHECKBOX_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
- 20,219,290,10
- LTEXT "Note: The filter gets invoked after the Advertisment Filter.\r\nThus, no instruction message will be sent in reply to advertisment messages.",
- IDC_TEXT_WARNING,20,241,301,19
- DEFPUSHBUTTON "OK",IDOK,204,265,50,14
- PUSHBUTTON "Cancel",IDCANCEL,260,265,50,14
-END
-
-IDD_INFO_SPAMDEFINITIONS DIALOGEX 0, 0, 248, 194
-STYLE DS_SETFOREGROUND | DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER |
- WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
-CAPTION "Spam Definitions: %s"
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- LTEXT "Installed Spam Definitions for filter:",
- IDC_TEXT_DESCRIPTION,3,3,242,10
- CONTROL "",IDC_LISTVIEW_SPAMDEFINITIONS,"SysListView32",
- LVS_REPORT | LVS_SINGLESEL | LVS_SORTASCENDING |
- LVS_NOSORTHEADER | WS_TABSTOP,5,29,238,138,
- WS_EX_STATICEDGE
- CONTROL "",IDC_TAB_SPAMDEFINITIONS,"SysTabControl32",
- TCS_HOTTRACK | TCS_MULTILINE | TCS_FOCUSNEVER |
- WS_TABSTOP,2,14,244,156
- CONTROL "Download more Spam Definitions",IDC_URL_GETMORE,
- "Hyperlink",WS_TABSTOP | 0x1,2,177,187,9
- SCROLLBAR IDC_SCROLLBAR_SIZEGRIP,242,188,6,6,
- SBS_SIZEBOXBOTTOMRIGHTALIGN | SBS_SIZEGRIP
- DEFPUSHBUTTON "OK",IDCANCEL,190,174,50,14
-END
-
-IDD_INFO_SPAMMERS DIALOGEX 0, 0, 253, 142
-STYLE DS_SETFOREGROUND | DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER |
- WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
-CAPTION "Ignored Spammers"
-FONT 8, "MS Shell Dlg"
-BEGIN
- PUSHBUTTON "OK",IDOK,193,102,53,14
- PUSHBUTTON "Cancel",IDCANCEL,193,120,53,14
- LTEXT "The following contacts were recognized as spammers:",
- IDC_TEXT_DESCRIPTION,4,5,247,8
- CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x193,4,17,180,
- 69,WS_EX_CLIENTEDGE
- ICON "",IDC_ICON_SPAM,187,13,20,20,SS_NOTIFY | SS_CENTERIMAGE
- LTEXT "Spammer",IDC_TEXT_SPAM,205,19,45,8,SS_NOPREFIX |
- SS_CENTERIMAGE
- ICON "",IDC_ICON_DELETE,187,28,20,20,SS_NOTIFY |
- SS_CENTERIMAGE
- LTEXT "Delete",IDC_TEXT_DELETE,205,34,45,8,SS_NOPREFIX |
- SS_CENTERIMAGE
- ICON "",IDC_ICON_NORMAL,187,43,20,20,SS_NOTIFY |
- SS_CENTERIMAGE
- LTEXT "Accept",IDC_TEXT_NORMAL,205,49,45,8,SS_NOPREFIX |
- SS_CENTERIMAGE
- GROUPBOX "",IDC_GROUP,4,87,180,51
- CONTROL "&Hide spammers from contact list",IDC_CHECKBOX_HIDE,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,96,166,10
- CONTROL "Store spammers in special &group:",IDC_CHECKBOX_GROUP,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,108,166,10
- EDITTEXT IDC_EDITBOX_GROUP,22,119,155,13,ES_AUTOHSCROLL
- SCROLLBAR IDC_SCROLLBAR_SIZEGRIP,247,136,6,6,
- SBS_SIZEBOXBOTTOMRIGHTALIGN | SBS_SIZEGRIP
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// DESIGNINFO
-//
-
-#ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO MOVEABLE PURE
-BEGIN
- IDD_LISTBOX_ADD_ITEM, DIALOG
- BEGIN
- VERTGUIDE, 65
- VERTGUIDE, 72
- VERTGUIDE, 235
- HORZGUIDE, 15
- HORZGUIDE, 60
- HORZGUIDE, 70
- HORZGUIDE, 80
- HORZGUIDE, 114
- HORZGUIDE, 140
- HORZGUIDE, 191
- END
-
- IDD_OPTIONS_CONFIGURE_ADVERTISMENTFILTER, DIALOG
- BEGIN
- VERTGUIDE, 7
- VERTGUIDE, 12
- VERTGUIDE, 18
- VERTGUIDE, 29
- VERTGUIDE, 159
- VERTGUIDE, 187
- VERTGUIDE, 199
- VERTGUIDE, 211
- VERTGUIDE, 329
- HORZGUIDE, 19
- HORZGUIDE, 39
- HORZGUIDE, 59
- HORZGUIDE, 107
- HORZGUIDE, 112
- HORZGUIDE, 139
- HORZGUIDE, 255
- END
-
- IDD_OPTIONS_MAIN, DIALOG
- BEGIN
- VERTGUIDE, 3
- VERTGUIDE, 10
- VERTGUIDE, 16
- VERTGUIDE, 19
- VERTGUIDE, 163
- VERTGUIDE, 171
- VERTGUIDE, 174
- VERTGUIDE, 182
- VERTGUIDE, 212
- VERTGUIDE, 226
- VERTGUIDE, 287
- VERTGUIDE, 308
- HORZGUIDE, 115
- HORZGUIDE, 128
- HORZGUIDE, 138
- HORZGUIDE, 150
- HORZGUIDE, 170
- HORZGUIDE, 172
- HORZGUIDE, 238
- END
-
- IDD_OPTIONS_CONFIGURE_DISLIKEDMESSAGEFILTER, DIALOG
- BEGIN
- VERTGUIDE, 7
- VERTGUIDE, 12
- VERTGUIDE, 18
- VERTGUIDE, 159
- VERTGUIDE, 167
- VERTGUIDE, 187
- VERTGUIDE, 201
- VERTGUIDE, 337
- HORZGUIDE, 7
- HORZGUIDE, 20
- HORZGUIDE, 189
- HORZGUIDE, 217
- END
-
- IDD_OPTIONS_CONFIGURE_ROBOTFILTER, DIALOG
- BEGIN
- VERTGUIDE, 7
- VERTGUIDE, 13
- VERTGUIDE, 20
- VERTGUIDE, 310
- VERTGUIDE, 321
- HORZGUIDE, 11
- END
-
- IDD_INFO_SPAMMERS, DIALOG
- BEGIN
- VERTGUIDE, 4
- VERTGUIDE, 10
- VERTGUIDE, 184
- END
-END
-#endif // APSTUDIO_INVOKED
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE MOVEABLE PURE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE MOVEABLE PURE
-BEGIN
- "#include <windows.h>\r\n"
- "#include <winres.h>\r\n"
- "#include ""Include\\m_utils.h""\r\n"
- "#include ""Include\\m_button.h""\r\n"
- "#include ""Include\\m_clc.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE MOVEABLE PURE
-BEGIN
- "#include ""version.rc""\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDI_DEFAULT ICON DISCARDABLE "Resources\\spam_16x16_256.ico"
-IDI_SPAM_LAYER ICON DISCARDABLE "Resources\\spam_layer_16x16_256.ico"
-IDI_ADD_BUTTON ICON DISCARDABLE "Resources\\add_button_16x16_256.ico"
-IDI_DELETE_BUTTON ICON DISCARDABLE "Resources\\delete_button_16x16_256.ico"
-IDI_DEFAULT_LARGE ICON DISCARDABLE "Resources\\spam_32x32_256.ico"
-IDI_SPAM_DEFINITIONS ICON DISCARDABLE "resources\\spam_definitions_16x16_256.ico"
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Menu
-//
-
-IDR_CONTEXT MENU DISCARDABLE
-BEGIN
- POPUP "WordsList"
- BEGIN
- MENUITEM "&Remove", ID_MENU_DELETE
- MENUITEM "&Add...", ID_MENU_ADD
- END
- POPUP "SpamDef"
- BEGIN
- MENUITEM "&Remove...", ID_MENU_DELETE
- END
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXT
-//
-
-IDR_XMLFILETEMPLATE TEXT MOVEABLE PURE "Resources\\log_main.xml"
-IDR_XMLITEMTEMPLATE TEXT MOVEABLE PURE "Resources\\log_item.xml"
-IDR_XSLLAYOUTFILETEMPLATE TEXT MOVEABLE PURE "Resources\\log_layout.xsl"
-#endif // Englisch (USA) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-#include "version.rc"
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+#include <winres.h>
+#include <m_utils.h>
+#include <m_button.h>
+#include <m_clc.h>
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Englisch (USA) 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_LISTBOX_ADD_ITEM DIALOGEX 0, 0, 240, 230
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_NOFAILCREATE |
+ WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Add %s"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "&New phrase/pattern:",IDC_TEXT_DESCRIPTION,5,5,120,8
+ EDITTEXT IDC_EDITBOX_NEWITEM,5,15,158,12,ES_AUTOHSCROLL |
+ ES_NOHIDESEL | WS_GROUP
+ CONTROL "",IDC_BUTTON_REGEXP,"MButtonClass",WS_TABSTOP,165,15,13,
+ 12,0x18000000L
+ LTEXT "(You can use normal words or Regular Expressions)",
+ IDC_TEXT_REGEXP,7,29,176,8
+ DEFPUSHBUTTON "OK",IDOK,185,6,50,14,WS_DISABLED
+ PUSHBUTTON "Cancel",IDCANCEL,185,23,50,14
+ CONTROL "",IDC_RECT_SEPARATOR,"Static",SS_ETCHEDHORZ,0,43,246,1,
+ WS_EX_STATICEDGE
+ LTEXT "Quick Quide to Regular Expressions:",IDC_TEXT_QUICKHELP,
+ 5,48,223,10
+ LTEXT "Alternatives:",IDC_STATIC,5,60,60,8
+ LTEXT "gilbert|sullivan finds ""gilbert"" or ""sullivan""",
+ IDC_STATIC,72,60,163,10
+ LTEXT "Subpatterns:",IDC_STATIC,5,70,60,8
+ LTEXT "cat(aract|erpillar) finds ""cataract"" or ""caterpillar""",
+ IDC_STATIC,72,70,163,8
+ LTEXT "Repetitions:",IDC_STATIC,5,80,60,8
+ LTEXT "z{2,4} matches ""zz"", ""zzz"" or ""zzzz""\r\n* is equivalent to {0,}\r\n+ is equivalent to {1,}\r\n? is equivalent to {0,1}",
+ IDC_STATIC,72,80,163,34
+ LTEXT "Generic Types:",IDC_STATIC,5,114,60,8
+ LTEXT "\\d represents any decimal digit\r\n\\D represents any character that is not a decimal digit",
+ IDC_STATIC,72,114,163,26
+ LTEXT "Assertions:",IDC_STATIC,5,140,60,8
+ LTEXT "(?<!foo)bar finds an occurrence of ""bar"" that is not preceded by ""foo""\r\n(?<= for positive lookahead assertions\r\n(?<! for negative lookahead assertions\r\n(?= for positive lookbehind assertions\r\n(?! for negative lookbehind assertions",
+ IDC_STATIC,72,140,163,51
+ LTEXT "Back References:",IDC_STATIC,5,191,60,8
+ LTEXT "(sens|respons)e and \\1ibility matches ""sense and sensibility"" and ""response and responsibility"", but not ""sense and responsibility""",
+ IDC_STATIC,72,191,163,26
+ LTEXT "All syntax elements can be combined or nested using subpatterns.",
+ IDC_TEXT_HELPNESTED,5,218,230,8
+END
+
+IDD_OPTIONS_CONFIGURE_ADVERTISMENTFILTER DIALOG DISCARDABLE 0, 0, 345, 264
+STYLE DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER | WS_POPUP | WS_VISIBLE |
+ WS_CAPTION | WS_SYSMENU
+CAPTION "Configure Advertisment Filter"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Bad Phrases/Patterns",IDC_GROUP_BADWORDS,7,7,160,173
+ CONTROL "Look for standard &bad phrases in received messages",
+ IDC_CHECKBOX_DEFAULTBADWORDS,"Button",BS_AUTOCHECKBOX |
+ BS_TOP | BS_MULTILINE | WS_GROUP | WS_TABSTOP,17,19,142,
+ 18
+ CONTROL "Also watch for following &customized bad phrases:",
+ IDC_CHECKBOX_CUSTOMIZEDBADWORDS,"Button",BS_AUTOCHECKBOX |
+ BS_TOP | BS_MULTILINE | WS_TABSTOP,17,39,142,16
+ LISTBOX IDC_LISTBOX_CUSTOMIZEDBADWORDS,29,59,112,69,NOT
+ LBS_NOTIFY | LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT |
+ LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL
+ CONTROL "",IDC_BUTTON_ADDBADWORD,"MButtonClass",WS_TABSTOP,145,
+ 59,14,13,0x18000000L
+ CONTROL "",IDC_BUTTON_DELETEBADWORD,"MButtonClass",WS_TABSTOP,
+ 145,75,14,13,0x18000000L
+ LTEXT "All&owed bad phrases until spam:",
+ IDC_TEXT_ALLOWEDBADWORDS,18,136,112,8,NOT WS_GROUP
+ EDITTEXT IDC_EDITBOX_ALLOWEDBADWORDS,133,135,27,12,ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "",IDC_SPIN_ALLOWEDBADWORDS,"msctls_updown32",
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,155,135,9,
+ 11
+ CONTROL "Recogni&ze different formating",IDC_CHECKBOX_FORMATING,
+ "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,17,151,
+ 146,8
+ CONTROL "Allowed &formated bad phrases:",
+ IDC_TEXT_ALLOWEDFORMATEDWORDS,"Static",SS_LEFTNOWORDWRAP,
+ 30,163,102,8
+ EDITTEXT IDC_EDITBOX_ALLOWEDFORMATEDWORDS,133,162,27,12,
+ ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_SPIN_ALLOWEDFORMATEDWORDS,"msctls_updown32",
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,155,162,9,
+ 11
+ GROUPBOX "Known Spammers",IDC_GROUP_SPAMMERS,7,187,160,38
+ CONTROL "Filter out messages from standard &known spammers",
+ IDC_CHECKBOX_DEFAULTSPAMMERS,"Button",BS_AUTOCHECKBOX |
+ BS_TOP | BS_MULTILINE | WS_GROUP | WS_TABSTOP,17,199,142,
+ 18
+ GROUPBOX "Bad Contents",IDC_GROUP_OTHERCONTENTS,177,7,160,86
+ CONTROL "&URL addresses",IDC_CHECKBOX_URL,"Button",
+ BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,187,21,148,8
+ CONTROL "&Phone numbers",IDC_CHECKBOX_PHONENUMBERS,"Button",
+ BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,187,32,148,8
+ CONTROL "C&apitalized messages",IDC_CHECKBOX_CAPITALIZED,"Button",
+ BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,187,43,148,8
+ CONTROL "Messages containing &spaces only",IDC_CHECKBOX_EMPTY,
+ "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,187,54,
+ 148,8
+ CONTROL "&Multiple messages with same content",
+ IDC_CHECKBOX_MULTIPLEMESSAGES,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,187,65,147,8
+ CONTROL "&Teaser messages",IDC_CHECKBOX_TEASERMESSAGES,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,187,76,147,8
+ GROUPBOX "Good Phrases/Patterns",IDC_GROUP_GOODWORDS,177,100,160,
+ 125
+ CONTROL "Messages are &no spam when containing some of the following phrases:",
+ IDC_CHECKBOX_CUSTOMIZEDGOODWORDS,"Button",
+ BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,187,
+ 112,142,17
+ LISTBOX IDC_LISTBOX_CUSTOMIZEDGOODWORDS,199,132,112,70,NOT
+ LBS_NOTIFY | LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT |
+ LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL
+ CONTROL "",IDC_BUTTON_ADDGOODWORD,"MButtonClass",WS_TABSTOP,315,
+ 132,14,13,0x18000000L
+ CONTROL "",IDC_BUTTON_DELETEGOODWORD,"MButtonClass",WS_TABSTOP,
+ 315,148,14,13,0x18000000L
+ CONTROL "Allo&wed phrases until no spam:",
+ IDC_TEXT_ALLOWEDGOODWORDS,"Static",SS_LEFTNOWORDWRAP,188,
+ 208,112,8
+ EDITTEXT IDC_EDITBOX_ALLOWEDGOODWORDS,303,206,27,12,
+ ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_SPIN_ALLOWEDGOODWORDS,"msctls_updown32",
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,325,206,9,
+ 11
+ LTEXT "Warning: Not all Spam Definitions are available! Some features are disabled.",
+ IDC_TEXT_WARNING,18,229,318,10,NOT WS_VISIBLE
+ PUSHBUTTON "Spam &Definitions",IDC_BUTTON_SPAMDEFINITIONS,17,240,84,
+ 14
+ DEFPUSHBUTTON "OK",IDOK,221,240,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,279,240,50,14
+END
+
+IDD_OPTIONS_MAIN DIALOGEX 0, 0, 314, 240
+STYLE DS_FIXEDSYS | DS_NOFAILCREATE | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Spam Filter",IDC_STATIC,0,0,314,112
+ CONTROL "&Advertisment Filter (recommended)",
+ IDC_CHECKBOX_ADVERTISMENTFILTER,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,10,14,213,8
+ LTEXT "Filters out advertisments from unknown users that are not on the contact list.",
+ IDC_TEXT_ADVERTISMENTFILTER,22,24,201,17
+ PUSHBUTTON "C&onfigure...",IDC_BUTTON_ADVERTISMENTFILTER,237,22,61,
+ 14
+ CONTROL "&Robot Filter",IDC_CHECKBOX_ROBOTFILTER,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,10,45,213,8
+ LTEXT "Filters out all automated messages from unknown contacts via requesting a correct answer from the sender.",
+ IDC_TEXT_ROBOTFILTER,22,55,201,17
+ PUSHBUTTON "Co&nfigure...",IDC_BUTTON_ROBOTFILTER,237,53,61,14
+ CONTROL "&Disliked Messages Filter",
+ IDC_CHECKBOX_DISLIKEDMESSAGEFILTER,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,10,76,213,8
+ LTEXT "Filters out disliked messages such as hoax messages from known contacts that are on your contact list.",
+ IDC_TEXT_DISLIKEDMESSAGEFILTER,22,86,201,17
+ PUSHBUTTON "Con&figure...",IDC_BUTTON_DISLIKEDMESSAGEFILTER,237,84,
+ 61,14
+ GROUPBOX "Auto Ignore",IDC_GROUP_IGNORE,0,117,171,64
+ CONTROL "Automatically &ignore spamming users",
+ IDC_CHECKBOX_AUTOADDSPAMMERS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,7,129,158,10
+ CONTROL "Allowed spam per &user:",IDC_TEXT_ALLOWEDSPAMMESSAGES,
+ "Static",SS_LEFTNOWORDWRAP,20,142,108,8
+ EDITTEXT IDC_EDITBOX_ALLOWEDSPAMMESSAGES,131,140,32,12,
+ ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_SPIN_ALLOWEDSPAMMESSAGES,"msctls_updown32",
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,157,140,8,
+ 11
+ PUSHBUTTON "Rese&t...",IDC_BUTTON_RESETAUTOIGNORE,19,159,70,14,
+ WS_DISABLED
+ PUSHBUTTON "Spa&mmers",IDC_BUTTON_SHOWSPAMMERS,93,159,70,14
+ GROUPBOX "Spam Notification",IDC_GROUP_LOGGING,0,185,171,55
+ CONTROL "Show &popup on spam message",IDC_CHECKBOX_POPUP,"Button",
+ BS_AUTOCHECKBOX | BS_TOP | WS_GROUP | WS_TABSTOP,7,197,
+ 158,9
+ CONTROL "&Log spam messages to file:",IDC_CHECKBOX_LOGGING,
+ "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,7,210,
+ 157,8
+ EDITTEXT IDC_EDITBOX_LOGFILE,19,220,102,13,ES_AUTOHSCROLL
+ PUSHBUTTON "&...",IDC_BUTTON_LOGBROWSE,107,220,15,13,BS_ICON |
+ BS_CENTER | BS_VCENTER
+ PUSHBUTTON "&Show",IDC_BUTTON_OPENLOG,124,220,41,13,WS_DISABLED
+ GROUPBOX "Behaviour",IDC_GROUP_BEHAVIOUR,178,117,135,40
+ CONTROL "Mar&k spam messages as read",IDC_RADIO_MARKREADMSG,
+ "Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,186,
+ 130,121,8
+ CONTROL "D&elete spam messages",IDC_RADIO_DELETEMSG,"Button",
+ BS_AUTORADIOBUTTON | WS_TABSTOP,186,142,121,8
+ GROUPBOX "Message Types",IDC_GROUP_MESSAGETYPES,178,161,135,79
+ LTEXT "Types of incoming e&vents which shall be checked for spam:",
+ IDC_TEXT_MESSAGETYPES,183,171,124,17
+ CONTROL "",IDC_TREEVIEW_MESSAGETYPES,"SysTreeView32",
+ TVS_DISABLEDRAGDROP | WS_BORDER | WS_TABSTOP | 0x8000,
+ 184,189,123,45
+END
+
+IDD_OPTIONS_CONFIGURE_DISLIKEDMESSAGEFILTER DIALOGEX 0, 0, 353, 227
+STYLE DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER | WS_POPUP | WS_VISIBLE |
+ WS_CAPTION | WS_SYSMENU
+CAPTION "Configure Disliked Messages Filter"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Disliked Contents",IDC_GROUP_OTHERCONTENTS,7,7,160,53
+ CONTROL "&Multiple messages with same content",
+ IDC_CHECKBOX_MULTIPLEMESSAGES,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,18,20,147,8
+ CONTROL "Messages containing &known hoax message texts",
+ IDC_CHECKBOX_HOAXTEXTS,"Button",BS_AUTOCHECKBOX | BS_TOP |
+ BS_MULTILINE | WS_GROUP | WS_TABSTOP,18,34,146,19
+ GROUPBOX "Indicating Phrases/Patterns",IDC_GROUP_WORDS,7,67,160,
+ 122
+ CONTROL "Look for the following indicating &phrases:",
+ IDC_CHECKBOX_CUSTOMIZEDWORDS,"Button",BS_AUTOCHECKBOX |
+ BS_TOP | BS_MULTILINE | WS_TABSTOP,18,79,142,16
+ LISTBOX IDC_LISTBOX_CUSTOMIZEDWORDS,30,99,112,78,NOT LBS_NOTIFY |
+ LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT |
+ LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL
+ CONTROL "",IDC_BUTTON_ADDWORD,"MButtonClass",WS_TABSTOP,145,98,
+ 14,13,0x18000000L
+ CONTROL "",IDC_BUTTON_DELETEWORD,"MButtonClass",WS_TABSTOP,145,
+ 114,14,13,0x18000000L
+ GROUPBOX "Auto Reply",IDC_GROUP_NOTIFYSENDER,177,7,168,182
+ CONTROL "Auto &reply to disliked messages using the following text:",
+ IDC_CHECKBOX_NOTIFYSENDER,"Button",BS_AUTOCHECKBOX |
+ BS_TOP | BS_MULTILINE | WS_TABSTOP,187,20,153,17
+ EDITTEXT IDC_EDITBOX_NOTIFYSENDER,200,39,137,92,ES_MULTILINE |
+ ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ LTEXT "(You can use the substitute symbols %sender% and %message% for the appropriate contents.)",
+ IDC_TEXT_NOTIFYSENDER,200,134,122,26
+ CONTROL "",IDC_BUTTON_NOTIFYSENDER_VARIABLES,"MButtonClass",
+ WS_TABSTOP,323,134,14,13,0x18000000L
+ CONTROL "Add the reply to contact &history",
+ IDC_CHECKBOX_ADDTOHISTORY,"Button",BS_AUTOCHECKBOX |
+ BS_TOP | BS_MULTILINE | WS_TABSTOP,187,163,153,18
+ LTEXT "Warning: Not all Spam Definitions are available! Some features are disabled.",
+ IDC_TEXT_WARNING,18,192,327,10,NOT WS_VISIBLE
+ PUSHBUTTON "Spam &Definitions",IDC_BUTTON_SPAMDEFINITIONS,17,203,84,
+ 14
+ DEFPUSHBUTTON "OK",IDOK,225,203,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,283,203,50,14
+END
+
+IDD_OPTIONS_CONFIGURE_ROBOTFILTER DIALOG DISCARDABLE 0, 0, 329, 287
+STYLE DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER | WS_POPUP | WS_VISIBLE |
+ WS_CAPTION | WS_SYSMENU
+CAPTION "Configure Robot Filter"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Message Texts",IDC_GROUP_MESSAGETEXTS,7,7,314,161
+ LTEXT "&Instruction:",IDC_STATIC,20,20,290,8
+ EDITTEXT IDC_EDITBOX_INSTRUCTION,20,29,290,40,ES_MULTILINE |
+ ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ CONTROL "",IDC_BUTTON_INSTRUCTION_VARIABLES,"MButtonClass",
+ WS_TABSTOP,296,70,14,13,0x18000000L
+ LTEXT "&Confirmation:",IDC_STATIC,20,75,271,8
+ EDITTEXT IDC_EDITBOX_CONFIRMATION,20,85,290,40,ES_MULTILINE |
+ ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ CONTROL "",IDC_BUTTON_CONFIRMATION_VARIABLES,"MButtonClass",
+ WS_TABSTOP,296,127,14,13,0x18000000L
+ LTEXT "(You can use the substitute symbols %sender%, %message%, %securitycode% and %triesleft% for the appropriate contents.)",
+ IDC_TEXT_VARS,20,130,271,18
+ CONTROL "Add the message texts to contact &history",
+ IDC_CHECKBOX_ADDTOHISTORY,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,20,149,290,10
+ GROUPBOX "Security Code",IDC_GROUP_ANSWER,7,177,314,59
+ LTEXT "The following text needs to be replied by the contact to confirm that the message was not sent automatically:",
+ IDC_STATIC,20,188,163,32
+ EDITTEXT IDC_EDITBOX_ANSWER,187,195,79,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Random",IDC_BUTTON_ANSWER,268,195,42,12
+ LTEXT "(You can use readable words, too.)",IDC_STATIC,187,210,
+ 123,8
+ CONTROL "&Hide users until they identified themselves",
+ IDC_CHECKBOX_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 20,219,290,10
+ LTEXT "Note: The filter gets invoked after the Advertisment Filter.\r\nThus, no instruction message will be sent in reply to advertisment messages.",
+ IDC_TEXT_WARNING,20,241,301,19
+ DEFPUSHBUTTON "OK",IDOK,204,265,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,260,265,50,14
+END
+
+IDD_INFO_SPAMDEFINITIONS DIALOGEX 0, 0, 248, 194
+STYLE DS_SETFOREGROUND | DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER |
+ WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+CAPTION "Spam Definitions: %s"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Installed Spam Definitions for filter:",
+ IDC_TEXT_DESCRIPTION,3,3,242,10
+ CONTROL "",IDC_LISTVIEW_SPAMDEFINITIONS,"SysListView32",
+ LVS_REPORT | LVS_SINGLESEL | LVS_SORTASCENDING |
+ LVS_NOSORTHEADER | WS_TABSTOP,5,29,238,138,
+ WS_EX_STATICEDGE
+ CONTROL "",IDC_TAB_SPAMDEFINITIONS,"SysTabControl32",
+ TCS_HOTTRACK | TCS_MULTILINE | TCS_FOCUSNEVER |
+ WS_TABSTOP,2,14,244,156
+ CONTROL "Download more Spam Definitions",IDC_URL_GETMORE,
+ "Hyperlink",WS_TABSTOP | 0x1,2,177,187,9
+ SCROLLBAR IDC_SCROLLBAR_SIZEGRIP,242,188,6,6,
+ SBS_SIZEBOXBOTTOMRIGHTALIGN | SBS_SIZEGRIP
+ DEFPUSHBUTTON "OK",IDCANCEL,190,174,50,14
+END
+
+IDD_INFO_SPAMMERS DIALOGEX 0, 0, 253, 142
+STYLE DS_SETFOREGROUND | DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER |
+ WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+CAPTION "Ignored Spammers"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ PUSHBUTTON "OK",IDOK,193,102,53,14
+ PUSHBUTTON "Cancel",IDCANCEL,193,120,53,14
+ LTEXT "The following contacts were recognized as spammers:",
+ IDC_TEXT_DESCRIPTION,4,5,247,8
+ CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x193,4,17,180,
+ 69,WS_EX_CLIENTEDGE
+ ICON "",IDC_ICON_SPAM,187,13,20,20,SS_NOTIFY | SS_CENTERIMAGE
+ LTEXT "Spammer",IDC_TEXT_SPAM,205,19,45,8,SS_NOPREFIX |
+ SS_CENTERIMAGE
+ ICON "",IDC_ICON_DELETE,187,28,20,20,SS_NOTIFY |
+ SS_CENTERIMAGE
+ LTEXT "Delete",IDC_TEXT_DELETE,205,34,45,8,SS_NOPREFIX |
+ SS_CENTERIMAGE
+ ICON "",IDC_ICON_NORMAL,187,43,20,20,SS_NOTIFY |
+ SS_CENTERIMAGE
+ LTEXT "Accept",IDC_TEXT_NORMAL,205,49,45,8,SS_NOPREFIX |
+ SS_CENTERIMAGE
+ GROUPBOX "",IDC_GROUP,4,87,180,51
+ CONTROL "&Hide spammers from contact list",IDC_CHECKBOX_HIDE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,96,166,10
+ CONTROL "Store spammers in special &group:",IDC_CHECKBOX_GROUP,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,108,166,10
+ EDITTEXT IDC_EDITBOX_GROUP,22,119,155,13,ES_AUTOHSCROLL
+ SCROLLBAR IDC_SCROLLBAR_SIZEGRIP,247,136,6,6,
+ SBS_SIZEBOXBOTTOMRIGHTALIGN | SBS_SIZEGRIP
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO MOVEABLE PURE
+BEGIN
+ IDD_LISTBOX_ADD_ITEM, DIALOG
+ BEGIN
+ VERTGUIDE, 65
+ VERTGUIDE, 72
+ VERTGUIDE, 235
+ HORZGUIDE, 15
+ HORZGUIDE, 60
+ HORZGUIDE, 70
+ HORZGUIDE, 80
+ HORZGUIDE, 114
+ HORZGUIDE, 140
+ HORZGUIDE, 191
+ END
+
+ IDD_OPTIONS_CONFIGURE_ADVERTISMENTFILTER, DIALOG
+ BEGIN
+ VERTGUIDE, 7
+ VERTGUIDE, 12
+ VERTGUIDE, 18
+ VERTGUIDE, 29
+ VERTGUIDE, 159
+ VERTGUIDE, 187
+ VERTGUIDE, 199
+ VERTGUIDE, 211
+ VERTGUIDE, 329
+ HORZGUIDE, 19
+ HORZGUIDE, 39
+ HORZGUIDE, 59
+ HORZGUIDE, 107
+ HORZGUIDE, 112
+ HORZGUIDE, 139
+ HORZGUIDE, 255
+ END
+
+ IDD_OPTIONS_MAIN, DIALOG
+ BEGIN
+ VERTGUIDE, 3
+ VERTGUIDE, 10
+ VERTGUIDE, 16
+ VERTGUIDE, 19
+ VERTGUIDE, 163
+ VERTGUIDE, 171
+ VERTGUIDE, 174
+ VERTGUIDE, 182
+ VERTGUIDE, 212
+ VERTGUIDE, 226
+ VERTGUIDE, 287
+ VERTGUIDE, 308
+ HORZGUIDE, 115
+ HORZGUIDE, 128
+ HORZGUIDE, 138
+ HORZGUIDE, 150
+ HORZGUIDE, 170
+ HORZGUIDE, 172
+ HORZGUIDE, 238
+ END
+
+ IDD_OPTIONS_CONFIGURE_DISLIKEDMESSAGEFILTER, DIALOG
+ BEGIN
+ VERTGUIDE, 7
+ VERTGUIDE, 12
+ VERTGUIDE, 18
+ VERTGUIDE, 159
+ VERTGUIDE, 167
+ VERTGUIDE, 187
+ VERTGUIDE, 201
+ VERTGUIDE, 337
+ HORZGUIDE, 7
+ HORZGUIDE, 20
+ HORZGUIDE, 189
+ HORZGUIDE, 217
+ END
+
+ IDD_OPTIONS_CONFIGURE_ROBOTFILTER, DIALOG
+ BEGIN
+ VERTGUIDE, 7
+ VERTGUIDE, 13
+ VERTGUIDE, 20
+ VERTGUIDE, 310
+ VERTGUIDE, 321
+ HORZGUIDE, 11
+ END
+
+ IDD_INFO_SPAMMERS, DIALOG
+ BEGIN
+ VERTGUIDE, 4
+ VERTGUIDE, 10
+ VERTGUIDE, 184
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE MOVEABLE PURE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE MOVEABLE PURE
+BEGIN
+ "#include <windows.h>\r\n"
+ "#include <winres.h>\r\n"
+ "#include ""Include\\m_utils.h""\r\n"
+ "#include ""Include\\m_button.h""\r\n"
+ "#include ""Include\\m_clc.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE MOVEABLE PURE
+BEGIN
+ "#include ""version.rc""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_DEFAULT ICON DISCARDABLE "Resources\\spam_16x16_256.ico"
+IDI_SPAM_LAYER ICON DISCARDABLE "Resources\\spam_layer_16x16_256.ico"
+IDI_ADD_BUTTON ICON DISCARDABLE "Resources\\add_button_16x16_256.ico"
+IDI_DELETE_BUTTON ICON DISCARDABLE "Resources\\delete_button_16x16_256.ico"
+IDI_DEFAULT_LARGE ICON DISCARDABLE "Resources\\spam_32x32_256.ico"
+IDI_SPAM_DEFINITIONS ICON DISCARDABLE "resources\\spam_definitions_16x16_256.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_CONTEXT MENU DISCARDABLE
+BEGIN
+ POPUP "WordsList"
+ BEGIN
+ MENUITEM "&Remove", ID_MENU_DELETE
+ MENUITEM "&Add...", ID_MENU_ADD
+ END
+ POPUP "SpamDef"
+ BEGIN
+ MENUITEM "&Remove...", ID_MENU_DELETE
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXT
+//
+
+IDR_XMLFILETEMPLATE TEXT MOVEABLE PURE "Resources\\log_main.xml"
+IDR_XMLITEMTEMPLATE TEXT MOVEABLE PURE "Resources\\log_item.xml"
+IDR_XSLLAYOUTFILETEMPLATE TEXT MOVEABLE PURE "Resources\\log_layout.xsl"
+#endif // Englisch (USA) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/SpamFilter.sln b/SpamFilter.sln
index f393f7c..12225b5 100644
--- a/SpamFilter.sln
+++ b/SpamFilter.sln
@@ -1,26 +1,26 @@
-
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpamFilter", "SpamFilter.vcproj", "{844ADB70-77B1-45F4-8295-B8246E5066E4}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug Unicode|Win32 = Debug Unicode|Win32
- Debug|Win32 = Debug|Win32
- Release Unicode|Win32 = Release Unicode|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {844ADB70-77B1-45F4-8295-B8246E5066E4}.Debug Unicode|Win32.ActiveCfg = Release Unicode 9x/ME|Win32
- {844ADB70-77B1-45F4-8295-B8246E5066E4}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
- {844ADB70-77B1-45F4-8295-B8246E5066E4}.Debug|Win32.ActiveCfg = Debug Unicode 9x/ME|Win32
- {844ADB70-77B1-45F4-8295-B8246E5066E4}.Debug|Win32.Build.0 = Debug|Win32
- {844ADB70-77B1-45F4-8295-B8246E5066E4}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
- {844ADB70-77B1-45F4-8295-B8246E5066E4}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
- {844ADB70-77B1-45F4-8295-B8246E5066E4}.Release|Win32.ActiveCfg = Release|Win32
- {844ADB70-77B1-45F4-8295-B8246E5066E4}.Release|Win32.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpamFilter", "SpamFilter.vcproj", "{844ADB70-77B1-45F4-8295-B8246E5066E4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug Unicode|Win32 = Debug Unicode|Win32
+ Debug|Win32 = Debug|Win32
+ Release Unicode|Win32 = Release Unicode|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {844ADB70-77B1-45F4-8295-B8246E5066E4}.Debug Unicode|Win32.ActiveCfg = Release Unicode 9x/ME|Win32
+ {844ADB70-77B1-45F4-8295-B8246E5066E4}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {844ADB70-77B1-45F4-8295-B8246E5066E4}.Debug|Win32.ActiveCfg = Debug Unicode 9x/ME|Win32
+ {844ADB70-77B1-45F4-8295-B8246E5066E4}.Debug|Win32.Build.0 = Debug|Win32
+ {844ADB70-77B1-45F4-8295-B8246E5066E4}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {844ADB70-77B1-45F4-8295-B8246E5066E4}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ {844ADB70-77B1-45F4-8295-B8246E5066E4}.Release|Win32.ActiveCfg = Release|Win32
+ {844ADB70-77B1-45F4-8295-B8246E5066E4}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/SpamFilter.vcproj b/SpamFilter.vcproj
index c7d2041..b722b5a 100644
--- a/SpamFilter.vcproj
+++ b/SpamFilter.vcproj
@@ -1,2243 +1,2243 @@
-<?xml version="1.0" encoding="windows-1251"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="9,00"
- Name="SpamFilter"
- ProjectGUID="{844ADB70-77B1-45F4-8295-B8246E5066E4}"
- RootNamespace="SpamFilter"
- TargetFrameworkVersion="131072"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Release Unicode 9x/ME|Win32"
- OutputDirectory=".\Temp\ReleaseW9x"
- IntermediateDirectory=".\Temp\ReleaseW9x"
- ConfigurationType="2"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
- UseOfMFC="0"
- ATLMinimizesCRunTimeLibraryUsage="false"
- CharacterSet="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- PreprocessorDefinitions="NDEBUG"
- SuppressStartupBanner="true"
- TargetEnvironment="1"
- TypeLibraryName=".\Temp\ReleaseW9x/SpamFilter.tlb"
- HeaderFileName=""
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="1"
- AdditionalIncludeDirectories=".\Include"
- PreprocessorDefinitions="NDEBUG;UNICOWS;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_USE_32BIT_TIME_T"
- StringPooling="true"
- RuntimeLibrary="2"
- EnableFunctionLevelLinking="true"
- PrecompiledHeaderFile=".\Temp\ReleaseW9x/SpamFilter.pch"
- AssemblerListingLocation=".\Temp\ReleaseW9x/"
- ObjectFile=".\Temp\ReleaseW9x/"
- ProgramDataBaseFileName=".\Temp\ReleaseW9x/"
- BrowseInformation="1"
- WarningLevel="4"
- SuppressStartupBanner="true"
- UndefinePreprocessorDefinitions="_MBCS,NO_STRICT"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
- Culture="1033"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- IgnoreImportLibrary="true"
- AdditionalOptions="/ignore:4078"
- AdditionalDependencies="unicows.lib comctl32.lib shlwapi.lib version.lib"
- LinkIncremental="1"
- SuppressStartupBanner="true"
- IgnoreDefaultLibraryNames="kernel32.lib,advapi32.lib,user32.lib,gdi32.lib,shell32.lib,comdlg32.lib,version.lib,mpr.lib,rasapi32.lib,winmm.lib,winspool.lib,vfw32.lib,secur32.lib,oleacc.lib,oledlg.lib,sensapi.lib,uuid.lib,OLDNAMES"
- GenerateDebugInformation="true"
- SetChecksum="true"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- ImportLibrary=".\Temp\ReleaseW9x/spamfilterW9x.lib"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- SuppressStartupBanner="true"
- OutputFile=".\Temp\ReleaseW9x/SpamFilter.bsc"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Debug Unicode|Win32"
- OutputDirectory=".\Temp\DebugW"
- IntermediateDirectory=".\Temp\DebugW"
- ConfigurationType="2"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.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=".\Temp\DebugW/SpamFilter.tlb"
- HeaderFileName=""
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=".\Include"
- PreprocessorDefinitions="_DEBUG;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- PrecompiledHeaderFile=".\Temp\DebugW/SpamFilter.pch"
- AssemblerListingLocation=".\Temp\DebugW/"
- ObjectFile=".\Temp\DebugW/"
- ProgramDataBaseFileName=".\Temp\DebugW/"
- BrowseInformation="1"
- WarningLevel="4"
- SuppressStartupBanner="true"
- DebugInformationFormat="4"
- UndefinePreprocessorDefinitions="_MBCS,NO_STRICT"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
- Culture="1033"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- IgnoreImportLibrary="true"
- AdditionalDependencies="comctl32.lib shlwapi.lib version.lib"
- OutputFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW.dll"
- LinkIncremental="2"
- SuppressStartupBanner="true"
- IgnoreDefaultLibraryNames="uuid.lib,OLDNAMES"
- GenerateDebugInformation="true"
- ProgramDatabaseFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW.pdb"
- GenerateMapFile="true"
- MapFileName=".\Temp\DebugW/spamfilterW.map"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- ImportLibrary=".\Temp\DebugW/spamfilterW.lib"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- SuppressStartupBanner="true"
- OutputFile=".\Temp\DebugW/SpamFilter.bsc"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory=".\Temp\Release"
- IntermediateDirectory=".\Temp\Release"
- 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"
- PreprocessorDefinitions="NDEBUG"
- SuppressStartupBanner="true"
- TargetEnvironment="1"
- TypeLibraryName=".\Temp\Release/SpamFilter.tlb"
- HeaderFileName=""
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/opt:nowin98 "
- Optimization="2"
- InlineFunctionExpansion="1"
- AdditionalIncludeDirectories=".\Include"
- PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS;_USE_32BIT_TIME_T;_CRT_SECURE_NO_DEPRECATE"
- StringPooling="true"
- RuntimeLibrary="2"
- EnableFunctionLevelLinking="true"
- PrecompiledHeaderFile=".\Temp\Release/SpamFilter.pch"
- AssemblerListingLocation=".\Temp\Release/"
- ObjectFile=".\Temp\Release/"
- ProgramDataBaseFileName=".\Temp\Release/"
- BrowseInformation="1"
- WarningLevel="4"
- SuppressStartupBanner="true"
- UndefinePreprocessorDefinitions="NO_STRICT"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
- Culture="1033"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- IgnoreImportLibrary="true"
- AdditionalOptions="/ignore:4078 "
- AdditionalDependencies="comctl32.lib shlwapi.lib version.lib"
- LinkIncremental="1"
- SuppressStartupBanner="true"
- IgnoreDefaultLibraryNames="uuid.lib,OLDNAMES"
- GenerateDebugInformation="true"
- OptimizeForWindows98="1"
- SetChecksum="true"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- ImportLibrary=".\Temp\Release/spamfilter.lib"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- SuppressStartupBanner="true"
- OutputFile=".\Temp\Release/SpamFilter.bsc"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Debug Unicode 9x/ME|Win32"
- OutputDirectory=".\Temp\DebugW9x"
- IntermediateDirectory=".\Temp\DebugW9x"
- ConfigurationType="2"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.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=".\Temp\DebugW9x/SpamFilter.tlb"
- HeaderFileName=""
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=".\Include"
- PreprocessorDefinitions="_DEBUG;UNICOWS;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- PrecompiledHeaderFile=".\Temp\DebugW9x/SpamFilter.pch"
- AssemblerListingLocation=".\Temp\DebugW9x/"
- ObjectFile=".\Temp\DebugW9x/"
- ProgramDataBaseFileName=".\Temp\DebugW9x/"
- BrowseInformation="1"
- WarningLevel="4"
- SuppressStartupBanner="true"
- DebugInformationFormat="4"
- UndefinePreprocessorDefinitions="_MBCS,NO_STRICT"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
- Culture="1033"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- IgnoreImportLibrary="true"
- AdditionalDependencies="unicows.lib comctl32.lib shlwapi.lib version.lib"
- OutputFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW9x.dll"
- LinkIncremental="2"
- SuppressStartupBanner="true"
- IgnoreDefaultLibraryNames="kernel32.lib,advapi32.lib,user32.lib,gdi32.lib,shell32.lib,comdlg32.lib,version.lib,mpr.lib,rasapi32.lib,winmm.lib,winspool.lib,vfw32.lib,secur32.lib,oleacc.lib,oledlg.lib,sensapi.lib,uuid.lib,OLDNAMES"
- GenerateDebugInformation="true"
- ProgramDatabaseFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW9x.pdb"
- GenerateMapFile="true"
- MapFileName=".\Temp\DebugW9x/spamfilterW9x.map"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- ImportLibrary=".\Temp\DebugW9x/spamfilterW9x.lib"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- SuppressStartupBanner="true"
- OutputFile=".\Temp\DebugW9x/SpamFilter.bsc"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release Unicode|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="2"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
- UseOfMFC="0"
- ATLMinimizesCRunTimeLibraryUsage="false"
- CharacterSet="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- PreprocessorDefinitions="NDEBUG"
- SuppressStartupBanner="true"
- TargetEnvironment="1"
- TypeLibraryName=".\Temp\ReleaseW/SpamFilter.tlb"
- HeaderFileName=""
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/opt:nowin98 "
- Optimization="1"
- InlineFunctionExpansion="1"
- FavorSizeOrSpeed="2"
- AdditionalIncludeDirectories=".\Include"
- PreprocessorDefinitions="NDEBUG;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS;_USE_32BIT_TIME_T;_CRT_SECURE_NO_DEPRECATE"
- StringPooling="true"
- RuntimeLibrary="2"
- EnableFunctionLevelLinking="true"
- UsePrecompiledHeader="2"
- PrecompiledHeaderThrough="common.h"
- PrecompiledHeaderFile=".\Temp\ReleaseW/SpamFilter.pch"
- AssemblerListingLocation=".\Temp\ReleaseW/"
- ObjectFile=".\Temp\ReleaseW/"
- ProgramDataBaseFileName=".\Temp\ReleaseW/"
- BrowseInformation="1"
- WarningLevel="3"
- SuppressStartupBanner="true"
- UndefinePreprocessorDefinitions="_MBCS,NO_STRICT"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
- Culture="1033"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- IgnoreImportLibrary="true"
- AdditionalOptions="/ignore:4078 "
- AdditionalDependencies="comctl32.lib shlwapi.lib version.lib"
- LinkIncremental="1"
- SuppressStartupBanner="true"
- IgnoreDefaultLibraryNames="uuid.lib,OLDNAMES"
- GenerateDebugInformation="true"
- OptimizeForWindows98="1"
- SetChecksum="true"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- ImportLibrary=".\Temp\ReleaseW/spamfilterW.lib"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- SuppressStartupBanner="true"
- OutputFile=".\Temp\ReleaseW/SpamFilter.bsc"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory=".\Temp\Debug"
- IntermediateDirectory=".\Temp\Debug"
- 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"
- PreprocessorDefinitions="_DEBUG"
- MkTypLibCompatible="true"
- SuppressStartupBanner="true"
- TargetEnvironment="1"
- TypeLibraryName=".\Temp\Debug/SpamFilter.tlb"
- HeaderFileName=""
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=".\Include"
- PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- PrecompiledHeaderFile=".\Temp\Debug/SpamFilter.pch"
- AssemblerListingLocation=".\Temp\Debug/"
- ObjectFile=".\Temp\Debug/"
- ProgramDataBaseFileName=".\Temp\Debug/"
- BrowseInformation="1"
- WarningLevel="4"
- SuppressStartupBanner="true"
- DebugInformationFormat="4"
- UndefinePreprocessorDefinitions="NO_STRICT"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
- Culture="1033"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- IgnoreImportLibrary="true"
- AdditionalDependencies="comctl32.lib shlwapi.lib version.lib"
- OutputFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilter.dll"
- LinkIncremental="2"
- SuppressStartupBanner="true"
- IgnoreDefaultLibraryNames="uuid.lib,OLDNAMES"
- GenerateDebugInformation="true"
- ProgramDatabaseFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilter.pdb"
- GenerateMapFile="true"
- MapFileName=".\Temp\Debug/spamfilter.map"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- ImportLibrary=".\Temp\Debug/spamfilter.lib"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- SuppressStartupBanner="true"
- OutputFile=".\Temp\Debug/SpamFilter.bsc"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <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="contact.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="dlg.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="extraimg.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="folders.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="forkthread.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="logfile.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="main.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UsePrecompiledHeader="1"
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="menuitems.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="options.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="path.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="popup.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="regexp.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="services.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="spamcheck.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="spamcheckdata.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="spamdefinitions.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="string.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="stringlist.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="trigger.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="utilities.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="variables.c"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- UndefinePreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl"
- >
- <File
- RelativePath="common.h"
- >
- </File>
- <File
- RelativePath="contact.h"
- >
- </File>
- <File
- RelativePath="dlg.h"
- >
- </File>
- <File
- RelativePath="extraimg.h"
- >
- </File>
- <File
- RelativePath="folders.h"
- >
- </File>
- <File
- RelativePath="forkthread.h"
- >
- </File>
- <File
- RelativePath="logfile.h"
- >
- </File>
- <File
- RelativePath="menuitems.h"
- >
- </File>
- <File
- RelativePath="options.h"
- >
- </File>
- <File
- RelativePath="path.h"
- >
- </File>
- <File
- RelativePath="popup.h"
- >
- </File>
- <File
- RelativePath="regexp.h"
- >
- </File>
- <File
- RelativePath="services.h"
- >
- </File>
- <File
- RelativePath="spamcheck.h"
- >
- </File>
- <File
- RelativePath="spamcheckdata.h"
- >
- </File>
- <File
- RelativePath="spamdefinitions.h"
- >
- </File>
- <File
- RelativePath="string.h"
- >
- </File>
- <File
- RelativePath="stringlist.h"
- >
- </File>
- <File
- RelativePath="trigger.h"
- >
- </File>
- <File
- RelativePath="utilities.h"
- >
- </File>
- <File
- RelativePath="variables.h"
- >
- </File>
- <File
- RelativePath="version.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
- >
- <File
- RelativePath="Resources\add_button_16x16_256.ico"
- >
- </File>
- <File
- RelativePath="Resources\delete_button_16x16_256.ico"
- >
- </File>
- <File
- RelativePath="Resources\log_item.xml"
- >
- </File>
- <File
- RelativePath="Resources\log_layout.xsl"
- >
- </File>
- <File
- RelativePath="Resources\log_main.xml"
- >
- </File>
- <File
- RelativePath="resource.h"
- >
- </File>
- <File
- RelativePath="Resources\spam_16x16_256.ico"
- >
- </File>
- <File
- RelativePath="Resources\spam_32x32_256.ico"
- >
- </File>
- <File
- RelativePath="Resources\spam_definitions_16x16_256.ico"
- >
- </File>
- <File
- RelativePath="Resources\spam_layer_16x16_256.ico"
- >
- </File>
- <File
- RelativePath="SpamFilter.rc"
- >
- <FileConfiguration
- Name="Release Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode|Win32"
- >
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Unicode 9x/ME|Win32"
- >
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release Unicode|Win32"
- >
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions=""
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions=""
- />
- </FileConfiguration>
- </File>
- </Filter>
- <Filter
- Name="Documentation"
- Filter="*.txt"
- >
- <File
- RelativePath="Docs\PCRE-License.txt"
- >
- </File>
- <File
- RelativePath="Docs\SpamFilter-Developer.txt"
- >
- </File>
- <File
- RelativePath="Docs\SpamFilter-License.txt"
- >
- </File>
- <File
- RelativePath="Docs\SpamFilter-Readme.txt"
- >
- </File>
- <File
- RelativePath="Docs\SpamFilter-Translation.txt"
- >
- </File>
- </Filter>
- <Filter
- Name="Extensions"
- >
- <File
- RelativePath="Extensions\filtered1.wav"
- >
- </File>
- <File
- RelativePath="Extensions\filtered2.wav"
- >
- </File>
- <File
- RelativePath="Extensions\filtered3.wav"
- >
- </File>
- <File
- RelativePath="Extensions\InstallScript.xml"
- >
- </File>
- <File
- RelativePath="m_spamfilter.h"
- >
- </File>
- <File
- RelativePath="m_spamfilter.inc"
- >
- </File>
- </Filter>
- <Filter
- Name="Utilities"
- Filter="h;hpp;hxx;hm;inl"
- >
- <File
- RelativePath="Utilities\DebugHelper.h"
- >
- </File>
- <File
- RelativePath="Utilities\Pcre\include\pcre.h"
- >
- </File>
- </Filter>
- <File
- RelativePath="Info_Src.txt"
- >
- </File>
- <File
- RelativePath="License_Appendix.txt"
- >
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="SpamFilter"
+ ProjectGUID="{844ADB70-77B1-45F4-8295-B8246E5066E4}"
+ RootNamespace="SpamFilter"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release Unicode 9x/ME|Win32"
+ OutputDirectory=".\Temp\ReleaseW9x"
+ IntermediateDirectory=".\Temp\ReleaseW9x"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Temp\ReleaseW9x/SpamFilter.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories=".\Include"
+ PreprocessorDefinitions="NDEBUG;UNICOWS;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_USE_32BIT_TIME_T"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ PrecompiledHeaderFile=".\Temp\ReleaseW9x/SpamFilter.pch"
+ AssemblerListingLocation=".\Temp\ReleaseW9x/"
+ ObjectFile=".\Temp\ReleaseW9x/"
+ ProgramDataBaseFileName=".\Temp\ReleaseW9x/"
+ BrowseInformation="1"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ UndefinePreprocessorDefinitions="_MBCS,NO_STRICT"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/ignore:4078"
+ AdditionalDependencies="unicows.lib comctl32.lib shlwapi.lib version.lib"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ IgnoreDefaultLibraryNames="kernel32.lib,advapi32.lib,user32.lib,gdi32.lib,shell32.lib,comdlg32.lib,version.lib,mpr.lib,rasapi32.lib,winmm.lib,winspool.lib,vfw32.lib,secur32.lib,oleacc.lib,oledlg.lib,sensapi.lib,uuid.lib,OLDNAMES"
+ GenerateDebugInformation="true"
+ SetChecksum="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary=".\Temp\ReleaseW9x/spamfilterW9x.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Temp\ReleaseW9x/SpamFilter.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug Unicode|Win32"
+ OutputDirectory=".\Temp\DebugW"
+ IntermediateDirectory=".\Temp\DebugW"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.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=".\Temp\DebugW/SpamFilter.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".\Include"
+ PreprocessorDefinitions="_DEBUG;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Temp\DebugW/SpamFilter.pch"
+ AssemblerListingLocation=".\Temp\DebugW/"
+ ObjectFile=".\Temp\DebugW/"
+ ProgramDataBaseFileName=".\Temp\DebugW/"
+ BrowseInformation="1"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ UndefinePreprocessorDefinitions="_MBCS,NO_STRICT"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="comctl32.lib shlwapi.lib version.lib"
+ OutputFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ IgnoreDefaultLibraryNames="uuid.lib,OLDNAMES"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW.pdb"
+ GenerateMapFile="true"
+ MapFileName=".\Temp\DebugW/spamfilterW.map"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary=".\Temp\DebugW/spamfilterW.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Temp\DebugW/SpamFilter.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Temp\Release"
+ IntermediateDirectory=".\Temp\Release"
+ 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"
+ PreprocessorDefinitions="NDEBUG"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Temp\Release/SpamFilter.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/opt:nowin98 "
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories=".\Include"
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS;_USE_32BIT_TIME_T;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ PrecompiledHeaderFile=".\Temp\Release/SpamFilter.pch"
+ AssemblerListingLocation=".\Temp\Release/"
+ ObjectFile=".\Temp\Release/"
+ ProgramDataBaseFileName=".\Temp\Release/"
+ BrowseInformation="1"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ UndefinePreprocessorDefinitions="NO_STRICT"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/ignore:4078 "
+ AdditionalDependencies="comctl32.lib shlwapi.lib version.lib"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ IgnoreDefaultLibraryNames="uuid.lib,OLDNAMES"
+ GenerateDebugInformation="true"
+ OptimizeForWindows98="1"
+ SetChecksum="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary=".\Temp\Release/spamfilter.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Temp\Release/SpamFilter.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug Unicode 9x/ME|Win32"
+ OutputDirectory=".\Temp\DebugW9x"
+ IntermediateDirectory=".\Temp\DebugW9x"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.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=".\Temp\DebugW9x/SpamFilter.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".\Include"
+ PreprocessorDefinitions="_DEBUG;UNICOWS;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Temp\DebugW9x/SpamFilter.pch"
+ AssemblerListingLocation=".\Temp\DebugW9x/"
+ ObjectFile=".\Temp\DebugW9x/"
+ ProgramDataBaseFileName=".\Temp\DebugW9x/"
+ BrowseInformation="1"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ UndefinePreprocessorDefinitions="_MBCS,NO_STRICT"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="unicows.lib comctl32.lib shlwapi.lib version.lib"
+ OutputFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW9x.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ IgnoreDefaultLibraryNames="kernel32.lib,advapi32.lib,user32.lib,gdi32.lib,shell32.lib,comdlg32.lib,version.lib,mpr.lib,rasapi32.lib,winmm.lib,winspool.lib,vfw32.lib,secur32.lib,oleacc.lib,oledlg.lib,sensapi.lib,uuid.lib,OLDNAMES"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilterW9x.pdb"
+ GenerateMapFile="true"
+ MapFileName=".\Temp\DebugW9x/spamfilterW9x.map"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary=".\Temp\DebugW9x/spamfilterW9x.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Temp\DebugW9x/SpamFilter.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release Unicode|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Temp\ReleaseW/SpamFilter.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/opt:nowin98 "
+ Optimization="1"
+ InlineFunctionExpansion="1"
+ FavorSizeOrSpeed="2"
+ AdditionalIncludeDirectories=".\Include"
+ PreprocessorDefinitions="NDEBUG;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS;_USE_32BIT_TIME_T;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="common.h"
+ PrecompiledHeaderFile=".\Temp\ReleaseW/SpamFilter.pch"
+ AssemblerListingLocation=".\Temp\ReleaseW/"
+ ObjectFile=".\Temp\ReleaseW/"
+ ProgramDataBaseFileName=".\Temp\ReleaseW/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ UndefinePreprocessorDefinitions="_MBCS,NO_STRICT"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalOptions="/ignore:4078 "
+ AdditionalDependencies="comctl32.lib shlwapi.lib version.lib"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ IgnoreDefaultLibraryNames="uuid.lib,OLDNAMES"
+ GenerateDebugInformation="true"
+ OptimizeForWindows98="1"
+ SetChecksum="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary=".\Temp\ReleaseW/spamfilterW.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Temp\ReleaseW/SpamFilter.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Temp\Debug"
+ IntermediateDirectory=".\Temp\Debug"
+ 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"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Temp\Debug/SpamFilter.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".\Include"
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL;STRICT;SPAMFILTER_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Temp\Debug/SpamFilter.pch"
+ AssemblerListingLocation=".\Temp\Debug/"
+ ObjectFile=".\Temp\Debug/"
+ ProgramDataBaseFileName=".\Temp\Debug/"
+ BrowseInformation="1"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ UndefinePreprocessorDefinitions="NO_STRICT"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="comctl32.lib shlwapi.lib version.lib"
+ OutputFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilter.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ IgnoreDefaultLibraryNames="uuid.lib,OLDNAMES"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="C:\PROGRA~1\MIRAND~1\PLUGINS\spamfilter.pdb"
+ GenerateMapFile="true"
+ MapFileName=".\Temp\Debug/spamfilter.map"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary=".\Temp\Debug/spamfilter.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Temp\Debug/SpamFilter.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <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="contact.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dlg.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="extraimg.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="folders.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="forkthread.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="logfile.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="main.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="1"
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="menuitems.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="options.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="path.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="popup.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="regexp.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="services.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="spamcheck.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="spamcheckdata.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="spamdefinitions.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="string.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="stringlist.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="trigger.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="utilities.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="variables.c"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UndefinePreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="common.h"
+ >
+ </File>
+ <File
+ RelativePath="contact.h"
+ >
+ </File>
+ <File
+ RelativePath="dlg.h"
+ >
+ </File>
+ <File
+ RelativePath="extraimg.h"
+ >
+ </File>
+ <File
+ RelativePath="folders.h"
+ >
+ </File>
+ <File
+ RelativePath="forkthread.h"
+ >
+ </File>
+ <File
+ RelativePath="logfile.h"
+ >
+ </File>
+ <File
+ RelativePath="menuitems.h"
+ >
+ </File>
+ <File
+ RelativePath="options.h"
+ >
+ </File>
+ <File
+ RelativePath="path.h"
+ >
+ </File>
+ <File
+ RelativePath="popup.h"
+ >
+ </File>
+ <File
+ RelativePath="regexp.h"
+ >
+ </File>
+ <File
+ RelativePath="services.h"
+ >
+ </File>
+ <File
+ RelativePath="spamcheck.h"
+ >
+ </File>
+ <File
+ RelativePath="spamcheckdata.h"
+ >
+ </File>
+ <File
+ RelativePath="spamdefinitions.h"
+ >
+ </File>
+ <File
+ RelativePath="string.h"
+ >
+ </File>
+ <File
+ RelativePath="stringlist.h"
+ >
+ </File>
+ <File
+ RelativePath="trigger.h"
+ >
+ </File>
+ <File
+ RelativePath="utilities.h"
+ >
+ </File>
+ <File
+ RelativePath="variables.h"
+ >
+ </File>
+ <File
+ RelativePath="version.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ <File
+ RelativePath="Resources\add_button_16x16_256.ico"
+ >
+ </File>
+ <File
+ RelativePath="Resources\delete_button_16x16_256.ico"
+ >
+ </File>
+ <File
+ RelativePath="Resources\log_item.xml"
+ >
+ </File>
+ <File
+ RelativePath="Resources\log_layout.xsl"
+ >
+ </File>
+ <File
+ RelativePath="Resources\log_main.xml"
+ >
+ </File>
+ <File
+ RelativePath="resource.h"
+ >
+ </File>
+ <File
+ RelativePath="Resources\spam_16x16_256.ico"
+ >
+ </File>
+ <File
+ RelativePath="Resources\spam_32x32_256.ico"
+ >
+ </File>
+ <File
+ RelativePath="Resources\spam_definitions_16x16_256.ico"
+ >
+ </File>
+ <File
+ RelativePath="Resources\spam_layer_16x16_256.ico"
+ >
+ </File>
+ <File
+ RelativePath="SpamFilter.rc"
+ >
+ <FileConfiguration
+ Name="Release Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode 9x/ME|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Documentation"
+ Filter="*.txt"
+ >
+ <File
+ RelativePath="Docs\PCRE-License.txt"
+ >
+ </File>
+ <File
+ RelativePath="Docs\SpamFilter-Developer.txt"
+ >
+ </File>
+ <File
+ RelativePath="Docs\SpamFilter-License.txt"
+ >
+ </File>
+ <File
+ RelativePath="Docs\SpamFilter-Readme.txt"
+ >
+ </File>
+ <File
+ RelativePath="Docs\SpamFilter-Translation.txt"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Extensions"
+ >
+ <File
+ RelativePath="Extensions\filtered1.wav"
+ >
+ </File>
+ <File
+ RelativePath="Extensions\filtered2.wav"
+ >
+ </File>
+ <File
+ RelativePath="Extensions\filtered3.wav"
+ >
+ </File>
+ <File
+ RelativePath="Extensions\InstallScript.xml"
+ >
+ </File>
+ <File
+ RelativePath="m_spamfilter.h"
+ >
+ </File>
+ <File
+ RelativePath="m_spamfilter.inc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Utilities"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="Utilities\DebugHelper.h"
+ >
+ </File>
+ <File
+ RelativePath="Utilities\Pcre\include\pcre.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="Info_Src.txt"
+ >
+ </File>
+ <File
+ RelativePath="License_Appendix.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Utilities/DebugHelper.h b/Utilities/DebugHelper.h
index cf1b4b3..aa2af94 100644
--- a/Utilities/DebugHelper.h
+++ b/Utilities/DebugHelper.h
@@ -1,338 +1,338 @@
-/*
-
-DebugHelper.h
-Copyright © 2004-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-// Version 3.0, Sept 26 2005
-// Heiko Herkenrath
-
-// -----------------------------
-
-// Switches:
-
-//#define DEACTIVATE_DEBUG_HELPER
-//#define NO_DEBUG_HELPER
-//#define ALSO_USE_DEBUG_HELPER_FOR_RELEASE
-
-// -----------------------------
-
-#if !defined(ALSO_USE_DEBUG_HELPER_FOR_RELEASE)
- #if !defined(_DEBUG)
- #define DEACTIVATE_DEBUG_HELPER
- #endif
-#endif
-
-// -----------------------------
-
-#ifndef NO_DEBUG_HELPERS
-
- #define DEBUG_BUFFER_SIZE 1024
-
- // Creating display text for all functions
- #if !defined(DEACTIVATE_DEBUG_HELPER)
- __inline WCHAR* CreateDebugText(const WCHAR* pszFmt, const WCHAR* pszFile, unsigned int uLine, va_list va)
- {
- static int iDebugCallCount = 0;
- TCHAR* pszDebugText;
- TCHAR* pszDebugBuf;
- TCHAR* ptszLastError;
- DWORD dwLastError;
- #if defined(UNICODE)
- char* pszLastError;
- #endif
-
- dwLastError = GetLastError();
- iDebugCallCount++;
- MessageBeep(MB_ICONQUESTION);
-
- if (!pszFmt) return NULL;
-
- pszDebugText = (TCHAR*)malloc(DEBUG_BUFFER_SIZE*sizeof(TCHAR));
- if (pszDebugText)
- {
- pszDebugBuf = (TCHAR*)malloc(DEBUG_BUFFER_SIZE*sizeof(TCHAR));
- if (pszDebugBuf)
- {
- ptszLastError = NULL;
-
- #if defined(UNICODE) // FormatMessageW does not work with UnicoWS layer on Win9x/ME
-
- pszLastError = NULL;
-
- if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPWSTR)&ptszLastError, 0, NULL) == 0)
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPSTR)&pszLastError, 0, NULL);
-
- mir_sntprintf(pszDebugBuf, DEBUG_BUFFER_SIZE, _T("[Message %i]\r\nLast Error: %u\r\nDescription: %hs%sCall: %s, %u\r\n\r\n%s"), iDebugCallCount, dwLastError, pszLastError?pszLastError:"", ptszLastError?ptszLastError:_T(""), PathFindFileName(pszFile), uLine, pszFmt);
-
- if (pszLastError) LocalFree(pszLastError);
- if (ptszLastError) LocalFree(ptszLastError);
-
- #else
-
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPTSTR)&ptszLastError, 0, NULL);
- mir_sntprintf(pszDebugBuf, DEBUG_BUFFER_SIZE, _T("[Message %i]\r\nLast Error: %u\r\nDescription: %sCall: %s, %u\r\n\r\n%s"), iDebugCallCount, dwLastError, ptszLastError?ptszLastError:_T(""), PathFindFileName(pszFile), uLine, pszFmt);
- if (ptszLastError) LocalFree(ptszLastError);
-
- #endif
-
- mir_vsnprintf(pszDebugText, DEBUG_BUFFER_SIZE, pszDebugBuf, va);
- free(pszDebugBuf);
- }
- }
-
- SetLastError(ERROR_SUCCESS);
- return pszDebugText;
- }
- #endif
-
-
- // Check if a specific flag is bitwise-or'ed into a flags variable
- // (returns flag name as string or empty string if not contained)
- #if !defined(DEACTIVATE_DEBUG_HELPER)
- #define INFLAGS(flags, flag) ( ((flags&flag) && ((flags^=flag)||TRUE))?_T("|"#flag):_T(""))
- #else
- #define INFLAGS(flags, flag)
- #endif
-
-
- // BOOLSTR [make a string out of a boolean value]
- #if !defined(DEACTIVATE_DEBUG_HELPER)
- #define BOOLSTR(b) ((b)?_T("TRUE"):_T("FALSE"))
- #else
- #define BOOLSTR(b)
- #endif
-
-
- // BOX [show debug message box with text]
- #if !defined(DEACTIVATE_DEBUG_HELPER)
-
- // Functions:
- #define BOX(str) BOX_Helper(_T(__FILE__), __LINE__, _T("%s"), _T(str))
- #define BOX1(fmt, p1) BOX_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), NULL, NULL, NULL)
- #define BOX2(fmt, p1, p2) BOX_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), NULL, NULL)
- #define BOX3(fmt, p1, p2, p3) BOX_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), NULL)
- #define BOX4(fmt, p1, p2, p3, p4) BOX_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), (p4))
- // ---
-
- __inline void BOX_Helper(const TCHAR* pszFile, unsigned int uLine, const TCHAR* pszFmt, ...)
- {
- va_list va;
- TCHAR* pszText;
-
- va_start(va, pszFmt);
- pszText = CreateDebugText(pszFmt, pszFile, uLine, va);
- va_end(va);
-
- if (pszText)
- {
- // Only show if CTRL is not pressed
- if (!(GetAsyncKeyState(VK_CONTROL)&0x8000))
- MessageBoxEx(NULL, pszText, _T("Debug"), MB_OK|MB_TASKMODAL|MB_SETFOREGROUND, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
-
- free(pszText);
- }
- }
-
- #else
- #define BOX(str)
- #define BOX1(fmt, p1)
- #define BOX2(fmt, p1, p2)
- #define BOX3(fmt, p1, p2, p3)
- #define BOX4(fmt, p1, p2, p3, p4)
- #endif
-
-
-
- // STEP [show debug message box with current code step]
- #define STEP(section, id) BOX2("Reached Step %s|%u", _T(section), id)
-
-
-
- // STR [write line into debugger output]
- #if !defined(DEACTIVATE_DEBUG_HELPER)
-
- // Functions:
- #define STR(str) STR_Helper(_T(__FILE__), __LINE__, _T("%s"), _T(str))
- #define STR1(fmt, p1) STR_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), NULL, NULL, NULL)
- #define STR2(fmt, p1, p2) STR_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), NULL, NULL)
- #define STR3(fmt, p1, p2, p3) STR_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), NULL, NULL)
- #define STR4(fmt, p1, p2, p3, p4) STR_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), (p4))
- // ---
-
- __inline void STR_Helper(const TCHAR* pszFile, unsigned int uLine, const TCHAR* pszFmt, ...)
- {
- va_list va;
- TCHAR* pszText;
-
- va_start(va, pszFmt);
- pszText = CreateDebugText(pszFmt, pszFile, uLine, va);
- va_end(va);
-
- if (pszText)
- {
- OutputDebugString(pszText);
- OutputDebugString(_T("\r\n"));
-
- free(pszText);
- }
- }
-
- #else
- #define STR(str)
- #define STR1(fmt, p1)
- #define STR2(fmt, p1, p2)
- #define STR3(fmt, p1, p2, p3)
- #define STR4(fmt, p1, p2, p3, p4)
- #endif
-
-
-
- // DBG [simple wrapper around OutputDebugString]
- #if !defined(DEACTIVATE_DEBUG_HELPER)
- #define DBGT(str) OutputDebugString(_T(str)_T("\r\n"))
- #define DBG(str) { OutputDebugString(str); OutputDebugString(_T("\r\n")); }
- #else
- #define DBGT(str)
- #define DBG(str)
- #endif
-
-
-
- // LOG [append line to debug log file]
- #if !defined(DEACTIVATE_DEBUG_HELPER)
-
- // Functions:
- #define LOG(str) LOG_Helper(_T(__FILE__), __LINE__, _T("%s"), _T(str))
- #define LOG1(fmt, p1) LOG_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), NULL, NULL, NULL)
- #define LOG2(fmt, p1, p2) LOG_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), NULL, NULL)
- #define LOG3(fmt, p1, p2, p3) LOG_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), NULL)
- #define LOG4(fmt, p1, p2, p3, p4) LOG_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), (p4))
- // ---
-
- __inline void LOG_Helper(const TCHAR* pszFile, unsigned int uLine, const TCHAR* pszFmt, ...)
- {
- va_list va;
- DWORD dwDebugFileWritten = 0;
- TCHAR* pszText;
- TCHAR szDebugLogFile[MAX_PATH];
- HANDLE hDebugLogFile;
-
- static BOOL bFirstCall = TRUE;
-
- va_start(va, pszFmt);
- pszText = CreateDebugText(pszFmt, pszFile, uLine, va);
- va_end(va);
-
- // Filename
- if (pszText)
- {
- GetModuleFileName(NULL, szDebugLogFile, sizeof(szDebugLogFile)-1);
- PathRemoveFileSpec(szDebugLogFile);
- PathAppend(szDebugLogFile, _T("Debug.log"));
-
- hDebugLogFile = CreateFile(szDebugLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (hDebugLogFile == INVALID_HANDLE_VALUE)
- BOX("LOG ERROR: INVALID_HANDLE_VALUE");
-
- SetFilePointer(hDebugLogFile, 0, NULL, bFirstCall?FILE_BEGIN:FILE_END);
- WriteFile(hDebugLogFile, "\r\n", 2*sizeof(TCHAR), &dwDebugFileWritten, NULL);
- WriteFile(hDebugLogFile, (PBYTE*)pszText, (DWORD)(lstrlen(pszText)*sizeof(TCHAR)), &dwDebugFileWritten, NULL);
- SetEndOfFile(hDebugLogFile);
-
- CloseHandle(hDebugLogFile);
- free(pszText);
-
- bFirstCall = FALSE;
- }
- }
-
- #else
- #define LOG(str)
- #define LOG1(fmt, p1)
- #define LOG2(fmt, p1, p2)
- #define LOG3(fmt, p1, p2, p3)
- #define LOG4(fmt, p1, p2, p3, p4)
- #endif
-
-
-
- // POP [show debug popup (Popup Plugin) with text]
- /*
- #if !defined(DEACTIVATE_DEBUG_HELPER)
-
- // Functions:
- #define POP(str) POP_Helper(_T(__FILE__), __LINE__, _T("%s"), _T(str))
- #define POP1(fmt, p1) POP_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), NULL, NULL, NULL)
- #define POP2(fmt, p1, p2) POP_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), NULL, NULL)
- #define POP3(fmt, p1, p2, p3) POP_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), NULL)
- #define POP4(fmt, p1, p2, p3, p4) POP_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), (p4))
- // ---
-
- __inline void POP_Helper(const TCHAR* pszFile, unsigned int uLine, const TCHAR* pszFmt, ...)
- {
- #ifdef MS_POPUP_SHOWMESSAGE
- va_list va;
- TCHAR* pszText;
-
- va_start(va, pszFmt);
- pszText = CreateDebugText(pszFmt, pszFile, uLine, va);
- va_end(va);
-
- // Only show if CTRL is not pressed
- if (pszText)
- {
- if (!(GetAsyncKeyState(VK_CONTROL)&0x8000))
- CallServiceSync(MS_POPUP_SHOWMESSAGE, (WPARAM)pszText, (LPARAM)SM_NOTIFY);
-
- free(pszText);
- }
- #endif
- }
- #else
- #define POP(str)
- #define POP1(fmt, p1)
- #define POP2(fmt, p1, p2)
- #define POP3(fmt, p1, p2, p3)
- #define POP4(fmt, p1, p2, p3, p4)
- #endif
- */
-
-
- // LOOPPROT [prevent a loop (for/while/repeat) from becoming an infinite loop]
- #if !defined(DEACTIVATE_DEBUG_HELPER)
-
- // LOOPROT(0) breaks the loop when "Esc" is pressed
-
- #define LOOPPROT(max) { \
- static unsigned int uDebugLoopCount = 1; \
- uDebugLoopCount++; \
- if (GetAsyncKeyState(VK_ESCAPE)&0x8000) break; \
- MessageBeep(MB_ICONEXCLAMATION); \
- if (uDebugLoopCount > (max)) { \
- break; \
- BOX1("LOOPPROT:\nThe execution of the loop was stopped because it looped %u times.", max); \
- uDebugLoopCount = 1;\
- } \
- }
-
- #else
- #define LOOPPROT(max)
- #endif
-
-#endif
+/*
+
+DebugHelper.h
+Copyright © 2004-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// Version 3.0, Sept 26 2005
+// Heiko Herkenrath
+
+// -----------------------------
+
+// Switches:
+
+//#define DEACTIVATE_DEBUG_HELPER
+//#define NO_DEBUG_HELPER
+//#define ALSO_USE_DEBUG_HELPER_FOR_RELEASE
+
+// -----------------------------
+
+#if !defined(ALSO_USE_DEBUG_HELPER_FOR_RELEASE)
+ #if !defined(_DEBUG)
+ #define DEACTIVATE_DEBUG_HELPER
+ #endif
+#endif
+
+// -----------------------------
+
+#ifndef NO_DEBUG_HELPERS
+
+ #define DEBUG_BUFFER_SIZE 1024
+
+ // Creating display text for all functions
+ #if !defined(DEACTIVATE_DEBUG_HELPER)
+ __inline WCHAR* CreateDebugText(const WCHAR* pszFmt, const WCHAR* pszFile, unsigned int uLine, va_list va)
+ {
+ static int iDebugCallCount = 0;
+ TCHAR* pszDebugText;
+ TCHAR* pszDebugBuf;
+ TCHAR* ptszLastError;
+ DWORD dwLastError;
+ #if defined(UNICODE)
+ char* pszLastError;
+ #endif
+
+ dwLastError = GetLastError();
+ iDebugCallCount++;
+ MessageBeep(MB_ICONQUESTION);
+
+ if (!pszFmt) return NULL;
+
+ pszDebugText = (TCHAR*)malloc(DEBUG_BUFFER_SIZE*sizeof(TCHAR));
+ if (pszDebugText)
+ {
+ pszDebugBuf = (TCHAR*)malloc(DEBUG_BUFFER_SIZE*sizeof(TCHAR));
+ if (pszDebugBuf)
+ {
+ ptszLastError = NULL;
+
+ #if defined(UNICODE) // FormatMessageW does not work with UnicoWS layer on Win9x/ME
+
+ pszLastError = NULL;
+
+ if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPWSTR)&ptszLastError, 0, NULL) == 0)
+ FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPSTR)&pszLastError, 0, NULL);
+
+ mir_sntprintf(pszDebugBuf, DEBUG_BUFFER_SIZE, _T("[Message %i]\r\nLast Error: %u\r\nDescription: %hs%sCall: %s, %u\r\n\r\n%s"), iDebugCallCount, dwLastError, pszLastError?pszLastError:"", ptszLastError?ptszLastError:_T(""), PathFindFileName(pszFile), uLine, pszFmt);
+
+ if (pszLastError) LocalFree(pszLastError);
+ if (ptszLastError) LocalFree(ptszLastError);
+
+ #else
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPTSTR)&ptszLastError, 0, NULL);
+ mir_sntprintf(pszDebugBuf, DEBUG_BUFFER_SIZE, _T("[Message %i]\r\nLast Error: %u\r\nDescription: %sCall: %s, %u\r\n\r\n%s"), iDebugCallCount, dwLastError, ptszLastError?ptszLastError:_T(""), PathFindFileName(pszFile), uLine, pszFmt);
+ if (ptszLastError) LocalFree(ptszLastError);
+
+ #endif
+
+ mir_vsnprintf(pszDebugText, DEBUG_BUFFER_SIZE, pszDebugBuf, va);
+ free(pszDebugBuf);
+ }
+ }
+
+ SetLastError(ERROR_SUCCESS);
+ return pszDebugText;
+ }
+ #endif
+
+
+ // Check if a specific flag is bitwise-or'ed into a flags variable
+ // (returns flag name as string or empty string if not contained)
+ #if !defined(DEACTIVATE_DEBUG_HELPER)
+ #define INFLAGS(flags, flag) ( ((flags&flag) && ((flags^=flag)||TRUE))?_T("|"#flag):_T(""))
+ #else
+ #define INFLAGS(flags, flag)
+ #endif
+
+
+ // BOOLSTR [make a string out of a boolean value]
+ #if !defined(DEACTIVATE_DEBUG_HELPER)
+ #define BOOLSTR(b) ((b)?_T("TRUE"):_T("FALSE"))
+ #else
+ #define BOOLSTR(b)
+ #endif
+
+
+ // BOX [show debug message box with text]
+ #if !defined(DEACTIVATE_DEBUG_HELPER)
+
+ // Functions:
+ #define BOX(str) BOX_Helper(_T(__FILE__), __LINE__, _T("%s"), _T(str))
+ #define BOX1(fmt, p1) BOX_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), NULL, NULL, NULL)
+ #define BOX2(fmt, p1, p2) BOX_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), NULL, NULL)
+ #define BOX3(fmt, p1, p2, p3) BOX_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), NULL)
+ #define BOX4(fmt, p1, p2, p3, p4) BOX_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), (p4))
+ // ---
+
+ __inline void BOX_Helper(const TCHAR* pszFile, unsigned int uLine, const TCHAR* pszFmt, ...)
+ {
+ va_list va;
+ TCHAR* pszText;
+
+ va_start(va, pszFmt);
+ pszText = CreateDebugText(pszFmt, pszFile, uLine, va);
+ va_end(va);
+
+ if (pszText)
+ {
+ // Only show if CTRL is not pressed
+ if (!(GetAsyncKeyState(VK_CONTROL)&0x8000))
+ MessageBoxEx(NULL, pszText, _T("Debug"), MB_OK|MB_TASKMODAL|MB_SETFOREGROUND, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
+
+ free(pszText);
+ }
+ }
+
+ #else
+ #define BOX(str)
+ #define BOX1(fmt, p1)
+ #define BOX2(fmt, p1, p2)
+ #define BOX3(fmt, p1, p2, p3)
+ #define BOX4(fmt, p1, p2, p3, p4)
+ #endif
+
+
+
+ // STEP [show debug message box with current code step]
+ #define STEP(section, id) BOX2("Reached Step %s|%u", _T(section), id)
+
+
+
+ // STR [write line into debugger output]
+ #if !defined(DEACTIVATE_DEBUG_HELPER)
+
+ // Functions:
+ #define STR(str) STR_Helper(_T(__FILE__), __LINE__, _T("%s"), _T(str))
+ #define STR1(fmt, p1) STR_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), NULL, NULL, NULL)
+ #define STR2(fmt, p1, p2) STR_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), NULL, NULL)
+ #define STR3(fmt, p1, p2, p3) STR_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), NULL, NULL)
+ #define STR4(fmt, p1, p2, p3, p4) STR_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), (p4))
+ // ---
+
+ __inline void STR_Helper(const TCHAR* pszFile, unsigned int uLine, const TCHAR* pszFmt, ...)
+ {
+ va_list va;
+ TCHAR* pszText;
+
+ va_start(va, pszFmt);
+ pszText = CreateDebugText(pszFmt, pszFile, uLine, va);
+ va_end(va);
+
+ if (pszText)
+ {
+ OutputDebugString(pszText);
+ OutputDebugString(_T("\r\n"));
+
+ free(pszText);
+ }
+ }
+
+ #else
+ #define STR(str)
+ #define STR1(fmt, p1)
+ #define STR2(fmt, p1, p2)
+ #define STR3(fmt, p1, p2, p3)
+ #define STR4(fmt, p1, p2, p3, p4)
+ #endif
+
+
+
+ // DBG [simple wrapper around OutputDebugString]
+ #if !defined(DEACTIVATE_DEBUG_HELPER)
+ #define DBGT(str) OutputDebugString(_T(str)_T("\r\n"))
+ #define DBG(str) { OutputDebugString(str); OutputDebugString(_T("\r\n")); }
+ #else
+ #define DBGT(str)
+ #define DBG(str)
+ #endif
+
+
+
+ // LOG [append line to debug log file]
+ #if !defined(DEACTIVATE_DEBUG_HELPER)
+
+ // Functions:
+ #define LOG(str) LOG_Helper(_T(__FILE__), __LINE__, _T("%s"), _T(str))
+ #define LOG1(fmt, p1) LOG_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), NULL, NULL, NULL)
+ #define LOG2(fmt, p1, p2) LOG_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), NULL, NULL)
+ #define LOG3(fmt, p1, p2, p3) LOG_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), NULL)
+ #define LOG4(fmt, p1, p2, p3, p4) LOG_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), (p4))
+ // ---
+
+ __inline void LOG_Helper(const TCHAR* pszFile, unsigned int uLine, const TCHAR* pszFmt, ...)
+ {
+ va_list va;
+ DWORD dwDebugFileWritten = 0;
+ TCHAR* pszText;
+ TCHAR szDebugLogFile[MAX_PATH];
+ HANDLE hDebugLogFile;
+
+ static BOOL bFirstCall = TRUE;
+
+ va_start(va, pszFmt);
+ pszText = CreateDebugText(pszFmt, pszFile, uLine, va);
+ va_end(va);
+
+ // Filename
+ if (pszText)
+ {
+ GetModuleFileName(NULL, szDebugLogFile, sizeof(szDebugLogFile)-1);
+ PathRemoveFileSpec(szDebugLogFile);
+ PathAppend(szDebugLogFile, _T("Debug.log"));
+
+ hDebugLogFile = CreateFile(szDebugLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hDebugLogFile == INVALID_HANDLE_VALUE)
+ BOX("LOG ERROR: INVALID_HANDLE_VALUE");
+
+ SetFilePointer(hDebugLogFile, 0, NULL, bFirstCall?FILE_BEGIN:FILE_END);
+ WriteFile(hDebugLogFile, "\r\n", 2*sizeof(TCHAR), &dwDebugFileWritten, NULL);
+ WriteFile(hDebugLogFile, (PBYTE*)pszText, (DWORD)(lstrlen(pszText)*sizeof(TCHAR)), &dwDebugFileWritten, NULL);
+ SetEndOfFile(hDebugLogFile);
+
+ CloseHandle(hDebugLogFile);
+ free(pszText);
+
+ bFirstCall = FALSE;
+ }
+ }
+
+ #else
+ #define LOG(str)
+ #define LOG1(fmt, p1)
+ #define LOG2(fmt, p1, p2)
+ #define LOG3(fmt, p1, p2, p3)
+ #define LOG4(fmt, p1, p2, p3, p4)
+ #endif
+
+
+
+ // POP [show debug popup (Popup Plugin) with text]
+ /*
+ #if !defined(DEACTIVATE_DEBUG_HELPER)
+
+ // Functions:
+ #define POP(str) POP_Helper(_T(__FILE__), __LINE__, _T("%s"), _T(str))
+ #define POP1(fmt, p1) POP_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), NULL, NULL, NULL)
+ #define POP2(fmt, p1, p2) POP_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), NULL, NULL)
+ #define POP3(fmt, p1, p2, p3) POP_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), NULL)
+ #define POP4(fmt, p1, p2, p3, p4) POP_Helper(_T(__FILE__), __LINE__, _T(fmt), (p1), (p2), (p3), (p4))
+ // ---
+
+ __inline void POP_Helper(const TCHAR* pszFile, unsigned int uLine, const TCHAR* pszFmt, ...)
+ {
+ #ifdef MS_POPUP_SHOWMESSAGE
+ va_list va;
+ TCHAR* pszText;
+
+ va_start(va, pszFmt);
+ pszText = CreateDebugText(pszFmt, pszFile, uLine, va);
+ va_end(va);
+
+ // Only show if CTRL is not pressed
+ if (pszText)
+ {
+ if (!(GetAsyncKeyState(VK_CONTROL)&0x8000))
+ CallServiceSync(MS_POPUP_SHOWMESSAGE, (WPARAM)pszText, (LPARAM)SM_NOTIFY);
+
+ free(pszText);
+ }
+ #endif
+ }
+ #else
+ #define POP(str)
+ #define POP1(fmt, p1)
+ #define POP2(fmt, p1, p2)
+ #define POP3(fmt, p1, p2, p3)
+ #define POP4(fmt, p1, p2, p3, p4)
+ #endif
+ */
+
+
+ // LOOPPROT [prevent a loop (for/while/repeat) from becoming an infinite loop]
+ #if !defined(DEACTIVATE_DEBUG_HELPER)
+
+ // LOOPROT(0) breaks the loop when "Esc" is pressed
+
+ #define LOOPPROT(max) { \
+ static unsigned int uDebugLoopCount = 1; \
+ uDebugLoopCount++; \
+ if (GetAsyncKeyState(VK_ESCAPE)&0x8000) break; \
+ MessageBeep(MB_ICONEXCLAMATION); \
+ if (uDebugLoopCount > (max)) { \
+ break; \
+ BOX1("LOOPPROT:\nThe execution of the loop was stopped because it looped %u times.", max); \
+ uDebugLoopCount = 1;\
+ } \
+ }
+
+ #else
+ #define LOOPPROT(max)
+ #endif
+
+#endif
diff --git a/common.h b/common.h
index 0cf6cd5..b556f73 100644
--- a/common.h
+++ b/common.h
@@ -1,284 +1,284 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_COMMON_H__
-#define SF_COMMON_H__ 1
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-// -- Includes: CRT (C Runtime Library)
-//#include <tchar.h> // generic Ansi/Unicode functions
-#include <wchar.h> // unicode functions
-#include <stdio.h> // for mir_snprintf() etc.
-#include <process.h> // for forkthread()
-#include <time.h> // for time()
-
-// -- Includes: WinAPI
-#define _WIN32_WINNT 0x0501
-//#define WINVER 0x0502
-#define _WIN32_IE 0x0500 // for SHFileOperation
-
-#include <windows.h>
-#include <commctrl.h>
-#include <shlwapi.h>
-#include <shlobj.h>
-
-
-// -- Include: MirandaAPI
-//#define NOWIN2K
-#include <win2k.h>
-#include <newpluginapi.h>
-#include <m_clist.h>
-#include <m_clui.h>
-#include <m_database.h>
-#include <m_langpack.h>
-#include <m_options.h>
-#include <m_skin.h>
-#include <m_button.h>
-#include <m_protosvc.h>
-#include <m_protocols.h>
-#include <m_protomod.h>
-#include <m_plugins.h>
-#include <m_ignore.h>
-#include <m_contacts.h>
-#include <m_utils.h>
-#include <m_url.h>
-#include <m_file.h>
-#include <m_message.h>
-#include <m_popup.h>
-//#define VARIABLES_NOHELPER
-#include <m_variables.h>
-#include <m_icolib.h>
-#include <m_clc.h>
-#include <m_fontservice.h>
-#include <m_netlib.h>
-#include <m_updater.h>
-#include <m_folders.h>
-#include "m_trigger.h"
-#include <m_icq.h>
-#include <m_cluiframes.h>
-
-// -- Includes: Header
-#include "m_spamfilter.h"
-#include "forkthread.h"
-#include "path.h"
-#include "stringlist.h"
-#include "string.h"
-#include "regexp.h"
-#include "utilities.h"
-#include "spamdefinitions.h"
-#include "spamcheckdata.h"
-#include "popup.h"
-#include "logfile.h"
-#include "contact.h"
-#include "dlg.h"
-#include "options.h"
-#include "services.h"
-#include "spamcheck.h"
-#include "variables.h"
-#include "folders.h"
-#include "trigger.h"
-#include "extraimg.h"
-#include "menuitems.h"
-#include "version.h"
-#include "resource.h"
-#include <m_system.h>
-struct MM_INTERFACE memoryManagerInterface;
-struct UTF8_INTERFACE utfi;
-
-
-
-// -- Includes: Utilities
-#if defined(_DEBUG)
- // Memory leak and invalid access detection
- //#define _CRTDBG_MAP_ALLOC
- #include <crtdbg.h>
- //#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
-
- // Check database setting type (m_database.h)
- //#define DBCHECKSETTINGS
-#else
- // Prevent C Runtime Library (CRT)
- /*
- #pragma comment(linker,"/ENTRY:DllMain")
- #pragma comment(linker,"/NODEFAULTLIB")
- */
-#endif
-
-// Debug Functions
-#include "Utilities/DebugHelper.h"
-
-
-// -- Variables: Plugin
-HINSTANCE hInstance;
-PLUGINLINK* pluginLink;
-
-
-// -- Variables: Window Handles
-HWND hwndSpamFilterOpt;
-HWND hwndAdvertismentFilter;
-HWND hwndRobotFilter;
-HWND hwndDislikedMessagesFilter;
-HWND hwndSpamDefinitionsInfo;
-HWND hwndSpammersInfo;
-
-// -- Variables: Message Types List
-CRITICAL_SECTION csMsgTypes;
-unsigned int uMsgTypesCount; // protected by csMsgTypes
-MESSAGETYPEDESC* pamtdMsgTypes; // protected by csMsgTypes
-
-// -- Defines: General
-#define DEFAULT_LOGFILE TranslateT("Spam.xml")
-
-#define DEFAULT_ADVERTISMENT_SOUNDFILE _T("filtered1.wav") // Sound files must not be translated and must be lower case
-#define DEFAULT_DISLIKEDMESSAGE_SOUNDFILE _T("filtered2.wav")
-#define DEFAULT_ROBOT_SOUNDFILE _T("filtered3.wav")
-
-#define SOUNDS_SUBDIRECTORY _T("Sounds") // Dirs must have no backslash at the end!
-#define DOCS_SUBDIRECTORY _T("Docs")
-#define LOGS_SUBDIRECTORY _T("Logs")
-#define DATA_SUBDIRECTORY _T("Spam Filter")
-
-#define RANDOM_ANSWER_LENGTH 8
-
-#define MAX_INT_LENGTH 15 // or just 10
-
-#define MS_CONTACTS_SEND "ContactsTransfer/SendContacts"
-#define MS_CONTACTS_RECEIVE "ContactsTransfer/ReceiveContacts"
-
-
-// -- Defines: Default Settings
-#define DEFAULT_SETTING_BEHAVIOUR 1 // 1 = Mark message read or 2 = Delete message
-#define DEFAULT_SETTING_POPUP FALSE
-#define DEFAULT_SETTING_LOGGING FALSE
-#define DEFAULT_SETTING_AUTOADDSPAMMERS TRUE
-#define DEFAULT_SETTING_ALLOWEDSPAMMESSAGES 3 // 0 to x
-#define DEFAULT_SETTING_HIDEFROMCLIST TRUE
-#define DEFAULT_SETTING_MOVETOGROUP FALSE
-#define DEFAULT_SETTING_MOVETOGROUPNAME TranslateT("Spammers")
-#define DEFAULT_SETTING_SETSPAMMERFLAGS 0 // flags can be SCASF_NO_REMOVE_HISTORY, SCASF_NO_DENY_AUTHREQUESTS, SCASF_NO_NOTIFY
-
-#define DEFAULT_SETTING_ADVERTISMENTFILTER TRUE
-#define DEFAULT_SETTING_ADVERTISMENT_DEFAULTBADWORDS TRUE
-#define DEFAULT_SETTING_ADVERTISMENT_FORMATING TRUE
-#define DEFAULT_SETTING_ADVERTISMENT_URL FALSE
-#define DEFAULT_SETTING_ADVERTISMENT_PHONENUMBERS FALSE
-#define DEFAULT_SETTING_ADVERTISMENT_CAPITALIZED FALSE
-#define DEFAULT_SETTING_ADVERTISMENT_EMPTY TRUE
-#define DEFAULT_SETTING_ADVERTISMENT_DEFAULTSPAMMERS TRUE
-#define DEFAULT_SETTING_ADVERTISMENT_MULTIPLEMESSAGES TRUE
-#define DEFAULT_SETTING_ADVERTISMENT_TEASERMESSAGES TRUE
-#define DEFAULT_SETTING_ADVERTISMENT_ALLOWEDBADWORDS 3 // 0 to x
-#define DEFAULT_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS 0 // 0 to x
-#define DEFAULT_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS 1 // 0 to x
-
-#define DEFAULT_SETTING_DISLIKEDMESSAGEFILTER FALSE
-#define DEFAULT_SETTING_DISLIKEDMESSAGE_HOAXTEXTS TRUE
-#define DEFAULT_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES TRUE
-#define DEFAULT_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER FALSE
-#define DEFAULT_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY TRUE
-#define DEFAULT_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE TranslateT("Hello %sender%,\r\nI don't like such messages. Please don't send them to me anymore.\r\nThanks.\r\n\r\n(Automated message)")
-
-#define DEFAULT_SETTING_ROBOTFILTER FALSE
-#define DEFAULT_SETTING_ROBOT_INSTRUCTION TranslateT("Hello %sender%,\r\nPlease reply \"%securitycode%\" if you want to contact me. If you don't reply correctly your messages will be ignored. Sorry for the inconvenience.\r\nThis spam check guarantees that you are a real person.\r\nYou have %triesleft% tries left.\r\nThanks in advance!\r\n\r\n(Automated message)")
-#define DEFAULT_SETTING_ROBOT_CONFIRMATION TranslateT("Thank you for your help!\r\nAll your previous messages were delivered. New messages do now reach me directly without an additional spam check.\r\n\r\n(Automated message)")
-#define DEFAULT_SETTING_ROBOT_ADDTOHISTORY TRUE
-#define DEFAULT_SETTING_ROBOT_HIDEUSERS TRUE
-
-// -- Defines: Database
-#define DB_MODULE_NAME "SpamFilter"
-#define DB_MODULE_NAME_PRESPAMMERS "SpamFilterAutoIgnore"
-#define DB_MODULE_NAME_MSGTYPES "SpamFilterMsgTypes"
-
-#define DB_SETTING_FIRSTRUNDONE "FirstRunDone"
-
-#define DB_SETTING_POPUP "PopupActivated"
-#define DB_SETTING_BEHAVIOUR "FilterBehaviour"
-#define DB_SETTING_AUTOADDSPAMMERS "AutoIgnoreSpammers"
-#define DB_SETTING_ALLOWEDSPAMMESSAGES "AllowedSpamMsgs"
-#define DB_SETTING_MOVETOGROUP "MoveToGroup"
-#define DB_SETTING_HIDEFROMCLIST "HideFromCList"
-#define DB_SETTING_MOVETOGROUPNAME "MoveToGroupName"
-#define DB_SETTING_LOGGING "LoggingActivated"
-#define DB_SETTING_LOGFILE "LogFile"
-
-#define DB_SETTING_ADVERTISMENTFILTER "AFActivated"
-#define DB_SETTING_ADVERTISMENT_DEFAULTBADWORDS "AFDefaultBadWordsCheck"
-#define DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS "AFCustomizedBadWordsCheck"
-#define DB_SETTING_ADVERTISMENT_CUSTOMIZEDGOODWORDS "AFGoodWordsCheck"
-#define DB_SETTING_ADVERTISMENT_FORMATING "AFDifferentFormatingCheck"
-#define DB_SETTING_ADVERTISMENT_URL "AFMsgContainsUrlCheck"
-#define DB_SETTING_ADVERTISMENT_PHONENUMBERS "AFMsgContainsPhoneNumbersCheck"
-#define DB_SETTING_ADVERTISMENT_CAPITALIZED "AFCapitalizedMsgsCheck"
-#define DB_SETTING_ADVERTISMENT_EMPTY "AFEmptyMsgsCheck"
-#define DB_SETTING_ADVERTISMENT_DEFAULTSPAMMERS "AFDefaultSpammersCheck"
-#define DB_SETTING_ADVERTISMENT_MULTIPLEMESSAGES "AFMultipleMsgsCheck"
-#define DB_SETTING_ADVERTISMENT_LASTMESSAGE "AFLastFilteredMsg"
-#define DB_SETTING_ADVERTISMENT_TEASERMESSAGES "AFTeaserMsgCheck"
-#define DB_SETTING_ADVERTISMENT_ALLOWEDBADWORDS "AFAllowedBadWords"
-#define DB_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS "AFAllowedGoodWords"
-#define DB_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS "AFAllowedFormatedWords"
-#define DB_SETTING_ADVERTISMENT_DIALOGPOSITION "AFConfigureDialog_"
-
-#define DB_SETTING_DISLIKEDMESSAGEFILTER "DFActivated"
-#define DB_SETTING_DISLIKEDMESSAGE_CUSTOMIZEDWORDS "DFIndicatingWordsCheck"
-#define DB_SETTING_DISLIKEDMESSAGE_HOAXTEXTS "DFHoaxTextsCheck"
-#define DB_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES "DFMultipleMsgsCheck"
-#define DB_SETTING_DISLIKEDMESSAGE_LASTMESSAGE "DFLastFilteredMsg"
-#define DB_SETTING_DISLIKEDMESSAGE_LASTSENDER "DFLastFilteredSender"
-#define DB_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER "DFNotifySender"
-#define DB_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE "DFNotifySenderMsg"
-#define DB_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY "DFAddReplyToHistory"
-#define DB_SETTING_DISLIKEDMESSAGE_DIALOGPOSITION "DFConfigureDialog_"
-
-#define DB_SETTING_ROBOTFILTER "RFActivated"
-#define DB_SETTING_ROBOT_INSTRUCTION "RFInstructionMsg"
-#define DB_SETTING_ROBOT_CONFIRMATION "RFConfirmationMsg"
-#define DB_SETTING_ROBOT_ADDTOHISTORY "RFAddMsgsToHistory"
-#define DB_SETTING_ROBOT_DIALOGPOSITION "RFConfigureDialog_"
-#define DB_SETTING_ROBOT_ANSWER "RFCorrectAnswer"
-#define DB_SETTING_ROBOT_HIDEUSERS "RFHideUntilConfirmed"
-
-#define DB_SETTING_SPAMDEF_DIALOGPOSITION "SpamDefinitionsDlg_"
-#define DB_SETTING_SPAMMERS_DIALOGPOSITION "SpammersDlg_"
-
-// Per contact settings
-#define DB_SETTING_ROBOT_TESTPASSED "RFTestPassed"
-#define DB_SETTING_ISSPAMMER "IsSpammer"
-
-// Sounds
-#define DB_SOUND_ADVERTISMENT_SETTING DB_MODULE_NAME"_AdvertismentFiltered"
-#define DB_SOUND_DISLIKEDMESSAGE_SETTING DB_MODULE_NAME"_DislikedMessageFiltered"
-#define DB_SOUND_ROBOT_SETTING DB_MODULE_NAME"_RobotFiltered"
-
-// Icons
-#define DB_ICON_SPAMLAYER_SETTING DB_MODULE_NAME"_SpamLayer"
-#define DB_ICON_SPAMMANUALLY_SETTING DB_MODULE_NAME"_SpamManually"
-#define DB_ICON_ISSPAMMER_SETTING DB_MODULE_NAME"_IsSpammer"
-
-// Colors
-#define DB_COLOR_POPUPBACKGROUND_SETTING DB_MODULE_NAME"_PopupBackground"
-#define DB_COLOR_POPUPTEXT_SETTING DB_MODULE_NAME"_PopupText"
-
-
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_COMMON_H__
+#define SF_COMMON_H__ 1
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+// -- Includes: CRT (C Runtime Library)
+//#include <tchar.h> // generic Ansi/Unicode functions
+#include <wchar.h> // unicode functions
+#include <stdio.h> // for mir_snprintf() etc.
+#include <process.h> // for forkthread()
+#include <time.h> // for time()
+
+// -- Includes: WinAPI
+#define _WIN32_WINNT 0x0501
+//#define WINVER 0x0502
+#define _WIN32_IE 0x0500 // for SHFileOperation
+
+#include <windows.h>
+#include <commctrl.h>
+#include <shlwapi.h>
+#include <shlobj.h>
+
+
+// -- Include: MirandaAPI
+//#define NOWIN2K
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_options.h>
+#include <m_skin.h>
+#include <m_button.h>
+#include <m_protosvc.h>
+#include <m_protocols.h>
+#include <m_protomod.h>
+#include <m_plugins.h>
+#include <m_ignore.h>
+#include <m_contacts.h>
+#include <m_utils.h>
+#include <m_url.h>
+#include <m_file.h>
+#include <m_message.h>
+#include <m_popup.h>
+//#define VARIABLES_NOHELPER
+#include <m_variables.h>
+#include <m_icolib.h>
+#include <m_clc.h>
+#include <m_fontservice.h>
+#include <m_netlib.h>
+#include <m_updater.h>
+#include <m_folders.h>
+#include "m_trigger.h"
+#include <m_icq.h>
+#include <m_cluiframes.h>
+
+// -- Includes: Header
+#include "m_spamfilter.h"
+#include "forkthread.h"
+#include "path.h"
+#include "stringlist.h"
+#include "string.h"
+#include "regexp.h"
+#include "utilities.h"
+#include "spamdefinitions.h"
+#include "spamcheckdata.h"
+#include "popup.h"
+#include "logfile.h"
+#include "contact.h"
+#include "dlg.h"
+#include "options.h"
+#include "services.h"
+#include "spamcheck.h"
+#include "variables.h"
+#include "folders.h"
+#include "trigger.h"
+#include "extraimg.h"
+#include "menuitems.h"
+#include "version.h"
+#include "resource.h"
+#include <m_system.h>
+struct MM_INTERFACE memoryManagerInterface;
+struct UTF8_INTERFACE utfi;
+
+
+
+// -- Includes: Utilities
+#if defined(_DEBUG)
+ // Memory leak and invalid access detection
+ //#define _CRTDBG_MAP_ALLOC
+ #include <crtdbg.h>
+ //#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+
+ // Check database setting type (m_database.h)
+ //#define DBCHECKSETTINGS
+#else
+ // Prevent C Runtime Library (CRT)
+ /*
+ #pragma comment(linker,"/ENTRY:DllMain")
+ #pragma comment(linker,"/NODEFAULTLIB")
+ */
+#endif
+
+// Debug Functions
+#include "Utilities/DebugHelper.h"
+
+
+// -- Variables: Plugin
+HINSTANCE hInstance;
+PLUGINLINK* pluginLink;
+
+
+// -- Variables: Window Handles
+HWND hwndSpamFilterOpt;
+HWND hwndAdvertismentFilter;
+HWND hwndRobotFilter;
+HWND hwndDislikedMessagesFilter;
+HWND hwndSpamDefinitionsInfo;
+HWND hwndSpammersInfo;
+
+// -- Variables: Message Types List
+CRITICAL_SECTION csMsgTypes;
+unsigned int uMsgTypesCount; // protected by csMsgTypes
+MESSAGETYPEDESC* pamtdMsgTypes; // protected by csMsgTypes
+
+// -- Defines: General
+#define DEFAULT_LOGFILE TranslateT("Spam.xml")
+
+#define DEFAULT_ADVERTISMENT_SOUNDFILE _T("filtered1.wav") // Sound files must not be translated and must be lower case
+#define DEFAULT_DISLIKEDMESSAGE_SOUNDFILE _T("filtered2.wav")
+#define DEFAULT_ROBOT_SOUNDFILE _T("filtered3.wav")
+
+#define SOUNDS_SUBDIRECTORY _T("Sounds") // Dirs must have no backslash at the end!
+#define DOCS_SUBDIRECTORY _T("Docs")
+#define LOGS_SUBDIRECTORY _T("Logs")
+#define DATA_SUBDIRECTORY _T("Spam Filter")
+
+#define RANDOM_ANSWER_LENGTH 8
+
+#define MAX_INT_LENGTH 15 // or just 10
+
+#define MS_CONTACTS_SEND "ContactsTransfer/SendContacts"
+#define MS_CONTACTS_RECEIVE "ContactsTransfer/ReceiveContacts"
+
+
+// -- Defines: Default Settings
+#define DEFAULT_SETTING_BEHAVIOUR 1 // 1 = Mark message read or 2 = Delete message
+#define DEFAULT_SETTING_POPUP FALSE
+#define DEFAULT_SETTING_LOGGING FALSE
+#define DEFAULT_SETTING_AUTOADDSPAMMERS TRUE
+#define DEFAULT_SETTING_ALLOWEDSPAMMESSAGES 3 // 0 to x
+#define DEFAULT_SETTING_HIDEFROMCLIST TRUE
+#define DEFAULT_SETTING_MOVETOGROUP FALSE
+#define DEFAULT_SETTING_MOVETOGROUPNAME TranslateT("Spammers")
+#define DEFAULT_SETTING_SETSPAMMERFLAGS 0 // flags can be SCASF_NO_REMOVE_HISTORY, SCASF_NO_DENY_AUTHREQUESTS, SCASF_NO_NOTIFY
+
+#define DEFAULT_SETTING_ADVERTISMENTFILTER TRUE
+#define DEFAULT_SETTING_ADVERTISMENT_DEFAULTBADWORDS TRUE
+#define DEFAULT_SETTING_ADVERTISMENT_FORMATING TRUE
+#define DEFAULT_SETTING_ADVERTISMENT_URL FALSE
+#define DEFAULT_SETTING_ADVERTISMENT_PHONENUMBERS FALSE
+#define DEFAULT_SETTING_ADVERTISMENT_CAPITALIZED FALSE
+#define DEFAULT_SETTING_ADVERTISMENT_EMPTY TRUE
+#define DEFAULT_SETTING_ADVERTISMENT_DEFAULTSPAMMERS TRUE
+#define DEFAULT_SETTING_ADVERTISMENT_MULTIPLEMESSAGES TRUE
+#define DEFAULT_SETTING_ADVERTISMENT_TEASERMESSAGES TRUE
+#define DEFAULT_SETTING_ADVERTISMENT_ALLOWEDBADWORDS 3 // 0 to x
+#define DEFAULT_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS 0 // 0 to x
+#define DEFAULT_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS 1 // 0 to x
+
+#define DEFAULT_SETTING_DISLIKEDMESSAGEFILTER FALSE
+#define DEFAULT_SETTING_DISLIKEDMESSAGE_HOAXTEXTS TRUE
+#define DEFAULT_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES TRUE
+#define DEFAULT_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER FALSE
+#define DEFAULT_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY TRUE
+#define DEFAULT_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE TranslateT("Hello %sender%,\r\nI don't like such messages. Please don't send them to me anymore.\r\nThanks.\r\n\r\n(Automated message)")
+
+#define DEFAULT_SETTING_ROBOTFILTER FALSE
+#define DEFAULT_SETTING_ROBOT_INSTRUCTION TranslateT("Hello %sender%,\r\nPlease reply \"%securitycode%\" if you want to contact me. If you don't reply correctly your messages will be ignored. Sorry for the inconvenience.\r\nThis spam check guarantees that you are a real person.\r\nYou have %triesleft% tries left.\r\nThanks in advance!\r\n\r\n(Automated message)")
+#define DEFAULT_SETTING_ROBOT_CONFIRMATION TranslateT("Thank you for your help!\r\nAll your previous messages were delivered. New messages do now reach me directly without an additional spam check.\r\n\r\n(Automated message)")
+#define DEFAULT_SETTING_ROBOT_ADDTOHISTORY TRUE
+#define DEFAULT_SETTING_ROBOT_HIDEUSERS TRUE
+
+// -- Defines: Database
+#define DB_MODULE_NAME "SpamFilter"
+#define DB_MODULE_NAME_PRESPAMMERS "SpamFilterAutoIgnore"
+#define DB_MODULE_NAME_MSGTYPES "SpamFilterMsgTypes"
+
+#define DB_SETTING_FIRSTRUNDONE "FirstRunDone"
+
+#define DB_SETTING_POPUP "PopupActivated"
+#define DB_SETTING_BEHAVIOUR "FilterBehaviour"
+#define DB_SETTING_AUTOADDSPAMMERS "AutoIgnoreSpammers"
+#define DB_SETTING_ALLOWEDSPAMMESSAGES "AllowedSpamMsgs"
+#define DB_SETTING_MOVETOGROUP "MoveToGroup"
+#define DB_SETTING_HIDEFROMCLIST "HideFromCList"
+#define DB_SETTING_MOVETOGROUPNAME "MoveToGroupName"
+#define DB_SETTING_LOGGING "LoggingActivated"
+#define DB_SETTING_LOGFILE "LogFile"
+
+#define DB_SETTING_ADVERTISMENTFILTER "AFActivated"
+#define DB_SETTING_ADVERTISMENT_DEFAULTBADWORDS "AFDefaultBadWordsCheck"
+#define DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS "AFCustomizedBadWordsCheck"
+#define DB_SETTING_ADVERTISMENT_CUSTOMIZEDGOODWORDS "AFGoodWordsCheck"
+#define DB_SETTING_ADVERTISMENT_FORMATING "AFDifferentFormatingCheck"
+#define DB_SETTING_ADVERTISMENT_URL "AFMsgContainsUrlCheck"
+#define DB_SETTING_ADVERTISMENT_PHONENUMBERS "AFMsgContainsPhoneNumbersCheck"
+#define DB_SETTING_ADVERTISMENT_CAPITALIZED "AFCapitalizedMsgsCheck"
+#define DB_SETTING_ADVERTISMENT_EMPTY "AFEmptyMsgsCheck"
+#define DB_SETTING_ADVERTISMENT_DEFAULTSPAMMERS "AFDefaultSpammersCheck"
+#define DB_SETTING_ADVERTISMENT_MULTIPLEMESSAGES "AFMultipleMsgsCheck"
+#define DB_SETTING_ADVERTISMENT_LASTMESSAGE "AFLastFilteredMsg"
+#define DB_SETTING_ADVERTISMENT_TEASERMESSAGES "AFTeaserMsgCheck"
+#define DB_SETTING_ADVERTISMENT_ALLOWEDBADWORDS "AFAllowedBadWords"
+#define DB_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS "AFAllowedGoodWords"
+#define DB_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS "AFAllowedFormatedWords"
+#define DB_SETTING_ADVERTISMENT_DIALOGPOSITION "AFConfigureDialog_"
+
+#define DB_SETTING_DISLIKEDMESSAGEFILTER "DFActivated"
+#define DB_SETTING_DISLIKEDMESSAGE_CUSTOMIZEDWORDS "DFIndicatingWordsCheck"
+#define DB_SETTING_DISLIKEDMESSAGE_HOAXTEXTS "DFHoaxTextsCheck"
+#define DB_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES "DFMultipleMsgsCheck"
+#define DB_SETTING_DISLIKEDMESSAGE_LASTMESSAGE "DFLastFilteredMsg"
+#define DB_SETTING_DISLIKEDMESSAGE_LASTSENDER "DFLastFilteredSender"
+#define DB_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER "DFNotifySender"
+#define DB_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE "DFNotifySenderMsg"
+#define DB_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY "DFAddReplyToHistory"
+#define DB_SETTING_DISLIKEDMESSAGE_DIALOGPOSITION "DFConfigureDialog_"
+
+#define DB_SETTING_ROBOTFILTER "RFActivated"
+#define DB_SETTING_ROBOT_INSTRUCTION "RFInstructionMsg"
+#define DB_SETTING_ROBOT_CONFIRMATION "RFConfirmationMsg"
+#define DB_SETTING_ROBOT_ADDTOHISTORY "RFAddMsgsToHistory"
+#define DB_SETTING_ROBOT_DIALOGPOSITION "RFConfigureDialog_"
+#define DB_SETTING_ROBOT_ANSWER "RFCorrectAnswer"
+#define DB_SETTING_ROBOT_HIDEUSERS "RFHideUntilConfirmed"
+
+#define DB_SETTING_SPAMDEF_DIALOGPOSITION "SpamDefinitionsDlg_"
+#define DB_SETTING_SPAMMERS_DIALOGPOSITION "SpammersDlg_"
+
+// Per contact settings
+#define DB_SETTING_ROBOT_TESTPASSED "RFTestPassed"
+#define DB_SETTING_ISSPAMMER "IsSpammer"
+
+// Sounds
+#define DB_SOUND_ADVERTISMENT_SETTING DB_MODULE_NAME"_AdvertismentFiltered"
+#define DB_SOUND_DISLIKEDMESSAGE_SETTING DB_MODULE_NAME"_DislikedMessageFiltered"
+#define DB_SOUND_ROBOT_SETTING DB_MODULE_NAME"_RobotFiltered"
+
+// Icons
+#define DB_ICON_SPAMLAYER_SETTING DB_MODULE_NAME"_SpamLayer"
+#define DB_ICON_SPAMMANUALLY_SETTING DB_MODULE_NAME"_SpamManually"
+#define DB_ICON_ISSPAMMER_SETTING DB_MODULE_NAME"_IsSpammer"
+
+// Colors
+#define DB_COLOR_POPUPBACKGROUND_SETTING DB_MODULE_NAME"_PopupBackground"
+#define DB_COLOR_POPUPTEXT_SETTING DB_MODULE_NAME"_PopupText"
+
+
#endif // SF_COMMON_H__ \ No newline at end of file
diff --git a/contact.c b/contact.c
index 6891b9c..97102c1 100644
--- a/contact.c
+++ b/contact.c
@@ -1,818 +1,818 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-
-// -----------------------------------------
-
-
-WORD IncreasePreSpammerCount(SPAMCHECKDATA* pscd)
-{
- WCHAR* pszUnique;
- char* pszUniqueUtf8;
- WORD sentSpam;
-
- // Get UTF-8 encoded unique str
- pszUnique = SCD_GetContactUniqueStr(pscd, FALSE);
- if (!pszUnique) return FALSE;
- pszUniqueUtf8 = mir_utf8encodeW(pszUnique);
- mir_free(pszUnique);
- if (!pszUniqueUtf8) return FALSE;
-
- // Inc count
- sentSpam = (WORD)DBGetContactSettingWord(NULL, DB_MODULE_NAME_PRESPAMMERS, pszUniqueUtf8, 0);
- sentSpam++;
- DBWriteContactSettingWord(NULL, DB_MODULE_NAME_PRESPAMMERS, pszUniqueUtf8, sentSpam);
-
- mir_free(pszUniqueUtf8);
-
- // Update "Auto-Ignore" button if options are opened
- if (IsWindow(hwndSpamFilterOpt))
- PostMessage(hwndSpamFilterOpt, SFM_CHECK_AUTOIGNORE, 0, 0);
-
- return sentSpam;
-}
-
-WORD GetPreSpammerCount(SPAMCHECKDATA* pscd)
-{
- WCHAR* pszUnique;
- char* pszUniqueUtf8;
- WORD sentSpam;
-
- // Get UTF-8 encoded unique str
- pszUnique = SCD_GetContactUniqueStr(pscd, FALSE);
- if (!pszUnique) return 0;
- pszUniqueUtf8 = mir_utf8encodeW(pszUnique);
- mir_free(pszUnique);
- if (!pszUniqueUtf8) return 0;
-
- sentSpam = (WORD)DBGetContactSettingWord(NULL, DB_MODULE_NAME_PRESPAMMERS, pszUniqueUtf8, 0);
- mir_free(pszUniqueUtf8);
- return sentSpam;
-}
-
-BOOL RemovePreSpammerCount(SPAMCHECKDATA* pscd)
-{
- WCHAR* pszUnique;
- char* pszUniqueUtf8;
- BOOL bReturn;
-
- // Get UTF-8 encoded unique str
- pszUnique = SCD_GetContactUniqueStr(pscd, FALSE);
- if (!pszUnique) return FALSE;
- pszUniqueUtf8 = mir_utf8encodeW(pszUnique);
- mir_free(pszUnique);
- if (!pszUniqueUtf8) return FALSE;
-
- bReturn = (DBDeleteContactSetting(NULL, DB_MODULE_NAME_PRESPAMMERS, pszUniqueUtf8) == 0);
-
- // Update "Auto-Ignore" button if options are opened
- if (IsWindow(hwndSpamFilterOpt))
- PostMessage(hwndSpamFilterOpt, SFM_CHECK_AUTOIGNORE, 0, 0);
-
- mir_free(pszUniqueUtf8);
- return bReturn;
-}
-
-
-int MarkAllContactEventsUnRead(HANDLE hContact)
-{
- int iReturn;
- HANDLE* hDbEvents = NULL;
- HANDLE* hDbEventsBuf;
- int iEventCount;
- HANDLE hDbEvent;
- int i;
- DBEVENTINFO dbei;
-
- iReturn = 0;
-
- // Loop through all events in the contact chain
- iEventCount = 0;
- for (hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0); hDbEvent; hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0))
- {
- // Store all events in memory
- hDbEventsBuf = (HANDLE*)mir_realloc(hDbEvents, (iEventCount+1)*sizeof(HANDLE));
- if (!hDbEventsBuf) break;
- hDbEvents = hDbEventsBuf;
- hDbEvents[iEventCount] = hDbEvent;
- iEventCount++;
- BOX2("cnt:%i, hndl:%i", iEventCount, hDbEvent);
- }
-
- // Add all old events back to the contact
- for (i=0; i<iEventCount; i++)
- {
- ZeroMemory(&dbei, sizeof(dbei));
- dbei.cbSize = sizeof(dbei);
- dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvents[i], 0);
- if (dbei.cbBlob <= 0) continue;
- dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob);
- if (!dbei.pBlob) continue;
-
- if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvents[i], (LPARAM)&dbei) == 0)
- {
- switch (dbei.eventType)
- {
- case EVENTTYPE_AUTHREQUEST:
- case EVENTTYPE_ADDED:
- case EVENTTYPE_CONTACTS:
- case EVENTTYPE_MESSAGE:
- case EVENTTYPE_URL:
- case EVENTTYPE_FILE:
- {
- if (!(dbei.flags&DBEF_SENT))
- dbei.flags ^= DBEF_READ;
-
- CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvents[i]);
-
- // Re-add event
- BOX2("handle evnts: %i hdl:%i", i, hDbEvents[i]);
- if (CallService(MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hDbEvents[i]) == 0)
- if ((HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei) != NULL)
- iReturn++;
- break;
- }
- }
- }
-
- mir_free(dbei.pBlob);
- }
-
- // Authorization requests are stored under the main contact
- // Loop through all events in the main chain
- iEventCount = 0;
- for (hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)NULL, 0); hDbEvent; hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0))
- {
- // Store all events in memory
- hDbEventsBuf = (HANDLE*)mir_realloc(hDbEvents, (iEventCount+1)*sizeof(HANDLE));
- if (!hDbEventsBuf) break;
- hDbEvents = hDbEventsBuf;
- hDbEvents[iEventCount] = hDbEvent;
- iEventCount++;
- }
-
- // Add all old events back to the contact
- for (i=0; i<iEventCount; i++)
- {
- ZeroMemory(&dbei, sizeof(dbei));
- dbei.cbSize = sizeof(dbei);
- dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvents[i], 0);
- if (dbei.cbBlob <= 0) continue;
- dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob);
- if (!dbei.pBlob) continue;
-
- if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvents[i], (LPARAM)&dbei) == 0)
- {
- if ((dbei.eventType == EVENTTYPE_AUTHREQUEST) || (dbei.eventType == EVENTTYPE_ADDED))
- {
- // DB event corrupt check
- if (dbei.cbBlob >= (sizeof(DWORD)+sizeof(HANDLE)))
- {
- if (*((PHANDLE)(dbei.pBlob+sizeof(DWORD))) == hContact)
- {
- if (!(dbei.flags&DBEF_SENT))
- dbei.flags ^= DBEF_READ;
-
- CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvents[i]);
-
- // Re-add event
- if (CallService(MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hDbEvents[i]) == 0) // if successful
- if ((HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei) != NULL)
- iReturn++;
- }
- }
- }
- }
-
- mir_free(dbei.pBlob);
- }
-
- if (hDbEvents) mir_free(hDbEvents);
- return iReturn;
-}
-
-BOOL SendContactAutomatedMessage(HANDLE hContact, WCHAR* pszMessage, BOOL bAddToHistory)
-{
- BOOL bReturn;
- WCHAR* sendBuffer;
- int bufSize;
- char* pszProto;
- int iSendRes;
-
- if (!hContact || !pszMessage || (pszMessage[0] == _T('\0'))) return FALSE;
- pszProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
- if (!pszProto) return FALSE;
-
- // Limit the message to max possible length
- {
- int iMaxLen = CallProtoService(pszProto, PS_GETCAPS, (WPARAM)PFLAG_MAXLENOFMESSAGE, (LPARAM)hContact);
- if (iMaxLen != CALLSERVICE_NOTFOUND)
- if ((int)lstrlen(pszMessage) > iMaxLen)
- pszMessage[iMaxLen] = _T('\0');
- }
-
- // Construct message text
- #if defined(UNICODE)
- {
- char* buf;
- mir_utf8decode((char*)pszMessage,&sendBuffer);
- if (!sendBuffer) return FALSE;
- bufSize = lstrlenW(sendBuffer)+1;
- bufSize *= sizeof(WCHAR)+1;
- buf = (char*)mir_realloc(sendBuffer, bufSize);
- if (!buf) {
- mir_free(sendBuffer);
- return FALSE;
- }
- }
- #else
- sendBuffer = pszMessage;
- bufSize = lstrlen(pszMessage)+1;
- #endif
-
- // Send the message
- #if defined(UNICODE)
- if (pszProto) {
- char szService[MAXMODULELABELLENGTH+10];
- mir_snprintf(szService, ARRAYSIZE(szService), "%s%sW", pszProto, PSS_MESSAGE);
- bReturn = ServiceExists(szService);
- } else {
- bReturn = FALSE;
- }
- iSendRes = CallContactService(hContact, bReturn?PSS_MESSAGE"W":PSS_MESSAGE, (WPARAM)PREF_UNICODE, (LPARAM)sendBuffer);
- #else
- iSendRes = CallContactService(hContact, PSS_MESSAGE, (WPARAM)0, (LPARAM)sendBuffer);
- #endif
- bReturn = ((iSendRes != CALLSERVICE_NOTFOUND) && (iSendRes != 0));
-
- // Add the message to history
- if (bReturn && bAddToHistory)
- {
- DBEVENTINFO dbei;
-
- ZeroMemory(&dbei, sizeof(dbei));
- dbei.cbSize = sizeof(dbei);
- dbei.timestamp = time(NULL);
- dbei.eventType = EVENTTYPE_MESSAGE;
- dbei.flags = DBEF_SENT;
- dbei.szModule = pszProto;
- dbei.cbBlob = bufSize; // Blob without terminating zero, but adding it though to avoid problems
- dbei.pBlob = (PBYTE)sendBuffer;
-
- CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);
- }
-
- #if defined(UNICODE)
- mir_free(sendBuffer);
- #endif
-
- return bReturn;
-}
-
-
-BOOL CreateContactListGroup(WCHAR* pszGroupName)
-{
- int i;
- char str[MAX_INT_LENGTH+1];
- WCHAR name[256];
- DBVARIANT dbv;
-
- if (!pszGroupName) return FALSE;
-
- for (i=0; ;i++)
- {
- mir_snprintf(str, ARRAYSIZE(str), "%i", i);
- if (DBGetContactSettingTString(NULL, "CListGroups", str, &dbv) != 0)
- break;
- if (dbv.ptszVal[0] && !StrCmpI(dbv.ptszVal+1, pszGroupName)) {
- DBFreeVariant(&dbv);
- return FALSE;
- }
- DBFreeVariant(&dbv);
- }
-
- name[0] = 1|GROUPF_EXPANDED;
- mir_sntprintf(&name[1], ARRAYSIZE(name)-1, _T("%s"), pszGroupName);
- DBWriteContactSettingTString(NULL, "CListGroups", str, name);
- CallService(MS_CLUI_GROUPADDED, (WPARAM)i+1, 0);
- return TRUE;
-}
-
-
-BOOL RemoveContactListGroup(WCHAR* pszGroupName)
-{
- int i;
- char str[MAX_INT_LENGTH+1];
- DBVARIANT dbv;
-
- if (!pszGroupName) return FALSE;
- for (i=0; ;i++)
- {
- mir_snprintf(str, ARRAYSIZE(str), "%i", i);
- if (DBGetContactSettingTString(NULL, "CListGroups", str, &dbv) != 0)
- return FALSE;
- if (dbv.ptszVal[0] && !StrCmpI(dbv.ptszVal+1, pszGroupName)) {
- DBFreeVariant(&dbv);
- break;
- }
- DBFreeVariant(&dbv);
- }
-
- // Bring up confirm window
- return (CallService(MS_CLIST_GROUPDELETE, (WPARAM)i+1, 0) == 0);
-}
-
-
-BOOL RemoveContactFromIgnoreList(HANDLE hContact)
-{
- // Un-Ignore all events for the contact
- BOOL bReturn = (CallService(MS_IGNORE_UNIGNORE, (WPARAM)hContact, IGNOREEVENT_ALL) == 0);
-
- // Remove group association
- DBDeleteContactSetting(hContact, "CList", "Group");
-
- // Restore NotOnList state
- if (!DBGetContactSettingByte(hContact, DB_MODULE_NAME, "WasOnList", 0))
- DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
- DBDeleteContactSetting(hContact, DB_MODULE_NAME, "WasOnList");
-
- // Unhide the contact
- DBDeleteContactSetting(hContact, "CList", "Hidden");
-
- // Re-Accept typing notifications
- DBWriteContactSettingByte(hContact, "SRMM", "SupportTyping", 1);
-
- // Restore not to appear as offline to the contact (back to normal mode)
- CallContactService(hContact, PSS_SETAPPARENTMODE, (WPARAM)0, 0);
-
- // Rename contact (to default name)
- DBDeleteContactSetting(hContact, "CList", "MyHandle");
- // Tell clist to refresh it's cache
- CallService(MS_CLIST_INVALIDATEDISPLAYNAME, (WPARAM)hContact, 0);
-
- // NotifySpammerStateChanged will be called automatically on settings change
- DBWriteContactSettingByte(hContact, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)FALSE);
-
- return bReturn;
-}
-
-
-BOOL AddContactToIgnoreList(HANDLE hContact, BOOL bKeepHistory, BOOL bDenyAuthRequests, BOOL bNoLog)
-{
- BOOL bReturn;
- DBVARIANT dbv;
-
- // NotifySpammerStateChanged will be called automatically on settings change
- DBWriteContactSettingByte(hContact, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)TRUE);
-
- // Ignore all events for the contact
- bReturn = (CallService(MS_IGNORE_IGNORE, (WPARAM)hContact, IGNOREEVENT_ALL) == 0);
-
- if (DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
- {
- // Hide the contact
- // (Hide it before removing NotOnList setting, so that no YouWereAdded notification is sent)
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_HIDEFROMCLIST, (BYTE)DEFAULT_SETTING_HIDEFROMCLIST))
- DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);
- else
- DBDeleteContactSetting(hContact, "CList", "Hidden");
-
- // Add permanently to list (after hide!!!)
- DBDeleteContactSetting(hContact, "CList", "NotOnList");
-
- // Remove association to a contactlist group (change to spammers)
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUP, (BYTE)DEFAULT_SETTING_MOVETOGROUP) &&
- DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUPNAME, &dbv) == 0)
- {
- CreateContactListGroup(dbv.ptszVal);
- DBWriteContactSettingTString(hContact, "CList", "Group", dbv.ptszVal);
- DBFreeVariant(&dbv);
- } else {
- DBDeleteContactSetting(hContact, "CList", "Group");
- }
- } else {
- DBWriteContactSettingByte(hContact, DB_MODULE_NAME, "WasOnList", 1);
- }
-
- // Do not send typing notifications
- DBWriteContactSettingByte(hContact, "SRMM", "SupportTyping", 0);
-
- // Appear as offline to the contact
- CallContactService(hContact, PSS_SETAPPARENTMODE, (WPARAM)ID_STATUS_OFFLINE, 0);
-
- // Rename contact
- {
- CONTACTINFO ci;
-
- ZeroMemory(&ci, sizeof(ci));
- ci.cbSize = sizeof(ci);
- ci.hContact = hContact;
- #if defined(UNICODE)
- ci.dwFlag = CNF_UNIQUEID|CNF_UNICODE;
- #else
- ci.dwFlag = CNF_UNIQUEID;
- #endif
-
- if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
- {
- WCHAR* pszUniqueID = NULL;
-
- if (ci.type == CNFT_ASCIIZ) {
- pszUniqueID = ci.pszVal; // mir_alloc used by MS_CONTACT_GETCONTACTINFO
- } else if (ci.type == CNFT_DWORD) {
- pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
- if (pszUniqueID)
- mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.dVal);
- } else if (ci.type == CNFT_WORD) {
- pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
- if (pszUniqueID)
- mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.wVal);
- } else if (ci.type == CNFT_BYTE) {
- pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
- if (pszUniqueID)
- mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.bVal);
- }
-
- if (pszUniqueID) {
- DBWriteContactSettingTString(hContact, "CList", "MyHandle", pszUniqueID);
- mir_free(pszUniqueID);
- }
- }
-/*
- pszSuffix = TranslateT(" (Spammer)");
- if (pszUniqueID && pszSuffix)
- {
- TCHAR* pszNewName = (TCHAR*)mir_alloc((lstrlen(pszUniqueID)+lstrlen(pszSuffix)+1)*sizeof(TCHAR));
-
- if (pszNewName)
- {
- mir_sntprintf(pszNewName, lstrlen(pszUniqueID)+lstrlen(pszSuffix)+1, _T("%s%s"), pszUniqueID, pszSuffix);
-
- DBWriteContactSettingTString(hContact, "CList", "MyHandle", pszNewName);
-
- // Tell CList to refresh it's cache
- CallService(MS_CLIST_INVALIDATEDISPLAYNAME, (WPARAM)hContact, 0);
-
- mir_free(pszNewName);
- }
- }
-*/
- }
-
- // Remove History (or mark read to get rid of pending "new message" notifications)
- {
- HANDLE hDbEvent, hDbEventBuf;
-
- STRINGLIST* pslRecognition = NULL;
- DBEVENTINFO dbei;
- PBYTE pLogText;
- WCHAR* pszUserName;
- BOOL bDoWriteLog;
-
- bDoWriteLog = !bNoLog && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, DEFAULT_SETTING_LOGGING);
- if (bDoWriteLog)
- {
- pslRecognition = SLNewList();
- SLAddItem(pslRecognition, TranslateT("Contact set as spammer"));
- }
-
- // ** History of the contact **
- // hDbEvent gets buffered to allow deleting while enumerating (handle is offset)
- hDbEventBuf = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0);
- hDbEvent = hDbEventBuf;
-
- while (hDbEvent)
- {
- hDbEventBuf = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hDbEvent, 0);
-
- // Now handle hDbEvent
- {
- if (bDoWriteLog || bDenyAuthRequests)
- {
- ZeroMemory(&dbei, sizeof(dbei));
- dbei.cbSize = sizeof(dbei);
- dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0);
- if (dbei.cbBlob <= 0)
- {
- dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob+sizeof(WCHAR)); // adding terminating zeros (security)
- if (!dbei.pBlob)
- {
- // Ensure terminating zero
- ZeroMemory(dbei.pBlob+dbei.cbBlob, sizeof(WCHAR));
-
- if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei) == 0) // if successful
- {
- if (!(dbei.flags&DBEF_SENT) && !(dbei.flags&DBEF_READ))
- {
- switch (dbei.eventType)
- {
- case EVENTTYPE_MESSAGE:
- {
- if (bDoWriteLog)
- {
- if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_MESSAGE))
- {
- #if defined(UNICODE)
- // Checking if Unicode text available
- if (dbei.cbBlob > lstrlenA((char*)dbei.pBlob))
- pLogText = dbei.pBlob+(lstrlenA((char*)dbei.pBlob)+1)*sizeof(char);
- else
- pLogText = (PBYTE)mir_utf8encodeW((WCHAR*)dbei.pBlob);
- #else
- pLogText = dbei.pBlob;
- #endif
-
- pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
- WriteToLogFile(dbei.szModule, SFMT_MESSAGE, pszUserName, (WCHAR*)pLogText, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
-
- #if defined(UNICODE)
- if (pLogText)
- if (dbei.cbBlob <= lstrlenA((char*)dbei.pBlob))
- mir_free(pLogText);
- #endif
- }
- }
- break;
- }
-
- case EVENTTYPE_URL:
- {
- if (bDoWriteLog)
- {
- if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_URL))
- {
- // DB event corrupt check
- if (dbei.cbBlob >= 2*sizeof(char))
- {
- pLogText = dbei.pBlob+(lstrlenA((char*)dbei.pBlob)+1)*sizeof(char);
-
- #if defined(UNICODE)
- pLogText = (PBYTE)mir_utf8encodeW((WCHAR*)pLogText);
- #endif
-
- pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
-
- WriteToLogFile(dbei.szModule, SFMT_URL, pszUserName, (WCHAR*)pLogText, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
-
- #if defined(UNICODE)
- if (pLogText) mir_free(pLogText);
- #endif
- }
- }
- }
- break;
- }
-
- case EVENTTYPE_FILE:
- {
- if (bDoWriteLog)
- {
- if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_FILE))
- {
- // DB event corrupt check
- if (dbei.cbBlob >= (sizeof(DWORD)+3*sizeof(char)))
- {
- pLogText = dbei.pBlob+sizeof(DWORD); // hTransfer, filename(s)
- pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // description
-
- #if defined(UNICODE)
- pLogText = (PBYTE)mir_utf8encodeW((WCHAR*)pLogText);
- #endif
-
- pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
-
- WriteToLogFile(dbei.szModule, SFMT_FILE, pszUserName, (WCHAR*)pLogText, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
-
- #if defined(UNICODE)
- if (pLogText) mir_free(pLogText);
- #endif
- }
- }
- }
- break;
- }
-
- case EVENTTYPE_CONTACTS:
- {
- if (bDoWriteLog)
- {
- if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_CONTACTS))
- {
- pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
-
- WriteToLogFile(dbei.szModule, SFMT_CONTACTS, pszUserName, NULL, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
- }
- }
- break;
- }
-
- case EVENTTYPE_AUTHREQUEST:
- {
- if (bDoWriteLog)
- {
- if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_MESSAGE))
- {
- // DB event corrupt check
- if (dbei.cbBlob >= (sizeof(DWORD)+sizeof(HANDLE)+5*sizeof(char)))
- {
- pLogText = dbei.pBlob+sizeof(DWORD)+sizeof(HANDLE); // uin, hcontact, nick
- pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // first
- pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // last
- pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // email
- pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // reason
-
- #if defined(UNICODE)
- pLogText = (PBYTE)mir_utf8encodeW((WCHAR*)pLogText);
- #endif
-
- pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
-
- WriteToLogFile(dbei.szModule, SFMT_AUTHREQUEST, pszUserName, (WCHAR*)pLogText, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
-
- #if defined(UNICODE)
- if (pLogText) mir_free(pLogText);
- #endif
- }
- }
- }
-
- // Deny authorisation
- if (bDenyAuthRequests)
- CallProtoService(dbei.szModule, PS_AUTHDENY, (WPARAM)hDbEvent, (LPARAM)NULL); // without reason
-
- break;
- }
-
- case EVENTTYPE_ADDED:
- {
- if (bDoWriteLog)
- {
- if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_MESSAGE))
- {
- pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
-
- WriteToLogFile(dbei.szModule, SFMT_ADDED, pszUserName, NULL, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
- }
- }
- break;
- }
-
- } // switch
- }
-
- mir_free(dbei.pBlob);
- }
- }
- }
- }
-
- CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvent);
-
- if (bKeepHistory)
- CallService(MS_DB_EVENT_MARKREAD, (WPARAM)hContact, (LPARAM)hDbEvent);
- else
- CallService(MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hDbEvent);
- }
-
- hDbEvent = hDbEventBuf;
- }
-
- return TRUE;
-
- // ** Main contact **
- // Authorization Requests and Added Notifications are stored under the main contact
- // hDbEvent gets buffered to allow deleting while enumerating (handle is offset)
- hDbEventBuf = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0);
- hDbEvent = hDbEventBuf;
-
- while (hDbEvent)
- {
- hDbEventBuf = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hDbEvent, 0);
-
- // Now handle hDbEvent
- {
- ZeroMemory(&dbei,sizeof(dbei));
- dbei.cbSize = sizeof(dbei);
- dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0);
- if (dbei.cbBlob < 0)
- {
- dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob+sizeof(WCHAR));
- if (dbei.pBlob)
- {
- // Ensure terminating zero
- ZeroMemory(dbei.pBlob+dbei.cbBlob, sizeof(WCHAR));
-
- if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei) == 0)
- {
- if ((dbei.eventType == EVENTTYPE_AUTHREQUEST) || (dbei.eventType == EVENTTYPE_ADDED))
- {
- // DB event corrupt check
- if (dbei.cbBlob >= (sizeof(DWORD)+sizeof(HANDLE)))
- {
- if (*((PHANDLE)(dbei.pBlob+sizeof(DWORD))) == hContact)
- {
- if (bDoWriteLog || bDenyAuthRequests)
- {
- if (!(dbei.flags&DBEF_SENT) && !(dbei.flags&DBEF_READ))
- {
- switch (dbei.eventType)
- {
- case EVENTTYPE_AUTHREQUEST:
- {
- if (bDoWriteLog)
- {
- if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_AUTHREQUEST))
- {
- // DB event corrupt check
- if (dbei.cbBlob >= (sizeof(DWORD)+sizeof(HANDLE)+5*sizeof(char)))
- {
- pLogText = dbei.pBlob+sizeof(DWORD)+sizeof(HANDLE); // uin, hcontact, nick
- pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // first
- pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // last
- pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // email
- pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // reason
-
- #if defined(UNICODE)
- pLogText = (PBYTE)mir_utf8encodeW((WCHAR*)pLogText);
- #endif
-
- pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
-
- WriteToLogFile(dbei.szModule, SFMT_AUTHREQUEST, pszUserName, (WCHAR*)pLogText, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
-
- #if defined(UNICODE)
- if (pLogText) mir_free(pLogText);
- #endif
- }
- }
- }
-
- // Deny authorisation
- if (bDenyAuthRequests)
- CallProtoService(dbei.szModule, PS_AUTHDENY, (WPARAM)hDbEvent, (LPARAM)NULL); // without reason
-
- break;
- }
-
- case EVENTTYPE_ADDED:
- {
- if (bDoWriteLog)
- {
- if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_ADDED))
- {
- pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
-
- WriteToLogFile(dbei.szModule, SFMT_ADDED, pszUserName, NULL, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
- }
- }
- break;
- }
- } // switch
- }
- }
-
- CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvent);
-
- if (bKeepHistory)
- CallService(MS_DB_EVENT_MARKREAD, (WPARAM)hContact, (LPARAM)hDbEvent);
- else
- CallService(MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hDbEvent); }
- }
- }
-
- }
-
- mir_free(dbei.pBlob);
- }
- }
-
- }
-
- hDbEvent = hDbEventBuf;
- }
- }
-
- return bReturn;
-}
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+
+// -----------------------------------------
+
+
+WORD IncreasePreSpammerCount(SPAMCHECKDATA* pscd)
+{
+ WCHAR* pszUnique;
+ char* pszUniqueUtf8;
+ WORD sentSpam;
+
+ // Get UTF-8 encoded unique str
+ pszUnique = SCD_GetContactUniqueStr(pscd, FALSE);
+ if (!pszUnique) return FALSE;
+ pszUniqueUtf8 = mir_utf8encodeW(pszUnique);
+ mir_free(pszUnique);
+ if (!pszUniqueUtf8) return FALSE;
+
+ // Inc count
+ sentSpam = (WORD)DBGetContactSettingWord(NULL, DB_MODULE_NAME_PRESPAMMERS, pszUniqueUtf8, 0);
+ sentSpam++;
+ DBWriteContactSettingWord(NULL, DB_MODULE_NAME_PRESPAMMERS, pszUniqueUtf8, sentSpam);
+
+ mir_free(pszUniqueUtf8);
+
+ // Update "Auto-Ignore" button if options are opened
+ if (IsWindow(hwndSpamFilterOpt))
+ PostMessage(hwndSpamFilterOpt, SFM_CHECK_AUTOIGNORE, 0, 0);
+
+ return sentSpam;
+}
+
+WORD GetPreSpammerCount(SPAMCHECKDATA* pscd)
+{
+ WCHAR* pszUnique;
+ char* pszUniqueUtf8;
+ WORD sentSpam;
+
+ // Get UTF-8 encoded unique str
+ pszUnique = SCD_GetContactUniqueStr(pscd, FALSE);
+ if (!pszUnique) return 0;
+ pszUniqueUtf8 = mir_utf8encodeW(pszUnique);
+ mir_free(pszUnique);
+ if (!pszUniqueUtf8) return 0;
+
+ sentSpam = (WORD)DBGetContactSettingWord(NULL, DB_MODULE_NAME_PRESPAMMERS, pszUniqueUtf8, 0);
+ mir_free(pszUniqueUtf8);
+ return sentSpam;
+}
+
+BOOL RemovePreSpammerCount(SPAMCHECKDATA* pscd)
+{
+ WCHAR* pszUnique;
+ char* pszUniqueUtf8;
+ BOOL bReturn;
+
+ // Get UTF-8 encoded unique str
+ pszUnique = SCD_GetContactUniqueStr(pscd, FALSE);
+ if (!pszUnique) return FALSE;
+ pszUniqueUtf8 = mir_utf8encodeW(pszUnique);
+ mir_free(pszUnique);
+ if (!pszUniqueUtf8) return FALSE;
+
+ bReturn = (DBDeleteContactSetting(NULL, DB_MODULE_NAME_PRESPAMMERS, pszUniqueUtf8) == 0);
+
+ // Update "Auto-Ignore" button if options are opened
+ if (IsWindow(hwndSpamFilterOpt))
+ PostMessage(hwndSpamFilterOpt, SFM_CHECK_AUTOIGNORE, 0, 0);
+
+ mir_free(pszUniqueUtf8);
+ return bReturn;
+}
+
+
+int MarkAllContactEventsUnRead(HANDLE hContact)
+{
+ int iReturn;
+ HANDLE* hDbEvents = NULL;
+ HANDLE* hDbEventsBuf;
+ int iEventCount;
+ HANDLE hDbEvent;
+ int i;
+ DBEVENTINFO dbei;
+
+ iReturn = 0;
+
+ // Loop through all events in the contact chain
+ iEventCount = 0;
+ for (hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0); hDbEvent; hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0))
+ {
+ // Store all events in memory
+ hDbEventsBuf = (HANDLE*)mir_realloc(hDbEvents, (iEventCount+1)*sizeof(HANDLE));
+ if (!hDbEventsBuf) break;
+ hDbEvents = hDbEventsBuf;
+ hDbEvents[iEventCount] = hDbEvent;
+ iEventCount++;
+ BOX2("cnt:%i, hndl:%i", iEventCount, hDbEvent);
+ }
+
+ // Add all old events back to the contact
+ for (i=0; i<iEventCount; i++)
+ {
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvents[i], 0);
+ if (dbei.cbBlob <= 0) continue;
+ dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob);
+ if (!dbei.pBlob) continue;
+
+ if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvents[i], (LPARAM)&dbei) == 0)
+ {
+ switch (dbei.eventType)
+ {
+ case EVENTTYPE_AUTHREQUEST:
+ case EVENTTYPE_ADDED:
+ case EVENTTYPE_CONTACTS:
+ case EVENTTYPE_MESSAGE:
+ case EVENTTYPE_URL:
+ case EVENTTYPE_FILE:
+ {
+ if (!(dbei.flags&DBEF_SENT))
+ dbei.flags ^= DBEF_READ;
+
+ CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvents[i]);
+
+ // Re-add event
+ BOX2("handle evnts: %i hdl:%i", i, hDbEvents[i]);
+ if (CallService(MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hDbEvents[i]) == 0)
+ if ((HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei) != NULL)
+ iReturn++;
+ break;
+ }
+ }
+ }
+
+ mir_free(dbei.pBlob);
+ }
+
+ // Authorization requests are stored under the main contact
+ // Loop through all events in the main chain
+ iEventCount = 0;
+ for (hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)NULL, 0); hDbEvent; hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0))
+ {
+ // Store all events in memory
+ hDbEventsBuf = (HANDLE*)mir_realloc(hDbEvents, (iEventCount+1)*sizeof(HANDLE));
+ if (!hDbEventsBuf) break;
+ hDbEvents = hDbEventsBuf;
+ hDbEvents[iEventCount] = hDbEvent;
+ iEventCount++;
+ }
+
+ // Add all old events back to the contact
+ for (i=0; i<iEventCount; i++)
+ {
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvents[i], 0);
+ if (dbei.cbBlob <= 0) continue;
+ dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob);
+ if (!dbei.pBlob) continue;
+
+ if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvents[i], (LPARAM)&dbei) == 0)
+ {
+ if ((dbei.eventType == EVENTTYPE_AUTHREQUEST) || (dbei.eventType == EVENTTYPE_ADDED))
+ {
+ // DB event corrupt check
+ if (dbei.cbBlob >= (sizeof(DWORD)+sizeof(HANDLE)))
+ {
+ if (*((PHANDLE)(dbei.pBlob+sizeof(DWORD))) == hContact)
+ {
+ if (!(dbei.flags&DBEF_SENT))
+ dbei.flags ^= DBEF_READ;
+
+ CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvents[i]);
+
+ // Re-add event
+ if (CallService(MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hDbEvents[i]) == 0) // if successful
+ if ((HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei) != NULL)
+ iReturn++;
+ }
+ }
+ }
+ }
+
+ mir_free(dbei.pBlob);
+ }
+
+ if (hDbEvents) mir_free(hDbEvents);
+ return iReturn;
+}
+
+BOOL SendContactAutomatedMessage(HANDLE hContact, WCHAR* pszMessage, BOOL bAddToHistory)
+{
+ BOOL bReturn;
+ WCHAR* sendBuffer;
+ int bufSize;
+ char* pszProto;
+ int iSendRes;
+
+ if (!hContact || !pszMessage || (pszMessage[0] == _T('\0'))) return FALSE;
+ pszProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (!pszProto) return FALSE;
+
+ // Limit the message to max possible length
+ {
+ int iMaxLen = CallProtoService(pszProto, PS_GETCAPS, (WPARAM)PFLAG_MAXLENOFMESSAGE, (LPARAM)hContact);
+ if (iMaxLen != CALLSERVICE_NOTFOUND)
+ if ((int)lstrlen(pszMessage) > iMaxLen)
+ pszMessage[iMaxLen] = _T('\0');
+ }
+
+ // Construct message text
+ #if defined(UNICODE)
+ {
+ char* buf;
+ mir_utf8decode((char*)pszMessage,&sendBuffer);
+ if (!sendBuffer) return FALSE;
+ bufSize = lstrlenW(sendBuffer)+1;
+ bufSize *= sizeof(WCHAR)+1;
+ buf = (char*)mir_realloc(sendBuffer, bufSize);
+ if (!buf) {
+ mir_free(sendBuffer);
+ return FALSE;
+ }
+ }
+ #else
+ sendBuffer = pszMessage;
+ bufSize = lstrlen(pszMessage)+1;
+ #endif
+
+ // Send the message
+ #if defined(UNICODE)
+ if (pszProto) {
+ char szService[MAXMODULELABELLENGTH+10];
+ mir_snprintf(szService, ARRAYSIZE(szService), "%s%sW", pszProto, PSS_MESSAGE);
+ bReturn = ServiceExists(szService);
+ } else {
+ bReturn = FALSE;
+ }
+ iSendRes = CallContactService(hContact, bReturn?PSS_MESSAGE"W":PSS_MESSAGE, (WPARAM)PREF_UNICODE, (LPARAM)sendBuffer);
+ #else
+ iSendRes = CallContactService(hContact, PSS_MESSAGE, (WPARAM)0, (LPARAM)sendBuffer);
+ #endif
+ bReturn = ((iSendRes != CALLSERVICE_NOTFOUND) && (iSendRes != 0));
+
+ // Add the message to history
+ if (bReturn && bAddToHistory)
+ {
+ DBEVENTINFO dbei;
+
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.timestamp = time(NULL);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.flags = DBEF_SENT;
+ dbei.szModule = pszProto;
+ dbei.cbBlob = bufSize; // Blob without terminating zero, but adding it though to avoid problems
+ dbei.pBlob = (PBYTE)sendBuffer;
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);
+ }
+
+ #if defined(UNICODE)
+ mir_free(sendBuffer);
+ #endif
+
+ return bReturn;
+}
+
+
+BOOL CreateContactListGroup(WCHAR* pszGroupName)
+{
+ int i;
+ char str[MAX_INT_LENGTH+1];
+ WCHAR name[256];
+ DBVARIANT dbv;
+
+ if (!pszGroupName) return FALSE;
+
+ for (i=0; ;i++)
+ {
+ mir_snprintf(str, ARRAYSIZE(str), "%i", i);
+ if (DBGetContactSettingTString(NULL, "CListGroups", str, &dbv) != 0)
+ break;
+ if (dbv.ptszVal[0] && !StrCmpI(dbv.ptszVal+1, pszGroupName)) {
+ DBFreeVariant(&dbv);
+ return FALSE;
+ }
+ DBFreeVariant(&dbv);
+ }
+
+ name[0] = 1|GROUPF_EXPANDED;
+ mir_sntprintf(&name[1], ARRAYSIZE(name)-1, _T("%s"), pszGroupName);
+ DBWriteContactSettingTString(NULL, "CListGroups", str, name);
+ CallService(MS_CLUI_GROUPADDED, (WPARAM)i+1, 0);
+ return TRUE;
+}
+
+
+BOOL RemoveContactListGroup(WCHAR* pszGroupName)
+{
+ int i;
+ char str[MAX_INT_LENGTH+1];
+ DBVARIANT dbv;
+
+ if (!pszGroupName) return FALSE;
+ for (i=0; ;i++)
+ {
+ mir_snprintf(str, ARRAYSIZE(str), "%i", i);
+ if (DBGetContactSettingTString(NULL, "CListGroups", str, &dbv) != 0)
+ return FALSE;
+ if (dbv.ptszVal[0] && !StrCmpI(dbv.ptszVal+1, pszGroupName)) {
+ DBFreeVariant(&dbv);
+ break;
+ }
+ DBFreeVariant(&dbv);
+ }
+
+ // Bring up confirm window
+ return (CallService(MS_CLIST_GROUPDELETE, (WPARAM)i+1, 0) == 0);
+}
+
+
+BOOL RemoveContactFromIgnoreList(HANDLE hContact)
+{
+ // Un-Ignore all events for the contact
+ BOOL bReturn = (CallService(MS_IGNORE_UNIGNORE, (WPARAM)hContact, IGNOREEVENT_ALL) == 0);
+
+ // Remove group association
+ DBDeleteContactSetting(hContact, "CList", "Group");
+
+ // Restore NotOnList state
+ if (!DBGetContactSettingByte(hContact, DB_MODULE_NAME, "WasOnList", 0))
+ DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
+ DBDeleteContactSetting(hContact, DB_MODULE_NAME, "WasOnList");
+
+ // Unhide the contact
+ DBDeleteContactSetting(hContact, "CList", "Hidden");
+
+ // Re-Accept typing notifications
+ DBWriteContactSettingByte(hContact, "SRMM", "SupportTyping", 1);
+
+ // Restore not to appear as offline to the contact (back to normal mode)
+ CallContactService(hContact, PSS_SETAPPARENTMODE, (WPARAM)0, 0);
+
+ // Rename contact (to default name)
+ DBDeleteContactSetting(hContact, "CList", "MyHandle");
+ // Tell clist to refresh it's cache
+ CallService(MS_CLIST_INVALIDATEDISPLAYNAME, (WPARAM)hContact, 0);
+
+ // NotifySpammerStateChanged will be called automatically on settings change
+ DBWriteContactSettingByte(hContact, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)FALSE);
+
+ return bReturn;
+}
+
+
+BOOL AddContactToIgnoreList(HANDLE hContact, BOOL bKeepHistory, BOOL bDenyAuthRequests, BOOL bNoLog)
+{
+ BOOL bReturn;
+ DBVARIANT dbv;
+
+ // NotifySpammerStateChanged will be called automatically on settings change
+ DBWriteContactSettingByte(hContact, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)TRUE);
+
+ // Ignore all events for the contact
+ bReturn = (CallService(MS_IGNORE_IGNORE, (WPARAM)hContact, IGNOREEVENT_ALL) == 0);
+
+ if (DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ {
+ // Hide the contact
+ // (Hide it before removing NotOnList setting, so that no YouWereAdded notification is sent)
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_HIDEFROMCLIST, (BYTE)DEFAULT_SETTING_HIDEFROMCLIST))
+ DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);
+ else
+ DBDeleteContactSetting(hContact, "CList", "Hidden");
+
+ // Add permanently to list (after hide!!!)
+ DBDeleteContactSetting(hContact, "CList", "NotOnList");
+
+ // Remove association to a contactlist group (change to spammers)
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUP, (BYTE)DEFAULT_SETTING_MOVETOGROUP) &&
+ DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUPNAME, &dbv) == 0)
+ {
+ CreateContactListGroup(dbv.ptszVal);
+ DBWriteContactSettingTString(hContact, "CList", "Group", dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ DBDeleteContactSetting(hContact, "CList", "Group");
+ }
+ } else {
+ DBWriteContactSettingByte(hContact, DB_MODULE_NAME, "WasOnList", 1);
+ }
+
+ // Do not send typing notifications
+ DBWriteContactSettingByte(hContact, "SRMM", "SupportTyping", 0);
+
+ // Appear as offline to the contact
+ CallContactService(hContact, PSS_SETAPPARENTMODE, (WPARAM)ID_STATUS_OFFLINE, 0);
+
+ // Rename contact
+ {
+ CONTACTINFO ci;
+
+ ZeroMemory(&ci, sizeof(ci));
+ ci.cbSize = sizeof(ci);
+ ci.hContact = hContact;
+ #if defined(UNICODE)
+ ci.dwFlag = CNF_UNIQUEID|CNF_UNICODE;
+ #else
+ ci.dwFlag = CNF_UNIQUEID;
+ #endif
+
+ if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
+ {
+ WCHAR* pszUniqueID = NULL;
+
+ if (ci.type == CNFT_ASCIIZ) {
+ pszUniqueID = ci.pszVal; // mir_alloc used by MS_CONTACT_GETCONTACTINFO
+ } else if (ci.type == CNFT_DWORD) {
+ pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
+ if (pszUniqueID)
+ mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.dVal);
+ } else if (ci.type == CNFT_WORD) {
+ pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
+ if (pszUniqueID)
+ mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.wVal);
+ } else if (ci.type == CNFT_BYTE) {
+ pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
+ if (pszUniqueID)
+ mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.bVal);
+ }
+
+ if (pszUniqueID) {
+ DBWriteContactSettingTString(hContact, "CList", "MyHandle", pszUniqueID);
+ mir_free(pszUniqueID);
+ }
+ }
+/*
+ pszSuffix = TranslateT(" (Spammer)");
+ if (pszUniqueID && pszSuffix)
+ {
+ TCHAR* pszNewName = (TCHAR*)mir_alloc((lstrlen(pszUniqueID)+lstrlen(pszSuffix)+1)*sizeof(TCHAR));
+
+ if (pszNewName)
+ {
+ mir_sntprintf(pszNewName, lstrlen(pszUniqueID)+lstrlen(pszSuffix)+1, _T("%s%s"), pszUniqueID, pszSuffix);
+
+ DBWriteContactSettingTString(hContact, "CList", "MyHandle", pszNewName);
+
+ // Tell CList to refresh it's cache
+ CallService(MS_CLIST_INVALIDATEDISPLAYNAME, (WPARAM)hContact, 0);
+
+ mir_free(pszNewName);
+ }
+ }
+*/
+ }
+
+ // Remove History (or mark read to get rid of pending "new message" notifications)
+ {
+ HANDLE hDbEvent, hDbEventBuf;
+
+ STRINGLIST* pslRecognition = NULL;
+ DBEVENTINFO dbei;
+ PBYTE pLogText;
+ WCHAR* pszUserName;
+ BOOL bDoWriteLog;
+
+ bDoWriteLog = !bNoLog && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, DEFAULT_SETTING_LOGGING);
+ if (bDoWriteLog)
+ {
+ pslRecognition = SLNewList();
+ SLAddItem(pslRecognition, TranslateT("Contact set as spammer"));
+ }
+
+ // ** History of the contact **
+ // hDbEvent gets buffered to allow deleting while enumerating (handle is offset)
+ hDbEventBuf = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0);
+ hDbEvent = hDbEventBuf;
+
+ while (hDbEvent)
+ {
+ hDbEventBuf = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hDbEvent, 0);
+
+ // Now handle hDbEvent
+ {
+ if (bDoWriteLog || bDenyAuthRequests)
+ {
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0);
+ if (dbei.cbBlob <= 0)
+ {
+ dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob+sizeof(WCHAR)); // adding terminating zeros (security)
+ if (!dbei.pBlob)
+ {
+ // Ensure terminating zero
+ ZeroMemory(dbei.pBlob+dbei.cbBlob, sizeof(WCHAR));
+
+ if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei) == 0) // if successful
+ {
+ if (!(dbei.flags&DBEF_SENT) && !(dbei.flags&DBEF_READ))
+ {
+ switch (dbei.eventType)
+ {
+ case EVENTTYPE_MESSAGE:
+ {
+ if (bDoWriteLog)
+ {
+ if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_MESSAGE))
+ {
+ #if defined(UNICODE)
+ // Checking if Unicode text available
+ if (dbei.cbBlob > lstrlenA((char*)dbei.pBlob))
+ pLogText = dbei.pBlob+(lstrlenA((char*)dbei.pBlob)+1)*sizeof(char);
+ else
+ pLogText = (PBYTE)mir_utf8encodeW((WCHAR*)dbei.pBlob);
+ #else
+ pLogText = dbei.pBlob;
+ #endif
+
+ pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
+ WriteToLogFile(dbei.szModule, SFMT_MESSAGE, pszUserName, (WCHAR*)pLogText, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
+
+ #if defined(UNICODE)
+ if (pLogText)
+ if (dbei.cbBlob <= lstrlenA((char*)dbei.pBlob))
+ mir_free(pLogText);
+ #endif
+ }
+ }
+ break;
+ }
+
+ case EVENTTYPE_URL:
+ {
+ if (bDoWriteLog)
+ {
+ if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_URL))
+ {
+ // DB event corrupt check
+ if (dbei.cbBlob >= 2*sizeof(char))
+ {
+ pLogText = dbei.pBlob+(lstrlenA((char*)dbei.pBlob)+1)*sizeof(char);
+
+ #if defined(UNICODE)
+ pLogText = (PBYTE)mir_utf8encodeW((WCHAR*)pLogText);
+ #endif
+
+ pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
+
+ WriteToLogFile(dbei.szModule, SFMT_URL, pszUserName, (WCHAR*)pLogText, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
+
+ #if defined(UNICODE)
+ if (pLogText) mir_free(pLogText);
+ #endif
+ }
+ }
+ }
+ break;
+ }
+
+ case EVENTTYPE_FILE:
+ {
+ if (bDoWriteLog)
+ {
+ if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_FILE))
+ {
+ // DB event corrupt check
+ if (dbei.cbBlob >= (sizeof(DWORD)+3*sizeof(char)))
+ {
+ pLogText = dbei.pBlob+sizeof(DWORD); // hTransfer, filename(s)
+ pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // description
+
+ #if defined(UNICODE)
+ pLogText = (PBYTE)mir_utf8encodeW((WCHAR*)pLogText);
+ #endif
+
+ pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
+
+ WriteToLogFile(dbei.szModule, SFMT_FILE, pszUserName, (WCHAR*)pLogText, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
+
+ #if defined(UNICODE)
+ if (pLogText) mir_free(pLogText);
+ #endif
+ }
+ }
+ }
+ break;
+ }
+
+ case EVENTTYPE_CONTACTS:
+ {
+ if (bDoWriteLog)
+ {
+ if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_CONTACTS))
+ {
+ pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
+
+ WriteToLogFile(dbei.szModule, SFMT_CONTACTS, pszUserName, NULL, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
+ }
+ }
+ break;
+ }
+
+ case EVENTTYPE_AUTHREQUEST:
+ {
+ if (bDoWriteLog)
+ {
+ if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_MESSAGE))
+ {
+ // DB event corrupt check
+ if (dbei.cbBlob >= (sizeof(DWORD)+sizeof(HANDLE)+5*sizeof(char)))
+ {
+ pLogText = dbei.pBlob+sizeof(DWORD)+sizeof(HANDLE); // uin, hcontact, nick
+ pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // first
+ pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // last
+ pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // email
+ pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // reason
+
+ #if defined(UNICODE)
+ pLogText = (PBYTE)mir_utf8encodeW((WCHAR*)pLogText);
+ #endif
+
+ pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
+
+ WriteToLogFile(dbei.szModule, SFMT_AUTHREQUEST, pszUserName, (WCHAR*)pLogText, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
+
+ #if defined(UNICODE)
+ if (pLogText) mir_free(pLogText);
+ #endif
+ }
+ }
+ }
+
+ // Deny authorisation
+ if (bDenyAuthRequests)
+ CallProtoService(dbei.szModule, PS_AUTHDENY, (WPARAM)hDbEvent, (LPARAM)NULL); // without reason
+
+ break;
+ }
+
+ case EVENTTYPE_ADDED:
+ {
+ if (bDoWriteLog)
+ {
+ if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_MESSAGE))
+ {
+ pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
+
+ WriteToLogFile(dbei.szModule, SFMT_ADDED, pszUserName, NULL, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
+ }
+ }
+ break;
+ }
+
+ } // switch
+ }
+
+ mir_free(dbei.pBlob);
+ }
+ }
+ }
+ }
+
+ CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvent);
+
+ if (bKeepHistory)
+ CallService(MS_DB_EVENT_MARKREAD, (WPARAM)hContact, (LPARAM)hDbEvent);
+ else
+ CallService(MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hDbEvent);
+ }
+
+ hDbEvent = hDbEventBuf;
+ }
+
+ return TRUE;
+
+ // ** Main contact **
+ // Authorization Requests and Added Notifications are stored under the main contact
+ // hDbEvent gets buffered to allow deleting while enumerating (handle is offset)
+ hDbEventBuf = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0);
+ hDbEvent = hDbEventBuf;
+
+ while (hDbEvent)
+ {
+ hDbEventBuf = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hDbEvent, 0);
+
+ // Now handle hDbEvent
+ {
+ ZeroMemory(&dbei,sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0);
+ if (dbei.cbBlob < 0)
+ {
+ dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob+sizeof(WCHAR));
+ if (dbei.pBlob)
+ {
+ // Ensure terminating zero
+ ZeroMemory(dbei.pBlob+dbei.cbBlob, sizeof(WCHAR));
+
+ if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei) == 0)
+ {
+ if ((dbei.eventType == EVENTTYPE_AUTHREQUEST) || (dbei.eventType == EVENTTYPE_ADDED))
+ {
+ // DB event corrupt check
+ if (dbei.cbBlob >= (sizeof(DWORD)+sizeof(HANDLE)))
+ {
+ if (*((PHANDLE)(dbei.pBlob+sizeof(DWORD))) == hContact)
+ {
+ if (bDoWriteLog || bDenyAuthRequests)
+ {
+ if (!(dbei.flags&DBEF_SENT) && !(dbei.flags&DBEF_READ))
+ {
+ switch (dbei.eventType)
+ {
+ case EVENTTYPE_AUTHREQUEST:
+ {
+ if (bDoWriteLog)
+ {
+ if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_AUTHREQUEST))
+ {
+ // DB event corrupt check
+ if (dbei.cbBlob >= (sizeof(DWORD)+sizeof(HANDLE)+5*sizeof(char)))
+ {
+ pLogText = dbei.pBlob+sizeof(DWORD)+sizeof(HANDLE); // uin, hcontact, nick
+ pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // first
+ pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // last
+ pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // email
+ pLogText = pLogText+(lstrlenA((char*)pLogText)+1)*sizeof(char); // reason
+
+ #if defined(UNICODE)
+ pLogText = (PBYTE)mir_utf8encodeW((WCHAR*)pLogText);
+ #endif
+
+ pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
+
+ WriteToLogFile(dbei.szModule, SFMT_AUTHREQUEST, pszUserName, (WCHAR*)pLogText, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
+
+ #if defined(UNICODE)
+ if (pLogText) mir_free(pLogText);
+ #endif
+ }
+ }
+ }
+
+ // Deny authorisation
+ if (bDenyAuthRequests)
+ CallProtoService(dbei.szModule, PS_AUTHDENY, (WPARAM)hDbEvent, (LPARAM)NULL); // without reason
+
+ break;
+ }
+
+ case EVENTTYPE_ADDED:
+ {
+ if (bDoWriteLog)
+ {
+ if (!CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)dbei.szModule, (LPARAM)SFMT_ADDED))
+ {
+ pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
+
+ WriteToLogFile(dbei.szModule, SFMT_ADDED, pszUserName, NULL, pslRecognition, bKeepHistory ? SFF_MARKREAD : SFF_DELETE);
+ }
+ }
+ break;
+ }
+ } // switch
+ }
+ }
+
+ CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvent);
+
+ if (bKeepHistory)
+ CallService(MS_DB_EVENT_MARKREAD, (WPARAM)hContact, (LPARAM)hDbEvent);
+ else
+ CallService(MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hDbEvent); }
+ }
+ }
+
+ }
+
+ mir_free(dbei.pBlob);
+ }
+ }
+
+ }
+
+ hDbEvent = hDbEventBuf;
+ }
+ }
+
+ return bReturn;
+}
diff --git a/contact.h b/contact.h
index 80a3e8e..f544376 100644
--- a/contact.h
+++ b/contact.h
@@ -1,41 +1,41 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_CONTACT_H__
-#define SF_CONTACT_H__ 1
-
-
-// -- Prototypes
-WORD IncreasePreSpammerCount(SPAMCHECKDATA* pscd);
-WORD GetPreSpammerCount(SPAMCHECKDATA* pscd);
-BOOL RemovePreSpammerCount(SPAMCHECKDATA* pscd);
-
-int MarkAllContactEventsUnRead(HANDLE hContact);
-BOOL SendContactAutomatedMessage(HANDLE hContact, WCHAR* pszMessage, BOOL bAddToHistory);
-
-BOOL RemoveContactListGroup(WCHAR* pszGroupName);
-BOOL CreateContactListGroup(WCHAR* pszGroupName);
-
-BOOL RemoveContactFromIgnoreList(HANDLE hContact);
-BOOL AddContactToIgnoreList(HANDLE hContact, BOOL bKeepHistory, BOOL bDenyAuthRequests, BOOL bNoLog);
-
-
-#endif // SF_CONTACT_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_CONTACT_H__
+#define SF_CONTACT_H__ 1
+
+
+// -- Prototypes
+WORD IncreasePreSpammerCount(SPAMCHECKDATA* pscd);
+WORD GetPreSpammerCount(SPAMCHECKDATA* pscd);
+BOOL RemovePreSpammerCount(SPAMCHECKDATA* pscd);
+
+int MarkAllContactEventsUnRead(HANDLE hContact);
+BOOL SendContactAutomatedMessage(HANDLE hContact, WCHAR* pszMessage, BOOL bAddToHistory);
+
+BOOL RemoveContactListGroup(WCHAR* pszGroupName);
+BOOL CreateContactListGroup(WCHAR* pszGroupName);
+
+BOOL RemoveContactFromIgnoreList(HANDLE hContact);
+BOOL AddContactToIgnoreList(HANDLE hContact, BOOL bKeepHistory, BOOL bDenyAuthRequests, BOOL bNoLog);
+
+
+#endif // SF_CONTACT_H__
diff --git a/dlg.c b/dlg.c
index 83dd86d..8490802 100644
--- a/dlg.c
+++ b/dlg.c
@@ -1,385 +1,385 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -- Defines
-#define PROP_FILEEDIT_ASSO_BTN _T("FileEditBrowse_AssociatedButton")
-
-
-// -----------------------------------------
-
-
-/*
-BOOL ResizeWindow(HWND hWnd, int cx, int cy, BOOL bRepaint)
-{
- RECT rc;
-
- if (GetWindowRect(hWnd, &rc))
- return SetWindowPos(hWnd, NULL, 0, 0, (rc.right-rc.left)+cx, (rc.bottom-rc.top)+cy, SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE|(bRepaint?0:SWP_NOREDRAW));
- else
- return FALSE;
-}
-*/
-
-
-int GetCtrlTextExtent(HWND hwndCtrl, const WCHAR* pszText, BOOL bAddAveChar)
-{
- HDC hDC;
- HFONT hFont;
- SIZE size;
- HGDIOBJ hOldObj;
-
- if (!hwndCtrl || !pszText) return 0;
-
- hFont = (HFONT)SendMessage(hwndCtrl, WM_GETFONT, 0, 0);
-
- hDC = GetDC(hwndCtrl);
- if (!hDC) return 0;
-
- // If non-system font used select it first
- if (hFont)
- hOldObj = SelectObject(hDC, hFont);
- else
- hOldObj = NULL;
-
- if (!GetTextExtentPoint32(hDC, pszText, lstrlen(pszText), &size))
- size.cx = 0;
-
- if (hFont)
- SelectObject(hDC, hOldObj);
-
- ReleaseDC(hwndCtrl, hDC);
-
- if (bAddAveChar)
- {
- TEXTMETRIC tm;
- if (GetTextMetrics(hDC, &tm))
- size.cx += tm.tmAveCharWidth;
- }
-
- return size.cx;
-}
-
-
-
-BOOL ShowDlgItem(HWND hwndDlg, int iIDCtrl, BOOL bShow)
-{
- HWND hwndCtrl = GetDlgItem(hwndDlg, iIDCtrl);
- if (!hwndCtrl) return FALSE;
-
- // Avoid flickering
- if (bShow && IsWindowVisible(hwndCtrl))
- return TRUE;
-
- return ShowWindow(hwndCtrl, (bShow ? SW_SHOW : SW_HIDE));
-}
-
-
-
-BOOL EnableDlgItem(HWND hwndDlg, int iIDCtrl, BOOL bEnable)
-{
- HWND hwndCtrl = GetDlgItem(hwndDlg, iIDCtrl);
- if (!hwndCtrl) return FALSE;
-
- // Avoid flickering
- if (IsWindowEnabled(hwndCtrl) == bEnable)
- return (bEnable == FALSE);
-
- return EnableWindow(hwndCtrl, bEnable);
-}
-
-/*
-BOOL SetDlgItemPrintf(HWND hwndDlg, int iIDCtrl, unsigned int cbArgMaxLen, ...)
-{
- HWND hwndCtrl;
- BOOL bReturn;
- int iMaxLen;
- TCHAR* pszFmt;
- TCHAR* pszOut;
- va_list arglist;
-
- hwndCtrl = GetDlgItem(hwndDlg, iIDCtrl);
- if (!hwndCtrl) return FALSE;
-
- // Prepare fmt buffer
- iMaxLen = GetWindowTextLength(hwndCtrl);
- pszFmt = (TCHAR*)mir_alloc((iMaxLen+1)*sizeof(TCHAR));
- if (!pszFmt) return FALSE;
-
- // Get fmt text
- if (GetWindowText(hwndCtrl, pszFmt, iMaxLen+1) == 0)
- {
- mir_free(pszFmt);
- return FALSE;
- }
-
- // Prepare out buffer
- if (cbArgMaxLen > 0) iMaxLen = iMaxLen + cbArgMaxLen;
- pszOut = (TCHAR*)mir_alloc((iMaxLen+1)*sizeof(TCHAR));
-
- if (!pszOut)
- {
- mir_free(pszFmt);
- return FALSE;
- }
-
- // Generate out text
- va_start(arglist, cbArgMaxLen);
- mir_vsnprintf(pszOut, iMaxLen+1, pszFmt, arglist);
- va_end(arglist);
- mir_free(pszFmt);
-
- bReturn = SetWindowText(hwndCtrl, pszOut);
-
- mir_free(pszOut);
- return bReturn;
-}
-*/
-
-BOOL SetSpinCtrlRange(HWND hwndSpin, int iRangeMin, int iRangeMax, int iDefault, BOOL bForceDefault)
-{
- HWND hwndDlg, hwndEdit;
- int iIDEdit;
- int iOldValue, iNewValue;
- int iOldRangeMin, iOldRangeMax;
- BOOL bIsEnabled;
-
- hwndDlg = GetParent(hwndSpin);
- if (!hwndDlg) return FALSE;
-
- hwndEdit = (HWND)SendMessage(hwndSpin, UDM_GETBUDDY, 0 , 0);
- if (!hwndEdit || (GetParent(hwndEdit) != hwndDlg))
- return FALSE;
-
- iIDEdit = GetDlgCtrlID(hwndEdit);
-
- iOldValue = (int)GetDlgItemInt(hwndDlg, iIDEdit, NULL, TRUE);
-
- //if (iRangeMin < UD_MINVAL) iRangeMin = UD_MINVAL;
- //if (iRangeMax > UD_MAXVAL) iRangeMax = UD_MAXVAL;
-
- // Get data
- if (iRangeMax < iRangeMin) iRangeMax = iRangeMin;
- bIsEnabled = (iRangeMin != iRangeMax);
- SendMessage(hwndSpin, UDM_GETRANGE32, (WPARAM)&iOldRangeMin, (LPARAM)&iOldRangeMax);
-
- // Set default if necessary
- if (bForceDefault
- || ((iOldValue==iOldRangeMax) && (iDefault > iOldRangeMax))
- || ((iOldValue==iOldRangeMin) && (iDefault < iOldRangeMin))
- || (bIsEnabled && !IsWindowEnabled(hwndSpin) && !IsWindowEnabled(hwndEdit)) )
- iNewValue = iDefault;
- else
- iNewValue = iOldValue;
-
- if (iNewValue < iRangeMin) iNewValue = iRangeMin;
- if (iNewValue > iRangeMax) iNewValue = iRangeMax;
-
- // Set edit
- if (iNewValue != iOldValue)
- SetDlgItemInt(hwndDlg, iIDEdit, iNewValue, TRUE);
-
- // Set spin
- if ((iRangeMin != iOldRangeMin) || iRangeMax != iOldRangeMax)
- {
- WCHAR szRangeMin[MAX_INT_LENGTH];
- WCHAR szRangeMax[MAX_INT_LENGTH];
-
- mir_sntprintf(szRangeMin, ARRAYSIZE(szRangeMin), _T("%i"), iRangeMin);
- mir_sntprintf(szRangeMax, ARRAYSIZE(szRangeMax), _T("%i"), iRangeMax);
-
- SendMessage(hwndSpin, UDM_SETRANGE32, (WPARAM)iRangeMin, (LPARAM)iRangeMax);
- PostMessage(hwndEdit, EM_SETLIMITTEXT, (WPARAM)max(lstrlen(szRangeMin), lstrlen(szRangeMax)), 0);
- }
-
- if (iNewValue != iOldValue)
- SendMessage(hwndSpin, UDM_SETPOS32, 0, (LPARAM)iNewValue);
-
- // Avoiding flicker
- if (IsWindowEnabled(hwndSpin) != bIsEnabled) EnableWindow(hwndSpin, bIsEnabled);
- if (IsWindowEnabled(hwndEdit) != bIsEnabled) EnableWindow(hwndEdit, bIsEnabled);
-
- return bIsEnabled;
-}
-
-
-LRESULT CALLBACK PathEditSubclassProc(HWND hwndEdit, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- LRESULT lResult = CallWindowProc((WNDPROC)GetWindowLongPtr(hwndEdit, GWLP_USERDATA), hwndEdit, uMsg, wParam, lParam);
-
- switch(uMsg)
- {
- case WM_NCCALCSIZE:
- {
- if ((BOOL)wParam == TRUE)
- {
- // Resizing the client rect of the edit control
- // and moving the button in the space.
-
- HWND hwndButton = (HWND)GetProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN);
- NCCALCSIZE_PARAMS* pnccsp = (NCCALCSIZE_PARAMS*)lParam;
- RECT rc;
-
- if (hwndButton)
- if (GetWindowRect(hwndButton, &rc))
- {
- rc.right -= rc.left;
- rc.bottom = pnccsp->rgrc[0].bottom-pnccsp->rgrc[0].top;
- pnccsp->rgrc[0].right -= (rc.right+1);
- rc.left = pnccsp->rgrc[0].right+1;
- rc.top = pnccsp->rgrc[0].top;
-
- MoveWindow(hwndButton, rc.left, rc.top, rc.right, rc.bottom, TRUE);
- }
- }
-
- break;
- }
-
- case WM_NCHITTEST:
- {
- // When the mouse is hovering the button
- // HTTRANSPARENT needs to be returned
- // else no mouse messages will be sent to the button
-
- if (lResult == HTNOWHERE)
- {
- HWND hwndButton = (HWND)GetProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN);
- RECT rc;
- POINT pt;
-
- if (hwndButton)
- if (GetWindowRect(hwndButton, &rc))
- {
- POINTSTOPOINT(pt, lParam);
-
- if (PtInRect(&rc, pt))
- lResult = HTTRANSPARENT;
- }
- }
-
- break;
- }
-
- case WM_DROPFILES:
- {
- HDROP hDrop = (HDROP)wParam;
- WCHAR szFileName[MAX_PATH];
-
- DragQueryFile(hDrop, 0, szFileName, ARRAYSIZE(szFileName));
-
- // Insert the text and Mark it
- SetWindowText(hwndEdit, szFileName);
- DragFinish(hDrop);
-
- // Set focus to file editbox (SetFocus is not allowed in Dialogs)
- if (GetParent(hwndEdit))
- PostMessage(GetParent(hwndEdit), WM_NEXTDLGCTL, (WPARAM)hwndEdit, (LPARAM)TRUE);
- break;
- }
-
- case WM_DESTROY: // before the destroy
- {
- // Remove assoicated browse button
- RemoveProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN);
- break;
- }
-
- case WM_NCDESTROY: // after the destroy
- {
- // Uninit auto complete
- if (GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "SHAutoComplete"))
- CoUninitialize();
- break;
- }
-
- case WM_CHAR:
- {
- // Only allow valid path chars to be entered
- if (PathGetCharType((WCHAR)wParam)&GCT_INVALID)
- return FALSE;
- else
- break;
- }
- }
-
- return lResult;
-}
-
-
-BOOL MakePathEditCtrl(HWND hwndEdit, HWND hwndButton)
-{
- if (!hwndEdit || !hwndButton) return FALSE;
-
- // Don't make a new mask if there is already one available
- if((WNDPROC)GetWindowLongPtr(hwndEdit, GWLP_WNDPROC) == PathEditSubclassProc)
- return FALSE;
-
- // Remember associated button control
- if (!SetProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN, (HANDLE)hwndButton))
- {
- ShowWindow(hwndButton, SW_HIDE);
- return FALSE;
- }
-
- // Ansi/OEM codepage converting
- #if !defined(UNICODE)
- // Allow later converting to OEM encoding for some functions (see docs)
- SetWindowLongPtr(hwndEdit, GWL_STYLE, ES_OEMCONVERT|GetWindowLongPtr(hwndEdit, GWL_STYLE));
- #endif
-
- // Limit text
- PostMessage(hwndEdit, EM_SETLIMITTEXT, (WPARAM)MAX_PATH, 0);
-
- // Subclass
- SetWindowLongPtr(hwndEdit, GWLP_USERDATA, SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR)PathEditSubclassProc));
-
- // Init auto complete
- {
- HRESULT (STDAPICALLTYPE *MySHAutoComplete)(HWND, DWORD);
- *(FARPROC*)&MySHAutoComplete = GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "SHAutoComplete");
-
- if (MySHAutoComplete) {
- CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
- MySHAutoComplete(hwndEdit, SHACF_FILESYSTEM|SHACF_FILESYS_ONLY|SHACF_USETAB);
- } else OutputDebugString(_T("Spam Filter: SHAutoComplete in SHLWAPI.DLL not available.\r\n"));
- }
-
- // Accept drag & drop
- DragAcceptFiles(hwndEdit, TRUE);
-
- {
- RECT rcEdit;
- RECT rcButton;
-
- if (GetClientRect(hwndEdit, &rcEdit))
- if (GetClientRect(hwndButton, &rcButton))
- {
- // Send WM_NCCALCSIZE message to edit control and resize it to fit button
- SetWindowPos(hwndEdit, NULL, 0, 0, (rcEdit.right-rcEdit.left), (rcButton.bottom-rcButton.top)+2*GetSystemMetrics(SM_CYBORDER), SWP_NOMOVE|SWP_NOZORDER|SWP_DRAWFRAME);
- }
- }
-
- return TRUE;
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -- Defines
+#define PROP_FILEEDIT_ASSO_BTN _T("FileEditBrowse_AssociatedButton")
+
+
+// -----------------------------------------
+
+
+/*
+BOOL ResizeWindow(HWND hWnd, int cx, int cy, BOOL bRepaint)
+{
+ RECT rc;
+
+ if (GetWindowRect(hWnd, &rc))
+ return SetWindowPos(hWnd, NULL, 0, 0, (rc.right-rc.left)+cx, (rc.bottom-rc.top)+cy, SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE|(bRepaint?0:SWP_NOREDRAW));
+ else
+ return FALSE;
+}
+*/
+
+
+int GetCtrlTextExtent(HWND hwndCtrl, const WCHAR* pszText, BOOL bAddAveChar)
+{
+ HDC hDC;
+ HFONT hFont;
+ SIZE size;
+ HGDIOBJ hOldObj;
+
+ if (!hwndCtrl || !pszText) return 0;
+
+ hFont = (HFONT)SendMessage(hwndCtrl, WM_GETFONT, 0, 0);
+
+ hDC = GetDC(hwndCtrl);
+ if (!hDC) return 0;
+
+ // If non-system font used select it first
+ if (hFont)
+ hOldObj = SelectObject(hDC, hFont);
+ else
+ hOldObj = NULL;
+
+ if (!GetTextExtentPoint32(hDC, pszText, lstrlen(pszText), &size))
+ size.cx = 0;
+
+ if (hFont)
+ SelectObject(hDC, hOldObj);
+
+ ReleaseDC(hwndCtrl, hDC);
+
+ if (bAddAveChar)
+ {
+ TEXTMETRIC tm;
+ if (GetTextMetrics(hDC, &tm))
+ size.cx += tm.tmAveCharWidth;
+ }
+
+ return size.cx;
+}
+
+
+
+BOOL ShowDlgItem(HWND hwndDlg, int iIDCtrl, BOOL bShow)
+{
+ HWND hwndCtrl = GetDlgItem(hwndDlg, iIDCtrl);
+ if (!hwndCtrl) return FALSE;
+
+ // Avoid flickering
+ if (bShow && IsWindowVisible(hwndCtrl))
+ return TRUE;
+
+ return ShowWindow(hwndCtrl, (bShow ? SW_SHOW : SW_HIDE));
+}
+
+
+
+BOOL EnableDlgItem(HWND hwndDlg, int iIDCtrl, BOOL bEnable)
+{
+ HWND hwndCtrl = GetDlgItem(hwndDlg, iIDCtrl);
+ if (!hwndCtrl) return FALSE;
+
+ // Avoid flickering
+ if (IsWindowEnabled(hwndCtrl) == bEnable)
+ return (bEnable == FALSE);
+
+ return EnableWindow(hwndCtrl, bEnable);
+}
+
+/*
+BOOL SetDlgItemPrintf(HWND hwndDlg, int iIDCtrl, unsigned int cbArgMaxLen, ...)
+{
+ HWND hwndCtrl;
+ BOOL bReturn;
+ int iMaxLen;
+ TCHAR* pszFmt;
+ TCHAR* pszOut;
+ va_list arglist;
+
+ hwndCtrl = GetDlgItem(hwndDlg, iIDCtrl);
+ if (!hwndCtrl) return FALSE;
+
+ // Prepare fmt buffer
+ iMaxLen = GetWindowTextLength(hwndCtrl);
+ pszFmt = (TCHAR*)mir_alloc((iMaxLen+1)*sizeof(TCHAR));
+ if (!pszFmt) return FALSE;
+
+ // Get fmt text
+ if (GetWindowText(hwndCtrl, pszFmt, iMaxLen+1) == 0)
+ {
+ mir_free(pszFmt);
+ return FALSE;
+ }
+
+ // Prepare out buffer
+ if (cbArgMaxLen > 0) iMaxLen = iMaxLen + cbArgMaxLen;
+ pszOut = (TCHAR*)mir_alloc((iMaxLen+1)*sizeof(TCHAR));
+
+ if (!pszOut)
+ {
+ mir_free(pszFmt);
+ return FALSE;
+ }
+
+ // Generate out text
+ va_start(arglist, cbArgMaxLen);
+ mir_vsnprintf(pszOut, iMaxLen+1, pszFmt, arglist);
+ va_end(arglist);
+ mir_free(pszFmt);
+
+ bReturn = SetWindowText(hwndCtrl, pszOut);
+
+ mir_free(pszOut);
+ return bReturn;
+}
+*/
+
+BOOL SetSpinCtrlRange(HWND hwndSpin, int iRangeMin, int iRangeMax, int iDefault, BOOL bForceDefault)
+{
+ HWND hwndDlg, hwndEdit;
+ int iIDEdit;
+ int iOldValue, iNewValue;
+ int iOldRangeMin, iOldRangeMax;
+ BOOL bIsEnabled;
+
+ hwndDlg = GetParent(hwndSpin);
+ if (!hwndDlg) return FALSE;
+
+ hwndEdit = (HWND)SendMessage(hwndSpin, UDM_GETBUDDY, 0 , 0);
+ if (!hwndEdit || (GetParent(hwndEdit) != hwndDlg))
+ return FALSE;
+
+ iIDEdit = GetDlgCtrlID(hwndEdit);
+
+ iOldValue = (int)GetDlgItemInt(hwndDlg, iIDEdit, NULL, TRUE);
+
+ //if (iRangeMin < UD_MINVAL) iRangeMin = UD_MINVAL;
+ //if (iRangeMax > UD_MAXVAL) iRangeMax = UD_MAXVAL;
+
+ // Get data
+ if (iRangeMax < iRangeMin) iRangeMax = iRangeMin;
+ bIsEnabled = (iRangeMin != iRangeMax);
+ SendMessage(hwndSpin, UDM_GETRANGE32, (WPARAM)&iOldRangeMin, (LPARAM)&iOldRangeMax);
+
+ // Set default if necessary
+ if (bForceDefault
+ || ((iOldValue==iOldRangeMax) && (iDefault > iOldRangeMax))
+ || ((iOldValue==iOldRangeMin) && (iDefault < iOldRangeMin))
+ || (bIsEnabled && !IsWindowEnabled(hwndSpin) && !IsWindowEnabled(hwndEdit)) )
+ iNewValue = iDefault;
+ else
+ iNewValue = iOldValue;
+
+ if (iNewValue < iRangeMin) iNewValue = iRangeMin;
+ if (iNewValue > iRangeMax) iNewValue = iRangeMax;
+
+ // Set edit
+ if (iNewValue != iOldValue)
+ SetDlgItemInt(hwndDlg, iIDEdit, iNewValue, TRUE);
+
+ // Set spin
+ if ((iRangeMin != iOldRangeMin) || iRangeMax != iOldRangeMax)
+ {
+ WCHAR szRangeMin[MAX_INT_LENGTH];
+ WCHAR szRangeMax[MAX_INT_LENGTH];
+
+ mir_sntprintf(szRangeMin, ARRAYSIZE(szRangeMin), _T("%i"), iRangeMin);
+ mir_sntprintf(szRangeMax, ARRAYSIZE(szRangeMax), _T("%i"), iRangeMax);
+
+ SendMessage(hwndSpin, UDM_SETRANGE32, (WPARAM)iRangeMin, (LPARAM)iRangeMax);
+ PostMessage(hwndEdit, EM_SETLIMITTEXT, (WPARAM)max(lstrlen(szRangeMin), lstrlen(szRangeMax)), 0);
+ }
+
+ if (iNewValue != iOldValue)
+ SendMessage(hwndSpin, UDM_SETPOS32, 0, (LPARAM)iNewValue);
+
+ // Avoiding flicker
+ if (IsWindowEnabled(hwndSpin) != bIsEnabled) EnableWindow(hwndSpin, bIsEnabled);
+ if (IsWindowEnabled(hwndEdit) != bIsEnabled) EnableWindow(hwndEdit, bIsEnabled);
+
+ return bIsEnabled;
+}
+
+
+LRESULT CALLBACK PathEditSubclassProc(HWND hwndEdit, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT lResult = CallWindowProc((WNDPROC)GetWindowLongPtr(hwndEdit, GWLP_USERDATA), hwndEdit, uMsg, wParam, lParam);
+
+ switch(uMsg)
+ {
+ case WM_NCCALCSIZE:
+ {
+ if ((BOOL)wParam == TRUE)
+ {
+ // Resizing the client rect of the edit control
+ // and moving the button in the space.
+
+ HWND hwndButton = (HWND)GetProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN);
+ NCCALCSIZE_PARAMS* pnccsp = (NCCALCSIZE_PARAMS*)lParam;
+ RECT rc;
+
+ if (hwndButton)
+ if (GetWindowRect(hwndButton, &rc))
+ {
+ rc.right -= rc.left;
+ rc.bottom = pnccsp->rgrc[0].bottom-pnccsp->rgrc[0].top;
+ pnccsp->rgrc[0].right -= (rc.right+1);
+ rc.left = pnccsp->rgrc[0].right+1;
+ rc.top = pnccsp->rgrc[0].top;
+
+ MoveWindow(hwndButton, rc.left, rc.top, rc.right, rc.bottom, TRUE);
+ }
+ }
+
+ break;
+ }
+
+ case WM_NCHITTEST:
+ {
+ // When the mouse is hovering the button
+ // HTTRANSPARENT needs to be returned
+ // else no mouse messages will be sent to the button
+
+ if (lResult == HTNOWHERE)
+ {
+ HWND hwndButton = (HWND)GetProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN);
+ RECT rc;
+ POINT pt;
+
+ if (hwndButton)
+ if (GetWindowRect(hwndButton, &rc))
+ {
+ POINTSTOPOINT(pt, lParam);
+
+ if (PtInRect(&rc, pt))
+ lResult = HTTRANSPARENT;
+ }
+ }
+
+ break;
+ }
+
+ case WM_DROPFILES:
+ {
+ HDROP hDrop = (HDROP)wParam;
+ WCHAR szFileName[MAX_PATH];
+
+ DragQueryFile(hDrop, 0, szFileName, ARRAYSIZE(szFileName));
+
+ // Insert the text and Mark it
+ SetWindowText(hwndEdit, szFileName);
+ DragFinish(hDrop);
+
+ // Set focus to file editbox (SetFocus is not allowed in Dialogs)
+ if (GetParent(hwndEdit))
+ PostMessage(GetParent(hwndEdit), WM_NEXTDLGCTL, (WPARAM)hwndEdit, (LPARAM)TRUE);
+ break;
+ }
+
+ case WM_DESTROY: // before the destroy
+ {
+ // Remove assoicated browse button
+ RemoveProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN);
+ break;
+ }
+
+ case WM_NCDESTROY: // after the destroy
+ {
+ // Uninit auto complete
+ if (GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "SHAutoComplete"))
+ CoUninitialize();
+ break;
+ }
+
+ case WM_CHAR:
+ {
+ // Only allow valid path chars to be entered
+ if (PathGetCharType((WCHAR)wParam)&GCT_INVALID)
+ return FALSE;
+ else
+ break;
+ }
+ }
+
+ return lResult;
+}
+
+
+BOOL MakePathEditCtrl(HWND hwndEdit, HWND hwndButton)
+{
+ if (!hwndEdit || !hwndButton) return FALSE;
+
+ // Don't make a new mask if there is already one available
+ if((WNDPROC)GetWindowLongPtr(hwndEdit, GWLP_WNDPROC) == PathEditSubclassProc)
+ return FALSE;
+
+ // Remember associated button control
+ if (!SetProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN, (HANDLE)hwndButton))
+ {
+ ShowWindow(hwndButton, SW_HIDE);
+ return FALSE;
+ }
+
+ // Ansi/OEM codepage converting
+ #if !defined(UNICODE)
+ // Allow later converting to OEM encoding for some functions (see docs)
+ SetWindowLongPtr(hwndEdit, GWL_STYLE, ES_OEMCONVERT|GetWindowLongPtr(hwndEdit, GWL_STYLE));
+ #endif
+
+ // Limit text
+ PostMessage(hwndEdit, EM_SETLIMITTEXT, (WPARAM)MAX_PATH, 0);
+
+ // Subclass
+ SetWindowLongPtr(hwndEdit, GWLP_USERDATA, SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR)PathEditSubclassProc));
+
+ // Init auto complete
+ {
+ HRESULT (STDAPICALLTYPE *MySHAutoComplete)(HWND, DWORD);
+ *(FARPROC*)&MySHAutoComplete = GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "SHAutoComplete");
+
+ if (MySHAutoComplete) {
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ MySHAutoComplete(hwndEdit, SHACF_FILESYSTEM|SHACF_FILESYS_ONLY|SHACF_USETAB);
+ } else OutputDebugString(_T("Spam Filter: SHAutoComplete in SHLWAPI.DLL not available.\r\n"));
+ }
+
+ // Accept drag & drop
+ DragAcceptFiles(hwndEdit, TRUE);
+
+ {
+ RECT rcEdit;
+ RECT rcButton;
+
+ if (GetClientRect(hwndEdit, &rcEdit))
+ if (GetClientRect(hwndButton, &rcButton))
+ {
+ // Send WM_NCCALCSIZE message to edit control and resize it to fit button
+ SetWindowPos(hwndEdit, NULL, 0, 0, (rcEdit.right-rcEdit.left), (rcButton.bottom-rcButton.top)+2*GetSystemMetrics(SM_CYBORDER), SWP_NOMOVE|SWP_NOZORDER|SWP_DRAWFRAME);
+ }
+ }
+
+ return TRUE;
} \ No newline at end of file
diff --git a/dlg.h b/dlg.h
index 82a26fc..5be13f7 100644
--- a/dlg.h
+++ b/dlg.h
@@ -1,38 +1,38 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_DLG_H__
-#define SF_DLG_H__ 1
-
-
-// -- Prototypes
-BOOL ResizeWindow(HWND hWnd, int cx, int cy, BOOL bRepaint);
-
-BOOL ShowDlgItem(HWND hwndDlg, int iIDCtrl, BOOL bShow);
-BOOL EnableDlgItem(HWND hwndDlg, int iIDCtrl, BOOL bEnable);
-BOOL SetDlgItemPrintf(HWND hwndDlg, int iIDCtrl, unsigned int cbArgMaxLen, ...);
-BOOL SetSpinCtrlRange(HWND hwndSpin, int iRangeMin, int iRangeMax, int iDefault, BOOL bForceDefault);
-
-int GetCtrlTextExtent(HWND hwndCtrl, const WCHAR* pszText, BOOL bAddAveChar);
-BOOL MakePathEditCtrl(HWND hwndEdit, HWND hwndButton);
-
-
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_DLG_H__
+#define SF_DLG_H__ 1
+
+
+// -- Prototypes
+BOOL ResizeWindow(HWND hWnd, int cx, int cy, BOOL bRepaint);
+
+BOOL ShowDlgItem(HWND hwndDlg, int iIDCtrl, BOOL bShow);
+BOOL EnableDlgItem(HWND hwndDlg, int iIDCtrl, BOOL bEnable);
+BOOL SetDlgItemPrintf(HWND hwndDlg, int iIDCtrl, unsigned int cbArgMaxLen, ...);
+BOOL SetSpinCtrlRange(HWND hwndSpin, int iRangeMin, int iRangeMax, int iDefault, BOOL bForceDefault);
+
+int GetCtrlTextExtent(HWND hwndCtrl, const WCHAR* pszText, BOOL bAddAveChar);
+BOOL MakePathEditCtrl(HWND hwndEdit, HWND hwndButton);
+
+
#endif // SF_DLG_H__ \ No newline at end of file
diff --git a/extraimg.c b/extraimg.c
index 59cd79e..ba22a96 100644
--- a/extraimg.c
+++ b/extraimg.c
@@ -1,118 +1,118 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -- Variables: Events/Services
-HANDLE hHookExtraListRebuild = NULL;
-HANDLE hHookExtraImageApply = NULL;
-HANDLE hHookDbSettingChanged = NULL;
-
-// -- Variables
-HANDLE hSpammerImage;
-
-
-// -----------------------------------------
-
-
-void SetSpammerIcon(HANDLE hContact, BOOL bShow)
-{
- IconExtraColumn iec;
-
- ZeroMemory(&iec, sizeof(iec));
- iec.cbSize = sizeof(iec);
- iec.ColumnType = EXTRA_ICON_ADV2;
- iec.hImage = bShow?hSpammerImage:INVALID_HANDLE_VALUE;
-
- CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)&iec);
-}
-
-
-static int ExtraImageApply(WPARAM wParam, LPARAM lParam)
-{
- // Assign extra icon to contact
- if (DBGetContactSettingByte((HANDLE)wParam, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)FALSE))
- SetSpammerIcon((HANDLE)wParam, TRUE);
-
- return 0;
-}
-
-
-static int ExtraImageListRebuild(WPARAM wParam, LPARAM lParam)
-{
- HANDLE hContact;
-
- // Add spam icon to image list of clist extra images
- hSpammerImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)SkinGetIcon(DB_ICON_ISSPAMMER_SETTING, IDI_DEFAULT, FALSE), 0);
-
- // Update spammer icons for all contacts in list
- for (hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
- ExtraImageApply(wParam, lParam);
-
- return 0;
-}
-
-
-static int DbSettingChanged(WPARAM wParam, LPARAM lParam)
-{
- DBCONTACTWRITESETTING* pdcws = (DBCONTACTWRITESETTING*)lParam;
-
- // Watch DB_SETTING_ISSPAMMER to be in sync with spammer icon
- if (StrCmpA(pdcws->szModule, DB_MODULE_NAME) == 0)
- if (StrCmpA(pdcws->szSetting, DB_SETTING_ISSPAMMER) == 0)
- {
- BOOL bIsSpammer = (pdcws->value.type==DBVT_DELETED) ? FALSE : (pdcws->value.bVal?TRUE:FALSE);
- SetSpammerIcon((HANDLE)wParam, bIsSpammer);
- NotifySpammerStateChanged((HANDLE)wParam, bIsSpammer);
-
- if (IsWindow(hwndSpammersInfo))
- PostMessage(hwndSpammersInfo, SFM_REFRESH_SPAMMERS, 0, 0);
- }
-
- return 0;
-}
-
-
-// ------------------------------------
-
-
-void InitExtraImg(void)
-{
- // Enable CList extra image support (in clist clones)
- if (ServiceExists(MS_CLIST_EXTRA_SET_ICON) && ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
- {
- SkinAddNewIcon(DB_ICON_ISSPAMMER_SETTING, TranslateT("Spam Filter"), TranslateT("Spammer Indicator"), IDI_DEFAULT, FALSE);
-
- hHookExtraListRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, ExtraImageListRebuild);
- hHookExtraImageApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, ExtraImageApply);
- hHookDbSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, DbSettingChanged);
- }
-}
-
-
-void UninitExtraImg(void)
-{
- if (hHookExtraListRebuild) UnhookEvent(hHookExtraListRebuild);
- if (hHookExtraImageApply) UnhookEvent(hHookExtraImageApply);
- if (hHookDbSettingChanged) UnhookEvent(hHookDbSettingChanged);
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -- Variables: Events/Services
+HANDLE hHookExtraListRebuild = NULL;
+HANDLE hHookExtraImageApply = NULL;
+HANDLE hHookDbSettingChanged = NULL;
+
+// -- Variables
+HANDLE hSpammerImage;
+
+
+// -----------------------------------------
+
+
+void SetSpammerIcon(HANDLE hContact, BOOL bShow)
+{
+ IconExtraColumn iec;
+
+ ZeroMemory(&iec, sizeof(iec));
+ iec.cbSize = sizeof(iec);
+ iec.ColumnType = EXTRA_ICON_ADV2;
+ iec.hImage = bShow?hSpammerImage:INVALID_HANDLE_VALUE;
+
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)&iec);
+}
+
+
+static int ExtraImageApply(WPARAM wParam, LPARAM lParam)
+{
+ // Assign extra icon to contact
+ if (DBGetContactSettingByte((HANDLE)wParam, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)FALSE))
+ SetSpammerIcon((HANDLE)wParam, TRUE);
+
+ return 0;
+}
+
+
+static int ExtraImageListRebuild(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact;
+
+ // Add spam icon to image list of clist extra images
+ hSpammerImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)SkinGetIcon(DB_ICON_ISSPAMMER_SETTING, IDI_DEFAULT, FALSE), 0);
+
+ // Update spammer icons for all contacts in list
+ for (hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ ExtraImageApply(wParam, lParam);
+
+ return 0;
+}
+
+
+static int DbSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING* pdcws = (DBCONTACTWRITESETTING*)lParam;
+
+ // Watch DB_SETTING_ISSPAMMER to be in sync with spammer icon
+ if (StrCmpA(pdcws->szModule, DB_MODULE_NAME) == 0)
+ if (StrCmpA(pdcws->szSetting, DB_SETTING_ISSPAMMER) == 0)
+ {
+ BOOL bIsSpammer = (pdcws->value.type==DBVT_DELETED) ? FALSE : (pdcws->value.bVal?TRUE:FALSE);
+ SetSpammerIcon((HANDLE)wParam, bIsSpammer);
+ NotifySpammerStateChanged((HANDLE)wParam, bIsSpammer);
+
+ if (IsWindow(hwndSpammersInfo))
+ PostMessage(hwndSpammersInfo, SFM_REFRESH_SPAMMERS, 0, 0);
+ }
+
+ return 0;
+}
+
+
+// ------------------------------------
+
+
+void InitExtraImg(void)
+{
+ // Enable CList extra image support (in clist clones)
+ if (ServiceExists(MS_CLIST_EXTRA_SET_ICON) && ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+ SkinAddNewIcon(DB_ICON_ISSPAMMER_SETTING, TranslateT("Spam Filter"), TranslateT("Spammer Indicator"), IDI_DEFAULT, FALSE);
+
+ hHookExtraListRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, ExtraImageListRebuild);
+ hHookExtraImageApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, ExtraImageApply);
+ hHookDbSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, DbSettingChanged);
+ }
+}
+
+
+void UninitExtraImg(void)
+{
+ if (hHookExtraListRebuild) UnhookEvent(hHookExtraListRebuild);
+ if (hHookExtraImageApply) UnhookEvent(hHookExtraImageApply);
+ if (hHookDbSettingChanged) UnhookEvent(hHookDbSettingChanged);
} \ No newline at end of file
diff --git a/extraimg.h b/extraimg.h
index cd66c94..b7ee048 100644
--- a/extraimg.h
+++ b/extraimg.h
@@ -1,30 +1,30 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_EXTRAIMG_H__
-#define SF_EXTRAIMG_H__ 1
-
-// -- Prototypes
-void InitExtraImg(void);
-void UninitExtraImg(void);
-
-
-#endif // SF_EXTRAIMG_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_EXTRAIMG_H__
+#define SF_EXTRAIMG_H__ 1
+
+// -- Prototypes
+void InitExtraImg(void);
+void UninitExtraImg(void);
+
+
+#endif // SF_EXTRAIMG_H__
diff --git a/folders.c b/folders.c
index 182a2d1..5be282d 100644
--- a/folders.c
+++ b/folders.c
@@ -1,101 +1,101 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -- Variables
-HANDLE hDefinitionsFolder = NULL;
-HANDLE hCustomFolder = NULL;
-
-// -----------------------------------------
-
-
-BOOL GetDefinitionsPath(WCHAR* pszReturn, BOOL bCustomFile, WCHAR* pszAppend)
-{
- // pszReturn muss MAX_PATH groß sein
- BOOL bReturn = FALSE;
-
- if ((bCustomFile && hCustomFolder) || (!bCustomFile && hDefinitionsFolder))
- {
- FOLDERSGETDATA fgd;
-
- if (!pszReturn) return FALSE;
- ZeroMemory(&fgd, sizeof(fgd));
- fgd.cbSize = sizeof(fgd);
- fgd.nMaxPathSize = MAX_PATH;
- fgd.szPathT = pszReturn;
-
- if (CallService(MS_FOLDERS_GET_PATH, (WPARAM)(bCustomFile?hCustomFolder:hDefinitionsFolder), (LPARAM)&fgd) == 0)
- {
- if (pszAppend) PathAppend(pszReturn, pszAppend);
- bReturn = TRUE;
- }
- }
-
- // Custom Folder Plugin not installed (using standard folder)
- if (!bReturn)
- bReturn = PConstructLocalPath(pszReturn, bCustomFile?CSIDL_EXT_MIRANDAPROFILE:CSIDL_EXT_EXECUTABLE, DATA_SUBDIRECTORY, pszAppend, NULL);
-
- return bReturn;
-}
-
-
-BOOL IsCustomFoldersAvailable(void)
-{
- return (hCustomFolder || hDefinitionsFolder);
-}
-
-
-// ------------------------------------
-
-
-void InitFolders(void)
-{
- // Enable Custom Folder Plugin support (needs new version!)
- if (ServiceExists(MS_FOLDERS_REGISTER_PATH) && ServiceExists(MS_FOLDERS_GET_PATH))
- {
- FOLDERSDATA fd;
-
- ZeroMemory(&fd, sizeof(fd));
- fd.cbSize = sizeof(fd);
- #if defined(UNICODE)
- fd.flags = FF_UNICODE;
- #endif
- mir_snprintf(fd.szSection, ARRAYSIZE(fd.szSection), "%s", Translate("Spam Filter"));
-
- // Definitions Folder
- mir_snprintf(fd.szName, ARRAYSIZE(fd.szName), "%s", Translate("Spam Definitions"));
- fd.szFormatT = _T("%miranda_path%\\")DATA_SUBDIRECTORY; // readonly allocated
- hDefinitionsFolder = (HANDLE)CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM)&fd);
-
- // Custom Definitions Folder
- mir_snprintf(fd.szName, ARRAYSIZE(fd.szName), "%s", Translate("Customized Words"));
- fd.szFormatT = _T("%profile_path%\\")DATA_SUBDIRECTORY; // readonly allocated
- hCustomFolder = (HANDLE)CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM)&fd);
- }
-}
-
-
-void UninitFolders(void)
-{
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -- Variables
+HANDLE hDefinitionsFolder = NULL;
+HANDLE hCustomFolder = NULL;
+
+// -----------------------------------------
+
+
+BOOL GetDefinitionsPath(WCHAR* pszReturn, BOOL bCustomFile, WCHAR* pszAppend)
+{
+ // pszReturn muss MAX_PATH groß sein
+ BOOL bReturn = FALSE;
+
+ if ((bCustomFile && hCustomFolder) || (!bCustomFile && hDefinitionsFolder))
+ {
+ FOLDERSGETDATA fgd;
+
+ if (!pszReturn) return FALSE;
+ ZeroMemory(&fgd, sizeof(fgd));
+ fgd.cbSize = sizeof(fgd);
+ fgd.nMaxPathSize = MAX_PATH;
+ fgd.szPathT = pszReturn;
+
+ if (CallService(MS_FOLDERS_GET_PATH, (WPARAM)(bCustomFile?hCustomFolder:hDefinitionsFolder), (LPARAM)&fgd) == 0)
+ {
+ if (pszAppend) PathAppend(pszReturn, pszAppend);
+ bReturn = TRUE;
+ }
+ }
+
+ // Custom Folder Plugin not installed (using standard folder)
+ if (!bReturn)
+ bReturn = PConstructLocalPath(pszReturn, bCustomFile?CSIDL_EXT_MIRANDAPROFILE:CSIDL_EXT_EXECUTABLE, DATA_SUBDIRECTORY, pszAppend, NULL);
+
+ return bReturn;
+}
+
+
+BOOL IsCustomFoldersAvailable(void)
+{
+ return (hCustomFolder || hDefinitionsFolder);
+}
+
+
+// ------------------------------------
+
+
+void InitFolders(void)
+{
+ // Enable Custom Folder Plugin support (needs new version!)
+ if (ServiceExists(MS_FOLDERS_REGISTER_PATH) && ServiceExists(MS_FOLDERS_GET_PATH))
+ {
+ FOLDERSDATA fd;
+
+ ZeroMemory(&fd, sizeof(fd));
+ fd.cbSize = sizeof(fd);
+ #if defined(UNICODE)
+ fd.flags = FF_UNICODE;
+ #endif
+ mir_snprintf(fd.szSection, ARRAYSIZE(fd.szSection), "%s", Translate("Spam Filter"));
+
+ // Definitions Folder
+ mir_snprintf(fd.szName, ARRAYSIZE(fd.szName), "%s", Translate("Spam Definitions"));
+ fd.szFormatT = _T("%miranda_path%\\")DATA_SUBDIRECTORY; // readonly allocated
+ hDefinitionsFolder = (HANDLE)CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM)&fd);
+
+ // Custom Definitions Folder
+ mir_snprintf(fd.szName, ARRAYSIZE(fd.szName), "%s", Translate("Customized Words"));
+ fd.szFormatT = _T("%profile_path%\\")DATA_SUBDIRECTORY; // readonly allocated
+ hCustomFolder = (HANDLE)CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM)&fd);
+ }
+}
+
+
+void UninitFolders(void)
+{
} \ No newline at end of file
diff --git a/folders.h b/folders.h
index d874911..eba5e1f 100644
--- a/folders.h
+++ b/folders.h
@@ -1,33 +1,33 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_FOLDERS_H__
-#define SF_FOLDERS_H__ 1
-
-// -- Prototypes
-BOOL GetDefinitionsPath(WCHAR* pszReturn, BOOL bCustomPath, WCHAR* pszAppend);
-BOOL IsCustomFoldersAvailable(void);
-
-void InitFolders(void);
-void UninitFolders(void);
-
-
-#endif // SF_FOLDERS_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_FOLDERS_H__
+#define SF_FOLDERS_H__ 1
+
+// -- Prototypes
+BOOL GetDefinitionsPath(WCHAR* pszReturn, BOOL bCustomPath, WCHAR* pszAppend);
+BOOL IsCustomFoldersAvailable(void);
+
+void InitFolders(void);
+void UninitFolders(void);
+
+
+#endif // SF_FOLDERS_H__
diff --git a/forkthread.c b/forkthread.c
index 2613f62..d638817 100644
--- a/forkthread.c
+++ b/forkthread.c
@@ -1,112 +1,112 @@
-/*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2006 Miranda ICQ/IM project,
-all portions of this code file are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "common.h"
-
-struct FORK_ARG {
- HANDLE hEvent;
- void (__cdecl *threadcode)(void*);
- unsigned (__stdcall *threadcodeex)(void*);
- void *arg;
-};
-
-void __cdecl forkthread_r(void * arg)
-{
- struct FORK_ARG * fa = (struct FORK_ARG *) arg;
- void (*callercode)(void*)=fa->threadcode;
- void * cookie=fa->arg;
- CallService(MS_SYSTEM_THREAD_PUSH,0,0);
- if (fa->hEvent) SetEvent(fa->hEvent);
- __try {
- callercode(cookie);
- } __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 (fa.hEvent) {
- if ((unsigned long)-1L != rc) {
- WaitForSingleObject(fa.hEvent,INFINITE);
- } //if
- CloseHandle(fa.hEvent);
- } // if
- return rc;
-}
-
-
-/*
-unsigned __stdcall forkthreadex_r(void * arg)
-{
- struct FORK_ARG *fa=(struct FORK_ARG *)arg;
- unsigned (__stdcall * threadcode) (void *)=fa->threadcodeex;
- void *cookie=fa->arg;
- unsigned long rc;
-
- CallService(MS_SYSTEM_THREAD_PUSH,0,0);
- if (fa->hEvent) SetEvent(fa->hEvent);
- __try {
- rc=threadcode(cookie);
- } __finally {
- CallService(MS_SYSTEM_THREAD_POP,0,0);
- }
- return rc;
-}
-
-unsigned long forkthreadex(
- void *sec,
- unsigned stacksize,
- unsigned (__stdcall *threadcode)(void*),
- void *arg,
- unsigned cf,
- unsigned *thraddr
-)
-{
- unsigned long rc;
- struct FORK_ARG fa;
- fa.threadcodeex=threadcode;
- fa.arg=arg;
- fa.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
- rc=_beginthreadex(sec,stacksize,forkthreadex_r,(void *)&fa,0,thraddr);
- if (fa.hEvent) {
- if (rc) {
- WaitForSingleObject(fa.hEvent,INFINITE);
- } // if
- CloseHandle(fa.hEvent);
- }
- return rc;
-}
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2006 Miranda ICQ/IM project,
+all portions of this code file are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+struct FORK_ARG {
+ HANDLE hEvent;
+ void (__cdecl *threadcode)(void*);
+ unsigned (__stdcall *threadcodeex)(void*);
+ void *arg;
+};
+
+void __cdecl forkthread_r(void * arg)
+{
+ struct FORK_ARG * fa = (struct FORK_ARG *) arg;
+ void (*callercode)(void*)=fa->threadcode;
+ void * cookie=fa->arg;
+ CallService(MS_SYSTEM_THREAD_PUSH,0,0);
+ if (fa->hEvent) SetEvent(fa->hEvent);
+ __try {
+ callercode(cookie);
+ } __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 (fa.hEvent) {
+ if ((unsigned long)-1L != rc) {
+ WaitForSingleObject(fa.hEvent,INFINITE);
+ } //if
+ CloseHandle(fa.hEvent);
+ } // if
+ return rc;
+}
+
+
+/*
+unsigned __stdcall forkthreadex_r(void * arg)
+{
+ struct FORK_ARG *fa=(struct FORK_ARG *)arg;
+ unsigned (__stdcall * threadcode) (void *)=fa->threadcodeex;
+ void *cookie=fa->arg;
+ unsigned long rc;
+
+ CallService(MS_SYSTEM_THREAD_PUSH,0,0);
+ if (fa->hEvent) SetEvent(fa->hEvent);
+ __try {
+ rc=threadcode(cookie);
+ } __finally {
+ CallService(MS_SYSTEM_THREAD_POP,0,0);
+ }
+ return rc;
+}
+
+unsigned long forkthreadex(
+ void *sec,
+ unsigned stacksize,
+ unsigned (__stdcall *threadcode)(void*),
+ void *arg,
+ unsigned cf,
+ unsigned *thraddr
+)
+{
+ unsigned long rc;
+ struct FORK_ARG fa;
+ fa.threadcodeex=threadcode;
+ fa.arg=arg;
+ fa.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
+ rc=_beginthreadex(sec,stacksize,forkthreadex_r,(void *)&fa,0,thraddr);
+ if (fa.hEvent) {
+ if (rc) {
+ WaitForSingleObject(fa.hEvent,INFINITE);
+ } // if
+ CloseHandle(fa.hEvent);
+ }
+ return rc;
+}
*/ \ No newline at end of file
diff --git a/forkthread.h b/forkthread.h
index cbf32ad..e1f8a4e 100644
--- a/forkthread.h
+++ b/forkthread.h
@@ -1,64 +1,64 @@
-/*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2006 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-/*
-
-Purpose:
-
- A safe version of _beginthread()
-
-Description:
-
- A new thread is created and the source thread is paused until
- internal code to call MS_SYSTEM_THREAD_PUSH is made in the context
- if the new thread.
-
- The source thread is then released and then the user supplied
- code is called, when that function returns -- MS_SYSTEM_THREAD_POP
- is called and then the thread returns.
-
- This insures that Miranda will not exit whilst new threads
- are trying to be born; and the unwind wait stack will ensure
- that Miranda will wait for all created threads to return as well.
-
-Cavets:
-
- The function must be reimplemented across MT plugins, since thread
- creation depends on CRT which can not be shared.
-
-*/
-unsigned long forkthread (
- void (__cdecl *threadcode)(void*),
- unsigned long stacksize,
- void *arg
-);
-
-unsigned long forkthreadex(
- void *sec,
- unsigned stacksize,
- unsigned (__stdcall *threadcode)(void*),
- void *arg,
- unsigned cf,
- unsigned *thraddr
-);
-
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2006 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+
+Purpose:
+
+ A safe version of _beginthread()
+
+Description:
+
+ A new thread is created and the source thread is paused until
+ internal code to call MS_SYSTEM_THREAD_PUSH is made in the context
+ if the new thread.
+
+ The source thread is then released and then the user supplied
+ code is called, when that function returns -- MS_SYSTEM_THREAD_POP
+ is called and then the thread returns.
+
+ This insures that Miranda will not exit whilst new threads
+ are trying to be born; and the unwind wait stack will ensure
+ that Miranda will wait for all created threads to return as well.
+
+Cavets:
+
+ The function must be reimplemented across MT plugins, since thread
+ creation depends on CRT which can not be shared.
+
+*/
+unsigned long forkthread (
+ void (__cdecl *threadcode)(void*),
+ unsigned long stacksize,
+ void *arg
+);
+
+unsigned long forkthreadex(
+ void *sec,
+ unsigned stacksize,
+ unsigned (__stdcall *threadcode)(void*),
+ void *arg,
+ unsigned cf,
+ unsigned *thraddr
+);
+
diff --git a/logfile.c b/logfile.c
index 7712119..5482875 100644
--- a/logfile.c
+++ b/logfile.c
@@ -1,478 +1,478 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-
-// -----------------------------------------
-
-
-BOOL WriteToLogFile(const char* pszMsgTypeSection, const char* pszMsgTypeName, const WCHAR* pszUserName, const WCHAR* pszMsgContent, STRINGLIST* pslRecognition, DWORD dwResult)
-{
- BOOL bReturn;
-
- HANDLE hFile;
- DWORD dwWritten; // For Windows 95/98/ME compatibility for WriteFile (parameter needed)
-
- STRINGLIST* pslVariablesFromTo;
- WCHAR szLogFile[MAX_PATH];
-
- int iBuf;
- WCHAR* pszBuf;
-
- // Get file to log to
- {
- DBVARIANT dbv;
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_LOGFILE, &dbv) == 0)
- {
- mir_sntprintf(szLogFile, ARRAYSIZE(szLogFile), _T("%s"), dbv.pszVal);
- DBFreeVariant(&dbv);
- PMakePathUsable(szLogFile);
- } else {
- szLogFile[0] = _T('\0');
- }
- }
-
- // Make sure the directory exists: SILENT!
- PPreparePathForWrite(NULL, szLogFile, FALSE, TRUE);
-
- // Open file
- hFile = CreateFile(szLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- bReturn = (hFile != INVALID_HANDLE_VALUE);
- if (!bReturn)
- {
- WCHAR* pszLastError = GetLastErrorDescription(GetLastError());
-
- ShowInfoMessage(NIIF_ERROR, TranslateT("Spam Filter Error"), TranslateT("The log file \"%s\"\r\ncan not be written.\r\n\r\nProblem:\r\n%s\r\nPlease check the settings."), lstrlen(szLogFile)+lstrlen(pszLastError), (lstrlen(PathFindFileName(szLogFile))>0)?PathFindFileName(szLogFile):szLogFile, pszLastError?pszLastError:_T(""));
- if (pszLastError) mir_free(pszLastError);
-
- return FALSE;
- }
-
- // Variables list (From-To)
- pslVariablesFromTo = SLNewList();
-
- // %log_time%
- iBuf = GetTimeFormat(GetThreadLocale(), 0, NULL, NULL, NULL, 0); // or: LOCALE_USER_DEFAULT
- pszBuf = (WCHAR*)mir_alloc((iBuf+1)*sizeof(WCHAR));
- GetTimeFormat(GetThreadLocale(), 0, NULL, NULL, pszBuf, iBuf); // or: LOCALE_USER_DEFAULT
- SLAddItemPair(pslVariablesFromTo, _T("%log_time%"), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- // %log_date%
- iBuf = GetDateFormat(GetThreadLocale(), DATE_SHORTDATE, NULL, NULL, NULL, 0); // or: LOCALE_USER_DEFAULT
- pszBuf = (WCHAR*)mir_alloc((iBuf+1)*sizeof(WCHAR));
- GetDateFormat(GetThreadLocale(), DATE_SHORTDATE, NULL, NULL, pszBuf, iBuf); // or: LOCALE_USER_DEFAULT
- SLAddItemPair(pslVariablesFromTo, _T("%log_date%"), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- // %log_user%
- SLAddItemPair(pslVariablesFromTo, _T("%log_user%"), pszUserName);
-
- // %log_type%
- EnterCriticalSection(&csMsgTypes); // thread safety
- iBuf = GetMsgTypeID(pszMsgTypeSection, pszMsgTypeName);
- pszBuf = (iBuf >= 0) ? pamtdMsgTypes[iBuf].ptszDescription : NULL;
- SLAddItemPair(pslVariablesFromTo, _T("%log_type%"), pszBuf);
- LeaveCriticalSection(&csMsgTypes); // thread safety
-
- // %log_recognition%
- pszBuf = SLConvertToString(pslRecognition, TranslateT(", "), FALSE, FALSE, NULL);
- SLAddItemPair(pslVariablesFromTo, _T("%log_recognition%"), pszBuf);
- if (pszBuf) SLFreeReturn(pszBuf);
-
- // %log_result%
- if (dwResult&SFF_MARKREAD)
- pszBuf = TranslateT("Message marked read");
- else if (dwResult&SFF_IGNORE)
- pszBuf = TranslateT("Message deleted");
- else
- pszBuf = TranslateT("User ignored");
- SLAddItemPair(pslVariablesFromTo, _T("%log_result%"), pszBuf);
-
- // %log_message%
- SLAddItemPair(pslVariablesFromTo, _T("%log_message%"), pszMsgContent);
-
- // ##### XML format #####
- if (PathMatchSpec(szLogFile, _T("*.xml")))
- {
- HANDLE hXSLFile;
- WCHAR szXSLFile[MAX_PATH];
-
- STRINGLIST* pslSpecialCharsFromTo;
- char* pszUtf8;
- WCHAR* pszBuf2;
-
- // Create XSL file name
- mir_sntprintf(szXSLFile, ARRAYSIZE(szXSLFile), _T("%s"), szLogFile);
- PathRenameExtension(szXSLFile, _T(".xsl"));
-
- // Construct XML special char replace filter
- pslSpecialCharsFromTo = SLNewList();
- SLAddItemPair(pslSpecialCharsFromTo, _T("&"), _T("&amp;"));
- SLAddItemPair(pslSpecialCharsFromTo, _T("<"), _T("&lt;"));
- SLAddItemPair(pslSpecialCharsFromTo, _T(">"), _T("&gt;"));
- SLAddItemPair(pslSpecialCharsFromTo, _T("'"), _T("&apos;"));
- SLAddItemPair(pslSpecialCharsFromTo, _T("\""), _T("&quot;"));
- SLAddItemPair(pslSpecialCharsFromTo, _T(" "), _T("&nbsp;&nbsp;"));// Only one single space is allowed (multiple must be replaced)
-
- // Replace special chars in replacement variables
- for (iBuf=SL_MIN_POS; iBuf<=SLGetMaxPos(pslVariablesFromTo); iBuf+=2)
- {
- pszBuf = ReplaceSubStringWithStringMultiple(SLGetItem(pslVariablesFromTo, iBuf), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
- SLChangeItem(pslVariablesFromTo, iBuf, pszBuf, FALSE);
- if (pszBuf) mir_free(pszBuf);
- }
-
- // Write XSL stylesheet for XML (XSL-File)
- hXSLFile = CreateFile(szXSLFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hXSLFile != INVALID_HANDLE_VALUE) // If file does not already exist
- {
- STRINGLIST* pslXSLFromTo = SLNewList();
-
- // Translate file contents
- // ", "
- pszBuf = ReplaceSubStringWithStringMultiple(TranslateT(", "), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
- SLAddItemPair(pslXSLFromTo, _T(", "), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- // "Received Spam"
- pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Received Spam"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
- SLAddItemPair(pslXSLFromTo, _T("Received Spam"), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- // "Logged since"
- pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Logged since"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
- SLAddItemPair(pslXSLFromTo, _T("Logged since"), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- // "Date/Time:"
- pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Date/Time:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
- SLAddItemPair(pslXSLFromTo, _T("Date/Time:"), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- // "User:"
- pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("User:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
- SLAddItemPair(pslXSLFromTo, _T("User:"), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- // Type:
- pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Type:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
- SLAddItemPair(pslXSLFromTo, _T("Type:"), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- // "Recognition:"
- pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Recognition:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
- SLAddItemPair(pslXSLFromTo, _T("Recognition:"), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- // "Result:"
- pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Result:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
- SLAddItemPair(pslXSLFromTo, _T("Result:"), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- mir_utf8decode(LockResource(LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(IDR_XSLLAYOUTFILETEMPLATE), _T("TEXT")))),&pszBuf2);
- if (pszBuf2)
- {
- pszBuf = ReplaceSubStringWithStringMultiple(pszBuf2, pslXSLFromTo, TRUE, FALSE, NULL);
- mir_free(pszBuf2);
- if (pszBuf)
- {
- pszUtf8 = mir_utf8encodeW(pszBuf);
- mir_free(pszBuf);
- if (pszUtf8)
- {
- WriteFile(hXSLFile, (PBYTE)pszUtf8, lstrlenA(pszUtf8)*sizeof(char), &dwWritten, NULL);
- //SetEndOfFile(hXSLFile);
- mir_free(pszUtf8);
- }
- }
- }
-
- SLFreeList(pslXSLFromTo);
- CloseHandle(hXSLFile);
- }
-
- // Write XML header/footer (XML-File)
- if (GetFileSize(hFile, NULL) == 0) // If file is empty
- {
- // Replace spacial variables in header
- // %log_xslfile%
- SLAddItemPair(pslVariablesFromTo, _T("%log_xslfile%"), PathFindFileName(szXSLFile));
-
- mir_utf8decode(LockResource(LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(IDR_XMLFILETEMPLATE), _T("TEXT")))),&pszBuf2);
- if (pszBuf2)
- {
- pszBuf = ReplaceSubStringWithStringMultiple(pszBuf2, pslVariablesFromTo, TRUE, FALSE, NULL);
- mir_free(pszBuf2);
- if (pszBuf)
- {
- pszUtf8 = mir_utf8encodeW(pszBuf);
- mir_free(pszBuf);
- if (pszUtf8)
- {
- WriteFile(hFile, (PBYTE)pszUtf8, lstrlenA(pszUtf8)*sizeof(char), &dwWritten, NULL);
- //SetEndOfFile(hFile);
- mir_free(pszUtf8);
- }
- }
- }
- }
-
- // Inject new XML item (XML-File)
- mir_utf8decode(LockResource(LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(IDR_XMLITEMTEMPLATE), _T("TEXT")))),&pszBuf2);
- if (pszBuf2)
- {
- pszBuf = ReplaceSubStringWithStringMultiple(pszBuf2, pslVariablesFromTo, TRUE, FALSE, NULL);
- mir_free(pszBuf2);
- if (pszBuf)
- {
- pszUtf8 = mir_utf8encodeW(pszBuf);
- mir_free(pszBuf);
- if (pszUtf8)
- {
- SetFilePointer(hFile, -12, NULL, FILE_END);
- bReturn = WriteFile(hFile, (PBYTE)pszUtf8, lstrlenA(pszUtf8)*sizeof(char), &dwWritten, NULL);
- //SetEndOfFile(hFile);
- mir_free(pszUtf8);
- }
- }
- }
-
- SLFreeList(pslSpecialCharsFromTo);
-
-
- // ##### Character Separated Values (CSV) format #####
- } else if (PathMatchSpec(szLogFile, _T("*.csv"))) {
-
- BOOL bIsUnicodeFile;
-
- // Replace special chars in replacement variables
- for (iBuf=SL_MIN_POS; iBuf<=SLGetMaxPos(pslVariablesFromTo); iBuf+=2)
- {
- pszBuf = ReplaceSubStringWithString(SLGetItem(pslVariablesFromTo, iBuf), _T("\""), _T("\"\""), TRUE, FALSE, NULL);
- SLChangeItem(pslVariablesFromTo, iBuf, pszBuf, FALSE);
- if (pszBuf) mir_free(pszBuf);
- }
-
- // Unicode and CSV header (Byte-order Mark)
- if (GetFileSize(hFile, NULL) == 0) // If file is empty
- {
- #if defined(UNICODE)
- // Write Unicode BOM UTF-16LE (Notepad)
- // FF FE = UTF-16, little-endian
- // -> indicating Unicode text file
- if (IsWinVer2000Plus()) { // Notepad doesn't support Unicode on Win9x/ME -> no viewer available
- WCHAR chBOM = 0xFFFE;
- bIsUnicodeFile = WriteFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL);
- } else {
- bIsUnicodeFile = FALSE;
- }
- #else
- bIsUnicodeFile = FALSE;
- #endif
-
- pszBuf = TranslateT("\"Date\";\"Time\";\"User\";\"Type\";\"Recognition\";\"Result\";\"Message\"\r\n");
- if (pszBuf)
- {
- #if defined(UNICODE)
-
- if (!bIsUnicodeFile)
- {
- WCHAR* pszAnsi;
- mir_utf8decode((char*)pszBuf,&pszAnsi);
- if (pszAnsi)
- {
- bReturn = WriteFile(hFile, (PBYTE)pszAnsi, lstrlenW(pszAnsi)*sizeof(char), &dwWritten, NULL);
- mir_free(pszAnsi);
- }
-
- } else {
- bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlenW(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
- }
-
- #else
-
- if (bIsUnicodeFile)
- {
- WCHAR* pszUnicode = mir_utf8encodeW(pszBuf);
- if (pszUnicode)
- {
- bReturn = WriteFile(hFile, (PBYTE)pszUnicode, lstrlenW(pszUnicode)*sizeof(WCHAR), &dwWritten, NULL);
- mir_free(pszUnicode);
- }
-
- } else {
- bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlenA(pszBuf)*sizeof(char), &dwWritten, NULL);
- }
-
- #endif
- }
-
- } else {
-
- WCHAR chBOM;
-
- // Read BOM header (Is file UTF-16LE?)
- if (ReadFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL))
- bIsUnicodeFile = (chBOM == 0xFFFE);
- else
- bIsUnicodeFile = FALSE;
- }
-
- pszBuf = TranslateT("\"%log_date%\";\"%log_time%\";\"%log_user%\";\"%log_type%\";\"%log_recognition%\";\"%log_result%\";\"%log_message%\"\r\n");
- pszBuf = ReplaceSubStringWithStringMultiple(pszBuf, pslVariablesFromTo, TRUE, FALSE, NULL);
- if (pszBuf)
- {
- SetFilePointer(hFile, 0, NULL, FILE_END);
-
- // Append Unicode/ANSI CSV item
- #if defined(UNICODE)
-
- if (!bIsUnicodeFile)
- {
- WCHAR* pszAnsi;
- mir_utf8decode((char*)pszBuf,&pszAnsi);
- if (pszAnsi)
- {
- bReturn = WriteFile(hFile, (PBYTE)pszAnsi, lstrlenW(pszAnsi)*sizeof(char), &dwWritten, NULL);
- mir_free(pszAnsi);
- }
-
- } else {
- bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
- }
-
- #else
-
- if (bIsUnicodeFile)
- {
- WCHAR* pszUnicode = mir_utf8encodeW(pszBuf);
- if (pszUnicode)
- {
- bReturn = WriteFile(hFile, (PBYTE)pszUnicode, lstrlenW(pszUnicode)*sizeof(WCHAR), &dwWritten, NULL);
- mir_free(pszUnicode);
- }
-
- } else {
- bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
- }
-
- #endif
-
- //SetEndOfFile(hFile);
- mir_free(pszBuf);
- }
-
-
- // ##### Plain-Text format (TXT/LOG) #####
- } else {
-
- BOOL bIsUnicodeFile;
-
- // Unicode header (Byte-order Mark)
- if (GetFileSize(hFile, NULL) == 0) // If file is empty
- {
- #if defined(UNICODE)
- // Write Unicode BOM UTF-16LE (Notepad)
- // FF FE = UTF-16, little-endian
- // -> indicating Unicode text file
- if (IsWinVer2000Plus()) {// Notepad doesn't support Unicode on Win9x/ME -> no viewer available
- WCHAR chBOM = 0xFFFE;
- bIsUnicodeFile = WriteFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL);
- } else {
- bIsUnicodeFile = FALSE;
- }
- #else
- bIsUnicodeFile = FALSE;
- #endif
-
- } else {
-
- WCHAR chBOM;
- bIsUnicodeFile = FALSE;
-
- // Read BOM header (Is file UTF-16LE?)
- if (ReadFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL)) {
- bIsUnicodeFile = (chBOM == 0xFFFE);
- } else {
- bIsUnicodeFile = FALSE;
- }
- }
-
- pszBuf = TranslateT("[%log_date% %log_time%, User: %log_user%, Type: %log_type%]\r\nRecognition: %log_recognition%\t\r\nResult: %log_result%\r\n%log_message%\r\n\r\n");
- pszBuf = ReplaceSubStringWithStringMultiple(pszBuf, pslVariablesFromTo, TRUE, FALSE, NULL);
- if (pszBuf)
- {
- SetFilePointer(hFile, 0, NULL, FILE_END);
-
- // Append Unicode/ANSI log item
- #if defined(UNICODE)
-
- if (!bIsUnicodeFile)
- {
- WCHAR* pszAnsi;
- mir_utf8decode((char*)pszBuf,&pszAnsi);
- if (pszAnsi)
- {
- bReturn = WriteFile(hFile, (PBYTE)pszAnsi, lstrlenW(pszAnsi)*sizeof(char), &dwWritten, NULL);
- mir_free(pszAnsi);
- }
-
- } else {
- bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
- }
-
- #else
-
- if (bIsUnicodeFile)
- {
- WCHAR* pszUnicode = mir_utf8encodeW(pszBuf);
- if (pszUnicode)
- {
- bReturn = WriteFile(hFile, (PBYTE)pszUnicode, lstrlenW(pszUnicode)*sizeof(WCHAR), &dwWritten, NULL);
- mir_free(pszUnicode);
- }
-
- } else {
- bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(TCHAR), &dwWritten, NULL);
- }
-
- #endif
-
- //SetEndOfFile(hFile);
- mir_free(pszBuf);
- }
-
-
- } // ##### format end #####
-
- CloseHandle(hFile);
- SLFreeList(pslVariablesFromTo);
-
- // Enable "show log" button if log was created while window open
- if (IsWindow(hwndSpamFilterOpt))
- PostMessage(hwndSpamFilterOpt, SFM_VALIDATE_LOGFILENAME, 0, 0);
-
- return bReturn;
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+
+// -----------------------------------------
+
+
+BOOL WriteToLogFile(const char* pszMsgTypeSection, const char* pszMsgTypeName, const WCHAR* pszUserName, const WCHAR* pszMsgContent, STRINGLIST* pslRecognition, DWORD dwResult)
+{
+ BOOL bReturn;
+
+ HANDLE hFile;
+ DWORD dwWritten; // For Windows 95/98/ME compatibility for WriteFile (parameter needed)
+
+ STRINGLIST* pslVariablesFromTo;
+ WCHAR szLogFile[MAX_PATH];
+
+ int iBuf;
+ WCHAR* pszBuf;
+
+ // Get file to log to
+ {
+ DBVARIANT dbv;
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_LOGFILE, &dbv) == 0)
+ {
+ mir_sntprintf(szLogFile, ARRAYSIZE(szLogFile), _T("%s"), dbv.pszVal);
+ DBFreeVariant(&dbv);
+ PMakePathUsable(szLogFile);
+ } else {
+ szLogFile[0] = _T('\0');
+ }
+ }
+
+ // Make sure the directory exists: SILENT!
+ PPreparePathForWrite(NULL, szLogFile, FALSE, TRUE);
+
+ // Open file
+ hFile = CreateFile(szLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ bReturn = (hFile != INVALID_HANDLE_VALUE);
+ if (!bReturn)
+ {
+ WCHAR* pszLastError = GetLastErrorDescription(GetLastError());
+
+ ShowInfoMessage(NIIF_ERROR, TranslateT("Spam Filter Error"), TranslateT("The log file \"%s\"\r\ncan not be written.\r\n\r\nProblem:\r\n%s\r\nPlease check the settings."), lstrlen(szLogFile)+lstrlen(pszLastError), (lstrlen(PathFindFileName(szLogFile))>0)?PathFindFileName(szLogFile):szLogFile, pszLastError?pszLastError:_T(""));
+ if (pszLastError) mir_free(pszLastError);
+
+ return FALSE;
+ }
+
+ // Variables list (From-To)
+ pslVariablesFromTo = SLNewList();
+
+ // %log_time%
+ iBuf = GetTimeFormat(GetThreadLocale(), 0, NULL, NULL, NULL, 0); // or: LOCALE_USER_DEFAULT
+ pszBuf = (WCHAR*)mir_alloc((iBuf+1)*sizeof(WCHAR));
+ GetTimeFormat(GetThreadLocale(), 0, NULL, NULL, pszBuf, iBuf); // or: LOCALE_USER_DEFAULT
+ SLAddItemPair(pslVariablesFromTo, _T("%log_time%"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // %log_date%
+ iBuf = GetDateFormat(GetThreadLocale(), DATE_SHORTDATE, NULL, NULL, NULL, 0); // or: LOCALE_USER_DEFAULT
+ pszBuf = (WCHAR*)mir_alloc((iBuf+1)*sizeof(WCHAR));
+ GetDateFormat(GetThreadLocale(), DATE_SHORTDATE, NULL, NULL, pszBuf, iBuf); // or: LOCALE_USER_DEFAULT
+ SLAddItemPair(pslVariablesFromTo, _T("%log_date%"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // %log_user%
+ SLAddItemPair(pslVariablesFromTo, _T("%log_user%"), pszUserName);
+
+ // %log_type%
+ EnterCriticalSection(&csMsgTypes); // thread safety
+ iBuf = GetMsgTypeID(pszMsgTypeSection, pszMsgTypeName);
+ pszBuf = (iBuf >= 0) ? pamtdMsgTypes[iBuf].ptszDescription : NULL;
+ SLAddItemPair(pslVariablesFromTo, _T("%log_type%"), pszBuf);
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+
+ // %log_recognition%
+ pszBuf = SLConvertToString(pslRecognition, TranslateT(", "), FALSE, FALSE, NULL);
+ SLAddItemPair(pslVariablesFromTo, _T("%log_recognition%"), pszBuf);
+ if (pszBuf) SLFreeReturn(pszBuf);
+
+ // %log_result%
+ if (dwResult&SFF_MARKREAD)
+ pszBuf = TranslateT("Message marked read");
+ else if (dwResult&SFF_IGNORE)
+ pszBuf = TranslateT("Message deleted");
+ else
+ pszBuf = TranslateT("User ignored");
+ SLAddItemPair(pslVariablesFromTo, _T("%log_result%"), pszBuf);
+
+ // %log_message%
+ SLAddItemPair(pslVariablesFromTo, _T("%log_message%"), pszMsgContent);
+
+ // ##### XML format #####
+ if (PathMatchSpec(szLogFile, _T("*.xml")))
+ {
+ HANDLE hXSLFile;
+ WCHAR szXSLFile[MAX_PATH];
+
+ STRINGLIST* pslSpecialCharsFromTo;
+ char* pszUtf8;
+ WCHAR* pszBuf2;
+
+ // Create XSL file name
+ mir_sntprintf(szXSLFile, ARRAYSIZE(szXSLFile), _T("%s"), szLogFile);
+ PathRenameExtension(szXSLFile, _T(".xsl"));
+
+ // Construct XML special char replace filter
+ pslSpecialCharsFromTo = SLNewList();
+ SLAddItemPair(pslSpecialCharsFromTo, _T("&"), _T("&amp;"));
+ SLAddItemPair(pslSpecialCharsFromTo, _T("<"), _T("&lt;"));
+ SLAddItemPair(pslSpecialCharsFromTo, _T(">"), _T("&gt;"));
+ SLAddItemPair(pslSpecialCharsFromTo, _T("'"), _T("&apos;"));
+ SLAddItemPair(pslSpecialCharsFromTo, _T("\""), _T("&quot;"));
+ SLAddItemPair(pslSpecialCharsFromTo, _T(" "), _T("&nbsp;&nbsp;"));// Only one single space is allowed (multiple must be replaced)
+
+ // Replace special chars in replacement variables
+ for (iBuf=SL_MIN_POS; iBuf<=SLGetMaxPos(pslVariablesFromTo); iBuf+=2)
+ {
+ pszBuf = ReplaceSubStringWithStringMultiple(SLGetItem(pslVariablesFromTo, iBuf), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLChangeItem(pslVariablesFromTo, iBuf, pszBuf, FALSE);
+ if (pszBuf) mir_free(pszBuf);
+ }
+
+ // Write XSL stylesheet for XML (XSL-File)
+ hXSLFile = CreateFile(szXSLFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hXSLFile != INVALID_HANDLE_VALUE) // If file does not already exist
+ {
+ STRINGLIST* pslXSLFromTo = SLNewList();
+
+ // Translate file contents
+ // ", "
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT(", "), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T(", "), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "Received Spam"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Received Spam"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Received Spam"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "Logged since"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Logged since"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Logged since"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "Date/Time:"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Date/Time:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Date/Time:"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "User:"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("User:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("User:"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // Type:
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Type:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Type:"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "Recognition:"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Recognition:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Recognition:"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "Result:"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Result:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Result:"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ mir_utf8decode(LockResource(LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(IDR_XSLLAYOUTFILETEMPLATE), _T("TEXT")))),&pszBuf2);
+ if (pszBuf2)
+ {
+ pszBuf = ReplaceSubStringWithStringMultiple(pszBuf2, pslXSLFromTo, TRUE, FALSE, NULL);
+ mir_free(pszBuf2);
+ if (pszBuf)
+ {
+ pszUtf8 = mir_utf8encodeW(pszBuf);
+ mir_free(pszBuf);
+ if (pszUtf8)
+ {
+ WriteFile(hXSLFile, (PBYTE)pszUtf8, lstrlenA(pszUtf8)*sizeof(char), &dwWritten, NULL);
+ //SetEndOfFile(hXSLFile);
+ mir_free(pszUtf8);
+ }
+ }
+ }
+
+ SLFreeList(pslXSLFromTo);
+ CloseHandle(hXSLFile);
+ }
+
+ // Write XML header/footer (XML-File)
+ if (GetFileSize(hFile, NULL) == 0) // If file is empty
+ {
+ // Replace spacial variables in header
+ // %log_xslfile%
+ SLAddItemPair(pslVariablesFromTo, _T("%log_xslfile%"), PathFindFileName(szXSLFile));
+
+ mir_utf8decode(LockResource(LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(IDR_XMLFILETEMPLATE), _T("TEXT")))),&pszBuf2);
+ if (pszBuf2)
+ {
+ pszBuf = ReplaceSubStringWithStringMultiple(pszBuf2, pslVariablesFromTo, TRUE, FALSE, NULL);
+ mir_free(pszBuf2);
+ if (pszBuf)
+ {
+ pszUtf8 = mir_utf8encodeW(pszBuf);
+ mir_free(pszBuf);
+ if (pszUtf8)
+ {
+ WriteFile(hFile, (PBYTE)pszUtf8, lstrlenA(pszUtf8)*sizeof(char), &dwWritten, NULL);
+ //SetEndOfFile(hFile);
+ mir_free(pszUtf8);
+ }
+ }
+ }
+ }
+
+ // Inject new XML item (XML-File)
+ mir_utf8decode(LockResource(LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(IDR_XMLITEMTEMPLATE), _T("TEXT")))),&pszBuf2);
+ if (pszBuf2)
+ {
+ pszBuf = ReplaceSubStringWithStringMultiple(pszBuf2, pslVariablesFromTo, TRUE, FALSE, NULL);
+ mir_free(pszBuf2);
+ if (pszBuf)
+ {
+ pszUtf8 = mir_utf8encodeW(pszBuf);
+ mir_free(pszBuf);
+ if (pszUtf8)
+ {
+ SetFilePointer(hFile, -12, NULL, FILE_END);
+ bReturn = WriteFile(hFile, (PBYTE)pszUtf8, lstrlenA(pszUtf8)*sizeof(char), &dwWritten, NULL);
+ //SetEndOfFile(hFile);
+ mir_free(pszUtf8);
+ }
+ }
+ }
+
+ SLFreeList(pslSpecialCharsFromTo);
+
+
+ // ##### Character Separated Values (CSV) format #####
+ } else if (PathMatchSpec(szLogFile, _T("*.csv"))) {
+
+ BOOL bIsUnicodeFile;
+
+ // Replace special chars in replacement variables
+ for (iBuf=SL_MIN_POS; iBuf<=SLGetMaxPos(pslVariablesFromTo); iBuf+=2)
+ {
+ pszBuf = ReplaceSubStringWithString(SLGetItem(pslVariablesFromTo, iBuf), _T("\""), _T("\"\""), TRUE, FALSE, NULL);
+ SLChangeItem(pslVariablesFromTo, iBuf, pszBuf, FALSE);
+ if (pszBuf) mir_free(pszBuf);
+ }
+
+ // Unicode and CSV header (Byte-order Mark)
+ if (GetFileSize(hFile, NULL) == 0) // If file is empty
+ {
+ #if defined(UNICODE)
+ // Write Unicode BOM UTF-16LE (Notepad)
+ // FF FE = UTF-16, little-endian
+ // -> indicating Unicode text file
+ if (IsWinVer2000Plus()) { // Notepad doesn't support Unicode on Win9x/ME -> no viewer available
+ WCHAR chBOM = 0xFFFE;
+ bIsUnicodeFile = WriteFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL);
+ } else {
+ bIsUnicodeFile = FALSE;
+ }
+ #else
+ bIsUnicodeFile = FALSE;
+ #endif
+
+ pszBuf = TranslateT("\"Date\";\"Time\";\"User\";\"Type\";\"Recognition\";\"Result\";\"Message\"\r\n");
+ if (pszBuf)
+ {
+ #if defined(UNICODE)
+
+ if (!bIsUnicodeFile)
+ {
+ WCHAR* pszAnsi;
+ mir_utf8decode((char*)pszBuf,&pszAnsi);
+ if (pszAnsi)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszAnsi, lstrlenW(pszAnsi)*sizeof(char), &dwWritten, NULL);
+ mir_free(pszAnsi);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlenW(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
+ }
+
+ #else
+
+ if (bIsUnicodeFile)
+ {
+ WCHAR* pszUnicode = mir_utf8encodeW(pszBuf);
+ if (pszUnicode)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszUnicode, lstrlenW(pszUnicode)*sizeof(WCHAR), &dwWritten, NULL);
+ mir_free(pszUnicode);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlenA(pszBuf)*sizeof(char), &dwWritten, NULL);
+ }
+
+ #endif
+ }
+
+ } else {
+
+ WCHAR chBOM;
+
+ // Read BOM header (Is file UTF-16LE?)
+ if (ReadFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL))
+ bIsUnicodeFile = (chBOM == 0xFFFE);
+ else
+ bIsUnicodeFile = FALSE;
+ }
+
+ pszBuf = TranslateT("\"%log_date%\";\"%log_time%\";\"%log_user%\";\"%log_type%\";\"%log_recognition%\";\"%log_result%\";\"%log_message%\"\r\n");
+ pszBuf = ReplaceSubStringWithStringMultiple(pszBuf, pslVariablesFromTo, TRUE, FALSE, NULL);
+ if (pszBuf)
+ {
+ SetFilePointer(hFile, 0, NULL, FILE_END);
+
+ // Append Unicode/ANSI CSV item
+ #if defined(UNICODE)
+
+ if (!bIsUnicodeFile)
+ {
+ WCHAR* pszAnsi;
+ mir_utf8decode((char*)pszBuf,&pszAnsi);
+ if (pszAnsi)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszAnsi, lstrlenW(pszAnsi)*sizeof(char), &dwWritten, NULL);
+ mir_free(pszAnsi);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
+ }
+
+ #else
+
+ if (bIsUnicodeFile)
+ {
+ WCHAR* pszUnicode = mir_utf8encodeW(pszBuf);
+ if (pszUnicode)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszUnicode, lstrlenW(pszUnicode)*sizeof(WCHAR), &dwWritten, NULL);
+ mir_free(pszUnicode);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
+ }
+
+ #endif
+
+ //SetEndOfFile(hFile);
+ mir_free(pszBuf);
+ }
+
+
+ // ##### Plain-Text format (TXT/LOG) #####
+ } else {
+
+ BOOL bIsUnicodeFile;
+
+ // Unicode header (Byte-order Mark)
+ if (GetFileSize(hFile, NULL) == 0) // If file is empty
+ {
+ #if defined(UNICODE)
+ // Write Unicode BOM UTF-16LE (Notepad)
+ // FF FE = UTF-16, little-endian
+ // -> indicating Unicode text file
+ if (IsWinVer2000Plus()) {// Notepad doesn't support Unicode on Win9x/ME -> no viewer available
+ WCHAR chBOM = 0xFFFE;
+ bIsUnicodeFile = WriteFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL);
+ } else {
+ bIsUnicodeFile = FALSE;
+ }
+ #else
+ bIsUnicodeFile = FALSE;
+ #endif
+
+ } else {
+
+ WCHAR chBOM;
+ bIsUnicodeFile = FALSE;
+
+ // Read BOM header (Is file UTF-16LE?)
+ if (ReadFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL)) {
+ bIsUnicodeFile = (chBOM == 0xFFFE);
+ } else {
+ bIsUnicodeFile = FALSE;
+ }
+ }
+
+ pszBuf = TranslateT("[%log_date% %log_time%, User: %log_user%, Type: %log_type%]\r\nRecognition: %log_recognition%\t\r\nResult: %log_result%\r\n%log_message%\r\n\r\n");
+ pszBuf = ReplaceSubStringWithStringMultiple(pszBuf, pslVariablesFromTo, TRUE, FALSE, NULL);
+ if (pszBuf)
+ {
+ SetFilePointer(hFile, 0, NULL, FILE_END);
+
+ // Append Unicode/ANSI log item
+ #if defined(UNICODE)
+
+ if (!bIsUnicodeFile)
+ {
+ WCHAR* pszAnsi;
+ mir_utf8decode((char*)pszBuf,&pszAnsi);
+ if (pszAnsi)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszAnsi, lstrlenW(pszAnsi)*sizeof(char), &dwWritten, NULL);
+ mir_free(pszAnsi);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
+ }
+
+ #else
+
+ if (bIsUnicodeFile)
+ {
+ WCHAR* pszUnicode = mir_utf8encodeW(pszBuf);
+ if (pszUnicode)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszUnicode, lstrlenW(pszUnicode)*sizeof(WCHAR), &dwWritten, NULL);
+ mir_free(pszUnicode);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(TCHAR), &dwWritten, NULL);
+ }
+
+ #endif
+
+ //SetEndOfFile(hFile);
+ mir_free(pszBuf);
+ }
+
+
+ } // ##### format end #####
+
+ CloseHandle(hFile);
+ SLFreeList(pslVariablesFromTo);
+
+ // Enable "show log" button if log was created while window open
+ if (IsWindow(hwndSpamFilterOpt))
+ PostMessage(hwndSpamFilterOpt, SFM_VALIDATE_LOGFILENAME, 0, 0);
+
+ return bReturn;
} \ No newline at end of file
diff --git a/logfile.h b/logfile.h
index 265b534..a677dff 100644
--- a/logfile.h
+++ b/logfile.h
@@ -1,28 +1,28 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_LOGFILE_H__
-#define SF_LOGFILE_H__ 1
-
-// -- Prototypes
-BOOL WriteToLogFile(const char* pszMsgTypeSection, const char* pszMsgTypeName, const WCHAR* pszUserName, const WCHAR* pszMsgContent, STRINGLIST* pslRecognition, DWORD dwResult);
-
-#endif // SF_LOGFILE_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_LOGFILE_H__
+#define SF_LOGFILE_H__ 1
+
+// -- Prototypes
+BOOL WriteToLogFile(const char* pszMsgTypeSection, const char* pszMsgTypeName, const WCHAR* pszUserName, const WCHAR* pszMsgContent, STRINGLIST* pslRecognition, DWORD dwResult);
+
+#endif // SF_LOGFILE_H__
diff --git a/m_popup.h b/m_popup.h
index 7efad50..6888bd8 100644
--- a/m_popup.h
+++ b/m_popup.h
@@ -1,338 +1,338 @@
-/*
-===============================================================================
- 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_POPUP_H
-#define M_POPUP_H
-
-/*
-NOTE! Since Popup 1.0.1.2 there is a main meun group called "PopUps" where I
-have put a "Enable/Disable" item. You can add your own "enable/disable" items
-by adding these lines before you call MS_CLIST_ADDMAINMENUITEM:
-mi.pszPopUpName = Translate("PopUps");
-mi.position = 0; //You don't need it and it's better if you put it to zero.
-*/
-
-#define MAX_CONTACTNAME 2048
-#define MAX_SECONDLINE 2048
-
-// This is the basic data you'll need to fill and pass to the service function.
-typedef struct
-{
- HANDLE lchContact; // Handle to the contact, can be NULL (main contact).
- HICON lchIcon; // Handle to a icon to be shown. Cannot be NULL.
- union
- {
- char lptzContactName[MAX_CONTACTNAME]; // This is the contact name or the first line in the plugin. Cannot be NULL.
- char lpzContactName[MAX_CONTACTNAME];
- };
- union
- {
- char lptzText[MAX_SECONDLINE]; // This is the second line text. Users can choose to hide it. Cannot be NULL.
- char lpzText[MAX_SECONDLINE];
- };
- COLORREF colorBack; // COLORREF to be used for the background. Can be NULL, default will be used.
- COLORREF colorText; // COLORREF to be used for the text. Can be NULL, default will be used.
- WNDPROC PluginWindowProc; // Read below. Can be NULL; default will be used.
- void * PluginData; // Read below. Can be NULL.
-} POPUPDATA, * LPPOPUPDATA;
-
-// Extended popup data
-typedef struct
-{
- HANDLE lchContact;
- HICON lchIcon;
- union
- {
- char lptzContactName[MAX_CONTACTNAME];
- char lpzContactName[MAX_CONTACTNAME];
- };
- union
- {
- char lptzText[MAX_SECONDLINE];
- char lpzText[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.
-} POPUPDATAEX, *LPPOPUPDATAEX;
-
-// Unicode version of POPUPDATAEX
-typedef struct
-{
- HANDLE lchContact;
- HICON lchIcon;
- union
- {
- WCHAR lptzContactName[MAX_CONTACTNAME];
- WCHAR lpwzContactName[MAX_CONTACTNAME];
- };
- union
- {
- WCHAR lptzText[MAX_CONTACTNAME];
- WCHAR lpwzText[MAX_CONTACTNAME];
- };
- COLORREF colorBack;
- COLORREF colorText;
- WNDPROC PluginWindowProc;
- void * PluginData;
- int iSeconds;
- char cZero[16];
-} POPUPDATAW, *LPPOPUPDATAW;
-
-#if defined(_UNICODE) || defined(UNICODE)
- typedef POPUPDATAW POPUPDATAT;
- typedef LPPOPUPDATAW LPPOPUPDATAT;
-#else
- typedef POPUPDATAEX POPUPDATAT;
- typedef LPPOPUPDATAEX LPPOPUPDATAT;
-#endif
-
-/* PopUp/AddPopup
-Creates, adds and shows a popup, given a (valid) POPUPDATA structure pointer.
-
-wParam = (WPARAM)(*POPUPDATA)PopUpDataAddress
-lParam = 0
-
-Returns: > 0 on success, 0 if creation went bad, -1 if the PopUpData contained unacceptable values.
-NOTE: it returns -1 if the PopUpData was not valid, if there were already too many popups, if the module was disabled.
-Otherwise, it can return anything else...
-
-Popup Plus 2.0.4.0+
-You may pass additional creation flags via lParam:
- APF_RETURN_HWND ....... function returns handle to newly created popup window (however this calls are a bit slower)
- APF_CUSTOM_POPUP ...... new popup is created in hidden state and doesn't obey to popup queue rules.
- you may control it via UM_* messages and custom window procedure
-*/
-#define APF_RETURN_HWND 0x1
-#define APF_CUSTOM_POPUP 0x2
-
-#define MS_POPUP_ADDPOPUP "PopUp/AddPopUp"
-static int __inline PUAddPopUp(POPUPDATA* ppdp) {
- return CallService(MS_POPUP_ADDPOPUP, (WPARAM)ppdp,0);
-}
-
-#define MS_POPUP_ADDPOPUPEX "PopUp/AddPopUpEx"
-static int __inline PUAddPopUpEx(POPUPDATAEX* ppdp) {
- return CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)ppdp,0);
-}
-
-#define MS_POPUP_ADDPOPUPW "PopUp/AddPopUpW"
-static int __inline PUAddPopUpW(POPUPDATAW* ppdp) {
- return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)ppdp,0);
-}
-
-#if defined(_UNICODE) || defined(UNICODE)
- #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPW
- #define PUAddPopUpT PUAddPopUpW
-#else
- #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPEX
- #define PUAddPopUpT PUAddPopUpEx
-#endif
-
-
-/* PopUp/GetContact
-Returns the handle to the contact associated to the specified PopUpWindow.
-
-wParam = (WPARAM)(HWND)hPopUpWindow
-lParam = 0;
-
-Returns: the HANDLE of the contact. Can return NULL, meaning it's the main contact. -1 means failure.
-*/
-#define MS_POPUP_GETCONTACT "PopUp/GetContact"
-static HANDLE __inline PUGetContact(HWND hPopUpWindow) {
- return (HANDLE)CallService(MS_POPUP_GETCONTACT, (WPARAM)hPopUpWindow,0);
-}
-
-/* PopUp/GetPluginData
-Returns custom plugin date associated with popup
-
-wParam = (WPARAM)(HWND)hPopUpWindow
-lParam = (LPARAM)(PLUGINDATA*)PluginDataAddress;
-
-Returns: the address of the PLUGINDATA structure. Can return NULL, meaning nothing was given. -1 means failure.
-
-IMPORTANT NOTE: it doesn't seem to work if you do:
-CallService(..., (LPARAM)aPointerToAStruct);
-and then use that struct.
-Do this, instead:
-aPointerToStruct = CallService(..., (LPARAM)aPointerToAStruct);
-and it will work. Just look at the example I've written above (PopUpDlgProc).
-
-*/
-#define MS_POPUP_GETPLUGINDATA "PopUp/GetPluginData"
-static void __inline * PUGetPluginData(HWND hPopUpWindow) {
- long * uselessPointer = NULL;
- return (void*)CallService(MS_POPUP_GETPLUGINDATA,(WPARAM)hPopUpWindow,(LPARAM)uselessPointer);
-}
-
-/* PopUp/IsSecondLineShown
-Checks if second line is enable
-
-wParam = 0
-lParam = 0
-
-Returns: 0 if the user has chosen not to have the second line, 1 if he choose to have the second line.
-*/
-#define MS_POPUP_ISSECONDLINESHOWN "PopUp/IsSecondLineShown"
-static BOOL __inline PUIsSecondLineShown() {
- return (BOOL)CallService(MS_POPUP_ISSECONDLINESHOWN,0,0);
-}
-
-/* PopUp/Query
-
-Requests an action or an answer from PopUp module.
-
-wParam = (WPARAM)wpQuery
-
-returns 0 on success, -1 on error, 1 on stupid calls ;-)
-*/
-
-#define PUQS_ENABLEPOPUPS 1 // returns 0 if state was changed, 1 if state wasn't changed
-#define PUQS_DISABLEPOPUPS 2 // " "
-#define PUQS_GETSTATUS 3 //Returns 1 (TRUE) if popups are enabled, 0 (FALSE) if popups are disabled.
-
-#define MS_POPUP_QUERY "PopUp/Query"
-
-/* UM_FREEPLUGINDATA
-Process this message if you have allocated your own memory. (i.e.: POPUPDATA.PluginData != NULL)
-
-wParam = 0
-lParam = 0
-*/
-#define UM_FREEPLUGINDATA (WM_USER + 0x0200)
-
-/* UM_DESTROYPOPUP
-Send this message when you want to destroy the popup, or use the function below.
-
-wParam = 0
-lParam = 0
-*/
-#define UM_DESTROYPOPUP (WM_USER + 0x0201)
-static int __inline PUDeletePopUp(HWND hWndPopUp) {
- return (int)SendMessage(hWndPopUp, UM_DESTROYPOPUP,0,0);
-}
-
-/* UM_INITPOPUP
-This message is sent to the PopUp when its creation has been finished, so POPUPDATA (and thus your PluginData) is reachable.
-Catch it if you needed to catch WM_CREATE or WM_INITDIALOG, which you'll never ever get in your entire popup-life.
-Return value: if you process this message, return 0. If you don't process it, return 0. Do whatever you like ;-)
-
-wParam = (WPARAM)(HWND)hPopUpWindow (this is useless, you get message inside your popup window)
-lParam = 0
-*/
-#define UM_INITPOPUP (WM_USER + 0x0202)
-
-/* PopUp/Changetext
-Changes the text displayed in the second line of the popup.
-
-wParam = (WPARAM)(HWND)hPopUpWindow
-lParam = (LPARAM)(char*)lpzNewText
-
-returns: > 0 for success, -1 for failure, 0 if the failure is due to second line not being shown. (but you could call
-PUIsSecondLineShown() before changing the text...)
-*/
-#define MS_POPUP_CHANGETEXT "PopUp/Changetext"
-static int __inline PUChangeText(HWND hWndPopUp, LPCTSTR lpzNewText) {
- return (int)CallService(MS_POPUP_CHANGETEXT, (WPARAM)hWndPopUp, (LPARAM)lpzNewText);
-}
-
-#define MS_POPUP_CHANGETEXTW "PopUp/ChangetextW"
-static int __inline PUChangeTextW(HWND hWndPopUp, LPCWSTR lpwzNewText) {
- return (int)CallService(MS_POPUP_CHANGETEXTW, (WPARAM)hWndPopUp, (LPARAM)lpwzNewText);
-}
-
-#if defined(_UNICODE) || defined(UNICODE)
- #define MS_POPUP_CHANGETEXTT MS_POPUP_CHANGETEXTW
- #define PUChangeTextT PUChangeTextW
-#else
- #define MS_POPUP_CHANGETEXTT MS_POPUP_CHANGETEXT
- #define PUChangeTextT PUChangeText
-#endif
-
-/* PopUp/Change
-Changes the entire popup
-
-wParam = (WPARAM)(HWND)hPopUpWindow
-lParam = (LPARAM)(POPUPDATAEX*)newData
-*/
-#define MS_POPUP_CHANGE "PopUp/Change"
-static int __inline PUChange(HWND hWndPopUp, POPUPDATAEX *newData) {
- return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData);
-}
-
-#define MS_POPUP_CHANGEW "PopUp/ChangeW"
-static int __inline PUChangeW(HWND hWndPopUp, POPUPDATAW *newData) {
- return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData);
-}
-
-#if defined(_UNICODE) || defined(UNICODE)
- #define MS_POPUP_CHANGET MS_POPUP_CHANGEW
- #define PUChangeT PUChangeW
-#else
- #define MS_POPUP_CHANGET MS_POPUP_CHANGE
- #define PUChangeT PUChange
-#endif
-
-/* UM_CHANGEPOPUP
-This message is triggered by Change/ChangeText services. You also may post it directly :)
-
-wParam = Modification type
-lParam = value of type defined by wParam
-*/
-
-#define CPT_TEXT 1 // lParam = (char *)text
-#define CPT_TEXTW 2 // lParam = (WCHAR *)text
-#define CPT_TITLE 3 // lParam = (char *)title
-#define CPT_TITLEW 4 // lParam = (WCHAR *)title
-#define CPT_DATA 5 // lParam = (POPUPDATA *)data
-#define CPT_DATAEX 6 // lParam = (POPUPDATAEX *)data
-#define CPT_DATAW 7 // lParam = (POPUPDATAW *)data
-
-#define UM_CHANGEPOPUP (WM_USER + 0x0203)
-
-#if defined(_UNICODE) || defined(UNICODE)
- #define CPT_TEXTT CPT_TEXTW
- #define CPT_TITLET CPT_TITLEW
- #define CPT_DATAT CPT_DATAW
-#else
- #define CPT_TEXTT CPT_TEXT
- #define CPT_TITLET CPT_TITLE
- #define CPT_DATAT CPT_DATA
-#endif
-
-/* PopUp/ShowMessage
-This is mainly for developers.
-Shows a warning message in a PopUp. It's useful if you need a "MessageBox" like function, but you don't want a modal
-window (which will interfere with a DialogProcedure. MessageBox steals focus and control, this one not.
-
-wParam = (char *)lpzMessage
-lParam = 0;
-
-Returns: 0 if the popup was shown, -1 in case of failure.
-*/
-#define SM_WARNING 0x01 //Triangle icon.
-#define SM_NOTIFY 0x02 //Exclamation mark icon.
-#define MS_POPUP_SHOWMESSAGE "PopUp/ShowMessage"
-
-static int __inline PUShowMessage(char *lpzText, BYTE kind) {
- return (int)CallService(MS_POPUP_SHOWMESSAGE, (WPARAM)lpzText,(LPARAM)kind);
-}
-
-#endif // __m_popup_h__
+/*
+===============================================================================
+ 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_POPUP_H
+#define M_POPUP_H
+
+/*
+NOTE! Since Popup 1.0.1.2 there is a main meun group called "PopUps" where I
+have put a "Enable/Disable" item. You can add your own "enable/disable" items
+by adding these lines before you call MS_CLIST_ADDMAINMENUITEM:
+mi.pszPopUpName = Translate("PopUps");
+mi.position = 0; //You don't need it and it's better if you put it to zero.
+*/
+
+#define MAX_CONTACTNAME 2048
+#define MAX_SECONDLINE 2048
+
+// This is the basic data you'll need to fill and pass to the service function.
+typedef struct
+{
+ HANDLE lchContact; // Handle to the contact, can be NULL (main contact).
+ HICON lchIcon; // Handle to a icon to be shown. Cannot be NULL.
+ union
+ {
+ char lptzContactName[MAX_CONTACTNAME]; // This is the contact name or the first line in the plugin. Cannot be NULL.
+ char lpzContactName[MAX_CONTACTNAME];
+ };
+ union
+ {
+ char lptzText[MAX_SECONDLINE]; // This is the second line text. Users can choose to hide it. Cannot be NULL.
+ char lpzText[MAX_SECONDLINE];
+ };
+ COLORREF colorBack; // COLORREF to be used for the background. Can be NULL, default will be used.
+ COLORREF colorText; // COLORREF to be used for the text. Can be NULL, default will be used.
+ WNDPROC PluginWindowProc; // Read below. Can be NULL; default will be used.
+ void * PluginData; // Read below. Can be NULL.
+} POPUPDATA, * LPPOPUPDATA;
+
+// Extended popup data
+typedef struct
+{
+ HANDLE lchContact;
+ HICON lchIcon;
+ union
+ {
+ char lptzContactName[MAX_CONTACTNAME];
+ char lpzContactName[MAX_CONTACTNAME];
+ };
+ union
+ {
+ char lptzText[MAX_SECONDLINE];
+ char lpzText[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.
+} POPUPDATAEX, *LPPOPUPDATAEX;
+
+// Unicode version of POPUPDATAEX
+typedef struct
+{
+ HANDLE lchContact;
+ HICON lchIcon;
+ union
+ {
+ WCHAR lptzContactName[MAX_CONTACTNAME];
+ WCHAR lpwzContactName[MAX_CONTACTNAME];
+ };
+ union
+ {
+ WCHAR lptzText[MAX_CONTACTNAME];
+ WCHAR lpwzText[MAX_CONTACTNAME];
+ };
+ COLORREF colorBack;
+ COLORREF colorText;
+ WNDPROC PluginWindowProc;
+ void * PluginData;
+ int iSeconds;
+ char cZero[16];
+} POPUPDATAW, *LPPOPUPDATAW;
+
+#if defined(_UNICODE) || defined(UNICODE)
+ typedef POPUPDATAW POPUPDATAT;
+ typedef LPPOPUPDATAW LPPOPUPDATAT;
+#else
+ typedef POPUPDATAEX POPUPDATAT;
+ typedef LPPOPUPDATAEX LPPOPUPDATAT;
+#endif
+
+/* PopUp/AddPopup
+Creates, adds and shows a popup, given a (valid) POPUPDATA structure pointer.
+
+wParam = (WPARAM)(*POPUPDATA)PopUpDataAddress
+lParam = 0
+
+Returns: > 0 on success, 0 if creation went bad, -1 if the PopUpData contained unacceptable values.
+NOTE: it returns -1 if the PopUpData was not valid, if there were already too many popups, if the module was disabled.
+Otherwise, it can return anything else...
+
+Popup Plus 2.0.4.0+
+You may pass additional creation flags via lParam:
+ APF_RETURN_HWND ....... function returns handle to newly created popup window (however this calls are a bit slower)
+ APF_CUSTOM_POPUP ...... new popup is created in hidden state and doesn't obey to popup queue rules.
+ you may control it via UM_* messages and custom window procedure
+*/
+#define APF_RETURN_HWND 0x1
+#define APF_CUSTOM_POPUP 0x2
+
+#define MS_POPUP_ADDPOPUP "PopUp/AddPopUp"
+static int __inline PUAddPopUp(POPUPDATA* ppdp) {
+ return CallService(MS_POPUP_ADDPOPUP, (WPARAM)ppdp,0);
+}
+
+#define MS_POPUP_ADDPOPUPEX "PopUp/AddPopUpEx"
+static int __inline PUAddPopUpEx(POPUPDATAEX* ppdp) {
+ return CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)ppdp,0);
+}
+
+#define MS_POPUP_ADDPOPUPW "PopUp/AddPopUpW"
+static int __inline PUAddPopUpW(POPUPDATAW* ppdp) {
+ return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)ppdp,0);
+}
+
+#if defined(_UNICODE) || defined(UNICODE)
+ #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPW
+ #define PUAddPopUpT PUAddPopUpW
+#else
+ #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPEX
+ #define PUAddPopUpT PUAddPopUpEx
+#endif
+
+
+/* PopUp/GetContact
+Returns the handle to the contact associated to the specified PopUpWindow.
+
+wParam = (WPARAM)(HWND)hPopUpWindow
+lParam = 0;
+
+Returns: the HANDLE of the contact. Can return NULL, meaning it's the main contact. -1 means failure.
+*/
+#define MS_POPUP_GETCONTACT "PopUp/GetContact"
+static HANDLE __inline PUGetContact(HWND hPopUpWindow) {
+ return (HANDLE)CallService(MS_POPUP_GETCONTACT, (WPARAM)hPopUpWindow,0);
+}
+
+/* PopUp/GetPluginData
+Returns custom plugin date associated with popup
+
+wParam = (WPARAM)(HWND)hPopUpWindow
+lParam = (LPARAM)(PLUGINDATA*)PluginDataAddress;
+
+Returns: the address of the PLUGINDATA structure. Can return NULL, meaning nothing was given. -1 means failure.
+
+IMPORTANT NOTE: it doesn't seem to work if you do:
+CallService(..., (LPARAM)aPointerToAStruct);
+and then use that struct.
+Do this, instead:
+aPointerToStruct = CallService(..., (LPARAM)aPointerToAStruct);
+and it will work. Just look at the example I've written above (PopUpDlgProc).
+
+*/
+#define MS_POPUP_GETPLUGINDATA "PopUp/GetPluginData"
+static void __inline * PUGetPluginData(HWND hPopUpWindow) {
+ long * uselessPointer = NULL;
+ return (void*)CallService(MS_POPUP_GETPLUGINDATA,(WPARAM)hPopUpWindow,(LPARAM)uselessPointer);
+}
+
+/* PopUp/IsSecondLineShown
+Checks if second line is enable
+
+wParam = 0
+lParam = 0
+
+Returns: 0 if the user has chosen not to have the second line, 1 if he choose to have the second line.
+*/
+#define MS_POPUP_ISSECONDLINESHOWN "PopUp/IsSecondLineShown"
+static BOOL __inline PUIsSecondLineShown() {
+ return (BOOL)CallService(MS_POPUP_ISSECONDLINESHOWN,0,0);
+}
+
+/* PopUp/Query
+
+Requests an action or an answer from PopUp module.
+
+wParam = (WPARAM)wpQuery
+
+returns 0 on success, -1 on error, 1 on stupid calls ;-)
+*/
+
+#define PUQS_ENABLEPOPUPS 1 // returns 0 if state was changed, 1 if state wasn't changed
+#define PUQS_DISABLEPOPUPS 2 // " "
+#define PUQS_GETSTATUS 3 //Returns 1 (TRUE) if popups are enabled, 0 (FALSE) if popups are disabled.
+
+#define MS_POPUP_QUERY "PopUp/Query"
+
+/* UM_FREEPLUGINDATA
+Process this message if you have allocated your own memory. (i.e.: POPUPDATA.PluginData != NULL)
+
+wParam = 0
+lParam = 0
+*/
+#define UM_FREEPLUGINDATA (WM_USER + 0x0200)
+
+/* UM_DESTROYPOPUP
+Send this message when you want to destroy the popup, or use the function below.
+
+wParam = 0
+lParam = 0
+*/
+#define UM_DESTROYPOPUP (WM_USER + 0x0201)
+static int __inline PUDeletePopUp(HWND hWndPopUp) {
+ return (int)SendMessage(hWndPopUp, UM_DESTROYPOPUP,0,0);
+}
+
+/* UM_INITPOPUP
+This message is sent to the PopUp when its creation has been finished, so POPUPDATA (and thus your PluginData) is reachable.
+Catch it if you needed to catch WM_CREATE or WM_INITDIALOG, which you'll never ever get in your entire popup-life.
+Return value: if you process this message, return 0. If you don't process it, return 0. Do whatever you like ;-)
+
+wParam = (WPARAM)(HWND)hPopUpWindow (this is useless, you get message inside your popup window)
+lParam = 0
+*/
+#define UM_INITPOPUP (WM_USER + 0x0202)
+
+/* PopUp/Changetext
+Changes the text displayed in the second line of the popup.
+
+wParam = (WPARAM)(HWND)hPopUpWindow
+lParam = (LPARAM)(char*)lpzNewText
+
+returns: > 0 for success, -1 for failure, 0 if the failure is due to second line not being shown. (but you could call
+PUIsSecondLineShown() before changing the text...)
+*/
+#define MS_POPUP_CHANGETEXT "PopUp/Changetext"
+static int __inline PUChangeText(HWND hWndPopUp, LPCTSTR lpzNewText) {
+ return (int)CallService(MS_POPUP_CHANGETEXT, (WPARAM)hWndPopUp, (LPARAM)lpzNewText);
+}
+
+#define MS_POPUP_CHANGETEXTW "PopUp/ChangetextW"
+static int __inline PUChangeTextW(HWND hWndPopUp, LPCWSTR lpwzNewText) {
+ return (int)CallService(MS_POPUP_CHANGETEXTW, (WPARAM)hWndPopUp, (LPARAM)lpwzNewText);
+}
+
+#if defined(_UNICODE) || defined(UNICODE)
+ #define MS_POPUP_CHANGETEXTT MS_POPUP_CHANGETEXTW
+ #define PUChangeTextT PUChangeTextW
+#else
+ #define MS_POPUP_CHANGETEXTT MS_POPUP_CHANGETEXT
+ #define PUChangeTextT PUChangeText
+#endif
+
+/* PopUp/Change
+Changes the entire popup
+
+wParam = (WPARAM)(HWND)hPopUpWindow
+lParam = (LPARAM)(POPUPDATAEX*)newData
+*/
+#define MS_POPUP_CHANGE "PopUp/Change"
+static int __inline PUChange(HWND hWndPopUp, POPUPDATAEX *newData) {
+ return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData);
+}
+
+#define MS_POPUP_CHANGEW "PopUp/ChangeW"
+static int __inline PUChangeW(HWND hWndPopUp, POPUPDATAW *newData) {
+ return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData);
+}
+
+#if defined(_UNICODE) || defined(UNICODE)
+ #define MS_POPUP_CHANGET MS_POPUP_CHANGEW
+ #define PUChangeT PUChangeW
+#else
+ #define MS_POPUP_CHANGET MS_POPUP_CHANGE
+ #define PUChangeT PUChange
+#endif
+
+/* UM_CHANGEPOPUP
+This message is triggered by Change/ChangeText services. You also may post it directly :)
+
+wParam = Modification type
+lParam = value of type defined by wParam
+*/
+
+#define CPT_TEXT 1 // lParam = (char *)text
+#define CPT_TEXTW 2 // lParam = (WCHAR *)text
+#define CPT_TITLE 3 // lParam = (char *)title
+#define CPT_TITLEW 4 // lParam = (WCHAR *)title
+#define CPT_DATA 5 // lParam = (POPUPDATA *)data
+#define CPT_DATAEX 6 // lParam = (POPUPDATAEX *)data
+#define CPT_DATAW 7 // lParam = (POPUPDATAW *)data
+
+#define UM_CHANGEPOPUP (WM_USER + 0x0203)
+
+#if defined(_UNICODE) || defined(UNICODE)
+ #define CPT_TEXTT CPT_TEXTW
+ #define CPT_TITLET CPT_TITLEW
+ #define CPT_DATAT CPT_DATAW
+#else
+ #define CPT_TEXTT CPT_TEXT
+ #define CPT_TITLET CPT_TITLE
+ #define CPT_DATAT CPT_DATA
+#endif
+
+/* PopUp/ShowMessage
+This is mainly for developers.
+Shows a warning message in a PopUp. It's useful if you need a "MessageBox" like function, but you don't want a modal
+window (which will interfere with a DialogProcedure. MessageBox steals focus and control, this one not.
+
+wParam = (char *)lpzMessage
+lParam = 0;
+
+Returns: 0 if the popup was shown, -1 in case of failure.
+*/
+#define SM_WARNING 0x01 //Triangle icon.
+#define SM_NOTIFY 0x02 //Exclamation mark icon.
+#define MS_POPUP_SHOWMESSAGE "PopUp/ShowMessage"
+
+static int __inline PUShowMessage(char *lpzText, BYTE kind) {
+ return (int)CallService(MS_POPUP_SHOWMESSAGE, (WPARAM)lpzText,(LPARAM)kind);
+}
+
+#endif // __m_popup_h__
diff --git a/m_spamfilter.h b/m_spamfilter.h
index a8b48db..d27005e 100644
--- a/m_spamfilter.h
+++ b/m_spamfilter.h
@@ -1,826 +1,826 @@
-/*
-
-"Spam Filter"-Plugin for
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef M_SPAMFILTER_H__
-#define M_SPAMFILTER_H__ 1
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-
-// Spam Filter Version: 2.5.2.3
-// See "spamcheck.c" out of the source code for an example on how to use the spam checking services.
-
-// The functionality and the API of Spam Filter is quite complex
-// and not easy to describe or explain.
-// If you have any question or extension whishes please send me an e-mail:
-// hrathh at users.sourceforge.net
-
-// Notes:
-// * All services are fully thread-safe, you can call everything from any thread
-// (If there are problems with it it is a bug :-) )
-// * Unicode parameters can also be passed to the ANSI version of the plugin
-// and the other way round. The strings get converted as they are needed
-// using automatic two-way translation.
-// Unicode support was added in v2.5.0.0
-
-
-// -------------------------------------------
-// -- Getting handles ------------------------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_GETHANDLE "SpamFilter/GetHandle"
-
-// Description:
-// -------------
-// Gets a specified icon/window handle.
-
-// Parameters:
-// -------------
-// wParam = (UINT)uHandleType (see below)
-// lParam = 0
-
-// Possible values for wParam:
-#define SFHT_HWND_PLUGIN_OPTIONS 2 // HWND of the "Spam Filter" options dialog (if it is loaded; else NULL)
-#define SFHT_HICON_SPAM 3 // HICON of the spam icon (small): The returned HICON must be DestroyIcon()ed.
-
-// Added in v2.0.2.0:
-#define SFHT_HICON_SPAM_LARGE 4 // HICON of the spam icon (large): The returned HICON must be DestroyIcon()ed.
-#define SFHT_HICON_SPAM_LAYER 5 // HICON of the spam layer icon (small): The returned HICON must be DestroyIcon()ed.
-
-// Added in v2.1.0.0:
-#define SFHT_HWND_ADVERTISMENT_FILTER 6 // HWND of the "Advertisment Filter" settings dialog (if it is opened; else NULL)
-#define SFHT_HWND_ROBOT_FILTER 7 // HWND of the "Robot Filter" settings dialog (if it is opened; else NULL)
-#define SFHT_HWND_DISLIKEDMESSAGES_FILTER 8 // HWND of the "Disliked Messages Filter" settings dialog (if it is opened; else NULL)
-
-// Added in v2.5.0.0:
-#define SFHT_HWND_SPAMDEFINITIONS_INFO 9 // HWND of the "Spam Definitions" info dialog (if it is opened; else NULL)
-#define SFHT_HWND_SPAMMERS_INFO 10 // HWND of the Spammers info dialog (if it is opened; else NULL)
-
-#define SFHT_BOOL_IS_UNICODE 0 // No handle, returns TRUE if Spam Filter is installed as Unicode version, FALSE otherwise
- // (You probably never need to call this since Spam Filter performs automatic two-way translation
- // when a service is called)
-
-
-// Note: Icons are taken directly from resources, they are not skinned by user
-
-// Return Values:
-// --------------
-// Returns the specified handle value: HMODULE, HWND, ICON
-//
-// Note:
-// If a handle is not available (or if it was removed) the function will
-// return NULL.
-// When you are using this service you need to check always for the
-// NULL return value.
-
-
-
-// -------------------------------------------
-// -- Activating/Deactivating the filters ----
-// -------------------------------------------
-
-#define MS_SPAMFILTER_CHANGEFILTERACTIVATION "SpamFilter/ChangeFilterActivation"
-
-// Description:
-// -------------
-// Provides the possibility to enable or disable the spam filters.
-// Also updates the checkboxes in the spam filter options if the option dialog is opened.
-
-// Parameters:
-// -------------
-// wParam = (UINT)uFilterType (For possible values see below)
-// lParam = (BOOL)bNewState (new activation state of filter)
-
-// Possible filter type values (dwFilterType):
-#define SFT_ADVERTISMENT_FILTER 1
-#define SFT_DISLIKEDMESSAGES_FILTER 2
-#define SFT_ROBOT_FILTER 3
-
-
-// Return Values:
-// --------------
-// Returns 0 on success, nonzero on error.
-
-
-// -------------------------------------------
-// -- Showing configure dialogs --------------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_SHOWFILTERDIALOG "SpamFilter/ShowFilterDialog"
-
-// Description:
-// -------------
-// Shows the configure dialog of the specified filter.
-
-// Parameters:
-// -------------
-// wParam = (HWND)hwndParent (Can be NULL)
-// lParam = (UINT)uFilterType (For possible values see above, SFT_*)
-// -> since 2.0.2.0: If this is zero then the options dialog will be opened pointing to the Spam Filter options.
-// Note:
-// If hwndParent is not NULL the function will not return
-// until the configure dialog is closed.
-
-// Since 2.0.2.0:
-#define SFTEX_OPTIONS_PAGE 0
-
-// Since 2.5.0.0:
-// Combine the following flag with the lParam/uFilterType parameter
-// to show the corresponding Spam Definitions info dialog instead
-// of the settings dialog:
-#define SFTEXF_SPAMDEFINITIONS_INFO 0x2000
-// Note: SFTEXF_SPAMDEFINITIONS_INFO can't be combined with SFT_ROBOT_FILTER
-
-// Combine the following flag with the lParam/uFilterType of 0 parameter
-// to show the Spammers dialog instead of the settings dialog:
-#define SFTEXF_SPAMMERS_INFO 0x4000
-// Note: SFTEXF_SPAMMERS_INFO can't be combined with SFT_*
-
-
-// Return Values:
-// --------------
-// Returns 0 on success, nonzero on error.
-
-// Since v2.1.0.0:
-// If the specified settings window is already opened it will be
-// brought to front (reactivated) instead (returns success though).
-// This might be changed however in the future.
-
-// Changed behaviour since v2.1.0.0:
-// If hwndParent was not set then the function returned the handle to the new window.
-// Now the function returns 0 to indicate success instead.
-
-
-// -------------------------------------------
-// -- Adding message types -------------------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_REGISTERMESSAGETYPE "SpamFilter/MessageTypes/Register"
-
-// Description:
-// -------------
-// Adds a new message type which can be checked for spam.
-// Associated event: ME_SPAMFILTER_PREREGISTERMESSAGETYPE
-
-// Parameters:
-// -------------
-// wParam = 0
-// lParam = (MESSAGETYPEDESC*)mtd (see below)
-
-// Return Values:
-// --------------
-// Returns 0 on success, nonzero on error.
-
-
-// Already registered message types are:
-// (With pszSection set to the installed network protocol names, e.g. "ICQ")
-#define SFMT_AUTHREQUEST "Auth"
-#define SFMT_ADDED "Added" // since v2.1.0.0
-#define SFMT_MESSAGE "Msg"
-#define SFMT_URL "URL"
-#define SFMT_FILE "File"
-#define SFMT_CONTACTS "Contacts"
-
-// MESSAGETYPEDESC structure:
-typedef struct {
- int cbSize; // Set to sizeof(MESSAGETYPEDESC), in bytes
- char* pszSection; // Section of message name for database e.g. protocol name (Can not be NULL)
- // -> should be short, no-spaces, english and untranslated
- union {
- char* pszSectionDescription; // Readable name of section e.g. protocol name (can be NULL)
- WCHAR* ptszSectionDescription; // Ignored if section existed previously
- WCHAR* pwszSectionDescription;
- };
-
- HICON hSectionIcon; // Icon to show for section e.g. protocol icon (can be NULL)
- // -> Can be destroyed after service returns
- // Ignored if section existed previously
- char* pszName; // Name to refer to message type when spam checking and in db (Can not be NULL)
- // -> should be short, no-spaces, english and untranslated
-
- union {
- char* pszDescription; // Description for options dialog (can be NULL)
- WCHAR* ptszDescription;
- WCHAR* pwszDescription;
- };
-
- HICON hIcon; // EITHER: icon handle representing the message type OR: one of mirandas skin constants with a negative sign, e.g (HICON)-SKINICON_EVENT_MESSAGE, same as for LoadSkinnedIcon() -> can be NULL and can also be a normal icon handle (HICON)
- // -> Can be destroyed after service returns
- DWORD dwFlags; // Flags for the message type (for possible flags see below)
-
- // Added in v2.5.0.0:
- int iSectionPosition; // Approx position number for the section in the options list, lower numbers are nearer to the top (Can be 0 to be sorted alphabetically)
- // Ignored if section existed previously (or if pszSection is NULL)
- int iPosition; // Approx position number for the item in the options list, lower numbers are nearer to the top (Can be 0 to be sorted alphabetically)
-} MESSAGETYPEDESC;
-
-
-// Possible MESSAGETYPEDESC flags:
-#define MTDF_DEFAULTDISABLED 0x00000001 // Is disabled by default
-#define MTDF_HIDDEN 0x00000002 // Does not get shown on the options page
-
-// Since v2.5.0.0
-#define MTDF_UNICODE 0x00000004 // pszSectionDescription and pszDescription are Unicode strings
-
-
-// MESSAGETYPEDESC struct was enhanced in v2.5.0.0:
-#define MESSAGETYPEDESC_V2000_SIZE (((int)((LPBYTE)(&((MESSAGETYPEDESC*)0)->dwFlags) - ((LPBYTE)((MESSAGETYPEDESC*)0)))) + sizeof(((MESSAGETYPEDESC*)0)->dwFlags))
-
-
-#ifndef SPAMFILTER_NOHELPER
-static int __inline SFRegisterMessageType(const char* section, const WCHAR* sectionDesc, HICON sectionIcon, const char* name, const WCHAR* desc, HICON icon, int pos, DWORD flags)
-{
- MESSAGETYPEDESC mtd;
- mtd.cbSize = sizeof(MESSAGETYPEDESC);
- mtd.dwFlags = flags|MTDF_UNICODE;
- mtd.pszSection = (char*)section;
- mtd.ptszSectionDescription = (WCHAR*)sectionDesc;
- mtd.hSectionIcon = sectionIcon;
- mtd.iSectionPosition = 0; // not really needed
- mtd.pszName = (char*)name;
- mtd.ptszDescription = (WCHAR*)desc;
- mtd.hIcon = icon;
- mtd.iPosition = pos;
- return CallService(MS_SPAMFILTER_REGISTERMESSAGETYPE, 0, (LPARAM)&mtd);
-}
-#endif
-
-// -------------------------------------------
-// -- Modify new added message type (Event) --
-// -------------------------------------------
-
-#define ME_SPAMFILTER_PREREGISTERMESSAGETYPE "SpamFilter/MessageTypes/PreRegister"
-
-// Description:
-// -------------
-// Gets fired before a new message type is added.
-//
-// This is meant for asking other plugins if the specified default data is ok.
-// Other plugins (especially protocols) can disable a message type if either sending spam
-// is not possible for those protocols or if spam checking would cause unwanted side-effects.
-
-// Note: Works as it does now since v2.1.1.0
-
-// Warning: Most elements of the MESSAGETYPEDESC structure can also be NULL.
-// However, the structure was checked for errors before this events gets called.
-
-// Parameters:
-// -----------------
-// wParam = 0 (same wParam as used for MS_SPAMFILTER_REGISTERMESSAGETYPE)
-// lParam = (MESSAGETYPEDESC*)mtd (see above, contents can be modified)
-
-// Return Values:
-// -----------------
-// Returning 0 on this event will accept the message type to be added.
-// Returning 1 will prevent the the message type to be added.
-
-
-// -------------------------------------------
-// -- Uninstalling a message type ------------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_REMOVEMESSAGETYPE "SpamFilter/MessageTypes/Remove"
-
-// Description:
-// -------------
-// Uninstalls a specifed message type. It removes the database setting related to the given message type.
-// Should only be used for uninstalling purposes (e.g in uninstall function of PluginUninstaller)
-
-// Parameters:
-// -------------
-// wParam = (char*)pszMsgTypeName (Message type name; You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before)
-// lParam = (char*)pszMsgTypeSection (The section of the message type string; You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before)
-
-// Return Values:
-// --------------
-// Returns 0 on success, nonzero on error.
-
-
-// -------------------------------------------
-// -- Message type activation ----------------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_ISMESSAGETYPEACTIVATED "SpamFilter/MessageTypes/IsActivated"
-
-// Description:
-// -------------
-// Returns if a specified message type is activated or not.
-
-// Parameters:
-// -------------
-// wParam = (char*)pszMsgTypeName (Message type name; You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before)
-// lParam = (char*)pszMsgTypeSection (The section of the message type string; You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before)
-
-// Return Values:
-// --------------
-// Returns TRUE if the message type is activated and FALSE otherwise.
-
-
-// -------------------------------------------
-// -- Reset Auto-ignore counters -------------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_RESETAUTOIGNORE "SpamFilter/AutoIgnore/Reset"
-
-// Description:
-// -------------
-// Resets the list in which the total number of spam sent by
-// each user is kept.
-// The list is necessary to determine when a particular user reached the
-// allowed spam messages limit.
-
-// Parameters:
-// -------------
-// wParam = (BOOL)bOnlyCount (if TRUE the service will only return the user count without doing reset)
-// lParam = 0
-
-// Return Values:
-// --------------
-// Returns 0 on success, nonzero on error.
-
-
-// -----------------------------------------
-// -- Spam Checking ------------------------
-// -----------------------------------------
-
-#define MS_SPAMFILTER_ADVERTISMENTCHECK "SpamFilter/AdvertismentCheck"
-#define MS_SPAMFILTER_DISLIKEDMESSAGESCHECK "SpamFilter/DislikedMessagesCheck"
-#define MS_SPAMFILTER_ROBOTCHECK "SpamFilter/RobotCheck"
-
-// Description:
-// -------------
-// These services provide the possibility to check a specified text for contained spam.
-// The function checks for everything that is activated in the plugin's options.
-
-// Note: These functions work as they do now since v2.1.0.0
-
-// Parameters:
-// -------------
-// wParam = (SPAMCHECKDATA*)scd
-// lParam = 0
-
-// SPAMCHECKDATA structure:
-typedef struct {
- int cbSize; // Set to sizeof(SPAMCHECKDATA)
-
- char* pszMsgTypeSection; // The section of the message type string: You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before
- char* pszMsgTypeName; // Description of the message: You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before
-
- // Pointer to the text of a message which is checked for spam. Can not be NULL.
- // (To use Unicode, you need to set the flag SCDF_UNICODE)
- union {
- char* pszMsgText; // ANSI
- WCHAR* ptszMsgText; // Unicode or ANSI
- WCHAR* pwszMsgText; // Unicode
- };
-
- DWORD dwFlags; // Flags for the spam checking. (For more details see below.)
-
- union {
- HANDLE hContact; // Handle to the sending contact (use pszUserName instead if no hContact is available)
- char* pszUserName; // Name of the user, e.g. nick (set SCDF_NO_CONTACT in the flags to use this parameter)
- WCHAR* ptszUserName; // -"- (Unicode or ANSI)
- WCHAR* pwszUserName; // -"- (Unicode)
- // -> UserName should be as unique as possible (To use Unicode you need to specify SCDF_UNICODE)
- };
-} SPAMCHECKDATA;
-
-
-// Possible flags in the SPAMCHECKDATA structure:
-#define SCDF_NO_NOTIFY 0x00000001 // Don't show a popup, play sound or log to file if the message is spam.
-#define SCDF_NO_CANCEL 0x00000002 // Do check even if user pressed control key to avoid the spam check manually
-#define SCDF_NO_AUTOIGNORE 0x00000004 // Do not use the AutoIgnore feature for this check
-
-#define SCDF_NO_CONTACT 0x00000008 // Use pszUserName instead of hContact of union
-
-// Since v2.5.0.0:
-#define SCDF_UNICODE 0x00000010 // Specify this flag if associated message text and/or user name is Unicode
-
-
-// Return Values:
-// --------------
-// Possible return flags:
-#define SFF_MARKREAD 0x00000010 // Flag
-#define SFF_DELETE 0x00000020 // Flag
-#define SFF_IGNORE 0x00000040 // Flag
-#define SFF_SENDMSG_NOTIFY 0x00000100 // Flag, Only MS_SPAMFILTER_DISLIKEDMESSAGESCHECK
-#define SFF_SENDMSG_INSTRUCTION 0x00000200 // Flag, Only MS_SPAMFILTER_ROBOTCHECK
-#define SFF_SENDMSG_CONFIRMATION 0x00000400 // Flag, Only MS_SPAMFILTER_ROBOTCHECK
-#define SFF_TESTPASSED 0x00000080 // Flag, Only MS_SPAMFILTER_ROBOTCHECK
-#define SFF_ISSPAM 0x00000002 // Flag
-#define SFF_ISNORMAL 0x00000001 // Flag
-
-// Since 2.5.2.0:
-#define SFF_HIDE 0x00001000 // Flag, Only MS_SPAMFILTER_ROBOTCHECK
-
-
-// -------------------------------------------
-// -- Getting additional Check Info ----------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_GETSPAMCHECKINFO "SpamFilter/GetSpamCheckInfo"
-
-// Description:
-// -------------
-// Gets data needed for the processing of spam messages.
-
-// Parameters:
-// -------------
-// wParam = (UINT)uDataType (For possible values see below)
-// lParam = depends on wParam (see below)
-
-// Possible values for lParam:
-
-// TRUE/FALSE: if the specified filter is enabled
-#define SFSCI_ACTIVATION_FILTER 1 // lParam = uFilterType (For possible values see above)
-
-// Strings: Get the message texts specified by the user
-// ANSI
-#define SFSCI_MSGTEXT_NOTIFYA 2 // lParam = (SPAMCHECKDATA*)scd, scd->hContact (or scd->pszUserName) and scd->pszMsgText (and scd->cbSize) should be filled in.
-#define SFSCI_MSGTEXT_INSTRUCTIONA 3 // lParam: see SFSCI_MSGTEXT_NOTIFYA
-#define SFSCI_MSGTEXT_CONFIRMATIONA 4 // lParam: see SFSCI_MSGTEXT_NOTIFYA
-
-// Unicode (since v2.5.0.0)
-#define SFSCI_MSGTEXT_NOTIFYW 6 // lParam = (SPAMCHECKDATA*)scd, scd->hContact (or scd->pwszUserName) and scd->pwszMsgText (and scd->cbSize) should be filled in.
-#define SFSCI_MSGTEXT_INSTRUCTIONW 7 // lParam: see SFSCI_MSGTEXT_NOTIFYW
-#define SFSCI_MSGTEXT_CONFIRMATIONW 8 // lParam: see SFSCI_MSGTEXT_NOTIFYW
-
-// ANSI/Unicode
-#if defined(_UNICODE) || defined(UNICODE)
- #define SFSCI_MSGTEXT_NOTIFY SFSCI_MSGTEXT_NOTIFYW
- #define SFSCI_MSGTEXT_INSTRUCTION SFSCI_MSGTEXT_INSTRUCTIONW
- #define SFSCI_MSGTEXT_CONFIRMATION SFSCI_MSGTEXT_CONFIRMATIONW
-#else
- #define SFSCI_MSGTEXT_NOTIFY SFSCI_MSGTEXT_NOTIFYA
- #define SFSCI_MSGTEXT_INSTRUCTION SFSCI_MSGTEXT_INSTRUCTIONA
- #define SFSCI_MSGTEXT_CONFIRMATION SFSCI_MSGTEXT_CONFIRMATIONA
-#endif
-
-// TRUE/FALSE: if the above message text should be added to history.
-#define SFSCI_ADD_TO_HISTORY 5 // lParam = SFSCI_MSGTEXT_NOTIFY(A/W), SFSCI_MSGTEXT_INSTRUCTION(A/W) or SFSCI_MSGTEXT_CONFIRMATION(A/W)
-
-
-// Return Values:
-// --------------
-// SFSCI_ACTIVATION_FILTER -> (BOOL)TRUE/FALSE
-// SFSCI_DELAY_TIME_REPLY -> (BOOL)TRUE/FALSE
-
-// SFSCI_MSGTEXT_NOTIFYA -> (char*) free with miranda_sys_free() of "m_system.h", (all %vars% in the text are already resolved)
-// SFSCI_MSGTEXT_INSTRUCTIONA -> see SFSCI_MSGTEXT_NOTIFYA
-// SFSCI_MSGTEXT_CONFIRMATIONA -> see SFSCI_MSGTEXT_NOTIFYA
-
-// SFSCI_MSGTEXT_NOTIFYW -> (WCHAR*) free with miranda_sys_free() of "m_system.h", (all %vars% in the text are already resolved)
-// SFSCI_MSGTEXT_INSTRUCTIONW -> see SFSCI_MSGTEXT_NOTIFYW
-// SFSCI_MSGTEXT_CONFIRMATIONW -> see SFSCI_MSGTEXT_NOTIFYW
-
-// SFSCI_ADD_TO_HISTORY -> (BOOL)TRUE/FALSE
-
-// returns NULL on error
-
-
-// -------------------------------------------
-// -- Confirm spam check (Event) -------------
-// -------------------------------------------
-
-#define ME_SPAMFILTER_OKTOSPAMCHECK "SpamFilter/OkToSpamCheck"
-
-// Description:
-// -------------
-// Gets fired before the spam check for a message starts.
-
-// Parameters:
-// -----------------
-// wParam = (SPAMCHECKDATA*)scd (Pointer to SPAMCHECKDATA struct)
-// lParam = (UINT)uFilterType (For possible values see above)
-
-// Return Values:
-// -----------------
-// Returning 0 on this event will accept spam checking for the message,
-// Returning 1 will prevent the spam check.
-
-
-// -------------------------------------------
-// -- Confirm spam detection (Event) ---------
-// -------------------------------------------
-
-#define ME_SPAMFILTER_OKTOSPAMDETECTION "SpamFilter/OkToSpamDetection"
-
-// Description:
-// -------------
-// Gets fired after a spam message is detected.
-
-// Parameters:
-// -----------------
-// wParam = (SPAMCHECKDATA*)scd (Pointer to SPAMCHECKDATA struct)
-// lParam = (UINT)uFilterType (For possible values see above)
-
-// Return Values:
-// -----------------
-// Returning 0 on this event will accept the detection
-// Returning 1 cause the message not to be seen as spam.
-
-// Note: If you only would like to get the final result hook
-// ME_SPAMFILTER_SPAMRECEIVED instead
-
-
-// -------------------------------------------
-// -- Spam message received (Event) ----------
-// -------------------------------------------
-
-#define ME_SPAMFILTER_SPAMRECEIVED "SpamFilter/SpamReceived"
-
-// Description:
-// -------------
-// Gets fired when a message is recognized as spam.
-
-// Parameters:
-// -----------------
-// wParam = (SPAMCHECKDATA*)scd (Pointer to SPAMCHECKDATA struct)
-// lParam = (UINT)uFilterType (For possible values see above)
-
-// Return Values:
-// -----------------
-// The return value should be 0.
-
-
-
-// -------------------------------------------
-// -- Spam Filter loaded ---------------------
-// -------------------------------------------
-
-#define ME_SPAMFILTER_MODULELOADED "SpamFilter/ModuleLoaded"
-
-// Description:
-// -------------
-// Gets fired when a all parts of the "Spam Filter" were loaded and available
-// to other plugins.
-// Past this event all functionality of the plugin is fully available.
-//
-// The event works quite similar as ME_SYSTEM_MODULESLOADED.
-// You should use ME_SYSTEM_MODULESLOADED in most cases instead. Please do so!
-//
-// (Service added in v2.0.1.0)
-
-// Parameters:
-// -----------------
-// wParam = 0
-// lParam = 0
-
-// Return Values:
-// -----------------
-// The return value should be 0.
-
-
-
-// -------------------------------------------
-// -- Helper: Duplicate SPAMCHECKDATA --------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_COPYSPAMCHECKDATA "SpamFilter/SpamCheckData/Copy"
-
-// Description:
-// -------------
-// Copys all contents of a SPAMCHECKDATA struct (especially strings) to another one
-// using Miranda's Memory Manager Interface (see m_system.h).
-// Use MS_SPAMFILTER_FREESPAMCHECKDATA to free the result when no longer needed.
-
-// Available since 2.5.2.0.
-
-// An entire copy of the SPAMCHECKDATA structure is made at pscd->cbSize.
-// All strings are duplicated.
-// The pscdTo->cbSize member is set to the current size of SPAMCHECKDATA
-// that SpamFilter uses.
-
-// Warning:
-// If you pass a structure that is bigger than the current sizeof(SPAMCHECKDATA)
-// then do not use pointers not contained in the current area because
-// they will not be duplicated (However, you could duplicate them by yourself).
-
-// Parameters:
-// -------------
-// wParam = (SPAMCHECKDATA*)pscdTo
-// lParam = (SPAMCHECKDATA*)pscdFrom
-
-// Return Values:
-// --------------
-// Returns 0 on success, nonzero on error.
-
-
-
-// -------------------------------------------
-// -- Helper: Free SPAMCHECKDATA -------------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_FREESPAMCHECKDATA "SpamFilter/SpamCheckData/Free"
-
-// Description:
-// -------------
-// Frees the memory allocated by MS_SPAMFILTER_COPYSPAMCHECKDATA.
-// using Miranda's Memory Manager Interface (see m_system.h).
-
-// Available since 2.5.2.0.
-
-// Parameters:
-// -------------
-// wParam = (SPAMCHECKDATA*)pscd
-// lParam = 0
-
-// Return Values:
-// --------------
-// Returns 0 on success, nonzero on failure.
-
-
-
-// -------------------------------------------
-// -- Showing error messages -----------------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_SHOWERROR "SpamFilter/ShowError"
-
-// Description:
-// -------------
-// Shows a Miranda try balloon tip, popup or message box
-// with the specified error message.
-
-// Parameters:
-// -------------
-// wParam = (UINT)uErrorType (For possible values see below)
-// lParam = 0
-
-// Possible values for wParam:
-#define SFSE_CRITICAL_ERROR 1 // Unspecified critical error occured related to the spam check.
- // Only use this for situations that may never ever occur.
- // Please do avoid this if possible.
-
-#define SFSE_SEND_FAILED 2 // Show this error when a sending of SFSCI_MSGTEXT_NOTIFY,
- // SFSCI_MSGTEXT_INSTRUCTION, SFSCI_MSGTEXT_CONFIRMATION or
- // SFSCI_MSGTEXT_NOTIFY failed (SFSCI_MSGTEXT_*)
-
-// Return Values:
-// --------------
-// Returns 0 on success, nonzero on error.
-
-
-
-// -------------------------------------------
-// -- Set contact as spammer (Contact) -------
-// -------------------------------------------
-
-#define MS_SPAMFILTER_CONTACT_SETASSPAMMER "SpamFilter/Contact/SetAsSpammer"
-
-// Description:
-// -------------
-// This service adds a specified user to the spammer list (fully ignored).
-
-// Associated event: ME_SPAMFILTER_CONTACT_SPAMMERSTATECHANGED
-
-// Note: works same as MS_SPAMFILTER_CONTACT_SHOWSETASSPAMMERDIALOG
-// but does not prompt the user.
-
-// Available since v2.5.0.0
-
-// Parameters:
-// -------------
-// wParam = (HANDLE)hContact (Handle to a contact in database. Can't be NULL.)
-// lParam = (DWORD)dwFlags (flags about what should be done, see below)
-
-// Available Flags:
-#define SCASF_NO_NOTIFY 0x00000001 // Prevents logging and playing of sounds
-#define SCASF_USE_ROBOT_SOUND 0x00000002 // play robot sound instead of advertisment sound (only if SCASF_NO_NOTIFY is not set)
-#define SCASF_NO_REMOVE_HISTORY 0x00000004 // history is marked read instead of fully removed
-#define SCASF_NO_DENY_AUTHREQUESTS 0x00000008 // do not deny pending auth requests
-
-// Return Values:
-// --------------
-// Returns 0 on success, nonzero on error.
-
-
-// -------------------------------------------
-// -- Show mark spammer dialog (Contact) -----
-// -------------------------------------------
-
-#define MS_SPAMFILTER_CONTACT_SHOWSETASSPAMMERDIALOG "SpamFilter/Contact/ShowSetAsSpammerDlg"
-
-// Description:
-// -------------
-// This service adds a specified user to the spammer list.
-// Before it shows a dialog to let the user confirm the action.
-// For use for example as action for a button on the message dialog.
-
-// Note: This service performs the same tasks as MS_SPAMFILTER_SETCONTACTASSPAMMER
-// to execute the action the user chooses.
-
-// Associated event: ME_SPAMFILTER_CONTACT_SPAMMERSTATECHANGED
-
-// Available since v2.5.0.0
-
-// Parameters:
-// -------------
-// wParam = (HANDLE)hContact (Handle to a contact in database. Can't be NULL.)
-// lParam = (HWND)hwndParent (Handle to the parent window. Can be NULL.)
-
-// Return Values:
-// --------------
-// Returns FALSE if user clicked cancel on the dialog.
-// TRUE if the contact was handled as spammer.
-
-
-// Deprecated in v2.5.0.0:
-// The service MS_SPAMFILTER_SETSPAMMANUALLY has been deprecated.
-// New plugins should use MS_SPAMFILTER_CONTACT_SETASSPAMMERDLG instead.
-#define MS_SPAMFILTER_SETSPAMMANUALLY "SpamFilter/SetSpamManually"
-
-
-// Return Values:
-// --------------
-// Returns 0 on success, nozero otherwise.
-
-
-// -------------------------------------------
-// -- Test if contact is spammer (Contact) ---
-// -------------------------------------------
-
-#define MS_SPAMFILTER_CONTACT_ISSPAMMER "SpamFilter/Contact/IsSpammer"
-
-// Description:
-// -------------
-// This service tests if a specified contact is on the spammer list (fully ignored).
-
-// Available since v2.5.0.0
-
-// Parameters:
-// -------------
-// wParam = (HANDLE)hContact (Handle to a contact in database. Can't be NULL.)
-// lParam = 0
-
-// Return Values:
-// --------------
-// Returns TRUE when the contact is on the spammer list, FALSE otherwise.
-
-
-// -------------------------------------------
-// -- Unmarks a contact as spammer (Contact) -
-// -------------------------------------------
-
-#define MS_SPAMFILTER_CONTACT_UNSETSPAMMER "SpamFilter/Contact/UnSetSpammer"
-
-// Description:
-// -------------
-// This service restores a spammer to be again a normal contact (unignored).
-
-// Associated event: ME_SPAMFILTER_CONTACT_SPAMMERSTATECHANGED
-
-// Available since v2.5.0.0
-
-// Parameters:
-// -------------
-// wParam = (HANDLE)hContact (Handle to a contact in database. Can't be NULL.)
-// lParam = 0
-
-// Return Values:
-// --------------
-// Returns 0 on success, nonzero on error.
-
-
-// -------------------------------------------
-// -- Spammer state changed (Event) ----------
-// -------------------------------------------
-
-#define ME_SPAMFILTER_CONTACT_SPAMMERSTATECHANGED "SpamFilter/Contact/SpammerStateChanged"
-
-// Description:
-// -------------
-// Gets fired when a a contact gets marked as spammer or unmarked.
-
-// Parameters:
-// -----------------
-// wParam = (HANDLE)hContact
-// lParam = (BOOL)bIsSpammer (new state)
-
-// Return Values:
-// -----------------
-// The return value should be 0.
-
-
+/*
+
+"Spam Filter"-Plugin for
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef M_SPAMFILTER_H__
+#define M_SPAMFILTER_H__ 1
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+
+// Spam Filter Version: 2.5.2.3
+// See "spamcheck.c" out of the source code for an example on how to use the spam checking services.
+
+// The functionality and the API of Spam Filter is quite complex
+// and not easy to describe or explain.
+// If you have any question or extension whishes please send me an e-mail:
+// hrathh at users.sourceforge.net
+
+// Notes:
+// * All services are fully thread-safe, you can call everything from any thread
+// (If there are problems with it it is a bug :-) )
+// * Unicode parameters can also be passed to the ANSI version of the plugin
+// and the other way round. The strings get converted as they are needed
+// using automatic two-way translation.
+// Unicode support was added in v2.5.0.0
+
+
+// -------------------------------------------
+// -- Getting handles ------------------------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_GETHANDLE "SpamFilter/GetHandle"
+
+// Description:
+// -------------
+// Gets a specified icon/window handle.
+
+// Parameters:
+// -------------
+// wParam = (UINT)uHandleType (see below)
+// lParam = 0
+
+// Possible values for wParam:
+#define SFHT_HWND_PLUGIN_OPTIONS 2 // HWND of the "Spam Filter" options dialog (if it is loaded; else NULL)
+#define SFHT_HICON_SPAM 3 // HICON of the spam icon (small): The returned HICON must be DestroyIcon()ed.
+
+// Added in v2.0.2.0:
+#define SFHT_HICON_SPAM_LARGE 4 // HICON of the spam icon (large): The returned HICON must be DestroyIcon()ed.
+#define SFHT_HICON_SPAM_LAYER 5 // HICON of the spam layer icon (small): The returned HICON must be DestroyIcon()ed.
+
+// Added in v2.1.0.0:
+#define SFHT_HWND_ADVERTISMENT_FILTER 6 // HWND of the "Advertisment Filter" settings dialog (if it is opened; else NULL)
+#define SFHT_HWND_ROBOT_FILTER 7 // HWND of the "Robot Filter" settings dialog (if it is opened; else NULL)
+#define SFHT_HWND_DISLIKEDMESSAGES_FILTER 8 // HWND of the "Disliked Messages Filter" settings dialog (if it is opened; else NULL)
+
+// Added in v2.5.0.0:
+#define SFHT_HWND_SPAMDEFINITIONS_INFO 9 // HWND of the "Spam Definitions" info dialog (if it is opened; else NULL)
+#define SFHT_HWND_SPAMMERS_INFO 10 // HWND of the Spammers info dialog (if it is opened; else NULL)
+
+#define SFHT_BOOL_IS_UNICODE 0 // No handle, returns TRUE if Spam Filter is installed as Unicode version, FALSE otherwise
+ // (You probably never need to call this since Spam Filter performs automatic two-way translation
+ // when a service is called)
+
+
+// Note: Icons are taken directly from resources, they are not skinned by user
+
+// Return Values:
+// --------------
+// Returns the specified handle value: HMODULE, HWND, ICON
+//
+// Note:
+// If a handle is not available (or if it was removed) the function will
+// return NULL.
+// When you are using this service you need to check always for the
+// NULL return value.
+
+
+
+// -------------------------------------------
+// -- Activating/Deactivating the filters ----
+// -------------------------------------------
+
+#define MS_SPAMFILTER_CHANGEFILTERACTIVATION "SpamFilter/ChangeFilterActivation"
+
+// Description:
+// -------------
+// Provides the possibility to enable or disable the spam filters.
+// Also updates the checkboxes in the spam filter options if the option dialog is opened.
+
+// Parameters:
+// -------------
+// wParam = (UINT)uFilterType (For possible values see below)
+// lParam = (BOOL)bNewState (new activation state of filter)
+
+// Possible filter type values (dwFilterType):
+#define SFT_ADVERTISMENT_FILTER 1
+#define SFT_DISLIKEDMESSAGES_FILTER 2
+#define SFT_ROBOT_FILTER 3
+
+
+// Return Values:
+// --------------
+// Returns 0 on success, nonzero on error.
+
+
+// -------------------------------------------
+// -- Showing configure dialogs --------------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_SHOWFILTERDIALOG "SpamFilter/ShowFilterDialog"
+
+// Description:
+// -------------
+// Shows the configure dialog of the specified filter.
+
+// Parameters:
+// -------------
+// wParam = (HWND)hwndParent (Can be NULL)
+// lParam = (UINT)uFilterType (For possible values see above, SFT_*)
+// -> since 2.0.2.0: If this is zero then the options dialog will be opened pointing to the Spam Filter options.
+// Note:
+// If hwndParent is not NULL the function will not return
+// until the configure dialog is closed.
+
+// Since 2.0.2.0:
+#define SFTEX_OPTIONS_PAGE 0
+
+// Since 2.5.0.0:
+// Combine the following flag with the lParam/uFilterType parameter
+// to show the corresponding Spam Definitions info dialog instead
+// of the settings dialog:
+#define SFTEXF_SPAMDEFINITIONS_INFO 0x2000
+// Note: SFTEXF_SPAMDEFINITIONS_INFO can't be combined with SFT_ROBOT_FILTER
+
+// Combine the following flag with the lParam/uFilterType of 0 parameter
+// to show the Spammers dialog instead of the settings dialog:
+#define SFTEXF_SPAMMERS_INFO 0x4000
+// Note: SFTEXF_SPAMMERS_INFO can't be combined with SFT_*
+
+
+// Return Values:
+// --------------
+// Returns 0 on success, nonzero on error.
+
+// Since v2.1.0.0:
+// If the specified settings window is already opened it will be
+// brought to front (reactivated) instead (returns success though).
+// This might be changed however in the future.
+
+// Changed behaviour since v2.1.0.0:
+// If hwndParent was not set then the function returned the handle to the new window.
+// Now the function returns 0 to indicate success instead.
+
+
+// -------------------------------------------
+// -- Adding message types -------------------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_REGISTERMESSAGETYPE "SpamFilter/MessageTypes/Register"
+
+// Description:
+// -------------
+// Adds a new message type which can be checked for spam.
+// Associated event: ME_SPAMFILTER_PREREGISTERMESSAGETYPE
+
+// Parameters:
+// -------------
+// wParam = 0
+// lParam = (MESSAGETYPEDESC*)mtd (see below)
+
+// Return Values:
+// --------------
+// Returns 0 on success, nonzero on error.
+
+
+// Already registered message types are:
+// (With pszSection set to the installed network protocol names, e.g. "ICQ")
+#define SFMT_AUTHREQUEST "Auth"
+#define SFMT_ADDED "Added" // since v2.1.0.0
+#define SFMT_MESSAGE "Msg"
+#define SFMT_URL "URL"
+#define SFMT_FILE "File"
+#define SFMT_CONTACTS "Contacts"
+
+// MESSAGETYPEDESC structure:
+typedef struct {
+ int cbSize; // Set to sizeof(MESSAGETYPEDESC), in bytes
+ char* pszSection; // Section of message name for database e.g. protocol name (Can not be NULL)
+ // -> should be short, no-spaces, english and untranslated
+ union {
+ char* pszSectionDescription; // Readable name of section e.g. protocol name (can be NULL)
+ WCHAR* ptszSectionDescription; // Ignored if section existed previously
+ WCHAR* pwszSectionDescription;
+ };
+
+ HICON hSectionIcon; // Icon to show for section e.g. protocol icon (can be NULL)
+ // -> Can be destroyed after service returns
+ // Ignored if section existed previously
+ char* pszName; // Name to refer to message type when spam checking and in db (Can not be NULL)
+ // -> should be short, no-spaces, english and untranslated
+
+ union {
+ char* pszDescription; // Description for options dialog (can be NULL)
+ WCHAR* ptszDescription;
+ WCHAR* pwszDescription;
+ };
+
+ HICON hIcon; // EITHER: icon handle representing the message type OR: one of mirandas skin constants with a negative sign, e.g (HICON)-SKINICON_EVENT_MESSAGE, same as for LoadSkinnedIcon() -> can be NULL and can also be a normal icon handle (HICON)
+ // -> Can be destroyed after service returns
+ DWORD dwFlags; // Flags for the message type (for possible flags see below)
+
+ // Added in v2.5.0.0:
+ int iSectionPosition; // Approx position number for the section in the options list, lower numbers are nearer to the top (Can be 0 to be sorted alphabetically)
+ // Ignored if section existed previously (or if pszSection is NULL)
+ int iPosition; // Approx position number for the item in the options list, lower numbers are nearer to the top (Can be 0 to be sorted alphabetically)
+} MESSAGETYPEDESC;
+
+
+// Possible MESSAGETYPEDESC flags:
+#define MTDF_DEFAULTDISABLED 0x00000001 // Is disabled by default
+#define MTDF_HIDDEN 0x00000002 // Does not get shown on the options page
+
+// Since v2.5.0.0
+#define MTDF_UNICODE 0x00000004 // pszSectionDescription and pszDescription are Unicode strings
+
+
+// MESSAGETYPEDESC struct was enhanced in v2.5.0.0:
+#define MESSAGETYPEDESC_V2000_SIZE (((int)((LPBYTE)(&((MESSAGETYPEDESC*)0)->dwFlags) - ((LPBYTE)((MESSAGETYPEDESC*)0)))) + sizeof(((MESSAGETYPEDESC*)0)->dwFlags))
+
+
+#ifndef SPAMFILTER_NOHELPER
+static int __inline SFRegisterMessageType(const char* section, const WCHAR* sectionDesc, HICON sectionIcon, const char* name, const WCHAR* desc, HICON icon, int pos, DWORD flags)
+{
+ MESSAGETYPEDESC mtd;
+ mtd.cbSize = sizeof(MESSAGETYPEDESC);
+ mtd.dwFlags = flags|MTDF_UNICODE;
+ mtd.pszSection = (char*)section;
+ mtd.ptszSectionDescription = (WCHAR*)sectionDesc;
+ mtd.hSectionIcon = sectionIcon;
+ mtd.iSectionPosition = 0; // not really needed
+ mtd.pszName = (char*)name;
+ mtd.ptszDescription = (WCHAR*)desc;
+ mtd.hIcon = icon;
+ mtd.iPosition = pos;
+ return CallService(MS_SPAMFILTER_REGISTERMESSAGETYPE, 0, (LPARAM)&mtd);
+}
+#endif
+
+// -------------------------------------------
+// -- Modify new added message type (Event) --
+// -------------------------------------------
+
+#define ME_SPAMFILTER_PREREGISTERMESSAGETYPE "SpamFilter/MessageTypes/PreRegister"
+
+// Description:
+// -------------
+// Gets fired before a new message type is added.
+//
+// This is meant for asking other plugins if the specified default data is ok.
+// Other plugins (especially protocols) can disable a message type if either sending spam
+// is not possible for those protocols or if spam checking would cause unwanted side-effects.
+
+// Note: Works as it does now since v2.1.1.0
+
+// Warning: Most elements of the MESSAGETYPEDESC structure can also be NULL.
+// However, the structure was checked for errors before this events gets called.
+
+// Parameters:
+// -----------------
+// wParam = 0 (same wParam as used for MS_SPAMFILTER_REGISTERMESSAGETYPE)
+// lParam = (MESSAGETYPEDESC*)mtd (see above, contents can be modified)
+
+// Return Values:
+// -----------------
+// Returning 0 on this event will accept the message type to be added.
+// Returning 1 will prevent the the message type to be added.
+
+
+// -------------------------------------------
+// -- Uninstalling a message type ------------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_REMOVEMESSAGETYPE "SpamFilter/MessageTypes/Remove"
+
+// Description:
+// -------------
+// Uninstalls a specifed message type. It removes the database setting related to the given message type.
+// Should only be used for uninstalling purposes (e.g in uninstall function of PluginUninstaller)
+
+// Parameters:
+// -------------
+// wParam = (char*)pszMsgTypeName (Message type name; You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before)
+// lParam = (char*)pszMsgTypeSection (The section of the message type string; You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before)
+
+// Return Values:
+// --------------
+// Returns 0 on success, nonzero on error.
+
+
+// -------------------------------------------
+// -- Message type activation ----------------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_ISMESSAGETYPEACTIVATED "SpamFilter/MessageTypes/IsActivated"
+
+// Description:
+// -------------
+// Returns if a specified message type is activated or not.
+
+// Parameters:
+// -------------
+// wParam = (char*)pszMsgTypeName (Message type name; You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before)
+// lParam = (char*)pszMsgTypeSection (The section of the message type string; You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before)
+
+// Return Values:
+// --------------
+// Returns TRUE if the message type is activated and FALSE otherwise.
+
+
+// -------------------------------------------
+// -- Reset Auto-ignore counters -------------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_RESETAUTOIGNORE "SpamFilter/AutoIgnore/Reset"
+
+// Description:
+// -------------
+// Resets the list in which the total number of spam sent by
+// each user is kept.
+// The list is necessary to determine when a particular user reached the
+// allowed spam messages limit.
+
+// Parameters:
+// -------------
+// wParam = (BOOL)bOnlyCount (if TRUE the service will only return the user count without doing reset)
+// lParam = 0
+
+// Return Values:
+// --------------
+// Returns 0 on success, nonzero on error.
+
+
+// -----------------------------------------
+// -- Spam Checking ------------------------
+// -----------------------------------------
+
+#define MS_SPAMFILTER_ADVERTISMENTCHECK "SpamFilter/AdvertismentCheck"
+#define MS_SPAMFILTER_DISLIKEDMESSAGESCHECK "SpamFilter/DislikedMessagesCheck"
+#define MS_SPAMFILTER_ROBOTCHECK "SpamFilter/RobotCheck"
+
+// Description:
+// -------------
+// These services provide the possibility to check a specified text for contained spam.
+// The function checks for everything that is activated in the plugin's options.
+
+// Note: These functions work as they do now since v2.1.0.0
+
+// Parameters:
+// -------------
+// wParam = (SPAMCHECKDATA*)scd
+// lParam = 0
+
+// SPAMCHECKDATA structure:
+typedef struct {
+ int cbSize; // Set to sizeof(SPAMCHECKDATA)
+
+ char* pszMsgTypeSection; // The section of the message type string: You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before
+ char* pszMsgTypeName; // Description of the message: You need to use MS_SPAMFILTER_REGISTERMESSAGETYPE before
+
+ // Pointer to the text of a message which is checked for spam. Can not be NULL.
+ // (To use Unicode, you need to set the flag SCDF_UNICODE)
+ union {
+ char* pszMsgText; // ANSI
+ WCHAR* ptszMsgText; // Unicode or ANSI
+ WCHAR* pwszMsgText; // Unicode
+ };
+
+ DWORD dwFlags; // Flags for the spam checking. (For more details see below.)
+
+ union {
+ HANDLE hContact; // Handle to the sending contact (use pszUserName instead if no hContact is available)
+ char* pszUserName; // Name of the user, e.g. nick (set SCDF_NO_CONTACT in the flags to use this parameter)
+ WCHAR* ptszUserName; // -"- (Unicode or ANSI)
+ WCHAR* pwszUserName; // -"- (Unicode)
+ // -> UserName should be as unique as possible (To use Unicode you need to specify SCDF_UNICODE)
+ };
+} SPAMCHECKDATA;
+
+
+// Possible flags in the SPAMCHECKDATA structure:
+#define SCDF_NO_NOTIFY 0x00000001 // Don't show a popup, play sound or log to file if the message is spam.
+#define SCDF_NO_CANCEL 0x00000002 // Do check even if user pressed control key to avoid the spam check manually
+#define SCDF_NO_AUTOIGNORE 0x00000004 // Do not use the AutoIgnore feature for this check
+
+#define SCDF_NO_CONTACT 0x00000008 // Use pszUserName instead of hContact of union
+
+// Since v2.5.0.0:
+#define SCDF_UNICODE 0x00000010 // Specify this flag if associated message text and/or user name is Unicode
+
+
+// Return Values:
+// --------------
+// Possible return flags:
+#define SFF_MARKREAD 0x00000010 // Flag
+#define SFF_DELETE 0x00000020 // Flag
+#define SFF_IGNORE 0x00000040 // Flag
+#define SFF_SENDMSG_NOTIFY 0x00000100 // Flag, Only MS_SPAMFILTER_DISLIKEDMESSAGESCHECK
+#define SFF_SENDMSG_INSTRUCTION 0x00000200 // Flag, Only MS_SPAMFILTER_ROBOTCHECK
+#define SFF_SENDMSG_CONFIRMATION 0x00000400 // Flag, Only MS_SPAMFILTER_ROBOTCHECK
+#define SFF_TESTPASSED 0x00000080 // Flag, Only MS_SPAMFILTER_ROBOTCHECK
+#define SFF_ISSPAM 0x00000002 // Flag
+#define SFF_ISNORMAL 0x00000001 // Flag
+
+// Since 2.5.2.0:
+#define SFF_HIDE 0x00001000 // Flag, Only MS_SPAMFILTER_ROBOTCHECK
+
+
+// -------------------------------------------
+// -- Getting additional Check Info ----------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_GETSPAMCHECKINFO "SpamFilter/GetSpamCheckInfo"
+
+// Description:
+// -------------
+// Gets data needed for the processing of spam messages.
+
+// Parameters:
+// -------------
+// wParam = (UINT)uDataType (For possible values see below)
+// lParam = depends on wParam (see below)
+
+// Possible values for lParam:
+
+// TRUE/FALSE: if the specified filter is enabled
+#define SFSCI_ACTIVATION_FILTER 1 // lParam = uFilterType (For possible values see above)
+
+// Strings: Get the message texts specified by the user
+// ANSI
+#define SFSCI_MSGTEXT_NOTIFYA 2 // lParam = (SPAMCHECKDATA*)scd, scd->hContact (or scd->pszUserName) and scd->pszMsgText (and scd->cbSize) should be filled in.
+#define SFSCI_MSGTEXT_INSTRUCTIONA 3 // lParam: see SFSCI_MSGTEXT_NOTIFYA
+#define SFSCI_MSGTEXT_CONFIRMATIONA 4 // lParam: see SFSCI_MSGTEXT_NOTIFYA
+
+// Unicode (since v2.5.0.0)
+#define SFSCI_MSGTEXT_NOTIFYW 6 // lParam = (SPAMCHECKDATA*)scd, scd->hContact (or scd->pwszUserName) and scd->pwszMsgText (and scd->cbSize) should be filled in.
+#define SFSCI_MSGTEXT_INSTRUCTIONW 7 // lParam: see SFSCI_MSGTEXT_NOTIFYW
+#define SFSCI_MSGTEXT_CONFIRMATIONW 8 // lParam: see SFSCI_MSGTEXT_NOTIFYW
+
+// ANSI/Unicode
+#if defined(_UNICODE) || defined(UNICODE)
+ #define SFSCI_MSGTEXT_NOTIFY SFSCI_MSGTEXT_NOTIFYW
+ #define SFSCI_MSGTEXT_INSTRUCTION SFSCI_MSGTEXT_INSTRUCTIONW
+ #define SFSCI_MSGTEXT_CONFIRMATION SFSCI_MSGTEXT_CONFIRMATIONW
+#else
+ #define SFSCI_MSGTEXT_NOTIFY SFSCI_MSGTEXT_NOTIFYA
+ #define SFSCI_MSGTEXT_INSTRUCTION SFSCI_MSGTEXT_INSTRUCTIONA
+ #define SFSCI_MSGTEXT_CONFIRMATION SFSCI_MSGTEXT_CONFIRMATIONA
+#endif
+
+// TRUE/FALSE: if the above message text should be added to history.
+#define SFSCI_ADD_TO_HISTORY 5 // lParam = SFSCI_MSGTEXT_NOTIFY(A/W), SFSCI_MSGTEXT_INSTRUCTION(A/W) or SFSCI_MSGTEXT_CONFIRMATION(A/W)
+
+
+// Return Values:
+// --------------
+// SFSCI_ACTIVATION_FILTER -> (BOOL)TRUE/FALSE
+// SFSCI_DELAY_TIME_REPLY -> (BOOL)TRUE/FALSE
+
+// SFSCI_MSGTEXT_NOTIFYA -> (char*) free with miranda_sys_free() of "m_system.h", (all %vars% in the text are already resolved)
+// SFSCI_MSGTEXT_INSTRUCTIONA -> see SFSCI_MSGTEXT_NOTIFYA
+// SFSCI_MSGTEXT_CONFIRMATIONA -> see SFSCI_MSGTEXT_NOTIFYA
+
+// SFSCI_MSGTEXT_NOTIFYW -> (WCHAR*) free with miranda_sys_free() of "m_system.h", (all %vars% in the text are already resolved)
+// SFSCI_MSGTEXT_INSTRUCTIONW -> see SFSCI_MSGTEXT_NOTIFYW
+// SFSCI_MSGTEXT_CONFIRMATIONW -> see SFSCI_MSGTEXT_NOTIFYW
+
+// SFSCI_ADD_TO_HISTORY -> (BOOL)TRUE/FALSE
+
+// returns NULL on error
+
+
+// -------------------------------------------
+// -- Confirm spam check (Event) -------------
+// -------------------------------------------
+
+#define ME_SPAMFILTER_OKTOSPAMCHECK "SpamFilter/OkToSpamCheck"
+
+// Description:
+// -------------
+// Gets fired before the spam check for a message starts.
+
+// Parameters:
+// -----------------
+// wParam = (SPAMCHECKDATA*)scd (Pointer to SPAMCHECKDATA struct)
+// lParam = (UINT)uFilterType (For possible values see above)
+
+// Return Values:
+// -----------------
+// Returning 0 on this event will accept spam checking for the message,
+// Returning 1 will prevent the spam check.
+
+
+// -------------------------------------------
+// -- Confirm spam detection (Event) ---------
+// -------------------------------------------
+
+#define ME_SPAMFILTER_OKTOSPAMDETECTION "SpamFilter/OkToSpamDetection"
+
+// Description:
+// -------------
+// Gets fired after a spam message is detected.
+
+// Parameters:
+// -----------------
+// wParam = (SPAMCHECKDATA*)scd (Pointer to SPAMCHECKDATA struct)
+// lParam = (UINT)uFilterType (For possible values see above)
+
+// Return Values:
+// -----------------
+// Returning 0 on this event will accept the detection
+// Returning 1 cause the message not to be seen as spam.
+
+// Note: If you only would like to get the final result hook
+// ME_SPAMFILTER_SPAMRECEIVED instead
+
+
+// -------------------------------------------
+// -- Spam message received (Event) ----------
+// -------------------------------------------
+
+#define ME_SPAMFILTER_SPAMRECEIVED "SpamFilter/SpamReceived"
+
+// Description:
+// -------------
+// Gets fired when a message is recognized as spam.
+
+// Parameters:
+// -----------------
+// wParam = (SPAMCHECKDATA*)scd (Pointer to SPAMCHECKDATA struct)
+// lParam = (UINT)uFilterType (For possible values see above)
+
+// Return Values:
+// -----------------
+// The return value should be 0.
+
+
+
+// -------------------------------------------
+// -- Spam Filter loaded ---------------------
+// -------------------------------------------
+
+#define ME_SPAMFILTER_MODULELOADED "SpamFilter/ModuleLoaded"
+
+// Description:
+// -------------
+// Gets fired when a all parts of the "Spam Filter" were loaded and available
+// to other plugins.
+// Past this event all functionality of the plugin is fully available.
+//
+// The event works quite similar as ME_SYSTEM_MODULESLOADED.
+// You should use ME_SYSTEM_MODULESLOADED in most cases instead. Please do so!
+//
+// (Service added in v2.0.1.0)
+
+// Parameters:
+// -----------------
+// wParam = 0
+// lParam = 0
+
+// Return Values:
+// -----------------
+// The return value should be 0.
+
+
+
+// -------------------------------------------
+// -- Helper: Duplicate SPAMCHECKDATA --------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_COPYSPAMCHECKDATA "SpamFilter/SpamCheckData/Copy"
+
+// Description:
+// -------------
+// Copys all contents of a SPAMCHECKDATA struct (especially strings) to another one
+// using Miranda's Memory Manager Interface (see m_system.h).
+// Use MS_SPAMFILTER_FREESPAMCHECKDATA to free the result when no longer needed.
+
+// Available since 2.5.2.0.
+
+// An entire copy of the SPAMCHECKDATA structure is made at pscd->cbSize.
+// All strings are duplicated.
+// The pscdTo->cbSize member is set to the current size of SPAMCHECKDATA
+// that SpamFilter uses.
+
+// Warning:
+// If you pass a structure that is bigger than the current sizeof(SPAMCHECKDATA)
+// then do not use pointers not contained in the current area because
+// they will not be duplicated (However, you could duplicate them by yourself).
+
+// Parameters:
+// -------------
+// wParam = (SPAMCHECKDATA*)pscdTo
+// lParam = (SPAMCHECKDATA*)pscdFrom
+
+// Return Values:
+// --------------
+// Returns 0 on success, nonzero on error.
+
+
+
+// -------------------------------------------
+// -- Helper: Free SPAMCHECKDATA -------------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_FREESPAMCHECKDATA "SpamFilter/SpamCheckData/Free"
+
+// Description:
+// -------------
+// Frees the memory allocated by MS_SPAMFILTER_COPYSPAMCHECKDATA.
+// using Miranda's Memory Manager Interface (see m_system.h).
+
+// Available since 2.5.2.0.
+
+// Parameters:
+// -------------
+// wParam = (SPAMCHECKDATA*)pscd
+// lParam = 0
+
+// Return Values:
+// --------------
+// Returns 0 on success, nonzero on failure.
+
+
+
+// -------------------------------------------
+// -- Showing error messages -----------------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_SHOWERROR "SpamFilter/ShowError"
+
+// Description:
+// -------------
+// Shows a Miranda try balloon tip, popup or message box
+// with the specified error message.
+
+// Parameters:
+// -------------
+// wParam = (UINT)uErrorType (For possible values see below)
+// lParam = 0
+
+// Possible values for wParam:
+#define SFSE_CRITICAL_ERROR 1 // Unspecified critical error occured related to the spam check.
+ // Only use this for situations that may never ever occur.
+ // Please do avoid this if possible.
+
+#define SFSE_SEND_FAILED 2 // Show this error when a sending of SFSCI_MSGTEXT_NOTIFY,
+ // SFSCI_MSGTEXT_INSTRUCTION, SFSCI_MSGTEXT_CONFIRMATION or
+ // SFSCI_MSGTEXT_NOTIFY failed (SFSCI_MSGTEXT_*)
+
+// Return Values:
+// --------------
+// Returns 0 on success, nonzero on error.
+
+
+
+// -------------------------------------------
+// -- Set contact as spammer (Contact) -------
+// -------------------------------------------
+
+#define MS_SPAMFILTER_CONTACT_SETASSPAMMER "SpamFilter/Contact/SetAsSpammer"
+
+// Description:
+// -------------
+// This service adds a specified user to the spammer list (fully ignored).
+
+// Associated event: ME_SPAMFILTER_CONTACT_SPAMMERSTATECHANGED
+
+// Note: works same as MS_SPAMFILTER_CONTACT_SHOWSETASSPAMMERDIALOG
+// but does not prompt the user.
+
+// Available since v2.5.0.0
+
+// Parameters:
+// -------------
+// wParam = (HANDLE)hContact (Handle to a contact in database. Can't be NULL.)
+// lParam = (DWORD)dwFlags (flags about what should be done, see below)
+
+// Available Flags:
+#define SCASF_NO_NOTIFY 0x00000001 // Prevents logging and playing of sounds
+#define SCASF_USE_ROBOT_SOUND 0x00000002 // play robot sound instead of advertisment sound (only if SCASF_NO_NOTIFY is not set)
+#define SCASF_NO_REMOVE_HISTORY 0x00000004 // history is marked read instead of fully removed
+#define SCASF_NO_DENY_AUTHREQUESTS 0x00000008 // do not deny pending auth requests
+
+// Return Values:
+// --------------
+// Returns 0 on success, nonzero on error.
+
+
+// -------------------------------------------
+// -- Show mark spammer dialog (Contact) -----
+// -------------------------------------------
+
+#define MS_SPAMFILTER_CONTACT_SHOWSETASSPAMMERDIALOG "SpamFilter/Contact/ShowSetAsSpammerDlg"
+
+// Description:
+// -------------
+// This service adds a specified user to the spammer list.
+// Before it shows a dialog to let the user confirm the action.
+// For use for example as action for a button on the message dialog.
+
+// Note: This service performs the same tasks as MS_SPAMFILTER_SETCONTACTASSPAMMER
+// to execute the action the user chooses.
+
+// Associated event: ME_SPAMFILTER_CONTACT_SPAMMERSTATECHANGED
+
+// Available since v2.5.0.0
+
+// Parameters:
+// -------------
+// wParam = (HANDLE)hContact (Handle to a contact in database. Can't be NULL.)
+// lParam = (HWND)hwndParent (Handle to the parent window. Can be NULL.)
+
+// Return Values:
+// --------------
+// Returns FALSE if user clicked cancel on the dialog.
+// TRUE if the contact was handled as spammer.
+
+
+// Deprecated in v2.5.0.0:
+// The service MS_SPAMFILTER_SETSPAMMANUALLY has been deprecated.
+// New plugins should use MS_SPAMFILTER_CONTACT_SETASSPAMMERDLG instead.
+#define MS_SPAMFILTER_SETSPAMMANUALLY "SpamFilter/SetSpamManually"
+
+
+// Return Values:
+// --------------
+// Returns 0 on success, nozero otherwise.
+
+
+// -------------------------------------------
+// -- Test if contact is spammer (Contact) ---
+// -------------------------------------------
+
+#define MS_SPAMFILTER_CONTACT_ISSPAMMER "SpamFilter/Contact/IsSpammer"
+
+// Description:
+// -------------
+// This service tests if a specified contact is on the spammer list (fully ignored).
+
+// Available since v2.5.0.0
+
+// Parameters:
+// -------------
+// wParam = (HANDLE)hContact (Handle to a contact in database. Can't be NULL.)
+// lParam = 0
+
+// Return Values:
+// --------------
+// Returns TRUE when the contact is on the spammer list, FALSE otherwise.
+
+
+// -------------------------------------------
+// -- Unmarks a contact as spammer (Contact) -
+// -------------------------------------------
+
+#define MS_SPAMFILTER_CONTACT_UNSETSPAMMER "SpamFilter/Contact/UnSetSpammer"
+
+// Description:
+// -------------
+// This service restores a spammer to be again a normal contact (unignored).
+
+// Associated event: ME_SPAMFILTER_CONTACT_SPAMMERSTATECHANGED
+
+// Available since v2.5.0.0
+
+// Parameters:
+// -------------
+// wParam = (HANDLE)hContact (Handle to a contact in database. Can't be NULL.)
+// lParam = 0
+
+// Return Values:
+// --------------
+// Returns 0 on success, nonzero on error.
+
+
+// -------------------------------------------
+// -- Spammer state changed (Event) ----------
+// -------------------------------------------
+
+#define ME_SPAMFILTER_CONTACT_SPAMMERSTATECHANGED "SpamFilter/Contact/SpammerStateChanged"
+
+// Description:
+// -------------
+// Gets fired when a a contact gets marked as spammer or unmarked.
+
+// Parameters:
+// -----------------
+// wParam = (HANDLE)hContact
+// lParam = (BOOL)bIsSpammer (new state)
+
+// Return Values:
+// -----------------
+// The return value should be 0.
+
+
#endif // M_SPAMFILTER_H \ No newline at end of file
diff --git a/m_trigger.h b/m_trigger.h
index cfee738..1a118c7 100644
--- a/m_trigger.h
+++ b/m_trigger.h
@@ -1,348 +1,348 @@
-/* Triggers */
-
-typedef struct {
- int cbSize;
- char *pszName; // used as identifier, must be unique
- HINSTANCE hInstance; // only needed when options screen is available
- DLGPROC pfnDlgProc; // only needed when options screen is available; the callback proc
- char *pszTemplate; // only needed when options screen is available; must be WS_CHILD, Control parent and !visible are recommended
-} TRIGGERREGISTER;
-
-/* /Trigger/RegisterTrigger service
-Register your trigger at the TriggerPlugin
- wParam = 0
- lParam = (LPARAM)(TRIGGERREGISTER *)&tr
-If you try to register a trigger with a name that already exists, the service will fail.
-Returns 0 on success, any other value on failure.
-*/
-#define MS_TRIGGER_REGISTERTRIGGER "/Trigger/RegisterTrigger"
-
-/* Dialog messages
-These message will be send to the options dialog, if available.
-*/
-/* TM_ADDTRIGGER
-'OK' is pressed and a new trigger will be added. Save your settings using the given triggerID.
- wParam = (WPARAM)(DWORD)triggerID
- lParam = 0
-*/
-#define TM_ADDTRIGGER WM_USER+10
-/* TM_DELTRIGGER
-The trigger addociated with the given triggerID will be removed, cleanup your settings for this trigger.
- wParam = (WPARAM)(DWORD)triggerID
- lParam = 0
-*/
-#define TM_DELTRIGGER WM_USER+11
-
-#define DF_CONTACT 0x01 // the hContact member is valid
-#define DF_PROTO 0x02 // the szProto member is valid
-#define DF_STATUS 0x04 // the status member is valid
-#define DF_TEXT 0x08 // the szText member is valid
-#define DF_LPARAM 0x10 // reserverd, lParam is valid
-
-typedef struct {
- int cbSize;
- int dFlags; // DF_*
- HANDLE hContact;
- char *szProto;
- int status;
- char *szText;
- LPARAM lParam;
-} TRIGGERDATA;
-
-typedef struct {
- int cbSize;
- DWORD triggerID;
- char *pszSummary; // small summary to be shown in the options screen
- TRIGGERDATA *td; // may be NULL, or only the dfFlags member set if triggerID is 0
-} SPECIFICTRIGGERINFO;
-
-/* TM_GETTRIGGERINFO
-(optional) Information for a specific trigger is requested.
- wParam = (WPARAM)(DWORD)triggerID
- lParam = (LPARAM)(SPECIFICTRIGGERINFO **)&sti
-Set *(SPECIFICTRIGGERINFO **)lParam to a (SPECIFICTRIGGERINFO *)&sti, and keep it in memory
-If triggerID is 0, you may only set the dFlags member of the TRIGGERDATA struct.
-*/
-#define TM_GETTRIGGERINFO WM_USER+12
-/* TM_ACTIONCHANGED
-(optional) Notification when the user changed the action in the options dialog.
- wParam = 0
- lParam = (SPECIFICACTIONINFO *)&sai
-*/
-#define TM_ACTIONCHANGED WM_USER+13
-
-#define TRG_PERFORM 0x01 // perform the actions associated to this trigger
-#define TRG_CLEANUP 0x02 // remove all related information after the call
-#define TRG_GETINFO 0x04 // retrieve the (SPECIFICATIONINFO *)&sai for this trigger (only if triggerID != 0)
-
-typedef struct {
- int cbSize;
- DWORD triggerID; // triggerID of the event to trigger or 0 for all
- char *pszName; // name of trigger (may be NULL if triggerID isn't 0)
- int flags; // flags (TRG_*)
- SPECIFICTRIGGERINFO *sti; // may be NULL
-} REPORT_INFO;
-
-/* /Trigger/ReportAction
-Service to call when you trigger your event.
- wParam = 0
- lParam = (REPORT_INFO *)&ri
-If you're trigger does not have any options, set triggerID to 0 and TriggerPlugin will call all
-associated actions, but set the triggerName member in that case.
-*/
-#define MS_TRIGGER_REPORTACTION "/Trigger/ReportAction"
-
-
-
-
-/* Actions */
-
-typedef struct {
- int cbSize;
- char *pszName; // must be unique!
- char *pszService; // called with wParam = flags, lParam = (SPECIFICATIONINFO *)&sai
- HINSTANCE hInstance; // only needed when options screen is available
- DLGPROC pfnDlgProc; // only needed when options screen is available; the callback proc
- char *pszTemplate; // only needed when options screen is available; must be WS_CHILD, Control parent and !visible are recommended
-} ACTIONREGISTER;
-
-/* /Trigger/RegisterAction service
-Register your action at the TriggerPlugin
- wParam = 0
- lParam = (LPARAM)(ACTIONREGISTER *)&ar
-If you try to register an action with a name that already exists, the service will fail.
-Returns 0 on success, any other value on failure.
-*/
-#define MS_TRIGGER_REGISTERACTION "/Trigger/RegisterAction"
-
-/* Dialog messages
-These message will be send to the options dialog, if available.
-*/
-/* TM_ADDACTION
-'OK' is pressed and a new trigger will be added. Save your settings using the given actionID.
- wParam = (WPARAM)(DWORD)actionID
- lParam = 0
-*/
-#define TM_ADDACTION WM_USER+1
-/* TM_TRIGGERCHANGED
-(optional) Notification when the user changed the trigger in the options dialog.
- wParam = 0
- lParam = (SPECIFICTRIGGERINFO *)&sai
-*/
-#define TM_TRIGGERCHANGED WM_USER+2
-
-#define ACT_PERFORM 0x01 // perform your action
-#define ACT_CLEANUP 0x02 // cleanup associated settings
-#define ACT_GETINFO 0x04 // return (SPECIFICACTIONINFO *)&sai
-
-/* pszService
-The service called, specified in the ACTIONREGISTER
- wParam = (WPARAM)ACT_* flags
- lParam = (LPARAM)SPECIFICACTIONINFO *)&sai
-You can retrieve the actionID from the SPECIFICACTIONINFO. If ACT_PERFORM is set, you can retrive
-additional data given by the trigger plugin from the (TRIGGERDATA *)&td member (this can be NULL).
-Return 0 on success, any other on failure.
-*/
-typedef struct {
- int cbSize;
- DWORD actionID; // actionID of the info requested
- char *pszSummary; // null terminating string containing a summary of the action, may be NULL
- TRIGGERDATA *td; // may be NULL
-} SPECIFICACTIONINFO;
-
-
-
-/* Helpers */
-#define PREFIX_ACTIONID "aid"
-#define PREFIX_TRIGGERID "tid"
-
-typedef struct {
- int cbSize;
- char *prefix; // prefix, defaults are PREFIX_ACTIONID for actions, PREFIX_TRIGGERID for triggers
- DWORD id; // action or trigger ID of the setting to remove
- char *szModule; // module where the settings are stored
- HANDLE hContact; // associated contact
-} REMOVETRIGGERSETTINGS;
-
-/* /Trigger/RemoveSettings Service
- wParam = 0
- lParam = (LPARAM)(REMOVETRIGGERSETTINGS *)&rts
-Removes settings from the database you wrote with the DBWriteAction* or DBWriteTrigger* helpers.
-Returns the number of settings removed or -1 on failure.
-*/
-#define MS_TRIGGER_REMOVESETTINGS "/Trigger/RemoveSettings"
-
-typedef struct {
- int cbSize;
- char *prefix; // prefix, defaults are PREFIX_ACTIONID for actions, PREFIX_TRIGGERID for triggers
- DWORD id; // action or trigger ID of the previous setting
- char *szName; // either the name of the trigger or the action, or NULL for all
- char *szModule; // module where the settings are stored
- HANDLE hContact; // assoicated contact
-} FINDTRIGGERSETTING;
-
-/* /Trigger/FindNextSetting Service
- wParam = 0
- lParam = (LPARAM)(FINDTRIGGERSETTING *)&fts
-Search for a setting in the database. Set id to 0 to start from the beginning, else search is done from id+1.
-Returns (DWORD)triggerID or actionID depending on prefix of the next setting in the database. Returns 0 if
-no more settings are found.
-*/
-#define MS_TRIGGER_FINDNEXTSETTING "/Trigger/FindNextSetting"
-
-
-
-/* Database helpers */
-static int __inline DBWriteActionSettingByte(DWORD actionID, HANDLE hContact,const char *szModule,const char *szSetting,BYTE val) {
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
- return DBWriteContactSettingByte(hContact, szModule, dbSetting, val);
-}
-
-static int __inline DBWriteActionSettingWord(DWORD actionID, HANDLE hContact,const char *szModule,const char *szSetting,WORD val) {
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
- return DBWriteContactSettingWord(hContact, szModule, dbSetting, val);
-}
-
-static int __inline DBWriteActionSettingDword(DWORD actionID, HANDLE hContact,const char *szModule,const char *szSetting,DWORD val) {
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
- return DBWriteContactSettingDword(hContact, szModule, dbSetting, val);
-}
-
-static int __inline DBWriteActionSettingString(DWORD actionID, HANDLE hContact,const char *szModule,const char *szSetting,const char *val) {
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
- return DBWriteContactSettingString(hContact, szModule, dbSetting, val);
-}
-
-static BYTE __inline DBGetActionSettingByte(DWORD actionID, HANDLE hContact, const char *szModule, const char *szSetting, BYTE errorValue) {
-
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
- return (BYTE)DBGetContactSettingByte(hContact, szModule, dbSetting, errorValue);
-}
-
-static WORD __inline DBGetActionSettingWord(DWORD actionID, HANDLE hContact, const char *szModule, const char *szSetting, WORD errorValue) {
-
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
- return (WORD)DBGetContactSettingWord(hContact, szModule, dbSetting, errorValue);
-}
-
-static DWORD __inline DBGetActionSettingDword(DWORD actionID, HANDLE hContact, const char *szModule, const char *szSetting, int errorValue) {
-
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
- return DBGetContactSettingDword(hContact, szModule, dbSetting, errorValue);
-}
-
-static int __inline DBGetActionSetting(DWORD actionID, HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) {
-
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
- return DBGetContactSetting(hContact, szModule, dbSetting, dbv);
-}
-
-static int __inline DBDeleteActionSetting(DWORD actionID, HANDLE hContact,const char *szModule,const char *szSetting) {
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
- return DBDeleteContactSetting(hContact, szModule, dbSetting);
-}
-
-/* Triggers */
-
-static int __inline DBWriteTriggerSettingByte(DWORD triggerID, HANDLE hContact,const char *szModule,const char *szSetting,BYTE val) {
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
- return DBWriteContactSettingByte(hContact, szModule, dbSetting, val);
-}
-
-static int __inline DBWriteTriggerSettingWord(DWORD triggerID, HANDLE hContact,const char *szModule,const char *szSetting,WORD val) {
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
- return DBWriteContactSettingWord(hContact, szModule, dbSetting, val);
-}
-
-static int __inline DBWriteTriggerSettingDword(DWORD triggerID, HANDLE hContact,const char *szModule,const char *szSetting,DWORD val) {
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
- return DBWriteContactSettingDword(hContact, szModule, dbSetting, val);
-}
-
-static int __inline DBWriteTriggerSettingString(DWORD triggerID, HANDLE hContact,const char *szModule,const char *szSetting,const char *val) {
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
- return DBWriteContactSettingString(hContact, szModule, dbSetting, val);
-}
-
-static BYTE __inline DBGetTriggerSettingByte(DWORD triggerID, HANDLE hContact, const char *szModule, const char *szSetting, BYTE errorValue) {
-
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
- return (BYTE)DBGetContactSettingByte(hContact, szModule, dbSetting, errorValue);
-}
-
-static WORD __inline DBGetTriggerSettingWord(DWORD triggerID, HANDLE hContact, const char *szModule, const char *szSetting, WORD errorValue) {
-
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
- return (WORD)DBGetContactSettingWord(hContact, szModule, dbSetting, errorValue);
-}
-
-static DWORD __inline DBGetTriggerSettingDword(DWORD triggerID, HANDLE hContact, const char *szModule, const char *szSetting, int errorValue) {
-
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
- return DBGetContactSettingDword(hContact, szModule, dbSetting, errorValue);
-}
-
-static int __inline DBGetTriggerSetting(DWORD triggerID, HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) {
-
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
- return DBGetContactSetting(hContact, szModule, dbSetting, dbv);
-}
-
-static int __inline DBDeleteTriggerSetting(DWORD triggerID, HANDLE hContact,const char *szModule,const char *szSetting) {
-
- char dbSetting[128];
-
- _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
- return DBDeleteContactSetting(hContact, szModule, dbSetting);
-}
+/* Triggers */
+
+typedef struct {
+ int cbSize;
+ char *pszName; // used as identifier, must be unique
+ HINSTANCE hInstance; // only needed when options screen is available
+ DLGPROC pfnDlgProc; // only needed when options screen is available; the callback proc
+ char *pszTemplate; // only needed when options screen is available; must be WS_CHILD, Control parent and !visible are recommended
+} TRIGGERREGISTER;
+
+/* /Trigger/RegisterTrigger service
+Register your trigger at the TriggerPlugin
+ wParam = 0
+ lParam = (LPARAM)(TRIGGERREGISTER *)&tr
+If you try to register a trigger with a name that already exists, the service will fail.
+Returns 0 on success, any other value on failure.
+*/
+#define MS_TRIGGER_REGISTERTRIGGER "/Trigger/RegisterTrigger"
+
+/* Dialog messages
+These message will be send to the options dialog, if available.
+*/
+/* TM_ADDTRIGGER
+'OK' is pressed and a new trigger will be added. Save your settings using the given triggerID.
+ wParam = (WPARAM)(DWORD)triggerID
+ lParam = 0
+*/
+#define TM_ADDTRIGGER WM_USER+10
+/* TM_DELTRIGGER
+The trigger addociated with the given triggerID will be removed, cleanup your settings for this trigger.
+ wParam = (WPARAM)(DWORD)triggerID
+ lParam = 0
+*/
+#define TM_DELTRIGGER WM_USER+11
+
+#define DF_CONTACT 0x01 // the hContact member is valid
+#define DF_PROTO 0x02 // the szProto member is valid
+#define DF_STATUS 0x04 // the status member is valid
+#define DF_TEXT 0x08 // the szText member is valid
+#define DF_LPARAM 0x10 // reserverd, lParam is valid
+
+typedef struct {
+ int cbSize;
+ int dFlags; // DF_*
+ HANDLE hContact;
+ char *szProto;
+ int status;
+ char *szText;
+ LPARAM lParam;
+} TRIGGERDATA;
+
+typedef struct {
+ int cbSize;
+ DWORD triggerID;
+ char *pszSummary; // small summary to be shown in the options screen
+ TRIGGERDATA *td; // may be NULL, or only the dfFlags member set if triggerID is 0
+} SPECIFICTRIGGERINFO;
+
+/* TM_GETTRIGGERINFO
+(optional) Information for a specific trigger is requested.
+ wParam = (WPARAM)(DWORD)triggerID
+ lParam = (LPARAM)(SPECIFICTRIGGERINFO **)&sti
+Set *(SPECIFICTRIGGERINFO **)lParam to a (SPECIFICTRIGGERINFO *)&sti, and keep it in memory
+If triggerID is 0, you may only set the dFlags member of the TRIGGERDATA struct.
+*/
+#define TM_GETTRIGGERINFO WM_USER+12
+/* TM_ACTIONCHANGED
+(optional) Notification when the user changed the action in the options dialog.
+ wParam = 0
+ lParam = (SPECIFICACTIONINFO *)&sai
+*/
+#define TM_ACTIONCHANGED WM_USER+13
+
+#define TRG_PERFORM 0x01 // perform the actions associated to this trigger
+#define TRG_CLEANUP 0x02 // remove all related information after the call
+#define TRG_GETINFO 0x04 // retrieve the (SPECIFICATIONINFO *)&sai for this trigger (only if triggerID != 0)
+
+typedef struct {
+ int cbSize;
+ DWORD triggerID; // triggerID of the event to trigger or 0 for all
+ char *pszName; // name of trigger (may be NULL if triggerID isn't 0)
+ int flags; // flags (TRG_*)
+ SPECIFICTRIGGERINFO *sti; // may be NULL
+} REPORT_INFO;
+
+/* /Trigger/ReportAction
+Service to call when you trigger your event.
+ wParam = 0
+ lParam = (REPORT_INFO *)&ri
+If you're trigger does not have any options, set triggerID to 0 and TriggerPlugin will call all
+associated actions, but set the triggerName member in that case.
+*/
+#define MS_TRIGGER_REPORTACTION "/Trigger/ReportAction"
+
+
+
+
+/* Actions */
+
+typedef struct {
+ int cbSize;
+ char *pszName; // must be unique!
+ char *pszService; // called with wParam = flags, lParam = (SPECIFICATIONINFO *)&sai
+ HINSTANCE hInstance; // only needed when options screen is available
+ DLGPROC pfnDlgProc; // only needed when options screen is available; the callback proc
+ char *pszTemplate; // only needed when options screen is available; must be WS_CHILD, Control parent and !visible are recommended
+} ACTIONREGISTER;
+
+/* /Trigger/RegisterAction service
+Register your action at the TriggerPlugin
+ wParam = 0
+ lParam = (LPARAM)(ACTIONREGISTER *)&ar
+If you try to register an action with a name that already exists, the service will fail.
+Returns 0 on success, any other value on failure.
+*/
+#define MS_TRIGGER_REGISTERACTION "/Trigger/RegisterAction"
+
+/* Dialog messages
+These message will be send to the options dialog, if available.
+*/
+/* TM_ADDACTION
+'OK' is pressed and a new trigger will be added. Save your settings using the given actionID.
+ wParam = (WPARAM)(DWORD)actionID
+ lParam = 0
+*/
+#define TM_ADDACTION WM_USER+1
+/* TM_TRIGGERCHANGED
+(optional) Notification when the user changed the trigger in the options dialog.
+ wParam = 0
+ lParam = (SPECIFICTRIGGERINFO *)&sai
+*/
+#define TM_TRIGGERCHANGED WM_USER+2
+
+#define ACT_PERFORM 0x01 // perform your action
+#define ACT_CLEANUP 0x02 // cleanup associated settings
+#define ACT_GETINFO 0x04 // return (SPECIFICACTIONINFO *)&sai
+
+/* pszService
+The service called, specified in the ACTIONREGISTER
+ wParam = (WPARAM)ACT_* flags
+ lParam = (LPARAM)SPECIFICACTIONINFO *)&sai
+You can retrieve the actionID from the SPECIFICACTIONINFO. If ACT_PERFORM is set, you can retrive
+additional data given by the trigger plugin from the (TRIGGERDATA *)&td member (this can be NULL).
+Return 0 on success, any other on failure.
+*/
+typedef struct {
+ int cbSize;
+ DWORD actionID; // actionID of the info requested
+ char *pszSummary; // null terminating string containing a summary of the action, may be NULL
+ TRIGGERDATA *td; // may be NULL
+} SPECIFICACTIONINFO;
+
+
+
+/* Helpers */
+#define PREFIX_ACTIONID "aid"
+#define PREFIX_TRIGGERID "tid"
+
+typedef struct {
+ int cbSize;
+ char *prefix; // prefix, defaults are PREFIX_ACTIONID for actions, PREFIX_TRIGGERID for triggers
+ DWORD id; // action or trigger ID of the setting to remove
+ char *szModule; // module where the settings are stored
+ HANDLE hContact; // associated contact
+} REMOVETRIGGERSETTINGS;
+
+/* /Trigger/RemoveSettings Service
+ wParam = 0
+ lParam = (LPARAM)(REMOVETRIGGERSETTINGS *)&rts
+Removes settings from the database you wrote with the DBWriteAction* or DBWriteTrigger* helpers.
+Returns the number of settings removed or -1 on failure.
+*/
+#define MS_TRIGGER_REMOVESETTINGS "/Trigger/RemoveSettings"
+
+typedef struct {
+ int cbSize;
+ char *prefix; // prefix, defaults are PREFIX_ACTIONID for actions, PREFIX_TRIGGERID for triggers
+ DWORD id; // action or trigger ID of the previous setting
+ char *szName; // either the name of the trigger or the action, or NULL for all
+ char *szModule; // module where the settings are stored
+ HANDLE hContact; // assoicated contact
+} FINDTRIGGERSETTING;
+
+/* /Trigger/FindNextSetting Service
+ wParam = 0
+ lParam = (LPARAM)(FINDTRIGGERSETTING *)&fts
+Search for a setting in the database. Set id to 0 to start from the beginning, else search is done from id+1.
+Returns (DWORD)triggerID or actionID depending on prefix of the next setting in the database. Returns 0 if
+no more settings are found.
+*/
+#define MS_TRIGGER_FINDNEXTSETTING "/Trigger/FindNextSetting"
+
+
+
+/* Database helpers */
+static int __inline DBWriteActionSettingByte(DWORD actionID, HANDLE hContact,const char *szModule,const char *szSetting,BYTE val) {
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
+ return DBWriteContactSettingByte(hContact, szModule, dbSetting, val);
+}
+
+static int __inline DBWriteActionSettingWord(DWORD actionID, HANDLE hContact,const char *szModule,const char *szSetting,WORD val) {
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
+ return DBWriteContactSettingWord(hContact, szModule, dbSetting, val);
+}
+
+static int __inline DBWriteActionSettingDword(DWORD actionID, HANDLE hContact,const char *szModule,const char *szSetting,DWORD val) {
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
+ return DBWriteContactSettingDword(hContact, szModule, dbSetting, val);
+}
+
+static int __inline DBWriteActionSettingString(DWORD actionID, HANDLE hContact,const char *szModule,const char *szSetting,const char *val) {
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
+ return DBWriteContactSettingString(hContact, szModule, dbSetting, val);
+}
+
+static BYTE __inline DBGetActionSettingByte(DWORD actionID, HANDLE hContact, const char *szModule, const char *szSetting, BYTE errorValue) {
+
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
+ return (BYTE)DBGetContactSettingByte(hContact, szModule, dbSetting, errorValue);
+}
+
+static WORD __inline DBGetActionSettingWord(DWORD actionID, HANDLE hContact, const char *szModule, const char *szSetting, WORD errorValue) {
+
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
+ return (WORD)DBGetContactSettingWord(hContact, szModule, dbSetting, errorValue);
+}
+
+static DWORD __inline DBGetActionSettingDword(DWORD actionID, HANDLE hContact, const char *szModule, const char *szSetting, int errorValue) {
+
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
+ return DBGetContactSettingDword(hContact, szModule, dbSetting, errorValue);
+}
+
+static int __inline DBGetActionSetting(DWORD actionID, HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) {
+
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
+ return DBGetContactSetting(hContact, szModule, dbSetting, dbv);
+}
+
+static int __inline DBDeleteActionSetting(DWORD actionID, HANDLE hContact,const char *szModule,const char *szSetting) {
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_ACTIONID, actionID, szSetting);
+ return DBDeleteContactSetting(hContact, szModule, dbSetting);
+}
+
+/* Triggers */
+
+static int __inline DBWriteTriggerSettingByte(DWORD triggerID, HANDLE hContact,const char *szModule,const char *szSetting,BYTE val) {
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
+ return DBWriteContactSettingByte(hContact, szModule, dbSetting, val);
+}
+
+static int __inline DBWriteTriggerSettingWord(DWORD triggerID, HANDLE hContact,const char *szModule,const char *szSetting,WORD val) {
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
+ return DBWriteContactSettingWord(hContact, szModule, dbSetting, val);
+}
+
+static int __inline DBWriteTriggerSettingDword(DWORD triggerID, HANDLE hContact,const char *szModule,const char *szSetting,DWORD val) {
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
+ return DBWriteContactSettingDword(hContact, szModule, dbSetting, val);
+}
+
+static int __inline DBWriteTriggerSettingString(DWORD triggerID, HANDLE hContact,const char *szModule,const char *szSetting,const char *val) {
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
+ return DBWriteContactSettingString(hContact, szModule, dbSetting, val);
+}
+
+static BYTE __inline DBGetTriggerSettingByte(DWORD triggerID, HANDLE hContact, const char *szModule, const char *szSetting, BYTE errorValue) {
+
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
+ return (BYTE)DBGetContactSettingByte(hContact, szModule, dbSetting, errorValue);
+}
+
+static WORD __inline DBGetTriggerSettingWord(DWORD triggerID, HANDLE hContact, const char *szModule, const char *szSetting, WORD errorValue) {
+
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
+ return (WORD)DBGetContactSettingWord(hContact, szModule, dbSetting, errorValue);
+}
+
+static DWORD __inline DBGetTriggerSettingDword(DWORD triggerID, HANDLE hContact, const char *szModule, const char *szSetting, int errorValue) {
+
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
+ return DBGetContactSettingDword(hContact, szModule, dbSetting, errorValue);
+}
+
+static int __inline DBGetTriggerSetting(DWORD triggerID, HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) {
+
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
+ return DBGetContactSetting(hContact, szModule, dbSetting, dbv);
+}
+
+static int __inline DBDeleteTriggerSetting(DWORD triggerID, HANDLE hContact,const char *szModule,const char *szSetting) {
+
+ char dbSetting[128];
+
+ _snprintf(dbSetting, sizeof(dbSetting), "%s%u_%s", PREFIX_TRIGGERID, triggerID, szSetting);
+ return DBDeleteContactSetting(hContact, szModule, dbSetting);
+}
diff --git a/main.c b/main.c
index 88bb5de..412f69a 100644
--- a/main.c
+++ b/main.c
@@ -1,595 +1,595 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-
-HINSTANCE hInst;
-PLUGINLINK *pluginLink;
-
-
-
-
-// -- Plugin Info
-PLUGININFOEX pluginInfo = {
- sizeof(PLUGININFOEX),
- "Spam Filter Mod (Unicode)",
- PLUGIN_VERSION,
- "Filters out advertisment messages, messages sent by robots and other disliked messages such as hoax messages.", // Gets translated automatically
- "Heiko Herkenrath",
- "", // PLUGIN_EMAIL will get set later
- "© 2003-2006 Heiko Herkenrath",
- "",
- 1,
- 0, // Does not replace anything built-in
- { 0xecb1c450, 0xf71a, 0x425d, { 0xab, 0x63, 0xed, 0x17, 0x5a, 0x86, 0x23, 0x84 } }
-};
-
-// -- Variables: Events/Hooks
-HANDLE hHookModulesLoaded;
-
-// -----------------------------------------
-
-
-static void ThreadInstallation(void* arg)
-{
- WCHAR* szFileName = 0;
-
- if (Miranda_Terminated()) return;
-
- // Install Files
- {
- // Spam Definitions
- // Move "Spam Filter" subdirectory to Miranda IM folder.
- // Since the Plugins directory should only contain DLLs and no additional data files
- GetDefinitionsPath(szFileName, FALSE, NULL);
- PInstallFile(DATA_SUBDIRECTORY, szFileName);
-
- // Documentation
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, DOCS_SUBDIRECTORY, NULL, NULL);
- PInstallFile(_T("SpamFilter-Readme.txt"), szFileName);
- PInstallFile(_T("SpamFilter-License.txt"), szFileName);
- PInstallFile(_T("SpamFilter-SDK.zip"), szFileName);
- PInstallFile(_T("SpamFilter-Translation.txt"), szFileName); // normally in SDK
- PInstallFile(_T("SpamFilter-Developer.txt"), szFileName); // normally in SDK
- PInstallFile(_T("m_spamfilter.h"), szFileName); // normally in SDK
- PInstallFile(_T("m_spamfilter.inc"), szFileName); // normally in SDK
-
- PInstallFile(_T("SpamDefinitions-*.txt"), szFileName); // additional SpamDefs installed
-
- PInstallFile(_T("PCRE-License.txt"), szFileName);
-
- // Sounds
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, SOUNDS_SUBDIRECTORY, NULL, NULL);
- PInstallFile(DEFAULT_ADVERTISMENT_SOUNDFILE, szFileName);
- PInstallFile(DEFAULT_DISLIKEDMESSAGE_SOUNDFILE, szFileName);
- PInstallFile(DEFAULT_ROBOT_SOUNDFILE, szFileName);
-
- // DLLs (non-plugin)
- PInstallDLLFile(_T("pcre.dll"), TRUE, TRUE);
-
- // InstallScript.xml
- PConstructLocalPath(szFileName, CSIDL_EXT_MODULE, NULL, _T("InstallScript.xml"), NULL);
- DeleteFile(szFileName);
- }
-
- if (Miranda_Terminated()) return;
-
- // Add default list items
- {
- STRINGLIST* pslWords = SLNewList();
-
- // Create default bad words
- if (!IsSpamDefinitionDataPresent(SDID_CUSTOM_BADWORDS))
- {
- SLAddItem(pslWords, TranslateT("Automated message"));
- SetSpamDefinitionData(pslWords, SDID_CUSTOM_BADWORDS, NULL);
-
- SLClearList(pslWords);
- }
-
- // Create default good words
- if (!IsSpamDefinitionDataPresent(SDID_CUSTOM_GOODWORDS))
- {
- SLAddItem(pslWords, TranslateT("Miranda IM"));
- SetSpamDefinitionData(pslWords, SDID_CUSTOM_GOODWORDS, NULL);
-
- SLClearList(pslWords);
- }
-
- // Create default disliked message words
- if (!IsSpamDefinitionDataPresent(SDID_CUSTOM_DISLIKEDWORDS))
- {
- SLAddItem(pslWords, TranslateT("Please forward"));
- SetSpamDefinitionData(pslWords, SDID_CUSTOM_DISLIKEDWORDS, NULL);
- }
-
- SLFreeList(pslWords);
- }
-
- if (Miranda_Terminated()) return;
-
- // On First Run
- if (DBGetContactSettingDword(NULL, DB_MODULE_NAME, DB_SETTING_FIRSTRUNDONE, 0) != PLUGIN_VERSION) // no use of "<"!
- {
- // Import bad words v1.0.4.0 -> v2.0.0.0 (DB->FILE converter)
- {
- STRINGLIST* pslBadWords = NULL;
- STRINGLIST* pslDefaultBadWords = NULL;
- int i;
- char szSetting[7+MAX_INT_LENGTH+1];
- DBVARIANT dbv;
-
- // Get old bad words out of database
- for (i=0;; i++) // no break condition
- {
- mir_snprintf(szSetting, ARRAYSIZE(szSetting), "BadWord%i", i);
-
- if (DBGetContactSettingTString(NULL, "SpamFilter", szSetting, &dbv) != 0)
- break;
-
- // Load default list when needed
- if (!pslBadWords)
- {
- pslDefaultBadWords = SLNewList();
- pslBadWords = SLNewList();
-
- // Load default bad words
- GetSpamDefinitionData(pslDefaultBadWords, SDID_BADWORDS);
-
- // Load bad words already in file
- GetSpamDefinitionData(pslBadWords, SDID_CUSTOM_BADWORDS);
- }
-
- if (!SLIsItem(pslDefaultBadWords, dbv.ptszVal, FALSE) && !SLIsItem(pslBadWords, dbv.ptszVal, FALSE))
- SLAddItem(pslBadWords, dbv.ptszVal);
-
- DBFreeVariant(&dbv);
-
- // Delete old setting (important! else it will reimport every version change)
- DBDeleteContactSetting(NULL, "SpamFilter", szSetting);
- }
-
- // Save old and new bad words
- if (pslBadWords) {
- SetSpamDefinitionData(pslBadWords, SDID_CUSTOM_BADWORDS, NULL);
- SLFreeList(pslBadWords);
- }
- if (pslDefaultBadWords)
- SLFreeList(pslDefaultBadWords);
- }
-
- if (Miranda_Terminated()) return;
-
- // Import old spammers in database of v2.0.1.0 (DB->DB converter)
- {
- WCHAR* pszSuffix = _T(" (Spammer)"); // readonly allocated
- WCHAR* pszSuffixT = TranslateTS(pszSuffix);
- WCHAR* pszUserName;
- HANDLE hContact;
- BOOL bIsOldSpammer;
-
- if (pszSuffix)
- {
- for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); hContact; hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0))
- {
- // Skip if not hidden
- if (!DBGetContactSettingByte(hContact, "CList", "Hidden", 0))
- continue;
-
- // Skip if is already "new" spammer
- if (CallService(MS_SPAMFILTER_CONTACT_ISSPAMMER, (WPARAM)hContact, 0))
- continue;
-
- pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
-
- // Find suffix
- bIsOldSpammer = FALSE;
- if (lstrlen(pszUserName) > lstrlen(pszSuffix))
- if (StrCmp(pszUserName+lstrlen(pszUserName)-lstrlen(pszSuffix), pszSuffix) == 0)
- bIsOldSpammer = TRUE;
- if (lstrlen(pszUserName) > lstrlen(pszSuffixT))
- if (StrCmp(pszUserName+lstrlen(pszUserName)-lstrlen(pszSuffixT), pszSuffixT) == 0)
- bIsOldSpammer = TRUE;
-
- if (bIsOldSpammer)
- CallService(MS_SPAMFILTER_CONTACT_SETASSPAMMER, (WPARAM)hContact, (LPARAM)SCASF_NO_NOTIFY|SCASF_NO_REMOVE_HISTORY|SCASF_NO_DENY_AUTHREQUESTS);
- }
- }
-
- }
-
- if (Miranda_Terminated()) return;
-
- // Import Spam Definition Data previous to v2.5.0.0 (ANSI->UTF8 converter)
- {
- // own-badwords.sfw
- PConstructLocalPath(szFileName, CSIDL_EXT_MIRANDAPROFILE, _T("Spam Filter"), _T("own-badwords.sfw"), NULL);
- mir_utf8encodeW(szFileName); // current codepage
-
- // own-goodwords.sfw
- PConstructLocalPath(szFileName, CSIDL_EXT_MIRANDAPROFILE, _T("Spam Filter"), _T("own-goodwords.sfw"), NULL);
- mir_utf8encodeW(szFileName); // current codepage
-
- // own-dislikedwords.sfw
- PConstructLocalPath(szFileName, CSIDL_EXT_MIRANDAPROFILE, _T("Spam Filter"), _T("own-dislikedwords.sfw"), NULL);
- mir_utf8encodeW(szFileName); // current codepage
-
- // BadWords\*.sfw
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("Chinese (Traditional).sfw"), NULL);
- mir_utf8encodeW(szFileName); // big5 codepage (Chinese) [PRC and Singapore have other codepages]
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("Russian.sfw"), NULL);
- mir_utf8encodeW(szFileName); // cp-1251 codepage (Russian)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("English.sfw"), NULL);
- mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("German.sfw"), NULL);
- mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("French.sfw"), NULL);
- mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("Portuguese (Brazil).sfw"), NULL);
- mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("*.sfw"), NULL);
- mir_utf8encodeW(szFileName); // customized reminder
-
- // HoaxTexts\*.sft
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\HoaxTexts"), _T("Example.sft"), NULL);
- mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\HoaxTexts"), _T("Example.sft"), NULL);
- mir_utf8encodeW(szFileName); // customized reminder
-
- // Teasers\*.sft
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Teasers"), _T("English.sft"), NULL);
- mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Teasers"), _T("German.sft"), NULL);
- mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Teasers"), _T("*.sft"), NULL);
- mir_utf8encodeW(szFileName); // reminder customized
-
- // Urls\*.sfc
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Urls"), _T("*.sfc"), NULL);
- mir_utf8encodeW(szFileName); // url strings are all English
-
- // PhoneNumbers\*.sfc
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\PhoneNumbers"), _T("Russian.sfc"), NULL);
- mir_utf8encodeW(szFileName); // cp-1251 codepage (Russian)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\PhoneNumbers"), _T("German.sfc"), NULL);
- mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\PhoneNumbers"), _T("*.sfc"), NULL);
- mir_utf8encodeW(szFileName); // reminder customizd
-
- // Spammers\*.sfc
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Spammers"), _T("Russian.sfc"), NULL);
- mir_utf8encodeW(szFileName); // cp-1251 codepage (Russian)
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Spammers"), _T("*.sfc"), NULL);
- mir_utf8encodeW(szFileName); // reminder customized
-
- // format_text.sfc
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter"), _T("format_text.sfc"), NULL);
- mir_utf8encodeW(szFileName); // was English only
-
- // format_numbers.sfc
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter"), _T("format_numbers.sfc"), NULL);
- mir_utf8encodeW(szFileName); // was English only
-
- // separators.sfc
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter"), _T("separators.sfc"), NULL);
- mir_utf8encodeW(szFileName); // was English only
- }
-
- if (Miranda_Terminated()) return;
-
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER) || DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)DEFAULT_SETTING_ROBOTFILTER))
- {
- CallService(MS_IGNORE_UNIGNORE, (WPARAM)NULL, (LPARAM)IGNOREEVENT_MESSAGE);
- CallService(MS_IGNORE_UNIGNORE, (WPARAM)NULL, (LPARAM)IGNOREEVENT_URL);
- CallService(MS_IGNORE_UNIGNORE, (WPARAM)NULL, (LPARAM)IGNOREEVENT_FILE);
- CallService(MS_IGNORE_UNIGNORE, (WPARAM)NULL, (LPARAM)IGNOREEVENT_AUTHORIZATION);
-
- CallService(MS_IGNORE_IGNORE, (WPARAM)NULL, (LPARAM)IGNOREEVENT_USERONLINE);
-
- {
- DBVARIANT dbv;
-
- if (DBGetContactSetting(NULL, "SRMM", "UnknownTyping", &dbv) == 0) // If existant
- {
- if (dbv.type == DBVT_BYTE)
- DBWriteContactSettingByte(NULL, "SRMM", "UnknownTyping", 0);
- DBFreeVariant(&dbv);
- }
- }
- }
-
- // Disable "old"/other spam plugins (if installed) to avoid conflicts and user confusion
- // (All features of them included in Spam Filter)
- if (GetModuleHandle(_T("SpamBlock")))
- DBWriteContactSettingByte(NULL, "PluginDisable", "spamblock.dll", 1);
- if (GetModuleHandle(_T("SpamBlockPlus")))
- DBWriteContactSettingByte(NULL, "PluginDisable", "spamblockplus.dll", 1);
- if (GetModuleHandle(_T("spamreturner")))
- DBWriteContactSettingByte(NULL, "PluginDisable", "spamreturner.dll", 1);
- if (GetModuleHandle(_T("stopspam"))) {
- DBWriteContactSettingByte(NULL, "PluginDisable", "stopspam.dll", 1);
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)TRUE);
- }
- if (GetModuleHandle(_T("ignorecontact")))
- DBWriteContactSettingByte(NULL, "PluginDisable", "ignorecontact.dll", 1);
-
- #if defined (UNICODE)
- DBWriteContactSettingByte(NULL, "PluginDisable", "spamfilter.dll", 1);
- #else
- DBWriteContactSettingByte(NULL, "PluginDisable", "spamfilterw.dll", 1);
- #endif
-
- // FirstRunDone
- DBWriteContactSettingDword(NULL, DB_MODULE_NAME, DB_SETTING_FIRSTRUNDONE, PLUGIN_VERSION);
- }
-}
-
-
-__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
-{
- if (mirandaVersion < NEEDED_MIRANDA_VERSION)
- {
- // No Translate() here! (langpack service not yet loaded, no need anyway)
- MessageBoxEx(NULL, _T("The Spam Filter plugin can not be loaded. It requires Miranda IM ")_T(NEEDED_MIRANDA_VERSION_STR)_T(" or later."), _T("Spam Filter Plugin"), MB_OK|MB_ICONERROR|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
- return NULL;
- }
-
- return &pluginInfo;
-}
-static const MUUID interfaces[] = {MIID_SERVICEMODE, MIID_LAST};
-__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
-{
- return interfaces;
-}
-
-
-
-BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
-{
- hInst = hinstDLL;
-
- return TRUE;
-}
-
-
-
-static int AllModulesLoaded(WPARAM wParam, LPARAM lParam)
-{
- AssignAllContacts();
-
- // Custom Profile Folder Plugin support (as early as possible!)
- InitFolders();
-
- // Definition file cache (after folder)
- InitSpamDefinitions();
-
- // Load regular expressions DLL
- // Important: Not in Load() to allow other plugins to update/replace the DLL in their Load()
- InitRegExp();
-
- // Trigger Plugin support
- InitTrigger();
-
- // Add message types for filter
- {
- int i, iProtoCount = 0;
- WCHAR szProtoNameBuf[256];
- WCHAR* pszProtoName;
- DWORD dwProtoCaps, dwProtoCaps4;
- HICON hProtoIcon;
- PROTOCOLDESCRIPTOR** appd = NULL;
-
- if (CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&iProtoCount, (LPARAM)&appd) == 0)
- {
- for (i=0; i<iProtoCount; i++)
- {
- if (appd[i]->type != PROTOTYPE_PROTOCOL) continue;
-
- // Get capabilities
- dwProtoCaps = CallProtoService(appd[i]->szName, PS_GETCAPS, (WPARAM)PFLAGNUM_1, 0);
- if ((int)dwProtoCaps == CALLSERVICE_NOTFOUND) continue;
- dwProtoCaps4 = CallProtoService(appd[i]->szName, PS_GETCAPS, (WPARAM)PFLAGNUM_4, 0);
-
- // Get icon
- hProtoIcon = (HICON)CallProtoService(appd[i]->szName, PS_LOADICON, PLI_PROTOCOL|PLIF_SMALL, 0);
- if ((int)hProtoIcon == CALLSERVICE_NOTFOUND) hProtoIcon = NULL;
-
- // Get readable name
- #if defined(UNICODE)
- if (CallProtoService(appd[i]->szName, PS_GETNAME"W", ARRAYSIZE(szProtoNameBuf), (LPARAM)szProtoNameBuf) == 0) {
- pszProtoName = szProtoNameBuf;
- } else if (CallProtoService(appd[i]->szName, PS_GETNAME, ARRAYSIZE(szProtoNameBuf), (LPARAM)szProtoNameBuf) == 0) {
- pszProtoName = (WCHAR*)mir_utf8encodeW(szProtoNameBuf);
- } else {
- pszProtoName = (WCHAR*)mir_utf8encodeW((WCHAR*)appd[i]->szName);
- }
- #else
- if (CallProtoService(appd[i]->szName, PS_GETNAME, ARRAYSIZE(szProtoNameBuf), (LPARAM)szProtoNameBuf) == 0) {
- pszProtoName = szProtoNameBuf;
- } else {
- pszProtoName = appd[i]->szName;
- }
- #endif
-
- // Authorization Requests (flag supported and display module installed)
- if (dwProtoCaps&PF1_AUTHREQ)
- SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_AUTHREQUEST, TranslateT("Authorization Request"), (HICON)-SKINICON_OTHER_MIRANDA, 100, ((dwProtoCaps4&PF4_FORCEAUTH) ? MTDF_DEFAULTDISABLED : 0));
-
- // YouWereAdded Notification (flag supported and display module installed)
- if (dwProtoCaps&PF1_ADDED)
- SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_ADDED, TranslateT("Added Notification"), (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(210), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED), 110, ((dwProtoCaps4&PF4_FORCEADDED) ? MTDF_DEFAULTDISABLED : 0));
-
- // Special support for ICQ (workaround, quite hacky)
- if (StrCmpA(appd[i]->szName, "ICQ") == 0)
- {
- // WebPager (display module installed: WebPager Plugin)
- if (ServiceExists("WebPager/ReceiveWebPager"))
- SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, "WebPager", TranslateT("WebPager"), GetModuleHandle(_T("WebPager")) ? (HICON)LoadImage(GetModuleHandle(_T("WebPager")), MAKEINTRESOURCE(101), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) : NULL, 200, 0);
-
- // EmailExpress (display module installed: EmailExpress Plugin)
- if (ServiceExists("EmailExpress/ReceiveEmailExpress"))
- SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, "EmailExpress", TranslateT("EmailExpress"), GetModuleHandle(_T("EmailExpress")) ? (HICON)LoadImage(GetModuleHandle(_T("EmailExpress")), MAKEINTRESOURCE(102), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) : NULL, 210, 0);
- }
-
- // Instant Messages (flag supported and display module installed)
- if ((dwProtoCaps&PF1_IMRECV) && ServiceExists(MS_MSG_SENDMESSAGE))
- SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_MESSAGE, TranslateT("Message"), (HICON)-SKINICON_EVENT_MESSAGE, 300, ((dwProtoCaps&PF1_IMSEND) ? 0 : MTDF_DEFAULTDISABLED));
-
- // URLs (flag supported and display module installed)
- if ((dwProtoCaps&PF1_URLRECV) && ServiceExists(MS_URL_SENDURL))
- SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_URL, TranslateT("URL"), (HICON)-SKINICON_EVENT_URL, 400, ((dwProtoCaps&PF1_URLSEND) ? 0 : MTDF_DEFAULTDISABLED));
-
- // File Transfers (flag supported and display module installed)
- if ((dwProtoCaps&PF1_FILERECV) && ServiceExists(MS_FILE_SENDFILE))
- SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_FILE, TranslateT("File"), (HICON)-SKINICON_EVENT_FILE, 500, ((dwProtoCaps&PF1_FILESEND) ? 0 : MTDF_DEFAULTDISABLED));
-
- // Contact Transfers (flag supported and display module installed)
- if ((dwProtoCaps&PF1_CONTACTRECV) && ServiceExists(MS_CONTACTS_SEND))
- SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_CONTACTS, TranslateT("Contacts"), GetModuleHandle(_T("contacts")) ? (HICON)LoadImage(GetModuleHandle(_T("contacts")), MAKEINTRESOURCE(109), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) : NULL, 600, ((dwProtoCaps&PF1_CONTACTSEND) ? 0 : MTDF_DEFAULTDISABLED));
-
-
- if (hProtoIcon) DestroyIcon(hProtoIcon); // must be destroyed
-
- #if defined(UNICODE)
- if (pszProtoName != szProtoNameBuf)
- mir_free(pszProtoName);
- #endif
- }
- }
- }
-
- // Options
- InitOptions();
-
- // Add sounds
- SkinAddNewSoundBundled(DB_SOUND_ADVERTISMENT_SETTING, Translate("Spam Filter"), Translate("Advertisment Alert"), DEFAULT_ADVERTISMENT_SOUNDFILE);
- SkinAddNewSoundBundled(DB_SOUND_DISLIKEDMESSAGE_SETTING, Translate("Spam Filter"), Translate("Disliked Message Alert"), DEFAULT_DISLIKEDMESSAGE_SOUNDFILE);
- SkinAddNewSoundBundled(DB_SOUND_ROBOT_SETTING, Translate("Spam Filter"), Translate("Robot Alert"), DEFAULT_ROBOT_SOUNDFILE);
-
- // Add known database modules (Support for DBEditor++)
- if (ServiceExists("DBEditorpp/RegisterModule"))
- {
- const char* apszModuleNames[] = {DB_MODULE_NAME, DB_MODULE_NAME_MSGTYPES, DB_MODULE_NAME_PRESPAMMERS};
- CallService("DBEditorpp/RegisterModule", (WPARAM)apszModuleNames, (LPARAM)ARRAYSIZE(apszModuleNames));
- }
-
- // Support for own variables in Variables-Plugin
- InitVariables();
-
- // Init CList extra image (for spammers)
- InitExtraImg();
-
- // Support for Popup/PopupPlus Plugin
- if (IsPopupAvailable(FALSE))
- {
- BOOL bFilterActive = DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, DEFAULT_SETTING_ADVERTISMENTFILTER) || DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, DEFAULT_SETTING_DISLIKEDMESSAGEFILTER);
- BOOL bPopupsActive = DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, DEFAULT_SETTING_POPUP);
-
- InitPopup();
-
- // Init popup menu item
- SetPopupMenuItem(bPopupsActive, !bFilterActive);
-
- // Add colors
- SkinAddNewColor(DB_COLOR_POPUPBACKGROUND_SETTING, Translate("Spam Filter"), Translate("Popup Background"), RGB(213,209,208), FALSE);
- SkinAddNewColor(DB_COLOR_POPUPTEXT_SETTING, Translate("Spam Filter"), Translate("Popup Text"), RGB(193,0,38), FALSE);
- }
-
- // Init contact menu item
- InitMenuItems();
-
- // SpamFilter fully loaded
- NotifyModuleLoaded();
- return 0;
-}
-
-
-__declspec(dllexport) int Load(PLUGINLINK* link)
-{
- pluginLink = (PLUGINLINK*)link;;
-
- hwndSpamFilterOpt = NULL;
- hwndAdvertismentFilter = NULL;
- hwndRobotFilter = NULL;
- hwndDislikedMessagesFilter = NULL;
- hwndSpamDefinitionsInfo = NULL;
- hwndSpammersInfo = NULL;
-
- if (!ServiceExists(MS_DB_CONTACT_GETSETTING_STR))
- {
- // No Translate() here
- MessageBoxEx(NULL, _T("The Spam Filter plugin requires database driver (db3x) 0.5.1.0 or later."), _T("Spam Filter Plugin"), MB_OK|MB_ICONERROR|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
- return 1;
- }
-
- // Load Unicode version only for Unicode core
- {
- char szVer[128];
- if (CallService(MS_SYSTEM_GETVERSIONTEXT, (WPARAM)ARRAYSIZE(szVer), (LPARAM)szVer) == 0)
- if (!StrStrA(szVer, "Unicode")) {
- OutputDebugString(_T("Spam Filter: No Unicode core, Unicode version not loaded.\r\n"));
- return 1;
- }
- }
-
- // Get Miranda's simple memory problems catcher
-
- memset(&memoryManagerInterface,0,sizeof(memoryManagerInterface));
- memoryManagerInterface.cbSize = sizeof(memoryManagerInterface);
- CallService(MS_SYSTEM_GET_MMI, 0, (LPARAM)&memoryManagerInterface);
- mir_getUTFI( &utfi );
-
- // Init SpamFilter-API
- InitServices();
-
- // Establish the filter protocol
- InitSpamCheck();
-
- // Installation (making sure files are placed correctly)
- forkthread(ThreadInstallation, 0, NULL);
- hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, AllModulesLoaded);
- if (!hHookModulesLoaded) CallService(MS_SPAMFILTER_SHOWERROR, SFSE_CRITICAL_ERROR, 0);
-
- return 0;
-}
-
-
-__declspec(dllexport) int Unload(void)
-{
- if (hHookModulesLoaded) UnhookEvent(hHookModulesLoaded);
- UninitExtraImg();
- UninitMenuItems();
- UninitOptions();
- UninitPopup();
- UninitSpamCheck();
- UninitVariables();
- UninitServices();
- UninitRegExp();
- UninitSpamDefinitions();
- UninitTrigger();
- UninitFolders();
- return 0;
-}
-
-
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+
+
+
+
+// -- Plugin Info
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "Spam Filter Mod (Unicode)",
+ PLUGIN_VERSION,
+ "Filters out advertisment messages, messages sent by robots and other disliked messages such as hoax messages.", // Gets translated automatically
+ "Heiko Herkenrath",
+ "", // PLUGIN_EMAIL will get set later
+ "© 2003-2006 Heiko Herkenrath",
+ "",
+ 1,
+ 0, // Does not replace anything built-in
+ { 0xecb1c450, 0xf71a, 0x425d, { 0xab, 0x63, 0xed, 0x17, 0x5a, 0x86, 0x23, 0x84 } }
+};
+
+// -- Variables: Events/Hooks
+HANDLE hHookModulesLoaded;
+
+// -----------------------------------------
+
+
+static void ThreadInstallation(void* arg)
+{
+ WCHAR* szFileName = 0;
+
+ if (Miranda_Terminated()) return;
+
+ // Install Files
+ {
+ // Spam Definitions
+ // Move "Spam Filter" subdirectory to Miranda IM folder.
+ // Since the Plugins directory should only contain DLLs and no additional data files
+ GetDefinitionsPath(szFileName, FALSE, NULL);
+ PInstallFile(DATA_SUBDIRECTORY, szFileName);
+
+ // Documentation
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, DOCS_SUBDIRECTORY, NULL, NULL);
+ PInstallFile(_T("SpamFilter-Readme.txt"), szFileName);
+ PInstallFile(_T("SpamFilter-License.txt"), szFileName);
+ PInstallFile(_T("SpamFilter-SDK.zip"), szFileName);
+ PInstallFile(_T("SpamFilter-Translation.txt"), szFileName); // normally in SDK
+ PInstallFile(_T("SpamFilter-Developer.txt"), szFileName); // normally in SDK
+ PInstallFile(_T("m_spamfilter.h"), szFileName); // normally in SDK
+ PInstallFile(_T("m_spamfilter.inc"), szFileName); // normally in SDK
+
+ PInstallFile(_T("SpamDefinitions-*.txt"), szFileName); // additional SpamDefs installed
+
+ PInstallFile(_T("PCRE-License.txt"), szFileName);
+
+ // Sounds
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, SOUNDS_SUBDIRECTORY, NULL, NULL);
+ PInstallFile(DEFAULT_ADVERTISMENT_SOUNDFILE, szFileName);
+ PInstallFile(DEFAULT_DISLIKEDMESSAGE_SOUNDFILE, szFileName);
+ PInstallFile(DEFAULT_ROBOT_SOUNDFILE, szFileName);
+
+ // DLLs (non-plugin)
+ PInstallDLLFile(_T("pcre.dll"), TRUE, TRUE);
+
+ // InstallScript.xml
+ PConstructLocalPath(szFileName, CSIDL_EXT_MODULE, NULL, _T("InstallScript.xml"), NULL);
+ DeleteFile(szFileName);
+ }
+
+ if (Miranda_Terminated()) return;
+
+ // Add default list items
+ {
+ STRINGLIST* pslWords = SLNewList();
+
+ // Create default bad words
+ if (!IsSpamDefinitionDataPresent(SDID_CUSTOM_BADWORDS))
+ {
+ SLAddItem(pslWords, TranslateT("Automated message"));
+ SetSpamDefinitionData(pslWords, SDID_CUSTOM_BADWORDS, NULL);
+
+ SLClearList(pslWords);
+ }
+
+ // Create default good words
+ if (!IsSpamDefinitionDataPresent(SDID_CUSTOM_GOODWORDS))
+ {
+ SLAddItem(pslWords, TranslateT("Miranda IM"));
+ SetSpamDefinitionData(pslWords, SDID_CUSTOM_GOODWORDS, NULL);
+
+ SLClearList(pslWords);
+ }
+
+ // Create default disliked message words
+ if (!IsSpamDefinitionDataPresent(SDID_CUSTOM_DISLIKEDWORDS))
+ {
+ SLAddItem(pslWords, TranslateT("Please forward"));
+ SetSpamDefinitionData(pslWords, SDID_CUSTOM_DISLIKEDWORDS, NULL);
+ }
+
+ SLFreeList(pslWords);
+ }
+
+ if (Miranda_Terminated()) return;
+
+ // On First Run
+ if (DBGetContactSettingDword(NULL, DB_MODULE_NAME, DB_SETTING_FIRSTRUNDONE, 0) != PLUGIN_VERSION) // no use of "<"!
+ {
+ // Import bad words v1.0.4.0 -> v2.0.0.0 (DB->FILE converter)
+ {
+ STRINGLIST* pslBadWords = NULL;
+ STRINGLIST* pslDefaultBadWords = NULL;
+ int i;
+ char szSetting[7+MAX_INT_LENGTH+1];
+ DBVARIANT dbv;
+
+ // Get old bad words out of database
+ for (i=0;; i++) // no break condition
+ {
+ mir_snprintf(szSetting, ARRAYSIZE(szSetting), "BadWord%i", i);
+
+ if (DBGetContactSettingTString(NULL, "SpamFilter", szSetting, &dbv) != 0)
+ break;
+
+ // Load default list when needed
+ if (!pslBadWords)
+ {
+ pslDefaultBadWords = SLNewList();
+ pslBadWords = SLNewList();
+
+ // Load default bad words
+ GetSpamDefinitionData(pslDefaultBadWords, SDID_BADWORDS);
+
+ // Load bad words already in file
+ GetSpamDefinitionData(pslBadWords, SDID_CUSTOM_BADWORDS);
+ }
+
+ if (!SLIsItem(pslDefaultBadWords, dbv.ptszVal, FALSE) && !SLIsItem(pslBadWords, dbv.ptszVal, FALSE))
+ SLAddItem(pslBadWords, dbv.ptszVal);
+
+ DBFreeVariant(&dbv);
+
+ // Delete old setting (important! else it will reimport every version change)
+ DBDeleteContactSetting(NULL, "SpamFilter", szSetting);
+ }
+
+ // Save old and new bad words
+ if (pslBadWords) {
+ SetSpamDefinitionData(pslBadWords, SDID_CUSTOM_BADWORDS, NULL);
+ SLFreeList(pslBadWords);
+ }
+ if (pslDefaultBadWords)
+ SLFreeList(pslDefaultBadWords);
+ }
+
+ if (Miranda_Terminated()) return;
+
+ // Import old spammers in database of v2.0.1.0 (DB->DB converter)
+ {
+ WCHAR* pszSuffix = _T(" (Spammer)"); // readonly allocated
+ WCHAR* pszSuffixT = TranslateTS(pszSuffix);
+ WCHAR* pszUserName;
+ HANDLE hContact;
+ BOOL bIsOldSpammer;
+
+ if (pszSuffix)
+ {
+ for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); hContact; hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0))
+ {
+ // Skip if not hidden
+ if (!DBGetContactSettingByte(hContact, "CList", "Hidden", 0))
+ continue;
+
+ // Skip if is already "new" spammer
+ if (CallService(MS_SPAMFILTER_CONTACT_ISSPAMMER, (WPARAM)hContact, 0))
+ continue;
+
+ pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
+
+ // Find suffix
+ bIsOldSpammer = FALSE;
+ if (lstrlen(pszUserName) > lstrlen(pszSuffix))
+ if (StrCmp(pszUserName+lstrlen(pszUserName)-lstrlen(pszSuffix), pszSuffix) == 0)
+ bIsOldSpammer = TRUE;
+ if (lstrlen(pszUserName) > lstrlen(pszSuffixT))
+ if (StrCmp(pszUserName+lstrlen(pszUserName)-lstrlen(pszSuffixT), pszSuffixT) == 0)
+ bIsOldSpammer = TRUE;
+
+ if (bIsOldSpammer)
+ CallService(MS_SPAMFILTER_CONTACT_SETASSPAMMER, (WPARAM)hContact, (LPARAM)SCASF_NO_NOTIFY|SCASF_NO_REMOVE_HISTORY|SCASF_NO_DENY_AUTHREQUESTS);
+ }
+ }
+
+ }
+
+ if (Miranda_Terminated()) return;
+
+ // Import Spam Definition Data previous to v2.5.0.0 (ANSI->UTF8 converter)
+ {
+ // own-badwords.sfw
+ PConstructLocalPath(szFileName, CSIDL_EXT_MIRANDAPROFILE, _T("Spam Filter"), _T("own-badwords.sfw"), NULL);
+ mir_utf8encodeW(szFileName); // current codepage
+
+ // own-goodwords.sfw
+ PConstructLocalPath(szFileName, CSIDL_EXT_MIRANDAPROFILE, _T("Spam Filter"), _T("own-goodwords.sfw"), NULL);
+ mir_utf8encodeW(szFileName); // current codepage
+
+ // own-dislikedwords.sfw
+ PConstructLocalPath(szFileName, CSIDL_EXT_MIRANDAPROFILE, _T("Spam Filter"), _T("own-dislikedwords.sfw"), NULL);
+ mir_utf8encodeW(szFileName); // current codepage
+
+ // BadWords\*.sfw
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("Chinese (Traditional).sfw"), NULL);
+ mir_utf8encodeW(szFileName); // big5 codepage (Chinese) [PRC and Singapore have other codepages]
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("Russian.sfw"), NULL);
+ mir_utf8encodeW(szFileName); // cp-1251 codepage (Russian)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("English.sfw"), NULL);
+ mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("German.sfw"), NULL);
+ mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("French.sfw"), NULL);
+ mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("Portuguese (Brazil).sfw"), NULL);
+ mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\BadWords"), _T("*.sfw"), NULL);
+ mir_utf8encodeW(szFileName); // customized reminder
+
+ // HoaxTexts\*.sft
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\HoaxTexts"), _T("Example.sft"), NULL);
+ mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\HoaxTexts"), _T("Example.sft"), NULL);
+ mir_utf8encodeW(szFileName); // customized reminder
+
+ // Teasers\*.sft
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Teasers"), _T("English.sft"), NULL);
+ mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Teasers"), _T("German.sft"), NULL);
+ mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Teasers"), _T("*.sft"), NULL);
+ mir_utf8encodeW(szFileName); // reminder customized
+
+ // Urls\*.sfc
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Urls"), _T("*.sfc"), NULL);
+ mir_utf8encodeW(szFileName); // url strings are all English
+
+ // PhoneNumbers\*.sfc
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\PhoneNumbers"), _T("Russian.sfc"), NULL);
+ mir_utf8encodeW(szFileName); // cp-1251 codepage (Russian)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\PhoneNumbers"), _T("German.sfc"), NULL);
+ mir_utf8encodeW(szFileName); // English, German, French, Portuguese codepage (European)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\PhoneNumbers"), _T("*.sfc"), NULL);
+ mir_utf8encodeW(szFileName); // reminder customizd
+
+ // Spammers\*.sfc
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Spammers"), _T("Russian.sfc"), NULL);
+ mir_utf8encodeW(szFileName); // cp-1251 codepage (Russian)
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter\\Spammers"), _T("*.sfc"), NULL);
+ mir_utf8encodeW(szFileName); // reminder customized
+
+ // format_text.sfc
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter"), _T("format_text.sfc"), NULL);
+ mir_utf8encodeW(szFileName); // was English only
+
+ // format_numbers.sfc
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter"), _T("format_numbers.sfc"), NULL);
+ mir_utf8encodeW(szFileName); // was English only
+
+ // separators.sfc
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, _T("Spam Filter"), _T("separators.sfc"), NULL);
+ mir_utf8encodeW(szFileName); // was English only
+ }
+
+ if (Miranda_Terminated()) return;
+
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER) || DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)DEFAULT_SETTING_ROBOTFILTER))
+ {
+ CallService(MS_IGNORE_UNIGNORE, (WPARAM)NULL, (LPARAM)IGNOREEVENT_MESSAGE);
+ CallService(MS_IGNORE_UNIGNORE, (WPARAM)NULL, (LPARAM)IGNOREEVENT_URL);
+ CallService(MS_IGNORE_UNIGNORE, (WPARAM)NULL, (LPARAM)IGNOREEVENT_FILE);
+ CallService(MS_IGNORE_UNIGNORE, (WPARAM)NULL, (LPARAM)IGNOREEVENT_AUTHORIZATION);
+
+ CallService(MS_IGNORE_IGNORE, (WPARAM)NULL, (LPARAM)IGNOREEVENT_USERONLINE);
+
+ {
+ DBVARIANT dbv;
+
+ if (DBGetContactSetting(NULL, "SRMM", "UnknownTyping", &dbv) == 0) // If existant
+ {
+ if (dbv.type == DBVT_BYTE)
+ DBWriteContactSettingByte(NULL, "SRMM", "UnknownTyping", 0);
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+
+ // Disable "old"/other spam plugins (if installed) to avoid conflicts and user confusion
+ // (All features of them included in Spam Filter)
+ if (GetModuleHandle(_T("SpamBlock")))
+ DBWriteContactSettingByte(NULL, "PluginDisable", "spamblock.dll", 1);
+ if (GetModuleHandle(_T("SpamBlockPlus")))
+ DBWriteContactSettingByte(NULL, "PluginDisable", "spamblockplus.dll", 1);
+ if (GetModuleHandle(_T("spamreturner")))
+ DBWriteContactSettingByte(NULL, "PluginDisable", "spamreturner.dll", 1);
+ if (GetModuleHandle(_T("stopspam"))) {
+ DBWriteContactSettingByte(NULL, "PluginDisable", "stopspam.dll", 1);
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)TRUE);
+ }
+ if (GetModuleHandle(_T("ignorecontact")))
+ DBWriteContactSettingByte(NULL, "PluginDisable", "ignorecontact.dll", 1);
+
+ #if defined (UNICODE)
+ DBWriteContactSettingByte(NULL, "PluginDisable", "spamfilter.dll", 1);
+ #else
+ DBWriteContactSettingByte(NULL, "PluginDisable", "spamfilterw.dll", 1);
+ #endif
+
+ // FirstRunDone
+ DBWriteContactSettingDword(NULL, DB_MODULE_NAME, DB_SETTING_FIRSTRUNDONE, PLUGIN_VERSION);
+ }
+}
+
+
+__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ if (mirandaVersion < NEEDED_MIRANDA_VERSION)
+ {
+ // No Translate() here! (langpack service not yet loaded, no need anyway)
+ MessageBoxEx(NULL, _T("The Spam Filter plugin can not be loaded. It requires Miranda IM ")_T(NEEDED_MIRANDA_VERSION_STR)_T(" or later."), _T("Spam Filter Plugin"), MB_OK|MB_ICONERROR|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
+ return NULL;
+ }
+
+ return &pluginInfo;
+}
+static const MUUID interfaces[] = {MIID_SERVICEMODE, MIID_LAST};
+__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+
+ return TRUE;
+}
+
+
+
+static int AllModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ AssignAllContacts();
+
+ // Custom Profile Folder Plugin support (as early as possible!)
+ InitFolders();
+
+ // Definition file cache (after folder)
+ InitSpamDefinitions();
+
+ // Load regular expressions DLL
+ // Important: Not in Load() to allow other plugins to update/replace the DLL in their Load()
+ InitRegExp();
+
+ // Trigger Plugin support
+ InitTrigger();
+
+ // Add message types for filter
+ {
+ int i, iProtoCount = 0;
+ WCHAR szProtoNameBuf[256];
+ WCHAR* pszProtoName;
+ DWORD dwProtoCaps, dwProtoCaps4;
+ HICON hProtoIcon;
+ PROTOCOLDESCRIPTOR** appd = NULL;
+
+ if (CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&iProtoCount, (LPARAM)&appd) == 0)
+ {
+ for (i=0; i<iProtoCount; i++)
+ {
+ if (appd[i]->type != PROTOTYPE_PROTOCOL) continue;
+
+ // Get capabilities
+ dwProtoCaps = CallProtoService(appd[i]->szName, PS_GETCAPS, (WPARAM)PFLAGNUM_1, 0);
+ if ((int)dwProtoCaps == CALLSERVICE_NOTFOUND) continue;
+ dwProtoCaps4 = CallProtoService(appd[i]->szName, PS_GETCAPS, (WPARAM)PFLAGNUM_4, 0);
+
+ // Get icon
+ hProtoIcon = (HICON)CallProtoService(appd[i]->szName, PS_LOADICON, PLI_PROTOCOL|PLIF_SMALL, 0);
+ if ((int)hProtoIcon == CALLSERVICE_NOTFOUND) hProtoIcon = NULL;
+
+ // Get readable name
+ #if defined(UNICODE)
+ if (CallProtoService(appd[i]->szName, PS_GETNAME"W", ARRAYSIZE(szProtoNameBuf), (LPARAM)szProtoNameBuf) == 0) {
+ pszProtoName = szProtoNameBuf;
+ } else if (CallProtoService(appd[i]->szName, PS_GETNAME, ARRAYSIZE(szProtoNameBuf), (LPARAM)szProtoNameBuf) == 0) {
+ pszProtoName = (WCHAR*)mir_utf8encodeW(szProtoNameBuf);
+ } else {
+ pszProtoName = (WCHAR*)mir_utf8encodeW((WCHAR*)appd[i]->szName);
+ }
+ #else
+ if (CallProtoService(appd[i]->szName, PS_GETNAME, ARRAYSIZE(szProtoNameBuf), (LPARAM)szProtoNameBuf) == 0) {
+ pszProtoName = szProtoNameBuf;
+ } else {
+ pszProtoName = appd[i]->szName;
+ }
+ #endif
+
+ // Authorization Requests (flag supported and display module installed)
+ if (dwProtoCaps&PF1_AUTHREQ)
+ SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_AUTHREQUEST, TranslateT("Authorization Request"), (HICON)-SKINICON_OTHER_MIRANDA, 100, ((dwProtoCaps4&PF4_FORCEAUTH) ? MTDF_DEFAULTDISABLED : 0));
+
+ // YouWereAdded Notification (flag supported and display module installed)
+ if (dwProtoCaps&PF1_ADDED)
+ SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_ADDED, TranslateT("Added Notification"), (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(210), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED), 110, ((dwProtoCaps4&PF4_FORCEADDED) ? MTDF_DEFAULTDISABLED : 0));
+
+ // Special support for ICQ (workaround, quite hacky)
+ if (StrCmpA(appd[i]->szName, "ICQ") == 0)
+ {
+ // WebPager (display module installed: WebPager Plugin)
+ if (ServiceExists("WebPager/ReceiveWebPager"))
+ SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, "WebPager", TranslateT("WebPager"), GetModuleHandle(_T("WebPager")) ? (HICON)LoadImage(GetModuleHandle(_T("WebPager")), MAKEINTRESOURCE(101), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) : NULL, 200, 0);
+
+ // EmailExpress (display module installed: EmailExpress Plugin)
+ if (ServiceExists("EmailExpress/ReceiveEmailExpress"))
+ SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, "EmailExpress", TranslateT("EmailExpress"), GetModuleHandle(_T("EmailExpress")) ? (HICON)LoadImage(GetModuleHandle(_T("EmailExpress")), MAKEINTRESOURCE(102), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) : NULL, 210, 0);
+ }
+
+ // Instant Messages (flag supported and display module installed)
+ if ((dwProtoCaps&PF1_IMRECV) && ServiceExists(MS_MSG_SENDMESSAGE))
+ SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_MESSAGE, TranslateT("Message"), (HICON)-SKINICON_EVENT_MESSAGE, 300, ((dwProtoCaps&PF1_IMSEND) ? 0 : MTDF_DEFAULTDISABLED));
+
+ // URLs (flag supported and display module installed)
+ if ((dwProtoCaps&PF1_URLRECV) && ServiceExists(MS_URL_SENDURL))
+ SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_URL, TranslateT("URL"), (HICON)-SKINICON_EVENT_URL, 400, ((dwProtoCaps&PF1_URLSEND) ? 0 : MTDF_DEFAULTDISABLED));
+
+ // File Transfers (flag supported and display module installed)
+ if ((dwProtoCaps&PF1_FILERECV) && ServiceExists(MS_FILE_SENDFILE))
+ SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_FILE, TranslateT("File"), (HICON)-SKINICON_EVENT_FILE, 500, ((dwProtoCaps&PF1_FILESEND) ? 0 : MTDF_DEFAULTDISABLED));
+
+ // Contact Transfers (flag supported and display module installed)
+ if ((dwProtoCaps&PF1_CONTACTRECV) && ServiceExists(MS_CONTACTS_SEND))
+ SFRegisterMessageType(appd[i]->szName, pszProtoName, hProtoIcon, SFMT_CONTACTS, TranslateT("Contacts"), GetModuleHandle(_T("contacts")) ? (HICON)LoadImage(GetModuleHandle(_T("contacts")), MAKEINTRESOURCE(109), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) : NULL, 600, ((dwProtoCaps&PF1_CONTACTSEND) ? 0 : MTDF_DEFAULTDISABLED));
+
+
+ if (hProtoIcon) DestroyIcon(hProtoIcon); // must be destroyed
+
+ #if defined(UNICODE)
+ if (pszProtoName != szProtoNameBuf)
+ mir_free(pszProtoName);
+ #endif
+ }
+ }
+ }
+
+ // Options
+ InitOptions();
+
+ // Add sounds
+ SkinAddNewSoundBundled(DB_SOUND_ADVERTISMENT_SETTING, Translate("Spam Filter"), Translate("Advertisment Alert"), DEFAULT_ADVERTISMENT_SOUNDFILE);
+ SkinAddNewSoundBundled(DB_SOUND_DISLIKEDMESSAGE_SETTING, Translate("Spam Filter"), Translate("Disliked Message Alert"), DEFAULT_DISLIKEDMESSAGE_SOUNDFILE);
+ SkinAddNewSoundBundled(DB_SOUND_ROBOT_SETTING, Translate("Spam Filter"), Translate("Robot Alert"), DEFAULT_ROBOT_SOUNDFILE);
+
+ // Add known database modules (Support for DBEditor++)
+ if (ServiceExists("DBEditorpp/RegisterModule"))
+ {
+ const char* apszModuleNames[] = {DB_MODULE_NAME, DB_MODULE_NAME_MSGTYPES, DB_MODULE_NAME_PRESPAMMERS};
+ CallService("DBEditorpp/RegisterModule", (WPARAM)apszModuleNames, (LPARAM)ARRAYSIZE(apszModuleNames));
+ }
+
+ // Support for own variables in Variables-Plugin
+ InitVariables();
+
+ // Init CList extra image (for spammers)
+ InitExtraImg();
+
+ // Support for Popup/PopupPlus Plugin
+ if (IsPopupAvailable(FALSE))
+ {
+ BOOL bFilterActive = DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, DEFAULT_SETTING_ADVERTISMENTFILTER) || DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, DEFAULT_SETTING_DISLIKEDMESSAGEFILTER);
+ BOOL bPopupsActive = DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, DEFAULT_SETTING_POPUP);
+
+ InitPopup();
+
+ // Init popup menu item
+ SetPopupMenuItem(bPopupsActive, !bFilterActive);
+
+ // Add colors
+ SkinAddNewColor(DB_COLOR_POPUPBACKGROUND_SETTING, Translate("Spam Filter"), Translate("Popup Background"), RGB(213,209,208), FALSE);
+ SkinAddNewColor(DB_COLOR_POPUPTEXT_SETTING, Translate("Spam Filter"), Translate("Popup Text"), RGB(193,0,38), FALSE);
+ }
+
+ // Init contact menu item
+ InitMenuItems();
+
+ // SpamFilter fully loaded
+ NotifyModuleLoaded();
+ return 0;
+}
+
+
+__declspec(dllexport) int Load(PLUGINLINK* link)
+{
+ pluginLink = (PLUGINLINK*)link;;
+
+ hwndSpamFilterOpt = NULL;
+ hwndAdvertismentFilter = NULL;
+ hwndRobotFilter = NULL;
+ hwndDislikedMessagesFilter = NULL;
+ hwndSpamDefinitionsInfo = NULL;
+ hwndSpammersInfo = NULL;
+
+ if (!ServiceExists(MS_DB_CONTACT_GETSETTING_STR))
+ {
+ // No Translate() here
+ MessageBoxEx(NULL, _T("The Spam Filter plugin requires database driver (db3x) 0.5.1.0 or later."), _T("Spam Filter Plugin"), MB_OK|MB_ICONERROR|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
+ return 1;
+ }
+
+ // Load Unicode version only for Unicode core
+ {
+ char szVer[128];
+ if (CallService(MS_SYSTEM_GETVERSIONTEXT, (WPARAM)ARRAYSIZE(szVer), (LPARAM)szVer) == 0)
+ if (!StrStrA(szVer, "Unicode")) {
+ OutputDebugString(_T("Spam Filter: No Unicode core, Unicode version not loaded.\r\n"));
+ return 1;
+ }
+ }
+
+ // Get Miranda's simple memory problems catcher
+
+ memset(&memoryManagerInterface,0,sizeof(memoryManagerInterface));
+ memoryManagerInterface.cbSize = sizeof(memoryManagerInterface);
+ CallService(MS_SYSTEM_GET_MMI, 0, (LPARAM)&memoryManagerInterface);
+ mir_getUTFI( &utfi );
+
+ // Init SpamFilter-API
+ InitServices();
+
+ // Establish the filter protocol
+ InitSpamCheck();
+
+ // Installation (making sure files are placed correctly)
+ forkthread(ThreadInstallation, 0, NULL);
+ hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, AllModulesLoaded);
+ if (!hHookModulesLoaded) CallService(MS_SPAMFILTER_SHOWERROR, SFSE_CRITICAL_ERROR, 0);
+
+ return 0;
+}
+
+
+__declspec(dllexport) int Unload(void)
+{
+ if (hHookModulesLoaded) UnhookEvent(hHookModulesLoaded);
+ UninitExtraImg();
+ UninitMenuItems();
+ UninitOptions();
+ UninitPopup();
+ UninitSpamCheck();
+ UninitVariables();
+ UninitServices();
+ UninitRegExp();
+ UninitSpamDefinitions();
+ UninitTrigger();
+ UninitFolders();
+ return 0;
+}
+
+
diff --git a/menuitems.c b/menuitems.c
index ff0412e..9bb5745 100644
--- a/menuitems.c
+++ b/menuitems.c
@@ -1,136 +1,136 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -- Variables: Events/Hooks
-HANDLE hHookPreBuildContactMenu;
-HANDLE hHookIconsChanged;
-
-
-// -----------------------------------------
-
-
-// -- Contact Menu Items --
-
-void SetContactMenuItem_Mark(BOOL bShowItem)
-{
- static HANDLE hContactMenuItemMark = NULL;
- CLISTMENUITEM cmi;
-
- ZeroMemory(&cmi, sizeof(cmi));
- cmi.cbSize = sizeof(cmi);
- cmi.flags = CMIF_NOTONLIST;
- if (!bShowItem) cmi.flags |= CMIF_HIDDEN;
- cmi.hIcon = SkinGetIcon(DB_ICON_SPAMMANUALLY_SETTING, IDI_DEFAULT, FALSE);
-
- if (hContactMenuItemMark)
- {
- cmi.flags |= CMIM_FLAGS|CMIM_ICON;
- CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuItemMark, (LPARAM)&cmi);
-
- } else {
-
- cmi.pszName = Translate("&Mark as spammer");
- cmi.position = -2050000001; // "Add user to contact list"/"Add permanently to list" is -2050000000
- cmi.pszService = MS_SPAMFILTER_CONTACT_SHOWSETASSPAMMERDIALOG;
-
- hContactMenuItemMark = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&cmi);
- }
-}
-
-
-void SetContactMenuItem_Unmark(BOOL bShowItem)
-{
- static HANDLE hContactMenuItemUnmark = NULL;
- CLISTMENUITEM cmi;
-
- ZeroMemory(&cmi, sizeof(cmi));
- cmi.cbSize = sizeof(cmi);
- cmi.flags = CMIF_NOTOFFLIST;
- if (!bShowItem) cmi.flags |= CMIF_HIDDEN;
- cmi.hIcon = SkinGetIcon(DB_ICON_SPAMMANUALLY_SETTING, IDI_DEFAULT, FALSE);
-
- if (hContactMenuItemUnmark)
- {
- cmi.flags |= CMIM_FLAGS|CMIM_ICON;
- CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuItemUnmark, (LPARAM)&cmi);
-
- } else {
-
- cmi.pszName = Translate("&Unmark spammer");
- cmi.position = -2050000001; // "Add user to contact list"/"Add permanently to list" is -2050000000
- cmi.pszService = MS_SPAMFILTER_CONTACT_UNSETSPAMMER;
-
- hContactMenuItemUnmark = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&cmi);
- }
-}
-
-
-static int IconsChanged(WPARAM wParam, LPARAM lParam)
-{
- // Update menu item
- SetContactMenuItem_Mark(TRUE);
- SetContactMenuItem_Unmark(FALSE);
- return 0;
-}
-
-
-static int PreBuildContactMenu(WPARAM wParam, LPARAM lParam)
-{
- HANDLE hContact = (HANDLE)wParam;
- char* pszProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
-
- if (hContact && pszProto)
- if (!DBGetContactSettingByte(hContact, pszProto, "ChatRoom", 0))
- {
- BOOL bNotOnList = DBGetContactSettingByte(hContact, "CList", "NotOnList", 0);
- BOOL bIsSpammer = DBGetContactSettingByte((HANDLE)wParam, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)FALSE);
-
- SetContactMenuItem_Mark(bNotOnList && !bIsSpammer);
- SetContactMenuItem_Unmark(bIsSpammer && !IsWindow(hwndSpammersInfo));
- }
-
- return 0;
-}
-
-
-// -----------------------------------------
-
-
-void InitMenuItems(void)
-{
- if (ServiceExists(MS_SKIN2_GETICON))
- hHookIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, IconsChanged);
-
- hHookPreBuildContactMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PreBuildContactMenu);
-
- SetContactMenuItem_Mark(TRUE);
- SetContactMenuItem_Unmark(FALSE);
-}
-
-void UninitMenuItems(void)
-{
- if (hHookPreBuildContactMenu) UnhookEvent(hHookPreBuildContactMenu);
- if (hHookIconsChanged) UnhookEvent(hHookIconsChanged);
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -- Variables: Events/Hooks
+HANDLE hHookPreBuildContactMenu;
+HANDLE hHookIconsChanged;
+
+
+// -----------------------------------------
+
+
+// -- Contact Menu Items --
+
+void SetContactMenuItem_Mark(BOOL bShowItem)
+{
+ static HANDLE hContactMenuItemMark = NULL;
+ CLISTMENUITEM cmi;
+
+ ZeroMemory(&cmi, sizeof(cmi));
+ cmi.cbSize = sizeof(cmi);
+ cmi.flags = CMIF_NOTONLIST;
+ if (!bShowItem) cmi.flags |= CMIF_HIDDEN;
+ cmi.hIcon = SkinGetIcon(DB_ICON_SPAMMANUALLY_SETTING, IDI_DEFAULT, FALSE);
+
+ if (hContactMenuItemMark)
+ {
+ cmi.flags |= CMIM_FLAGS|CMIM_ICON;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuItemMark, (LPARAM)&cmi);
+
+ } else {
+
+ cmi.pszName = Translate("&Mark as spammer");
+ cmi.position = -2050000001; // "Add user to contact list"/"Add permanently to list" is -2050000000
+ cmi.pszService = MS_SPAMFILTER_CONTACT_SHOWSETASSPAMMERDIALOG;
+
+ hContactMenuItemMark = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&cmi);
+ }
+}
+
+
+void SetContactMenuItem_Unmark(BOOL bShowItem)
+{
+ static HANDLE hContactMenuItemUnmark = NULL;
+ CLISTMENUITEM cmi;
+
+ ZeroMemory(&cmi, sizeof(cmi));
+ cmi.cbSize = sizeof(cmi);
+ cmi.flags = CMIF_NOTOFFLIST;
+ if (!bShowItem) cmi.flags |= CMIF_HIDDEN;
+ cmi.hIcon = SkinGetIcon(DB_ICON_SPAMMANUALLY_SETTING, IDI_DEFAULT, FALSE);
+
+ if (hContactMenuItemUnmark)
+ {
+ cmi.flags |= CMIM_FLAGS|CMIM_ICON;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuItemUnmark, (LPARAM)&cmi);
+
+ } else {
+
+ cmi.pszName = Translate("&Unmark spammer");
+ cmi.position = -2050000001; // "Add user to contact list"/"Add permanently to list" is -2050000000
+ cmi.pszService = MS_SPAMFILTER_CONTACT_UNSETSPAMMER;
+
+ hContactMenuItemUnmark = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&cmi);
+ }
+}
+
+
+static int IconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ // Update menu item
+ SetContactMenuItem_Mark(TRUE);
+ SetContactMenuItem_Unmark(FALSE);
+ return 0;
+}
+
+
+static int PreBuildContactMenu(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ char* pszProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if (hContact && pszProto)
+ if (!DBGetContactSettingByte(hContact, pszProto, "ChatRoom", 0))
+ {
+ BOOL bNotOnList = DBGetContactSettingByte(hContact, "CList", "NotOnList", 0);
+ BOOL bIsSpammer = DBGetContactSettingByte((HANDLE)wParam, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)FALSE);
+
+ SetContactMenuItem_Mark(bNotOnList && !bIsSpammer);
+ SetContactMenuItem_Unmark(bIsSpammer && !IsWindow(hwndSpammersInfo));
+ }
+
+ return 0;
+}
+
+
+// -----------------------------------------
+
+
+void InitMenuItems(void)
+{
+ if (ServiceExists(MS_SKIN2_GETICON))
+ hHookIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, IconsChanged);
+
+ hHookPreBuildContactMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PreBuildContactMenu);
+
+ SetContactMenuItem_Mark(TRUE);
+ SetContactMenuItem_Unmark(FALSE);
+}
+
+void UninitMenuItems(void)
+{
+ if (hHookPreBuildContactMenu) UnhookEvent(hHookPreBuildContactMenu);
+ if (hHookIconsChanged) UnhookEvent(hHookIconsChanged);
} \ No newline at end of file
diff --git a/menuitems.h b/menuitems.h
index c116a13..4e76c75 100644
--- a/menuitems.h
+++ b/menuitems.h
@@ -1,30 +1,30 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_MENUITEMS_H__
-#define SF_MENUITEMS_H__ 1
-
-
-// -- Prototypes
-void InitMenuItems(void);
-void UninitMenuItems(void);
-
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_MENUITEMS_H__
+#define SF_MENUITEMS_H__ 1
+
+
+// -- Prototypes
+void InitMenuItems(void);
+void UninitMenuItems(void);
+
#endif // SF_MENUITEMS_H__ \ No newline at end of file
diff --git a/options.c b/options.c
index 62c2af3..dc91247 100644
--- a/options.c
+++ b/options.c
@@ -1,3699 +1,3699 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -- Variables: Events/Services
-HANDLE hHookOptInit = NULL;
-HANDLE hHookDbSettingChangedOpt = NULL;
-
-// -- Defines: Self-defined dialog messages
-#define SFM_ENABLE_SUBCTRLS (WM_APP+121) // wParam=lParam=0
-#define SFM_REMOVE_SPAMDEFINITIONFILE (WM_APP+122) // wParam=(int)listIndex, lParam=0
-
-// -- Structs
-struct WORDSLISTBOXADDITEMPARAMS
-{
- POINT ptPos;
- WCHAR* pszTitle;
- WCHAR* pszNewItem;
-};
-
-
-// -----------------------------------------
-
-
-BOOL CALLBACK DlgProcSpamFilterOpt(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg)
- {
- /*
- #if defined(UNICODE)
- case WM_NOTIFYFORMAT:
- {
- SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)NFR_UNICODE);
- return TRUE;
- }
- #endif
- */
-
- case WM_INITDIALOG:
- {
- hwndSpamFilterOpt = hwndDlg;
-
- /*
- #if defined(UNICODE)
- // Convert DlgProc to Unicode (IsWindowUnicode returns true after this call -> see docs)
- SetWindowLongPtrW(hwndDlg, DWLP_DLGPROC, (LONG_PTR)DlgProcSpamFilterOpt);
- #endif
- */
-
- // Init treeview (TVS_CHECKBOXES style is too buggy [it behaves incorrect when space pressed on sections], so self-implementing checkboxes)
- // The treeview does checkboxes exactly the same as it is done here
- TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES), LoadSystemCheckboxImageList(), TVSIL_STATE);
-
- // Translate dialog
- TranslateDialogDefault(hwndDlg);
-
- // Set font
- {
- HFONT hUnderlinedFont;
- LOGFONT lf;
-
- GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER, WM_GETFONT, 0, 0), sizeof(lf), &lf);
- lf.lfUnderline = TRUE;
- hUnderlinedFont = CreateFontIndirect(&lf);
-
- SendDlgItemMessage(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER, WM_SETFONT, (WPARAM)hUnderlinedFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER, WM_SETFONT, (WPARAM)hUnderlinedFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_CHECKBOX_ROBOTFILTER, WM_SETFONT, (WPARAM)hUnderlinedFont, 0);
- }
-
- // Init file name control
- {
- RECT rc;
-
- // Set icon and resize button
- SendDlgItemMessage(hwndDlg, IDC_BUTTON_LOGBROWSE, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)LoadSystemIcon(IDB_STD_SMALL_COLOR, STD_FILEOPEN));
- SetWindowPos(GetDlgItem(hwndDlg, IDC_BUTTON_LOGBROWSE), NULL, 0, 0, 20, 20, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
-
- // Transform into file edit browse combo control
- MakePathEditCtrl(GetDlgItem(hwndDlg, IDC_EDITBOX_LOGFILE), GetDlgItem(hwndDlg, IDC_BUTTON_LOGBROWSE));
-
- if (GetClientRect(GetDlgItem(hwndDlg, IDC_BUTTON_OPENLOG), &rc))
- SetWindowPos(GetDlgItem(hwndDlg, IDC_BUTTON_OPENLOG), NULL, 0, 0, (rc.right-rc.left), (rc.bottom-rc.top)+2*GetSystemMetrics(SM_CYBORDER), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
-
- // Forwarding all file drag/drops of spam filter options to the file edit
- // (child windows of childs seem not to receive that message...)
- DragAcceptFiles(hwndDlg, (BOOL)SendMessage(GetParent(hwndDlg), PSM_ISEXPERT, 0, 0));
- }
-
- // Load log file from database
- {
- DBVARIANT dbv;
-
- if(DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_LOGFILE, &dbv) == 0) // If existant
- {
- SetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, dbv.ptszVal);
- DBFreeVariant(&dbv);
-
- } else {
- // Nothing specified, display default log filename and path
- WCHAR szLogFile[MAX_PATH];
-
- PConstructLocalPath(szLogFile, CSIDL_EXT_EXECUTABLE, LOGS_SUBDIRECTORY, DEFAULT_LOGFILE, NULL);
- PMakePathPretty(szLogFile, PC_ABSOLUTERELATIVE);
-
- SetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile);
- }
- }
-
- // Init checkboxes
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER) ? BST_CHECKED : BST_UNCHECKED));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)DEFAULT_SETTING_DISLIKEDMESSAGEFILTER) ? BST_CHECKED : BST_UNCHECKED));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_ROBOTFILTER, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)DEFAULT_SETTING_ROBOTFILTER) ? BST_CHECKED : BST_UNCHECKED));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_POPUP, IsPopupAvailable(TRUE) ? DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, (BYTE)(DEFAULT_SETTING_POPUP ? BST_CHECKED : BST_UNCHECKED)) : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_AUTOADDSPAMMERS, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, (BYTE)(DEFAULT_SETTING_AUTOADDSPAMMERS ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_LOGGING, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, (BYTE)DEFAULT_SETTING_LOGGING) ? BST_CHECKED : BST_UNCHECKED));
-
- // Check/Uncheck radio buttons:
- // Delete/Mark read?
- CheckRadioButton(hwndDlg, IDC_RADIO_MARKREADMSG, IDC_RADIO_DELETEMSG, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, (BYTE)DEFAULT_SETTING_BEHAVIOUR) == 1) ? IDC_RADIO_MARKREADMSG : IDC_RADIO_DELETEMSG);
-
- // Init sub control state
- SendMessage(hwndDlg, SFM_ENABLE_SUBCTRLS, 0, 0);
- SendMessage(hwndDlg, SFM_REBUILD_MSGTYPES, 0, 0);
-
- SendMessage(hwndDlg, SFM_CHECK_AUTOIGNORE, 0, 0);
- PostMessage(hwndDlg, SFM_VALIDATE_LOGFILENAME, 0, 0);
- return TRUE;
- }
-
- case SFM_ENABLE_SUBCTRLS:
- {
- BOOL bStatus;
-
- // IDC_CHECKBOX_ADVERTISMENTFILTER
- BOOL bStatusRobotFilter = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ROBOTFILTER) == BST_CHECKED);
- BOOL bStatusChainFilter = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER) == BST_CHECKED);
- BOOL bStatusAdvertismentFilter = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER) == BST_CHECKED);
- bStatus = bStatusAdvertismentFilter || bStatusChainFilter || bStatusRobotFilter;
-
- EnableDlgItem(hwndDlg, IDC_BUTTON_ADVERTISMENTFILTER, bStatusAdvertismentFilter);
- EnableDlgItem(hwndDlg, IDC_BUTTON_DISLIKEDMESSAGEFILTER, bStatusChainFilter);
- EnableDlgItem(hwndDlg, IDC_BUTTON_ROBOTFILTER, bStatusRobotFilter);
-
- EnableDlgItem(hwndDlg, IDC_GROUP_BEHAVIOUR, bStatus);
- EnableDlgItem(hwndDlg, IDC_RADIO_MARKREADMSG, bStatus);
- EnableDlgItem(hwndDlg, IDC_RADIO_DELETEMSG, bStatus);
-
- EnableDlgItem(hwndDlg, IDC_GROUP_IGNORE, bStatus);
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_AUTOADDSPAMMERS, bStatus);
-
- EnableDlgItem(hwndDlg, IDC_GROUP_LOGGING, bStatus);
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_LOGGING, bStatus);
-
- EnableDlgItem(hwndDlg, IDC_GROUP_MESSAGETYPES, bStatus);
- EnableDlgItem(hwndDlg, IDC_TEXT_MESSAGETYPES, bStatus);
- EnableDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES, bStatus);
-
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_POPUP, IsPopupAvailable(TRUE) ? bStatus: FALSE);
-
- // Auto Ignore
- SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDSPAMMESSAGES), bStatusRobotFilter?1:0, 999, DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, (DWORD)DEFAULT_SETTING_ALLOWEDSPAMMESSAGES), FALSE);
- bStatus = (IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHECKBOX_AUTOADDSPAMMERS)) && (IsDlgButtonChecked(hwndDlg,IDC_CHECKBOX_AUTOADDSPAMMERS) == BST_CHECKED));
- EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDSPAMMESSAGES, bStatus);
- EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDSPAMMESSAGES, bStatus);
- EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDSPAMMESSAGES, bStatus);
-
- // Logging
- bStatus = (IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHECKBOX_LOGGING)) && (IsDlgButtonChecked(hwndDlg,IDC_CHECKBOX_LOGGING) == BST_CHECKED));
- EnableDlgItem(hwndDlg, IDC_EDITBOX_LOGFILE, bStatus);
- EnableDlgItem(hwndDlg, IDC_BUTTON_LOGBROWSE, bStatus);
-
- return TRUE;
- }
-
- case SFM_REBUILD_MSGTYPES:
- {
- HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES);
- HIMAGELIST hImageList;
-
- unsigned int u;
- char* pszSetting;
- TVINSERTSTRUCT tvis;
- BOOL bUseSections;
-
- HTREEITEM hItem;
- MESSAGETYPEDESC* pmtd;
- int iCmpResult;
-
- // Clear treeview
- TreeView_DeleteAllItems(hwndTreeView);
-
- if (InSendMessage())
- ReplyMessage(TRUE);
-
- // Check if only one section is installed
- // -> if only one section is installed it is not necessary to show the section
- EnterCriticalSection(&csMsgTypes); // thread safety
-
- bUseSections = !IsOnlyOneMsgTypeSectionRegistered();
-
- // New image list
- hImageList = TreeView_GetImageList(hwndTreeView, TVSIL_NORMAL);
- if (hImageList) ImageList_Destroy(hImageList);
- hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON), (IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK, uMsgTypesCount, bUseSections?uMsgTypesCount:0); // includes msgtype and section images
- TreeView_SetImageList(hwndTreeView, hImageList, TVSIL_NORMAL);
-
- // Add items to treeview
- if (pamtdMsgTypes)
- {
- for (u=0; u<uMsgTypesCount; u++)
- {
- if (pamtdMsgTypes[u].dwFlags&MTDF_HIDDEN) continue;
-
- if (!bUseSections)
- {
- tvis.hParent = NULL;
-
- } else {
- // Find section if already added
- tvis.hParent = NULL;
- for (hItem=TreeView_GetRoot(hwndTreeView); hItem; hItem=TreeView_GetNextSibling(hwndTreeView, hItem))
- {
- pmtd = GetDataFromTreeViewItem(hwndTreeView, hItem);
- if (pmtd)
- if (StrCmpA(pamtdMsgTypes[u].pszSection, pmtd->pszSection) == 0)
- {
- tvis.hParent = hItem;
- break;
- }
- }
-
- // Section does not yet exist: add it first
- if (!tvis.hParent)
- {
- tvis.item.mask = TVIF_TEXT|TVIF_STATE|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
- tvis.item.pszText = pamtdMsgTypes[u].ptszSectionDescription;
- tvis.item.stateMask = TVIS_BOLD|TVIS_EXPANDED|TVIS_STATEIMAGEMASK;
- tvis.item.state = TVIS_BOLD|TVIS_EXPANDED|INDEXTOSTATEIMAGEMASK(0); // no checkbox for sections
- tvis.item.lParam = (LPARAM)u;
- tvis.item.iImage = ImageList_AddIcon(hImageList, (pamtdMsgTypes[u].hSectionIcon ? pamtdMsgTypes[u].hSectionIcon : LoadSkinnedIcon(SKINICON_OTHER_MIRANDA)) );
- tvis.item.iSelectedImage = tvis.item.iImage; // else the wrong icon will be shown when selected
-
- // Position new section using position numbers (lowest first)
- tvis.hInsertAfter = TVI_FIRST;
- for (hItem=TreeView_GetRoot(hwndTreeView); hItem; hItem=TreeView_GetNextSibling(hwndTreeView, hItem))
- {
- pmtd = GetDataFromTreeViewItem(hwndTreeView, hItem);
- if (pmtd)
- {
- if (pamtdMsgTypes[u].iSectionPosition > pmtd->iSectionPosition)
- {
- tvis.hInsertAfter = hItem;
-
- // Colliding numbers are sorted alphabetically
- } else if (pamtdMsgTypes[u].iSectionPosition == pmtd->iSectionPosition) {
-
- int iCmpResult;
-
- iCmpResult = CompareString(GetThreadLocale(), 0, pamtdMsgTypes[u].ptszSectionDescription, -1, pmtd->ptszSectionDescription, -1); // or: LOCALE_USER_DEFAULT
-
- if (iCmpResult != 0) iCmpResult -= 2; // see docs
-
- if (iCmpResult >= 0)
- tvis.hInsertAfter = hItem;
-
- } else {
- // iteration pos is larger than new item pos
- // (or reached "Other" section)
- // -> found out where to sort in
- break;
- }
- }
- }
-
- tvis.hParent = TreeView_InsertItem(hwndTreeView, &tvis);
- }
- }
-
- pszSetting = GetMsgTypeSettingName(pamtdMsgTypes[u].pszSection, pamtdMsgTypes[u].pszName);
- if (!pszSetting) continue;
-
- tvis.item.mask = TVIF_TEXT|TVIF_STATE|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
- tvis.item.pszText = pamtdMsgTypes[u].ptszDescription;
- tvis.item.stateMask = TVIS_STATEIMAGEMASK;
- tvis.item.state = INDEXTOSTATEIMAGEMASK(DBGetContactSettingByte(NULL, DB_MODULE_NAME_MSGTYPES, pszSetting, (BYTE)!(pamtdMsgTypes[u].dwFlags&MTDF_DEFAULTDISABLED))?2:1);
- tvis.item.lParam = (LPARAM)u;
-
- if ((int)pamtdMsgTypes[u].hIcon < 0)
- tvis.item.iImage = ImageList_AddIcon(hImageList, LoadSkinnedIcon((-1)*(int)pamtdMsgTypes[u].hIcon));
- else
- tvis.item.iImage = ImageList_AddIcon(hImageList, pamtdMsgTypes[u].hIcon ? pamtdMsgTypes[u].hIcon : (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED));
-
- tvis.item.iSelectedImage = tvis.item.iImage; // else the wrong icon will be shown when selected
- mir_free(pszSetting);
-
- // Position new item using position numbers (lowest first)
- tvis.hInsertAfter = TVI_FIRST;
- for (hItem=TreeView_GetChild(hwndTreeView, tvis.hParent); hItem; hItem=TreeView_GetNextSibling(hwndTreeView, hItem))
- {
- pmtd = GetDataFromTreeViewItem(hwndTreeView, hItem);
- if (pmtd)
- {
- if (pamtdMsgTypes[u].iPosition > pmtd->iPosition)
- {
- tvis.hInsertAfter = hItem;
-
- // Colliding numbers are sorted alphabetically
- } else if (pamtdMsgTypes[u].iPosition == pmtd->iPosition)
- {
- iCmpResult = CompareString(GetThreadLocale(), 0, pamtdMsgTypes[u].ptszDescription, -1, pmtd->ptszDescription, -1); // or: LOCALE_USER_DEFAULT
-
- if (iCmpResult != 0) iCmpResult -= 2; // see docs
-
- if (iCmpResult >= 0)
- tvis.hInsertAfter = hItem;
-
- } else {
- // Iteration pos is larger than new item pos
- // -> found out where to sort in
- break;
- }
- }
- }
-
- TreeView_InsertItem(hwndTreeView, &tvis);
- }
- }
-
- LeaveCriticalSection(&csMsgTypes); // thread safety
-
- return TRUE;
- }
-
- case SFM_CHECK_AUTOIGNORE:
- {
- EnableDlgItem(hwndDlg, IDC_BUTTON_RESETAUTOIGNORE, (CallService(MS_SPAMFILTER_RESETAUTOIGNORE, (WPARAM)TRUE, 0) > 0));
- return TRUE;
- }
-
- case SFM_VALIDATE_LOGFILENAME:
- {
- const WCHAR* aszFileExtensions[] = {_T(".txt"), _T(".log"), _T(".csv"), _T(".xml"), _T("."), _T(""), NULL};
- const WCHAR* aszContentTypes[] = {_T("text/plain"), _T("text/xml"), _T("application/xml"), NULL};
-
- WCHAR szLogFile[MAX_PATH];
- DWORD dwPathFlags;
- BOOL bIsValid;
-
- GetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile, ARRAYSIZE(szLogFile));
- dwPathFlags = PMakePathUsable(szLogFile);
-
- // Make sure the correct xml file extension is specified
- if (PathMatchSpec(szLogFile, _T("*.xsl")))
- PathRenameExtension(szLogFile, _T(".xml"));
-
- bIsValid = PIsValidFile(szLogFile, aszFileExtensions, ARRAYSIZE(aszFileExtensions), aszContentTypes, ARRAYSIZE(aszContentTypes));
-
- PMakePathPretty(szLogFile, dwPathFlags);
- SetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile);
-
- EnableDlgItem(hwndDlg, IDC_BUTTON_OPENLOG, bIsValid);
- return TRUE;
- }
-
- case WM_DROPFILES:
- {
- // Forward do log edit (child windows of childs can not receive that message)
- PostMessage(GetDlgItem(hwndDlg, IDC_EDITBOX_LOGFILE), uMsg, wParam, lParam);
- return TRUE;
- }
-
- case WM_DESTROY:
- {
- HIMAGELIST hImgLst;
- // Free font
- DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER, WM_GETFONT, 0, 0));
-
- // Destroy tree view imagelist since it does not get destroyed automatically (see msdn docs)
- hImgLst = TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES), TVSIL_STATE);
- if (hImgLst) {
- TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES), NULL, TVSIL_STATE); // Avoiding Access Violation in CommonControls DLL
- ImageList_Destroy(hImgLst);
- }
- hImgLst = TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES), TVSIL_NORMAL);
- if (hImgLst) {
- TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES), NULL, TVSIL_NORMAL); // Avoiding Access Violation in CommonControls DLL
- ImageList_Destroy(hImgLst);
- }
-
- // Destroy open icon
- DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_BUTTON_LOGBROWSE, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0));
-
- hwndSpamFilterOpt = NULL;
- return TRUE;
- }
-
- case WM_COMMAND:
- {
- switch (LOWORD(wParam))
- {
- case IDC_BUTTON_ADVERTISMENTFILTER:
- {
- CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)hwndDlg, (LPARAM)SFT_ADVERTISMENT_FILTER);
-
- // Do not activate "Apply" button
- return FALSE;
- }
-
- case IDC_BUTTON_DISLIKEDMESSAGEFILTER:
- {
- CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)hwndDlg, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER);
-
- // Do not activate "Apply" button
- return FALSE;
- }
-
- case IDC_BUTTON_ROBOTFILTER:
- {
- CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)hwndDlg, (LPARAM)SFT_ROBOT_FILTER);
-
- // Do not activate "Apply" button
- return FALSE;
- }
-
- case IDC_BUTTON_LOGBROWSE:
- {
- WCHAR szLogFile[MAX_PATH];
- WCHAR szInitialDir[MAX_PATH];
- WCHAR szDefaultLogFile[MAX_PATH];
- BOOL bDefaultDirUsed, bDefaultFileUsed;
- BOOL bFileChanged;
- DWORD dwPathFlags;
- int iIndexAll, iIndexOther;
- OPENFILENAME ofn;
-
- // Set focus on editbox
- SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_LOGFILE), (LPARAM)TRUE);
-
- // Get chosen log file
- GetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile, ARRAYSIZE(szLogFile));
- dwPathFlags = PMakePathUsable(szLogFile);
-
- // Construct default log file
- PConstructLocalPath(szDefaultLogFile, CSIDL_EXT_EXECUTABLE, LOGS_SUBDIRECTORY, DEFAULT_LOGFILE, NULL);
-
- // Check if default file gets used
- if ((lstrlen(szLogFile) == 0) || (PathFindFileName(szLogFile) == szLogFile))
- {
- // Using default dir if nothing specified
- mir_sntprintf(szLogFile, ARRAYSIZE(szLogFile), _T("%s"), szDefaultLogFile);
- bDefaultDirUsed = bDefaultFileUsed = TRUE;
- } else {
- bDefaultDirUsed = bDefaultFileUsed = (StrCmpI(szLogFile, szDefaultLogFile) == 0);
- }
-
- // Using default file name when no file given
- if ( (lstrlen(PathFindFileName(szLogFile)) == 0) || PathIsDirectory(szLogFile))
- {
- PathAppend(szLogFile, PathFindFileName(szDefaultLogFile));
- bDefaultFileUsed = TRUE;
- }
-
- // Split file name
- {
- mir_sntprintf(szInitialDir, ARRAYSIZE(szInitialDir), _T("%s"), szLogFile);
-
- // Get file name
- mir_sntprintf(szLogFile, ARRAYSIZE(szLogFile), _T("%s"), PathFindFileName(szInitialDir));
-
- // Get initial dir
- PathRemoveFileSpec(szInitialDir);
- }
-
- // Initialize OPENFILENAME structure
- ZeroMemory(&ofn, sizeof(ofn));
- ofn.lStructSize = (IsWinVerNT() && !IsWinVer2000Plus()) ? OPENFILENAME_SIZE_VERSION_400 : sizeof(ofn); // backward compatibility for NT4
- ofn.hwndOwner = hwndDlg;
- ofn.Flags = OFN_ENABLESIZING|OFN_EXPLORER | OFN_LONGNAMES|OFN_HIDEREADONLY|OFN_NOREADONLYRETURN|OFN_OVERWRITEPROMPT; // also possible: OFN_DONTADDTORECENT, OFN_CREATEPROMPT
- ofn.lpstrFile = szLogFile;
- ofn.nMaxFile = ARRAYSIZE(szLogFile);
- ofn.lpstrTitle = TranslateT("Select Log File");
- ofn.lpstrDefExt = CharNext(PathFindExtension(DEFAULT_LOGFILE));
-
- // Make sure the initial directory exists
- if (SUCCEEDED(PPreparePathForWrite(hwndDlg, szInitialDir, !bDefaultDirUsed, FALSE)))
- ofn.lpstrInitialDir = szInitialDir;
-
- // File Filter
- {
- STRINGLIST* pslFilter = SLNewList();
-
- SLAddItemPair(pslFilter, TranslateT("Log Files (*.log)"), _T("*.log"));
- SLAddItemPair(pslFilter, TranslateT("Text Files (*.txt)"), _T("*.txt"));
- SLAddItemPair(pslFilter, TranslateT("Comma Separated Values Files (*.csv)"), _T("*.csv"));
- SLAddItemPair(pslFilter, TranslateT("XML Files (*.xml; *.xsl)"), _T("*.xml; *.xsl"));
- iIndexAll = SLAddItemPair(pslFilter, TranslateT("All Logging Files (*.log; *.txt; *.csv; *.xml)"), _T("*.log; *.txt; *.csv; *.xml"));
- iIndexOther = SLAddItemPair(pslFilter, TranslateT("All Files (*.*)"), _T("*.*"));
-
- ofn.lpstrFilter = SLConvertToString(pslFilter, NULL, FALSE, TRUE, NULL);
- SLFreeList(pslFilter);
- }
-
- // Default selected index
- if ( PathMatchSpec(szLogFile, _T("*.log")) ||
- PathMatchSpec(szLogFile, _T("*.txt")) ||
- PathMatchSpec(szLogFile, _T("*.csv")) ||
- PathMatchSpec(szLogFile, _T("*.xml")) )
- {
- // Show "all logging files" to show the user the possibilities
- ofn.nFilterIndex = (iIndexAll/2)+1; // filter index is 1 based
- } else {
- // Select "All files"
- ofn.nFilterIndex = (iIndexOther/2)+1; // filter index is 1 based
- }
-
- // Show browse file dialog
- bFileChanged = GetSaveFileName(&ofn);
- SLFreeReturn((WCHAR*)ofn.lpstrFilter);
-
- if (bFileChanged)
- {
- PMakePathPretty(szLogFile, dwPathFlags);
- SetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile);
-
- // Re-Set focus on editbox
- PostMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_LOGFILE), (LPARAM)TRUE);
- PostMessage(hwndDlg, SFM_VALIDATE_LOGFILENAME, 0, 0);
-
- } else {
- PostMessage(hwndDlg, SFM_VALIDATE_LOGFILENAME, 0, 0);
- // Do not activate "Apply" button
- return FALSE;
- }
-
- break;
- }
-
- case IDC_BUTTON_OPENLOG:
- {
- WCHAR szLogFile[MAX_PATH];
-
- GetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile, ARRAYSIZE(szLogFile));
- PMakePathUsable(szLogFile);
-
- if ((int)ShellExecute(hwndDlg, _T("open"), szLogFile, NULL, NULL, SW_SHOWNORMAL) <= 32)
- EnableDlgItem(hwndDlg, IDC_BUTTON_OPENLOG, FALSE);
-
- // Do not activate "Apply" button
- return FALSE;
- }
-
- case IDC_BUTTON_RESETAUTOIGNORE:
- {
- // Show message box before doing reset
- if (MessageBoxEx(hwndDlg, TranslateT("Are you sure that the Auto Ignore counters shall really be reset?\r\n\r\nSpammers that are not already ignored will then not be remembered any longer."), TranslateT("Reset Auto Ignore"), MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON1, LANGIDFROMLCID(GetThreadLocale())) == IDYES)
- EnableDlgItem(hwndDlg, IDC_BUTTON_RESETAUTOIGNORE, (CallService(MS_SPAMFILTER_RESETAUTOIGNORE, (WPARAM)FALSE, 0) != 0) );
-
- // Do not activate "Apply" button
- return FALSE;
- }
-
- case IDC_BUTTON_SHOWSPAMMERS:
- {
- CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)hwndDlg, (LPARAM)SFTEXF_SPAMMERS_INFO);
-
- // Do not activate "Apply" button
- return FALSE;
- }
-
- case IDC_CHECKBOX_AUTOADDSPAMMERS:
- case IDC_CHECKBOX_LOGGING:
- case IDC_CHECKBOX_ADVERTISMENTFILTER:
- case IDC_CHECKBOX_DISLIKEDMESSAGEFILTER:
- case IDC_CHECKBOX_ROBOTFILTER:
- {
- PostMessage(hwndDlg, SFM_ENABLE_SUBCTRLS, 0, 0);
- break;
- }
-
- case IDC_EDITBOX_LOGFILE:
- {
- switch (HIWORD(wParam))
- {
- case EN_CHANGE:
- {
- EnableDlgItem(hwndDlg, IDC_BUTTON_OPENLOG, FALSE);
- break;
- }
-
- case EN_KILLFOCUS:
- {
- PostMessage(hwndDlg, SFM_VALIDATE_LOGFILENAME, 0, 0);
- break;
- }
- }
-
- // fall through
- }
-
- case IDC_EDITBOX_ALLOWEDSPAMMESSAGES:
- {
- if (HIWORD(wParam) != EN_SETFOCUS)
- {
- // Do not activate "Apply" button
- return FALSE;
- }
-
- break;
- }
- }
-
- // Send message to activate "Apply" button...
- PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
- return FALSE;
- }
-
- case WM_NOTIFY:
- {
- LPNMHDR pnmhdr = (LPNMHDR)lParam;
-
- switch (pnmhdr->idFrom)
- {
- case IDC_TREEVIEW_MESSAGETYPES:
- {
- switch (pnmhdr->code)
- {
- case TVN_KEYDOWN:
- {
- switch (((NMTVKEYDOWN*)lParam)->wVKey)
- {
- case VK_SPACE:
- {
- if (TreeView_GetSelection(pnmhdr->hwndFrom))
- {
- ToggleTreeViewItemState(pnmhdr->hwndFrom, TreeView_GetSelection(pnmhdr->hwndFrom));
-
- // Send message to activate "Apply" button...
- PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
- }
-
- // Prevent default processing
- SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)FALSE);
- return TRUE;
- }
- }
-
- break;
- }
-
- case NM_CLICK:
- {
- TVHITTESTINFO hti;
-
- // Get click position
- GetCursorPos(&hti.pt);
- ScreenToClient(pnmhdr->hwndFrom, &hti.pt);
-
- // Check if click was on state icon
- if (TreeView_HitTest(pnmhdr->hwndFrom, &hti))
- if (hti.flags&TVHT_ONITEMSTATEICON)
- {
- ToggleTreeViewItemState(pnmhdr->hwndFrom, hti.hItem);
-
- // Send message to activate "Apply" button...
- PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
- }
-
- return TRUE;
- }
- }
-
- break;
- }
-
- case 0:
- {
- switch (pnmhdr->code)
- {
- case PSN_EXPERTCHANGED: // Expert mode checkbox checked/unchecked
- {
- BOOL bNewState = (BOOL)lParam;
-
- // Accept files (when log file edit control is visible)
- DragAcceptFiles(hwndDlg, bNewState);
- return TRUE;
- }
-
- case PSN_APPLY: // When "Apply"/"OK" pressed in options dialog then save changes
- {
- BOOL bFilterState = ( (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER) == BST_CHECKED) ||
- (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER) == BST_CHECKED) ||
- (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ROBOTFILTER) == BST_CHECKED) );
-
- // Save filter state
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ROBOTFILTER) == BST_CHECKED));
-
- // Save popup state
- if (IsPopupAvailable(TRUE))
- {
- BOOL bPopupState = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_POPUP) == BST_CHECKED);
-
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, (BYTE)bPopupState);
- SetPopupMenuItem(bPopupState, !bFilterState);
- }
-
- // Save Auto Ignore
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_AUTOADDSPAMMERS) == BST_CHECKED));
- DBWriteContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, (WORD)GetDlgItemInt(hwndDlg, IDC_EDITBOX_ALLOWEDSPAMMESSAGES, NULL, FALSE));
-
- // Save behaviour
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, (BYTE)((IsDlgButtonChecked(hwndDlg, IDC_RADIO_MARKREADMSG) == BST_CHECKED) ? 1 : 2));
-
- // Save log file
- {
- WCHAR szLogFile[MAX_PATH];
-
- GetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile, ARRAYSIZE(szLogFile));
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_LOGFILE, szLogFile);
-
- // Save activation of logging
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, (BYTE)((lstrlen(szLogFile) > 0) ? (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_LOGGING) == BST_CHECKED) : FALSE));
- }
-
- // Save message types
- {
- HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES);
- MESSAGETYPEDESC* pmtd;
- HTREEITEM hSectionItem;
- HTREEITEM hItem;
- char* pszSetting;
-
- for (hSectionItem=TreeView_GetRoot(hwndTreeView); hSectionItem; hSectionItem=TreeView_GetNextSibling(hwndTreeView, hSectionItem))
- for (hItem=TreeView_GetChild(hwndTreeView, hSectionItem); hItem; hItem=TreeView_GetNextSibling(hwndTreeView, hItem))
- {
- EnterCriticalSection(&csMsgTypes); // thread safety
-
- pmtd = GetDataFromTreeViewItem(hwndTreeView, hItem);
- if (pmtd)
- {
- // Save setting
- pszSetting = GetMsgTypeSettingName(pmtd->pszSection, pmtd->pszName);
- if (!pszSetting) continue;
-
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME_MSGTYPES, pszSetting, (BYTE)((TreeView_GetItemState(hwndTreeView, hItem, TVIS_STATEIMAGEMASK)&INDEXTOSTATEIMAGEMASK(2))?TRUE:FALSE));
-
- mir_free(pszSetting);
- }
-
- LeaveCriticalSection(&csMsgTypes); // thread safety
- }
- }
-
- return FALSE;
- }
-
- } // switch code
-
- break;
- }
-
- } // switch idFrom
-
- break;
- }
-
- }
-
- return FALSE;
-}
-
-
-BOOL CALLBACK DlgProcConfigureAdvertismentFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- hwndAdvertismentFilter = hwndDlg;
-
- // Translate dialog
- TranslateDialogDefault(hwndDlg);
-
- // Make group headings bold
- {
- HFONT hBoldFont;
- LOGFONT lf;
-
- GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_BADWORDS, WM_GETFONT, 0, 0), sizeof(lf), &lf);
- lf.lfWeight = FW_BOLD;
- hBoldFont = CreateFontIndirect(&lf);
-
- SendDlgItemMessage(hwndDlg, IDC_GROUP_BADWORDS, WM_SETFONT, (WPARAM)hBoldFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_GROUP_OTHERCONTENTS, WM_SETFONT, (WPARAM)hBoldFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_GROUP_SPAMMERS, WM_SETFONT, (WPARAM)hBoldFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_GROUP_GOODWORDS, WM_SETFONT, (WPARAM)hBoldFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_TEXT_WARNING, WM_SETFONT, (WPARAM)hBoldFont, 0);
- }
-
- // Set icon
- SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)(HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED));
-
- // Init checkboxes
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTBADWORDS, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_DEFAULTBADWORDS ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_FORMATING, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_FORMATING, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_FORMATING ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_URL, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_URL, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_URL)) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_CAPITALIZED, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CAPITALIZED, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_CAPITALIZED ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_DEFAULTSPAMMERS, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTSPAMMERS, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_DEFAULTSPAMMERS ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_MULTIPLEMESSAGES, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_MULTIPLEMESSAGES, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_MULTIPLEMESSAGES ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_TEASERMESSAGES, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_TEASERMESSAGES, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_TEASERMESSAGES ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_EMPTY, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_EMPTY, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_EMPTY ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_PHONENUMBERS, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_PHONENUMBERS, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_PHONENUMBERS ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
-
- // Load default bad words count (for spins)
- SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)SLNewList());
- SendMessage(hwndDlg, SFM_RELOAD_DEFAULTBADWORDS, 0, 0);
-
- // Init listboxes
- {
- STRINGLIST* pslWords = SLNewList();
-
- // Bad words
- GetSpamDefinitionData(pslWords, SDID_CUSTOM_BADWORDS);
- WordsListBoxInit(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, IDC_BUTTON_ADDBADWORD, IDC_BUTTON_DELETEBADWORD, pslWords, Translate("Add bad phrase/pattern"), Translate("Remove bad phrase/pattern"));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS, (SLGetItemCount(pslWords) > 0) ? (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS, (BYTE)TRUE)?BST_CHECKED:BST_UNCHECKED) : BST_UNCHECKED);
-
- SLClearList(pslWords);
-
- // Good words
- GetSpamDefinitionData(pslWords, SDID_CUSTOM_GOODWORDS);
- WordsListBoxInit(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, IDC_BUTTON_ADDGOODWORD, IDC_BUTTON_DELETEGOODWORD, pslWords, Translate("Add good phrase/pattern"), Translate("Remove good phrase/pattern"));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, (SLGetItemCount(pslWords) > 0) ? (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDGOODWORDS, (BYTE)TRUE)?BST_CHECKED:BST_UNCHECKED) : BST_UNCHECKED);
-
- SLFreeList(pslWords);
- }
-
- // Init editboxes and spins
- {
- BOOL bStatus = TRUE;
- int iBadWordsCount = ( (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS) == BST_CHECKED) ? SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, LB_GETCOUNT, 0, 0) : 0)
- + ( (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS) == BST_CHECKED) ? SLGetItemCount((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER)) : 0)
- - 1;
-
- // Allowed bad words edit/spin
- bStatus = SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDBADWORDS), 0, iBadWordsCount, DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDBADWORDS, (DWORD)DEFAULT_SETTING_ADVERTISMENT_ALLOWEDBADWORDS), TRUE);
- EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDBADWORDS, bStatus);
-
- // Allowed formated words edit/spin
- bStatus = SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDFORMATEDWORDS), 0, iBadWordsCount, DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS, (DWORD)DEFAULT_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS), TRUE);
- EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDFORMATEDWORDS, bStatus);
-
- // Allowed good words edit/spin
- SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDGOODWORDS), 0, (SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, LB_GETCOUNT, 0, 0) - 1), DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS, (DWORD)DEFAULT_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS), TRUE);
- }
-
- // Check if all definition files do exist
- if (SLGetItemCount((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER)) <= 0) {
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS, FALSE);
- ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
- }
- if (!IsSpamDefinitionDataPresent(SDID_URLTLDS)) {
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_URL, FALSE);
- ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
- }
- if (!IsSpamDefinitionDataPresent(SDID_SPAMMERS)) {
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_DEFAULTSPAMMERS, FALSE);
- ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
- }
- if (!IsSpamDefinitionDataPresent(SDID_PHONENUMBERS)) {
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_PHONENUMBERS, FALSE);
- ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
- }
- if (!IsSpamDefinitionDataPresent(SDID_TEASERTEXTS)) {
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_TEASERMESSAGES, FALSE);
- ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
- }
-
- // Simulate messages
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDBADWORDS, BN_CLICKED), (LPARAM)NULL);
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, BN_CLICKED), (LPARAM)NULL);
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_FORMATING, BN_CLICKED), (LPARAM)NULL);
-
- // Restore dlg position (at the end, so the dialog does not get shown early)
- Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DIALOGPOSITION);
- // Make sure the dialog is not moved out of sight
- SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
-
- // SetFocus (SetFocus() is not allowed in Dialogs)
- SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), (LPARAM)TRUE);
- return FALSE;
- }
-
- case SFM_RELOAD_DEFAULTBADWORDS:
- {
- if (InSendMessage())
- ReplyMessage(TRUE);
-
- SLClearList((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER));
- GetSpamDefinitionData((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER), SDID_BADWORDS);
- return TRUE;
- }
-
- case WM_DESTROY:
- {
- // Save dlg position
- Utils_SaveWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DIALOGPOSITION);
-
- // Free default bad words
- SLFreeList((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER));
-
- // Free font
- DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_BADWORDS, WM_GETFONT, 0, 0));
-
- hwndAdvertismentFilter = NULL;
- return TRUE;
- }
-
- case WM_COMMAND:
- {
- switch (LOWORD(wParam))
- {
- case IDC_CHECKBOX_DEFAULTBADWORDS:
- case IDC_CHECKBOX_CUSTOMIZEDBADWORDS:
- {
- int iListCount = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, LB_GETCOUNT, 0, 0);
- BOOL bStatus = ((IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS) == BST_CHECKED)
- || (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS) == BST_CHECKED));
-
- EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDBADWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDFORMATEDWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_FORMATING, bStatus);
-
- bStatus = (bStatus && ((iListCount+SLGetItemCount((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER))) > 1));
- EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDBADWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDBADWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDBADWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDFORMATEDWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDFORMATEDWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDFORMATEDWORDS, bStatus);
-
- // Customized bad words box checked -> Deactivate all customized bad words options
- bStatus = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS) == BST_CHECKED);
-
- EnableDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_BUTTON_ADDBADWORD, bStatus);
- EnableDlgItem(hwndDlg, IDC_BUTTON_DELETEBADWORD, (iListCount > 0) ? bStatus : FALSE);
-
- // Set/Check allowed bad words value (Simulate changed edit box)
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDITBOX_ALLOWEDBADWORDS, EN_KILLFOCUS), 0);
-
- return TRUE;
- }
-
- case IDC_CHECKBOX_CUSTOMIZEDGOODWORDS:
- {
- BOOL bStatus;
- int iListCount = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, LB_GETCOUNT, 0, 0);
-
- // Customized good words box checked -> Deactivate all good words options
- bStatus = (IsDlgButtonChecked(hwndDlg,IDC_CHECKBOX_CUSTOMIZEDGOODWORDS) == BST_CHECKED);
-
- EnableDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDGOODWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDGOODWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDGOODWORDS, bStatus);
-
- // Activate Add/Delete buttons?
- EnableDlgItem(hwndDlg, IDC_BUTTON_ADDGOODWORD, bStatus);
- EnableDlgItem(hwndDlg, IDC_BUTTON_DELETEGOODWORD, (iListCount > 0) ? bStatus : FALSE);
-
- EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDGOODWORDS, bStatus);
-
- bStatus = (bStatus && (iListCount > 1));
- EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDGOODWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDGOODWORDS, bStatus);
-
- return TRUE;
- }
-
- case IDC_CHECKBOX_FORMATING:
- {
- BOOL bStatus = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_FORMATING) == BST_CHECKED);
-
- EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDFORMATEDWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDFORMATEDWORDS, bStatus);
- EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDFORMATEDWORDS, bStatus);
-
- return TRUE;
- }
-
- case IDC_EDITBOX_ALLOWEDBADWORDS:
- case IDC_EDITBOX_ALLOWEDFORMATEDWORDS:
- {
- switch(HIWORD(wParam))
- {
- case EN_KILLFOCUS:
- {
- int iRangeMax = ((IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS) == BST_CHECKED) ? SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, LB_GETCOUNT, 0, 0) : 0)
- + ((IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS) == BST_CHECKED) ? SLGetItemCount((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER)) : 0)
- - 1;
-
- // Check allowed bad words value
- SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDBADWORDS), 0, iRangeMax, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDBADWORDS, FALSE);
-
- // Check allowed formated words value
- SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDFORMATEDWORDS), 0, iRangeMax, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS, FALSE);
-
- return TRUE;
- }
- }
-
- break;
- }
-
- case IDC_EDITBOX_ALLOWEDGOODWORDS:
- {
- switch (HIWORD(wParam))
- {
- case EN_KILLFOCUS:
- {
- int iRangeMax = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, LB_GETCOUNT, 0, 0) - 1;
- if (iRangeMax < 0) iRangeMax = 0;
-
- // Check allowed good words value
- SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDGOODWORDS), 0, iRangeMax, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS, FALSE);
-
- return TRUE;
- }
- }
-
- break;
- }
-
- case IDC_BUTTON_ADDBADWORD:
- {
- WCHAR* pszMsgTitle = TranslateT("Add bad phrase/pattern");
- WCHAR* pszMsgTextInList = TranslateT("The entered bad phrase \"%s\" already exists in the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the bad phrase be added anyway?");
- WCHAR* pszMsgTextInOther = TranslateT("The entered bad phrase \"%s\" already exists in the default bad phrases lists.\r\n\r\nAllowing the same bad phrase in the customized bad phrases lists will\npull down the filter quality.\r\n\r\nShall the bad phrase be added anyway?");
-
- WordsListBoxAddItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, (STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER), pszMsgTitle, pszMsgTextInList, pszMsgTextInOther, IDC_BUTTON_DELETEBADWORD);
-
- // Set/Check allowed bad words value (Simulate changed edit box)
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDITBOX_ALLOWEDBADWORDS, EN_KILLFOCUS), 0);
-
- // Simulate messages
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDBADWORDS, BN_CLICKED), 0);
-
- return TRUE;
- }
-
- case IDC_BUTTON_DELETEBADWORD:
- {
- int iItemCount = WordsListBoxDeleteItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, IDC_BUTTON_DELETEBADWORD);
-
- // Deactivate list on zero entries
- if (iItemCount == 0)
- {
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS, BST_UNCHECKED);
- SendMessage(hwndDlg, WM_COMMAND, IDC_CHECKBOX_CUSTOMIZEDBADWORDS, 0);
- }
-
- // Set/Check allowed bad words value (Simulate changed edit box)
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDITBOX_ALLOWEDBADWORDS, EN_KILLFOCUS), 0);
-
- // Simulate messages
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDBADWORDS, BN_CLICKED), 0);
-
- return TRUE;
- }
-
- case IDC_BUTTON_ADDGOODWORD:
- {
- WCHAR* pszMsgTitle = TranslateT("Add good phrase/pattern");
- WCHAR* pszMsgTextInList = TranslateT("The entered good phrase \"%s\" already exists\r\nin the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the good phrase be added anyway?");
-
- WordsListBoxAddItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, NULL, pszMsgTitle, pszMsgTextInList, NULL, IDC_BUTTON_DELETEGOODWORD);
-
- // Set/Check allowed bad words value (Simulate changed edit box)
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDITBOX_ALLOWEDGOODWORDS, EN_KILLFOCUS), 0);
-
- // Simulate messages
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, BN_CLICKED), 0);
-
- return TRUE;
- }
-
- case IDC_BUTTON_DELETEGOODWORD:
- {
- int iItemCount = WordsListBoxDeleteItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, IDC_BUTTON_DELETEGOODWORD);
- int iRangeMax = iItemCount - 1;
-
- // Deactivate list on zero entries
- if (iItemCount == 0)
- {
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, BST_UNCHECKED);
- SendMessage(hwndDlg, WM_COMMAND, IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, 0);
- }
-
- // Update allowed good words spin
- SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDGOODWORDS), 0, iRangeMax, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS, FALSE);
-
- // Set/Check allowed bad words value (Simulate changed edit box)
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDITBOX_ALLOWEDGOODWORDS, EN_KILLFOCUS), 0);
-
- // Simulate messages
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, BN_CLICKED), 0);
-
- // Set focus on list box again (might have gotten lost on IDC_CHECKBOX_CUSTOMIZEDGOODWORDS)
- PostMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS), (LPARAM)TRUE);
- return TRUE;
- }
-
- case IDC_BUTTON_SPAMDEFINITIONS:
- {
- CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)NULL, (LPARAM)SFT_ADVERTISMENT_FILTER|SFTEXF_SPAMDEFINITIONS_INFO);
- return TRUE;
- }
-
- case IDOK:
- {
- EnableDlgItem(hwndDlg, IDOK, FALSE);
-
- // Save changes
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTBADWORDS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_FORMATING, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_FORMATING) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_URL, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_URL) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CAPITALIZED, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CAPITALIZED) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTSPAMMERS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DEFAULTSPAMMERS) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_MULTIPLEMESSAGES, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_MULTIPLEMESSAGES) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_TEASERMESSAGES, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_TEASERMESSAGES) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_EMPTY, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_EMPTY) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_PHONENUMBERS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_PHONENUMBERS) == BST_CHECKED));
-
- DBWriteContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDBADWORDS, (WORD)GetDlgItemInt(hwndDlg, IDC_EDITBOX_ALLOWEDBADWORDS, NULL, FALSE));
- DBWriteContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS, (WORD)GetDlgItemInt(hwndDlg, IDC_EDITBOX_ALLOWEDFORMATEDWORDS, NULL, FALSE));
- DBWriteContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS, (WORD)GetDlgItemInt(hwndDlg, IDC_EDITBOX_ALLOWEDGOODWORDS, NULL, FALSE));
-
- // Save listbox contents
- {
- STRINGLIST* pslWords = SLNewList();
-
- // Bad words
- SLRetrieveFromListBoxCtrl(pslWords, GetDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS));
-
- SetSpamDefinitionData(pslWords, SDID_CUSTOM_BADWORDS, hwndDlg);
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS, (BYTE)((SLGetItemCount(pslWords) > 0) ? (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS) == BST_CHECKED) : FALSE));
-
- SLClearList(pslWords);
-
- // Good words
- SLRetrieveFromListBoxCtrl(pslWords, GetDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS));
-
- SetSpamDefinitionData(pslWords, SDID_CUSTOM_GOODWORDS, hwndDlg);
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDGOODWORDS, (BYTE)((SLGetItemCount(pslWords) > 0) ? (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDGOODWORDS) == BST_CHECKED) : FALSE));
-
- SLFreeList(pslWords);
- }
-
- // fall through
- }
-
- case IDCANCEL:
- // WM_CLOSE is transformed into an IDCANCEL by dialog manager
- {
- // Different method of closing the window depending on if the window
- // was created modal or not
- if (!GetParent(hwndDlg))
- DestroyWindow(hwndDlg);
- else
- EndDialog(hwndDlg, LOWORD(wParam));
-
- return TRUE;
- }
-
- } // switch wParam
-
- break;
- }
-
- default:
- {
- if (WordsListBoxDragDrop(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, uMsg, lParam, FALSE)
- || WordsListBoxDragDrop(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, uMsg, lParam, FALSE) )
- return TRUE;
- }
-
- } // switch uMsg
-
- return FALSE;
-}
-
-
-BOOL CALLBACK DlgProcConfigureDislikedMessagesFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- hwndDislikedMessagesFilter = hwndDlg;
-
- // Translate dialog
- TranslateDialogDefault(hwndDlg);
-
- // Make group headings bold
- {
- HFONT hBoldFont;
- LOGFONT lf;
-
- GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_OTHERCONTENTS, WM_GETFONT, 0, 0), sizeof(lf), &lf);
- lf.lfWeight = FW_BOLD;
- hBoldFont = CreateFontIndirect(&lf);
-
- SendDlgItemMessage(hwndDlg, IDC_GROUP_OTHERCONTENTS, WM_SETFONT, (WPARAM)hBoldFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_GROUP_WORDS, WM_SETFONT, (WPARAM)hBoldFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_GROUP_NOTIFYSENDER, WM_SETFONT, (WPARAM)hBoldFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_TEXT_WARNING, WM_SETFONT, (WPARAM)hBoldFont, 0);
- }
-
- // Load icons
- SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)(HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED));
-
- // Set Data
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_HOAXTEXTS, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_HOAXTEXTS, (BYTE)(DEFAULT_SETTING_DISLIKEDMESSAGE_HOAXTEXTS ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_MULTIPLEMESSAGES, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES, (BYTE)(DEFAULT_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_NOTIFYSENDER, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER, (BYTE)(DEFAULT_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_ADDTOHISTORY, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY, (BYTE)(DEFAULT_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED));
-
- // Init listboxes
- {
- STRINGLIST* pslWords = SLNewList();
-
- // Disliked words
- GetSpamDefinitionData(pslWords, SDID_CUSTOM_DISLIKEDWORDS);
- WordsListBoxInit(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, IDC_BUTTON_ADDWORD, IDC_BUTTON_DELETEWORD, pslWords, Translate("Add indicating phrase/pattern"), Translate("Remove indicating phrase"));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDWORDS, (SLGetItemCount(pslWords) > 0) ? (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_CUSTOMIZEDWORDS, (BYTE)TRUE)?BST_CHECKED:BST_UNCHECKED) : BST_UNCHECKED);
-
- SLFreeList(pslWords);
- }
-
- // Init editbox
- {
- DBVARIANT dbv;
-
- // Notify text
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE, &dbv) == 0)
- {
- SetDlgItemText(hwndDlg, IDC_EDITBOX_NOTIFYSENDER, dbv.ptszVal);
- DBFreeVariant(&dbv);
- } else {
- SetDlgItemText(hwndDlg, IDC_EDITBOX_NOTIFYSENDER, DEFAULT_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE);
- }
- }
-
- if (!IsSpamDefinitionDataPresent(SDID_HOAXTEXTS)) {
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_HOAXTEXTS, FALSE);
- ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
- }
-
- // Show/Hide Variables Plugin help button
- if (!MakeVariablesHelpButton(hwndDlg, IDC_BUTTON_NOTIFYSENDER_VARIABLES))
- {
- RECT rc;
-
- if (GetWindowRect(GetDlgItem(hwndDlg, IDC_TEXT_NOTIFYSENDER), &rc))
- SetWindowPos(GetDlgItem(hwndDlg, IDC_TEXT_NOTIFYSENDER), NULL, 0, 0, (rc.right-rc.left)+25, (rc.bottom-rc.top), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
- }
-
- // Simulate messages
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDWORDS, BN_CLICKED), 0);
- SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_NOTIFYSENDER, BN_CLICKED), 0);
-
- // Restore dlg position (at the end, so the dialog does not get shown early)
- Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_DIALOGPOSITION);
- // Make sure the dialog is not moved out of sight
- SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
-
- // SetFocus (SetFocus() is not allowed in Dialogs)
- SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), (LPARAM)TRUE);
- return FALSE;
- }
-
- case WM_DESTROY:
- {
- // Save dlg position
- Utils_SaveWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_DIALOGPOSITION);
-
- // Free font
- DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_OTHERCONTENTS, WM_GETFONT, 0, 0));
-
- // Destroy help icon
- DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_BUTTON_NOTIFYSENDER_VARIABLES, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0));
-
- hwndDislikedMessagesFilter = NULL;
- return TRUE;
- }
-
- case WM_COMMAND:
- {
- switch (LOWORD(wParam))
- {
- case IDC_CHECKBOX_NOTIFYSENDER:
- {
- BOOL bStatus = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_NOTIFYSENDER) == BST_CHECKED);
-
- EnableDlgItem(hwndDlg, IDC_EDITBOX_NOTIFYSENDER, bStatus);
- EnableDlgItem(hwndDlg, IDC_TEXT_NOTIFYSENDER, bStatus);
- EnableDlgItem(hwndDlg, IDC_CHECKBOX_ADDTOHISTORY, bStatus);
-
- if (ServiceExists(MS_VARS_SHOWHELP) && ServiceExists(MS_VARS_FORMATSTRING))
- EnableDlgItem(hwndDlg, IDC_BUTTON_NOTIFYSENDER_VARIABLES, bStatus);
-
- // Avoid passing simulated messages to the system
- if (!lParam) return TRUE;
- break;
- }
-
- case IDC_CHECKBOX_CUSTOMIZEDWORDS:
- {
- BOOL bStatus = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDWORDS) == BST_CHECKED);
- int iListCount = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, LB_GETCOUNT, 0, 0);
-
- // Customized bad words box checked -> Deactivate all customized bad words options
- EnableDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, bStatus);
-
- // Deactivate Add/Delete buttons?
- EnableDlgItem(hwndDlg, IDC_BUTTON_ADDWORD, bStatus);
- EnableDlgItem(hwndDlg, IDC_BUTTON_DELETEWORD, (iListCount > 0) ? bStatus : FALSE);
-
- // Avoid passing simulated messages to the system
- if (!lParam) return TRUE;
-
- break;
- }
-
- case IDC_BUTTON_NOTIFYSENDER_VARIABLES:
- {
- // SetFocus (SetFocus() is not allowed in Dialogs)
- SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_NOTIFYSENDER), (LPARAM)TRUE);
-
- CallService(MS_VARS_SHOWHELP, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_NOTIFYSENDER), (LPARAM)NULL);
- break;
- }
-
- case IDC_BUTTON_ADDWORD:
- {
- WCHAR* pszMsgTitle = TranslateT("Add indicating phrase/pattern");
- WCHAR* pszMsgTextInList = TranslateT("The entered indicating phrase \"%s\" already exists in the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the indicating phrase be added anyway?");
-
- WordsListBoxAddItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, NULL, pszMsgTitle, pszMsgTextInList, NULL, IDC_BUTTON_DELETEWORD);
-
- break;
- }
-
- case IDC_BUTTON_DELETEWORD:
- {
- int iItemCount = WordsListBoxDeleteItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, IDC_BUTTON_DELETEWORD);
-
- // Deactivate list on zero entries
- if (iItemCount == 0)
- {
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDWORDS, BST_UNCHECKED);
- SendMessage(hwndDlg, WM_COMMAND, IDC_CHECKBOX_CUSTOMIZEDWORDS, 0);
- }
-
- break;
- }
-
- case IDC_BUTTON_SPAMDEFINITIONS:
- {
- CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)NULL, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER|SFTEXF_SPAMDEFINITIONS_INFO);
- break;
- }
-
- case IDOK:
- {
- EnableDlgItem(hwndDlg, IDOK, FALSE);
-
- // Save changes
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_MULTIPLEMESSAGES) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_HOAXTEXTS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_HOAXTEXTS) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ADDTOHISTORY) == BST_CHECKED));
-
- // Save texts
- {
- HWND hwndEdit = GetDlgItem(hwndDlg, IDC_EDITBOX_NOTIFYSENDER);
- int iTextLen = GetWindowTextLength(hwndEdit);
- WCHAR* pszText = (WCHAR*)mir_alloc((iTextLen+1)*sizeof(WCHAR));
-
- // Get entered text
- if (pszText)
- {
- if (GetWindowText(hwndEdit, pszText, iTextLen+1) == 0)
- pszText[0] = _T('\0');
-
- // Save text
- if (lstrlen(pszText) > 0) {
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE, pszText);
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_NOTIFYSENDER) == BST_CHECKED));
- } else{
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE, DEFAULT_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE);
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER, (BYTE)FALSE);
- }
-
- mir_free(pszText);
- }
- }
-
- // Save listbox contents
- {
- STRINGLIST* pslWords = SLNewList();
-
- // Chain words
- SLRetrieveFromListBoxCtrl(pslWords, GetDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS));
-
- SetSpamDefinitionData(pslWords, SDID_CUSTOM_DISLIKEDWORDS, hwndDlg);
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_CUSTOMIZEDWORDS, (BYTE)((SLGetItemCount(pslWords) > 0) ? (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDWORDS) == BST_CHECKED) : FALSE));
-
- SLFreeList(pslWords);
- }
-
- // fall through
- }
-
- case IDCANCEL:
- // WM_CLOSE is transformed into an IDCANCEL by dialog manager
- {
- // Different method of closing the window depending on if the window
- // was created modal or not
- if (!GetParent(hwndDlg))
- DestroyWindow(hwndDlg);
- else
- EndDialog(hwndDlg, LOWORD(wParam));
-
- return TRUE;
- }
-
- } // switch wParam
- break;
- }
-
- default:
- {
- if (WordsListBoxDragDrop(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, uMsg, lParam, FALSE))
- return TRUE;
- }
-
- }
- return FALSE;
-}
-
-
-BOOL CALLBACK DlgProcConfigureRobotFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- hwndRobotFilter = hwndDlg;
-
- // Translate dialog
- TranslateDialogDefault(hwndDlg);
-
- // Make group headings bold
- {
- HFONT hBoldFont;
- LOGFONT lf;
-
- GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_MESSAGETEXTS, WM_GETFONT, 0, 0), sizeof(lf), &lf);
- lf.lfWeight = FW_BOLD;
- hBoldFont = CreateFontIndirect(&lf);
-
- SendDlgItemMessage(hwndDlg, IDC_GROUP_MESSAGETEXTS, WM_SETFONT, (WPARAM)hBoldFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_GROUP_ANSWER, WM_SETFONT, (WPARAM)hBoldFont, 0);
- }
-
- // Load icons
- SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)(HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED));
-
- // Set Data
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_ADDTOHISTORY, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ADDTOHISTORY, (BYTE)DEFAULT_SETTING_ROBOT_ADDTOHISTORY) ? BST_CHECKED : BST_UNCHECKED));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_HIDE, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_HIDEUSERS, (BYTE)DEFAULT_SETTING_ROBOT_HIDEUSERS) ? BST_CHECKED : BST_UNCHECKED));
-
- // Init editboxes
- {
- DBVARIANT dbv;
-
- // Question
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_INSTRUCTION, &dbv) == 0) {
- SetDlgItemText(hwndDlg, IDC_EDITBOX_INSTRUCTION, dbv.ptszVal);
- DBFreeVariant(&dbv);
- } else {
- SetDlgItemText(hwndDlg, IDC_EDITBOX_INSTRUCTION, DEFAULT_SETTING_ROBOT_INSTRUCTION);
- }
-
- // Congratulation
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_CONFIRMATION, &dbv) == 0) {
- SetDlgItemText(hwndDlg, IDC_EDITBOX_CONFIRMATION, dbv.ptszVal);
- DBFreeVariant(&dbv);
- } else {
- SetDlgItemText(hwndDlg, IDC_EDITBOX_CONFIRMATION, DEFAULT_SETTING_ROBOT_CONFIRMATION);
- }
-
- // Answer
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, &dbv) == 0) {
- SetDlgItemText(hwndDlg, IDC_EDITBOX_ANSWER, dbv.ptszVal);
- DBFreeVariant(&dbv);
- } else {
- WCHAR szRnd[RANDOM_ANSWER_LENGTH+1];
- GetRandomString(szRnd, ARRAYSIZE(szRnd));
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, szRnd);
- SetDlgItemText(hwndDlg, IDC_EDITBOX_ANSWER, szRnd);
- }
- }
-
- // Show/Hide Variables Plugin help button (Question)
- MakeVariablesHelpButton(hwndDlg, IDC_BUTTON_INSTRUCTION_VARIABLES);
-
- // Show/Hide Variables Plugin help button (Confirmation)
- if (!MakeVariablesHelpButton(hwndDlg, IDC_BUTTON_CONFIRMATION_VARIABLES))
- {
- RECT rc;
- if (GetWindowRect(GetDlgItem(hwndDlg, IDC_TEXT_VARS), &rc))
- SetWindowPos(GetDlgItem(hwndDlg, IDC_TEXT_VARS), NULL, 0, 0, (rc.right-rc.left)+25, (rc.bottom-rc.top), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
- }
-
-
- // Restore dlg position (at the end, so the dialog does not get shown early)
- Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_DIALOGPOSITION);
- // Make sure the dialog is not moved out of sight
- SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
-
- // SetFocus (SetFocus() is not allowed in Dialogs)
- SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), (LPARAM)TRUE);
- return FALSE;
- }
-
- case WM_DESTROY:
- {
- // Save dlg position
- Utils_SaveWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_DIALOGPOSITION);
-
- // Free font
- DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_MESSAGETEXTS, WM_GETFONT, 0, 0));
-
- // Destroy help icons
- DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_BUTTON_INSTRUCTION_VARIABLES, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0));
- DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_BUTTON_CONFIRMATION_VARIABLES, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0));
-
- hwndRobotFilter = NULL;
- return TRUE;
- }
-
- case WM_COMMAND:
- {
- switch (LOWORD(wParam))
- {
- case IDC_BUTTON_INSTRUCTION_VARIABLES:
- {
- // SetFocus (SetFocus() is not allowed in Dialogs)
- SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_INSTRUCTION), (LPARAM)TRUE);
-
- CallService(MS_VARS_SHOWHELP, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_INSTRUCTION), (LPARAM)NULL);
- break;
- }
-
- case IDC_BUTTON_CONFIRMATION_VARIABLES:
- {
- // SetFocus (SetFocus() is not allowed in Dialogs)
- SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_CONFIRMATION), (LPARAM)TRUE);
-
- CallService(MS_VARS_SHOWHELP, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_CONFIRMATION), (LPARAM)NULL);
- break;
- }
-
- case IDC_BUTTON_ANSWER:
- {
- WCHAR szRnd[RANDOM_ANSWER_LENGTH+1];
-
- GetRandomString(szRnd, ARRAYSIZE(szRnd));
- SetDlgItemText(hwndDlg, IDC_EDITBOX_ANSWER, szRnd);
- break;
- }
-
- case IDOK:
- {
- EnableDlgItem(hwndDlg, IDOK, FALSE);
-
- // Save changes
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ADDTOHISTORY, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ADDTOHISTORY) == BST_CHECKED));
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_HIDEUSERS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_HIDE) == BST_CHECKED));
-
- // Save texts
- {
- int iTextLen;
- WCHAR* pszText;
-
- // Instruction
- iTextLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_EDITBOX_INSTRUCTION));
- pszText = (WCHAR*)mir_alloc((iTextLen+1)*sizeof(WCHAR));
- if (pszText)
- {
- if (GetWindowText(GetDlgItem(hwndDlg, IDC_EDITBOX_INSTRUCTION), pszText, iTextLen+1) == 0)
- pszText[0] = _T('\0');
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_INSTRUCTION, (lstrlen(pszText)>0) ? pszText : DEFAULT_SETTING_ROBOT_INSTRUCTION);
- mir_free(pszText);
- }
-
- // Confirmation
- iTextLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_EDITBOX_CONFIRMATION));
- pszText = (WCHAR*)mir_alloc((iTextLen+1)*sizeof(WCHAR));
- if (pszText)
- {
- if (GetWindowText(GetDlgItem(hwndDlg, IDC_EDITBOX_CONFIRMATION), pszText, iTextLen+1) == 0)
- pszText[0] = _T('\0');
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_CONFIRMATION, (lstrlen(pszText)>0) ? pszText : DEFAULT_SETTING_ROBOT_CONFIRMATION);
- mir_free(pszText);
- }
-
- // Correct Answer
- iTextLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_EDITBOX_ANSWER));
- pszText = (WCHAR*)mir_alloc((iTextLen+1)*sizeof(WCHAR));
- if (pszText)
- {
- if (GetWindowText(GetDlgItem(hwndDlg, IDC_EDITBOX_ANSWER), pszText, iTextLen+1) == 0)
- pszText[0] = _T('\0');
- if (lstrlen(pszText) > 0) {
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, pszText);
- } else {
- WCHAR szRnd[RANDOM_ANSWER_LENGTH+1];
- GetRandomString(szRnd, ARRAYSIZE(szRnd));
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, szRnd);
- }
- mir_free(pszText);
- }
- }
-
- // fall through
- }
-
- case IDCANCEL:
- // WM_CLOSE is transformed into an IDCANCEL by dialog manager
- {
- // Different method of closing the window depending on if the window
- // was created modal or not
- if (!GetParent(hwndDlg))
- DestroyWindow(hwndDlg);
- else
- EndDialog(hwndDlg, LOWORD(wParam));
-
- return TRUE;
- }
-
- } // switch wParam
- break;
- }
- }
-
- return FALSE;
-}
-
-
-// -- Spam Definitions Info
-
-static BOOL CALLBACK EnumSpamDefinitions_InsertItem(UINT uSpamDefID, WCHAR* pszFilePath, WCHAR* pszName, SYSTEMTIME* pstDate, WPARAM wParam, LPARAM lParam)
-{
- LVITEM lvi;
-
- if (!lParam) return FALSE;
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.mask = LVIF_TEXT|LVIF_PARAM;
- lvi.pszText = pszName?TranslateTS(pszName):TranslateT("Not Available");
- lvi.lParam = (LPARAM)mir_wstrdup(pszFilePath);
-
- lvi.iItem = ListView_InsertItem((HWND)wParam, &lvi);
- if (lvi.iItem >= 0)
- {
- // Version
- if (pstDate)
- {
- WCHAR szDate[9];
- if (GetDateFormat(GetThreadLocale(), 0, pstDate, _T("yy'.'MM'.'dd"), szDate, ARRAYSIZE(szDate)) != 0)
- ListView_SetItemText((HWND)wParam, lvi.iItem, 1, szDate);
- }
-
- if (!IsWinVerXPPlus() || !ListView_IsGroupViewEnabled((HWND)wParam))
- {
- ListView_SetItemText((HWND)wParam, lvi.iItem, 2, (WCHAR*)lParam); // Type
-
- } else {
-
- if (ListView_HasGroup((HWND)wParam, uSpamDefID))
- {
- lvi.mask = LVIF_GROUPID;
- lvi.iGroupId = uSpamDefID;
-
- ListView_SetItem((HWND)wParam, &lvi);
- // ListView_MoveItemToGroup not implemented in WinSDK
-
- } else {
-
- LVGROUP lvg;
-
- ZeroMemory(&lvg, sizeof(lvg));
- lvg.cbSize = sizeof(lvg);
- lvg.mask = LVGF_HEADER|LVGF_GROUPID;
- lvg.iGroupId = uSpamDefID;
- #if defined(UNICODE)
- lvg.pszHeader = (WCHAR*)lParam;
- ListView_InsertGroup((HWND)wParam, lvi.iItem, &lvg);
- #else
- lvg.pszHeader = mir_utf8encodeW((WCHAR*)lParam);
- ListView_InsertGroup((HWND)wParam, lvi.iItem, &lvg);
- if (lvg.pszHeader) mir_free(lvg.pszHeader);
- #endif
- }
- }
- }
-
- return TRUE;
-}
-
-
-static int ResizeProcSpamDefinitionsInfo(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL *urc)
-{
- switch(urc->wId)
- {
- case IDC_TEXT_DESCRIPTION:
- return RD_ANCHORY_TOP|RD_ANCHORX_WIDTH;
-
- case IDC_TAB_SPAMDEFINITIONS:
- return RD_ANCHORY_HEIGHT|RD_ANCHORX_WIDTH;
-
- case IDC_LISTVIEW_SPAMDEFINITIONS:
- {
- POINT pt = {0, 0};
-
- // Keep exactly same position (resized later)
- GetWindowRect(GetDlgItem(hwndDlg, urc->wId), &urc->rcItem);
- if (ClientToScreen(hwndDlg, &pt))
- OffsetRect(&urc->rcItem, -pt.x, -pt.y);
-
- return RD_ANCHORY_CUSTOM|RD_ANCHORX_CUSTOM;
- }
-
- case IDC_URL_GETMORE:
- return RD_ANCHORY_BOTTOM|RD_ANCHORX_WIDTH;
-
- //case IDCANCEL:
- //case IDC_SCROLLBAR_SIZEGRIP:
- default:
- return RD_ANCHORY_BOTTOM|RD_ANCHORX_RIGHT;
- }
-}
-
-void FixListHeader(HWND hwndListView)
-{
- // Resize header (does not fit fully using small border)
- // at least on WinME
- RECT rcList, rcHeader;
- HWND hwndHeader = ListView_GetHeader(hwndListView);
-
- if (GetClientRect(hwndListView, &rcList) && GetClientRect(hwndHeader, &rcHeader))
- if ((rcHeader.right-rcHeader.left) != (rcList.right-rcList.left))
- SetWindowPos(hwndHeader, NULL, 0, 0, rcList.right-rcList.left, rcHeader.bottom-rcHeader.top, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
-}
-
-BOOL CALLBACK DlgProcSpamDefinitionsInfo(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- hwndSpamDefinitionsInfo = hwndDlg;
-
- /*
- #if defined(UNICODE)
- // Convert DlgProc to Unicode (IsWindowUnicode returns true after this call -> see docs)
- SetWindowLongPtrW(hwndDlg, DWLP_DLGPROC, (LONG_PTR)DlgProcSpamDefinitionsInfo);
- #endif
- */
-
- // Translate dialog first
- TranslateDialogDefault(hwndDlg);
-
- // Set icon
- SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)(HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_SPAM_DEFINITIONS), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED));
-
- // Make heading
- {
- HFONT hBoldFont;
- LOGFONT lf;
-
- GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0), sizeof(lf), &lf);
- lf.lfWeight = FW_BOLD;
- hBoldFont = CreateFontIndirect(&lf);
-
- SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_SETFONT, (WPARAM)hBoldFont, 0);
- }
-
- // Init tabs
- {
- HWND hwndTab = GetDlgItem(hwndDlg, IDC_TAB_SPAMDEFINITIONS);
- TCITEM tci;
-
- tci.mask = TCIF_TEXT|TCIF_PARAM;
- tci.pszText = TranslateT("Advertisment Filter");
- tci.lParam = SFT_ADVERTISMENT_FILTER;
- TabCtrl_InsertItem(hwndTab, 0, &tci);
-
- tci.pszText = TranslateT("Disliked Messages Filter");
- tci.lParam = SFT_DISLIKEDMESSAGES_FILTER;
- TabCtrl_InsertItem(hwndTab, 1, &tci);
- }
-
- // Init ListView
- {
- HWND hwndList = GetDlgItem(hwndDlg, IDC_LISTVIEW_SPAMDEFINITIONS);
- LVCOLUMN lvc;
- int iMinSizePacketCol;
-
- ListView_SetExtendedListViewStyle(hwndList, LVS_EX_LABELTIP|LVS_EX_FULLROWSELECT);
-
- if (IsWinVerXPPlus())
- ListView_EnableGroupView(hwndList, TRUE);
-
- lvc.mask = LVCF_TEXT;
-
- if (IsWinVerXPPlus() && ListView_IsGroupViewEnabled(hwndList))
- {
- // Name
- lvc.pszText = TranslateT("Packet");
- ListView_InsertColumn(hwndList, 0, &lvc);
- iMinSizePacketCol = 200;
-
- // Date
- lvc.mask |= LVCF_FMT;
- lvc.pszText = TranslateT("Version");
- lvc.fmt = LVCFMT_RIGHT;
- ListView_InsertColumn(hwndList, 1, &lvc);
-
- } else {
-
- // Name
- lvc.pszText = TranslateT("Packet");
- ListView_InsertColumn(hwndList, 0, &lvc);
- iMinSizePacketCol = 120;
-
- // Date
- lvc.mask |= LVCF_FMT;
- lvc.pszText = TranslateT("Version");
- lvc.fmt = LVCFMT_RIGHT;
- ListView_InsertColumn(hwndList, 1, &lvc);
-
- // Type
- lvc.mask ^= LVCF_FMT;
- lvc.pszText = TranslateT("Type");
- ListView_InsertColumn(hwndList, 2, &lvc);
- }
-
- // Insert info items
- SendMessage(hwndDlg, SFM_REFRESH_SPAMDEFINITIONS, (WPARAM)TRUE, (LPARAM)lParam);
-
- ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE_USEHEADER);
- if (ListView_GetColumnWidth(hwndList, 0) < iMinSizePacketCol)
- ListView_SetColumnWidth(hwndList, 0, iMinSizePacketCol);
-
- ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
- if (ListView_GetColumnWidth(hwndList, 1) < 60)
- ListView_SetColumnWidth(hwndList, 1, 60);
-
- // Restore dlg position (at the end, so the dialog does not get shown early)
- Utils_RestoreWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_SPAMDEF_DIALOGPOSITION);
- // Make sure the dialog is not moved out of sight
- SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
- SendMessage(hwndDlg, WM_SIZE, 0, 0); //simulate message
-
- // Stretch last column to fit remaining space
- if (!IsWinVerXPPlus() || !ListView_IsGroupViewEnabled(hwndList))
- ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE_USEHEADER);
- else
- ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
-
- FixListHeader(hwndList);
- }
-
- // SetFocus (SetFocus() is not allowed in Dialogs)
- SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDCANCEL), (LPARAM)TRUE);
- return FALSE;
- }
-
- case SFM_REFRESH_SPAMDEFINITIONS:
- {
- HWND hwndList = GetDlgItem(hwndDlg, IDC_LISTVIEW_SPAMDEFINITIONS);
- DWORD dwFilterType;
- int iSelectedIndex = ListView_GetSelectionMark(hwndList);
-
- if ((DWORD)lParam == 0) {
- dwFilterType = (DWORD)GetWindowLongPtr(hwndDlg, DWLP_USER);
- } else {
- dwFilterType = (DWORD)lParam;
- if ((DWORD)SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)dwFilterType) == dwFilterType)
- if (!(BOOL)wParam) // if not forced refresh
- return TRUE;
- }
-
- ListView_DeleteAllItems(hwndList);
- //ListView_RemoveAllGroups(); // not really needed, always the same groups
-
- FixListHeader(hwndList);
-
- if (InSendMessage())
- ReplyMessage(TRUE);
-
- // Change tab
- {
- HWND hwndTab = GetDlgItem(hwndDlg, IDC_TAB_SPAMDEFINITIONS);
- int i;
- TCITEM tci;
-
- tci.mask = TCIF_PARAM;
- for (i=TabCtrl_GetItemCount(hwndTab)-1; i>=0; i--)
- {
- if (TabCtrl_GetItem(hwndTab, i, &tci))
- if ((DWORD)tci.lParam == dwFilterType)
- {
- if (TabCtrl_GetCurSel(hwndTab) != i)
- TabCtrl_SetCurSel(hwndTab, i);
- break;
- }
-
- if (i==0) TabCtrl_SetCurSel(hwndTab, -1);
- }
- FixListHeader(hwndList);
- }
-
- // Insert info items
- switch (dwFilterType)
- {
- case SFT_ADVERTISMENT_FILTER:
- {
- SetWindowText(hwndDlg, TranslateT("Spam Definitions: Advertisment Filter"));
-
- EnumSpamDefinitions(SDID_BADWORDS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Default Bad Words"));
- EnumSpamDefinitions(SDID_SPAMMERS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Known Spammers"));
- EnumSpamDefinitions(SDID_TEASERTEXTS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Known Teaser Texts"));
-
- EnumSpamDefinitions(SDID_URLTLDS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("URL Recognition"));
- EnumSpamDefinitions(SDID_PHONENUMBERS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Phone Number Recognition"));
-
- EnumSpamDefinitions(SDID_SPECIALCHARS_REPLACE_TEXT, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Different Format Recognition: Text"));
- EnumSpamDefinitions(SDID_SPECIALCHARS_REPLACE_NUMBERS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Different Format Recognition: Numbers"));
- EnumSpamDefinitions(SDID_SPECIALCHARS_SEPARATORS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Different Format Recognition: Separators"));
- break;
- }
-
- case SFT_DISLIKEDMESSAGES_FILTER:
- {
- SetWindowText(hwndDlg, TranslateT("Spam Definitions: Disliked Messages Filter"));
-
- EnumSpamDefinitions(SDID_HOAXTEXTS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Known Hoax Texts"));
- break;
- }
- }
-
- if (iSelectedIndex >= 0)
- {
- if (iSelectedIndex >= ListView_GetItemCount(hwndList))
- iSelectedIndex = ListView_GetItemCount(hwndList)-1;
-
- ListView_SetSelectionMark(hwndList, iSelectedIndex);
- ListView_EnsureVisible(hwndList, iSelectedIndex, FALSE);
- }
-
- FixListHeader(hwndList);
- return TRUE;
- }
-
- case SFM_REMOVE_SPAMDEFINITIONFILE:
- {
- int iItem = (int)wParam;
- HWND hwndList = GetDlgItem(hwndDlg, IDC_LISTVIEW_SPAMDEFINITIONS);
-
- LVITEM lvi;
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.mask = LVIF_PARAM;
- lvi.iItem = iItem;
-
- // Get item
- if (ListView_GetItem(hwndList, &lvi))
- {
- if (lvi.lParam)
- {
- SHFILEOPSTRUCT sfo;
-
- // Doubly-null terminated pFrom (as required)
- WCHAR szFrom[MAX_PATH+1];
- mir_sntprintf(szFrom, ARRAYSIZE(szFrom)-1, _T("%s"), lvi.lParam);
- szFrom[lstrlen(szFrom)+1] = _T('\0');
-
- ZeroMemory(&sfo, sizeof(sfo));
- sfo.hwnd = hwndDlg;
- sfo.wFunc = FO_DELETE;
- sfo.pFrom = szFrom;
- sfo.fFlags = FOF_SIMPLEPROGRESS|FOF_NO_CONNECTED_ELEMENTS;
- sfo.lpszProgressTitle = lvi.pszText;
-
- // Ask to delete file
- if (SHFileOperation(&sfo) == 0)
- if (!sfo.fAnyOperationsAborted)
- if (ListView_DeleteItem(hwndList, iItem))
- {
- // Select next item
- if (iItem >= ListView_GetItemCount(hwndList))
- iItem--;
-
- ListView_SetSelectionMark(hwndList, iItem);
- }
-
- }
- }
-
- return TRUE;
- }
-
- case WM_NOTIFY:
- {
- LPNMHDR pnmhdr = (LPNMHDR)lParam;
-
- switch (pnmhdr->idFrom)
- {
- case IDC_TAB_SPAMDEFINITIONS:
- {
- switch (pnmhdr->code)
- {
- case TCN_SELCHANGE:
- {
- TCITEM tci;
- tci.mask = TCIF_PARAM;
-
- if (TabCtrl_GetItem(pnmhdr->hwndFrom, TabCtrl_GetCurSel(pnmhdr->hwndFrom), &tci))
- SendMessage(hwndDlg, SFM_REFRESH_SPAMDEFINITIONS, (WPARAM)FALSE, (LPARAM)tci.lParam);
-
- return TRUE;
- }
- }
-
- break;
- }
-
- case IDC_LISTVIEW_SPAMDEFINITIONS:
- {
- switch (pnmhdr->code)
- {
- case LVN_DELETEITEM:
- {
- LVITEM lvi;
-
- lvi.mask = LVIF_PARAM;
- lvi.iItem = ((LPNMLISTVIEW)lParam)->iItem;
-
- // Release lParam memory of removed item
- if (ListView_GetItem(pnmhdr->hwndFrom, &lvi))
- if (lvi.lParam)
- mir_free((WCHAR*)lvi.lParam);
-
- return FALSE;
- }
-
- case LVN_KEYDOWN:
- {
- switch (((NMLVKEYDOWN*)lParam)->wVKey)
- {
- case VK_DELETE:
- {
- PostMessage(hwndDlg, SFM_REMOVE_SPAMDEFINITIONFILE, (WPARAM)ListView_GetSelectionMark(pnmhdr->hwndFrom), 0);
-
- // Prevent default processing
- SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)FALSE);
- return TRUE;
- }
- }
-
- break;
- }
-
- case NM_RCLICK:
- {
- LPNMLISTVIEW pnmlw = (LPNMLISTVIEW)lParam;
-
- HMENU hMenu, hContextMenu;
- LVITEM lvi;
-
- // Click was not on an item
- if (pnmlw->iItem < 0) break;
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.mask = LVIF_PARAM;
- lvi.iItem = pnmlw->iItem;
-
- // Get item
- if (!ListView_GetItem(pnmhdr->hwndFrom, &lvi)) break;
- if (!lvi.lParam) break;
- if (!ClientToScreen(pnmhdr->hwndFrom, &(pnmlw->ptAction))) break;
-
- // Context menu
- hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_CONTEXT));
- hContextMenu = GetSubMenu(hMenu, 1);
- CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hContextMenu, 0);
- switch (TrackPopupMenuEx(hContextMenu, TPM_RETURNCMD|TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, pnmlw->ptAction.x, pnmlw->ptAction.y, pnmhdr->hwndFrom, NULL))
- {
- case ID_MENU_DELETE:
- {
- PostMessage(hwndDlg, SFM_REMOVE_SPAMDEFINITIONFILE, (WPARAM)pnmlw->iItem, 0);
- break;
- }
- }
-
- // Destroy context menu
- if (hMenu) DestroyMenu(hMenu);
-
- // Prevent default processing
- SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)FALSE);
- return TRUE;
- }
-
- } // switch
-
- break;
- }
-
- } // switch
-
- break;
- }
-
- case WM_DESTROY:
- {
- hwndSpamDefinitionsInfo = NULL;
-
- // Free font
- DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0));
-
- // Save dlg position
- Utils_SaveWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_SPAMDEF_DIALOGPOSITION);
-
- return TRUE;
- }
-
- case WM_CLOSE:
- {
- // Different method of closing the window depending on if the window
- // was created modal or not
- if (!GetParent(hwndDlg))
- DestroyWindow(hwndDlg);
- else
- EndDialog(hwndDlg, IDCANCEL);
-
- return TRUE;
- }
-
- case WM_COMMAND:
- {
- switch (LOWORD(wParam))
- {
- case IDC_URL_GETMORE:
- {
- CallService(MS_UTILS_OPENURL, (WPARAM)TRUE, (LPARAM)Translate("http://addons.miranda-im.org/index.php?action=display&id=92"));
- return TRUE;
- }
-
- case IDOK:
- case IDCANCEL:
- // WM_CLOSE is transformed into an IDCANCEL by dialog manager
- {
- // Different method of closing the window depending on if the window
- // was created modal or not
- if (!GetParent(hwndDlg))
- DestroyWindow(hwndDlg);
- else
- EndDialog(hwndDlg, LOWORD(wParam));
-
- return TRUE;
- }
-
- } // switch wParam
-
- break;
- }
-
- case WM_SIZE:
- {
- UTILRESIZEDIALOG urd;
-
- ZeroMemory(&urd, sizeof(urd));
- urd.cbSize = sizeof(urd);
- urd.hInstance = hInstance;
- urd.hwndDlg = hwndDlg;
- urd.lpTemplate = MAKEINTRESOURCEA(IDD_INFO_SPAMDEFINITIONS);
- urd.pfnResizer = ResizeProcSpamDefinitionsInfo;
-
- CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd);
-
- // Resize listview to exactly fit tab control
- {
- RECT rcDisplay;
- POINT pt = {0, 0};
-
- if (GetWindowRect(GetDlgItem(hwndDlg, IDC_TAB_SPAMDEFINITIONS), &rcDisplay))
- {
- TabCtrl_AdjustRect(GetDlgItem(hwndDlg, IDC_TAB_SPAMDEFINITIONS), FALSE, &rcDisplay);
- if (ClientToScreen(hwndDlg, &pt))
- OffsetRect(&rcDisplay, -pt.x, -pt.y);
-
- SetWindowPos(GetDlgItem(hwndDlg, IDC_LISTVIEW_SPAMDEFINITIONS), HWND_TOP, rcDisplay.left, rcDisplay.top, rcDisplay.right-rcDisplay.left, rcDisplay.bottom-rcDisplay.top, SWP_NOACTIVATE);
- }
- }
-
- FixListHeader(GetDlgItem(hwndDlg, IDC_LISTVIEW_SPAMDEFINITIONS));
- return TRUE;
- }
-
- case WM_GETMINMAXINFO:
- {
- ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = 340;
- ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = 150;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-
-
-void Spammers_ResetListOptions(HWND hwndList)
-{
- int i;
-
- // Same layout as Ignore options
- SendMessage(hwndList, CLM_SETBKBITMAP, 0, (LPARAM)(HBITMAP)NULL);
- SendMessage(hwndList, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW),0);
- SendMessage(hwndList, CLM_SETGREYOUTFLAGS, 0, 0);
- SendMessage(hwndList, CLM_SETLEFTMARGIN, 4, 0);
- SendMessage(hwndList, CLM_SETINDENT, 10, 0);
- SendMessage(hwndList, CLM_SETHIDEEMPTYGROUPS, TRUE, 0);
- SendMessage(hwndList, CLM_SETUSEGROUPS, FALSE, 0);
-
- for(i=0;i<=FONTID_MAX;i++)
- SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
-}
-
-int Spammers_GetListIcon(HWND hwndList, HANDLE hItem)
-{
- int i;
-
- for (i=0; i<SendMessage(hwndList, CLM_GETEXTRACOLUMNS, 0, 0); i++)
- if (SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(i, 0)) == i)
- return i;
-
- return -1;
-}
-
-void Spammers_SetListIcon(HWND hwndList, HANDLE hItem, int iColumn)
-{
- int i, iColCount;
-
- iColCount = SendMessage(hwndList, CLM_GETEXTRACOLUMNS, 0, 0);
- for (i=0; i<iColCount; i++)
- SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(i, (i==iColumn)?i:iColCount));
-}
-
-void Spammers_SetAllListIcons(HWND hwndList, int iColumn, BOOL bForce, BOOL bWatchForDeleted)
-{
- HANDLE hContact, hItem;
-
- for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); hContact; hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0))
- {
- hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
- if (!hItem) continue;
-
- if (CallService(MS_SPAMFILTER_CONTACT_ISSPAMMER, (WPARAM)hContact, 0))
- {
- if (bWatchForDeleted)
- if (DBGetContactSettingByte(hContact, "CList", "Delete", 0)) {
- Spammers_SetListIcon(hwndList, hItem, 1);
- BOX("wathce ditem found");
- continue;
- }
- if (bForce || (Spammers_GetListIcon(hwndList, hItem) == -1))
- Spammers_SetListIcon(hwndList, hItem, iColumn);
- } else {
- SendMessage(hwndList, CLM_DELETEITEM, (WPARAM)hItem, 0); // Remove no-spammers
- }
- }
-}
-
-
-static int ResizeProcSpammersInfo(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL *urc)
-{
- switch(urc->wId)
- {
- case IDC_TEXT_DESCRIPTION:
- return RD_ANCHORY_TOP|RD_ANCHORX_WIDTH;
-
- case IDC_CLIST:
- return RD_ANCHORY_HEIGHT|RD_ANCHORX_WIDTH;
-
- case IDC_GROUP:
- case IDC_CHECKBOX_GROUP:
- case IDC_CHECKBOX_HIDE:
- case IDC_EDITBOX_GROUP:
- return RD_ANCHORY_BOTTOM|RD_ANCHORX_WIDTH;
-
- case IDC_ICON_SPAM:
- case IDC_TEXT_SPAM:
- case IDC_ICON_NORMAL:
- case IDC_TEXT_NORMAL:
- case IDC_ICON_DELETE:
- case IDC_TEXT_DELETE:
- return RD_ANCHORY_TOP|RD_ANCHORX_RIGHT;
-
- //case IDOK:
- //case IDC_BUTTON_RESET:
- //case IDC_SCROLLBAR_SIZEGRIP:
- default:
- return RD_ANCHORY_BOTTOM|RD_ANCHORX_RIGHT;
- }
-}
-
-BOOL CALLBACK DlgProcSpammersInfo(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- HIMAGELIST hIml;
- HICON hSpam, hNormal, hDelete, hDots;
-
- hwndSpammersInfo = hwndDlg;
-
- // Translate dialog first
- TranslateDialogDefault(hwndDlg);
-
- // Init set/unset icons (Loading icons out of miranda32.exe)
- hIml = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), (IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK, 4, 0);
- hSpam = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(212), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
- ImageList_AddIcon(hIml, hSpam);
- hDelete = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(175), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
- ImageList_AddIcon(hIml, hDelete);
- hNormal = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(213), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
- ImageList_AddIcon(hIml, hNormal);
- SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hIml);
- hDots = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(211), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
- ImageList_AddIcon(hIml, hDots);
-
- Spammers_ResetListOptions(GetDlgItem(hwndDlg, IDC_CLIST));
- SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRACOLUMNS, (WPARAM)3, 0);
- Spammers_SetAllListIcons(GetDlgItem(hwndDlg, IDC_CLIST), 0, TRUE, TRUE);
-
- SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ICON_SPAM), GWLP_USERDATA, (LONG_PTR)0);
- SendDlgItemMessage(hwndDlg, IDC_ICON_SPAM, STM_SETICON, (WPARAM)hSpam, 0);
- SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ICON_DELETE), GWLP_USERDATA, (LONG_PTR)1);
- SendDlgItemMessage(hwndDlg, IDC_ICON_DELETE, STM_SETICON, (WPARAM)hDelete, 0);
- SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ICON_NORMAL), GWLP_USERDATA, (LONG_PTR)2);
- SendDlgItemMessage(hwndDlg, IDC_ICON_NORMAL, STM_SETICON, (WPARAM)hNormal, 0);
-
- // New window icon
- SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hSpam);
-
- // Make top text
- {
- HFONT hBoldFont;
- LOGFONT lf;
-
- GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0), sizeof(lf), &lf);
- lf.lfWeight = FW_BOLD;
- hBoldFont = CreateFontIndirect(&lf);
-
- SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_SETFONT, (WPARAM)hBoldFont, 0);
- }
-
- // Spammers group
- {
- DBVARIANT dbv;
-
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUPNAME, &dbv) == 0) {
- SetDlgItemText(hwndDlg, IDC_EDITBOX_GROUP, dbv.ptszVal);
- DBFreeVariant(&dbv);
- } else {
- SetDlgItemText(hwndDlg, IDC_EDITBOX_GROUP, DEFAULT_SETTING_MOVETOGROUPNAME);
- }
-
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_GROUP, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUP, (BYTE)DEFAULT_SETTING_MOVETOGROUP) ? BST_CHECKED : BST_UNCHECKED));
- CheckDlgButton(hwndDlg, IDC_CHECKBOX_HIDE, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_HIDEFROMCLIST, (BYTE)DEFAULT_SETTING_HIDEFROMCLIST) ? BST_CHECKED : BST_UNCHECKED));
- }
-
- SendMessage(hwndDlg, SFM_ENABLE_SUBCTRLS, 0, 0);
-
- // Restore dlg position (at the end, so the dialog does not get shown early)
- Utils_RestoreWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_SPAMMERS_DIALOGPOSITION);
- // Make sure the dialog is not moved out of sight
- SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
- SendMessage(hwndDlg, WM_SIZE, 0, 0); //simulate message
-
- // SetFocus (SetFocus() is not allowed in Dialogs)
- SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), (LPARAM)TRUE);
- return FALSE;
- }
-
- case WM_NOTIFY:
- {
- LPNMHDR pnmh = (LPNMHDR)lParam;
-
- switch (pnmh->idFrom)
- {
- case IDC_CLIST:
- {
- switch (pnmh->code)
- {
- case CLN_NEWCONTACT:
- case CLN_CONTACTMOVED:
- case CLN_LISTREBUILT:
- Spammers_SetAllListIcons(pnmh->hwndFrom, 0, FALSE, TRUE);
- return TRUE;
-
- case CLN_OPTIONSCHANGED:
- Spammers_ResetListOptions(pnmh->hwndFrom);
- return TRUE;
-
- case NM_CLICK:
- {
- HANDLE hItem;
- NMCLISTCONTROL* nm = (NMCLISTCONTROL*)lParam;
- DWORD hitFlags;
-
- if (nm->iColumn < 0) break;
- hItem = (HANDLE)SendMessage(pnmh->hwndFrom, CLM_HITTEST, (WPARAM)&hitFlags, MAKELPARAM(nm->pt.x, nm->pt.y));
- if (hItem == NULL) break;
- if (!(hitFlags&CLCHT_ONITEMEXTRA)) break;
-
- Spammers_SetListIcon(pnmh->hwndFrom, hItem, nm->iColumn);
- return TRUE;
- }
- }
-
- break;
- }
-
- }
- break;
- }
-
- case SFM_REFRESH_SPAMMERS:
- {
- SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_AUTOREBUILD, 0, 0);
- return TRUE;
- }
-
- case SFM_ENABLE_SUBCTRLS:
- {
- BOOL bStatus = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_GROUP) == BST_CHECKED);
- EnableDlgItem(hwndDlg, IDC_EDITBOX_GROUP, bStatus);
- return TRUE;
- }
-
- case WM_CLOSE:
- {
- // Different method of closing the window depending on if the window
- // was created modal or not
- if (!GetParent(hwndDlg))
- DestroyWindow(hwndDlg);
- else
- EndDialog(hwndDlg, IDCANCEL);
-
- return TRUE;
- }
-
- case WM_COMMAND:
- {
- switch (LOWORD(wParam))
- {
- case IDC_ICON_SPAM:
- case IDC_ICON_NORMAL:
- case IDC_ICON_DELETE:
- {
- if (HIWORD(wParam) == STN_CLICKED)
- {
- Spammers_SetAllListIcons(GetDlgItem(hwndDlg, IDC_CLIST), (int)GetWindowLongPtr(GetDlgItem(hwndDlg, LOWORD(wParam)), GWLP_USERDATA), TRUE, FALSE);
- return TRUE;
- }
- break;
- }
-
- case IDC_CHECKBOX_GROUP:
- {
- SendMessage(hwndDlg, SFM_ENABLE_SUBCTRLS, 0, 0);
- return TRUE;
- }
-
- case IDOK:
- {
- HANDLE hContact, hItem;
- HWND hwndList = GetDlgItem(hwndDlg, IDC_CLIST);
-
- EnableDlgItem(hwndDlg, IDOK, FALSE);
-
- // Spammers group
- {
- HWND hwndEdit = GetDlgItem(hwndDlg, IDC_EDITBOX_GROUP);
- int iTextLen = GetWindowTextLength(hwndEdit);
- WCHAR* pszText = (WCHAR*)mir_alloc((iTextLen+1)*sizeof(WCHAR));
- BOOL bUseGroup, bGroupCreated;
- DBVARIANT dbv;
-
- // Get entered text
- if (pszText)
- {
- if (GetWindowText(hwndEdit, pszText, iTextLen+1) == 0)
- pszText[0] = _T('\0');
-
- // Save text
- if (lstrlen(pszText) > 0) {
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUPNAME, pszText);
- bUseGroup = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_GROUP) == BST_CHECKED);
- } else {
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUPNAME, DEFAULT_SETTING_MOVETOGROUPNAME);
- bUseGroup = FALSE;
- }
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUP, (BYTE)bUseGroup);
- } else {
- bUseGroup = FALSE;
- }
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_HIDEFROMCLIST, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_HIDE) == BST_CHECKED));
-
- // Remove previous group (if changed)
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUPNAME, &dbv) == 0)
- {
- // Show remove group UI
- if (StrCmp(dbv.ptszVal, pszText) != 0)
- RemoveContactListGroup(dbv.ptszVal);
- DBFreeVariant(&dbv);
- }
-
- // Move all spammers to this group
- bGroupCreated = FALSE;
- for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); hContact; hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0))
- {
- hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
- if (!hItem) continue;
-
- switch (Spammers_GetListIcon(hwndList, hItem))
- {
- case 1: // delete
- {
- int status;
- char* pszProto;
-
- // Check if protocol uses server side lists
- pszProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
- if (pszProto)
- if ((DWORD)CallProtoService(pszProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_SERVERCLIST)
- {
- status = CallProtoService(pszProto, PS_GETSTATUS, 0, 0);
- if (status == ID_STATUS_OFFLINE || (status >= ID_STATUS_CONNECTING && status < ID_STATUS_CONNECTING + MAX_CONNECT_RETRIES))
- {
- DBWriteContactSettingByte(hContact, "CList", "Delete", 1);
- break;
- }
- }
-
- CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
- break;
- }
- case 2: // normal
- DBDeleteContactSetting(hContact, "CList", "Delete");
- CallService(MS_SPAMFILTER_CONTACT_UNSETSPAMMER, (WPARAM)hContact, 0);
- break;
-
- case 0: // spammer
- if (bUseGroup && !bGroupCreated) {
- CreateContactListGroup(pszText);
- bGroupCreated = TRUE;
- }
- if (bUseGroup) {
- if (DBGetContactSettingTString(hContact, "CList", "Group", &dbv) == 0)
- {
- if (StrCmp(dbv.ptszVal, pszText) != 0)
- DBWriteContactSettingTString(hContact, "CList", "Group", pszText);
- DBFreeVariant(&dbv);
- }
- } else {
- DBDeleteContactSetting(hContact, "CList", "Group");
- }
- DBDeleteContactSetting(hContact, "CList", "Delete");
- break;
- }
- }
-
- // Display remove group window
- //if (!bUseGroup || !bGroupCreated)
- // RemoveContactListGroup(pszText);
-
- if (pszText) mir_free(pszText);
- }
-
- // fall through
- }
-
- case IDCANCEL:
- // WM_CLOSE is transformed into an IDCANCEL by dialog manager
- {
- // Different method of closing the window depending on if the window
- // was created modal or not
- if (!GetParent(hwndDlg))
- DestroyWindow(hwndDlg);
- else
- EndDialog(hwndDlg, LOWORD(wParam));
-
- return TRUE;
- }
-
- }
-
- break;
- }
-
- case WM_DESTROY:
- {
- hwndSpammersInfo = NULL;
-
- ImageList_Destroy((HIMAGELIST)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETEXTRAIMAGELIST, 0, 0));
-
- // Free font
- DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0));
-
- // Save dlg position
- Utils_SaveWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_SPAMMERS_DIALOGPOSITION);
- return TRUE;
- }
-
- case WM_SIZE:
- {
- UTILRESIZEDIALOG urd;
-
- ZeroMemory(&urd, sizeof(urd));
- urd.cbSize = sizeof(urd);
- urd.hInstance = hInstance;
- urd.hwndDlg = hwndDlg;
- urd.lpTemplate = MAKEINTRESOURCEA(IDD_INFO_SPAMMERS);
- urd.pfnResizer = ResizeProcSpammersInfo;
-
- CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd);
- return TRUE;
- }
-
- case WM_GETMINMAXINFO:
- {
- ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = 370;
- ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = 220;
- return TRUE;
- }
-
- }
-
- return FALSE;
-}
-
-
-// -- ListBox helper functions
-
-LRESULT CALLBACK WordsListBoxSubclassProc(HWND hwndListBox, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- int iButtonAdd;
- int iButtonDelete;
-
- // Get associated list box control id
- switch (GetDlgCtrlID(hwndListBox))
- {
- case IDC_LISTBOX_CUSTOMIZEDBADWORDS:
- {
- iButtonAdd = IDC_BUTTON_ADDBADWORD;
- iButtonDelete = IDC_BUTTON_DELETEBADWORD;
- break;
- }
-
- case IDC_LISTBOX_CUSTOMIZEDGOODWORDS:
- {
- iButtonAdd = IDC_BUTTON_ADDGOODWORD;
- iButtonDelete = IDC_BUTTON_DELETEGOODWORD;
- break;
- }
-
- case IDC_LISTBOX_CUSTOMIZEDWORDS:
- {
- iButtonAdd = IDC_BUTTON_ADDWORD;
- iButtonDelete = IDC_BUTTON_DELETEWORD;
- break;
- }
-
- default:
- {
- iButtonAdd = -1;
- iButtonDelete = -1;
- break;
- }
- }
-
- switch (uMsg)
- {
- case LB_INSERTSTRING:
- case LB_ADDSTRING:
- {
- // Set horizontal extent
- int iHorExt;
-
- if (!lParam) break;
-
- iHorExt = GetCtrlTextExtent(hwndListBox, (WCHAR*)lParam, TRUE);
-
- if (iHorExt > SendMessage(hwndListBox, LB_GETHORIZONTALEXTENT, 0, 0))
- PostMessage(hwndListBox, LB_SETHORIZONTALEXTENT, (LPARAM)iHorExt, 0);
-
- break;
- }
-
- case LB_DELETESTRING:
- {
- // Set horizontal extent
- int i;
- int iLen, iHorExt = 0;
- int iItemCount = (int)SendMessage(hwndListBox, LB_GETCOUNT, 0, 0);
- WCHAR* pszItemText;
-
- for (i=0; i<iItemCount; i++)
- {
- // Ignore the item that is to be deleted
- if (i == (int)wParam) continue;
-
- iLen = (int)SendMessage(hwndListBox, LB_GETTEXTLEN, (WPARAM)i, 0);
- if (iLen < 0) continue;
-
- pszItemText = (WCHAR*)mir_alloc((iLen+1)*sizeof(WCHAR));
- if (!pszItemText) continue;
-
- if (SendMessage(hwndListBox, LB_GETTEXT, (WPARAM)i, (LPARAM)pszItemText) == LB_ERR)
- *pszItemText = _T('\0');
-
- iHorExt = max(iHorExt, GetCtrlTextExtent(hwndListBox, pszItemText, TRUE));
- mir_free(pszItemText);
- }
-
- if (iHorExt != SendMessage(hwndListBox, LB_GETHORIZONTALEXTENT, 0, 0))
- PostMessage(hwndListBox, LB_SETHORIZONTALEXTENT, (WPARAM)iHorExt, 0);
-
- break;
- }
-
- case LB_RESETCONTENT:
- {
- // Reset horizontal extent
- PostMessage(hwndListBox, LB_SETHORIZONTALEXTENT, 0, 0);
-
- break;
- }
-
- case LB_SETHORIZONTALEXTENT:
- {
- RECT rc;
- BOOL bShowHScroll;
-
- // Do not show horizontal scrollbars if not needed
- if (GetClientRect(hwndListBox, &rc))
- bShowHScroll = ((int)wParam > (rc.right-rc.left));
- else
- bShowHScroll = TRUE;
-
- // Show/Hide horizontal scrollbars; DISABLENOSCROLL does not work correctly
- ShowScrollBar(hwndListBox, SB_HORZ, bShowHScroll);
-
- // Scroll to left if scrollbar hidden
- if (!bShowHScroll)
- PostMessage(hwndListBox, WM_HSCROLL, SB_LEFT, 0);
-
- break;
- }
-
- case WM_CONTEXTMENU:
- {
- HMENU hMenu, hContextMenu;
- int iHoveredItem;
- POINT pt;
- POINTSTOPOINT(pt, MAKEPOINTS(lParam));
-
- // Menu started by keyboard shortcut
- if ((pt.x == -1) && (pt.y == -1))
- {
- RECT rc;
-
- iHoveredItem = SendMessage(hwndListBox, LB_GETCURSEL, 0, 0);
-
- // Get item pos
- if (SendMessage(hwndListBox, LB_GETITEMRECT, (WPARAM)iHoveredItem, (LPARAM)&rc) != LB_ERR)
- if (!GetWindowRect(hwndListBox, &rc))
- rc.left = rc.top = rc.right = rc.bottom = 0;
-
- // Position it in the middle of the rect
- pt.x = rc.left + (int)((rc.right-rc.left)/2);
- pt.y = rc.top + (int)((rc.bottom-rc.top)/2);
-
- } else {
- // LBItemFromPt returns an item if no item is in list
- if (SendMessage(hwndListBox, LB_GETCOUNT, 0, 0) == 0)
- iHoveredItem = LB_ERR;
- else
- iHoveredItem = LBItemFromPt(hwndListBox, pt, FALSE);
-
- // Select list box item
- if (iHoveredItem >= 0)
- SendMessage(hwndListBox, LB_SETCURSEL, iHoveredItem, 0);
- }
-
- // Context menu
- hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_CONTEXT));
- hContextMenu = GetSubMenu(hMenu, 0);
- CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hContextMenu, 0);
-
- // If user did not click on a list item
- if (iHoveredItem < 0)
- RemoveMenu(hContextMenu, ID_MENU_DELETE, MF_BYCOMMAND);
-
- switch (TrackPopupMenuEx(hContextMenu, TPM_RETURNCMD|TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, hwndListBox, NULL))
- {
- case ID_MENU_DELETE:
- {
- // Simulate 'Delete' button
- if (iButtonDelete >= 0)
- SendMessage(GetParent(hwndListBox), WM_COMMAND, MAKEWPARAM(iButtonDelete, BN_CLICKED), (LPARAM)GetDlgItem(GetParent(hwndListBox), iButtonDelete));
- break;
- }
-
- case ID_MENU_ADD:
- {
- // Simulate 'Add' button
- if (iButtonAdd >= 0)
- SendMessage(GetParent(hwndListBox), WM_COMMAND, MAKEWPARAM(iButtonAdd, BN_CLICKED), (LPARAM)GetDlgItem(GetParent(hwndListBox), iButtonAdd));
- break;
- }
- }
-
- // Destroy context menu
- if (hMenu) DestroyMenu(hMenu);
-
- return 0;
- }
-
- case WM_KEYDOWN:
- {
- int iSelectedItem = SendMessage(hwndListBox, LB_GETCURSEL, 0, 0);
-
- if (iSelectedItem >= 0)
- {
- switch (wParam)
- {
- case VK_BACK:
- case VK_SUBTRACT:
- case VK_DELETE:
- {
- // Simulate 'Delete' button
- if (iButtonDelete >= 0)
- SendMessage(GetParent(hwndListBox), WM_COMMAND, MAKEWPARAM(iButtonDelete, BN_CLICKED), (LPARAM)GetDlgItem(GetParent(hwndListBox), iButtonDelete));
-
- return TRUE;
- }
-
- case VK_SPACE:
- case VK_ADD:
- case VK_INSERT:
- {
- // Simulate 'Add' button
- if (iButtonAdd >= 0)
- SendMessage(GetParent(hwndListBox), WM_COMMAND, MAKEWPARAM(iButtonAdd, BN_CLICKED), (LPARAM)GetDlgItem(GetParent(hwndListBox), iButtonAdd));
-
- return TRUE;
- }
-
- //case VK_PRIOR:
- case VK_UP:
- {
- // Select one entry up if not first entry
- if (iSelectedItem > 0)
- SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)iSelectedItem-1, 0);
-
- return TRUE;
- }
-
- //case VK_NEXT:
- case VK_DOWN:
- {
- // Select one entry down
- SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)iSelectedItem+1, 0);
-
- return TRUE;
- }
-
- } // switch wParam
-
- }
-
- return FALSE;
- }
-
- case WM_GETDLGCODE:
- {
- return DLGC_WANTALLKEYS;
- }
-
- } //switch uMsg
-
- return CallWindowProc((WNDPROC)GetWindowLongPtr(hwndListBox, GWLP_USERDATA), hwndListBox, uMsg, wParam, lParam);
-}
-
-
-BOOL CALLBACK DlgProcWordsListBoxAddItem(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- // Get passed data
- struct WORDSLISTBOXADDITEMPARAMS* pwlbaip = (struct WORDSLISTBOXADDITEMPARAMS*)lParam;
-
- SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pwlbaip);
-
- // Translate dialog
- TranslateDialogDefault(hwndDlg);
-
- // Set text
- SetWindowText(hwndDlg, pwlbaip->pszTitle);
-
- // Make button and caption use message box font
- {
- NONCLIENTMETRICS ncm;
- HFONT hBoldFont;
-
- ZeroMemory(&ncm, sizeof(ncm));
- ncm.cbSize = sizeof(ncm);
- if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0))
- {
- hBoldFont = CreateFontIndirect(&ncm.lfMessageFont);
-
- SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_SETFONT, (WPARAM)hBoldFont, 0);
- //SendDlgItemMessage(hwndDlg, IDOK, WM_SETFONT, (WPARAM)hBoldFont, 0);
- //SendDlgItemMessage(hwndDlg, IDCANCEL, WM_SETFONT, (WPARAM)hBoldFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_TEXT_QUICKHELP, WM_SETFONT, (WPARAM)hBoldFont, 0);
- SendDlgItemMessage(hwndDlg, IDC_TEXT_HELPNESTED, WM_SETFONT, (WPARAM)hBoldFont, 0);
- }
- }
-
- // Show/Hide RegExp hint and help
- // More info about Regular Expressions: http://perldoc.perl.org/perlrequick.html
- {
- // Set icon and resize button
- SetWindowPos(GetDlgItem(hwndDlg, IDC_BUTTON_REGEXP), NULL, 0, 0, 20, 20, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
- SendDlgItemMessage(hwndDlg, IDC_BUTTON_REGEXP, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)LoadSystemIcon(IDB_STD_SMALL_COLOR, STD_HELP));
- PostMessage(GetDlgItem(hwndDlg, IDC_BUTTON_REGEXP), BUTTONADDTOOLTIP, (WPARAM)Translate("&How to use Regular Expressions"), 0);
- SendMessage(GetDlgItem(hwndDlg, IDC_BUTTON_REGEXP), BUTTONSETASFLATBTN, 0, 0);
- SendMessage(GetDlgItem(hwndDlg, IDC_BUTTON_REGEXP), BUTTONSETASPUSHBTN, 0, 0);
-
- // Do not show hint/help if RegExp DLL not available
- if (!RegExpEnabled())
- {
- RECT rcEdit, rcBtn;
-
- SetDlgItemText(hwndDlg, IDC_TEXT_REGEXP, TranslateT("(Regular Expressions disabled)"));
- ShowDlgItem(hwndDlg, IDC_BUTTON_REGEXP, FALSE);
-
- if (GetWindowRect(GetDlgItem(hwndDlg, IDC_EDITBOX_NEWITEM), &rcEdit))
- if (GetWindowRect(GetDlgItem(hwndDlg, IDC_BUTTON_REGEXP), &rcBtn))
- SetWindowPos(GetDlgItem(hwndDlg, IDC_EDITBOX_NEWITEM), NULL, 0, 0, (rcBtn.right-rcEdit.left), (rcEdit.bottom-rcEdit.top), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
- }
- }
-
- // Position/Resize window
- {
- RECT rcWin, rcSep;
- int iHeight, iWidth;
-
- // Get sizes
- if ( GetWindowRect(hwndDlg, &rcWin) &&
- GetWindowRect(GetDlgItem(hwndDlg, IDC_RECT_SEPARATOR), &rcSep) )
- {
- iHeight = rcSep.top-rcWin.top + (int)((rcSep.bottom-rcSep.top)/2);
- iWidth = rcWin.right-rcWin.left;
-
- // Remember normal height
- SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_RECT_SEPARATOR), GWLP_USERDATA, (LONG_PTR)(rcWin.bottom-rcWin.top));
-
- // Hide separator
- ShowDlgItem(hwndDlg, IDC_RECT_SEPARATOR, FALSE);
-
- } else {
- iHeight = 0;
- iWidth = 0;
- }
-
- // Position the window (and hide RegExp help initially)
- SetWindowPos(hwndDlg, NULL, pwlbaip->ptPos.x, pwlbaip->ptPos.y, iWidth, iHeight, (((iHeight==0)||(iWidth==0))?SWP_NOSIZE:0)|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
-
- // Make sure the dialog is not moved out of sight
- SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
- }
-
- // SetFocus (SetFocus() is not allowed in Dialogs)
- SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_NEWITEM), (LPARAM)TRUE);
- return FALSE;
- }
-
- case WM_SETTINGCHANGE:
- {
- NONCLIENTMETRICS ncm;
- HFONT hBoldFont;
-
- // Free old message box font
- DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0));
-
- // Update message box font
- ZeroMemory(&ncm, sizeof(ncm));
- ncm.cbSize = sizeof(ncm);
- if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0))
- {
- hBoldFont = CreateFontIndirect(&ncm.lfMessageFont);
-
- SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_SETFONT, (WPARAM)hBoldFont, 0);
- //SendDlgItemMessage(hwndDlg, IDOK, WM_SETFONT, (WPARAM)hBoldFont, 0);
- //SendDlgItemMessage(hwndDlg, IDCANCEL, WM_SETFONT, (WPARAM)hBoldFont, 0);
- }
- return TRUE;
- }
-
- case WM_DESTROY:
- {
- // Destroy help icon
- DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_BUTTON_REGEXP, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0));
-
- // Free message box font
- DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0));
-
- return TRUE;
- }
-
- case WM_COMMAND:
- {
- switch (LOWORD(wParam))
- {
- case IDC_BUTTON_REGEXP:
- {
- // Show/Hide RegExp help part
- RECT rcWin, rcSep;
- int iHeight, iWidth;
-
- if (GetWindowRect(hwndDlg, &rcWin))
- {
- iWidth = rcWin.right-rcWin.left;
-
- // Hide/Show help
- if (!IsDlgButtonChecked(hwndDlg, IDC_BUTTON_REGEXP))
- {
- if (GetWindowRect(GetDlgItem(hwndDlg, IDC_RECT_SEPARATOR), &rcSep))
- {
- iHeight = rcSep.top-rcWin.top + (int)((rcSep.bottom-rcSep.top)/2);
-
- // Position the window
- ShowDlgItem(hwndDlg, IDC_RECT_SEPARATOR, FALSE);
- SetWindowPos(hwndDlg, NULL, 0, 0, iWidth, iHeight, SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE);
- }
- } else {
- iHeight = (int)GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_RECT_SEPARATOR), GWLP_USERDATA);
-
- // Position the window
- SetWindowPos(hwndDlg, NULL, 0, 0, iWidth, iHeight, SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE);
- ShowDlgItem(hwndDlg, IDC_RECT_SEPARATOR, TRUE);
- }
- }
-
- // Make sure the dialog is not enlarged out of sight
- SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
-
- return TRUE;
- }
-
- case IDOK:
- {
- struct WORDSLISTBOXADDITEMPARAMS* pwlbaip;
- HWND hwndEdit;
- int iNewItemSize;
-
- pwlbaip = (struct WORDSLISTBOXADDITEMPARAMS*)GetWindowLongPtr(hwndDlg, DWLP_USER);
-
- // Get entered text
- if (pwlbaip)
- {
- hwndEdit = GetDlgItem(hwndDlg, IDC_EDITBOX_NEWITEM);
- iNewItemSize = GetWindowTextLength(hwndEdit)+1;
- pwlbaip->pszNewItem = (WCHAR*)mir_alloc((iNewItemSize)*sizeof(WCHAR));
-
- if (pwlbaip->pszNewItem)
- if (GetWindowText(hwndEdit, pwlbaip->pszNewItem, iNewItemSize) == 0) // GetWindowText takes the size not the len of the string
- *pwlbaip->pszNewItem = _T('\0');
- }
-
- // fall through
- }
-
- case IDCANCEL:
- // WM_CLOSE is transformed into an IDCANCEL by dialog manager
- {
- EndDialog(hwndDlg, LOWORD(wParam));
- return TRUE;
- }
-
- case IDC_EDITBOX_NEWITEM:
- {
- switch (HIWORD(wParam))
- {
- case EN_CHANGE:
- {
- HWND hwndEdit = GetDlgItem(hwndDlg, IDC_EDITBOX_NEWITEM);
- int iNewItemLen = GetWindowTextLength(hwndEdit);
- WCHAR* pszNewItem = (WCHAR*)mir_alloc((iNewItemLen+1)*sizeof(WCHAR));
-
- if (pszNewItem)
- {
- // Get entered text
- if (GetWindowText(hwndEdit, pszNewItem, iNewItemLen+1) == 0)
- pszNewItem[0] = _T('\0');
-
- // Check if OK button can be released
- EnableDlgItem(hwndDlg, IDOK, (lstrlen(pszNewItem) > 0));
-
- mir_free(pszNewItem);
- }
-
- return TRUE;
- }
- } // switch HIWORD(wParam)
- break;
- }
-
- } // switch wParam
- break;
- }
- }
-
- return FALSE;
-}
-
-
-void WordsListBoxInit(HWND hwndDlg, int iIDListBox, int iIDAddButton, int iIDDeleteButton, STRINGLIST* pslContents, const char* pszAddTooltip, const char* pszDeleteTooltip)
-{
- HWND hwndListBox = GetDlgItem(hwndDlg, iIDListBox);
- HWND hwndAddButton = GetDlgItem(hwndDlg, iIDAddButton);
- HWND hwndDeleteButton = GetDlgItem(hwndDlg, iIDDeleteButton);
- HICON hAddIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_ADD_BUTTON), IMAGE_ICON, 0, 0, LR_SHARED);
- HICON hDeleteIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DELETE_BUTTON), IMAGE_ICON, 0, 0, LR_SHARED);
-
- // Subclass to get key strokes/contextmenu/horizontal extent
- SetWindowLongPtr(hwndListBox, GWLP_USERDATA, SetWindowLongPtr(hwndListBox, GWLP_WNDPROC, (LONG_PTR)WordsListBoxSubclassProc));
-
- // Init drag-drop support
- MakeDragList(hwndListBox);
-
- // Insert contents
- SLAssignToListBoxCtrl(pslContents, hwndListBox);
-
- // Select first item
- SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)0, 0);
-
- // Init add button
- SetWindowPos(hwndAddButton, NULL, 0, 0, 20, 20, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
- SendMessage(hwndAddButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hAddIcon);
- PostMessage(hwndAddButton, BUTTONADDTOOLTIP, (WPARAM)pszAddTooltip, 0);
- SendMessage(hwndAddButton, BUTTONSETASFLATBTN, 0, 0);
-
- // Init delete button
- SetWindowPos(hwndDeleteButton, NULL, 0, 0, 20, 20, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
- SendMessage(hwndDeleteButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hDeleteIcon);
- PostMessage(hwndDeleteButton, BUTTONADDTOOLTIP, (WPARAM)pszDeleteTooltip, 0);
- SendMessage(hwndDeleteButton, BUTTONSETASFLATBTN, 0, 0);
-}
-
-
-BOOL WordsListBoxDragDrop(HWND hwndDlg, int iIDListBox, UINT uMsg, LPARAM lParam, BOOL bAllowCopy)
-{
- // This function needs to be called in the default handler of the dialog
-
- if (uMsg == RegisterWindowMessage(DRAGLISTMSGSTRING))
- {
- DRAGLISTINFO* pdli = (DRAGLISTINFO*)lParam;
-
- if (GetDlgItem(hwndDlg, iIDListBox) == pdli->hWnd)
- {
- int iHoveredItem = LBItemFromPt(pdli->hWnd, pdli->ptCursor, (pdli->uNotification==DL_DRAGGING));
-
- switch (pdli->uNotification)
- {
- case DL_BEGINDRAG:
- {
- // Remember start position
- SetProp(pdli->hWnd, DRAGLISTMSGSTRING, (HANDLE)iHoveredItem);
-
- // Allow/Disallow drag
- SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)(BOOL)(iHoveredItem >= 0));
- return TRUE;
- }
-
- case DL_DRAGGING:
- {
- // LBItemFromPt returns an item if no item is in list
- if (SendMessage(pdli->hWnd, LB_GETCOUNT, 0, 0) <= 1)
- iHoveredItem = LB_ERR;
-
- if (iHoveredItem >= 0)
- {
- BOOL bMakeCopy = ((bAllowCopy) && (GetAsyncKeyState(VK_CONTROL) < 0));
-
- // Show insertion mark
- DrawInsert(hwndDlg, pdli->hWnd, iHoveredItem);
-
- SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)(bMakeCopy?DL_COPYCURSOR:DL_MOVECURSOR));
-
- } else {
- // Cursor moved to impossible position
- DrawInsert(hwndDlg, pdli->hWnd, LB_ERR);
-
- SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)DL_STOPCURSOR);
- }
-
- return TRUE;
- }
-
- case DL_DROPPED:
- {
- int iDragItem = (int)GetProp(pdli->hWnd, DRAGLISTMSGSTRING);
-
- if ((iHoveredItem >= 0 ) && (iHoveredItem != iDragItem) && (iHoveredItem != iDragItem+1))
- {
- LPARAM lParamItemData;
- int iLenItem;
- WCHAR* pszItemText;
-
- iLenItem = (int)SendMessage(pdli->hWnd, LB_GETTEXTLEN, (WPARAM)iDragItem, 0);
- if (iLenItem == LB_ERR) iLenItem = 0;
- pszItemText = (WCHAR*)mir_alloc((iLenItem+1)*sizeof(WCHAR));
-
- if (pszItemText)
- {
- if (SendMessage(pdli->hWnd, LB_GETTEXT, (WPARAM)iDragItem, (LPARAM)pszItemText) != LB_ERR)
- {
- lParamItemData = (LPARAM)SendMessage(pdli->hWnd, LB_GETITEMDATA, (WPARAM)iDragItem, 0);
-
- // Make copy of item
- iHoveredItem = (int)SendMessage(pdli->hWnd, LB_INSERTSTRING, (WPARAM)iHoveredItem, (LPARAM)pszItemText);
-
- if (iHoveredItem >= 0)
- {
- BOOL bMakeCopy = ((bAllowCopy) && (GetAsyncKeyState(VK_CONTROL) < 0));
-
- SendMessage(pdli->hWnd, LB_SETITEMDATA, (WPARAM)iHoveredItem, (LPARAM)lParamItemData);
-
- // Delete old item if moving
- if (!bMakeCopy)
- {
- if (iHoveredItem < iDragItem)
- iDragItem++;
-
- SendMessage(pdli->hWnd, LB_DELETESTRING, (WPARAM)iDragItem, 0);
- }
-
- // Set current selection
- SendMessage(pdli->hWnd, LB_SETCURSEL, (WPARAM)iHoveredItem, 0);
- }
- }
-
- mir_free(pszItemText);
- }
- }
-
- // fall trough
- }
-
- case DL_CANCELDRAG:
- {
- // Remove insertion mark
- DrawInsert(hwndDlg, pdli->hWnd, LB_ERR);
-
- // Remove buffer data
- RemoveProp(pdli->hWnd, DRAGLISTMSGSTRING);
- return TRUE;
- }
-
- } // switch
- }
- }
-
- return FALSE;
-}
-
-
-BOOL WordsListBoxAddItem(HWND hwndDlg, int iIDListBox, STRINGLIST* pslOtherContents, const WCHAR* pszMsgTitle, const WCHAR* pszMsgTextInList, const WCHAR* pszMsgTextInOther, int iIDButtonDelete)
-{
- HWND hwndListBox = GetDlgItem(hwndDlg, iIDListBox);
- BOOL bDoAdd;
- struct WORDSLISTBOXADDITEMPARAMS wlbaip;
- RECT rc;
-
- if (!hwndListBox) return FALSE;
-
- if (GetWindowRect(hwndListBox, &rc)) {
- wlbaip.ptPos.x = rc.left-30;
- wlbaip.ptPos.y = rc.top-5;
- } else {
- wlbaip.ptPos.x = 0;
- wlbaip.ptPos.y = 0;
- }
-
- wlbaip.pszTitle = (WCHAR*)pszMsgTitle;
-
- // Show dialog
- bDoAdd = (DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_LISTBOX_ADD_ITEM), hwndDlg, DlgProcWordsListBoxAddItem, (LPARAM)&wlbaip) == IDOK);
- if (bDoAdd)
- {
- // Check if regular expression is valid (if any)
- if (!wlbaip.pszNewItem || !ValidateRegExp(wlbaip.pszNewItem))
- {
- WCHAR* pszBoxTextFmt = TranslateT("The entered phrase \"%s\" consists of a Regular Expression containing a syntax error!\r\n\r\nAdding an malformed Regular Expression will cause the filter\r\nto treat the expression as a normal phrase.\r\n\r\nShall the malformed Regular Expression be added anyway?");
- WCHAR* pszBoxText = (WCHAR*)mir_alloc((lstrlen(pszBoxTextFmt)+lstrlen(wlbaip.pszNewItem)+1)*sizeof(WCHAR));
- bDoAdd = FALSE;
-
- if (pszBoxTextFmt && pszBoxText)
- {
- mir_sntprintf(pszBoxText, (lstrlen(pszBoxTextFmt)+lstrlen(wlbaip.pszNewItem)+1), pszBoxTextFmt, wlbaip.pszNewItem);
-
- // Show message box that the item is malformed
- if (!Miranda_Terminated())
- bDoAdd = (MessageBoxEx(hwndDlg, pszBoxText, TranslateT("Syntax Error in Regular Expression"), MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2, LANGIDFROMLCID(GetThreadLocale())) == IDYES);
- }
-
- if (pszBoxTextFmt) mir_free(pszBoxTextFmt);
- if (pszBoxText) mir_free(pszBoxText);
-
- } else {
- bDoAdd = TRUE;
- }
-
- if (bDoAdd)
- {
- int iIndexIfFound;
-
- // Look for same item in list (not case sensitive)
- iIndexIfFound = SendMessage(hwndListBox, LB_FINDSTRINGEXACT, 0, (LPARAM)wlbaip.pszNewItem);
- if (iIndexIfFound >= 0)
- {
- WCHAR* pszBoxText = (WCHAR*)mir_alloc((lstrlen(pszMsgTextInList)+lstrlen(wlbaip.pszNewItem)+1)*sizeof(WCHAR));
- bDoAdd = FALSE;
-
- if (pszBoxText)
- {
- mir_sntprintf(pszBoxText, (lstrlen(pszMsgTextInList) + lstrlen(wlbaip.pszNewItem) + 1), pszMsgTextInList, wlbaip.pszNewItem);
-
- SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)iIndexIfFound, 0);
-
- // Show message box that the item can not be added
- if (!Miranda_Terminated())
- bDoAdd = (MessageBoxEx(hwndDlg, pszBoxText, pszMsgTitle, MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2, LANGIDFROMLCID(GetThreadLocale())) == IDYES);
-
- mir_free(pszBoxText);
- }
-
- } else if (pslOtherContents && SLIsItem(pslOtherContents, wlbaip.pszNewItem, FALSE) )
- {
- WCHAR* pszBoxText = (WCHAR*)mir_alloc((lstrlen(pszMsgTextInOther)+lstrlen(wlbaip.pszNewItem)+1)*sizeof(WCHAR));
- bDoAdd = FALSE;
-
- if (pszBoxText)
- {
- // Show message box that it is not good to add the item
- mir_sntprintf(pszBoxText, (lstrlen(pszMsgTextInOther) + lstrlen(wlbaip.pszNewItem) + 1), pszMsgTextInOther, wlbaip.pszNewItem);
-
- if (!Miranda_Terminated())
- bDoAdd = (MessageBoxEx(hwndDlg, pszBoxText, pszMsgTitle, MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2, LANGIDFROMLCID(GetThreadLocale())) == IDYES);
-
- mir_free(pszBoxText);
- }
-
- } else {
- bDoAdd = TRUE;
- }
-
- }
-
- // Add the item if everything is OK
- if (bDoAdd)
- {
- int iPos;
-
- // Add new item to list
- iPos = SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)wlbaip.pszNewItem);
- if (iPos >= 0)
- {
- // Select new entry
- SendMessage(hwndListBox, LB_SETCURSEL, iPos, 0);
-
- // Activate delete button
- EnableDlgItem(hwndDlg, iIDButtonDelete, TRUE);
-
- } else {
- bDoAdd = FALSE;
- }
- }
-
- // Free allocated memory
- mir_free(wlbaip.pszNewItem);
- }
-
- // Set focus on list box
- SetFocus(hwndListBox);
-
- return bDoAdd;
-}
-
-
-int WordsListBoxDeleteItem(HWND hwndDlg, int iIDListBox, int iIDButtonDelete)
-{
- HWND hwndListBox = GetDlgItem(hwndDlg, iIDListBox);
- int iSelectedItem;
- int iItemCount;
-
- if (!hwndListBox) return LB_ERR;
-
- iSelectedItem = SendMessage(hwndListBox, LB_GETCURSEL, 0, 0);
- if (iSelectedItem >= 0)
- {
- // Delete entry and get new list item count
- iItemCount = SendMessage(hwndListBox, LB_DELETESTRING, (WPARAM)iSelectedItem, 0);
-
- // Deactivate delete button?
- if (iItemCount == 0)
- EnableDlgItem(hwndDlg, iIDButtonDelete, FALSE);
-
- // Select next item for 'fast delete'
- if (SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)iSelectedItem, 0) < 0)
- SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)((iSelectedItem>0)?(iSelectedItem-1):0), 0);
-
- } else {
- iItemCount = LB_ERR;
- }
-
- // Set focus on list box
- SetFocus(hwndListBox);
-
- return iItemCount;
-}
-
-
-BOOL ToggleTreeViewItemState(HWND hwndTreeView, HTREEITEM hTreeItem)
-{
- UINT uCurrentState;
- BOOL bChangeAllowed;
-
- uCurrentState = TreeView_GetItemState(hwndTreeView, hTreeItem, TVIS_STATEIMAGEMASK);
-
- // No toggle if item is section item
- if (uCurrentState&INDEXTOSTATEIMAGEMASK(0)) // no checkbox
- {
- bChangeAllowed = FALSE;
-
- // Check if another checkbox is still checked before unchecking this one
- } else if (uCurrentState&INDEXTOSTATEIMAGEMASK(2)) // checkbox checked
- {
- HTREEITEM hItem;
- HTREEITEM hSectionItem;
-
- bChangeAllowed = FALSE;
- for (hSectionItem=TreeView_GetRoot(hwndTreeView); hSectionItem; hSectionItem=TreeView_GetNextSibling(hwndTreeView, hSectionItem))
- {
- for (hItem=TreeView_GetChild(hwndTreeView, hSectionItem); hItem; hItem=TreeView_GetNextSibling(hwndTreeView, hItem))
- {
- if (hItem == hTreeItem) continue;
-
- // Check setting (checkbox checked?)
- if (TreeView_GetItemState(hwndTreeView, hItem, TVIS_STATEIMAGEMASK)&INDEXTOSTATEIMAGEMASK(2))
- {
- bChangeAllowed = TRUE;
- break;
- }
- }
- }
-
- // System default sound (mistake notify)
- if (!bChangeAllowed)
- MessageBeep(MB_OK);
-
- } else {
- bChangeAllowed = TRUE;
- }
-
- if (bChangeAllowed)
- TreeView_SetItemState(hwndTreeView, hTreeItem, INDEXTOSTATEIMAGEMASK((uCurrentState&INDEXTOSTATEIMAGEMASK(2))?1:2), TVIS_STATEIMAGEMASK);
-
- return bChangeAllowed;
-}
-
-
-MESSAGETYPEDESC* GetDataFromTreeViewItem(HWND hwndTreeView, HTREEITEM hTreeItem)
-{
- TVITEM tvi;
-
- tvi.hItem = hTreeItem;
- tvi.mask = TVIF_HANDLE|TVIF_PARAM;
-
- if (TreeView_GetItem(hwndTreeView, &tvi))
- if (((unsigned int)tvi.lParam >= 0) && ((unsigned int)tvi.lParam < uMsgTypesCount))
- return &pamtdMsgTypes[(unsigned int)tvi.lParam];
-
- return NULL;
-}
-
-
-BOOL MakeVariablesHelpButton(HWND hwndDlg, int iIDButton)
-{
- BOOL bReturn;
-
- // Set icon and resize button
- SetWindowPos(GetDlgItem(hwndDlg, iIDButton), NULL, 0, 0, 20, 20, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
- SendDlgItemMessage(hwndDlg, iIDButton, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)LoadSystemIcon(IDB_STD_SMALL_COLOR, STD_HELP));
- PostMessage(GetDlgItem(hwndDlg, iIDButton), BUTTONADDTOOLTIP, (WPARAM)Translate("Use variables in the message text"), 0);
- SendMessage(GetDlgItem(hwndDlg, iIDButton), BUTTONSETASFLATBTN, 0, 0);
-
- // Do not show help button if variables are not available
- bReturn = (ServiceExists(MS_VARS_SHOWHELP) && ServiceExists(MS_VARS_FORMATSTRING));
- ShowDlgItem(hwndDlg, iIDButton, bReturn);
-
- return bReturn;
-}
-
-
-// ------------------------------
-
-
-static int OptionsInitialise(WPARAM wParam, LPARAM lParam)
-{
- // (Options page max. size: 314, 240)
-
- // These controls will be hidden in simple (non-expert) options mode
- static UINT SpamFilterExpertOnlyControls[] = {IDC_BUTTON_ADVERTISMENTFILTER, IDC_BUTTON_DISLIKEDMESSAGEFILTER, IDC_BUTTON_ROBOTFILTER, IDC_BUTTON_RESETAUTOIGNORE, IDC_GROUP_MESSAGETYPES, IDC_TEXT_MESSAGETYPES, IDC_TREEVIEW_MESSAGETYPES};
-
- OPTIONSDIALOGPAGE odp;
- INITCOMMONCONTROLSEX icc;
-
- // Add Spam Filter option page
- ZeroMemory(&odp, sizeof(odp));
- odp.cbSize = sizeof(odp);
- odp.hInstance = hInstance;
- odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_MAIN);
- odp.position = 900000001; // 900000000 = Ignore options
- odp.ptszTitle = TranslateT("Spam Filter");
- odp.ptszGroup = TranslateT("Events");
- odp.flags = ODPF_BOLDGROUPS|ODPF_UNICODE;
- odp.pfnDlgProc = DlgProcSpamFilterOpt;
- //odp.nIDBottomSimpleControl = IDC_GROUP_POPUP; // In simple mode the dlg will be cut off after this control
- odp.expertOnlyControls = SpamFilterExpertOnlyControls;
- odp.nExpertOnlyControls = ARRAYSIZE(SpamFilterExpertOnlyControls);
-
- // Ensure the needed common controls are loaded
- ZeroMemory(&icc, sizeof(icc));
- icc.dwSize = sizeof(icc);
- icc.dwICC = ICC_TREEVIEW_CLASSES|ICC_UPDOWN_CLASS;
- InitCommonControlsEx(&icc);
-
- CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
- return 0;
-}
-
-
-static int DbSettingChanged(WPARAM wParam, LPARAM lParam)
-{
- DBCONTACTWRITESETTING* pdcws = (DBCONTACTWRITESETTING*)lParam;
- HANDLE hContact = (HANDLE)wParam;
-
- // Ignore Options Extension
- if ( (hContact == NULL) && (StrCmpA(pdcws->szModule, "Ignore") == 0))
- {
- if ( (( (IsWindow(hwndSpamFilterOpt) ? IsDlgButtonChecked(hwndSpamFilterOpt, IDC_CHECKBOX_ADVERTISMENTFILTER) : FALSE) || DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER) )
- || ( (IsWindow(hwndSpamFilterOpt) ? IsDlgButtonChecked(hwndSpamFilterOpt, IDC_CHECKBOX_ROBOTFILTER) : FALSE) || DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)DEFAULT_SETTING_ROBOTFILTER) ))
- && (BOOL)CallService(MS_IGNORE_ISIGNORED, (WPARAM)NULL, (LPARAM)IGNOREEVENT_MESSAGE)
- && (BOOL)CallService(MS_IGNORE_ISIGNORED, (WPARAM)NULL, (LPARAM)IGNOREEVENT_URL)
- && (BOOL)CallService(MS_IGNORE_ISIGNORED, (WPARAM)NULL, (LPARAM)IGNOREEVENT_FILE)
- && (BOOL)CallService(MS_IGNORE_ISIGNORED, (WPARAM)NULL, (LPARAM)IGNOREEVENT_AUTHORIZATION) )
- {
- if (!Miranda_Terminated())
- {
- HWND hwndParent = IsWindow(hwndSpamFilterOpt) ? GetParent(hwndSpamFilterOpt) : NULL;
-
- if (MessageBoxEx(hwndParent, TranslateT("You chose to ignore all kind of messages from contacts that are not on your contact list although the spam filter is activated.\r\n\r\nShall the spam filter be deactivated?"), TranslateT("Spam Filter"), MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON1|(!hwndParent?(MB_SETFOREGROUND|MB_TASKMODAL):0), LANGIDFROMLCID(GetThreadLocale())) == IDYES)
- {
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)FALSE);
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)FALSE);
-
- if (IsWindow(hwndSpamFilterOpt))
- {
- CheckDlgButton(hwndSpamFilterOpt, IDC_CHECKBOX_ADVERTISMENTFILTER, BST_UNCHECKED);
- CheckDlgButton(hwndSpamFilterOpt, IDC_CHECKBOX_ROBOTFILTER, BST_UNCHECKED);
- }
- }
- }
-
- }
- }
-
- // Watch "Hidden" setting to sync with IsSammer-state (Ignore opts change)
-/* if (StrCmpA(pdcws->szModule, "CList") == 0)
- if (StrCmpA(pdcws->szSetting, "Hidden") == 0)
- if ((pdcws->value.type==DBVT_DELETED) || !pdcws->value.bVal)
- if ((BOOL)CallService(MS_SPAMFILTER_CONTACT_ISSPAMMER, (WPARAM)hContact, 0))
- DBWriteContactSettingByte((HANDLE)wParam, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)FALSE); // no service call here!
-*/
-
- // Cache starting/stopping according to Filter settings (to save a little memory)
- if ( (hContact == NULL) && (StrCmpA(pdcws->szModule, DB_MODULE_NAME) == 0) &&
- (StrCmpA(pdcws->szSetting, DB_SETTING_ADVERTISMENTFILTER) == 0) )
- {
- BOOL bAdvertismentFilter = (pdcws->value.type==DBVT_BYTE) ? pdcws->value.bVal : DEFAULT_SETTING_ADVERTISMENTFILTER;
- BOOL bDislikedMessagesFilter = DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)DEFAULT_SETTING_DISLIKEDMESSAGEFILTER);
-
- ToggleSpamDefinitionsCache(bAdvertismentFilter || bDislikedMessagesFilter);
- }
- if ( (hContact == NULL) && (StrCmpA(pdcws->szModule, DB_MODULE_NAME) == 0) &&
- (StrCmpA(pdcws->szSetting, DB_SETTING_DISLIKEDMESSAGEFILTER) == 0) )
- {
- BOOL bDislikedMessagesFilter = (pdcws->value.type==DBVT_BYTE) ? pdcws->value.bVal : DEFAULT_SETTING_DISLIKEDMESSAGEFILTER;
- BOOL bAdvertismentFilter = DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER);
-
- ToggleSpamDefinitionsCache(bAdvertismentFilter || bDislikedMessagesFilter);
- }
-
- return 0;
-}
-
-
-// ------------------------------------
-
-
-void InitOptions(void)
-{
- hHookOptInit = HookEvent(ME_OPT_INITIALISE, OptionsInitialise);
- hHookDbSettingChangedOpt = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, DbSettingChanged);
-}
-
-void UninitOptions(void)
-{
- if (hHookOptInit) UnhookEvent(hHookOptInit);
- if (hHookDbSettingChangedOpt) UnhookEvent(hHookDbSettingChangedOpt);
-
- // Dialogs that are created without parent (non-modal) need to be destroyed
- if (IsWindow(hwndAdvertismentFilter))
- SendMessage(hwndAdvertismentFilter, WM_CLOSE, 0, 0);
- if (IsWindow(hwndRobotFilter))
- SendMessage(hwndRobotFilter, WM_CLOSE, 0, 0);
- if (IsWindow(hwndDislikedMessagesFilter))
- SendMessage(hwndDislikedMessagesFilter, WM_CLOSE, 0, 0);
- if (IsWindow(hwndSpamDefinitionsInfo))
- SendMessage(hwndSpamDefinitionsInfo, WM_CLOSE, 0, 0);
- if (IsWindow(hwndSpammersInfo))
- SendMessage(hwndSpammersInfo, WM_CLOSE, 0, 0);
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -- Variables: Events/Services
+HANDLE hHookOptInit = NULL;
+HANDLE hHookDbSettingChangedOpt = NULL;
+
+// -- Defines: Self-defined dialog messages
+#define SFM_ENABLE_SUBCTRLS (WM_APP+121) // wParam=lParam=0
+#define SFM_REMOVE_SPAMDEFINITIONFILE (WM_APP+122) // wParam=(int)listIndex, lParam=0
+
+// -- Structs
+struct WORDSLISTBOXADDITEMPARAMS
+{
+ POINT ptPos;
+ WCHAR* pszTitle;
+ WCHAR* pszNewItem;
+};
+
+
+// -----------------------------------------
+
+
+BOOL CALLBACK DlgProcSpamFilterOpt(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ /*
+ #if defined(UNICODE)
+ case WM_NOTIFYFORMAT:
+ {
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)NFR_UNICODE);
+ return TRUE;
+ }
+ #endif
+ */
+
+ case WM_INITDIALOG:
+ {
+ hwndSpamFilterOpt = hwndDlg;
+
+ /*
+ #if defined(UNICODE)
+ // Convert DlgProc to Unicode (IsWindowUnicode returns true after this call -> see docs)
+ SetWindowLongPtrW(hwndDlg, DWLP_DLGPROC, (LONG_PTR)DlgProcSpamFilterOpt);
+ #endif
+ */
+
+ // Init treeview (TVS_CHECKBOXES style is too buggy [it behaves incorrect when space pressed on sections], so self-implementing checkboxes)
+ // The treeview does checkboxes exactly the same as it is done here
+ TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES), LoadSystemCheckboxImageList(), TVSIL_STATE);
+
+ // Translate dialog
+ TranslateDialogDefault(hwndDlg);
+
+ // Set font
+ {
+ HFONT hUnderlinedFont;
+ LOGFONT lf;
+
+ GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER, WM_GETFONT, 0, 0), sizeof(lf), &lf);
+ lf.lfUnderline = TRUE;
+ hUnderlinedFont = CreateFontIndirect(&lf);
+
+ SendDlgItemMessage(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER, WM_SETFONT, (WPARAM)hUnderlinedFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER, WM_SETFONT, (WPARAM)hUnderlinedFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHECKBOX_ROBOTFILTER, WM_SETFONT, (WPARAM)hUnderlinedFont, 0);
+ }
+
+ // Init file name control
+ {
+ RECT rc;
+
+ // Set icon and resize button
+ SendDlgItemMessage(hwndDlg, IDC_BUTTON_LOGBROWSE, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)LoadSystemIcon(IDB_STD_SMALL_COLOR, STD_FILEOPEN));
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_BUTTON_LOGBROWSE), NULL, 0, 0, 20, 20, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+
+ // Transform into file edit browse combo control
+ MakePathEditCtrl(GetDlgItem(hwndDlg, IDC_EDITBOX_LOGFILE), GetDlgItem(hwndDlg, IDC_BUTTON_LOGBROWSE));
+
+ if (GetClientRect(GetDlgItem(hwndDlg, IDC_BUTTON_OPENLOG), &rc))
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_BUTTON_OPENLOG), NULL, 0, 0, (rc.right-rc.left), (rc.bottom-rc.top)+2*GetSystemMetrics(SM_CYBORDER), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+
+ // Forwarding all file drag/drops of spam filter options to the file edit
+ // (child windows of childs seem not to receive that message...)
+ DragAcceptFiles(hwndDlg, (BOOL)SendMessage(GetParent(hwndDlg), PSM_ISEXPERT, 0, 0));
+ }
+
+ // Load log file from database
+ {
+ DBVARIANT dbv;
+
+ if(DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_LOGFILE, &dbv) == 0) // If existant
+ {
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+
+ } else {
+ // Nothing specified, display default log filename and path
+ WCHAR szLogFile[MAX_PATH];
+
+ PConstructLocalPath(szLogFile, CSIDL_EXT_EXECUTABLE, LOGS_SUBDIRECTORY, DEFAULT_LOGFILE, NULL);
+ PMakePathPretty(szLogFile, PC_ABSOLUTERELATIVE);
+
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile);
+ }
+ }
+
+ // Init checkboxes
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)DEFAULT_SETTING_DISLIKEDMESSAGEFILTER) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_ROBOTFILTER, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)DEFAULT_SETTING_ROBOTFILTER) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_POPUP, IsPopupAvailable(TRUE) ? DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, (BYTE)(DEFAULT_SETTING_POPUP ? BST_CHECKED : BST_UNCHECKED)) : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_AUTOADDSPAMMERS, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, (BYTE)(DEFAULT_SETTING_AUTOADDSPAMMERS ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_LOGGING, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, (BYTE)DEFAULT_SETTING_LOGGING) ? BST_CHECKED : BST_UNCHECKED));
+
+ // Check/Uncheck radio buttons:
+ // Delete/Mark read?
+ CheckRadioButton(hwndDlg, IDC_RADIO_MARKREADMSG, IDC_RADIO_DELETEMSG, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, (BYTE)DEFAULT_SETTING_BEHAVIOUR) == 1) ? IDC_RADIO_MARKREADMSG : IDC_RADIO_DELETEMSG);
+
+ // Init sub control state
+ SendMessage(hwndDlg, SFM_ENABLE_SUBCTRLS, 0, 0);
+ SendMessage(hwndDlg, SFM_REBUILD_MSGTYPES, 0, 0);
+
+ SendMessage(hwndDlg, SFM_CHECK_AUTOIGNORE, 0, 0);
+ PostMessage(hwndDlg, SFM_VALIDATE_LOGFILENAME, 0, 0);
+ return TRUE;
+ }
+
+ case SFM_ENABLE_SUBCTRLS:
+ {
+ BOOL bStatus;
+
+ // IDC_CHECKBOX_ADVERTISMENTFILTER
+ BOOL bStatusRobotFilter = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ROBOTFILTER) == BST_CHECKED);
+ BOOL bStatusChainFilter = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER) == BST_CHECKED);
+ BOOL bStatusAdvertismentFilter = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER) == BST_CHECKED);
+ bStatus = bStatusAdvertismentFilter || bStatusChainFilter || bStatusRobotFilter;
+
+ EnableDlgItem(hwndDlg, IDC_BUTTON_ADVERTISMENTFILTER, bStatusAdvertismentFilter);
+ EnableDlgItem(hwndDlg, IDC_BUTTON_DISLIKEDMESSAGEFILTER, bStatusChainFilter);
+ EnableDlgItem(hwndDlg, IDC_BUTTON_ROBOTFILTER, bStatusRobotFilter);
+
+ EnableDlgItem(hwndDlg, IDC_GROUP_BEHAVIOUR, bStatus);
+ EnableDlgItem(hwndDlg, IDC_RADIO_MARKREADMSG, bStatus);
+ EnableDlgItem(hwndDlg, IDC_RADIO_DELETEMSG, bStatus);
+
+ EnableDlgItem(hwndDlg, IDC_GROUP_IGNORE, bStatus);
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_AUTOADDSPAMMERS, bStatus);
+
+ EnableDlgItem(hwndDlg, IDC_GROUP_LOGGING, bStatus);
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_LOGGING, bStatus);
+
+ EnableDlgItem(hwndDlg, IDC_GROUP_MESSAGETYPES, bStatus);
+ EnableDlgItem(hwndDlg, IDC_TEXT_MESSAGETYPES, bStatus);
+ EnableDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES, bStatus);
+
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_POPUP, IsPopupAvailable(TRUE) ? bStatus: FALSE);
+
+ // Auto Ignore
+ SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDSPAMMESSAGES), bStatusRobotFilter?1:0, 999, DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, (DWORD)DEFAULT_SETTING_ALLOWEDSPAMMESSAGES), FALSE);
+ bStatus = (IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHECKBOX_AUTOADDSPAMMERS)) && (IsDlgButtonChecked(hwndDlg,IDC_CHECKBOX_AUTOADDSPAMMERS) == BST_CHECKED));
+ EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDSPAMMESSAGES, bStatus);
+ EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDSPAMMESSAGES, bStatus);
+ EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDSPAMMESSAGES, bStatus);
+
+ // Logging
+ bStatus = (IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHECKBOX_LOGGING)) && (IsDlgButtonChecked(hwndDlg,IDC_CHECKBOX_LOGGING) == BST_CHECKED));
+ EnableDlgItem(hwndDlg, IDC_EDITBOX_LOGFILE, bStatus);
+ EnableDlgItem(hwndDlg, IDC_BUTTON_LOGBROWSE, bStatus);
+
+ return TRUE;
+ }
+
+ case SFM_REBUILD_MSGTYPES:
+ {
+ HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES);
+ HIMAGELIST hImageList;
+
+ unsigned int u;
+ char* pszSetting;
+ TVINSERTSTRUCT tvis;
+ BOOL bUseSections;
+
+ HTREEITEM hItem;
+ MESSAGETYPEDESC* pmtd;
+ int iCmpResult;
+
+ // Clear treeview
+ TreeView_DeleteAllItems(hwndTreeView);
+
+ if (InSendMessage())
+ ReplyMessage(TRUE);
+
+ // Check if only one section is installed
+ // -> if only one section is installed it is not necessary to show the section
+ EnterCriticalSection(&csMsgTypes); // thread safety
+
+ bUseSections = !IsOnlyOneMsgTypeSectionRegistered();
+
+ // New image list
+ hImageList = TreeView_GetImageList(hwndTreeView, TVSIL_NORMAL);
+ if (hImageList) ImageList_Destroy(hImageList);
+ hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON), (IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK, uMsgTypesCount, bUseSections?uMsgTypesCount:0); // includes msgtype and section images
+ TreeView_SetImageList(hwndTreeView, hImageList, TVSIL_NORMAL);
+
+ // Add items to treeview
+ if (pamtdMsgTypes)
+ {
+ for (u=0; u<uMsgTypesCount; u++)
+ {
+ if (pamtdMsgTypes[u].dwFlags&MTDF_HIDDEN) continue;
+
+ if (!bUseSections)
+ {
+ tvis.hParent = NULL;
+
+ } else {
+ // Find section if already added
+ tvis.hParent = NULL;
+ for (hItem=TreeView_GetRoot(hwndTreeView); hItem; hItem=TreeView_GetNextSibling(hwndTreeView, hItem))
+ {
+ pmtd = GetDataFromTreeViewItem(hwndTreeView, hItem);
+ if (pmtd)
+ if (StrCmpA(pamtdMsgTypes[u].pszSection, pmtd->pszSection) == 0)
+ {
+ tvis.hParent = hItem;
+ break;
+ }
+ }
+
+ // Section does not yet exist: add it first
+ if (!tvis.hParent)
+ {
+ tvis.item.mask = TVIF_TEXT|TVIF_STATE|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvis.item.pszText = pamtdMsgTypes[u].ptszSectionDescription;
+ tvis.item.stateMask = TVIS_BOLD|TVIS_EXPANDED|TVIS_STATEIMAGEMASK;
+ tvis.item.state = TVIS_BOLD|TVIS_EXPANDED|INDEXTOSTATEIMAGEMASK(0); // no checkbox for sections
+ tvis.item.lParam = (LPARAM)u;
+ tvis.item.iImage = ImageList_AddIcon(hImageList, (pamtdMsgTypes[u].hSectionIcon ? pamtdMsgTypes[u].hSectionIcon : LoadSkinnedIcon(SKINICON_OTHER_MIRANDA)) );
+ tvis.item.iSelectedImage = tvis.item.iImage; // else the wrong icon will be shown when selected
+
+ // Position new section using position numbers (lowest first)
+ tvis.hInsertAfter = TVI_FIRST;
+ for (hItem=TreeView_GetRoot(hwndTreeView); hItem; hItem=TreeView_GetNextSibling(hwndTreeView, hItem))
+ {
+ pmtd = GetDataFromTreeViewItem(hwndTreeView, hItem);
+ if (pmtd)
+ {
+ if (pamtdMsgTypes[u].iSectionPosition > pmtd->iSectionPosition)
+ {
+ tvis.hInsertAfter = hItem;
+
+ // Colliding numbers are sorted alphabetically
+ } else if (pamtdMsgTypes[u].iSectionPosition == pmtd->iSectionPosition) {
+
+ int iCmpResult;
+
+ iCmpResult = CompareString(GetThreadLocale(), 0, pamtdMsgTypes[u].ptszSectionDescription, -1, pmtd->ptszSectionDescription, -1); // or: LOCALE_USER_DEFAULT
+
+ if (iCmpResult != 0) iCmpResult -= 2; // see docs
+
+ if (iCmpResult >= 0)
+ tvis.hInsertAfter = hItem;
+
+ } else {
+ // iteration pos is larger than new item pos
+ // (or reached "Other" section)
+ // -> found out where to sort in
+ break;
+ }
+ }
+ }
+
+ tvis.hParent = TreeView_InsertItem(hwndTreeView, &tvis);
+ }
+ }
+
+ pszSetting = GetMsgTypeSettingName(pamtdMsgTypes[u].pszSection, pamtdMsgTypes[u].pszName);
+ if (!pszSetting) continue;
+
+ tvis.item.mask = TVIF_TEXT|TVIF_STATE|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvis.item.pszText = pamtdMsgTypes[u].ptszDescription;
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ tvis.item.state = INDEXTOSTATEIMAGEMASK(DBGetContactSettingByte(NULL, DB_MODULE_NAME_MSGTYPES, pszSetting, (BYTE)!(pamtdMsgTypes[u].dwFlags&MTDF_DEFAULTDISABLED))?2:1);
+ tvis.item.lParam = (LPARAM)u;
+
+ if ((int)pamtdMsgTypes[u].hIcon < 0)
+ tvis.item.iImage = ImageList_AddIcon(hImageList, LoadSkinnedIcon((-1)*(int)pamtdMsgTypes[u].hIcon));
+ else
+ tvis.item.iImage = ImageList_AddIcon(hImageList, pamtdMsgTypes[u].hIcon ? pamtdMsgTypes[u].hIcon : (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED));
+
+ tvis.item.iSelectedImage = tvis.item.iImage; // else the wrong icon will be shown when selected
+ mir_free(pszSetting);
+
+ // Position new item using position numbers (lowest first)
+ tvis.hInsertAfter = TVI_FIRST;
+ for (hItem=TreeView_GetChild(hwndTreeView, tvis.hParent); hItem; hItem=TreeView_GetNextSibling(hwndTreeView, hItem))
+ {
+ pmtd = GetDataFromTreeViewItem(hwndTreeView, hItem);
+ if (pmtd)
+ {
+ if (pamtdMsgTypes[u].iPosition > pmtd->iPosition)
+ {
+ tvis.hInsertAfter = hItem;
+
+ // Colliding numbers are sorted alphabetically
+ } else if (pamtdMsgTypes[u].iPosition == pmtd->iPosition)
+ {
+ iCmpResult = CompareString(GetThreadLocale(), 0, pamtdMsgTypes[u].ptszDescription, -1, pmtd->ptszDescription, -1); // or: LOCALE_USER_DEFAULT
+
+ if (iCmpResult != 0) iCmpResult -= 2; // see docs
+
+ if (iCmpResult >= 0)
+ tvis.hInsertAfter = hItem;
+
+ } else {
+ // Iteration pos is larger than new item pos
+ // -> found out where to sort in
+ break;
+ }
+ }
+ }
+
+ TreeView_InsertItem(hwndTreeView, &tvis);
+ }
+ }
+
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+
+ return TRUE;
+ }
+
+ case SFM_CHECK_AUTOIGNORE:
+ {
+ EnableDlgItem(hwndDlg, IDC_BUTTON_RESETAUTOIGNORE, (CallService(MS_SPAMFILTER_RESETAUTOIGNORE, (WPARAM)TRUE, 0) > 0));
+ return TRUE;
+ }
+
+ case SFM_VALIDATE_LOGFILENAME:
+ {
+ const WCHAR* aszFileExtensions[] = {_T(".txt"), _T(".log"), _T(".csv"), _T(".xml"), _T("."), _T(""), NULL};
+ const WCHAR* aszContentTypes[] = {_T("text/plain"), _T("text/xml"), _T("application/xml"), NULL};
+
+ WCHAR szLogFile[MAX_PATH];
+ DWORD dwPathFlags;
+ BOOL bIsValid;
+
+ GetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile, ARRAYSIZE(szLogFile));
+ dwPathFlags = PMakePathUsable(szLogFile);
+
+ // Make sure the correct xml file extension is specified
+ if (PathMatchSpec(szLogFile, _T("*.xsl")))
+ PathRenameExtension(szLogFile, _T(".xml"));
+
+ bIsValid = PIsValidFile(szLogFile, aszFileExtensions, ARRAYSIZE(aszFileExtensions), aszContentTypes, ARRAYSIZE(aszContentTypes));
+
+ PMakePathPretty(szLogFile, dwPathFlags);
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile);
+
+ EnableDlgItem(hwndDlg, IDC_BUTTON_OPENLOG, bIsValid);
+ return TRUE;
+ }
+
+ case WM_DROPFILES:
+ {
+ // Forward do log edit (child windows of childs can not receive that message)
+ PostMessage(GetDlgItem(hwndDlg, IDC_EDITBOX_LOGFILE), uMsg, wParam, lParam);
+ return TRUE;
+ }
+
+ case WM_DESTROY:
+ {
+ HIMAGELIST hImgLst;
+ // Free font
+ DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER, WM_GETFONT, 0, 0));
+
+ // Destroy tree view imagelist since it does not get destroyed automatically (see msdn docs)
+ hImgLst = TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES), TVSIL_STATE);
+ if (hImgLst) {
+ TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES), NULL, TVSIL_STATE); // Avoiding Access Violation in CommonControls DLL
+ ImageList_Destroy(hImgLst);
+ }
+ hImgLst = TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES), TVSIL_NORMAL);
+ if (hImgLst) {
+ TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES), NULL, TVSIL_NORMAL); // Avoiding Access Violation in CommonControls DLL
+ ImageList_Destroy(hImgLst);
+ }
+
+ // Destroy open icon
+ DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_BUTTON_LOGBROWSE, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0));
+
+ hwndSpamFilterOpt = NULL;
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_BUTTON_ADVERTISMENTFILTER:
+ {
+ CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)hwndDlg, (LPARAM)SFT_ADVERTISMENT_FILTER);
+
+ // Do not activate "Apply" button
+ return FALSE;
+ }
+
+ case IDC_BUTTON_DISLIKEDMESSAGEFILTER:
+ {
+ CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)hwndDlg, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER);
+
+ // Do not activate "Apply" button
+ return FALSE;
+ }
+
+ case IDC_BUTTON_ROBOTFILTER:
+ {
+ CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)hwndDlg, (LPARAM)SFT_ROBOT_FILTER);
+
+ // Do not activate "Apply" button
+ return FALSE;
+ }
+
+ case IDC_BUTTON_LOGBROWSE:
+ {
+ WCHAR szLogFile[MAX_PATH];
+ WCHAR szInitialDir[MAX_PATH];
+ WCHAR szDefaultLogFile[MAX_PATH];
+ BOOL bDefaultDirUsed, bDefaultFileUsed;
+ BOOL bFileChanged;
+ DWORD dwPathFlags;
+ int iIndexAll, iIndexOther;
+ OPENFILENAME ofn;
+
+ // Set focus on editbox
+ SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_LOGFILE), (LPARAM)TRUE);
+
+ // Get chosen log file
+ GetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile, ARRAYSIZE(szLogFile));
+ dwPathFlags = PMakePathUsable(szLogFile);
+
+ // Construct default log file
+ PConstructLocalPath(szDefaultLogFile, CSIDL_EXT_EXECUTABLE, LOGS_SUBDIRECTORY, DEFAULT_LOGFILE, NULL);
+
+ // Check if default file gets used
+ if ((lstrlen(szLogFile) == 0) || (PathFindFileName(szLogFile) == szLogFile))
+ {
+ // Using default dir if nothing specified
+ mir_sntprintf(szLogFile, ARRAYSIZE(szLogFile), _T("%s"), szDefaultLogFile);
+ bDefaultDirUsed = bDefaultFileUsed = TRUE;
+ } else {
+ bDefaultDirUsed = bDefaultFileUsed = (StrCmpI(szLogFile, szDefaultLogFile) == 0);
+ }
+
+ // Using default file name when no file given
+ if ( (lstrlen(PathFindFileName(szLogFile)) == 0) || PathIsDirectory(szLogFile))
+ {
+ PathAppend(szLogFile, PathFindFileName(szDefaultLogFile));
+ bDefaultFileUsed = TRUE;
+ }
+
+ // Split file name
+ {
+ mir_sntprintf(szInitialDir, ARRAYSIZE(szInitialDir), _T("%s"), szLogFile);
+
+ // Get file name
+ mir_sntprintf(szLogFile, ARRAYSIZE(szLogFile), _T("%s"), PathFindFileName(szInitialDir));
+
+ // Get initial dir
+ PathRemoveFileSpec(szInitialDir);
+ }
+
+ // Initialize OPENFILENAME structure
+ ZeroMemory(&ofn, sizeof(ofn));
+ ofn.lStructSize = (IsWinVerNT() && !IsWinVer2000Plus()) ? OPENFILENAME_SIZE_VERSION_400 : sizeof(ofn); // backward compatibility for NT4
+ ofn.hwndOwner = hwndDlg;
+ ofn.Flags = OFN_ENABLESIZING|OFN_EXPLORER | OFN_LONGNAMES|OFN_HIDEREADONLY|OFN_NOREADONLYRETURN|OFN_OVERWRITEPROMPT; // also possible: OFN_DONTADDTORECENT, OFN_CREATEPROMPT
+ ofn.lpstrFile = szLogFile;
+ ofn.nMaxFile = ARRAYSIZE(szLogFile);
+ ofn.lpstrTitle = TranslateT("Select Log File");
+ ofn.lpstrDefExt = CharNext(PathFindExtension(DEFAULT_LOGFILE));
+
+ // Make sure the initial directory exists
+ if (SUCCEEDED(PPreparePathForWrite(hwndDlg, szInitialDir, !bDefaultDirUsed, FALSE)))
+ ofn.lpstrInitialDir = szInitialDir;
+
+ // File Filter
+ {
+ STRINGLIST* pslFilter = SLNewList();
+
+ SLAddItemPair(pslFilter, TranslateT("Log Files (*.log)"), _T("*.log"));
+ SLAddItemPair(pslFilter, TranslateT("Text Files (*.txt)"), _T("*.txt"));
+ SLAddItemPair(pslFilter, TranslateT("Comma Separated Values Files (*.csv)"), _T("*.csv"));
+ SLAddItemPair(pslFilter, TranslateT("XML Files (*.xml; *.xsl)"), _T("*.xml; *.xsl"));
+ iIndexAll = SLAddItemPair(pslFilter, TranslateT("All Logging Files (*.log; *.txt; *.csv; *.xml)"), _T("*.log; *.txt; *.csv; *.xml"));
+ iIndexOther = SLAddItemPair(pslFilter, TranslateT("All Files (*.*)"), _T("*.*"));
+
+ ofn.lpstrFilter = SLConvertToString(pslFilter, NULL, FALSE, TRUE, NULL);
+ SLFreeList(pslFilter);
+ }
+
+ // Default selected index
+ if ( PathMatchSpec(szLogFile, _T("*.log")) ||
+ PathMatchSpec(szLogFile, _T("*.txt")) ||
+ PathMatchSpec(szLogFile, _T("*.csv")) ||
+ PathMatchSpec(szLogFile, _T("*.xml")) )
+ {
+ // Show "all logging files" to show the user the possibilities
+ ofn.nFilterIndex = (iIndexAll/2)+1; // filter index is 1 based
+ } else {
+ // Select "All files"
+ ofn.nFilterIndex = (iIndexOther/2)+1; // filter index is 1 based
+ }
+
+ // Show browse file dialog
+ bFileChanged = GetSaveFileName(&ofn);
+ SLFreeReturn((WCHAR*)ofn.lpstrFilter);
+
+ if (bFileChanged)
+ {
+ PMakePathPretty(szLogFile, dwPathFlags);
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile);
+
+ // Re-Set focus on editbox
+ PostMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_LOGFILE), (LPARAM)TRUE);
+ PostMessage(hwndDlg, SFM_VALIDATE_LOGFILENAME, 0, 0);
+
+ } else {
+ PostMessage(hwndDlg, SFM_VALIDATE_LOGFILENAME, 0, 0);
+ // Do not activate "Apply" button
+ return FALSE;
+ }
+
+ break;
+ }
+
+ case IDC_BUTTON_OPENLOG:
+ {
+ WCHAR szLogFile[MAX_PATH];
+
+ GetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile, ARRAYSIZE(szLogFile));
+ PMakePathUsable(szLogFile);
+
+ if ((int)ShellExecute(hwndDlg, _T("open"), szLogFile, NULL, NULL, SW_SHOWNORMAL) <= 32)
+ EnableDlgItem(hwndDlg, IDC_BUTTON_OPENLOG, FALSE);
+
+ // Do not activate "Apply" button
+ return FALSE;
+ }
+
+ case IDC_BUTTON_RESETAUTOIGNORE:
+ {
+ // Show message box before doing reset
+ if (MessageBoxEx(hwndDlg, TranslateT("Are you sure that the Auto Ignore counters shall really be reset?\r\n\r\nSpammers that are not already ignored will then not be remembered any longer."), TranslateT("Reset Auto Ignore"), MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON1, LANGIDFROMLCID(GetThreadLocale())) == IDYES)
+ EnableDlgItem(hwndDlg, IDC_BUTTON_RESETAUTOIGNORE, (CallService(MS_SPAMFILTER_RESETAUTOIGNORE, (WPARAM)FALSE, 0) != 0) );
+
+ // Do not activate "Apply" button
+ return FALSE;
+ }
+
+ case IDC_BUTTON_SHOWSPAMMERS:
+ {
+ CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)hwndDlg, (LPARAM)SFTEXF_SPAMMERS_INFO);
+
+ // Do not activate "Apply" button
+ return FALSE;
+ }
+
+ case IDC_CHECKBOX_AUTOADDSPAMMERS:
+ case IDC_CHECKBOX_LOGGING:
+ case IDC_CHECKBOX_ADVERTISMENTFILTER:
+ case IDC_CHECKBOX_DISLIKEDMESSAGEFILTER:
+ case IDC_CHECKBOX_ROBOTFILTER:
+ {
+ PostMessage(hwndDlg, SFM_ENABLE_SUBCTRLS, 0, 0);
+ break;
+ }
+
+ case IDC_EDITBOX_LOGFILE:
+ {
+ switch (HIWORD(wParam))
+ {
+ case EN_CHANGE:
+ {
+ EnableDlgItem(hwndDlg, IDC_BUTTON_OPENLOG, FALSE);
+ break;
+ }
+
+ case EN_KILLFOCUS:
+ {
+ PostMessage(hwndDlg, SFM_VALIDATE_LOGFILENAME, 0, 0);
+ break;
+ }
+ }
+
+ // fall through
+ }
+
+ case IDC_EDITBOX_ALLOWEDSPAMMESSAGES:
+ {
+ if (HIWORD(wParam) != EN_SETFOCUS)
+ {
+ // Do not activate "Apply" button
+ return FALSE;
+ }
+
+ break;
+ }
+ }
+
+ // Send message to activate "Apply" button...
+ PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ return FALSE;
+ }
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pnmhdr = (LPNMHDR)lParam;
+
+ switch (pnmhdr->idFrom)
+ {
+ case IDC_TREEVIEW_MESSAGETYPES:
+ {
+ switch (pnmhdr->code)
+ {
+ case TVN_KEYDOWN:
+ {
+ switch (((NMTVKEYDOWN*)lParam)->wVKey)
+ {
+ case VK_SPACE:
+ {
+ if (TreeView_GetSelection(pnmhdr->hwndFrom))
+ {
+ ToggleTreeViewItemState(pnmhdr->hwndFrom, TreeView_GetSelection(pnmhdr->hwndFrom));
+
+ // Send message to activate "Apply" button...
+ PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+
+ // Prevent default processing
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)FALSE);
+ return TRUE;
+ }
+ }
+
+ break;
+ }
+
+ case NM_CLICK:
+ {
+ TVHITTESTINFO hti;
+
+ // Get click position
+ GetCursorPos(&hti.pt);
+ ScreenToClient(pnmhdr->hwndFrom, &hti.pt);
+
+ // Check if click was on state icon
+ if (TreeView_HitTest(pnmhdr->hwndFrom, &hti))
+ if (hti.flags&TVHT_ONITEMSTATEICON)
+ {
+ ToggleTreeViewItemState(pnmhdr->hwndFrom, hti.hItem);
+
+ // Send message to activate "Apply" button...
+ PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+
+ return TRUE;
+ }
+ }
+
+ break;
+ }
+
+ case 0:
+ {
+ switch (pnmhdr->code)
+ {
+ case PSN_EXPERTCHANGED: // Expert mode checkbox checked/unchecked
+ {
+ BOOL bNewState = (BOOL)lParam;
+
+ // Accept files (when log file edit control is visible)
+ DragAcceptFiles(hwndDlg, bNewState);
+ return TRUE;
+ }
+
+ case PSN_APPLY: // When "Apply"/"OK" pressed in options dialog then save changes
+ {
+ BOOL bFilterState = ( (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER) == BST_CHECKED) ||
+ (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER) == BST_CHECKED) ||
+ (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ROBOTFILTER) == BST_CHECKED) );
+
+ // Save filter state
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ADVERTISMENTFILTER) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ROBOTFILTER) == BST_CHECKED));
+
+ // Save popup state
+ if (IsPopupAvailable(TRUE))
+ {
+ BOOL bPopupState = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_POPUP) == BST_CHECKED);
+
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, (BYTE)bPopupState);
+ SetPopupMenuItem(bPopupState, !bFilterState);
+ }
+
+ // Save Auto Ignore
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_AUTOADDSPAMMERS) == BST_CHECKED));
+ DBWriteContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, (WORD)GetDlgItemInt(hwndDlg, IDC_EDITBOX_ALLOWEDSPAMMESSAGES, NULL, FALSE));
+
+ // Save behaviour
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, (BYTE)((IsDlgButtonChecked(hwndDlg, IDC_RADIO_MARKREADMSG) == BST_CHECKED) ? 1 : 2));
+
+ // Save log file
+ {
+ WCHAR szLogFile[MAX_PATH];
+
+ GetDlgItemText(hwndDlg, IDC_EDITBOX_LOGFILE, szLogFile, ARRAYSIZE(szLogFile));
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_LOGFILE, szLogFile);
+
+ // Save activation of logging
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, (BYTE)((lstrlen(szLogFile) > 0) ? (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_LOGGING) == BST_CHECKED) : FALSE));
+ }
+
+ // Save message types
+ {
+ HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_TREEVIEW_MESSAGETYPES);
+ MESSAGETYPEDESC* pmtd;
+ HTREEITEM hSectionItem;
+ HTREEITEM hItem;
+ char* pszSetting;
+
+ for (hSectionItem=TreeView_GetRoot(hwndTreeView); hSectionItem; hSectionItem=TreeView_GetNextSibling(hwndTreeView, hSectionItem))
+ for (hItem=TreeView_GetChild(hwndTreeView, hSectionItem); hItem; hItem=TreeView_GetNextSibling(hwndTreeView, hItem))
+ {
+ EnterCriticalSection(&csMsgTypes); // thread safety
+
+ pmtd = GetDataFromTreeViewItem(hwndTreeView, hItem);
+ if (pmtd)
+ {
+ // Save setting
+ pszSetting = GetMsgTypeSettingName(pmtd->pszSection, pmtd->pszName);
+ if (!pszSetting) continue;
+
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME_MSGTYPES, pszSetting, (BYTE)((TreeView_GetItemState(hwndTreeView, hItem, TVIS_STATEIMAGEMASK)&INDEXTOSTATEIMAGEMASK(2))?TRUE:FALSE));
+
+ mir_free(pszSetting);
+ }
+
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ }
+ }
+
+ return FALSE;
+ }
+
+ } // switch code
+
+ break;
+ }
+
+ } // switch idFrom
+
+ break;
+ }
+
+ }
+
+ return FALSE;
+}
+
+
+BOOL CALLBACK DlgProcConfigureAdvertismentFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ hwndAdvertismentFilter = hwndDlg;
+
+ // Translate dialog
+ TranslateDialogDefault(hwndDlg);
+
+ // Make group headings bold
+ {
+ HFONT hBoldFont;
+ LOGFONT lf;
+
+ GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_BADWORDS, WM_GETFONT, 0, 0), sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ hBoldFont = CreateFontIndirect(&lf);
+
+ SendDlgItemMessage(hwndDlg, IDC_GROUP_BADWORDS, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_GROUP_OTHERCONTENTS, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_GROUP_SPAMMERS, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_GROUP_GOODWORDS, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TEXT_WARNING, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ }
+
+ // Set icon
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)(HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED));
+
+ // Init checkboxes
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTBADWORDS, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_DEFAULTBADWORDS ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_FORMATING, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_FORMATING, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_FORMATING ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_URL, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_URL, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_URL)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_CAPITALIZED, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CAPITALIZED, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_CAPITALIZED ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_DEFAULTSPAMMERS, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTSPAMMERS, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_DEFAULTSPAMMERS ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_MULTIPLEMESSAGES, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_MULTIPLEMESSAGES, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_MULTIPLEMESSAGES ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_TEASERMESSAGES, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_TEASERMESSAGES, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_TEASERMESSAGES ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_EMPTY, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_EMPTY, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_EMPTY ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_PHONENUMBERS, DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_PHONENUMBERS, (BYTE)(DEFAULT_SETTING_ADVERTISMENT_PHONENUMBERS ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED);
+
+ // Load default bad words count (for spins)
+ SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)SLNewList());
+ SendMessage(hwndDlg, SFM_RELOAD_DEFAULTBADWORDS, 0, 0);
+
+ // Init listboxes
+ {
+ STRINGLIST* pslWords = SLNewList();
+
+ // Bad words
+ GetSpamDefinitionData(pslWords, SDID_CUSTOM_BADWORDS);
+ WordsListBoxInit(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, IDC_BUTTON_ADDBADWORD, IDC_BUTTON_DELETEBADWORD, pslWords, Translate("Add bad phrase/pattern"), Translate("Remove bad phrase/pattern"));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS, (SLGetItemCount(pslWords) > 0) ? (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS, (BYTE)TRUE)?BST_CHECKED:BST_UNCHECKED) : BST_UNCHECKED);
+
+ SLClearList(pslWords);
+
+ // Good words
+ GetSpamDefinitionData(pslWords, SDID_CUSTOM_GOODWORDS);
+ WordsListBoxInit(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, IDC_BUTTON_ADDGOODWORD, IDC_BUTTON_DELETEGOODWORD, pslWords, Translate("Add good phrase/pattern"), Translate("Remove good phrase/pattern"));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, (SLGetItemCount(pslWords) > 0) ? (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDGOODWORDS, (BYTE)TRUE)?BST_CHECKED:BST_UNCHECKED) : BST_UNCHECKED);
+
+ SLFreeList(pslWords);
+ }
+
+ // Init editboxes and spins
+ {
+ BOOL bStatus = TRUE;
+ int iBadWordsCount = ( (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS) == BST_CHECKED) ? SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, LB_GETCOUNT, 0, 0) : 0)
+ + ( (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS) == BST_CHECKED) ? SLGetItemCount((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER)) : 0)
+ - 1;
+
+ // Allowed bad words edit/spin
+ bStatus = SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDBADWORDS), 0, iBadWordsCount, DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDBADWORDS, (DWORD)DEFAULT_SETTING_ADVERTISMENT_ALLOWEDBADWORDS), TRUE);
+ EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDBADWORDS, bStatus);
+
+ // Allowed formated words edit/spin
+ bStatus = SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDFORMATEDWORDS), 0, iBadWordsCount, DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS, (DWORD)DEFAULT_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS), TRUE);
+ EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDFORMATEDWORDS, bStatus);
+
+ // Allowed good words edit/spin
+ SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDGOODWORDS), 0, (SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, LB_GETCOUNT, 0, 0) - 1), DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS, (DWORD)DEFAULT_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS), TRUE);
+ }
+
+ // Check if all definition files do exist
+ if (SLGetItemCount((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER)) <= 0) {
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS, FALSE);
+ ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
+ }
+ if (!IsSpamDefinitionDataPresent(SDID_URLTLDS)) {
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_URL, FALSE);
+ ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
+ }
+ if (!IsSpamDefinitionDataPresent(SDID_SPAMMERS)) {
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_DEFAULTSPAMMERS, FALSE);
+ ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
+ }
+ if (!IsSpamDefinitionDataPresent(SDID_PHONENUMBERS)) {
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_PHONENUMBERS, FALSE);
+ ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
+ }
+ if (!IsSpamDefinitionDataPresent(SDID_TEASERTEXTS)) {
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_TEASERMESSAGES, FALSE);
+ ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
+ }
+
+ // Simulate messages
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDBADWORDS, BN_CLICKED), (LPARAM)NULL);
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, BN_CLICKED), (LPARAM)NULL);
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_FORMATING, BN_CLICKED), (LPARAM)NULL);
+
+ // Restore dlg position (at the end, so the dialog does not get shown early)
+ Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DIALOGPOSITION);
+ // Make sure the dialog is not moved out of sight
+ SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
+
+ // SetFocus (SetFocus() is not allowed in Dialogs)
+ SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), (LPARAM)TRUE);
+ return FALSE;
+ }
+
+ case SFM_RELOAD_DEFAULTBADWORDS:
+ {
+ if (InSendMessage())
+ ReplyMessage(TRUE);
+
+ SLClearList((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER));
+ GetSpamDefinitionData((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER), SDID_BADWORDS);
+ return TRUE;
+ }
+
+ case WM_DESTROY:
+ {
+ // Save dlg position
+ Utils_SaveWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DIALOGPOSITION);
+
+ // Free default bad words
+ SLFreeList((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER));
+
+ // Free font
+ DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_BADWORDS, WM_GETFONT, 0, 0));
+
+ hwndAdvertismentFilter = NULL;
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CHECKBOX_DEFAULTBADWORDS:
+ case IDC_CHECKBOX_CUSTOMIZEDBADWORDS:
+ {
+ int iListCount = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, LB_GETCOUNT, 0, 0);
+ BOOL bStatus = ((IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS) == BST_CHECKED)
+ || (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS) == BST_CHECKED));
+
+ EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDBADWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDFORMATEDWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_FORMATING, bStatus);
+
+ bStatus = (bStatus && ((iListCount+SLGetItemCount((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER))) > 1));
+ EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDBADWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDBADWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDBADWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDFORMATEDWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDFORMATEDWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDFORMATEDWORDS, bStatus);
+
+ // Customized bad words box checked -> Deactivate all customized bad words options
+ bStatus = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS) == BST_CHECKED);
+
+ EnableDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_BUTTON_ADDBADWORD, bStatus);
+ EnableDlgItem(hwndDlg, IDC_BUTTON_DELETEBADWORD, (iListCount > 0) ? bStatus : FALSE);
+
+ // Set/Check allowed bad words value (Simulate changed edit box)
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDITBOX_ALLOWEDBADWORDS, EN_KILLFOCUS), 0);
+
+ return TRUE;
+ }
+
+ case IDC_CHECKBOX_CUSTOMIZEDGOODWORDS:
+ {
+ BOOL bStatus;
+ int iListCount = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, LB_GETCOUNT, 0, 0);
+
+ // Customized good words box checked -> Deactivate all good words options
+ bStatus = (IsDlgButtonChecked(hwndDlg,IDC_CHECKBOX_CUSTOMIZEDGOODWORDS) == BST_CHECKED);
+
+ EnableDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDGOODWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDGOODWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDGOODWORDS, bStatus);
+
+ // Activate Add/Delete buttons?
+ EnableDlgItem(hwndDlg, IDC_BUTTON_ADDGOODWORD, bStatus);
+ EnableDlgItem(hwndDlg, IDC_BUTTON_DELETEGOODWORD, (iListCount > 0) ? bStatus : FALSE);
+
+ EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDGOODWORDS, bStatus);
+
+ bStatus = (bStatus && (iListCount > 1));
+ EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDGOODWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDGOODWORDS, bStatus);
+
+ return TRUE;
+ }
+
+ case IDC_CHECKBOX_FORMATING:
+ {
+ BOOL bStatus = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_FORMATING) == BST_CHECKED);
+
+ EnableDlgItem(hwndDlg, IDC_TEXT_ALLOWEDFORMATEDWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_EDITBOX_ALLOWEDFORMATEDWORDS, bStatus);
+ EnableDlgItem(hwndDlg, IDC_SPIN_ALLOWEDFORMATEDWORDS, bStatus);
+
+ return TRUE;
+ }
+
+ case IDC_EDITBOX_ALLOWEDBADWORDS:
+ case IDC_EDITBOX_ALLOWEDFORMATEDWORDS:
+ {
+ switch(HIWORD(wParam))
+ {
+ case EN_KILLFOCUS:
+ {
+ int iRangeMax = ((IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS) == BST_CHECKED) ? SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, LB_GETCOUNT, 0, 0) : 0)
+ + ((IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS) == BST_CHECKED) ? SLGetItemCount((STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER)) : 0)
+ - 1;
+
+ // Check allowed bad words value
+ SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDBADWORDS), 0, iRangeMax, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDBADWORDS, FALSE);
+
+ // Check allowed formated words value
+ SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDFORMATEDWORDS), 0, iRangeMax, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS, FALSE);
+
+ return TRUE;
+ }
+ }
+
+ break;
+ }
+
+ case IDC_EDITBOX_ALLOWEDGOODWORDS:
+ {
+ switch (HIWORD(wParam))
+ {
+ case EN_KILLFOCUS:
+ {
+ int iRangeMax = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, LB_GETCOUNT, 0, 0) - 1;
+ if (iRangeMax < 0) iRangeMax = 0;
+
+ // Check allowed good words value
+ SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDGOODWORDS), 0, iRangeMax, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS, FALSE);
+
+ return TRUE;
+ }
+ }
+
+ break;
+ }
+
+ case IDC_BUTTON_ADDBADWORD:
+ {
+ WCHAR* pszMsgTitle = TranslateT("Add bad phrase/pattern");
+ WCHAR* pszMsgTextInList = TranslateT("The entered bad phrase \"%s\" already exists in the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the bad phrase be added anyway?");
+ WCHAR* pszMsgTextInOther = TranslateT("The entered bad phrase \"%s\" already exists in the default bad phrases lists.\r\n\r\nAllowing the same bad phrase in the customized bad phrases lists will\npull down the filter quality.\r\n\r\nShall the bad phrase be added anyway?");
+
+ WordsListBoxAddItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, (STRINGLIST*)GetWindowLongPtr(hwndDlg, DWLP_USER), pszMsgTitle, pszMsgTextInList, pszMsgTextInOther, IDC_BUTTON_DELETEBADWORD);
+
+ // Set/Check allowed bad words value (Simulate changed edit box)
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDITBOX_ALLOWEDBADWORDS, EN_KILLFOCUS), 0);
+
+ // Simulate messages
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDBADWORDS, BN_CLICKED), 0);
+
+ return TRUE;
+ }
+
+ case IDC_BUTTON_DELETEBADWORD:
+ {
+ int iItemCount = WordsListBoxDeleteItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, IDC_BUTTON_DELETEBADWORD);
+
+ // Deactivate list on zero entries
+ if (iItemCount == 0)
+ {
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS, BST_UNCHECKED);
+ SendMessage(hwndDlg, WM_COMMAND, IDC_CHECKBOX_CUSTOMIZEDBADWORDS, 0);
+ }
+
+ // Set/Check allowed bad words value (Simulate changed edit box)
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDITBOX_ALLOWEDBADWORDS, EN_KILLFOCUS), 0);
+
+ // Simulate messages
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDBADWORDS, BN_CLICKED), 0);
+
+ return TRUE;
+ }
+
+ case IDC_BUTTON_ADDGOODWORD:
+ {
+ WCHAR* pszMsgTitle = TranslateT("Add good phrase/pattern");
+ WCHAR* pszMsgTextInList = TranslateT("The entered good phrase \"%s\" already exists\r\nin the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the good phrase be added anyway?");
+
+ WordsListBoxAddItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, NULL, pszMsgTitle, pszMsgTextInList, NULL, IDC_BUTTON_DELETEGOODWORD);
+
+ // Set/Check allowed bad words value (Simulate changed edit box)
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDITBOX_ALLOWEDGOODWORDS, EN_KILLFOCUS), 0);
+
+ // Simulate messages
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, BN_CLICKED), 0);
+
+ return TRUE;
+ }
+
+ case IDC_BUTTON_DELETEGOODWORD:
+ {
+ int iItemCount = WordsListBoxDeleteItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, IDC_BUTTON_DELETEGOODWORD);
+ int iRangeMax = iItemCount - 1;
+
+ // Deactivate list on zero entries
+ if (iItemCount == 0)
+ {
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, BST_UNCHECKED);
+ SendMessage(hwndDlg, WM_COMMAND, IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, 0);
+ }
+
+ // Update allowed good words spin
+ SetSpinCtrlRange(GetDlgItem(hwndDlg, IDC_SPIN_ALLOWEDGOODWORDS), 0, iRangeMax, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS, FALSE);
+
+ // Set/Check allowed bad words value (Simulate changed edit box)
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_EDITBOX_ALLOWEDGOODWORDS, EN_KILLFOCUS), 0);
+
+ // Simulate messages
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDGOODWORDS, BN_CLICKED), 0);
+
+ // Set focus on list box again (might have gotten lost on IDC_CHECKBOX_CUSTOMIZEDGOODWORDS)
+ PostMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS), (LPARAM)TRUE);
+ return TRUE;
+ }
+
+ case IDC_BUTTON_SPAMDEFINITIONS:
+ {
+ CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)NULL, (LPARAM)SFT_ADVERTISMENT_FILTER|SFTEXF_SPAMDEFINITIONS_INFO);
+ return TRUE;
+ }
+
+ case IDOK:
+ {
+ EnableDlgItem(hwndDlg, IDOK, FALSE);
+
+ // Save changes
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTBADWORDS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DEFAULTBADWORDS) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_FORMATING, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_FORMATING) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_URL, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_URL) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CAPITALIZED, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CAPITALIZED) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTSPAMMERS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_DEFAULTSPAMMERS) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_MULTIPLEMESSAGES, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_MULTIPLEMESSAGES) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_TEASERMESSAGES, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_TEASERMESSAGES) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_EMPTY, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_EMPTY) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_PHONENUMBERS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_PHONENUMBERS) == BST_CHECKED));
+
+ DBWriteContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDBADWORDS, (WORD)GetDlgItemInt(hwndDlg, IDC_EDITBOX_ALLOWEDBADWORDS, NULL, FALSE));
+ DBWriteContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS, (WORD)GetDlgItemInt(hwndDlg, IDC_EDITBOX_ALLOWEDFORMATEDWORDS, NULL, FALSE));
+ DBWriteContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS, (WORD)GetDlgItemInt(hwndDlg, IDC_EDITBOX_ALLOWEDGOODWORDS, NULL, FALSE));
+
+ // Save listbox contents
+ {
+ STRINGLIST* pslWords = SLNewList();
+
+ // Bad words
+ SLRetrieveFromListBoxCtrl(pslWords, GetDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS));
+
+ SetSpamDefinitionData(pslWords, SDID_CUSTOM_BADWORDS, hwndDlg);
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS, (BYTE)((SLGetItemCount(pslWords) > 0) ? (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDBADWORDS) == BST_CHECKED) : FALSE));
+
+ SLClearList(pslWords);
+
+ // Good words
+ SLRetrieveFromListBoxCtrl(pslWords, GetDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS));
+
+ SetSpamDefinitionData(pslWords, SDID_CUSTOM_GOODWORDS, hwndDlg);
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDGOODWORDS, (BYTE)((SLGetItemCount(pslWords) > 0) ? (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDGOODWORDS) == BST_CHECKED) : FALSE));
+
+ SLFreeList(pslWords);
+ }
+
+ // fall through
+ }
+
+ case IDCANCEL:
+ // WM_CLOSE is transformed into an IDCANCEL by dialog manager
+ {
+ // Different method of closing the window depending on if the window
+ // was created modal or not
+ if (!GetParent(hwndDlg))
+ DestroyWindow(hwndDlg);
+ else
+ EndDialog(hwndDlg, LOWORD(wParam));
+
+ return TRUE;
+ }
+
+ } // switch wParam
+
+ break;
+ }
+
+ default:
+ {
+ if (WordsListBoxDragDrop(hwndDlg, IDC_LISTBOX_CUSTOMIZEDBADWORDS, uMsg, lParam, FALSE)
+ || WordsListBoxDragDrop(hwndDlg, IDC_LISTBOX_CUSTOMIZEDGOODWORDS, uMsg, lParam, FALSE) )
+ return TRUE;
+ }
+
+ } // switch uMsg
+
+ return FALSE;
+}
+
+
+BOOL CALLBACK DlgProcConfigureDislikedMessagesFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ hwndDislikedMessagesFilter = hwndDlg;
+
+ // Translate dialog
+ TranslateDialogDefault(hwndDlg);
+
+ // Make group headings bold
+ {
+ HFONT hBoldFont;
+ LOGFONT lf;
+
+ GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_OTHERCONTENTS, WM_GETFONT, 0, 0), sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ hBoldFont = CreateFontIndirect(&lf);
+
+ SendDlgItemMessage(hwndDlg, IDC_GROUP_OTHERCONTENTS, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_GROUP_WORDS, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_GROUP_NOTIFYSENDER, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TEXT_WARNING, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ }
+
+ // Load icons
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)(HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED));
+
+ // Set Data
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_HOAXTEXTS, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_HOAXTEXTS, (BYTE)(DEFAULT_SETTING_DISLIKEDMESSAGE_HOAXTEXTS ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_MULTIPLEMESSAGES, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES, (BYTE)(DEFAULT_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_NOTIFYSENDER, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER, (BYTE)(DEFAULT_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_ADDTOHISTORY, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY, (BYTE)(DEFAULT_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY ? BST_CHECKED : BST_UNCHECKED)) ? BST_CHECKED : BST_UNCHECKED));
+
+ // Init listboxes
+ {
+ STRINGLIST* pslWords = SLNewList();
+
+ // Disliked words
+ GetSpamDefinitionData(pslWords, SDID_CUSTOM_DISLIKEDWORDS);
+ WordsListBoxInit(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, IDC_BUTTON_ADDWORD, IDC_BUTTON_DELETEWORD, pslWords, Translate("Add indicating phrase/pattern"), Translate("Remove indicating phrase"));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDWORDS, (SLGetItemCount(pslWords) > 0) ? (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_CUSTOMIZEDWORDS, (BYTE)TRUE)?BST_CHECKED:BST_UNCHECKED) : BST_UNCHECKED);
+
+ SLFreeList(pslWords);
+ }
+
+ // Init editbox
+ {
+ DBVARIANT dbv;
+
+ // Notify text
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE, &dbv) == 0)
+ {
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_NOTIFYSENDER, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_NOTIFYSENDER, DEFAULT_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE);
+ }
+ }
+
+ if (!IsSpamDefinitionDataPresent(SDID_HOAXTEXTS)) {
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_HOAXTEXTS, FALSE);
+ ShowDlgItem(hwndDlg, IDC_TEXT_WARNING, TRUE);
+ }
+
+ // Show/Hide Variables Plugin help button
+ if (!MakeVariablesHelpButton(hwndDlg, IDC_BUTTON_NOTIFYSENDER_VARIABLES))
+ {
+ RECT rc;
+
+ if (GetWindowRect(GetDlgItem(hwndDlg, IDC_TEXT_NOTIFYSENDER), &rc))
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_TEXT_NOTIFYSENDER), NULL, 0, 0, (rc.right-rc.left)+25, (rc.bottom-rc.top), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+ }
+
+ // Simulate messages
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_CUSTOMIZEDWORDS, BN_CLICKED), 0);
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHECKBOX_NOTIFYSENDER, BN_CLICKED), 0);
+
+ // Restore dlg position (at the end, so the dialog does not get shown early)
+ Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_DIALOGPOSITION);
+ // Make sure the dialog is not moved out of sight
+ SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
+
+ // SetFocus (SetFocus() is not allowed in Dialogs)
+ SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), (LPARAM)TRUE);
+ return FALSE;
+ }
+
+ case WM_DESTROY:
+ {
+ // Save dlg position
+ Utils_SaveWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_DIALOGPOSITION);
+
+ // Free font
+ DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_OTHERCONTENTS, WM_GETFONT, 0, 0));
+
+ // Destroy help icon
+ DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_BUTTON_NOTIFYSENDER_VARIABLES, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0));
+
+ hwndDislikedMessagesFilter = NULL;
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CHECKBOX_NOTIFYSENDER:
+ {
+ BOOL bStatus = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_NOTIFYSENDER) == BST_CHECKED);
+
+ EnableDlgItem(hwndDlg, IDC_EDITBOX_NOTIFYSENDER, bStatus);
+ EnableDlgItem(hwndDlg, IDC_TEXT_NOTIFYSENDER, bStatus);
+ EnableDlgItem(hwndDlg, IDC_CHECKBOX_ADDTOHISTORY, bStatus);
+
+ if (ServiceExists(MS_VARS_SHOWHELP) && ServiceExists(MS_VARS_FORMATSTRING))
+ EnableDlgItem(hwndDlg, IDC_BUTTON_NOTIFYSENDER_VARIABLES, bStatus);
+
+ // Avoid passing simulated messages to the system
+ if (!lParam) return TRUE;
+ break;
+ }
+
+ case IDC_CHECKBOX_CUSTOMIZEDWORDS:
+ {
+ BOOL bStatus = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDWORDS) == BST_CHECKED);
+ int iListCount = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, LB_GETCOUNT, 0, 0);
+
+ // Customized bad words box checked -> Deactivate all customized bad words options
+ EnableDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, bStatus);
+
+ // Deactivate Add/Delete buttons?
+ EnableDlgItem(hwndDlg, IDC_BUTTON_ADDWORD, bStatus);
+ EnableDlgItem(hwndDlg, IDC_BUTTON_DELETEWORD, (iListCount > 0) ? bStatus : FALSE);
+
+ // Avoid passing simulated messages to the system
+ if (!lParam) return TRUE;
+
+ break;
+ }
+
+ case IDC_BUTTON_NOTIFYSENDER_VARIABLES:
+ {
+ // SetFocus (SetFocus() is not allowed in Dialogs)
+ SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_NOTIFYSENDER), (LPARAM)TRUE);
+
+ CallService(MS_VARS_SHOWHELP, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_NOTIFYSENDER), (LPARAM)NULL);
+ break;
+ }
+
+ case IDC_BUTTON_ADDWORD:
+ {
+ WCHAR* pszMsgTitle = TranslateT("Add indicating phrase/pattern");
+ WCHAR* pszMsgTextInList = TranslateT("The entered indicating phrase \"%s\" already exists in the list.\r\n\r\nThe filter doesn't differentiate between lower and upper case.\r\nTwo entries with the same phrase are not neccessary\nand will decrease the filter quality.\r\n\r\nShall the indicating phrase be added anyway?");
+
+ WordsListBoxAddItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, NULL, pszMsgTitle, pszMsgTextInList, NULL, IDC_BUTTON_DELETEWORD);
+
+ break;
+ }
+
+ case IDC_BUTTON_DELETEWORD:
+ {
+ int iItemCount = WordsListBoxDeleteItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, IDC_BUTTON_DELETEWORD);
+
+ // Deactivate list on zero entries
+ if (iItemCount == 0)
+ {
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDWORDS, BST_UNCHECKED);
+ SendMessage(hwndDlg, WM_COMMAND, IDC_CHECKBOX_CUSTOMIZEDWORDS, 0);
+ }
+
+ break;
+ }
+
+ case IDC_BUTTON_SPAMDEFINITIONS:
+ {
+ CallService(MS_SPAMFILTER_SHOWFILTERDIALOG, (WPARAM)NULL, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER|SFTEXF_SPAMDEFINITIONS_INFO);
+ break;
+ }
+
+ case IDOK:
+ {
+ EnableDlgItem(hwndDlg, IDOK, FALSE);
+
+ // Save changes
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_MULTIPLEMESSAGES) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_HOAXTEXTS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_HOAXTEXTS) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ADDTOHISTORY) == BST_CHECKED));
+
+ // Save texts
+ {
+ HWND hwndEdit = GetDlgItem(hwndDlg, IDC_EDITBOX_NOTIFYSENDER);
+ int iTextLen = GetWindowTextLength(hwndEdit);
+ WCHAR* pszText = (WCHAR*)mir_alloc((iTextLen+1)*sizeof(WCHAR));
+
+ // Get entered text
+ if (pszText)
+ {
+ if (GetWindowText(hwndEdit, pszText, iTextLen+1) == 0)
+ pszText[0] = _T('\0');
+
+ // Save text
+ if (lstrlen(pszText) > 0) {
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE, pszText);
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_NOTIFYSENDER) == BST_CHECKED));
+ } else{
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE, DEFAULT_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE);
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER, (BYTE)FALSE);
+ }
+
+ mir_free(pszText);
+ }
+ }
+
+ // Save listbox contents
+ {
+ STRINGLIST* pslWords = SLNewList();
+
+ // Chain words
+ SLRetrieveFromListBoxCtrl(pslWords, GetDlgItem(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS));
+
+ SetSpamDefinitionData(pslWords, SDID_CUSTOM_DISLIKEDWORDS, hwndDlg);
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_CUSTOMIZEDWORDS, (BYTE)((SLGetItemCount(pslWords) > 0) ? (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_CUSTOMIZEDWORDS) == BST_CHECKED) : FALSE));
+
+ SLFreeList(pslWords);
+ }
+
+ // fall through
+ }
+
+ case IDCANCEL:
+ // WM_CLOSE is transformed into an IDCANCEL by dialog manager
+ {
+ // Different method of closing the window depending on if the window
+ // was created modal or not
+ if (!GetParent(hwndDlg))
+ DestroyWindow(hwndDlg);
+ else
+ EndDialog(hwndDlg, LOWORD(wParam));
+
+ return TRUE;
+ }
+
+ } // switch wParam
+ break;
+ }
+
+ default:
+ {
+ if (WordsListBoxDragDrop(hwndDlg, IDC_LISTBOX_CUSTOMIZEDWORDS, uMsg, lParam, FALSE))
+ return TRUE;
+ }
+
+ }
+ return FALSE;
+}
+
+
+BOOL CALLBACK DlgProcConfigureRobotFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ hwndRobotFilter = hwndDlg;
+
+ // Translate dialog
+ TranslateDialogDefault(hwndDlg);
+
+ // Make group headings bold
+ {
+ HFONT hBoldFont;
+ LOGFONT lf;
+
+ GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_MESSAGETEXTS, WM_GETFONT, 0, 0), sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ hBoldFont = CreateFontIndirect(&lf);
+
+ SendDlgItemMessage(hwndDlg, IDC_GROUP_MESSAGETEXTS, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_GROUP_ANSWER, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ }
+
+ // Load icons
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)(HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED));
+
+ // Set Data
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_ADDTOHISTORY, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ADDTOHISTORY, (BYTE)DEFAULT_SETTING_ROBOT_ADDTOHISTORY) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_HIDE, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_HIDEUSERS, (BYTE)DEFAULT_SETTING_ROBOT_HIDEUSERS) ? BST_CHECKED : BST_UNCHECKED));
+
+ // Init editboxes
+ {
+ DBVARIANT dbv;
+
+ // Question
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_INSTRUCTION, &dbv) == 0) {
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_INSTRUCTION, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_INSTRUCTION, DEFAULT_SETTING_ROBOT_INSTRUCTION);
+ }
+
+ // Congratulation
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_CONFIRMATION, &dbv) == 0) {
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_CONFIRMATION, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_CONFIRMATION, DEFAULT_SETTING_ROBOT_CONFIRMATION);
+ }
+
+ // Answer
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, &dbv) == 0) {
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_ANSWER, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ WCHAR szRnd[RANDOM_ANSWER_LENGTH+1];
+ GetRandomString(szRnd, ARRAYSIZE(szRnd));
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, szRnd);
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_ANSWER, szRnd);
+ }
+ }
+
+ // Show/Hide Variables Plugin help button (Question)
+ MakeVariablesHelpButton(hwndDlg, IDC_BUTTON_INSTRUCTION_VARIABLES);
+
+ // Show/Hide Variables Plugin help button (Confirmation)
+ if (!MakeVariablesHelpButton(hwndDlg, IDC_BUTTON_CONFIRMATION_VARIABLES))
+ {
+ RECT rc;
+ if (GetWindowRect(GetDlgItem(hwndDlg, IDC_TEXT_VARS), &rc))
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_TEXT_VARS), NULL, 0, 0, (rc.right-rc.left)+25, (rc.bottom-rc.top), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+ }
+
+
+ // Restore dlg position (at the end, so the dialog does not get shown early)
+ Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_DIALOGPOSITION);
+ // Make sure the dialog is not moved out of sight
+ SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
+
+ // SetFocus (SetFocus() is not allowed in Dialogs)
+ SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), (LPARAM)TRUE);
+ return FALSE;
+ }
+
+ case WM_DESTROY:
+ {
+ // Save dlg position
+ Utils_SaveWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_DIALOGPOSITION);
+
+ // Free font
+ DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_GROUP_MESSAGETEXTS, WM_GETFONT, 0, 0));
+
+ // Destroy help icons
+ DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_BUTTON_INSTRUCTION_VARIABLES, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0));
+ DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_BUTTON_CONFIRMATION_VARIABLES, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0));
+
+ hwndRobotFilter = NULL;
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_BUTTON_INSTRUCTION_VARIABLES:
+ {
+ // SetFocus (SetFocus() is not allowed in Dialogs)
+ SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_INSTRUCTION), (LPARAM)TRUE);
+
+ CallService(MS_VARS_SHOWHELP, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_INSTRUCTION), (LPARAM)NULL);
+ break;
+ }
+
+ case IDC_BUTTON_CONFIRMATION_VARIABLES:
+ {
+ // SetFocus (SetFocus() is not allowed in Dialogs)
+ SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_CONFIRMATION), (LPARAM)TRUE);
+
+ CallService(MS_VARS_SHOWHELP, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_CONFIRMATION), (LPARAM)NULL);
+ break;
+ }
+
+ case IDC_BUTTON_ANSWER:
+ {
+ WCHAR szRnd[RANDOM_ANSWER_LENGTH+1];
+
+ GetRandomString(szRnd, ARRAYSIZE(szRnd));
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_ANSWER, szRnd);
+ break;
+ }
+
+ case IDOK:
+ {
+ EnableDlgItem(hwndDlg, IDOK, FALSE);
+
+ // Save changes
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ADDTOHISTORY, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_ADDTOHISTORY) == BST_CHECKED));
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_HIDEUSERS, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_HIDE) == BST_CHECKED));
+
+ // Save texts
+ {
+ int iTextLen;
+ WCHAR* pszText;
+
+ // Instruction
+ iTextLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_EDITBOX_INSTRUCTION));
+ pszText = (WCHAR*)mir_alloc((iTextLen+1)*sizeof(WCHAR));
+ if (pszText)
+ {
+ if (GetWindowText(GetDlgItem(hwndDlg, IDC_EDITBOX_INSTRUCTION), pszText, iTextLen+1) == 0)
+ pszText[0] = _T('\0');
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_INSTRUCTION, (lstrlen(pszText)>0) ? pszText : DEFAULT_SETTING_ROBOT_INSTRUCTION);
+ mir_free(pszText);
+ }
+
+ // Confirmation
+ iTextLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_EDITBOX_CONFIRMATION));
+ pszText = (WCHAR*)mir_alloc((iTextLen+1)*sizeof(WCHAR));
+ if (pszText)
+ {
+ if (GetWindowText(GetDlgItem(hwndDlg, IDC_EDITBOX_CONFIRMATION), pszText, iTextLen+1) == 0)
+ pszText[0] = _T('\0');
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_CONFIRMATION, (lstrlen(pszText)>0) ? pszText : DEFAULT_SETTING_ROBOT_CONFIRMATION);
+ mir_free(pszText);
+ }
+
+ // Correct Answer
+ iTextLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_EDITBOX_ANSWER));
+ pszText = (WCHAR*)mir_alloc((iTextLen+1)*sizeof(WCHAR));
+ if (pszText)
+ {
+ if (GetWindowText(GetDlgItem(hwndDlg, IDC_EDITBOX_ANSWER), pszText, iTextLen+1) == 0)
+ pszText[0] = _T('\0');
+ if (lstrlen(pszText) > 0) {
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, pszText);
+ } else {
+ WCHAR szRnd[RANDOM_ANSWER_LENGTH+1];
+ GetRandomString(szRnd, ARRAYSIZE(szRnd));
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, szRnd);
+ }
+ mir_free(pszText);
+ }
+ }
+
+ // fall through
+ }
+
+ case IDCANCEL:
+ // WM_CLOSE is transformed into an IDCANCEL by dialog manager
+ {
+ // Different method of closing the window depending on if the window
+ // was created modal or not
+ if (!GetParent(hwndDlg))
+ DestroyWindow(hwndDlg);
+ else
+ EndDialog(hwndDlg, LOWORD(wParam));
+
+ return TRUE;
+ }
+
+ } // switch wParam
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+// -- Spam Definitions Info
+
+static BOOL CALLBACK EnumSpamDefinitions_InsertItem(UINT uSpamDefID, WCHAR* pszFilePath, WCHAR* pszName, SYSTEMTIME* pstDate, WPARAM wParam, LPARAM lParam)
+{
+ LVITEM lvi;
+
+ if (!lParam) return FALSE;
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_TEXT|LVIF_PARAM;
+ lvi.pszText = pszName?TranslateTS(pszName):TranslateT("Not Available");
+ lvi.lParam = (LPARAM)mir_wstrdup(pszFilePath);
+
+ lvi.iItem = ListView_InsertItem((HWND)wParam, &lvi);
+ if (lvi.iItem >= 0)
+ {
+ // Version
+ if (pstDate)
+ {
+ WCHAR szDate[9];
+ if (GetDateFormat(GetThreadLocale(), 0, pstDate, _T("yy'.'MM'.'dd"), szDate, ARRAYSIZE(szDate)) != 0)
+ ListView_SetItemText((HWND)wParam, lvi.iItem, 1, szDate);
+ }
+
+ if (!IsWinVerXPPlus() || !ListView_IsGroupViewEnabled((HWND)wParam))
+ {
+ ListView_SetItemText((HWND)wParam, lvi.iItem, 2, (WCHAR*)lParam); // Type
+
+ } else {
+
+ if (ListView_HasGroup((HWND)wParam, uSpamDefID))
+ {
+ lvi.mask = LVIF_GROUPID;
+ lvi.iGroupId = uSpamDefID;
+
+ ListView_SetItem((HWND)wParam, &lvi);
+ // ListView_MoveItemToGroup not implemented in WinSDK
+
+ } else {
+
+ LVGROUP lvg;
+
+ ZeroMemory(&lvg, sizeof(lvg));
+ lvg.cbSize = sizeof(lvg);
+ lvg.mask = LVGF_HEADER|LVGF_GROUPID;
+ lvg.iGroupId = uSpamDefID;
+ #if defined(UNICODE)
+ lvg.pszHeader = (WCHAR*)lParam;
+ ListView_InsertGroup((HWND)wParam, lvi.iItem, &lvg);
+ #else
+ lvg.pszHeader = mir_utf8encodeW((WCHAR*)lParam);
+ ListView_InsertGroup((HWND)wParam, lvi.iItem, &lvg);
+ if (lvg.pszHeader) mir_free(lvg.pszHeader);
+ #endif
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+static int ResizeProcSpamDefinitionsInfo(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL *urc)
+{
+ switch(urc->wId)
+ {
+ case IDC_TEXT_DESCRIPTION:
+ return RD_ANCHORY_TOP|RD_ANCHORX_WIDTH;
+
+ case IDC_TAB_SPAMDEFINITIONS:
+ return RD_ANCHORY_HEIGHT|RD_ANCHORX_WIDTH;
+
+ case IDC_LISTVIEW_SPAMDEFINITIONS:
+ {
+ POINT pt = {0, 0};
+
+ // Keep exactly same position (resized later)
+ GetWindowRect(GetDlgItem(hwndDlg, urc->wId), &urc->rcItem);
+ if (ClientToScreen(hwndDlg, &pt))
+ OffsetRect(&urc->rcItem, -pt.x, -pt.y);
+
+ return RD_ANCHORY_CUSTOM|RD_ANCHORX_CUSTOM;
+ }
+
+ case IDC_URL_GETMORE:
+ return RD_ANCHORY_BOTTOM|RD_ANCHORX_WIDTH;
+
+ //case IDCANCEL:
+ //case IDC_SCROLLBAR_SIZEGRIP:
+ default:
+ return RD_ANCHORY_BOTTOM|RD_ANCHORX_RIGHT;
+ }
+}
+
+void FixListHeader(HWND hwndListView)
+{
+ // Resize header (does not fit fully using small border)
+ // at least on WinME
+ RECT rcList, rcHeader;
+ HWND hwndHeader = ListView_GetHeader(hwndListView);
+
+ if (GetClientRect(hwndListView, &rcList) && GetClientRect(hwndHeader, &rcHeader))
+ if ((rcHeader.right-rcHeader.left) != (rcList.right-rcList.left))
+ SetWindowPos(hwndHeader, NULL, 0, 0, rcList.right-rcList.left, rcHeader.bottom-rcHeader.top, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
+}
+
+BOOL CALLBACK DlgProcSpamDefinitionsInfo(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ hwndSpamDefinitionsInfo = hwndDlg;
+
+ /*
+ #if defined(UNICODE)
+ // Convert DlgProc to Unicode (IsWindowUnicode returns true after this call -> see docs)
+ SetWindowLongPtrW(hwndDlg, DWLP_DLGPROC, (LONG_PTR)DlgProcSpamDefinitionsInfo);
+ #endif
+ */
+
+ // Translate dialog first
+ TranslateDialogDefault(hwndDlg);
+
+ // Set icon
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)(HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_SPAM_DEFINITIONS), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED));
+
+ // Make heading
+ {
+ HFONT hBoldFont;
+ LOGFONT lf;
+
+ GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0), sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ hBoldFont = CreateFontIndirect(&lf);
+
+ SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ }
+
+ // Init tabs
+ {
+ HWND hwndTab = GetDlgItem(hwndDlg, IDC_TAB_SPAMDEFINITIONS);
+ TCITEM tci;
+
+ tci.mask = TCIF_TEXT|TCIF_PARAM;
+ tci.pszText = TranslateT("Advertisment Filter");
+ tci.lParam = SFT_ADVERTISMENT_FILTER;
+ TabCtrl_InsertItem(hwndTab, 0, &tci);
+
+ tci.pszText = TranslateT("Disliked Messages Filter");
+ tci.lParam = SFT_DISLIKEDMESSAGES_FILTER;
+ TabCtrl_InsertItem(hwndTab, 1, &tci);
+ }
+
+ // Init ListView
+ {
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LISTVIEW_SPAMDEFINITIONS);
+ LVCOLUMN lvc;
+ int iMinSizePacketCol;
+
+ ListView_SetExtendedListViewStyle(hwndList, LVS_EX_LABELTIP|LVS_EX_FULLROWSELECT);
+
+ if (IsWinVerXPPlus())
+ ListView_EnableGroupView(hwndList, TRUE);
+
+ lvc.mask = LVCF_TEXT;
+
+ if (IsWinVerXPPlus() && ListView_IsGroupViewEnabled(hwndList))
+ {
+ // Name
+ lvc.pszText = TranslateT("Packet");
+ ListView_InsertColumn(hwndList, 0, &lvc);
+ iMinSizePacketCol = 200;
+
+ // Date
+ lvc.mask |= LVCF_FMT;
+ lvc.pszText = TranslateT("Version");
+ lvc.fmt = LVCFMT_RIGHT;
+ ListView_InsertColumn(hwndList, 1, &lvc);
+
+ } else {
+
+ // Name
+ lvc.pszText = TranslateT("Packet");
+ ListView_InsertColumn(hwndList, 0, &lvc);
+ iMinSizePacketCol = 120;
+
+ // Date
+ lvc.mask |= LVCF_FMT;
+ lvc.pszText = TranslateT("Version");
+ lvc.fmt = LVCFMT_RIGHT;
+ ListView_InsertColumn(hwndList, 1, &lvc);
+
+ // Type
+ lvc.mask ^= LVCF_FMT;
+ lvc.pszText = TranslateT("Type");
+ ListView_InsertColumn(hwndList, 2, &lvc);
+ }
+
+ // Insert info items
+ SendMessage(hwndDlg, SFM_REFRESH_SPAMDEFINITIONS, (WPARAM)TRUE, (LPARAM)lParam);
+
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE_USEHEADER);
+ if (ListView_GetColumnWidth(hwndList, 0) < iMinSizePacketCol)
+ ListView_SetColumnWidth(hwndList, 0, iMinSizePacketCol);
+
+ ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
+ if (ListView_GetColumnWidth(hwndList, 1) < 60)
+ ListView_SetColumnWidth(hwndList, 1, 60);
+
+ // Restore dlg position (at the end, so the dialog does not get shown early)
+ Utils_RestoreWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_SPAMDEF_DIALOGPOSITION);
+ // Make sure the dialog is not moved out of sight
+ SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0); //simulate message
+
+ // Stretch last column to fit remaining space
+ if (!IsWinVerXPPlus() || !ListView_IsGroupViewEnabled(hwndList))
+ ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE_USEHEADER);
+ else
+ ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
+
+ FixListHeader(hwndList);
+ }
+
+ // SetFocus (SetFocus() is not allowed in Dialogs)
+ SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDCANCEL), (LPARAM)TRUE);
+ return FALSE;
+ }
+
+ case SFM_REFRESH_SPAMDEFINITIONS:
+ {
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LISTVIEW_SPAMDEFINITIONS);
+ DWORD dwFilterType;
+ int iSelectedIndex = ListView_GetSelectionMark(hwndList);
+
+ if ((DWORD)lParam == 0) {
+ dwFilterType = (DWORD)GetWindowLongPtr(hwndDlg, DWLP_USER);
+ } else {
+ dwFilterType = (DWORD)lParam;
+ if ((DWORD)SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)dwFilterType) == dwFilterType)
+ if (!(BOOL)wParam) // if not forced refresh
+ return TRUE;
+ }
+
+ ListView_DeleteAllItems(hwndList);
+ //ListView_RemoveAllGroups(); // not really needed, always the same groups
+
+ FixListHeader(hwndList);
+
+ if (InSendMessage())
+ ReplyMessage(TRUE);
+
+ // Change tab
+ {
+ HWND hwndTab = GetDlgItem(hwndDlg, IDC_TAB_SPAMDEFINITIONS);
+ int i;
+ TCITEM tci;
+
+ tci.mask = TCIF_PARAM;
+ for (i=TabCtrl_GetItemCount(hwndTab)-1; i>=0; i--)
+ {
+ if (TabCtrl_GetItem(hwndTab, i, &tci))
+ if ((DWORD)tci.lParam == dwFilterType)
+ {
+ if (TabCtrl_GetCurSel(hwndTab) != i)
+ TabCtrl_SetCurSel(hwndTab, i);
+ break;
+ }
+
+ if (i==0) TabCtrl_SetCurSel(hwndTab, -1);
+ }
+ FixListHeader(hwndList);
+ }
+
+ // Insert info items
+ switch (dwFilterType)
+ {
+ case SFT_ADVERTISMENT_FILTER:
+ {
+ SetWindowText(hwndDlg, TranslateT("Spam Definitions: Advertisment Filter"));
+
+ EnumSpamDefinitions(SDID_BADWORDS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Default Bad Words"));
+ EnumSpamDefinitions(SDID_SPAMMERS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Known Spammers"));
+ EnumSpamDefinitions(SDID_TEASERTEXTS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Known Teaser Texts"));
+
+ EnumSpamDefinitions(SDID_URLTLDS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("URL Recognition"));
+ EnumSpamDefinitions(SDID_PHONENUMBERS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Phone Number Recognition"));
+
+ EnumSpamDefinitions(SDID_SPECIALCHARS_REPLACE_TEXT, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Different Format Recognition: Text"));
+ EnumSpamDefinitions(SDID_SPECIALCHARS_REPLACE_NUMBERS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Different Format Recognition: Numbers"));
+ EnumSpamDefinitions(SDID_SPECIALCHARS_SEPARATORS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Different Format Recognition: Separators"));
+ break;
+ }
+
+ case SFT_DISLIKEDMESSAGES_FILTER:
+ {
+ SetWindowText(hwndDlg, TranslateT("Spam Definitions: Disliked Messages Filter"));
+
+ EnumSpamDefinitions(SDID_HOAXTEXTS, TRUE, EnumSpamDefinitions_InsertItem, (WPARAM)hwndList, (LPARAM)TranslateT("Known Hoax Texts"));
+ break;
+ }
+ }
+
+ if (iSelectedIndex >= 0)
+ {
+ if (iSelectedIndex >= ListView_GetItemCount(hwndList))
+ iSelectedIndex = ListView_GetItemCount(hwndList)-1;
+
+ ListView_SetSelectionMark(hwndList, iSelectedIndex);
+ ListView_EnsureVisible(hwndList, iSelectedIndex, FALSE);
+ }
+
+ FixListHeader(hwndList);
+ return TRUE;
+ }
+
+ case SFM_REMOVE_SPAMDEFINITIONFILE:
+ {
+ int iItem = (int)wParam;
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LISTVIEW_SPAMDEFINITIONS);
+
+ LVITEM lvi;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = iItem;
+
+ // Get item
+ if (ListView_GetItem(hwndList, &lvi))
+ {
+ if (lvi.lParam)
+ {
+ SHFILEOPSTRUCT sfo;
+
+ // Doubly-null terminated pFrom (as required)
+ WCHAR szFrom[MAX_PATH+1];
+ mir_sntprintf(szFrom, ARRAYSIZE(szFrom)-1, _T("%s"), lvi.lParam);
+ szFrom[lstrlen(szFrom)+1] = _T('\0');
+
+ ZeroMemory(&sfo, sizeof(sfo));
+ sfo.hwnd = hwndDlg;
+ sfo.wFunc = FO_DELETE;
+ sfo.pFrom = szFrom;
+ sfo.fFlags = FOF_SIMPLEPROGRESS|FOF_NO_CONNECTED_ELEMENTS;
+ sfo.lpszProgressTitle = lvi.pszText;
+
+ // Ask to delete file
+ if (SHFileOperation(&sfo) == 0)
+ if (!sfo.fAnyOperationsAborted)
+ if (ListView_DeleteItem(hwndList, iItem))
+ {
+ // Select next item
+ if (iItem >= ListView_GetItemCount(hwndList))
+ iItem--;
+
+ ListView_SetSelectionMark(hwndList, iItem);
+ }
+
+ }
+ }
+
+ return TRUE;
+ }
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pnmhdr = (LPNMHDR)lParam;
+
+ switch (pnmhdr->idFrom)
+ {
+ case IDC_TAB_SPAMDEFINITIONS:
+ {
+ switch (pnmhdr->code)
+ {
+ case TCN_SELCHANGE:
+ {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+
+ if (TabCtrl_GetItem(pnmhdr->hwndFrom, TabCtrl_GetCurSel(pnmhdr->hwndFrom), &tci))
+ SendMessage(hwndDlg, SFM_REFRESH_SPAMDEFINITIONS, (WPARAM)FALSE, (LPARAM)tci.lParam);
+
+ return TRUE;
+ }
+ }
+
+ break;
+ }
+
+ case IDC_LISTVIEW_SPAMDEFINITIONS:
+ {
+ switch (pnmhdr->code)
+ {
+ case LVN_DELETEITEM:
+ {
+ LVITEM lvi;
+
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = ((LPNMLISTVIEW)lParam)->iItem;
+
+ // Release lParam memory of removed item
+ if (ListView_GetItem(pnmhdr->hwndFrom, &lvi))
+ if (lvi.lParam)
+ mir_free((WCHAR*)lvi.lParam);
+
+ return FALSE;
+ }
+
+ case LVN_KEYDOWN:
+ {
+ switch (((NMLVKEYDOWN*)lParam)->wVKey)
+ {
+ case VK_DELETE:
+ {
+ PostMessage(hwndDlg, SFM_REMOVE_SPAMDEFINITIONFILE, (WPARAM)ListView_GetSelectionMark(pnmhdr->hwndFrom), 0);
+
+ // Prevent default processing
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)FALSE);
+ return TRUE;
+ }
+ }
+
+ break;
+ }
+
+ case NM_RCLICK:
+ {
+ LPNMLISTVIEW pnmlw = (LPNMLISTVIEW)lParam;
+
+ HMENU hMenu, hContextMenu;
+ LVITEM lvi;
+
+ // Click was not on an item
+ if (pnmlw->iItem < 0) break;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = pnmlw->iItem;
+
+ // Get item
+ if (!ListView_GetItem(pnmhdr->hwndFrom, &lvi)) break;
+ if (!lvi.lParam) break;
+ if (!ClientToScreen(pnmhdr->hwndFrom, &(pnmlw->ptAction))) break;
+
+ // Context menu
+ hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_CONTEXT));
+ hContextMenu = GetSubMenu(hMenu, 1);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hContextMenu, 0);
+ switch (TrackPopupMenuEx(hContextMenu, TPM_RETURNCMD|TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, pnmlw->ptAction.x, pnmlw->ptAction.y, pnmhdr->hwndFrom, NULL))
+ {
+ case ID_MENU_DELETE:
+ {
+ PostMessage(hwndDlg, SFM_REMOVE_SPAMDEFINITIONFILE, (WPARAM)pnmlw->iItem, 0);
+ break;
+ }
+ }
+
+ // Destroy context menu
+ if (hMenu) DestroyMenu(hMenu);
+
+ // Prevent default processing
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)FALSE);
+ return TRUE;
+ }
+
+ } // switch
+
+ break;
+ }
+
+ } // switch
+
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ hwndSpamDefinitionsInfo = NULL;
+
+ // Free font
+ DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0));
+
+ // Save dlg position
+ Utils_SaveWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_SPAMDEF_DIALOGPOSITION);
+
+ return TRUE;
+ }
+
+ case WM_CLOSE:
+ {
+ // Different method of closing the window depending on if the window
+ // was created modal or not
+ if (!GetParent(hwndDlg))
+ DestroyWindow(hwndDlg);
+ else
+ EndDialog(hwndDlg, IDCANCEL);
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_URL_GETMORE:
+ {
+ CallService(MS_UTILS_OPENURL, (WPARAM)TRUE, (LPARAM)Translate("http://addons.miranda-im.org/index.php?action=display&id=92"));
+ return TRUE;
+ }
+
+ case IDOK:
+ case IDCANCEL:
+ // WM_CLOSE is transformed into an IDCANCEL by dialog manager
+ {
+ // Different method of closing the window depending on if the window
+ // was created modal or not
+ if (!GetParent(hwndDlg))
+ DestroyWindow(hwndDlg);
+ else
+ EndDialog(hwndDlg, LOWORD(wParam));
+
+ return TRUE;
+ }
+
+ } // switch wParam
+
+ break;
+ }
+
+ case WM_SIZE:
+ {
+ UTILRESIZEDIALOG urd;
+
+ ZeroMemory(&urd, sizeof(urd));
+ urd.cbSize = sizeof(urd);
+ urd.hInstance = hInstance;
+ urd.hwndDlg = hwndDlg;
+ urd.lpTemplate = MAKEINTRESOURCEA(IDD_INFO_SPAMDEFINITIONS);
+ urd.pfnResizer = ResizeProcSpamDefinitionsInfo;
+
+ CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd);
+
+ // Resize listview to exactly fit tab control
+ {
+ RECT rcDisplay;
+ POINT pt = {0, 0};
+
+ if (GetWindowRect(GetDlgItem(hwndDlg, IDC_TAB_SPAMDEFINITIONS), &rcDisplay))
+ {
+ TabCtrl_AdjustRect(GetDlgItem(hwndDlg, IDC_TAB_SPAMDEFINITIONS), FALSE, &rcDisplay);
+ if (ClientToScreen(hwndDlg, &pt))
+ OffsetRect(&rcDisplay, -pt.x, -pt.y);
+
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_LISTVIEW_SPAMDEFINITIONS), HWND_TOP, rcDisplay.left, rcDisplay.top, rcDisplay.right-rcDisplay.left, rcDisplay.bottom-rcDisplay.top, SWP_NOACTIVATE);
+ }
+ }
+
+ FixListHeader(GetDlgItem(hwndDlg, IDC_LISTVIEW_SPAMDEFINITIONS));
+ return TRUE;
+ }
+
+ case WM_GETMINMAXINFO:
+ {
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = 340;
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = 150;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+void Spammers_ResetListOptions(HWND hwndList)
+{
+ int i;
+
+ // Same layout as Ignore options
+ SendMessage(hwndList, CLM_SETBKBITMAP, 0, (LPARAM)(HBITMAP)NULL);
+ SendMessage(hwndList, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW),0);
+ SendMessage(hwndList, CLM_SETGREYOUTFLAGS, 0, 0);
+ SendMessage(hwndList, CLM_SETLEFTMARGIN, 4, 0);
+ SendMessage(hwndList, CLM_SETINDENT, 10, 0);
+ SendMessage(hwndList, CLM_SETHIDEEMPTYGROUPS, TRUE, 0);
+ SendMessage(hwndList, CLM_SETUSEGROUPS, FALSE, 0);
+
+ for(i=0;i<=FONTID_MAX;i++)
+ SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+}
+
+int Spammers_GetListIcon(HWND hwndList, HANDLE hItem)
+{
+ int i;
+
+ for (i=0; i<SendMessage(hwndList, CLM_GETEXTRACOLUMNS, 0, 0); i++)
+ if (SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(i, 0)) == i)
+ return i;
+
+ return -1;
+}
+
+void Spammers_SetListIcon(HWND hwndList, HANDLE hItem, int iColumn)
+{
+ int i, iColCount;
+
+ iColCount = SendMessage(hwndList, CLM_GETEXTRACOLUMNS, 0, 0);
+ for (i=0; i<iColCount; i++)
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(i, (i==iColumn)?i:iColCount));
+}
+
+void Spammers_SetAllListIcons(HWND hwndList, int iColumn, BOOL bForce, BOOL bWatchForDeleted)
+{
+ HANDLE hContact, hItem;
+
+ for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); hContact; hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0))
+ {
+ hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (!hItem) continue;
+
+ if (CallService(MS_SPAMFILTER_CONTACT_ISSPAMMER, (WPARAM)hContact, 0))
+ {
+ if (bWatchForDeleted)
+ if (DBGetContactSettingByte(hContact, "CList", "Delete", 0)) {
+ Spammers_SetListIcon(hwndList, hItem, 1);
+ BOX("wathce ditem found");
+ continue;
+ }
+ if (bForce || (Spammers_GetListIcon(hwndList, hItem) == -1))
+ Spammers_SetListIcon(hwndList, hItem, iColumn);
+ } else {
+ SendMessage(hwndList, CLM_DELETEITEM, (WPARAM)hItem, 0); // Remove no-spammers
+ }
+ }
+}
+
+
+static int ResizeProcSpammersInfo(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL *urc)
+{
+ switch(urc->wId)
+ {
+ case IDC_TEXT_DESCRIPTION:
+ return RD_ANCHORY_TOP|RD_ANCHORX_WIDTH;
+
+ case IDC_CLIST:
+ return RD_ANCHORY_HEIGHT|RD_ANCHORX_WIDTH;
+
+ case IDC_GROUP:
+ case IDC_CHECKBOX_GROUP:
+ case IDC_CHECKBOX_HIDE:
+ case IDC_EDITBOX_GROUP:
+ return RD_ANCHORY_BOTTOM|RD_ANCHORX_WIDTH;
+
+ case IDC_ICON_SPAM:
+ case IDC_TEXT_SPAM:
+ case IDC_ICON_NORMAL:
+ case IDC_TEXT_NORMAL:
+ case IDC_ICON_DELETE:
+ case IDC_TEXT_DELETE:
+ return RD_ANCHORY_TOP|RD_ANCHORX_RIGHT;
+
+ //case IDOK:
+ //case IDC_BUTTON_RESET:
+ //case IDC_SCROLLBAR_SIZEGRIP:
+ default:
+ return RD_ANCHORY_BOTTOM|RD_ANCHORX_RIGHT;
+ }
+}
+
+BOOL CALLBACK DlgProcSpammersInfo(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ HIMAGELIST hIml;
+ HICON hSpam, hNormal, hDelete, hDots;
+
+ hwndSpammersInfo = hwndDlg;
+
+ // Translate dialog first
+ TranslateDialogDefault(hwndDlg);
+
+ // Init set/unset icons (Loading icons out of miranda32.exe)
+ hIml = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), (IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK, 4, 0);
+ hSpam = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(212), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ ImageList_AddIcon(hIml, hSpam);
+ hDelete = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(175), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ ImageList_AddIcon(hIml, hDelete);
+ hNormal = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(213), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ ImageList_AddIcon(hIml, hNormal);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hIml);
+ hDots = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(211), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ ImageList_AddIcon(hIml, hDots);
+
+ Spammers_ResetListOptions(GetDlgItem(hwndDlg, IDC_CLIST));
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRACOLUMNS, (WPARAM)3, 0);
+ Spammers_SetAllListIcons(GetDlgItem(hwndDlg, IDC_CLIST), 0, TRUE, TRUE);
+
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ICON_SPAM), GWLP_USERDATA, (LONG_PTR)0);
+ SendDlgItemMessage(hwndDlg, IDC_ICON_SPAM, STM_SETICON, (WPARAM)hSpam, 0);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ICON_DELETE), GWLP_USERDATA, (LONG_PTR)1);
+ SendDlgItemMessage(hwndDlg, IDC_ICON_DELETE, STM_SETICON, (WPARAM)hDelete, 0);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ICON_NORMAL), GWLP_USERDATA, (LONG_PTR)2);
+ SendDlgItemMessage(hwndDlg, IDC_ICON_NORMAL, STM_SETICON, (WPARAM)hNormal, 0);
+
+ // New window icon
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hSpam);
+
+ // Make top text
+ {
+ HFONT hBoldFont;
+ LOGFONT lf;
+
+ GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0), sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ hBoldFont = CreateFontIndirect(&lf);
+
+ SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ }
+
+ // Spammers group
+ {
+ DBVARIANT dbv;
+
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUPNAME, &dbv) == 0) {
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_GROUP, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ SetDlgItemText(hwndDlg, IDC_EDITBOX_GROUP, DEFAULT_SETTING_MOVETOGROUPNAME);
+ }
+
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_GROUP, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUP, (BYTE)DEFAULT_SETTING_MOVETOGROUP) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHECKBOX_HIDE, (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_HIDEFROMCLIST, (BYTE)DEFAULT_SETTING_HIDEFROMCLIST) ? BST_CHECKED : BST_UNCHECKED));
+ }
+
+ SendMessage(hwndDlg, SFM_ENABLE_SUBCTRLS, 0, 0);
+
+ // Restore dlg position (at the end, so the dialog does not get shown early)
+ Utils_RestoreWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_SPAMMERS_DIALOGPOSITION);
+ // Make sure the dialog is not moved out of sight
+ SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0); //simulate message
+
+ // SetFocus (SetFocus() is not allowed in Dialogs)
+ SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), (LPARAM)TRUE);
+ return FALSE;
+ }
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pnmh = (LPNMHDR)lParam;
+
+ switch (pnmh->idFrom)
+ {
+ case IDC_CLIST:
+ {
+ switch (pnmh->code)
+ {
+ case CLN_NEWCONTACT:
+ case CLN_CONTACTMOVED:
+ case CLN_LISTREBUILT:
+ Spammers_SetAllListIcons(pnmh->hwndFrom, 0, FALSE, TRUE);
+ return TRUE;
+
+ case CLN_OPTIONSCHANGED:
+ Spammers_ResetListOptions(pnmh->hwndFrom);
+ return TRUE;
+
+ case NM_CLICK:
+ {
+ HANDLE hItem;
+ NMCLISTCONTROL* nm = (NMCLISTCONTROL*)lParam;
+ DWORD hitFlags;
+
+ if (nm->iColumn < 0) break;
+ hItem = (HANDLE)SendMessage(pnmh->hwndFrom, CLM_HITTEST, (WPARAM)&hitFlags, MAKELPARAM(nm->pt.x, nm->pt.y));
+ if (hItem == NULL) break;
+ if (!(hitFlags&CLCHT_ONITEMEXTRA)) break;
+
+ Spammers_SetListIcon(pnmh->hwndFrom, hItem, nm->iColumn);
+ return TRUE;
+ }
+ }
+
+ break;
+ }
+
+ }
+ break;
+ }
+
+ case SFM_REFRESH_SPAMMERS:
+ {
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_AUTOREBUILD, 0, 0);
+ return TRUE;
+ }
+
+ case SFM_ENABLE_SUBCTRLS:
+ {
+ BOOL bStatus = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_GROUP) == BST_CHECKED);
+ EnableDlgItem(hwndDlg, IDC_EDITBOX_GROUP, bStatus);
+ return TRUE;
+ }
+
+ case WM_CLOSE:
+ {
+ // Different method of closing the window depending on if the window
+ // was created modal or not
+ if (!GetParent(hwndDlg))
+ DestroyWindow(hwndDlg);
+ else
+ EndDialog(hwndDlg, IDCANCEL);
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_ICON_SPAM:
+ case IDC_ICON_NORMAL:
+ case IDC_ICON_DELETE:
+ {
+ if (HIWORD(wParam) == STN_CLICKED)
+ {
+ Spammers_SetAllListIcons(GetDlgItem(hwndDlg, IDC_CLIST), (int)GetWindowLongPtr(GetDlgItem(hwndDlg, LOWORD(wParam)), GWLP_USERDATA), TRUE, FALSE);
+ return TRUE;
+ }
+ break;
+ }
+
+ case IDC_CHECKBOX_GROUP:
+ {
+ SendMessage(hwndDlg, SFM_ENABLE_SUBCTRLS, 0, 0);
+ return TRUE;
+ }
+
+ case IDOK:
+ {
+ HANDLE hContact, hItem;
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_CLIST);
+
+ EnableDlgItem(hwndDlg, IDOK, FALSE);
+
+ // Spammers group
+ {
+ HWND hwndEdit = GetDlgItem(hwndDlg, IDC_EDITBOX_GROUP);
+ int iTextLen = GetWindowTextLength(hwndEdit);
+ WCHAR* pszText = (WCHAR*)mir_alloc((iTextLen+1)*sizeof(WCHAR));
+ BOOL bUseGroup, bGroupCreated;
+ DBVARIANT dbv;
+
+ // Get entered text
+ if (pszText)
+ {
+ if (GetWindowText(hwndEdit, pszText, iTextLen+1) == 0)
+ pszText[0] = _T('\0');
+
+ // Save text
+ if (lstrlen(pszText) > 0) {
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUPNAME, pszText);
+ bUseGroup = (IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_GROUP) == BST_CHECKED);
+ } else {
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUPNAME, DEFAULT_SETTING_MOVETOGROUPNAME);
+ bUseGroup = FALSE;
+ }
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUP, (BYTE)bUseGroup);
+ } else {
+ bUseGroup = FALSE;
+ }
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_HIDEFROMCLIST, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CHECKBOX_HIDE) == BST_CHECKED));
+
+ // Remove previous group (if changed)
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_MOVETOGROUPNAME, &dbv) == 0)
+ {
+ // Show remove group UI
+ if (StrCmp(dbv.ptszVal, pszText) != 0)
+ RemoveContactListGroup(dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+
+ // Move all spammers to this group
+ bGroupCreated = FALSE;
+ for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); hContact; hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0))
+ {
+ hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (!hItem) continue;
+
+ switch (Spammers_GetListIcon(hwndList, hItem))
+ {
+ case 1: // delete
+ {
+ int status;
+ char* pszProto;
+
+ // Check if protocol uses server side lists
+ pszProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (pszProto)
+ if ((DWORD)CallProtoService(pszProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_SERVERCLIST)
+ {
+ status = CallProtoService(pszProto, PS_GETSTATUS, 0, 0);
+ if (status == ID_STATUS_OFFLINE || (status >= ID_STATUS_CONNECTING && status < ID_STATUS_CONNECTING + MAX_CONNECT_RETRIES))
+ {
+ DBWriteContactSettingByte(hContact, "CList", "Delete", 1);
+ break;
+ }
+ }
+
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+ break;
+ }
+ case 2: // normal
+ DBDeleteContactSetting(hContact, "CList", "Delete");
+ CallService(MS_SPAMFILTER_CONTACT_UNSETSPAMMER, (WPARAM)hContact, 0);
+ break;
+
+ case 0: // spammer
+ if (bUseGroup && !bGroupCreated) {
+ CreateContactListGroup(pszText);
+ bGroupCreated = TRUE;
+ }
+ if (bUseGroup) {
+ if (DBGetContactSettingTString(hContact, "CList", "Group", &dbv) == 0)
+ {
+ if (StrCmp(dbv.ptszVal, pszText) != 0)
+ DBWriteContactSettingTString(hContact, "CList", "Group", pszText);
+ DBFreeVariant(&dbv);
+ }
+ } else {
+ DBDeleteContactSetting(hContact, "CList", "Group");
+ }
+ DBDeleteContactSetting(hContact, "CList", "Delete");
+ break;
+ }
+ }
+
+ // Display remove group window
+ //if (!bUseGroup || !bGroupCreated)
+ // RemoveContactListGroup(pszText);
+
+ if (pszText) mir_free(pszText);
+ }
+
+ // fall through
+ }
+
+ case IDCANCEL:
+ // WM_CLOSE is transformed into an IDCANCEL by dialog manager
+ {
+ // Different method of closing the window depending on if the window
+ // was created modal or not
+ if (!GetParent(hwndDlg))
+ DestroyWindow(hwndDlg);
+ else
+ EndDialog(hwndDlg, LOWORD(wParam));
+
+ return TRUE;
+ }
+
+ }
+
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ hwndSpammersInfo = NULL;
+
+ ImageList_Destroy((HIMAGELIST)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETEXTRAIMAGELIST, 0, 0));
+
+ // Free font
+ DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0));
+
+ // Save dlg position
+ Utils_SaveWindowPosition(hwndDlg, NULL, DB_MODULE_NAME, DB_SETTING_SPAMMERS_DIALOGPOSITION);
+ return TRUE;
+ }
+
+ case WM_SIZE:
+ {
+ UTILRESIZEDIALOG urd;
+
+ ZeroMemory(&urd, sizeof(urd));
+ urd.cbSize = sizeof(urd);
+ urd.hInstance = hInstance;
+ urd.hwndDlg = hwndDlg;
+ urd.lpTemplate = MAKEINTRESOURCEA(IDD_INFO_SPAMMERS);
+ urd.pfnResizer = ResizeProcSpammersInfo;
+
+ CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd);
+ return TRUE;
+ }
+
+ case WM_GETMINMAXINFO:
+ {
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = 370;
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = 220;
+ return TRUE;
+ }
+
+ }
+
+ return FALSE;
+}
+
+
+// -- ListBox helper functions
+
+LRESULT CALLBACK WordsListBoxSubclassProc(HWND hwndListBox, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int iButtonAdd;
+ int iButtonDelete;
+
+ // Get associated list box control id
+ switch (GetDlgCtrlID(hwndListBox))
+ {
+ case IDC_LISTBOX_CUSTOMIZEDBADWORDS:
+ {
+ iButtonAdd = IDC_BUTTON_ADDBADWORD;
+ iButtonDelete = IDC_BUTTON_DELETEBADWORD;
+ break;
+ }
+
+ case IDC_LISTBOX_CUSTOMIZEDGOODWORDS:
+ {
+ iButtonAdd = IDC_BUTTON_ADDGOODWORD;
+ iButtonDelete = IDC_BUTTON_DELETEGOODWORD;
+ break;
+ }
+
+ case IDC_LISTBOX_CUSTOMIZEDWORDS:
+ {
+ iButtonAdd = IDC_BUTTON_ADDWORD;
+ iButtonDelete = IDC_BUTTON_DELETEWORD;
+ break;
+ }
+
+ default:
+ {
+ iButtonAdd = -1;
+ iButtonDelete = -1;
+ break;
+ }
+ }
+
+ switch (uMsg)
+ {
+ case LB_INSERTSTRING:
+ case LB_ADDSTRING:
+ {
+ // Set horizontal extent
+ int iHorExt;
+
+ if (!lParam) break;
+
+ iHorExt = GetCtrlTextExtent(hwndListBox, (WCHAR*)lParam, TRUE);
+
+ if (iHorExt > SendMessage(hwndListBox, LB_GETHORIZONTALEXTENT, 0, 0))
+ PostMessage(hwndListBox, LB_SETHORIZONTALEXTENT, (LPARAM)iHorExt, 0);
+
+ break;
+ }
+
+ case LB_DELETESTRING:
+ {
+ // Set horizontal extent
+ int i;
+ int iLen, iHorExt = 0;
+ int iItemCount = (int)SendMessage(hwndListBox, LB_GETCOUNT, 0, 0);
+ WCHAR* pszItemText;
+
+ for (i=0; i<iItemCount; i++)
+ {
+ // Ignore the item that is to be deleted
+ if (i == (int)wParam) continue;
+
+ iLen = (int)SendMessage(hwndListBox, LB_GETTEXTLEN, (WPARAM)i, 0);
+ if (iLen < 0) continue;
+
+ pszItemText = (WCHAR*)mir_alloc((iLen+1)*sizeof(WCHAR));
+ if (!pszItemText) continue;
+
+ if (SendMessage(hwndListBox, LB_GETTEXT, (WPARAM)i, (LPARAM)pszItemText) == LB_ERR)
+ *pszItemText = _T('\0');
+
+ iHorExt = max(iHorExt, GetCtrlTextExtent(hwndListBox, pszItemText, TRUE));
+ mir_free(pszItemText);
+ }
+
+ if (iHorExt != SendMessage(hwndListBox, LB_GETHORIZONTALEXTENT, 0, 0))
+ PostMessage(hwndListBox, LB_SETHORIZONTALEXTENT, (WPARAM)iHorExt, 0);
+
+ break;
+ }
+
+ case LB_RESETCONTENT:
+ {
+ // Reset horizontal extent
+ PostMessage(hwndListBox, LB_SETHORIZONTALEXTENT, 0, 0);
+
+ break;
+ }
+
+ case LB_SETHORIZONTALEXTENT:
+ {
+ RECT rc;
+ BOOL bShowHScroll;
+
+ // Do not show horizontal scrollbars if not needed
+ if (GetClientRect(hwndListBox, &rc))
+ bShowHScroll = ((int)wParam > (rc.right-rc.left));
+ else
+ bShowHScroll = TRUE;
+
+ // Show/Hide horizontal scrollbars; DISABLENOSCROLL does not work correctly
+ ShowScrollBar(hwndListBox, SB_HORZ, bShowHScroll);
+
+ // Scroll to left if scrollbar hidden
+ if (!bShowHScroll)
+ PostMessage(hwndListBox, WM_HSCROLL, SB_LEFT, 0);
+
+ break;
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ HMENU hMenu, hContextMenu;
+ int iHoveredItem;
+ POINT pt;
+ POINTSTOPOINT(pt, MAKEPOINTS(lParam));
+
+ // Menu started by keyboard shortcut
+ if ((pt.x == -1) && (pt.y == -1))
+ {
+ RECT rc;
+
+ iHoveredItem = SendMessage(hwndListBox, LB_GETCURSEL, 0, 0);
+
+ // Get item pos
+ if (SendMessage(hwndListBox, LB_GETITEMRECT, (WPARAM)iHoveredItem, (LPARAM)&rc) != LB_ERR)
+ if (!GetWindowRect(hwndListBox, &rc))
+ rc.left = rc.top = rc.right = rc.bottom = 0;
+
+ // Position it in the middle of the rect
+ pt.x = rc.left + (int)((rc.right-rc.left)/2);
+ pt.y = rc.top + (int)((rc.bottom-rc.top)/2);
+
+ } else {
+ // LBItemFromPt returns an item if no item is in list
+ if (SendMessage(hwndListBox, LB_GETCOUNT, 0, 0) == 0)
+ iHoveredItem = LB_ERR;
+ else
+ iHoveredItem = LBItemFromPt(hwndListBox, pt, FALSE);
+
+ // Select list box item
+ if (iHoveredItem >= 0)
+ SendMessage(hwndListBox, LB_SETCURSEL, iHoveredItem, 0);
+ }
+
+ // Context menu
+ hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_CONTEXT));
+ hContextMenu = GetSubMenu(hMenu, 0);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hContextMenu, 0);
+
+ // If user did not click on a list item
+ if (iHoveredItem < 0)
+ RemoveMenu(hContextMenu, ID_MENU_DELETE, MF_BYCOMMAND);
+
+ switch (TrackPopupMenuEx(hContextMenu, TPM_RETURNCMD|TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, hwndListBox, NULL))
+ {
+ case ID_MENU_DELETE:
+ {
+ // Simulate 'Delete' button
+ if (iButtonDelete >= 0)
+ SendMessage(GetParent(hwndListBox), WM_COMMAND, MAKEWPARAM(iButtonDelete, BN_CLICKED), (LPARAM)GetDlgItem(GetParent(hwndListBox), iButtonDelete));
+ break;
+ }
+
+ case ID_MENU_ADD:
+ {
+ // Simulate 'Add' button
+ if (iButtonAdd >= 0)
+ SendMessage(GetParent(hwndListBox), WM_COMMAND, MAKEWPARAM(iButtonAdd, BN_CLICKED), (LPARAM)GetDlgItem(GetParent(hwndListBox), iButtonAdd));
+ break;
+ }
+ }
+
+ // Destroy context menu
+ if (hMenu) DestroyMenu(hMenu);
+
+ return 0;
+ }
+
+ case WM_KEYDOWN:
+ {
+ int iSelectedItem = SendMessage(hwndListBox, LB_GETCURSEL, 0, 0);
+
+ if (iSelectedItem >= 0)
+ {
+ switch (wParam)
+ {
+ case VK_BACK:
+ case VK_SUBTRACT:
+ case VK_DELETE:
+ {
+ // Simulate 'Delete' button
+ if (iButtonDelete >= 0)
+ SendMessage(GetParent(hwndListBox), WM_COMMAND, MAKEWPARAM(iButtonDelete, BN_CLICKED), (LPARAM)GetDlgItem(GetParent(hwndListBox), iButtonDelete));
+
+ return TRUE;
+ }
+
+ case VK_SPACE:
+ case VK_ADD:
+ case VK_INSERT:
+ {
+ // Simulate 'Add' button
+ if (iButtonAdd >= 0)
+ SendMessage(GetParent(hwndListBox), WM_COMMAND, MAKEWPARAM(iButtonAdd, BN_CLICKED), (LPARAM)GetDlgItem(GetParent(hwndListBox), iButtonAdd));
+
+ return TRUE;
+ }
+
+ //case VK_PRIOR:
+ case VK_UP:
+ {
+ // Select one entry up if not first entry
+ if (iSelectedItem > 0)
+ SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)iSelectedItem-1, 0);
+
+ return TRUE;
+ }
+
+ //case VK_NEXT:
+ case VK_DOWN:
+ {
+ // Select one entry down
+ SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)iSelectedItem+1, 0);
+
+ return TRUE;
+ }
+
+ } // switch wParam
+
+ }
+
+ return FALSE;
+ }
+
+ case WM_GETDLGCODE:
+ {
+ return DLGC_WANTALLKEYS;
+ }
+
+ } //switch uMsg
+
+ return CallWindowProc((WNDPROC)GetWindowLongPtr(hwndListBox, GWLP_USERDATA), hwndListBox, uMsg, wParam, lParam);
+}
+
+
+BOOL CALLBACK DlgProcWordsListBoxAddItem(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ // Get passed data
+ struct WORDSLISTBOXADDITEMPARAMS* pwlbaip = (struct WORDSLISTBOXADDITEMPARAMS*)lParam;
+
+ SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pwlbaip);
+
+ // Translate dialog
+ TranslateDialogDefault(hwndDlg);
+
+ // Set text
+ SetWindowText(hwndDlg, pwlbaip->pszTitle);
+
+ // Make button and caption use message box font
+ {
+ NONCLIENTMETRICS ncm;
+ HFONT hBoldFont;
+
+ ZeroMemory(&ncm, sizeof(ncm));
+ ncm.cbSize = sizeof(ncm);
+ if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0))
+ {
+ hBoldFont = CreateFontIndirect(&ncm.lfMessageFont);
+
+ SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ //SendDlgItemMessage(hwndDlg, IDOK, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ //SendDlgItemMessage(hwndDlg, IDCANCEL, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TEXT_QUICKHELP, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TEXT_HELPNESTED, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ }
+ }
+
+ // Show/Hide RegExp hint and help
+ // More info about Regular Expressions: http://perldoc.perl.org/perlrequick.html
+ {
+ // Set icon and resize button
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_BUTTON_REGEXP), NULL, 0, 0, 20, 20, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+ SendDlgItemMessage(hwndDlg, IDC_BUTTON_REGEXP, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)LoadSystemIcon(IDB_STD_SMALL_COLOR, STD_HELP));
+ PostMessage(GetDlgItem(hwndDlg, IDC_BUTTON_REGEXP), BUTTONADDTOOLTIP, (WPARAM)Translate("&How to use Regular Expressions"), 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_BUTTON_REGEXP), BUTTONSETASFLATBTN, 0, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_BUTTON_REGEXP), BUTTONSETASPUSHBTN, 0, 0);
+
+ // Do not show hint/help if RegExp DLL not available
+ if (!RegExpEnabled())
+ {
+ RECT rcEdit, rcBtn;
+
+ SetDlgItemText(hwndDlg, IDC_TEXT_REGEXP, TranslateT("(Regular Expressions disabled)"));
+ ShowDlgItem(hwndDlg, IDC_BUTTON_REGEXP, FALSE);
+
+ if (GetWindowRect(GetDlgItem(hwndDlg, IDC_EDITBOX_NEWITEM), &rcEdit))
+ if (GetWindowRect(GetDlgItem(hwndDlg, IDC_BUTTON_REGEXP), &rcBtn))
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_EDITBOX_NEWITEM), NULL, 0, 0, (rcBtn.right-rcEdit.left), (rcEdit.bottom-rcEdit.top), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+ }
+ }
+
+ // Position/Resize window
+ {
+ RECT rcWin, rcSep;
+ int iHeight, iWidth;
+
+ // Get sizes
+ if ( GetWindowRect(hwndDlg, &rcWin) &&
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_RECT_SEPARATOR), &rcSep) )
+ {
+ iHeight = rcSep.top-rcWin.top + (int)((rcSep.bottom-rcSep.top)/2);
+ iWidth = rcWin.right-rcWin.left;
+
+ // Remember normal height
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_RECT_SEPARATOR), GWLP_USERDATA, (LONG_PTR)(rcWin.bottom-rcWin.top));
+
+ // Hide separator
+ ShowDlgItem(hwndDlg, IDC_RECT_SEPARATOR, FALSE);
+
+ } else {
+ iHeight = 0;
+ iWidth = 0;
+ }
+
+ // Position the window (and hide RegExp help initially)
+ SetWindowPos(hwndDlg, NULL, pwlbaip->ptPos.x, pwlbaip->ptPos.y, iWidth, iHeight, (((iHeight==0)||(iWidth==0))?SWP_NOSIZE:0)|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+
+ // Make sure the dialog is not moved out of sight
+ SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
+ }
+
+ // SetFocus (SetFocus() is not allowed in Dialogs)
+ SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_EDITBOX_NEWITEM), (LPARAM)TRUE);
+ return FALSE;
+ }
+
+ case WM_SETTINGCHANGE:
+ {
+ NONCLIENTMETRICS ncm;
+ HFONT hBoldFont;
+
+ // Free old message box font
+ DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0));
+
+ // Update message box font
+ ZeroMemory(&ncm, sizeof(ncm));
+ ncm.cbSize = sizeof(ncm);
+ if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0))
+ {
+ hBoldFont = CreateFontIndirect(&ncm.lfMessageFont);
+
+ SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ //SendDlgItemMessage(hwndDlg, IDOK, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ //SendDlgItemMessage(hwndDlg, IDCANCEL, WM_SETFONT, (WPARAM)hBoldFont, 0);
+ }
+ return TRUE;
+ }
+
+ case WM_DESTROY:
+ {
+ // Destroy help icon
+ DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_BUTTON_REGEXP, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0));
+
+ // Free message box font
+ DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_DESCRIPTION, WM_GETFONT, 0, 0));
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_BUTTON_REGEXP:
+ {
+ // Show/Hide RegExp help part
+ RECT rcWin, rcSep;
+ int iHeight, iWidth;
+
+ if (GetWindowRect(hwndDlg, &rcWin))
+ {
+ iWidth = rcWin.right-rcWin.left;
+
+ // Hide/Show help
+ if (!IsDlgButtonChecked(hwndDlg, IDC_BUTTON_REGEXP))
+ {
+ if (GetWindowRect(GetDlgItem(hwndDlg, IDC_RECT_SEPARATOR), &rcSep))
+ {
+ iHeight = rcSep.top-rcWin.top + (int)((rcSep.bottom-rcSep.top)/2);
+
+ // Position the window
+ ShowDlgItem(hwndDlg, IDC_RECT_SEPARATOR, FALSE);
+ SetWindowPos(hwndDlg, NULL, 0, 0, iWidth, iHeight, SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE);
+ }
+ } else {
+ iHeight = (int)GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_RECT_SEPARATOR), GWLP_USERDATA);
+
+ // Position the window
+ SetWindowPos(hwndDlg, NULL, 0, 0, iWidth, iHeight, SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE);
+ ShowDlgItem(hwndDlg, IDC_RECT_SEPARATOR, TRUE);
+ }
+ }
+
+ // Make sure the dialog is not enlarged out of sight
+ SendMessage(hwndDlg, DM_REPOSITION, 0, 0);
+
+ return TRUE;
+ }
+
+ case IDOK:
+ {
+ struct WORDSLISTBOXADDITEMPARAMS* pwlbaip;
+ HWND hwndEdit;
+ int iNewItemSize;
+
+ pwlbaip = (struct WORDSLISTBOXADDITEMPARAMS*)GetWindowLongPtr(hwndDlg, DWLP_USER);
+
+ // Get entered text
+ if (pwlbaip)
+ {
+ hwndEdit = GetDlgItem(hwndDlg, IDC_EDITBOX_NEWITEM);
+ iNewItemSize = GetWindowTextLength(hwndEdit)+1;
+ pwlbaip->pszNewItem = (WCHAR*)mir_alloc((iNewItemSize)*sizeof(WCHAR));
+
+ if (pwlbaip->pszNewItem)
+ if (GetWindowText(hwndEdit, pwlbaip->pszNewItem, iNewItemSize) == 0) // GetWindowText takes the size not the len of the string
+ *pwlbaip->pszNewItem = _T('\0');
+ }
+
+ // fall through
+ }
+
+ case IDCANCEL:
+ // WM_CLOSE is transformed into an IDCANCEL by dialog manager
+ {
+ EndDialog(hwndDlg, LOWORD(wParam));
+ return TRUE;
+ }
+
+ case IDC_EDITBOX_NEWITEM:
+ {
+ switch (HIWORD(wParam))
+ {
+ case EN_CHANGE:
+ {
+ HWND hwndEdit = GetDlgItem(hwndDlg, IDC_EDITBOX_NEWITEM);
+ int iNewItemLen = GetWindowTextLength(hwndEdit);
+ WCHAR* pszNewItem = (WCHAR*)mir_alloc((iNewItemLen+1)*sizeof(WCHAR));
+
+ if (pszNewItem)
+ {
+ // Get entered text
+ if (GetWindowText(hwndEdit, pszNewItem, iNewItemLen+1) == 0)
+ pszNewItem[0] = _T('\0');
+
+ // Check if OK button can be released
+ EnableDlgItem(hwndDlg, IDOK, (lstrlen(pszNewItem) > 0));
+
+ mir_free(pszNewItem);
+ }
+
+ return TRUE;
+ }
+ } // switch HIWORD(wParam)
+ break;
+ }
+
+ } // switch wParam
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+void WordsListBoxInit(HWND hwndDlg, int iIDListBox, int iIDAddButton, int iIDDeleteButton, STRINGLIST* pslContents, const char* pszAddTooltip, const char* pszDeleteTooltip)
+{
+ HWND hwndListBox = GetDlgItem(hwndDlg, iIDListBox);
+ HWND hwndAddButton = GetDlgItem(hwndDlg, iIDAddButton);
+ HWND hwndDeleteButton = GetDlgItem(hwndDlg, iIDDeleteButton);
+ HICON hAddIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_ADD_BUTTON), IMAGE_ICON, 0, 0, LR_SHARED);
+ HICON hDeleteIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DELETE_BUTTON), IMAGE_ICON, 0, 0, LR_SHARED);
+
+ // Subclass to get key strokes/contextmenu/horizontal extent
+ SetWindowLongPtr(hwndListBox, GWLP_USERDATA, SetWindowLongPtr(hwndListBox, GWLP_WNDPROC, (LONG_PTR)WordsListBoxSubclassProc));
+
+ // Init drag-drop support
+ MakeDragList(hwndListBox);
+
+ // Insert contents
+ SLAssignToListBoxCtrl(pslContents, hwndListBox);
+
+ // Select first item
+ SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)0, 0);
+
+ // Init add button
+ SetWindowPos(hwndAddButton, NULL, 0, 0, 20, 20, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+ SendMessage(hwndAddButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hAddIcon);
+ PostMessage(hwndAddButton, BUTTONADDTOOLTIP, (WPARAM)pszAddTooltip, 0);
+ SendMessage(hwndAddButton, BUTTONSETASFLATBTN, 0, 0);
+
+ // Init delete button
+ SetWindowPos(hwndDeleteButton, NULL, 0, 0, 20, 20, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+ SendMessage(hwndDeleteButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hDeleteIcon);
+ PostMessage(hwndDeleteButton, BUTTONADDTOOLTIP, (WPARAM)pszDeleteTooltip, 0);
+ SendMessage(hwndDeleteButton, BUTTONSETASFLATBTN, 0, 0);
+}
+
+
+BOOL WordsListBoxDragDrop(HWND hwndDlg, int iIDListBox, UINT uMsg, LPARAM lParam, BOOL bAllowCopy)
+{
+ // This function needs to be called in the default handler of the dialog
+
+ if (uMsg == RegisterWindowMessage(DRAGLISTMSGSTRING))
+ {
+ DRAGLISTINFO* pdli = (DRAGLISTINFO*)lParam;
+
+ if (GetDlgItem(hwndDlg, iIDListBox) == pdli->hWnd)
+ {
+ int iHoveredItem = LBItemFromPt(pdli->hWnd, pdli->ptCursor, (pdli->uNotification==DL_DRAGGING));
+
+ switch (pdli->uNotification)
+ {
+ case DL_BEGINDRAG:
+ {
+ // Remember start position
+ SetProp(pdli->hWnd, DRAGLISTMSGSTRING, (HANDLE)iHoveredItem);
+
+ // Allow/Disallow drag
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)(BOOL)(iHoveredItem >= 0));
+ return TRUE;
+ }
+
+ case DL_DRAGGING:
+ {
+ // LBItemFromPt returns an item if no item is in list
+ if (SendMessage(pdli->hWnd, LB_GETCOUNT, 0, 0) <= 1)
+ iHoveredItem = LB_ERR;
+
+ if (iHoveredItem >= 0)
+ {
+ BOOL bMakeCopy = ((bAllowCopy) && (GetAsyncKeyState(VK_CONTROL) < 0));
+
+ // Show insertion mark
+ DrawInsert(hwndDlg, pdli->hWnd, iHoveredItem);
+
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)(bMakeCopy?DL_COPYCURSOR:DL_MOVECURSOR));
+
+ } else {
+ // Cursor moved to impossible position
+ DrawInsert(hwndDlg, pdli->hWnd, LB_ERR);
+
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)DL_STOPCURSOR);
+ }
+
+ return TRUE;
+ }
+
+ case DL_DROPPED:
+ {
+ int iDragItem = (int)GetProp(pdli->hWnd, DRAGLISTMSGSTRING);
+
+ if ((iHoveredItem >= 0 ) && (iHoveredItem != iDragItem) && (iHoveredItem != iDragItem+1))
+ {
+ LPARAM lParamItemData;
+ int iLenItem;
+ WCHAR* pszItemText;
+
+ iLenItem = (int)SendMessage(pdli->hWnd, LB_GETTEXTLEN, (WPARAM)iDragItem, 0);
+ if (iLenItem == LB_ERR) iLenItem = 0;
+ pszItemText = (WCHAR*)mir_alloc((iLenItem+1)*sizeof(WCHAR));
+
+ if (pszItemText)
+ {
+ if (SendMessage(pdli->hWnd, LB_GETTEXT, (WPARAM)iDragItem, (LPARAM)pszItemText) != LB_ERR)
+ {
+ lParamItemData = (LPARAM)SendMessage(pdli->hWnd, LB_GETITEMDATA, (WPARAM)iDragItem, 0);
+
+ // Make copy of item
+ iHoveredItem = (int)SendMessage(pdli->hWnd, LB_INSERTSTRING, (WPARAM)iHoveredItem, (LPARAM)pszItemText);
+
+ if (iHoveredItem >= 0)
+ {
+ BOOL bMakeCopy = ((bAllowCopy) && (GetAsyncKeyState(VK_CONTROL) < 0));
+
+ SendMessage(pdli->hWnd, LB_SETITEMDATA, (WPARAM)iHoveredItem, (LPARAM)lParamItemData);
+
+ // Delete old item if moving
+ if (!bMakeCopy)
+ {
+ if (iHoveredItem < iDragItem)
+ iDragItem++;
+
+ SendMessage(pdli->hWnd, LB_DELETESTRING, (WPARAM)iDragItem, 0);
+ }
+
+ // Set current selection
+ SendMessage(pdli->hWnd, LB_SETCURSEL, (WPARAM)iHoveredItem, 0);
+ }
+ }
+
+ mir_free(pszItemText);
+ }
+ }
+
+ // fall trough
+ }
+
+ case DL_CANCELDRAG:
+ {
+ // Remove insertion mark
+ DrawInsert(hwndDlg, pdli->hWnd, LB_ERR);
+
+ // Remove buffer data
+ RemoveProp(pdli->hWnd, DRAGLISTMSGSTRING);
+ return TRUE;
+ }
+
+ } // switch
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOL WordsListBoxAddItem(HWND hwndDlg, int iIDListBox, STRINGLIST* pslOtherContents, const WCHAR* pszMsgTitle, const WCHAR* pszMsgTextInList, const WCHAR* pszMsgTextInOther, int iIDButtonDelete)
+{
+ HWND hwndListBox = GetDlgItem(hwndDlg, iIDListBox);
+ BOOL bDoAdd;
+ struct WORDSLISTBOXADDITEMPARAMS wlbaip;
+ RECT rc;
+
+ if (!hwndListBox) return FALSE;
+
+ if (GetWindowRect(hwndListBox, &rc)) {
+ wlbaip.ptPos.x = rc.left-30;
+ wlbaip.ptPos.y = rc.top-5;
+ } else {
+ wlbaip.ptPos.x = 0;
+ wlbaip.ptPos.y = 0;
+ }
+
+ wlbaip.pszTitle = (WCHAR*)pszMsgTitle;
+
+ // Show dialog
+ bDoAdd = (DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_LISTBOX_ADD_ITEM), hwndDlg, DlgProcWordsListBoxAddItem, (LPARAM)&wlbaip) == IDOK);
+ if (bDoAdd)
+ {
+ // Check if regular expression is valid (if any)
+ if (!wlbaip.pszNewItem || !ValidateRegExp(wlbaip.pszNewItem))
+ {
+ WCHAR* pszBoxTextFmt = TranslateT("The entered phrase \"%s\" consists of a Regular Expression containing a syntax error!\r\n\r\nAdding an malformed Regular Expression will cause the filter\r\nto treat the expression as a normal phrase.\r\n\r\nShall the malformed Regular Expression be added anyway?");
+ WCHAR* pszBoxText = (WCHAR*)mir_alloc((lstrlen(pszBoxTextFmt)+lstrlen(wlbaip.pszNewItem)+1)*sizeof(WCHAR));
+ bDoAdd = FALSE;
+
+ if (pszBoxTextFmt && pszBoxText)
+ {
+ mir_sntprintf(pszBoxText, (lstrlen(pszBoxTextFmt)+lstrlen(wlbaip.pszNewItem)+1), pszBoxTextFmt, wlbaip.pszNewItem);
+
+ // Show message box that the item is malformed
+ if (!Miranda_Terminated())
+ bDoAdd = (MessageBoxEx(hwndDlg, pszBoxText, TranslateT("Syntax Error in Regular Expression"), MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2, LANGIDFROMLCID(GetThreadLocale())) == IDYES);
+ }
+
+ if (pszBoxTextFmt) mir_free(pszBoxTextFmt);
+ if (pszBoxText) mir_free(pszBoxText);
+
+ } else {
+ bDoAdd = TRUE;
+ }
+
+ if (bDoAdd)
+ {
+ int iIndexIfFound;
+
+ // Look for same item in list (not case sensitive)
+ iIndexIfFound = SendMessage(hwndListBox, LB_FINDSTRINGEXACT, 0, (LPARAM)wlbaip.pszNewItem);
+ if (iIndexIfFound >= 0)
+ {
+ WCHAR* pszBoxText = (WCHAR*)mir_alloc((lstrlen(pszMsgTextInList)+lstrlen(wlbaip.pszNewItem)+1)*sizeof(WCHAR));
+ bDoAdd = FALSE;
+
+ if (pszBoxText)
+ {
+ mir_sntprintf(pszBoxText, (lstrlen(pszMsgTextInList) + lstrlen(wlbaip.pszNewItem) + 1), pszMsgTextInList, wlbaip.pszNewItem);
+
+ SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)iIndexIfFound, 0);
+
+ // Show message box that the item can not be added
+ if (!Miranda_Terminated())
+ bDoAdd = (MessageBoxEx(hwndDlg, pszBoxText, pszMsgTitle, MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2, LANGIDFROMLCID(GetThreadLocale())) == IDYES);
+
+ mir_free(pszBoxText);
+ }
+
+ } else if (pslOtherContents && SLIsItem(pslOtherContents, wlbaip.pszNewItem, FALSE) )
+ {
+ WCHAR* pszBoxText = (WCHAR*)mir_alloc((lstrlen(pszMsgTextInOther)+lstrlen(wlbaip.pszNewItem)+1)*sizeof(WCHAR));
+ bDoAdd = FALSE;
+
+ if (pszBoxText)
+ {
+ // Show message box that it is not good to add the item
+ mir_sntprintf(pszBoxText, (lstrlen(pszMsgTextInOther) + lstrlen(wlbaip.pszNewItem) + 1), pszMsgTextInOther, wlbaip.pszNewItem);
+
+ if (!Miranda_Terminated())
+ bDoAdd = (MessageBoxEx(hwndDlg, pszBoxText, pszMsgTitle, MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2, LANGIDFROMLCID(GetThreadLocale())) == IDYES);
+
+ mir_free(pszBoxText);
+ }
+
+ } else {
+ bDoAdd = TRUE;
+ }
+
+ }
+
+ // Add the item if everything is OK
+ if (bDoAdd)
+ {
+ int iPos;
+
+ // Add new item to list
+ iPos = SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)wlbaip.pszNewItem);
+ if (iPos >= 0)
+ {
+ // Select new entry
+ SendMessage(hwndListBox, LB_SETCURSEL, iPos, 0);
+
+ // Activate delete button
+ EnableDlgItem(hwndDlg, iIDButtonDelete, TRUE);
+
+ } else {
+ bDoAdd = FALSE;
+ }
+ }
+
+ // Free allocated memory
+ mir_free(wlbaip.pszNewItem);
+ }
+
+ // Set focus on list box
+ SetFocus(hwndListBox);
+
+ return bDoAdd;
+}
+
+
+int WordsListBoxDeleteItem(HWND hwndDlg, int iIDListBox, int iIDButtonDelete)
+{
+ HWND hwndListBox = GetDlgItem(hwndDlg, iIDListBox);
+ int iSelectedItem;
+ int iItemCount;
+
+ if (!hwndListBox) return LB_ERR;
+
+ iSelectedItem = SendMessage(hwndListBox, LB_GETCURSEL, 0, 0);
+ if (iSelectedItem >= 0)
+ {
+ // Delete entry and get new list item count
+ iItemCount = SendMessage(hwndListBox, LB_DELETESTRING, (WPARAM)iSelectedItem, 0);
+
+ // Deactivate delete button?
+ if (iItemCount == 0)
+ EnableDlgItem(hwndDlg, iIDButtonDelete, FALSE);
+
+ // Select next item for 'fast delete'
+ if (SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)iSelectedItem, 0) < 0)
+ SendMessage(hwndListBox, LB_SETCURSEL, (WPARAM)((iSelectedItem>0)?(iSelectedItem-1):0), 0);
+
+ } else {
+ iItemCount = LB_ERR;
+ }
+
+ // Set focus on list box
+ SetFocus(hwndListBox);
+
+ return iItemCount;
+}
+
+
+BOOL ToggleTreeViewItemState(HWND hwndTreeView, HTREEITEM hTreeItem)
+{
+ UINT uCurrentState;
+ BOOL bChangeAllowed;
+
+ uCurrentState = TreeView_GetItemState(hwndTreeView, hTreeItem, TVIS_STATEIMAGEMASK);
+
+ // No toggle if item is section item
+ if (uCurrentState&INDEXTOSTATEIMAGEMASK(0)) // no checkbox
+ {
+ bChangeAllowed = FALSE;
+
+ // Check if another checkbox is still checked before unchecking this one
+ } else if (uCurrentState&INDEXTOSTATEIMAGEMASK(2)) // checkbox checked
+ {
+ HTREEITEM hItem;
+ HTREEITEM hSectionItem;
+
+ bChangeAllowed = FALSE;
+ for (hSectionItem=TreeView_GetRoot(hwndTreeView); hSectionItem; hSectionItem=TreeView_GetNextSibling(hwndTreeView, hSectionItem))
+ {
+ for (hItem=TreeView_GetChild(hwndTreeView, hSectionItem); hItem; hItem=TreeView_GetNextSibling(hwndTreeView, hItem))
+ {
+ if (hItem == hTreeItem) continue;
+
+ // Check setting (checkbox checked?)
+ if (TreeView_GetItemState(hwndTreeView, hItem, TVIS_STATEIMAGEMASK)&INDEXTOSTATEIMAGEMASK(2))
+ {
+ bChangeAllowed = TRUE;
+ break;
+ }
+ }
+ }
+
+ // System default sound (mistake notify)
+ if (!bChangeAllowed)
+ MessageBeep(MB_OK);
+
+ } else {
+ bChangeAllowed = TRUE;
+ }
+
+ if (bChangeAllowed)
+ TreeView_SetItemState(hwndTreeView, hTreeItem, INDEXTOSTATEIMAGEMASK((uCurrentState&INDEXTOSTATEIMAGEMASK(2))?1:2), TVIS_STATEIMAGEMASK);
+
+ return bChangeAllowed;
+}
+
+
+MESSAGETYPEDESC* GetDataFromTreeViewItem(HWND hwndTreeView, HTREEITEM hTreeItem)
+{
+ TVITEM tvi;
+
+ tvi.hItem = hTreeItem;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+
+ if (TreeView_GetItem(hwndTreeView, &tvi))
+ if (((unsigned int)tvi.lParam >= 0) && ((unsigned int)tvi.lParam < uMsgTypesCount))
+ return &pamtdMsgTypes[(unsigned int)tvi.lParam];
+
+ return NULL;
+}
+
+
+BOOL MakeVariablesHelpButton(HWND hwndDlg, int iIDButton)
+{
+ BOOL bReturn;
+
+ // Set icon and resize button
+ SetWindowPos(GetDlgItem(hwndDlg, iIDButton), NULL, 0, 0, 20, 20, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+ SendDlgItemMessage(hwndDlg, iIDButton, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)LoadSystemIcon(IDB_STD_SMALL_COLOR, STD_HELP));
+ PostMessage(GetDlgItem(hwndDlg, iIDButton), BUTTONADDTOOLTIP, (WPARAM)Translate("Use variables in the message text"), 0);
+ SendMessage(GetDlgItem(hwndDlg, iIDButton), BUTTONSETASFLATBTN, 0, 0);
+
+ // Do not show help button if variables are not available
+ bReturn = (ServiceExists(MS_VARS_SHOWHELP) && ServiceExists(MS_VARS_FORMATSTRING));
+ ShowDlgItem(hwndDlg, iIDButton, bReturn);
+
+ return bReturn;
+}
+
+
+// ------------------------------
+
+
+static int OptionsInitialise(WPARAM wParam, LPARAM lParam)
+{
+ // (Options page max. size: 314, 240)
+
+ // These controls will be hidden in simple (non-expert) options mode
+ static UINT SpamFilterExpertOnlyControls[] = {IDC_BUTTON_ADVERTISMENTFILTER, IDC_BUTTON_DISLIKEDMESSAGEFILTER, IDC_BUTTON_ROBOTFILTER, IDC_BUTTON_RESETAUTOIGNORE, IDC_GROUP_MESSAGETYPES, IDC_TEXT_MESSAGETYPES, IDC_TREEVIEW_MESSAGETYPES};
+
+ OPTIONSDIALOGPAGE odp;
+ INITCOMMONCONTROLSEX icc;
+
+ // Add Spam Filter option page
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInstance;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_MAIN);
+ odp.position = 900000001; // 900000000 = Ignore options
+ odp.ptszTitle = TranslateT("Spam Filter");
+ odp.ptszGroup = TranslateT("Events");
+ odp.flags = ODPF_BOLDGROUPS|ODPF_UNICODE;
+ odp.pfnDlgProc = DlgProcSpamFilterOpt;
+ //odp.nIDBottomSimpleControl = IDC_GROUP_POPUP; // In simple mode the dlg will be cut off after this control
+ odp.expertOnlyControls = SpamFilterExpertOnlyControls;
+ odp.nExpertOnlyControls = ARRAYSIZE(SpamFilterExpertOnlyControls);
+
+ // Ensure the needed common controls are loaded
+ ZeroMemory(&icc, sizeof(icc));
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_TREEVIEW_CLASSES|ICC_UPDOWN_CLASS;
+ InitCommonControlsEx(&icc);
+
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+ return 0;
+}
+
+
+static int DbSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING* pdcws = (DBCONTACTWRITESETTING*)lParam;
+ HANDLE hContact = (HANDLE)wParam;
+
+ // Ignore Options Extension
+ if ( (hContact == NULL) && (StrCmpA(pdcws->szModule, "Ignore") == 0))
+ {
+ if ( (( (IsWindow(hwndSpamFilterOpt) ? IsDlgButtonChecked(hwndSpamFilterOpt, IDC_CHECKBOX_ADVERTISMENTFILTER) : FALSE) || DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER) )
+ || ( (IsWindow(hwndSpamFilterOpt) ? IsDlgButtonChecked(hwndSpamFilterOpt, IDC_CHECKBOX_ROBOTFILTER) : FALSE) || DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)DEFAULT_SETTING_ROBOTFILTER) ))
+ && (BOOL)CallService(MS_IGNORE_ISIGNORED, (WPARAM)NULL, (LPARAM)IGNOREEVENT_MESSAGE)
+ && (BOOL)CallService(MS_IGNORE_ISIGNORED, (WPARAM)NULL, (LPARAM)IGNOREEVENT_URL)
+ && (BOOL)CallService(MS_IGNORE_ISIGNORED, (WPARAM)NULL, (LPARAM)IGNOREEVENT_FILE)
+ && (BOOL)CallService(MS_IGNORE_ISIGNORED, (WPARAM)NULL, (LPARAM)IGNOREEVENT_AUTHORIZATION) )
+ {
+ if (!Miranda_Terminated())
+ {
+ HWND hwndParent = IsWindow(hwndSpamFilterOpt) ? GetParent(hwndSpamFilterOpt) : NULL;
+
+ if (MessageBoxEx(hwndParent, TranslateT("You chose to ignore all kind of messages from contacts that are not on your contact list although the spam filter is activated.\r\n\r\nShall the spam filter be deactivated?"), TranslateT("Spam Filter"), MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON1|(!hwndParent?(MB_SETFOREGROUND|MB_TASKMODAL):0), LANGIDFROMLCID(GetThreadLocale())) == IDYES)
+ {
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)FALSE);
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)FALSE);
+
+ if (IsWindow(hwndSpamFilterOpt))
+ {
+ CheckDlgButton(hwndSpamFilterOpt, IDC_CHECKBOX_ADVERTISMENTFILTER, BST_UNCHECKED);
+ CheckDlgButton(hwndSpamFilterOpt, IDC_CHECKBOX_ROBOTFILTER, BST_UNCHECKED);
+ }
+ }
+ }
+
+ }
+ }
+
+ // Watch "Hidden" setting to sync with IsSammer-state (Ignore opts change)
+/* if (StrCmpA(pdcws->szModule, "CList") == 0)
+ if (StrCmpA(pdcws->szSetting, "Hidden") == 0)
+ if ((pdcws->value.type==DBVT_DELETED) || !pdcws->value.bVal)
+ if ((BOOL)CallService(MS_SPAMFILTER_CONTACT_ISSPAMMER, (WPARAM)hContact, 0))
+ DBWriteContactSettingByte((HANDLE)wParam, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)FALSE); // no service call here!
+*/
+
+ // Cache starting/stopping according to Filter settings (to save a little memory)
+ if ( (hContact == NULL) && (StrCmpA(pdcws->szModule, DB_MODULE_NAME) == 0) &&
+ (StrCmpA(pdcws->szSetting, DB_SETTING_ADVERTISMENTFILTER) == 0) )
+ {
+ BOOL bAdvertismentFilter = (pdcws->value.type==DBVT_BYTE) ? pdcws->value.bVal : DEFAULT_SETTING_ADVERTISMENTFILTER;
+ BOOL bDislikedMessagesFilter = DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)DEFAULT_SETTING_DISLIKEDMESSAGEFILTER);
+
+ ToggleSpamDefinitionsCache(bAdvertismentFilter || bDislikedMessagesFilter);
+ }
+ if ( (hContact == NULL) && (StrCmpA(pdcws->szModule, DB_MODULE_NAME) == 0) &&
+ (StrCmpA(pdcws->szSetting, DB_SETTING_DISLIKEDMESSAGEFILTER) == 0) )
+ {
+ BOOL bDislikedMessagesFilter = (pdcws->value.type==DBVT_BYTE) ? pdcws->value.bVal : DEFAULT_SETTING_DISLIKEDMESSAGEFILTER;
+ BOOL bAdvertismentFilter = DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER);
+
+ ToggleSpamDefinitionsCache(bAdvertismentFilter || bDislikedMessagesFilter);
+ }
+
+ return 0;
+}
+
+
+// ------------------------------------
+
+
+void InitOptions(void)
+{
+ hHookOptInit = HookEvent(ME_OPT_INITIALISE, OptionsInitialise);
+ hHookDbSettingChangedOpt = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, DbSettingChanged);
+}
+
+void UninitOptions(void)
+{
+ if (hHookOptInit) UnhookEvent(hHookOptInit);
+ if (hHookDbSettingChangedOpt) UnhookEvent(hHookDbSettingChangedOpt);
+
+ // Dialogs that are created without parent (non-modal) need to be destroyed
+ if (IsWindow(hwndAdvertismentFilter))
+ SendMessage(hwndAdvertismentFilter, WM_CLOSE, 0, 0);
+ if (IsWindow(hwndRobotFilter))
+ SendMessage(hwndRobotFilter, WM_CLOSE, 0, 0);
+ if (IsWindow(hwndDislikedMessagesFilter))
+ SendMessage(hwndDislikedMessagesFilter, WM_CLOSE, 0, 0);
+ if (IsWindow(hwndSpamDefinitionsInfo))
+ SendMessage(hwndSpamDefinitionsInfo, WM_CLOSE, 0, 0);
+ if (IsWindow(hwndSpammersInfo))
+ SendMessage(hwndSpammersInfo, WM_CLOSE, 0, 0);
} \ No newline at end of file
diff --git a/options.h b/options.h
index b5b0380..9459518 100644
--- a/options.h
+++ b/options.h
@@ -1,60 +1,60 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_OPTIONS_H__
-#define SF_OPTIONS_H__ 1
-
-// -- Defines: Self-defined dialog messages
-#define SFM_REBUILD_MSGTYPES (WM_APP+111) // wParam=lParam=0
-#define SFM_VALIDATE_LOGFILENAME (WM_APP+112) // wParam=lParam=0
-#define SFM_CHECK_AUTOIGNORE (WM_APP+113) // wParam=lParam=0
-#define SFM_RELOAD_DEFAULTBADWORDS (WM_APP+114) // wParam=lParam=0
-#define SFM_REFRESH_SPAMDEFINITIONS (WM_APP+115) // wParam=bForceRefresh; lParam=0 or lParam=dwFilterType
-#define SFM_REFRESH_SPAMMERS (WM_APP+116) // wParam=lParam=0
-
-// -- Protoypes
-BOOL CALLBACK DlgProcSpamFilterOpt(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-BOOL CALLBACK DlgProcConfigureAdvertismentFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-BOOL CALLBACK DlgProcConfigureDislikedMessagesFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-BOOL CALLBACK DlgProcConfigureRobotFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-
-BOOL CALLBACK DlgProcSpamDefinitionsInfo(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-BOOL CALLBACK DlgProcSpammersInfo(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-
-static int OptionsInitialise(WPARAM wParam, LPARAM lParam);
-static int DbSettingChanged(WPARAM wParam, LPARAM lParam);
-
-LRESULT CALLBACK WordsListBoxSubclassProc(HWND hwndList, UINT uMsg, WPARAM wParam, LPARAM lParam);
-BOOL CALLBACK DlgProcWordsListBoxAddItem(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-void WordsListBoxInit(HWND hwndDlg, int iIDListBox, int iIDAddButton, int iIDDeleteButton, STRINGLIST* pslContents, const char* pszAddTooltip, const char* pszDeleteTooltip);
-BOOL WordsListBoxDragDrop(HWND hwndDlg, int iIDListBox, UINT uMsg, LPARAM lParam, BOOL bAllowCopy);
-BOOL WordsListBoxAddItem(HWND hwndDlg, int iIDListbox, STRINGLIST* pslOtherContents, const WCHAR* pszMsgTitle, const WCHAR* pszMsgTextInList, const WCHAR* pszMsgTextInOther, int iIDButtonDelete);
-int WordsListBoxDeleteItem(HWND hwndDlg, int iIDListBox, int iIDButtonDelete);
-
-BOOL ToggleTreeViewItemState(HWND hwndTreeView, HTREEITEM hItem) ;
-MESSAGETYPEDESC* GetDataFromTreeViewItem(HWND hwndTreeView, HTREEITEM hTreeItem);
-
-BOOL MakeVariablesHelpButton(HWND hwndDlg, int iIDButton);
-
-void InitOptions(void);
-void UninitOptions(void);
-
-#endif // SF_OPTIONS_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_OPTIONS_H__
+#define SF_OPTIONS_H__ 1
+
+// -- Defines: Self-defined dialog messages
+#define SFM_REBUILD_MSGTYPES (WM_APP+111) // wParam=lParam=0
+#define SFM_VALIDATE_LOGFILENAME (WM_APP+112) // wParam=lParam=0
+#define SFM_CHECK_AUTOIGNORE (WM_APP+113) // wParam=lParam=0
+#define SFM_RELOAD_DEFAULTBADWORDS (WM_APP+114) // wParam=lParam=0
+#define SFM_REFRESH_SPAMDEFINITIONS (WM_APP+115) // wParam=bForceRefresh; lParam=0 or lParam=dwFilterType
+#define SFM_REFRESH_SPAMMERS (WM_APP+116) // wParam=lParam=0
+
+// -- Protoypes
+BOOL CALLBACK DlgProcSpamFilterOpt(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK DlgProcConfigureAdvertismentFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK DlgProcConfigureDislikedMessagesFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK DlgProcConfigureRobotFilter(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+BOOL CALLBACK DlgProcSpamDefinitionsInfo(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK DlgProcSpammersInfo(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+static int OptionsInitialise(WPARAM wParam, LPARAM lParam);
+static int DbSettingChanged(WPARAM wParam, LPARAM lParam);
+
+LRESULT CALLBACK WordsListBoxSubclassProc(HWND hwndList, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK DlgProcWordsListBoxAddItem(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+void WordsListBoxInit(HWND hwndDlg, int iIDListBox, int iIDAddButton, int iIDDeleteButton, STRINGLIST* pslContents, const char* pszAddTooltip, const char* pszDeleteTooltip);
+BOOL WordsListBoxDragDrop(HWND hwndDlg, int iIDListBox, UINT uMsg, LPARAM lParam, BOOL bAllowCopy);
+BOOL WordsListBoxAddItem(HWND hwndDlg, int iIDListbox, STRINGLIST* pslOtherContents, const WCHAR* pszMsgTitle, const WCHAR* pszMsgTextInList, const WCHAR* pszMsgTextInOther, int iIDButtonDelete);
+int WordsListBoxDeleteItem(HWND hwndDlg, int iIDListBox, int iIDButtonDelete);
+
+BOOL ToggleTreeViewItemState(HWND hwndTreeView, HTREEITEM hItem) ;
+MESSAGETYPEDESC* GetDataFromTreeViewItem(HWND hwndTreeView, HTREEITEM hTreeItem);
+
+BOOL MakeVariablesHelpButton(HWND hwndDlg, int iIDButton);
+
+void InitOptions(void);
+void UninitOptions(void);
+
+#endif // SF_OPTIONS_H__
diff --git a/path.c b/path.c
index b829c68..325a78a 100644
--- a/path.c
+++ b/path.c
@@ -1,541 +1,541 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-
-// -----------------------------------------
-
-
-BOOL PPreparePathForWrite(HWND hwndDlg, const WCHAR* pszPath, BOOL bAskDirCreate, BOOL bContainsFileName)
-{
- // Using SHPathPrepareForWrite on Win2000+ (best, only if avail)
- {
- HRESULT (STDAPICALLTYPE *MySHPathPrepareForWrite)(HWND, IUnknown*, LPCTSTR, DWORD);
-
- #if defined(UNICODE)
- *(FARPROC*)&MySHPathPrepareForWrite = GetProcAddress(GetModuleHandle(_T("USER32")), "SHPathPrepareForWriteW");
- #else
- *(FARPROC*)&MySHPathPrepareForWrite = GetProcAddress(GetModuleHandle(_T("USER32")), "SHPathPrepareForWriteA");
- #endif
-
- if (MySHPathPrepareForWrite)
- {
- DWORD dwFlags = SHPPFW_NOWRITECHECK; // Not impl anyway
-
- if (bContainsFileName)
- dwFlags |= SHPPFW_IGNOREFILENAME;
-
- dwFlags |= bAskDirCreate ? SHPPFW_ASKDIRCREATE : SHPPFW_DIRCREATE;
-
- return SUCCEEDED(MySHPathPrepareForWrite(hwndDlg, NULL, (LPCTSTR)pszPath, dwFlags));
- }
- }
-
- // Emulating SHPathPrepareForWrite:
- // Using SHCreateDirectoryEx on WinME
- // And: Using emulated version of SHCreateDirectoryEx on Win95/98
- {
- WCHAR* pszDir;
- BOOL bReturn = FALSE;
-
- pszDir = mir_wstrdup(pszPath);
- if (!pszDir) return FALSE;
-
- if (bContainsFileName)
- PathRemoveFileSpec((LPWSTR)pszDir);
-
- // No dialog is emulated, instead always behave as
- // if "No" was clicked
- if (bAskDirCreate)
- return FALSE;
-
- // Create all sub directories
- {
- int (STDAPICALLTYPE *MySHCreateDirectoryEx)(HWND, LPCTSTR, SECURITY_ATTRIBUTES*);
-
- #if defined(UNICODE)
- *(FARPROC*)&MySHCreateDirectoryEx = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHELL32")), "SHCreateDirectoryExW");
- #else
- *(FARPROC*)&MySHCreateDirectoryEx = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHELL32")), "SHCreateDirectoryExA");
- #endif
-
- if (MySHCreateDirectoryEx)
- {
- int iRet = (SHCreateDirectoryEx(hwndDlg, pszDir, NULL) == ERROR_SUCCESS);
- bReturn = ((iRet == ERROR_SUCCESS) || (iRet == ERROR_ALREADY_EXISTS));
-
- } else {
-
- int iSlashOcc;
- int iAbsSlashOcc;
- WCHAR* pszSlash;
- WCHAR szDirTemp[MAX_PATH];
- WCHAR szDirOutput[MAX_PATH];
-
- ZeroMemory(&szDirTemp, sizeof(szDirTemp));
- ZeroMemory(&szDirOutput, sizeof(szDirOutput));
-
- // Skip drive letter
- pszSlash = StrChr(pszDir, _T('\\')); // Search for the first :'\\'
-
- if (pszSlash != NULL) // does not contain any slashs
- {
- iSlashOcc = (int)(pszSlash-pszDir+1); // Pointer arithmetic
- StrCpyN(szDirTemp, pszDir+iSlashOcc, lstrlen(pszDir)-iSlashOcc); // Pointer arithmetic
- iAbsSlashOcc = iSlashOcc;
-
- bReturn = TRUE;
- pszSlash = szDirTemp;
- while (pszSlash)
- {
- pszSlash = StrChr(szDirTemp, _T('\\'));
-
- iSlashOcc = (int)(pszSlash-szDirTemp+1); // Pointer arithmetic
- iAbsSlashOcc = iAbsSlashOcc + iSlashOcc;
-
- StrCpyN(szDirOutput, pszPath, iAbsSlashOcc); // Pointer arithmetic
-
- StrCpyN(szDirTemp, szDirTemp+iSlashOcc, lstrlen(szDirTemp)-iSlashOcc); // Pointer arithmetic
- ZeroMemory((PBYTE)szDirTemp+((lstrlen(szDirTemp)-iSlashOcc)*sizeof(WCHAR)), iSlashOcc*sizeof(WCHAR));
-
- bReturn = (CreateDirectory(szDirOutput, NULL) && bReturn);
- }
- }
- }
- }
-
- mir_free(pszDir);
- return bReturn;
- }
-}
-
-
-BOOL PIsValidFile(const WCHAR* pszFileName, const WCHAR* aszFileExtensions[], int nFileExtensions, const WCHAR* aszContentTypes[], int nContentTypes)
-{
- BOOL bIsOk = FALSE;
- int i;
-
- if (!pszFileName) return FALSE;
-
- // Check file extensions
- for (i=0; i<nFileExtensions; i++)
- {
- bIsOk = (StrCmpI(PathFindExtension(pszFileName), aszFileExtensions[i]) == 0);
- if (bIsOk) break;
- }
-
- if (!bIsOk)
- {
- // Check content types
- for (i=0; i<nContentTypes; i++)
- {
- bIsOk = PathIsContentType(pszFileName, aszContentTypes[i]);
- if (bIsOk) break;
- }
-
- if (!bIsOk)
- return FALSE;
- }
-
- // Check if the file name is actually a directory
- if (PathIsDirectory(pszFileName))
- return FALSE;
-
- // Finally check if file is present
- return PathFileExists(pszFileName);
-}
-
-
-void PMakePathPretty(WCHAR* pszPath, DWORD dwFlags)
-{
- WCHAR szBuf[MAX_PATH];
- WCHAR szRelativeTo[MAX_PATH];
-
- if (!pszPath)
- return;
-
- if (!PConstructLocalPath(szRelativeTo, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL))
- szRelativeTo[0] = _T('\0');
-
- // Create absolute path if path is relative
- if (PathIsRelative(pszPath))
- {
- if (PathCombine(szBuf, szRelativeTo, pszPath))
- {
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- dwFlags |= PC_ABSOLUTERELATIVE; // Convert back after making pretty
- }
- }
-
- // Make pretty
- {
- if (PathCanonicalize(szBuf, pszPath))
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
-
- // Convert slightly wrong chars
- ReplaceSubStringWithStringBuf(pszPath, 0, _T("/"), _T("\\"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszPath, 0, _T("\\\\"), _T("\\"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszPath, 0, _T("\""), NULL, TRUE, FALSE);
-
- /*
- {
- int i;
-
- // Remove wildcard characters
- if (dwFlags&PC_ALLOW_WILDCARDS)
- for (i=lstrlen(pszPath); i>=0; i--)
- if (PathGetCharType(pszPath[i])&GCT_WILD)
- RemoveSubStr(pszPath, i, 1);
-
- // Remove disallowed TCHARs
- for (i=lstrlen(pszPath); i>=0; i--)
- if (PathGetCharType(pszPath[i])&GCT_INVALID)
- RemoveSubStr(pszPath, i, 1);
- }
- */
-
- PathRemoveBlanks(pszPath);
- PathUnquoteSpaces(pszPath);
-
- // Upper case drive TCHAR
- if (PathGetDriveNumber(pszPath) != -1)
- CharUpperBuff(pszPath, 1);
-
- // Make it use the long path name (Win98+/Win2000+)
- {
- DWORD (WINAPI *MyGetLongPathName)(LPCTSTR, LPCTSTR, DWORD);
-
- #if defined(UNICODE)
- *(FARPROC*)&MyGetLongPathName = GetProcAddress(GetModuleHandle(_T("KERNEL32")), "GetLongPathNameW");
- #else
- *(FARPROC*)&MyGetLongPathName = GetProcAddress(GetModuleHandle(_T("KERNEL32")), "GetLongPathNameA");
- #endif
-
- if (MyGetLongPathName)
- {
- if (MyGetLongPathName(pszPath, pszPath, MAX_PATH) == 0)
- {
- // Try to remove file name and see if it works then
- mir_sntprintf(szBuf, ARRAYSIZE(szBuf), _T("%s"), pszPath);
-
- if (PathRemoveFileSpec(szBuf) && (MyGetLongPathName(szBuf, szBuf, ARRAYSIZE(szBuf)) != 0))
- {
- PathAppend(szBuf, PathFindFileName(pszPath));
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- }
- }
- }
- }
-
- // Lower case path if all upper case (only if user activated this feature for Windows-Explorer)
- {
- SHELLFLAGSTATE sfs;
- SHGetSettings(&sfs, SSF_DONTPRETTYPATH);
-
- if (!sfs.fDontPrettyPath)
- PathMakePretty(pszPath);
- }
- }
-
- // Make relative
- if (dwFlags&PC_ABSOLUTERELATIVE)
- {
- if (PathRelativePathTo(szBuf, szRelativeTo, FILE_ATTRIBUTE_DIRECTORY, pszPath, FILE_ATTRIBUTE_NORMAL))
- {
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
-
- // Remove backslash in front -> does not belong there (causes by PathRelativePathTo)
- if ((pszPath[0] == _T('\\')) || (pszPath[0] == _T('/')))
- MoveMemory(pszPath, CharNext(pszPath), (lstrlen(CharNext(pszPath))+1)*sizeof(WCHAR));
- }
-
- // Miranda Utils contains a quite less featured implementation of relative paths
- // (not all cases are captured, does not support Unicode, too)
- //if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)pszPath, (LPARAM)szBuf) == 0)
- // mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- }
-
- // Environment strings
- if (dwFlags&PC_ENVIRONMENTSTRINGS)
- {
- BOOL (STDAPICALLTYPE *MyPathUnExpandEnvStrings)(LPCTSTR, LPTSTR, UINT);
-
- // PathUnExpandEnvStrings is Win98/2000+
- #if defined(UNICODE)
- *(FARPROC*)&MyPathUnExpandEnvStrings = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "PathUnExpandEnvStringsW");
- #else
- *(FARPROC*)&MyPathUnExpandEnvStrings = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "PathUnExpandEnvStringsA");
- #endif
-
- if (MyPathUnExpandEnvStrings)
- if (MyPathUnExpandEnvStrings(pszPath, szBuf, MAX_PATH))
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- }
-}
-
-
-DWORD PMakePathUsable(WCHAR* pszPath)
-{
- WCHAR szBuf[MAX_PATH];
- DWORD dwFlags = 0;
-
- if (!pszPath)
- return dwFlags;
-
- PathUnquoteSpaces(pszPath);
-
- // Environment strings
- {
- if (ExpandEnvironmentStrings(pszPath, szBuf, ARRAYSIZE(szBuf)) != 0)
- {
- // Success?
- if (StrCmp(pszPath, szBuf) != 0)
- dwFlags |= PC_ENVIRONMENTSTRINGS;
-
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- }
- }
-
- // Absolute/relative path
- {
- WCHAR szRelativeTo[MAX_PATH];
- PConstructLocalPath(szRelativeTo, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL);
-
- // Miranda Utils contains not a very good implementation of relative paths
- // (not all cases are captured)
- //(CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)szBuf, (LPARAM)pszPath) != lstrlenA(szBuf))
-
- // Create absolute path if path is relative
- if (PathIsRelative(pszPath))
- {
- if (PathCombine(szBuf, szRelativeTo, pszPath))
- {
- dwFlags |= PC_ABSOLUTERELATIVE;
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- }
- }
- }
-
- return dwFlags;
-}
-
-
-
-BOOL PConstructLocalPath(WCHAR* pszReturn, int nMainFolder, const WCHAR* pszSubFolders, const WCHAR* pszFileName, const WCHAR* pszOptFileExtension)
-{
- // pszReturn muss MAX_PATH groß sein
- if (!pszReturn) return FALSE;
-
- pszReturn[0] = _T('\0');
-
- switch (nMainFolder)
- {
- case CSIDL_EXT_MIRANDAPROFILE:
- {
- // Profile directory of Miranda's database
- WCHAR szBuf[MAX_PATH];
-
- if (CallService(MS_DB_GETPROFILEPATH, (WPARAM)ARRAYSIZE(szBuf), (LPARAM)szBuf) != 0)
- return FALSE;
-
- #if defined(UNICODE)
- {
- WCHAR* pszBuf = (WCHAR*)mir_utf8encodeW(szBuf);
- if (!pszBuf) return FALSE;
-
- mir_sntprintf(pszReturn, MAX_PATH, _T("%s"), pszBuf);
- mir_free(pszBuf);
- }
- #else
- mir_sntprintf(pszReturn, MAX_PATH, _T("%s"), szBuf);
- #endif
-
- break;
- }
-
- case CSIDL_EXT_MODULE:
- {
- // Current DLL's directory
- if (GetModuleFileName(hInstance, pszReturn, MAX_PATH) == 0)
- return FALSE;
-
- PathRemoveFileSpec(pszReturn);
- break;
- }
-
- case CSIDL_EXT_EXECUTABLE:
- {
- // Current executable path
- if (GetModuleFileName(NULL, pszReturn, MAX_PATH) == 0)
- return FALSE;
-
- PathRemoveFileSpec(pszReturn);
- break;
- }
-
- case CSIDL_EXT_TEMP:
- {
- // Temp directory
- if (GetTempPath(MAX_PATH, pszReturn) == 0)
- return FALSE;
- break;
- }
-
- case CSIDL_EXT_CURRENT:
- {
- // Current directory
- if (GetCurrentDirectory(MAX_PATH, pszReturn) == 0)
- return FALSE;
- break;
- }
-
- default:
- {
- // CSIDL directory
- if (!SHGetSpecialFolderPath(NULL, pszReturn, nMainFolder, FALSE))
- return FALSE;
-
- break;
- }
- }
-
- if (!PathAddBackslash(pszReturn))
- return FALSE;
-
- if (pszSubFolders)
- {
- if (!PathAppend(pszReturn, pszSubFolders))
- return FALSE;
-
- if (!PathAddBackslash(pszReturn))
- return FALSE;
- }
-
- if (pszFileName)
- if (!PathAppend(pszReturn, pszFileName))
- return FALSE;
-
- if (pszFileName && pszOptFileExtension)
- if (!PathAddExtension(pszReturn, pszOptFileExtension))
- return FALSE;
-
- return TRUE;
-}
-
-// Move files or whole folder from module to destination directory
-BOOL PInstallFile(const WCHAR* pszFileName, const WCHAR* pszDestDir)
-{
- BOOL bReturn;
- WCHAR szFileFrom[MAX_PATH+1];
- WCHAR szFileTo[MAX_PATH+1];
-
- if (!pszFileName) return FALSE;
- PConstructLocalPath(szFileFrom, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
- if (!PathFileExists(szFileFrom)) return FALSE;
- mir_sntprintf(szFileTo, ARRAYSIZE(szFileTo), _T("%s"), pszDestDir);
-
- if (PathIsDirectory(szFileFrom))
- {
- SHFILEOPSTRUCT sfo;
-
- ZeroMemory(&sfo, sizeof(sfo));
- sfo.fFlags = FOF_MULTIDESTFILES|FOF_NOERRORUI|FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SILENT;
- sfo.wFunc = FO_MOVE;
- szFileFrom[lstrlen(szFileFrom)+1] = _T('\0');
- sfo.pFrom = szFileFrom;
- szFileTo[lstrlen(szFileTo)+1] = _T('\0');
- sfo.pTo = szFileTo;
- bReturn = (SHFileOperation(&sfo) == 0);
-
- } else {
- PathAppend(szFileTo, pszFileName);
-
- DeleteFile(szFileTo);
- bReturn = MoveFile(szFileFrom, szFileTo); // MoveFile does only support directories limitedly
- }
-
- return bReturn;
-}
-
-BOOL PInstallDLLFile(const WCHAR* pszFileName, BOOL bIgnoreLanguage, BOOL bIgnoreOpSystem)
-{
- DWORD dwErr;
- WCHAR szSrcDir[MAX_PATH];
- WCHAR szDestDir[MAX_PATH];
- WCHAR szTmpFile[MAX_PATH];
- UINT uTmpFileSize = ARRAYSIZE(szTmpFile);
-
- if (!pszFileName) return FALSE;
-
- // Test if file-to-be-installed exists
- PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
- if (!PathFileExists(szSrcDir)) return FALSE;
-
- // Source: module dir (Plugins directory)
- PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, NULL, NULL);
-
- // Destination: app dir
- PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL);
-
- // Install DLL using version verfication
- szTmpFile[0] = _T('\0'); // needs to be empty (docs)
- dwErr = VerInstallFile(0, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
- if (!(dwErr&VIF_WRITEPROT) && !(dwErr&VIF_SRCOLD))
- {
- // Ignore language/codepage of the DLL (install anyway) -> useful for DLLs without user interface
- if (bIgnoreLanguage)
- if ((dwErr&VIF_DIFFLANG) && (dwErr&VIF_DIFFCODEPG))
- dwErr = VerInstallFile(VIFF_FORCEINSTALL, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
-
- // Ignore operating system of the DLL (install anyway) -> useful for DLLs that work anyway
- if (bIgnoreOpSystem)
- if (dwErr&VIF_DIFFTYPE)
- dwErr = VerInstallFile(VIFF_FORCEINSTALL, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
- }
-
- // Delete temp file
- if ((dwErr&VIF_TEMPFILE) && !(dwErr&VIF_BUFFTOOSMALL)) // buffer too small for temp file
- DeleteFile(szTmpFile);
-
- // Test for success
- PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, pszFileName, NULL);
- if (PathFileExists(szDestDir))
- {
- PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
- DeleteFile(szSrcDir);
- return TRUE;
- }
-
- // Debug output
- OutputDebugString(_T("Spam Filter: VersionInfo DLL (VERSION.DLL) could not be used to install DLL file.\r\n"));
-
- // Source: module dir (Plugins directory)
- PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
- // Destination: app dir
- PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, pszFileName, NULL);
-
- // Copy without version checking [danger!]
- DeleteFile(szDestDir);
- return MoveFile(szSrcDir, szDestDir);
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+
+// -----------------------------------------
+
+
+BOOL PPreparePathForWrite(HWND hwndDlg, const WCHAR* pszPath, BOOL bAskDirCreate, BOOL bContainsFileName)
+{
+ // Using SHPathPrepareForWrite on Win2000+ (best, only if avail)
+ {
+ HRESULT (STDAPICALLTYPE *MySHPathPrepareForWrite)(HWND, IUnknown*, LPCTSTR, DWORD);
+
+ #if defined(UNICODE)
+ *(FARPROC*)&MySHPathPrepareForWrite = GetProcAddress(GetModuleHandle(_T("USER32")), "SHPathPrepareForWriteW");
+ #else
+ *(FARPROC*)&MySHPathPrepareForWrite = GetProcAddress(GetModuleHandle(_T("USER32")), "SHPathPrepareForWriteA");
+ #endif
+
+ if (MySHPathPrepareForWrite)
+ {
+ DWORD dwFlags = SHPPFW_NOWRITECHECK; // Not impl anyway
+
+ if (bContainsFileName)
+ dwFlags |= SHPPFW_IGNOREFILENAME;
+
+ dwFlags |= bAskDirCreate ? SHPPFW_ASKDIRCREATE : SHPPFW_DIRCREATE;
+
+ return SUCCEEDED(MySHPathPrepareForWrite(hwndDlg, NULL, (LPCTSTR)pszPath, dwFlags));
+ }
+ }
+
+ // Emulating SHPathPrepareForWrite:
+ // Using SHCreateDirectoryEx on WinME
+ // And: Using emulated version of SHCreateDirectoryEx on Win95/98
+ {
+ WCHAR* pszDir;
+ BOOL bReturn = FALSE;
+
+ pszDir = mir_wstrdup(pszPath);
+ if (!pszDir) return FALSE;
+
+ if (bContainsFileName)
+ PathRemoveFileSpec((LPWSTR)pszDir);
+
+ // No dialog is emulated, instead always behave as
+ // if "No" was clicked
+ if (bAskDirCreate)
+ return FALSE;
+
+ // Create all sub directories
+ {
+ int (STDAPICALLTYPE *MySHCreateDirectoryEx)(HWND, LPCTSTR, SECURITY_ATTRIBUTES*);
+
+ #if defined(UNICODE)
+ *(FARPROC*)&MySHCreateDirectoryEx = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHELL32")), "SHCreateDirectoryExW");
+ #else
+ *(FARPROC*)&MySHCreateDirectoryEx = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHELL32")), "SHCreateDirectoryExA");
+ #endif
+
+ if (MySHCreateDirectoryEx)
+ {
+ int iRet = (SHCreateDirectoryEx(hwndDlg, pszDir, NULL) == ERROR_SUCCESS);
+ bReturn = ((iRet == ERROR_SUCCESS) || (iRet == ERROR_ALREADY_EXISTS));
+
+ } else {
+
+ int iSlashOcc;
+ int iAbsSlashOcc;
+ WCHAR* pszSlash;
+ WCHAR szDirTemp[MAX_PATH];
+ WCHAR szDirOutput[MAX_PATH];
+
+ ZeroMemory(&szDirTemp, sizeof(szDirTemp));
+ ZeroMemory(&szDirOutput, sizeof(szDirOutput));
+
+ // Skip drive letter
+ pszSlash = StrChr(pszDir, _T('\\')); // Search for the first :'\\'
+
+ if (pszSlash != NULL) // does not contain any slashs
+ {
+ iSlashOcc = (int)(pszSlash-pszDir+1); // Pointer arithmetic
+ StrCpyN(szDirTemp, pszDir+iSlashOcc, lstrlen(pszDir)-iSlashOcc); // Pointer arithmetic
+ iAbsSlashOcc = iSlashOcc;
+
+ bReturn = TRUE;
+ pszSlash = szDirTemp;
+ while (pszSlash)
+ {
+ pszSlash = StrChr(szDirTemp, _T('\\'));
+
+ iSlashOcc = (int)(pszSlash-szDirTemp+1); // Pointer arithmetic
+ iAbsSlashOcc = iAbsSlashOcc + iSlashOcc;
+
+ StrCpyN(szDirOutput, pszPath, iAbsSlashOcc); // Pointer arithmetic
+
+ StrCpyN(szDirTemp, szDirTemp+iSlashOcc, lstrlen(szDirTemp)-iSlashOcc); // Pointer arithmetic
+ ZeroMemory((PBYTE)szDirTemp+((lstrlen(szDirTemp)-iSlashOcc)*sizeof(WCHAR)), iSlashOcc*sizeof(WCHAR));
+
+ bReturn = (CreateDirectory(szDirOutput, NULL) && bReturn);
+ }
+ }
+ }
+ }
+
+ mir_free(pszDir);
+ return bReturn;
+ }
+}
+
+
+BOOL PIsValidFile(const WCHAR* pszFileName, const WCHAR* aszFileExtensions[], int nFileExtensions, const WCHAR* aszContentTypes[], int nContentTypes)
+{
+ BOOL bIsOk = FALSE;
+ int i;
+
+ if (!pszFileName) return FALSE;
+
+ // Check file extensions
+ for (i=0; i<nFileExtensions; i++)
+ {
+ bIsOk = (StrCmpI(PathFindExtension(pszFileName), aszFileExtensions[i]) == 0);
+ if (bIsOk) break;
+ }
+
+ if (!bIsOk)
+ {
+ // Check content types
+ for (i=0; i<nContentTypes; i++)
+ {
+ bIsOk = PathIsContentType(pszFileName, aszContentTypes[i]);
+ if (bIsOk) break;
+ }
+
+ if (!bIsOk)
+ return FALSE;
+ }
+
+ // Check if the file name is actually a directory
+ if (PathIsDirectory(pszFileName))
+ return FALSE;
+
+ // Finally check if file is present
+ return PathFileExists(pszFileName);
+}
+
+
+void PMakePathPretty(WCHAR* pszPath, DWORD dwFlags)
+{
+ WCHAR szBuf[MAX_PATH];
+ WCHAR szRelativeTo[MAX_PATH];
+
+ if (!pszPath)
+ return;
+
+ if (!PConstructLocalPath(szRelativeTo, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL))
+ szRelativeTo[0] = _T('\0');
+
+ // Create absolute path if path is relative
+ if (PathIsRelative(pszPath))
+ {
+ if (PathCombine(szBuf, szRelativeTo, pszPath))
+ {
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ dwFlags |= PC_ABSOLUTERELATIVE; // Convert back after making pretty
+ }
+ }
+
+ // Make pretty
+ {
+ if (PathCanonicalize(szBuf, pszPath))
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+
+ // Convert slightly wrong chars
+ ReplaceSubStringWithStringBuf(pszPath, 0, _T("/"), _T("\\"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszPath, 0, _T("\\\\"), _T("\\"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszPath, 0, _T("\""), NULL, TRUE, FALSE);
+
+ /*
+ {
+ int i;
+
+ // Remove wildcard characters
+ if (dwFlags&PC_ALLOW_WILDCARDS)
+ for (i=lstrlen(pszPath); i>=0; i--)
+ if (PathGetCharType(pszPath[i])&GCT_WILD)
+ RemoveSubStr(pszPath, i, 1);
+
+ // Remove disallowed TCHARs
+ for (i=lstrlen(pszPath); i>=0; i--)
+ if (PathGetCharType(pszPath[i])&GCT_INVALID)
+ RemoveSubStr(pszPath, i, 1);
+ }
+ */
+
+ PathRemoveBlanks(pszPath);
+ PathUnquoteSpaces(pszPath);
+
+ // Upper case drive TCHAR
+ if (PathGetDriveNumber(pszPath) != -1)
+ CharUpperBuff(pszPath, 1);
+
+ // Make it use the long path name (Win98+/Win2000+)
+ {
+ DWORD (WINAPI *MyGetLongPathName)(LPCTSTR, LPCTSTR, DWORD);
+
+ #if defined(UNICODE)
+ *(FARPROC*)&MyGetLongPathName = GetProcAddress(GetModuleHandle(_T("KERNEL32")), "GetLongPathNameW");
+ #else
+ *(FARPROC*)&MyGetLongPathName = GetProcAddress(GetModuleHandle(_T("KERNEL32")), "GetLongPathNameA");
+ #endif
+
+ if (MyGetLongPathName)
+ {
+ if (MyGetLongPathName(pszPath, pszPath, MAX_PATH) == 0)
+ {
+ // Try to remove file name and see if it works then
+ mir_sntprintf(szBuf, ARRAYSIZE(szBuf), _T("%s"), pszPath);
+
+ if (PathRemoveFileSpec(szBuf) && (MyGetLongPathName(szBuf, szBuf, ARRAYSIZE(szBuf)) != 0))
+ {
+ PathAppend(szBuf, PathFindFileName(pszPath));
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ }
+ }
+ }
+ }
+
+ // Lower case path if all upper case (only if user activated this feature for Windows-Explorer)
+ {
+ SHELLFLAGSTATE sfs;
+ SHGetSettings(&sfs, SSF_DONTPRETTYPATH);
+
+ if (!sfs.fDontPrettyPath)
+ PathMakePretty(pszPath);
+ }
+ }
+
+ // Make relative
+ if (dwFlags&PC_ABSOLUTERELATIVE)
+ {
+ if (PathRelativePathTo(szBuf, szRelativeTo, FILE_ATTRIBUTE_DIRECTORY, pszPath, FILE_ATTRIBUTE_NORMAL))
+ {
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+
+ // Remove backslash in front -> does not belong there (causes by PathRelativePathTo)
+ if ((pszPath[0] == _T('\\')) || (pszPath[0] == _T('/')))
+ MoveMemory(pszPath, CharNext(pszPath), (lstrlen(CharNext(pszPath))+1)*sizeof(WCHAR));
+ }
+
+ // Miranda Utils contains a quite less featured implementation of relative paths
+ // (not all cases are captured, does not support Unicode, too)
+ //if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)pszPath, (LPARAM)szBuf) == 0)
+ // mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ }
+
+ // Environment strings
+ if (dwFlags&PC_ENVIRONMENTSTRINGS)
+ {
+ BOOL (STDAPICALLTYPE *MyPathUnExpandEnvStrings)(LPCTSTR, LPTSTR, UINT);
+
+ // PathUnExpandEnvStrings is Win98/2000+
+ #if defined(UNICODE)
+ *(FARPROC*)&MyPathUnExpandEnvStrings = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "PathUnExpandEnvStringsW");
+ #else
+ *(FARPROC*)&MyPathUnExpandEnvStrings = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "PathUnExpandEnvStringsA");
+ #endif
+
+ if (MyPathUnExpandEnvStrings)
+ if (MyPathUnExpandEnvStrings(pszPath, szBuf, MAX_PATH))
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ }
+}
+
+
+DWORD PMakePathUsable(WCHAR* pszPath)
+{
+ WCHAR szBuf[MAX_PATH];
+ DWORD dwFlags = 0;
+
+ if (!pszPath)
+ return dwFlags;
+
+ PathUnquoteSpaces(pszPath);
+
+ // Environment strings
+ {
+ if (ExpandEnvironmentStrings(pszPath, szBuf, ARRAYSIZE(szBuf)) != 0)
+ {
+ // Success?
+ if (StrCmp(pszPath, szBuf) != 0)
+ dwFlags |= PC_ENVIRONMENTSTRINGS;
+
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ }
+ }
+
+ // Absolute/relative path
+ {
+ WCHAR szRelativeTo[MAX_PATH];
+ PConstructLocalPath(szRelativeTo, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL);
+
+ // Miranda Utils contains not a very good implementation of relative paths
+ // (not all cases are captured)
+ //(CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)szBuf, (LPARAM)pszPath) != lstrlenA(szBuf))
+
+ // Create absolute path if path is relative
+ if (PathIsRelative(pszPath))
+ {
+ if (PathCombine(szBuf, szRelativeTo, pszPath))
+ {
+ dwFlags |= PC_ABSOLUTERELATIVE;
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ }
+ }
+ }
+
+ return dwFlags;
+}
+
+
+
+BOOL PConstructLocalPath(WCHAR* pszReturn, int nMainFolder, const WCHAR* pszSubFolders, const WCHAR* pszFileName, const WCHAR* pszOptFileExtension)
+{
+ // pszReturn muss MAX_PATH groß sein
+ if (!pszReturn) return FALSE;
+
+ pszReturn[0] = _T('\0');
+
+ switch (nMainFolder)
+ {
+ case CSIDL_EXT_MIRANDAPROFILE:
+ {
+ // Profile directory of Miranda's database
+ WCHAR szBuf[MAX_PATH];
+
+ if (CallService(MS_DB_GETPROFILEPATH, (WPARAM)ARRAYSIZE(szBuf), (LPARAM)szBuf) != 0)
+ return FALSE;
+
+ #if defined(UNICODE)
+ {
+ WCHAR* pszBuf = (WCHAR*)mir_utf8encodeW(szBuf);
+ if (!pszBuf) return FALSE;
+
+ mir_sntprintf(pszReturn, MAX_PATH, _T("%s"), pszBuf);
+ mir_free(pszBuf);
+ }
+ #else
+ mir_sntprintf(pszReturn, MAX_PATH, _T("%s"), szBuf);
+ #endif
+
+ break;
+ }
+
+ case CSIDL_EXT_MODULE:
+ {
+ // Current DLL's directory
+ if (GetModuleFileName(hInstance, pszReturn, MAX_PATH) == 0)
+ return FALSE;
+
+ PathRemoveFileSpec(pszReturn);
+ break;
+ }
+
+ case CSIDL_EXT_EXECUTABLE:
+ {
+ // Current executable path
+ if (GetModuleFileName(NULL, pszReturn, MAX_PATH) == 0)
+ return FALSE;
+
+ PathRemoveFileSpec(pszReturn);
+ break;
+ }
+
+ case CSIDL_EXT_TEMP:
+ {
+ // Temp directory
+ if (GetTempPath(MAX_PATH, pszReturn) == 0)
+ return FALSE;
+ break;
+ }
+
+ case CSIDL_EXT_CURRENT:
+ {
+ // Current directory
+ if (GetCurrentDirectory(MAX_PATH, pszReturn) == 0)
+ return FALSE;
+ break;
+ }
+
+ default:
+ {
+ // CSIDL directory
+ if (!SHGetSpecialFolderPath(NULL, pszReturn, nMainFolder, FALSE))
+ return FALSE;
+
+ break;
+ }
+ }
+
+ if (!PathAddBackslash(pszReturn))
+ return FALSE;
+
+ if (pszSubFolders)
+ {
+ if (!PathAppend(pszReturn, pszSubFolders))
+ return FALSE;
+
+ if (!PathAddBackslash(pszReturn))
+ return FALSE;
+ }
+
+ if (pszFileName)
+ if (!PathAppend(pszReturn, pszFileName))
+ return FALSE;
+
+ if (pszFileName && pszOptFileExtension)
+ if (!PathAddExtension(pszReturn, pszOptFileExtension))
+ return FALSE;
+
+ return TRUE;
+}
+
+// Move files or whole folder from module to destination directory
+BOOL PInstallFile(const WCHAR* pszFileName, const WCHAR* pszDestDir)
+{
+ BOOL bReturn;
+ WCHAR szFileFrom[MAX_PATH+1];
+ WCHAR szFileTo[MAX_PATH+1];
+
+ if (!pszFileName) return FALSE;
+ PConstructLocalPath(szFileFrom, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
+ if (!PathFileExists(szFileFrom)) return FALSE;
+ mir_sntprintf(szFileTo, ARRAYSIZE(szFileTo), _T("%s"), pszDestDir);
+
+ if (PathIsDirectory(szFileFrom))
+ {
+ SHFILEOPSTRUCT sfo;
+
+ ZeroMemory(&sfo, sizeof(sfo));
+ sfo.fFlags = FOF_MULTIDESTFILES|FOF_NOERRORUI|FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SILENT;
+ sfo.wFunc = FO_MOVE;
+ szFileFrom[lstrlen(szFileFrom)+1] = _T('\0');
+ sfo.pFrom = szFileFrom;
+ szFileTo[lstrlen(szFileTo)+1] = _T('\0');
+ sfo.pTo = szFileTo;
+ bReturn = (SHFileOperation(&sfo) == 0);
+
+ } else {
+ PathAppend(szFileTo, pszFileName);
+
+ DeleteFile(szFileTo);
+ bReturn = MoveFile(szFileFrom, szFileTo); // MoveFile does only support directories limitedly
+ }
+
+ return bReturn;
+}
+
+BOOL PInstallDLLFile(const WCHAR* pszFileName, BOOL bIgnoreLanguage, BOOL bIgnoreOpSystem)
+{
+ DWORD dwErr;
+ WCHAR szSrcDir[MAX_PATH];
+ WCHAR szDestDir[MAX_PATH];
+ WCHAR szTmpFile[MAX_PATH];
+ UINT uTmpFileSize = ARRAYSIZE(szTmpFile);
+
+ if (!pszFileName) return FALSE;
+
+ // Test if file-to-be-installed exists
+ PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
+ if (!PathFileExists(szSrcDir)) return FALSE;
+
+ // Source: module dir (Plugins directory)
+ PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, NULL, NULL);
+
+ // Destination: app dir
+ PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL);
+
+ // Install DLL using version verfication
+ szTmpFile[0] = _T('\0'); // needs to be empty (docs)
+ dwErr = VerInstallFile(0, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
+ if (!(dwErr&VIF_WRITEPROT) && !(dwErr&VIF_SRCOLD))
+ {
+ // Ignore language/codepage of the DLL (install anyway) -> useful for DLLs without user interface
+ if (bIgnoreLanguage)
+ if ((dwErr&VIF_DIFFLANG) && (dwErr&VIF_DIFFCODEPG))
+ dwErr = VerInstallFile(VIFF_FORCEINSTALL, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
+
+ // Ignore operating system of the DLL (install anyway) -> useful for DLLs that work anyway
+ if (bIgnoreOpSystem)
+ if (dwErr&VIF_DIFFTYPE)
+ dwErr = VerInstallFile(VIFF_FORCEINSTALL, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
+ }
+
+ // Delete temp file
+ if ((dwErr&VIF_TEMPFILE) && !(dwErr&VIF_BUFFTOOSMALL)) // buffer too small for temp file
+ DeleteFile(szTmpFile);
+
+ // Test for success
+ PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, pszFileName, NULL);
+ if (PathFileExists(szDestDir))
+ {
+ PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
+ DeleteFile(szSrcDir);
+ return TRUE;
+ }
+
+ // Debug output
+ OutputDebugString(_T("Spam Filter: VersionInfo DLL (VERSION.DLL) could not be used to install DLL file.\r\n"));
+
+ // Source: module dir (Plugins directory)
+ PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
+ // Destination: app dir
+ PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, pszFileName, NULL);
+
+ // Copy without version checking [danger!]
+ DeleteFile(szDestDir);
+ return MoveFile(szSrcDir, szDestDir);
} \ No newline at end of file
diff --git a/path.h b/path.h
index 0c9929d..24cd8c9 100644
--- a/path.h
+++ b/path.h
@@ -1,52 +1,52 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_PATH_H__
-#define SF_PATH_H__ 1
-
-
-// -- Defines
-// PMakePathPretty() and PMakePathUsable()
-#define PC_ENVIRONMENTSTRINGS 0x00000001
-#define PC_ABSOLUTERELATIVE 0x00000002
-#define PC_ALLOW_WILDCARDS 0x00000004
-
-// ConstructLocalPath():
-// (Reusing CSIDLs that are virtual folders)
-#define CSIDL_EXT_EXECUTABLE CSIDL_DESKTOP
-#define CSIDL_EXT_MODULE CSIDL_DRIVES
-#define CSIDL_EXT_TEMP CSIDL_PRINTERS
-#define CSIDL_EXT_CURRENT CSIDL_CONTROLS
-#define CSIDL_EXT_MIRANDAPROFILE CSIDL_INTERNET
-
-// -- Prototypes
-BOOL PConstructLocalPath(WCHAR* pszReturn, int nMainFolder, const WCHAR* pszSubFolders, const WCHAR* pszFileName, const WCHAR* pszOptFileExtension);
-BOOL PPreparePathForWrite(HWND hwndDlg, const WCHAR* pszPath, BOOL bAskDirCreate, BOOL bContainsFileName);
-
-BOOL PIsValidFile(const WCHAR* pszFileName, const WCHAR* aszFileExtensions[], int nFileExtensions, const WCHAR* aszContentTypes[], int nContentTypes);
-
-void PMakePathPretty(WCHAR* pszPath, DWORD dwFlags);
-DWORD PMakePathUsable(WCHAR* pszPath);
-
-BOOL PInstallFile(const WCHAR* pszFileName, const WCHAR* pszDestDir);
-BOOL PInstallDLLFile(const WCHAR* pszFileName, BOOL bIgnoreLanguage, BOOL bIgnoreOpSystem);
-
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_PATH_H__
+#define SF_PATH_H__ 1
+
+
+// -- Defines
+// PMakePathPretty() and PMakePathUsable()
+#define PC_ENVIRONMENTSTRINGS 0x00000001
+#define PC_ABSOLUTERELATIVE 0x00000002
+#define PC_ALLOW_WILDCARDS 0x00000004
+
+// ConstructLocalPath():
+// (Reusing CSIDLs that are virtual folders)
+#define CSIDL_EXT_EXECUTABLE CSIDL_DESKTOP
+#define CSIDL_EXT_MODULE CSIDL_DRIVES
+#define CSIDL_EXT_TEMP CSIDL_PRINTERS
+#define CSIDL_EXT_CURRENT CSIDL_CONTROLS
+#define CSIDL_EXT_MIRANDAPROFILE CSIDL_INTERNET
+
+// -- Prototypes
+BOOL PConstructLocalPath(WCHAR* pszReturn, int nMainFolder, const WCHAR* pszSubFolders, const WCHAR* pszFileName, const WCHAR* pszOptFileExtension);
+BOOL PPreparePathForWrite(HWND hwndDlg, const WCHAR* pszPath, BOOL bAskDirCreate, BOOL bContainsFileName);
+
+BOOL PIsValidFile(const WCHAR* pszFileName, const WCHAR* aszFileExtensions[], int nFileExtensions, const WCHAR* aszContentTypes[], int nContentTypes);
+
+void PMakePathPretty(WCHAR* pszPath, DWORD dwFlags);
+DWORD PMakePathUsable(WCHAR* pszPath);
+
+BOOL PInstallFile(const WCHAR* pszFileName, const WCHAR* pszDestDir);
+BOOL PInstallDLLFile(const WCHAR* pszFileName, BOOL bIgnoreLanguage, BOOL bIgnoreOpSystem);
+
#endif // SF_PATH_H__ \ No newline at end of file
diff --git a/popup.c b/popup.c
index 818d3a9..5c8dd4d 100644
--- a/popup.c
+++ b/popup.c
@@ -1,285 +1,285 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -----------------------------------------
-
-
-// -- Popup Menu Item --
-
-static int InternalServicePopupMenuItemCommand(WPARAM wParam, LPARAM lParam)
-{
- BOOL bPopupState = !DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, DEFAULT_SETTING_POPUP);
-
- DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, (BYTE)bPopupState);
- SetPopupMenuItem(bPopupState, FALSE);
-
- return 0;
-}
-
-void SetPopupMenuItem(BOOL bPopupsActivated, BOOL bGrayItem)
-{
- static HANDLE hPopupMenuItem = NULL;
-
- CLISTMENUITEM cmi;
-
- ZeroMemory(&cmi, sizeof(cmi));
- cmi.cbSize = sizeof(cmi);
-
- if (bPopupsActivated)
- {
- cmi.pszName = Translate("Disable &spam popups");
- // Getting icons out of from popup.dll (Plus/Non-Plus) (so they are always up-to-date)
- cmi.hIcon = SkinGetIcon("popup_enabled", 0, FALSE);
- if (!cmi.hIcon)
- cmi.hIcon = GetModuleHandle(_T("popup")) ? (HICON)LoadImage(GetModuleHandleA("popup"), MAKEINTRESOURCE(118), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) : NULL;
-
- } else {
- cmi.pszName = Translate("Enable &spam popups");
- // Getting icons out of from popup.dll (Plus/Non-Plus) (so they are always up-to-date)
- cmi.hIcon = SkinGetIcon("popup_disabled", 0, FALSE);
- if (!cmi.hIcon)
- cmi.hIcon = GetModuleHandle(_T("popup")) ? (HICON)LoadImage(GetModuleHandleA("popup"), MAKEINTRESOURCE(120), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) : NULL;
- }
-
- if (hPopupMenuItem)
- {
- cmi.flags = CMIM_NAME|CMIM_ICON|CMIM_FLAGS;
-
- if (bGrayItem)
- cmi.flags |= CMIF_GRAYED;
-
- CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hPopupMenuItem, (LPARAM)&cmi);
-
- } else {
-
- // Item can't be grayed out the first time
- //cmi.flags = bGrayItem ? CMIF_GRAYED : 0;
-
- cmi.pszPopupName = Translate("PopUps");
- cmi.pszService = "SpamFilter/PopupMenuItemCommand";
-
- CreateServiceFunction(cmi.pszService, InternalServicePopupMenuItemCommand);
- hPopupMenuItem = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&cmi);
-
- // Call twice to initilialize the grayed out setting
- if (bGrayItem)
- SetPopupMenuItem(bPopupsActivated, bGrayItem);
- }
-}
-
-
-
-// -- Spam Popup --
-BOOL ShowSpamPopup(const char* pszMsgTypeSection, const char* pszMsgTypeName, const WCHAR* pszCustomUserName, HANDLE hContact, DWORD dwFilterType)
-{
- BOOL bReturn = FALSE;
- int iMsgType;
-
- // Support for Popup / PopupPlus
- #if defined(UNICODE)
- if (ServiceExists(MS_POPUP_ADDPOPUPW))
- {
- POPUPDATAW ppd;
- HICON hIconBuf;
- WCHAR* pszText;
-
- switch (dwFilterType)
- {
- case SFT_DISLIKEDMESSAGES_FILTER:
- pszText = TranslateW("Disliked Message Alert!");
- break;
- case SFT_ADVERTISMENT_FILTER:
- pszText = TranslateW("Advertisment Alert!");
- break;
- case SFT_ROBOT_FILTER:
- pszText = TranslateW("Robot Alert!");
- break;
- default:
- pszText = NULL;
- }
-
- ZeroMemory(&ppd, sizeof(ppd));
- ppd.lchContact = hContact;
- ppd.colorText = SkinGetColor(DB_COLOR_POPUPTEXT_SETTING, Translate("Popup Text"), Translate("Spam Filter"), RGB(255,255,255), FALSE);
- ppd.colorBack = SkinGetColor(DB_COLOR_POPUPBACKGROUND_SETTING, Translate("Popup Background"), Translate("Spam Filter"), RGB(0,0,0), FALSE);
- if (pszText) mir_sntprintf(ppd.lpwzText, ARRAYSIZE(ppd.lpwzText), _T("%s"), pszText);
- if (pszCustomUserName) mir_sntprintf(ppd.lpwzContactName, ARRAYSIZE(ppd.lpwzContactName), _T("%s"), pszCustomUserName);
-
- // Determine main icon
- EnterCriticalSection(&csMsgTypes); // thread safety
- iMsgType = GetMsgTypeID(pszMsgTypeSection, pszMsgTypeName);
-
- if ((iMsgType >= 0) && ((int)pamtdMsgTypes[iMsgType].hIcon < 0))
- hIconBuf = LoadSkinnedIcon((-1)*(int)pamtdMsgTypes[iMsgType].hIcon); // skinned icon
- else if ((iMsgType >= 0) && pamtdMsgTypes[iMsgType].hIcon)
- hIconBuf = pamtdMsgTypes[iMsgType].hIcon;
- else
- hIconBuf = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
-
- LeaveCriticalSection(&csMsgTypes); // thread safety
-
- // Overlay small spam icon
- if (hIconBuf)
- ppd.lchIcon = OverlayIcon(hIconBuf, SkinGetIcon(DB_ICON_SPAMLAYER_SETTING, IDI_SPAM_LAYER, FALSE), GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
-
- // I don't know if popup module author made it thread safe...
- if (CallServiceSync(MS_POPUP_ADDPOPUPW, (WPARAM)&ppd, 0) > 0)
- bReturn = TRUE;
-
- if (ppd.lchIcon) DestroyIcon(ppd.lchIcon);
- }
- #else
- if (ServiceExists(MS_POPUP_ADDPOPUPEX))
- {
- POPUPDATAEX ppd;
- HICON hIconBuf;
- char* pszText;
-
- switch (dwFilterType)
- {
- case SFT_DISLIKEDMESSAGES_FILTER:
- pszText = Translate("Disliked Message Alert!");
- break;
- case SFT_ADVERTISMENT_FILTER:
- pszText = Translate("Advertisment Alert!");
- break;
- case SFT_ROBOT_FILTER:
- pszText = Translate("Robot Alert!");
- break;
- default:
- pszText = NULL;
- }
-
- ZeroMemory(&ppd, sizeof(ppd));
- ppd.lchContact = hContact;
- ppd.colorText = SkinGetColor(DB_COLOR_POPUPTEXT_SETTING, Translate("Popup Text"), Translate("Spam Filter"), RGB(255,255,255), FALSE);
- ppd.colorBack = SkinGetColor(DB_COLOR_POPUPBACKGROUND_SETTING, Translate("Popup Background"), Translate("Spam Filter"), RGB(0,0,0), FALSE);
- if (pszText)
- mir_snprintf(ppd.lpzText, ARRAYSIZE(ppd.lpzText), "%s", pszText);
- if (pszCustomUserName)
- mir_snprintf(ppd.lpzContactName, ARRAYSIZE(ppd.lpzContactName), "%s", pszCustomUserName);
-
- // Determine main icon
- EnterCriticalSection(&csMsgTypes); // thread safety
- iMsgType = GetMsgTypeID(pszMsgTypeSection, pszMsgTypeName);
-
- if ((iMsgType >= 0) && ((int)pamtdMsgTypes[iMsgType].hIcon < 0))
- hIconBuf = LoadSkinnedIcon((-1)*(int)pamtdMsgTypes[iMsgType].hIcon); // skinned icon
- else if ((iMsgType >= 0) && pamtdMsgTypes[iMsgType].hIcon)
- hIconBuf = pamtdMsgTypes[iMsgType].hIcon;
- else
- hIconBuf = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
-
- LeaveCriticalSection(&csMsgTypes); // thread safety
-
- // Overlay small spam icon
- if (hIconBuf)
- ppd.lchIcon = OverlayIcon(hIconBuf, SkinGetIcon(DB_ICON_SPAMLAYER_SETTING, IDI_SPAM_LAYER, FALSE), GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
-
- // Support for Popup Plus
- if (ServiceExists(MS_POPUP_ADDCLASS))
- {
- ppd.skinBack = ppd.colorBack;
- ppd.colorBack = POPUP_USE_SKINNED_BG;
- ppd.lpzClass = (LPCTSTR)POPUP_CLASS_SPAM; // type "LPCTSTR" of lpzClass is wrong (or: POPUP_CLASS_DEFAULT)
- }
-
- // I don't know if popup module author made it thread safe...
- if (CallServiceSync(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0) > 0)
- bReturn = TRUE;
-
- if (ppd.lchIcon) DestroyIcon(ppd.lchIcon);
- }
- #endif
-
- // Support for OSD / WanneBeOSD
- if (ServiceExists("OSD/Announce")) // no m_osd.h file yet available.. .don't like it :-/
- {
- WCHAR* pszText;
-
- switch (dwFilterType)
- {
- case SFT_DISLIKEDMESSAGES_FILTER:
- pszText = TranslateT("Disliked Message Alert!");
- break;
-
- case SFT_ADVERTISMENT_FILTER:
- pszText = TranslateT("Advertisment Alert!");
- break;
-
- case SFT_ROBOT_FILTER:
- pszText = TranslateT("Robot Alert!");
- break;
-
- default:
- pszText = NULL;
- }
-
- if (pszText)
- {
- // I don't know if OSD module author made it thread safe...
- // quite bad: return value of OSDAnnounce does not indicate anything (SendMessage result)
- // bad unicode implementation (simply expects unicode text when wbosdW.dll is used)
- // -> might cuase crashes (buffer overruns) when SF-Unicode is run with OSD-Ansi
- if (CallService("OSD/Announce", (WPARAM)pszText, (LPARAM)0) == 0);
- bReturn = TRUE;
- }
- }
-
- return bReturn;
-}
-
-
-// -- Popup Available --
-
-BOOL IsPopupAvailable(BOOL bAlsoOSD)
-{
- #if defined(UNICODE)
- return (ServiceExists(MS_POPUP_ADDPOPUPW) || (bAlsoOSD ? ServiceExists("OSD/Announce") : FALSE));
- #else
- return (ServiceExists(MS_POPUP_ADDPOPUPEX) || (bAlsoOSD ? ServiceExists("OSD/Announce") : FALSE));
- #endif
-}
-
-
-// ------------------------------------
-
-
-void InitPopup(void)
-{
- // Add class (Support for PopupPlus)
- #if !defined(UNICODE)
- if (ServiceExists(MS_POPUP_ADDCLASS))
- CallService(MS_POPUP_ADDCLASS, 0, (LPARAM)POPUP_CLASS_SPAM);
- #endif
-
- if (IsPopupAvailable(FALSE))
- SkinAddNewIcon(DB_ICON_SPAMLAYER_SETTING, TranslateT("Spam Filter"), TranslateT("Spam Message Overlay"), IDI_SPAM_LAYER, FALSE);
-}
-
-
-void UninitPopup(void)
-{
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -----------------------------------------
+
+
+// -- Popup Menu Item --
+
+static int InternalServicePopupMenuItemCommand(WPARAM wParam, LPARAM lParam)
+{
+ BOOL bPopupState = !DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, DEFAULT_SETTING_POPUP);
+
+ DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, (BYTE)bPopupState);
+ SetPopupMenuItem(bPopupState, FALSE);
+
+ return 0;
+}
+
+void SetPopupMenuItem(BOOL bPopupsActivated, BOOL bGrayItem)
+{
+ static HANDLE hPopupMenuItem = NULL;
+
+ CLISTMENUITEM cmi;
+
+ ZeroMemory(&cmi, sizeof(cmi));
+ cmi.cbSize = sizeof(cmi);
+
+ if (bPopupsActivated)
+ {
+ cmi.pszName = Translate("Disable &spam popups");
+ // Getting icons out of from popup.dll (Plus/Non-Plus) (so they are always up-to-date)
+ cmi.hIcon = SkinGetIcon("popup_enabled", 0, FALSE);
+ if (!cmi.hIcon)
+ cmi.hIcon = GetModuleHandle(_T("popup")) ? (HICON)LoadImage(GetModuleHandleA("popup"), MAKEINTRESOURCE(118), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) : NULL;
+
+ } else {
+ cmi.pszName = Translate("Enable &spam popups");
+ // Getting icons out of from popup.dll (Plus/Non-Plus) (so they are always up-to-date)
+ cmi.hIcon = SkinGetIcon("popup_disabled", 0, FALSE);
+ if (!cmi.hIcon)
+ cmi.hIcon = GetModuleHandle(_T("popup")) ? (HICON)LoadImage(GetModuleHandleA("popup"), MAKEINTRESOURCE(120), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) : NULL;
+ }
+
+ if (hPopupMenuItem)
+ {
+ cmi.flags = CMIM_NAME|CMIM_ICON|CMIM_FLAGS;
+
+ if (bGrayItem)
+ cmi.flags |= CMIF_GRAYED;
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hPopupMenuItem, (LPARAM)&cmi);
+
+ } else {
+
+ // Item can't be grayed out the first time
+ //cmi.flags = bGrayItem ? CMIF_GRAYED : 0;
+
+ cmi.pszPopupName = Translate("PopUps");
+ cmi.pszService = "SpamFilter/PopupMenuItemCommand";
+
+ CreateServiceFunction(cmi.pszService, InternalServicePopupMenuItemCommand);
+ hPopupMenuItem = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&cmi);
+
+ // Call twice to initilialize the grayed out setting
+ if (bGrayItem)
+ SetPopupMenuItem(bPopupsActivated, bGrayItem);
+ }
+}
+
+
+
+// -- Spam Popup --
+BOOL ShowSpamPopup(const char* pszMsgTypeSection, const char* pszMsgTypeName, const WCHAR* pszCustomUserName, HANDLE hContact, DWORD dwFilterType)
+{
+ BOOL bReturn = FALSE;
+ int iMsgType;
+
+ // Support for Popup / PopupPlus
+ #if defined(UNICODE)
+ if (ServiceExists(MS_POPUP_ADDPOPUPW))
+ {
+ POPUPDATAW ppd;
+ HICON hIconBuf;
+ WCHAR* pszText;
+
+ switch (dwFilterType)
+ {
+ case SFT_DISLIKEDMESSAGES_FILTER:
+ pszText = TranslateW("Disliked Message Alert!");
+ break;
+ case SFT_ADVERTISMENT_FILTER:
+ pszText = TranslateW("Advertisment Alert!");
+ break;
+ case SFT_ROBOT_FILTER:
+ pszText = TranslateW("Robot Alert!");
+ break;
+ default:
+ pszText = NULL;
+ }
+
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = hContact;
+ ppd.colorText = SkinGetColor(DB_COLOR_POPUPTEXT_SETTING, Translate("Popup Text"), Translate("Spam Filter"), RGB(255,255,255), FALSE);
+ ppd.colorBack = SkinGetColor(DB_COLOR_POPUPBACKGROUND_SETTING, Translate("Popup Background"), Translate("Spam Filter"), RGB(0,0,0), FALSE);
+ if (pszText) mir_sntprintf(ppd.lpwzText, ARRAYSIZE(ppd.lpwzText), _T("%s"), pszText);
+ if (pszCustomUserName) mir_sntprintf(ppd.lpwzContactName, ARRAYSIZE(ppd.lpwzContactName), _T("%s"), pszCustomUserName);
+
+ // Determine main icon
+ EnterCriticalSection(&csMsgTypes); // thread safety
+ iMsgType = GetMsgTypeID(pszMsgTypeSection, pszMsgTypeName);
+
+ if ((iMsgType >= 0) && ((int)pamtdMsgTypes[iMsgType].hIcon < 0))
+ hIconBuf = LoadSkinnedIcon((-1)*(int)pamtdMsgTypes[iMsgType].hIcon); // skinned icon
+ else if ((iMsgType >= 0) && pamtdMsgTypes[iMsgType].hIcon)
+ hIconBuf = pamtdMsgTypes[iMsgType].hIcon;
+ else
+ hIconBuf = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+
+ // Overlay small spam icon
+ if (hIconBuf)
+ ppd.lchIcon = OverlayIcon(hIconBuf, SkinGetIcon(DB_ICON_SPAMLAYER_SETTING, IDI_SPAM_LAYER, FALSE), GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
+
+ // I don't know if popup module author made it thread safe...
+ if (CallServiceSync(MS_POPUP_ADDPOPUPW, (WPARAM)&ppd, 0) > 0)
+ bReturn = TRUE;
+
+ if (ppd.lchIcon) DestroyIcon(ppd.lchIcon);
+ }
+ #else
+ if (ServiceExists(MS_POPUP_ADDPOPUPEX))
+ {
+ POPUPDATAEX ppd;
+ HICON hIconBuf;
+ char* pszText;
+
+ switch (dwFilterType)
+ {
+ case SFT_DISLIKEDMESSAGES_FILTER:
+ pszText = Translate("Disliked Message Alert!");
+ break;
+ case SFT_ADVERTISMENT_FILTER:
+ pszText = Translate("Advertisment Alert!");
+ break;
+ case SFT_ROBOT_FILTER:
+ pszText = Translate("Robot Alert!");
+ break;
+ default:
+ pszText = NULL;
+ }
+
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = hContact;
+ ppd.colorText = SkinGetColor(DB_COLOR_POPUPTEXT_SETTING, Translate("Popup Text"), Translate("Spam Filter"), RGB(255,255,255), FALSE);
+ ppd.colorBack = SkinGetColor(DB_COLOR_POPUPBACKGROUND_SETTING, Translate("Popup Background"), Translate("Spam Filter"), RGB(0,0,0), FALSE);
+ if (pszText)
+ mir_snprintf(ppd.lpzText, ARRAYSIZE(ppd.lpzText), "%s", pszText);
+ if (pszCustomUserName)
+ mir_snprintf(ppd.lpzContactName, ARRAYSIZE(ppd.lpzContactName), "%s", pszCustomUserName);
+
+ // Determine main icon
+ EnterCriticalSection(&csMsgTypes); // thread safety
+ iMsgType = GetMsgTypeID(pszMsgTypeSection, pszMsgTypeName);
+
+ if ((iMsgType >= 0) && ((int)pamtdMsgTypes[iMsgType].hIcon < 0))
+ hIconBuf = LoadSkinnedIcon((-1)*(int)pamtdMsgTypes[iMsgType].hIcon); // skinned icon
+ else if ((iMsgType >= 0) && pamtdMsgTypes[iMsgType].hIcon)
+ hIconBuf = pamtdMsgTypes[iMsgType].hIcon;
+ else
+ hIconBuf = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+
+ // Overlay small spam icon
+ if (hIconBuf)
+ ppd.lchIcon = OverlayIcon(hIconBuf, SkinGetIcon(DB_ICON_SPAMLAYER_SETTING, IDI_SPAM_LAYER, FALSE), GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
+
+ // Support for Popup Plus
+ if (ServiceExists(MS_POPUP_ADDCLASS))
+ {
+ ppd.skinBack = ppd.colorBack;
+ ppd.colorBack = POPUP_USE_SKINNED_BG;
+ ppd.lpzClass = (LPCTSTR)POPUP_CLASS_SPAM; // type "LPCTSTR" of lpzClass is wrong (or: POPUP_CLASS_DEFAULT)
+ }
+
+ // I don't know if popup module author made it thread safe...
+ if (CallServiceSync(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0) > 0)
+ bReturn = TRUE;
+
+ if (ppd.lchIcon) DestroyIcon(ppd.lchIcon);
+ }
+ #endif
+
+ // Support for OSD / WanneBeOSD
+ if (ServiceExists("OSD/Announce")) // no m_osd.h file yet available.. .don't like it :-/
+ {
+ WCHAR* pszText;
+
+ switch (dwFilterType)
+ {
+ case SFT_DISLIKEDMESSAGES_FILTER:
+ pszText = TranslateT("Disliked Message Alert!");
+ break;
+
+ case SFT_ADVERTISMENT_FILTER:
+ pszText = TranslateT("Advertisment Alert!");
+ break;
+
+ case SFT_ROBOT_FILTER:
+ pszText = TranslateT("Robot Alert!");
+ break;
+
+ default:
+ pszText = NULL;
+ }
+
+ if (pszText)
+ {
+ // I don't know if OSD module author made it thread safe...
+ // quite bad: return value of OSDAnnounce does not indicate anything (SendMessage result)
+ // bad unicode implementation (simply expects unicode text when wbosdW.dll is used)
+ // -> might cuase crashes (buffer overruns) when SF-Unicode is run with OSD-Ansi
+ if (CallService("OSD/Announce", (WPARAM)pszText, (LPARAM)0) == 0);
+ bReturn = TRUE;
+ }
+ }
+
+ return bReturn;
+}
+
+
+// -- Popup Available --
+
+BOOL IsPopupAvailable(BOOL bAlsoOSD)
+{
+ #if defined(UNICODE)
+ return (ServiceExists(MS_POPUP_ADDPOPUPW) || (bAlsoOSD ? ServiceExists("OSD/Announce") : FALSE));
+ #else
+ return (ServiceExists(MS_POPUP_ADDPOPUPEX) || (bAlsoOSD ? ServiceExists("OSD/Announce") : FALSE));
+ #endif
+}
+
+
+// ------------------------------------
+
+
+void InitPopup(void)
+{
+ // Add class (Support for PopupPlus)
+ #if !defined(UNICODE)
+ if (ServiceExists(MS_POPUP_ADDCLASS))
+ CallService(MS_POPUP_ADDCLASS, 0, (LPARAM)POPUP_CLASS_SPAM);
+ #endif
+
+ if (IsPopupAvailable(FALSE))
+ SkinAddNewIcon(DB_ICON_SPAMLAYER_SETTING, TranslateT("Spam Filter"), TranslateT("Spam Message Overlay"), IDI_SPAM_LAYER, FALSE);
+}
+
+
+void UninitPopup(void)
+{
} \ No newline at end of file
diff --git a/popup.h b/popup.h
index c37e8e8..83b75c4 100644
--- a/popup.h
+++ b/popup.h
@@ -1,39 +1,39 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_POPUP_H__
-#define SF_POPUP_H__ 1
-
-
-// -- Defines
-#define POPUP_CLASS_SPAM "Spam Alerts" // must not be translated
-
-// -- Prototypes
-void SetPopupMenuItem(BOOL bPopupsActivated, BOOL bGrayItem);
-
-BOOL ShowSpamPopup(const char* pszMsgTypeSection, const char* pszMsgTypeName, const WCHAR* pszCustomUserName, HANDLE hContact, DWORD dwFilterType);
-BOOL IsPopupAvailable(BOOL bAlsoOSD);
-
-void InitPopup(void);
-void UninitPopup(void);
-
-
-#endif // SF_POPUP_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_POPUP_H__
+#define SF_POPUP_H__ 1
+
+
+// -- Defines
+#define POPUP_CLASS_SPAM "Spam Alerts" // must not be translated
+
+// -- Prototypes
+void SetPopupMenuItem(BOOL bPopupsActivated, BOOL bGrayItem);
+
+BOOL ShowSpamPopup(const char* pszMsgTypeSection, const char* pszMsgTypeName, const WCHAR* pszCustomUserName, HANDLE hContact, DWORD dwFilterType);
+BOOL IsPopupAvailable(BOOL bAlsoOSD);
+
+void InitPopup(void);
+void UninitPopup(void);
+
+
+#endif // SF_POPUP_H__
diff --git a/regexp.c b/regexp.c
index 9f15df6..71cc199 100644
--- a/regexp.c
+++ b/regexp.c
@@ -1,225 +1,225 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Defines
-//#define DISABLE_REGEXP_SUPPORT
-
-// -- Includes
-#include "common.h"
-#include "Utilities/PCRE/include/pcre.h"
-
-// -- Variables
-HMODULE hPcreDLL = NULL;
-
-// -- Function Pointers
-int (*dyn_pcre_config)(int, void*);
-pcre* (*dyn_pcre_compile)(const char*, int, const char**, int*, const unsigned char*);
-pcre_extra* (*dyn_pcre_study)(const pcre*, int, const char **);
-int (*dyn_pcre_exec)(const pcre*, const pcre_extra*, const char*, int, int, int, int*, int);
-void (**dyn_pointer_pcre_free)(void*);
-#define dyn_pcre_free (*dyn_pointer_pcre_free);
-
-
-// -----------------------------------------
-
-
-BOOL RegExpExistsInString(const WCHAR* pszString, const WCHAR* pszRegEx, BOOL bCaseSensitive, BOOL* pbRegExMalformed)
-{
- if (pbRegExMalformed) *pbRegExMalformed = FALSE;
-
- if (!pszString || !pszRegEx) return FALSE;
-
- if (hPcreDLL)
- {
- int iRc;
- pcre* pPcre;
- pcre_extra* pExtra;
-
- // Following are dummy buffers that are needed for the functions to work
- const char* pszErr;
- int iErrOffset;
-
- // 1.) Interpret regular expression
- #if defined(UNICODE)
- {
- char* pszRegExUtf8 = mir_utf8encodeW(pszRegEx);
- if (pszRegExUtf8)
- {
- pPcre = dyn_pcre_compile(pszRegExUtf8, (bCaseSensitive ? 0 : PCRE_CASELESS)|PCRE_UTF8|PCRE_NO_UTF8_CHECK, &pszErr, &iErrOffset, NULL);
- mir_free(pszRegExUtf8);
- } else {
- pPcre = NULL;
- }
- }
- #else
- pPcre = dyn_pcre_compile(pszRegEx, (bCaseSensitive ? 0 : PCRE_CASELESS), &pszErr, &iErrOffset, NULL);
- #endif
-
- if (pPcre)
- {
- // 2.) Study regular expression (not necessary)
- pExtra = dyn_pcre_study(pPcre, 0, &pszErr);
-
- // 3.) Search for regular expression
- #if defined(UNICODE)
- {
- char* pszStringUtf8 = mir_utf8encodeW(pszString);
-
- if (pszStringUtf8)
- {
- iRc = dyn_pcre_exec(pPcre, pExtra, (char*)pszStringUtf8, (int)lstrlenA(pszStringUtf8), 0, PCRE_NOTEMPTY|PCRE_NO_UTF8_CHECK, NULL, 0);
- mir_free(pszStringUtf8);
- } else {
- iRc = 0;
- }
- }
- #else
- iRc = dyn_pcre_exec(pPcre, pExtra, pszString, (int)lstrlen(pszString), 0, PCRE_NOTEMPTY, NULL, 0);
- #endif
-
- // Release memory
- dyn_pcre_free(pPcre);
- if (pExtra) dyn_pcre_free(pExtra);
-
- return (iRc >= 0);
- } else {
- if (pbRegExMalformed)
- *pbRegExMalformed = TRUE;
-
- #if !defined(_DEBUG)
- if (!pbRegExMalformed)
- #endif
- {
- WCHAR szOut[128];
- mir_sntprintf(szOut, ARRAYSIZE(szOut), _T("Spam Filter: Syntax error in RegExp (%s).\r\n"), pszRegEx);
- OutputDebugString(szOut);
- }
- }
- }
-
- // Default string search (fallback)
- return (bCaseSensitive ? StrStr(pszString, pszRegEx) : StrStrI(pszString, pszRegEx)) ? TRUE : FALSE;
-}
-
-
-
-BOOL ValidateRegExp(const WCHAR* pszRegEx)
-{
- if (hPcreDLL)
- {
- pcre* pPcre;
- char* pszErr;
- int iErrOffset;
-
- // Parameter check
- if (!pszRegEx) return FALSE;
-
- // Interpret regular expression
- #if defined(UNICODE)
- {
- char* pszRegExUtf8 = mir_utf8encodeW(pszRegEx);
-
- if (pszRegExUtf8) {
- pPcre = dyn_pcre_compile(pszRegExUtf8, PCRE_UTF8|PCRE_NO_UTF8_CHECK, &pszErr, &iErrOffset, NULL);
- mir_free(pszRegExUtf8);
- } else {
- pPcre = NULL;
- }
- }
- #else
- pPcre = dyn_pcre_compile(pszRegEx, 0, &pszErr, &iErrOffset, NULL);
- #endif
-
- if (pPcre) {
- dyn_pcre_free(pPcre); // Release memory
- return TRUE;
- } else {
- return FALSE;
- }
-
- } else {
- return TRUE;
- }
-}
-
-
-BOOL RegExpEnabled(void)
-{
- return (hPcreDLL ? TRUE : FALSE);
-}
-
-
-// ------------------------------------
-
-
-void InitRegExp(void)
-{
- #if !defined(DISABLE_REGEXP_SUPPORT)
-
- hPcreDLL = LoadLibrary(_T("PCRE"));
- if (hPcreDLL)
- {
- // Exported functions
- // GetProcAddress returns the pointer to the function
- *(FARPROC*)&dyn_pcre_config = GetProcAddress(hPcreDLL, "pcre_config");
- *(FARPROC*)&dyn_pcre_compile = GetProcAddress(hPcreDLL, "pcre_compile");
- *(FARPROC*)&dyn_pcre_study = GetProcAddress(hPcreDLL, "pcre_study");
- *(FARPROC*)&dyn_pcre_exec = GetProcAddress(hPcreDLL, "pcre_exec");
-
- // Exported variables
- // GetProcAddress returns the pointer to the variable containing the pointer to the function...jippieh! :-)
- *(FARPROC*)&dyn_pointer_pcre_free = GetProcAddress(hPcreDLL, "pcre_free");
-
- if (dyn_pcre_compile && dyn_pcre_exec && dyn_pointer_pcre_free && (*dyn_pointer_pcre_free))
- {
- #if defined(UNICODE)
- int iUtf8Supported = 0;
-
- if (dyn_pcre_config)
- dyn_pcre_config(PCRE_CONFIG_UTF8, &iUtf8Supported);
-
- if (iUtf8Supported != 0)
- return;
- #else
- return;
- #endif
- }
-
- // Error: Unloading
- FreeLibrary(hPcreDLL);
- hPcreDLL = NULL;
- }
-
- // Debug output
- OutputDebugString(_T("Spam Filter: RegExp DLL (PCRE.DLL) not found or not compatible.\r\n"));
-
- #else
- // Debug output
- OutputDebugString(_T("Spam Filter: RegExp support disabled.\r\n"));
- #endif
-}
-
-
-void UninitRegExp(void)
-{
- if (hPcreDLL) FreeLibrary(hPcreDLL);
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Defines
+//#define DISABLE_REGEXP_SUPPORT
+
+// -- Includes
+#include "common.h"
+#include "Utilities/PCRE/include/pcre.h"
+
+// -- Variables
+HMODULE hPcreDLL = NULL;
+
+// -- Function Pointers
+int (*dyn_pcre_config)(int, void*);
+pcre* (*dyn_pcre_compile)(const char*, int, const char**, int*, const unsigned char*);
+pcre_extra* (*dyn_pcre_study)(const pcre*, int, const char **);
+int (*dyn_pcre_exec)(const pcre*, const pcre_extra*, const char*, int, int, int, int*, int);
+void (**dyn_pointer_pcre_free)(void*);
+#define dyn_pcre_free (*dyn_pointer_pcre_free);
+
+
+// -----------------------------------------
+
+
+BOOL RegExpExistsInString(const WCHAR* pszString, const WCHAR* pszRegEx, BOOL bCaseSensitive, BOOL* pbRegExMalformed)
+{
+ if (pbRegExMalformed) *pbRegExMalformed = FALSE;
+
+ if (!pszString || !pszRegEx) return FALSE;
+
+ if (hPcreDLL)
+ {
+ int iRc;
+ pcre* pPcre;
+ pcre_extra* pExtra;
+
+ // Following are dummy buffers that are needed for the functions to work
+ const char* pszErr;
+ int iErrOffset;
+
+ // 1.) Interpret regular expression
+ #if defined(UNICODE)
+ {
+ char* pszRegExUtf8 = mir_utf8encodeW(pszRegEx);
+ if (pszRegExUtf8)
+ {
+ pPcre = dyn_pcre_compile(pszRegExUtf8, (bCaseSensitive ? 0 : PCRE_CASELESS)|PCRE_UTF8|PCRE_NO_UTF8_CHECK, &pszErr, &iErrOffset, NULL);
+ mir_free(pszRegExUtf8);
+ } else {
+ pPcre = NULL;
+ }
+ }
+ #else
+ pPcre = dyn_pcre_compile(pszRegEx, (bCaseSensitive ? 0 : PCRE_CASELESS), &pszErr, &iErrOffset, NULL);
+ #endif
+
+ if (pPcre)
+ {
+ // 2.) Study regular expression (not necessary)
+ pExtra = dyn_pcre_study(pPcre, 0, &pszErr);
+
+ // 3.) Search for regular expression
+ #if defined(UNICODE)
+ {
+ char* pszStringUtf8 = mir_utf8encodeW(pszString);
+
+ if (pszStringUtf8)
+ {
+ iRc = dyn_pcre_exec(pPcre, pExtra, (char*)pszStringUtf8, (int)lstrlenA(pszStringUtf8), 0, PCRE_NOTEMPTY|PCRE_NO_UTF8_CHECK, NULL, 0);
+ mir_free(pszStringUtf8);
+ } else {
+ iRc = 0;
+ }
+ }
+ #else
+ iRc = dyn_pcre_exec(pPcre, pExtra, pszString, (int)lstrlen(pszString), 0, PCRE_NOTEMPTY, NULL, 0);
+ #endif
+
+ // Release memory
+ dyn_pcre_free(pPcre);
+ if (pExtra) dyn_pcre_free(pExtra);
+
+ return (iRc >= 0);
+ } else {
+ if (pbRegExMalformed)
+ *pbRegExMalformed = TRUE;
+
+ #if !defined(_DEBUG)
+ if (!pbRegExMalformed)
+ #endif
+ {
+ WCHAR szOut[128];
+ mir_sntprintf(szOut, ARRAYSIZE(szOut), _T("Spam Filter: Syntax error in RegExp (%s).\r\n"), pszRegEx);
+ OutputDebugString(szOut);
+ }
+ }
+ }
+
+ // Default string search (fallback)
+ return (bCaseSensitive ? StrStr(pszString, pszRegEx) : StrStrI(pszString, pszRegEx)) ? TRUE : FALSE;
+}
+
+
+
+BOOL ValidateRegExp(const WCHAR* pszRegEx)
+{
+ if (hPcreDLL)
+ {
+ pcre* pPcre;
+ char* pszErr;
+ int iErrOffset;
+
+ // Parameter check
+ if (!pszRegEx) return FALSE;
+
+ // Interpret regular expression
+ #if defined(UNICODE)
+ {
+ char* pszRegExUtf8 = mir_utf8encodeW(pszRegEx);
+
+ if (pszRegExUtf8) {
+ pPcre = dyn_pcre_compile(pszRegExUtf8, PCRE_UTF8|PCRE_NO_UTF8_CHECK, &pszErr, &iErrOffset, NULL);
+ mir_free(pszRegExUtf8);
+ } else {
+ pPcre = NULL;
+ }
+ }
+ #else
+ pPcre = dyn_pcre_compile(pszRegEx, 0, &pszErr, &iErrOffset, NULL);
+ #endif
+
+ if (pPcre) {
+ dyn_pcre_free(pPcre); // Release memory
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+
+ } else {
+ return TRUE;
+ }
+}
+
+
+BOOL RegExpEnabled(void)
+{
+ return (hPcreDLL ? TRUE : FALSE);
+}
+
+
+// ------------------------------------
+
+
+void InitRegExp(void)
+{
+ #if !defined(DISABLE_REGEXP_SUPPORT)
+
+ hPcreDLL = LoadLibrary(_T("PCRE"));
+ if (hPcreDLL)
+ {
+ // Exported functions
+ // GetProcAddress returns the pointer to the function
+ *(FARPROC*)&dyn_pcre_config = GetProcAddress(hPcreDLL, "pcre_config");
+ *(FARPROC*)&dyn_pcre_compile = GetProcAddress(hPcreDLL, "pcre_compile");
+ *(FARPROC*)&dyn_pcre_study = GetProcAddress(hPcreDLL, "pcre_study");
+ *(FARPROC*)&dyn_pcre_exec = GetProcAddress(hPcreDLL, "pcre_exec");
+
+ // Exported variables
+ // GetProcAddress returns the pointer to the variable containing the pointer to the function...jippieh! :-)
+ *(FARPROC*)&dyn_pointer_pcre_free = GetProcAddress(hPcreDLL, "pcre_free");
+
+ if (dyn_pcre_compile && dyn_pcre_exec && dyn_pointer_pcre_free && (*dyn_pointer_pcre_free))
+ {
+ #if defined(UNICODE)
+ int iUtf8Supported = 0;
+
+ if (dyn_pcre_config)
+ dyn_pcre_config(PCRE_CONFIG_UTF8, &iUtf8Supported);
+
+ if (iUtf8Supported != 0)
+ return;
+ #else
+ return;
+ #endif
+ }
+
+ // Error: Unloading
+ FreeLibrary(hPcreDLL);
+ hPcreDLL = NULL;
+ }
+
+ // Debug output
+ OutputDebugString(_T("Spam Filter: RegExp DLL (PCRE.DLL) not found or not compatible.\r\n"));
+
+ #else
+ // Debug output
+ OutputDebugString(_T("Spam Filter: RegExp support disabled.\r\n"));
+ #endif
+}
+
+
+void UninitRegExp(void)
+{
+ if (hPcreDLL) FreeLibrary(hPcreDLL);
} \ No newline at end of file
diff --git a/regexp.h b/regexp.h
index 4972b6d..a6cc3d4 100644
--- a/regexp.h
+++ b/regexp.h
@@ -1,35 +1,35 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_REGEXP_H__
-#define SF_REGEXP_H__ 1
-
-
-// -- Prototypes
-BOOL RegExpExistsInString(const WCHAR* pszString, const WCHAR* pszRegEx, BOOL bCaseSensitive, BOOL* pbRegExInvalid);
-BOOL ValidateRegExp(const WCHAR* pszRegEx);
-BOOL RegExpEnabled(void);
-
-void InitRegExp(void);
-void UninitRegExp(void);
-
-
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_REGEXP_H__
+#define SF_REGEXP_H__ 1
+
+
+// -- Prototypes
+BOOL RegExpExistsInString(const WCHAR* pszString, const WCHAR* pszRegEx, BOOL bCaseSensitive, BOOL* pbRegExInvalid);
+BOOL ValidateRegExp(const WCHAR* pszRegEx);
+BOOL RegExpEnabled(void);
+
+void InitRegExp(void);
+void UninitRegExp(void);
+
+
#endif // SF_REGEXP_H__ \ No newline at end of file
diff --git a/resource.h b/resource.h
index 37e7d5b..ceaaa3f 100644
--- a/resource.h
+++ b/resource.h
@@ -1,139 +1,139 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by SpamFilter.rc
-//
-#define IDI_DEFAULT 101
-#define IDI_DEFAULT_LARGE 102
-#define IDI_SPAM_LAYER 103
-#define IDI_ADD_BUTTON 104
-#define IDI_DELETE_BUTTON 105
-#define IDI_SPAM_DEFINITIONS 106
-#define IDD_OPTIONS_MAIN 107
-#define IDD_OPTIONS_CONFIGURE_ADVERTISMENTFILTER 108
-#define IDD_OPTIONS_CONFIGURE_ROBOTFILTER 109
-#define IDD_OPTIONS_CONFIGURE_DISLIKEDMESSAGEFILTER 110
-#define IDD_LISTBOX_ADD_ITEM 111
-#define IDD_INFO_SPAMDEFINITIONS 112
-#define IDD_INFO_SPAMMERS 113
-#define IDR_CONTEXT 114
-#define IDR_XMLFILETEMPLATE 115
-#define IDR_XMLITEMTEMPLATE 116
-#define IDR_XSLLAYOUTFILETEMPLATE 117
-#define IDC_TEXT_DESCRIPTION 1001
-#define IDC_EDITBOX_INSTRUCTION 1002
-#define IDC_GROUP_BEHAVIOUR 1003
-#define IDC_GROUP_SPAMMERS 1004
-#define IDC_GROUP_MESSAGETYPES 1005
-#define IDC_EDITBOX_CONFIRMATION 1006
-#define IDC_GROUP_LOGGING 1007
-#define IDC_CHECKBOX_LOGGING 1008
-#define IDC_CHECKBOX_POPUP 1009
-#define IDC_CHECKBOX_CAPITALIZED 1010
-#define IDC_EDITBOX_NEWITEM 1011
-#define IDC_EDITBOX_LOGFILE 1012
-#define IDC_CHECKBOX_EMPTY 1013
-#define IDC_GROUP_IGNORE 1014
-#define IDC_EDITBOX_ALLOWEDBADWORDS 1015
-#define IDC_EDITBOX_ALLOWEDGOODWORDS 1016
-#define IDC_EDITBOX_ALLOWEDFORMATEDWORDS 1017
-#define IDC_EDITBOX_ALLOWEDSPAMMESSAGES 1018
-#define IDC_BUTTON_LOGBROWSE 1019
-#define IDC_RADIO_MARKREADMSG 1020
-#define IDC_RADIO_DELETEMSG 1021
-#define IDC_TEXT_ALLOWEDBADWORDS 1022
-#define IDC_SPIN_ALLOWEDBADWORDS 1023
-#define IDC_TEXT_ALLOWEDGOODWORDS 1024
-#define IDC_TEXT_ALLOWEDFORMATEDWORDS 1025
-#define IDC_SPIN_ALLOWEDGOODWORDS 1026
-#define IDC_SPIN_ALLOWEDFORMATEDWORDS 1027
-#define IDC_CHECKBOX_FORMATING 1028
-#define IDC_TEXT_ALLOWEDSPAMMESSAGES 1029
-#define IDC_SPIN_ALLOWEDSPAMMESSAGES 1030
-#define IDC_CHECKBOX_ADVERTISMENTFILTER 1031
-#define IDC_BUTTON_ADVERTISMENTFILTER 1032
-#define IDC_TEXT_ADVERTISMENTFILTER 1033
-#define IDC_CHECKBOX_DISLIKEDMESSAGEFILTER 1034
-#define IDC_BUTTON_DISLIKEDMESSAGEFILTER 1035
-#define IDC_TEXT_DISLIKEDMESSAGEFILTER 1036
-#define IDC_CHECKBOX_AUTOADDSPAMMERS 1037
-#define IDC_LISTBOX_CUSTOMIZEDWORDS 1038
-#define IDC_CHECKBOX_ROBOTFILTER 1039
-#define IDC_CHECKBOX_NOTIFYSENDER 1040
-#define IDC_TEXT_ROBOTFILTER 1041
-#define IDC_LISTBOX_CUSTOMIZEDGOODWORDS 1042
-#define IDC_BUTTON_ROBOTFILTER 1043
-#define IDC_GROUP_WORDS 1044
-#define IDC_GROUP_NOTIFYSENDER 1045
-#define IDC_GROUP_OTHERCONTENTS 1046
-#define IDC_GROUP_BADWORDS 1047
-#define IDC_CHECKBOX_DEFAULTSPAMMERS 1048
-#define IDC_CHECKBOX_HOAXTEXTS 1049
-#define IDC_GROUP_GOODWORDS 1050
-#define IDC_CHECKBOX_CUSTOMIZEDWORDS 1051
-#define IDC_CHECKBOX_URL 1052
-#define IDC_BUTTON_ADDWORD 1053
-#define IDC_BUTTON_DELETEWORD 1054
-#define IDC_CHECKBOX_CUSTOMIZEDGOODWORDS 1055
-#define IDC_EDITBOX_NOTIFYSENDER 1056
-#define IDC_BUTTON_ADDGOODWORD 1057
-#define IDC_TEXT_NOTIFYSENDER 1058
-#define IDC_BUTTON_DELETEGOODWORD 1059
-#define IDC_CHECKBOX_MULTIPLEMESSAGES 1060
-#define IDC_CHECKBOX_PHONENUMBERS 1061
-#define IDC_BUTTON_OPENLOG 1062
-#define IDC_CHECKBOX_TEASERMESSAGES 1063
-#define IDC_BUTTON_RESETAUTOIGNORE 1064
-#define IDC_LISTBOX_CUSTOMIZEDBADWORDS 1065
-#define IDC_BUTTON_SHOWSPAMMERS 1066
-#define IDC_BUTTON_ADDBADWORD 1067
-#define IDC_BUTTON_DELETEBADWORD 1068
-#define IDC_CHECKBOX_CUSTOMIZEDBADWORDS 1069
-#define IDC_CHECKBOX_DEFAULTBADWORDS 1070
-#define IDC_TREEVIEW_MESSAGETYPES 1071
-#define IDC_TEXT_MESSAGETYPES 1072
-#define IDC_CHECKBOX_ADDTOHISTORY 1073
-#define IDC_GROUP_MESSAGETEXTS 1074
-#define IDC_GROUP_ANSWER 1075
-#define IDC_EDITBOX_ANSWER 1076
-#define IDC_BUTTON_ANSWER 1077
-#define IDC_TEXT_REGEXP 1078
-#define IDC_CHECKBOX_ADDTOHISTORY2 1078
-#define IDC_BUTTON_REGEXP 1079
-#define IDC_CLIST 1080
-#define IDC_BUTTON_NOTIFYSENDER_VARIABLES 1081
-#define IDC_TEXT_VARS 1082
-#define IDC_BUTTON_CONFIRMATION_VARIABLES 1083
-#define IDC_BUTTON_INSTRUCTION_VARIABLES 1084
-#define IDC_TEXT_WARNING 1085
-#define IDC_TEXT_QUICKHELP 1086
-#define IDC_TEXT_HELPNESTED 1087
-#define IDC_RECT_SEPARATOR 1088
-#define IDC_LISTVIEW_SPAMDEFINITIONS 1089
-#define IDC_BUTTON_SPAMDEFINITIONS 1090
-#define IDC_URL_GETMORE 1091
-#define IDC_SCROLLBAR_SIZEGRIP 1092
-#define IDC_TAB_SPAMDEFINITIONS 1093
-#define IDC_ICON_SPAM 1094
-#define IDC_TEXT_SPAM 1095
-#define IDC_ICON_DELETE 1096
-#define IDC_TEXT_DELETE 1097
-#define IDC_ICON_NORMAL 1098
-#define IDC_TEXT_NORMAL 1099
-#define IDC_EDITBOX_GROUP 1100
-#define IDC_CHECKBOX_GROUP 1101
-#define IDC_CHECKBOX_HIDE 1102
-#define IDC_GROUP 1103
-#define ID_MENU_ADD 40001
-#define ID_MENU_DELETE 40002
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NO_MFC 1
-#define _APS_NEXT_RESOURCE_VALUE 118
-#define _APS_NEXT_COMMAND_VALUE 40003
-#define _APS_NEXT_CONTROL_VALUE 1104
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by SpamFilter.rc
+//
+#define IDI_DEFAULT 101
+#define IDI_DEFAULT_LARGE 102
+#define IDI_SPAM_LAYER 103
+#define IDI_ADD_BUTTON 104
+#define IDI_DELETE_BUTTON 105
+#define IDI_SPAM_DEFINITIONS 106
+#define IDD_OPTIONS_MAIN 107
+#define IDD_OPTIONS_CONFIGURE_ADVERTISMENTFILTER 108
+#define IDD_OPTIONS_CONFIGURE_ROBOTFILTER 109
+#define IDD_OPTIONS_CONFIGURE_DISLIKEDMESSAGEFILTER 110
+#define IDD_LISTBOX_ADD_ITEM 111
+#define IDD_INFO_SPAMDEFINITIONS 112
+#define IDD_INFO_SPAMMERS 113
+#define IDR_CONTEXT 114
+#define IDR_XMLFILETEMPLATE 115
+#define IDR_XMLITEMTEMPLATE 116
+#define IDR_XSLLAYOUTFILETEMPLATE 117
+#define IDC_TEXT_DESCRIPTION 1001
+#define IDC_EDITBOX_INSTRUCTION 1002
+#define IDC_GROUP_BEHAVIOUR 1003
+#define IDC_GROUP_SPAMMERS 1004
+#define IDC_GROUP_MESSAGETYPES 1005
+#define IDC_EDITBOX_CONFIRMATION 1006
+#define IDC_GROUP_LOGGING 1007
+#define IDC_CHECKBOX_LOGGING 1008
+#define IDC_CHECKBOX_POPUP 1009
+#define IDC_CHECKBOX_CAPITALIZED 1010
+#define IDC_EDITBOX_NEWITEM 1011
+#define IDC_EDITBOX_LOGFILE 1012
+#define IDC_CHECKBOX_EMPTY 1013
+#define IDC_GROUP_IGNORE 1014
+#define IDC_EDITBOX_ALLOWEDBADWORDS 1015
+#define IDC_EDITBOX_ALLOWEDGOODWORDS 1016
+#define IDC_EDITBOX_ALLOWEDFORMATEDWORDS 1017
+#define IDC_EDITBOX_ALLOWEDSPAMMESSAGES 1018
+#define IDC_BUTTON_LOGBROWSE 1019
+#define IDC_RADIO_MARKREADMSG 1020
+#define IDC_RADIO_DELETEMSG 1021
+#define IDC_TEXT_ALLOWEDBADWORDS 1022
+#define IDC_SPIN_ALLOWEDBADWORDS 1023
+#define IDC_TEXT_ALLOWEDGOODWORDS 1024
+#define IDC_TEXT_ALLOWEDFORMATEDWORDS 1025
+#define IDC_SPIN_ALLOWEDGOODWORDS 1026
+#define IDC_SPIN_ALLOWEDFORMATEDWORDS 1027
+#define IDC_CHECKBOX_FORMATING 1028
+#define IDC_TEXT_ALLOWEDSPAMMESSAGES 1029
+#define IDC_SPIN_ALLOWEDSPAMMESSAGES 1030
+#define IDC_CHECKBOX_ADVERTISMENTFILTER 1031
+#define IDC_BUTTON_ADVERTISMENTFILTER 1032
+#define IDC_TEXT_ADVERTISMENTFILTER 1033
+#define IDC_CHECKBOX_DISLIKEDMESSAGEFILTER 1034
+#define IDC_BUTTON_DISLIKEDMESSAGEFILTER 1035
+#define IDC_TEXT_DISLIKEDMESSAGEFILTER 1036
+#define IDC_CHECKBOX_AUTOADDSPAMMERS 1037
+#define IDC_LISTBOX_CUSTOMIZEDWORDS 1038
+#define IDC_CHECKBOX_ROBOTFILTER 1039
+#define IDC_CHECKBOX_NOTIFYSENDER 1040
+#define IDC_TEXT_ROBOTFILTER 1041
+#define IDC_LISTBOX_CUSTOMIZEDGOODWORDS 1042
+#define IDC_BUTTON_ROBOTFILTER 1043
+#define IDC_GROUP_WORDS 1044
+#define IDC_GROUP_NOTIFYSENDER 1045
+#define IDC_GROUP_OTHERCONTENTS 1046
+#define IDC_GROUP_BADWORDS 1047
+#define IDC_CHECKBOX_DEFAULTSPAMMERS 1048
+#define IDC_CHECKBOX_HOAXTEXTS 1049
+#define IDC_GROUP_GOODWORDS 1050
+#define IDC_CHECKBOX_CUSTOMIZEDWORDS 1051
+#define IDC_CHECKBOX_URL 1052
+#define IDC_BUTTON_ADDWORD 1053
+#define IDC_BUTTON_DELETEWORD 1054
+#define IDC_CHECKBOX_CUSTOMIZEDGOODWORDS 1055
+#define IDC_EDITBOX_NOTIFYSENDER 1056
+#define IDC_BUTTON_ADDGOODWORD 1057
+#define IDC_TEXT_NOTIFYSENDER 1058
+#define IDC_BUTTON_DELETEGOODWORD 1059
+#define IDC_CHECKBOX_MULTIPLEMESSAGES 1060
+#define IDC_CHECKBOX_PHONENUMBERS 1061
+#define IDC_BUTTON_OPENLOG 1062
+#define IDC_CHECKBOX_TEASERMESSAGES 1063
+#define IDC_BUTTON_RESETAUTOIGNORE 1064
+#define IDC_LISTBOX_CUSTOMIZEDBADWORDS 1065
+#define IDC_BUTTON_SHOWSPAMMERS 1066
+#define IDC_BUTTON_ADDBADWORD 1067
+#define IDC_BUTTON_DELETEBADWORD 1068
+#define IDC_CHECKBOX_CUSTOMIZEDBADWORDS 1069
+#define IDC_CHECKBOX_DEFAULTBADWORDS 1070
+#define IDC_TREEVIEW_MESSAGETYPES 1071
+#define IDC_TEXT_MESSAGETYPES 1072
+#define IDC_CHECKBOX_ADDTOHISTORY 1073
+#define IDC_GROUP_MESSAGETEXTS 1074
+#define IDC_GROUP_ANSWER 1075
+#define IDC_EDITBOX_ANSWER 1076
+#define IDC_BUTTON_ANSWER 1077
+#define IDC_TEXT_REGEXP 1078
+#define IDC_CHECKBOX_ADDTOHISTORY2 1078
+#define IDC_BUTTON_REGEXP 1079
+#define IDC_CLIST 1080
+#define IDC_BUTTON_NOTIFYSENDER_VARIABLES 1081
+#define IDC_TEXT_VARS 1082
+#define IDC_BUTTON_CONFIRMATION_VARIABLES 1083
+#define IDC_BUTTON_INSTRUCTION_VARIABLES 1084
+#define IDC_TEXT_WARNING 1085
+#define IDC_TEXT_QUICKHELP 1086
+#define IDC_TEXT_HELPNESTED 1087
+#define IDC_RECT_SEPARATOR 1088
+#define IDC_LISTVIEW_SPAMDEFINITIONS 1089
+#define IDC_BUTTON_SPAMDEFINITIONS 1090
+#define IDC_URL_GETMORE 1091
+#define IDC_SCROLLBAR_SIZEGRIP 1092
+#define IDC_TAB_SPAMDEFINITIONS 1093
+#define IDC_ICON_SPAM 1094
+#define IDC_TEXT_SPAM 1095
+#define IDC_ICON_DELETE 1096
+#define IDC_TEXT_DELETE 1097
+#define IDC_ICON_NORMAL 1098
+#define IDC_TEXT_NORMAL 1099
+#define IDC_EDITBOX_GROUP 1100
+#define IDC_CHECKBOX_GROUP 1101
+#define IDC_CHECKBOX_HIDE 1102
+#define IDC_GROUP 1103
+#define ID_MENU_ADD 40001
+#define ID_MENU_DELETE 40002
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 118
+#define _APS_NEXT_COMMAND_VALUE 40003
+#define _APS_NEXT_CONTROL_VALUE 1104
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/services.c b/services.c
index 188cf41..0b66506 100644
--- a/services.c
+++ b/services.c
@@ -1,2038 +1,2038 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-// -- Includes
-#include "common.h"
-
-// -- Variables: Events/Hooks
-HANDLE hEventPreRegisterMessageType = NULL;
-HANDLE hEventOkToSpamCheck = NULL;
-HANDLE hEventOkToSpamDetection = NULL;
-HANDLE hEventSpamReceived = NULL;
-HANDLE hEventModuleLoaded = NULL;
-HANDLE hEventContactSpammerStateChanged = NULL;
-
-// -- Variables: Services
-HANDLE* hServices[19] = {NULL};
-
-
-// -----------------------------------------
-
-// Service: MS_SPAMFILTER_GETHANDLE
-static int ServiceGetHandle(WPARAM wParam, LPARAM lParam)
-{
- switch ((UINT)wParam)
- {
- //case 1: return NULL; // hInstance was removed in v2.5.1.0
-
- case SFHT_HWND_PLUGIN_OPTIONS: return IsWindow(hwndSpamFilterOpt) ? (int)hwndSpamFilterOpt : (int)NULL;
- case SFHT_HWND_ADVERTISMENT_FILTER: return IsWindow(hwndAdvertismentFilter) ? (int)hwndAdvertismentFilter : (int)NULL;
- case SFHT_HWND_ROBOT_FILTER: return IsWindow(hwndRobotFilter) ? (int)hwndRobotFilter : (int)NULL;
- case SFHT_HWND_DISLIKEDMESSAGES_FILTER: return IsWindow(hwndDislikedMessagesFilter) ? (int)hwndDislikedMessagesFilter : (int)NULL;
- case SFHT_HWND_SPAMDEFINITIONS_INFO: return IsWindow(hwndSpamDefinitionsInfo) ? (int)hwndSpamDefinitionsInfo : (int)NULL;
- case SFHT_HWND_SPAMMERS_INFO: return IsWindow(hwndSpammersInfo) ? (int)hwndSpammersInfo : (int)NULL;
-
- case SFHT_HICON_SPAM: return (int)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
- case SFHT_HICON_SPAM_LARGE: return (int)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT_LARGE), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
- case SFHT_HICON_SPAM_LAYER: return (int)LoadImage(hInstance, MAKEINTRESOURCE(IDI_SPAM_LAYER), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
-
- case 100: // backward compatibility
- #if defined(UNICODE)
- case SFHT_BOOL_IS_UNICODE: return TRUE;
- #else
- case SFHT_BOOL_IS_UNICODE: return FALSE;
- #endif
-
- default: return (int)NULL;
- }
-}
-
-
-// Service: MS_SPAMFILTER_SHOWERROR
-static int ServiceShowError(WPARAM wParam, LPARAM lParam)
-{
- switch ((UINT)wParam)
- {
- case SFSE_CRITICAL_ERROR:
- {
- ShowInfoMessage(NIIF_ERROR, TranslateW("Spam Filter Critical Error"), TranslateW("A very critical internal error was detected!\r\nProbably the filter will not work at all.\r\n\r\nPlease update to the most current version if this problem persists."), 0);
- return 0;
- }
-
- case SFSE_SEND_FAILED:
- {
- WCHAR* pszUserName;
- if (lParam && (((SPAMCHECKDATA*)lParam)->cbSize < sizeof(SPAMCHECKDATA))) return 1;
- pszUserName = lParam?SCD_GetContactCustomDisplayName((SPAMCHECKDATA*)lParam):NULL;
- ShowInfoMessage(NIIF_WARNING, TranslateW("Spam Filter Error"), TranslateW("Spam Filter was not able to send an automated message to the user \"%s\"."), pszUserName?lstrlen(pszUserName):0, pszUserName?pszUserName:_T(""));
- if (pszUserName) mir_free(pszUserName);
- return 0;
- }
-
- default:
- return 1;
- }
-}
-
-
-// Service: MS_SPAMFILTER_COPYSPAMCHECKDATA
-static int ServiceCopySpamCheckData(WPARAM wParam, LPARAM lParam)
-{
- SPAMCHECKDATA* to = (SPAMCHECKDATA*)wParam;
- SPAMCHECKDATA* from = (SPAMCHECKDATA*)lParam;
-
-
- if (!from || !to || (from && (from->cbSize < sizeof(SPAMCHECKDATA))) ) {
- if (to) to->cbSize = sizeof(SPAMCHECKDATA);
- return 1;
- }
- CopyMemory(to, from, from->cbSize);
- if (to->pszMsgTypeName) to->pszMsgTypeName = mir_strdup(to->pszMsgTypeName);
- if (to->pszMsgTypeSection) to->pszMsgTypeSection = mir_strdup(to->pszMsgTypeSection);
- if (to->pszMsgText) {
- if (to->dwFlags&SCDF_UNICODE)
- to->pszMsgText = mir_strdup(to->pszMsgText);
- else
- to->pwszMsgText = mir_wstrdup(to->pwszMsgText);
- }
- if ((to->dwFlags&SCDF_NO_CONTACT) && to->pszUserName) {
- if (to->dwFlags&SCDF_UNICODE)
- to->pszUserName = mir_strdup(to->pszUserName);
- else
- to->pwszUserName = mir_wstrdup(to->pwszUserName);
- }
- to->cbSize = sizeof(SPAMCHECKDATA);
- return 0;
-}
-
-
-// Service: MS_SPAMFILTER_FREESPAMCHECKDATA
-static int ServiceFreeSpamCheckData(WPARAM wParam, LPARAM lParam)
-{
- SPAMCHECKDATA* pscd = (SPAMCHECKDATA*)wParam;
-
- if (!pscd || (pscd->cbSize < sizeof(SPAMCHECKDATA))) return 1;
- if (pscd->pszMsgTypeName) mir_free(pscd->pszMsgTypeName);
- if (pscd->pszMsgTypeSection) mir_free(pscd->pszMsgTypeSection);
- if (pscd->ptszMsgText) mir_free(pscd->ptszMsgText);
- if ((pscd->dwFlags&SCDF_NO_CONTACT) && pscd->ptszUserName) mir_free(pscd->ptszUserName);
- return 0;
-}
-
-
-// Service: MS_SPAMFILTER_SHOWFILTERDIALOG
-static int ServiceShowFilterDialog(WPARAM wParam, LPARAM lParam)
-{
- HWND hwndParent = (HWND)wParam;
- DWORD dwFilterType = (DWORD)lParam;
-
- if (dwFilterType&SFTEXF_SPAMDEFINITIONS_INFO)
- {
- INITCOMMONCONTROLSEX icc;
-
- dwFilterType ^= SFTEXF_SPAMDEFINITIONS_INFO;
- if ((dwFilterType != SFT_ADVERTISMENT_FILTER) && (dwFilterType != SFT_DISLIKEDMESSAGES_FILTER))
- return 1;
-
- if (IsWindow(hwndSpamDefinitionsInfo))
- {
- PostMessage(hwndSpamDefinitionsInfo, SFM_REFRESH_SPAMDEFINITIONS, (WPARAM)FALSE, (LPARAM)dwFilterType);
- SetForegroundWindow(hwndSpamDefinitionsInfo);
- return 0;
- }
-
- // Ensure the needed common controls are loaded
- ZeroMemory(&icc, sizeof(icc));
- icc.dwSize = sizeof(icc);
- icc.dwICC = ICC_TAB_CLASSES|ICC_LISTVIEW_CLASSES;
- InitCommonControlsEx(&icc);
-
- if (hwndParent) {
- // hwndSpamDefinitionsInfo will be set on WM_INITDIALOG and set to NULL on WM_DESTROY
- // *** using ANSI version here because Hyperlink control of Miranda doesn't support Unicode ***
- //return (DialogBoxParamA(hInstance, MAKEINTRESOURCEA(IDD_INFO_SPAMDEFINITIONS), hwndParent, DlgProcSpamDefinitionsInfo, dwFilterType)>0) ? 0 : 1;
- return (DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_INFO_SPAMDEFINITIONS), hwndParent, DlgProcSpamDefinitionsInfo, dwFilterType)>0) ? 0 : 1;
-
- } else {
- // *** using ANSI version here because Hyperlink control of Miranda doesn't (yet) support Unicode ***
- //hwndSpamDefinitionsInfo = CreateDialogParamA(hInstance, MAKEINTRESOURCEA(IDD_INFO_SPAMDEFINITIONS), (HWND)NULL, DlgProcSpamDefinitionsInfo, dwFilterType);
- hwndSpamDefinitionsInfo = CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_INFO_SPAMDEFINITIONS), (HWND)NULL, DlgProcSpamDefinitionsInfo, dwFilterType);
- return (hwndSpamDefinitionsInfo ? 0 : 1);
- }
-
- } else if (dwFilterType&SFTEXF_SPAMMERS_INFO)
- {
- dwFilterType ^= SFTEXF_SPAMMERS_INFO;
- if (dwFilterType != SFTEX_OPTIONS_PAGE)
- return 1;
-
- if (IsWindow(hwndSpammersInfo)) {
- SetForegroundWindow(hwndSpammersInfo);
- return 0;
- }
-
- if (hwndParent) {
- // hwndSpammersInfo will be set on WM_INITDIALOG and set to NULL on WM_DESTROY
- return (DialogBox(hInstance, MAKEINTRESOURCE(IDD_INFO_SPAMMERS), hwndParent, DlgProcSpammersInfo)>0) ? 0 : 1;
-
- } else {
- hwndSpammersInfo = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_INFO_SPAMMERS), (HWND)NULL, DlgProcSpammersInfo);
- return (hwndSpammersInfo ? 0 : 1);
- }
-
- } else {
-
- switch (dwFilterType)
- {
- case SFTEX_OPTIONS_PAGE:
- {
- OPENOPTIONSDIALOG ood;
-
- ZeroMemory(&ood, sizeof(ood));
- ood.cbSize = sizeof(ood);
- ood.pszGroup = Translate("Events");
- ood.pszPage = Translate("Spam Filter");
-
- return CallService(MS_OPT_OPENOPTIONS, 0, (LPARAM)&ood);
- }
-
- case SFT_DISLIKEDMESSAGES_FILTER:
- {
- if (IsWindow(hwndDislikedMessagesFilter)) {
- SetForegroundWindow(hwndDislikedMessagesFilter);
- return 0;
- }
-
- if (hwndParent) {
- // hwndDislikedMessagesFilter will be set on WM_INITDIALOG and set to NULL on WM_DESTROY
- return (DialogBox(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_DISLIKEDMESSAGEFILTER), hwndParent, DlgProcConfigureDislikedMessagesFilter)>0) ? 0 : 1;
-
- } else {
- hwndDislikedMessagesFilter = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_DISLIKEDMESSAGEFILTER), (HWND)NULL, DlgProcConfigureDislikedMessagesFilter);
- return (hwndDislikedMessagesFilter ? 0 : 1);
- }
- }
-
- case SFT_ADVERTISMENT_FILTER:
- {
- INITCOMMONCONTROLSEX icc;
-
- if (IsWindow(hwndAdvertismentFilter)) {
- SetForegroundWindow(hwndAdvertismentFilter);
- return 0;
- }
-
- // Ensure the needed common controls are loaded
- ZeroMemory(&icc, sizeof(icc));
- icc.dwSize = sizeof(icc);
- icc.dwICC = ICC_UPDOWN_CLASS;
- InitCommonControlsEx(&icc);
-
- if (hwndParent) {
- // hwndAdvertismentFilter will be set on WM_INITDIALOG and set to NULL on WM_DESTROY
- return (DialogBox(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_ADVERTISMENTFILTER), hwndParent, DlgProcConfigureAdvertismentFilter)>0) ? 0 : 1;
-
- } else {
- hwndAdvertismentFilter = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_ADVERTISMENTFILTER), (HWND)NULL, DlgProcConfigureAdvertismentFilter);
- return (hwndAdvertismentFilter ? 0 : 1);
- }
- }
-
- case SFT_ROBOT_FILTER:
- {
- if (IsWindow(hwndRobotFilter)) {
- SetForegroundWindow(hwndRobotFilter);
- return 0;
- }
-
- if (hwndParent) {
- // hwndRobotFilter will be set on WM_INITDIALOG and set to NULL on WM_DESTROY
- return (DialogBox(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_ROBOTFILTER), hwndParent, DlgProcConfigureRobotFilter)>0) ? 0 : 1;
-
- } else {
- hwndRobotFilter = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_ROBOTFILTER), (HWND)NULL, DlgProcConfigureRobotFilter);
- return (hwndRobotFilter ? 0 : 1);
- }
- }
-
- default:
- return 1;
- }
-
- }
-}
-
-
-// Service: MS_SPAMFILTER_RESETAUTOIGNORE
-static int EnumAutoIgnoreSettingsProc(const char* pszSetting, LPARAM lParam)
-{
- WCHAR* pszBuf;
- mir_utf8decode((char*)pszSetting,&pszBuf);
- if (pszBuf) {
- SLAddItem((STRINGLIST*)lParam, pszBuf);
- mir_free(pszBuf);
- }
- return 0;
-}
-
-static int ServiceResetAutoIgnore(WPARAM wParam, LPARAM lParam)
-{
- BOOL bOnlyCount = (BOOL)wParam;
-
- int iReturn;
- DBCONTACTENUMSETTINGS dbces;
- STRINGLIST* pslSettings = SLNewList();
- int i;
- #if defined(UNICODE)
- char* pszBuf;
- #endif
-
- // Enum settings
- dbces.szModule = DB_MODULE_NAME_PRESPAMMERS;
- dbces.pfnEnumProc = EnumAutoIgnoreSettingsProc;
- dbces.lParam = (LPARAM)pslSettings;
-
- CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces);
-
- // Delete settings
- if (!bOnlyCount)
- {
- iReturn = 0;
- for (i=SL_MIN_POS; i<=SLGetMaxPos(pslSettings); i++)
- {
- #if defined(UNICODE)
- pszBuf = mir_utf8encodeW(SLGetItem(pslSettings, i));
- if (pszBuf)
- {
- if (DBDeleteContactSetting(NULL, dbces.szModule, pszBuf) != 0)
- iReturn++;
- }
- #else
- if (DBDeleteContactSetting(NULL, dbces.szModule, SLGetItem(pslSettings, i)) != 0)
- iReturn++;
- #endif
- }
- } else {
- iReturn = SLGetItemCount(pslSettings);
- }
-
- // Free memory
- SLFreeList(pslSettings);
-
- return iReturn;
-}
-
-
-// Service: MS_SPAMFILTER_CONTACT_SETASSPAMMER
-static int ServiceContactSetAsSpammer(WPARAM wParam, LPARAM lParam)
-{
- HANDLE hContact = (HANDLE)wParam;
- DWORD dwFlags = (DWORD)lParam;
-
- if (!hContact || (hContact == INVALID_HANDLE_VALUE)) return 1;
-
- if (dwFlags & SCASF_NO_NOTIFY)
- {
- if (dwFlags & SCASF_USE_ROBOT_SOUND)
- SkinPlaySound(DB_SOUND_ROBOT_SETTING);
- else
- SkinPlaySound(DB_SOUND_ADVERTISMENT_SETTING);
- }
-
- // Add contact to spammer list
- AddContactToIgnoreList(hContact, !(dwFlags&SCASF_NO_REMOVE_HISTORY), !(dwFlags&SCASF_NO_DENY_AUTHREQUESTS), (dwFlags & SCASF_NO_NOTIFY));
-
- // Remove pre-spammer flag if exists (now is real spammer)
- {
- SPAMCHECKDATA scd;
-
- ZeroMemory(&scd, sizeof(scd));
- scd.cbSize = sizeof(scd);
- scd.hContact = hContact;
-
- RemovePreSpammerCount(&scd);
- }
-
- return 0;
-}
-
-
-// Service: MS_SPAMFILTER_CONTACT_SHOWSETASSPAMMERDIALOG
-static int ServiceContactShowSetAsSpammerDialog(WPARAM wParam, LPARAM lParam)
-{
- HANDLE hContact = (HANDLE)wParam;
- HWND hwndParent = (HWND)lParam;
- BOOL bDlgOK;
-
- WCHAR* pszFmt;
- WCHAR* pszUserName;
- MSGBOXPARAMS mbp;
-
- if (!hContact || (hContact == INVALID_HANDLE_VALUE)) return 1;
-
- // Correct wrong call (backward compatibility)
- if (hwndParent == INVALID_HANDLE_VALUE) hwndParent = NULL;
-
- ZeroMemory(&mbp, sizeof(mbp));
- mbp.cbSize = sizeof(mbp);
- mbp.dwLanguageId = LANGIDFROMLCID(GetThreadLocale()); // Current system language: MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
- mbp.hwndOwner = hwndParent;
- mbp.hInstance = hInstance;
- mbp.lpszIcon = MAKEINTRESOURCE(IDI_DEFAULT_LARGE);
- mbp.dwStyle = MB_USERICON|MB_YESNO|MB_DEFBUTTON1|MB_SETFOREGROUND|MB_TASKMODAL; // MB_RTLREADING works also on non-arabic systems (Win 2000/XP)
- mbp.lpszCaption = TranslateW("Mark Contact as Spammer");
- pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
- pszFmt = TranslateW("Are you sure that the contact \"%s\" shall be marked as spammer?\r\n\r\nMarking a contact as spammer means that all associated messages will be recognized as spam and the contact will be completely ignored in the future.\r\n\r\nA contact that was marked as spammer can be restored using the options dialog.");
- mbp.lpszText = (WCHAR*)mir_alloc((lstrlen(pszFmt)+(pszUserName?lstrlen(pszUserName):0)+1)*sizeof(WCHAR));
- mir_sntprintf((WCHAR*)mbp.lpszText, (lstrlen(pszFmt) + (pszUserName?lstrlen(pszUserName):0) + 1), pszFmt, pszUserName?pszUserName:_T(""));
-
- bDlgOK = (MessageBoxIndirect(&mbp) == IDYES);
- if ((char*)mbp.lpszText) mir_free((char*)mbp.lpszText);
-
- if (bDlgOK)
- {
- BOOL bNoLog;
- BOOL bKeepHistory;
-
- // Get mark-read / delete setting
- bKeepHistory = ((DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, DEFAULT_SETTING_BEHAVIOUR) == 1) ? TRUE : FALSE);
-
- // Check id ctrl key is pressed to manually cancel logging
- if (GetAsyncKeyState(VK_CONTROL)&0x8000)
- bNoLog = FALSE;
- else
- bNoLog = TRUE;
-
- SkinPlaySound(DB_SOUND_ADVERTISMENT_SETTING);
-
- // Add contact to spammer list
- AddContactToIgnoreList(hContact, bKeepHistory, TRUE, bNoLog);
-
- // Remove pre-spammer flag (now is real spammer)
- {
- SPAMCHECKDATA scd;
-
- ZeroMemory(&scd, sizeof(scd));
- scd.cbSize = sizeof(scd);
- scd.hContact = hContact;
-
- RemovePreSpammerCount(&scd);
- }
- }
-
- return (int)bDlgOK;
-}
-
-
-// Service: MS_SPAMFILTER_CONTACT_ISSPAMMER
-static int ServiceContactIsSpammer(WPARAM wParam, LPARAM lParam)
-{
- return (BYTE)(DBGetContactSettingByte((HANDLE)wParam, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)FALSE)?TRUE:FALSE);
-}
-
-
-// Service: MS_SPAMFILTER_CONTACT_UNSETSPAMMER
-static int ServiceContactUnSetSpammer(WPARAM wParam, LPARAM lParam)
-{
- // Internal note: lParam is hwndParent when used as menu item service
-
- if ((HANDLE)wParam && ((HANDLE)wParam != INVALID_HANDLE_VALUE) )
- return RemoveContactFromIgnoreList((HANDLE)wParam) ? 0 : 1;
- else
- return 1;
-}
-
-
-// Service: MS_SPAMFILTER_CHANGEFILTERACTIVATION
-static int ServiceChangeFilterActivation(WPARAM wParam, LPARAM lParam)
-{
- BOOL bNewStatus = (BOOL)lParam;
- DWORD dwFilterType = (DWORD)wParam;
-
- switch (dwFilterType)
- {
- case SFT_DISLIKEDMESSAGES_FILTER:
- {
- if (IsWindow(hwndSpamFilterOpt))
- CheckDlgButton(hwndSpamFilterOpt, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER, (bNewStatus ? BST_CHECKED : BST_UNCHECKED));
-
- return DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)bNewStatus);
- }
-
- case SFT_ADVERTISMENT_FILTER:
- {
- if (IsWindow(hwndSpamFilterOpt))
- CheckDlgButton(hwndSpamFilterOpt, IDC_CHECKBOX_ADVERTISMENTFILTER, (bNewStatus ? BST_CHECKED : BST_UNCHECKED));
-
- return DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)bNewStatus);
- }
-
- case SFT_ROBOT_FILTER:
- {
- if (IsWindow(hwndSpamFilterOpt))
- CheckDlgButton(hwndSpamFilterOpt, IDC_CHECKBOX_ROBOTFILTER, (bNewStatus ? BST_CHECKED : BST_UNCHECKED));
-
- return DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)bNewStatus);
- }
-
- default:
- return 1;
- }
-}
-
-
-// Service: MS_SPAMFILTER_GETSPAMCHECKINFO
-static int ServiceGetSpamCheckInfo(WPARAM wParam, LPARAM lParam)
-{
- DWORD dwInfoType = (DWORD)wParam;
-
- switch (dwInfoType)
- {
- case SFSCI_ACTIVATION_FILTER:
- {
- switch ((DWORD)lParam)
- {
- case SFT_DISLIKEDMESSAGES_FILTER:
- return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, DEFAULT_SETTING_DISLIKEDMESSAGEFILTER)?TRUE:FALSE);
-
- case SFT_ADVERTISMENT_FILTER:
- return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, DEFAULT_SETTING_ADVERTISMENTFILTER)?TRUE:FALSE);
-
- case SFT_ROBOT_FILTER:
- return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, DEFAULT_SETTING_ROBOTFILTER)?TRUE:FALSE);
- }
-
- break;
- }
-
- case SFSCI_ADD_TO_HISTORY:
- {
- switch ((DWORD)lParam)
- {
- // Disliked Messages Filter
- case SFSCI_MSGTEXT_NOTIFYA:
- case SFSCI_MSGTEXT_NOTIFYW:
- return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY, DEFAULT_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY)?TRUE:FALSE);
-
- // Robot Filter
- case SFSCI_MSGTEXT_INSTRUCTIONA:
- case SFSCI_MSGTEXT_INSTRUCTIONW:
- return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ADDTOHISTORY, DEFAULT_SETTING_ROBOT_ADDTOHISTORY)?TRUE:FALSE);
-
- case SFSCI_MSGTEXT_CONFIRMATIONA:
- case SFSCI_MSGTEXT_CONFIRMATIONW:
- return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ADDTOHISTORY, DEFAULT_SETTING_ROBOT_ADDTOHISTORY)?TRUE:FALSE);
- }
- }
-
- case SFSCI_MSGTEXT_NOTIFYA:
- case SFSCI_MSGTEXT_INSTRUCTIONA:
- case SFSCI_MSGTEXT_CONFIRMATIONA:
- case SFSCI_MSGTEXT_NOTIFYW:
- case SFSCI_MSGTEXT_INSTRUCTIONW:
- case SFSCI_MSGTEXT_CONFIRMATIONW:
- {
- SPAMCHECKDATA* pscd = (SPAMCHECKDATA*)lParam;
- char* pszSetting;
- WCHAR* pszBuf;
- WCHAR* pReturn;
- DBVARIANT dbv;
- STRINGLIST* pslFromTo;
-
- if (!pscd || (pscd->cbSize < sizeof(SPAMCHECKDATA)) || !SCD_IsUserValid(pscd))
- break;
-
- switch (dwInfoType)
- {
- // Disliked Messages Filter
- case SFSCI_MSGTEXT_NOTIFYA:
- case SFSCI_MSGTEXT_NOTIFYW:
- pszSetting = DB_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE; // readonly allocated
- break;
-
- // Robot Filter
- case SFSCI_MSGTEXT_INSTRUCTIONA:
- case SFSCI_MSGTEXT_INSTRUCTIONW:
- pszSetting = DB_SETTING_ROBOT_INSTRUCTION; // readonly allocated
- break;
-
- case SFSCI_MSGTEXT_CONFIRMATIONA:
- case SFSCI_MSGTEXT_CONFIRMATIONW:
- pszSetting = DB_SETTING_ROBOT_CONFIRMATION; // readonly allocated
- break;
-
- default:
- pszSetting = NULL;
- }
-
- if (pszSetting)
- {
- WCHAR* pszVariablesOut = NULL;
- pslFromTo = SLNewList();
-
- if ((dwInfoType != SFSCI_MSGTEXT_NOTIFYA) && (dwInfoType != SFSCI_MSGTEXT_NOTIFYW))
- {
- // %securitycode%
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, &dbv) == 0)
- {
- SLAddItemPair(pslFromTo, _T("%securitycode%"), dbv.ptszVal);
- DBFreeVariant(&dbv);
- } else {
- WCHAR szRnd[RANDOM_ANSWER_LENGTH+1];
- GetRandomString(szRnd, ARRAYSIZE(szRnd));
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, szRnd);
- SLAddItemPair(pslFromTo, _T("%securitycode%"), szRnd);
- }
-
- // %triesleft%
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, DEFAULT_SETTING_AUTOADDSPAMMERS))
- {
- WCHAR szTriesLeft[MAX_INT_LENGTH+1];
- mir_sntprintf(szTriesLeft, ARRAYSIZE(szTriesLeft), _T("%u"), DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, DEFAULT_SETTING_ALLOWEDSPAMMESSAGES)-GetPreSpammerCount(pscd)+1);
- SLAddItemPair(pslFromTo, _T("%triesleft%"), szTriesLeft);
- } else {
- SLAddItemPair(pslFromTo, _T("%triesleft%"), TranslateW("unlimited"));
- }
- }
-
- // %message%
- #if defined(UNICODE)
- if (pscd->dwFlags&SCDF_UNICODE)
- pszBuf = pscd->ptszMsgText;
- else
- pszBuf = (WCHAR*)mir_utf8encodeW((WCHAR*)pscd->pszMsgText);
-
- SLAddItemPair(pslFromTo, _T("%message%"), pszBuf);
-
- if (pszBuf && !(pscd->dwFlags&SCDF_UNICODE))
- mir_free(pszBuf);
- #else
- if (pscd->dwFlags&SCDF_UNICODE)
- pszBuf = UnicodeToAnsi(pscd->pwszMsgText);
- else
- pszBuf = pscd->ptszMsgText;
-
- SLAddItemPair(pslFromTo, _T("%message%"), pszBuf);
-
- if ((pscd->dwFlags&SCDF_UNICODE) && pszBuf)
- mir_free(pszBuf);
- #endif
-
- // %sender%
- pszBuf = SCD_GetContactName(pscd, FALSE);
- SLAddItemPair(pslFromTo, _T("%sender%"), pszBuf);
- if (pszBuf) mir_free(pszBuf);
-
- // Retrieve message text
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, pszSetting, &dbv) == 0) {
- pszBuf = ReplaceSubStringWithStringMultiple(dbv.ptszVal, pslFromTo, TRUE, FALSE, NULL);
- DBFreeVariant(&dbv);
- } else {
- pszBuf = NULL;
- }
-
- // Retrieve message text
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, pszSetting, &dbv) == 0) {
- pszBuf = ReplaceSubStringWithStringMultiple(dbv.ptszVal, pslFromTo, TRUE, FALSE, NULL);
- DBFreeVariant(&dbv);
- } else {
- pszBuf = NULL;
- }
- SLFreeList(pslFromTo);
-
- // Support for "Variables" plugin
- if (ServiceExists(MS_VARS_FORMATSTRING))
- {
- FORMATINFO fi;
-
- ZeroMemory(&fi, sizeof(fi));
- fi.cbSize = sizeof(fi);
- fi.flags = FIF_UNICODE;
- fi.tszFormat = pszBuf;
- fi.tszExtraText = pscd->ptszMsgText; // %message% variable is handled earlier by Spam Filter itself
- fi.hContact = (pscd->dwFlags&SCDF_NO_CONTACT)?NULL:pscd->hContact;
-
- pszVariablesOut = (WCHAR*)CallService(MS_VARS_FORMATSTRING, (WPARAM)&fi, 0);
- }
-
-
- // Convert return value
- pReturn = NULL;
- if (pszVariablesOut?pszVariablesOut:pszBuf)
- {
- switch (dwInfoType)
- {
- case SFSCI_MSGTEXT_NOTIFYA:
- case SFSCI_MSGTEXT_INSTRUCTIONA:
- case SFSCI_MSGTEXT_CONFIRMATIONA:
- {
- #if defined(UNICODE)
- // UnicodeToAnsi uses mir_alloc
- mir_utf8decode((char*)pszVariablesOut?(char*)pszVariablesOut:(char*)pszBuf,&pReturn);
- #else
- // AnsiDup uses mir_alloc
- pReturn = (PBYTE)mir_strdup(pszVariablesOut?pszVariablesOut:pszBuf);
- #endif
- break;
- }
-
- case SFSCI_MSGTEXT_NOTIFYW:
- case SFSCI_MSGTEXT_INSTRUCTIONW:
- case SFSCI_MSGTEXT_CONFIRMATIONW:
- {
- #if defined(UNICODE)
- // UnicodeDup uses mir_alloc
- pReturn = mir_wstrdup(pszVariablesOut?pszVariablesOut:pszBuf);
- #else
- // mir_utf8encodeW uses mir_alloc
- pReturn = (PBYTE)mir_utf8encodeW(pszVariablesOut?pszVariablesOut:pszBuf);
- #endif
- break;
- }
- }
- }
-
-
- if (pszBuf)
- SLFreeReturn(pszBuf);
-
- // Support for "Variables" plugin
- if (pszVariablesOut)
- CallService(MS_VARS_FREEMEMORY, (WPARAM)pszVariablesOut, 0);
-
- return (int)pReturn;
- }
-
- break;
- }
- }
-
- return 0;
-}
-
-
-// Service: MS_SPAMFILTER_REGISTERMESSAGETYPE
-static int ServiceRegisterMessageType(WPARAM wParam, LPARAM lParam)
-{
- MESSAGETYPEDESC* pmtdNew = (MESSAGETYPEDESC*)lParam;
-
- if (!pmtdNew->pszName || !pmtdNew->pszSection || (pmtdNew->cbSize < MESSAGETYPEDESC_V2000_SIZE))
- return 1;
-
- // Do not add if already added
- EnterCriticalSection(&csMsgTypes); // thread safety
- if (GetMsgTypeID(pmtdNew->pszSection, pmtdNew->pszName) >= 0) {
- LeaveCriticalSection(&csMsgTypes); // thread safety
- return 1;
- }
- LeaveCriticalSection(&csMsgTypes); // thread safety
-
- // outside critical section:
- // Hand out event (asking other plugins if default data is ok)
- if (NotifyEventHooks(hEventPreRegisterMessageType, (WPARAM)wParam, (LPARAM)lParam) == 1) {
- OutputDebugString(_T("Spam Filter: Adding message type denied (by event).\r\n"));
- return 1;
- }
-
- // Do not add if already added (check again)
- EnterCriticalSection(&csMsgTypes); // thread safety
- if (GetMsgTypeID(pmtdNew->pszSection, pmtdNew->pszName) >= 0) {
- LeaveCriticalSection(&csMsgTypes); // thread safety
- return 1;
- }
-
- // Resize list array
- {
- MESSAGETYPEDESC* pamtdMsgTypesBuf;
- pamtdMsgTypesBuf = (MESSAGETYPEDESC*)mir_realloc(pamtdMsgTypes, (uMsgTypesCount+1)*sizeof(MESSAGETYPEDESC));
-
- if (pamtdMsgTypesBuf) {
- pamtdMsgTypes = pamtdMsgTypesBuf;
- } else {
- // Fatal error: list was not reallocated, insufficient memory (old data still valid)
- LeaveCriticalSection(&csMsgTypes); // thread safety
- return 1;
- }
- }
-
- pamtdMsgTypes[uMsgTypesCount].cbSize = sizeof(MESSAGETYPEDESC);
- pamtdMsgTypes[uMsgTypesCount].dwFlags = pmtdNew->dwFlags;
-
- // Backward compatibility (struct extended in v2.1.1.0)
- if (pmtdNew->cbSize > MESSAGETYPEDESC_V2000_SIZE) {
- pamtdMsgTypes[uMsgTypesCount].iPosition = pmtdNew->iPosition;
- pamtdMsgTypes[uMsgTypesCount].iSectionPosition = pmtdNew->iSectionPosition;
- } else {
- pamtdMsgTypes[uMsgTypesCount].iPosition = 0;
- pamtdMsgTypes[uMsgTypesCount].iSectionPosition = pmtdNew->iSectionPosition;
- }
-
- pamtdMsgTypes[uMsgTypesCount].pszSection = mir_strdup(pmtdNew->pszSection);
- pamtdMsgTypes[uMsgTypesCount].pszName = mir_strdup(pmtdNew->pszName);
-
- #if defined(UNICODE)
- if (pmtdNew->dwFlags&MTDF_UNICODE) {
- pamtdMsgTypes[uMsgTypesCount].ptszSectionDescription = pmtdNew->pwszSectionDescription ? mir_wstrdup(pmtdNew->pwszSectionDescription) : (WCHAR*)mir_utf8encodeW((WCHAR*)Translate((WCHAR*)pmtdNew->pszSection));
- pamtdMsgTypes[uMsgTypesCount].ptszDescription = pmtdNew->pwszDescription ? mir_wstrdup(pmtdNew->pwszDescription) : (WCHAR*)mir_utf8encodeW((WCHAR*)Translate((WCHAR*)pmtdNew->pszName));
- } else {
- pamtdMsgTypes[uMsgTypesCount].dwFlags |= MTDF_UNICODE;
- pamtdMsgTypes[uMsgTypesCount].ptszSectionDescription = pmtdNew->pszSectionDescription ? (WCHAR*)mir_utf8encodeW((WCHAR*)pmtdNew->pszSectionDescription) : (WCHAR*)mir_utf8encodeW((WCHAR*)Translate((WCHAR*)pmtdNew->pszSection));
- pamtdMsgTypes[uMsgTypesCount].ptszDescription = pmtdNew->pszDescription ? (WCHAR*)mir_utf8encodeW((WCHAR*)pmtdNew->pszDescription) : (WCHAR*)mir_utf8encodeW((WCHAR*)Translate((WCHAR*)pmtdNew->pszName));
- }
- #else
- if (pmtdNew->dwFlags&MTDF_UNICODE) {
- pamtdMsgTypes[uMsgTypesCount].dwFlags ^= MTDF_UNICODE;
- pamtdMsgTypes[uMsgTypesCount].ptszSectionDescription = pmtdNew->pwszSectionDescription ? UnicodeToAnsi(pmtdNew->pwszSectionDescription) : mir_strdup(Translate(pmtdNew->pszSection));
- pamtdMsgTypes[uMsgTypesCount].ptszDescription = pmtdNew->pwszDescription ? UnicodeToAnsi(pmtdNew->pwszDescription) : mir_strdup(Translate(pmtdNew->pszName));
- } else {
- pamtdMsgTypes[uMsgTypesCount].ptszSectionDescription = pmtdNew->pszSectionDescription ? AnsiDup(pmtdNew->pszSectionDescription) : AnsiDup(Translate(pmtdNew->pszSection));
- pamtdMsgTypes[uMsgTypesCount].ptszDescription = pmtdNew->pszDescription ? AnsiDup(pmtdNew->ptszDescription) : AnsiDup(Translate(pmtdNew->pszName));
- }
- #endif
-
- // Fatal error (strings were not allocated, insufficient memory)
- if (!pamtdMsgTypes[uMsgTypesCount].pszSection || !pamtdMsgTypes[uMsgTypesCount].pszSectionDescription || !pamtdMsgTypes[uMsgTypesCount].pszName || !pamtdMsgTypes[uMsgTypesCount].pszDescription)
- {
- if (pamtdMsgTypes[uMsgTypesCount].pszSection) mir_free(pamtdMsgTypes[uMsgTypesCount].pszSection);
- if (pamtdMsgTypes[uMsgTypesCount].pszSectionDescription) mir_free(pamtdMsgTypes[uMsgTypesCount].pszSectionDescription);
- if (pamtdMsgTypes[uMsgTypesCount].pszName) mir_free(pamtdMsgTypes[uMsgTypesCount].pszName);
- if (pamtdMsgTypes[uMsgTypesCount].pszDescription) mir_free(pamtdMsgTypes[uMsgTypesCount].pszDescription);
-
- LeaveCriticalSection(&csMsgTypes); // thread safety
- return 1;
- }
-
- pamtdMsgTypes[uMsgTypesCount].hSectionIcon = pmtdNew->hSectionIcon ? (HICON)CopyImage(pmtdNew->hSectionIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_COPYFROMRESOURCE) : NULL;
-
- if ((int)pmtdNew->hIcon < 0) // if is miranda skinned icon constant
- pamtdMsgTypes[uMsgTypesCount].hIcon = pmtdNew->hIcon;
- else
- pamtdMsgTypes[uMsgTypesCount].hIcon = pmtdNew->hIcon ? (HICON)CopyImage(pmtdNew->hIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_COPYFROMRESOURCE) : NULL;
-
-
- uMsgTypesCount++;
-
- LeaveCriticalSection(&csMsgTypes); // thread safety
-
- // Refresh shown list
- if (IsWindow(hwndSpamFilterOpt))
- SendMessage(hwndSpamFilterOpt, SFM_REBUILD_MSGTYPES, 0, 0);
-
- return 0;
-}
-
-
-// Service: MS_SPAMFILTER_REMOVEMESSAGETYPE
-static int ServiceRemoveMessageType(WPARAM wParam, LPARAM lParam)
-{
- char* pszMsgTypeSection = (char*)wParam;
- char* pszMsgTypeName = (char*)lParam;
-
- MESSAGETYPEDESC* pamtdMsgTypesBuf;
- int iReturn;
- char* pszSetting;
- unsigned int u;
-
- if (!pszMsgTypeName || !pszMsgTypeSection) return 1;
- iReturn = 1;
-
- EnterCriticalSection(&csMsgTypes); // thread safety
-
- // Remove array item
- if (pamtdMsgTypes)
- {
- for (u=0; u<uMsgTypesCount; u++)
- {
- // Same pszSection?
- if (StrCmpA(pamtdMsgTypes[u].pszSection, pszMsgTypeSection) == 0)
- {
- // Same pszName? (when no name is specified all items of the same section are removed)
- if (StrCmpA(pamtdMsgTypes[u].pszName, pszMsgTypeName) == 0)
- {
- // -> Item to remove found
-
- // Delete database setting
- pszSetting = GetMsgTypeSettingName(pamtdMsgTypes[u].pszSection, pamtdMsgTypes[u].pszName);
- if (pszSetting)
- {
- DBDeleteContactSetting(NULL, DB_MODULE_NAME_MSGTYPES, pszSetting);
- mir_free(pszSetting);
- }
-
- // Free array item memory
- if (pamtdMsgTypes[u].pszSection) mir_free(pamtdMsgTypes[u].pszSection);
- if (pamtdMsgTypes[u].pszName) mir_free(pamtdMsgTypes[u].pszName);
- if (pamtdMsgTypes[u].ptszSectionDescription) mir_free(pamtdMsgTypes[u].ptszSectionDescription);
- if (pamtdMsgTypes[u].ptszDescription) mir_free(pamtdMsgTypes[u].ptszDescription);
- if (pamtdMsgTypes[u].hIcon && ((int)pamtdMsgTypes[u].hIcon > 0)) DestroyIcon(pamtdMsgTypes[u].hIcon);
- if (pamtdMsgTypes[u].hSectionIcon) DestroyIcon(pamtdMsgTypes[u].hSectionIcon);
-
- // Move other array items (if not last item)
- if ((u+1) < uMsgTypesCount)
- MoveMemory(&pamtdMsgTypes[u], &pamtdMsgTypes[u+1], ((uMsgTypesCount-u-1)*sizeof(MESSAGETYPEDESC)));
-
- // Resize array
- pamtdMsgTypesBuf = (MESSAGETYPEDESC*)mir_realloc(pamtdMsgTypes, (uMsgTypesCount-1)*sizeof(MESSAGETYPEDESC));
- if (pamtdMsgTypesBuf)
- pamtdMsgTypes = pamtdMsgTypesBuf;
-
- // Decrase list count
- uMsgTypesCount--;
-
- iReturn = 0;
- break;
- }
- }
- }
- }
-
- LeaveCriticalSection(&csMsgTypes); // thread safety
-
- // Refresh shown list
- if (IsWindow(hwndSpamFilterOpt))
- SendMessage(hwndSpamFilterOpt, SFM_REBUILD_MSGTYPES, 0, 0);
-
- return iReturn;
-}
-
-
-// Service: MS_SPAMFILTER_ISMESSAGETYPEACTIVATED
-static int ServiceIsMessageTypeActivated(WPARAM wParam, LPARAM lParam)
-{
- int iMsgType;
- BOOL bReturn = FALSE;
-
- EnterCriticalSection(&csMsgTypes); // thread safety
-
- iMsgType = GetMsgTypeID((const char*)wParam, (const char*)lParam);
- if (iMsgType != -1)
- if (pamtdMsgTypes[iMsgType].dwFlags&MTDF_HIDDEN)
- {
- bReturn = !(pamtdMsgTypes[iMsgType].dwFlags&MTDF_DEFAULTDISABLED);
- } else {
- char* pszSetting = GetMsgTypeSettingName(pamtdMsgTypes[iMsgType].pszSection, pamtdMsgTypes[iMsgType].pszName);
- if (pszSetting)
- {
- bReturn = DBGetContactSettingByte(NULL, DB_MODULE_NAME_MSGTYPES, pszSetting, (BYTE)!(pamtdMsgTypes[iMsgType].dwFlags&MTDF_DEFAULTDISABLED));
- mir_free(pszSetting);
- }
- }
-
- LeaveCriticalSection(&csMsgTypes); // thread safety
- return (int)bReturn;
-}
-
-
-// Service: MS_SPAMFILTER_ROBOTCHECK
-static int ServiceRobotCheck(WPARAM wParam, LPARAM lParam) // wParam = SPAMCHECKDATA, lParam = 0
-{
- SPAMCHECKDATA* pscd = (SPAMCHECKDATA*)wParam;
-
- if (!pscd || !pscd->pszMsgTypeSection || !pscd->pszMsgTypeName || (pscd->cbSize < sizeof(SPAMCHECKDATA)) || !SCD_IsUserValid(pscd))
- return SFF_ISNORMAL;
-
- // Check id ctrl key is pressed to manually cancel spam check
- if (!(pscd->dwFlags&SCDF_NO_CANCEL) && (GetAsyncKeyState(VK_CONTROL)&0x8000))
- return SFF_ISNORMAL;
-
- if ( !CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)pscd->pszMsgTypeSection, (LPARAM)pscd->pszMsgTypeName)
- || !CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ACTIVATION_FILTER, (LPARAM)SFT_ROBOT_FILTER) )
- return SFF_ISNORMAL;
-
- if (NotifyEventHooks(hEventOkToSpamCheck, (WPARAM)pscd, (LPARAM)SFT_ROBOT_FILTER) == 1) {
- OutputDebugString(_T("Spam Filter: Spam check denied (by event).\r\n"));
- return SFF_ISNORMAL;
- }
-
- {
- WCHAR* pszNormalMsgText;
- WCHAR* pszClearedMsgText = NULL;
-
- DWORD dwReturn = SFF_ISNORMAL;
-
- // Buffer the msg content
- if (pscd->ptszMsgText)
- {
- #if defined(UNICODE)
- if (pscd->dwFlags&SCDF_UNICODE)
- pszNormalMsgText = pscd->ptszMsgText;
- else
- pszNormalMsgText = (WCHAR*)mir_utf8encodeW((WCHAR*)pscd->pszMsgText);
- #else
- if (pscd->dwFlags&SCDF_UNICODE)
- pszNormalMsgText = UnicodeToAnsi(pscd->pwszMsgText);
- else
- pszNormalMsgText = pscd->ptszMsgText;
- #endif
-
- } else {
- pszNormalMsgText = NULL;
- }
-
- pszClearedMsgText = mir_wstrdup(pszNormalMsgText);
- if (pszClearedMsgText)
- RemoveWhiteSpaces(pszClearedMsgText, FALSE, TRUE);
- else
- pszClearedMsgText = NULL;
-
- if (pszClearedMsgText)
- {
- DBVARIANT dbv;
-
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, &dbv) == 0)
- {
- // If message contains correct answer
- RemoveWhiteSpaces(dbv.ptszVal, FALSE, TRUE);
- if ((StrCmp(pszClearedMsgText, dbv.ptszVal) == 0) || // or allow for quotes (below)
- (StrCmpN(&pszClearedMsgText[1], dbv.ptszVal, lstrlen(pszClearedMsgText)-2) == 0))
- dwReturn |= SFF_SENDMSG_CONFIRMATION|SFF_TESTPASSED|(DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ADDTOHISTORY, DEFAULT_SETTING_ROBOT_ADDTOHISTORY) ? SFF_MARKREAD : SFF_DELETE);
-
- DBFreeVariant(&dbv);
- }
- }
-
- if (pszClearedMsgText) mir_free(pszClearedMsgText);
-
- #if defined(UNICODE)
- if (!(pscd->dwFlags&SCDF_UNICODE))
- if (pszNormalMsgText) mir_free(pszNormalMsgText);
- #else
- if ((pscd->dwFlags&SCDF_UNICODE))
- if (pszNormalMsgText) mir_free(pszNormalMsgText);
- #endif
-
- // Kick out spam
- if ( (!(dwReturn&SFF_TESTPASSED)) && (NotifyEventHooks(hEventOkToSpamDetection, (WPARAM)pscd, (LPARAM)SFT_ROBOT_FILTER) == 0))
- {
- dwReturn = SFF_ISSPAM|((DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, DEFAULT_SETTING_BEHAVIOUR) == 1) ? SFF_MARKREAD : SFF_DELETE);
-
- // Add user to ignore list
- if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE) && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, DEFAULT_SETTING_AUTOADDSPAMMERS) )
- {
- if (IncreasePreSpammerCount(pscd) > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, DEFAULT_SETTING_ALLOWEDSPAMMESSAGES))
- {
- RemovePreSpammerCount(pscd);
- dwReturn |= SFF_IGNORE;
- }
- }
-
- // Do not send question message when next messages will be ignored
- if (!(dwReturn&SFF_IGNORE)) {
- dwReturn |= SFF_SENDMSG_INSTRUCTION;
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_HIDEUSERS, (BYTE)DEFAULT_SETTING_ROBOT_HIDEUSERS))
- dwReturn |= SFF_HIDE;
- }
-
- if (!(pscd->dwFlags&SCDF_NO_NOTIFY))
- {
- // Play sound file
- SkinPlaySound(DB_SOUND_ROBOT_SETTING);
-
- // Show Popup
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, DEFAULT_SETTING_POPUP))
- {
- WCHAR* pszDisplayName = SCD_GetContactCustomDisplayName(pscd);
-
- ShowSpamPopup(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszDisplayName, (pscd->dwFlags&SCDF_NO_CONTACT)?NULL:pscd->hContact, SFT_ROBOT_FILTER);
- if (pszDisplayName) mir_free(pszDisplayName);
- }
-
- // Append to log file
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, DEFAULT_SETTING_LOGGING))
- {
- STRINGLIST* pslRecognition = SLNewList();
- WCHAR* pszUserName = SCD_GetContactName(pscd, TRUE);
-
- SLAddItem(pslRecognition, TranslateW("Robot message"));
- WriteToLogFile(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszUserName, pszNormalMsgText, pslRecognition, dwReturn);
-
- if (pszUserName) mir_free(pszUserName);
- SLFreeList(pslRecognition);
- }
-
- // Hand out event
- NotifyEventHooks(hEventSpamReceived, (WPARAM)pscd, (LPARAM)SFT_ROBOT_FILTER);
-
- // Trigger Plugin Support
- TriggerIncomingSpam();
- }
-
-
- } else {
-
- if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE))
- RemovePreSpammerCount(pscd);
-
- // Message is normal
- }
-
- return dwReturn;
- }
-}
-
-
-// Service: MS_SPAMFILTER_DISLIKEDMESSAGECHECK
-static int ServiceDislikedMessageCheck(WPARAM wParam, LPARAM lParam) // wParam = SPAMCHECKDATA, lParam = 0
-{
- SPAMCHECKDATA* pscd = (SPAMCHECKDATA*)wParam;
-
- if (!pscd || !pscd->pszMsgTypeSection || !pscd->pszMsgTypeName || (pscd->cbSize < sizeof(SPAMCHECKDATA)) || !SCD_IsUserValid(pscd))
- return SFF_ISNORMAL;
-
- // Check id ctrl key is pressed to manually cancel spam check
- if (!(pscd->dwFlags&SCDF_NO_CANCEL) && (GetAsyncKeyState(VK_CONTROL)&0x8000))
- return SFF_ISNORMAL;
-
- if ( !CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)pscd->pszMsgTypeSection, (LPARAM)pscd->pszMsgTypeName)
- || !CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ACTIVATION_FILTER, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER) )
- return SFF_ISNORMAL;
-
- if (NotifyEventHooks(hEventOkToSpamCheck, (WPARAM)pscd, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER) == 1) {
- OutputDebugString(_T("Spam Filter: Spam check denied (by event).\r\n"));
- return SFF_ISNORMAL;
- }
-
- {
- BOOL bDoLog = ( (!(pscd->dwFlags&SCDF_NO_NOTIFY)) && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, DEFAULT_SETTING_LOGGING) );
- BOOL bKickOut = FALSE;
-
- int i;
- WCHAR* pszNormalMsgText;
- WCHAR* pszClearedMsgText;
- STRINGLIST* pslRecognition = NULL;
-
- // Create recognition texts list
- if (bDoLog) pslRecognition = SLNewList();
-
- // Buffer the msg content
- if (pscd->pszMsgText)
- {
- #if defined(UNICODE)
- if (pscd->dwFlags&SCDF_UNICODE)
- pszNormalMsgText = pscd->ptszMsgText;
- else
- pszNormalMsgText = (WCHAR*)mir_utf8encodeW((WCHAR*)pscd->pszMsgText);
- #else
- if (pscd->dwFlags&SCDF_UNICODE)
- pszNormalMsgText = UnicodeToAnsi(pscd->pwszMsgText);
- else
- pszNormalMsgText = pscd->ptszMsgText;
- #endif
-
- pszClearedMsgText = mir_wstrdup(pszNormalMsgText);
- if (pszClearedMsgText)
- RemoveWhiteSpaces(pszClearedMsgText, TRUE, TRUE);
-
- } else {
- pszNormalMsgText = NULL;
- pszClearedMsgText = NULL;
- }
-
- // -SPAMCHECKS-
-
- // Customized indicating words
- if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_CUSTOMIZEDWORDS, (BYTE)TRUE))
- {
- STRINGLIST* pslChainWords = SLNewList();
- unsigned int uFoundChainWords = 0;
-
- GetSpamDefinitionData(pslChainWords, SDID_CUSTOM_DISLIKEDWORDS);
-
- // Check how many words exist in the message
- for (i=0; i<=SLGetMaxPos(pslChainWords); i++)
- if (RegExpExistsInString(pszClearedMsgText, SLGetItem(pslChainWords, i), FALSE, NULL))
- uFoundChainWords++;
-
- SLFreeList(pslChainWords);
-
- if (uFoundChainWords > 0)
- {
- if (bDoLog) SLItemPrintf(pslRecognition, SLAddItem(pslRecognition, TranslateW("Contains %u disliked indicating phrase(s)/pattern(s)")), MAX_INT_LENGTH, uFoundChainWords);
- bKickOut = TRUE;
- if (!bDoLog) goto DislikedMessageResult;
- }
- }
-
-
- // Multiple message check
- if (pszNormalMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES, DEFAULT_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES))
- {
- DBVARIANT dbv;
- BOOL bFound;
- WCHAR* pszSender;
-
- pszSender = SCD_GetContactUniqueStr(pscd, FALSE);
-
- bFound = FALSE;
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTMESSAGE, &dbv) == 0)
- {
- if (StrCmp(pszNormalMsgText, dbv.ptszVal) == 0)
- {
- DBFreeVariant(&dbv);
-
- if (pszSender)
- {
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTSENDER, &dbv) == 0)
- if (StrCmp(pszSender, dbv.ptszVal) == 0)
- bFound = TRUE;
-
- } else {
- bFound = TRUE;
- }
- }
- DBFreeVariant(&dbv);
- }
-
- // Always save current msg content
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTMESSAGE, pszNormalMsgText);
- if (pszSender)
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTSENDER, pszSender);
- else
- DBDeleteContactSetting(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTSENDER);
-
- if (pszSender) mir_free(pszSender);
-
- if (bFound)
- {
- if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is multiple"));
- bKickOut = TRUE;
- if (!bDoLog) goto DislikedMessageResult;
- }
-
- } else if (!pszNormalMsgText) {
- DBDeleteContactSetting(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTMESSAGE);
- }
-
-
- // Default hoax texts
- if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_HOAXTEXTS, DEFAULT_SETTING_DISLIKEDMESSAGE_HOAXTEXTS))
- {
- STRINGLIST* pslHoaxTexts = SLNewList();
- BOOL bFound;
-
- // Load hoax texts
- GetSpamDefinitionData(pslHoaxTexts, SDID_HOAXTEXTS);
-
- bFound = FALSE;
- for (i=SL_MIN_POS; i<=SLGetMaxPos(pslHoaxTexts); i++)
- if (StrCmpI(pszClearedMsgText, SLGetItem(pslHoaxTexts, i)) == 0)
- {
- bFound = TRUE;
- break;
- }
-
- SLFreeList(pslHoaxTexts);
-
- if (bFound)
- {
- if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is hoax text"));
- bKickOut = TRUE;
- if (!bDoLog) goto DislikedMessageResult;
- }
- }
-
-
-DislikedMessageResult:
-
- if (pszClearedMsgText) mir_free(pszClearedMsgText);
-
- #if defined(UNICODE)
- if (!(pscd->dwFlags&SCDF_UNICODE) && pszNormalMsgText)
- if (pszNormalMsgText) mir_free(pszNormalMsgText);
- #else
- if ((pscd->dwFlags&SCDF_UNICODE) && pszNormalMsgText)
- mir_free(pszNormalMsgText);
- #endif
-
- // Kick out spam
- if ( bKickOut && (NotifyEventHooks(hEventOkToSpamDetection, (WPARAM)pscd, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER) == 0))
- {
- DWORD dwReturn = SFF_ISSPAM|((DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, DEFAULT_SETTING_BEHAVIOUR) == 1) ? SFF_MARKREAD : SFF_DELETE);
-
- // Add user to ignore list
- if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE) && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, DEFAULT_SETTING_AUTOADDSPAMMERS) )
- {
- if (IncreasePreSpammerCount(pscd) > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, DEFAULT_SETTING_ALLOWEDSPAMMESSAGES))
- {
- RemovePreSpammerCount(pscd);
- dwReturn |= SFF_IGNORE;
- }
- }
-
- // Reply to sender
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER, DEFAULT_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER))
- dwReturn |= SFF_SENDMSG_NOTIFY;
-
- if (!(pscd->dwFlags&SCDF_NO_NOTIFY))
- {
- // Play sound file
- SkinPlaySound(DB_SOUND_DISLIKEDMESSAGE_SETTING);
-
- // Show Popup
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, DEFAULT_SETTING_POPUP))
- {
- WCHAR* pszDisplayName = SCD_GetContactCustomDisplayName(pscd);
- ShowSpamPopup(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszDisplayName, (pscd->dwFlags&SCDF_NO_CONTACT)?NULL:pscd->hContact, SFT_DISLIKEDMESSAGES_FILTER);
- if (pszDisplayName) mir_free(pszDisplayName);
- }
-
- // Hand out event
- NotifyEventHooks(hEventSpamReceived, (WPARAM)pscd, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER);
-
- // Trigger Plugin Support
- TriggerIncomingSpam();
- }
-
- // Append to log file
- if (bDoLog)
- {
- WCHAR* pszUserName = SCD_GetContactName(pscd, TRUE);
-
- WriteToLogFile(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszUserName, pszNormalMsgText, pslRecognition, dwReturn);
- if (pszUserName) mir_free(pszUserName);
-
- SLFreeList(pslRecognition);
- }
-
- return dwReturn;
-
- } else {
-
- if (bDoLog)
- SLFreeList(pslRecognition);
-
- if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE))
- RemovePreSpammerCount(pscd); // count can be removed here
-
- // Message is normal
- return SFF_ISNORMAL;
- }
-
- }
-}
-
-
-// Service : MS_SPAMFILTER_ADVERTISMENTCHECK
-static int ServiceAdvertismentCheck(WPARAM wParam, LPARAM lParam) // wParam = SPAMCHECKDATA, lParam = 0
-{
- SPAMCHECKDATA* pscd = (SPAMCHECKDATA*)wParam;
-
- if (!pscd || !pscd->pszMsgTypeSection || !pscd->pszMsgTypeName || (pscd->cbSize < sizeof(SPAMCHECKDATA)) || !SCD_IsUserValid(pscd))
- return SFF_ISNORMAL;
-
- // Check id ctrl key is pressed to manually cancel spam check
- if (!(pscd->dwFlags&SCDF_NO_CANCEL) && (GetAsyncKeyState(VK_CONTROL)&0x8000))
- return SFF_ISNORMAL;
-
- if ( !CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)pscd->pszMsgTypeSection, (LPARAM)pscd->pszMsgTypeName)
- || !CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ACTIVATION_FILTER, (LPARAM)SFT_ADVERTISMENT_FILTER) )
- return SFF_ISNORMAL;
-
- if (NotifyEventHooks(hEventOkToSpamCheck, (WPARAM)pscd, (LPARAM)SFT_ADVERTISMENT_FILTER) == 1) {
- OutputDebugString(_T("Spam Filter: Spam check denied (by event).\r\n"));
- return SFF_ISNORMAL;
- }
-
- {
- BOOL bDoLog = ( (!(pscd->dwFlags&SCDF_NO_NOTIFY)) && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, DEFAULT_SETTING_LOGGING) );
- BOOL bIsKnownSpammer = FALSE;
- BOOL bKickOut = FALSE;
- BOOL bFound;
-
- int i;
- WCHAR* pszNormalMsgText;
- WCHAR* pszClearedMsgText;
- WCHAR* pszFormatedMsgText;
- STRINGLIST* pslRecognition = NULL;
-
- // Create recognition texts list
- if (bDoLog) pslRecognition = SLNewList();
-
- // Buffer the msg content
- if (pscd->pszMsgText)
- {
- #if defined(UNICODE)
- if (pscd->dwFlags&SCDF_UNICODE)
- pszNormalMsgText = pscd->ptszMsgText;
- else
- pszNormalMsgText = (WCHAR*)mir_utf8encodeW((WCHAR*)pscd->pszMsgText);
- #else
- if (pscd->dwFlags&SCDF_UNICODE)
- pszNormalMsgText = UnicodeToAnsi(pscd->pwszMsgText);
- else
- pszNormalMsgText = pscd->ptszMsgText;
- #endif
-
- pszClearedMsgText = mir_wstrdup(pszNormalMsgText);
- if (pszClearedMsgText)
- RemoveWhiteSpaces(pszClearedMsgText, TRUE, TRUE);
-
- } else {
- pszNormalMsgText = NULL;
- pszClearedMsgText = NULL;
- }
-
- // Create different format check text
- if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_FORMATING, DEFAULT_SETTING_ADVERTISMENT_FORMATING))
- {
- pszFormatedMsgText = mir_wstrdup(pszClearedMsgText);
- if (pszFormatedMsgText)
- {
- STRINGLIST* pslFormat = SLNewList();
-
- // Some words may have special chars in between the chars
- GetSpamDefinitionData(pslFormat, SDID_SPECIALCHARS_SEPARATORS);
-
- for (i=SL_MIN_POS; i<=SLGetMaxPos(pslFormat); i++)
- ReplaceSubStringWithStringBuf(pszFormatedMsgText, 0, SLGetItem(pslFormat, i), _T(" "), TRUE, FALSE);
-
- SLClearList(pslFormat);
-
- // Translate some chars
- GetSpamDefinitionData(pslFormat, SDID_SPECIALCHARS_REPLACE_TEXT);
- ReplaceSubStringWithStringMultipleBuf(pszFormatedMsgText, 0, pslFormat, TRUE, FALSE);
-
- SLFreeList(pslFormat);
- }
- } else {
- pszFormatedMsgText = NULL;
- }
-
- // -SPAMCHECKS-
- // Multiple message check
- if (pszNormalMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_MULTIPLEMESSAGES, DEFAULT_SETTING_ADVERTISMENT_MULTIPLEMESSAGES))
- {
- DBVARIANT dbv;
- bFound = FALSE;
-
- // Do not consider sender of NotOnList messages
- if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_LASTMESSAGE, &dbv) == 0)
- {
- if (StrCmp(pszNormalMsgText, dbv.ptszVal) == 0)
- bFound = TRUE;
-
- DBFreeVariant(&dbv);
- }
-
- // Always save current msg content
- DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_LASTMESSAGE, pszNormalMsgText);
-
- if (bFound)
- {
- if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is multiple"));
- bKickOut = TRUE;
- if (!bDoLog) goto AdvertismentResult;
- }
-
- } else if (!pszNormalMsgText) {
- DBDeleteContactSetting(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_LASTMESSAGE);
- }
-
- // Empty message?
- if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_EMPTY, DEFAULT_SETTING_ADVERTISMENT_EMPTY))
- {
- if (lstrlen(pszClearedMsgText) <= 0)
- {
- if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is empty"));
- bKickOut = TRUE;
- if (!bDoLog) goto AdvertismentResult;
- }
- }
-
- // Message capitalized?
- if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CAPITALIZED, DEFAULT_SETTING_ADVERTISMENT_CAPITALIZED))
- {
- bFound = TRUE;
-
- for (i=0; i<(int)lstrlen(pszClearedMsgText); i++)
- if (IsCharLower(pszClearedMsgText[i]))
- {
- bFound = FALSE;
- break;
- }
-
- if (bFound)
- {
- if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is capitalized"));
- bKickOut = TRUE;
- if (!bDoLog) goto AdvertismentResult;
- }
- }
-
- // Sender is default spammer?
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTSPAMMERS, DEFAULT_SETTING_ADVERTISMENT_DEFAULTSPAMMERS))
- {
- STRINGLIST* psl = SLNewList();
- WCHAR* pszUnique;
-
- // Load spammers definitions
- GetSpamDefinitionData(psl, SDID_SPAMMERS);
-
- // Check if unique user id is listed in def file
- pszUnique = SCD_GetContactUniqueStr(pscd, FALSE);
- if (pszUnique)
- {
- bFound = SLIsItem(psl, pszUnique, TRUE);
- mir_free(pszUnique);
- } else {
- bFound = FALSE;
- }
-
- // Check if nickname is listed in def file
- if (!bFound)
- {
- pszUnique = SCD_GetContactUniqueStr(pscd, TRUE);
- if (pszUnique)
- {
- bFound = SLIsItem(psl, pszUnique, TRUE);
- mir_free(pszUnique);
- }
- }
- SLFreeList(psl);
-
- if (bFound)
- {
- if (bDoLog) SLAddItem(pslRecognition, TranslateW("User is known as spammer"));
- bKickOut = bIsKnownSpammer = TRUE;
- if (!bDoLog) goto AdvertismentResult;
- }
- }
-
- // Teaser Message?
- if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_TEASERMESSAGES, DEFAULT_SETTING_ADVERTISMENT_TEASERMESSAGES))
- {
- STRINGLIST* pslTeasers = SLNewList();
- bFound = FALSE;
-
- // Load teasers
- GetSpamDefinitionData(pslTeasers, SDID_TEASERTEXTS);
-
- for (i=SL_MIN_POS; i<=SLGetMaxPos(pslTeasers); i++)
- if (StrCmp(pszClearedMsgText, SLGetItem(pslTeasers, i)) == 0)
- {
- bFound = TRUE;
- break;
- }
-
- SLFreeList(pslTeasers);
-
- if (bFound)
- {
- if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is teaser"));
- bKickOut = TRUE;
- if (!bDoLog) goto AdvertismentResult;
- }
- }
-
- // Message containing URLs?
- if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_URL, DEFAULT_SETTING_ADVERTISMENT_URL))
- {
- STRINGLIST* psl = SLNewList();
- WCHAR* pszModUrlInd = NULL;
- bFound = FALSE;
-
- // Load url definition files
- GetSpamDefinitionData(psl, SDID_URLTLDS);
-
- for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
- {
- // Different formated check?
- if (pszFormatedMsgText)
- pszModUrlInd = InsertSubStrEveryNChars(SLGetItem(psl, i), 1, _T(" "), FALSE, FALSE); // check for words with spaces/linefeeds/slashes between each char
-
- if (StrStrI(pszClearedMsgText, SLGetItem(psl, i)) || ((pszModUrlInd && pszFormatedMsgText) ? StrStrI(pszFormatedMsgText, pszModUrlInd) : FALSE) )
- {
- bFound = TRUE;
- break;
- }
-
- if (pszModUrlInd)
- {
- mir_free(pszModUrlInd);
- pszModUrlInd = NULL;
- }
- }
-
- SLFreeList(psl);
-
- if (bFound)
- {
- if (bDoLog) SLAddItem(pslRecognition, TranslateW("Contains URL address"));
- bKickOut = TRUE;
- if (!bDoLog) goto AdvertismentResult;
- }
- }
-
- // Message containing phone numbers?
- if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_PHONENUMBERS, DEFAULT_SETTING_ADVERTISMENT_PHONENUMBERS))
- {
- STRINGLIST* psl = SLNewList();
- WCHAR* pszModContent;
- bFound = FALSE;
-
- // Load localized phonenumbers
- GetSpamDefinitionData(psl, SDID_PHONENUMBERS);
-
- pszModContent = mir_wstrdup(pszClearedMsgText);
- if (pszModContent)
- {
- // Check for normal formated phonennumbers
- {
- // Remove spaces
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T(" "), NULL, TRUE, FALSE);
- // Replace wrong slashs
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("\\"), _T("/"), TRUE, FALSE);
-
- // Replace numbers
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("0"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("1"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("2"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("3"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("4"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("5"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("6"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("7"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("8"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("9"), _T("#"), TRUE, FALSE);
-
- for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
- if (StrStrI(pszModContent, SLGetItem(psl, i)))
- {
- bFound = TRUE;
- break;
- }
- }
-
- // Check different formated phone numbers
- if (!bFound && pszFormatedMsgText)
- {
- WCHAR* pszNumberFormatedMsgText = mir_wstrdup(pszClearedMsgText);
- if (pszNumberFormatedMsgText)
- {
- // -- Create number formated text
- STRINGLIST* pslFormat = SLNewList();
-
- // Some words may have special chars in between the chars
- GetSpamDefinitionData(pslFormat, SDID_SPECIALCHARS_SEPARATORS);
-
- for (i=SL_MIN_POS; i<=SLGetMaxPos(pslFormat); i++)
- ReplaceSubStringWithStringBuf(pszNumberFormatedMsgText, 0, SLGetItem(pslFormat, i), _T(" "), TRUE, FALSE);
-
- SLClearList(pslFormat);
-
- // Translate some chars
- GetSpamDefinitionData(pslFormat, SDID_SPECIALCHARS_REPLACE_NUMBERS);
- ReplaceSubStringWithStringMultipleBuf(pszNumberFormatedMsgText, 0, pslFormat, TRUE, FALSE);
-
- SLFreeList(pslFormat);
-
-
- //-- Check the text
- // Remove spaces
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T(" "), NULL, TRUE, FALSE);
- // Replace wrong slashs
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("\\"), _T("/"), TRUE, FALSE);
-
- // Replace numbers
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("0"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("1"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("2"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("3"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("4"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("5"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("6"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("7"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("8"), _T("#"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszModContent, 0, _T("9"), _T("#"), TRUE, FALSE);
-
- for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
- if (StrStrI(pszModContent, SLGetItem(psl, i)))
- {
- bFound = TRUE;
- break;
- }
- }
- }
-
- mir_free(pszModContent);
- }
-
- SLFreeList(psl);
-
- if (bFound)
- {
- if (bDoLog) SLAddItem(pslRecognition, TranslateW("Contains phone number"));
- bKickOut = TRUE;
- if (!bDoLog) goto AdvertismentResult;
- }
- }
-
- // Message contains bad words and/or formated bad words?
- if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS, (BYTE)TRUE) || DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTBADWORDS, DEFAULT_SETTING_ADVERTISMENT_DEFAULTBADWORDS) )
- {
- STRINGLIST* psl = SLNewList();
- unsigned int uFoundBadWords = 0;
- unsigned int uFoundFormatedWords = 0;
- BOOL bRegExpMalformed;
- unsigned int uRegExpErrors;
-
- // Load cutomized bad words if activated
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS, (BYTE)TRUE) )
- GetSpamDefinitionData(psl, SDID_CUSTOM_BADWORDS);
-
- // Check customized bad words...
- for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
- if (RegExpExistsInString(pszClearedMsgText, SLGetItem(psl, i), FALSE, NULL))
- uFoundBadWords++;
-
- // Load all default bad words files if activated
- SLClearList(psl);
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTBADWORDS, DEFAULT_SETTING_ADVERTISMENT_DEFAULTBADWORDS) )
- GetSpamDefinitionData(psl, SDID_BADWORDS);
-
- // Check default bad words...
- uRegExpErrors = 0;
- for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
- {
- if (RegExpExistsInString(pszClearedMsgText, SLGetItem(psl, i), FALSE, &bRegExpMalformed))
- uFoundBadWords++;
-
- if (bRegExpMalformed)
- uRegExpErrors++;
- }
- if (uRegExpErrors > 0)
- ShowInfoMessage(NIIF_WARNING, TranslateW("Spam Filter Warning"), TranslateW("The filter has detected %u malformed Regular Expression(s) in the default bad words!\r\n\r\nPlease update your installed Spam Definitions to the latest versions to resolve this problem.\r\nThis problem might also be caused by Spam Definitions that are not compatible with your system codepage."), MAX_INT_LENGTH, uRegExpErrors);
-
- // Check different formated bad words...
- if (pszFormatedMsgText)
- {
- WCHAR* pszDiffWord;
-
- // AGAIN!: Load cutomized bad words again if activated
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS, (BYTE)TRUE) )
- GetSpamDefinitionData(psl, SDID_CUSTOM_BADWORDS);
-
- // Check again for bad words
- for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
- {
- pszDiffWord = InsertSubStrEveryNChars(SLGetItem(psl, i), 1, _T(" "), FALSE, FALSE); // check for words with spaces/linefeeds between each char
-
- if (RegExpExistsInString(pszFormatedMsgText, SLGetItem(psl, i), FALSE, NULL))
- {
- uFoundFormatedWords++;
-
- } else {
- pszDiffWord = InsertSubStrEveryNChars(SLGetItem(psl, i), 1, _T(" "), FALSE, FALSE); // check for words with spaces/linefeeds between each char
- if (pszDiffWord)
- {
- if (StrStrI(pszFormatedMsgText, pszDiffWord))
- uFoundFormatedWords++;
-
- mir_free(pszDiffWord);
- }
- }
- }
-
- // Calculate diff
- uFoundFormatedWords = (uFoundFormatedWords > uFoundBadWords) ? uFoundFormatedWords = uFoundFormatedWords-uFoundBadWords : 0;
- }
-
- SLFreeList(psl);
-
- // Enough bad words for spam found?
- if (uFoundBadWords > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDBADWORDS, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDBADWORDS))
- {
- if (bDoLog) SLItemPrintf(pslRecognition, SLAddItem(pslRecognition, TranslateW("Contains %u bad phrase(s)/pattern(s)")) , MAX_INT_LENGTH, uFoundBadWords);
- bKickOut = TRUE;
- }
-
- // Enough formated bad words found?
- if (uFoundFormatedWords > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS))
- {
- if (bDoLog) SLItemPrintf(pslRecognition, SLAddItem(pslRecognition, TranslateW("Contains %u differently formated bad phrase(s)/pattern(s)")), MAX_INT_LENGTH, uFoundFormatedWords);
- bKickOut = TRUE;
- }
-
- if (bKickOut && !bDoLog) goto AdvertismentResult;
- }
-
- // Good words check
- if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDGOODWORDS, (BYTE)TRUE) )
- {
- STRINGLIST* psl = SLNewList();
- unsigned int uFoundGoodWords = 0;
-
- // Load customized good words
- GetSpamDefinitionData(psl, SDID_CUSTOM_GOODWORDS);
-
- for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
- if (RegExpExistsInString(pszClearedMsgText, SLGetItem(psl, i), FALSE, NULL))
- uFoundGoodWords++;
-
- SLFreeList(psl);
-
- // Enough good words for non-spam found?
- if (uFoundGoodWords > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS))
- {
- if (bDoLog) SLItemPrintf(pslRecognition, SLAddItem(pslRecognition, TranslateW("Contains %u good phrase(s)/pattern(s)")), MAX_INT_LENGTH, uFoundGoodWords);
- bKickOut = FALSE;
- if (!bDoLog) goto AdvertismentResult;
- }
- }
-
-
-AdvertismentResult:
-
- if (pszClearedMsgText) mir_free(pszClearedMsgText);
- if (pszFormatedMsgText) mir_free(pszFormatedMsgText);
-
- #if defined(UNICODE)
- if (!(pscd->dwFlags&SCDF_UNICODE) && pszNormalMsgText)
- mir_free(pszNormalMsgText);
- #else
- if ((pscd->dwFlags&SCDF_UNICODE) && pszNormalMsgText)
- mir_free(pszNormalMsgText);
- #endif
-
-
- // Kick out spam
- if ( bKickOut && (NotifyEventHooks(hEventOkToSpamDetection, (WPARAM)pscd, (LPARAM)SFT_ADVERTISMENT_FILTER) == 0))
- {
- DWORD dwReturn = SFF_ISSPAM | ((DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, DEFAULT_SETTING_BEHAVIOUR) == 1) ? SFF_MARKREAD : SFF_DELETE);
-
- if (!(pscd->dwFlags&SCDF_NO_NOTIFY))
- {
- // Play sound file
- SkinPlaySound(DB_SOUND_ADVERTISMENT_SETTING);
-
- // Show Popup
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, DEFAULT_SETTING_POPUP))
- {
- WCHAR* pszDisplayName = SCD_GetContactCustomDisplayName(pscd);
-
- ShowSpamPopup(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszDisplayName, (pscd->dwFlags&SCDF_NO_CONTACT)?NULL:pscd->hContact, SFT_ADVERTISMENT_FILTER);
- if (pszDisplayName) mir_free(pszDisplayName);
- }
-
- // Hand out event
- NotifyEventHooks(hEventSpamReceived, (WPARAM)pscd, (LPARAM)SFT_ADVERTISMENT_FILTER);
-
- // Trigger Plugin Support
- TriggerIncomingSpam();
- }
-
- // Append to log file
- if (bDoLog)
- {
- WCHAR* pszUserName = SCD_GetContactName(pscd, TRUE);
-
- WriteToLogFile(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszUserName, pszNormalMsgText, pslRecognition, dwReturn);
- if (pszUserName) mir_free(pszUserName);
-
- SLFreeList(pslRecognition);
- }
-
- // Add user to ignore list
- if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE) && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, DEFAULT_SETTING_AUTOADDSPAMMERS) )
- {
- if (IncreasePreSpammerCount(pscd) > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, DEFAULT_SETTING_ALLOWEDSPAMMESSAGES))
- {
- RemovePreSpammerCount(pscd);
- dwReturn |= SFF_IGNORE;
- }
- }
-
- return dwReturn;
-
- } else {
-
- if (bDoLog)
- SLFreeList(pslRecognition);
-
- //if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE))
- // RemovePreSpammerCount(scd); // do not remove count here! (will cause problems)
-
- // Message is normal
- return SFF_ISNORMAL;
- }
-
- }
-}
-
-
-// --------------------------------
-
-int GetMsgTypeID(const char* pszSection, const char* pszName)
-{
- unsigned int u;
-
- EnterCriticalSection(&csMsgTypes); // thread safety
-
- if (pszSection && pszName && pamtdMsgTypes)
- for (u=0; u<uMsgTypesCount; u++)
- if (StrCmpA(pamtdMsgTypes[u].pszSection, pszSection) == 0)
- if (StrCmpA(pamtdMsgTypes[u].pszName, pszName) == 0)
- {
- LeaveCriticalSection(&csMsgTypes); // thread safety
- return u;
- }
-
- LeaveCriticalSection(&csMsgTypes); // thread safety
- return -1;
-}
-
-
-char* GetMsgTypeSettingName(const char* pszSection, const char* pszName)
-{
- // returned char* needs to be freed
- char* pszReturn;
- int iSize;
-
- if (!pszSection || !pszName) return NULL;
-
- iSize = lstrlenA(pszSection)+1+lstrlenA(pszName)+1;
- pszReturn = (char*)mir_alloc(iSize*sizeof(char));
-
- if (pszReturn)
- mir_snprintf(pszReturn, iSize, "%s_%s", pszSection, pszName);
-
- return pszReturn;
-}
-
-
-BOOL IsOnlyOneMsgTypeSectionRegistered(void)
-{
- unsigned int u;
-
- EnterCriticalSection(&csMsgTypes); // thread safety
-
- if (pamtdMsgTypes)
- for (u=0; u<(uMsgTypesCount-1); u++)
- if (StrCmpA(pamtdMsgTypes[u].pszSection, pamtdMsgTypes[u+1].pszSection) != 0)
- {
- LeaveCriticalSection(&csMsgTypes); // thread safety
- return FALSE;
- }
-
- LeaveCriticalSection(&csMsgTypes); // thread safety
- return TRUE;
-}
-
-
-void NotifyModuleLoaded(void)
-{
- // Hand out event (spam filter functionality now fully available)
- NotifyEventHooks(hEventModuleLoaded, 0, 0);
-}
-
-void NotifySpammerStateChanged(HANDLE hContact, BOOL bNewIsSpammer)
-{
- // Hand out event (spammer state setting was changed)
- NotifyEventHooks(hEventContactSpammerStateChanged, (WPARAM)hContact, (LPARAM)bNewIsSpammer);
-}
-
-// --------------------------------
-
-
-void InitServices(void)
-{
- // Init message type list
- uMsgTypesCount = 0;
- pamtdMsgTypes = NULL;
- InitializeCriticalSection(&csMsgTypes); // thread safety
-
- hEventPreRegisterMessageType = CreateHookableEvent(ME_SPAMFILTER_PREREGISTERMESSAGETYPE);
- hEventOkToSpamCheck = CreateHookableEvent(ME_SPAMFILTER_OKTOSPAMCHECK);
- hEventOkToSpamDetection = CreateHookableEvent(ME_SPAMFILTER_OKTOSPAMDETECTION);
- hEventSpamReceived = CreateHookableEvent(ME_SPAMFILTER_SPAMRECEIVED);
- hEventModuleLoaded = CreateHookableEvent(ME_SPAMFILTER_MODULELOADED);
- hEventContactSpammerStateChanged = CreateHookableEvent(ME_SPAMFILTER_CONTACT_SPAMMERSTATECHANGED);
-
- hServices[0] = CreateServiceFunction(MS_SPAMFILTER_ADVERTISMENTCHECK, ServiceAdvertismentCheck);
- hServices[1] = CreateServiceFunction(MS_SPAMFILTER_DISLIKEDMESSAGESCHECK, ServiceDislikedMessageCheck);
- hServices[2] = CreateServiceFunction(MS_SPAMFILTER_ROBOTCHECK, ServiceRobotCheck);
-
- hServices[3] = CreateServiceFunction(MS_SPAMFILTER_REGISTERMESSAGETYPE, ServiceRegisterMessageType);
- hServices[4] = CreateServiceFunction(MS_SPAMFILTER_REMOVEMESSAGETYPE, ServiceRemoveMessageType);
- hServices[5] = CreateServiceFunction(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, ServiceIsMessageTypeActivated);
-
- hServices[6] = CreateServiceFunction(MS_SPAMFILTER_GETHANDLE, ServiceGetHandle);
- hServices[7] = CreateServiceFunction(MS_SPAMFILTER_SHOWERROR, ServiceShowError);
- hServices[8] = CreateServiceFunction(MS_SPAMFILTER_SHOWFILTERDIALOG, ServiceShowFilterDialog);
-
- hServices[9] = CreateServiceFunction(MS_SPAMFILTER_CHANGEFILTERACTIVATION, ServiceChangeFilterActivation);
- hServices[10] = CreateServiceFunction(MS_SPAMFILTER_GETSPAMCHECKINFO, ServiceGetSpamCheckInfo);
-
- hServices[11] = CreateServiceFunction(MS_SPAMFILTER_RESETAUTOIGNORE, ServiceResetAutoIgnore);
-
- hServices[12] = CreateServiceFunction(MS_SPAMFILTER_CONTACT_SETASSPAMMER, ServiceContactSetAsSpammer);
- hServices[13] = CreateServiceFunction(MS_SPAMFILTER_CONTACT_SHOWSETASSPAMMERDIALOG, ServiceContactShowSetAsSpammerDialog);
- hServices[14] = CreateServiceFunction(MS_SPAMFILTER_CONTACT_ISSPAMMER, ServiceContactIsSpammer);
- hServices[15] = CreateServiceFunction(MS_SPAMFILTER_CONTACT_UNSETSPAMMER, ServiceContactUnSetSpammer);
-
- hServices[16] = CreateServiceFunction(MS_SPAMFILTER_COPYSPAMCHECKDATA, ServiceCopySpamCheckData);
- hServices[17] = CreateServiceFunction(MS_SPAMFILTER_FREESPAMCHECKDATA, ServiceFreeSpamCheckData);
-
- // Backward compatibility (for v1.0.1.0)
- hServices[18] = CreateServiceFunction(MS_SPAMFILTER_SETSPAMMANUALLY, ServiceContactShowSetAsSpammerDialog);
-}
-
-void UninitServices(void)
-{
- // Destroy services
- int i;
- for (i=0; i<ARRAYSIZE(hServices); i++)
- if (hServices[i]) DestroyServiceFunction(hServices[i]);
-
- if (hEventPreRegisterMessageType)
- DestroyHookableEvent(hEventPreRegisterMessageType);
- if (hEventOkToSpamCheck)
- DestroyHookableEvent(hEventOkToSpamCheck);
- if (hEventOkToSpamDetection)
- DestroyHookableEvent(hEventOkToSpamDetection);
- if (hEventSpamReceived)
- DestroyHookableEvent(hEventSpamReceived);
- if (hEventModuleLoaded)
- DestroyHookableEvent(hEventModuleLoaded);
- if (hEventContactSpammerStateChanged)
- DestroyHookableEvent(hEventContactSpammerStateChanged);
-
- // Unload message type list
- EnterCriticalSection(&csMsgTypes); // thread safety (waiting for operations to fisnish)
- if (pamtdMsgTypes)
- {
- unsigned int u;
- for (u=0; u<uMsgTypesCount; u++)
- {
- if (pamtdMsgTypes[u].pszSection) mir_free(pamtdMsgTypes[u].pszSection);
- if (pamtdMsgTypes[u].pszSectionDescription) mir_free(pamtdMsgTypes[u].pszSectionDescription);
- if (pamtdMsgTypes[u].pszName) mir_free(pamtdMsgTypes[u].pszName);
- if (pamtdMsgTypes[u].pszDescription) mir_free(pamtdMsgTypes[u].pszDescription);
- if (pamtdMsgTypes[u].hIcon && ((int)pamtdMsgTypes[u].hIcon > 0)) DestroyIcon(pamtdMsgTypes[u].hIcon);
- if (pamtdMsgTypes[u].hSectionIcon) DestroyIcon(pamtdMsgTypes[u].hSectionIcon);
- }
- mir_free(pamtdMsgTypes);
- }
- uMsgTypesCount = 0;
- pamtdMsgTypes = NULL;
- LeaveCriticalSection(&csMsgTypes); // thread safety
- DeleteCriticalSection(&csMsgTypes); // thread safety
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// -- Includes
+#include "common.h"
+
+// -- Variables: Events/Hooks
+HANDLE hEventPreRegisterMessageType = NULL;
+HANDLE hEventOkToSpamCheck = NULL;
+HANDLE hEventOkToSpamDetection = NULL;
+HANDLE hEventSpamReceived = NULL;
+HANDLE hEventModuleLoaded = NULL;
+HANDLE hEventContactSpammerStateChanged = NULL;
+
+// -- Variables: Services
+HANDLE* hServices[19] = {NULL};
+
+
+// -----------------------------------------
+
+// Service: MS_SPAMFILTER_GETHANDLE
+static int ServiceGetHandle(WPARAM wParam, LPARAM lParam)
+{
+ switch ((UINT)wParam)
+ {
+ //case 1: return NULL; // hInstance was removed in v2.5.1.0
+
+ case SFHT_HWND_PLUGIN_OPTIONS: return IsWindow(hwndSpamFilterOpt) ? (int)hwndSpamFilterOpt : (int)NULL;
+ case SFHT_HWND_ADVERTISMENT_FILTER: return IsWindow(hwndAdvertismentFilter) ? (int)hwndAdvertismentFilter : (int)NULL;
+ case SFHT_HWND_ROBOT_FILTER: return IsWindow(hwndRobotFilter) ? (int)hwndRobotFilter : (int)NULL;
+ case SFHT_HWND_DISLIKEDMESSAGES_FILTER: return IsWindow(hwndDislikedMessagesFilter) ? (int)hwndDislikedMessagesFilter : (int)NULL;
+ case SFHT_HWND_SPAMDEFINITIONS_INFO: return IsWindow(hwndSpamDefinitionsInfo) ? (int)hwndSpamDefinitionsInfo : (int)NULL;
+ case SFHT_HWND_SPAMMERS_INFO: return IsWindow(hwndSpammersInfo) ? (int)hwndSpammersInfo : (int)NULL;
+
+ case SFHT_HICON_SPAM: return (int)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
+ case SFHT_HICON_SPAM_LARGE: return (int)LoadImage(hInstance, MAKEINTRESOURCE(IDI_DEFAULT_LARGE), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
+ case SFHT_HICON_SPAM_LAYER: return (int)LoadImage(hInstance, MAKEINTRESOURCE(IDI_SPAM_LAYER), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
+
+ case 100: // backward compatibility
+ #if defined(UNICODE)
+ case SFHT_BOOL_IS_UNICODE: return TRUE;
+ #else
+ case SFHT_BOOL_IS_UNICODE: return FALSE;
+ #endif
+
+ default: return (int)NULL;
+ }
+}
+
+
+// Service: MS_SPAMFILTER_SHOWERROR
+static int ServiceShowError(WPARAM wParam, LPARAM lParam)
+{
+ switch ((UINT)wParam)
+ {
+ case SFSE_CRITICAL_ERROR:
+ {
+ ShowInfoMessage(NIIF_ERROR, TranslateW("Spam Filter Critical Error"), TranslateW("A very critical internal error was detected!\r\nProbably the filter will not work at all.\r\n\r\nPlease update to the most current version if this problem persists."), 0);
+ return 0;
+ }
+
+ case SFSE_SEND_FAILED:
+ {
+ WCHAR* pszUserName;
+ if (lParam && (((SPAMCHECKDATA*)lParam)->cbSize < sizeof(SPAMCHECKDATA))) return 1;
+ pszUserName = lParam?SCD_GetContactCustomDisplayName((SPAMCHECKDATA*)lParam):NULL;
+ ShowInfoMessage(NIIF_WARNING, TranslateW("Spam Filter Error"), TranslateW("Spam Filter was not able to send an automated message to the user \"%s\"."), pszUserName?lstrlen(pszUserName):0, pszUserName?pszUserName:_T(""));
+ if (pszUserName) mir_free(pszUserName);
+ return 0;
+ }
+
+ default:
+ return 1;
+ }
+}
+
+
+// Service: MS_SPAMFILTER_COPYSPAMCHECKDATA
+static int ServiceCopySpamCheckData(WPARAM wParam, LPARAM lParam)
+{
+ SPAMCHECKDATA* to = (SPAMCHECKDATA*)wParam;
+ SPAMCHECKDATA* from = (SPAMCHECKDATA*)lParam;
+
+
+ if (!from || !to || (from && (from->cbSize < sizeof(SPAMCHECKDATA))) ) {
+ if (to) to->cbSize = sizeof(SPAMCHECKDATA);
+ return 1;
+ }
+ CopyMemory(to, from, from->cbSize);
+ if (to->pszMsgTypeName) to->pszMsgTypeName = mir_strdup(to->pszMsgTypeName);
+ if (to->pszMsgTypeSection) to->pszMsgTypeSection = mir_strdup(to->pszMsgTypeSection);
+ if (to->pszMsgText) {
+ if (to->dwFlags&SCDF_UNICODE)
+ to->pszMsgText = mir_strdup(to->pszMsgText);
+ else
+ to->pwszMsgText = mir_wstrdup(to->pwszMsgText);
+ }
+ if ((to->dwFlags&SCDF_NO_CONTACT) && to->pszUserName) {
+ if (to->dwFlags&SCDF_UNICODE)
+ to->pszUserName = mir_strdup(to->pszUserName);
+ else
+ to->pwszUserName = mir_wstrdup(to->pwszUserName);
+ }
+ to->cbSize = sizeof(SPAMCHECKDATA);
+ return 0;
+}
+
+
+// Service: MS_SPAMFILTER_FREESPAMCHECKDATA
+static int ServiceFreeSpamCheckData(WPARAM wParam, LPARAM lParam)
+{
+ SPAMCHECKDATA* pscd = (SPAMCHECKDATA*)wParam;
+
+ if (!pscd || (pscd->cbSize < sizeof(SPAMCHECKDATA))) return 1;
+ if (pscd->pszMsgTypeName) mir_free(pscd->pszMsgTypeName);
+ if (pscd->pszMsgTypeSection) mir_free(pscd->pszMsgTypeSection);
+ if (pscd->ptszMsgText) mir_free(pscd->ptszMsgText);
+ if ((pscd->dwFlags&SCDF_NO_CONTACT) && pscd->ptszUserName) mir_free(pscd->ptszUserName);
+ return 0;
+}
+
+
+// Service: MS_SPAMFILTER_SHOWFILTERDIALOG
+static int ServiceShowFilterDialog(WPARAM wParam, LPARAM lParam)
+{
+ HWND hwndParent = (HWND)wParam;
+ DWORD dwFilterType = (DWORD)lParam;
+
+ if (dwFilterType&SFTEXF_SPAMDEFINITIONS_INFO)
+ {
+ INITCOMMONCONTROLSEX icc;
+
+ dwFilterType ^= SFTEXF_SPAMDEFINITIONS_INFO;
+ if ((dwFilterType != SFT_ADVERTISMENT_FILTER) && (dwFilterType != SFT_DISLIKEDMESSAGES_FILTER))
+ return 1;
+
+ if (IsWindow(hwndSpamDefinitionsInfo))
+ {
+ PostMessage(hwndSpamDefinitionsInfo, SFM_REFRESH_SPAMDEFINITIONS, (WPARAM)FALSE, (LPARAM)dwFilterType);
+ SetForegroundWindow(hwndSpamDefinitionsInfo);
+ return 0;
+ }
+
+ // Ensure the needed common controls are loaded
+ ZeroMemory(&icc, sizeof(icc));
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_TAB_CLASSES|ICC_LISTVIEW_CLASSES;
+ InitCommonControlsEx(&icc);
+
+ if (hwndParent) {
+ // hwndSpamDefinitionsInfo will be set on WM_INITDIALOG and set to NULL on WM_DESTROY
+ // *** using ANSI version here because Hyperlink control of Miranda doesn't support Unicode ***
+ //return (DialogBoxParamA(hInstance, MAKEINTRESOURCEA(IDD_INFO_SPAMDEFINITIONS), hwndParent, DlgProcSpamDefinitionsInfo, dwFilterType)>0) ? 0 : 1;
+ return (DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_INFO_SPAMDEFINITIONS), hwndParent, DlgProcSpamDefinitionsInfo, dwFilterType)>0) ? 0 : 1;
+
+ } else {
+ // *** using ANSI version here because Hyperlink control of Miranda doesn't (yet) support Unicode ***
+ //hwndSpamDefinitionsInfo = CreateDialogParamA(hInstance, MAKEINTRESOURCEA(IDD_INFO_SPAMDEFINITIONS), (HWND)NULL, DlgProcSpamDefinitionsInfo, dwFilterType);
+ hwndSpamDefinitionsInfo = CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_INFO_SPAMDEFINITIONS), (HWND)NULL, DlgProcSpamDefinitionsInfo, dwFilterType);
+ return (hwndSpamDefinitionsInfo ? 0 : 1);
+ }
+
+ } else if (dwFilterType&SFTEXF_SPAMMERS_INFO)
+ {
+ dwFilterType ^= SFTEXF_SPAMMERS_INFO;
+ if (dwFilterType != SFTEX_OPTIONS_PAGE)
+ return 1;
+
+ if (IsWindow(hwndSpammersInfo)) {
+ SetForegroundWindow(hwndSpammersInfo);
+ return 0;
+ }
+
+ if (hwndParent) {
+ // hwndSpammersInfo will be set on WM_INITDIALOG and set to NULL on WM_DESTROY
+ return (DialogBox(hInstance, MAKEINTRESOURCE(IDD_INFO_SPAMMERS), hwndParent, DlgProcSpammersInfo)>0) ? 0 : 1;
+
+ } else {
+ hwndSpammersInfo = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_INFO_SPAMMERS), (HWND)NULL, DlgProcSpammersInfo);
+ return (hwndSpammersInfo ? 0 : 1);
+ }
+
+ } else {
+
+ switch (dwFilterType)
+ {
+ case SFTEX_OPTIONS_PAGE:
+ {
+ OPENOPTIONSDIALOG ood;
+
+ ZeroMemory(&ood, sizeof(ood));
+ ood.cbSize = sizeof(ood);
+ ood.pszGroup = Translate("Events");
+ ood.pszPage = Translate("Spam Filter");
+
+ return CallService(MS_OPT_OPENOPTIONS, 0, (LPARAM)&ood);
+ }
+
+ case SFT_DISLIKEDMESSAGES_FILTER:
+ {
+ if (IsWindow(hwndDislikedMessagesFilter)) {
+ SetForegroundWindow(hwndDislikedMessagesFilter);
+ return 0;
+ }
+
+ if (hwndParent) {
+ // hwndDislikedMessagesFilter will be set on WM_INITDIALOG and set to NULL on WM_DESTROY
+ return (DialogBox(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_DISLIKEDMESSAGEFILTER), hwndParent, DlgProcConfigureDislikedMessagesFilter)>0) ? 0 : 1;
+
+ } else {
+ hwndDislikedMessagesFilter = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_DISLIKEDMESSAGEFILTER), (HWND)NULL, DlgProcConfigureDislikedMessagesFilter);
+ return (hwndDislikedMessagesFilter ? 0 : 1);
+ }
+ }
+
+ case SFT_ADVERTISMENT_FILTER:
+ {
+ INITCOMMONCONTROLSEX icc;
+
+ if (IsWindow(hwndAdvertismentFilter)) {
+ SetForegroundWindow(hwndAdvertismentFilter);
+ return 0;
+ }
+
+ // Ensure the needed common controls are loaded
+ ZeroMemory(&icc, sizeof(icc));
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_UPDOWN_CLASS;
+ InitCommonControlsEx(&icc);
+
+ if (hwndParent) {
+ // hwndAdvertismentFilter will be set on WM_INITDIALOG and set to NULL on WM_DESTROY
+ return (DialogBox(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_ADVERTISMENTFILTER), hwndParent, DlgProcConfigureAdvertismentFilter)>0) ? 0 : 1;
+
+ } else {
+ hwndAdvertismentFilter = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_ADVERTISMENTFILTER), (HWND)NULL, DlgProcConfigureAdvertismentFilter);
+ return (hwndAdvertismentFilter ? 0 : 1);
+ }
+ }
+
+ case SFT_ROBOT_FILTER:
+ {
+ if (IsWindow(hwndRobotFilter)) {
+ SetForegroundWindow(hwndRobotFilter);
+ return 0;
+ }
+
+ if (hwndParent) {
+ // hwndRobotFilter will be set on WM_INITDIALOG and set to NULL on WM_DESTROY
+ return (DialogBox(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_ROBOTFILTER), hwndParent, DlgProcConfigureRobotFilter)>0) ? 0 : 1;
+
+ } else {
+ hwndRobotFilter = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_OPTIONS_CONFIGURE_ROBOTFILTER), (HWND)NULL, DlgProcConfigureRobotFilter);
+ return (hwndRobotFilter ? 0 : 1);
+ }
+ }
+
+ default:
+ return 1;
+ }
+
+ }
+}
+
+
+// Service: MS_SPAMFILTER_RESETAUTOIGNORE
+static int EnumAutoIgnoreSettingsProc(const char* pszSetting, LPARAM lParam)
+{
+ WCHAR* pszBuf;
+ mir_utf8decode((char*)pszSetting,&pszBuf);
+ if (pszBuf) {
+ SLAddItem((STRINGLIST*)lParam, pszBuf);
+ mir_free(pszBuf);
+ }
+ return 0;
+}
+
+static int ServiceResetAutoIgnore(WPARAM wParam, LPARAM lParam)
+{
+ BOOL bOnlyCount = (BOOL)wParam;
+
+ int iReturn;
+ DBCONTACTENUMSETTINGS dbces;
+ STRINGLIST* pslSettings = SLNewList();
+ int i;
+ #if defined(UNICODE)
+ char* pszBuf;
+ #endif
+
+ // Enum settings
+ dbces.szModule = DB_MODULE_NAME_PRESPAMMERS;
+ dbces.pfnEnumProc = EnumAutoIgnoreSettingsProc;
+ dbces.lParam = (LPARAM)pslSettings;
+
+ CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces);
+
+ // Delete settings
+ if (!bOnlyCount)
+ {
+ iReturn = 0;
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(pslSettings); i++)
+ {
+ #if defined(UNICODE)
+ pszBuf = mir_utf8encodeW(SLGetItem(pslSettings, i));
+ if (pszBuf)
+ {
+ if (DBDeleteContactSetting(NULL, dbces.szModule, pszBuf) != 0)
+ iReturn++;
+ }
+ #else
+ if (DBDeleteContactSetting(NULL, dbces.szModule, SLGetItem(pslSettings, i)) != 0)
+ iReturn++;
+ #endif
+ }
+ } else {
+ iReturn = SLGetItemCount(pslSettings);
+ }
+
+ // Free memory
+ SLFreeList(pslSettings);
+
+ return iReturn;
+}
+
+
+// Service: MS_SPAMFILTER_CONTACT_SETASSPAMMER
+static int ServiceContactSetAsSpammer(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ DWORD dwFlags = (DWORD)lParam;
+
+ if (!hContact || (hContact == INVALID_HANDLE_VALUE)) return 1;
+
+ if (dwFlags & SCASF_NO_NOTIFY)
+ {
+ if (dwFlags & SCASF_USE_ROBOT_SOUND)
+ SkinPlaySound(DB_SOUND_ROBOT_SETTING);
+ else
+ SkinPlaySound(DB_SOUND_ADVERTISMENT_SETTING);
+ }
+
+ // Add contact to spammer list
+ AddContactToIgnoreList(hContact, !(dwFlags&SCASF_NO_REMOVE_HISTORY), !(dwFlags&SCASF_NO_DENY_AUTHREQUESTS), (dwFlags & SCASF_NO_NOTIFY));
+
+ // Remove pre-spammer flag if exists (now is real spammer)
+ {
+ SPAMCHECKDATA scd;
+
+ ZeroMemory(&scd, sizeof(scd));
+ scd.cbSize = sizeof(scd);
+ scd.hContact = hContact;
+
+ RemovePreSpammerCount(&scd);
+ }
+
+ return 0;
+}
+
+
+// Service: MS_SPAMFILTER_CONTACT_SHOWSETASSPAMMERDIALOG
+static int ServiceContactShowSetAsSpammerDialog(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ HWND hwndParent = (HWND)lParam;
+ BOOL bDlgOK;
+
+ WCHAR* pszFmt;
+ WCHAR* pszUserName;
+ MSGBOXPARAMS mbp;
+
+ if (!hContact || (hContact == INVALID_HANDLE_VALUE)) return 1;
+
+ // Correct wrong call (backward compatibility)
+ if (hwndParent == INVALID_HANDLE_VALUE) hwndParent = NULL;
+
+ ZeroMemory(&mbp, sizeof(mbp));
+ mbp.cbSize = sizeof(mbp);
+ mbp.dwLanguageId = LANGIDFROMLCID(GetThreadLocale()); // Current system language: MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
+ mbp.hwndOwner = hwndParent;
+ mbp.hInstance = hInstance;
+ mbp.lpszIcon = MAKEINTRESOURCE(IDI_DEFAULT_LARGE);
+ mbp.dwStyle = MB_USERICON|MB_YESNO|MB_DEFBUTTON1|MB_SETFOREGROUND|MB_TASKMODAL; // MB_RTLREADING works also on non-arabic systems (Win 2000/XP)
+ mbp.lpszCaption = TranslateW("Mark Contact as Spammer");
+ pszUserName = (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE);
+ pszFmt = TranslateW("Are you sure that the contact \"%s\" shall be marked as spammer?\r\n\r\nMarking a contact as spammer means that all associated messages will be recognized as spam and the contact will be completely ignored in the future.\r\n\r\nA contact that was marked as spammer can be restored using the options dialog.");
+ mbp.lpszText = (WCHAR*)mir_alloc((lstrlen(pszFmt)+(pszUserName?lstrlen(pszUserName):0)+1)*sizeof(WCHAR));
+ mir_sntprintf((WCHAR*)mbp.lpszText, (lstrlen(pszFmt) + (pszUserName?lstrlen(pszUserName):0) + 1), pszFmt, pszUserName?pszUserName:_T(""));
+
+ bDlgOK = (MessageBoxIndirect(&mbp) == IDYES);
+ if ((char*)mbp.lpszText) mir_free((char*)mbp.lpszText);
+
+ if (bDlgOK)
+ {
+ BOOL bNoLog;
+ BOOL bKeepHistory;
+
+ // Get mark-read / delete setting
+ bKeepHistory = ((DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, DEFAULT_SETTING_BEHAVIOUR) == 1) ? TRUE : FALSE);
+
+ // Check id ctrl key is pressed to manually cancel logging
+ if (GetAsyncKeyState(VK_CONTROL)&0x8000)
+ bNoLog = FALSE;
+ else
+ bNoLog = TRUE;
+
+ SkinPlaySound(DB_SOUND_ADVERTISMENT_SETTING);
+
+ // Add contact to spammer list
+ AddContactToIgnoreList(hContact, bKeepHistory, TRUE, bNoLog);
+
+ // Remove pre-spammer flag (now is real spammer)
+ {
+ SPAMCHECKDATA scd;
+
+ ZeroMemory(&scd, sizeof(scd));
+ scd.cbSize = sizeof(scd);
+ scd.hContact = hContact;
+
+ RemovePreSpammerCount(&scd);
+ }
+ }
+
+ return (int)bDlgOK;
+}
+
+
+// Service: MS_SPAMFILTER_CONTACT_ISSPAMMER
+static int ServiceContactIsSpammer(WPARAM wParam, LPARAM lParam)
+{
+ return (BYTE)(DBGetContactSettingByte((HANDLE)wParam, DB_MODULE_NAME, DB_SETTING_ISSPAMMER, (BYTE)FALSE)?TRUE:FALSE);
+}
+
+
+// Service: MS_SPAMFILTER_CONTACT_UNSETSPAMMER
+static int ServiceContactUnSetSpammer(WPARAM wParam, LPARAM lParam)
+{
+ // Internal note: lParam is hwndParent when used as menu item service
+
+ if ((HANDLE)wParam && ((HANDLE)wParam != INVALID_HANDLE_VALUE) )
+ return RemoveContactFromIgnoreList((HANDLE)wParam) ? 0 : 1;
+ else
+ return 1;
+}
+
+
+// Service: MS_SPAMFILTER_CHANGEFILTERACTIVATION
+static int ServiceChangeFilterActivation(WPARAM wParam, LPARAM lParam)
+{
+ BOOL bNewStatus = (BOOL)lParam;
+ DWORD dwFilterType = (DWORD)wParam;
+
+ switch (dwFilterType)
+ {
+ case SFT_DISLIKEDMESSAGES_FILTER:
+ {
+ if (IsWindow(hwndSpamFilterOpt))
+ CheckDlgButton(hwndSpamFilterOpt, IDC_CHECKBOX_DISLIKEDMESSAGEFILTER, (bNewStatus ? BST_CHECKED : BST_UNCHECKED));
+
+ return DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)bNewStatus);
+ }
+
+ case SFT_ADVERTISMENT_FILTER:
+ {
+ if (IsWindow(hwndSpamFilterOpt))
+ CheckDlgButton(hwndSpamFilterOpt, IDC_CHECKBOX_ADVERTISMENTFILTER, (bNewStatus ? BST_CHECKED : BST_UNCHECKED));
+
+ return DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)bNewStatus);
+ }
+
+ case SFT_ROBOT_FILTER:
+ {
+ if (IsWindow(hwndSpamFilterOpt))
+ CheckDlgButton(hwndSpamFilterOpt, IDC_CHECKBOX_ROBOTFILTER, (bNewStatus ? BST_CHECKED : BST_UNCHECKED));
+
+ return DBWriteContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, (BYTE)bNewStatus);
+ }
+
+ default:
+ return 1;
+ }
+}
+
+
+// Service: MS_SPAMFILTER_GETSPAMCHECKINFO
+static int ServiceGetSpamCheckInfo(WPARAM wParam, LPARAM lParam)
+{
+ DWORD dwInfoType = (DWORD)wParam;
+
+ switch (dwInfoType)
+ {
+ case SFSCI_ACTIVATION_FILTER:
+ {
+ switch ((DWORD)lParam)
+ {
+ case SFT_DISLIKEDMESSAGES_FILTER:
+ return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, DEFAULT_SETTING_DISLIKEDMESSAGEFILTER)?TRUE:FALSE);
+
+ case SFT_ADVERTISMENT_FILTER:
+ return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, DEFAULT_SETTING_ADVERTISMENTFILTER)?TRUE:FALSE);
+
+ case SFT_ROBOT_FILTER:
+ return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOTFILTER, DEFAULT_SETTING_ROBOTFILTER)?TRUE:FALSE);
+ }
+
+ break;
+ }
+
+ case SFSCI_ADD_TO_HISTORY:
+ {
+ switch ((DWORD)lParam)
+ {
+ // Disliked Messages Filter
+ case SFSCI_MSGTEXT_NOTIFYA:
+ case SFSCI_MSGTEXT_NOTIFYW:
+ return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY, DEFAULT_SETTING_DISLIKEDMESSAGE_ADDTOHISTORY)?TRUE:FALSE);
+
+ // Robot Filter
+ case SFSCI_MSGTEXT_INSTRUCTIONA:
+ case SFSCI_MSGTEXT_INSTRUCTIONW:
+ return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ADDTOHISTORY, DEFAULT_SETTING_ROBOT_ADDTOHISTORY)?TRUE:FALSE);
+
+ case SFSCI_MSGTEXT_CONFIRMATIONA:
+ case SFSCI_MSGTEXT_CONFIRMATIONW:
+ return (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ADDTOHISTORY, DEFAULT_SETTING_ROBOT_ADDTOHISTORY)?TRUE:FALSE);
+ }
+ }
+
+ case SFSCI_MSGTEXT_NOTIFYA:
+ case SFSCI_MSGTEXT_INSTRUCTIONA:
+ case SFSCI_MSGTEXT_CONFIRMATIONA:
+ case SFSCI_MSGTEXT_NOTIFYW:
+ case SFSCI_MSGTEXT_INSTRUCTIONW:
+ case SFSCI_MSGTEXT_CONFIRMATIONW:
+ {
+ SPAMCHECKDATA* pscd = (SPAMCHECKDATA*)lParam;
+ char* pszSetting;
+ WCHAR* pszBuf;
+ WCHAR* pReturn;
+ DBVARIANT dbv;
+ STRINGLIST* pslFromTo;
+
+ if (!pscd || (pscd->cbSize < sizeof(SPAMCHECKDATA)) || !SCD_IsUserValid(pscd))
+ break;
+
+ switch (dwInfoType)
+ {
+ // Disliked Messages Filter
+ case SFSCI_MSGTEXT_NOTIFYA:
+ case SFSCI_MSGTEXT_NOTIFYW:
+ pszSetting = DB_SETTING_DISLIKEDMESSAGE_RETURNMESSAGE; // readonly allocated
+ break;
+
+ // Robot Filter
+ case SFSCI_MSGTEXT_INSTRUCTIONA:
+ case SFSCI_MSGTEXT_INSTRUCTIONW:
+ pszSetting = DB_SETTING_ROBOT_INSTRUCTION; // readonly allocated
+ break;
+
+ case SFSCI_MSGTEXT_CONFIRMATIONA:
+ case SFSCI_MSGTEXT_CONFIRMATIONW:
+ pszSetting = DB_SETTING_ROBOT_CONFIRMATION; // readonly allocated
+ break;
+
+ default:
+ pszSetting = NULL;
+ }
+
+ if (pszSetting)
+ {
+ WCHAR* pszVariablesOut = NULL;
+ pslFromTo = SLNewList();
+
+ if ((dwInfoType != SFSCI_MSGTEXT_NOTIFYA) && (dwInfoType != SFSCI_MSGTEXT_NOTIFYW))
+ {
+ // %securitycode%
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, &dbv) == 0)
+ {
+ SLAddItemPair(pslFromTo, _T("%securitycode%"), dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ WCHAR szRnd[RANDOM_ANSWER_LENGTH+1];
+ GetRandomString(szRnd, ARRAYSIZE(szRnd));
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, szRnd);
+ SLAddItemPair(pslFromTo, _T("%securitycode%"), szRnd);
+ }
+
+ // %triesleft%
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, DEFAULT_SETTING_AUTOADDSPAMMERS))
+ {
+ WCHAR szTriesLeft[MAX_INT_LENGTH+1];
+ mir_sntprintf(szTriesLeft, ARRAYSIZE(szTriesLeft), _T("%u"), DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, DEFAULT_SETTING_ALLOWEDSPAMMESSAGES)-GetPreSpammerCount(pscd)+1);
+ SLAddItemPair(pslFromTo, _T("%triesleft%"), szTriesLeft);
+ } else {
+ SLAddItemPair(pslFromTo, _T("%triesleft%"), TranslateW("unlimited"));
+ }
+ }
+
+ // %message%
+ #if defined(UNICODE)
+ if (pscd->dwFlags&SCDF_UNICODE)
+ pszBuf = pscd->ptszMsgText;
+ else
+ pszBuf = (WCHAR*)mir_utf8encodeW((WCHAR*)pscd->pszMsgText);
+
+ SLAddItemPair(pslFromTo, _T("%message%"), pszBuf);
+
+ if (pszBuf && !(pscd->dwFlags&SCDF_UNICODE))
+ mir_free(pszBuf);
+ #else
+ if (pscd->dwFlags&SCDF_UNICODE)
+ pszBuf = UnicodeToAnsi(pscd->pwszMsgText);
+ else
+ pszBuf = pscd->ptszMsgText;
+
+ SLAddItemPair(pslFromTo, _T("%message%"), pszBuf);
+
+ if ((pscd->dwFlags&SCDF_UNICODE) && pszBuf)
+ mir_free(pszBuf);
+ #endif
+
+ // %sender%
+ pszBuf = SCD_GetContactName(pscd, FALSE);
+ SLAddItemPair(pslFromTo, _T("%sender%"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // Retrieve message text
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, pszSetting, &dbv) == 0) {
+ pszBuf = ReplaceSubStringWithStringMultiple(dbv.ptszVal, pslFromTo, TRUE, FALSE, NULL);
+ DBFreeVariant(&dbv);
+ } else {
+ pszBuf = NULL;
+ }
+
+ // Retrieve message text
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, pszSetting, &dbv) == 0) {
+ pszBuf = ReplaceSubStringWithStringMultiple(dbv.ptszVal, pslFromTo, TRUE, FALSE, NULL);
+ DBFreeVariant(&dbv);
+ } else {
+ pszBuf = NULL;
+ }
+ SLFreeList(pslFromTo);
+
+ // Support for "Variables" plugin
+ if (ServiceExists(MS_VARS_FORMATSTRING))
+ {
+ FORMATINFO fi;
+
+ ZeroMemory(&fi, sizeof(fi));
+ fi.cbSize = sizeof(fi);
+ fi.flags = FIF_UNICODE;
+ fi.tszFormat = pszBuf;
+ fi.tszExtraText = pscd->ptszMsgText; // %message% variable is handled earlier by Spam Filter itself
+ fi.hContact = (pscd->dwFlags&SCDF_NO_CONTACT)?NULL:pscd->hContact;
+
+ pszVariablesOut = (WCHAR*)CallService(MS_VARS_FORMATSTRING, (WPARAM)&fi, 0);
+ }
+
+
+ // Convert return value
+ pReturn = NULL;
+ if (pszVariablesOut?pszVariablesOut:pszBuf)
+ {
+ switch (dwInfoType)
+ {
+ case SFSCI_MSGTEXT_NOTIFYA:
+ case SFSCI_MSGTEXT_INSTRUCTIONA:
+ case SFSCI_MSGTEXT_CONFIRMATIONA:
+ {
+ #if defined(UNICODE)
+ // UnicodeToAnsi uses mir_alloc
+ mir_utf8decode((char*)pszVariablesOut?(char*)pszVariablesOut:(char*)pszBuf,&pReturn);
+ #else
+ // AnsiDup uses mir_alloc
+ pReturn = (PBYTE)mir_strdup(pszVariablesOut?pszVariablesOut:pszBuf);
+ #endif
+ break;
+ }
+
+ case SFSCI_MSGTEXT_NOTIFYW:
+ case SFSCI_MSGTEXT_INSTRUCTIONW:
+ case SFSCI_MSGTEXT_CONFIRMATIONW:
+ {
+ #if defined(UNICODE)
+ // UnicodeDup uses mir_alloc
+ pReturn = mir_wstrdup(pszVariablesOut?pszVariablesOut:pszBuf);
+ #else
+ // mir_utf8encodeW uses mir_alloc
+ pReturn = (PBYTE)mir_utf8encodeW(pszVariablesOut?pszVariablesOut:pszBuf);
+ #endif
+ break;
+ }
+ }
+ }
+
+
+ if (pszBuf)
+ SLFreeReturn(pszBuf);
+
+ // Support for "Variables" plugin
+ if (pszVariablesOut)
+ CallService(MS_VARS_FREEMEMORY, (WPARAM)pszVariablesOut, 0);
+
+ return (int)pReturn;
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+// Service: MS_SPAMFILTER_REGISTERMESSAGETYPE
+static int ServiceRegisterMessageType(WPARAM wParam, LPARAM lParam)
+{
+ MESSAGETYPEDESC* pmtdNew = (MESSAGETYPEDESC*)lParam;
+
+ if (!pmtdNew->pszName || !pmtdNew->pszSection || (pmtdNew->cbSize < MESSAGETYPEDESC_V2000_SIZE))
+ return 1;
+
+ // Do not add if already added
+ EnterCriticalSection(&csMsgTypes); // thread safety
+ if (GetMsgTypeID(pmtdNew->pszSection, pmtdNew->pszName) >= 0) {
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ return 1;
+ }
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+
+ // outside critical section:
+ // Hand out event (asking other plugins if default data is ok)
+ if (NotifyEventHooks(hEventPreRegisterMessageType, (WPARAM)wParam, (LPARAM)lParam) == 1) {
+ OutputDebugString(_T("Spam Filter: Adding message type denied (by event).\r\n"));
+ return 1;
+ }
+
+ // Do not add if already added (check again)
+ EnterCriticalSection(&csMsgTypes); // thread safety
+ if (GetMsgTypeID(pmtdNew->pszSection, pmtdNew->pszName) >= 0) {
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ return 1;
+ }
+
+ // Resize list array
+ {
+ MESSAGETYPEDESC* pamtdMsgTypesBuf;
+ pamtdMsgTypesBuf = (MESSAGETYPEDESC*)mir_realloc(pamtdMsgTypes, (uMsgTypesCount+1)*sizeof(MESSAGETYPEDESC));
+
+ if (pamtdMsgTypesBuf) {
+ pamtdMsgTypes = pamtdMsgTypesBuf;
+ } else {
+ // Fatal error: list was not reallocated, insufficient memory (old data still valid)
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ return 1;
+ }
+ }
+
+ pamtdMsgTypes[uMsgTypesCount].cbSize = sizeof(MESSAGETYPEDESC);
+ pamtdMsgTypes[uMsgTypesCount].dwFlags = pmtdNew->dwFlags;
+
+ // Backward compatibility (struct extended in v2.1.1.0)
+ if (pmtdNew->cbSize > MESSAGETYPEDESC_V2000_SIZE) {
+ pamtdMsgTypes[uMsgTypesCount].iPosition = pmtdNew->iPosition;
+ pamtdMsgTypes[uMsgTypesCount].iSectionPosition = pmtdNew->iSectionPosition;
+ } else {
+ pamtdMsgTypes[uMsgTypesCount].iPosition = 0;
+ pamtdMsgTypes[uMsgTypesCount].iSectionPosition = pmtdNew->iSectionPosition;
+ }
+
+ pamtdMsgTypes[uMsgTypesCount].pszSection = mir_strdup(pmtdNew->pszSection);
+ pamtdMsgTypes[uMsgTypesCount].pszName = mir_strdup(pmtdNew->pszName);
+
+ #if defined(UNICODE)
+ if (pmtdNew->dwFlags&MTDF_UNICODE) {
+ pamtdMsgTypes[uMsgTypesCount].ptszSectionDescription = pmtdNew->pwszSectionDescription ? mir_wstrdup(pmtdNew->pwszSectionDescription) : (WCHAR*)mir_utf8encodeW((WCHAR*)Translate((WCHAR*)pmtdNew->pszSection));
+ pamtdMsgTypes[uMsgTypesCount].ptszDescription = pmtdNew->pwszDescription ? mir_wstrdup(pmtdNew->pwszDescription) : (WCHAR*)mir_utf8encodeW((WCHAR*)Translate((WCHAR*)pmtdNew->pszName));
+ } else {
+ pamtdMsgTypes[uMsgTypesCount].dwFlags |= MTDF_UNICODE;
+ pamtdMsgTypes[uMsgTypesCount].ptszSectionDescription = pmtdNew->pszSectionDescription ? (WCHAR*)mir_utf8encodeW((WCHAR*)pmtdNew->pszSectionDescription) : (WCHAR*)mir_utf8encodeW((WCHAR*)Translate((WCHAR*)pmtdNew->pszSection));
+ pamtdMsgTypes[uMsgTypesCount].ptszDescription = pmtdNew->pszDescription ? (WCHAR*)mir_utf8encodeW((WCHAR*)pmtdNew->pszDescription) : (WCHAR*)mir_utf8encodeW((WCHAR*)Translate((WCHAR*)pmtdNew->pszName));
+ }
+ #else
+ if (pmtdNew->dwFlags&MTDF_UNICODE) {
+ pamtdMsgTypes[uMsgTypesCount].dwFlags ^= MTDF_UNICODE;
+ pamtdMsgTypes[uMsgTypesCount].ptszSectionDescription = pmtdNew->pwszSectionDescription ? UnicodeToAnsi(pmtdNew->pwszSectionDescription) : mir_strdup(Translate(pmtdNew->pszSection));
+ pamtdMsgTypes[uMsgTypesCount].ptszDescription = pmtdNew->pwszDescription ? UnicodeToAnsi(pmtdNew->pwszDescription) : mir_strdup(Translate(pmtdNew->pszName));
+ } else {
+ pamtdMsgTypes[uMsgTypesCount].ptszSectionDescription = pmtdNew->pszSectionDescription ? AnsiDup(pmtdNew->pszSectionDescription) : AnsiDup(Translate(pmtdNew->pszSection));
+ pamtdMsgTypes[uMsgTypesCount].ptszDescription = pmtdNew->pszDescription ? AnsiDup(pmtdNew->ptszDescription) : AnsiDup(Translate(pmtdNew->pszName));
+ }
+ #endif
+
+ // Fatal error (strings were not allocated, insufficient memory)
+ if (!pamtdMsgTypes[uMsgTypesCount].pszSection || !pamtdMsgTypes[uMsgTypesCount].pszSectionDescription || !pamtdMsgTypes[uMsgTypesCount].pszName || !pamtdMsgTypes[uMsgTypesCount].pszDescription)
+ {
+ if (pamtdMsgTypes[uMsgTypesCount].pszSection) mir_free(pamtdMsgTypes[uMsgTypesCount].pszSection);
+ if (pamtdMsgTypes[uMsgTypesCount].pszSectionDescription) mir_free(pamtdMsgTypes[uMsgTypesCount].pszSectionDescription);
+ if (pamtdMsgTypes[uMsgTypesCount].pszName) mir_free(pamtdMsgTypes[uMsgTypesCount].pszName);
+ if (pamtdMsgTypes[uMsgTypesCount].pszDescription) mir_free(pamtdMsgTypes[uMsgTypesCount].pszDescription);
+
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ return 1;
+ }
+
+ pamtdMsgTypes[uMsgTypesCount].hSectionIcon = pmtdNew->hSectionIcon ? (HICON)CopyImage(pmtdNew->hSectionIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_COPYFROMRESOURCE) : NULL;
+
+ if ((int)pmtdNew->hIcon < 0) // if is miranda skinned icon constant
+ pamtdMsgTypes[uMsgTypesCount].hIcon = pmtdNew->hIcon;
+ else
+ pamtdMsgTypes[uMsgTypesCount].hIcon = pmtdNew->hIcon ? (HICON)CopyImage(pmtdNew->hIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_COPYFROMRESOURCE) : NULL;
+
+
+ uMsgTypesCount++;
+
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+
+ // Refresh shown list
+ if (IsWindow(hwndSpamFilterOpt))
+ SendMessage(hwndSpamFilterOpt, SFM_REBUILD_MSGTYPES, 0, 0);
+
+ return 0;
+}
+
+
+// Service: MS_SPAMFILTER_REMOVEMESSAGETYPE
+static int ServiceRemoveMessageType(WPARAM wParam, LPARAM lParam)
+{
+ char* pszMsgTypeSection = (char*)wParam;
+ char* pszMsgTypeName = (char*)lParam;
+
+ MESSAGETYPEDESC* pamtdMsgTypesBuf;
+ int iReturn;
+ char* pszSetting;
+ unsigned int u;
+
+ if (!pszMsgTypeName || !pszMsgTypeSection) return 1;
+ iReturn = 1;
+
+ EnterCriticalSection(&csMsgTypes); // thread safety
+
+ // Remove array item
+ if (pamtdMsgTypes)
+ {
+ for (u=0; u<uMsgTypesCount; u++)
+ {
+ // Same pszSection?
+ if (StrCmpA(pamtdMsgTypes[u].pszSection, pszMsgTypeSection) == 0)
+ {
+ // Same pszName? (when no name is specified all items of the same section are removed)
+ if (StrCmpA(pamtdMsgTypes[u].pszName, pszMsgTypeName) == 0)
+ {
+ // -> Item to remove found
+
+ // Delete database setting
+ pszSetting = GetMsgTypeSettingName(pamtdMsgTypes[u].pszSection, pamtdMsgTypes[u].pszName);
+ if (pszSetting)
+ {
+ DBDeleteContactSetting(NULL, DB_MODULE_NAME_MSGTYPES, pszSetting);
+ mir_free(pszSetting);
+ }
+
+ // Free array item memory
+ if (pamtdMsgTypes[u].pszSection) mir_free(pamtdMsgTypes[u].pszSection);
+ if (pamtdMsgTypes[u].pszName) mir_free(pamtdMsgTypes[u].pszName);
+ if (pamtdMsgTypes[u].ptszSectionDescription) mir_free(pamtdMsgTypes[u].ptszSectionDescription);
+ if (pamtdMsgTypes[u].ptszDescription) mir_free(pamtdMsgTypes[u].ptszDescription);
+ if (pamtdMsgTypes[u].hIcon && ((int)pamtdMsgTypes[u].hIcon > 0)) DestroyIcon(pamtdMsgTypes[u].hIcon);
+ if (pamtdMsgTypes[u].hSectionIcon) DestroyIcon(pamtdMsgTypes[u].hSectionIcon);
+
+ // Move other array items (if not last item)
+ if ((u+1) < uMsgTypesCount)
+ MoveMemory(&pamtdMsgTypes[u], &pamtdMsgTypes[u+1], ((uMsgTypesCount-u-1)*sizeof(MESSAGETYPEDESC)));
+
+ // Resize array
+ pamtdMsgTypesBuf = (MESSAGETYPEDESC*)mir_realloc(pamtdMsgTypes, (uMsgTypesCount-1)*sizeof(MESSAGETYPEDESC));
+ if (pamtdMsgTypesBuf)
+ pamtdMsgTypes = pamtdMsgTypesBuf;
+
+ // Decrase list count
+ uMsgTypesCount--;
+
+ iReturn = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+
+ // Refresh shown list
+ if (IsWindow(hwndSpamFilterOpt))
+ SendMessage(hwndSpamFilterOpt, SFM_REBUILD_MSGTYPES, 0, 0);
+
+ return iReturn;
+}
+
+
+// Service: MS_SPAMFILTER_ISMESSAGETYPEACTIVATED
+static int ServiceIsMessageTypeActivated(WPARAM wParam, LPARAM lParam)
+{
+ int iMsgType;
+ BOOL bReturn = FALSE;
+
+ EnterCriticalSection(&csMsgTypes); // thread safety
+
+ iMsgType = GetMsgTypeID((const char*)wParam, (const char*)lParam);
+ if (iMsgType != -1)
+ if (pamtdMsgTypes[iMsgType].dwFlags&MTDF_HIDDEN)
+ {
+ bReturn = !(pamtdMsgTypes[iMsgType].dwFlags&MTDF_DEFAULTDISABLED);
+ } else {
+ char* pszSetting = GetMsgTypeSettingName(pamtdMsgTypes[iMsgType].pszSection, pamtdMsgTypes[iMsgType].pszName);
+ if (pszSetting)
+ {
+ bReturn = DBGetContactSettingByte(NULL, DB_MODULE_NAME_MSGTYPES, pszSetting, (BYTE)!(pamtdMsgTypes[iMsgType].dwFlags&MTDF_DEFAULTDISABLED));
+ mir_free(pszSetting);
+ }
+ }
+
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ return (int)bReturn;
+}
+
+
+// Service: MS_SPAMFILTER_ROBOTCHECK
+static int ServiceRobotCheck(WPARAM wParam, LPARAM lParam) // wParam = SPAMCHECKDATA, lParam = 0
+{
+ SPAMCHECKDATA* pscd = (SPAMCHECKDATA*)wParam;
+
+ if (!pscd || !pscd->pszMsgTypeSection || !pscd->pszMsgTypeName || (pscd->cbSize < sizeof(SPAMCHECKDATA)) || !SCD_IsUserValid(pscd))
+ return SFF_ISNORMAL;
+
+ // Check id ctrl key is pressed to manually cancel spam check
+ if (!(pscd->dwFlags&SCDF_NO_CANCEL) && (GetAsyncKeyState(VK_CONTROL)&0x8000))
+ return SFF_ISNORMAL;
+
+ if ( !CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)pscd->pszMsgTypeSection, (LPARAM)pscd->pszMsgTypeName)
+ || !CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ACTIVATION_FILTER, (LPARAM)SFT_ROBOT_FILTER) )
+ return SFF_ISNORMAL;
+
+ if (NotifyEventHooks(hEventOkToSpamCheck, (WPARAM)pscd, (LPARAM)SFT_ROBOT_FILTER) == 1) {
+ OutputDebugString(_T("Spam Filter: Spam check denied (by event).\r\n"));
+ return SFF_ISNORMAL;
+ }
+
+ {
+ WCHAR* pszNormalMsgText;
+ WCHAR* pszClearedMsgText = NULL;
+
+ DWORD dwReturn = SFF_ISNORMAL;
+
+ // Buffer the msg content
+ if (pscd->ptszMsgText)
+ {
+ #if defined(UNICODE)
+ if (pscd->dwFlags&SCDF_UNICODE)
+ pszNormalMsgText = pscd->ptszMsgText;
+ else
+ pszNormalMsgText = (WCHAR*)mir_utf8encodeW((WCHAR*)pscd->pszMsgText);
+ #else
+ if (pscd->dwFlags&SCDF_UNICODE)
+ pszNormalMsgText = UnicodeToAnsi(pscd->pwszMsgText);
+ else
+ pszNormalMsgText = pscd->ptszMsgText;
+ #endif
+
+ } else {
+ pszNormalMsgText = NULL;
+ }
+
+ pszClearedMsgText = mir_wstrdup(pszNormalMsgText);
+ if (pszClearedMsgText)
+ RemoveWhiteSpaces(pszClearedMsgText, FALSE, TRUE);
+ else
+ pszClearedMsgText = NULL;
+
+ if (pszClearedMsgText)
+ {
+ DBVARIANT dbv;
+
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ANSWER, &dbv) == 0)
+ {
+ // If message contains correct answer
+ RemoveWhiteSpaces(dbv.ptszVal, FALSE, TRUE);
+ if ((StrCmp(pszClearedMsgText, dbv.ptszVal) == 0) || // or allow for quotes (below)
+ (StrCmpN(&pszClearedMsgText[1], dbv.ptszVal, lstrlen(pszClearedMsgText)-2) == 0))
+ dwReturn |= SFF_SENDMSG_CONFIRMATION|SFF_TESTPASSED|(DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_ADDTOHISTORY, DEFAULT_SETTING_ROBOT_ADDTOHISTORY) ? SFF_MARKREAD : SFF_DELETE);
+
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ if (pszClearedMsgText) mir_free(pszClearedMsgText);
+
+ #if defined(UNICODE)
+ if (!(pscd->dwFlags&SCDF_UNICODE))
+ if (pszNormalMsgText) mir_free(pszNormalMsgText);
+ #else
+ if ((pscd->dwFlags&SCDF_UNICODE))
+ if (pszNormalMsgText) mir_free(pszNormalMsgText);
+ #endif
+
+ // Kick out spam
+ if ( (!(dwReturn&SFF_TESTPASSED)) && (NotifyEventHooks(hEventOkToSpamDetection, (WPARAM)pscd, (LPARAM)SFT_ROBOT_FILTER) == 0))
+ {
+ dwReturn = SFF_ISSPAM|((DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, DEFAULT_SETTING_BEHAVIOUR) == 1) ? SFF_MARKREAD : SFF_DELETE);
+
+ // Add user to ignore list
+ if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE) && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, DEFAULT_SETTING_AUTOADDSPAMMERS) )
+ {
+ if (IncreasePreSpammerCount(pscd) > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, DEFAULT_SETTING_ALLOWEDSPAMMESSAGES))
+ {
+ RemovePreSpammerCount(pscd);
+ dwReturn |= SFF_IGNORE;
+ }
+ }
+
+ // Do not send question message when next messages will be ignored
+ if (!(dwReturn&SFF_IGNORE)) {
+ dwReturn |= SFF_SENDMSG_INSTRUCTION;
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ROBOT_HIDEUSERS, (BYTE)DEFAULT_SETTING_ROBOT_HIDEUSERS))
+ dwReturn |= SFF_HIDE;
+ }
+
+ if (!(pscd->dwFlags&SCDF_NO_NOTIFY))
+ {
+ // Play sound file
+ SkinPlaySound(DB_SOUND_ROBOT_SETTING);
+
+ // Show Popup
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, DEFAULT_SETTING_POPUP))
+ {
+ WCHAR* pszDisplayName = SCD_GetContactCustomDisplayName(pscd);
+
+ ShowSpamPopup(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszDisplayName, (pscd->dwFlags&SCDF_NO_CONTACT)?NULL:pscd->hContact, SFT_ROBOT_FILTER);
+ if (pszDisplayName) mir_free(pszDisplayName);
+ }
+
+ // Append to log file
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, DEFAULT_SETTING_LOGGING))
+ {
+ STRINGLIST* pslRecognition = SLNewList();
+ WCHAR* pszUserName = SCD_GetContactName(pscd, TRUE);
+
+ SLAddItem(pslRecognition, TranslateW("Robot message"));
+ WriteToLogFile(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszUserName, pszNormalMsgText, pslRecognition, dwReturn);
+
+ if (pszUserName) mir_free(pszUserName);
+ SLFreeList(pslRecognition);
+ }
+
+ // Hand out event
+ NotifyEventHooks(hEventSpamReceived, (WPARAM)pscd, (LPARAM)SFT_ROBOT_FILTER);
+
+ // Trigger Plugin Support
+ TriggerIncomingSpam();
+ }
+
+
+ } else {
+
+ if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE))
+ RemovePreSpammerCount(pscd);
+
+ // Message is normal
+ }
+
+ return dwReturn;
+ }
+}
+
+
+// Service: MS_SPAMFILTER_DISLIKEDMESSAGECHECK
+static int ServiceDislikedMessageCheck(WPARAM wParam, LPARAM lParam) // wParam = SPAMCHECKDATA, lParam = 0
+{
+ SPAMCHECKDATA* pscd = (SPAMCHECKDATA*)wParam;
+
+ if (!pscd || !pscd->pszMsgTypeSection || !pscd->pszMsgTypeName || (pscd->cbSize < sizeof(SPAMCHECKDATA)) || !SCD_IsUserValid(pscd))
+ return SFF_ISNORMAL;
+
+ // Check id ctrl key is pressed to manually cancel spam check
+ if (!(pscd->dwFlags&SCDF_NO_CANCEL) && (GetAsyncKeyState(VK_CONTROL)&0x8000))
+ return SFF_ISNORMAL;
+
+ if ( !CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)pscd->pszMsgTypeSection, (LPARAM)pscd->pszMsgTypeName)
+ || !CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ACTIVATION_FILTER, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER) )
+ return SFF_ISNORMAL;
+
+ if (NotifyEventHooks(hEventOkToSpamCheck, (WPARAM)pscd, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER) == 1) {
+ OutputDebugString(_T("Spam Filter: Spam check denied (by event).\r\n"));
+ return SFF_ISNORMAL;
+ }
+
+ {
+ BOOL bDoLog = ( (!(pscd->dwFlags&SCDF_NO_NOTIFY)) && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, DEFAULT_SETTING_LOGGING) );
+ BOOL bKickOut = FALSE;
+
+ int i;
+ WCHAR* pszNormalMsgText;
+ WCHAR* pszClearedMsgText;
+ STRINGLIST* pslRecognition = NULL;
+
+ // Create recognition texts list
+ if (bDoLog) pslRecognition = SLNewList();
+
+ // Buffer the msg content
+ if (pscd->pszMsgText)
+ {
+ #if defined(UNICODE)
+ if (pscd->dwFlags&SCDF_UNICODE)
+ pszNormalMsgText = pscd->ptszMsgText;
+ else
+ pszNormalMsgText = (WCHAR*)mir_utf8encodeW((WCHAR*)pscd->pszMsgText);
+ #else
+ if (pscd->dwFlags&SCDF_UNICODE)
+ pszNormalMsgText = UnicodeToAnsi(pscd->pwszMsgText);
+ else
+ pszNormalMsgText = pscd->ptszMsgText;
+ #endif
+
+ pszClearedMsgText = mir_wstrdup(pszNormalMsgText);
+ if (pszClearedMsgText)
+ RemoveWhiteSpaces(pszClearedMsgText, TRUE, TRUE);
+
+ } else {
+ pszNormalMsgText = NULL;
+ pszClearedMsgText = NULL;
+ }
+
+ // -SPAMCHECKS-
+
+ // Customized indicating words
+ if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_CUSTOMIZEDWORDS, (BYTE)TRUE))
+ {
+ STRINGLIST* pslChainWords = SLNewList();
+ unsigned int uFoundChainWords = 0;
+
+ GetSpamDefinitionData(pslChainWords, SDID_CUSTOM_DISLIKEDWORDS);
+
+ // Check how many words exist in the message
+ for (i=0; i<=SLGetMaxPos(pslChainWords); i++)
+ if (RegExpExistsInString(pszClearedMsgText, SLGetItem(pslChainWords, i), FALSE, NULL))
+ uFoundChainWords++;
+
+ SLFreeList(pslChainWords);
+
+ if (uFoundChainWords > 0)
+ {
+ if (bDoLog) SLItemPrintf(pslRecognition, SLAddItem(pslRecognition, TranslateW("Contains %u disliked indicating phrase(s)/pattern(s)")), MAX_INT_LENGTH, uFoundChainWords);
+ bKickOut = TRUE;
+ if (!bDoLog) goto DislikedMessageResult;
+ }
+ }
+
+
+ // Multiple message check
+ if (pszNormalMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES, DEFAULT_SETTING_DISLIKEDMESSAGE_MULTIPLEMESSAGES))
+ {
+ DBVARIANT dbv;
+ BOOL bFound;
+ WCHAR* pszSender;
+
+ pszSender = SCD_GetContactUniqueStr(pscd, FALSE);
+
+ bFound = FALSE;
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTMESSAGE, &dbv) == 0)
+ {
+ if (StrCmp(pszNormalMsgText, dbv.ptszVal) == 0)
+ {
+ DBFreeVariant(&dbv);
+
+ if (pszSender)
+ {
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTSENDER, &dbv) == 0)
+ if (StrCmp(pszSender, dbv.ptszVal) == 0)
+ bFound = TRUE;
+
+ } else {
+ bFound = TRUE;
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+
+ // Always save current msg content
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTMESSAGE, pszNormalMsgText);
+ if (pszSender)
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTSENDER, pszSender);
+ else
+ DBDeleteContactSetting(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTSENDER);
+
+ if (pszSender) mir_free(pszSender);
+
+ if (bFound)
+ {
+ if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is multiple"));
+ bKickOut = TRUE;
+ if (!bDoLog) goto DislikedMessageResult;
+ }
+
+ } else if (!pszNormalMsgText) {
+ DBDeleteContactSetting(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_LASTMESSAGE);
+ }
+
+
+ // Default hoax texts
+ if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_HOAXTEXTS, DEFAULT_SETTING_DISLIKEDMESSAGE_HOAXTEXTS))
+ {
+ STRINGLIST* pslHoaxTexts = SLNewList();
+ BOOL bFound;
+
+ // Load hoax texts
+ GetSpamDefinitionData(pslHoaxTexts, SDID_HOAXTEXTS);
+
+ bFound = FALSE;
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(pslHoaxTexts); i++)
+ if (StrCmpI(pszClearedMsgText, SLGetItem(pslHoaxTexts, i)) == 0)
+ {
+ bFound = TRUE;
+ break;
+ }
+
+ SLFreeList(pslHoaxTexts);
+
+ if (bFound)
+ {
+ if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is hoax text"));
+ bKickOut = TRUE;
+ if (!bDoLog) goto DislikedMessageResult;
+ }
+ }
+
+
+DislikedMessageResult:
+
+ if (pszClearedMsgText) mir_free(pszClearedMsgText);
+
+ #if defined(UNICODE)
+ if (!(pscd->dwFlags&SCDF_UNICODE) && pszNormalMsgText)
+ if (pszNormalMsgText) mir_free(pszNormalMsgText);
+ #else
+ if ((pscd->dwFlags&SCDF_UNICODE) && pszNormalMsgText)
+ mir_free(pszNormalMsgText);
+ #endif
+
+ // Kick out spam
+ if ( bKickOut && (NotifyEventHooks(hEventOkToSpamDetection, (WPARAM)pscd, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER) == 0))
+ {
+ DWORD dwReturn = SFF_ISSPAM|((DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, DEFAULT_SETTING_BEHAVIOUR) == 1) ? SFF_MARKREAD : SFF_DELETE);
+
+ // Add user to ignore list
+ if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE) && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, DEFAULT_SETTING_AUTOADDSPAMMERS) )
+ {
+ if (IncreasePreSpammerCount(pscd) > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, DEFAULT_SETTING_ALLOWEDSPAMMESSAGES))
+ {
+ RemovePreSpammerCount(pscd);
+ dwReturn |= SFF_IGNORE;
+ }
+ }
+
+ // Reply to sender
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER, DEFAULT_SETTING_DISLIKEDMESSAGE_NOTIFYSENDER))
+ dwReturn |= SFF_SENDMSG_NOTIFY;
+
+ if (!(pscd->dwFlags&SCDF_NO_NOTIFY))
+ {
+ // Play sound file
+ SkinPlaySound(DB_SOUND_DISLIKEDMESSAGE_SETTING);
+
+ // Show Popup
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, DEFAULT_SETTING_POPUP))
+ {
+ WCHAR* pszDisplayName = SCD_GetContactCustomDisplayName(pscd);
+ ShowSpamPopup(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszDisplayName, (pscd->dwFlags&SCDF_NO_CONTACT)?NULL:pscd->hContact, SFT_DISLIKEDMESSAGES_FILTER);
+ if (pszDisplayName) mir_free(pszDisplayName);
+ }
+
+ // Hand out event
+ NotifyEventHooks(hEventSpamReceived, (WPARAM)pscd, (LPARAM)SFT_DISLIKEDMESSAGES_FILTER);
+
+ // Trigger Plugin Support
+ TriggerIncomingSpam();
+ }
+
+ // Append to log file
+ if (bDoLog)
+ {
+ WCHAR* pszUserName = SCD_GetContactName(pscd, TRUE);
+
+ WriteToLogFile(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszUserName, pszNormalMsgText, pslRecognition, dwReturn);
+ if (pszUserName) mir_free(pszUserName);
+
+ SLFreeList(pslRecognition);
+ }
+
+ return dwReturn;
+
+ } else {
+
+ if (bDoLog)
+ SLFreeList(pslRecognition);
+
+ if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE))
+ RemovePreSpammerCount(pscd); // count can be removed here
+
+ // Message is normal
+ return SFF_ISNORMAL;
+ }
+
+ }
+}
+
+
+// Service : MS_SPAMFILTER_ADVERTISMENTCHECK
+static int ServiceAdvertismentCheck(WPARAM wParam, LPARAM lParam) // wParam = SPAMCHECKDATA, lParam = 0
+{
+ SPAMCHECKDATA* pscd = (SPAMCHECKDATA*)wParam;
+
+ if (!pscd || !pscd->pszMsgTypeSection || !pscd->pszMsgTypeName || (pscd->cbSize < sizeof(SPAMCHECKDATA)) || !SCD_IsUserValid(pscd))
+ return SFF_ISNORMAL;
+
+ // Check id ctrl key is pressed to manually cancel spam check
+ if (!(pscd->dwFlags&SCDF_NO_CANCEL) && (GetAsyncKeyState(VK_CONTROL)&0x8000))
+ return SFF_ISNORMAL;
+
+ if ( !CallService(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, (WPARAM)pscd->pszMsgTypeSection, (LPARAM)pscd->pszMsgTypeName)
+ || !CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ACTIVATION_FILTER, (LPARAM)SFT_ADVERTISMENT_FILTER) )
+ return SFF_ISNORMAL;
+
+ if (NotifyEventHooks(hEventOkToSpamCheck, (WPARAM)pscd, (LPARAM)SFT_ADVERTISMENT_FILTER) == 1) {
+ OutputDebugString(_T("Spam Filter: Spam check denied (by event).\r\n"));
+ return SFF_ISNORMAL;
+ }
+
+ {
+ BOOL bDoLog = ( (!(pscd->dwFlags&SCDF_NO_NOTIFY)) && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_LOGGING, DEFAULT_SETTING_LOGGING) );
+ BOOL bIsKnownSpammer = FALSE;
+ BOOL bKickOut = FALSE;
+ BOOL bFound;
+
+ int i;
+ WCHAR* pszNormalMsgText;
+ WCHAR* pszClearedMsgText;
+ WCHAR* pszFormatedMsgText;
+ STRINGLIST* pslRecognition = NULL;
+
+ // Create recognition texts list
+ if (bDoLog) pslRecognition = SLNewList();
+
+ // Buffer the msg content
+ if (pscd->pszMsgText)
+ {
+ #if defined(UNICODE)
+ if (pscd->dwFlags&SCDF_UNICODE)
+ pszNormalMsgText = pscd->ptszMsgText;
+ else
+ pszNormalMsgText = (WCHAR*)mir_utf8encodeW((WCHAR*)pscd->pszMsgText);
+ #else
+ if (pscd->dwFlags&SCDF_UNICODE)
+ pszNormalMsgText = UnicodeToAnsi(pscd->pwszMsgText);
+ else
+ pszNormalMsgText = pscd->ptszMsgText;
+ #endif
+
+ pszClearedMsgText = mir_wstrdup(pszNormalMsgText);
+ if (pszClearedMsgText)
+ RemoveWhiteSpaces(pszClearedMsgText, TRUE, TRUE);
+
+ } else {
+ pszNormalMsgText = NULL;
+ pszClearedMsgText = NULL;
+ }
+
+ // Create different format check text
+ if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_FORMATING, DEFAULT_SETTING_ADVERTISMENT_FORMATING))
+ {
+ pszFormatedMsgText = mir_wstrdup(pszClearedMsgText);
+ if (pszFormatedMsgText)
+ {
+ STRINGLIST* pslFormat = SLNewList();
+
+ // Some words may have special chars in between the chars
+ GetSpamDefinitionData(pslFormat, SDID_SPECIALCHARS_SEPARATORS);
+
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(pslFormat); i++)
+ ReplaceSubStringWithStringBuf(pszFormatedMsgText, 0, SLGetItem(pslFormat, i), _T(" "), TRUE, FALSE);
+
+ SLClearList(pslFormat);
+
+ // Translate some chars
+ GetSpamDefinitionData(pslFormat, SDID_SPECIALCHARS_REPLACE_TEXT);
+ ReplaceSubStringWithStringMultipleBuf(pszFormatedMsgText, 0, pslFormat, TRUE, FALSE);
+
+ SLFreeList(pslFormat);
+ }
+ } else {
+ pszFormatedMsgText = NULL;
+ }
+
+ // -SPAMCHECKS-
+ // Multiple message check
+ if (pszNormalMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_MULTIPLEMESSAGES, DEFAULT_SETTING_ADVERTISMENT_MULTIPLEMESSAGES))
+ {
+ DBVARIANT dbv;
+ bFound = FALSE;
+
+ // Do not consider sender of NotOnList messages
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_LASTMESSAGE, &dbv) == 0)
+ {
+ if (StrCmp(pszNormalMsgText, dbv.ptszVal) == 0)
+ bFound = TRUE;
+
+ DBFreeVariant(&dbv);
+ }
+
+ // Always save current msg content
+ DBWriteContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_LASTMESSAGE, pszNormalMsgText);
+
+ if (bFound)
+ {
+ if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is multiple"));
+ bKickOut = TRUE;
+ if (!bDoLog) goto AdvertismentResult;
+ }
+
+ } else if (!pszNormalMsgText) {
+ DBDeleteContactSetting(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_LASTMESSAGE);
+ }
+
+ // Empty message?
+ if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_EMPTY, DEFAULT_SETTING_ADVERTISMENT_EMPTY))
+ {
+ if (lstrlen(pszClearedMsgText) <= 0)
+ {
+ if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is empty"));
+ bKickOut = TRUE;
+ if (!bDoLog) goto AdvertismentResult;
+ }
+ }
+
+ // Message capitalized?
+ if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CAPITALIZED, DEFAULT_SETTING_ADVERTISMENT_CAPITALIZED))
+ {
+ bFound = TRUE;
+
+ for (i=0; i<(int)lstrlen(pszClearedMsgText); i++)
+ if (IsCharLower(pszClearedMsgText[i]))
+ {
+ bFound = FALSE;
+ break;
+ }
+
+ if (bFound)
+ {
+ if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is capitalized"));
+ bKickOut = TRUE;
+ if (!bDoLog) goto AdvertismentResult;
+ }
+ }
+
+ // Sender is default spammer?
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTSPAMMERS, DEFAULT_SETTING_ADVERTISMENT_DEFAULTSPAMMERS))
+ {
+ STRINGLIST* psl = SLNewList();
+ WCHAR* pszUnique;
+
+ // Load spammers definitions
+ GetSpamDefinitionData(psl, SDID_SPAMMERS);
+
+ // Check if unique user id is listed in def file
+ pszUnique = SCD_GetContactUniqueStr(pscd, FALSE);
+ if (pszUnique)
+ {
+ bFound = SLIsItem(psl, pszUnique, TRUE);
+ mir_free(pszUnique);
+ } else {
+ bFound = FALSE;
+ }
+
+ // Check if nickname is listed in def file
+ if (!bFound)
+ {
+ pszUnique = SCD_GetContactUniqueStr(pscd, TRUE);
+ if (pszUnique)
+ {
+ bFound = SLIsItem(psl, pszUnique, TRUE);
+ mir_free(pszUnique);
+ }
+ }
+ SLFreeList(psl);
+
+ if (bFound)
+ {
+ if (bDoLog) SLAddItem(pslRecognition, TranslateW("User is known as spammer"));
+ bKickOut = bIsKnownSpammer = TRUE;
+ if (!bDoLog) goto AdvertismentResult;
+ }
+ }
+
+ // Teaser Message?
+ if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_TEASERMESSAGES, DEFAULT_SETTING_ADVERTISMENT_TEASERMESSAGES))
+ {
+ STRINGLIST* pslTeasers = SLNewList();
+ bFound = FALSE;
+
+ // Load teasers
+ GetSpamDefinitionData(pslTeasers, SDID_TEASERTEXTS);
+
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(pslTeasers); i++)
+ if (StrCmp(pszClearedMsgText, SLGetItem(pslTeasers, i)) == 0)
+ {
+ bFound = TRUE;
+ break;
+ }
+
+ SLFreeList(pslTeasers);
+
+ if (bFound)
+ {
+ if (bDoLog) SLAddItem(pslRecognition, TranslateW("Is teaser"));
+ bKickOut = TRUE;
+ if (!bDoLog) goto AdvertismentResult;
+ }
+ }
+
+ // Message containing URLs?
+ if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_URL, DEFAULT_SETTING_ADVERTISMENT_URL))
+ {
+ STRINGLIST* psl = SLNewList();
+ WCHAR* pszModUrlInd = NULL;
+ bFound = FALSE;
+
+ // Load url definition files
+ GetSpamDefinitionData(psl, SDID_URLTLDS);
+
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
+ {
+ // Different formated check?
+ if (pszFormatedMsgText)
+ pszModUrlInd = InsertSubStrEveryNChars(SLGetItem(psl, i), 1, _T(" "), FALSE, FALSE); // check for words with spaces/linefeeds/slashes between each char
+
+ if (StrStrI(pszClearedMsgText, SLGetItem(psl, i)) || ((pszModUrlInd && pszFormatedMsgText) ? StrStrI(pszFormatedMsgText, pszModUrlInd) : FALSE) )
+ {
+ bFound = TRUE;
+ break;
+ }
+
+ if (pszModUrlInd)
+ {
+ mir_free(pszModUrlInd);
+ pszModUrlInd = NULL;
+ }
+ }
+
+ SLFreeList(psl);
+
+ if (bFound)
+ {
+ if (bDoLog) SLAddItem(pslRecognition, TranslateW("Contains URL address"));
+ bKickOut = TRUE;
+ if (!bDoLog) goto AdvertismentResult;
+ }
+ }
+
+ // Message containing phone numbers?
+ if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_PHONENUMBERS, DEFAULT_SETTING_ADVERTISMENT_PHONENUMBERS))
+ {
+ STRINGLIST* psl = SLNewList();
+ WCHAR* pszModContent;
+ bFound = FALSE;
+
+ // Load localized phonenumbers
+ GetSpamDefinitionData(psl, SDID_PHONENUMBERS);
+
+ pszModContent = mir_wstrdup(pszClearedMsgText);
+ if (pszModContent)
+ {
+ // Check for normal formated phonennumbers
+ {
+ // Remove spaces
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T(" "), NULL, TRUE, FALSE);
+ // Replace wrong slashs
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("\\"), _T("/"), TRUE, FALSE);
+
+ // Replace numbers
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("0"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("1"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("2"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("3"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("4"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("5"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("6"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("7"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("8"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("9"), _T("#"), TRUE, FALSE);
+
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
+ if (StrStrI(pszModContent, SLGetItem(psl, i)))
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ // Check different formated phone numbers
+ if (!bFound && pszFormatedMsgText)
+ {
+ WCHAR* pszNumberFormatedMsgText = mir_wstrdup(pszClearedMsgText);
+ if (pszNumberFormatedMsgText)
+ {
+ // -- Create number formated text
+ STRINGLIST* pslFormat = SLNewList();
+
+ // Some words may have special chars in between the chars
+ GetSpamDefinitionData(pslFormat, SDID_SPECIALCHARS_SEPARATORS);
+
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(pslFormat); i++)
+ ReplaceSubStringWithStringBuf(pszNumberFormatedMsgText, 0, SLGetItem(pslFormat, i), _T(" "), TRUE, FALSE);
+
+ SLClearList(pslFormat);
+
+ // Translate some chars
+ GetSpamDefinitionData(pslFormat, SDID_SPECIALCHARS_REPLACE_NUMBERS);
+ ReplaceSubStringWithStringMultipleBuf(pszNumberFormatedMsgText, 0, pslFormat, TRUE, FALSE);
+
+ SLFreeList(pslFormat);
+
+
+ //-- Check the text
+ // Remove spaces
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T(" "), NULL, TRUE, FALSE);
+ // Replace wrong slashs
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("\\"), _T("/"), TRUE, FALSE);
+
+ // Replace numbers
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("0"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("1"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("2"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("3"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("4"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("5"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("6"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("7"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("8"), _T("#"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszModContent, 0, _T("9"), _T("#"), TRUE, FALSE);
+
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
+ if (StrStrI(pszModContent, SLGetItem(psl, i)))
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+ }
+
+ mir_free(pszModContent);
+ }
+
+ SLFreeList(psl);
+
+ if (bFound)
+ {
+ if (bDoLog) SLAddItem(pslRecognition, TranslateW("Contains phone number"));
+ bKickOut = TRUE;
+ if (!bDoLog) goto AdvertismentResult;
+ }
+ }
+
+ // Message contains bad words and/or formated bad words?
+ if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS, (BYTE)TRUE) || DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTBADWORDS, DEFAULT_SETTING_ADVERTISMENT_DEFAULTBADWORDS) )
+ {
+ STRINGLIST* psl = SLNewList();
+ unsigned int uFoundBadWords = 0;
+ unsigned int uFoundFormatedWords = 0;
+ BOOL bRegExpMalformed;
+ unsigned int uRegExpErrors;
+
+ // Load cutomized bad words if activated
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS, (BYTE)TRUE) )
+ GetSpamDefinitionData(psl, SDID_CUSTOM_BADWORDS);
+
+ // Check customized bad words...
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
+ if (RegExpExistsInString(pszClearedMsgText, SLGetItem(psl, i), FALSE, NULL))
+ uFoundBadWords++;
+
+ // Load all default bad words files if activated
+ SLClearList(psl);
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_DEFAULTBADWORDS, DEFAULT_SETTING_ADVERTISMENT_DEFAULTBADWORDS) )
+ GetSpamDefinitionData(psl, SDID_BADWORDS);
+
+ // Check default bad words...
+ uRegExpErrors = 0;
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
+ {
+ if (RegExpExistsInString(pszClearedMsgText, SLGetItem(psl, i), FALSE, &bRegExpMalformed))
+ uFoundBadWords++;
+
+ if (bRegExpMalformed)
+ uRegExpErrors++;
+ }
+ if (uRegExpErrors > 0)
+ ShowInfoMessage(NIIF_WARNING, TranslateW("Spam Filter Warning"), TranslateW("The filter has detected %u malformed Regular Expression(s) in the default bad words!\r\n\r\nPlease update your installed Spam Definitions to the latest versions to resolve this problem.\r\nThis problem might also be caused by Spam Definitions that are not compatible with your system codepage."), MAX_INT_LENGTH, uRegExpErrors);
+
+ // Check different formated bad words...
+ if (pszFormatedMsgText)
+ {
+ WCHAR* pszDiffWord;
+
+ // AGAIN!: Load cutomized bad words again if activated
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDBADWORDS, (BYTE)TRUE) )
+ GetSpamDefinitionData(psl, SDID_CUSTOM_BADWORDS);
+
+ // Check again for bad words
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
+ {
+ pszDiffWord = InsertSubStrEveryNChars(SLGetItem(psl, i), 1, _T(" "), FALSE, FALSE); // check for words with spaces/linefeeds between each char
+
+ if (RegExpExistsInString(pszFormatedMsgText, SLGetItem(psl, i), FALSE, NULL))
+ {
+ uFoundFormatedWords++;
+
+ } else {
+ pszDiffWord = InsertSubStrEveryNChars(SLGetItem(psl, i), 1, _T(" "), FALSE, FALSE); // check for words with spaces/linefeeds between each char
+ if (pszDiffWord)
+ {
+ if (StrStrI(pszFormatedMsgText, pszDiffWord))
+ uFoundFormatedWords++;
+
+ mir_free(pszDiffWord);
+ }
+ }
+ }
+
+ // Calculate diff
+ uFoundFormatedWords = (uFoundFormatedWords > uFoundBadWords) ? uFoundFormatedWords = uFoundFormatedWords-uFoundBadWords : 0;
+ }
+
+ SLFreeList(psl);
+
+ // Enough bad words for spam found?
+ if (uFoundBadWords > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDBADWORDS, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDBADWORDS))
+ {
+ if (bDoLog) SLItemPrintf(pslRecognition, SLAddItem(pslRecognition, TranslateW("Contains %u bad phrase(s)/pattern(s)")) , MAX_INT_LENGTH, uFoundBadWords);
+ bKickOut = TRUE;
+ }
+
+ // Enough formated bad words found?
+ if (uFoundFormatedWords > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDFORMATEDWORDS))
+ {
+ if (bDoLog) SLItemPrintf(pslRecognition, SLAddItem(pslRecognition, TranslateW("Contains %u differently formated bad phrase(s)/pattern(s)")), MAX_INT_LENGTH, uFoundFormatedWords);
+ bKickOut = TRUE;
+ }
+
+ if (bKickOut && !bDoLog) goto AdvertismentResult;
+ }
+
+ // Good words check
+ if (pszClearedMsgText && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_CUSTOMIZEDGOODWORDS, (BYTE)TRUE) )
+ {
+ STRINGLIST* psl = SLNewList();
+ unsigned int uFoundGoodWords = 0;
+
+ // Load customized good words
+ GetSpamDefinitionData(psl, SDID_CUSTOM_GOODWORDS);
+
+ for (i=SL_MIN_POS; i<=SLGetMaxPos(psl); i++)
+ if (RegExpExistsInString(pszClearedMsgText, SLGetItem(psl, i), FALSE, NULL))
+ uFoundGoodWords++;
+
+ SLFreeList(psl);
+
+ // Enough good words for non-spam found?
+ if (uFoundGoodWords > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS, DEFAULT_SETTING_ADVERTISMENT_ALLOWEDGOODWORDS))
+ {
+ if (bDoLog) SLItemPrintf(pslRecognition, SLAddItem(pslRecognition, TranslateW("Contains %u good phrase(s)/pattern(s)")), MAX_INT_LENGTH, uFoundGoodWords);
+ bKickOut = FALSE;
+ if (!bDoLog) goto AdvertismentResult;
+ }
+ }
+
+
+AdvertismentResult:
+
+ if (pszClearedMsgText) mir_free(pszClearedMsgText);
+ if (pszFormatedMsgText) mir_free(pszFormatedMsgText);
+
+ #if defined(UNICODE)
+ if (!(pscd->dwFlags&SCDF_UNICODE) && pszNormalMsgText)
+ mir_free(pszNormalMsgText);
+ #else
+ if ((pscd->dwFlags&SCDF_UNICODE) && pszNormalMsgText)
+ mir_free(pszNormalMsgText);
+ #endif
+
+
+ // Kick out spam
+ if ( bKickOut && (NotifyEventHooks(hEventOkToSpamDetection, (WPARAM)pscd, (LPARAM)SFT_ADVERTISMENT_FILTER) == 0))
+ {
+ DWORD dwReturn = SFF_ISSPAM | ((DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_BEHAVIOUR, DEFAULT_SETTING_BEHAVIOUR) == 1) ? SFF_MARKREAD : SFF_DELETE);
+
+ if (!(pscd->dwFlags&SCDF_NO_NOTIFY))
+ {
+ // Play sound file
+ SkinPlaySound(DB_SOUND_ADVERTISMENT_SETTING);
+
+ // Show Popup
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_POPUP, DEFAULT_SETTING_POPUP))
+ {
+ WCHAR* pszDisplayName = SCD_GetContactCustomDisplayName(pscd);
+
+ ShowSpamPopup(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszDisplayName, (pscd->dwFlags&SCDF_NO_CONTACT)?NULL:pscd->hContact, SFT_ADVERTISMENT_FILTER);
+ if (pszDisplayName) mir_free(pszDisplayName);
+ }
+
+ // Hand out event
+ NotifyEventHooks(hEventSpamReceived, (WPARAM)pscd, (LPARAM)SFT_ADVERTISMENT_FILTER);
+
+ // Trigger Plugin Support
+ TriggerIncomingSpam();
+ }
+
+ // Append to log file
+ if (bDoLog)
+ {
+ WCHAR* pszUserName = SCD_GetContactName(pscd, TRUE);
+
+ WriteToLogFile(pscd->pszMsgTypeSection, pscd->pszMsgTypeName, pszUserName, pszNormalMsgText, pslRecognition, dwReturn);
+ if (pszUserName) mir_free(pszUserName);
+
+ SLFreeList(pslRecognition);
+ }
+
+ // Add user to ignore list
+ if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE) && DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_AUTOADDSPAMMERS, DEFAULT_SETTING_AUTOADDSPAMMERS) )
+ {
+ if (IncreasePreSpammerCount(pscd) > DBGetContactSettingWord(NULL, DB_MODULE_NAME, DB_SETTING_ALLOWEDSPAMMESSAGES, DEFAULT_SETTING_ALLOWEDSPAMMESSAGES))
+ {
+ RemovePreSpammerCount(pscd);
+ dwReturn |= SFF_IGNORE;
+ }
+ }
+
+ return dwReturn;
+
+ } else {
+
+ if (bDoLog)
+ SLFreeList(pslRecognition);
+
+ //if (!(pscd->dwFlags&SCDF_NO_AUTOIGNORE))
+ // RemovePreSpammerCount(scd); // do not remove count here! (will cause problems)
+
+ // Message is normal
+ return SFF_ISNORMAL;
+ }
+
+ }
+}
+
+
+// --------------------------------
+
+int GetMsgTypeID(const char* pszSection, const char* pszName)
+{
+ unsigned int u;
+
+ EnterCriticalSection(&csMsgTypes); // thread safety
+
+ if (pszSection && pszName && pamtdMsgTypes)
+ for (u=0; u<uMsgTypesCount; u++)
+ if (StrCmpA(pamtdMsgTypes[u].pszSection, pszSection) == 0)
+ if (StrCmpA(pamtdMsgTypes[u].pszName, pszName) == 0)
+ {
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ return u;
+ }
+
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ return -1;
+}
+
+
+char* GetMsgTypeSettingName(const char* pszSection, const char* pszName)
+{
+ // returned char* needs to be freed
+ char* pszReturn;
+ int iSize;
+
+ if (!pszSection || !pszName) return NULL;
+
+ iSize = lstrlenA(pszSection)+1+lstrlenA(pszName)+1;
+ pszReturn = (char*)mir_alloc(iSize*sizeof(char));
+
+ if (pszReturn)
+ mir_snprintf(pszReturn, iSize, "%s_%s", pszSection, pszName);
+
+ return pszReturn;
+}
+
+
+BOOL IsOnlyOneMsgTypeSectionRegistered(void)
+{
+ unsigned int u;
+
+ EnterCriticalSection(&csMsgTypes); // thread safety
+
+ if (pamtdMsgTypes)
+ for (u=0; u<(uMsgTypesCount-1); u++)
+ if (StrCmpA(pamtdMsgTypes[u].pszSection, pamtdMsgTypes[u+1].pszSection) != 0)
+ {
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ return FALSE;
+ }
+
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ return TRUE;
+}
+
+
+void NotifyModuleLoaded(void)
+{
+ // Hand out event (spam filter functionality now fully available)
+ NotifyEventHooks(hEventModuleLoaded, 0, 0);
+}
+
+void NotifySpammerStateChanged(HANDLE hContact, BOOL bNewIsSpammer)
+{
+ // Hand out event (spammer state setting was changed)
+ NotifyEventHooks(hEventContactSpammerStateChanged, (WPARAM)hContact, (LPARAM)bNewIsSpammer);
+}
+
+// --------------------------------
+
+
+void InitServices(void)
+{
+ // Init message type list
+ uMsgTypesCount = 0;
+ pamtdMsgTypes = NULL;
+ InitializeCriticalSection(&csMsgTypes); // thread safety
+
+ hEventPreRegisterMessageType = CreateHookableEvent(ME_SPAMFILTER_PREREGISTERMESSAGETYPE);
+ hEventOkToSpamCheck = CreateHookableEvent(ME_SPAMFILTER_OKTOSPAMCHECK);
+ hEventOkToSpamDetection = CreateHookableEvent(ME_SPAMFILTER_OKTOSPAMDETECTION);
+ hEventSpamReceived = CreateHookableEvent(ME_SPAMFILTER_SPAMRECEIVED);
+ hEventModuleLoaded = CreateHookableEvent(ME_SPAMFILTER_MODULELOADED);
+ hEventContactSpammerStateChanged = CreateHookableEvent(ME_SPAMFILTER_CONTACT_SPAMMERSTATECHANGED);
+
+ hServices[0] = CreateServiceFunction(MS_SPAMFILTER_ADVERTISMENTCHECK, ServiceAdvertismentCheck);
+ hServices[1] = CreateServiceFunction(MS_SPAMFILTER_DISLIKEDMESSAGESCHECK, ServiceDislikedMessageCheck);
+ hServices[2] = CreateServiceFunction(MS_SPAMFILTER_ROBOTCHECK, ServiceRobotCheck);
+
+ hServices[3] = CreateServiceFunction(MS_SPAMFILTER_REGISTERMESSAGETYPE, ServiceRegisterMessageType);
+ hServices[4] = CreateServiceFunction(MS_SPAMFILTER_REMOVEMESSAGETYPE, ServiceRemoveMessageType);
+ hServices[5] = CreateServiceFunction(MS_SPAMFILTER_ISMESSAGETYPEACTIVATED, ServiceIsMessageTypeActivated);
+
+ hServices[6] = CreateServiceFunction(MS_SPAMFILTER_GETHANDLE, ServiceGetHandle);
+ hServices[7] = CreateServiceFunction(MS_SPAMFILTER_SHOWERROR, ServiceShowError);
+ hServices[8] = CreateServiceFunction(MS_SPAMFILTER_SHOWFILTERDIALOG, ServiceShowFilterDialog);
+
+ hServices[9] = CreateServiceFunction(MS_SPAMFILTER_CHANGEFILTERACTIVATION, ServiceChangeFilterActivation);
+ hServices[10] = CreateServiceFunction(MS_SPAMFILTER_GETSPAMCHECKINFO, ServiceGetSpamCheckInfo);
+
+ hServices[11] = CreateServiceFunction(MS_SPAMFILTER_RESETAUTOIGNORE, ServiceResetAutoIgnore);
+
+ hServices[12] = CreateServiceFunction(MS_SPAMFILTER_CONTACT_SETASSPAMMER, ServiceContactSetAsSpammer);
+ hServices[13] = CreateServiceFunction(MS_SPAMFILTER_CONTACT_SHOWSETASSPAMMERDIALOG, ServiceContactShowSetAsSpammerDialog);
+ hServices[14] = CreateServiceFunction(MS_SPAMFILTER_CONTACT_ISSPAMMER, ServiceContactIsSpammer);
+ hServices[15] = CreateServiceFunction(MS_SPAMFILTER_CONTACT_UNSETSPAMMER, ServiceContactUnSetSpammer);
+
+ hServices[16] = CreateServiceFunction(MS_SPAMFILTER_COPYSPAMCHECKDATA, ServiceCopySpamCheckData);
+ hServices[17] = CreateServiceFunction(MS_SPAMFILTER_FREESPAMCHECKDATA, ServiceFreeSpamCheckData);
+
+ // Backward compatibility (for v1.0.1.0)
+ hServices[18] = CreateServiceFunction(MS_SPAMFILTER_SETSPAMMANUALLY, ServiceContactShowSetAsSpammerDialog);
+}
+
+void UninitServices(void)
+{
+ // Destroy services
+ int i;
+ for (i=0; i<ARRAYSIZE(hServices); i++)
+ if (hServices[i]) DestroyServiceFunction(hServices[i]);
+
+ if (hEventPreRegisterMessageType)
+ DestroyHookableEvent(hEventPreRegisterMessageType);
+ if (hEventOkToSpamCheck)
+ DestroyHookableEvent(hEventOkToSpamCheck);
+ if (hEventOkToSpamDetection)
+ DestroyHookableEvent(hEventOkToSpamDetection);
+ if (hEventSpamReceived)
+ DestroyHookableEvent(hEventSpamReceived);
+ if (hEventModuleLoaded)
+ DestroyHookableEvent(hEventModuleLoaded);
+ if (hEventContactSpammerStateChanged)
+ DestroyHookableEvent(hEventContactSpammerStateChanged);
+
+ // Unload message type list
+ EnterCriticalSection(&csMsgTypes); // thread safety (waiting for operations to fisnish)
+ if (pamtdMsgTypes)
+ {
+ unsigned int u;
+ for (u=0; u<uMsgTypesCount; u++)
+ {
+ if (pamtdMsgTypes[u].pszSection) mir_free(pamtdMsgTypes[u].pszSection);
+ if (pamtdMsgTypes[u].pszSectionDescription) mir_free(pamtdMsgTypes[u].pszSectionDescription);
+ if (pamtdMsgTypes[u].pszName) mir_free(pamtdMsgTypes[u].pszName);
+ if (pamtdMsgTypes[u].pszDescription) mir_free(pamtdMsgTypes[u].pszDescription);
+ if (pamtdMsgTypes[u].hIcon && ((int)pamtdMsgTypes[u].hIcon > 0)) DestroyIcon(pamtdMsgTypes[u].hIcon);
+ if (pamtdMsgTypes[u].hSectionIcon) DestroyIcon(pamtdMsgTypes[u].hSectionIcon);
+ }
+ mir_free(pamtdMsgTypes);
+ }
+ uMsgTypesCount = 0;
+ pamtdMsgTypes = NULL;
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+ DeleteCriticalSection(&csMsgTypes); // thread safety
} \ No newline at end of file
diff --git a/services.h b/services.h
index d5ad3f7..8c5d6a1 100644
--- a/services.h
+++ b/services.h
@@ -1,39 +1,39 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_SERVICES_H__
-#define SF_SERVICES_H__ 1
-
-
-// -- Protoypes
-int GetMsgTypeID(const char* pszSection, const char* pszName);
-BOOL IsOnlyOneMsgTypeSectionRegistered(void);
-char* GetMsgTypeSettingName(const char* pszSection, const char* pszName);
-
-int QueryAutoIgnore(BOOL bReset);
-void NotifyModuleLoaded(void);
-void NotifySpammerStateChanged(HANDLE hContact, BOOL bNewIsSpammer);
-
-void InitServices(void);
-void UninitServices(void);
-
-
-#endif // SF_SERVICES_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_SERVICES_H__
+#define SF_SERVICES_H__ 1
+
+
+// -- Protoypes
+int GetMsgTypeID(const char* pszSection, const char* pszName);
+BOOL IsOnlyOneMsgTypeSectionRegistered(void);
+char* GetMsgTypeSettingName(const char* pszSection, const char* pszName);
+
+int QueryAutoIgnore(BOOL bReset);
+void NotifyModuleLoaded(void);
+void NotifySpammerStateChanged(HANDLE hContact, BOOL bNewIsSpammer);
+
+void InitServices(void);
+void UninitServices(void);
+
+
+#endif // SF_SERVICES_H__
diff --git a/spamcheck.c b/spamcheck.c
index 7078941..e5a0168 100644
--- a/spamcheck.c
+++ b/spamcheck.c
@@ -1,683 +1,683 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -- Variables: Events/Hooks/Services
-HANDLE hHookDbContactAdded = NULL;
-HANDLE hHookDbEventFilterAdd = NULL;
-
-
-// -----------------------------------------
-
-static int SpamCheckProtoRecv(WPARAM wParam, LPARAM lParam)
-{
- CCSDATA* pccsd = (CCSDATA*)lParam;
- BOOL bNotOnList;
- SPAMCHECKDATA scd;
- DWORD dwSpamResult;
- int iReturn;
-
- ZeroMemory(&scd, sizeof(scd));
- Netlib_Logf(NULL, "Spam Filter: Catching MS_PROTO_CHAINRECV");
-
- // Message already marked as read (skipping spam check)
- if (((PROTORECVEVENT*)pccsd->lParam)->flags&PREF_CREATEREAD)
- {
- Netlib_Logf(NULL, "Spam Filter: Already marked as read (skipping spam check)");
- return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
- }
-
- if (StrCmpA(pccsd->szProtoService, PSR_URL) == 0)
- {
- PROTORECVEVENT* ppre = ((PROTORECVEVENT*)pccsd->lParam);
-
- scd.hContact = pccsd->hContact;
-
- // Interpret blob (ignore url itself, only description)
- scd.pszMsgText = ppre->szMessage;
-
- scd.pszMsgTypeName = SFMT_URL;
-
- } else if (StrCmpA(pccsd->szProtoService, PSR_AUTH) == 0)
- {
- PROTORECVEVENT* ppre = ((PROTORECVEVENT*)pccsd->lParam);
-
- scd.hContact = (*((PHANDLE)(ppre->szMessage+sizeof(DWORD))));
-
- // Check if stored hContact is still valid
- if (!CallService(MS_DB_CONTACT_IS, (WPARAM)scd.hContact, 0))
- {
- Netlib_Logf(NULL, "Spam Filter: Contact invalid (skipping spam check)");
-
- // Continue the chain
- return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
- }
-
- // Interpret blob (only use reason text)
- scd.pszMsgText = (char*)(ppre->szMessage+sizeof(DWORD)+sizeof(HANDLE)); // uin, hcontact, nick
- scd.pszMsgText = scd.pszMsgText+(lstrlenA(scd.pszMsgText)+1)*sizeof(char); // first
- scd.pszMsgText = scd.pszMsgText+(lstrlenA(scd.pszMsgText)+1)*sizeof(char); // last
- scd.pszMsgText = scd.pszMsgText+(lstrlenA(scd.pszMsgText)+1)*sizeof(char); // email
- scd.pszMsgText = scd.pszMsgText+(lstrlenA(scd.pszMsgText)+1)*sizeof(char); // reason
-
- // If no reason text is given deactivate the text checking
- if (strlen(scd.pszMsgText) <= 0)
- scd.pszMsgText = NULL;
-
- scd.pszMsgTypeName = SFMT_AUTHREQUEST;
-
- } else if (StrCmpA(pccsd->szProtoService, PSR_MESSAGE) == 0)
- {
- PROTORECVEVENT* ppre = ((PROTORECVEVENT*)pccsd->lParam);
-
- scd.hContact = pccsd->hContact;
-
- // Interpret blob (use all message)
- if (ppre->flags&PREF_UNICODE) {
- scd.dwFlags |= SCDF_UNICODE;
- scd.pszMsgText = ppre->szMessage+lstrlenA(ppre->szMessage)+1;
- } else {
- scd.pszMsgText = ppre->szMessage;
- }
-
- scd.pszMsgTypeName = SFMT_MESSAGE;
-
- } else if (StrCmpA(pccsd->szProtoService, PSR_FILE) == 0)
- {
- PROTORECVFILE* pprf = ((PROTORECVFILE*)pccsd->lParam);
-
- scd.hContact = pccsd->hContact;
-
- // Interpret blob (only use description text)
- scd.pszMsgText = pprf->szDescription;
-
- scd.pszMsgTypeName = SFMT_FILE;
-
- } else if (StrCmpA(pccsd->szProtoService, PSR_CONTACTS) == 0)
- {
- scd.hContact = pccsd->hContact;
-
- // Does not have any text to filter only contact names: nick, first, last, email
- scd.pszMsgText = NULL;
-
- scd.pszMsgTypeName = SFMT_CONTACTS;
-
- } else {
- Netlib_Logf(NULL, "Spam Filter: Format unknown (skipping spam check)");
-
- // Continue the chain
- return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
- }
-
- scd.cbSize = sizeof(scd);
- scd.pszMsgTypeSection = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)scd.hContact, 0);
-
- // If message is from "Unknown Contact" (very unlikely) -> MS_PROTO_GETCONTACTBASEPROTO returns NULL
- if (!scd.pszMsgTypeSection)
- {
- Netlib_Logf(NULL, "Spam Filter Result: No base protocol (skipping spam check)");
- return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
- }
-
- Netlib_Logf(NULL, "Spam Filter: Type = %s_%s", scd.pszMsgTypeSection, scd.pszMsgTypeName);
-
- // Result check
- bNotOnList = (DBGetContactSettingByte(scd.hContact, "CList", "NotOnList", 0) ? TRUE : FALSE);
- if (bNotOnList)
- {
- // If message is from test passed contact
- if(DBGetContactSettingByte(scd.hContact, DB_MODULE_NAME, DB_SETTING_ROBOT_TESTPASSED, (BYTE)FALSE))
- {
- Netlib_Logf(NULL, "Spam Filter: Result = Already passed robot test (no spam)");
- return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
- }
-
- Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_ADVERTISMENTCHECK");
- dwSpamResult = CallService(MS_SPAMFILTER_ADVERTISMENTCHECK, (WPARAM)&scd, 0);
- if (dwSpamResult&SFF_ISNORMAL)
- {
- Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_ROBOTCHECK");
- dwSpamResult = CallService(MS_SPAMFILTER_ROBOTCHECK, (WPARAM)&scd, 0);
- }
-
- } else {
- Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_DISLIKEDMESSAGESCHECK");
- dwSpamResult = CallService(MS_SPAMFILTER_DISLIKEDMESSAGESCHECK, (WPARAM)&scd, 0);
- }
-
- if (dwSpamResult&SFF_ISNORMAL) {
- Netlib_Logf(NULL, "Spam Filter: Recognition = No-Spam");
- } else {
- Netlib_Logf(NULL, "Spam Filter: Recognition = Spam!");
- }
-
-
- // Message handling
- if (dwSpamResult&SFF_DELETE)
- {
- Netlib_Logf(NULL, "Spam Filter: Result = Event suppressed (stopping recv chain)");
-
- // Cache chain (see reply messages)
- iReturn = 1; // Stop processing the chain
-
- } else if (dwSpamResult&SFF_MARKREAD)
- {
- (((PROTORECVEVENT*)pccsd->lParam)->flags) |= PREF_CREATEREAD;
- Netlib_Logf(NULL, "Spam Filter: Result = PREF_CREATEREAD flag set (continuing recv chain)");
-
- // Cache chain (see reply messages)
- iReturn = CallService(MS_PROTO_CHAINRECV, wParam, lParam);
-
- } else {
- Netlib_Logf(NULL, "Spam Filter: Result = Event accepted (continuing recv chain)");
-
- // Cache chain (see reply messages)
- iReturn = CallService(MS_PROTO_CHAINRECV, wParam, lParam);
- }
-
-
- // IMPORTANT!: The following is done *after* the call to MS_PROTO_CHAINRECV so that
- // the protocol has had the chance to add the recved event to the db.
- // The events to be sent are then ordered correctly in db.
-
- // The contact might have been deleted etc. by another filter protcol in recv chain
- // -> just a safety check
- if (!CallService(MS_DB_CONTACT_IS, (WPARAM)scd.hContact, 0))
- {
- Netlib_Logf(NULL, "Spam Filter: Contact deleted by other filter (stopping processing)");
- return iReturn;
- }
-
- // Remember test passed (robot filter)
- if (dwSpamResult&SFF_TESTPASSED)
- {
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_TESTPASSED (restoring contact)");
-
- // Mark contact as answered
- DBWriteContactSettingByte(scd.hContact, DB_MODULE_NAME, DB_SETTING_ROBOT_TESTPASSED, (BYTE)TRUE);
- DBDeleteContactSetting(scd.hContact, "CList", "Hidden");
-
- // Show the old events again
- MarkAllContactEventsUnRead(scd.hContact);
- }
-
- // Contact handling
- if (dwSpamResult&SFF_IGNORE)
- {
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_IGNORE (ignoring contact)");
- AddContactToIgnoreList(scd.hContact, (dwSpamResult&SFF_MARKREAD), TRUE, FALSE);
- }
- if (dwSpamResult&SFF_HIDE)
- {
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_HIDE (hiding contact)");
- DBWriteContactSettingByte(scd.hContact, "CList", "Hidden", 1);
- }
-
- // Reply messages
- if (dwSpamResult&SFF_SENDMSG_NOTIFY)
- {
- WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_NOTIFY, (LPARAM)&scd);
- BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_NOTIFY);
-
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_NOTIFY (sending reply)");
- if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
- CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
-
- if (pszMsgText) mir_free(pszMsgText);
- }
-
- if (dwSpamResult&SFF_SENDMSG_INSTRUCTION)
- {
- WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_INSTRUCTION, (LPARAM)&scd);
- BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_INSTRUCTION);
-
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_INSTRUCTION (sending reply)");
- if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
- CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
-
- if (pszMsgText) mir_free(pszMsgText);
- }
-
- if (dwSpamResult&SFF_SENDMSG_CONFIRMATION)
- {
- WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_CONFIRMATION, (LPARAM)&scd);
- BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_CONFIRMATION);
-
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_CONFIRMATION (sending reply)");
- if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
- CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
-
- if (pszMsgText) mir_free(pszMsgText);
- }
-
-
- // Contact handling
- if ((dwSpamResult&SFF_DELETE) && !(dwSpamResult&SFF_IGNORE))
- {
- if (bNotOnList && !(dwSpamResult&SFF_TESTPASSED) && (CallService(MS_DB_EVENT_GETCOUNT, (WPARAM)scd.hContact, 0) == 0) )
- {
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_DELETE (deleting contact)");
- CallService(MS_DB_CONTACT_DELETE, (WPARAM)scd.hContact, 0);
- }
- }
-
- // return queue value
- return iReturn;
-}
-
-
-static int DbEventFilterAdd(WPARAM wParam, LPARAM lParam)
-{
- DBEVENTINFO* pdbei = (DBEVENTINFO*)lParam;
- HANDLE hContact = (HANDLE)wParam;
-
- // Filtring events that don't have any protorecv service
- // -> hacky workaround: filtering db adds
-
- // Only filter incoming events
- if (!pdbei || !pdbei->pBlob ||
- (pdbei->flags&DBEF_SENT) || (pdbei->flags&DBEF_READ) )
- return 0; // continue adding the event
-
-
- // Only filter following events
- if ( (pdbei->eventType != EVENTTYPE_ADDED) &&
- (pdbei->eventType != ICQEVENTTYPE_EMAILEXPRESS) &&
- (pdbei->eventType != ICQEVENTTYPE_WEBPAGER) &&
- (pdbei->eventType != ICQEVENTTYPE_SMS) )
- return 0;
-
- {
- BOOL bNotOnList;
- BOOL bAlsoDoRobotCheck;
- SPAMCHECKDATA scd;
- DWORD dwSpamResult;
-
- Netlib_Logf(NULL, "Spam Filter: Catching ME_DB_EVENT_FILTER_ADD");
-
- // Collecting data out of blob
- ZeroMemory(&scd, sizeof(scd));
- switch (pdbei->eventType)
- {
- case EVENTTYPE_ADDED:
- {
- // Blob: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ)
- if (hContact)
- scd.hContact = hContact;
- else
- scd.hContact = *((PHANDLE)(pdbei->pBlob+sizeof(DWORD)));
-
- // Check if stored hContact is still valid
- if (!CallService(MS_DB_CONTACT_IS, (WPARAM)scd.hContact, 0))
- {
- Netlib_Logf(NULL, "Spam Filter: Contact invalid (skipping spam check)");
-
- return 0; // continue adding the event
- }
-
- // No text to be checked available
- scd.pszMsgText = NULL;
-
- scd.pszMsgTypeName = SFMT_ADDED;
-
- bAlsoDoRobotCheck = TRUE;
- break;
- }
-
- case ICQEVENTTYPE_EMAILEXPRESS: // (ICQ only)
- {
- // Blob: text, usually "Sender IP: xxx.xxx.xxx.xxx\r\n%s"(ASCIIZ), name(ASCIIZ), email(ASCIIZ)
-
- // Interpret blob (get sender name)
- if (hContact) {
- scd.hContact = hContact;
- } else {
- scd.pszUserName = (char*)pdbei->pBlob; // text
- scd.pszUserName = scd.pszUserName+lstrlenA(scd.pszUserName)+1; // name
-
- scd.dwFlags = SCDF_NO_CONTACT|SCDF_NO_AUTOIGNORE;
- }
-
- // Interpret blob (only use message text)
- scd.pszMsgText = (char*)pdbei->pBlob; // text
-
- scd.pszMsgTypeName = "EmailExpress";
-
- bAlsoDoRobotCheck = FALSE;
- break;
- }
-
- case ICQEVENTTYPE_WEBPAGER: // (ICQ only)
- {
- // Blob: text, usually "Subject: %s\r\n%s"(ASCIIZ), name(ASCIIZ), email(ASCIIZ)
-
- if (hContact) {
- scd.hContact = hContact;
- } else {
- // Interpret blob (get sender name)
- scd.pszUserName = (char*)pdbei->pBlob; // text
- scd.pszUserName = scd.pszUserName+lstrlenA(scd.pszUserName)+1; // name
-
- scd.dwFlags = SCDF_NO_CONTACT|SCDF_NO_AUTOIGNORE;
- }
-
- // Interpret blob (only use message text)
- scd.pszMsgText = (char*)pdbei->pBlob; // text
-
- scd.pszMsgTypeName = "WebPager";
-
- bAlsoDoRobotCheck = FALSE;
- break;
- }
-
- default:
- return 0;
- }
-
- scd.pszMsgTypeSection = pdbei->szModule;
- if (!scd.pszMsgTypeSection)
- {
- Netlib_Logf(NULL, "Spam Filter: No base protocol (skipping spam check)");
- return 0; // continue adding the event
- }
-
- scd.cbSize = sizeof(scd);
-
- Netlib_Logf(NULL, "Spam Filter: Type = %s_%s", scd.pszMsgTypeSection, scd.pszMsgTypeName);
-
- // Result check
- bNotOnList = !bAlsoDoRobotCheck || (DBGetContactSettingByte(scd.hContact, "CList", "NotOnList", 0) ? TRUE : FALSE);
- if (bNotOnList)
- {
- if (bAlsoDoRobotCheck)
- {
- // If message is from test passed contact
- if(DBGetContactSettingByte(scd.hContact, DB_MODULE_NAME, DB_SETTING_ROBOT_TESTPASSED, (BYTE)FALSE))
- {
- Netlib_Logf(NULL, "Spam Filter: Result = Already passed robot test (no spam)");
- return 0; // continue adding the event
- }
- }
-
- Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_ADVERTISMENTCHECK");
- dwSpamResult = CallService(MS_SPAMFILTER_ADVERTISMENTCHECK, (WPARAM)&scd, 0);
- if (dwSpamResult&SFF_ISNORMAL)
- {
- if (bAlsoDoRobotCheck)
- {
- Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_ROBOTCHECK");
- dwSpamResult = CallService(MS_SPAMFILTER_ROBOTCHECK, (WPARAM)&scd, 0);
- }
- }
-
- } else {
- Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_DISLIKEDMESSAGESCHECK");
- dwSpamResult = CallService(MS_SPAMFILTER_DISLIKEDMESSAGESCHECK, (WPARAM)&scd, 0);
- }
-
- if (dwSpamResult&SFF_ISNORMAL) {
- Netlib_Logf(NULL, "Spam Filter: Recognition = No-Spam");
- } else {
- Netlib_Logf(NULL, "Spam Filter: Recognition = Spam!");
- }
-
- // Remember test passed (robot filter)
- if (dwSpamResult&SFF_TESTPASSED)
- {
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_TESTPASSED (restoring contact)");
-
- // Mark contact as answered
- DBWriteContactSettingByte(scd.hContact, DB_MODULE_NAME, DB_SETTING_ROBOT_TESTPASSED, (BYTE)TRUE);
- DBDeleteContactSetting(scd.hContact, "CList", "Hidden");
-
- // Show the old events again
- MarkAllContactEventsUnRead(scd.hContact);
- }
-
- // Contact handling
- if (dwSpamResult&SFF_IGNORE)
- {
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_IGNORE (ignoring contact)");
- AddContactToIgnoreList(scd.hContact, (dwSpamResult&SFF_MARKREAD), TRUE, FALSE);
- }
- if (dwSpamResult&SFF_HIDE)
- {
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_HIDE (hiding contact)");
- DBWriteContactSettingByte(scd.hContact, "CList", "Hidden", 1);
- }
-
- // Reply messages
- if (dwSpamResult&SFF_SENDMSG_NOTIFY)
- {
- WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_NOTIFY, (LPARAM)&scd);
- BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_NOTIFY);
-
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_NOTIFY (sending reply)");
- if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
- CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
-
- if (pszMsgText) mir_free(pszMsgText);
- }
-
- if (dwSpamResult&SFF_SENDMSG_INSTRUCTION)
- {
- WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_INSTRUCTION, (LPARAM)&scd);
- BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_INSTRUCTION);
-
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_INSTRUCTION (sending reply)");
- if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
- CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
-
- if (pszMsgText) mir_free(pszMsgText);
- }
-
- if (dwSpamResult&SFF_SENDMSG_CONFIRMATION)
- {
- WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_CONFIRMATION, (LPARAM)&scd);
- BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_CONFIRMATION);
-
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_CONFIRMATION (sending reply)");
- if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
- CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
-
- if (pszMsgText) mir_free(pszMsgText);
- }
-
- // Contact handling
- if ((dwSpamResult&SFF_DELETE) && !(dwSpamResult&SFF_IGNORE))
- {
- if (bNotOnList && !(dwSpamResult&SFF_TESTPASSED) && (CallService(MS_DB_EVENT_GETCOUNT, (WPARAM)scd.hContact, 0) == 0) )
- {
- Netlib_Logf(NULL, "Spam Filter: Action = SFF_DELETE (deleting contact)");
- CallService(MS_DB_CONTACT_DELETE, (WPARAM)scd.hContact, 0);
- }
- }
-
- // Message handling
- if (dwSpamResult&SFF_DELETE)
- {
- Netlib_Logf(NULL, "Spam Filter: Result = Event add prevented");
- return 1; // Stop adding the event
-
- } else if (dwSpamResult&SFF_MARKREAD)
- {
- pdbei->flags |= DBEF_READ;
- Netlib_Logf(NULL, "Spam Filter: Result = DBEF_READ flag set (continuing add)");
- return 0;
-
- } else {
- Netlib_Logf(NULL, "Spam Filter: Result = Event accepted (continuing add)");
- return 0;
- }
- }
-}
-
-
-
-// ----------------------------------
-
-
-static int SpamCheckProtoGetCaps(WPARAM wParam, LPARAM lParam)
-{
- // Non-network-access modules should return flags
- // to represent the things they actually actively use
-
- switch (wParam)
- {
- case PFLAGNUM_1:
- return PF1_IMSEND|PF1_IMRECV|PF1_URLRECV|PF1_FILERECV|PF1_CONTACTRECV|PF1_AUTHREQ|PF1_ADDED;
- default:
- return 0;
- }
-}
-
-
-#if defined(UNICODE)
-static int SpamCheckProtoGetNameW(WPARAM wParam, LPARAM lParam)
-{
- int cchName = (int)wParam;
- WCHAR* pszName = (WCHAR*)lParam;
-
- if (pszName && (cchName > 0)) {
- mir_sntprintf(pszName, cchName, _T("%s"), TranslateT("Spam Filter"));
- return 0;
- }
-
- return 1;
-}
-#endif
-
-
-static int SpamCheckProtoGetName(WPARAM wParam, LPARAM lParam)
-{
- int cchName = (int)wParam;
- char* pszName = (char*)lParam;
-
- if (pszName && (cchName > 0))
- {
- mir_snprintf(pszName, cchName, "%s", Translate("Spam Filter"));
- return 0;
- }
-
- return 1;
-}
-
-
-static int DbContactAdded(WPARAM wParam, LPARAM lParam)
-{
- // Error here is very very unlikely
- if (CallService(MS_PROTO_ADDTOCONTACT, wParam, (LPARAM)DB_MODULE_NAME) == 0)
- Netlib_Logf(NULL, "Spam Filter: Protocol filter attached to contact \"%s\" (%i)", (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)wParam, (LPARAM)GCDNF_UNICODE), wParam);
- else
- CallService(MS_SPAMFILTER_SHOWERROR, SFSE_CRITICAL_ERROR, 0);
-
- return 0;
-}
-
-
-// ----------------------------------
-
-
-void AssignAllContacts(void)
-{
- HANDLE hContact;
-
- // MS_PROTO_ADDTOCONTACT needs to be call in AllModulesLoaded!
- // Bug-Tracker #787:
- // If MS_PROTO_ADDTOCONTACT is called when some plugin mentioned
- // in modules chain isn't loaded, the chain will be sorted incorrectly,
- // because the call to Proto_IsProtocolLoaded in service Proto_AddToContact
- // returns NULL pointer to PROTOCOLDESCRIPTOR and the service can't determine the order.
-
- for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
- if (!CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM)hContact, (LPARAM)DB_MODULE_NAME))
- {
- if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)DB_MODULE_NAME) == 0)
- Netlib_Logf(NULL, "Spam Filter: Protocol filter attached to contact \"%s\" (%i)", (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE), hContact);
- else
- CallService(MS_SPAMFILTER_SHOWERROR, SFSE_CRITICAL_ERROR, 0);
- }
-}
-
-
-void InitSpamCheck(void)
-{
- BOOL bSuccess;
- PROTOCOLDESCRIPTOR pd;
-
- ZeroMemory(&pd, sizeof(pd));
- pd.cbSize = sizeof(pd);
- pd.szName = DB_MODULE_NAME;
- pd.type = PROTOTYPE_IGNORE+100; // Ignore module = PROTOTYPE_IGNORE (old: PROTOTYPE_FILTER-100)
-
- if (CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd) == 0)
- {
- bSuccess = TRUE;
-
- // General protocol functions
- CreateProtoServiceFunction(pd.szName, PS_GETNAME, SpamCheckProtoGetName);
- CreateProtoServiceFunction(pd.szName, PS_GETCAPS, SpamCheckProtoGetCaps);
- #if defined(UNICODE)
- CreateProtoServiceFunction(pd.szName, PS_GETNAME"W", SpamCheckProtoGetNameW);
- #endif
-
- // Recv chain functions
- if (!CreateProtoServiceFunction(pd.szName, PSR_AUTH, SpamCheckProtoRecv))
- bSuccess = FALSE;
- if (!CreateProtoServiceFunction(pd.szName, PSR_MESSAGE, SpamCheckProtoRecv))
- bSuccess = FALSE;
- if (!CreateProtoServiceFunction(pd.szName, PSR_URL, SpamCheckProtoRecv))
- bSuccess = FALSE;
- if (!CreateProtoServiceFunction(pd.szName, PSR_FILE, SpamCheckProtoRecv))
- bSuccess = FALSE;
- if (!CreateProtoServiceFunction(pd.szName, PSR_CONTACTS, SpamCheckProtoRecv))
- bSuccess = FALSE;
-
- // Register for events not added via recv chain
- hHookDbEventFilterAdd = HookEvent(ME_DB_EVENT_FILTER_ADD, DbEventFilterAdd);
- if (!hHookDbEventFilterAdd) bSuccess = FALSE;
-
- // Add filter protocol to all contacts
- hHookDbContactAdded = HookEvent(ME_DB_CONTACT_ADDED, DbContactAdded);
- if (!hHookDbContactAdded) bSuccess = FALSE;
-
- } else {
- bSuccess = FALSE;
- }
-
- // Error here is very very unlikely
- if (bSuccess)
- Netlib_Logf(NULL, "Spam Filter: Protocol filter initialized (%hs)", DB_MODULE_NAME);
- else
- CallService(MS_SPAMFILTER_SHOWERROR, SFSE_CRITICAL_ERROR, 0);
-}
-
-
-void UninitSpamCheck(void)
-{
- if (hHookDbContactAdded) UnhookEvent(hHookDbContactAdded);
- if (hHookDbEventFilterAdd) UnhookEvent(hHookDbEventFilterAdd);
-
- Netlib_Logf(NULL, "Spam Filter: Protocol filter uninitialized (%hs)", DB_MODULE_NAME);
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -- Variables: Events/Hooks/Services
+HANDLE hHookDbContactAdded = NULL;
+HANDLE hHookDbEventFilterAdd = NULL;
+
+
+// -----------------------------------------
+
+static int SpamCheckProtoRecv(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA* pccsd = (CCSDATA*)lParam;
+ BOOL bNotOnList;
+ SPAMCHECKDATA scd;
+ DWORD dwSpamResult;
+ int iReturn;
+
+ ZeroMemory(&scd, sizeof(scd));
+ Netlib_Logf(NULL, "Spam Filter: Catching MS_PROTO_CHAINRECV");
+
+ // Message already marked as read (skipping spam check)
+ if (((PROTORECVEVENT*)pccsd->lParam)->flags&PREF_CREATEREAD)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Already marked as read (skipping spam check)");
+ return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+ }
+
+ if (StrCmpA(pccsd->szProtoService, PSR_URL) == 0)
+ {
+ PROTORECVEVENT* ppre = ((PROTORECVEVENT*)pccsd->lParam);
+
+ scd.hContact = pccsd->hContact;
+
+ // Interpret blob (ignore url itself, only description)
+ scd.pszMsgText = ppre->szMessage;
+
+ scd.pszMsgTypeName = SFMT_URL;
+
+ } else if (StrCmpA(pccsd->szProtoService, PSR_AUTH) == 0)
+ {
+ PROTORECVEVENT* ppre = ((PROTORECVEVENT*)pccsd->lParam);
+
+ scd.hContact = (*((PHANDLE)(ppre->szMessage+sizeof(DWORD))));
+
+ // Check if stored hContact is still valid
+ if (!CallService(MS_DB_CONTACT_IS, (WPARAM)scd.hContact, 0))
+ {
+ Netlib_Logf(NULL, "Spam Filter: Contact invalid (skipping spam check)");
+
+ // Continue the chain
+ return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+ }
+
+ // Interpret blob (only use reason text)
+ scd.pszMsgText = (char*)(ppre->szMessage+sizeof(DWORD)+sizeof(HANDLE)); // uin, hcontact, nick
+ scd.pszMsgText = scd.pszMsgText+(lstrlenA(scd.pszMsgText)+1)*sizeof(char); // first
+ scd.pszMsgText = scd.pszMsgText+(lstrlenA(scd.pszMsgText)+1)*sizeof(char); // last
+ scd.pszMsgText = scd.pszMsgText+(lstrlenA(scd.pszMsgText)+1)*sizeof(char); // email
+ scd.pszMsgText = scd.pszMsgText+(lstrlenA(scd.pszMsgText)+1)*sizeof(char); // reason
+
+ // If no reason text is given deactivate the text checking
+ if (strlen(scd.pszMsgText) <= 0)
+ scd.pszMsgText = NULL;
+
+ scd.pszMsgTypeName = SFMT_AUTHREQUEST;
+
+ } else if (StrCmpA(pccsd->szProtoService, PSR_MESSAGE) == 0)
+ {
+ PROTORECVEVENT* ppre = ((PROTORECVEVENT*)pccsd->lParam);
+
+ scd.hContact = pccsd->hContact;
+
+ // Interpret blob (use all message)
+ if (ppre->flags&PREF_UNICODE) {
+ scd.dwFlags |= SCDF_UNICODE;
+ scd.pszMsgText = ppre->szMessage+lstrlenA(ppre->szMessage)+1;
+ } else {
+ scd.pszMsgText = ppre->szMessage;
+ }
+
+ scd.pszMsgTypeName = SFMT_MESSAGE;
+
+ } else if (StrCmpA(pccsd->szProtoService, PSR_FILE) == 0)
+ {
+ PROTORECVFILE* pprf = ((PROTORECVFILE*)pccsd->lParam);
+
+ scd.hContact = pccsd->hContact;
+
+ // Interpret blob (only use description text)
+ scd.pszMsgText = pprf->szDescription;
+
+ scd.pszMsgTypeName = SFMT_FILE;
+
+ } else if (StrCmpA(pccsd->szProtoService, PSR_CONTACTS) == 0)
+ {
+ scd.hContact = pccsd->hContact;
+
+ // Does not have any text to filter only contact names: nick, first, last, email
+ scd.pszMsgText = NULL;
+
+ scd.pszMsgTypeName = SFMT_CONTACTS;
+
+ } else {
+ Netlib_Logf(NULL, "Spam Filter: Format unknown (skipping spam check)");
+
+ // Continue the chain
+ return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+ }
+
+ scd.cbSize = sizeof(scd);
+ scd.pszMsgTypeSection = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)scd.hContact, 0);
+
+ // If message is from "Unknown Contact" (very unlikely) -> MS_PROTO_GETCONTACTBASEPROTO returns NULL
+ if (!scd.pszMsgTypeSection)
+ {
+ Netlib_Logf(NULL, "Spam Filter Result: No base protocol (skipping spam check)");
+ return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+ }
+
+ Netlib_Logf(NULL, "Spam Filter: Type = %s_%s", scd.pszMsgTypeSection, scd.pszMsgTypeName);
+
+ // Result check
+ bNotOnList = (DBGetContactSettingByte(scd.hContact, "CList", "NotOnList", 0) ? TRUE : FALSE);
+ if (bNotOnList)
+ {
+ // If message is from test passed contact
+ if(DBGetContactSettingByte(scd.hContact, DB_MODULE_NAME, DB_SETTING_ROBOT_TESTPASSED, (BYTE)FALSE))
+ {
+ Netlib_Logf(NULL, "Spam Filter: Result = Already passed robot test (no spam)");
+ return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+ }
+
+ Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_ADVERTISMENTCHECK");
+ dwSpamResult = CallService(MS_SPAMFILTER_ADVERTISMENTCHECK, (WPARAM)&scd, 0);
+ if (dwSpamResult&SFF_ISNORMAL)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_ROBOTCHECK");
+ dwSpamResult = CallService(MS_SPAMFILTER_ROBOTCHECK, (WPARAM)&scd, 0);
+ }
+
+ } else {
+ Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_DISLIKEDMESSAGESCHECK");
+ dwSpamResult = CallService(MS_SPAMFILTER_DISLIKEDMESSAGESCHECK, (WPARAM)&scd, 0);
+ }
+
+ if (dwSpamResult&SFF_ISNORMAL) {
+ Netlib_Logf(NULL, "Spam Filter: Recognition = No-Spam");
+ } else {
+ Netlib_Logf(NULL, "Spam Filter: Recognition = Spam!");
+ }
+
+
+ // Message handling
+ if (dwSpamResult&SFF_DELETE)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Result = Event suppressed (stopping recv chain)");
+
+ // Cache chain (see reply messages)
+ iReturn = 1; // Stop processing the chain
+
+ } else if (dwSpamResult&SFF_MARKREAD)
+ {
+ (((PROTORECVEVENT*)pccsd->lParam)->flags) |= PREF_CREATEREAD;
+ Netlib_Logf(NULL, "Spam Filter: Result = PREF_CREATEREAD flag set (continuing recv chain)");
+
+ // Cache chain (see reply messages)
+ iReturn = CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+
+ } else {
+ Netlib_Logf(NULL, "Spam Filter: Result = Event accepted (continuing recv chain)");
+
+ // Cache chain (see reply messages)
+ iReturn = CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+ }
+
+
+ // IMPORTANT!: The following is done *after* the call to MS_PROTO_CHAINRECV so that
+ // the protocol has had the chance to add the recved event to the db.
+ // The events to be sent are then ordered correctly in db.
+
+ // The contact might have been deleted etc. by another filter protcol in recv chain
+ // -> just a safety check
+ if (!CallService(MS_DB_CONTACT_IS, (WPARAM)scd.hContact, 0))
+ {
+ Netlib_Logf(NULL, "Spam Filter: Contact deleted by other filter (stopping processing)");
+ return iReturn;
+ }
+
+ // Remember test passed (robot filter)
+ if (dwSpamResult&SFF_TESTPASSED)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_TESTPASSED (restoring contact)");
+
+ // Mark contact as answered
+ DBWriteContactSettingByte(scd.hContact, DB_MODULE_NAME, DB_SETTING_ROBOT_TESTPASSED, (BYTE)TRUE);
+ DBDeleteContactSetting(scd.hContact, "CList", "Hidden");
+
+ // Show the old events again
+ MarkAllContactEventsUnRead(scd.hContact);
+ }
+
+ // Contact handling
+ if (dwSpamResult&SFF_IGNORE)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_IGNORE (ignoring contact)");
+ AddContactToIgnoreList(scd.hContact, (dwSpamResult&SFF_MARKREAD), TRUE, FALSE);
+ }
+ if (dwSpamResult&SFF_HIDE)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_HIDE (hiding contact)");
+ DBWriteContactSettingByte(scd.hContact, "CList", "Hidden", 1);
+ }
+
+ // Reply messages
+ if (dwSpamResult&SFF_SENDMSG_NOTIFY)
+ {
+ WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_NOTIFY, (LPARAM)&scd);
+ BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_NOTIFY);
+
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_NOTIFY (sending reply)");
+ if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
+ CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
+
+ if (pszMsgText) mir_free(pszMsgText);
+ }
+
+ if (dwSpamResult&SFF_SENDMSG_INSTRUCTION)
+ {
+ WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_INSTRUCTION, (LPARAM)&scd);
+ BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_INSTRUCTION);
+
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_INSTRUCTION (sending reply)");
+ if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
+ CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
+
+ if (pszMsgText) mir_free(pszMsgText);
+ }
+
+ if (dwSpamResult&SFF_SENDMSG_CONFIRMATION)
+ {
+ WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_CONFIRMATION, (LPARAM)&scd);
+ BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_CONFIRMATION);
+
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_CONFIRMATION (sending reply)");
+ if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
+ CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
+
+ if (pszMsgText) mir_free(pszMsgText);
+ }
+
+
+ // Contact handling
+ if ((dwSpamResult&SFF_DELETE) && !(dwSpamResult&SFF_IGNORE))
+ {
+ if (bNotOnList && !(dwSpamResult&SFF_TESTPASSED) && (CallService(MS_DB_EVENT_GETCOUNT, (WPARAM)scd.hContact, 0) == 0) )
+ {
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_DELETE (deleting contact)");
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)scd.hContact, 0);
+ }
+ }
+
+ // return queue value
+ return iReturn;
+}
+
+
+static int DbEventFilterAdd(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO* pdbei = (DBEVENTINFO*)lParam;
+ HANDLE hContact = (HANDLE)wParam;
+
+ // Filtring events that don't have any protorecv service
+ // -> hacky workaround: filtering db adds
+
+ // Only filter incoming events
+ if (!pdbei || !pdbei->pBlob ||
+ (pdbei->flags&DBEF_SENT) || (pdbei->flags&DBEF_READ) )
+ return 0; // continue adding the event
+
+
+ // Only filter following events
+ if ( (pdbei->eventType != EVENTTYPE_ADDED) &&
+ (pdbei->eventType != ICQEVENTTYPE_EMAILEXPRESS) &&
+ (pdbei->eventType != ICQEVENTTYPE_WEBPAGER) &&
+ (pdbei->eventType != ICQEVENTTYPE_SMS) )
+ return 0;
+
+ {
+ BOOL bNotOnList;
+ BOOL bAlsoDoRobotCheck;
+ SPAMCHECKDATA scd;
+ DWORD dwSpamResult;
+
+ Netlib_Logf(NULL, "Spam Filter: Catching ME_DB_EVENT_FILTER_ADD");
+
+ // Collecting data out of blob
+ ZeroMemory(&scd, sizeof(scd));
+ switch (pdbei->eventType)
+ {
+ case EVENTTYPE_ADDED:
+ {
+ // Blob: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ)
+ if (hContact)
+ scd.hContact = hContact;
+ else
+ scd.hContact = *((PHANDLE)(pdbei->pBlob+sizeof(DWORD)));
+
+ // Check if stored hContact is still valid
+ if (!CallService(MS_DB_CONTACT_IS, (WPARAM)scd.hContact, 0))
+ {
+ Netlib_Logf(NULL, "Spam Filter: Contact invalid (skipping spam check)");
+
+ return 0; // continue adding the event
+ }
+
+ // No text to be checked available
+ scd.pszMsgText = NULL;
+
+ scd.pszMsgTypeName = SFMT_ADDED;
+
+ bAlsoDoRobotCheck = TRUE;
+ break;
+ }
+
+ case ICQEVENTTYPE_EMAILEXPRESS: // (ICQ only)
+ {
+ // Blob: text, usually "Sender IP: xxx.xxx.xxx.xxx\r\n%s"(ASCIIZ), name(ASCIIZ), email(ASCIIZ)
+
+ // Interpret blob (get sender name)
+ if (hContact) {
+ scd.hContact = hContact;
+ } else {
+ scd.pszUserName = (char*)pdbei->pBlob; // text
+ scd.pszUserName = scd.pszUserName+lstrlenA(scd.pszUserName)+1; // name
+
+ scd.dwFlags = SCDF_NO_CONTACT|SCDF_NO_AUTOIGNORE;
+ }
+
+ // Interpret blob (only use message text)
+ scd.pszMsgText = (char*)pdbei->pBlob; // text
+
+ scd.pszMsgTypeName = "EmailExpress";
+
+ bAlsoDoRobotCheck = FALSE;
+ break;
+ }
+
+ case ICQEVENTTYPE_WEBPAGER: // (ICQ only)
+ {
+ // Blob: text, usually "Subject: %s\r\n%s"(ASCIIZ), name(ASCIIZ), email(ASCIIZ)
+
+ if (hContact) {
+ scd.hContact = hContact;
+ } else {
+ // Interpret blob (get sender name)
+ scd.pszUserName = (char*)pdbei->pBlob; // text
+ scd.pszUserName = scd.pszUserName+lstrlenA(scd.pszUserName)+1; // name
+
+ scd.dwFlags = SCDF_NO_CONTACT|SCDF_NO_AUTOIGNORE;
+ }
+
+ // Interpret blob (only use message text)
+ scd.pszMsgText = (char*)pdbei->pBlob; // text
+
+ scd.pszMsgTypeName = "WebPager";
+
+ bAlsoDoRobotCheck = FALSE;
+ break;
+ }
+
+ default:
+ return 0;
+ }
+
+ scd.pszMsgTypeSection = pdbei->szModule;
+ if (!scd.pszMsgTypeSection)
+ {
+ Netlib_Logf(NULL, "Spam Filter: No base protocol (skipping spam check)");
+ return 0; // continue adding the event
+ }
+
+ scd.cbSize = sizeof(scd);
+
+ Netlib_Logf(NULL, "Spam Filter: Type = %s_%s", scd.pszMsgTypeSection, scd.pszMsgTypeName);
+
+ // Result check
+ bNotOnList = !bAlsoDoRobotCheck || (DBGetContactSettingByte(scd.hContact, "CList", "NotOnList", 0) ? TRUE : FALSE);
+ if (bNotOnList)
+ {
+ if (bAlsoDoRobotCheck)
+ {
+ // If message is from test passed contact
+ if(DBGetContactSettingByte(scd.hContact, DB_MODULE_NAME, DB_SETTING_ROBOT_TESTPASSED, (BYTE)FALSE))
+ {
+ Netlib_Logf(NULL, "Spam Filter: Result = Already passed robot test (no spam)");
+ return 0; // continue adding the event
+ }
+ }
+
+ Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_ADVERTISMENTCHECK");
+ dwSpamResult = CallService(MS_SPAMFILTER_ADVERTISMENTCHECK, (WPARAM)&scd, 0);
+ if (dwSpamResult&SFF_ISNORMAL)
+ {
+ if (bAlsoDoRobotCheck)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_ROBOTCHECK");
+ dwSpamResult = CallService(MS_SPAMFILTER_ROBOTCHECK, (WPARAM)&scd, 0);
+ }
+ }
+
+ } else {
+ Netlib_Logf(NULL, "Spam Filter: Running MS_SPAMFILTER_DISLIKEDMESSAGESCHECK");
+ dwSpamResult = CallService(MS_SPAMFILTER_DISLIKEDMESSAGESCHECK, (WPARAM)&scd, 0);
+ }
+
+ if (dwSpamResult&SFF_ISNORMAL) {
+ Netlib_Logf(NULL, "Spam Filter: Recognition = No-Spam");
+ } else {
+ Netlib_Logf(NULL, "Spam Filter: Recognition = Spam!");
+ }
+
+ // Remember test passed (robot filter)
+ if (dwSpamResult&SFF_TESTPASSED)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_TESTPASSED (restoring contact)");
+
+ // Mark contact as answered
+ DBWriteContactSettingByte(scd.hContact, DB_MODULE_NAME, DB_SETTING_ROBOT_TESTPASSED, (BYTE)TRUE);
+ DBDeleteContactSetting(scd.hContact, "CList", "Hidden");
+
+ // Show the old events again
+ MarkAllContactEventsUnRead(scd.hContact);
+ }
+
+ // Contact handling
+ if (dwSpamResult&SFF_IGNORE)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_IGNORE (ignoring contact)");
+ AddContactToIgnoreList(scd.hContact, (dwSpamResult&SFF_MARKREAD), TRUE, FALSE);
+ }
+ if (dwSpamResult&SFF_HIDE)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_HIDE (hiding contact)");
+ DBWriteContactSettingByte(scd.hContact, "CList", "Hidden", 1);
+ }
+
+ // Reply messages
+ if (dwSpamResult&SFF_SENDMSG_NOTIFY)
+ {
+ WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_NOTIFY, (LPARAM)&scd);
+ BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_NOTIFY);
+
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_NOTIFY (sending reply)");
+ if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
+ CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
+
+ if (pszMsgText) mir_free(pszMsgText);
+ }
+
+ if (dwSpamResult&SFF_SENDMSG_INSTRUCTION)
+ {
+ WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_INSTRUCTION, (LPARAM)&scd);
+ BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_INSTRUCTION);
+
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_INSTRUCTION (sending reply)");
+ if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
+ CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
+
+ if (pszMsgText) mir_free(pszMsgText);
+ }
+
+ if (dwSpamResult&SFF_SENDMSG_CONFIRMATION)
+ {
+ WCHAR* pszMsgText = (WCHAR*)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_MSGTEXT_CONFIRMATION, (LPARAM)&scd);
+ BOOL bAddToHistory = (BOOL)CallService(MS_SPAMFILTER_GETSPAMCHECKINFO, (WPARAM)SFSCI_ADD_TO_HISTORY, (LPARAM)SFSCI_MSGTEXT_CONFIRMATION);
+
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_SENDMSG_CONFIRMATION (sending reply)");
+ if (!SendContactAutomatedMessage(scd.hContact, pszMsgText, bAddToHistory))
+ CallService(MS_SPAMFILTER_SHOWERROR, (WPARAM)SFSE_SEND_FAILED, (LPARAM)&scd);
+
+ if (pszMsgText) mir_free(pszMsgText);
+ }
+
+ // Contact handling
+ if ((dwSpamResult&SFF_DELETE) && !(dwSpamResult&SFF_IGNORE))
+ {
+ if (bNotOnList && !(dwSpamResult&SFF_TESTPASSED) && (CallService(MS_DB_EVENT_GETCOUNT, (WPARAM)scd.hContact, 0) == 0) )
+ {
+ Netlib_Logf(NULL, "Spam Filter: Action = SFF_DELETE (deleting contact)");
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)scd.hContact, 0);
+ }
+ }
+
+ // Message handling
+ if (dwSpamResult&SFF_DELETE)
+ {
+ Netlib_Logf(NULL, "Spam Filter: Result = Event add prevented");
+ return 1; // Stop adding the event
+
+ } else if (dwSpamResult&SFF_MARKREAD)
+ {
+ pdbei->flags |= DBEF_READ;
+ Netlib_Logf(NULL, "Spam Filter: Result = DBEF_READ flag set (continuing add)");
+ return 0;
+
+ } else {
+ Netlib_Logf(NULL, "Spam Filter: Result = Event accepted (continuing add)");
+ return 0;
+ }
+ }
+}
+
+
+
+// ----------------------------------
+
+
+static int SpamCheckProtoGetCaps(WPARAM wParam, LPARAM lParam)
+{
+ // Non-network-access modules should return flags
+ // to represent the things they actually actively use
+
+ switch (wParam)
+ {
+ case PFLAGNUM_1:
+ return PF1_IMSEND|PF1_IMRECV|PF1_URLRECV|PF1_FILERECV|PF1_CONTACTRECV|PF1_AUTHREQ|PF1_ADDED;
+ default:
+ return 0;
+ }
+}
+
+
+#if defined(UNICODE)
+static int SpamCheckProtoGetNameW(WPARAM wParam, LPARAM lParam)
+{
+ int cchName = (int)wParam;
+ WCHAR* pszName = (WCHAR*)lParam;
+
+ if (pszName && (cchName > 0)) {
+ mir_sntprintf(pszName, cchName, _T("%s"), TranslateT("Spam Filter"));
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+
+static int SpamCheckProtoGetName(WPARAM wParam, LPARAM lParam)
+{
+ int cchName = (int)wParam;
+ char* pszName = (char*)lParam;
+
+ if (pszName && (cchName > 0))
+ {
+ mir_snprintf(pszName, cchName, "%s", Translate("Spam Filter"));
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static int DbContactAdded(WPARAM wParam, LPARAM lParam)
+{
+ // Error here is very very unlikely
+ if (CallService(MS_PROTO_ADDTOCONTACT, wParam, (LPARAM)DB_MODULE_NAME) == 0)
+ Netlib_Logf(NULL, "Spam Filter: Protocol filter attached to contact \"%s\" (%i)", (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)wParam, (LPARAM)GCDNF_UNICODE), wParam);
+ else
+ CallService(MS_SPAMFILTER_SHOWERROR, SFSE_CRITICAL_ERROR, 0);
+
+ return 0;
+}
+
+
+// ----------------------------------
+
+
+void AssignAllContacts(void)
+{
+ HANDLE hContact;
+
+ // MS_PROTO_ADDTOCONTACT needs to be call in AllModulesLoaded!
+ // Bug-Tracker #787:
+ // If MS_PROTO_ADDTOCONTACT is called when some plugin mentioned
+ // in modules chain isn't loaded, the chain will be sorted incorrectly,
+ // because the call to Proto_IsProtocolLoaded in service Proto_AddToContact
+ // returns NULL pointer to PROTOCOLDESCRIPTOR and the service can't determine the order.
+
+ for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ if (!CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM)hContact, (LPARAM)DB_MODULE_NAME))
+ {
+ if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)DB_MODULE_NAME) == 0)
+ Netlib_Logf(NULL, "Spam Filter: Protocol filter attached to contact \"%s\" (%i)", (WCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_UNICODE), hContact);
+ else
+ CallService(MS_SPAMFILTER_SHOWERROR, SFSE_CRITICAL_ERROR, 0);
+ }
+}
+
+
+void InitSpamCheck(void)
+{
+ BOOL bSuccess;
+ PROTOCOLDESCRIPTOR pd;
+
+ ZeroMemory(&pd, sizeof(pd));
+ pd.cbSize = sizeof(pd);
+ pd.szName = DB_MODULE_NAME;
+ pd.type = PROTOTYPE_IGNORE+100; // Ignore module = PROTOTYPE_IGNORE (old: PROTOTYPE_FILTER-100)
+
+ if (CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd) == 0)
+ {
+ bSuccess = TRUE;
+
+ // General protocol functions
+ CreateProtoServiceFunction(pd.szName, PS_GETNAME, SpamCheckProtoGetName);
+ CreateProtoServiceFunction(pd.szName, PS_GETCAPS, SpamCheckProtoGetCaps);
+ #if defined(UNICODE)
+ CreateProtoServiceFunction(pd.szName, PS_GETNAME"W", SpamCheckProtoGetNameW);
+ #endif
+
+ // Recv chain functions
+ if (!CreateProtoServiceFunction(pd.szName, PSR_AUTH, SpamCheckProtoRecv))
+ bSuccess = FALSE;
+ if (!CreateProtoServiceFunction(pd.szName, PSR_MESSAGE, SpamCheckProtoRecv))
+ bSuccess = FALSE;
+ if (!CreateProtoServiceFunction(pd.szName, PSR_URL, SpamCheckProtoRecv))
+ bSuccess = FALSE;
+ if (!CreateProtoServiceFunction(pd.szName, PSR_FILE, SpamCheckProtoRecv))
+ bSuccess = FALSE;
+ if (!CreateProtoServiceFunction(pd.szName, PSR_CONTACTS, SpamCheckProtoRecv))
+ bSuccess = FALSE;
+
+ // Register for events not added via recv chain
+ hHookDbEventFilterAdd = HookEvent(ME_DB_EVENT_FILTER_ADD, DbEventFilterAdd);
+ if (!hHookDbEventFilterAdd) bSuccess = FALSE;
+
+ // Add filter protocol to all contacts
+ hHookDbContactAdded = HookEvent(ME_DB_CONTACT_ADDED, DbContactAdded);
+ if (!hHookDbContactAdded) bSuccess = FALSE;
+
+ } else {
+ bSuccess = FALSE;
+ }
+
+ // Error here is very very unlikely
+ if (bSuccess)
+ Netlib_Logf(NULL, "Spam Filter: Protocol filter initialized (%hs)", DB_MODULE_NAME);
+ else
+ CallService(MS_SPAMFILTER_SHOWERROR, SFSE_CRITICAL_ERROR, 0);
+}
+
+
+void UninitSpamCheck(void)
+{
+ if (hHookDbContactAdded) UnhookEvent(hHookDbContactAdded);
+ if (hHookDbEventFilterAdd) UnhookEvent(hHookDbEventFilterAdd);
+
+ Netlib_Logf(NULL, "Spam Filter: Protocol filter uninitialized (%hs)", DB_MODULE_NAME);
} \ No newline at end of file
diff --git a/spamcheck.h b/spamcheck.h
index 5ec035b..b818f91 100644
--- a/spamcheck.h
+++ b/spamcheck.h
@@ -1,33 +1,33 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_SPAMCHECK_H__
-#define SF_SPAMCHECK_H__ 1
-
-
-// -- Prototypes
-void AssignAllContacts(void);
-
-void InitSpamCheck(void);
-void UninitSpamCheck(void);
-
-
-#endif // SF_SPAMCHECK_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_SPAMCHECK_H__
+#define SF_SPAMCHECK_H__ 1
+
+
+// -- Prototypes
+void AssignAllContacts(void);
+
+void InitSpamCheck(void);
+void UninitSpamCheck(void);
+
+
+#endif // SF_SPAMCHECK_H__
diff --git a/spamcheckdata.c b/spamcheckdata.c
index 5e27150..09430cb 100644
--- a/spamcheckdata.c
+++ b/spamcheckdata.c
@@ -1,273 +1,273 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-
-// -----------------------------------------
-
-
-
-WCHAR* SCD_DecodeUserName(SPAMCHECKDATA* pscd)
-{
- if (pscd->dwFlags & SCDF_NO_CONTACT)
- {
- #if defined(UNICODE)
- if (pscd->dwFlags&SCDF_UNICODE)
- return mir_wstrdup(pscd->pwszUserName);
- else
- return (WCHAR*)mir_utf8encodeW((WCHAR*)pscd->pszUserName);
- #else
- if (pscd->dwFlags&SCDF_UNICODE)
- return UnicodeToAnsi(pscd->pwszUserName);
- else
- return mir_strdup(pscd->pszUserName);
- #endif
-
- } else {
- return NULL;
- }
-}
-
-
-BOOL SCD_IsUserValid(SPAMCHECKDATA* pscd)
-{
- if (pscd->dwFlags&SCDF_NO_CONTACT)
- return (pscd->ptszUserName ? TRUE : FALSE);
- else
- return (pscd->hContact && (pscd->hContact != INVALID_HANDLE_VALUE));
-}
-
-
-
-WCHAR* SCD_GetContactCustomDisplayName(SPAMCHECKDATA* pscd)
-{
- // MS_CLIST_GETCONTACTDISPLAYNAME caches it's internal calls to
- // MS_CONTACT_GETCONTACTINFO, we use it directly here (avoiding cached data)
-
- // GCDNF_NOCACHE flag for MS_CLIST_GETCONTACTDISPLAYNAME
- // could be used, too
-
- WCHAR* pszReturn;
-
- // No contact available
- if (pscd->dwFlags&SCDF_NO_CONTACT)
- {
- return SCD_DecodeUserName(pscd);
-
-
- // Normal hContact (CList name)
- } else {
-
- CONTACTINFO ci;
-
- ZeroMemory(&ci, sizeof(ci));
- ci.cbSize = sizeof(ci);
- ci.hContact = pscd->hContact;
- #if defined(UNICODE)
- ci.dwFlag = CNF_DISPLAY|CNF_UNICODE;
- #else
- ci.dwFlag = CNF_DISPLAY;
- #endif
-
- pszReturn = NULL;
- if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
- if (ci.type == CNFT_ASCIIZ)
- if (lstrlen(ci.pszVal) > 0)
- pszReturn = ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc
-
- if (!pszReturn)
- {
- #if defined(UNICODE)
- ci.dwFlag = CNF_UNIQUEID|CNF_UNICODE;
- #else
- ci.dwFlag = CNF_UNIQUEID;
- #endif
-
- if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
- {
- if (ci.type == CNFT_ASCIIZ) {
- pszReturn = ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc
- } else if (ci.type == CNFT_DWORD) {
- pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
- if (pszReturn)
- mir_sntprintf(pszReturn, (MAX_INT_LENGTH+1), _T("%u"), ci.dVal);
- } else if (ci.type == CNFT_WORD) {
- pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
- if (pszReturn)
- mir_sntprintf(pszReturn, (MAX_INT_LENGTH+1), _T("%u"), ci.wVal);
- } else if (ci.type == CNFT_BYTE) {
- pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
- if (pszReturn)
- mir_sntprintf(pszReturn, (MAX_INT_LENGTH+1), _T("%u"), ci.bVal);
- }
- }
- }
-
- }
-
- return pszReturn;
-}
-
-
-WCHAR* SCD_GetContactName(SPAMCHECKDATA* pscd, BOOL bIncludeUniqueID)
-{
- // No contact available
- if (pscd->dwFlags & SCDF_NO_CONTACT)
- {
- return SCD_DecodeUserName(pscd);
-
- // Normal hContact (CList name)
- } else {
-
- WCHAR* pszNick;
- CONTACTINFO ci;
-
- ZeroMemory(&ci, sizeof(ci));
- ci.cbSize = sizeof(ci);
- ci.hContact = pscd->hContact;
- #if defined(UNICODE)
- ci.dwFlag = CNF_NICK|CNF_UNICODE;
- #else
- ci.dwFlag = CNF_NICK;
- #endif
-
- pszNick = NULL;
- if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
- if (ci.type == CNFT_ASCIIZ)
- if (lstrlen(ci.pszVal) > 0)
- pszNick = ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc
-
- // Append unique id (if whished) or if nick is not available
- if (bIncludeUniqueID || !pszNick)
- {
- WCHAR* pszUniqueID = NULL;
-
- #if defined(UNICODE)
- ci.dwFlag = CNF_UNIQUEID|CNF_UNICODE;
- #else
- ci.dwFlag = CNF_UNIQUEID;
- #endif
-
- if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
- {
- if (ci.type == CNFT_ASCIIZ) {
- pszUniqueID = ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc
- } else if (ci.type == CNFT_DWORD) {
- pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
- if (pszUniqueID)
- mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.dVal);
- } else if (ci.type == CNFT_WORD) {
- pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
- if (pszUniqueID)
- mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.wVal);
- } else if (ci.type == CNFT_BYTE) {
- pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
- if (pszUniqueID)
- mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.bVal);
- }
- }
-
- if (!pszNick) {
- return pszUniqueID;
-
- } else if (!pszUniqueID) {
- return pszNick;
-
- } else {
-
- int iSize;
- WCHAR* pszReturn;
- WCHAR* pszFmt = TranslateT("%s (%s)");
-
- iSize = (lstrlen(pszFmt) + lstrlen(pszNick) + lstrlen(pszUniqueID) + 1);
-
- pszReturn = (WCHAR*)mir_alloc(iSize*sizeof(WCHAR));
- if (!pszReturn) return pszNick;
-
- mir_sntprintf(pszReturn, iSize, pszFmt, pszNick, pszUniqueID);
-
- mir_free(pszUniqueID);
- mir_free(pszNick);
- return pszReturn;
- }
-
- } else {
- return pszNick;
- }
-
- }
-}
-
-
-WCHAR* SCD_GetContactUniqueStr(SPAMCHECKDATA* pscd, BOOL bUseNick)
-{
- // No contact available
- if (pscd->dwFlags & SCDF_NO_CONTACT)
- {
- return SCD_DecodeUserName(pscd);
-
-
- // Normal hContact (CList name)
- } else {
-
- CONTACTINFO ci;
- WCHAR* pszReturn;
-
- ZeroMemory(&ci, sizeof(ci));
- ci.cbSize = sizeof(ci);
- ci.hContact = pscd->hContact;
- #if defined(UNICODE)
- if (bUseNick)
- ci.dwFlag = CNF_NICK|CNF_UNICODE;
- else
- ci.dwFlag = CNF_UNIQUEID|CNF_UNICODE;
- #else
- if (bUseNick)
- ci.dwFlag = CNF_NICK;
- else
- ci.dwFlag = CNF_UNIQUEID;
- #endif
-
- pszReturn = NULL;
- if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
- {
- if (ci.type == CNFT_ASCIIZ) {
- pszReturn = (WCHAR*)mir_alloc((lstrlen(ci.pszVal) + lstrlenA(ci.szProto) + 2)*sizeof(WCHAR));
- mir_sntprintf(pszReturn, (lstrlen(ci.pszVal) + lstrlenA(ci.szProto) + 2), _T("%hs:%s"), ci.szProto ? ci.szProto : "", ci.pszVal);
- mir_free(ci.pszVal);
- } else if (ci.type == CNFT_DWORD) {
- pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2)*sizeof(WCHAR));
- mir_sntprintf(pszReturn, (MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2), _T("%hs:%u"), ci.szProto ? ci.szProto : "", ci.dVal);
- } else if (ci.type == CNFT_WORD) {
- pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2)*sizeof(WCHAR));
- mir_sntprintf(pszReturn, (MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2), _T("%hs:%u"), ci.szProto ? ci.szProto : "", ci.wVal);
- } else if (ci.type == CNFT_BYTE) {
- pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2)*sizeof(WCHAR));
- mir_sntprintf(pszReturn, (MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2), _T("%hs:%u"), ci.szProto ? ci.szProto : "", ci.bVal);
- }
- }
-
- return pszReturn;
- }
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+
+// -----------------------------------------
+
+
+
+WCHAR* SCD_DecodeUserName(SPAMCHECKDATA* pscd)
+{
+ if (pscd->dwFlags & SCDF_NO_CONTACT)
+ {
+ #if defined(UNICODE)
+ if (pscd->dwFlags&SCDF_UNICODE)
+ return mir_wstrdup(pscd->pwszUserName);
+ else
+ return (WCHAR*)mir_utf8encodeW((WCHAR*)pscd->pszUserName);
+ #else
+ if (pscd->dwFlags&SCDF_UNICODE)
+ return UnicodeToAnsi(pscd->pwszUserName);
+ else
+ return mir_strdup(pscd->pszUserName);
+ #endif
+
+ } else {
+ return NULL;
+ }
+}
+
+
+BOOL SCD_IsUserValid(SPAMCHECKDATA* pscd)
+{
+ if (pscd->dwFlags&SCDF_NO_CONTACT)
+ return (pscd->ptszUserName ? TRUE : FALSE);
+ else
+ return (pscd->hContact && (pscd->hContact != INVALID_HANDLE_VALUE));
+}
+
+
+
+WCHAR* SCD_GetContactCustomDisplayName(SPAMCHECKDATA* pscd)
+{
+ // MS_CLIST_GETCONTACTDISPLAYNAME caches it's internal calls to
+ // MS_CONTACT_GETCONTACTINFO, we use it directly here (avoiding cached data)
+
+ // GCDNF_NOCACHE flag for MS_CLIST_GETCONTACTDISPLAYNAME
+ // could be used, too
+
+ WCHAR* pszReturn;
+
+ // No contact available
+ if (pscd->dwFlags&SCDF_NO_CONTACT)
+ {
+ return SCD_DecodeUserName(pscd);
+
+
+ // Normal hContact (CList name)
+ } else {
+
+ CONTACTINFO ci;
+
+ ZeroMemory(&ci, sizeof(ci));
+ ci.cbSize = sizeof(ci);
+ ci.hContact = pscd->hContact;
+ #if defined(UNICODE)
+ ci.dwFlag = CNF_DISPLAY|CNF_UNICODE;
+ #else
+ ci.dwFlag = CNF_DISPLAY;
+ #endif
+
+ pszReturn = NULL;
+ if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
+ if (ci.type == CNFT_ASCIIZ)
+ if (lstrlen(ci.pszVal) > 0)
+ pszReturn = ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc
+
+ if (!pszReturn)
+ {
+ #if defined(UNICODE)
+ ci.dwFlag = CNF_UNIQUEID|CNF_UNICODE;
+ #else
+ ci.dwFlag = CNF_UNIQUEID;
+ #endif
+
+ if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
+ {
+ if (ci.type == CNFT_ASCIIZ) {
+ pszReturn = ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc
+ } else if (ci.type == CNFT_DWORD) {
+ pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
+ if (pszReturn)
+ mir_sntprintf(pszReturn, (MAX_INT_LENGTH+1), _T("%u"), ci.dVal);
+ } else if (ci.type == CNFT_WORD) {
+ pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
+ if (pszReturn)
+ mir_sntprintf(pszReturn, (MAX_INT_LENGTH+1), _T("%u"), ci.wVal);
+ } else if (ci.type == CNFT_BYTE) {
+ pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
+ if (pszReturn)
+ mir_sntprintf(pszReturn, (MAX_INT_LENGTH+1), _T("%u"), ci.bVal);
+ }
+ }
+ }
+
+ }
+
+ return pszReturn;
+}
+
+
+WCHAR* SCD_GetContactName(SPAMCHECKDATA* pscd, BOOL bIncludeUniqueID)
+{
+ // No contact available
+ if (pscd->dwFlags & SCDF_NO_CONTACT)
+ {
+ return SCD_DecodeUserName(pscd);
+
+ // Normal hContact (CList name)
+ } else {
+
+ WCHAR* pszNick;
+ CONTACTINFO ci;
+
+ ZeroMemory(&ci, sizeof(ci));
+ ci.cbSize = sizeof(ci);
+ ci.hContact = pscd->hContact;
+ #if defined(UNICODE)
+ ci.dwFlag = CNF_NICK|CNF_UNICODE;
+ #else
+ ci.dwFlag = CNF_NICK;
+ #endif
+
+ pszNick = NULL;
+ if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
+ if (ci.type == CNFT_ASCIIZ)
+ if (lstrlen(ci.pszVal) > 0)
+ pszNick = ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc
+
+ // Append unique id (if whished) or if nick is not available
+ if (bIncludeUniqueID || !pszNick)
+ {
+ WCHAR* pszUniqueID = NULL;
+
+ #if defined(UNICODE)
+ ci.dwFlag = CNF_UNIQUEID|CNF_UNICODE;
+ #else
+ ci.dwFlag = CNF_UNIQUEID;
+ #endif
+
+ if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
+ {
+ if (ci.type == CNFT_ASCIIZ) {
+ pszUniqueID = ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc
+ } else if (ci.type == CNFT_DWORD) {
+ pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
+ if (pszUniqueID)
+ mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.dVal);
+ } else if (ci.type == CNFT_WORD) {
+ pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
+ if (pszUniqueID)
+ mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.wVal);
+ } else if (ci.type == CNFT_BYTE) {
+ pszUniqueID = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
+ if (pszUniqueID)
+ mir_sntprintf(pszUniqueID, (MAX_INT_LENGTH+1), _T("%u"), ci.bVal);
+ }
+ }
+
+ if (!pszNick) {
+ return pszUniqueID;
+
+ } else if (!pszUniqueID) {
+ return pszNick;
+
+ } else {
+
+ int iSize;
+ WCHAR* pszReturn;
+ WCHAR* pszFmt = TranslateT("%s (%s)");
+
+ iSize = (lstrlen(pszFmt) + lstrlen(pszNick) + lstrlen(pszUniqueID) + 1);
+
+ pszReturn = (WCHAR*)mir_alloc(iSize*sizeof(WCHAR));
+ if (!pszReturn) return pszNick;
+
+ mir_sntprintf(pszReturn, iSize, pszFmt, pszNick, pszUniqueID);
+
+ mir_free(pszUniqueID);
+ mir_free(pszNick);
+ return pszReturn;
+ }
+
+ } else {
+ return pszNick;
+ }
+
+ }
+}
+
+
+WCHAR* SCD_GetContactUniqueStr(SPAMCHECKDATA* pscd, BOOL bUseNick)
+{
+ // No contact available
+ if (pscd->dwFlags & SCDF_NO_CONTACT)
+ {
+ return SCD_DecodeUserName(pscd);
+
+
+ // Normal hContact (CList name)
+ } else {
+
+ CONTACTINFO ci;
+ WCHAR* pszReturn;
+
+ ZeroMemory(&ci, sizeof(ci));
+ ci.cbSize = sizeof(ci);
+ ci.hContact = pscd->hContact;
+ #if defined(UNICODE)
+ if (bUseNick)
+ ci.dwFlag = CNF_NICK|CNF_UNICODE;
+ else
+ ci.dwFlag = CNF_UNIQUEID|CNF_UNICODE;
+ #else
+ if (bUseNick)
+ ci.dwFlag = CNF_NICK;
+ else
+ ci.dwFlag = CNF_UNIQUEID;
+ #endif
+
+ pszReturn = NULL;
+ if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
+ {
+ if (ci.type == CNFT_ASCIIZ) {
+ pszReturn = (WCHAR*)mir_alloc((lstrlen(ci.pszVal) + lstrlenA(ci.szProto) + 2)*sizeof(WCHAR));
+ mir_sntprintf(pszReturn, (lstrlen(ci.pszVal) + lstrlenA(ci.szProto) + 2), _T("%hs:%s"), ci.szProto ? ci.szProto : "", ci.pszVal);
+ mir_free(ci.pszVal);
+ } else if (ci.type == CNFT_DWORD) {
+ pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2)*sizeof(WCHAR));
+ mir_sntprintf(pszReturn, (MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2), _T("%hs:%u"), ci.szProto ? ci.szProto : "", ci.dVal);
+ } else if (ci.type == CNFT_WORD) {
+ pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2)*sizeof(WCHAR));
+ mir_sntprintf(pszReturn, (MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2), _T("%hs:%u"), ci.szProto ? ci.szProto : "", ci.wVal);
+ } else if (ci.type == CNFT_BYTE) {
+ pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2)*sizeof(WCHAR));
+ mir_sntprintf(pszReturn, (MAX_INT_LENGTH + lstrlenA(ci.szProto) + 2), _T("%hs:%u"), ci.szProto ? ci.szProto : "", ci.bVal);
+ }
+ }
+
+ return pszReturn;
+ }
} \ No newline at end of file
diff --git a/spamcheckdata.h b/spamcheckdata.h
index 9f020e6..4477f69 100644
--- a/spamcheckdata.h
+++ b/spamcheckdata.h
@@ -1,36 +1,36 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_SPAMCHECKDATA_H__
-#define SF_SPAMCHECKDATA_H__ 1
-
-
-// -- Prototypes
-WCHAR* SCD_DecodeUserName(SPAMCHECKDATA* pscd);
-
-BOOL SCD_IsUserValid(SPAMCHECKDATA* pscd);
-
-WCHAR* SCD_GetContactName(SPAMCHECKDATA* pscd, BOOL bIncludeUniqueID);
-WCHAR* SCD_GetContactCustomDisplayName(SPAMCHECKDATA* pscd);
-WCHAR* SCD_GetContactUniqueStr(SPAMCHECKDATA* pscd, BOOL bUseNick);
-
-
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_SPAMCHECKDATA_H__
+#define SF_SPAMCHECKDATA_H__ 1
+
+
+// -- Prototypes
+WCHAR* SCD_DecodeUserName(SPAMCHECKDATA* pscd);
+
+BOOL SCD_IsUserValid(SPAMCHECKDATA* pscd);
+
+WCHAR* SCD_GetContactName(SPAMCHECKDATA* pscd, BOOL bIncludeUniqueID);
+WCHAR* SCD_GetContactCustomDisplayName(SPAMCHECKDATA* pscd);
+WCHAR* SCD_GetContactUniqueStr(SPAMCHECKDATA* pscd, BOOL bUseNick);
+
+
#endif // SF_SPAMCHECKDATA_H__ \ No newline at end of file
diff --git a/spamdefinitions.c b/spamdefinitions.c
index 5cfe40b..854fc8f 100644
--- a/spamdefinitions.c
+++ b/spamdefinitions.c
@@ -1,850 +1,850 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-
-// -- Defines
-#define CACHE_MODE_DISABLED (-1)
-
-// -- Variables
-STRINGLIST** apslCache = NULL;
-CRITICAL_SECTION csCacheAccess;
-int iCacheMode = CACHE_MODE_DISABLED;
-
-HANDLE hDefinitionPathChange = INVALID_HANDLE_VALUE;
-HANDLE hCustomPathChange = INVALID_HANDLE_VALUE;
-
-// -- Variables: Events/Hooks
-HANDLE hHookCustomFoldersChanged = NULL;
-
-// -- Prototypes
-void ToggleFileUpdateWatcher(BOOL bEnable); // HELPER
-
-
-// -----------------------------------------
-
-
-BOOL GetSpamDefinitionData(STRINGLIST* psl, UINT uSpamDefID)
-{
- if (!psl || (uSpamDefID > SDID_MAX))
- return FALSE;
-
- // Return cached item if available
- if (iCacheMode != CACHE_MODE_DISABLED)
- {
- EnterCriticalSection(&csCacheAccess);
-
- if (apslCache[uSpamDefID])
- if (SLMergeList(psl, apslCache[uSpamDefID]))
- {
- LeaveCriticalSection(&csCacheAccess);
- return TRUE;
- }
-
- LeaveCriticalSection(&csCacheAccess);
- }
-
- {
- WCHAR szFileName[MAX_PATH];
- BOOL bReturn;
-
- switch (uSpamDefID)
- {
- case SDID_CUSTOM_BADWORDS:
- {
- bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-badwords.sfw"));
- break;
- }
-
- case SDID_CUSTOM_GOODWORDS:
- {
- bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-goodwords.sfw"));
- break;
- }
-
- case SDID_CUSTOM_DISLIKEDWORDS:
- {
- bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-dislikedwords.sfw"));
- break;
- }
-
- case SDID_BADWORDS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\BadWords\\*.sfw"));
- break;
- }
-
- case SDID_HOAXTEXTS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\HoaxTexts\\*.sft"));
- break;
- }
-
- case SDID_TEASERTEXTS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\Teasers\\*.sft"));
- break;
- }
-
- case SDID_URLTLDS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\URLs\\*.sfc"));
- break;
- }
-
- case SDID_PHONENUMBERS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\PhoneNumbers\\*.sfc"));
- break;
- }
-
- case SDID_SPECIALCHARS_REPLACE_TEXT:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatText\\*.sfc"));
- break;
- }
-
- case SDID_SPECIALCHARS_REPLACE_NUMBERS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatNumbers\\*.sfc"));
- break;
- }
-
- case SDID_SPECIALCHARS_SEPARATORS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatSeparators\\*.sfc"));
- break;
- }
-
- case SDID_SPAMMERS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\Spammers\\*.sfc"));
- break;
- }
-
- default:
- bReturn = FALSE;
- }
-
- if (!bReturn) return FALSE;
- bReturn = SLLoadFromFile(psl, szFileName);
-
- // Add item to cache
- if (iCacheMode != CACHE_MODE_DISABLED)
- {
- EnterCriticalSection(&csCacheAccess);
-
- // Insert new item
- if (!apslCache[uSpamDefID])
- apslCache[uSpamDefID] = SLNewList();
-
- // Update cache item
- SLClearList(apslCache[uSpamDefID]);
- if (!SLMergeList(apslCache[uSpamDefID], psl)) {
- SLFreeList(apslCache[uSpamDefID]);
- apslCache[uSpamDefID] = NULL;
- }
-
- LeaveCriticalSection(&csCacheAccess);
- }
-
- return bReturn;
- }
-}
-
-
-BOOL SetSpamDefinitionData(STRINGLIST* psl, UINT uSpamDefID, HWND hwndDlg)
-{
- WCHAR szFileName[MAX_PATH];
- BOOL bReturn;
-
- switch (uSpamDefID)
- {
- case SDID_CUSTOM_BADWORDS:
- {
- bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-badwords.sfw"));
- break;
- }
-
- case SDID_CUSTOM_GOODWORDS:
- {
- bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-goodwords.sfw"));
- break;
- }
-
- case SDID_CUSTOM_DISLIKEDWORDS:
- {
- bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-dislikedwords.sfw"));
- break;
- }
-
- // Default data can't be saved
- default:
- bReturn = FALSE;
- }
-
- if (!bReturn) return FALSE;
-
- // Make sure the directory exists
- PPreparePathForWrite(hwndDlg, szFileName, FALSE, TRUE);
-
- // Temporaryly disable file change watcher
- if (iCacheMode != CACHE_MODE_DISABLED)
- iCacheMode++;
-
- bReturn = SLSaveToFile(psl, szFileName);
- OUT("re-enabled ignored event");
-
- // Re-enable file change watcher
- if (iCacheMode != CACHE_MODE_DISABLED)
- iCacheMode--;
-
- // Update item in cache
- if (iCacheMode != CACHE_MODE_DISABLED)
- {
- EnterCriticalSection(&csCacheAccess);
-
- // Insert new item
- if (!apslCache[uSpamDefID])
- apslCache[uSpamDefID] = SLNewList();
-
- // Update cache
- SLClearList(apslCache[uSpamDefID]);
- if (!SLMergeList(apslCache[uSpamDefID], psl)) {
- SLFreeList(apslCache[uSpamDefID]);
- apslCache[uSpamDefID] = NULL;
- }
-
- LeaveCriticalSection(&csCacheAccess);
- }
-
- return bReturn;
-}
-
-
-BOOL IsSpamDefinitionDataPresent(UINT uSpamDefID)
-{
- switch (uSpamDefID)
- {
- // Custom data can also be empty
- case SDID_CUSTOM_BADWORDS:
- {
- WCHAR szFileName[MAX_PATH];
- GetDefinitionsPath(szFileName, TRUE, _T("own-badwords.sfw"));
-
- return PathFileExists(szFileName);
- }
-
- case SDID_CUSTOM_GOODWORDS:
- {
- WCHAR szFileName[MAX_PATH];
- GetDefinitionsPath(szFileName, TRUE, _T("own-goodwords.sfw"));
-
- return PathFileExists(szFileName);
- }
-
- case SDID_CUSTOM_DISLIKEDWORDS:
- {
- WCHAR szFileName[MAX_PATH];
- GetDefinitionsPath(szFileName, TRUE, _T("own-dislikedwords.sfw"));
-
- return PathFileExists(szFileName);
- }
-
- // Default data is not allowed to be empty
- default:
- {
- STRINGLIST* psl = SLNewList();
- BOOL bReturn;
-
- GetSpamDefinitionData(psl, uSpamDefID);
- bReturn = (SLGetItemCount(psl) > 0);
-
- SLFreeList(psl);
- return bReturn;
- }
- }
-}
-
-
-
-// -----------------------------------------
-
-
-BOOL EnumSpamDefinitions(UINT uSpamDefID, BOOL bAtLeastOneTime, SPAMDEFINITIONS_ENUMPROC psdenump, WPARAM wParam, LPARAM lParam)
-{
- BOOL bReturn;
-
- WCHAR szFileName[MAX_PATH];
- WCHAR szFullPath[MAX_PATH];
- WIN32_FIND_DATA wfd;
- HANDLE hFind;
- SYSTEMTIME stDate;
-
- if (!psdenump) return FALSE;
-
- switch (uSpamDefID)
- {
- case SDID_BADWORDS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\BadWords\\*.sfw"));
- break;
- }
-
- case SDID_HOAXTEXTS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\HoaxTexts\\*.sft"));
- break;
- }
-
- case SDID_TEASERTEXTS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\Teasers\\*.sft"));
- break;
- }
-
- case SDID_URLTLDS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\URLs\\*.sfc"));
- break;
- }
-
- case SDID_PHONENUMBERS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\PhoneNumbers\\*.sfc"));
- break;
- }
-
- case SDID_SPECIALCHARS_REPLACE_TEXT:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatText\\*.sfc"));
- break;
- }
-
- case SDID_SPECIALCHARS_REPLACE_NUMBERS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatNumbers\\*.sfc"));
- break;
- }
-
- case SDID_SPECIALCHARS_SEPARATORS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatSeparators\\*.sfc"));
- break;
- }
-
- case SDID_SPAMMERS:
- {
- bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\Spammers\\*.sfc"));
- break;
- }
-
- /*
- case SDID_CUSTOM_BADWORDS:
- case SDID_CUSTOM_GOODWORDS:
- case SDID_CUSTOM_DISLIKEDWORDS:
- */
- default:
- bReturn = FALSE;
- }
-
- if (bReturn)
- {
- bReturn = FALSE;
- hFind = FindFirstFile(szFileName, &wfd);
- PathRemoveFileSpec(szFileName);
- if (hFind != INVALID_HANDLE_VALUE)
- {
- do {
- if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
- continue;
-
- if (FileTimeToSystemTime(&wfd.ftLastWriteTime, &stDate))
- {
- // Construct full path
- StrCpy(szFullPath, szFileName);
- PathAppend(szFullPath, wfd.cFileName);
-
- // Extract name only
- PathRemoveExtension(wfd.cFileName);
-
- // Ignore "Empty" placeholders
- if (StrCmpI(wfd.cFileName, _T("Empty")) == 0)
- continue;
-
- if (psdenump(uSpamDefID, szFullPath, wfd.cFileName, &stDate, wParam, lParam))
- bReturn = TRUE;
- else
- break;
- }
-
- } while (FindNextFile(hFind, &wfd));
-
- FindClose(hFind);
- }
- }
-
- if (bAtLeastOneTime && !bReturn)
- psdenump(uSpamDefID, NULL, NULL, NULL, wParam, lParam);
-
- return bReturn;
-}
-
-// -----------------------------------------
-
-static void ThreadSpamDefinitionCheck(void* arg)
-{
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
-
- // Give miranda some time to load
- SleepEx(30000, TRUE);
-
- OutputDebugString(_T("Spam Filter: Validating Spam Definitions...\r\n"));
-
- if (!Miranda_Terminated())
- {
- BOOL bChecked = FALSE;
- STRINGLIST* pslCheck = SLNewList();
-
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER))
- {
- bChecked = TRUE;
-
- GetSpamDefinitionData(pslCheck, SDID_BADWORDS);
- if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
-
- GetSpamDefinitionData(pslCheck, SDID_TEASERTEXTS);
- if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
-
- GetSpamDefinitionData(pslCheck, SDID_URLTLDS);
- if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
-
- GetSpamDefinitionData(pslCheck, SDID_PHONENUMBERS);
- if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
-
- GetSpamDefinitionData(pslCheck, SDID_SPAMMERS);
- if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
-
- GetSpamDefinitionData(pslCheck, SDID_SPECIALCHARS_REPLACE_TEXT);
- if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
-
- GetSpamDefinitionData(pslCheck, SDID_SPECIALCHARS_REPLACE_NUMBERS);
- if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
-
- GetSpamDefinitionData(pslCheck, SDID_SPECIALCHARS_SEPARATORS);
- if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
- }
-
- if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)DEFAULT_SETTING_DISLIKEDMESSAGEFILTER))
- {
- bChecked = TRUE;
- GetSpamDefinitionData(pslCheck, SDID_HOAXTEXTS);
- if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
- }
-
- // Show warning if no spam definitions are present
- if (bChecked)
- ShowInfoMessage(NIIF_WARNING, TranslateT("Spam Filter Warning"), TranslateT("You did not install any Spam Definition files! Spam Filter can not work as powerful as it could.\r\n\r\nPlease install at least one language of the Spam Definitions."), 0);
-
-
-CheckResultOk:
-
- SLFreeList(pslCheck);
- }
-}
-
-
-// -----------------------------------------
-
-
-static int CustomFoldersChanged(WPARAM wParam, LPARAM lParam)
-{
- if ((hDefinitionPathChange != INVALID_HANDLE_VALUE) || (hCustomPathChange != INVALID_HANDLE_VALUE))
- {
- ToggleFileUpdateWatcher(FALSE);
- ToggleFileUpdateWatcher(TRUE);
- }
-
- return 0;
-}
-
-
-static int InternalServiceWaitOnDataPathChange(WPARAM wParam, LPARAM lParam) // HELPER
-{
- int i;
-
- OutputDebugString(_T("Spam Filter: Clearing Spam Definitions cache (file was modified).\r\n"));
-
- EnterCriticalSection(&csCacheAccess);
- for (i=0; i<=SDID_MAX; i++)
- {
- // Skip custom file cache items when waited separately
- if (i <= SDID_CUSTOMMAX)
- if (ServiceExists("SpamFilter/Wait/CustomPathChange"))
- continue;
-
- // Reset cache item
- SLFreeList(apslCache[i]);
- apslCache[i] = NULL;
- }
- LeaveCriticalSection(&csCacheAccess);
-
- // Refresh windows
- if (IsWindow(hwndSpamDefinitionsInfo))
- PostMessage(hwndSpamDefinitionsInfo, SFM_REFRESH_SPAMDEFINITIONS, (WPARAM)TRUE, (LPARAM)0);
- if (IsWindow(hwndAdvertismentFilter))
- PostMessage(hwndAdvertismentFilter, SFM_RELOAD_DEFAULTBADWORDS, 0, 0);
-
-
- // Register for next notification
- if (!FindNextChangeNotification((HANDLE)wParam))
- ToggleFileUpdateWatcher(FALSE);
-
- return 0;
-}
-
-static int InternalServiceWaitOnCustomPathChange(WPARAM wParam, LPARAM lParam) // HELPER
-{
- int i;
-
- OutputDebugString(_T("Spam Filter: Clearing Custom Definitions cache (file was modified).\r\n"));
-
- // Reset custom cache
- EnterCriticalSection(&csCacheAccess);
-
- for (i=0; i<=SDID_CUSTOMMAX; i++)
- {
- // Reset CUSTOM cache item
- SLFreeList(apslCache[i]);
- apslCache[i] = NULL;
- }
-
- LeaveCriticalSection(&csCacheAccess);
-
- // Register for next notification
- return (FindNextChangeNotification((HANDLE)wParam) ? 0 : 1);
-}
-
-void ToggleFileUpdateWatcher(BOOL bEnable) // HELPER
-{
- static HANDLE hDefinitionPathService;
- static HANDLE hCustomPathService;
-
- // * START WATCHER
- // Get watch handles and tell Miranda to wait for those handles
- if (bEnable)
- {
- WCHAR szDataPath[MAX_PATH];
- WCHAR szCustomPath[MAX_PATH];
- char* pszService;
- BOOL bStarted = FALSE;
-
- const DWORD dwNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE;
-
- // Already started?
- if (hDefinitionPathChange != INVALID_HANDLE_VALUE)
- return;
-
- // Watch the data directory "Spam Filter" for any changes
- GetDefinitionsPath(szDataPath, FALSE, NULL);
- hDefinitionPathChange = FindFirstChangeNotification(szDataPath, TRUE, dwNotifyFilter);
- if (hDefinitionPathChange != INVALID_HANDLE_VALUE)
- {
- pszService = "SpamFilter/Wait/DataPathChange";
- hDefinitionPathService = CreateServiceFunction(pszService, InternalServiceWaitOnDataPathChange);
-
- if (hDefinitionPathService)
- if (CallService(MS_SYSTEM_WAITONHANDLE, (WPARAM)hDefinitionPathChange, (LPARAM)pszService) == 0)
- bStarted = TRUE;
- }
-
- // Watch the profile sub-directory "Spam Filter" (custom files) for any changes
- if (bStarted)
- {
- GetDefinitionsPath(szCustomPath, TRUE, NULL);
- if (StrCmp(szDataPath, szCustomPath) != 0)
- {
- hCustomPathChange = FindFirstChangeNotification(szCustomPath, FALSE, dwNotifyFilter);
- if (hCustomPathChange != INVALID_HANDLE_VALUE)
- {
- pszService = "SpamFilter/Wait/CustomPathChange";
- hCustomPathService = CreateServiceFunction(pszService, InternalServiceWaitOnCustomPathChange);
-
- if (hCustomPathService)
- if (CallService(MS_SYSTEM_WAITONHANDLE, (WPARAM)hCustomPathChange, (LPARAM)pszService) != 0)
- {
- DestroyServiceFunction(hDefinitionPathService);
- hDefinitionPathService = NULL;
- }
- }
- }
-
- if (IsCustomFoldersAvailable())
- hHookCustomFoldersChanged = HookEvent(ME_FOLDERS_PATH_CHANGED, CustomFoldersChanged);
-
- OutputDebugString(_T("Spam Filter: Spam Definitions file watcher started.\r\n"));
- return; // SUCCESS!
- } // else fall through to cleanup
- }
-
- // * STOP WATCHER
- // Stop data path wait
- if (hDefinitionPathChange != INVALID_HANDLE_VALUE)
- {
- CallService(MS_SYSTEM_REMOVEWAIT, (WPARAM)hDefinitionPathChange, 0);
- Sleep(0); // give rest of time slice to miranda (maybe currently waiting) ~10-15ms
- if (hDefinitionPathService)
- DestroyServiceFunction(hDefinitionPathService);
-
- FindCloseChangeNotification(hDefinitionPathChange);
- hDefinitionPathChange = INVALID_HANDLE_VALUE;
-
- // Stop custom path wait
- if (hCustomPathChange != INVALID_HANDLE_VALUE)
- {
- CallService(MS_SYSTEM_REMOVEWAIT, (WPARAM)hCustomPathChange, 0);
- Sleep(0); // give rest of time slice to miranda (maybe currently waiting) ~10-15ms
- if (hCustomPathService)
- DestroyServiceFunction(hCustomPathService);
-
- FindCloseChangeNotification(hCustomPathChange);
- hCustomPathChange = INVALID_HANDLE_VALUE;
- }
-
- // Custom Folders Plugin support
- if (hHookCustomFoldersChanged) UnhookEvent(hHookCustomFoldersChanged);
-
- OutputDebugString(_T("Spam Filter: Spam Definitions file watcher stopped.\r\n"));
- }
-}
-
-/*
-static void ThreadFileUpdateWatcher(void* arg)
-{
- static bThreadRunning = FALSE;
-
- DWORD dwWaitStatus;
- BOOL bResetCache;
- HANDLE ahChangeHandles[2];
-
- // Allow thread only run once at a time
- if (bThreadRunning) return;
- bThreadRunning = TRUE;
-
- OutputDebugString(_T("Spam Filter: Data file watcher started\r\n"));
-
- // Get watch handles
- {
- TCHAR szDataPath[MAX_PATH];
- TCHAR szCustomPath[MAX_PATH];
-
- // FIXME!:
- // Custom Folder Plugin: not reloaded when user changed folder
-
- // Watch the data directory "Spam Filter" for any changes
- GetDefinitionsPath(szDataPath, FALSE, NULL);
- ahChangeHandles[0] = FindFirstChangeNotification(szDataPath, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE);
- if (ahChangeHandles[0] == INVALID_HANDLE_VALUE) {
- ahChangeHandles[1] = INVALID_HANDLE_VALUE;
- goto CleanupChangeHandles;
- }
-
- // Watch the profile sub-directory "Spam Filter" (custom files) for any changes
- GetDefinitionsPath(szCustomPath, TRUE, NULL);
- if (StrCmp(szDataPath, szCustomPath) != 0)
- ahChangeHandles[1] = FindFirstChangeNotification(szCustomPath, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE);
- else
- ahChangeHandles[1] = INVALID_HANDLE_VALUE;
- }
-
- // Change notification is set:
- // Now wait on both notification handles and refresh accordingly.
- while (!Miranda_Terminated() && (iCacheMode != CACHE_MODE_DISABLED))
- {
- if (ahChangeHandles[1] == INVALID_HANDLE_VALUE)
- dwWaitStatus = WaitForSingleObjectEx(ahChangeHandles[0], INFINITE, TRUE);
- else
- dwWaitStatus = WaitForMultipleObjectsEx(ARRAYSIZE(ahChangeHandles), ahChangeHandles, FALSE, INFINITE, TRUE);
-
- bResetCache = (iCacheMode == 0);
-
- if ((iCacheMode == CACHE_MODE_DISABLED) || Miranda_Terminated()) break;
-
- switch (dwWaitStatus)
- {
- // Something in data directory was changed (-> reset data cache)
- case WAIT_OBJECT_0:
- {
- // Check if file watcher is temporaryly disabled
- if (bResetCache)
- {
- int i;
- OutputDebugString(_T("Spam Filter: File change event, Spam Definition file cache reset\r\n"));
-
- EnterCriticalSection(&csCacheAccess);
-
- for (i=0; i<=SDID_MAX; i++)
- {
- if (i <= SDID_CUSTOMMAX)
- if (ahChangeHandles[1] != INVALID_HANDLE_VALUE)
- continue;
-
- // Reset cache item
- SLFreeList(apslCache[i]);
- apslCache[i] = NULL;
- }
-
- LeaveCriticalSection(&csCacheAccess);
-
- if (IsWindow(hwndSpamDefinitionsInfo))
- PostMessage(hwndSpamDefinitionsInfo, SFM_REFRESH_SPAMDEFINITIONS, (WPARAM)TRUE, (LPARAM)0);
-
- if (IsWindow(hwndAdvertismentFilter))
- PostMessage(hwndAdvertismentFilter, SFM_RELOAD_DEFAULTBADWORDS, 0, 0);
- }
-
- if (!FindNextChangeNotification(ahChangeHandles[0]))
- goto CleanupChangeHandles;
- break;
- }
-
- // Custom files changed (-> reset custom cache)
- case WAIT_OBJECT_0+1:
- {
- // Check if file watcher is temporaryly disabled
- if (bResetCache)
- {
- OutputDebugString(_T("Spam Filter: File change event, custom data file cache reset\r\n"));
-
- // Reset custom cache
- EnterCriticalSection(&csCacheAccess);
-
- SLFreeList(apslCache[SDID_CUSTOM_BADWORDS]);
- apslCache[SDID_CUSTOM_BADWORDS] = NULL;
-
- SLFreeList(apslCache[SDID_CUSTOM_GOODWORDS]);
- apslCache[SDID_CUSTOM_GOODWORDS] = NULL;
-
- SLFreeList(apslCache[SDID_CUSTOM_DISLIKEDWORDS]);
- apslCache[SDID_CUSTOM_DISLIKEDWORDS] = NULL;
-
- LeaveCriticalSection(&csCacheAccess);
- }
-
- // Register for next notification
- FindNextChangeNotification(ahChangeHandles[1]);
- break;
- }
- }
- }
-
-
-CleanupChangeHandles:
-
- bThreadRunning = FALSE;
-
- // Close change notification handles
- if (ahChangeHandles[0] != INVALID_HANDLE_VALUE)
- FindCloseChangeNotification(ahChangeHandles[0]);
-
- if (ahChangeHandles[1] != INVALID_HANDLE_VALUE)
- FindCloseChangeNotification(ahChangeHandles[1]);
-
- OutputDebugString(_T("Spam Filter: Data file watcher closed\r\n"));
-}
-*/
-
-
-// -----------------------------------------
-
-
-void ToggleSpamDefinitionsCache(BOOL bEnable)
-{
- if ((iCacheMode != CACHE_MODE_DISABLED) == bEnable)
- return;
-
- if (bEnable)
- {
- // Show warning if no spam definitions are present
- if (bEnable)
- forkthread(ThreadSpamDefinitionCheck, 0, NULL);
-
- OutputDebugString(_T("Spam Filter: Starting Spam Definitions cache...\r\n"));
-
- apslCache = (STRINGLIST**)mir_alloc(sizeof(STRINGLIST*) * (SDID_MAX+1));
- if (apslCache)
- {
- ZeroMemory(apslCache, sizeof(STRINGLIST*) * (SDID_MAX+1));
- InitializeCriticalSection(&csCacheAccess);
- iCacheMode = 0;
-
- // Start file change watcher
- // Replaced with Miranda's wait service
- //forkthread(ThreadFileUpdateWatcher, 0, NULL);
- ToggleFileUpdateWatcher(TRUE);
- }
-
- } else {
-
- int i;
-
- ToggleFileUpdateWatcher(FALSE);
-
- // Clear cache
- iCacheMode = CACHE_MODE_DISABLED;
-
- // Release memory
- EnterCriticalSection(&csCacheAccess);
- for (i=0; i<=SDID_MAX; i++) {
- SLFreeList(apslCache[i]);
- apslCache[i] = NULL;
- }
- LeaveCriticalSection(&csCacheAccess);
-
- mir_free(apslCache);
- apslCache = NULL;
- DeleteCriticalSection(&csCacheAccess);
-
- OutputDebugString(_T("Spam Filter: Spam Definitions cache stopped.\r\n"));
- }
-}
-
-
-// -----------------------------------------
-
-
-void InitSpamDefinitions(void)
-{
- // Only start cache if Disliked Messages or Advertisment Filter is enabled (saving memory)
- if ( DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER) ||
- DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)DEFAULT_SETTING_DISLIKEDMESSAGEFILTER) )
- {
- ToggleSpamDefinitionsCache(TRUE);
- }
-}
-
-void UninitSpamDefinitions(void)
-{
- ToggleSpamDefinitionsCache(FALSE);
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+
+// -- Defines
+#define CACHE_MODE_DISABLED (-1)
+
+// -- Variables
+STRINGLIST** apslCache = NULL;
+CRITICAL_SECTION csCacheAccess;
+int iCacheMode = CACHE_MODE_DISABLED;
+
+HANDLE hDefinitionPathChange = INVALID_HANDLE_VALUE;
+HANDLE hCustomPathChange = INVALID_HANDLE_VALUE;
+
+// -- Variables: Events/Hooks
+HANDLE hHookCustomFoldersChanged = NULL;
+
+// -- Prototypes
+void ToggleFileUpdateWatcher(BOOL bEnable); // HELPER
+
+
+// -----------------------------------------
+
+
+BOOL GetSpamDefinitionData(STRINGLIST* psl, UINT uSpamDefID)
+{
+ if (!psl || (uSpamDefID > SDID_MAX))
+ return FALSE;
+
+ // Return cached item if available
+ if (iCacheMode != CACHE_MODE_DISABLED)
+ {
+ EnterCriticalSection(&csCacheAccess);
+
+ if (apslCache[uSpamDefID])
+ if (SLMergeList(psl, apslCache[uSpamDefID]))
+ {
+ LeaveCriticalSection(&csCacheAccess);
+ return TRUE;
+ }
+
+ LeaveCriticalSection(&csCacheAccess);
+ }
+
+ {
+ WCHAR szFileName[MAX_PATH];
+ BOOL bReturn;
+
+ switch (uSpamDefID)
+ {
+ case SDID_CUSTOM_BADWORDS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-badwords.sfw"));
+ break;
+ }
+
+ case SDID_CUSTOM_GOODWORDS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-goodwords.sfw"));
+ break;
+ }
+
+ case SDID_CUSTOM_DISLIKEDWORDS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-dislikedwords.sfw"));
+ break;
+ }
+
+ case SDID_BADWORDS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\BadWords\\*.sfw"));
+ break;
+ }
+
+ case SDID_HOAXTEXTS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\HoaxTexts\\*.sft"));
+ break;
+ }
+
+ case SDID_TEASERTEXTS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\Teasers\\*.sft"));
+ break;
+ }
+
+ case SDID_URLTLDS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\URLs\\*.sfc"));
+ break;
+ }
+
+ case SDID_PHONENUMBERS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\PhoneNumbers\\*.sfc"));
+ break;
+ }
+
+ case SDID_SPECIALCHARS_REPLACE_TEXT:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatText\\*.sfc"));
+ break;
+ }
+
+ case SDID_SPECIALCHARS_REPLACE_NUMBERS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatNumbers\\*.sfc"));
+ break;
+ }
+
+ case SDID_SPECIALCHARS_SEPARATORS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatSeparators\\*.sfc"));
+ break;
+ }
+
+ case SDID_SPAMMERS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\Spammers\\*.sfc"));
+ break;
+ }
+
+ default:
+ bReturn = FALSE;
+ }
+
+ if (!bReturn) return FALSE;
+ bReturn = SLLoadFromFile(psl, szFileName);
+
+ // Add item to cache
+ if (iCacheMode != CACHE_MODE_DISABLED)
+ {
+ EnterCriticalSection(&csCacheAccess);
+
+ // Insert new item
+ if (!apslCache[uSpamDefID])
+ apslCache[uSpamDefID] = SLNewList();
+
+ // Update cache item
+ SLClearList(apslCache[uSpamDefID]);
+ if (!SLMergeList(apslCache[uSpamDefID], psl)) {
+ SLFreeList(apslCache[uSpamDefID]);
+ apslCache[uSpamDefID] = NULL;
+ }
+
+ LeaveCriticalSection(&csCacheAccess);
+ }
+
+ return bReturn;
+ }
+}
+
+
+BOOL SetSpamDefinitionData(STRINGLIST* psl, UINT uSpamDefID, HWND hwndDlg)
+{
+ WCHAR szFileName[MAX_PATH];
+ BOOL bReturn;
+
+ switch (uSpamDefID)
+ {
+ case SDID_CUSTOM_BADWORDS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-badwords.sfw"));
+ break;
+ }
+
+ case SDID_CUSTOM_GOODWORDS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-goodwords.sfw"));
+ break;
+ }
+
+ case SDID_CUSTOM_DISLIKEDWORDS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, TRUE, _T("own-dislikedwords.sfw"));
+ break;
+ }
+
+ // Default data can't be saved
+ default:
+ bReturn = FALSE;
+ }
+
+ if (!bReturn) return FALSE;
+
+ // Make sure the directory exists
+ PPreparePathForWrite(hwndDlg, szFileName, FALSE, TRUE);
+
+ // Temporaryly disable file change watcher
+ if (iCacheMode != CACHE_MODE_DISABLED)
+ iCacheMode++;
+
+ bReturn = SLSaveToFile(psl, szFileName);
+ OUT("re-enabled ignored event");
+
+ // Re-enable file change watcher
+ if (iCacheMode != CACHE_MODE_DISABLED)
+ iCacheMode--;
+
+ // Update item in cache
+ if (iCacheMode != CACHE_MODE_DISABLED)
+ {
+ EnterCriticalSection(&csCacheAccess);
+
+ // Insert new item
+ if (!apslCache[uSpamDefID])
+ apslCache[uSpamDefID] = SLNewList();
+
+ // Update cache
+ SLClearList(apslCache[uSpamDefID]);
+ if (!SLMergeList(apslCache[uSpamDefID], psl)) {
+ SLFreeList(apslCache[uSpamDefID]);
+ apslCache[uSpamDefID] = NULL;
+ }
+
+ LeaveCriticalSection(&csCacheAccess);
+ }
+
+ return bReturn;
+}
+
+
+BOOL IsSpamDefinitionDataPresent(UINT uSpamDefID)
+{
+ switch (uSpamDefID)
+ {
+ // Custom data can also be empty
+ case SDID_CUSTOM_BADWORDS:
+ {
+ WCHAR szFileName[MAX_PATH];
+ GetDefinitionsPath(szFileName, TRUE, _T("own-badwords.sfw"));
+
+ return PathFileExists(szFileName);
+ }
+
+ case SDID_CUSTOM_GOODWORDS:
+ {
+ WCHAR szFileName[MAX_PATH];
+ GetDefinitionsPath(szFileName, TRUE, _T("own-goodwords.sfw"));
+
+ return PathFileExists(szFileName);
+ }
+
+ case SDID_CUSTOM_DISLIKEDWORDS:
+ {
+ WCHAR szFileName[MAX_PATH];
+ GetDefinitionsPath(szFileName, TRUE, _T("own-dislikedwords.sfw"));
+
+ return PathFileExists(szFileName);
+ }
+
+ // Default data is not allowed to be empty
+ default:
+ {
+ STRINGLIST* psl = SLNewList();
+ BOOL bReturn;
+
+ GetSpamDefinitionData(psl, uSpamDefID);
+ bReturn = (SLGetItemCount(psl) > 0);
+
+ SLFreeList(psl);
+ return bReturn;
+ }
+ }
+}
+
+
+
+// -----------------------------------------
+
+
+BOOL EnumSpamDefinitions(UINT uSpamDefID, BOOL bAtLeastOneTime, SPAMDEFINITIONS_ENUMPROC psdenump, WPARAM wParam, LPARAM lParam)
+{
+ BOOL bReturn;
+
+ WCHAR szFileName[MAX_PATH];
+ WCHAR szFullPath[MAX_PATH];
+ WIN32_FIND_DATA wfd;
+ HANDLE hFind;
+ SYSTEMTIME stDate;
+
+ if (!psdenump) return FALSE;
+
+ switch (uSpamDefID)
+ {
+ case SDID_BADWORDS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\BadWords\\*.sfw"));
+ break;
+ }
+
+ case SDID_HOAXTEXTS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\HoaxTexts\\*.sft"));
+ break;
+ }
+
+ case SDID_TEASERTEXTS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\Teasers\\*.sft"));
+ break;
+ }
+
+ case SDID_URLTLDS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\URLs\\*.sfc"));
+ break;
+ }
+
+ case SDID_PHONENUMBERS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\PhoneNumbers\\*.sfc"));
+ break;
+ }
+
+ case SDID_SPECIALCHARS_REPLACE_TEXT:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatText\\*.sfc"));
+ break;
+ }
+
+ case SDID_SPECIALCHARS_REPLACE_NUMBERS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatNumbers\\*.sfc"));
+ break;
+ }
+
+ case SDID_SPECIALCHARS_SEPARATORS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\FormatSeparators\\*.sfc"));
+ break;
+ }
+
+ case SDID_SPAMMERS:
+ {
+ bReturn = GetDefinitionsPath(szFileName, FALSE, _T("\\Spammers\\*.sfc"));
+ break;
+ }
+
+ /*
+ case SDID_CUSTOM_BADWORDS:
+ case SDID_CUSTOM_GOODWORDS:
+ case SDID_CUSTOM_DISLIKEDWORDS:
+ */
+ default:
+ bReturn = FALSE;
+ }
+
+ if (bReturn)
+ {
+ bReturn = FALSE;
+ hFind = FindFirstFile(szFileName, &wfd);
+ PathRemoveFileSpec(szFileName);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ do {
+ if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ if (FileTimeToSystemTime(&wfd.ftLastWriteTime, &stDate))
+ {
+ // Construct full path
+ StrCpy(szFullPath, szFileName);
+ PathAppend(szFullPath, wfd.cFileName);
+
+ // Extract name only
+ PathRemoveExtension(wfd.cFileName);
+
+ // Ignore "Empty" placeholders
+ if (StrCmpI(wfd.cFileName, _T("Empty")) == 0)
+ continue;
+
+ if (psdenump(uSpamDefID, szFullPath, wfd.cFileName, &stDate, wParam, lParam))
+ bReturn = TRUE;
+ else
+ break;
+ }
+
+ } while (FindNextFile(hFind, &wfd));
+
+ FindClose(hFind);
+ }
+ }
+
+ if (bAtLeastOneTime && !bReturn)
+ psdenump(uSpamDefID, NULL, NULL, NULL, wParam, lParam);
+
+ return bReturn;
+}
+
+// -----------------------------------------
+
+static void ThreadSpamDefinitionCheck(void* arg)
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
+
+ // Give miranda some time to load
+ SleepEx(30000, TRUE);
+
+ OutputDebugString(_T("Spam Filter: Validating Spam Definitions...\r\n"));
+
+ if (!Miranda_Terminated())
+ {
+ BOOL bChecked = FALSE;
+ STRINGLIST* pslCheck = SLNewList();
+
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER))
+ {
+ bChecked = TRUE;
+
+ GetSpamDefinitionData(pslCheck, SDID_BADWORDS);
+ if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
+
+ GetSpamDefinitionData(pslCheck, SDID_TEASERTEXTS);
+ if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
+
+ GetSpamDefinitionData(pslCheck, SDID_URLTLDS);
+ if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
+
+ GetSpamDefinitionData(pslCheck, SDID_PHONENUMBERS);
+ if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
+
+ GetSpamDefinitionData(pslCheck, SDID_SPAMMERS);
+ if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
+
+ GetSpamDefinitionData(pslCheck, SDID_SPECIALCHARS_REPLACE_TEXT);
+ if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
+
+ GetSpamDefinitionData(pslCheck, SDID_SPECIALCHARS_REPLACE_NUMBERS);
+ if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
+
+ GetSpamDefinitionData(pslCheck, SDID_SPECIALCHARS_SEPARATORS);
+ if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
+ }
+
+ if (DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)DEFAULT_SETTING_DISLIKEDMESSAGEFILTER))
+ {
+ bChecked = TRUE;
+ GetSpamDefinitionData(pslCheck, SDID_HOAXTEXTS);
+ if (SLGetItemCount(pslCheck) > 0) goto CheckResultOk;
+ }
+
+ // Show warning if no spam definitions are present
+ if (bChecked)
+ ShowInfoMessage(NIIF_WARNING, TranslateT("Spam Filter Warning"), TranslateT("You did not install any Spam Definition files! Spam Filter can not work as powerful as it could.\r\n\r\nPlease install at least one language of the Spam Definitions."), 0);
+
+
+CheckResultOk:
+
+ SLFreeList(pslCheck);
+ }
+}
+
+
+// -----------------------------------------
+
+
+static int CustomFoldersChanged(WPARAM wParam, LPARAM lParam)
+{
+ if ((hDefinitionPathChange != INVALID_HANDLE_VALUE) || (hCustomPathChange != INVALID_HANDLE_VALUE))
+ {
+ ToggleFileUpdateWatcher(FALSE);
+ ToggleFileUpdateWatcher(TRUE);
+ }
+
+ return 0;
+}
+
+
+static int InternalServiceWaitOnDataPathChange(WPARAM wParam, LPARAM lParam) // HELPER
+{
+ int i;
+
+ OutputDebugString(_T("Spam Filter: Clearing Spam Definitions cache (file was modified).\r\n"));
+
+ EnterCriticalSection(&csCacheAccess);
+ for (i=0; i<=SDID_MAX; i++)
+ {
+ // Skip custom file cache items when waited separately
+ if (i <= SDID_CUSTOMMAX)
+ if (ServiceExists("SpamFilter/Wait/CustomPathChange"))
+ continue;
+
+ // Reset cache item
+ SLFreeList(apslCache[i]);
+ apslCache[i] = NULL;
+ }
+ LeaveCriticalSection(&csCacheAccess);
+
+ // Refresh windows
+ if (IsWindow(hwndSpamDefinitionsInfo))
+ PostMessage(hwndSpamDefinitionsInfo, SFM_REFRESH_SPAMDEFINITIONS, (WPARAM)TRUE, (LPARAM)0);
+ if (IsWindow(hwndAdvertismentFilter))
+ PostMessage(hwndAdvertismentFilter, SFM_RELOAD_DEFAULTBADWORDS, 0, 0);
+
+
+ // Register for next notification
+ if (!FindNextChangeNotification((HANDLE)wParam))
+ ToggleFileUpdateWatcher(FALSE);
+
+ return 0;
+}
+
+static int InternalServiceWaitOnCustomPathChange(WPARAM wParam, LPARAM lParam) // HELPER
+{
+ int i;
+
+ OutputDebugString(_T("Spam Filter: Clearing Custom Definitions cache (file was modified).\r\n"));
+
+ // Reset custom cache
+ EnterCriticalSection(&csCacheAccess);
+
+ for (i=0; i<=SDID_CUSTOMMAX; i++)
+ {
+ // Reset CUSTOM cache item
+ SLFreeList(apslCache[i]);
+ apslCache[i] = NULL;
+ }
+
+ LeaveCriticalSection(&csCacheAccess);
+
+ // Register for next notification
+ return (FindNextChangeNotification((HANDLE)wParam) ? 0 : 1);
+}
+
+void ToggleFileUpdateWatcher(BOOL bEnable) // HELPER
+{
+ static HANDLE hDefinitionPathService;
+ static HANDLE hCustomPathService;
+
+ // * START WATCHER
+ // Get watch handles and tell Miranda to wait for those handles
+ if (bEnable)
+ {
+ WCHAR szDataPath[MAX_PATH];
+ WCHAR szCustomPath[MAX_PATH];
+ char* pszService;
+ BOOL bStarted = FALSE;
+
+ const DWORD dwNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE;
+
+ // Already started?
+ if (hDefinitionPathChange != INVALID_HANDLE_VALUE)
+ return;
+
+ // Watch the data directory "Spam Filter" for any changes
+ GetDefinitionsPath(szDataPath, FALSE, NULL);
+ hDefinitionPathChange = FindFirstChangeNotification(szDataPath, TRUE, dwNotifyFilter);
+ if (hDefinitionPathChange != INVALID_HANDLE_VALUE)
+ {
+ pszService = "SpamFilter/Wait/DataPathChange";
+ hDefinitionPathService = CreateServiceFunction(pszService, InternalServiceWaitOnDataPathChange);
+
+ if (hDefinitionPathService)
+ if (CallService(MS_SYSTEM_WAITONHANDLE, (WPARAM)hDefinitionPathChange, (LPARAM)pszService) == 0)
+ bStarted = TRUE;
+ }
+
+ // Watch the profile sub-directory "Spam Filter" (custom files) for any changes
+ if (bStarted)
+ {
+ GetDefinitionsPath(szCustomPath, TRUE, NULL);
+ if (StrCmp(szDataPath, szCustomPath) != 0)
+ {
+ hCustomPathChange = FindFirstChangeNotification(szCustomPath, FALSE, dwNotifyFilter);
+ if (hCustomPathChange != INVALID_HANDLE_VALUE)
+ {
+ pszService = "SpamFilter/Wait/CustomPathChange";
+ hCustomPathService = CreateServiceFunction(pszService, InternalServiceWaitOnCustomPathChange);
+
+ if (hCustomPathService)
+ if (CallService(MS_SYSTEM_WAITONHANDLE, (WPARAM)hCustomPathChange, (LPARAM)pszService) != 0)
+ {
+ DestroyServiceFunction(hDefinitionPathService);
+ hDefinitionPathService = NULL;
+ }
+ }
+ }
+
+ if (IsCustomFoldersAvailable())
+ hHookCustomFoldersChanged = HookEvent(ME_FOLDERS_PATH_CHANGED, CustomFoldersChanged);
+
+ OutputDebugString(_T("Spam Filter: Spam Definitions file watcher started.\r\n"));
+ return; // SUCCESS!
+ } // else fall through to cleanup
+ }
+
+ // * STOP WATCHER
+ // Stop data path wait
+ if (hDefinitionPathChange != INVALID_HANDLE_VALUE)
+ {
+ CallService(MS_SYSTEM_REMOVEWAIT, (WPARAM)hDefinitionPathChange, 0);
+ Sleep(0); // give rest of time slice to miranda (maybe currently waiting) ~10-15ms
+ if (hDefinitionPathService)
+ DestroyServiceFunction(hDefinitionPathService);
+
+ FindCloseChangeNotification(hDefinitionPathChange);
+ hDefinitionPathChange = INVALID_HANDLE_VALUE;
+
+ // Stop custom path wait
+ if (hCustomPathChange != INVALID_HANDLE_VALUE)
+ {
+ CallService(MS_SYSTEM_REMOVEWAIT, (WPARAM)hCustomPathChange, 0);
+ Sleep(0); // give rest of time slice to miranda (maybe currently waiting) ~10-15ms
+ if (hCustomPathService)
+ DestroyServiceFunction(hCustomPathService);
+
+ FindCloseChangeNotification(hCustomPathChange);
+ hCustomPathChange = INVALID_HANDLE_VALUE;
+ }
+
+ // Custom Folders Plugin support
+ if (hHookCustomFoldersChanged) UnhookEvent(hHookCustomFoldersChanged);
+
+ OutputDebugString(_T("Spam Filter: Spam Definitions file watcher stopped.\r\n"));
+ }
+}
+
+/*
+static void ThreadFileUpdateWatcher(void* arg)
+{
+ static bThreadRunning = FALSE;
+
+ DWORD dwWaitStatus;
+ BOOL bResetCache;
+ HANDLE ahChangeHandles[2];
+
+ // Allow thread only run once at a time
+ if (bThreadRunning) return;
+ bThreadRunning = TRUE;
+
+ OutputDebugString(_T("Spam Filter: Data file watcher started\r\n"));
+
+ // Get watch handles
+ {
+ TCHAR szDataPath[MAX_PATH];
+ TCHAR szCustomPath[MAX_PATH];
+
+ // FIXME!:
+ // Custom Folder Plugin: not reloaded when user changed folder
+
+ // Watch the data directory "Spam Filter" for any changes
+ GetDefinitionsPath(szDataPath, FALSE, NULL);
+ ahChangeHandles[0] = FindFirstChangeNotification(szDataPath, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE);
+ if (ahChangeHandles[0] == INVALID_HANDLE_VALUE) {
+ ahChangeHandles[1] = INVALID_HANDLE_VALUE;
+ goto CleanupChangeHandles;
+ }
+
+ // Watch the profile sub-directory "Spam Filter" (custom files) for any changes
+ GetDefinitionsPath(szCustomPath, TRUE, NULL);
+ if (StrCmp(szDataPath, szCustomPath) != 0)
+ ahChangeHandles[1] = FindFirstChangeNotification(szCustomPath, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE);
+ else
+ ahChangeHandles[1] = INVALID_HANDLE_VALUE;
+ }
+
+ // Change notification is set:
+ // Now wait on both notification handles and refresh accordingly.
+ while (!Miranda_Terminated() && (iCacheMode != CACHE_MODE_DISABLED))
+ {
+ if (ahChangeHandles[1] == INVALID_HANDLE_VALUE)
+ dwWaitStatus = WaitForSingleObjectEx(ahChangeHandles[0], INFINITE, TRUE);
+ else
+ dwWaitStatus = WaitForMultipleObjectsEx(ARRAYSIZE(ahChangeHandles), ahChangeHandles, FALSE, INFINITE, TRUE);
+
+ bResetCache = (iCacheMode == 0);
+
+ if ((iCacheMode == CACHE_MODE_DISABLED) || Miranda_Terminated()) break;
+
+ switch (dwWaitStatus)
+ {
+ // Something in data directory was changed (-> reset data cache)
+ case WAIT_OBJECT_0:
+ {
+ // Check if file watcher is temporaryly disabled
+ if (bResetCache)
+ {
+ int i;
+ OutputDebugString(_T("Spam Filter: File change event, Spam Definition file cache reset\r\n"));
+
+ EnterCriticalSection(&csCacheAccess);
+
+ for (i=0; i<=SDID_MAX; i++)
+ {
+ if (i <= SDID_CUSTOMMAX)
+ if (ahChangeHandles[1] != INVALID_HANDLE_VALUE)
+ continue;
+
+ // Reset cache item
+ SLFreeList(apslCache[i]);
+ apslCache[i] = NULL;
+ }
+
+ LeaveCriticalSection(&csCacheAccess);
+
+ if (IsWindow(hwndSpamDefinitionsInfo))
+ PostMessage(hwndSpamDefinitionsInfo, SFM_REFRESH_SPAMDEFINITIONS, (WPARAM)TRUE, (LPARAM)0);
+
+ if (IsWindow(hwndAdvertismentFilter))
+ PostMessage(hwndAdvertismentFilter, SFM_RELOAD_DEFAULTBADWORDS, 0, 0);
+ }
+
+ if (!FindNextChangeNotification(ahChangeHandles[0]))
+ goto CleanupChangeHandles;
+ break;
+ }
+
+ // Custom files changed (-> reset custom cache)
+ case WAIT_OBJECT_0+1:
+ {
+ // Check if file watcher is temporaryly disabled
+ if (bResetCache)
+ {
+ OutputDebugString(_T("Spam Filter: File change event, custom data file cache reset\r\n"));
+
+ // Reset custom cache
+ EnterCriticalSection(&csCacheAccess);
+
+ SLFreeList(apslCache[SDID_CUSTOM_BADWORDS]);
+ apslCache[SDID_CUSTOM_BADWORDS] = NULL;
+
+ SLFreeList(apslCache[SDID_CUSTOM_GOODWORDS]);
+ apslCache[SDID_CUSTOM_GOODWORDS] = NULL;
+
+ SLFreeList(apslCache[SDID_CUSTOM_DISLIKEDWORDS]);
+ apslCache[SDID_CUSTOM_DISLIKEDWORDS] = NULL;
+
+ LeaveCriticalSection(&csCacheAccess);
+ }
+
+ // Register for next notification
+ FindNextChangeNotification(ahChangeHandles[1]);
+ break;
+ }
+ }
+ }
+
+
+CleanupChangeHandles:
+
+ bThreadRunning = FALSE;
+
+ // Close change notification handles
+ if (ahChangeHandles[0] != INVALID_HANDLE_VALUE)
+ FindCloseChangeNotification(ahChangeHandles[0]);
+
+ if (ahChangeHandles[1] != INVALID_HANDLE_VALUE)
+ FindCloseChangeNotification(ahChangeHandles[1]);
+
+ OutputDebugString(_T("Spam Filter: Data file watcher closed\r\n"));
+}
+*/
+
+
+// -----------------------------------------
+
+
+void ToggleSpamDefinitionsCache(BOOL bEnable)
+{
+ if ((iCacheMode != CACHE_MODE_DISABLED) == bEnable)
+ return;
+
+ if (bEnable)
+ {
+ // Show warning if no spam definitions are present
+ if (bEnable)
+ forkthread(ThreadSpamDefinitionCheck, 0, NULL);
+
+ OutputDebugString(_T("Spam Filter: Starting Spam Definitions cache...\r\n"));
+
+ apslCache = (STRINGLIST**)mir_alloc(sizeof(STRINGLIST*) * (SDID_MAX+1));
+ if (apslCache)
+ {
+ ZeroMemory(apslCache, sizeof(STRINGLIST*) * (SDID_MAX+1));
+ InitializeCriticalSection(&csCacheAccess);
+ iCacheMode = 0;
+
+ // Start file change watcher
+ // Replaced with Miranda's wait service
+ //forkthread(ThreadFileUpdateWatcher, 0, NULL);
+ ToggleFileUpdateWatcher(TRUE);
+ }
+
+ } else {
+
+ int i;
+
+ ToggleFileUpdateWatcher(FALSE);
+
+ // Clear cache
+ iCacheMode = CACHE_MODE_DISABLED;
+
+ // Release memory
+ EnterCriticalSection(&csCacheAccess);
+ for (i=0; i<=SDID_MAX; i++) {
+ SLFreeList(apslCache[i]);
+ apslCache[i] = NULL;
+ }
+ LeaveCriticalSection(&csCacheAccess);
+
+ mir_free(apslCache);
+ apslCache = NULL;
+ DeleteCriticalSection(&csCacheAccess);
+
+ OutputDebugString(_T("Spam Filter: Spam Definitions cache stopped.\r\n"));
+ }
+}
+
+
+// -----------------------------------------
+
+
+void InitSpamDefinitions(void)
+{
+ // Only start cache if Disliked Messages or Advertisment Filter is enabled (saving memory)
+ if ( DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_ADVERTISMENTFILTER, (BYTE)DEFAULT_SETTING_ADVERTISMENTFILTER) ||
+ DBGetContactSettingByte(NULL, DB_MODULE_NAME, DB_SETTING_DISLIKEDMESSAGEFILTER, (BYTE)DEFAULT_SETTING_DISLIKEDMESSAGEFILTER) )
+ {
+ ToggleSpamDefinitionsCache(TRUE);
+ }
+}
+
+void UninitSpamDefinitions(void)
+{
+ ToggleSpamDefinitionsCache(FALSE);
} \ No newline at end of file
diff --git a/spamdefinitions.h b/spamdefinitions.h
index 00b2bb0..a030bad 100644
--- a/spamdefinitions.h
+++ b/spamdefinitions.h
@@ -1,59 +1,59 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_SPAMDEFINITIONS_H__
-#define SF_SPAMDEFINITIONS_H__ 1
-
-
-// -- Defines
-#define SDID_CUSTOM_BADWORDS 0
-#define SDID_CUSTOM_GOODWORDS 1
-#define SDID_CUSTOM_DISLIKEDWORDS 2
-#define SDID_BADWORDS 3
-#define SDID_HOAXTEXTS 4
-#define SDID_TEASERTEXTS 5
-#define SDID_URLTLDS 6
-#define SDID_PHONENUMBERS 7
-#define SDID_SPECIALCHARS_REPLACE_TEXT 8
-#define SDID_SPECIALCHARS_REPLACE_NUMBERS 9
-#define SDID_SPECIALCHARS_SEPARATORS 10
-#define SDID_SPAMMERS 11
-
-#define SDID_CUSTOMMAX 2
-#define SDID_MAX 11
-
-
-// -- Callbacks
-typedef BOOL (CALLBACK* SPAMDEFINITIONS_ENUMPROC)(UINT uSpamDefID, WCHAR* pszFilePath, WCHAR* pszName, SYSTEMTIME* pstDate, WPARAM wParam, LPARAM lParam);
-
-// -- Prototypes
-BOOL GetSpamDefinitionData(STRINGLIST* psl, UINT uSpamDefID);
-BOOL SetSpamDefinitionData(STRINGLIST* psl, UINT uSpamDefID, HWND hwndDlg);
-
-BOOL IsSpamDefinitionDataPresent(UINT uSpamDefID);
-BOOL EnumSpamDefinitions(UINT uSpamDefID, BOOL AtLeastOneTime, SPAMDEFINITIONS_ENUMPROC psdenump, WPARAM wParam, LPARAM lParam);
-
-void ToggleSpamDefinitionsCache(BOOL bEnable);
-
-void InitSpamDefinitions(void);
-void UninitSpamDefinitions(void);
-
-#endif // SF_SPAMDEFINITIONS_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_SPAMDEFINITIONS_H__
+#define SF_SPAMDEFINITIONS_H__ 1
+
+
+// -- Defines
+#define SDID_CUSTOM_BADWORDS 0
+#define SDID_CUSTOM_GOODWORDS 1
+#define SDID_CUSTOM_DISLIKEDWORDS 2
+#define SDID_BADWORDS 3
+#define SDID_HOAXTEXTS 4
+#define SDID_TEASERTEXTS 5
+#define SDID_URLTLDS 6
+#define SDID_PHONENUMBERS 7
+#define SDID_SPECIALCHARS_REPLACE_TEXT 8
+#define SDID_SPECIALCHARS_REPLACE_NUMBERS 9
+#define SDID_SPECIALCHARS_SEPARATORS 10
+#define SDID_SPAMMERS 11
+
+#define SDID_CUSTOMMAX 2
+#define SDID_MAX 11
+
+
+// -- Callbacks
+typedef BOOL (CALLBACK* SPAMDEFINITIONS_ENUMPROC)(UINT uSpamDefID, WCHAR* pszFilePath, WCHAR* pszName, SYSTEMTIME* pstDate, WPARAM wParam, LPARAM lParam);
+
+// -- Prototypes
+BOOL GetSpamDefinitionData(STRINGLIST* psl, UINT uSpamDefID);
+BOOL SetSpamDefinitionData(STRINGLIST* psl, UINT uSpamDefID, HWND hwndDlg);
+
+BOOL IsSpamDefinitionDataPresent(UINT uSpamDefID);
+BOOL EnumSpamDefinitions(UINT uSpamDefID, BOOL AtLeastOneTime, SPAMDEFINITIONS_ENUMPROC psdenump, WPARAM wParam, LPARAM lParam);
+
+void ToggleSpamDefinitionsCache(BOOL bEnable);
+
+void InitSpamDefinitions(void);
+void UninitSpamDefinitions(void);
+
+#endif // SF_SPAMDEFINITIONS_H__
diff --git a/string.c b/string.c
index 2660b77..fc9695e 100644
--- a/string.c
+++ b/string.c
@@ -1,310 +1,310 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-
-// -----------------------------------------
-
-
-/*
-int SubStringExistsInStringCount(const TCHAR* pszStr, const TCHAR* pszSubString, BOOL bCaseSensitive)
-{
- int iSubStrLen;
- char* pszOcc;
- int iReturn;
-
- if (!pszSubString) return 0;
-
- pszOcc = pszStr;
- iCount = 0;
- iSubStrLen = lstrlen(pszSubString);
- while ((pszOcc = bCaseSensitive?StrStr(pszOcc, pszOldSubStr):StrStrI(pszOcc, pszOldSubStr)) != NULL)
- {
- iCount++;
- pszOcc = pszOcc+iSubStrLen;
- }
-
- return iCount;
-}
-*/
-
-
-WCHAR* RemoveSubStr(WCHAR* pszStr, int iPos, int iSubStrLen)
-{
- if (!pszStr) return NULL;
- if ((iPos > 0) && (iSubStrLen > 0) && (iPos < lstrlen(pszStr)))
- MoveMemory(&pszStr[iPos], &pszStr[iPos+iSubStrLen], (lstrlen(&pszStr[iPos])+1)*sizeof(WCHAR));
- return pszStr;
-}
-
-/*
-BOOL HasSubStr(const TCHAR* pszStr, int iPos, const TCHAR* pszSubStr);
-{
- TCHAR* pszPos;
-
- if (!pszSubStr || !pszStr || (iPos >= lstrlen(pszStr))) return FALSE;
-
- // Test for suffix
- if (iPos < 0)
- return ((lstrlen(pszStr) <= lstrlen(pszSubStr)) || (StrCmp(pszStr+lstrlen(pszStr)-lstrlen(pszSubStr), pszSubStr) != 0));
- else
- return (StrCmpN(&pszStr[iPos], pszSubStr, lstrlen(pszSubStr)) != 0))
-}
-*/
-
-WCHAR* InsertSubStr(WCHAR* pszStr, int cchMaxSize, int iPos, const WCHAR* pszSubStr)
-{
- int iSubStrLen;
-
- if (!pszStr) return NULL;
- if (!pszSubStr || (iPos < 0) || (iPos >= lstrlen(pszStr))) return pszStr;
- iSubStrLen = lstrlen(pszSubStr);
- if ((cchMaxSize > 0) && ((iSubStrLen+lstrlen(pszStr)+1) > cchMaxSize))
- return pszStr;
- MoveMemory(&pszStr[iPos+iSubStrLen], &pszStr[iPos], (lstrlen(&pszStr[iPos])+1)*sizeof(WCHAR));
- CopyMemory(&pszStr[iPos], pszSubStr, iSubStrLen*sizeof(WCHAR)); // no terminating zero
- return pszStr;
-}
-
-
-WCHAR* ReplaceSubStringWithString(const WCHAR* pszStr, const WCHAR* pszOldSubStr, const WCHAR* pszNewSubStr, BOOL bCaseSensitive, BOOL bAlsoSearchNewString, BOOL* pbSthReplaced)
-{
- // returned TCHAR* needs to be mir_free()'d
- // returns NULL on error
-
- int iOldSubStrLen, iNewSubStrLen;
- int iPos;
- WCHAR* pszOcc;
- WCHAR* pszReturn;
- WCHAR* pszReturnBuf;
-
- if (pbSthReplaced) *pbSthReplaced = FALSE;
- if (!pszStr) return NULL;
- if (!pszOldSubStr) {
- *pbSthReplaced = TRUE;
- return mir_wstrdup(pszStr);
- }
-
- iOldSubStrLen = (int)lstrlen(pszOldSubStr);
- iNewSubStrLen = pszNewSubStr?(int)lstrlen(pszNewSubStr):0;
-
- // Make sure that no infinite loop occurs (on str in new one)
- if (bAlsoSearchNewString && pszNewSubStr)
- if (bCaseSensitive?StrStr(pszNewSubStr, pszOldSubStr):StrStrI(pszNewSubStr, pszOldSubStr))
- bAlsoSearchNewString = FALSE;
-
- pszReturn = mir_wstrdup(pszStr);
- if (!pszReturn) return NULL;
-
- pszOcc = pszReturn;
- while ((pszOcc = bCaseSensitive?StrStr(pszOcc, pszOldSubStr):StrStrI(pszOcc, pszOldSubStr)) != NULL)
- {
- // Reallocate more memory (memory block might get moved)
- if (iNewSubStrLen > iOldSubStrLen)
- {
- pszReturnBuf = pszReturn;
- pszReturn = (WCHAR*)mir_realloc(pszReturnBuf, (lstrlen(pszReturn)+iNewSubStrLen-iOldSubStrLen+1)*sizeof(WCHAR));
- if (!pszReturn) {
- mir_free(pszReturnBuf);
- return NULL;
- }
- }
-
- iPos = pszOcc-pszReturn;
- RemoveSubStr(pszReturn, iPos, iOldSubStrLen);
- if (pszNewSubStr) InsertSubStr(pszReturn, 0, iPos, pszNewSubStr);
-
- // Get new start position for search
- if (!bAlsoSearchNewString)
- pszOcc = &pszReturn[iPos+iNewSubStrLen];
-
- if (pbSthReplaced) *pbSthReplaced = TRUE;
- }
-
- // Correct memory allocation (if less needed)
- if (iNewSubStrLen < iOldSubStrLen)
- {
- pszReturnBuf = pszReturn;
- pszReturn = (WCHAR*)mir_realloc(pszReturnBuf, (lstrlen(pszReturn)+1)*sizeof(WCHAR));
- if (!pszReturn) pszReturn = pszReturnBuf;
- }
-
- return pszReturn;
-}
-
-
-BOOL ReplaceSubStringWithStringBuf(WCHAR* pszStr, int cchMaxSize, const WCHAR* pszOldSubStr, const WCHAR* pszNewSubStr, BOOL bCaseSensitive, BOOL bAlsoSearchNewString)
-{
- int iOldSubStrLen, iNewSubStrLen;
- int iPos;
- WCHAR* pszOcc;
- BOOL bSthReplaced;
-
- if (!pszStr) return FALSE;
- if (!pszOldSubStr || (cchMaxSize <= 0)) return TRUE;
-
- iOldSubStrLen = (int)lstrlen(pszOldSubStr);
- iNewSubStrLen = pszNewSubStr?(int)lstrlen(pszNewSubStr):0;
-
- // Make sure that no infinite loop occurs (on str in new one)
- if (bAlsoSearchNewString && pszNewSubStr)
- if (bCaseSensitive?StrStr(pszNewSubStr, pszOldSubStr):StrStrI(pszNewSubStr, pszOldSubStr))
- bAlsoSearchNewString = FALSE;
-
- pszOcc = pszStr;
- bSthReplaced = FALSE;
- while ((pszOcc = bCaseSensitive?StrStr(pszOcc, pszOldSubStr):StrStrI(pszOcc, pszOldSubStr)) != NULL)
- {
- if (cchMaxSize < lstrlen(pszStr)+iNewSubStrLen-iOldSubStrLen+1);
- break;
-
- iPos = pszOcc-pszStr;
- RemoveSubStr(pszStr, iPos, iOldSubStrLen);
- if (pszNewSubStr) InsertSubStr(pszStr, 0, iPos, pszNewSubStr);
-
- // Get new start position for search
- if (!bAlsoSearchNewString)
- pszOcc = &pszStr[iPos+iNewSubStrLen];
-
- bSthReplaced = TRUE;
- }
-
- return bSthReplaced;
-}
-
-
-WCHAR* ReplaceSubStringWithStringMultiple(const WCHAR* pszStr, STRINGLIST* pslFromTo, BOOL bCaseSensitive, BOOL bAlsoSearchNewString, BOOL* pbSthReplaced)
-{
- WCHAR* pszReplaced;
- WCHAR* pszStrBuf;
- int i;
- BOOL bSthReplacedBuf;
-
- if (pbSthReplaced) *pbSthReplaced = FALSE;
- if (!pszStr) return NULL;
- pszStrBuf = mir_wstrdup(pszStr);
- if (pszStrBuf && pslFromTo)
- for (i=SL_MIN_POS; i<SLGetMaxPos(pslFromTo); i+=2)
- {
- pszReplaced = ReplaceSubStringWithString(pszStrBuf, SLGetItem(pslFromTo, i), SLGetItem(pslFromTo, i+1), bCaseSensitive, bAlsoSearchNewString, &bSthReplacedBuf);
- if (!pszReplaced) continue;
- if (pszStrBuf) mir_free(pszStrBuf);
- pszStrBuf = pszReplaced;
- if (pbSthReplaced && bSthReplacedBuf) *pbSthReplaced = TRUE;
- }
-
- return pszStrBuf;
-}
-
-
-BOOL ReplaceSubStringWithStringMultipleBuf(WCHAR* pszStr, int cchMaxSize, STRINGLIST* pslFromTo, BOOL bCaseSensitive, BOOL bAlsoSearchNewString)
-{
- int i;
- BOOL bSthReplaced;
-
- if (!pszStr) return FALSE;
- if (!pslFromTo) return TRUE;
-
- bSthReplaced = FALSE;
- for (i=SL_MIN_POS; i<SLGetMaxPos(pslFromTo); i+=2)
- if (ReplaceSubStringWithStringBuf(pszStr, cchMaxSize, SLGetItem(pslFromTo, i), SLGetItem(pslFromTo, i+1), bCaseSensitive, bAlsoSearchNewString))
- bSthReplaced = TRUE;
-
- return bSthReplaced;
-}
-
-
-WCHAR* InsertSubStrEveryNChars(const WCHAR* pszStr, int iDist, const WCHAR* pszSubStr, BOOL bAlsoDoFirst, BOOL bAlsoDoLast)
-{
- // returned char needs to be mir_free()'d
- // returns NULL on error
-
- int iSubStrLen;
- int iLoops;
- WCHAR* pszReturn;
- int i;
-
- if (!pszStr) return NULL;
- if (iDist <= 0) return mir_wstrdup(pszStr);
-
- iSubStrLen = pszSubStr?lstrlen(pszSubStr):0;
- iLoops = (int)(lstrlen(pszStr)/iDist);
- if ((iLoops == (int)(lstrlen(pszStr)/iDist)) && !bAlsoDoLast) iLoops--;
- if (bAlsoDoFirst) iLoops++;
-
- pszReturn = (WCHAR*)mir_alloc((lstrlen(pszStr)+(iLoops*iSubStrLen)+1)*sizeof(WCHAR));
- if (!pszReturn) return NULL;
- mir_sntprintf(pszReturn, lstrlen(pszStr)+(iLoops*iSubStrLen)+1, _T("%s"), pszStr);
-
- if (iSubStrLen > 0)
- for (i=0; i<iLoops; i++) // FIX ME: use NextChar() instead
- InsertSubStr(pszReturn, 0, (bAlsoDoFirst?0:iDist)+(i*(iSubStrLen+iDist)), pszSubStr);
-
- return pszReturn;
-}
-
-
-BOOL RemoveWhiteSpaces(WCHAR* pszStr, BOOL bReplaceWithSpaces, BOOL bAlsoUnneededSpaces)
-{
- BOOL bReturn = FALSE;
-
- if (!pszStr) return bReturn;
-
- if (StrTrim(pszStr, _T("\r\n\t"))) bReturn = TRUE;
- if (ReplaceSubStringWithStringBuf(pszStr, 0, _T("\r\n"), bReplaceWithSpaces?_T(" "):_T(""), TRUE, FALSE)) bReturn = TRUE;
- if (ReplaceSubStringWithStringBuf(pszStr, 0, _T("\r"), bReplaceWithSpaces?_T(" "):_T(""), TRUE, FALSE)) bReturn = TRUE;
- if (ReplaceSubStringWithStringBuf(pszStr, 0, _T("\n"), bReplaceWithSpaces?_T(" "):_T(""), TRUE, FALSE)) bReturn = TRUE;
- if (ReplaceSubStringWithStringBuf(pszStr, 0, _T("\t"), bReplaceWithSpaces?_T(" "):_T(""), TRUE, FALSE)) bReturn = TRUE;
-
- if (bAlsoUnneededSpaces)
- {
- if (StrTrim(pszStr, _T(" "))) bReturn = TRUE;
- if (ReplaceSubStringWithStringBuf(pszStr, 0, _T(" "), _T(" "), TRUE, TRUE)) bReturn = TRUE;
- }
-
- return bReturn;
-}
-
-
-BOOL GetRandomString(WCHAR* pszStr, int cchSize)
-{
- static BOOL bRandInited = FALSE;
- const WCHAR* pszChars = TranslateT("abcdefghkmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWXYZ23456789"); // misunderstandable chars were removed (l=I=1, O=0=o, i=j)
- int i;
-
- if (!pszChars || !pszStr || (cchSize < 1)) return FALSE;
-
- // Initialize random seed
- if (!bRandInited)
- {
- srand((unsigned int)(GetTickCount()+time(NULL))); // very random
- bRandInited = TRUE;
- }
-
- for (i=0; i<(cchSize-1); i++)
- pszStr[i] = pszChars[(rand()*lstrlen(pszChars))/RAND_MAX]; // % operator is not a good choice
-
- pszStr[cchSize-1] = _T('\0');
- return TRUE;
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+
+// -----------------------------------------
+
+
+/*
+int SubStringExistsInStringCount(const TCHAR* pszStr, const TCHAR* pszSubString, BOOL bCaseSensitive)
+{
+ int iSubStrLen;
+ char* pszOcc;
+ int iReturn;
+
+ if (!pszSubString) return 0;
+
+ pszOcc = pszStr;
+ iCount = 0;
+ iSubStrLen = lstrlen(pszSubString);
+ while ((pszOcc = bCaseSensitive?StrStr(pszOcc, pszOldSubStr):StrStrI(pszOcc, pszOldSubStr)) != NULL)
+ {
+ iCount++;
+ pszOcc = pszOcc+iSubStrLen;
+ }
+
+ return iCount;
+}
+*/
+
+
+WCHAR* RemoveSubStr(WCHAR* pszStr, int iPos, int iSubStrLen)
+{
+ if (!pszStr) return NULL;
+ if ((iPos > 0) && (iSubStrLen > 0) && (iPos < lstrlen(pszStr)))
+ MoveMemory(&pszStr[iPos], &pszStr[iPos+iSubStrLen], (lstrlen(&pszStr[iPos])+1)*sizeof(WCHAR));
+ return pszStr;
+}
+
+/*
+BOOL HasSubStr(const TCHAR* pszStr, int iPos, const TCHAR* pszSubStr);
+{
+ TCHAR* pszPos;
+
+ if (!pszSubStr || !pszStr || (iPos >= lstrlen(pszStr))) return FALSE;
+
+ // Test for suffix
+ if (iPos < 0)
+ return ((lstrlen(pszStr) <= lstrlen(pszSubStr)) || (StrCmp(pszStr+lstrlen(pszStr)-lstrlen(pszSubStr), pszSubStr) != 0));
+ else
+ return (StrCmpN(&pszStr[iPos], pszSubStr, lstrlen(pszSubStr)) != 0))
+}
+*/
+
+WCHAR* InsertSubStr(WCHAR* pszStr, int cchMaxSize, int iPos, const WCHAR* pszSubStr)
+{
+ int iSubStrLen;
+
+ if (!pszStr) return NULL;
+ if (!pszSubStr || (iPos < 0) || (iPos >= lstrlen(pszStr))) return pszStr;
+ iSubStrLen = lstrlen(pszSubStr);
+ if ((cchMaxSize > 0) && ((iSubStrLen+lstrlen(pszStr)+1) > cchMaxSize))
+ return pszStr;
+ MoveMemory(&pszStr[iPos+iSubStrLen], &pszStr[iPos], (lstrlen(&pszStr[iPos])+1)*sizeof(WCHAR));
+ CopyMemory(&pszStr[iPos], pszSubStr, iSubStrLen*sizeof(WCHAR)); // no terminating zero
+ return pszStr;
+}
+
+
+WCHAR* ReplaceSubStringWithString(const WCHAR* pszStr, const WCHAR* pszOldSubStr, const WCHAR* pszNewSubStr, BOOL bCaseSensitive, BOOL bAlsoSearchNewString, BOOL* pbSthReplaced)
+{
+ // returned TCHAR* needs to be mir_free()'d
+ // returns NULL on error
+
+ int iOldSubStrLen, iNewSubStrLen;
+ int iPos;
+ WCHAR* pszOcc;
+ WCHAR* pszReturn;
+ WCHAR* pszReturnBuf;
+
+ if (pbSthReplaced) *pbSthReplaced = FALSE;
+ if (!pszStr) return NULL;
+ if (!pszOldSubStr) {
+ *pbSthReplaced = TRUE;
+ return mir_wstrdup(pszStr);
+ }
+
+ iOldSubStrLen = (int)lstrlen(pszOldSubStr);
+ iNewSubStrLen = pszNewSubStr?(int)lstrlen(pszNewSubStr):0;
+
+ // Make sure that no infinite loop occurs (on str in new one)
+ if (bAlsoSearchNewString && pszNewSubStr)
+ if (bCaseSensitive?StrStr(pszNewSubStr, pszOldSubStr):StrStrI(pszNewSubStr, pszOldSubStr))
+ bAlsoSearchNewString = FALSE;
+
+ pszReturn = mir_wstrdup(pszStr);
+ if (!pszReturn) return NULL;
+
+ pszOcc = pszReturn;
+ while ((pszOcc = bCaseSensitive?StrStr(pszOcc, pszOldSubStr):StrStrI(pszOcc, pszOldSubStr)) != NULL)
+ {
+ // Reallocate more memory (memory block might get moved)
+ if (iNewSubStrLen > iOldSubStrLen)
+ {
+ pszReturnBuf = pszReturn;
+ pszReturn = (WCHAR*)mir_realloc(pszReturnBuf, (lstrlen(pszReturn)+iNewSubStrLen-iOldSubStrLen+1)*sizeof(WCHAR));
+ if (!pszReturn) {
+ mir_free(pszReturnBuf);
+ return NULL;
+ }
+ }
+
+ iPos = pszOcc-pszReturn;
+ RemoveSubStr(pszReturn, iPos, iOldSubStrLen);
+ if (pszNewSubStr) InsertSubStr(pszReturn, 0, iPos, pszNewSubStr);
+
+ // Get new start position for search
+ if (!bAlsoSearchNewString)
+ pszOcc = &pszReturn[iPos+iNewSubStrLen];
+
+ if (pbSthReplaced) *pbSthReplaced = TRUE;
+ }
+
+ // Correct memory allocation (if less needed)
+ if (iNewSubStrLen < iOldSubStrLen)
+ {
+ pszReturnBuf = pszReturn;
+ pszReturn = (WCHAR*)mir_realloc(pszReturnBuf, (lstrlen(pszReturn)+1)*sizeof(WCHAR));
+ if (!pszReturn) pszReturn = pszReturnBuf;
+ }
+
+ return pszReturn;
+}
+
+
+BOOL ReplaceSubStringWithStringBuf(WCHAR* pszStr, int cchMaxSize, const WCHAR* pszOldSubStr, const WCHAR* pszNewSubStr, BOOL bCaseSensitive, BOOL bAlsoSearchNewString)
+{
+ int iOldSubStrLen, iNewSubStrLen;
+ int iPos;
+ WCHAR* pszOcc;
+ BOOL bSthReplaced;
+
+ if (!pszStr) return FALSE;
+ if (!pszOldSubStr || (cchMaxSize <= 0)) return TRUE;
+
+ iOldSubStrLen = (int)lstrlen(pszOldSubStr);
+ iNewSubStrLen = pszNewSubStr?(int)lstrlen(pszNewSubStr):0;
+
+ // Make sure that no infinite loop occurs (on str in new one)
+ if (bAlsoSearchNewString && pszNewSubStr)
+ if (bCaseSensitive?StrStr(pszNewSubStr, pszOldSubStr):StrStrI(pszNewSubStr, pszOldSubStr))
+ bAlsoSearchNewString = FALSE;
+
+ pszOcc = pszStr;
+ bSthReplaced = FALSE;
+ while ((pszOcc = bCaseSensitive?StrStr(pszOcc, pszOldSubStr):StrStrI(pszOcc, pszOldSubStr)) != NULL)
+ {
+ if (cchMaxSize < lstrlen(pszStr)+iNewSubStrLen-iOldSubStrLen+1);
+ break;
+
+ iPos = pszOcc-pszStr;
+ RemoveSubStr(pszStr, iPos, iOldSubStrLen);
+ if (pszNewSubStr) InsertSubStr(pszStr, 0, iPos, pszNewSubStr);
+
+ // Get new start position for search
+ if (!bAlsoSearchNewString)
+ pszOcc = &pszStr[iPos+iNewSubStrLen];
+
+ bSthReplaced = TRUE;
+ }
+
+ return bSthReplaced;
+}
+
+
+WCHAR* ReplaceSubStringWithStringMultiple(const WCHAR* pszStr, STRINGLIST* pslFromTo, BOOL bCaseSensitive, BOOL bAlsoSearchNewString, BOOL* pbSthReplaced)
+{
+ WCHAR* pszReplaced;
+ WCHAR* pszStrBuf;
+ int i;
+ BOOL bSthReplacedBuf;
+
+ if (pbSthReplaced) *pbSthReplaced = FALSE;
+ if (!pszStr) return NULL;
+ pszStrBuf = mir_wstrdup(pszStr);
+ if (pszStrBuf && pslFromTo)
+ for (i=SL_MIN_POS; i<SLGetMaxPos(pslFromTo); i+=2)
+ {
+ pszReplaced = ReplaceSubStringWithString(pszStrBuf, SLGetItem(pslFromTo, i), SLGetItem(pslFromTo, i+1), bCaseSensitive, bAlsoSearchNewString, &bSthReplacedBuf);
+ if (!pszReplaced) continue;
+ if (pszStrBuf) mir_free(pszStrBuf);
+ pszStrBuf = pszReplaced;
+ if (pbSthReplaced && bSthReplacedBuf) *pbSthReplaced = TRUE;
+ }
+
+ return pszStrBuf;
+}
+
+
+BOOL ReplaceSubStringWithStringMultipleBuf(WCHAR* pszStr, int cchMaxSize, STRINGLIST* pslFromTo, BOOL bCaseSensitive, BOOL bAlsoSearchNewString)
+{
+ int i;
+ BOOL bSthReplaced;
+
+ if (!pszStr) return FALSE;
+ if (!pslFromTo) return TRUE;
+
+ bSthReplaced = FALSE;
+ for (i=SL_MIN_POS; i<SLGetMaxPos(pslFromTo); i+=2)
+ if (ReplaceSubStringWithStringBuf(pszStr, cchMaxSize, SLGetItem(pslFromTo, i), SLGetItem(pslFromTo, i+1), bCaseSensitive, bAlsoSearchNewString))
+ bSthReplaced = TRUE;
+
+ return bSthReplaced;
+}
+
+
+WCHAR* InsertSubStrEveryNChars(const WCHAR* pszStr, int iDist, const WCHAR* pszSubStr, BOOL bAlsoDoFirst, BOOL bAlsoDoLast)
+{
+ // returned char needs to be mir_free()'d
+ // returns NULL on error
+
+ int iSubStrLen;
+ int iLoops;
+ WCHAR* pszReturn;
+ int i;
+
+ if (!pszStr) return NULL;
+ if (iDist <= 0) return mir_wstrdup(pszStr);
+
+ iSubStrLen = pszSubStr?lstrlen(pszSubStr):0;
+ iLoops = (int)(lstrlen(pszStr)/iDist);
+ if ((iLoops == (int)(lstrlen(pszStr)/iDist)) && !bAlsoDoLast) iLoops--;
+ if (bAlsoDoFirst) iLoops++;
+
+ pszReturn = (WCHAR*)mir_alloc((lstrlen(pszStr)+(iLoops*iSubStrLen)+1)*sizeof(WCHAR));
+ if (!pszReturn) return NULL;
+ mir_sntprintf(pszReturn, lstrlen(pszStr)+(iLoops*iSubStrLen)+1, _T("%s"), pszStr);
+
+ if (iSubStrLen > 0)
+ for (i=0; i<iLoops; i++) // FIX ME: use NextChar() instead
+ InsertSubStr(pszReturn, 0, (bAlsoDoFirst?0:iDist)+(i*(iSubStrLen+iDist)), pszSubStr);
+
+ return pszReturn;
+}
+
+
+BOOL RemoveWhiteSpaces(WCHAR* pszStr, BOOL bReplaceWithSpaces, BOOL bAlsoUnneededSpaces)
+{
+ BOOL bReturn = FALSE;
+
+ if (!pszStr) return bReturn;
+
+ if (StrTrim(pszStr, _T("\r\n\t"))) bReturn = TRUE;
+ if (ReplaceSubStringWithStringBuf(pszStr, 0, _T("\r\n"), bReplaceWithSpaces?_T(" "):_T(""), TRUE, FALSE)) bReturn = TRUE;
+ if (ReplaceSubStringWithStringBuf(pszStr, 0, _T("\r"), bReplaceWithSpaces?_T(" "):_T(""), TRUE, FALSE)) bReturn = TRUE;
+ if (ReplaceSubStringWithStringBuf(pszStr, 0, _T("\n"), bReplaceWithSpaces?_T(" "):_T(""), TRUE, FALSE)) bReturn = TRUE;
+ if (ReplaceSubStringWithStringBuf(pszStr, 0, _T("\t"), bReplaceWithSpaces?_T(" "):_T(""), TRUE, FALSE)) bReturn = TRUE;
+
+ if (bAlsoUnneededSpaces)
+ {
+ if (StrTrim(pszStr, _T(" "))) bReturn = TRUE;
+ if (ReplaceSubStringWithStringBuf(pszStr, 0, _T(" "), _T(" "), TRUE, TRUE)) bReturn = TRUE;
+ }
+
+ return bReturn;
+}
+
+
+BOOL GetRandomString(WCHAR* pszStr, int cchSize)
+{
+ static BOOL bRandInited = FALSE;
+ const WCHAR* pszChars = TranslateT("abcdefghkmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWXYZ23456789"); // misunderstandable chars were removed (l=I=1, O=0=o, i=j)
+ int i;
+
+ if (!pszChars || !pszStr || (cchSize < 1)) return FALSE;
+
+ // Initialize random seed
+ if (!bRandInited)
+ {
+ srand((unsigned int)(GetTickCount()+time(NULL))); // very random
+ bRandInited = TRUE;
+ }
+
+ for (i=0; i<(cchSize-1); i++)
+ pszStr[i] = pszChars[(rand()*lstrlen(pszChars))/RAND_MAX]; // % operator is not a good choice
+
+ pszStr[cchSize-1] = _T('\0');
+ return TRUE;
} \ No newline at end of file
diff --git a/string.h b/string.h
index aec6b8e..6e67c84 100644
--- a/string.h
+++ b/string.h
@@ -1,41 +1,41 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_STRING_H__
-#define SF_STRING_H__ 1
-
-
-// -- Prototypes
-WCHAR* InsertSubStr(WCHAR* pszStr, int cchSize, int iPos, const WCHAR* pszSubStr);
-WCHAR* RemoveSubStr(WCHAR* pszStr, int iPos, int iSubStrLen);
-BOOL HasSubStr(const WCHAR* pszStr, int iPos, const WCHAR* pszSubStr);
-
-WCHAR* InsertSubStrEveryNChars(const WCHAR* pszStr, int iDist, const WCHAR* pszSubStr, BOOL bAlsoDoFirst, BOOL bAlsoDoLast);
-WCHAR* ReplaceSubStringWithString(const WCHAR* pszStr, const WCHAR* pszOldSubStr, const WCHAR* pszNewSubStr, BOOL bCaseSensitive, BOOL bAlsoSearchNewString, BOOL* pbSthReplaced);
-BOOL ReplaceSubStringWithStringBuf(WCHAR* pszStr, int cchMaxSize, const WCHAR* pszOldSubStr, const WCHAR* pszNewSubStr, BOOL bCaseSensitive, BOOL bAlsoSearchNewString);
-WCHAR* ReplaceSubStringWithStringMultiple(const WCHAR* pszStr, STRINGLIST* pslFromTo, BOOL bCaseSensitive, BOOL bAlsoSearchNewString, BOOL* pbSthReplaced);
-BOOL ReplaceSubStringWithStringMultipleBuf(WCHAR* pszStr, int cchMaxSize, STRINGLIST* pslFromTo, BOOL bCaseSensitive, BOOL bAlsoSearchNewString);
-int SubStringExistsInStringCount(const WCHAR* pszStr, const WCHAR* pszSubString, BOOL bCaseSensitive);
-
-BOOL RemoveWhiteSpaces(WCHAR* pszStr, BOOL bReplaceWithSpaces, BOOL bAlsoUnneededSpaces);
-BOOL GetRandomString(WCHAR* pszStr, int cchSize);
-
-#endif // SF_STRING_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_STRING_H__
+#define SF_STRING_H__ 1
+
+
+// -- Prototypes
+WCHAR* InsertSubStr(WCHAR* pszStr, int cchSize, int iPos, const WCHAR* pszSubStr);
+WCHAR* RemoveSubStr(WCHAR* pszStr, int iPos, int iSubStrLen);
+BOOL HasSubStr(const WCHAR* pszStr, int iPos, const WCHAR* pszSubStr);
+
+WCHAR* InsertSubStrEveryNChars(const WCHAR* pszStr, int iDist, const WCHAR* pszSubStr, BOOL bAlsoDoFirst, BOOL bAlsoDoLast);
+WCHAR* ReplaceSubStringWithString(const WCHAR* pszStr, const WCHAR* pszOldSubStr, const WCHAR* pszNewSubStr, BOOL bCaseSensitive, BOOL bAlsoSearchNewString, BOOL* pbSthReplaced);
+BOOL ReplaceSubStringWithStringBuf(WCHAR* pszStr, int cchMaxSize, const WCHAR* pszOldSubStr, const WCHAR* pszNewSubStr, BOOL bCaseSensitive, BOOL bAlsoSearchNewString);
+WCHAR* ReplaceSubStringWithStringMultiple(const WCHAR* pszStr, STRINGLIST* pslFromTo, BOOL bCaseSensitive, BOOL bAlsoSearchNewString, BOOL* pbSthReplaced);
+BOOL ReplaceSubStringWithStringMultipleBuf(WCHAR* pszStr, int cchMaxSize, STRINGLIST* pslFromTo, BOOL bCaseSensitive, BOOL bAlsoSearchNewString);
+int SubStringExistsInStringCount(const WCHAR* pszStr, const WCHAR* pszSubString, BOOL bCaseSensitive);
+
+BOOL RemoveWhiteSpaces(WCHAR* pszStr, BOOL bReplaceWithSpaces, BOOL bAlsoUnneededSpaces);
+BOOL GetRandomString(WCHAR* pszStr, int cchSize);
+
+#endif // SF_STRING_H__
diff --git a/stringlist.c b/stringlist.c
index e1d6de5..c7012e4 100644
--- a/stringlist.c
+++ b/stringlist.c
@@ -1,1007 +1,1007 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -- Macros
-#define SLAlloc(s) mir_alloc(s)
-#define SLReAlloc(p, s) mir_realloc((p), (s))
-#define SLFree(p) mir_free(p)
-//#define SLAlloc(s) HeapAlloc(GetProcessHeap(), 0, (s))
-//#define SLReAlloc(p, s) HeapReAlloc(GetProcessHeap(), 0, (p), (s))
-//#define SLFree(p) HeapFree(GetProcessHeap(), 0, (p))
-
-
-// -----------------------------------------
-
-
-BOOL SLAssignToListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox)
-{
- BOOL bReturn = FALSE;
- int i;
-
- if (!psl || !hwndListBox) return FALSE;
- SendMessage(hwndListBox, LB_RESETCONTENT, 0, 0);
- SendMessage(hwndListBox, LB_INITSTORAGE, (WPARAM)psl->uCount, (LPARAM)(SLGetSize(psl, TRUE)*sizeof(WCHAR)));
- EnterCriticalSection(&psl->csListAccess);
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- if (SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)psl->papszList[i]) >= 0)
- bReturn = TRUE;
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-BOOL SLRetrieveFromListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox)
-{
- int iCount, i, iPos;
- BOOL bReturn;
-
- if (!psl || !hwndListBox) return FALSE;
- bReturn = FALSE;
- EnterCriticalSection(&psl->csListAccess);
- iCount = SendMessage(hwndListBox, LB_GETCOUNT, 0, 0);
- for (i=0; i<iCount; i++)
- {
- iPos = SLPrepareItem(psl, SendMessage(hwndListBox, LB_GETTEXTLEN, (WPARAM)i, 0));
- if (iPos != SL_INVALID_POS)
- {
- if (SendMessage(hwndListBox, LB_GETTEXT, (WPARAM)i, (LPARAM)psl->papszList[iPos]) != LB_ERR)
- bReturn = TRUE;
- else
- SLDeleteItem(psl, iPos);
- }
- }
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-/*
-BOOL SLLoadFromIniFile(LPSTRINGLIST psl, const TCHAR* pszSearchPath, const TCHAR* pszSection, const TCHAR* pszSettingPrefix)
-{
- TCHAR szFile[MAX_PATH];
- BOOL bFileFound;
- BOOL bReturn = FALSE;
- int i, iLen, iSize;
- TCHAR* pszItem;
- TCHAR* pszBuf;
- WIN32_FIND_DATA wfd;
- HANDLE hFind;
-
- if (!psl || !pszSection || !pszSearchPath)
- return FALSE;
-
- ZeroMemory(&wfd, sizeof(wfd));
-
- EnterCriticalSection(&psl->csListAccess);
-
- // Enum all files in the directory
- hFind = FindFirstFile(pszSearchPath, &wfd);
- for (bFileFound=(hFind!=INVALID_HANDLE_VALUE); bFileFound; bFileFound=FindNextFile(hFind, &wfd))
- {
- if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
- continue;
-
- // Construct the file name
- mir_sntprintf(szFile, ARRAYSIZE(szFile), _T("%s"), pszSearchPath);
- PathRemoveFileSpec(szFile);
- PathAppend(szFile, wfd.cFileName);
-
- // Load the data from ini file
- iSize = (pszSettingPrefix?(lstrlen(pszSettingPrefix)+1):0)+MAX_INT_LENGTH+1);
- pszItem = (TCHAR*)mir_alloc(iSize*sizeof(TCHAR));
- if (!pszItem) continue;
-
- for (i=SL_MIN_POS;;i++) // no break condition
- {
- mir_sntprintf(pszItem, _T("%s%s%i"), iSize, pszSettingPrefix?pszSettingPrefix:_T(""), pszSettingPrefix?_T("|"):_T(""), i);
-
- iLen = GetPrivateProfileString(pszSection, pszItem, NULL, NULL, 0, szFile);
- if (iLen < 0) break;
-
- pszBuf = (TCHAR*)mir_alloc((iLen+1)*sizeof(TCHAR));
- if (!pszBuf) continue;
-
- GetPrivateProfileString(pszSection, pszItem, NULL, pszBuf, iLen, szFile);
- if (lstrlen(pszBuf) <= 0) break;
-
- if (SLAddItem(psl, pszBuf) != SL_INVALID_POS)
- if (!bReturn) bReturn = TRUE;
-
- mir_free(pszBuf);
- }
-
- mir_free(pszItem);
- }
-
- LeaveCriticalSection(&psl->csListAccess);
-
- if (hFind) FindClose(hFind);
-
- return bReturn;
-}
-
-
-
-BOOL SLSaveToIniFile(LPSTRINGLIST psl, const TCHAR* pszFileName, const TCHAR* pszSection, const TCHAR* pszSettingPrefix)
-{
- int i;
- char* pszItem;
- int iSize;
- BOOL bReturn = FALSE;
-
- if (!psl || !pszSection || !pszFileName)
- return FALSE;
-
- iSize = (pszSettingPrefix?(lstrlen(pszSettingPrefix)+1):0)+MAX_INT_LENGTH+1;
- pszItem = (TCHAR*)mir_alloc(iSize*sizeof(TCHAR));
-
- if (pszItem)
- {
- EnterCriticalSection(&psl->csListAccess);
-
- // Delete old items (empty section)
- WritePrivateProfileString(pszSection, NULL, NULL, pszFileName);
-
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- {
- mir_sntprintf(pszItem, iSize, _T("%s%s%i"), pszSettingPrefix?pszSettingPrefix:_T(""), pszSettingPrefix?_T("|"):_T(""), i);
-
- if (WritePrivateProfileString(pszSection, pszItem, psl->papszList[i], pszFileName))
- bReturn = TRUE;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
-
- mir_free(pszItem);
- }
-
- return bReturn;
-}
-*/
-
-
-BOOL SLLoadFromFile(LPSTRINGLIST psl, const WCHAR* pszSearchPath)
-{
- BOOL bReturn;
- WIN32_FIND_DATA wfd;
- HANDLE hFind;
- BOOL bFileFound;
- WCHAR szFile[MAX_PATH];
- HANDLE hFile;
- DWORD dwRead;
- int iAllocBufSize;
- int iAllocBufStep;
- char* pszAllocBuf;
- char* pszAllocBufTmp;
- const char szBOM[3] = {0xEF, 0xBB, 0xBF};
- BOOL bWatchBOM;
- BOOL bEndOfFile;
- WCHAR* pszContentConv;
- WCHAR* pszBuf;
-
- if (!psl || !pszSearchPath) return FALSE;
- EnterCriticalSection(&psl->csListAccess);
-
- // Initial buffer size (gets auto-enlarged if needed)
- iAllocBufSize = 128; // read-in chars buffer
- pszAllocBuf = NULL;
-
- // Enum all files in the directory
- bReturn = FALSE;
- hFind = FindFirstFile(pszSearchPath, &wfd);
- for (bFileFound=(hFind!=INVALID_HANDLE_VALUE); bFileFound; bFileFound=FindNextFile(hFind, &wfd))
- {
- if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
- continue;
- mir_sntprintf(szFile, ARRAYSIZE(szFile), _T("%s"), pszSearchPath);
- PathRemoveFileSpec(szFile);
- PathAppend(szFile, wfd.cFileName);
-
- hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- if (hFile == INVALID_HANDLE_VALUE) continue;
- bWatchBOM = TRUE;
- bEndOfFile = FALSE;
- iAllocBufStep = 0;
- while (!bEndOfFile)
- {
- // Enlarge buffer if needed
- if (!pszAllocBuf || (iAllocBufStep >= iAllocBufSize))
- {
- pszAllocBufTmp = (char*)mir_realloc(pszAllocBuf, (iAllocBufSize*2)*sizeof(char));
- if (pszAllocBufTmp) {
- if (pszAllocBuf) iAllocBufSize *= 2;
- pszAllocBuf = pszAllocBufTmp;
- } else {
- bEndOfFile = TRUE; // out of memory
- }
- }
- if (!bEndOfFile) {
- if (!ReadFile(hFile, &pszAllocBuf[iAllocBufStep], sizeof(char), &dwRead, NULL))
- bEndOfFile = TRUE;
- if (dwRead < sizeof(char))
- bEndOfFile = TRUE;
- }
- if ((pszAllocBuf[iAllocBufStep] == '\n') || bEndOfFile)
- {
- if (!bEndOfFile && (iAllocBufStep>0) && (pszAllocBuf[iAllocBufStep-1] == '\r'))
- pszAllocBuf[iAllocBufStep-1] = '\0';
- else
- pszAllocBuf[iAllocBufStep] = '\0';
-
- if (lstrlenA(pszAllocBuf) > 0)
- {
- // Test UTF-8 BOM
- // EF BB BF = UTF-8
- // -> indicating UTF-8 Unicode text file (check only once)
- if (bWatchBOM)
- {
- if (StrCmpNA(pszAllocBuf, szBOM, ARRAYSIZE(szBOM)) == 0)
- MoveMemory(pszAllocBuf, (PBYTE)pszAllocBuf+sizeof(szBOM), ((lstrlenA(pszAllocBuf)+1)*sizeof(char))-sizeof(szBOM));
- bWatchBOM = FALSE;
- }
-
- // Decode Utf8
- mir_utf8decode(pszAllocBuf,&pszContentConv);
- if (pszContentConv)
- {
- pszBuf = pszContentConv;
- while (pszBuf)
- {
- // Find comment indicator
- pszBuf = StrChr(pszBuf, _T(';')); // find ";" comment indicator
- if (pszBuf && (*CharPrev(pszContentConv, pszBuf) != _T('\\'))) // ignore "\;" chars
- {
- *pszBuf = _T('\0');
- break;
- }
- }
-
- // Replace no-comment indicators
- pszBuf = ReplaceSubStringWithString(pszContentConv, _T("\\;"), _T(";"), TRUE, FALSE, NULL);
-
- // Add item to list (disallow empty items)
- if (lstrlen(pszContentConv) > 0)
- if (SLAddItem(psl, pszBuf?pszBuf:pszContentConv) >= 0)
- bReturn = TRUE;
-
- mir_free(pszContentConv);
- if (pszBuf) mir_free(pszBuf);
- }
- }
-
- // Reset step count
- iAllocBufStep = 0;
-
- } else {
- // Step up in string
- iAllocBufStep++;
- }
-
- } // while (!bEndOfFile)
-
- CloseHandle(hFile);
- }
-
- if (hFind) FindClose(hFind);
- if (pszAllocBuf) mir_free(pszAllocBuf);
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-
-BOOL SLSaveToFile(LPSTRINGLIST psl, const WCHAR* pszFileName)
-{
- BOOL bReturn;
- int i;
- const char szBOM[3] = {0xEF, 0xBB, 0xBF};
- HANDLE hFile;
- DWORD dwWritten; // Win98 compatibility
- WCHAR* pszBuf;
- char* pszContentUtf8;
-
- if (!psl || !pszFileName) return FALSE;
- hFile = CreateFile(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
- if (hFile == INVALID_HANDLE_VALUE) return FALSE;
- bReturn = FALSE;
- EnterCriticalSection(&psl->csListAccess);
-
- // Write UTF-8 BOM
- // EF BB BF = UTF-8
- // -> indicating UTF-8 Unicode text file
- if (WriteFile(hFile, &szBOM, sizeof(szBOM), &dwWritten, NULL))
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- {
- // Replace comment indicators
- pszBuf = ReplaceSubStringWithString(psl->papszList[i], _T(";"), _T("\\;"), TRUE, FALSE, NULL);
- if (!pszBuf) continue;
- pszContentUtf8 = mir_utf8encodeW(pszBuf);
- if (pszContentUtf8) {
- if (WriteFile(hFile, pszContentUtf8, lstrlenA(pszContentUtf8)*sizeof(char), &dwWritten, NULL))
- if (WriteFile(hFile, "\r\n", 2*sizeof(char), &dwWritten, NULL))
- bReturn = TRUE;
- mir_free(pszContentUtf8);
- }
- mir_free(pszBuf);
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- SetEndOfFile(hFile); // if it was longer before
- FlushFileBuffers(hFile); // just to be sure
- CloseHandle(hFile);
- return bReturn;
-}
-
-
-/*
-BOOL SLConvertFromString(LPSTRINGLIST psl, const TCHAR* pszString, int cchSize, const TCHAR* pszSeparator, BOOL bIgnoreEmptyItems)
-{
- // If pszSeparator is NULL a _T('\0') is taken as separator
- BOOL bReturn;
- int cchSepLen;
-
- BOOL bReachedEnd;
- TCHAR* pszAfterPrev;
- TCHAR* pszNext;
- int iPos;
-
- if (!pszString || !psl) return 0;
-
- if (cchSize < 0) cchSize = lstrlen(pszString)+1;
- cchSepLen = pszSeparator?lstrlen(pszSeparator):1;
-
- EnterCriticalSection(&psl->csListAccess);
-
- // Loop through string
- bReturn = 0;
- pszAfterPrev = (TCHAR*)pszString;
- bReachedEnd = FALSE;
- while (!bReachedEnd)
- {
- // Find first/next occurence
- if (pszSeparator)
- {
- pszNext = StrStr(pszAfterPrev, pszSeparator);
- if (!pszNext)
- {
- bReachedEnd = TRUE;
- pszNext = (TCHAR*)pszString+(cchSize*sizeof(TCHAR));
- }
-
- } else {
-
- // Find NULL separator
- pszNext = pszAfterPrev;
- while (*pszNext != _T('\0'));
- {
- pszNext = CharNext(pszNext);
- if ( pszNext >= (szString+((cchSize-1)*sizeof(TCHAR)) )
- {
- bReachedEnd = TRUE;
- break;
- }
- }
- }
-
- // Add item
- if (!bIgnoreEmptyItems || (pszNext != pszAfterPrev))
- {
- i2
- if (iPos < 0) continue;
- CopyMemory((PBYTE)psl->papszList[iPos], pszAfterPrev, ((PBYTE)pszNext-(PBYTE)pszAfterPrev));
-
- bReturn = TRUE;
- }
-
- // Step up one separated item
- pszAfterPrev = pszNext+(cchSepLen*sizeof(TCHAR));
- if ( pszAfterPrev >= pszString+((cchSize-1)*sizeof(TCHAR)) )
- bReachedEnd = TRUE;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
-
- return bReturn;
-}
-*/
-
-
-WCHAR* SLConvertToString(LPSTRINGLIST psl, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast, int* piSize)
-{
- // Returned string needs to be freed with SLFreeReturn()
- // If pszSeparator is NULL a _T('\0') is taken as separator
-
- int i;
- int iSepLen;
- int iSize;
- WCHAR* pszReturn;
- WCHAR* pszStep;
-
- if (piSize) *piSize = 0;
- if (!psl) return NULL;
-
- EnterCriticalSection(&psl->csListAccess);
-
- // Get needed size
- iSepLen = pszSeparator?lstrlen(pszSeparator):1;
- iSize = SLGetSize(psl, FALSE)+1; // character count in string list
- if (psl->uCount > 0) iSize += (psl->uCount-1)*iSepLen;
- if ((psl->uCount > 0) && bAlsoDoFirst) iSize += iSepLen;
- if (bAlsoDoLast) iSize += iSepLen;
-
- pszReturn = (WCHAR*)SLAlloc(iSize*sizeof(WCHAR));
- if (!pszReturn) {
- LeaveCriticalSection(&psl->csListAccess);
- return NULL;
- }
- if (piSize) *piSize = iSize;
-
- // Add items to memory
- pszStep = pszReturn;
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- {
- if ((i>SL_MIN_POS) || bAlsoDoFirst)
- {
- if (pszSeparator)
- CopyMemory(pszStep, pszSeparator, iSepLen*sizeof(WCHAR)); // no terminating zero
- else
- ZeroMemory(pszStep, sizeof(WCHAR));
- pszStep = &pszStep[iSepLen];
- }
-
- // Add item
- CopyMemory(pszStep, psl->papszList[i], lstrlen(psl->papszList[i])*sizeof(WCHAR)); // no terminating zero
- pszStep = &pszStep[lstrlen(psl->papszList[i])];
- }
- LeaveCriticalSection(&psl->csListAccess);
-
- if (bAlsoDoLast)
- {
- if (pszSeparator)
- CopyMemory(pszStep, pszSeparator, iSepLen*sizeof(WCHAR)); // no terminating zero
- else
- ZeroMemory(pszStep, sizeof(WCHAR));
- pszStep = &pszStep[iSepLen];
- }
-
- ZeroMemory(pszStep, sizeof(WCHAR));
- return pszReturn;
-}
-
-void SLFreeReturn(void* pPntr)
-{
- if (pPntr) SLFree(pPntr);
-}
-
-BOOL SLConvertToStringBuf(LPSTRINGLIST psl, WCHAR* pszOutput, int cchMaxSize, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast)
-{
- BOOL bReturn;
- int iSize;
- WCHAR* pszBuf;
-
- if (!psl || !pszOutput || (cchMaxSize <= 0)) return FALSE;
- pszBuf = SLConvertToString(psl, pszSeparator, bAlsoDoFirst, bAlsoDoLast, &iSize);
- if (pszBuf) {
- if (cchMaxSize < iSize) iSize = cchMaxSize;
- CopyMemory(pszOutput, pszBuf, iSize*sizeof(WCHAR));
- SLFreeReturn(pszBuf);
- bReturn = TRUE;
- } else {
- iSize = 1;
- bReturn = FALSE;
- }
- if (cchMaxSize > 1)
- ZeroMemory(&pszOutput[iSize-1], sizeof(WCHAR));
- if (!pszSeparator && bAlsoDoLast && (cchMaxSize > 2))
- ZeroMemory(&pszOutput[iSize], sizeof(WCHAR));
- return bReturn;
-}
-
-
-BOOL SLMergeList(LPSTRINGLIST pslDest, LPSTRINGLIST pslFrom)
-{
- BOOL bReturn;
- int i;
-
- if (!pslDest || !pslFrom || (pslDest == pslFrom)) return FALSE;
- EnterCriticalSection(&pslFrom->csListAccess); // first list
- if (pslFrom->uCount == 0) {
- LeaveCriticalSection(&pslFrom->csListAccess);
- return TRUE;
- }
- EnterCriticalSection(&pslDest->csListAccess); // second list
- bReturn = FALSE;
- for (i=SL_MIN_POS; i<(int)(pslFrom->uCount); i++)
- if (SLAddItem(pslDest, pslFrom->papszList[i]) != SL_INVALID_POS)
- bReturn = TRUE;
- LeaveCriticalSection(&pslFrom->csListAccess); // first list
- LeaveCriticalSection(&pslDest->csListAccess); // second list
- return bReturn;
-}
-
-
-int SLFindItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive, int iStartPos)
-{
- int i, iReturn;
-
- if (!psl || !pszItem) return SL_INVALID_POS;
- EnterCriticalSection(&psl->csListAccess);
- if (!SLIsValid(psl, iStartPos)) {
- LeaveCriticalSection(&psl->csListAccess);
- return SL_INVALID_POS;
- }
- iReturn = SL_INVALID_POS;
- for (i=iStartPos; i<(int)psl->uCount; i++)
- if ((bCaseSensitive?StrCmp(psl->papszList[i], pszItem):StrCmpI(psl->papszList[i], pszItem)) == 0) {
- iReturn = i;
- break;
- }
- LeaveCriticalSection(&psl->csListAccess);
- return iReturn;
-}
-
-BOOL SLIsItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive)
-{
- return (SLFindItem(psl, pszItem, bCaseSensitive, SL_MIN_POS) != SL_INVALID_POS);
-}
-
-int SLAddItem(LPSTRINGLIST psl, const WCHAR* pszNewItem)
-{
- WCHAR** apszBuf;
- WCHAR* pszBuf;
- int i;
-
- if (!psl) return SL_INVALID_POS;
- EnterCriticalSection(&psl->csListAccess);
- if (((int)(psl->uCount+1) <= 0) || ((int)(psl->uCount+1) == psl->uCount)) {
- #if defined(_DEBUG)
- OutputDebugString(_T("Spam Filter: Stringlist overflow.\r\n"));
- DebugBreak();
- #endif
- LeaveCriticalSection(&psl->csListAccess);
- return SL_INVALID_POS;
- }
-
- // Create/Resize the array
- if (!psl->papszList) {
- apszBuf = (WCHAR**)SLAlloc(sizeof(WCHAR*));
- psl->uCount = 0;
- } else {
- apszBuf = (WCHAR**)SLReAlloc(psl->papszList, (psl->uCount+1)*sizeof(WCHAR*));
- }
- if (apszBuf) {
- psl->papszList = apszBuf;
- } else {
- LeaveCriticalSection(&psl->csListAccess);
- return SL_INVALID_POS;
- }
-
- // Prepare new string memory
- pszBuf = (WCHAR*)SLAlloc(((pszNewItem?lstrlen(pszNewItem):0)+1)*sizeof(WCHAR));
- if (!pszBuf) {
- LeaveCriticalSection(&psl->csListAccess);
- return SL_INVALID_POS;
- }
- // Prepare new string
- if (pszNewItem)
- CopyMemory(pszBuf, pszNewItem, (lstrlen(pszNewItem)+1)*sizeof(WCHAR));
- else
- ZeroMemory(pszBuf, sizeof(WCHAR));
-
- // Insert the new string
- i = psl->uCount;
- psl->papszList[i] = pszBuf;
- psl->uCount++;
-
- LeaveCriticalSection(&psl->csListAccess);
- return i;
-}
-
-int SLAddItemPair(LPSTRINGLIST psl, const WCHAR* pszNewItem1, const WCHAR* pszNewItem2)
-{
- int iPos;
-
- if (!psl) return SL_INVALID_POS;
- EnterCriticalSection(&psl->csListAccess);
- iPos = SLAddItem(psl, pszNewItem1);
- if (iPos != SL_INVALID_POS)
- if (SLAddItem(psl, pszNewItem2) == SL_INVALID_POS)
- SLDeleteItem(psl, iPos);
- LeaveCriticalSection(&psl->csListAccess);
- return iPos;
-}
-
-int SLPrepareItem(LPSTRINGLIST psl, int cchLength)
-{
- int iPos;
-
- if (!psl) return SL_INVALID_POS;
- EnterCriticalSection(&psl->csListAccess);
- iPos = SLAddItem(psl, NULL); // empty item
- if (iPos != SL_INVALID_POS)
- if (!SLSetItemLength(psl, iPos, cchLength)) {
- SLDeleteItem(psl, iPos);
- iPos = SL_INVALID_POS;
- }
- LeaveCriticalSection(&psl->csListAccess);
- return iPos;
-}
-
-/*
-BOOL SLAddItems(LPSTRINGLIST psl, const TCHAR* apszNewItems[], UINT uNewItemsCount)
-{
- int i;
- TCHAR** apszBuf;
-
- if (!psl || !apszNewItems || (uNewItemsCount <= 0))
- return FALSE;
-
- EnterCriticalSection(&psl->csListAccess);
-
- // Create/Resize the array
- if (!psl->papszList) {
- apszBuf = (TCHAR**)SLAlloc(uNewItemCount*sizeof(TCHAR*));
- psl->uCount = 0; // just to be sure
- } else {
- apszBuf = (TCHAR**)SLReAlloc(psl->papszList, (psl->uCount+uNewItemCount)*sizeof(TCHAR*));
- }
-
- if (apszBuf) {
- psl->papszList = apszBuf;
- } else {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
-
- // Insert the new string
- for (i=SL_MIN_POS; i<=iNewItemCount; i++)
- {
- psl->papszList[psl->uCount+i] = (TCHAR*)SLAlloc((lstrlen(apszNewItems[i])+1)*sizeof(TCHAR));
-
- if (psl->papszList[psl->uCount+i])
- {
- CopyMemory((PBYTE)psl->papszList[psl->uCount+i], apszNewItems[i], (lstrlen(apszNewItems[i])+1)*sizeof(TCHAR));
- // Increase list count
- psl->uCount++;
-
- } else {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-*/
-
-BOOL SLDeleteItems(LPSTRINGLIST psl, int iPosFirst, int iPosLast)
-{
- int i;
- WCHAR** apszBuf;
-
- if (!psl) return FALSE;
- if (iPosLast < iPosFirst) {
- i = iPosLast;
- iPosLast = iPosFirst;
- iPosFirst = i;
- }
- EnterCriticalSection(&psl->csListAccess);
- if (!SLIsValid(psl, iPosFirst) || !SLIsValid(psl, iPosLast)) {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
-
- for (i=iPosFirst; i<=iPosLast; i++)
- SLFree(psl->papszList[i]);
- if ((iPosLast+1) < (int)uMsgTypesCount)
- MoveMemory(&pamtdMsgTypes[iPosFirst], &pamtdMsgTypes[iPosLast+1], (iPosLast-iPosFirst+1)*sizeof(WCHAR));
-
- psl->uCount -= (iPosLast-iPosFirst+1);
-
- if (psl->papszList && (psl->uCount > 0)) {
- apszBuf = (WCHAR**)SLReAlloc(psl->papszList, psl->uCount*sizeof(WCHAR*));
- if (apszBuf) psl->papszList = apszBuf;
- } else {
- if (psl->papszList) SLFree(psl->papszList);
- psl->papszList = NULL;
- psl->uCount = 0;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-
-BOOL SLDeleteItem(LPSTRINGLIST psl, int iPos)
-{
- return SLDeleteItems(psl, iPos, iPos);
-}
-
-BOOL SLSetItemLength(LPSTRINGLIST psl, int iPos, int cchLength)
-{
- WCHAR* pszBuf;
- int iOldLen;
- BOOL bReturn;
-
- if (!psl) return FALSE;
- if (cchLength < 0) cchLength = 0;
- EnterCriticalSection(&psl->csListAccess);
- if (!SLIsValid(psl, iPos)) {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
-
- iOldLen = lstrlen(psl->papszList[iPos]);
- pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], (cchLength+1)*sizeof(WCHAR));
- if (pszBuf) {
- psl->papszList[iPos] = pszBuf;
- if (cchLength <= iOldLen)
- ZeroMemory(&pszBuf[cchLength], sizeof(WCHAR));
- else
- ZeroMemory(&pszBuf[iOldLen], (cchLength-iOldLen+1)*sizeof(WCHAR));
- bReturn = TRUE;
- } else {
- bReturn = FALSE;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-
-BOOL SLChangeItem(LPSTRINGLIST psl, int iPos, WCHAR* pszNewStr, BOOL bDoAppend)
-{
- BOOL bReturn;
- WCHAR* pszBuf;
-
- if (!psl) return FALSE;
- EnterCriticalSection(&psl->csListAccess);
- if (!SLIsValid(psl, iPos)) {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
-
- pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], ((pszNewStr?lstrlen(pszNewStr):0) + (bDoAppend?lstrlen(psl->papszList[iPos]):0) + 1)*sizeof(WCHAR));
- if (pszBuf)
- {
- psl->papszList[iPos] = pszBuf;
-
- if (bDoAppend && pszNewStr)
- CopyMemory(&pszBuf[lstrlen(pszBuf)], pszNewStr, (lstrlen(pszNewStr)+1)*sizeof(WCHAR));
- else if (pszNewStr)
- CopyMemory(pszBuf, pszNewStr, (lstrlen(pszNewStr)+1)*sizeof(WCHAR));
- else if (!bDoAppend)
- ZeroMemory(psl->papszList[iPos], sizeof(WCHAR));
-
- bReturn = TRUE;
- } else {
- if (!bDoAppend) ZeroMemory(psl->papszList[iPos], sizeof(WCHAR));
- bReturn = FALSE;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-
-
-BOOL SLItemPrintf(LPSTRINGLIST psl, int iPos, int cchArgMaxLen, ...)
-{
- BOOL bReturn = FALSE;
- WCHAR* pszBuf;
- WCHAR* pszFmt;
- va_list arglist;
-
- if (!psl) return FALSE;
- if (cchArgMaxLen < 0) cchArgMaxLen = 0;
- EnterCriticalSection(&psl->csListAccess);
- if (SLIsValid(psl, iPos))
- {
- pszFmt = (WCHAR*)SLAlloc((lstrlen(psl->papszList[iPos])+1)*sizeof(WCHAR));
- if (pszFmt)
- {
- CopyMemory(pszFmt, psl->papszList[iPos], (lstrlen(psl->papszList[iPos])+1)*sizeof(WCHAR));
- pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], (lstrlen(psl->papszList[iPos])+cchArgMaxLen+1)*sizeof(WCHAR));
- if (pszBuf)
- {
- psl->papszList[iPos] = pszBuf;
-
- va_start(arglist, cchArgMaxLen);
- mir_vsntprintf(pszBuf, lstrlen(pszBuf)+cchArgMaxLen+1, pszFmt, arglist);
- va_end(arglist);
-
- bReturn = TRUE;
- mir_free(pszFmt);
- }
- }
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-
-/*
-BOOL SLMoveItem(LPSTRINGLIST psl, int iOldPos, int iNewPos, BOOL bOnlySwitch)
-{
- TCHAR* pszBuf;
-
- if (!psl) return FALSE;
-
- EnterCriticalSection(&psl->csListAccess);
-
- if (!SLIsValid(psl, iOldPos) || !SLIsValid(psl, iNewPos)) {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
-
- if (iNewPos == iOldPos) {
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
- }
-
- if (bOnlySwitch)
- {
- // Switch the items
- pszBuf = psl->papszList[iOldPos];
- psl->papszList[iOldPos] = psl->papszList[iNewPos];
- psl->papszList[iOldPos] = pszBuf;
-
- } else {
-
- int i;
-
- // Cache the old item
- pszBuf = psl->papszList[iOldPos];
-
- if (iNewPos > iOldPos)
- {
- // Move items in between one down
- for (i=iNewPos; i<iOldPos; i++)
- psl->papszList[i+1] = psl->papszList[i];
- } else {
- // Move items in between one up
- for (i=(iOldPos+1); i<=iNewPos; i++)
- psl->papszList[i] = psl->papszList[i+1];
- }
-
- psl->papszList[iNewPos] = pszBuf;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-*/
-
-BOOL SLIsValid(LPSTRINGLIST psl, int iPos)
-{
- BOOL bReturn;
-
- if (!psl) return FALSE;
- EnterCriticalSection(&psl->csListAccess);
- bReturn = (psl->papszList && (iPos>=SL_MIN_POS) && (iPos<(int)psl->uCount));
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-WCHAR* SLGetItem(LPSTRINGLIST psl, int iPos)
-{
- WCHAR* pszReturn;
-
- EnterCriticalSection(&psl->csListAccess); // other operations finished
- pszReturn = SLIsValid(psl, iPos) ? psl->papszList[iPos] : NULL;
- LeaveCriticalSection(&psl->csListAccess);
- return pszReturn;
-}
-
-int SLGetMaxPos(LPSTRINGLIST psl)
-{
- int iReturn;
-
- if (!psl) return SL_INVALID_POS;
- EnterCriticalSection(&psl->csListAccess); // other operations finished
- iReturn = (psl->uCount > 0) ? (int)(psl->uCount-1) : SL_INVALID_POS;
- LeaveCriticalSection(&psl->csListAccess);
- return iReturn;
-}
-
-
-int SLGetItemCount(LPSTRINGLIST psl)
-{
- int iReturn;
- if (!psl) return 0;
-
- EnterCriticalSection(&psl->csListAccess); // other operations finished
- iReturn = (int)psl->uCount;
- LeaveCriticalSection(&psl->csListAccess);
- return iReturn;
-}
-
-
-int SLGetSize(LPSTRINGLIST psl, BOOL bAlsoTerminatingZeros) // character count size
-{
- int i, iReturn;
-
- if (!psl) return 0;
- EnterCriticalSection(&psl->csListAccess);
- iReturn = 0;
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- iReturn += lstrlen(psl->papszList[i]);
- if (bAlsoTerminatingZeros)
- iReturn += (int)psl->uCount;
- LeaveCriticalSection(&psl->csListAccess);
- return iReturn;
-}
-
-BOOL SLClearList(LPSTRINGLIST psl)
-{
- int i;
-
- if (!psl) return FALSE;
- EnterCriticalSection(&psl->csListAccess);
-
- // Free string memory
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- SLFree(psl->papszList[i]);
-
- // Free the array
- psl->uCount = 0;
- if (psl->papszList) SLFree(psl->papszList);
- psl->papszList = NULL;
-
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-
-/*
-BOOL SLBlockList(LPSTRINGLIST psl)
-{
- if (!psl) return FALSE;
- EnterCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-
-BOOL SLUnBlockList(LPSTRINGLIST psl)
-{
- if (!psl) return FALSE;
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-*/
-
-LPSTRINGLIST SLNewList(void)
-{
- LPSTRINGLIST psl = (LPSTRINGLIST)SLAlloc(sizeof(STRINGLIST));
- psl->papszList = NULL;
- psl->uCount = 0;
- InitializeCriticalSection(&psl->csListAccess);
- return psl;
-
-}
-
-void SLFreeList(LPSTRINGLIST psl)
-{
- if (!psl) return;
- SLClearList(psl);
- DeleteCriticalSection(&psl->csListAccess);
- SLFree(psl);
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -- Macros
+#define SLAlloc(s) mir_alloc(s)
+#define SLReAlloc(p, s) mir_realloc((p), (s))
+#define SLFree(p) mir_free(p)
+//#define SLAlloc(s) HeapAlloc(GetProcessHeap(), 0, (s))
+//#define SLReAlloc(p, s) HeapReAlloc(GetProcessHeap(), 0, (p), (s))
+//#define SLFree(p) HeapFree(GetProcessHeap(), 0, (p))
+
+
+// -----------------------------------------
+
+
+BOOL SLAssignToListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox)
+{
+ BOOL bReturn = FALSE;
+ int i;
+
+ if (!psl || !hwndListBox) return FALSE;
+ SendMessage(hwndListBox, LB_RESETCONTENT, 0, 0);
+ SendMessage(hwndListBox, LB_INITSTORAGE, (WPARAM)psl->uCount, (LPARAM)(SLGetSize(psl, TRUE)*sizeof(WCHAR)));
+ EnterCriticalSection(&psl->csListAccess);
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ if (SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)psl->papszList[i]) >= 0)
+ bReturn = TRUE;
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+BOOL SLRetrieveFromListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox)
+{
+ int iCount, i, iPos;
+ BOOL bReturn;
+
+ if (!psl || !hwndListBox) return FALSE;
+ bReturn = FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+ iCount = SendMessage(hwndListBox, LB_GETCOUNT, 0, 0);
+ for (i=0; i<iCount; i++)
+ {
+ iPos = SLPrepareItem(psl, SendMessage(hwndListBox, LB_GETTEXTLEN, (WPARAM)i, 0));
+ if (iPos != SL_INVALID_POS)
+ {
+ if (SendMessage(hwndListBox, LB_GETTEXT, (WPARAM)i, (LPARAM)psl->papszList[iPos]) != LB_ERR)
+ bReturn = TRUE;
+ else
+ SLDeleteItem(psl, iPos);
+ }
+ }
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+/*
+BOOL SLLoadFromIniFile(LPSTRINGLIST psl, const TCHAR* pszSearchPath, const TCHAR* pszSection, const TCHAR* pszSettingPrefix)
+{
+ TCHAR szFile[MAX_PATH];
+ BOOL bFileFound;
+ BOOL bReturn = FALSE;
+ int i, iLen, iSize;
+ TCHAR* pszItem;
+ TCHAR* pszBuf;
+ WIN32_FIND_DATA wfd;
+ HANDLE hFind;
+
+ if (!psl || !pszSection || !pszSearchPath)
+ return FALSE;
+
+ ZeroMemory(&wfd, sizeof(wfd));
+
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Enum all files in the directory
+ hFind = FindFirstFile(pszSearchPath, &wfd);
+ for (bFileFound=(hFind!=INVALID_HANDLE_VALUE); bFileFound; bFileFound=FindNextFile(hFind, &wfd))
+ {
+ if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ // Construct the file name
+ mir_sntprintf(szFile, ARRAYSIZE(szFile), _T("%s"), pszSearchPath);
+ PathRemoveFileSpec(szFile);
+ PathAppend(szFile, wfd.cFileName);
+
+ // Load the data from ini file
+ iSize = (pszSettingPrefix?(lstrlen(pszSettingPrefix)+1):0)+MAX_INT_LENGTH+1);
+ pszItem = (TCHAR*)mir_alloc(iSize*sizeof(TCHAR));
+ if (!pszItem) continue;
+
+ for (i=SL_MIN_POS;;i++) // no break condition
+ {
+ mir_sntprintf(pszItem, _T("%s%s%i"), iSize, pszSettingPrefix?pszSettingPrefix:_T(""), pszSettingPrefix?_T("|"):_T(""), i);
+
+ iLen = GetPrivateProfileString(pszSection, pszItem, NULL, NULL, 0, szFile);
+ if (iLen < 0) break;
+
+ pszBuf = (TCHAR*)mir_alloc((iLen+1)*sizeof(TCHAR));
+ if (!pszBuf) continue;
+
+ GetPrivateProfileString(pszSection, pszItem, NULL, pszBuf, iLen, szFile);
+ if (lstrlen(pszBuf) <= 0) break;
+
+ if (SLAddItem(psl, pszBuf) != SL_INVALID_POS)
+ if (!bReturn) bReturn = TRUE;
+
+ mir_free(pszBuf);
+ }
+
+ mir_free(pszItem);
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+
+ if (hFind) FindClose(hFind);
+
+ return bReturn;
+}
+
+
+
+BOOL SLSaveToIniFile(LPSTRINGLIST psl, const TCHAR* pszFileName, const TCHAR* pszSection, const TCHAR* pszSettingPrefix)
+{
+ int i;
+ char* pszItem;
+ int iSize;
+ BOOL bReturn = FALSE;
+
+ if (!psl || !pszSection || !pszFileName)
+ return FALSE;
+
+ iSize = (pszSettingPrefix?(lstrlen(pszSettingPrefix)+1):0)+MAX_INT_LENGTH+1;
+ pszItem = (TCHAR*)mir_alloc(iSize*sizeof(TCHAR));
+
+ if (pszItem)
+ {
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Delete old items (empty section)
+ WritePrivateProfileString(pszSection, NULL, NULL, pszFileName);
+
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ {
+ mir_sntprintf(pszItem, iSize, _T("%s%s%i"), pszSettingPrefix?pszSettingPrefix:_T(""), pszSettingPrefix?_T("|"):_T(""), i);
+
+ if (WritePrivateProfileString(pszSection, pszItem, psl->papszList[i], pszFileName))
+ bReturn = TRUE;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+
+ mir_free(pszItem);
+ }
+
+ return bReturn;
+}
+*/
+
+
+BOOL SLLoadFromFile(LPSTRINGLIST psl, const WCHAR* pszSearchPath)
+{
+ BOOL bReturn;
+ WIN32_FIND_DATA wfd;
+ HANDLE hFind;
+ BOOL bFileFound;
+ WCHAR szFile[MAX_PATH];
+ HANDLE hFile;
+ DWORD dwRead;
+ int iAllocBufSize;
+ int iAllocBufStep;
+ char* pszAllocBuf;
+ char* pszAllocBufTmp;
+ const char szBOM[3] = {0xEF, 0xBB, 0xBF};
+ BOOL bWatchBOM;
+ BOOL bEndOfFile;
+ WCHAR* pszContentConv;
+ WCHAR* pszBuf;
+
+ if (!psl || !pszSearchPath) return FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Initial buffer size (gets auto-enlarged if needed)
+ iAllocBufSize = 128; // read-in chars buffer
+ pszAllocBuf = NULL;
+
+ // Enum all files in the directory
+ bReturn = FALSE;
+ hFind = FindFirstFile(pszSearchPath, &wfd);
+ for (bFileFound=(hFind!=INVALID_HANDLE_VALUE); bFileFound; bFileFound=FindNextFile(hFind, &wfd))
+ {
+ if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+ mir_sntprintf(szFile, ARRAYSIZE(szFile), _T("%s"), pszSearchPath);
+ PathRemoveFileSpec(szFile);
+ PathAppend(szFile, wfd.cFileName);
+
+ hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) continue;
+ bWatchBOM = TRUE;
+ bEndOfFile = FALSE;
+ iAllocBufStep = 0;
+ while (!bEndOfFile)
+ {
+ // Enlarge buffer if needed
+ if (!pszAllocBuf || (iAllocBufStep >= iAllocBufSize))
+ {
+ pszAllocBufTmp = (char*)mir_realloc(pszAllocBuf, (iAllocBufSize*2)*sizeof(char));
+ if (pszAllocBufTmp) {
+ if (pszAllocBuf) iAllocBufSize *= 2;
+ pszAllocBuf = pszAllocBufTmp;
+ } else {
+ bEndOfFile = TRUE; // out of memory
+ }
+ }
+ if (!bEndOfFile) {
+ if (!ReadFile(hFile, &pszAllocBuf[iAllocBufStep], sizeof(char), &dwRead, NULL))
+ bEndOfFile = TRUE;
+ if (dwRead < sizeof(char))
+ bEndOfFile = TRUE;
+ }
+ if ((pszAllocBuf[iAllocBufStep] == '\n') || bEndOfFile)
+ {
+ if (!bEndOfFile && (iAllocBufStep>0) && (pszAllocBuf[iAllocBufStep-1] == '\r'))
+ pszAllocBuf[iAllocBufStep-1] = '\0';
+ else
+ pszAllocBuf[iAllocBufStep] = '\0';
+
+ if (lstrlenA(pszAllocBuf) > 0)
+ {
+ // Test UTF-8 BOM
+ // EF BB BF = UTF-8
+ // -> indicating UTF-8 Unicode text file (check only once)
+ if (bWatchBOM)
+ {
+ if (StrCmpNA(pszAllocBuf, szBOM, ARRAYSIZE(szBOM)) == 0)
+ MoveMemory(pszAllocBuf, (PBYTE)pszAllocBuf+sizeof(szBOM), ((lstrlenA(pszAllocBuf)+1)*sizeof(char))-sizeof(szBOM));
+ bWatchBOM = FALSE;
+ }
+
+ // Decode Utf8
+ mir_utf8decode(pszAllocBuf,&pszContentConv);
+ if (pszContentConv)
+ {
+ pszBuf = pszContentConv;
+ while (pszBuf)
+ {
+ // Find comment indicator
+ pszBuf = StrChr(pszBuf, _T(';')); // find ";" comment indicator
+ if (pszBuf && (*CharPrev(pszContentConv, pszBuf) != _T('\\'))) // ignore "\;" chars
+ {
+ *pszBuf = _T('\0');
+ break;
+ }
+ }
+
+ // Replace no-comment indicators
+ pszBuf = ReplaceSubStringWithString(pszContentConv, _T("\\;"), _T(";"), TRUE, FALSE, NULL);
+
+ // Add item to list (disallow empty items)
+ if (lstrlen(pszContentConv) > 0)
+ if (SLAddItem(psl, pszBuf?pszBuf:pszContentConv) >= 0)
+ bReturn = TRUE;
+
+ mir_free(pszContentConv);
+ if (pszBuf) mir_free(pszBuf);
+ }
+ }
+
+ // Reset step count
+ iAllocBufStep = 0;
+
+ } else {
+ // Step up in string
+ iAllocBufStep++;
+ }
+
+ } // while (!bEndOfFile)
+
+ CloseHandle(hFile);
+ }
+
+ if (hFind) FindClose(hFind);
+ if (pszAllocBuf) mir_free(pszAllocBuf);
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+
+BOOL SLSaveToFile(LPSTRINGLIST psl, const WCHAR* pszFileName)
+{
+ BOOL bReturn;
+ int i;
+ const char szBOM[3] = {0xEF, 0xBB, 0xBF};
+ HANDLE hFile;
+ DWORD dwWritten; // Win98 compatibility
+ WCHAR* pszBuf;
+ char* pszContentUtf8;
+
+ if (!psl || !pszFileName) return FALSE;
+ hFile = CreateFile(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) return FALSE;
+ bReturn = FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Write UTF-8 BOM
+ // EF BB BF = UTF-8
+ // -> indicating UTF-8 Unicode text file
+ if (WriteFile(hFile, &szBOM, sizeof(szBOM), &dwWritten, NULL))
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ {
+ // Replace comment indicators
+ pszBuf = ReplaceSubStringWithString(psl->papszList[i], _T(";"), _T("\\;"), TRUE, FALSE, NULL);
+ if (!pszBuf) continue;
+ pszContentUtf8 = mir_utf8encodeW(pszBuf);
+ if (pszContentUtf8) {
+ if (WriteFile(hFile, pszContentUtf8, lstrlenA(pszContentUtf8)*sizeof(char), &dwWritten, NULL))
+ if (WriteFile(hFile, "\r\n", 2*sizeof(char), &dwWritten, NULL))
+ bReturn = TRUE;
+ mir_free(pszContentUtf8);
+ }
+ mir_free(pszBuf);
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ SetEndOfFile(hFile); // if it was longer before
+ FlushFileBuffers(hFile); // just to be sure
+ CloseHandle(hFile);
+ return bReturn;
+}
+
+
+/*
+BOOL SLConvertFromString(LPSTRINGLIST psl, const TCHAR* pszString, int cchSize, const TCHAR* pszSeparator, BOOL bIgnoreEmptyItems)
+{
+ // If pszSeparator is NULL a _T('\0') is taken as separator
+ BOOL bReturn;
+ int cchSepLen;
+
+ BOOL bReachedEnd;
+ TCHAR* pszAfterPrev;
+ TCHAR* pszNext;
+ int iPos;
+
+ if (!pszString || !psl) return 0;
+
+ if (cchSize < 0) cchSize = lstrlen(pszString)+1;
+ cchSepLen = pszSeparator?lstrlen(pszSeparator):1;
+
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Loop through string
+ bReturn = 0;
+ pszAfterPrev = (TCHAR*)pszString;
+ bReachedEnd = FALSE;
+ while (!bReachedEnd)
+ {
+ // Find first/next occurence
+ if (pszSeparator)
+ {
+ pszNext = StrStr(pszAfterPrev, pszSeparator);
+ if (!pszNext)
+ {
+ bReachedEnd = TRUE;
+ pszNext = (TCHAR*)pszString+(cchSize*sizeof(TCHAR));
+ }
+
+ } else {
+
+ // Find NULL separator
+ pszNext = pszAfterPrev;
+ while (*pszNext != _T('\0'));
+ {
+ pszNext = CharNext(pszNext);
+ if ( pszNext >= (szString+((cchSize-1)*sizeof(TCHAR)) )
+ {
+ bReachedEnd = TRUE;
+ break;
+ }
+ }
+ }
+
+ // Add item
+ if (!bIgnoreEmptyItems || (pszNext != pszAfterPrev))
+ {
+ i2
+ if (iPos < 0) continue;
+ CopyMemory((PBYTE)psl->papszList[iPos], pszAfterPrev, ((PBYTE)pszNext-(PBYTE)pszAfterPrev));
+
+ bReturn = TRUE;
+ }
+
+ // Step up one separated item
+ pszAfterPrev = pszNext+(cchSepLen*sizeof(TCHAR));
+ if ( pszAfterPrev >= pszString+((cchSize-1)*sizeof(TCHAR)) )
+ bReachedEnd = TRUE;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+
+ return bReturn;
+}
+*/
+
+
+WCHAR* SLConvertToString(LPSTRINGLIST psl, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast, int* piSize)
+{
+ // Returned string needs to be freed with SLFreeReturn()
+ // If pszSeparator is NULL a _T('\0') is taken as separator
+
+ int i;
+ int iSepLen;
+ int iSize;
+ WCHAR* pszReturn;
+ WCHAR* pszStep;
+
+ if (piSize) *piSize = 0;
+ if (!psl) return NULL;
+
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Get needed size
+ iSepLen = pszSeparator?lstrlen(pszSeparator):1;
+ iSize = SLGetSize(psl, FALSE)+1; // character count in string list
+ if (psl->uCount > 0) iSize += (psl->uCount-1)*iSepLen;
+ if ((psl->uCount > 0) && bAlsoDoFirst) iSize += iSepLen;
+ if (bAlsoDoLast) iSize += iSepLen;
+
+ pszReturn = (WCHAR*)SLAlloc(iSize*sizeof(WCHAR));
+ if (!pszReturn) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return NULL;
+ }
+ if (piSize) *piSize = iSize;
+
+ // Add items to memory
+ pszStep = pszReturn;
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ {
+ if ((i>SL_MIN_POS) || bAlsoDoFirst)
+ {
+ if (pszSeparator)
+ CopyMemory(pszStep, pszSeparator, iSepLen*sizeof(WCHAR)); // no terminating zero
+ else
+ ZeroMemory(pszStep, sizeof(WCHAR));
+ pszStep = &pszStep[iSepLen];
+ }
+
+ // Add item
+ CopyMemory(pszStep, psl->papszList[i], lstrlen(psl->papszList[i])*sizeof(WCHAR)); // no terminating zero
+ pszStep = &pszStep[lstrlen(psl->papszList[i])];
+ }
+ LeaveCriticalSection(&psl->csListAccess);
+
+ if (bAlsoDoLast)
+ {
+ if (pszSeparator)
+ CopyMemory(pszStep, pszSeparator, iSepLen*sizeof(WCHAR)); // no terminating zero
+ else
+ ZeroMemory(pszStep, sizeof(WCHAR));
+ pszStep = &pszStep[iSepLen];
+ }
+
+ ZeroMemory(pszStep, sizeof(WCHAR));
+ return pszReturn;
+}
+
+void SLFreeReturn(void* pPntr)
+{
+ if (pPntr) SLFree(pPntr);
+}
+
+BOOL SLConvertToStringBuf(LPSTRINGLIST psl, WCHAR* pszOutput, int cchMaxSize, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast)
+{
+ BOOL bReturn;
+ int iSize;
+ WCHAR* pszBuf;
+
+ if (!psl || !pszOutput || (cchMaxSize <= 0)) return FALSE;
+ pszBuf = SLConvertToString(psl, pszSeparator, bAlsoDoFirst, bAlsoDoLast, &iSize);
+ if (pszBuf) {
+ if (cchMaxSize < iSize) iSize = cchMaxSize;
+ CopyMemory(pszOutput, pszBuf, iSize*sizeof(WCHAR));
+ SLFreeReturn(pszBuf);
+ bReturn = TRUE;
+ } else {
+ iSize = 1;
+ bReturn = FALSE;
+ }
+ if (cchMaxSize > 1)
+ ZeroMemory(&pszOutput[iSize-1], sizeof(WCHAR));
+ if (!pszSeparator && bAlsoDoLast && (cchMaxSize > 2))
+ ZeroMemory(&pszOutput[iSize], sizeof(WCHAR));
+ return bReturn;
+}
+
+
+BOOL SLMergeList(LPSTRINGLIST pslDest, LPSTRINGLIST pslFrom)
+{
+ BOOL bReturn;
+ int i;
+
+ if (!pslDest || !pslFrom || (pslDest == pslFrom)) return FALSE;
+ EnterCriticalSection(&pslFrom->csListAccess); // first list
+ if (pslFrom->uCount == 0) {
+ LeaveCriticalSection(&pslFrom->csListAccess);
+ return TRUE;
+ }
+ EnterCriticalSection(&pslDest->csListAccess); // second list
+ bReturn = FALSE;
+ for (i=SL_MIN_POS; i<(int)(pslFrom->uCount); i++)
+ if (SLAddItem(pslDest, pslFrom->papszList[i]) != SL_INVALID_POS)
+ bReturn = TRUE;
+ LeaveCriticalSection(&pslFrom->csListAccess); // first list
+ LeaveCriticalSection(&pslDest->csListAccess); // second list
+ return bReturn;
+}
+
+
+int SLFindItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive, int iStartPos)
+{
+ int i, iReturn;
+
+ if (!psl || !pszItem) return SL_INVALID_POS;
+ EnterCriticalSection(&psl->csListAccess);
+ if (!SLIsValid(psl, iStartPos)) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return SL_INVALID_POS;
+ }
+ iReturn = SL_INVALID_POS;
+ for (i=iStartPos; i<(int)psl->uCount; i++)
+ if ((bCaseSensitive?StrCmp(psl->papszList[i], pszItem):StrCmpI(psl->papszList[i], pszItem)) == 0) {
+ iReturn = i;
+ break;
+ }
+ LeaveCriticalSection(&psl->csListAccess);
+ return iReturn;
+}
+
+BOOL SLIsItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive)
+{
+ return (SLFindItem(psl, pszItem, bCaseSensitive, SL_MIN_POS) != SL_INVALID_POS);
+}
+
+int SLAddItem(LPSTRINGLIST psl, const WCHAR* pszNewItem)
+{
+ WCHAR** apszBuf;
+ WCHAR* pszBuf;
+ int i;
+
+ if (!psl) return SL_INVALID_POS;
+ EnterCriticalSection(&psl->csListAccess);
+ if (((int)(psl->uCount+1) <= 0) || ((int)(psl->uCount+1) == psl->uCount)) {
+ #if defined(_DEBUG)
+ OutputDebugString(_T("Spam Filter: Stringlist overflow.\r\n"));
+ DebugBreak();
+ #endif
+ LeaveCriticalSection(&psl->csListAccess);
+ return SL_INVALID_POS;
+ }
+
+ // Create/Resize the array
+ if (!psl->papszList) {
+ apszBuf = (WCHAR**)SLAlloc(sizeof(WCHAR*));
+ psl->uCount = 0;
+ } else {
+ apszBuf = (WCHAR**)SLReAlloc(psl->papszList, (psl->uCount+1)*sizeof(WCHAR*));
+ }
+ if (apszBuf) {
+ psl->papszList = apszBuf;
+ } else {
+ LeaveCriticalSection(&psl->csListAccess);
+ return SL_INVALID_POS;
+ }
+
+ // Prepare new string memory
+ pszBuf = (WCHAR*)SLAlloc(((pszNewItem?lstrlen(pszNewItem):0)+1)*sizeof(WCHAR));
+ if (!pszBuf) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return SL_INVALID_POS;
+ }
+ // Prepare new string
+ if (pszNewItem)
+ CopyMemory(pszBuf, pszNewItem, (lstrlen(pszNewItem)+1)*sizeof(WCHAR));
+ else
+ ZeroMemory(pszBuf, sizeof(WCHAR));
+
+ // Insert the new string
+ i = psl->uCount;
+ psl->papszList[i] = pszBuf;
+ psl->uCount++;
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return i;
+}
+
+int SLAddItemPair(LPSTRINGLIST psl, const WCHAR* pszNewItem1, const WCHAR* pszNewItem2)
+{
+ int iPos;
+
+ if (!psl) return SL_INVALID_POS;
+ EnterCriticalSection(&psl->csListAccess);
+ iPos = SLAddItem(psl, pszNewItem1);
+ if (iPos != SL_INVALID_POS)
+ if (SLAddItem(psl, pszNewItem2) == SL_INVALID_POS)
+ SLDeleteItem(psl, iPos);
+ LeaveCriticalSection(&psl->csListAccess);
+ return iPos;
+}
+
+int SLPrepareItem(LPSTRINGLIST psl, int cchLength)
+{
+ int iPos;
+
+ if (!psl) return SL_INVALID_POS;
+ EnterCriticalSection(&psl->csListAccess);
+ iPos = SLAddItem(psl, NULL); // empty item
+ if (iPos != SL_INVALID_POS)
+ if (!SLSetItemLength(psl, iPos, cchLength)) {
+ SLDeleteItem(psl, iPos);
+ iPos = SL_INVALID_POS;
+ }
+ LeaveCriticalSection(&psl->csListAccess);
+ return iPos;
+}
+
+/*
+BOOL SLAddItems(LPSTRINGLIST psl, const TCHAR* apszNewItems[], UINT uNewItemsCount)
+{
+ int i;
+ TCHAR** apszBuf;
+
+ if (!psl || !apszNewItems || (uNewItemsCount <= 0))
+ return FALSE;
+
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Create/Resize the array
+ if (!psl->papszList) {
+ apszBuf = (TCHAR**)SLAlloc(uNewItemCount*sizeof(TCHAR*));
+ psl->uCount = 0; // just to be sure
+ } else {
+ apszBuf = (TCHAR**)SLReAlloc(psl->papszList, (psl->uCount+uNewItemCount)*sizeof(TCHAR*));
+ }
+
+ if (apszBuf) {
+ psl->papszList = apszBuf;
+ } else {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+
+ // Insert the new string
+ for (i=SL_MIN_POS; i<=iNewItemCount; i++)
+ {
+ psl->papszList[psl->uCount+i] = (TCHAR*)SLAlloc((lstrlen(apszNewItems[i])+1)*sizeof(TCHAR));
+
+ if (psl->papszList[psl->uCount+i])
+ {
+ CopyMemory((PBYTE)psl->papszList[psl->uCount+i], apszNewItems[i], (lstrlen(apszNewItems[i])+1)*sizeof(TCHAR));
+ // Increase list count
+ psl->uCount++;
+
+ } else {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+*/
+
+BOOL SLDeleteItems(LPSTRINGLIST psl, int iPosFirst, int iPosLast)
+{
+ int i;
+ WCHAR** apszBuf;
+
+ if (!psl) return FALSE;
+ if (iPosLast < iPosFirst) {
+ i = iPosLast;
+ iPosLast = iPosFirst;
+ iPosFirst = i;
+ }
+ EnterCriticalSection(&psl->csListAccess);
+ if (!SLIsValid(psl, iPosFirst) || !SLIsValid(psl, iPosLast)) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+
+ for (i=iPosFirst; i<=iPosLast; i++)
+ SLFree(psl->papszList[i]);
+ if ((iPosLast+1) < (int)uMsgTypesCount)
+ MoveMemory(&pamtdMsgTypes[iPosFirst], &pamtdMsgTypes[iPosLast+1], (iPosLast-iPosFirst+1)*sizeof(WCHAR));
+
+ psl->uCount -= (iPosLast-iPosFirst+1);
+
+ if (psl->papszList && (psl->uCount > 0)) {
+ apszBuf = (WCHAR**)SLReAlloc(psl->papszList, psl->uCount*sizeof(WCHAR*));
+ if (apszBuf) psl->papszList = apszBuf;
+ } else {
+ if (psl->papszList) SLFree(psl->papszList);
+ psl->papszList = NULL;
+ psl->uCount = 0;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+
+BOOL SLDeleteItem(LPSTRINGLIST psl, int iPos)
+{
+ return SLDeleteItems(psl, iPos, iPos);
+}
+
+BOOL SLSetItemLength(LPSTRINGLIST psl, int iPos, int cchLength)
+{
+ WCHAR* pszBuf;
+ int iOldLen;
+ BOOL bReturn;
+
+ if (!psl) return FALSE;
+ if (cchLength < 0) cchLength = 0;
+ EnterCriticalSection(&psl->csListAccess);
+ if (!SLIsValid(psl, iPos)) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+
+ iOldLen = lstrlen(psl->papszList[iPos]);
+ pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], (cchLength+1)*sizeof(WCHAR));
+ if (pszBuf) {
+ psl->papszList[iPos] = pszBuf;
+ if (cchLength <= iOldLen)
+ ZeroMemory(&pszBuf[cchLength], sizeof(WCHAR));
+ else
+ ZeroMemory(&pszBuf[iOldLen], (cchLength-iOldLen+1)*sizeof(WCHAR));
+ bReturn = TRUE;
+ } else {
+ bReturn = FALSE;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+
+BOOL SLChangeItem(LPSTRINGLIST psl, int iPos, WCHAR* pszNewStr, BOOL bDoAppend)
+{
+ BOOL bReturn;
+ WCHAR* pszBuf;
+
+ if (!psl) return FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+ if (!SLIsValid(psl, iPos)) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+
+ pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], ((pszNewStr?lstrlen(pszNewStr):0) + (bDoAppend?lstrlen(psl->papszList[iPos]):0) + 1)*sizeof(WCHAR));
+ if (pszBuf)
+ {
+ psl->papszList[iPos] = pszBuf;
+
+ if (bDoAppend && pszNewStr)
+ CopyMemory(&pszBuf[lstrlen(pszBuf)], pszNewStr, (lstrlen(pszNewStr)+1)*sizeof(WCHAR));
+ else if (pszNewStr)
+ CopyMemory(pszBuf, pszNewStr, (lstrlen(pszNewStr)+1)*sizeof(WCHAR));
+ else if (!bDoAppend)
+ ZeroMemory(psl->papszList[iPos], sizeof(WCHAR));
+
+ bReturn = TRUE;
+ } else {
+ if (!bDoAppend) ZeroMemory(psl->papszList[iPos], sizeof(WCHAR));
+ bReturn = FALSE;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+
+
+BOOL SLItemPrintf(LPSTRINGLIST psl, int iPos, int cchArgMaxLen, ...)
+{
+ BOOL bReturn = FALSE;
+ WCHAR* pszBuf;
+ WCHAR* pszFmt;
+ va_list arglist;
+
+ if (!psl) return FALSE;
+ if (cchArgMaxLen < 0) cchArgMaxLen = 0;
+ EnterCriticalSection(&psl->csListAccess);
+ if (SLIsValid(psl, iPos))
+ {
+ pszFmt = (WCHAR*)SLAlloc((lstrlen(psl->papszList[iPos])+1)*sizeof(WCHAR));
+ if (pszFmt)
+ {
+ CopyMemory(pszFmt, psl->papszList[iPos], (lstrlen(psl->papszList[iPos])+1)*sizeof(WCHAR));
+ pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], (lstrlen(psl->papszList[iPos])+cchArgMaxLen+1)*sizeof(WCHAR));
+ if (pszBuf)
+ {
+ psl->papszList[iPos] = pszBuf;
+
+ va_start(arglist, cchArgMaxLen);
+ mir_vsntprintf(pszBuf, lstrlen(pszBuf)+cchArgMaxLen+1, pszFmt, arglist);
+ va_end(arglist);
+
+ bReturn = TRUE;
+ mir_free(pszFmt);
+ }
+ }
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+
+/*
+BOOL SLMoveItem(LPSTRINGLIST psl, int iOldPos, int iNewPos, BOOL bOnlySwitch)
+{
+ TCHAR* pszBuf;
+
+ if (!psl) return FALSE;
+
+ EnterCriticalSection(&psl->csListAccess);
+
+ if (!SLIsValid(psl, iOldPos) || !SLIsValid(psl, iNewPos)) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+
+ if (iNewPos == iOldPos) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+ }
+
+ if (bOnlySwitch)
+ {
+ // Switch the items
+ pszBuf = psl->papszList[iOldPos];
+ psl->papszList[iOldPos] = psl->papszList[iNewPos];
+ psl->papszList[iOldPos] = pszBuf;
+
+ } else {
+
+ int i;
+
+ // Cache the old item
+ pszBuf = psl->papszList[iOldPos];
+
+ if (iNewPos > iOldPos)
+ {
+ // Move items in between one down
+ for (i=iNewPos; i<iOldPos; i++)
+ psl->papszList[i+1] = psl->papszList[i];
+ } else {
+ // Move items in between one up
+ for (i=(iOldPos+1); i<=iNewPos; i++)
+ psl->papszList[i] = psl->papszList[i+1];
+ }
+
+ psl->papszList[iNewPos] = pszBuf;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+*/
+
+BOOL SLIsValid(LPSTRINGLIST psl, int iPos)
+{
+ BOOL bReturn;
+
+ if (!psl) return FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+ bReturn = (psl->papszList && (iPos>=SL_MIN_POS) && (iPos<(int)psl->uCount));
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+WCHAR* SLGetItem(LPSTRINGLIST psl, int iPos)
+{
+ WCHAR* pszReturn;
+
+ EnterCriticalSection(&psl->csListAccess); // other operations finished
+ pszReturn = SLIsValid(psl, iPos) ? psl->papszList[iPos] : NULL;
+ LeaveCriticalSection(&psl->csListAccess);
+ return pszReturn;
+}
+
+int SLGetMaxPos(LPSTRINGLIST psl)
+{
+ int iReturn;
+
+ if (!psl) return SL_INVALID_POS;
+ EnterCriticalSection(&psl->csListAccess); // other operations finished
+ iReturn = (psl->uCount > 0) ? (int)(psl->uCount-1) : SL_INVALID_POS;
+ LeaveCriticalSection(&psl->csListAccess);
+ return iReturn;
+}
+
+
+int SLGetItemCount(LPSTRINGLIST psl)
+{
+ int iReturn;
+ if (!psl) return 0;
+
+ EnterCriticalSection(&psl->csListAccess); // other operations finished
+ iReturn = (int)psl->uCount;
+ LeaveCriticalSection(&psl->csListAccess);
+ return iReturn;
+}
+
+
+int SLGetSize(LPSTRINGLIST psl, BOOL bAlsoTerminatingZeros) // character count size
+{
+ int i, iReturn;
+
+ if (!psl) return 0;
+ EnterCriticalSection(&psl->csListAccess);
+ iReturn = 0;
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ iReturn += lstrlen(psl->papszList[i]);
+ if (bAlsoTerminatingZeros)
+ iReturn += (int)psl->uCount;
+ LeaveCriticalSection(&psl->csListAccess);
+ return iReturn;
+}
+
+BOOL SLClearList(LPSTRINGLIST psl)
+{
+ int i;
+
+ if (!psl) return FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Free string memory
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ SLFree(psl->papszList[i]);
+
+ // Free the array
+ psl->uCount = 0;
+ if (psl->papszList) SLFree(psl->papszList);
+ psl->papszList = NULL;
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+
+/*
+BOOL SLBlockList(LPSTRINGLIST psl)
+{
+ if (!psl) return FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+
+BOOL SLUnBlockList(LPSTRINGLIST psl)
+{
+ if (!psl) return FALSE;
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+*/
+
+LPSTRINGLIST SLNewList(void)
+{
+ LPSTRINGLIST psl = (LPSTRINGLIST)SLAlloc(sizeof(STRINGLIST));
+ psl->papszList = NULL;
+ psl->uCount = 0;
+ InitializeCriticalSection(&psl->csListAccess);
+ return psl;
+
+}
+
+void SLFreeList(LPSTRINGLIST psl)
+{
+ if (!psl) return;
+ SLClearList(psl);
+ DeleteCriticalSection(&psl->csListAccess);
+ SLFree(psl);
} \ No newline at end of file
diff --git a/stringlist.h b/stringlist.h
index ec10883..1200491 100644
--- a/stringlist.h
+++ b/stringlist.h
@@ -1,81 +1,81 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_STRINGLIST_H__
-#define SF_STRINGLIST_H__ 1
-
-
-// -- Structs
-typedef struct {
- UINT uCount; // protected by csListAccess
- WCHAR** papszList; // protected by csListAccess
- CRITICAL_SECTION csListAccess;
-} STRINGLIST, *LPSTRINGLIST;
-
-// -- Defines
-#define SL_MIN_POS 0
-#define SL_INVALID_POS (-1)
-
-// -- Prototypes
-LPSTRINGLIST SLNewList(void);
-void SLFreeList(LPSTRINGLIST psl);
-BOOL SLClearList(LPSTRINGLIST psl);
-BOOL SLMergeList(LPSTRINGLIST pslDest, LPSTRINGLIST pslFrom);
-
-int SLGetMaxPos(LPSTRINGLIST psl);
-int SLGetSize(LPSTRINGLIST psl, BOOL bAlsoTerminatingZeros); // character count size
-int SLGetItemCount(LPSTRINGLIST psl);
-WCHAR* SLGetItem(LPSTRINGLIST psl, int iPos);
-BOOL SLIsValid(LPSTRINGLIST psl, int iPos);
-
-BOOL SLMoveItem(LPSTRINGLIST psl, int iOldPos, int iNewPos, BOOL bOnlySwitch);
-BOOL SLItemPrintf(LPSTRINGLIST psl, int iPos, int cchArgMaxLen, ...);
-BOOL SLSetItemLength(LPSTRINGLIST psl, int iPos, int cchLength);
-BOOL SLChangeItem(LPSTRINGLIST psl, int iPos, WCHAR* pszNewStr, BOOL bDoAppend);
-
-BOOL SLDeleteItem(LPSTRINGLIST psl, int iPos);
-BOOL SLDeleteItems(LPSTRINGLIST psl, int iPosFirst, int iPosLast);
-
-BOOL SLAddItems(LPSTRINGLIST psl, const WCHAR* apszNewItems[], UINT uNewItemsCount);
-int SLAddItem(LPSTRINGLIST psl, const WCHAR* pszNewItem);
-int SLAddItemPair(LPSTRINGLIST psl, const WCHAR* pszNewItem1, const WCHAR* pszNewItem2);
-int SLPrepareItem(LPSTRINGLIST psl, int cchLength);
-
-BOOL SLIsItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive);
-int SLFindItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive, int iStartPos);
-
-WCHAR* SLConvertToString(LPSTRINGLIST psl, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast, int* piSize);
-void SLFreeReturn(void* pszPntr);
-BOOL SLConvertToStringBuf(LPSTRINGLIST psl, WCHAR* pszOutput, int cchMaxSize, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast);
-BOOL SLConvertFromString(LPSTRINGLIST psl, const WCHAR* pszString, int cchSize, const WCHAR* pszSeparator, BOOL bIgnoreEmptyItems);
-
-BOOL SLLoadFromFile(LPSTRINGLIST psl, const WCHAR* pszSearchPath);
-BOOL SLSaveToFile(LPSTRINGLIST psl, const WCHAR* pszFileName);
-BOOL SLLoadFromIniFile(LPSTRINGLIST psl, const WCHAR* pszSearchPath, const WCHAR* pszSection, const WCHAR* pszSettingPrefix);
-BOOL SLSaveToIniFile(LPSTRINGLIST psl, const WCHAR* pszFileName, const WCHAR* pszSection, const WCHAR* pszSettingPrefix);
-
-BOOL SLRetrieveFromListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox);
-BOOL SLAssignToListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox);
-
-BOOL SLBlockList(LPSTRINGLIST psl);
-BOOL SLUnBlockList(LPSTRINGLIST psl);
-
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_STRINGLIST_H__
+#define SF_STRINGLIST_H__ 1
+
+
+// -- Structs
+typedef struct {
+ UINT uCount; // protected by csListAccess
+ WCHAR** papszList; // protected by csListAccess
+ CRITICAL_SECTION csListAccess;
+} STRINGLIST, *LPSTRINGLIST;
+
+// -- Defines
+#define SL_MIN_POS 0
+#define SL_INVALID_POS (-1)
+
+// -- Prototypes
+LPSTRINGLIST SLNewList(void);
+void SLFreeList(LPSTRINGLIST psl);
+BOOL SLClearList(LPSTRINGLIST psl);
+BOOL SLMergeList(LPSTRINGLIST pslDest, LPSTRINGLIST pslFrom);
+
+int SLGetMaxPos(LPSTRINGLIST psl);
+int SLGetSize(LPSTRINGLIST psl, BOOL bAlsoTerminatingZeros); // character count size
+int SLGetItemCount(LPSTRINGLIST psl);
+WCHAR* SLGetItem(LPSTRINGLIST psl, int iPos);
+BOOL SLIsValid(LPSTRINGLIST psl, int iPos);
+
+BOOL SLMoveItem(LPSTRINGLIST psl, int iOldPos, int iNewPos, BOOL bOnlySwitch);
+BOOL SLItemPrintf(LPSTRINGLIST psl, int iPos, int cchArgMaxLen, ...);
+BOOL SLSetItemLength(LPSTRINGLIST psl, int iPos, int cchLength);
+BOOL SLChangeItem(LPSTRINGLIST psl, int iPos, WCHAR* pszNewStr, BOOL bDoAppend);
+
+BOOL SLDeleteItem(LPSTRINGLIST psl, int iPos);
+BOOL SLDeleteItems(LPSTRINGLIST psl, int iPosFirst, int iPosLast);
+
+BOOL SLAddItems(LPSTRINGLIST psl, const WCHAR* apszNewItems[], UINT uNewItemsCount);
+int SLAddItem(LPSTRINGLIST psl, const WCHAR* pszNewItem);
+int SLAddItemPair(LPSTRINGLIST psl, const WCHAR* pszNewItem1, const WCHAR* pszNewItem2);
+int SLPrepareItem(LPSTRINGLIST psl, int cchLength);
+
+BOOL SLIsItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive);
+int SLFindItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive, int iStartPos);
+
+WCHAR* SLConvertToString(LPSTRINGLIST psl, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast, int* piSize);
+void SLFreeReturn(void* pszPntr);
+BOOL SLConvertToStringBuf(LPSTRINGLIST psl, WCHAR* pszOutput, int cchMaxSize, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast);
+BOOL SLConvertFromString(LPSTRINGLIST psl, const WCHAR* pszString, int cchSize, const WCHAR* pszSeparator, BOOL bIgnoreEmptyItems);
+
+BOOL SLLoadFromFile(LPSTRINGLIST psl, const WCHAR* pszSearchPath);
+BOOL SLSaveToFile(LPSTRINGLIST psl, const WCHAR* pszFileName);
+BOOL SLLoadFromIniFile(LPSTRINGLIST psl, const WCHAR* pszSearchPath, const WCHAR* pszSection, const WCHAR* pszSettingPrefix);
+BOOL SLSaveToIniFile(LPSTRINGLIST psl, const WCHAR* pszFileName, const WCHAR* pszSection, const WCHAR* pszSettingPrefix);
+
+BOOL SLRetrieveFromListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox);
+BOOL SLAssignToListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox);
+
+BOOL SLBlockList(LPSTRINGLIST psl);
+BOOL SLUnBlockList(LPSTRINGLIST psl);
+
#endif // SF_STRINGLIST_H__ \ No newline at end of file
diff --git a/trigger.c b/trigger.c
index 94ff0f3..23eb260 100644
--- a/trigger.c
+++ b/trigger.c
@@ -1,63 +1,63 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -----------------------------------------
-
-void TriggerIncomingSpam(void)
-{
- if (ServiceExists(MS_TRIGGER_REGISTERTRIGGER) && ServiceExists(MS_TRIGGER_REPORTACTION))
- {
- REPORT_INFO ri;
-
- ZeroMemory(&ri, sizeof(ri));
- ri.cbSize = sizeof(ri);
- ri.pszName = "Spam Filter: Incoming Spam"; // may be NULL if triggerID!=0
- ri.flags = TRG_PERFORM;
-
- CallService(MS_TRIGGER_REPORTACTION, 0, (LPARAM)&ri);
- }
-}
-
-
-// ------------------------------------
-
-
-void InitTrigger(void)
-{
- if (ServiceExists(MS_TRIGGER_REGISTERTRIGGER) && ServiceExists(MS_TRIGGER_REPORTACTION))
- {
- TRIGGERREGISTER tr;
-
- ZeroMemory(&tr, sizeof(tr));
- tr.cbSize = sizeof(tr);
- tr.pszName = "Spam Filter: Incoming Spam"; // identifier; no translate!
- CallService(MS_TRIGGER_REGISTERTRIGGER, 0, (LPARAM)&tr);
- }
-}
-
-
-void UninitTrigger(void)
-{
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -----------------------------------------
+
+void TriggerIncomingSpam(void)
+{
+ if (ServiceExists(MS_TRIGGER_REGISTERTRIGGER) && ServiceExists(MS_TRIGGER_REPORTACTION))
+ {
+ REPORT_INFO ri;
+
+ ZeroMemory(&ri, sizeof(ri));
+ ri.cbSize = sizeof(ri);
+ ri.pszName = "Spam Filter: Incoming Spam"; // may be NULL if triggerID!=0
+ ri.flags = TRG_PERFORM;
+
+ CallService(MS_TRIGGER_REPORTACTION, 0, (LPARAM)&ri);
+ }
+}
+
+
+// ------------------------------------
+
+
+void InitTrigger(void)
+{
+ if (ServiceExists(MS_TRIGGER_REGISTERTRIGGER) && ServiceExists(MS_TRIGGER_REPORTACTION))
+ {
+ TRIGGERREGISTER tr;
+
+ ZeroMemory(&tr, sizeof(tr));
+ tr.cbSize = sizeof(tr);
+ tr.pszName = "Spam Filter: Incoming Spam"; // identifier; no translate!
+ CallService(MS_TRIGGER_REGISTERTRIGGER, 0, (LPARAM)&tr);
+ }
+}
+
+
+void UninitTrigger(void)
+{
} \ No newline at end of file
diff --git a/trigger.h b/trigger.h
index 3438fd8..1e1d903 100644
--- a/trigger.h
+++ b/trigger.h
@@ -1,32 +1,32 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_TRIGGER_H__
-#define SF_TRIGGER_H__ 1
-
-// -- Prototypes
-void TriggerIncomingSpam(void);
-
-void InitTrigger(void);
-void UninitTrigger(void);
-
-
-#endif // SF_TRIGGER_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_TRIGGER_H__
+#define SF_TRIGGER_H__ 1
+
+// -- Prototypes
+void TriggerIncomingSpam(void);
+
+void InitTrigger(void);
+void UninitTrigger(void);
+
+
+#endif // SF_TRIGGER_H__
diff --git a/utilities.c b/utilities.c
index 013c806..6e78596 100644
--- a/utilities.c
+++ b/utilities.c
@@ -1,629 +1,629 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-
-// -----------------------------------------
-
-// -- Error Output --
-
-static void ThreadMessageBox(void* arg)
-{
- MSGBOXPARAMS* pmbp = (MSGBOXPARAMS*)arg;
-
- MessageBoxIndirect(pmbp);
-
- mir_free((WCHAR*)pmbp->lpszCaption);
- mir_free((WCHAR*)pmbp->lpszText);
- mir_free(pmbp);
-}
-
-
-void ShowInfoMessage(UINT uIconID, const WCHAR* pszCaption, const WCHAR* pszTextFmt, size_t cchExtraSize, ...)
-{
- // Params:
- // uIconID - NIIF_INFO, NIIF_WARNING or NIIF_ERROR
- // pszCaption - Only 64chars of it will be used.
- // pszTextFmt - Only 256chars of it will be used.
-
- va_list va;
- WCHAR* pszText;
- BOOL bErrorShown = FALSE;
-
- if (!pszCaption || !pszTextFmt || Miranda_Terminated()) return;
- pszText = mir_alloc((lstrlen(pszTextFmt)+((cchExtraSize>0)?cchExtraSize:0)+1)*sizeof(WCHAR));
- if (!pszText) return;
-
- if (cchExtraSize <= 0) {
- mir_sntprintf(pszText, lstrlen(pszTextFmt)+1, _T("%s"), pszTextFmt);
- } else {
- va_start(va, cchExtraSize);
- mir_vsntprintf(pszText, lstrlen(pszTextFmt)+((cchExtraSize>0)?cchExtraSize:0)+1, pszTextFmt, va);
- va_end(va);
- }
-
- if (ServiceExists(MS_CLIST_SYSTRAY_NOTIFY))
- {
- // Output balloon tip if supported
- MIRANDASYSTRAYNOTIFY msn;
-
- ZeroMemory(&msn, sizeof(msn)); // forward compatibility
- msn.cbSize = sizeof(msn);
- #if defined(UNICODE)
- // SystrayNotify does not support Unicode
- // We need to convert Unicode->Ansi
- mir_utf8decode(msn.szInfoTitle,&pszCaption);
- mir_utf8decode(msn.szInfo,&pszText);
- #else
- msn.szInfoTitle = (char*)pszCaption;
- msn.szInfo = (char*)pszText;
- #endif
- //msn.szProto = NULL;
- msn.uTimeout = 20000; // 30 sec is current max timeout that is possible
- if (uIconID == NIIF_ERROR)
- msn.dwInfoFlags = NIIF_ERROR;
- else if (uIconID == NIIF_WARNING)
- msn.dwInfoFlags = NIIF_WARNING;
- else
- msn.dwInfoFlags = NIIF_INFO;
-
- // I don't know if service is thread safe therefor using sync
- bErrorShown = (CallServiceSync(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&msn) == 0);
-
- #if defined(UNICODE)
- if (msn.szInfoTitle) mir_free(msn.szInfoTitle);
- if (msn.szInfo) mir_free(msn.szInfo);
- #endif
-
-
- #if defined(UNICODE)
- } else if (ServiceExists(MS_POPUP_ADDPOPUPW))
- {
- // Output a popup message as alternative
- POPUPDATAW ppd;
-
- ZeroMemory(&ppd, sizeof(ppd));
- mir_sntprintf(ppd.lpwzContactName, ARRAYSIZE(ppd.lpwzContactName), _T("%s"), pszCaption);
- mir_sntprintf(ppd.lpwzText, ARRAYSIZE(ppd.lpwzText), _T("%s"), pszText);
- //ppd.iSeconds = 0;
- //ppd.lchContact = NULL;
- //ppd.colorText = GetSysColor(COLOR_INFOTEXT); // or GetSysColor(COLOR_WINDOWTEXT)
- //ppd.colorBack = GetSysColor(COLOR_INFOBK); // or GetSysColor(COLOR_3DFACE)
- if (uIconID == NIIF_WARNING)
- ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_WARNING), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
- else if (uIconID == NIIF_ERROR)
- ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_ERROR), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
- else
- ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_INFORMATION), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
-
- // I don't know if popup module author made it thread safe...
- bErrorShown = (CallServiceSync(MS_POPUP_ADDPOPUPW, (WPARAM)&ppd, 0) >= 0);
- }
- #else
- } else if (ServiceExists(MS_POPUP_ADDPOPUPEX))
- {
- // Output a popup message as alternative
- POPUPDATAEX ppd;
-
- ZeroMemory(&ppd, sizeof(ppd));
- mir_snprintf(ppd.lpzContactName, ARRAYSIZE(ppd.lpzContactName), "%s", pszCaption);
- mir_snprintf(ppd.lpzText, ARRAYSIZE(ppd.lpzText), "%s", pszText);
- //ppd.iSeconds = 0;
- //ppd.lchContact = NULL;
- //ppd.colorText = GetSysColor(COLOR_INFOTEXT); // or GetSysColor(COLOR_WINDOWTEXT)
- //ppd.colorBack = GetSysColor(COLOR_INFOBK); // or GetSysColor(COLOR_3DFACE)
-
- if (ServiceExists(MS_POPUP_ADDCLASS)) {
- //ppd.skinBack = ppd.colorBack;
- ppd.colorBack = POPUP_USE_SKINNED_BG;
- }
-
- if (uIconID == NIIF_WARNING) {
- ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_WARNING), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
-
- if (ppd.colorBack == POPUP_USE_SKINNED_BG)
- ppd.lpzClass = (LPCTSTR)POPUP_CLASS_NOTIFY; // type "LPCTSTR" of lpzClass is wrong!
-
- } else if (uIconID == NIIF_ERROR) {
- ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_ERROR), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
-
- if (ppd.colorBack == POPUP_USE_SKINNED_BG)
- ppd.lpzClass = (LPCTSTR)POPUP_CLASS_WARNING; // type "LPCTSTR" of lpzClass is wrong!
-
- } else {
- ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_INFORMATION), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
-
- if (ppd.colorBack == POPUP_USE_SKINNED_BG)
- ppd.lpzClass = (LPCTSTR)POPUP_CLASS_DEFAULT; // type "LPCTSTR" of lpzClass is wrong!
- }
-
- bErrorShown = (CallServiceSync(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0) >= 0); // I don't know if popup module author made it thread safe...
- }
- #endif
-
- if (!bErrorShown)
- {
- // Output normal message dialog when popup plugin is not installed
- // or when Windows doesn't support balloon tips
- // or if an popup error occured
-
- MSGBOXPARAMS* pmbp = (MSGBOXPARAMS*)mir_alloc(sizeof(MSGBOXPARAMS));
- if (pmbp)
- {
- ZeroMemory(pmbp, sizeof(MSGBOXPARAMS));
- pmbp->cbSize = sizeof(MSGBOXPARAMS);
- pmbp->lpszCaption = mir_wstrdup(pszCaption); // will be freed by thread
- pmbp->lpszText = pszText; // will be freed by thread
- pszText = NULL;
- pmbp->hwndOwner = NULL;
- pmbp->dwStyle = MB_OK|MB_SETFOREGROUND|MB_TASKMODAL;
- pmbp->dwLanguageId = LANGIDFROMLCID(GetThreadLocale());
- if (uIconID == NIIF_WARNING)
- pmbp->dwStyle |= MB_ICONWARNING;
- else if (uIconID == NIIF_ERROR)
- pmbp->dwStyle |= MB_ICONERROR;
- else
- pmbp->dwStyle |= MB_ICONINFORMATION;
-
- forkthread(ThreadMessageBox, 0, pmbp);
- }
- }
-
- if (pszText) mir_free(pszText);
-}
-
-
-WCHAR* GetLastErrorDescription(DWORD dwLastError)
-{
- WCHAR* pszReturn;
-
- #if defined(UNICODE)
-
- #if defined(MICROSOFT_LAYER_FOR_UNICODE)
- char* pszLastError = NULL;
-
- // FormatMessageW does not work with UnicoWS layer on Win9x/ME
- if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPSTR)&pszLastError, 0, NULL) != 0) {
- pszReturn = mir_utf8encodeW(pszLastError);
- LocalFree(pszLastError);
- } else {
- pszReturn = NULL;
- }
-
- #else
- WCHAR* pwszLastError;
- if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPWSTR)&pwszLastError, 0, NULL) != 0) {
- pszReturn = mir_wstrdup(pwszLastError);
- LocalFree(pwszLastError);
- } else {
- pszReturn = NULL;
- }
- #endif
-
- #else
- WCHAR* pszLastError;
- if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPTSTR)&pszLastError, 0, NULL) != 0) {
- pszReturn = mir_strdup(pszLastError);
- LocalFree(pszLastError);
- } else {
- pszReturn = NULL;
- }
- #endif
-
- return pszReturn;
-}
-
-
-// -- Sounds --
-
-void SkinAddNewSoundBundled(const char* pszName, const char* pszSection, const char* pszDescription, const WCHAR* pszDefaultFile)
-{
- SKINSOUNDDESCEX ssd;
- WCHAR szFileName[MAX_PATH];
- char szFileNameFin[MAX_PATH];
-
- ZeroMemory(&ssd, sizeof(ssd));
- ssd.cbSize = sizeof(ssd);
- ssd.pszSection = (char*)pszSection;
- ssd.pszName = (char*)pszName;
- ssd.pszDescription = (char*)pszDescription;
-
- PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, SOUNDS_SUBDIRECTORY, (WCHAR*)pszDefaultFile, NULL);
- if (PathFileExists(szFileName))
- {
- #if defined(UNICODE)
- WCHAR* pszBuf;
- mir_utf8decode((char*)szFileName,&pszBuf);
- if (pszBuf) {
- if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)pszBuf, (LPARAM)szFileNameFin) <= 0)
- mir_snprintf(szFileNameFin, ARRAYSIZE(szFileNameFin), "%s", pszBuf);
- ssd.pszDefaultFile = szFileNameFin;
- mir_free(pszBuf);
- }
- #else
- if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)szFileName, (LPARAM)szFileNameFin) <= 0)
- ssd.pszDefaultFile = szFileName;
- else
- ssd.pszDefaultFile = szFileNameFin;
- #endif
- }
-
- CallService(MS_SKIN_ADDNEWSOUND, 0, (LPARAM)&ssd);
-}
-
-
-// -- Icons --
-
-void SkinAddNewIcon(const char* pszName, const WCHAR* pszSection, const WCHAR* pszDescription, int iDefResID, BOOL bLarge)
-{
- // Support for IcoLib
- if (ServiceExists(MS_SKIN2_ADDICON) && ServiceExists(MS_SKIN2_GETICON))
- {
- SKINICONDESC sid;
-
- ZeroMemory(&sid, sizeof(sid));
- sid.cbSize = sizeof(sid);
- sid.ptszSection = (WCHAR*)pszSection;
- sid.ptszDescription = (WCHAR*)pszDescription;
- sid.pszName = (char*)pszName;
- sid.hDefaultIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(iDefResID), IMAGE_ICON, bLarge?0:GetSystemMetrics(SM_CXSMICON), bLarge?0:GetSystemMetrics(SM_CYSMICON), (bLarge?LR_DEFAULTSIZE:0)|LR_SHARED);
- sid.cx = GetSystemMetrics(bLarge?SM_CXICON:SM_CXSMICON);
- sid.cy = GetSystemMetrics(bLarge?SM_CYICON:SM_CYSMICON);
- sid.flags = SIDF_UNICODE;
-
- CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
- }
-}
-
-
-HICON SkinGetIcon(const char* pszName, int iDefResID, BOOL bLarge)
-{
- // Support for IcoLib
- if (ServiceExists(MS_SKIN2_GETICON) && ServiceExists(MS_SKIN2_ADDICON)) {
- HICON hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)pszName);
- if (hIcon) return hIcon;
- }
- if (iDefResID <= 0) return NULL;
- return (HICON)LoadImage(hInstance, MAKEINTRESOURCE(iDefResID), IMAGE_ICON, bLarge?0:GetSystemMetrics(SM_CXSMICON), bLarge?0:GetSystemMetrics(SM_CYSMICON), (bLarge?LR_DEFAULTSIZE:0)|LR_SHARED);
-}
-
-
-// -- Hotkeys --
-
-/*
-void SkinAddNewHotkey(const char* pszName, const char* pszSection, const char* pszDescription, const int iDefHotkey, const char* pszServiceName)
-{
- // Support for CList_MW
- if (ServiceExists(MS_SKIN_ADDHOTKEY))
- {
- SKINHOTKEYDESCEX shd;
-
- ZeroMemory(&shd, sizeof(shd));
- shd.cbSize = sizeof(shd);
- shd.pszName = (char*)pszName;
- shd.pszDescription = (char*)pszDescription;
- shd.pszSection = (char*)pszSection;
- shd.pszService = (char*)pszServiceName;
- shd.DefHotKey = iDefHotkey;
-
- CallService(MS_SKIN_ADDHOTKEY, 0, (LPARAM)&shd);
- }
-}
-*/
-
-
-// -- Fonts --
-
-/*
-void SkinAddNewFont(const char* pszName, const char* pszSection, const char* pszDescription, COLORREF clrColor, const char* pszFace, int iSize, DWORD dwStyleFlags)
-{
- if (pszName && ServiceExists(MS_FONT_REGISTER))
- {
- FontID fid;
-
- ZeroMemory(&fid, sizeof(fid));
- fid.cbSize = sizeof(fid);
- mir_snprintf(fid.name, ARRAYSIZE(fid.name), "%s", pszName);
- mir_snprintf(fid.group, ARRAYSIZE(fid.group), "%s", pszSection ? pszSection : Translate("Other"));
- mir_snprintf(fid.dbSettingsGroup, ARRAYSIZE(fid.dbSettingsGroup), "%s", DB_MODULE_NAME);
- mir_snprintf(fid.prefix, ARRAYSIZE(fid.prefix), "%s", "Font_");
- //fid.order = 0;
- fid.flags = FIDF_DEFAULTVALID|FIDF_ALLOWEFFECTS;
- fid.deffontsettings.charset = DEFAULT_CHARSET;
- fid.deffontsettings.colour = clrColor;
- fid.deffontsettings.size = (iSize > 0)?iSize:12;
- fid.deffontsettings.style = dwStyleFlags;
- mir_snprintf(fid.deffontsettings.szFace, ARRAYSIZE(fid.deffontsettings.szFace), "%s", pszFace ? pszFace : "MS Sans Serif");
-
- CallService(MS_FONT_REGISTER, (WPARAM)&fid, 0);
- }
-}
-
-
-BOOL SkinAddNewFontSameAs(const char* pszDescription, const char* pszSection, const char* pszSameAsDescription)
-{
- if (ServiceExists(MS_FONT_REGISTER))
- {
- FontID fid;
- LOGFONT lf;
-
- ZeroMemory(&fid, sizeof(fid));
- fid.cbSize = sizeof(fid);
- mir_snprintf(fid.name, ARRAYSIZE(fid.name), "%s", pszDescription);
- mir_snprintf(fid.group, ARRAYSIZE(fid.group), "%s", pszSection ? pszSection : Translate("Other"));
- mir_snprintf(fid.dbSettingsGroup, ARRAYSIZE(fid.dbSettingsGroup), "%s", DB_MODULE_NAME);
- mir_snprintf(fid.prefix, ARRAYSIZE(fid.name), "%s", "Font_");
- //fid.order = 0;
- fid.flags = FIDF_ALLOWEFFECTS;
- if (pszSameAsDescription)
- {
- ZeroMemory(&lf, sizeof(lf)); // not good; SkinGetFont has no error indicating value (workaround)
-
- fid.deffontsettings.colour = SkinGetFont(pszSameAsDescription, &lf);
- fid.deffontsettings.charset = lf.lfCharSet;
- fid.deffontsettings.size = (char)lf.lfHeight;
- fid.deffontsettings.style = 0;
-
- mir_snprintf(fid.deffontsettings.szFace, ARRAYSIZE(fid.deffontsettings.szFace), "%s", lf.lfFaceName);
-
- if (lf.lfItalic) fid.deffontsettings.style = DBFONTF_ITALIC;
- if (lf.lfWeight) fid.deffontsettings.style = DBFONTF_BOLD;
- if (lf.lfUnderline) fid.deffontsettings.style = DBFONTF_UNDERLINE;
- if (lf.lfStrikeOut) fid.deffontsettings.style = DBFONTF_STRIKEOUT;
-
- fid.flags |= FIDF_DEFAULTVALID;
-
- CallService(MS_FONT_REGISTER, (WPARAM)&fid, 0);
- return TRUE;
- } else {
- CallService(MS_FONT_REGISTER, (WPARAM)&fid, 0);
- return FALSE;
- }
- }
-}
-
-
-BOOL SkinGetFont(const char* pszDescription, const char* pszSection, COLORREF* pclrColor, LOGFONT* plfFont)
-{
- if (pszName && pclrColor && plfFont && ServiceExists(MS_FONT_GET))
- {
- FontID fid;
-
- mir_snprintf(fid.name, 64, "%s", pszDescription);
- mir_snprintf(fid.group, 64, "%s", pszSection ? pszSection : Translate("Other"));
-
- *pclrColor = (COLORREF)CallService(MS_FONT_GET, (WPARAM)&fid, (LPARAM)plfFont);
-
- return TRUE;
- } else {
- return FALSE;
- }
-}
-*/
-
-
-// -- Colors --
-
-void SkinAddNewColor(const char* pszDbName, const char* pszSection, const char* pszDescription, COLORREF clrDefColor, BOOL bFontRelated)
-{
- if (!pszSection || (pszDbName && !pszDescription)) return;
-
- // Support for FontService
- if (bFontRelated && ServiceExists(MS_COLOUR_REGISTER) && ServiceExists(MS_COLOUR_GET))
- {
- ColourID cid;
-
- ZeroMemory(&cid, sizeof(cid));
- cid.cbSize = sizeof(cid);
- cid.defcolour = clrDefColor;
- mir_snprintf(cid.dbSettingsGroup, ARRAYSIZE(cid.dbSettingsGroup), "%s", DB_MODULE_NAME);
- mir_snprintf(cid.group, ARRAYSIZE(cid.group), "%s", pszSection);
- mir_snprintf(cid.setting, ARRAYSIZE(cid.setting), "%s", pszDbName?pszDbName:"BkgColour");
- mir_snprintf(cid.name, ARRAYSIZE(cid.name), "%s", pszDbName?pszDescription:Translate("Background"));
-
- CallService(MS_COLOUR_REGISTER, (WPARAM)&cid, 0);
- return;
- }
-
-}
-
-
-COLORREF SkinGetColor(const char* pszDbName, const char* pszDescription, const char* pszSection, COLORREF clrDefColor, BOOL bFontRelated)
-{
- if (!pszSection || (pszDbName && !pszDescription)) return clrDefColor;
-
- // Support for FontService
- if (bFontRelated && ServiceExists(MS_COLOUR_REGISTER) && ServiceExists(MS_COLOUR_GET))
- {
- ColourID cid;
-
- ZeroMemory(&cid, sizeof(cid));
- cid.cbSize = sizeof(cid);
- mir_snprintf(cid.setting, ARRAYSIZE(cid.setting), "%s", pszDbName?pszDbName:"BkgColour");
- mir_snprintf(cid.group, ARRAYSIZE(cid.group), "%s", pszSection);
- mir_snprintf(cid.name, ARRAYSIZE(cid.name), "%s", pszDescription?(char*)pszDescription:Translate("Background"));
-
- return (COLORREF)CallService(MS_COLOUR_GET, (WPARAM)&cid, 0);
- }
-
- return clrDefColor;
-}
-
-
-// -- System Icons --
-
-HIMAGELIST LoadSystemCheckboxImageList(void)
-{
- HWND hwndTreeView;
- HIMAGELIST hImageList, hImgLstBuf;
- INITCOMMONCONTROLSEX icc;
-
- ZeroMemory(&icc, sizeof(icc));
- icc.dwSize = sizeof(icc);
- icc.dwICC = ICC_TREEVIEW_CLASSES;
- InitCommonControlsEx(&icc);
-
- // Create hidden treeview
- hwndTreeView = CreateWindowEx(0, WC_TREEVIEW, NULL, 0, 0, 0, 0, 0, NULL, 0, hInstance, NULL);
- if (!hwndTreeView) return NULL;
- SetWindowLongPtr(hwndTreeView, GWL_STYLE, (LONG_PTR)TVS_CHECKBOXES); // Style needs to be set after creating
-
- // Get imagelist
- hImgLstBuf = TreeView_GetImageList(hwndTreeView, TVSIL_STATE);
- hImageList = ImageList_Duplicate(hImgLstBuf);
-
- // Destroy treeview
- TreeView_SetImageList(hwndTreeView, NULL, TVSIL_STATE); // Avoiding Access Violation in CommonControls DLL
- ImageList_Destroy(hImgLstBuf);
- DestroyWindow(hwndTreeView);
-
- return hImageList;
-}
-
-
-HICON LoadSystemIcon(int iListID, int iIconIndex) // Returned icon needs to be destroyed using DestroyIcon()
-{
-/*
-Index values for IDB_HIST_LARGE_COLOR and IDB_HIST_SMALL_COLOR:
-(Microsoft Windows Explorer bitmaps)
-HIST_ADDTOFAVORITES
-Add to favorites.
-HIST_BACK
-Move back.
-HIST_FAVORITES
-Open favorites folder.
-HIST_FORWARD
-Move forward.
-HIST_VIEWTREE
-View tree.
-
-Index values for IDB_STD_LARGE_COLOR and IDB_STD_SMALL_COLOR:
-(Standard bitmaps)
-STD_COPY
-Copy operation.
-STD_CUT
-Cut operation.
-STD_DELETE
-Delete operation.
-STD_FILENEW
-New file operation.
-STD_FILEOPEN
-Open file operation.
-STD_FILESAVE
-Save file operation.
-STD_FIND
-Find operation.
-STD_HELP
-Help operation.
-STD_PASTE
-Paste operation.
-STD_PRINT
-Print operation.
-STD_PRINTPRE
-Print preview operation.
-STD_PROPERTIES
-Properties operation.
-STD_REDOW
-Redo operation.
-STD_REPLACE
-Replace operation.
-STD_UNDO
-Undo operation.
-
-Index values for IDB_VIEW_LARGE_COLOR and IDB_VIEW_SMALL_COLOR:
-(View bitmaps)
-VIEW_DETAILS
-Details view.
-VIEW_LARGEICONS
-Large icons view.
-VIEW_LIST
-List view.
-VIEW_NETCONNECT
-Connect to network drive.
-VIEW_NETDISCONNECT
-Disconnect from network drive.
-VIEW_NEWFOLDER
-New folder.
-VIEW_PARENTFOLDER
-Go to parent folder.
-VIEW_SMALLICONS
-Small icon view.
-VIEW_SORTDATE
-Sort by date.
-VIEW_SORTNAME
-Sort by name.
-VIEW_SORTSIZE
-Sort by size.
-VIEW_SORTTYPE
-Sort by type.
-*/
-
- HWND hwndToolbar;
- HICON hIcon;
- INITCOMMONCONTROLSEX icc;
-
- ZeroMemory(&icc, sizeof(icc));
- icc.dwSize = sizeof(icc);
- icc.dwICC = ICC_BAR_CLASSES;
- InitCommonControlsEx(&icc);
-
- // Create hidden toolbar
- hwndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, _T(""), 0, 0, 0, 0, 0, NULL, 0, hInstance, NULL);
- if (!hwndToolbar) return NULL;
- SendMessage(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
-
- // Get icon
- SendMessage(hwndToolbar, TB_LOADIMAGES, (WPARAM)iListID, (LPARAM)HINST_COMMCTRL);
- hIcon = ImageList_GetIcon((HIMAGELIST)SendMessage(hwndToolbar, TB_GETIMAGELIST, 0, 0), iIconIndex, ILD_TRANSPARENT);
-
- // Destroy toolbar
- DestroyWindow(hwndToolbar);
-
- return hIcon;
-}
-
-
-// -- Icon Overlay --
-
-HICON OverlayIcon(HICON hMainIcon, HICON hOverlayIcon, int cxWidth, int cyHeight)
-{
- HICON hIconReturn;
- HIMAGELIST himlIconList, himlIconListBuf; // New image lists
- int iMainIcon, iOverlayIcon;
-
- if ((cxWidth < 0) || (cyHeight < 0) || !hMainIcon || !hOverlayIcon)
- return NULL;
-
- himlIconList = ImageList_Create((cxWidth==0)?GetSystemMetrics(SM_CXICON):cxWidth, (cyHeight==0)?GetSystemMetrics(SM_CYICON):cyHeight, (IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK,2, 0);
- iMainIcon = ImageList_AddIcon(himlIconList, hMainIcon);
- iOverlayIcon = ImageList_AddIcon(himlIconList, hOverlayIcon);
-
- himlIconListBuf = ImageList_Merge(himlIconList, iMainIcon, himlIconList, iOverlayIcon, 0, 0);
- ImageList_Destroy(himlIconList);
-
- hIconReturn = ImageList_GetIcon(himlIconListBuf, iMainIcon, ILD_TRANSPARENT);
- ImageList_Destroy(himlIconListBuf);
-
- return hIconReturn; // returned HICON needs to be destroyed (DestroyIcon())
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+
+// -----------------------------------------
+
+// -- Error Output --
+
+static void ThreadMessageBox(void* arg)
+{
+ MSGBOXPARAMS* pmbp = (MSGBOXPARAMS*)arg;
+
+ MessageBoxIndirect(pmbp);
+
+ mir_free((WCHAR*)pmbp->lpszCaption);
+ mir_free((WCHAR*)pmbp->lpszText);
+ mir_free(pmbp);
+}
+
+
+void ShowInfoMessage(UINT uIconID, const WCHAR* pszCaption, const WCHAR* pszTextFmt, size_t cchExtraSize, ...)
+{
+ // Params:
+ // uIconID - NIIF_INFO, NIIF_WARNING or NIIF_ERROR
+ // pszCaption - Only 64chars of it will be used.
+ // pszTextFmt - Only 256chars of it will be used.
+
+ va_list va;
+ WCHAR* pszText;
+ BOOL bErrorShown = FALSE;
+
+ if (!pszCaption || !pszTextFmt || Miranda_Terminated()) return;
+ pszText = mir_alloc((lstrlen(pszTextFmt)+((cchExtraSize>0)?cchExtraSize:0)+1)*sizeof(WCHAR));
+ if (!pszText) return;
+
+ if (cchExtraSize <= 0) {
+ mir_sntprintf(pszText, lstrlen(pszTextFmt)+1, _T("%s"), pszTextFmt);
+ } else {
+ va_start(va, cchExtraSize);
+ mir_vsntprintf(pszText, lstrlen(pszTextFmt)+((cchExtraSize>0)?cchExtraSize:0)+1, pszTextFmt, va);
+ va_end(va);
+ }
+
+ if (ServiceExists(MS_CLIST_SYSTRAY_NOTIFY))
+ {
+ // Output balloon tip if supported
+ MIRANDASYSTRAYNOTIFY msn;
+
+ ZeroMemory(&msn, sizeof(msn)); // forward compatibility
+ msn.cbSize = sizeof(msn);
+ #if defined(UNICODE)
+ // SystrayNotify does not support Unicode
+ // We need to convert Unicode->Ansi
+ mir_utf8decode(msn.szInfoTitle,&pszCaption);
+ mir_utf8decode(msn.szInfo,&pszText);
+ #else
+ msn.szInfoTitle = (char*)pszCaption;
+ msn.szInfo = (char*)pszText;
+ #endif
+ //msn.szProto = NULL;
+ msn.uTimeout = 20000; // 30 sec is current max timeout that is possible
+ if (uIconID == NIIF_ERROR)
+ msn.dwInfoFlags = NIIF_ERROR;
+ else if (uIconID == NIIF_WARNING)
+ msn.dwInfoFlags = NIIF_WARNING;
+ else
+ msn.dwInfoFlags = NIIF_INFO;
+
+ // I don't know if service is thread safe therefor using sync
+ bErrorShown = (CallServiceSync(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&msn) == 0);
+
+ #if defined(UNICODE)
+ if (msn.szInfoTitle) mir_free(msn.szInfoTitle);
+ if (msn.szInfo) mir_free(msn.szInfo);
+ #endif
+
+
+ #if defined(UNICODE)
+ } else if (ServiceExists(MS_POPUP_ADDPOPUPW))
+ {
+ // Output a popup message as alternative
+ POPUPDATAW ppd;
+
+ ZeroMemory(&ppd, sizeof(ppd));
+ mir_sntprintf(ppd.lpwzContactName, ARRAYSIZE(ppd.lpwzContactName), _T("%s"), pszCaption);
+ mir_sntprintf(ppd.lpwzText, ARRAYSIZE(ppd.lpwzText), _T("%s"), pszText);
+ //ppd.iSeconds = 0;
+ //ppd.lchContact = NULL;
+ //ppd.colorText = GetSysColor(COLOR_INFOTEXT); // or GetSysColor(COLOR_WINDOWTEXT)
+ //ppd.colorBack = GetSysColor(COLOR_INFOBK); // or GetSysColor(COLOR_3DFACE)
+ if (uIconID == NIIF_WARNING)
+ ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_WARNING), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ else if (uIconID == NIIF_ERROR)
+ ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_ERROR), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ else
+ ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_INFORMATION), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+
+ // I don't know if popup module author made it thread safe...
+ bErrorShown = (CallServiceSync(MS_POPUP_ADDPOPUPW, (WPARAM)&ppd, 0) >= 0);
+ }
+ #else
+ } else if (ServiceExists(MS_POPUP_ADDPOPUPEX))
+ {
+ // Output a popup message as alternative
+ POPUPDATAEX ppd;
+
+ ZeroMemory(&ppd, sizeof(ppd));
+ mir_snprintf(ppd.lpzContactName, ARRAYSIZE(ppd.lpzContactName), "%s", pszCaption);
+ mir_snprintf(ppd.lpzText, ARRAYSIZE(ppd.lpzText), "%s", pszText);
+ //ppd.iSeconds = 0;
+ //ppd.lchContact = NULL;
+ //ppd.colorText = GetSysColor(COLOR_INFOTEXT); // or GetSysColor(COLOR_WINDOWTEXT)
+ //ppd.colorBack = GetSysColor(COLOR_INFOBK); // or GetSysColor(COLOR_3DFACE)
+
+ if (ServiceExists(MS_POPUP_ADDCLASS)) {
+ //ppd.skinBack = ppd.colorBack;
+ ppd.colorBack = POPUP_USE_SKINNED_BG;
+ }
+
+ if (uIconID == NIIF_WARNING) {
+ ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_WARNING), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+
+ if (ppd.colorBack == POPUP_USE_SKINNED_BG)
+ ppd.lpzClass = (LPCTSTR)POPUP_CLASS_NOTIFY; // type "LPCTSTR" of lpzClass is wrong!
+
+ } else if (uIconID == NIIF_ERROR) {
+ ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_ERROR), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+
+ if (ppd.colorBack == POPUP_USE_SKINNED_BG)
+ ppd.lpzClass = (LPCTSTR)POPUP_CLASS_WARNING; // type "LPCTSTR" of lpzClass is wrong!
+
+ } else {
+ ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_INFORMATION), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+
+ if (ppd.colorBack == POPUP_USE_SKINNED_BG)
+ ppd.lpzClass = (LPCTSTR)POPUP_CLASS_DEFAULT; // type "LPCTSTR" of lpzClass is wrong!
+ }
+
+ bErrorShown = (CallServiceSync(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0) >= 0); // I don't know if popup module author made it thread safe...
+ }
+ #endif
+
+ if (!bErrorShown)
+ {
+ // Output normal message dialog when popup plugin is not installed
+ // or when Windows doesn't support balloon tips
+ // or if an popup error occured
+
+ MSGBOXPARAMS* pmbp = (MSGBOXPARAMS*)mir_alloc(sizeof(MSGBOXPARAMS));
+ if (pmbp)
+ {
+ ZeroMemory(pmbp, sizeof(MSGBOXPARAMS));
+ pmbp->cbSize = sizeof(MSGBOXPARAMS);
+ pmbp->lpszCaption = mir_wstrdup(pszCaption); // will be freed by thread
+ pmbp->lpszText = pszText; // will be freed by thread
+ pszText = NULL;
+ pmbp->hwndOwner = NULL;
+ pmbp->dwStyle = MB_OK|MB_SETFOREGROUND|MB_TASKMODAL;
+ pmbp->dwLanguageId = LANGIDFROMLCID(GetThreadLocale());
+ if (uIconID == NIIF_WARNING)
+ pmbp->dwStyle |= MB_ICONWARNING;
+ else if (uIconID == NIIF_ERROR)
+ pmbp->dwStyle |= MB_ICONERROR;
+ else
+ pmbp->dwStyle |= MB_ICONINFORMATION;
+
+ forkthread(ThreadMessageBox, 0, pmbp);
+ }
+ }
+
+ if (pszText) mir_free(pszText);
+}
+
+
+WCHAR* GetLastErrorDescription(DWORD dwLastError)
+{
+ WCHAR* pszReturn;
+
+ #if defined(UNICODE)
+
+ #if defined(MICROSOFT_LAYER_FOR_UNICODE)
+ char* pszLastError = NULL;
+
+ // FormatMessageW does not work with UnicoWS layer on Win9x/ME
+ if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPSTR)&pszLastError, 0, NULL) != 0) {
+ pszReturn = mir_utf8encodeW(pszLastError);
+ LocalFree(pszLastError);
+ } else {
+ pszReturn = NULL;
+ }
+
+ #else
+ WCHAR* pwszLastError;
+ if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPWSTR)&pwszLastError, 0, NULL) != 0) {
+ pszReturn = mir_wstrdup(pwszLastError);
+ LocalFree(pwszLastError);
+ } else {
+ pszReturn = NULL;
+ }
+ #endif
+
+ #else
+ WCHAR* pszLastError;
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (LPTSTR)&pszLastError, 0, NULL) != 0) {
+ pszReturn = mir_strdup(pszLastError);
+ LocalFree(pszLastError);
+ } else {
+ pszReturn = NULL;
+ }
+ #endif
+
+ return pszReturn;
+}
+
+
+// -- Sounds --
+
+void SkinAddNewSoundBundled(const char* pszName, const char* pszSection, const char* pszDescription, const WCHAR* pszDefaultFile)
+{
+ SKINSOUNDDESCEX ssd;
+ WCHAR szFileName[MAX_PATH];
+ char szFileNameFin[MAX_PATH];
+
+ ZeroMemory(&ssd, sizeof(ssd));
+ ssd.cbSize = sizeof(ssd);
+ ssd.pszSection = (char*)pszSection;
+ ssd.pszName = (char*)pszName;
+ ssd.pszDescription = (char*)pszDescription;
+
+ PConstructLocalPath(szFileName, CSIDL_EXT_EXECUTABLE, SOUNDS_SUBDIRECTORY, (WCHAR*)pszDefaultFile, NULL);
+ if (PathFileExists(szFileName))
+ {
+ #if defined(UNICODE)
+ WCHAR* pszBuf;
+ mir_utf8decode((char*)szFileName,&pszBuf);
+ if (pszBuf) {
+ if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)pszBuf, (LPARAM)szFileNameFin) <= 0)
+ mir_snprintf(szFileNameFin, ARRAYSIZE(szFileNameFin), "%s", pszBuf);
+ ssd.pszDefaultFile = szFileNameFin;
+ mir_free(pszBuf);
+ }
+ #else
+ if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)szFileName, (LPARAM)szFileNameFin) <= 0)
+ ssd.pszDefaultFile = szFileName;
+ else
+ ssd.pszDefaultFile = szFileNameFin;
+ #endif
+ }
+
+ CallService(MS_SKIN_ADDNEWSOUND, 0, (LPARAM)&ssd);
+}
+
+
+// -- Icons --
+
+void SkinAddNewIcon(const char* pszName, const WCHAR* pszSection, const WCHAR* pszDescription, int iDefResID, BOOL bLarge)
+{
+ // Support for IcoLib
+ if (ServiceExists(MS_SKIN2_ADDICON) && ServiceExists(MS_SKIN2_GETICON))
+ {
+ SKINICONDESC sid;
+
+ ZeroMemory(&sid, sizeof(sid));
+ sid.cbSize = sizeof(sid);
+ sid.ptszSection = (WCHAR*)pszSection;
+ sid.ptszDescription = (WCHAR*)pszDescription;
+ sid.pszName = (char*)pszName;
+ sid.hDefaultIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(iDefResID), IMAGE_ICON, bLarge?0:GetSystemMetrics(SM_CXSMICON), bLarge?0:GetSystemMetrics(SM_CYSMICON), (bLarge?LR_DEFAULTSIZE:0)|LR_SHARED);
+ sid.cx = GetSystemMetrics(bLarge?SM_CXICON:SM_CXSMICON);
+ sid.cy = GetSystemMetrics(bLarge?SM_CYICON:SM_CYSMICON);
+ sid.flags = SIDF_UNICODE;
+
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+}
+
+
+HICON SkinGetIcon(const char* pszName, int iDefResID, BOOL bLarge)
+{
+ // Support for IcoLib
+ if (ServiceExists(MS_SKIN2_GETICON) && ServiceExists(MS_SKIN2_ADDICON)) {
+ HICON hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)pszName);
+ if (hIcon) return hIcon;
+ }
+ if (iDefResID <= 0) return NULL;
+ return (HICON)LoadImage(hInstance, MAKEINTRESOURCE(iDefResID), IMAGE_ICON, bLarge?0:GetSystemMetrics(SM_CXSMICON), bLarge?0:GetSystemMetrics(SM_CYSMICON), (bLarge?LR_DEFAULTSIZE:0)|LR_SHARED);
+}
+
+
+// -- Hotkeys --
+
+/*
+void SkinAddNewHotkey(const char* pszName, const char* pszSection, const char* pszDescription, const int iDefHotkey, const char* pszServiceName)
+{
+ // Support for CList_MW
+ if (ServiceExists(MS_SKIN_ADDHOTKEY))
+ {
+ SKINHOTKEYDESCEX shd;
+
+ ZeroMemory(&shd, sizeof(shd));
+ shd.cbSize = sizeof(shd);
+ shd.pszName = (char*)pszName;
+ shd.pszDescription = (char*)pszDescription;
+ shd.pszSection = (char*)pszSection;
+ shd.pszService = (char*)pszServiceName;
+ shd.DefHotKey = iDefHotkey;
+
+ CallService(MS_SKIN_ADDHOTKEY, 0, (LPARAM)&shd);
+ }
+}
+*/
+
+
+// -- Fonts --
+
+/*
+void SkinAddNewFont(const char* pszName, const char* pszSection, const char* pszDescription, COLORREF clrColor, const char* pszFace, int iSize, DWORD dwStyleFlags)
+{
+ if (pszName && ServiceExists(MS_FONT_REGISTER))
+ {
+ FontID fid;
+
+ ZeroMemory(&fid, sizeof(fid));
+ fid.cbSize = sizeof(fid);
+ mir_snprintf(fid.name, ARRAYSIZE(fid.name), "%s", pszName);
+ mir_snprintf(fid.group, ARRAYSIZE(fid.group), "%s", pszSection ? pszSection : Translate("Other"));
+ mir_snprintf(fid.dbSettingsGroup, ARRAYSIZE(fid.dbSettingsGroup), "%s", DB_MODULE_NAME);
+ mir_snprintf(fid.prefix, ARRAYSIZE(fid.prefix), "%s", "Font_");
+ //fid.order = 0;
+ fid.flags = FIDF_DEFAULTVALID|FIDF_ALLOWEFFECTS;
+ fid.deffontsettings.charset = DEFAULT_CHARSET;
+ fid.deffontsettings.colour = clrColor;
+ fid.deffontsettings.size = (iSize > 0)?iSize:12;
+ fid.deffontsettings.style = dwStyleFlags;
+ mir_snprintf(fid.deffontsettings.szFace, ARRAYSIZE(fid.deffontsettings.szFace), "%s", pszFace ? pszFace : "MS Sans Serif");
+
+ CallService(MS_FONT_REGISTER, (WPARAM)&fid, 0);
+ }
+}
+
+
+BOOL SkinAddNewFontSameAs(const char* pszDescription, const char* pszSection, const char* pszSameAsDescription)
+{
+ if (ServiceExists(MS_FONT_REGISTER))
+ {
+ FontID fid;
+ LOGFONT lf;
+
+ ZeroMemory(&fid, sizeof(fid));
+ fid.cbSize = sizeof(fid);
+ mir_snprintf(fid.name, ARRAYSIZE(fid.name), "%s", pszDescription);
+ mir_snprintf(fid.group, ARRAYSIZE(fid.group), "%s", pszSection ? pszSection : Translate("Other"));
+ mir_snprintf(fid.dbSettingsGroup, ARRAYSIZE(fid.dbSettingsGroup), "%s", DB_MODULE_NAME);
+ mir_snprintf(fid.prefix, ARRAYSIZE(fid.name), "%s", "Font_");
+ //fid.order = 0;
+ fid.flags = FIDF_ALLOWEFFECTS;
+ if (pszSameAsDescription)
+ {
+ ZeroMemory(&lf, sizeof(lf)); // not good; SkinGetFont has no error indicating value (workaround)
+
+ fid.deffontsettings.colour = SkinGetFont(pszSameAsDescription, &lf);
+ fid.deffontsettings.charset = lf.lfCharSet;
+ fid.deffontsettings.size = (char)lf.lfHeight;
+ fid.deffontsettings.style = 0;
+
+ mir_snprintf(fid.deffontsettings.szFace, ARRAYSIZE(fid.deffontsettings.szFace), "%s", lf.lfFaceName);
+
+ if (lf.lfItalic) fid.deffontsettings.style = DBFONTF_ITALIC;
+ if (lf.lfWeight) fid.deffontsettings.style = DBFONTF_BOLD;
+ if (lf.lfUnderline) fid.deffontsettings.style = DBFONTF_UNDERLINE;
+ if (lf.lfStrikeOut) fid.deffontsettings.style = DBFONTF_STRIKEOUT;
+
+ fid.flags |= FIDF_DEFAULTVALID;
+
+ CallService(MS_FONT_REGISTER, (WPARAM)&fid, 0);
+ return TRUE;
+ } else {
+ CallService(MS_FONT_REGISTER, (WPARAM)&fid, 0);
+ return FALSE;
+ }
+ }
+}
+
+
+BOOL SkinGetFont(const char* pszDescription, const char* pszSection, COLORREF* pclrColor, LOGFONT* plfFont)
+{
+ if (pszName && pclrColor && plfFont && ServiceExists(MS_FONT_GET))
+ {
+ FontID fid;
+
+ mir_snprintf(fid.name, 64, "%s", pszDescription);
+ mir_snprintf(fid.group, 64, "%s", pszSection ? pszSection : Translate("Other"));
+
+ *pclrColor = (COLORREF)CallService(MS_FONT_GET, (WPARAM)&fid, (LPARAM)plfFont);
+
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+*/
+
+
+// -- Colors --
+
+void SkinAddNewColor(const char* pszDbName, const char* pszSection, const char* pszDescription, COLORREF clrDefColor, BOOL bFontRelated)
+{
+ if (!pszSection || (pszDbName && !pszDescription)) return;
+
+ // Support for FontService
+ if (bFontRelated && ServiceExists(MS_COLOUR_REGISTER) && ServiceExists(MS_COLOUR_GET))
+ {
+ ColourID cid;
+
+ ZeroMemory(&cid, sizeof(cid));
+ cid.cbSize = sizeof(cid);
+ cid.defcolour = clrDefColor;
+ mir_snprintf(cid.dbSettingsGroup, ARRAYSIZE(cid.dbSettingsGroup), "%s", DB_MODULE_NAME);
+ mir_snprintf(cid.group, ARRAYSIZE(cid.group), "%s", pszSection);
+ mir_snprintf(cid.setting, ARRAYSIZE(cid.setting), "%s", pszDbName?pszDbName:"BkgColour");
+ mir_snprintf(cid.name, ARRAYSIZE(cid.name), "%s", pszDbName?pszDescription:Translate("Background"));
+
+ CallService(MS_COLOUR_REGISTER, (WPARAM)&cid, 0);
+ return;
+ }
+
+}
+
+
+COLORREF SkinGetColor(const char* pszDbName, const char* pszDescription, const char* pszSection, COLORREF clrDefColor, BOOL bFontRelated)
+{
+ if (!pszSection || (pszDbName && !pszDescription)) return clrDefColor;
+
+ // Support for FontService
+ if (bFontRelated && ServiceExists(MS_COLOUR_REGISTER) && ServiceExists(MS_COLOUR_GET))
+ {
+ ColourID cid;
+
+ ZeroMemory(&cid, sizeof(cid));
+ cid.cbSize = sizeof(cid);
+ mir_snprintf(cid.setting, ARRAYSIZE(cid.setting), "%s", pszDbName?pszDbName:"BkgColour");
+ mir_snprintf(cid.group, ARRAYSIZE(cid.group), "%s", pszSection);
+ mir_snprintf(cid.name, ARRAYSIZE(cid.name), "%s", pszDescription?(char*)pszDescription:Translate("Background"));
+
+ return (COLORREF)CallService(MS_COLOUR_GET, (WPARAM)&cid, 0);
+ }
+
+ return clrDefColor;
+}
+
+
+// -- System Icons --
+
+HIMAGELIST LoadSystemCheckboxImageList(void)
+{
+ HWND hwndTreeView;
+ HIMAGELIST hImageList, hImgLstBuf;
+ INITCOMMONCONTROLSEX icc;
+
+ ZeroMemory(&icc, sizeof(icc));
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_TREEVIEW_CLASSES;
+ InitCommonControlsEx(&icc);
+
+ // Create hidden treeview
+ hwndTreeView = CreateWindowEx(0, WC_TREEVIEW, NULL, 0, 0, 0, 0, 0, NULL, 0, hInstance, NULL);
+ if (!hwndTreeView) return NULL;
+ SetWindowLongPtr(hwndTreeView, GWL_STYLE, (LONG_PTR)TVS_CHECKBOXES); // Style needs to be set after creating
+
+ // Get imagelist
+ hImgLstBuf = TreeView_GetImageList(hwndTreeView, TVSIL_STATE);
+ hImageList = ImageList_Duplicate(hImgLstBuf);
+
+ // Destroy treeview
+ TreeView_SetImageList(hwndTreeView, NULL, TVSIL_STATE); // Avoiding Access Violation in CommonControls DLL
+ ImageList_Destroy(hImgLstBuf);
+ DestroyWindow(hwndTreeView);
+
+ return hImageList;
+}
+
+
+HICON LoadSystemIcon(int iListID, int iIconIndex) // Returned icon needs to be destroyed using DestroyIcon()
+{
+/*
+Index values for IDB_HIST_LARGE_COLOR and IDB_HIST_SMALL_COLOR:
+(Microsoft Windows Explorer bitmaps)
+HIST_ADDTOFAVORITES
+Add to favorites.
+HIST_BACK
+Move back.
+HIST_FAVORITES
+Open favorites folder.
+HIST_FORWARD
+Move forward.
+HIST_VIEWTREE
+View tree.
+
+Index values for IDB_STD_LARGE_COLOR and IDB_STD_SMALL_COLOR:
+(Standard bitmaps)
+STD_COPY
+Copy operation.
+STD_CUT
+Cut operation.
+STD_DELETE
+Delete operation.
+STD_FILENEW
+New file operation.
+STD_FILEOPEN
+Open file operation.
+STD_FILESAVE
+Save file operation.
+STD_FIND
+Find operation.
+STD_HELP
+Help operation.
+STD_PASTE
+Paste operation.
+STD_PRINT
+Print operation.
+STD_PRINTPRE
+Print preview operation.
+STD_PROPERTIES
+Properties operation.
+STD_REDOW
+Redo operation.
+STD_REPLACE
+Replace operation.
+STD_UNDO
+Undo operation.
+
+Index values for IDB_VIEW_LARGE_COLOR and IDB_VIEW_SMALL_COLOR:
+(View bitmaps)
+VIEW_DETAILS
+Details view.
+VIEW_LARGEICONS
+Large icons view.
+VIEW_LIST
+List view.
+VIEW_NETCONNECT
+Connect to network drive.
+VIEW_NETDISCONNECT
+Disconnect from network drive.
+VIEW_NEWFOLDER
+New folder.
+VIEW_PARENTFOLDER
+Go to parent folder.
+VIEW_SMALLICONS
+Small icon view.
+VIEW_SORTDATE
+Sort by date.
+VIEW_SORTNAME
+Sort by name.
+VIEW_SORTSIZE
+Sort by size.
+VIEW_SORTTYPE
+Sort by type.
+*/
+
+ HWND hwndToolbar;
+ HICON hIcon;
+ INITCOMMONCONTROLSEX icc;
+
+ ZeroMemory(&icc, sizeof(icc));
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_BAR_CLASSES;
+ InitCommonControlsEx(&icc);
+
+ // Create hidden toolbar
+ hwndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, _T(""), 0, 0, 0, 0, 0, NULL, 0, hInstance, NULL);
+ if (!hwndToolbar) return NULL;
+ SendMessage(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
+
+ // Get icon
+ SendMessage(hwndToolbar, TB_LOADIMAGES, (WPARAM)iListID, (LPARAM)HINST_COMMCTRL);
+ hIcon = ImageList_GetIcon((HIMAGELIST)SendMessage(hwndToolbar, TB_GETIMAGELIST, 0, 0), iIconIndex, ILD_TRANSPARENT);
+
+ // Destroy toolbar
+ DestroyWindow(hwndToolbar);
+
+ return hIcon;
+}
+
+
+// -- Icon Overlay --
+
+HICON OverlayIcon(HICON hMainIcon, HICON hOverlayIcon, int cxWidth, int cyHeight)
+{
+ HICON hIconReturn;
+ HIMAGELIST himlIconList, himlIconListBuf; // New image lists
+ int iMainIcon, iOverlayIcon;
+
+ if ((cxWidth < 0) || (cyHeight < 0) || !hMainIcon || !hOverlayIcon)
+ return NULL;
+
+ himlIconList = ImageList_Create((cxWidth==0)?GetSystemMetrics(SM_CXICON):cxWidth, (cyHeight==0)?GetSystemMetrics(SM_CYICON):cyHeight, (IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK,2, 0);
+ iMainIcon = ImageList_AddIcon(himlIconList, hMainIcon);
+ iOverlayIcon = ImageList_AddIcon(himlIconList, hOverlayIcon);
+
+ himlIconListBuf = ImageList_Merge(himlIconList, iMainIcon, himlIconList, iOverlayIcon, 0, 0);
+ ImageList_Destroy(himlIconList);
+
+ hIconReturn = ImageList_GetIcon(himlIconListBuf, iMainIcon, ILD_TRANSPARENT);
+ ImageList_Destroy(himlIconListBuf);
+
+ return hIconReturn; // returned HICON needs to be destroyed (DestroyIcon())
} \ No newline at end of file
diff --git a/utilities.h b/utilities.h
index 0e68a79..d61fbd5 100644
--- a/utilities.h
+++ b/utilities.h
@@ -1,45 +1,45 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_UTILITIES_H__
-#define SF_UTILITIES_H__ 1
-
-
-// -- Prototypes
-void ShowInfoMessage(UINT uIconID, const WCHAR* pszCaption, const WCHAR* pszTextFmt, size_t cchExtraSize,...);
-WCHAR* GetLastErrorDescription(DWORD dwLastError);
-
-void SkinAddNewSoundBundled(const char* pszName, const char* pszSection, const char* pszDescription, const WCHAR* pszDefaultFile);
-void SkinAddNewIcon(const char* pszName, const WCHAR* pszSection, const WCHAR* pszDescription, int iDefResID, BOOL bLarge);
-HICON SkinGetIcon(const char* pszDescription, int iDefResID, BOOL bLarge);
-void SkinAddNewHotkey(const char* pszName, const char* pszSection, const char* pszDescription, const int iDefHotkey, const char* pszServiceName);
-void SkinAddNewFont(const char* pszName, const char* pszSection, const char* pszDescription, const char* pszDefaultFile);
-BOOL SkinAddNewFontSameAs(const char* pszDescription, const char* pszSection, const char* pszSameAsDescription);
-BOOL SkinGetFont(const char* pszDescription, const char* pszSection, COLORREF* pclrColor, LOGFONT* plfFont);
-void SkinAddNewColor(const char* pszName, const char* pszSection, const char* pszDescription, COLORREF clrDefColor, BOOL bFontRelated);
-COLORREF SkinGetColor(const char* pszDbName, const char* pszDescription, const char* pszSection, COLORREF clrDefColor, BOOL bFontRelated);
-
-HIMAGELIST LoadSystemCheckboxImageList(void);
-HICON LoadSystemIcon(int iListID, int iIconIndex);
-
-HICON OverlayIcon(HICON hMainIcon, HICON hOverlayIcon, int cxWidth, int cyHeight); // returned HICON needs to be destroyed
-
-#endif // SF_UTILITIES_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_UTILITIES_H__
+#define SF_UTILITIES_H__ 1
+
+
+// -- Prototypes
+void ShowInfoMessage(UINT uIconID, const WCHAR* pszCaption, const WCHAR* pszTextFmt, size_t cchExtraSize,...);
+WCHAR* GetLastErrorDescription(DWORD dwLastError);
+
+void SkinAddNewSoundBundled(const char* pszName, const char* pszSection, const char* pszDescription, const WCHAR* pszDefaultFile);
+void SkinAddNewIcon(const char* pszName, const WCHAR* pszSection, const WCHAR* pszDescription, int iDefResID, BOOL bLarge);
+HICON SkinGetIcon(const char* pszDescription, int iDefResID, BOOL bLarge);
+void SkinAddNewHotkey(const char* pszName, const char* pszSection, const char* pszDescription, const int iDefHotkey, const char* pszServiceName);
+void SkinAddNewFont(const char* pszName, const char* pszSection, const char* pszDescription, const char* pszDefaultFile);
+BOOL SkinAddNewFontSameAs(const char* pszDescription, const char* pszSection, const char* pszSameAsDescription);
+BOOL SkinGetFont(const char* pszDescription, const char* pszSection, COLORREF* pclrColor, LOGFONT* plfFont);
+void SkinAddNewColor(const char* pszName, const char* pszSection, const char* pszDescription, COLORREF clrDefColor, BOOL bFontRelated);
+COLORREF SkinGetColor(const char* pszDbName, const char* pszDescription, const char* pszSection, COLORREF clrDefColor, BOOL bFontRelated);
+
+HIMAGELIST LoadSystemCheckboxImageList(void);
+HICON LoadSystemIcon(int iListID, int iIconIndex);
+
+HICON OverlayIcon(HICON hMainIcon, HICON hOverlayIcon, int cxWidth, int cyHeight); // returned HICON needs to be destroyed
+
+#endif // SF_UTILITIES_H__
diff --git a/variables.c b/variables.c
index 47de3a9..0480bcb 100644
--- a/variables.c
+++ b/variables.c
@@ -1,65 +1,65 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -----------------------------------------
-
-// Resolve: %autoignore_count%
-static int ServiceVariables_autoignore_count(WPARAM wParam, LPARAM lParam)
-{
- WCHAR* pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
- if (pszReturn)
- mir_sntprintf(pszReturn, MAX_INT_LENGTH, _T("%i"), (int)CallService(MS_SPAMFILTER_RESETAUTOIGNORE, (BOOL)TRUE, 0));
-
- return (int)pszReturn;
-}
-
-
-// ------------------------------------
-
-
-void InitVariables(void)
-{
- if (ServiceExists(MS_VARS_REGISTERTOKEN))
- {
- TOKENREGISTER tr;
-
- // Register: %autoignore_count%
- ZeroMemory(&tr, sizeof(tr));
- tr.cbSize = sizeof(tr);
- tr.memType = TR_MEM_MIRANDA;
- tr.tszTokenString = _T("autoignore_count");
- tr.flags = TRF_FIELD|TRF_UNICODE;
- tr.szHelpText = "Spam Filter\tNumber of users currently being in danger of being ignored.";
- tr.szService = "SpamFilter/Variables/autoignore_count";
- CreateServiceFunction(tr.szService, ServiceVariables_autoignore_count);
-
- CallService(MS_VARS_REGISTERTOKEN, 0, (LPARAM)&tr);
- }
-}
-
-
-void UninitVariables(void)
-{
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -----------------------------------------
+
+// Resolve: %autoignore_count%
+static int ServiceVariables_autoignore_count(WPARAM wParam, LPARAM lParam)
+{
+ WCHAR* pszReturn = (WCHAR*)mir_alloc((MAX_INT_LENGTH+1)*sizeof(WCHAR));
+ if (pszReturn)
+ mir_sntprintf(pszReturn, MAX_INT_LENGTH, _T("%i"), (int)CallService(MS_SPAMFILTER_RESETAUTOIGNORE, (BOOL)TRUE, 0));
+
+ return (int)pszReturn;
+}
+
+
+// ------------------------------------
+
+
+void InitVariables(void)
+{
+ if (ServiceExists(MS_VARS_REGISTERTOKEN))
+ {
+ TOKENREGISTER tr;
+
+ // Register: %autoignore_count%
+ ZeroMemory(&tr, sizeof(tr));
+ tr.cbSize = sizeof(tr);
+ tr.memType = TR_MEM_MIRANDA;
+ tr.tszTokenString = _T("autoignore_count");
+ tr.flags = TRF_FIELD|TRF_UNICODE;
+ tr.szHelpText = "Spam Filter\tNumber of users currently being in danger of being ignored.";
+ tr.szService = "SpamFilter/Variables/autoignore_count";
+ CreateServiceFunction(tr.szService, ServiceVariables_autoignore_count);
+
+ CallService(MS_VARS_REGISTERTOKEN, 0, (LPARAM)&tr);
+ }
+}
+
+
+void UninitVariables(void)
+{
} \ No newline at end of file
diff --git a/variables.h b/variables.h
index 90f7712..39f2caa 100644
--- a/variables.h
+++ b/variables.h
@@ -1,30 +1,30 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef SF_VARIABLES_H__
-#define SF_VARIABLES_H__ 1
-
-// -- Prototypes
-void InitVariables(void);
-void UninitVariables(void);
-
-
-#endif // SF_VARIABLES_H__
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_VARIABLES_H__
+#define SF_VARIABLES_H__ 1
+
+// -- Prototypes
+void InitVariables(void);
+void UninitVariables(void);
+
+
+#endif // SF_VARIABLES_H__
diff --git a/version.h b/version.h
index 8689677..10b320c 100644
--- a/version.h
+++ b/version.h
@@ -1,36 +1,36 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Defines: Versions
-#define NEEDED_MIRANDA_VERSION PLUGIN_MAKE_VERSION(0, 7, 0, 0) // Needs CallServiceSync, etc. (after 0, 3, 3, 0)
- // Unicode: Needs Unicode core and Unicode plugins, MS_LANGPACK_GETCODEPAGE
-#define NEEDED_MIRANDA_VERSION_STR "0.7.0"
-
-#define PLUGIN_VERSION PLUGIN_MAKE_VERSION(2, 5, 2, 3)
-
-
-// -- Defines: Internet
-#define PLUGIN_EMAIL "hrathh users.sourceforge.net"
-#define PLUGIN_EMAIL_ATT_POS 7 // position of the @-sign in the email adress above
-
-#define PLUGIN_FILELISTINGID 2188 // Spam Filter 1.0.4.0 = 791
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Defines: Versions
+#define NEEDED_MIRANDA_VERSION PLUGIN_MAKE_VERSION(0, 7, 0, 0) // Needs CallServiceSync, etc. (after 0, 3, 3, 0)
+ // Unicode: Needs Unicode core and Unicode plugins, MS_LANGPACK_GETCODEPAGE
+#define NEEDED_MIRANDA_VERSION_STR "0.7.0"
+
+#define PLUGIN_VERSION PLUGIN_MAKE_VERSION(2, 5, 2, 3)
+
+
+// -- Defines: Internet
+#define PLUGIN_EMAIL "hrathh users.sourceforge.net"
+#define PLUGIN_EMAIL_ATT_POS 7 // position of the @-sign in the email adress above
+
+#define PLUGIN_FILELISTINGID 2188 // Spam Filter 1.0.4.0 = 791
#define PLUGIN_FILELISTINGID_STR "2188" \ No newline at end of file