2007-02-19 [paul] 2.7.2cvs51
authorPaul Mangan <paul@claws-mail.org>
Mon, 19 Feb 2007 17:29:00 +0000 (17:29 +0000)
committerPaul Mangan <paul@claws-mail.org>
Mon, 19 Feb 2007 17:29:00 +0000 (17:29 +0000)
* tools/Makefile.am
* tools/README
* tools/thunderbird-filters-convertor.pl
add new script which converts thunderbird filter
rules to Claws filter rules

ChangeLog
PATCHSETS
configure.ac
tools/Makefile.am
tools/README
tools/thunderbird-filters-convertor.pl [new file with mode: 0644]

index 2e50d1d0d69f03f330b5cd2ca2edae3ba211cdd0..366254324bed37ed890493b66fa0bb1c075ff459 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2007-02-19 [paul]      2.7.2cvs51
+
+       * tools/Makefile.am
+       * tools/README
+       * tools/thunderbird-filters-convertor.pl
+               add new script which converts thunderbird filter
+               rules to Claws filter rules
+
 2007-02-18 [paul]      2.7.2cvs50
 
        * src/plugins/pgpcore/prefs_gpg.c
index 757f960b52c6cef081d476e3aeb82f72c65a2c3c..7ef25aed9346ba26d6ad7dcbf2fe358262fb31d6 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.94.2.123 -r 1.94.2.124 src/messageview.c;  ) > 2.7.2cvs48.patchset
 ( cvs diff -u -r 1.105.2.86 -r 1.105.2.87 src/prefs_account.c;  ) > 2.7.2cvs49.patchset
 ( cvs diff -u -r 1.1.2.19 -r 1.1.2.20 src/plugins/pgpcore/prefs_gpg.c;  cvs diff -u -r 1.1.2.7 -r 1.1.2.8 src/plugins/pgpcore/prefs_gpg.h;  cvs diff -u -r 1.1.2.40 -r 1.1.2.41 src/plugins/pgpcore/sgpgme.c;  cvs diff -u -r 1.1.2.28 -r 1.1.2.29 src/plugins/pgpinline/pgpinline.c;  cvs diff -u -r 1.1.2.44 -r 1.1.2.45 src/plugins/pgpmime/pgpmime.c;  ) > 2.7.2cvs50.patchset
+( cvs diff -u -r 1.25.2.15 -r 1.25.2.16 tools/Makefile.am;  cvs diff -u -r 1.30.2.15 -r 1.30.2.16 tools/README;  diff -u /dev/null tools/thunderbird-filters-convertor.pl;  ) > 2.7.2cvs51.patchset
index d79b36f4528eb6737092e77a2b24715450c86a6c..00b21c289a8ddf1b249197ff1dd1d92c5387abab 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=7
 MICRO_VERSION=2
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=50
+EXTRA_VERSION=51
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 977a454367a43124ae17e363f9fd6f5487206b8b..0c54a3b127a8616c5a6ba8fb441ddeeec62edd62 100644 (file)
@@ -23,6 +23,7 @@ EXTRA_TOOLS = \
        tbird2claws.py \
        textviewer.pl \
        textviewer.sh \
+       thunderbird-filters-convertor.pl \
        update-po \
        uudec \
        uuooffice \
index d138b65a231ba282e32bf4be2bb4f1343e1a8f94..ee38543d05ba115df338e4ebcb82be5b2a89f3f1 100644 (file)
@@ -35,7 +35,9 @@ Other tools:
   nautilus2claws-mail.sh       Send files from Nautilus
   OOo2claws-mail.pl             Send documents from OpenOffice.org
   sylprint.pl                   Printing engine, explained in README.sylprint
-  textviewer.pl                        Display various attachments as text 
+  textviewer.pl                        Display various attachments as text
+  thunderbird-filters-convertor.pl
+                               Convert Thunderbird filtering rules
 
 Extra tools:
   gif2xface.pl                  Convert a 48x48 GIF file to an X-Face header
@@ -546,6 +548,45 @@ Other tools
        
   Contact: H.Merijn Brand <h.m.brand@xs4all.nl>
 
