Commit 3cfc57f3 authored by david.verdin's avatar david.verdin
Browse files

[svn] Retrieving latest modifications from 6.1 branch.


git-svn-id: https://subversion.renater.fr/sympa/branches/sympa-6.2-branch@7450 05aa8bb8-cd2b-0410-b1d7-8918dfa770ce
parent d0ac0dc0
......@@ -50,7 +50,18 @@ Subject: [% FILTER qencode %][%|loc(list.name)%]Unsubscribing from list %1[%END%
This query was issued from the IP number '%2'.
To confirm and get removed from the list, please click the link below: [%END%]
[% ELSE %]
[%|loc(list.name)%]You have requested to removed from list %1. To confirm and get removed from the list, please click the link below: [%END%]
[%|loc(list.name)%]You have requested to be removed from list %1. To confirm and get removed from the list, please click the link below: [%END%]
[% END %]
[% conf.wwsympa_url %]/ticket/[% one_time_ticket %]
[% ELSIF type == 'ticket_to_family_signoff' -%]
Subject: [% FILTER qencode %][%|loc(family)%]Unsubscribing from family %1[%END%][%END%]
[% IF context == 'family_signoff'%]
[%|loc(family,ip)%]Somebody (probably you) requested to unsubscribe you from family %1.
This query was issued from the IP number '%2'.
To confirm and get removed from all the lists of this family, please click the link below: [%END%]
[% ELSE %]
[%|loc(family)%]You have requested to be removed from family %1. To confirm and get removed from all the lists of this family, please click the link below: [%END%]
[% END %]
[% conf.wwsympa_url %]/ticket/[% one_time_ticket %]
......
......@@ -72,6 +72,7 @@ nobase_default_DATA = list_task_models/expire.yearly.task \
scenari/add.owner_notify \
scenari/automatic_list_creation.listmaster \
scenari/automatic_list_creation.public \
scenari/automatic_list_creation.family_owner \
scenari/create_list.intranet \
scenari/create_list.listmaster \
scenari/create_list.public_listmaster \
......
title.gettext Restricted to people subscribed to the list of family owners.
is_listmaster([sender]) smtp,dkim,md5,smime -> do_it
is_subscriber([family->family_owners_list],[sender]) smtp,dkim,md5,smime -> do_it
true() smtp,dkim,md5,smime -> reject,quiet
......@@ -997,6 +997,78 @@ sub load_sql_filter {
return (&load_generic_conf_file($file,\%sql_named_filter_params, 'abort'));
}
## load automatic_list_description.conf configuration file
sub load_automatic_lists_description {
my $robot = shift;
my $family = shift;
&Log::do_log('debug2','Starting: robot %s family %s',$robot,$family);
my %automatic_lists_params = (
'class' => {
'occurrence' => '1-n',
'format' => {
'name' => {'format' => '.*', 'occurrence' => '1', },
'stamp' => {'format' => '.*', 'occurrence' => '1', },
'description' => {'format' => '.*', 'occurrence' => '1', },
'order' => {'format' => '\d+', 'occurrence' => '1', },
'instances' => {'occurrence' => '1','format' => '.*',},
#'format' => {
#'instance' => {
#'occurrence' => '1-n',
#'format' => {
#'value' => {'format' => '.*', 'occurrence' => '1', },
#'tag' => {'format' => '.*', 'occurrence' => '1', },
#'order' => {'format' => '\d+', 'occurrence' => '1', },
#},
#},
#},
},
},
);
# find appropriate automatic_lists_description.tt2 file
my $config ;
if (defined $robot) {
$config = $Conf{'etc'}.'/'.$robot.'/families/'.$family.'/automatic_lists_description.conf';
}else{
$config = $Conf{'etc'}.'/families/'.$family.'/automatic_lists_description.conf';
}
return undef unless (-r $config);
my $description = &load_generic_conf_file($config,\%automatic_lists_params);
## Now doing some structuration work because Conf::load_automatic_lists_description() can't handle
## data structured beyond one level of hash. This needs to be changed.
my @structured_data;
foreach my $class (@{$description->{'class'}}){
my @structured_instances;
my @instances = split '%%%',$class->{'instances'};
my $default_found = 0;
foreach my $instance (@instances) {
my $structured_instance;
my @instance_params = split '---',$instance;
foreach my $instance_param (@instance_params) {
$instance_param =~ /^\s*(\S+)\s+(.*)\s*$/;
my $key = $1;
my $value = $2;
$key =~ s/^\s*//;
$key =~ s/\s*$//;
$value =~ s/^\s*//;
$value =~ s/\s*$//;
$structured_instance->{$key} = $value;
}
$structured_instances[$structured_instance->{'order'}] = $structured_instance;
if (defined $structured_instance->{'default'}) {
$default_found = 1;
}
}
unless($default_found) {$structured_instances[0]->{'default'} = 1;}
$class->{'instances'} = \@structured_instances;
$structured_data[$class->{'order'}] = $class;
}
$description->{'class'} = \@structured_data;
return $description;
}
## load trusted_application.conf configuration file
sub load_trusted_application {
my $robot = shift;
......@@ -1453,6 +1525,26 @@ sub _infer_robot_parameter_values {
$param->{'config_hash'}{'static_content_url'} ||= $Conf{'static_content_url'};
$param->{'config_hash'}{'static_content_path'} ||= $Conf{'static_content_path'};
# Hack because multi valued parameters are not available for Sympa 6.1.
if (defined $param->{'config_hash'}{'automatic_list_families'}) {
my @families = split ';',$param->{'config_hash'}{'automatic_list_families'};
my %families_description;
foreach my $family_description (@families) {
my %family;
my @family_parameters = split ':',$family_description;
foreach my $family_parameter (@family_parameters) {
my @parameter = split '=', $family_parameter;
$family{$parameter[0]} = $parameter[1];
}
$family{'escaped_prefix_separator'} = $family{'prefix_separator'};
$family{'escaped_prefix_separator'} =~ s/([+*?.])/\\$1/g;
$family{'escaped_classes_separator'} = $family{'classes_separator'};
$family{'escaped_classes_separator'} =~ s/([+*?.])/\\$1/g;
$families_description{$family{'name'}} = \%family;
$families_description{$family{'name'}}{'description'} = &load_automatic_lists_description(undef,$family{'name'});
}
$param->{'config_hash'}{'automatic_list_families'} = \%families_description;
}
## CSS
my $final_separator = '';
$final_separator = '/' if ($param->{'config_hash'}{'robot_name'});
......
......@@ -229,6 +229,13 @@ sub new {
$self->{'robot'} = $robot;
## Adding configuration related to automatic lists.
my $all_families_config = &Conf::get_robot_conf($robot,'automatic_list_families');
my $family_config = $all_families_config->{$name};
foreach my $key (keys %{$family_config}) {
$self->{$key} = $family_config->{$key};
}
## family directory
$self->{'dir'} = $self->_get_directory();
unless (defined $self->{'dir'}) {
......@@ -2807,8 +2814,69 @@ sub _load_param_constraint_conf {
return $constraint;
}
sub create_automatic_list {
my $self = shift;
my %param = @_;
my $auth_level = $param{'auth_level'};
my $sender = $param{'sender'};
my $message = $param{'message'};
my $listname = $param{'listname'};
unless ($self->is_allowed_to_create_automatic_lists(%param)){
&Log::do_log('err', 'Unconsistent scenario evaluation result for automatic list creation of list %s@%s by user %s.', $listname,$self->{'robot'},$sender);
return undef;
}
my $result = $self->add_list({listname=>$listname}, 1);
unless (defined $result->{'ok'}) {
my $details = $result->{'string_error'} || $result->{'string_info'} || [];
&Log::do_log('err', "Failed to add a dynamic list to the family %s : %s", $self->{'name'}, join(';', @{$details}));
return undef;
}
my $list = new List ($listname, $self->{'robot'});
unless (defined $list) {
&Log::do_log('err', 'sympa::DoFile() : dynamic list %s could not be created',$listname);
return undef;
}
return $list;
}
# Returns 1 if the user is allowed to create lists based on the family.
sub is_allowed_to_create_automatic_lists {
my $self = shift;
my %param = @_;
my $auth_level = $param{'auth_level'};
my $sender = $param{'sender'};
my $message = $param{'message'};
my $listname = $param{'listname'};
# check authorization
my $result = &Scenario::request_action('automatic_list_creation',$auth_level,$self->{'robot'},
{'sender' => $sender,
'message' => $message,
'family'=>$self,
'automatic_listname'=>$listname });
my $r_action;
unless (defined $result) {
&Log::do_log('err', 'Unable to evaluate scenario "automatic_list_creation" for family %s', $self->{'name'});
return undef;
}
if (ref($result) eq 'HASH') {
$r_action = $result->{'action'};
}else {
&Log::do_log('err', 'Unconsistent scenario evaluation result for automatic list creation in family %s', $self->{'name'});
return undef;
}
unless ($r_action =~ /do_it/) {
&Log::do_log('debug2', 'Automatic list creation refused to user %s for family %s', $sender, $self->{'name'});
return undef;
}
return 1;
}
=pod
=head1 AUTHORS
......
......@@ -5751,7 +5751,8 @@ sub insert_delete_exclusion {
my $list = shift;
my $robot = shift;
my $action = shift;
&Log::do_log('info', 'List::insert_delete_exclusion("%s", "%s", "%s", "%s")', $email, $list, $robot, $action);
my $family = shift;
&Log::do_log('info', 'List::insert_delete_exclusion("%s", "%s", "%s", "%s", "%s")', $email, $list, $robot, $action, $family);
my $r = 1;
......@@ -5765,9 +5766,9 @@ sub insert_delete_exclusion {
my $user = &get_list_member_no_object($options);
my $date = time;
if ($user->{'included'} eq '1') {
if ($user->{'included'} eq '1' or defined $family) {
## Insert : list, user and date
unless (&SDM::do_query("INSERT INTO exclusion_table (list_exclusion, robot_exclusion, user_exclusion, date_exclusion) VALUES (%s, %s, %s, %s)", &SDM::quote($list), &SDM::quote($robot), &SDM::quote($email), &SDM::quote($date))) {
unless (&SDM::do_query("INSERT INTO exclusion_table (list_exclusion, family_exclusion, robot_exclusion, user_exclusion, date_exclusion) VALUES (%s, %s, %s, %s)", &SDM::quote($list), &SDM::quote($family), &SDM::quote($robot), &SDM::quote($email), &SDM::quote($date))) {
&Log::do_log('err','Unable to exclude user %s from liste %s@%s', $email, $list, $robot);
return undef;
}
......@@ -5789,9 +5790,15 @@ sub insert_delete_exclusion {
foreach my $users (@users_excluded) {
if($email eq $users){
## Delete : list, user and date
unless ($sth = &SDM::do_query("DELETE FROM exclusion_table WHERE (list_exclusion = %s AND robot_exclusion = %s AND user_exclusion = %s)", &SDM::quote($list), &SDM::quote($robot), &SDM::quote($email))) {
&Log::do_log('err','Unable to remove entry %s for liste %s@%s for table exclusion_table', $email, $list, $robot);
return undef;
if (defined $family) {
unless ($sth = &SDM::do_query("DELETE FROM exclusion_table WHERE (family_exclusion = %s AND robot_exclusion = %s AND user_exclusion = %s)", &SDM::quote($family), &SDM::quote($robot), &SDM::quote($email))) {
&Log::do_log('err','Unable to remove entry %s for family %s (robot %s) from table exclusion_table', $email, $family, $robot);
}
}else{
unless ($sth = &SDM::do_query("DELETE FROM exclusion_table WHERE (list_exclusion = %s AND robot_exclusion = %s AND user_exclusion = %s)", &SDM::quote($list), &SDM::quote($robot), &SDM::quote($email))) {
&Log::do_log('err','Unable to remove entry %s for list %s@%s from table exclusion_table', $email, $family, $robot);
}
}
$r = $sth->rows;
}
......@@ -5819,14 +5826,29 @@ sub get_exclusion {
my $robot= shift;
&Log::do_log('debug2', 'List::get_exclusion(%s@%s)', $name,$robot);
push @sth_stack, $sth;
unless ($sth = &SDM::do_query("SELECT user_exclusion AS email, date_exclusion AS date FROM exclusion_table WHERE list_exclusion = %s AND robot_exclusion=%s",
&SDM::quote($name), &SDM::quote($robot))) {
&Log::do_log('err','Unable to retrieve excluded users for list %s@%s',$name, $robot);
my $list = new List($name, $robot);
unless (defined $list) {
&Log::do_log('err','List %s@%s does not exist', $name,$robot);
return undef;
}
if (defined $list->{'admin'}{'family_name'} && $list->{'admin'}{'family_name'} ne '') {
unless ($sth = &SDM::do_query("SELECT user_exclusion AS email, date_exclusion AS date FROM exclusion_table WHERE (list_exclusion = %s OR family_exclusion = %s) AND robot_exclusion=%s",
&SDM::quote($name),&SDM::quote($list->{'admin'}{'family_name'}), &SDM::quote($robot))) {
&Log::do_log('err','Unable to retrieve excluded users for list %s@%s',$name, $robot);
return undef;
}
}else{
unless ($sth = &SDM::do_query("SELECT user_exclusion AS email, date_exclusion AS date FROM exclusion_table WHERE list_exclusion = %s AND robot_exclusion=%s",
&SDM::quote($name), &SDM::quote($robot))) {
&Log::do_log('err','Unable to retrieve excluded users for list %s@%s',$name, $robot);
return undef;
}
}
push @sth_stack, $sth;
my @users;
my @date;
my $data;
......@@ -9612,6 +9634,17 @@ sub sync_include {
my @add_tab;
$users_added = 0;
foreach my $email (keys %{$new_subscribers}) {
my $compare = 0;
foreach my $sub_exclu (@subscriber_exclusion){
if ($email eq $sub_exclu){
$compare = 1;
last;
}
}
if($compare == 1){
delete $new_subscribers->{$email};
next;
}
if (defined($old_subscribers{$email}) ) {
if ($old_subscribers{$email}{'included'}) {
## If one user attribute has changed, then we should update the user entry
......
......@@ -589,6 +589,11 @@ sub verify {
$value =~ s/\[custom_vars\-\>([\w\-]+)\]/$context->{'custom_vars'}{$1}/;
}
## Family vars
if ($value =~ /\[family\-\>([\w\-]+)\]/i) {
$value =~ s/\[family\-\>([\w\-]+)\]/$context->{'family'}{$1}/;
}
## Config param
elsif ($value =~ /\[conf\-\>([\w\-]+)\]/i) {
if (my $conf_value = &Conf::get_robot_conf($robot, $1)) {
......
......@@ -42,6 +42,7 @@ use Log;
use tools;
use Sympa::Constants;
use File::Copy;
use Data::Dumper;
=pod
......@@ -442,6 +443,8 @@ sub create_list{
return undef;
}
my $family_config = &Conf::get_robot_conf($robot,'automatic_list_families');
$param->{'family_config'} = $family_config->{$family->{'name'}};
my $conf;
my $tt_result = &tt2::parse_tt2($param, 'config.tt2', \$conf, [$family->{'dir'}]);
unless (defined $tt_result || !$abort_on_error) {
......@@ -527,6 +530,24 @@ sub create_list{
}
}
## Create associated files if a template was given.
for my $file ('message.footer','message.header','message.footer.mime','message.header.mime','info') {
my $template_file = &tools::get_filename('etc',{},$file.".tt2", $robot,$family);
if (defined $template_file) {
my $file_content;
my $tt_result = &tt2::parse_tt2($param, $file.".tt2", \$file_content, [$family->{'dir'}]);
unless (defined $tt_result) {
&do_log('err', 'admin::create_list : tt2 error. List %s from family %s@%s, file %s',
$param->{'listname'}, $family->{'name'},$robot,$file);
}
unless (open FILE, '>:utf8', "$list_dir/$file") {
&do_log('err','Impossible to create %s/%s : %s',$list_dir,$file,$!);
}
print FILE $file_content;
close FILE;
}
}
## Create list object
my $list;
unless ($list = new List ($param->{'listname'}, $robot)) {
......
......@@ -364,21 +364,6 @@ our @params = (
'edit' => '1',
'advice' => gettext('This parameter is a scenario, check sympa documentation about scenarios if you want to define one'),
},
{
'name' => 'automatic_list_feature',
'default' => 'off',
'vhost' => '1',
},
{
'name' => 'automatic_list_creation',
'default' => 'public',
'vhost' => '1',
},
{
'name' => 'automatic_list_removal',
'optional' => '1', ## Can be 'if_empty',
'vhost' => '1',
},
{
'name' => 'global_remind',
'default' => 'listmaster',
......@@ -469,12 +454,43 @@ our @params = (
'file' => 'sympa.conf',
'advice' => gettext('Proposed value is quite low, you can rise it up to 100, 200 or even 300 with powerfull systems.'),
},
{
name => 'automatic_list_removal',
default => '', ## Can be 'if_empty'
vhost => '1',
},
{
name => 'automatic_list_feature',
default => 'off',
vhost => '1',
},
{
name => 'automatic_list_creation',
default => 'public',
vhost => '1',
},
{
name => 'automatic_list_families',
query => 'Defines the name of the family the automatic lists are based on.',
file => 'sympa.conf',
optional => '1',
},
{
name => 'automatic_list_prefix',
query => 'Defines the prefix allowing to recognize that a list is an automatic list.',
file => 'sympa.conf',
optional => '1',
},
{
'name' => 'log_smtp',
'default' => 'off',
'vhost' => '1',
'file' => 'sympa.conf',
},
{
name => 'global_remind',
default => 'listmaster',
},
{
'name' => 'use_blacklist',
'query' => gettext('comma separated list of operations for which blacklist filter is applied'),
......
......@@ -1400,54 +1400,21 @@ sub DoFile {
return undef;
}
# check authorization
my $auth_level = 'smtp';
$auth_level = 'dkim' if $message->{'dkim_pass'};
$auth_level = 'md5' if $message->{'md5_check'};
$auth_level = 'smime' if $message->{'smime_signed'};
my $result = &Scenario::request_action('automatic_list_creation',$auth_level,$robot,
{'sender' => $sender,
'message' => $message,
'family'=>$dyn_list_family,
'automatic_listname'=>$listname });
my $r_action;
unless (defined $result) {
&Log::do_log('err', 'sympa::DoFile(): message (%s) ignored because unable to evaluate scenario "automatic_list_creation" for list %s', $msg_id, $listname);
&report::reject_report_msg('intern','Message ignored because scenario "automatic_list_creation" cannot be evaluated',$sender,
{'msg_id' => $msg_id, 'message' => $message}, $robot,$message->{'msg_as_string'});
&List::send_notify_to_listmaster('automatic_list_creation_failed',$robot,["Failed to process $file"]);
&Log::db_log({'robot' => $robot,'list' => $listname,'action' => 'DoFile',
'parameters' => "$msg_id,$robot",'target_email' => '','msg_id' => $msg_id, 'status' => 'error','error_type' => 'internal','user_email' => $sender,'client' => $ip,'daemon' => $daemon_name});
if ($list = $dyn_family->create_automatic_list(('listname' => $listname,'auth_level' => $auth_level,'sender'=>$sender,'message'=>$message))) {
$dyn_just_created = 1;
}else {
&Log::do_log('err', 'Unable to create list %s. Message %s ignored.', $listname,'msg_id' => $hdr->get('Message-Id'));
&report::reject_report_msg('intern',"Message ignored because automatic list '$listname' creation could not be performed.",$sender,
{'msg_id' => $hdr->get('Message-Id'),'message' => $message}, $dyn_family->{'robot'},$message->{'msg_as_string'});
&List::send_notify_to_listmaster('automatic_list_creation_failed',$dyn_family->{'robot'},["Failed to process $file"]);
&Log::db_log({'robot' => $dyn_family->{'robot'},'list' => $listname,'action' => 'DoFile',
'parameters' => $hdr->get('Message-Id').",$dyn_family->{'robot'}",'target_email' => '','msg_id' => hdr->get('Message-Id'),'status' => 'error','error_type' => 'internal','user_email' => $sender,'client' => $ip,'daemon' => $daemon_name});
return undef ;
}
if (ref($result) eq 'HASH') {
$r_action = $result->{'action'};
}
unless ($r_action =~ /do_it/) {
&Log::do_log('info', 'automatic_list_creation %s@%s from %s refused', $listname,$robot,$sender);
&report::reject_report_msg('auth',$result->{'reason'},$sender,{'listname' => $listname,
'list'=>{'name'=>$listname, 'host'=>$robot},'message' => $message},$robot,$message->{'msg'}->as_string,'');
&List::send_notify_to_listmaster('automatic_list_creation_failed',$robot,["Failed to process $file"]);
return undef;
}
$result = $dyn_family->add_list({listname=>$listname}, 1);
unless (defined $result->{'ok'}) {
my $details = $result->{'string_error'} || $result->{'string_info'} || [];
&Log::do_log('err', "Failed to add a dynamic list to the family %s : ", $dyn_list_family, join(';', @{$details}));
&report::reject_report_msg('user','list_unknown',$sender,{'listname' => $listname, 'list'=>{'name'=>$listname},'message' => $message},$robot,$message->{'msg'}->as_string,'');
&List::send_notify_to_listmaster('automatic_list_creation_failed',$robot,["Failed to process $file."]);
return undef;
}
$list = new List ($listname, $robot);
unless (defined $list) {
&Log::do_log('err', 'sympa::DoFile() : dynamic list %s could not be created',$listname);
&report::reject_report_msg('user','list_unknown',$sender,{'listname' => $listname, 'list'=>{'name'=>$listname},'message' => $message},$robot,$message->{'msg'}->as_string,'');
&List::send_notify_to_listmaster('automatic_list_creation_failed',$robot,["Failed to process $file."]);
return undef;
}
$dyn_just_created = 1;
}
$host = $list->{'admin'}{'host'};
$name = $list->{'name'};
......
......@@ -30,6 +30,9 @@ webtemplate_DATA = active_lists.tt2 \
arcsearch.tt2 \
arc.tt2 \
auto_signoff.tt2 \
automatic_lists_management_request.tt2 \
automatic_lists_request.tt2 \
automatic_lists.tt2 \
blacklist.tt2 \
button_footer.tt2 \
button_header.tt2 \
......@@ -63,6 +66,8 @@ webtemplate_DATA = active_lists.tt2 \
editsubscriber.tt2 \
edit_template.tt2 \
error.tt2 \
family_signoff.tt2 \
family_signoff_request.tt2 \
footer.tt2 \
get_closed_lists.tt2 \
get_inactive_lists.tt2 \
......
<!-- Begin automatic_lists.tt2 -->
<div>
<h1>[%|loc%]Automatic lists result[% END %]</h1>
<p>The list created would be [% list_name %]</p>
</div>
<!-- End automatic_lists.tt2 -->
<!-- Begin automatic_list_management_request.tt2 -->
<div>
<h1>[%|loc%]Automatic lists management[% END %]</h1>
<p>[%|loc(automatic_lists_description.family_name)%]The automatic lists are based on the $1 family[% END %]</p>
[% FOREACH p = automatic_lists_description.class %]
<p>Found class [% p.name %]</p>
[%END%]
</div>
<!-- End automatic_list_management_request.tt2 -->
<!-- Begin automatic_lists_request.tt2 -->
<div>
<h1>[% family.display %]</h1>
<p>[%|loc%]In this form, you will be able to create and / or access lists created on the basis of parameters you will defined.[% END %]</p>
<form action="[% path_cgi %]" method="post" class="add-request" name="automatic_lists">
[% FOREACH p = family.description.class %]
<h2>[% p.stamp %]</h2>
<p> [% p.description %]</p>
[% FOREACH i = p.instances %]
<input type="radio" name="automatic_list_part_[% p.order %]" value="[% i.value %]"[% IF i.default %] checked="checked"[% END %]> [% i.tag %]<br>
[%END%]
[%END%]
<input class="MainMenuLinks" type="submit" name="action_automatic_lists" value="[%|loc%]Go to list[%END%]" />
<input type="hidden" name="family" value="[% family.name %]" />
</form>
</div>
<!-- End automatic_lists_request.tt2 -->
<h3>[%|loc%]Global unsubscription[% END %]</h3>
<p>[%|loc(signing_off_email,family)%]You successfully unsubscribed the address %1 from family %2.[% END %]</p>
<h3>[%|loc%]Global unsubscription request[% END %]</h3>
<p>[%|loc(signing_off_email,family)%]You clicked a link to unsubscribe the address %1 from family %2.[% END %]</p>
<p>[%|loc(family)%]A confirmation was just sent to this address. By clicking the link it contains, you will be definitively unsubscribed from all the lists from family %1[% END %]</p>
<h3>[%|loc%]Global unsubscription[% END %]</h3>
<p>[%|loc(signing_off_email,family)%]You successfully unsubscribed the address %1 from family %2.[% END %]</p>
......@@ -31,6 +31,12 @@
<li> <a class="MainMenuLinks" [% IF conf.main_menu_custom_button_3_target %] target ="[% conf.main_menu_custom_button_3_target %]"[% END %] href="[% conf.main_menu_custom_button_3_url %]">[% conf.main_menu_custom_button_3_title %]</a></li>
[%END%]
[% FOREACH alf IN conf.automatic_list_families.keys %]
[% IF session.is_family_owner.$alf %]
[% IF action == 'automatic_lists_request' && family.name == conf.automatic_list_families.$alf.name %][% SET class = 'MainMenuLinksCurrentPage' %][% ELSE %][% SET class = 'MainMenuLinks' %][% END %] <li><a class="[% class %]" href="[% path_cgi %]/automatic_lists_request/[% conf.automatic_list_families.$alf.name %]" >[% conf.automatic_list_families.$alf.display %]</a></li>
[% END %]
[% END %]
</ul>
......
......@@ -41,6 +41,7 @@ use lib '--modulesdir--';
 
use Getopt::Long;
use Archive::Zip;
use Data::Dumper;
use strict 'vars';
use Time::Local;
......@@ -206,6 +207,8 @@ my %comm = ('home' => 'do_home',
'suboptions' => 'do_suboptions',
'signoff' => 'do_signoff',
'auto_signoff' => 'do_auto_signoff',
'family_signoff' => 'do_family_signoff',
'family_signoff_request' => 'do_family_signoff_request',
'multiple_signoff' => 'do_multiple_sigoff',
'sigrequest' => 'do_sigrequest',
'ignoresub' => 'do_ignoresub',
......@@ -361,6 +364,10 @@ my %comm = ('home' => 'do_home',
'show_exclude' => 'do_show_exclude',
'ca' => 'do_ca', # 'ca' stands for 'custom_action'. I used a short name to make it discrete in a URL.
'lca' => 'do_lca', # 'lca' stands for 'list_custom_action'. I used a short name to make it discrete in a URL.
'automatic_lists_management_request' => 'do_automatic_lists_management_request',
'automatic_lists_management' => 'do_automatic_lists_management',
'automatic_lists_request' => 'do_automatic_lists_request',
'automatic_lists' => 'do_automatic_lists',
);
 
my %auth_action = ('logout' => 1,
......@@ -429,6 +436,8 @@ my %action_args = ('default' => ['list'],
'ignoresub' => ['list','@email','@gecos'],
'signoff' => ['list','email','passwd'],
'auto_signoff' => ['list','email'],
'family_signoff' => ['family','email'],
'family_signoff_request' => ['family','email'],
'sigrequest' => ['list','email'],