tab_other => _('Other'),
tab_winpos => _('Windows'),
tab_accounts => _('Accounts'),
+ tab_plugins => _('Plugins'),
ab_frame => _('Addressbook'),
mem_frame => _('Memory'),
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
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;
'int,0,3000', # 0 pixels - 3000 pixels
'3.9.0.74',
'-1',
- undef,
+ 'AttRemover',
],
arm_winh => [
'win_height',
'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 => [
'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";
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;
}
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;
}
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;
}
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;
}
$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;
}
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);