2013-02-28 [mones] 3.9.0cvs105
authorRicardo Mones <mones@claws-mail.org>
Thu, 28 Feb 2013 21:43:49 +0000 (21:43 +0000)
committerRicardo Mones <mones@claws-mail.org>
Thu, 28 Feb 2013 21:43:49 +0000 (21:43 +0000)
* configure.ac
* src/plugins/perl/Makefile.am
* src/plugins/perl/cm_perl.pod
* src/plugins/perl/tools/.cvsignore
* src/plugins/perl/tools/Makefile.am
* src/plugins/perl/tools/insert_perl.pl
* src/plugins/perl/tools/matcherrc2perlfilter.pl
Make perl plugin tools and manpage available into
distribution tarball.

ChangeLog
PATCHSETS
configure.ac
src/plugins/perl/Makefile.am
src/plugins/perl/cm_perl.pod [new file with mode: 0644]
src/plugins/perl/tools/.cvsignore [new file with mode: 0644]
src/plugins/perl/tools/Makefile.am [new file with mode: 0644]
src/plugins/perl/tools/insert_perl.pl [new file with mode: 0644]
src/plugins/perl/tools/matcherrc2perlfilter.pl [new file with mode: 0644]

index 4383e22192c65a837c712eabbb1b427042960089..a722c4b6b2e5a2c54a9ade60746757b3a82616c3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-02-28 [mones]     3.9.0cvs105
+
+       * configure.ac
+       * src/plugins/perl/Makefile.am
+       * src/plugins/perl/cm_perl.pod
+       * src/plugins/perl/tools/.cvsignore
+       * src/plugins/perl/tools/Makefile.am
+       * src/plugins/perl/tools/insert_perl.pl
+       * src/plugins/perl/tools/matcherrc2perlfilter.pl
+               Make perl plugin tools and manpage available into 
+               distribution tarball.
+
 2013-02-27 [mones]     3.9.0cvs104
 
        * README
index da04f9f75d625783f0dd9808e29ab6966bd28121..cbf049c387240143698f117416317b18a9129323 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src//plugins/vcalendar/libical/libical/Makefile.am;  ) > 3.9.0cvs102.patchset
 ( cvs diff -u -r 1.94.2.242 -r 1.94.2.243 src/messageview.c;  ) > 3.9.0cvs103.patchset
 ( cvs diff -u -r 1.8.2.67 -r 1.8.2.68 README;  ) > 3.9.0cvs104.patchset
+( cvs diff -u -r 1.654.2.4681 -r 1.654.2.4682 configure.ac;  cvs diff -u -r 1.1.2.4 -r 1.1.2.5 src/plugins/perl/Makefile.am;  diff -u /dev/null src/plugins/perl/cm_perl.pod;  diff -u /dev/null src/plugins/perl/tools/.cvsignore;  diff -u /dev/null src/plugins/perl/tools/Makefile.am;  diff -u /dev/null src/plugins/perl/tools/insert_perl.pl;  diff -u /dev/null src/plugins/perl/tools/matcherrc2perlfilter.pl;  ) > 3.9.0cvs105.patchset
index 1db118465f3a55e844cb275eca2eef5d709ec3ec..0c1e934479c1b254834811c628eb91652553070e 100644 (file)
@@ -12,7 +12,7 @@ MINOR_VERSION=9
 MICRO_VERSION=0
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=104
+EXTRA_VERSION=105
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
@@ -1840,6 +1840,7 @@ src/plugins/notification/Makefile
 src/plugins/notification/gtkhotkey/Makefile
 src/plugins/pdf_viewer/Makefile
 src/plugins/perl/Makefile
+src/plugins/perl/tools/Makefile
 src/plugins/python/Makefile
 src/plugins/pgpcore/Makefile
 src/plugins/pgpmime/Makefile
index ca38f6d57bd36728a8462f015198c850e0fae117..6924e68e0e7ed2312b970ef3052b3348b3adc6b5 100644 (file)
@@ -1,3 +1,5 @@
+SUBDIRS = tools
+
 plugindir = $(pkglibdir)/plugins
 
 if BUILD_PERL_PLUGIN