+
+* thunderbird-filters-convertor.pl
+
+  WHAT IT DOES
+       This perl script converts Thunderbird filtering rules into Claws Mail
+       filtering rules. It can be run several times, once for each filter
+       configuration file in Thunderbird.
+
+  HOW TO USE IT
+       The script takes 3 arguments:
+
+       --tbird-file=PATH TO FILE       The full path to the file to be converted
+       --mailbox-name=NAME             The name of the Claws Mail mailbox
+       --account-name=NAME             The name of the account to be used (optional)   
+
+       --tbird-file must point to the Thunderbird filter file (msgFilterRules.dat)
+       that you want to convert, it must contain the full path to the file.
+       --mailbox-name should be given the name of your mailbox in Claws Mail, e.g.
+       if the top-level folder is 'Mailbox (MH)' then this option should be
+       'Mailbox'.
+       --account-name is optional, only needed if you are creating account-specific
+       rules. This is the name of your account in Claws Mail, which should
+       correspond to an account that you had in Thunderbird, e.g. the acount whose
+       rules you are converting.
+
+       This script presumes that your folder hierarchy in Claws Mail matches the
+       one that you had in Thunderbird. If you used the tbird2claws.py script to
+       convert your Thunderbird mailbox, then the folder hierarchy should match.
+
+       If the Claws Mail filtering configuration file (matcherrc) does not exist,
+       the script will create it; if it does exist, the newly converted rules will
+       be appended to it.
+
+  REQUIREMENTS
+       Getopt::Long
+       URI::Escape
+
+  Contact: Paul Mangan <paul@claws-mail.org>
+
 --------------------------------------------------------------------------------
 
 Extra tools
