diff options
-rw-r--r-- | TODO.org | 34 | ||||
-rw-r--r-- | css/style.css | 3 | ||||
-rw-r--r-- | lib/Fripost/Panel/Interface.pm | 142 | ||||
-rw-r--r-- | lib/Fripost/Panel/Login.pm | 30 | ||||
-rw-r--r-- | lib/Fripost/Schema/Alias.pm | 2 | ||||
-rw-r--r-- | lib/Fripost/Schema/List.pm | 4 | ||||
-rw-r--r-- | lib/Fripost/Schema/Local.pm | 2 | ||||
-rw-r--r-- | lib/Fripost/Schema/Mailbox.pm | 2 | ||||
-rw-r--r-- | misc/mklist/INSTALL | 4 | ||||
-rwxr-xr-x | misc/mklist/mklist.pl | 4 | ||||
-rw-r--r-- | template/add-alias.html | 8 | ||||
-rw-r--r-- | template/add-list.html | 10 | ||||
-rw-r--r-- | template/add-mailbox.html | 8 | ||||
-rw-r--r-- | template/edit-alias.html | 10 | ||||
-rw-r--r-- | template/edit-domain.html | 8 | ||||
-rw-r--r-- | template/edit-list.html | 10 | ||||
-rw-r--r-- | template/edit-mailbox.html | 14 | ||||
-rw-r--r-- | template/list-domains.html | 8 | ||||
-rw-r--r-- | template/list-locals.html | 29 |
19 files changed, 191 insertions, 141 deletions
@@ -1,4 +1,4 @@ -* DONE Email::Valid does not accept UTF-8 emails adresses (e.g., test@ƛ.net). +* DONE Email::Valid does not accept UTF-8 emails adresses (e.g., peace@☮.net). LDAP doesn't allow UTF-8 in the DNs anyway, so maybe convert the domains/emails to Punycode internally? @@ -17,6 +17,7 @@ Actually Postfix checks it and warns the administrator with a in the logs. So it's fine to do a partial check here. * TODO Write a script to check every runmode against the W3 validator. +(Cf. cgiapp_postrun); * DONE Use FastCGI. References - http://www.cgi-app.org/index.cgi?FastCGI @@ -24,10 +25,33 @@ in the logs. So it's fine to do a partial check here. * TODO Use HTML::Template::Pro. Not sure it's really worth it, though. -* TODO Forbid `/' and `\0' to appear in the domain/user name. +* DONE Escape reserved characters in URLs: +http://mark.stosberg.com/blog/2010/12/percent-encoding-uris-in-perl.html -* TODO How should we encode the URL for internationalized domain names? Punicode vs. unicode vs. HTML entities? -(Right now it's HTML entities.) +* CANCELED How should we encode the URL for internationalized domain names? Punicode vs. unicode vs. HTML entities? +CLOSED: [2012-09-27 Thu 00:03] +- CLOSING NOTE [2012-09-27 Thu 00:03] \\ +It's up to the browser (Firefox support unicode in URLs). -* TODO Forbid UTF8 in the domain part of lists? (Test if the list +* CANCELED Forbid UTF8 in the domain part of lists? (Test if the list managers support it at least.) +CLOSED: [2012-09-27 Thu 03:38] +- CLOSING NOTE [2012-09-27 Thu 03:38] \\ +Mailman and Schleuder do not support IDNs, but we convert the list name +into punicode first. + +* TODO Give the right for domain owners and postmaster to grant the right +to create aliases and lists. + +* TODO Give the right to appoint co owners (for list and aliases). + +* TODO Make every service use Kerberos, and remove the passphrase on +their private keys. + +* TODO Check list names against mailman's and schleuder's regexps? + +* TODO What to do when a list creation fails? Set up a new service +to clean out the pending lists and domains if they have not been fixed +within 24h (daemon). + +* TODO Automatically generated passwords. diff --git a/css/style.css b/css/style.css index fa2f407..79fd1b6 100644 --- a/css/style.css +++ b/css/style.css @@ -14,6 +14,9 @@ body { .active { color: #32CD32; } +.pending { + color: #F77C13; +} h1, h2, h3 { margin: 15pt auto 10pt auto; width: 600pt; diff --git a/lib/Fripost/Panel/Interface.pm b/lib/Fripost/Panel/Interface.pm index f150a39..b9a9500 100644 --- a/lib/Fripost/Panel/Interface.pm +++ b/lib/Fripost/Panel/Interface.pm @@ -15,9 +15,9 @@ use parent 'Fripost::Panel::Login'; use Fripost::Schema; use Fripost::Password; -use HTML::Entities; +use HTML::Entities 'encode_entities'; +use URI::Escape::XS 'encodeURIComponent'; use Net::IDN::Encode qw/email_to_unicode domain_to_ascii/; -use CGI::Util qw/escape unescape/; # This method is called right before the 'setup' method below. It @@ -43,13 +43,11 @@ sub ListDomains : StartRunmode { my @domains = $fp->domain->search( -concat => "\n", -die => 403); $fp->done; - my $template = $self->load_tmpl( 'list-domains.html', cache => 1, utf8 => 1 + my $template = $self->load_tmpl( 'list-domains.html', cache => 1, , loop_context_vars => 1 , global_vars => 1 ); - $template->param( url => $self->query->url - , user_localpart => encode_entities($ul) - , user_domainpart => encode_entities($ud) - , domains => [ map { { domain => encode_entities($_->{domain}) + $template->param( $self->userInfo ); + $template->param( domains => [ map { { &mkLink( domain => $_->{domain}) , isactive => $_->{isactive} , description => $_->{description} } } @domains ] @@ -65,8 +63,7 @@ sub ListLocals : Runmode { my %CFG = $self->cfg; my ($ul,$ud) = split /\@/, email_to_unicode($self->authen->username), 2; - my $d = decode_entities ((split /\//, $ENV{PATH_INFO}, 3)[1]); - Encode::_utf8_on($d); + my $d = ($self->split_path)[1]; my $fp = Fripost::Schema::->SASLauth( $self->authen->username, %CFG ); # Query *the* matching domain @@ -77,18 +74,15 @@ sub ListLocals : Runmode { # crash. my @mailboxes = $fp->mailbox->search( $d ); my @aliases = $fp->alias->search( $d ); - my @lists = $fp->list->search( $d, -is_pending => 0 ); + my @lists = $fp->list->search( $d ); $fp->done; - my $template = $self->load_tmpl( 'list-locals.html', cache => 1, utf8 => 1 + my $template = $self->load_tmpl( 'list-locals.html', cache => 1, , loop_context_vars => 1 , global_vars => 1 ); - $template->param( url => $self->query->url - , user_localpart => encode_entities($ul) - , user_domainpart => encode_entities($ud) - ); + $template->param( $self->userInfo ); $template->param( domain => encode_entities($domain{domain}) , isactive => $domain{isactive} , description => join ("\n", @{$domain{description}}) ); @@ -102,7 +96,7 @@ sub ListLocals : Runmode { $template->param( listMailboxes => $#mailboxes >= 0 || $domain{permissions} =~ /p/ ); $template->param( mailboxes => [ - map { { user => encode_entities($_->{user}) + map { { &mkLink(user => $_->{user}) , description => join ("\n", @{$_->{description}}) , isactive => $_->{isactive} , forwards => [ map { {forward => encode_entities($_)} } @@ -119,9 +113,7 @@ sub ListLocals : Runmode { $template->param( listAliases => $#aliases >= 0 || $domain{permissions} =~ /[aop]/ ); $template->param( aliases => [ - map { my $a = escape(encode_entities($_->{alias})); # TODO - { aliasurl => escape($a) - , alias => $a + map { { &mkLink(alias => $_->{alias}) , description => join ("\n", @{$_->{description}}) , isactive => $_->{isactive} , destinations => [ map { {destination => encode_entities($_)} } @@ -139,11 +131,13 @@ sub ListLocals : Runmode { # Should we list lists? $template->param( listLists => $#lists >= 0 || $domain{permissions} =~ /[lop]/ ); $template->param( lists => [ - map { { list => encode_entities($_->{list}) + map { { &mkLink(list => $_->{list}) , description => join ("\n", @{$_->{description}}) , isactive => $_->{isactive} + , ispending => $_->{ispending} , transport => $_->{transport} - , listurl => $CFG{'listurl_'.$_->{transport}}.$_->{list}.'@'.domain_to_ascii($d) + , listURL => $CFG{'listurl_'.$_->{transport}}.$_->{list}. + '@'.domain_to_ascii($d) }; } @lists @@ -159,11 +153,10 @@ sub EditDomain : Runmode { my %CFG = $self->cfg; my ($ul,$ud) = split /\@/, email_to_unicode($self->authen->username), 2; - my $d = decode_entities ((split /\//, $ENV{PATH_INFO}, 3)[1]); - Encode::_utf8_on($d); + my $d = ($self->split_path)[1]; my $q = $self->query; - return $self->redirect($q->url .'/') if defined $q->param('cancel'); + return $self->redirect('./') if defined $q->param('cancel'); my $fp = Fripost::Schema::->SASLauth( $self->authen->username, %CFG ); @@ -180,14 +173,11 @@ sub EditDomain : Runmode { my %domain = $fp->domain->get( $d, -die => 404 ); $fp->done; - my $template = $self->load_tmpl( 'edit-domain.html', cache => 1, utf8 => 1 + my $template = $self->load_tmpl( 'edit-domain.html', cache => 1, , loop_context_vars => 1 , global_vars => 1 ); - $template->param( url => $q->url - , user_localpart => encode_entities($ul) - , user_domainpart => encode_entities($ud) - , domain => encode_entities($d) - ); + $template->param( $self->userInfo ); + $template->param( domain => encode_entities($d) ); if ($error) { # Preserve the (incorrect) form $template->param( isactive => $q->param('isactive') @@ -214,38 +204,35 @@ sub EditLocal : Runmode { my $self = shift; my %CFG = $self->cfg; - my ($ul,$ud) = split /\@/, email_to_unicode($self->authen->username), 2; - my ($null,$d,$l,$crap) = split /\//, $ENV{PATH_INFO}, 4; - my $du = decode_entities ($d); Encode::_utf8_on($du); - my $lu = decode_entities ($l); Encode::_utf8_on($lu); - my $q = $self->query; - return $self->redirect($q->url.'/'.$d.'/') if defined $q->param('cancel'); + return $self->redirect('../') if defined $q->param('cancel'); my $fp = Fripost::Schema::->SASLauth( $self->authen->username, %CFG ); # Search for *the* matching mailbox, alias or list. - my %local = $fp->local->get ($lu.'@'.$du, -die => 404, - -concat => "\x{0D}\x{0A}" ); + my ($d,$l) = ($self->split_path)[1,2]; + my %local = $fp->local->get ($l.'@'.$d, -die => 404, + -concat => "\x{0D}\x{0A}" ); die "Unknown type" unless grep { $local{type} eq $_ } qw/mailbox alias list/; + die "404\n" if $local{ispending}; my $error; # Tells whether the change submission has failed. my $t = $local{type}; if (defined $q->param('a') and $q->param('a') eq 'delete') { # Delete the entry - $error = $fp->$t->delete($lu.'@'.$du, -die => 0); + $error = $fp->$t->delete($l.'@'.$d, -die => 0); unless ($error) { $fp->done; - return $self->redirect($q->url .'/'. $d .'/'); + return $self->redirect('../'); } } if (defined $q->param('submit')) { # Changes have been submitted: process them my %entry; if ($t eq 'mailbox') { - $entry{user} = $lu.'@'.$du; + $entry{user} = $l.'@'.$d; $entry{forwards} = $q->param('forwards'); if ($q->param('oldpw') ne '' or @@ -282,11 +269,11 @@ sub EditLocal : Runmode { } } elsif ($t eq 'alias') { - $entry{alias} = $lu.'@'.$du; + $entry{alias} = $l.'@'.$d; $entry{maildrop} = $q->param('maildrop'); } elsif ($t eq 'list') { - $entry{list} = $lu.'@'.$du; + $entry{list} = $l.'@'.$d; $entry{transport} = $q->param('transport'); } $entry{isactive} = $q->param('isactive'); @@ -295,13 +282,10 @@ sub EditLocal : Runmode { unless $error; } - my $template = $self->load_tmpl( "edit-$t.html", - cache => 1, utf8 => 1 ); - $template->param( url => $q->url - , user_localpart => encode_entities($ul) - , user_domainpart => encode_entities($ud) - , domain => encode_entities($du) - ); + my $template = $self->load_tmpl( "edit-$t.html", cache => 1 ); + $template->param( $self->userInfo ); + $template->param( domain => encode_entities($d) ); + if ($error and defined $q->param('submit')) { # Preserve the (incorrect) form, except the passwords if ($t eq 'mailbox') { @@ -319,8 +303,8 @@ sub EditLocal : Runmode { , description => $q->param('description') ); } else { - %local = $fp->local->get ($lu.'@'.$du, -die => 404, - -concat => "\x{0D}\x{0A}" ); + %local = $fp->local->get ($l.'@'.$d, -die => 404, + -concat => "\x{0D}\x{0A}" ); if ($t eq 'mailbox') { $template->param( user => encode_entities($local{user}) , forwards => encode_entities($local{forwards}) ); @@ -340,8 +324,8 @@ sub EditLocal : Runmode { (defined $q->param('a') and $q->param('a') eq 'delete')); $template->param( newChanges => $news ); $template->param( error => encode_entities ($error) ) if $error; - $template->param( canDelete => 1 ) if $t eq 'alias'; # TODO - $template->param( listurl => $CFG{'listurl_'.$local{transport}}.$l.'@'.$d ) + $template->param( canDelete => 1 ) if $t eq 'alias'; + $template->param( listURL => $CFG{'listurl_'.$local{transport}}.$l.'@'.$d ) if $t eq 'list'; $q->delete('a'); return $template->output; @@ -354,13 +338,10 @@ sub AddLocal : Runmode { my $self = shift; my %CFG = $self->cfg; - my ($ul,$ud) = split /\@/, email_to_unicode($self->authen->username), 2; - my $d = (split /\//, $ENV{PATH_INFO}, 3)[1]; - my $du = decode_entities ($d); Encode::_utf8_on($du); - my $q = $self->query; - return $self->redirect($q->url.'/'.$d.'/') if defined $q->param('cancel'); + return $self->redirect('./') if defined $q->param('cancel'); + my $d = ($self->split_path)[1]; my $t = $q->param('t') // die "Undefined type"; my $error; # Tells whether the change submission has failed. if (defined $q->param('submit')) { @@ -368,7 +349,7 @@ sub AddLocal : Runmode { my %entry; my %rest; if ($t eq 'mailbox') { - $entry{user} = $q->param('user').'@'.$du; + $entry{user} = $q->param('user').'@'.$d; $entry{forwards} = $q->param('forwards'); if ($q->param('password') ne $q->param('password2')) { $error = "Passwords do not match"; @@ -384,11 +365,11 @@ sub AddLocal : Runmode { # TODO: inherit the quota from the postmaster's? } elsif ($t eq 'alias') { - $entry{alias} = $q->param('alias').'@'.$du; + $entry{alias} = $q->param('alias').'@'.$d; $entry{maildrop} = $q->param('maildrop'); } elsif ($t eq 'list') { - $entry{list} = $q->param('list').'@'.$du; + $entry{list} = $q->param('list').'@'.$d; $entry{transport} = $q->param('transport'); if ($q->param('password') ne $q->param('password2')) { $error = "Passwords do not match"; @@ -409,7 +390,7 @@ sub AddLocal : Runmode { } else { # Unknown type - return $self->redirect($q->url.'/'.$d.'/'); + return $self->redirect('./'); } $entry{isactive} = $q->param('isactive'); $entry{description} = $q->param('description'); @@ -418,16 +399,13 @@ sub AddLocal : Runmode { my $fp = Fripost::Schema::->SASLauth( $self->authen->username, %CFG ); $error = $fp->$t->add( \%entry, -concat => "(\n|\x{0D}\x{0A})", %rest); $fp->done; - return $self->redirect($q->url.'/'.$d.'/') unless $error; + return $self->redirect('./') unless $error; } } - my $template = $self->load_tmpl( "add-$t.html", cache => 1, utf8 => 1 ); - $template->param( url => $q->url - , user_localpart => encode_entities($ul) - , user_domainpart => encode_entities($ud) - , domain => encode_entities($du) - ); + my $template = $self->load_tmpl( "add-$t.html", cache => 1 ); + $template->param( $self->userInfo ); + $template->param( domain => encode_entities($d) ); if ($error) { # Preserve the (incorrect) form, except the passwords if ($t eq 'mailbox') { @@ -444,7 +422,7 @@ sub AddLocal : Runmode { } else { # Unknown type - return $self->redirect($q->url.'/'.$d.'/'); + return $self->redirect('./'); } $template->param( isactive => $q->param('isactive') , description => $q->param('description') @@ -456,6 +434,28 @@ sub AddLocal : Runmode { return $template->output; } +sub mkURL { + my $host = shift; + my @path = map { encodeURIComponent($_) } @_; + join '/', ($host, @path); +} + +sub mkLink { + my $k = shift; + my $d = shift; + ( $k => encode_entities($d), + $k.'URI' => &mkURL('.', $d) ) +} + +sub userInfo { + my $self = shift; + my ($l,$d) = split /\@/, email_to_unicode($self->authen->username), 2; + + ( user_localpart => encode_entities($l) + , user_domainpart => encode_entities($d) + , userURI => &mkURL ($ENV{SCRIPT_NAME}, $d, $l) + ) +} =head1 AUTHOR diff --git a/lib/Fripost/Panel/Login.pm b/lib/Fripost/Panel/Login.pm index 86b3e66..810f9e1 100644 --- a/lib/Fripost/Panel/Login.pm +++ b/lib/Fripost/Panel/Login.pm @@ -20,8 +20,9 @@ use CGI::Application::Plugin::Redirect; use CGI::Application::Plugin::ConfigAuto 'cfg'; use Fripost::Schema; -use HTML::Entities; -use Net::IDN::Encode qw/email_to_ascii/; +use HTML::Entities 'encode_entities'; +use URI::Escape::XS 'decodeURIComponent'; +use Net::IDN::Encode 'email_to_ascii'; # This method is called right before the 'setup' method below. It @@ -62,7 +63,7 @@ sub cgiapp_init { $u .= '@'.$CFG{default_realm}; } Encode::_utf8_on($u); - $u = Net::IDN::Encode::email_to_ascii($u); + $u = email_to_ascii($u); my $fp = Fripost::Schema::->auth($u, $p, ldap_uri => $CFG{ldap_uri}, ldap_suffix => $CFG{ldap_suffix}, @@ -80,7 +81,7 @@ sub cgiapp_init { ); # The run modes that require authentication - $self->authen->protected_runmodes( qw /okay error_rm/ ); + $self->authen->protected_runmodes( qw/okay error_rm/ ); } @@ -105,7 +106,7 @@ sub setup { return 'logout' if defined $a and $a eq 'logout'; # /domain/{user,alias,list}/?query_url - my ($null,$domain,$local,$crap) = split /\//, $ENV{PATH_INFO}; + my ($null,$domain,$local,$crap) = $self->split_path; return 'ListDomains' unless (defined $null) and $null eq ''; @@ -164,7 +165,7 @@ sub login : Runmode { sub login_box { my $self = shift; - my $template = $self->load_tmpl( 'login.html', cache => 1, utf8 => 1 ); + my $template = $self->load_tmpl( 'login.html', cache => 1 ); $template->param( error => $self->authen->login_attempts ); $template->param( redirect => $self->query->param('redirect') ); @@ -199,7 +200,7 @@ sub error_rm : ErrorRunmode { # HTTP client error. chomp $error; $self->header_props ( -status => $error ); - my $template = $self->load_tmpl( 'error_http.html', cache => 1, utf8 => 1 ); + my $template = $self->load_tmpl( 'error_http.html', cache => 1 ); my $mesg; if ($error eq '403' ) { $mesg = 'Forbidden' @@ -214,7 +215,7 @@ sub error_rm : ErrorRunmode { else { # Users are not supposed to see that unless the CGI crashes :P - my $template = $self->load_tmpl( 'error.html', cache => 1, utf8 => 1 ); + my $template = $self->load_tmpl( 'error.html', cache => 1 ); $template->param( email => $self->cfg('report_email') ); $template->param( message => $error ); $template->param( url => $self->query->url . '/'); @@ -222,6 +223,19 @@ sub error_rm : ErrorRunmode { } } +sub split_path { + my $self = shift; + my %options = @_; + + my $script = $ENV{SCRIPT_NAME} // ''; + my $uri = $self->query->request_uri; + $uri =~ s/^$script//s; + $uri =~ s/\?.*//s; + + map { my $x = decodeURIComponent($_); Encode::_utf8_on($x); $x } + (split /\//, $uri); +} + =head1 AUTHOR diff --git a/lib/Fripost/Schema/Alias.pm b/lib/Fripost/Schema/Alias.pm index 07ae84f..51bf98f 100644 --- a/lib/Fripost/Schema/Alias.pm +++ b/lib/Fripost/Schema/Alias.pm @@ -111,8 +111,8 @@ sub add { } eval { + die "Missing alias name\n" unless $a->{alias} =~ /^.+\@.+$/; my ($l,$d) = split /\@/, email_to_ascii($a->{alias}), 2; - die "Missing alias name\n" if $l eq ''; &_is_valid($a); die "‘".$a->{alias}."’ already exists\n" if $self->local->exists($a->{alias},%options); diff --git a/lib/Fripost/Schema/List.pm b/lib/Fripost/Schema/List.pm index 87876f6..67da859 100644 --- a/lib/Fripost/Schema/List.pm +++ b/lib/Fripost/Schema/List.pm @@ -51,6 +51,7 @@ sub search { deref => 'never', filter => $filter, attrs => [ qw/fvl description fripostIsStatusActive + fripostIsStatusPending fripostListManager/ ] ); if ($lists->code) { @@ -61,6 +62,7 @@ sub search { , isactive => $_->get_value('fripostIsStatusActive') eq 'TRUE' , description => concat($concat, $_->get_value('description')) , transport => $_->get_value('fripostListManager') + , ispending => ($_->get_value('fripostIsStatusPending') // '') eq 'TRUE' } } $lists->sorted('fvl') @@ -113,8 +115,8 @@ sub add { eval { + die "Missing list name\n" unless $l->{list} =~ /^.+\@.+$/; my ($l2,$d) = split /\@/, email_to_ascii($l->{list}), 2; - die "Missing list name\n" if $l eq ''; must_attrs( $l, 'transport' ); &_is_valid($l); die "‘".$l->{list}."’ already exists\n" diff --git a/lib/Fripost/Schema/Local.pm b/lib/Fripost/Schema/Local.pm index 9efff91..f497a4e 100644 --- a/lib/Fripost/Schema/Local.pm +++ b/lib/Fripost/Schema/Local.pm @@ -49,6 +49,7 @@ sub get { (&(objectClass=FripostVirtualList)(fvl=$l)))", attrs => [ qw/fvu description fripostIsStatusActive + fripostIsStatusPending fripostOptionalMaildrop fripostMailboxQuota fva fripostMaildrop @@ -91,6 +92,7 @@ sub get { } $ret{isactive} = $local->get_value('fripostIsStatusActive') eq 'TRUE'; $ret{description} = concat($concat, $local->get_value('description')); + $ret{ispending} = ($local->get_value('fripostIsStatusPending') // '') eq 'TRUE'; return %ret; } diff --git a/lib/Fripost/Schema/Mailbox.pm b/lib/Fripost/Schema/Mailbox.pm index 95e2d10..ce23d98 100644 --- a/lib/Fripost/Schema/Mailbox.pm +++ b/lib/Fripost/Schema/Mailbox.pm @@ -134,8 +134,8 @@ sub add { } eval { + die "Missing user name\n" unless $m->{user} =~ /^.+\@.+$/; my ($l,$d) = split /\@/, email_to_ascii($m->{user}), 2; - die "Missing user name\n" if $l eq ''; &_is_valid($m); die "‘".$m->{user}."’ already exists\n" if $self->local->exists($m->{user},%options); diff --git a/misc/mklist/INSTALL b/misc/mklist/INSTALL index 660bcf9..7164217 100644 --- a/misc/mklist/INSTALL +++ b/misc/mklist/INSTALL @@ -37,7 +37,7 @@ Postfix's master.cf mklist-mailman unix - n n - - pipe flags=FR directory=/opt/fripost-panel/ user=list:list argv=/opt/fripost-panel/misc/mklist/mklist.pl mailman ${size} - + mklist-schleuder unix - n n - - pipe flags=FR directory=/opt/fripost-panel/ user=schleuder:schleuder argv=/opt/fripost-panel/misc/mklist/mklist.pl schleuder ${size} @@ -50,7 +50,7 @@ Postfix's main.cf mklist-mailman_destination_concurrency_limit = 1 mklist-mailman_destination_recpipient_limit = 1 mklist-mailman_time_limit = 10m - + mklist-schleuder_destination_concurrency_limit = 1 mklist-schleuder_destination_recpipient_limit = 1 mklist-schleuder_time_limit = 2h diff --git a/misc/mklist/mklist.pl b/misc/mklist/mklist.pl index 3223c45..6d0b6b2 100755 --- a/misc/mklist/mklist.pl +++ b/misc/mklist/mklist.pl @@ -30,14 +30,14 @@ use lib 'lib'; use Mail::GnuPG; use MIME::Parser; use MIME::QuotedPrint; -use Net::IDN::Encode qw/email_to_ascii/; +use Net::IDN::Encode 'email_to_ascii'; use Fripost::Schema; my $transport = shift; pod2usage(2) unless defined $transport and grep { $transport eq $_} qw/mailman schleuder/; -my $configdir = catdir('/','etc','mklist'); +my $configdir = catdir(qw(/ etc mklist)); my $config = Config::Auto::parse( catfile($configdir, 'config'), format => "equal" ); diff --git a/template/add-alias.html b/template/add-alias.html index 7ceb4cf..8ad887f 100644 --- a/template/add-alias.html +++ b/template/add-alias.html @@ -8,13 +8,13 @@ <body> <div id="header"> <div class="left column"> - <a href="<TMPL_VAR NAME=url>/">Root</a> / - <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/"><TMPL_VAR NAME=domain></a> / + <a href="../">Root</a> / + <a href="./"><TMPL_VAR NAME=domain></a> / </div> <div class="right column"> - Logged as <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=user_domainpart>/<TMPL_VAR NAME=user_localpart>/?a=edit" + Logged as <a href="<TMPL_VAR NAME=userURI>/?a=edit" ><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></a> - | <a href="<TMPL_VAR NAME=url>/?a=logout">Log out</a> + | <a href="./?a=logout">Log out</a> </div> <br/> </div> diff --git a/template/add-list.html b/template/add-list.html index ef99497..e69690b 100644 --- a/template/add-list.html +++ b/template/add-list.html @@ -8,13 +8,13 @@ <body> <div id="header"> <div class="left column"> - <a href="<TMPL_VAR NAME=url>/">Root</a> / - <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/"><TMPL_VAR NAME=domain></a> / + <a href="../">Root</a> / + <a href="./"><TMPL_VAR NAME=domain></a> / </div> <div class="right column"> - Logged as <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=user_domainpart>/<TMPL_VAR NAME=user_localpart>/?a=edit" + Logged as <a href="<TMPL_VAR NAME=userURI>/?a=edit" ><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></a> - | <a href="<TMPL_VAR NAME=url>/?a=logout">Log out</a> + | <a href="./?a=logout">Log out</a> </div> <br/> </div> @@ -103,7 +103,7 @@ <i>Note</i>: No confirmation email will be sent. It may take a while for the list to be created (especially for the Schleuder list manager, as it requires a GPG key creation); Once the list has succefully been created, it will be visible under the - <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/">management page for <span class="domain"><TMPL_VAR NAME=domain></span></a>. + <a href="./">management page for <span class="domain"><TMPL_VAR NAME=domain></span></a>. </div> </div> </form> diff --git a/template/add-mailbox.html b/template/add-mailbox.html index d82af0e..6bcc748 100644 --- a/template/add-mailbox.html +++ b/template/add-mailbox.html @@ -8,13 +8,13 @@ <body> <div id="header"> <div class="left column"> - <a href="<TMPL_VAR NAME=url>/">Root</a> / - <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/"><TMPL_VAR NAME=domain></a> / + <a href="../">Root</a> / + <a href="./"><TMPL_VAR NAME=domain></a> / </div> <div class="right column"> - Logged as <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=user_domainpart>/<TMPL_VAR NAME=user_localpart>/?a=edit" + Logged as <a href="<TMPL_VAR NAME=userURI>/?a=edit" ><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></a> - | <a href="<TMPL_VAR NAME=url>/?a=logout">Log out</a> + | <a href="./?a=logout">Log out</a> </div> <br/> </div> diff --git a/template/edit-alias.html b/template/edit-alias.html index 85e2d5f..aa18faf 100644 --- a/template/edit-alias.html +++ b/template/edit-alias.html @@ -8,14 +8,14 @@ <body> <div id="header"> <div class="left column"> - <a href="<TMPL_VAR NAME=url>/">Root</a> / - <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/"><TMPL_VAR NAME=domain></a> / + <a href="../../">Root</a> / + <a href="../"><TMPL_VAR NAME=domain></a> / <TMPL_VAR NAME=alias> / </div> <div class="right column"> - Logged as <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=user_domainpart>/<TMPL_VAR NAME=user_localpart>/?a=edit" + Logged as <a href="<TMPL_VAR NAME=userURI>/?a=edit" ><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></a> - | <a href="<TMPL_VAR NAME=url>/?a=logout">Log out</a> + | <a href="./?a=logout">Log out</a> </div> <br/> </div> @@ -23,7 +23,7 @@ <div id="content"> <h1>Edit alias <span class="email"><TMPL_VAR NAME=alias>@<TMPL_VAR NAME=domain></span><TMPL_IF NAME=canDelete - ><span class="action">[<a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/<TMPL_VAR NAME=alias>/?a=delete">delete</a>]</span + ><span class="action">[<a href="./?a=delete">delete</a>]</span ></TMPL_IF></h1> <TMPL_IF NAME=newChanges> diff --git a/template/edit-domain.html b/template/edit-domain.html index e6373e8..a6d6b34 100644 --- a/template/edit-domain.html +++ b/template/edit-domain.html @@ -8,13 +8,13 @@ <body> <div id="header"> <div class="left column"> - <a href="<TMPL_VAR NAME=url>/">Root</a> / - <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/"><TMPL_VAR NAME=domain></a> / + <a href="../">Root</a> / + <a href="./"><TMPL_VAR NAME=domain></a> / </div> <div class="right column"> - Logged as <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=user_domainpart>/<TMPL_VAR NAME=user_localpart>/?a=edit" + Logged as <a href="<TMPL_VAR NAME=userURI>/?a=edit" ><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></a> - | <a href="<TMPL_VAR NAME=url>/?a=logout">Log out</a> + | <a href="./?a=logout">Log out</a> </div> <br/> </div> diff --git a/template/edit-list.html b/template/edit-list.html index f44e38c..1cc8148 100644 --- a/template/edit-list.html +++ b/template/edit-list.html @@ -8,21 +8,21 @@ <body> <div id="header"> <div class="left column"> - <a href="<TMPL_VAR NAME=url>/">Root</a> / - <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/"><TMPL_VAR NAME=domain></a> / + <a href="../../">Root</a> / + <a href="../"><TMPL_VAR NAME=domain></a> / <TMPL_VAR NAME=list> / </div> <div class="right column"> - Logged as <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=user_domainpart>/<TMPL_VAR NAME=user_localpart>/?a=edit" + Logged as <a href="<TMPL_VAR NAME=userURI>/?a=edit" ><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></a> - | <a href="<TMPL_VAR NAME=url>/?a=logout">Log out</a> + | <a href="./?a=logout">Log out</a> </div> <br/> </div> <hr/> <div id="content"> - <h1>Edit list <a class="external" target="_blank" href="<TMPL_VAR NAME=listurl>" + <h1>Edit list <a class="external" target="_blank" href="<TMPL_VAR NAME=listURL>" ><span class="email"><TMPL_VAR NAME=list>@<TMPL_VAR NAME=domain></span ></a></h1> diff --git a/template/edit-mailbox.html b/template/edit-mailbox.html index 5f5dc08..892c643 100644 --- a/template/edit-mailbox.html +++ b/template/edit-mailbox.html @@ -8,14 +8,14 @@ <body> <div id="header"> <div class="left column"> - <a href="<TMPL_VAR NAME=url>/">Root</a> / - <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/"><TMPL_VAR NAME=domain></a> / + <a href="../../">Root</a> / + <a href="../"><TMPL_VAR NAME=domain></a> / <TMPL_VAR NAME=user> / </div> <div class="right column"> - Logged as <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=user_domainpart>/<TMPL_VAR NAME=user_localpart>/?a=edit" + Logged as <a href="<TMPL_VAR NAME=userURI>/?a=edit" ><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></a> - | <a href="<TMPL_VAR NAME=url>/?a=logout">Log out</a> + | <a href="./?a=logout">Log out</a> </div> <br/> </div> @@ -71,9 +71,11 @@ <div class="help"> <i>Note</i>: - You need to enter - <span class="mailbox"><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></span>'s + You need to enter your + (<span class="mailbox"><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></span>'s) current password first. + Leave these fields empty if you do not want to change the + password. </div> <hr/> diff --git a/template/list-domains.html b/template/list-domains.html index 980b8de..5ebdd05 100644 --- a/template/list-domains.html +++ b/template/list-domains.html @@ -11,16 +11,16 @@ Root / </div> <div class="right column"> - Logged as <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=user_domainpart>/<TMPL_VAR NAME=user_localpart>/?a=edit" + Logged as <a href="<TMPL_VAR NAME=userURI>/?a=edit" ><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></a> - | <a href="<TMPL_VAR NAME=url>/?a=logout">Log out</a> + | <a href="./?a=logout">Log out</a> </div> <br/> </div> <hr/> <div id="content"> - <h1>Manage domains<span class="action">[<a href="<TMPL_VAR NAME=url>/?a=add">add</a>]</span></h1> + <h1>Manage domains<span class="action">[<a href="./?a=add">add</a>]</span></h1> <table class="list" id="domains"> <thead> @@ -33,7 +33,7 @@ <tbody> <TMPL_LOOP NAME=domains> <TMPL_IF NAME=__even__><tr class="odd"><TMPL_ELSE><tr></TMPL_IF> - <td><span class="domain"><a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/"><TMPL_VAR NAME=domain></a></span></td> + <td><span class="domain"><a href="<TMPL_VAR NAME=domainURI>/"><TMPL_VAR NAME=domain></a></span></td> <td><TMPL_IF NAME=description><TMPL_VAR NAME=description><TMPL_ELSE><span class="none">(none)</span></TMPL_IF></td> <td><TMPL_IF NAME=isactive><span class="active">✔</span><TMPL_ELSE><span class="inactive">✘</span></TMPL_IF></td> </tr> diff --git a/template/list-locals.html b/template/list-locals.html index cb6f057..40ebeec 100644 --- a/template/list-locals.html +++ b/template/list-locals.html @@ -8,12 +8,12 @@ <body> <div id="header"> <div class="left column"> - <a href="<TMPL_VAR NAME=url>/">Root</a> / <TMPL_VAR NAME=domain> / + <a href="../">Root</a> / <TMPL_VAR NAME=domain> / </div> <div class="right column"> - Logged as <a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=user_domainpart>/<TMPL_VAR NAME=user_localpart>/?a=edit" + Logged as <a href="<TMPL_VAR NAME=userURI>/?a=edit" ><TMPL_VAR NAME=user_localpart>@<TMPL_VAR NAME=user_domainpart></a> - | <a href="<TMPL_VAR NAME=url>/?a=logout">Log out</a> + | <a href="./?a=logout">Log out</a> </div> <br/> </div> @@ -21,7 +21,7 @@ <div id="content"> <h1>Manage domain <span class="domain"><TMPL_VAR NAME=domain></span - ><TMPL_IF NAME=canEditDomain><span class="action">[<a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/?a=edit">edit domain</a>]</span></TMPL_IF></h1> + ><TMPL_IF NAME=canEditDomain><span class="action">[<a href="./?a=edit">edit domain</a>]</span></TMPL_IF></h1> <TMPL_IF NAME=description><p class="description"><TMPL_VAR NAME=description></p></TMPL_IF> @@ -36,7 +36,7 @@ <TMPL_IF NAME=listMailboxes> <h3>Mailboxes<TMPL_IF NAME=canAddMailbox - ><span class="action">[<a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/?a=add&t=mailbox">add</a>]</span + ><span class="action">[<a href="./?a=add&t=mailbox">add</a>]</span ></TMPL_IF></h3> <table class="list" id="mailboxes"> @@ -52,7 +52,7 @@ <tbody> <TMPL_LOOP NAME=mailboxes> <TMPL_IF NAME=__even__><tr class="odd"><TMPL_ELSE><tr></TMPL_IF> - <td><span class="mailbox"><a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/<TMPL_VAR NAME=user>/"><TMPL_VAR NAME=user></a></span></td> + <td><span class="mailbox"><a href="<TMPL_VAR NAME=userURI>/"><TMPL_VAR NAME=user></a></span></td> <td><TMPL_IF NAME=description><TMPL_VAR NAME=description><TMPL_ELSE><span class="none">(none)</span></TMPL_IF></td> <td><TMPL_IF NAME=isactive><span class="active">✔</span><TMPL_ELSE><span class="inactive">✘</span></TMPL_IF></td> <td><TMPL_UNLESS NAME=forwards><span class="none">(none)</span></TMPL_UNLESS> @@ -69,7 +69,7 @@ <TMPL_IF NAME=listAliases> <h3>Alias<TMPL_IF NAME=canAddAlias - ><span class="action">[<a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/?a=add&t=alias">add</a>]</span + ><span class="action">[<a href="./?a=add&t=alias">add</a>]</span ></TMPL_IF></h3> <table class="list" id="aliases"> @@ -84,7 +84,7 @@ <tbody> <TMPL_LOOP NAME=aliases> <TMPL_IF NAME=__even__><tr class="odd"><TMPL_ELSE><tr></TMPL_IF> - <td><span class="alias"><a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/<TMPL_VAR NAME=aliasurl>/"><TMPL_VAR NAME=alias></a></span></td> + <td><span class="alias"><a href="<TMPL_VAR NAME=aliasURI>/"><TMPL_VAR NAME=alias></a></span></td> <td><TMPL_IF NAME=description><TMPL_VAR NAME=description><TMPL_ELSE><span class="none">(none)</span></TMPL_IF></td> <td><TMPL_IF NAME=isactive><span class="active">✔</span><TMPL_ELSE><span class="inactive">✘</span></TMPL_IF></td> <td><TMPL_UNLESS NAME=destinations><span class="none">(none)</span></TMPL_UNLESS> @@ -93,7 +93,7 @@ </TMPL_LOOP> <TMPL_IF NAME=catchalls> <TMPL_IF NAME=CAodd><tr class="odd"><TMPL_ELSE><tr></TMPL_IF> - <td><a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/?a=edit#catch-all">*</a></td> + <td><a href="./?a=edit#catch-all">*</a></td> <td>Catch-all alias(es) for domain <span class="domain"><TMPL_VAR NAME=domain></span>.</td> <td><span class="dunno">—</span></td> <td><TMPL_LOOP NAME=catchalls><span class="email"><TMPL_VAR NAME=catchall></span><TMPL_UNLESS NAME=__last__>, </TMPL_UNLESS></TMPL_LOOP></td> @@ -107,7 +107,7 @@ <TMPL_IF NAME=listLists> <h3>Lists<TMPL_IF NAME=canAddList - ><span class="action">[<a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/?a=add&t=list">add</a>]</span + ><span class="action">[<a href="./?a=add&t=list">add</a>]</span ></TMPL_IF></h3> <table class="list" id="lists"> @@ -122,10 +122,13 @@ <tbody> <TMPL_LOOP NAME=lists> <TMPL_IF NAME=__even__><tr class="odd"><TMPL_ELSE><tr></TMPL_IF> - <td><span class="list"><a href="<TMPL_VAR NAME=url>/<TMPL_VAR NAME=domain>/<TMPL_VAR NAME=list>/"><TMPL_VAR NAME=list></a></span - > <a class="external" target="_blank" href="<TMPL_VAR NAME=listurl>">➠</a></td> + <td><span class="list"><TMPL_UNLESS NAME=ispending><a href="./<TMPL_VAR NAME=listURI>/"></TMPL_UNLESS + ><TMPL_VAR NAME=list + ><TMPL_UNLESS NAME=ispending></a> <a class="external" target="_blank" href="<TMPL_VAR NAME=listURL>">➠</a></TMPL_UNLESS></span></td> <td><TMPL_IF NAME=description><TMPL_VAR NAME=description><TMPL_ELSE><span class="none">(none)</span></TMPL_IF></td> - <td><TMPL_IF NAME=isactive><span class="active">✔</span><TMPL_ELSE><span class="inactive">✘</span></TMPL_IF></td> + <td><TMPL_IF NAME=ispending><span class="pending">⚑</span> + <TMPL_ELSE><TMPL_IF NAME=isactive><span class="active">✔</span> + <TMPL_ELSE><span class="inactive">✘</span></TMPL_IF></TMPL_IF></td> <td><TMPL_VAR NAME=transport></td> </tr> </TMPL_LOOP> |