123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- #!/usr/bin/perl -w
- use strict;
- use XML::SimpleObject;
- # * 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, write to the Free Software
- # * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- # *
- # * Copyright 2006 Paul Mangan <paul@claws-mail.org>
- # *
- #
- # Convert new style Sylpheed filter rules (Sylpheed >= 0.9.99) to
- # Claws Mail filtering rules
- #
- #
- # TABLE OF EQUIVALENTS
- #
- # SYLPHEED : Claws Mail
- #------------------------------------------------------
- #
- # NAME
- #
- # name : rulename
- #
- # CONDITION LIST
- #
- # bool or : |
- # bool and : &
- #
- # match-header (name From) : from
- # match-header (name To) : to
- # match-header (name Cc) : cc
- # match-header (name Subject) : subject
- # else...
- # match-header : header
- #
- # match-header (type contains) : [nothing]
- # match-header (type not-contain) : [append with ~]
- # match-header (type is) : [no equivalent] (use type contains)
- # match-header (type is-not) : [no equivalent] (use type not-contain)
- # match-header (type regex) : regexpcase
- # match-header (type not-regex) : regexpcase [append with ~]
- #
- # matcher-any-header ; headers-part
- # match-to-or-cc : to_or_cc
- # match-body-text : body_part
- # command-test : test
- # size (type gt) : size_greater
- # size (type lt) : size_smaller
- # age (type gt) : age_greater
- # age (type lt) : age_lower
- #
- # ACTION LIST
- #
- # move : move
- # copy : copy
- # not-receive : [no equivalent] (use type delete)
- # delete : delete
- # mark : mark
- # color-label : color
- # mark-as-read : mark_as_read
- # exec : execute
- # stop-eval : stop
- #
- my $old_config = "$ENV{HOME}/.sylpheed-2.0/filter.xml";
- my $older_config = "$ENV{HOME}/.sylpheed/filter.xml";
- my $old_filters;
- my $config_dir = `claws-mail --config-dir` or die("ERROR:
- You don't appear to have Claws Mail installed\n");
- chomp $config_dir;
- chdir($ENV{HOME} . "/$config_dir") or die("ERROR:
- Claws Mail config directory not found [~/$config_dir]
- You need to run Claws Mail once, quit it, and then rerun this script\n");
- if (-e $old_config) {
- $old_filters = $old_config;
- } elsif (-e $older_config) {
- $old_filters = $older_config;
- } else {
- print "ERROR:\n\tSylpheed filter not found\n\t[$old_config]\n\t[$older_config]\n";
- exit;
- }
- my $claws_version = `claws-mail --version`;
- $claws_version =~ s/^Claws Mail version //;
- my ($major, $minor) = split(/\./, $claws_version);
- my $version_test = 0;
- if ($major > 2 || ($major == 2 && $minor >= 3)) {
- $version_test = 1;
- }
- my $parser = XML::Parser->new(ErrorContext => 2, Style => "Tree");
- my $xmlobj = XML::SimpleObject->new($parser->parsefile($old_filters));
- my @conditions = ('match-header','match-to-or-cc','match-any-header',
- 'match-body-text','command-test','size','age');
- my @actions = ('copy','not-receive','mark','color-label','mark-as-read',
- 'exec','stop-eval','move','delete');
- my $standard_headers = qr/^(?:Subject|From|To|Cc)$/;
- my $negative_matches = qr/^(?:not-contain|is-not|not-regex)$/;
- my $numeric_matches = qr/^(?:size|age)$/;
- my $exact_matches = qr/^(?:move|copy|delete|mark)$/;
- my @new_filters = ("[filtering]");
- my $disabled = 0;
- my $bool;
- ## rules list
- foreach my $element ($xmlobj->child("filter")->children("rule")) {
- my $new_filter = "\n";
- if ($element->attribute("enabled")) {
- if ($element->attribute("enabled") eq "false") {
- if ($version_test) {
- $new_filter .= "disabled ";
- } else {
- $disabled++;
- next; # skip disabled rules
- }
- } elsif ($version_test) {
- $new_filter .= "enabled ";
- }
- }
- if ($element->attribute("name")) {
- my $name = $element->attribute("name");
- $name = clean_me($name);
- $new_filter .= "rulename \"$name\" ";
- }
- ## condition list
- foreach my $parent ($element->children("condition-list")) {
- if ($parent->attribute("bool")) {
- $bool = $parent->attribute("bool");
- $bool =~ s/or/|/;
- $bool =~ s/and/&/;
- }
- foreach my $condition (@conditions) {
- my $new_condition = 0;
- my $type;
- if ($parent->children("$condition")) {
- foreach my $sibling ($parent->children("$condition")) {
- if ($new_condition) {
- $new_filter .= " $bool ";
- }
- if ($sibling->attribute("type")) {
- $type = $sibling->attribute("type");
- if ($type =~ m/$negative_matches/) {
- $new_filter .= '~';
- }
- }
- if ($sibling->attribute("name")) {
- my $name = $sibling->attribute("name");
- if ($condition eq "match-header") {
- if ($name =~ m/$standard_headers/) {
- $new_filter .= lc($name) . " ";
- } else {
- $new_filter .= "header \"$name\" ";
- }
- }
- }
- if ($condition eq "match-any-header") {
- $new_filter .= "headers_part ";
- } elsif ($condition eq "match-header-content") {
- $new_filter .= "headers_cont ";
- } elsif ($condition eq "match-to-or-cc") {
- $new_filter .= "to_or_cc ";
- } elsif ($condition eq "match-body-text") {
- $new_filter .= "body_part ";
- } elsif ($condition eq "command-test") {
- $new_filter .= "test ";
- } elsif ($condition eq "size") {
- if ($type eq "gt") {
- $new_filter .= "size_greater ";
- } else {
- $new_filter .= "size_smaller ";
- }
- } elsif ($condition eq "age") {
- if ($type eq "gt") {
- $new_filter .= "age_greater ";
- } else {
- $new_filter .= "age_lower ";
- }
- }
- if ($condition !~ m/$numeric_matches/ &&
- $condition ne "command-test") {
- if ($type =~ m/regex/) {
- $new_filter .= "regexpcase ";
- } else {
- $new_filter .= "matchcase ";
- }
- }
- my $value = clean_me($sibling->value);
- if ($condition =~ m/$numeric_matches/) {
- $new_filter .= "$value";
- } else {
- $new_filter .= "\"$value\"";
- }
- $new_condition++;
- }
- }
- }
- }
- ## end of condition list
- ## action list
- foreach my $parent ($element->children("action-list")) {
- foreach my $action (@actions) {
- if ($parent->children("$action")) {
- foreach my $sibling ($parent->children("$action")) {
- if ($action =~ m/$exact_matches/) {
- $new_filter .= " $action";
- } elsif ($action eq "not-receive") {
- $new_filter .= " delete";
- } elsif ($action eq "color-label") {
- $new_filter .= " color";
- } elsif ($action eq "mark-as-read") {
- $new_filter .= " mark_as_read";
- } elsif ($action eq "exec") {
- $new_filter .= " execute";
- } elsif ($action eq "stop-eval") {
- $new_filter .= " stop";
- }
- if ($sibling->value) {
- my $value = clean_me($sibling->value);
- if ($action eq "color-label") {
- $new_filter .= " $value";
- } else {
- $new_filter .= " \"$value\"";
- }
- }
- }
- }
- }
- }
- ## end of action list
- push(@new_filters, $new_filter) if (defined($new_filter));
- }
- ## end of rules list
- push(@new_filters, "\n");
- # write new config
- open(MATCHERRC, ">>matcherrc");
- print MATCHERRC @new_filters;
- close(MATCHERRC);
- print "Converted ". ($#new_filters-1) . " filters\n";
- if ($disabled) {
- print "[$disabled disabled filter(s) not converted]\n";
- }
- exit;
- sub clean_me {
- my ($dirty) = @_;
- $dirty =~ s/\"/\\\"/g;
- $dirty =~ s/\n/ /g;
- return $dirty;
- }
|