diff --git a/tools/thunderbird-filters-convertor.pl b/tools/thunderbird-filters-convertor.pl
new file mode 100644 (file)
index 0000000..7a42066
--- /dev/null
@@ -0,0 +1,518 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Getopt::Long;
+use URI::Escape;
+
+#  * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#  *
+#  * Copyright 2007 Paul Mangan <paul@claws-mail.org>
+#  *
+
+#
+# Convert Thunderbird filtering rules to Claws Mail filtering rules
+#
+
+#
+# TABLE OF EQUIVALENTS
+#
+# thunderbird                  :       Claws Mail
+#------------------------------------------------------
+#
+# name="NAME"                  :       rulename "NAME"
+#
+# enabled="yes"                        :       enabled / disabled
+#
+# CONDITION LIST
+# --------------
+#
+# OR                           :       |
+# AND                          :       &
+#
+# subject                      :       subject
+# from                         :       from
+# to                           :       to
+# cc                           :       cc
+# to or cc                     :       to_or_cc
+# body                         :       body-part
+# date                         :       ****
+# priority                     :       ****
+# status                       :       ****
+# age in days                  :       age_greater/age_lower
+# size                         :       size_greater/size_smaller
+# [custom header]              :       header
+#
+# 2nd level conditions
+# --------------------
+#
+# contains                     :       [nothing]
+# doesn't contain              :       [append with ~]
+# is                           :       regexpcase
+# isn't                                :       regexpcase
+# ends with                    :       regexpcase
+# begins with                  :       regexpcase
+# is in ab                     :       found_in_addressbook
+# isn't in ab                  :       ~found_in_addressbook
+#
+#
+# status 2nd and 3rd level conditions
+# -----------------------------------
+#
+# [is|isn't] replied
+# [is|isn't] read
+# [is|isn't] new
+# [is|isn't] forwarded
+# [is|isn't] flagged
+#
+#
+# Date header 2nd  level condition
+# --------------------------------
+#
+# is
+# isn't
+# is before
+# is after
+#
+#
+# Priority header 2nd and 3rd level conditions
+# --------------------------------------------
+# is            [Lowest|Low|Normal|High|Highest]
+# is higher than [Lowest|Low|Normal|High|Highest]
+# is lower than  [Lowest|Low|Normal|High|Highest]
+# 
+#
+# ACTION LIST
+# -----------
+#
+# Move to folder               :       move
+# Copy to folder               :       copy
+# Forward                      :       ****
+# Reply                                :       ****
+# Mark read                    :       mark_as_read
+# Mark flagged                 :       mark
+# Label                                :       ****
+# Change priority              :       ****
+# JunkScore 100 [mark as spam] :       ****
+# JunkScore 0 [mark as ham]    :       ****
+# Delete                       :       delete
+# Delete from Pop3 server      :       delete
+# Fetch body from Pop3Server   :       ****
+#
+
+my $script = "thunderbird-filters-convertor.pl";
+my ($tbirdfile, $account, $mailbox, $iNeedHelp) = 0;
+
+GetOptions("tbird-file=s"      => \$tbirdfile,
+          "account-name=s"     => \$account,
+          "mailbox-name=s"     => \$mailbox,
+          "help|h"             => \$iNeedHelp);
+
+if ($iNeedHelp) {
+       help_me();
+}
+
+if (!$tbirdfile) {
+       print "ERROR: No filename given\n";
+       print "Use $script -h for help\n";
+       exit;
+}
+
+unless (-e $tbirdfile) {
+       print "ERROR: $tbirdfile NOT FOUND!!\n";
+       exit;
+}
+
+if (!$mailbox) {
+       print "ERROR: No mailbox name given\n";
+       print "Use $script -h for help\n";
+       exit;
+}
+
+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 re-run this script\n");
+
+my $acrc = "accountrc";
+my $acc_number;
+
+if ($account) {
+       $acc_number = find_account_number();
+}
+if ($account && !$acc_number) {
+       print "ERROR: Account '$account' NOT FOUND!\n";
+       exit;
+}
+
+my @claws_filters = ();
+
+## check if matcherrc already exists
+if (-e "matcherrc") {
+       print "matcherrc exists!\n";
+       read_current_filters();
+} else {
+       push(@claws_filters, "[preglobal]\n\n[postglobal]\n\n[filtering]\n")
+}
+##
+my ($rule_count,@thunderbird_filters)  = read_thunderbird_filters();
+
+my ($conv_rule,$ignored_rule,$ignore_list) = convert_filters($rule_count,@thunderbird_filters);
+
+if (@claws_filters) {
+       system("mv matcherrc matcherrc-safecopy");
+       print "Moved ". $ENV{HOME}. "/$config_dir/matcherrc to "
+             . $ENV{HOME}. "/$config_dir/matcherrc-safecopy\n";
+}
+# write new config
+open(MATCHERRC, ">>matcherrc");
+       print MATCHERRC @claws_filters;
+close(MATCHERRC);
+
+print "We're done!\n";
+print "-------------\n";
+print "Converted $conv_rule rules";
+if (defined($ignored_rule)) {
+       print ", ignored $ignored_rule rules";
+}
+print "\n-------------\n";
+print "$ignore_list";
+
+exit;
+
+sub help_me {
+       print<<'EOH';
+Usage: 
+       thunderbird-filters-convertor.pl [options]
+Options:
+       --help -h                       Show this screen.
+       --tbird-file=PATH TO FILE       The full path to the file to be converted
+       --mailbox-name=NAME             The name of the Claws Mail mailbox
+       --account-name=NAME             The name of the account to be used (optional)   
+EOH
+exit;
+}
+
+sub find_account_number {
+       my $cur_acc_numb;
+       my $cur_acc_name;
+
+       open (ACCOUNTRC, "<$acrc") || 
+               die("Can't open the Accounts file [$acrc]\n");
+               my @acrclines = <ACCOUNTRC>;
+       close ACCOUNTRC;
+       
+       foreach my $line (@acrclines) {
+               unless ($line =~ m/^\[Account/ || 
+                       $line =~ m/^account_name/) { next; }
+               chomp($line);
+
+               if ($line =~ s/^\[Account: //) {
+                       $line =~ s/]$//;
+                       $cur_acc_numb = $line;
+               }
+               if ($line =~ s/^account_name=//) {
+                       $cur_acc_name = $line;
+               }
+               if (defined($cur_acc_name) && $cur_acc_name eq $account) {
+                       return($cur_acc_numb);
+               }
+       }
+}
+
+sub read_current_filters {
+       print "Reading current filters\n";
+
+       open (CFILTERS, "<matcherrc") || 
+               die("Can't open " . $ENV{HOME} . "/$config_dir/matcherrc");
+               @claws_filters = <CFILTERS>;
+       close CFILTERS;
+
+       remove_last_empty_lines();
+}
+
+sub remove_last_empty_lines {
+       my $line = pop(@claws_filters);
+       if ($line =~ m/^$/) {
+               remove_last_empty_lines();
+       } else {
+               push(@claws_filters, $line);
+       }
+}
+
+sub read_thunderbird_filters {
+       my @outer_array = ();
+       my @inner_array = ();
+       my $count = 0;
+
+       open (TBIRDFILE, "<$tbirdfile") || 
+               die("Can't open the tbird file [$tbirdfile]\n");
+               my @tbirdlines = <TBIRDFILE>;
+       close TBIRDFILE;
+
+       foreach my $line (@tbirdlines) {
+               if ($line =~ m/^version/ || $line =~ m/^logging/) { next; }
+
+               chomp($line);
+
+               push(@inner_array, "$line") unless $line eq "";
+               if ($line =~ m/^condition/) {
+                       push(@outer_array, [@inner_array]);
+                       @inner_array = ();
+                       $count++;
+               }
+       }
+       return($count-1,@outer_array);
+}
+
+sub convert_filters {
+       my ($rule_count,@thunderbird_filters) = @_;
+
+       my $tbird_action_no_value = qr/^(?:"Mark read"|"Mark flagged"|"Delete"|"Delete from Pop3 server"|"Fetch body from Pop3Server")$/;
+       my $tbird_action_ignore = qr/^(?:"Label"|"Change priority"|"JunkScore"|"Fetch body from Pop3Server"|"Delete from Pop3 server"|"Reply")$/;
+       my $exact_matches = qr/^(?:subject|from|to|cc)$/;
+       my $ignore_matches = qr/^(?:date|priority|status)$/;
+
+       my $conv_rules = my $ignored_rules = 0;
+       my $ignored_list = "";
+       for (my $outerloop = 0; $outerloop <= $rule_count; $outerloop++) {
+               my $part_one = my $part_two = my $part_three = my $part_four = "";
+               my $ignore_rule = my $move_rule = my $copy_rule = my $cond_count = 0;
+               my %ignore_hash;
+               my $bool = my $claws_condition = my $cur_name = "";
+               for (my $innerloop = 0; exists($thunderbird_filters[$outerloop][$innerloop]); $innerloop++) {
+                       my $entry = $thunderbird_filters[$outerloop][$innerloop];
+                       if ($entry =~ s/^name=//) {
+                               $cur_name = $entry;
+                               $part_one = "rulename $entry ";
+                       } elsif ($entry =~ s/^enabled=//) {
+                               if ($entry eq "\"yes\"") {
+                                       $part_one = "enabled $part_one";
+                               } else {
+                                       $part_one = "disabled $part_one";
+                               }
+                               if (defined($acc_number)) {
+                                       $part_one .= "account $acc_number ";
+                               }
+                       } elsif ($entry =~ s/^type=//) {
+                               # do nothing : what does 'type' mean??
+                       } elsif ($entry =~ s/^action=//) {
+                               if ($entry =~ m/$tbird_action_ignore/ && !$ignore_rule) {
+                                       $ignore_rule = 1;
+                                       unless ($ignore_hash{$cur_name}) {
+                                               $ignored_list .= "Ignored $cur_name because it contains $entry\n";
+                                               $ignored_rules++;
+                                       }
+                                       $ignore_hash{$cur_name}++;
+                                       $part_one = "";
+                                       next;
+                               } elsif ($entry =~ m/Move to folder/) {
+                                       $part_four = "move ";
+                                       $move_rule = 1;
+                               } elsif ($entry =~ m/Copy to folder/) {
+                                       $part_three .= "copy";
+                                       $copy_rule = 1;
+                               } elsif ($entry =~ m/Mark read/) {
+                                       $part_three .= "mark_as_read ";
+                               } elsif ($entry =~ m/Mark flagged/) {
+                                       $part_three .= "mark";
+                               } elsif ($entry =~ m/Delete/) {
+                                       $part_three .= "delete";
+                               }
+                       } elsif ($entry =~ s/^actionValue=//) {
+                               if ($ignore_rule) {
+                                       $ignore_rule = 0;
+                                       next;
+                               } elsif ($move_rule) {
+                                       $entry = rewrite_mailbox_name($entry);
+                                       $part_four .= uri_unescape($entry);
+                                       $move_rule = 0;                                 
+                               } elsif ($copy_rule) {
+                                       $entry = rewrite_mailbox_name($entry);
+                                       $part_three .= " " . uri_unescape($entry);
+                                       $copy_rule = 0;
+                               }
+                       } elsif ($entry =~ s/^condition=//) {
+                               if ($entry =~ s/^\"AND//) {
+                                       $bool= "&";
+                               } elsif ($entry =~ s/^\"OR//) {
+                                       $bool = "|";
+                               }
+                               my @tbird_conditions = split(/ \(/, $entry);
+                               foreach my $cond (@tbird_conditions) {
+                                       my $exact = my $endswith = my $beginswith = my $addrbook = 0;
+                                       my $age_condition = my $size_condition = my $exact_age = 0;
+                                       $cond =~ s/\) OR$//;
+                                       $cond =~ s/\) AND$//;
+                                       $cond =~ s/\)"$//;
+                                       my ($cpart_one, $cpart_two, $cpart_thr) = split(/,/, $cond, 3);
+                                       if ($cond) {
+                                               if ($cpart_one =~ m/$exact_matches/) {
+                                                       $claws_condition .= "$cpart_one";
+                                               } elsif ($cpart_one eq "to or cc") {
+                                                       $claws_condition .= "to_or_cc";
+                                               } elsif ($cpart_one eq "body") {
+                                                       $claws_condition .= "body-part";
+                                               } elsif ($cpart_one eq "age in days") {
+                                                       $age_condition = 1;
+                                               } elsif ($cpart_one eq "size") {
+                                                       $size_condition = 1;
+                                               } elsif ($cpart_one =~ m/$ignore_matches/) {
+                                                       $part_one = $claws_condition = $part_three = $part_four = "";
+                                                       next;
+                                               } else {
+                                                       $claws_condition = "head";
+                                               }
+
+                                               if ($cpart_two eq "doesn't contain") {
+                                                       $claws_condition = "~$claws_condition matchcase";
+                                               } elsif ($cpart_two eq "contains") {
+                                                       $claws_condition = "$claws_condition matchcase";
+                                               } elsif ($cpart_two eq "isn't") {
+                                                       $exact = 1;
+                                                       $claws_condition = "~$claws_condition regexpcase";
+                                               } elsif ($cpart_two eq "is") {
+                                                       if ($size_condition) {
+                                                               $claws_condition .= "size_equal";
+                                                       } elsif ($age_condition) {
+                                                               if ($bool ne "&") {
+                                                                       $part_one = $claws_condition = $part_three = $part_four = "";
+                                                                       if (!$ignored_list) {
+                                                                               $ignored_list .= "Ignored $cur_name because it matches an exact age and is an OR match\n";
+                                                                       }
+                                                                       next;
+                                                               } else {
+                                                                       $ignored_rules--;
+                                                                       $exact_age = 1;
+                                                               }
+                                                       } else {
+                                                               $exact = 1;
+                                                               $claws_condition = "$claws_condition regexpcase";
+                                                       }
+                                               } elsif ($cpart_two eq "ends with") {
+                                                       $endswith = 1;
+                                                       $claws_condition = "$claws_condition regexpcase";
+                                               } elsif ($cpart_two eq "begins with") {
+                                                       $beginswith = 1;
+                                                       $claws_condition = "$claws_condition regexpcase";
+                                               } elsif ($cpart_two eq "is in ab") {
+                                                       $addrbook = 1;
+                                                       $claws_condition = "found_in_addressbook \"$claws_condition\" in \"Any\" ";
+                                               } elsif ($cpart_two eq "isn't in ab") {
+                                                       $addrbook = 1;
+                                                       $claws_condition = "~found_in_addressbook \"$claws_condition\" in \"Any\" ";
+                                               } elsif ($cpart_two eq "is greater than") {
+                                                       if ($size_condition) {
+                                                               $claws_condition .= "size_greater";
+                                                       }
+                                                       if ($age_condition) {
+                                                               $claws_condition .= "age_greater";
+                                                       }
+                                               } elsif ($cpart_two eq "is less than") {
+                                                       if ($size_condition) {
+                                                               $claws_condition .= "size_smaller";
+                                                       }
+                                                       if ($age_condition) {
+                                                               $claws_condition .= "age_lower";
+                                                       }
+                                               }                                                       
+                               
+                                               if ($exact || $beginswith || $endswith) {
+                                                       $cpart_thr = escape_regex($cpart_thr);
+                                               }
+                                               if ($exact) {
+                                                       $cpart_thr = "^$cpart_thr\$";
+                                               } elsif ($beginswith) {
+                                                       $cpart_thr = "^$cpart_thr";
+                                               } elsif ($endswith) {
+                                                       $cpart_thr = "$cpart_thr\$";
+                                               }
+                                               unless ($addrbook) {
+                                                       if ($exact_age) {
+                                                               my $lower_limit = $cpart_thr-1;
+                                                               my $upper_limit = $cpart_thr+1;
+                                                               $lower_limit =~ s/^\"//;
+                                                               $lower_limit =~ s/\"$//;
+                                                               $upper_limit =~ s/^\"//;
+                                                               $upper_limit =~ s/\"$//;
+                                                               $claws_condition = "$claws_condition"."age_lower"
+                                                                                        . " $upper_limit $bool "
+                                                                                        . "age_greater $lower_limit ";
+                                                       } elsif ($size_condition || $age_condition) {
+                                                               $claws_condition = "$claws_condition $cpart_thr ";
+                                                       } else {        
+                                                               $claws_condition = "$claws_condition \"$cpart_thr\" ";
+                                                       }
+                                               }
+
+                                               if ($tbird_conditions[1] && $cond_count < $#tbird_conditions) {
+                                                       $claws_condition = "$claws_condition$bool ";
+                                               }
+                                       }
+                                       $cond_count++;
+                               }
+                               if ($part_one) {
+                                       $conv_rules++;
+                                       push(@claws_filters, "$part_one$claws_condition$part_three$part_four\n");
+                               }
+                       }
+               }
+       }
+       push(@claws_filters, "\n");
+       return($conv_rules,$ignored_rules,$ignored_list);
+}
+
+sub rewrite_mailbox_name {
+       my ($path) = @_;
+
+       my $new_path;
+
+       my ($front,$back) = split(/\/\//, $path, 2);
+
+       if ($front =~ m/^"mailbox/) {
+               $new_path = "\"#mh/$mailbox/";
+       } else {
+               $new_path = "\"#imap/$mailbox/";
+       }
+
+       my ($box,$name) = split(/\//, $back, 2);
+
+       if ($new_path =~ m/^"#mh/) {
+               $name =~ s/^Inbox/inbox/;
+               $name =~ s/^Sent/sent/;
+               $name =~ s/^Drafts/draft/;
+               $name =~ s/^Trash/trash/;
+       }
+       $new_path = $new_path.$name;
+
+       return($new_path);
+}
+
+sub escape_regex {
+       my ($string) = @_;
+
+       my $escstr = "";
+       my $symbols = qr/^(?:\[|\]|\{|\}|\(|\)|\||\+|\*|\.|\-|\$|\^)$/;
+       my @chars = split(//, $string);
+
+       foreach my $char (@chars) {
+               if ($char =~ m/$symbols/) { $char = "\\\\$char"; }
+               $escstr .= $char;
+       }
+
+       return($escstr);
+}