And more plugin hidden prefs: GPG
[clawsker.git] / clawsker
index 578c01c6f0de9ce0f6333f1e1e6dc5c1ca2f613c..d24171531af7f347ebf9dedab4db74a839b4ac0e 100755 (executable)
--- a/clawsker
+++ b/clawsker
@@ -70,6 +70,7 @@ sub _ {
     tab_other => _('Other'),
     tab_winpos => _('Windows'),
     tab_accounts => _('Accounts'),
+    tab_plugins => _('Plugins'),
 
     ab_frame => _('Addressbook'),
     mem_frame => _('Memory'),
@@ -212,25 +213,43 @@ sub _ {
     l_acc_gtls_pri => _('GnuTLS priority'),
     h_acc_gtls_pri => _('Value to use as GnuTLS priority string if custom priority check is enabled. Otherwise this value is ignored.'),
 
+    l_plu_gpg_alimit => _('Autocompletion limit'),
+    h_plu_gpg_alimit => _('Limits the number of addresses obtained from from keyring through autocompletion. Use 0 to get all matches.'),
     l_plu_lav_burl => _('Base URL'),
     h_plu_lav_burl => _('This is the URL where avatar requests are sent. You can use the one of your own libravatar server, if available.'),
+    l_plu_prl_flvb => _('Log level'),
+    h_plu_prl_flvb => _('Verbosity level of log, acumulative.'),
+    l_plu_prl_none => _('None'),
+    l_plu_prl_manual => _('Manual'),
+    l_plu_prl_action => _('Actions'),
+    l_plu_prl_match => _('Matches'),
 
     e_error => _('Error: '),
     e_noclawsrc => _('resource file for Claws Mail was not found.'),
     e_running => _('seems Claws Mail is currently running, close it first.'),
 );
 
+# data and metadata of resource files
+my $CONFIGDATA;
+my $CONFIGMETA;
+my $ACCOUNTDATA;
+my $ACCOUNTMETA;
 # all preferences read by load_preferences
 my %PREFS = ();
 my %ACPREFS = ();
+my %PLPREFS = ();
 # values of all preferences handled by clawsker
 my %HPVALUE = ();
 my %ACHPVALUE = ();
+my %PLHPVALUE = ();
 # default config dir and file name
 my $ALTCONFIGDIR = FALSE;
 my $CONFIGDIR = $ENV{HOME} . '/.claws-mail/';
 my $CONFIGRC = 'clawsrc';
 my $ACCOUNTRC = 'accountrc';
+# supported and available plugins lists
+my @PLUGINS = qw(AttRemover GPG ManageSieve Libravatar PerlPlugin);
+my @AVPLUGINS = ();
 
 # index constants for preference arrays
 use constant NAME  => 0; # the name on the rc file
@@ -239,6 +258,7 @@ use constant DESC  => 2; # the description for the hint/help
 use constant TYPE  => 3; # data type: bool, int, float, string, color
 use constant CMVER => 4; # lowest[,highest] Claws Mail version(s) the feature exists
 use constant CMDEF => 5; # default value for the preference in Claws Mail
+use constant PLUGIN => 6; # plugin section (only in plugin preferences)
 
 # constants for GUI spacing
 use constant HBOX_SPC => 5;
@@ -1850,7 +1870,7 @@ sub new_accounts_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '3.9.0.74',
         '-1',
-        undef,
+        'AttRemover',
     ],
     arm_winh => [
         'win_height',
@@ -1859,7 +1879,36 @@ sub new_accounts_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '3.9.0.74',
         '-1',
-        undef,
+        'AttRemover',
+    ],
+    # GPG
+    gpg_alimit => [
+        'autocompletion_limit',
+        $xl::s{l_plu_gpg_alimit},
+        $xl::s{h_plu_gpg_alimit},
+        'int,0,100',
+        '3.12.0.75',
+        '0',
+        'GPG',
+    ],
+    # managesieve
+    msv_winw => [
+        'manager_win_width',
+        $xl::s{l_win_w},
+        $xl::s{h_win_w},
+        'int,0,3000', # 0 pixels - 3000 pixels
+        '3.11.1.210',
+        '-1',
+        'ManageSieve',
+    ],
+    msv_winh => [
+        'manager_win_height',
+        $xl::s{l_win_h},
+        $xl::s{h_win_h},
+        'int,0,3000', # 0 pixels - 3000 pixels
+        '3.11.1.210',
+        '-1',
+        'ManageSieve',
     ],
     # libravatar
     lav_burl => [
@@ -1869,10 +1918,60 @@ sub new_accounts_page() {
         'char,0,1024,32',
         '3.9.3.32',
         'http://cdn.libravatar.org/avatar',
-        undef,
+        'Libravatar',
+    ],
+    # perl
+    prl_flvb => [
+        'filter_log_verbosity',
+        $xl::s{l_plu_prl_flvb},
+        $xl::s{h_plu_prl_flvb},
+        '0=l_plu_prl_none;1=l_plu_prl_manual;2=l_plu_prl_action;3=l_plu_prl_match',
+        '3.9.0.75',
+        '2',
+        'PerlPlugin',
     ],
 );
 