@@ -26,3 +28,6 @@ INCLUDES = \
        -I$(top_srcdir)/src/common \
        -I$(top_builddir)/src/common \
        -I$(top_srcdir)/src/gtk
+
+EXTRA_DIST = cm_perl.pod
+
diff --git a/src/plugins/perl/cm_perl.pod b/src/plugins/perl/cm_perl.pod
new file mode 100644 (file)
index 0000000..fd52295
--- /dev/null
@@ -0,0 +1,768 @@
+=head1 NAME
+
+cm_perl -- A Perl Plugin for Claws Mail
+
+
+=head1 DESCRIPTION
+
+This plugin provides an extended filtering engine for the email
+client Claws Mail. It allows for the use of full Perl power
+in email filters.
+
+=head1 QUICK START
+
+To get started, you can use the B<matcherrc2perlfilter.pl> script
+in the B<tools>-directory to translate your old filtering rules to
+Perl. Simply execute the script and follow the instructions.
+(note that with recent versions of Claws Mail, this script might not
+work due to upstream syntax changes. This will get updated in the
+future. Send me an email if you have problems getting started).
+
+However, you might want to consider reading the rest of this
+manual and rewriting your rules if you choose to use the plugin,
+since the Perl code produced by this script is not exactly
+pretty.
+
+Don't speak Perl? No problem, L<"perldoc perlintro"|perlintro>
+should give you enough information to do fancy stuff.
+
+=head1 USAGE
+
+The Perl plugin expects a Perl script file called B<perl_filter>
+in Claws Mail' config directory (usually $HOME/.claws-mail --
+try `claws-mail --config-dir' if you're unsure). If that file
+doesn't exist on plugin start, an empty one is created.  This
+file, which doesn't need to start with a sha-bang (!#/bin/perl),
+holds the Perl instructions for your email filters. To encourage
+some good manners, the code is executed in a C<use strict;>
+environment.
+
+Both Claws Mail' filtering B<conditions> and B<actions> are
+mapped to Perl functions with corresponding names, wherever this
+is possible.
+
+=head1 FUNCTION LISTING
+
+For a detailed function description, see section L</"FUNCTION
+DESCRIPTIONS">, below.
+
+=over 4
+
+=item Standard Filtering Conditions
+
+ all, marked, unread, deleted, new, replied,
+ forwarded, locked, ignore_thread, colorlabel,
+ match, matchcase, regexp, S<regexpcase, test,
+ size_greater, size_smaller, size_equal,
+ score_greater, score_lower, score_equal, age_greater,
+ age_lower, partial, tagged
+
+=item Standard Filtering Actions
+
+ mark, unmark, dele, mark_as_unread, mark_as_read,
+ lock, unlock, move, copy, color, execute,
+ hide, set_score, change_score, stop, forward,
+ forward_as_attachment, redirect, set_tag, unset_tag,
+ clear_tags
+
+=item Fun stuff
+
+ header, body, filepath, extract_addresses,
+ move_to_trash, abort, addr_in_addressbook,
+ from_in_addressbook, get_attribute_value, SA_is_spam,
+ exit, manual, make_sure_folder_exists,
+ filter_log, filter_log_verbosity,
+ make_sure_tag_exists
+
+=back
+
+=head1 FUNCTION DESCRIPTIONS
+
+In general, after the filtering invoked by the Perl script, the
+mail is passed on to Claws' internal filtering engine, I<unless>
+a B<final> rule was hit. Final rules stop not only the Perl
+filtering script at the point of their occurence, but also
+prevent processing that email by Claws' internal filtering engine
+(this might sound confusing, but you are already familiar with
+that concept from standard filters: After an email was
+e.g. I<move>d, the following rules don't apply anymore).
+
+Also, be careful with the way you quote. In particular, remember
+that the @-sign has a special meaning in Perl, and gets
+interpolated inside double quotes. See L<perlop/"Quote and
+Quote-like Operators"> to learn more about quoting and
+interpolation.
+
+
+=head2 Standard Filtering Conditions
+
+=over 8
+
+=item all
+
+Returns a true value. Available for completness only.
+
+=item marked
+
+Returns a true value if the marked flag is set, false otherwise.
+
+=item unread
+
+Returns a true value if the unread flag is set, false otherwise.
+
+=item deleted
+
+Returns a true value if the deleted flag is set, false otherwise.
+
+=item new
+
+Returns a true value if the new flag is set, false otherwise.
+
+=item replied
+
+Returns a true value if the replied flag is set, false otherwise.
+
+=item forwarded
+
+Returns a true value if the forwarded flag is set, false otherwise.
+
+=item locked
+
+Returns a true value if the locked flag is set, false otherwise.
+
+=item ignore_thread
+
+Returns a true value if the "Ignore Thread" flag is set, false otherwise.
+
+=item colorlabel COLOR
+
+=item colorlabel
+
+Returns a true value if message has the color COLOR. COLOR can be
+either a numeric value between 0 and 7 (with colors corresponding
+to the internal filtering engine), or the english color name as
+it is introduced in the filtering dialog (that is, one of: none,
+orange, red, pink, sky blue, blue, green or brown, while upper
+and lower case letters make no difference). If COLOR is omitted,
+0 (none) is assumed.
+
+=item size_greater SIZE
+
+Returns a true value if message size is greater than SIZE, false otherwise.
+
+=item size_smaller SIZE
+
+Returns a true value if message size is smaller than SIZE, false otherwise.
+
+=item size_equal SIZE
+
+Returns a true value if message size is equal to SIZE, false otherwise.
+
+=item score_greater SCORE
+
+Returns a true value if message score is greater than SCORE, false otherwise.
+
+=item score_lower SCORE
+
+Returns a true value if message score is lower than SCORE, false otherwise.
+
+=item score_equal SCORE
+
+Returns a true value if message score is equal to SCORE, false otherwise.
+
+=item age_greater AGE
+
+Returns a true value if message age is greater than AGE, false otherwise.
+
+=item age_lower AGE
+
+Returns a true value if message age is lower than AGE, false otherwise.
+
+=item partial
+
+Returns a true value if message has only partially been
+downloaded, false otherwise.
+
+=item tagged
+
+Returns a true value if the messages has one or more tags.
+
+=item test
+
+Corresponds the 'test' internal filtering rule. In particular, it
+accepts the same symbols, namely:
+
+=over 
+
+=item %%
+
+%
+
+=item %s
+
+Subject
+
+=item %f
+
+From
+
+=item %t
+
+To
+
+=item %c
+
+Cc
+
+=item %d
+
+Date
+
+=item %i
+
+Message-ID
+
+=item %n
+
+Newsgroups
+
+=item %r
+
+References
+
+=item %F
+
+Filename -- should not be modified
+
+=back
+
+=item match WHERE WHAT
+
+=item matchcase WHERE WHAT
+
+=item regexp WHERE WHAT
+
+=item regexpcase WHERE WHAT
+
+The matching functions have a special syntax. The first argument
+is either any of to_or_cc, body_part, headers_part, message, to,
+from, subject, cc, newsgroups, inreplyto, references, or tag (those
+strings may or may not be quoted), the patter matching works on
+that area. If it is any other string (which must then be quoted),
+this string is taken to be the name of a header field.
+
+The second argument is the string to look for. For match,
+matchcase, regexp and regexpcase we have case sensitive normal
+matching, case insensitive normal matching, case sensitive
+regular expression matching and case insensitive regular
+expression pattern matching, respectively.
+
+The functions return true if the pattern was found, false
+otherwise.
+
+Just as with the built-in filtering engine, the message body is
+searched and provided as is - no character-set analysis is
+done. Likewise, no HTML-tags are stripped. It should be possible
+to use external modules or programs for these tasks though. If
+you're doing that, drop me a message with your experiences.
+
+With Perl having its strenghts in pattern matching, using Perl's
+builtin operators are usually a better option than using these
+functions.
+
+=back
+
+=head2 Standard Filtering Actions
+
+The actions return a true value upon success, and 'undef' when an
+error occured. I<Final> message rules are indicated. (See above
+for a sketch what a final rule is)
+
+=over 8
+
+=item mark
+
+Mark the message.
+
+=item unmark
+
+Unmark the message.
+
+=item dele
+
+Delete the message. Note the name change of Claws Mail'
+"delete" to "dele". This is because "delete" is one of Perl's
+builtin commands which cannot be redefined (if it can, tell me
+how).
+
+This is a I<final> rule.
+
+=item mark_as_read
+
+Mark the message as read 
+
+=item mark_as_unread
+
+Mark the message as unread
+
+=item lock
+
+Lock the message
+
+=item unlock
+
+Remove the message lock
+
+=item move DESTINATION
+
+Move the message to folder DESTINATION. The folder notation is
+the same that Claws Mail uses. You can copy & paste from the
+move dialog of the normal filtering, until you get a feeling for
+the notation.
+
+This is a I<final> rule.
+
+=item copy DESTINATION
+
+Copy the message to folder DESTINATION. The folder notation is
+the same that Claws Mail uses. You can copy & paste from the
+move dialog of the normal filtering, until you get a feeling for
+the notation.
+
+=item execute COMMAND
+
+This is the same as the test - rule from section L</"Standard
+Filtering Conditions"> execpt that it always returns a true
+value.
+
+=item hide
+
+Hide the message
+
+=item set_score SCORE
+
+Set message score to SCORE
+
+=item change_score SCORE
+
+Change message score by SCORE
+
+=item stop
+
+Stop Perl script at this point. Note that this is B<not> a final
+rule, meaning that the email gets passed on to the internal
+filtering engine. See "abort" below if you don't want that.
+
+=item forward ACCOUNT, EMAIL
+
+Forward the message to email address EMAIL, using the account ID
+ACCOUNT as sender account. So far, you have to create a rule
+in the normal filtering engine to find out that number.
+
+=item forward_as_attachment, ACCOUNT EMAIL
+
+Forward the message to email address EMAIL in an attachment,
+using the account ID ACCOUNT as sender account. So far, you
+have to create a rule in the normal filtering engine to find out
+that number.
+
+=item redirect ACCOUNT, EMAIL
+
+Redirect the message to EMAIL, using the account ID ACCOUNT as
+sender account. So far, you have to create a rule in the normal
+filtering engine to find out that number.
+
+=item set_tag TAG
+
+Apply tag TAG. TAG must exist.
+
+=item unset_tag TAG
+
+Unset tag TAG.
+
+=item clear_tags
+
+Clear all tags.
+
+=back
+
+=head2 Fun stuff
+
+=head3 Functions
+
+=over 8
+
+=item header ARG
+
+=item header
+
+If ARG is not given, returns a list of all header field names of
+the mail.
+
+If ARG is given, returns 'undef' if the header field ARG does not
+exist in the email. Otherwise, it returns
+
+=over
+
+=item in scalar context
+
+The value of the header field ARG.
+
+=item in list context
+
+A list of all available header field values. This is useful if a
+header field occurs more than once in an email (eg the Received -
+header).
+
+=back
+
+The header field "References" forms a special case. In a scalar context,
+it returns the first reference. In a list context, it returns a list of
+all references.
+
+=item body
+
+Returns the email body in a scalar.
+
+=item filepath
+
+Returns the file and path of the email that is currently filtered
+(corresponds to the %F arguemnt in the 'test' rule).
+
+=item extract_addresses
+
+Extracts email addresses from a string and gives back a list of
+addresses found. Currently an email address is found using the
+regular expression '[-.+\w]+\@[-.+\w]+'. This will not find all
+valid email addresses. Feel free to send me a better regexp.
+
+=item move_to_trash
+
+Move the email message to default trash folder.
+
+This is a I<final> rule.
+
+=item abort
+
+Stop Perl script at this point.
+
+In contrast to 'stop', this is a I<final> rule.
+
+=item addr_in_addressbook EMAIL, ADDRESSBOOK
+
+=item addr_in_addressbook EMAIL
+
+Returns a true value if the email address EMAIL is in the addressbook
+with the name ADDRESSBOOK. If ADDRESSBOOK is not given, returns
+true if the email address is in any addressbook.
+
+=item from_in_addressbook ADDRESSBOOK
+
+=item from_in_addressbook
+
+Checks if the email address found in the From-header is in
+addressbook ADDRESSBOOK (or any, if omitted). It is implemented
+as
+
+ my ($from) = extract_addresses(header("from"));
+ return 0 unless $from;
+ return addr_in_addressbook($from,@_);
+
+so the same restrictions as to extract_addresses apply.
+
+=item get_attribute_value EMAIL, ATTRIBUTE, ADDRESSBOOK
+
+=item get_attribute_value EMAIL, ATTRIBUTE
+
+Looks through the addressbook ADDRESSBOOK (or all addressbooks,
+if omitted) for a contact with the an email address EMAIL. If
+found, the function checks if this contact has a user attribute
+with name ATTRIBUTE. It returns the value of this attribute, or
+an empty string if it was not found. As usual, 'undef' is
+returned if an error occured.
+
+=item SA_is_spam
+
+Is an alias to
+
+not test 'spamc -c < %F > /dev/null'
+
+=item exit
+
+Has been redefined to be an alias to 'stop'. You shouldn't use
+Perl's own 'exit' command, since it would exit Claws Mail.
+
+=item manual
+
+Returns a true value if the filter script was invoked manually,
+that is, via the Tools menu.
+
+=item make_sure_folder_exists IDENTIFIER
+
+Returns a true value if the folder with id IDENTIFIER (e.g. #mh/Mail/foo/bar)
+exists or could be created.
+
+=item make_sure_tag_exists TAG
+
+Returns a true value if the tag TAG exists or could be created.
+
+=item filter_log SECTION, TEXT
+
+=item filter_log TEXT
+
+Writes TEXT to the filter logfile. SECTION can be any of
+
+=over
+
+=item *
+
+"LOG_MANUAL"
+
+=item *
+
+"LOG_MATCH"
+
+=item *
+
+"LOG_ACTION"
+
+=back
+
+If the SECTION is omitted, "LOG_MANUAL" is assumed.
+
+=item filter_log_verbosity VERBOSITY
+
+=item filter_log_verbosity
+
+Changes the filter log verbosity for the current mail. VERBOSITY
+must be any of
+
+=over
+
+=item *
+
+0
+
+=item *
+
+1
+
+=item *
+
+2
+
+=item *
+
+3
+
+=back
+
+For the meaning of those numbers, read section L</"LOGGING">. If
+VERBOSITY is omitted, the filter logfile verbosity is not changed.
+
+This function returns the filter_log_verbosity number before the
+change (if any).
+
+=back
+
+=head3 Variables
+
+=over 8
+
+=item $permanent
+
+This scalar keeps its value between filtered mail messages. On
+plugin start, it is initialized to the empty string.
+
+=back
+
+=head1 LOGGING
+
+To keep track of what has been done to the mails while filtering,
+the plugin supports logging. Three verbosity levels are
+recognized:
+
+=over
+
+=item 0
+
+logging disabled
+
+=item 1
+
+log only manual messages, that is, messages introduced by the
+C<filter_log> command in filter scripts
+
+=item 2
+
+log manual messages and filter actions
+
+=item 3
+
+log manual messages, filter actions and filter matches
+
+=back
+
+The messages are logged in Claws Mail' log window.
+The default log level is 2. Log level 3 is not
+recommended, because the matcher functions log a message if they
+succeeded, and thus, if you have negative checks, you'll get
+confusing entries. If you want to keep track of matching, do it
+manually, using C<filter_log>, or do it by temporary enabling
+matcher logging using C<filter_log_verbosity>.
+
+The first time you unload this plugin (or shut down
+Claws Mail), a section called B<[PerlPlugin]> will be created
+in Claws Mail' configuration file B<clawsrc>, containing
+one variable:
+
+ * filter_log_verbosity
+
+If you want to change the default behaviour, you can edit this
+line. Make sure Claws Mail is not running while you do
+this.
+
+It will be possible to access these setting via the GUI, as soon
+as I find the time to write a corresponding GTK plugin, or
+somebody else is interested in contributing that.
+
+=head1 EXAMPLE
+
+This section lists a small example of a Perl script file. I'm
+sure you get the idea..
+
+ #-8<----------------------------------------------------
+ # -*- perl -*-
+ # local functions
+ # Learn ham messages, and move them to specified folder. This is
+ # useful for making sure a bayes filter sees ham as well.
+ sub learn_and_move {
+     execute('put command to learn ham here');
+     move(@_);
+ }
+ # Two-stage spam filter. Every email that scores higher than 15
+ # on SpamAssassin gets moved into the default trash folder.
+ # All mails lower than that, but higher than SpamAssassin's
+ # 'required_hits' go into  #mh/mail/Spam.
+ sub spamcheck {
+     my $surely_spam = 15;
+     my $filepath = filepath;
+     my $spamc = `spamc -c < $filepath`;
+     my ($value,$threshold) = ($spamc =~ m|([-.,0-9]+)/([-.,0-9]+)|);
+     if($value >= $surely_spam) {
+        mark_as_read;
+       move_to_trash;
+     }
+     if($value >= $threshold) {mark_as_read; move '#mh/mail/Spam';}
+ }
+ # Perl script execution starts here.
+ # Some specific sorting
+ learn_and_move '#mh/mail/MailLists/Claws Mail/user'
+   if matchcase('sender','claws-mail-users-admin@lists.sourceforge.net');
+ learn_and_move '#mh/mail/MailLists/Sylpheed'
+   if matchcase('list-id','sylpheed.good-day.net');
+ # Implement imcomming folders using addressbook
+ # attributes. Target folders for specific email addresses are
+ # stored directly in the addressbook. This way, if an email
+ # address changes, we only have to update the addressbook, not
+ # the filter rules! Besides that, we can greatly unclutter the
+ # filter script.
+
+ # get the email address in the from header
+ my $fromheader = header "from";
+ my ($from) = extract_addresses $fromheader;
+
+ # check if this email address has an associated attribute
+ # called "incomming_folder". If if has, the value of this
+ # attribute is supposed to be the target folder.
+ my $value = get_attribute_value $from, "incomming_folder";
+ learn_and_move($value) if $value;
+
+ # An example of a whitelist: If the from-address is in my
+ # "office" addressbook, move the mail to folder #mh/mail/office
+ learn_and_move '#mh/mail/office' if from_in_addressbook("office");
+ # If the from-address is in any other addressbook, move the
+ # mail to folder #mh/mail/inbox/known
+ learn_and_move '#mh/mail/inbox/known' if from_in_addressbook;
+
+ # Feed the remaining mails through SpamAssassin.
+ spamcheck;
+
+ # mails that make it to the end of the script are passed on to
+ # the internal filtering engine. If the internal rules don't say
+ # otherwise, the mails end up in the default inbox.
+ #-8<----------------------------------------------------
+
+
+=head1 BUGS
+
+=over 4
+
+=item *
+
+Do B<not> use this plugin together with other filtering plugins,
+especially the B<Spamassassin> and B<ClamAV> plugins. They are
+registered on the same hook and the order in which the plugins
+are executed is not guaranteed.
+
+=item *
+
+The filter script is not (yet) updated automatically when a
+folder gets renamed. The same applies for folder names in
+addressbook user attributes.
+
+=item *
+
+This plugin has only be tested with POP3 accounts. If you have
+experiences with IMAP or newsgroup accounts, drop me a message.
+
+=item *
+
+Warning during compile time:
+
+ *** Warning: Linking the shared library perl_plugin.la against the
+ *** static library
+ /usr/lib/perl5/5.8.3/i586-linux-thread-multi/auto/DynaLoader/DynaLoader.a
+ is not portable!
+
+Ideas to solve this one are welcome :-)
+
+=back
+
+Please report comments, suggestions and bugreports to the address
+given in the L</AUTHOR> section of this document.
+
+
+=head1 LICENSE and (no) WARRANTY
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation;
+either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see http://www.gnu.org/licenses/.
+
+=head1 SEE ALSO
+
+claws-mail(1), perl(1)
+
+
+=head1 AUTHOR
+
+Holger Berndt  <berndth@gmx.de>
+
+=cut
diff --git a/src/plugins/perl/tools/.cvsignore b/src/plugins/perl/tools/.cvsignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/src/plugins/perl/tools/Makefile.am b/src/plugins/perl/tools/Makefile.am
new file mode 100644 (file)
index 0000000..499944f
--- /dev/null
@@ -0,0 +1,10 @@
+EXTRA_TOOLS = \
+       matcherrc2perlfilter.pl
+
+EXTRA_DIST = \
+       $(EXTRA_TOOLS)
+
+MAKE_EXE = chmod u+x $(EXTRA_TOOLS)
+
+all-local:
+       $(MAKE_EXE)
\ No newline at end of file
diff --git a/src/plugins/perl/tools/insert_perl.pl b/src/plugins/perl/tools/insert_perl.pl
new file mode 100644 (file)
index 0000000..7d90f62
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/perl -w
+# parameters: <cmd> what perl-code c-code
+#
+use strict;
+use File::Copy;
+
+die "Wrong parameters\n" if $#ARGV != 2;
+
+my ($what,$perl_code,$c_code) = @ARGV;
+
+copy($c_code,$c_code.".bak") or die "Copy failed: $!";
+
+open FH,"<",$perl_code or die "Cannot open $perl_code: $!";
+my @perl_code = <FH>; close FH;
+
+foreach (@perl_code) {
+    s|\\|\\\\|g;
+    s|\"|\\\"|g;
+    s|(.*)|\"$1\\n\"|;
+}
+
+open FH,"<",$c_code or die "Cannot open $c_code: $!";
+my @c_code = <FH>; close FH;
+
+my (@c_code_new,$line);
+
+while($line = shift @c_code) {
+    if($line =~ /const\s+char\s+$what\s*\[\s*\]\s*=\s*\{/) {
+       push @c_code_new,$line;
+       push @c_code_new,$_ foreach (@perl_code);
+       $line = shift @c_code while(not ($line =~ m/^\s*\}\s*;\s*$/));
+       push @c_code_new,$line;
+    }
+    else {
+       push @c_code_new,$line;
+    }
+}
+
+open FH,">",$c_code or die "Cannot open $c_code: $!";
+print FH "$_" foreach (@c_code_new);
diff --git a/src/plugins/perl/tools/matcherrc2perlfilter.pl b/src/plugins/perl/tools/matcherrc2perlfilter.pl
new file mode 100644 (file)
index 0000000..5372372
--- /dev/null
@@ -0,0 +1,203 @@
+#!/usr/bin/perl -w
+#
+## script purpose : convert matcherrc filtering rules into
+##                  perl_filter rules
+#
+# This conversion-tool doesn't produce nice Perl code and is just
+# intended to get you started. If you choose to use the Perl plugin,
+# consider rewriting your rules.
+#
+# Copyright (C) 2004 Holger Berndt
+#
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+use strict;
+
+our $warnings = 0;
+our $lines    = 0;
+our $tokens   = 0;
+
+my $home_dir   = $ENV{"HOME"}; $home_dir ||= ".";
+my $sylph_dir  = `claws-mail --config-dir`;
+my $matcherrc  = "matcherrc";
+my $perlfilter = "perl_filter";
+my $dirsep     = "/";
+
+chomp($sylph_dir); $sylph_dir =~ s/.*\n(.*)$/$1/;
+my $inpath  = $home_dir.$dirsep.$sylph_dir.$dirsep.$matcherrc;
+my $outpath = $home_dir.$dirsep.$sylph_dir.$dirsep.$perlfilter;
+open IN,      $inpath  or die "Cannot open $inpath: $!";
+open OUT,">>",$outpath or die "Cannot open $outpath: $!";
+
+print "Filtering rules are read from `$inpath', converted to Perl\n";
+print "syntax and appended to `$outpath'\n";
+print "`$inpath' is not changed, so you might want to make a backup\n";
+print "copy of it and then remove your former filtering rules\n";
+print "---\n";
+my $date = `date`;
+chomp($date);
+print OUT "### Begin: Rules converted by matcherrc2perlfilter.pl $date ###\n";
+while(my $line = <IN>) {
+    $line =~ s/^\s*(.*)\s*$/$1/;
+    if($line =~ /^\[filtering\]$/i) {
+       while($line = <IN>) {
+           $line =~ s/^\s*(.*)\s*$/$1/;
+           next if $line =~ /^$/;
+           if($line =~ /^\[(.+)\]$/) {
+               last unless ($1 =~ /filtering/i);
+           }
+           my @fields = splitline($line);
+           $lines++;
+           convert(@fields);
+       }
+    }
+}
+print "---\n" if $warnings;
+print "Finished conversion of $lines rules with $warnings warnings.\n";
+print OUT "### End: Rules converted by matcherrc2perlfilter.pl $date ###\n";
+
+# convert a rule
+sub convert {
+    my $act = 0;
+    my $output="(";
+    while(my $token = shift) {
+       $tokens++;
+       if($token eq "&") {
+           $token = shift;
+       }
+       elsif($token eq "|") {
+           $output =~ s/&& $/\|\| /;
+           $token = shift;
+       }
+       elsif($tokens != 1 and $act == 0) {
+           $act = 1;
+           if($output =~ / (&&|\|\|) $/) {
+               $output =~ s/ (&&|\|\|) $/\) $1 /;
+           }
+           else {
+               $output .= ")";
+           }
+       }
+
+       if($token eq "~") {
+           $output .= "!";
+           $token = shift;
+       }
+
+       if($token eq "all"           or
+          $token eq "marked"        or
+          $token eq "deleted"       or
+          $token eq "replied"       or
+          $token eq "forwarded"     or
+          $token eq "locked"        or
+          $token eq "unread"        or
+          $token eq "new"           or
+          $token eq "partial"       or
+          $token eq "ignore_thread" or
+          $token eq "mark"          or
+          $token eq "unmark"        or
+          $token eq "lock"          or
+          $token eq "unlock"        or
+          $token eq "stop"          or
+          $token eq "hide"          or
+          $token eq "mark_as_read"  or
+          $token eq "mark_as_unread") {
+           $output .= qq|($token) && |;
+       }
+       elsif($token eq "delete") {
+           $output .= qq|(dele) && |;
+       }
+       elsif($token eq "subject"       or
+             $token eq "from"          or
+             $token eq "to"            or
+             $token eq "cc"            or
+             $token eq "to_or_cc"      or
+             $token eq "newsgroups"    or
+             $token eq "inreplyto"     or
+             $token eq "references"    or
+             $token eq "headers_part"  or
+             $token eq "body_part"     or
+             $token eq "message") {
+           my $match = shift;
+           my $what  = shift;
+           $what =~ s/\\"/"/g;$what =~ s/'/\\'/g;
+           $what =~ s/^"(.*)"$/'$1'/;
+           $output .= qq|($match($token,$what)) && |;
+       }
+       elsif($token eq "age_greater"   or
+             $token eq "age_lower"     or
+             $token eq "colorlabel"    or
+             $token eq "score_greater" or
+             $token eq "score_lower"   or
+             $token eq "score_equal"   or
+             $token eq "size_greater"  or
+             $token eq "size_smaller"  or
+             $token eq "size_equal"    or
+             $token eq "move"          or
+             $token eq "copy"          or
+             $token eq "execute"       or
+             $token eq "color"         or
+             $token eq "test"          or
+             $token eq "change_score"  or
+             $token eq "set_score") {
+           my $arg = shift;
+           $arg =~ s/\\"/"/g;$arg =~ s/'/\\'/g;
+           $arg =~ s/^"(.*)"$/'$1'/;
+           $output .= qq|($token($arg)) && |;
+       }
+       elsif($token eq "header") {
+           my $headername = shift;
+           $headername =~ s/\\"/"/g;$headername =~ s/'/\\'/g;
+           $headername =~ s/^"(.*)"$/'$1'/;
+           my $match = shift;
+           my $what = shift;
+           $what =~ s/\\"/"/g;$what =~ s/'/\\'/g;          
+           $what =~ s/^"(.*)"$/'$1'/;
+           $output .= qq|($match($headername,$what)) && |;
+       }
+       elsif($token eq "stop") {
+           $output .= qq|(return) && |;
+       }
+       else {
+           print STDERR "WARNING: unknown token in $inpath ignored: $token\n";
+           $warnings++;
+       }
+    }
+    $output =~ s| && $|;\n|;
+    print OUT $output;
+    $tokens = 0;
+}
+
+# split the input line
+sub splitline {
+    my @fields;
+    my $line = shift;
+    while($line) {
+       $line =~ s/^\s+//;
+       if($line =~ m#^"#) {
+          $line =~ s#^(".*?[^\\]")##;
+          push @fields,$1;
+        }
+       elsif($line =~ /^~/) {
+           $line =~ s#^(~)##;
+           push @fields,$1;
+       }
+       else {
+           $line =~ s#^(\S+)##;
+           push @fields,$1;
+       }
+    }
+    return @fields;
+}