Unverified Commit 5b5fd551 authored by IKEDA Soji's avatar IKEDA Soji Committed by GitHub
Browse files

Refactor internals of config (1) (#924)

* Merge @sympa::ConfDef::params into %Sympa::ListDef::pinfo
* Merge %Conf::old_params into %Sympa::ListDef::pinfo
* Add aliases of parameter names for compatibility to sympa.conf/robot.conf of earlier versions.
* Move content of Sympa::ListDef to Sympa::Config::Schema
* Move content of Sympa::ConfDef to Sympa::Config::Schema
* Defining additional format entries in config schema.
* Merge sympa.conf(5) and list_config(5) into sympa_config(5).
parent 680b0d40
......@@ -260,7 +260,7 @@
[% CATCH %]
[% END %]
[% IF conf.show_report_abuse %]
[% IF conf.show_report_abuse == 'on' %]
<li>
[% PROCESS report_abuse.tt2 ~%]
</li>
......
......@@ -72,7 +72,7 @@
</form>
[% END %]
[% IF session.auth == 'classic' AND conf.allow_account_deletion %]
[% IF session.auth == 'classic' AND conf.allow_account_deletion == 'on' %]
<h4>[%|loc%]Deleting your account[%END%]</h4>
<p>
[%|loc%]Deleting your account will unsubscribe you from all your lists, remove your ownership of your lists and permanently delete your account.[%END%]
......
......@@ -60,6 +60,7 @@ man5_MANS = \
list_config.5 \
nrcpt_by_domain.conf.5 \
sympa.conf.5 \
sympa_config.5 \
sympa_database.5 \
sympa.wsdl.5 \
sympa_scenario.5 \
......@@ -73,9 +74,10 @@ EXTRA_DIST = $(nobase_doc_DATA) \
crawlers_detection.conf.pod \
edit_list.conf.pod \
ldap_alias_manager.conf.pod \
list_config.podpl \
list_config.pod \
nrcpt_by_domain.conf.pod \
sympa.conf.podpl \
sympa.conf.pod \
sympa_config.podpl \
sympa_database.podpl \
sympa_scenario.pod \
sympa_toc.pod \
......
=encoding utf-8
=head1 NAME
list_config - Configuration file for mailing list
=head1 DESCRIPTION
See L<sympa_config(5)>.
=cut
=encoding utf-8
=head1 NAME
sympa.conf, robot.conf - Configuration file for default site and robot
=head1 DESCRIPTION
See L<sympa_config(5)>.
=cut
# $Id$
use strict;
use warnings;
use English qw(-no_match_vars);
use Sympa::ConfDef;
use Sympa::Constants;
use Sympa::ListDef;
my %overrides;
while (my ($pname, $pitem) = each %Sympa::ListDef::pinfo) {
%overrides = (%overrides, _get_overrides($pname, $pitem, [$pname]));
}
my $parameters = '';
foreach my $param (@Sympa::ConfDef::params) {
if (exists $param->{name}) {
my $name = $param->{name};
my $default =
(exists $param->{default_s}) ? $param->{default_s}
: (exists $param->{default}) ? $param->{default}
: undef;
my $query = $param->{gettext_id}
if exists $param->{gettext_id};
my $advice = $param->{gettext_comment}
if exists $param->{gettext_comment};
my $example = $param->{sample}
if exists $param->{sample};
my $optional = 1
if exists $param->{optional} and $param->{optional};
my $vhost = 1
if exists $param->{vhost} and $param->{vhost};
my $multiple = 1
if exists $param->{multiple} and $param->{multiple};
my $scenario = $name
if exists $param->{scenario} and $param->{scenario};
if ($name eq 'color_0') {
$parameters .= "=head4 C<color_0>, ..., C<color_15>\n\n";
} elsif ($name =~ /\Acolor_/) {
next;
} elsif ($name eq 'dark_color') {
$parameters .=
"=head4 C<dark_color>, C<light_color>, C<text_color>, C<bg_color>, C<error_color>, C<selected_color>, C<shaded_color>\n\n";
} elsif ($name =~ /_color\z/) {
next;
} elsif ($name eq 'main_menu_custom_button_1_title') {
$parameters .=
"=head4 C<main_menu_custom_button_1_title>, ... C<main_menu_custom_button_3_title>, C<main_menu_custom_button_1_url>, ... C<main_menu_custom_button_3_url>, C<main_menu_custom_button_1_target>, ... C<main_menu_custom_button_3_target>\n\n";
} elsif ($name =~ /\Amain_menu_custom_button_/) {
next;
} else {
$parameters .= sprintf "=head4 C<%s>\n\n", $param->{name};
}
$parameters .= sprintf "%s\n\n", _escape_pod($query)
if defined $query;
$parameters .= "=over\n\n";
$parameters .= "=item Default:\n\n";
if ($name =~ /\Acolor_/ or $name =~ /_color\z/) {
$parameters .= "See description on web interface.\n\n";
} elsif (defined $default) {
if (exists $param->{gettext_unit}) {
$parameters .= sprintf "C<%s> (%s)\n\n",
_escape_pod($default), $param->{gettext_unit};
} else {
$parameters .= sprintf "C<%s>\n\n", _escape_pod($default);
}
} elsif ($optional) {
if (exists $param->{gettext_unit}) {
$parameters .= sprintf "None (%s).\n\n",
$param->{gettext_unit};
} else {
$parameters .= "None.\n\n";
}
} else {
$parameters .= "None, I<mandatory>.\n\n";
}
$parameters .= "=item Overrides:\n\n";
$parameters .= "Virtual domain\n\n"
if defined $vhost;
if ($overrides{$name}) {
if ($overrides{$name} eq $name) {
$parameters .= "List\n\n";
} else {
$parameters .= sprintf "List (C<%s>)\n\n", $overrides{$name};
}
}
$parameters .= "None.\n\n"
unless defined $vhost or $overrides{$name};
$parameters .= "=back\n\n";
$parameters .=
sprintf "Value of this parameter is name of C<%s> scenario.\n\n",
$name
if defined $scenario;
$parameters .= sprintf "%s\n\n",
join("\n\n", split "\n", _escape_pod($advice))
if defined $advice;
if ($name eq 'main_menu_custom_button_1_title') {
$parameters .= "Example:\n\n";
$parameters .= " main_menu_custom_button_1_title FAQ\n";
$parameters .=
" main_menu_custom_button_1_url http://www.renater.fr/faq/universalistes/index\n";
$parameters .= " main_menu_custom_button_1_target Help\n\n";
} else {
$parameters .= sprintf "Example:\n\n %s %s\n\n", $name, $example
if defined $example;
}
} else {
$parameters .= sprintf "=head2 %s\n\n",
_escape_pod($param->{gettext_id});
$parameters .= sprintf "%s\n\n",
join("\n\n", split "\n", _escape_pod($param->{gettext_comment}))
if exists $param->{gettext_comment};
}
}
printf do { local $RS; <DATA> }, Sympa::Constants::CONFIG(), $parameters,
Sympa::Constants::CONFIG();
exit 0;
sub _get_overrides {
my $pname = shift;
my $pitem = shift;
my $pnames = shift;
return () if $pitem->{obsolete};
my %ov;
if (exists $pitem->{format} and ref $pitem->{format} eq 'HASH') {
%ov = map {
_get_overrides($_, $pitem->{format}->{$_}, [@$pnames, $_]);
} keys %{$pitem->{format}};
} elsif (exists $pitem->{default}
and ref $pitem->{default} eq 'HASH'
and exists $pitem->{default}->{conf}) {
%ov = ($pitem->{default}->{conf} => join('.', @$pnames));
} else {
%ov = ();
}
return %ov;
}
sub _escape_pod {
my $string = shift;
$string =~ s/([&<>])/
'E<' . {'&' => 'amp', '<' => 'lt', '>' => 'gt'}->{$1} . '>'
/eg;
return $string;
}
__END__
=encoding utf-8
=head1 NAME
sympa.conf, robot.conf - Configuration file for default site and robot
=head1 DESCRIPTION
F<%s> is main configuration file of Sympa.
Several parameters defined in this file may be overridden by F<robot.conf>
configuration file for each virtual domain, or by F<config> configuration file
for each mailing list.
Format of F<sympa.conf> and F<robot.conf> is as following:
=over
=item *
Lines beginning with C<#> and containing only spaces are ignored.
=item *
Each line has the form "I<parameter> I<value>".
I<value> may contain spaces but may not contain newlines.
=back
=head1 PARAMETERS
Below is entire list of configuration parameters.
"Default" is built-in default value if any.
"Overrides" lists contexts (with parameter name) which can override
settings in site-wide context (F<sympa.conf>): Virtual domain (F<robot.conf>)
and/or List (F<config>).
%s
=head1 FILES
=over
=item F<%s>
Sympa main configuration file.
=item F<$SYSCONFDIR/E<lt>robot nameE<gt>/robot.conf>
Configuration specific to each virtual domain.
=item F<$EXPLDIR/E<lt>list nameE<gt>/config>
or F<$EXPLDIR/E<lt>robot nameE<gt>/E<lt>list nameE<gt>/config>
Configuration specific to each list.
=back
=head1 SEE ALSO
I<Sympa Administration Manual>.
L<https://sympa-community.github.io/manual/>.
=cut
# $Id$
# -*- indent-tabs-mode: nil; -*-
# vim:ft=perl:et:sw=4
use strict;
use warnings;
......@@ -7,51 +8,69 @@ use English qw(-no_match_vars);
use Getopt::Long;
use Sympa::ConfDef;
use Sympa::ListDef;
use Sympa::Config::Schema;
use Sympa::Constants;
use Sympa::ListOpt;
my $top_srcdir;
GetOptions('top_srcdir=s' => \$top_srcdir);
$top_srcdir ||= '..';
my @groups = (
[description => 'List definition'],
[sending => 'Sending/receiving setup'],
[command => 'Privileges'],
[archives => 'Archives'],
[bounces => 'Bounces'],
[data_source => 'Data sources setup'],
[dkim => 'DKIM'],
[other => 'Miscellaneous'],
);
my %overrides;
foreach my $pitem (@Sympa::ConfDef::params) {
next unless $pitem and exists $pitem->{name};
$overrides{$pitem->{name}} = $pitem->{vhost};
}
my $parameters = '';
foreach my $g (@groups) {
my ($group, $gdesc) = @$g;
$parameters .= sprintf "=head2 %s\n\n", $gdesc;
my $group;
my $pinfo = {%Sympa::Config::Schema::pinfo};
foreach my $key (_keys($pinfo)) {
next if $pinfo->{$key}->{obsolete};
#next unless $pinfo->{$key}->{group};
unless (defined $group and $group eq $pinfo->{$key}->{group}) {
$group = $pinfo->{$key}->{group};
my $ginfo = $Sympa::Config::Schema::pgroup{$group} // {};
$parameters .= sprintf "=head2 %s\n\n",
($ginfo->{gettext_id} // $group);
$parameters .= sprintf "%s\n\n", join "\n\n", split "\n",
$ginfo->{gettext_comment}
if $ginfo->{gettext_comment};
}
my $pinfo = {%Sympa::ListDef::pinfo};
foreach my $key (_keys($pinfo)) {
next
unless $pinfo->{$key}->{group}
and $pinfo->{$key}->{group} eq $group;
my $pii = $pinfo->{$key};
my $ppi = [$key];
if ($key eq 'color_0') {
$parameters .= "=head3 C<color_0>, ..., C<color_15>\n\n";
} elsif ($key =~ /\Acolor_/) {
next;
} elsif ($key eq 'dark_color') {
$parameters .=
"=head3 C<dark_color>, C<light_color>, C<text_color>, C<bg_color>, C<error_color>, C<selected_color>, C<shaded_color>\n\n";
} elsif ($key =~ /_color\z/) {
next;
} elsif ($key eq 'main_menu_custom_button_1_title') {
$parameters .=
"=head3 C<main_menu_custom_button_1_title>, ... C<main_menu_custom_button_3_title>, C<main_menu_custom_button_1_url>, ... C<main_menu_custom_button_3_url>, C<main_menu_custom_button_1_target>, ... C<main_menu_custom_button_3_target>\n\n";
} elsif ($key =~ /\Amain_menu_custom_button_/) {
next;
} else {
$parameters .= sprintf "=head3 C<B<%s>>\n\n", _escape_pod($key);
}
_render($pii, $ppi);
}
my $pii = $pinfo->{$key};
my $ppi = [$key];
$parameters .= "=head2 Obsoleted F<sympa.conf> parameters\n\n";
$parameters .= "These parameters were used in F<sympa.conf> or F<robot.conf>";
$parameters .= " on Sympa 6.2.56 or earlier and are no longer recommended.\n\n";
foreach my $okey (sort keys %Sympa::Config::Schema::obsolete_robot_params) {
my $nkey = $Sympa::Config::Schema::obsolete_robot_params{$okey};
$parameters .= sprintf "=head3 C<%s>\n\n", _escape_pod($key);
_render($pii, $ppi);
}
$parameters .= sprintf "=head3 C<%s>\n\n", _escape_pod($okey);
$parameters .= sprintf "See L<C<%s>|/%s>.\n\n", _escape_pod($nkey),
_escape_pod($nkey);
}
printf do { local $RS; <DATA> }, $parameters;
printf do { local $RS; <DATA> }, Sympa::Constants::CONFIG(), $parameters,
Sympa::Constants::CONFIG();
exit 0;
......@@ -80,6 +99,7 @@ sub _render_paragraph {
my $pinfo = shift;
my $pnames = shift;
$parameters .= "(Paragraph)\n";
$parameters .= sprintf "%s\n\n", _escape_pod($pinfo->{gettext_id});
$parameters .= "=over\n\n";
......@@ -130,13 +150,15 @@ sub _render_set {
$parameters .= "=over\n\n";
_format($pinfo);
_default($pinfo);
_default($pinfo, $pnames);
_context($pinfo);
$parameters .= "=back\n\n";
$parameters .= sprintf "%s\n\n", join "\n\n", split /\n/,
_escape_pod($pinfo->{gettext_comment})
if exists $pinfo->{gettext_comment};
_sample($pinfo, $pnames);
}
sub _render_scalar {
......@@ -149,13 +171,16 @@ sub _render_scalar {
$parameters .= "=over\n\n";
_format($pinfo);
_default($pinfo);
_default($pinfo, $pnames);
_context($pinfo);
$parameters .= "=back\n\n";
$parameters .= sprintf "%s\n\n", join "\n\n", split /\n/,
_escape_pod($pinfo->{gettext_comment})
if exists $pinfo->{gettext_comment};
_sample($pinfo, $pnames);
}
sub _format {
......@@ -183,7 +208,7 @@ sub _format {
listtopic => 'List topic.',
unixtime => 'The time in second from Unix epoch.',
visibility => 'Visibility mode of list memeber.',
}->{$pinfo->{field_type}}
}->{$pinfo->{field_type}}
|| $pinfo->{field_type};
$parameters .= sprintf "%s\n\n", $desc;
} elsif (exists $pinfo->{scenario}) {
......@@ -239,24 +264,23 @@ sub _format {
}
sub _default {
my $pinfo = shift;
my $pinfo = shift;
my $pnames = shift;
my $fullname = join '.', @$pnames;
$parameters .= "=item Default:\n\n";
if (exists $pinfo->{default}) {
if ($fullname =~ /\Acolor_/ or $fullname =~ /_color\z/) {
$parameters .= "See description on web interface.\n\n";
} elsif (exists $pinfo->{default}) {
if (ref $pinfo->{default} eq 'ARRAY') {
$parameters .= sprintf "%s\n\n", join ', ',
map { sprintf "C<%s>", $_ } @{$pinfo->{default}};
} elsif (ref $pinfo->{default} eq 'HASH'
and $pinfo->{default}->{conf}) {
$parameters .=
sprintf
"Value of L<C<%s>|sympa.conf(5)/%s> parameter in F<sympa.conf>%s.\n\n",
$pinfo->{default}->{conf}, $pinfo->{default}->{conf},
(
$overrides{$pinfo->{default}->{conf}}
? ' or F<robot.conf>'
: ''
);
} elsif (ref $pinfo->{default}) {
die sprintf '%s->{default}: %s', $fullname, ref $pinfo->{default};
} elsif (exists $pinfo->{gettext_unit}) {
$parameters .= sprintf "C<%s> (%s)\n\n",
_escape_pod($pinfo->{default}), $pinfo->{gettext_unit};
} else {
$parameters .= sprintf "C<%s>\n\n", $pinfo->{default};
}
......@@ -267,6 +291,43 @@ sub _default {
}
}
sub _context {
my $pinfo = shift;
$parameters .= "=item Context:\n\n";
if (@{$pinfo->{context} || []}) {
$parameters .= join(
', ',
map {
{ list => 'list (F<config>)',
domain => 'domain (F<robot.conf>)',
site => 'site (F<sympa.conf>)',
}->{$_} // $_
} @{$pinfo->{context}}
) . "\n\n";
} else {
$parameters .= "Unknown.\n\n";
}
}
sub _sample {
my $pinfo = shift;
my $pnames = shift;
my $fullname = join '.', @$pnames;
if ($fullname eq 'main_menu_custom_button_1_title') {
$parameters .= "Example:\n\n";
$parameters .= " main_menu_custom_button_1_title FAQ\n";
$parameters .=
" main_menu_custom_button_1_url http://www.renater.fr/faq/universalistes/index\n";
$parameters .= " main_menu_custom_button_1_target Help\n\n";
} elsif (exists $pinfo->{sample}) {
$parameters .= "Example:\n\n";
$parameters .= sprintf " %s %s\n\n", $fullname, $pinfo->{sample};
}
}
sub _keys {
my $hash = shift;
my $phash = shift || $hash;
......@@ -291,11 +352,57 @@ __END__
=head1 NAME
list_config - Configuration file for mailing list
sympa_config - Configuration files for Sympa mailing list manager
=head1 DESCRIPTION
F<config> is main configuration file of the mailing list.
There are three levels in Sympa's main configuration:
site global, mail domain and list.
=head2 F<sympa.conf>: Configuration file for global settings
F<%s> is main configuration file of Sympa.
Several parameters defined in this file may be overridden by F<robot.conf>
configuration file for each virtual domain, or by F<config> configuration file
for each mailing list.
Format of F<sympa.conf> and F<robot.conf> is as following:
=over
=item *
Lines beginning with C<#> and containing only spaces are ignored.
=item *
Each line has the form "I<parameter> I<value>".
I<value> may contain spaces but may not contain newlines.
There are simple parameters and compound parameters.
The name of compound parameter consist of a paragraph name and
a sub-parameter name separated by period (C<.>).
However some compound parameters have simple synonym names to keep
compatibility to earlier versions (See L</"Obsoleted sympa.conf parameters">).
Example:
process_archive on
archive.web_access open
archive.mail_access closed
=back
=head2 F<robot.conf>: Optional configuration file for the mail domain
F<robot.conf> is the optional configuration file for each mail domain.
Format of F<robot.conf> is the same as F<sympa.conf> above.
=head2 F<config>: Configuration file for the mailing list
F<config> is main configuration file of each mailing list.
Format of F<config> is as following:
......@@ -307,14 +414,14 @@ Lines beginning with C<#> and containing only spaces are ignored.
=item *
There are parameters with single line and multiple lines:
There are simple parameters and compound parameters:
=over
=item *
On single line parameters,
each line has the form "I<parameter> I<value>".
A cimple parameter is expressed by single line by each.
The line has the form "I<parameter> I<value>".
I<value> may contain spaces but may not contain newlines.
Several parameters may have multiple values.
......@@ -335,8 +442,9 @@ Example:
=item *
A multiple line parameter, so-called "paragraph", consists of
the first line specifying parameter name and subsequent one or more
A compound parameter is expressed by multiple lines, so-called "paragraph",
that consists of
the first line specifying paragraph name and subsequent one or more
sub-parameter lines. Paragraph must be separated by one or more empty lines
from the other parameters.
......@@ -349,14 +457,34 @@ Several multiple line parameters may occur multiple times.
=head1 PARAMETERS
Below is entire list of configuration parameters.
=over
=item *
Sub-parameters in paragraph are listed as I<paragraph>C<.>I<sub-parameter>
by each.
=item *
"Default" is built-in default value if any.
=back
%s
=head1 FILES
=over
=item F<%s>
Sympa main configuration file.
=item F<$SYSCONFDIR/E<lt>mail domain nameE<gt>/robot.conf>