+sub new_plugins_page() {
+    my %frame = ();
+    $frame{'AttRemover'} =
+                new_subpage_frame (
+                     new_hbox_pack (
+                          new_text_box_for_int (\%pr::plu, 'arm_winw', $PLHPVALUE{'AttRemover'}),
+                          new_text_box_for_int (\%pr::plu, 'arm_winh', $PLHPVALUE{'AttRemover'})),
+                     _('Attachment remover'), 'not-packed');
+    $frame{'GPG'} =
+                new_subpage_frame (
+                     new_hbox_pack (
+                          new_text_box_for_int (\%pr::plu, 'gpg_alimit', $PLHPVALUE{'GPG'})),
+                     _('GPG'), 'not-packed');
+    $frame{'ManageSieve'} =
+                new_subpage_frame (
+                     new_hbox_pack (
+                          new_text_box_for_int (\%pr::plu, 'msv_winw', $PLHPVALUE{'ManageSieve'}),
+                          new_text_box_for_int (\%pr::plu, 'msv_winh', $PLHPVALUE{'ManageSieve'})),
+                     _('Sieve manager'), 'not-packed');
+    $frame{'Libravatar'} =
+                new_subpage_frame (
+                     new_hbox_pack (
+                          new_text_box_for_nchar (\%pr::plu, 'lav_burl', $PLHPVALUE{'Libravatar'})),
+                     _('Libravatar'), 'not-packed');
+    $frame{'PerlPlugin'} =
+                new_subpage_frame (
+                     new_hbox_pack (
+                          new_selection_box_for (\%pr::plu, 'prl_flvb', $PLHPVALUE{'PerlPlugin'})),
+                     _('Perl'), 'not-packed');
+    foreach (@PLUGINS) {
+        $frame{$_}->set_sensitive (defined $PLHPVALUE{$_});
+    }
+    return new_vbox_pack (
+                $frame{'AttRemover'},
+                $frame{'GPG'},
+                $frame{'ManageSieve'},
+                $frame{'Libravatar'},
+                $frame{'PerlPlugin'});
+}
+
 # version info
 sub print_version() {
     print $xl::s{about_title} . "\n";
@@ -1981,20 +2080,100 @@ sub init_ac_hidden_preferences {
     return TRUE;
 }
 
+sub init_plu_hidden_preferences {
+    foreach my $key (keys %pr::plu) {
+        my $plugin = $pr::plu{$key}[PLUGIN];
+        my $pname = $pr::plu{$key}[NAME];
+        if (defined $PLPREFS{$plugin}) {
+            $PLHPVALUE{$plugin}{$pname} = $PLPREFS{$plugin}{$pname};
+        }
+    }
+    return TRUE;
+}
+
+# generic load/save resource files
+sub load_resource {
+    my $rc = shift;
+    my %data = ();
+    my %meta = ();
+    my $line = 0;
+    open (RCF, '<:encoding(utf8)', $rc)
+        or die _("Error: opening '{file}' for reading", file => $rc) . ": $!";
+    my $section = '_'; # default unnamed section
+    while (<RCF>) {
+        chomp;
+        ++$line;
+        next if (/^\s*$/);
+        if (/^\[([^\]]+)\]$/) { # new section
+            $section = $1;
+            die _("Error: duplicate section '{sect}' in resource file '{file}'\n",
+                sect => $section, file => $rc) if ($data{$section});
+            $data{$section} = {};
+            $meta{$section}{'#'} = $line;
+        }
+        elsif (/^([0-9a-z_]+)=(.*)$/) { # key=value
+            $data{$section}{$1} = $2;
+            $meta{$section}{$1} = $line;
+        }
+        elsif (/^(.*)$/) { # lone value
+            push (@{$data{$section}{'_'}}, $1);
+        }
+    }
+    close (RCF);
+    return (\%data, \%meta);
+}
+
+sub save_resource {
+    my ($rc, $data, $meta) = @_;
+    open (RCF, '>:utf8', $rc)
+        or die _("Error: opening '{file}' for writing", file => $rc) . ": $!";
+    my @sections = keys %$data;
+    if (defined $meta) {
+        @sections = sort {
+            $meta->{$a}{'#'} <=> $meta->{$b}{'#'}
+        } @sections
+    }
+    foreach my $section (@sections) {
+        say RCF "[$section]";
+        if (ref ($data->{$section}{'_'}) eq 'ARRAY') {
+            foreach my $val (@{$data->{$section}{'_'}}) {
+                say RCF $val;
+            }
+        } else {
+            my @keys = keys %{$data->{$section}};
+            if (defined $meta) {
+                @keys = sort {
+                    $meta->{$section}{$a} <=> $meta->{$section}{$b}
+                } @keys
+            }
+            foreach my $key (@keys) {
+                my $val = $data->{$section}{$key};
+                say RCF "$key=$val";
+            }
+        }
+        say RCF "";
+    }
+    close (RCF);
+}
+
 # load current status from disc
 sub load_preferences {
     my $rc = get_rc_filename ();
     log_message ("Loading preferences from $rc\n");
     return FALSE unless check_rc_file ($rc);
     return FALSE unless check_claws_not_running ();
-    open (RCF, "<$rc");
-    while (<RCF>) {
-        chomp;
-        if (/^([8a-z_]+)=(.*)$/) {
-            $PREFS{$1} = decode('UTF-8', $2);
+    ($CONFIGDATA, $CONFIGMETA) = load_resource ($rc);
+    foreach (keys %{$CONFIGDATA->{'Common'}}) {
+        $PREFS{$_} = $CONFIGDATA->{'Common'}{$_};
+    }
+    foreach my $plugin (@PLUGINS) {
+        if (defined $CONFIGDATA->{$plugin}) {
+            push (@AVPLUGINS, $plugin);
+            foreach (keys %{$CONFIGDATA->{$plugin}}) {
+                $PLPREFS{$plugin}{$_} = $CONFIGDATA->{$plugin}{$_};
+            }
         }
     }
-    close (RCF);
     return TRUE;
 }
 
@@ -2003,19 +2182,14 @@ sub load_ac_preferences {
     log_message ("Loading account preferences from $rc\n");
     return FALSE unless check_rc_file ($rc);
     return FALSE unless check_claws_not_running ();
-    open (RCF, "<$rc");
-    my $akey;
-    while (<RCF>) {
-        chomp;
-        if (/^\[Account: (\d+)\]$/) {
-          $akey = $1;
-          next;
-        }
-        if (/^([8a-z_]+)=(.*)$/) {
-            $ACPREFS{$akey}{$1} = decode('UTF-8', $2);
+    ($ACCOUNTDATA, $ACCOUNTMETA) = load_resource ($rc);
+    foreach my $asect (keys %$ACCOUNTDATA) {
+        if ($asect =~ /^Account: (\d+)$/) {
+            foreach (keys %{$ACCOUNTDATA->{$asect}}) {
+                $ACPREFS{$1}{$_} = $ACCOUNTDATA->{$asect}{$_};
+            }
         }
     }
-    close (RCF);
     return TRUE;
 }
 
@@ -2027,24 +2201,19 @@ sub save_preferences {
     return FALSE unless check_claws_not_running ();
     my $rcbak = "$rc.backup";
     rename ($rc, $rcbak);
-    open (RCF, ">$rc");
-    open (RCB, "<$rcbak");
-    while (<RCB>) {
-        chomp;
-        if (/^([8a-z_]+)=(.*)$/) {
-            if (defined($HPVALUE{$1})) {
-                print RCF $1 . "=" . $HPVALUE{$1} . "\n";
-            }
-            else {
-                print RCF $_ . "\n";
-            }
+    foreach (keys %PREFS) {
+        if (defined $HPVALUE{$_}) {
+            $CONFIGDATA->{'Common'}{$_} = $HPVALUE{$_};
         }
-        else {
-            print RCF $_ . "\n";
+    }
+    foreach my $plugin (@AVPLUGINS) {
+        foreach (keys %{$CONFIGDATA->{$plugin}}) {
+            if (defined $PLHPVALUE{$plugin}{$_}) {
+                $CONFIGDATA->{$plugin}{$_} = $PLHPVALUE{$plugin}{$_};
+            }
         }
     }
-    close (RCB);
-    close (RCF);
+    save_resource ($rc, $CONFIGDATA, $CONFIGMETA);
     return TRUE;
 }
 
@@ -2055,30 +2224,16 @@ sub save_ac_preferences {
     return FALSE unless check_claws_not_running ();
     my $rcbak = "$rc.backup";
     rename ($rc, $rcbak);
-    open (RCF, ">$rc");
-    open (RCB, "<$rcbak");
-    my $akey;
-    while (<RCB>) {
-        chomp;
-        if (/^\[Account: (\d+)\]$/) {
-          $akey = $1;
-          print RCF $_ . "\n";
-          next;
-        }
-        if (/^([8a-z_]+)=(.*)$/) {
-            if (defined($ACHPVALUE{$akey}{$1})) {
-                print RCF $1 . "=" . $ACHPVALUE{$akey}{$1} . "\n";
-            }
-            else {
-                print RCF $_ . "\n";
+    foreach my $asect (keys %$ACCOUNTDATA) {
+        if ($asect =~ /^Account: (\d+)$/) {
+            foreach (keys %{$ACCOUNTDATA->{$asect}}) {
+                if (defined $ACHPVALUE{$1}{$_}) {
+                    $ACCOUNTDATA->{$asect}{$_} = $ACHPVALUE{$1}{$_};
+                }
             }
         }
-        else {
-            print RCF $_ . "\n";
-        }
     }
-    close (RCB);
-    close (RCF);
+    save_resource ($rc, $ACCOUNTDATA, $ACCOUNTMETA);
     return TRUE;
 }
 
@@ -2092,6 +2247,7 @@ sub new_notebook {
     $nb->append_page (new_other_page (), $xl::s{tab_other});
     $nb->append_page (new_winpos_page (), $xl::s{tab_winpos});
     $nb->append_page (new_accounts_page (), $xl::s{tab_accounts});
+    $nb->append_page (new_plugins_page (), $xl::s{tab_plugins});
 
     return $nb;
 }
@@ -2182,6 +2338,7 @@ exit unless load_preferences ();
 exit unless load_ac_preferences ();
 exit unless init_hidden_preferences ();
 exit unless init_ac_hidden_preferences ();
+exit unless init_plu_hidden_preferences ();
 # create main GUI
 my $box = Gtk2::VBox->new (FALSE, 5);
 $box->set_border_width(3);