From japc@co.sapo.pt Fri Feb 8 20:01:34 2002 Return-Path: Delivered-To: guy-ezmlm@rucus.ru.ac.za Received: (qmail 72201 invoked from network); 8 Feb 2002 18:01:34 -0000 Received: from isengard.sl.pt (HELO morgoth.sl.pt) (212.55.140.11) by server.rucus.ru.ac.za with SMTP; 8 Feb 2002 18:01:34 -0000 Received: (qmail 4347 invoked by uid 500); 8 Feb 2002 17:56:07 -0000 Date: Fri, 8 Feb 2002 17:56:07 +0000 From: Jose Celestino To: guy-ezmlm@rucus.ru.ac.za Cc: japc@co.sapo.pt Subject: Ezmlm-Web Message-ID: <20020208175607.GB4210@co.sapo.pt> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="bg08WKrSYDhXBjb5" Content-Disposition: inline Content-Transfer-Encoding: 8bit User-Agent: Mutt/1.3.27i X-URL: http://xpto.org/~japc X-System: Linux morgoth 2.4.18pre1 i686 X-Subliminal: Exchange Microsoft Status: RO Content-Length: 63760 Lines: 1546 --bg08WKrSYDhXBjb5 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hello Guy, don't know if you still maintain Ezmlm-Web but I've done some minor changes/improvements; - subscriber list can be filtered by the start character or by regexp (we had lists of nearly 50000 subscribers and it was a pain for the page to open); - support for $LIST/domains (for submission acls per domain): In $LIST/editor top you should add the following line (one line only): |export SENDER=`echo $SENDER | sed s/^.*@/@/g`; /servers/ezmlm/bin/ezmlm-issubn '/servers/virtualdomains/lists.mydomain.com/list1/domains' || { echo "Sorry, I'm reject mail from your domain ($SENDER). Contact sysadmin@mydomain.com if you have any questions about it.(#5.7.2)"; exit 100 ; } ad an extra list directory similar to mod for instance, $LIST/domains. - and, finally, support for newsletter administration (we use ezmlm here for newsletter sending - games, technology, health, etc.) for the non-technical dudes to manage and send issues for all the mailing list subscribers. I found the subscripter filter to be extremely useful :) -- Jose Celestino --------------------------------- Systems Administration - SAPO.pt --bg08WKrSYDhXBjb5 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: attachment; filename="ezmlm-web.cgi" Content-Transfer-Encoding: 8bit #!/usr/bin/perl #=========================================================================== # ezmlm-web.cgi - version 2.1 - 25/09/2000 # $Id: ezmlm-web.cgi,v 1.3 2000/09/25 19:58:07 guy Exp $ # # Copyright (C) 1999/2000, Guy Antony Halse, All Rights Reserved. # Please send bug reports and comments to guy-ezmlm@rucus.ru.ac.za # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # Neither name Guy Antony Halse nor the names of any contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS # IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # ========================================================================== # All user configuration happens in the config file ``ezmlmwebrc'' # POD documentation is at the end of this file # ========================================================================== # Modules to include use strict; use Getopt::Std; use Mail::Ezmlm; use Mail::Address; use DB_File; use CGI; use CGI::Carp qw(fatalsToBrowser set_message); # These two are actually included later and are put here so we remember them. #use File::Find if ($UNSAFE_RM == 1); #use File::Copy if ($UNSAFE_RM == 0); my @searchable=("TODOS","0-9","A","B","C","D","E","F","G","H","I","J","K", "L","M","N","O","P","Q","R","S","T","U","V","X","W","Y","Z","_"); my $q = new CGI; $q->import_names('Q'); use vars qw[$opt_c $opt_d $opt_C]; getopts('cd:C:'); # Suid stuff requires a secure path. $ENV{'PATH'} = '/bin'; # We run suid so we can't use $ENV{'HOME'} and $ENV{'USER'} to determine the # user. :( Don't alter this line unless you are _sure_ you have to. my @tmp = getpwuid($>); my $USER=$tmp[0]; # use strict is a good thing++ use vars qw[$HOME_DIR]; $HOME_DIR=$tmp[7]; use vars qw[$DEFAULT_OPTIONS %EZMLM_LABELS $UNSAFE_RM $ALIAS_USER $LIST_DIR]; use vars qw[$QMAIL_BASE $EZMLM_CGI_RC $EZMLM_CGI_URL $HTML_BGCOLOR $PRETTY_NAMES]; use vars qw[%HELPER $HELP_ICON_URL $HTML_HEADER $HTML_FOOTER $HTML_TEXT $HTML_LINK]; use vars qw[%BUTTON %LANGUAGE $HTML_VLINK $HTML_TITLE $FILE_UPLOAD]; # Get user configuration stuff if(defined($opt_C)) { require "$opt_C"; # Command Line } elsif(-e "$HOME_DIR/.ezmlmwebrc") { require "$HOME_DIR/.ezmlmwebrc"; # User } elsif(-e "/etc/ezmlm/ezmlmwebrc") { require "/etc/ezmlm/ezmlmwebrc"; # System } elsif(-e "./ezmlmwebrc") { require "./ezmlmwebrc"; # Install } else { die "Unable to read config file"; } # Allow suid wrapper to over-ride default list directory ... if(defined($opt_d)) { $LIST_DIR = $1 if ($opt_d =~ /^([-\@\w.\/]+)$/); } # Work out default domain name from qmail (for David Summers) my($DEFAULT_HOST); open (GETHOST, "<$QMAIL_BASE/me") || open (GETHOST, "<$QMAIL_BASE/defaultdomain") || die "Unable to read $QMAIL_BASE/me: $!"; chomp($DEFAULT_HOST = ); close GETHOST; # Untaint form input ... &untaint; # redirect must come before headers are printed if(defined($Q::action) && $Q::action eq '[Web Archive]') { print $q->redirect(&ezmlmcgirc); exit; } # Print header on every page ... print $q->header(-pragma=>'no-cache', '-cache-control'=>'no-cache', -expires=>'-1d'); print $q->start_html(-title=>$HTML_TITLE, -author=>'guy-ezmlm@rucus.ru.ac.za', -BGCOLOR=>$HTML_BGCOLOR, -LINK=>$HTML_LINK, -VLINK=>$HTML_VLINK, -TEXT=>$HTML_TEXT, -expires=>'-1d'); print $HTML_HEADER; # This is where we decide what to do, depending on the form state and the # users chosen course of action ... unless (defined($q->param('state'))) { # Default action. Present a list of available lists to the user ... &select_list; } elsif ($Q::state eq 'select') { # User selects an action to perorm on a list ... if ($Q::action eq "[$BUTTON{'create'}]") { # Create a new list ... &allow_create_list; } elsif (defined($Q::list)) { if ($Q::action eq "[$BUTTON{'edit'}]") { # Edit an existing list ... &display_list("NONE"); # open (ZBR,">>/tmp/123"); # print ZBR "FILTER:" . $q->param('filt') ."\n"; # while (defined($q->param('filt'))) { # print ZBR "DONEEEEEEEE\n"; # &display_list($q->param('filt')); # } # close ZBR; } elsif ($Q::action eq "[$BUTTON{'delete'}]") { # Delete a list ... &confirm_delete; } } else { &select_list; # NOP - Blank input ... } } elsif ($Q::state eq 'edit') { # User chooses to edit a list my($list); $list = $LIST_DIR . '/' . $q->param('list'); if ($Q::action eq "[$BUTTON{'deleteaddress'}]") { # Delete a subscriber ... &delete_address($list); &display_list("NONE"); } elsif ($Q::action eq "[$BUTTON{'addaddress'}]") { # Add a subscriber ... &add_address($list); &display_list("NONE"); } elsif ($Q::action eq "[$BUTTON{'edit_newsletter'}]") { # Send a newsletter issue... &edit_newsletter($list); } elsif ($Q::action eq "[$BUTTON{'moderators'}]") { # Edit the moderators ... &part_subscribers('mod'); } elsif ($Q::action eq "[$BUTTON{'domains'}]") { # Edit the domains ... &part_subscribers('domains'); } elsif ($Q::action eq "[$BUTTON{'denylist'}]") { # Edit the deny list ... &part_subscribers('deny'); } elsif ($Q::action eq "[$BUTTON{'allowlist'}]") { # edit the allow list ... &part_subscribers('allow'); } elsif ($Q::action eq "[$BUTTON{'digestsubscribers'}]") { # Edit the digest subscribers ... &part_subscribers('digest'); } elsif ($Q::action eq "[$BUTTON{'configuration'}]") { # Edit the config ... &list_config; } elsif (defined($q->param('filt'))) { &display_list($q->param('filt')); } elsif (defined($q->param('search')) && defined($q->param('searchfor'))) { &display_list($q->param('searchfor')); } else { # Cancel - Return a screen ... &select_list; } } elsif ($Q::state eq 'allow' || $Q::state eq 'mod' || $Q::state eq 'deny' || $q->param('state') eq 'digest') { # User edits moderators || deny || digest ... my($part); # Which list directory are we using ... if($Q::state eq 'mod') { $part = 'mod'; } elsif($Q::state eq 'deny' ) { $part = 'deny'; } elsif($Q::state eq 'allow') { $part = 'allow'; } else { $part = 'digest'; } if ($Q::action eq '[Delete Address]') { # Delete a subscriber ... &delete_address("$LIST_DIR/$Q::list", $part); &part_subscribers($part); } elsif ($Q::action eq "[$BUTTON{'addaddress'}]") { # Add a subscriber ... &add_address("$LIST_DIR/$Q::list", $part); &part_subscribers($part); } else { # Cancel - Return to the list ... &display_list("NONE"); } } elsif ($Q::state eq 'confirm_delete') { # User wants to delete a list ... &delete_list if($q->param('confirm') eq "[$BUTTON{'yes'}]"); # Do it ... $q->delete_all; &select_list; } elsif ($Q::state eq 'create') { # User wants to create a list ... if ($Q::action eq "[$BUTTON{'createlist'}]") { if (&create_list) { # Return if list creation is unsuccessful ... &allow_create_list; } else { &select_list; # Else choose a list ... } } else { # Cancel ... &select_list; } } elsif ($Q::state eq 'configuration') { # User updates configuration ... if ($Q::action eq "[$BUTTON{'updateconfiguration'}]") { # Save current settings ... &update_config; &display_list("NONE"); } elsif ($Q::action eq "[$BUTTON{'edittexts'}]") { # Edit DIR/text ... &list_text; } else { # Cancel - Return to list editing screen ... &display_list("NONE"); } } elsif ($Q::state eq 'list_text') { # User wants to edit texts associated with the list ... if ($Q::action eq "[$BUTTON{'editfile'}]") { &edit_text; } else { &list_config; # Cancel ... } } elsif ($Q::state eq 'edit_text') { # User wants to save a new version of something in DIR/text ... &save_text if ($Q::action eq "[$BUTTON{'savefile'}]"); &list_text; } elsif ($Q::state eq 'edit_newsletter') { # User wants to do something related with the newsletter if ($Q::action eq "[$BUTTON{'updateconfiguration'}]") { my $issue=$q->param('newsletterissue'); $issue="0$issue" if (($issue < 10) && ($issue !~ m/^0/)); my ($list) = new Mail::Ezmlm("$LIST_DIR/$Q::list"); # THOU SHALL NOT MESS $list->setpart("newsletter/localizacao", $q->param('newslettertree')); $list->setpart("newsletter/ficheiro", $q->param('newsletterhtml')); $list->setpart("newsletter/subject-da-edicao", $q->param('newslettersubject')); # THOU SHALL NOT MESS $list->setpart("newsletter/sender", $q->param('newslettersender')); $list->setpart("newsletter/edicao", $issue); &edit_newsletter; } &edit_newsletter if ($Q::action eq "[$BUTTON{'resetform'}]"); &sendnewsletter if ($Q::action eq "[$BUTTON{'sendnewsletter'}]"); &display_list("NONE") if ($Q::action eq "[$BUTTON{'cancel'}]"); } else { print "

$Q::action

$LANGUAGE{'nop'}


"; } # Print HTML footer and exit :) ... print $HTML_FOOTER, $q->end_html; exit; # ========================================================================= sub select_list { # List all mailing lists (sub directories) in the list directory. # Allow the user to choose a course of action; either editing an existing # list, creating a new one, or deleting an old one. my (@lists, @files, $i, $scrollsize); # Read the list directory for mailing lists. opendir DIR, $LIST_DIR || die "Unable to read $LIST_DIR: $!"; @files = grep !/^\./, readdir DIR; closedir DIR; # Check that they actually are lists ... foreach $i (0 .. $#files) { if (-e "$LIST_DIR/$files[$i]/lock") { if (-e "$LIST_DIR/webusers") { if (&webauth($files[$i]) == 0) { $lists[$#lists + 1] = $files[$i]; } } else { $lists[$#lists + 1] = $files[$i]; } } } # Keep selection box a resonable size - suggested by Sebastian Andersson $scrollsize = 25 if(($scrollsize = $#lists + 1) > 25); # Print a form $q->delete_all; print $q->startform; print $q->hidden(-name=>'state', -default=>'select'); print '
'; print $q->scrolling_list(-name=>'list', -size=>$scrollsize, -values=>\@lists) if defined(@lists); print '', $LANGUAGE{'chooselistinfo'}; print $q->submit(-name=>'action', -value=>"[$BUTTON{'create'}]"), ' ' if (!defined($opt_c)); print $q->submit(-name=>'action', -value=>"[$BUTTON{'edit'}]"), ' ' if(defined(@lists)); # JAPC // print $q->submit(-name=>'action', -value=>"[$BUTTON{'delete'}]") if(defined(@lists)); print '
'; print $q->endform; } # ------------------------------------------------------------------------ sub confirm_delete { # Make sure that the user really does want to delete the list! # Print a form ... $q->delete('state'); print $q->startform; print $q->hidden(-name=>'state', -default=>'confirm_delete'); print $q->hidden(-name=>'list', -default=>$q->param('list')); print '

', $LANGUAGE{'confirmdelete'}, ' ', $q->param('list'), '


'; print $q->submit(-name=>'confirm', -value=>"[$BUTTON{'no'}]"), ' '; print $q->submit(-name=>'confirm', -value=>"[$BUTTON{'yes'}]"), '
'; } # ------------------------------------------------------------------------ sub display_list { # Show a list of subscribers to the user ... my ($i, $list, $listaddress, $moderated, @subscribers, $scrollsize); my ($filt) = @_; my @subscribersfilt; # Work out the address of this list ... $list = new Mail::Ezmlm("$LIST_DIR/$Q::list"); $listaddress = &this_listaddress; # Get a list of subscribers from ezmlm ... @subscribers = $list->subscribers; if ("$filt" ne "NONE") { if ($filt eq "0-9") { $filt='\d' }; if ($filt eq "TODOS") { $filt='.*$' }; for (@subscribers) { if (defined($q->param('search'))) { push @subscribersfilt, $_ if (m/$filt/i); } else { push @subscribersfilt, $_ if (m/^$filt/i); } } } # Keep selection box a resonable size - suggested by Sebastian Andersson $scrollsize = 25 if(($scrollsize = $#subscribers + 1) > 25); # Print out a form of options ... $q->delete('state'); print "

$LANGUAGE{'subscribersto'} $Q::list ($listaddress)


"; print $q->start_multipart_form; print '
'; print $q->hidden(-name=>'state', -default=>'edit'); print $q->hidden(-name=>'list', -default=>$Q::list); print $q->scrolling_list(-name=>'delsubscriber', -size=>$scrollsize, -values=>\@subscribersfilt, -labels=>&pretty_names, -multiple=>'true');# if defined(@subscribersfilt) && ($#subscribers <= 50); print ''; print '
', ($#subscribers + 1), ' ', $LANGUAGE{'subscribers'}, ' || ', ($#subscribersfilt + 1), ' ', $LANGUAGE{'selected'},' (', $filt ,')

' if defined(@subscribers); if (defined(@subscribers)) { print "Filtrar:
"; for (@searchable) { print $q->submit(-name=>'filt', -value=>"$_"); } print "
[regexp]:" . $q->textfield(-name=>'searchfor', -size=>'40'); print $q->submit(-name=>'search', -value=>"[$BUTTON{'search'}]"), '

'; } print $q->submit(-name=>'action', -value=>"[$BUTTON{'deleteaddress'}]"), '

'; # if (defined(@subscribers) && ($#subscribers >= 51)); print $q->textfield(-name=>'addsubscriber', -size=>'40'), ' ', $HELPER{'addaddress'}, '
'; print $q->filefield(-name=>'addfile', -size=>20, -maxlength=>100), ' ', $HELPER{'addaddressfile'}, '
' if ($FILE_UPLOAD); print $q->submit(-name=>'action', -value=>"[$BUTTON{'addaddress'}]"), '

'; print '', $LANGUAGE{'additionalparts'}, ':
' if($list->ismodpost || $list->ismodsub || $list->isremote || $list->isdeny || $list->isallow || $list->isdigest); # JAPC // print $q->submit(-name=>'action', -value=>"[$BUTTON{'edit_newsletter'}]"), '', $HELPER{'edit_newsletter'}, ' '; #if ($list->ismodpost || $list->ismodsub || $list->isremote); print $q->submit(-name=>'action', -value=>"[$BUTTON{'moderators'}]"), '', $HELPER{'moderator'}, ' ' if ($list->ismodpost || $list->ismodsub || $list->isremote); print $q->submit(-name=>'action', -value=>"[$BUTTON{'domains'}]"), '', $HELPER{'domains'}, ' ' if (-d "$LIST_DIR/domains"); print $q->submit(-name=>'action', -value=>"[$BUTTON{'denylist'}]"), '', $HELPER{'deny'}, ' ' if ($list->isdeny); print $q->submit(-name=>'action', -value=>"[$BUTTON{'allowlist'}]"), '', $HELPER{'allow'}, ' ' if ($list->isallow); print $q->submit(-name=>'action', -value=>"[$BUTTON{'digestsubscribers'}]"), '', $HELPER{'digest'}, ' ' if ($list->isdigest); print '

'; print $q->submit(-name=>'action', -value=>"[$BUTTON{'webarchive'}]"), '', $HELPER{'webarch'}, ' ' if(&ezmlmcgirc); print $q->submit(-name=>'action', -value=>"[$BUTTON{'configuration'}]"), '', $HELPER{'config'}, '   '; print $q->submit(-name=>'action', -value=>"[$BUTTON{'selectlist'}]"); print '

'; print $q->endform; } # ------------------------------------------------------------------------ sub delete_list { # Delete a list ... # Fixes a bug from the previous version ... when the .qmail file has a # different name to the list. We use outlocal to handle vhosts ... my ($list, $listaddress, $listadd); $list = new Mail::Ezmlm("$LIST_DIR/$Q::list"); if ($listadd = $list->getpart('outlocal')) { chomp($listadd); } else { $listadd = $q->param('list'); } $listaddress = $1 if ($listadd =~ /-?(\w+)$/); if ($UNSAFE_RM == 0) { # This doesn't actually delete anything ... It just moves them so that # they don't show up. That way they can always be recovered by a helpful # sysadmin should he be in the mood :) use File::Copy; my ($oldfile); $oldfile = "$LIST_DIR/$Q::list"; my ($newfile); $newfile = "$LIST_DIR/.$Q::list"; move($oldfile, $newfile) or die "Unable to rename list: $!"; mkdir "$HOME_DIR/deleted.qmail", 0700 if(!-e "$HOME_DIR/deleted.qmail"); opendir(DIR, "$HOME_DIR") or die "Unable to get directory listing: $!"; my @files = map { "$HOME_DIR/$1" if m{^(\.qmail.+)$} } grep { /^\.qmail-$listaddress/ } readdir DIR; closedir DIR; foreach (@files) { unless (move($_, "$HOME_DIR/deleted.qmail/")) { die "Unable to move .qmail files: $!"; } } warn "List '$oldfile' moved (deleted)"; } else { # This, however, does DELETE the list. I don't like the idea, but I was # asked to include support for it so ... if (!rmtree("$LIST_DIR/$Q::list")) { die "Unable to delete list: $!"; } opendir(DIR, "$HOME_DIR") or die "Unable to get directory listing: $!"; my @files = map { "$HOME_DIR/$1" if m{^(\.qmail.+)$} } grep { /^\.qmail-$listaddress/ } readdir DIR; closedir DIR; if (unlink(@files) <= 0) { die "Unable to delete .qmail files: $!"; } warn "List '$list->thislist()' deleted"; } } # ------------------------------------------------------------------------ sub untaint { $DEFAULT_HOST = $1 if $DEFAULT_HOST =~ /^([\w\d\.-]+)$/; # Go through all the CGI input and make sure it is not tainted. Log any # tainted data that we come accross ... See the perlsec(1) man page ... my (@params, $i, $param); @params = $q->param; foreach $i (0 .. $#params) { my(@values); next if($params[$i] eq 'addfile'); foreach $param ($q->param($params[$i])) { next if $param eq ''; if ($param =~ /^([#-\@\w\.\/\[\]\:\n\r\>\< ]+)$/) { push @values, $1; } else { warn "Tainted input in '$params[$i]': " . $q->param($params[$i]); } $q->param(-name=>$params[$i], -values=>\@values); } } $q->import_names('Q'); } # ------------------------------------------------------------------------ sub add_address { # Add an address to a list .. my ($address, $list, @addresses, $count); my ($listname, $part) = @_; $list = new Mail::Ezmlm($listname); if($q->param('addfile')) { # Sanity check die "File upload must be of type text/*" unless($q->uploadInfo($q->param('addfile'))->{'Content-Type'} =~ m{^text/}); # Handle file uploads of addresses my($fh) = $q->upload('addfile'); return unless (defined($fh)); while (<$fh>) { next if (/^\s*$/ or /^#/); # blank, comments next unless (/\@/); # email address ... chomp(); push @addresses, $_; } } else { # User typed in an address return if ($q->param('addsubscriber') eq ''); $address = $q->param('addsubscriber'); $address .= $DEFAULT_HOST if ($q->param('addsubscriber') =~ /\@$/); push @addresses, $address; } foreach $address (@addresses) { my($add) = Mail::Address->parse($address); if(defined($add->name()) && $PRETTY_NAMES) { my(%pretty); tie %pretty, "DB_File", "$LIST_DIR/$Q::list/webnames"; $pretty{$add->address()} = $add->name(); untie %pretty; } if ($list->sub($add->address(), $part) != 1) { die "Unable to subscribe to list: $!"; } $count++; } $q->delete('addsubscriber'); } # ------------------------------------------------------------------------ sub delete_address { # Delete an address from a list ... my ($list, @address); my($listname, $part) = @_; $list = new Mail::Ezmlm($listname); return if ($q->param('delsubscriber') eq ''); @address = $q->param('delsubscriber'); if ($list->unsub(@address, $part) != 1) { die "Unable to unsubscribe from list $list: $!"; } if($PRETTY_NAMES) { my(%pretty, $add); tie %pretty, "DB_File", "$LIST_DIR/$Q::list/webnames"; foreach $add (@address) { delete $pretty{$add}; } untie %pretty; } $q->delete('delsubscriber'); } # ------------------------------------------------------------------------ sub part_subscribers { my($part) = @_; # Deal with list parts .... my ($i, $list, $listaddress, @subscribers, $moderated, $scrollsize, $type); # Work out the address of this list ... $list = new Mail::Ezmlm("$LIST_DIR/$Q::list"); $listaddress = &this_listaddress; if($part eq 'mod') { # Lets know what is moderated :) # do we store things in different directories? my $config = $list->getconfig; my($postpath) = $config =~ m{7\s*'([^']+)'}; my($subpath) = $config =~ m{8\s*'([^']+)'}; my($remotepath) = $config =~ m{9\s*'([^']+)'}; $moderated = '' if ($postpath); $moderated .= "[$LANGUAGE{'posting'}]" if ($list->ismodpost); $moderated .= 'Posting Moderators are stored in a non-standard location (' . $postpath . '). You will have to edit them manually.' if ($postpath); $moderated .= '' if ($subpath); $moderated .= " [$LANGUAGE{'subscription'}]" if($list->ismodsub); $moderated .= 'Subscriber Moderators are stored in a non-standard location (' . $subpath . '). You will have to edit them manually' if ($subpath); $moderated .= '' if ($remotepath); $moderated .= " [$LANGUAGE{'remoteadmin'}]" if($list->isremote); $moderated .= 'Remote Administrators are stored in a non-standard location (' . $remotepath . '). You will have to edit them manually' if ($remotepath); } # What type of sublist is this? ($type) = $Q::action =~ m/^\[(.+)\]$/; # Get a list of moderators from ezmlm ... @subscribers = $list->subscribers($part); # Keep selection box a resonable size - suggested by Sebastian Andersson $scrollsize = 25 if(($scrollsize = $#subscribers + 1) > 25); # Print out a form of options ... $q->delete('state'); print "

$type $LANGUAGE{'for'} $listaddress


"; print "
$moderated

" if(defined($moderated)); print $q->start_multipart_form; print '

'; print $q->hidden(-name=>'state', -default=>$part); print $q->hidden(-name=>'list', -default=>$Q::list), "\n"; print $q->scrolling_list(-name=>'delsubscriber', -size=>$scrollsize, -values=>\@subscribers, -multiple=>'true', -labels=>&pretty_names) if defined(@subscribers); print '
'; print $q->submit(-name=>'action', -value=>"[$BUTTON{'deleteaddress'}]"), '

' if defined(@subscribers); print $q->textfield(-name=>'addsubscriber', -size=>'40'), ' ', $HELPER{'addaddress'}, '
'; print $q->filefield(-name=>'addfile', -size=>20, -maxlength=>100), ' ', $HELPER{'addaddressfile'}, '
' if ($FILE_UPLOAD); print $q->submit(-name=>'action', -value=>"[$BUTTON{'addaddress'}]"), '

'; print $q->submit(-name=>'action', -value=>"[$BUTTON{'subscribers'}]"); print '

'; print $q->endform; } # ------------------------------------------------------------------------ sub allow_create_list { # Let the user select options for list creation ... my($username, $hostname, %labels, $j); # Work out if this user has a virtual host and set input accordingly ... if(-e "$QMAIL_BASE/virtualdomains") { open(VD, "<$QMAIL_BASE/virtualdomains") || warn "Can't read virtual domains file: $!"; while() { last if(($hostname) = /(.+?):$USER/); } close VD; } if(!defined($hostname)) { $username = "$USER-" if ($USER ne $ALIAS_USER); $hostname = $DEFAULT_HOST; } # Print a form of options ... $q->delete_all; print '

', $LANGUAGE{'createnew'}, '


'; print $q->startform; print $q->hidden(-name=>'state', -value=>'create'); print '', $LANGUAGE{'listname'}, ': ', $q->textfield(-name=>'list', -size=>'20'), ' ', $HELPER{'listname'}, '

'; print '', $LANGUAGE{'listaddress'}, ': '; print $q->textfield(-name=>'inlocal', -default=>$username, -size=>'10'); print ' @ ', $q->textfield(-name=>'inhost', -default=>$hostname, -size=>'30'), ' ', $HELPER{'listadd'}, '

'; print '

', $LANGUAGE{'listoptions'}, ':'; &display_options($DEFAULT_OPTIONS); # Allow creation of mysql table if the module allows it if($Mail::Ezmlm::MYSQL_BASE) { print '

', $q->checkbox(-name=>'sql', -label=>$LANGUAGE{'mysqlcreate'}, -on=>1); print ' ', $HELPER{'mysqlcreate'}, ''; } print '

', $LANGUAGE{'allowedtoedit'}, ': ', $q->textfield(-name=>'webusers', -value=>$ENV{'REMOTE_USER'}||'ALL', -size=>'30'), ' ', $HELPER{'webusers'}, '', '
', $HELPER{'allowedit'}, '' if(-e "$LIST_DIR/webusers"); print '

', $q->submit(-name=>'action', -value=>"[$BUTTON{'createlist'}]"), ' '; print $q->reset(-value=>"[$BUTTON{'resetform'}]"), ' '; print $q->submit(-name=>'action', -value=>"[$BUTTON{'cancel'}]"); print $q->endform; } # ------------------------------------------------------------------------ sub create_list { # Create a list acording to user selections ... # Check the list directory exists and create if necessary ... if(!-e $LIST_DIR) { die "Unable to create directory ($LIST_DIR): $!" unless mkdir $LIST_DIR, 0700; } my ($qmail, $listname, $options, $i); # Some taint checking ... $qmail = $1 if $q->param('inlocal') =~ /(?:$USER-)?([^\<\>\\\/\s]+)$/; $listname = $q->param('list'); $listname =~ s/ /_/g; # In case some git tries to put a space in the file name # Sanity Checks ... return 1 if ($listname eq '' || $qmail eq ''); if(-e ("$LIST_DIR/$listname/lock") || -e ("$HOME_DIR/.qmail-$qmail")) { print "

List '$listname' already exists :(

"; return 1; } # Work out the command line options foreach $i (grep {/\D/} keys %EZMLM_LABELS) { if (defined($q->param($i))) { $options .= $i; } else { $options .= uc($i); } } foreach $i (grep {/\d/} keys %EZMLM_LABELS) { if (defined($q->param($i))) { $options .= " -$i '" . $q->param("$i-value") . "'"; } } my($list) = new Mail::Ezmlm; unless ($list->make(-dir=>"$LIST_DIR/$listname", -qmail=>"$HOME_DIR/.qmail-$qmail", -name=>$q->param('inlocal'), -host=>$q->param('inhost'), -switches=>$options, -user=>$USER) ) { die 'List creation failed', $list->errmsg(); } # handle MySQL stuff if($q->param('sql') && $options =~ m/-6\s+/) { unless($list->createsql()) { die 'SQL table creation failed: ', $list->errmsg(); } } # Handle authentication stuff if ($Q::webusers) { open(WEBUSER, ">>$LIST_DIR/webusers") || die "Unable to open webusers: $!"; print WEBUSER "$Q::list: $Q::webusers\n"; close WEBUSER; } return 0; } # ------------------------------------------------------------------------ sub list_config { # Allow user to alter the list configuration ... my ($list, $listaddress, $listname, $options); my ($headeradd, $headerremove, $mimeremove, $prefix, $j); # Store some variables before we delete them ... $list = new Mail::Ezmlm("$LIST_DIR/$Q::list"); $listname = $q->param('list'); $listaddress = &this_listaddress; # Print a form of options ... $q->delete_all; print '

', $LANGUAGE{'editconfiguration'}, '


'; print $q->startform; print $q->hidden(-name=>'state', -value=>'configuration'); print $q->hidden(-name=>'list', -value=>$listname); print '', $LANGUAGE{'listname'}, ": $listname
"; print "$LANGUAGE{'listaddress'}: $listaddress

"; print '', $LANGUAGE{'listoptions'}, ':
'; # Print a list of options, selecting the ones that apply to this list ... &display_options($list->getconfig); # Get the contents of the headeradd, headerremove, mimeremove and prefix files $headeradd = $list->getpart('headeradd'); $headerremove = $list->getpart('headerremove'); $mimeremove = $list->getpart('mimeremove'); $prefix = $list->getpart('prefix'); print '

', $LANGUAGE{'prefix'}, ': ', $q->textfield(-name=>'prefix', -default=>$prefix, -size=>12), ' ', $HELPER{'prefix'}, '' if defined($prefix); print '

', $LANGUAGE{'headerremove'}, ': ', $HELPER{'headerremove'}, '
', $q->textarea(-name=>'headerremove', -default=>$headerremove, -rows=>5, -columns=>70); print '

', $LANGUAGE{'headeradd'}, ': ', $HELPER{'headeradd'}, '
', $q->textarea(-name=>'headeradd', -default=>$headeradd, -rows=>5, -columns=>70); print '

', $LANGUAGE{'mimeremove'}, ': ', $HELPER{'mimeremove'}, '
', $q->textarea(-name=>'mimeremove', -default=>$mimeremove, -rows=>5, -columns=>70) if defined($mimeremove); if(open(WEBUSER, "<$LIST_DIR/webusers")) { my($webusers); while() { last if (($webusers) = m{^$listname\s*\:\s*(.+)$}); } close WEBUSER; $webusers ||= $ENV{'REMOTE_USER'} || 'ALL'; print '

', $LANGUAGE{'allowedtoedit'}, ': ', $q->textfield(-name=>'webusers', -value=>$webusers, -size=>'30'), ' ', $HELPER{'webusers'}, '', '
', $HELPER{'allowedit'}, ''; } print '

', $q->submit(-name=>'action', -value=>"[$BUTTON{'updateconfiguration'}]"), ' '; print $q->reset(-value=>"[$BUTTON{'resetform'}]"), ' '; print $q->submit(-name=>'action', -value=>"[$BUTTON{'cancel'}]"), ' '; print $q->submit(-name=>'action', -value=>"[$BUTTON{'edittexts'}]"); print $q->endform; } # ------------------------------------------------------------------------ sub update_config { # Save the new user entered config ... my ($list, $options, $i, @inlocal, @inhost); $list = new Mail::Ezmlm("$LIST_DIR/$Q::list"); # Work out the command line options ... foreach $i (grep {/\D/} keys %EZMLM_LABELS) { if (defined($q->param($i))) { $options .= $i; } else { $options .= uc($i); } } foreach $i (grep {/\d/} keys %EZMLM_LABELS) { if (defined($q->param($i))) { $options .= " -$i '" . $q->param("$i-value") . "'"; } } # Actually update the list ... unless($list->update($options)) { die "List update failed"; } # Update headeradd, headerremove, mimeremove and prefix ... $list->setpart('headeradd', $q->param('headeradd')); $list->setpart('headerremove', $q->param('headerremove')); $list->setpart('mimeremove', $q->param('mimeremove')) if defined($q->param('mimeremove')); $list->setpart('prefix', $q->param('prefix')) if defined($q->param('prefix')); if($Q::webusers) { # Back up web users file open(TMP, ">/tmp/ezmlm-web.$$"); open(WU, "<$LIST_DIR/webusers"); while() { print TMP; } close TMP; close WU; open(TMP, "$LIST_DIR/webusers"); while() { if(/^$Q::list\s*:/) { print WU "$Q::list\: $Q::webusers\n"; } else { print WU; } } close TMP; close WU; unlink "/tmp/ezmlm-web.$$"; } } # ------------------------------------------------------------------------ sub this_listaddress { # Work out the address of this list ... Used often so put in its own subroutine ... my ($list, $listaddress); $list = new Mail::Ezmlm("$LIST_DIR/$Q::list"); chomp($listaddress = $list->getpart('outlocal')); $listaddress .= '@'; chomp($listaddress .= $list->getpart('outhost')); return $listaddress; } # ------------------------------------------------------------------------ sub list_text { # Show a listing of what is in DIR/text ... my(@files, $list); $list = $LIST_DIR . '/' . $q->param('list'); # Read the list directory for text ... opendir DIR, "$list/text" || die "Unable to read DIR/text: $!"; @files = grep !/^\./, readdir DIR; closedir DIR; # Print a form ... $q->delete('state'); print $q->startform; print $q->hidden(-name=>'state', -default=>'list_text'); print $q->hidden(-name=>'list', -default=>$q->param('list')); print '

'; print $q->scrolling_list(-name=>'file', -values=>\@files); print ''; print $q->submit(-name=>'action', -value=>"[$BUTTON{'editfile'}]"), ' '; print $q->submit(-name=>'action', -value=>"[$BUTTON{'cancel'}]"); print '

', $LANGUAGE{'edittextinfo'}, '

'; print $q->endform; } # ------------------------------------------------------------------------ sub edit_text { # Allow user to edit the contents of DIR/text ... my ($content); my($list) = new Mail::Ezmlm("$LIST_DIR/$Q::list"); $content = $list->getpart("text/$Q::file"); # Print a form ... $q->delete('state'); print '

', $LANGUAGE{'editingfile'}, ': ', $Q::file, '

'; print '
'; print $q->startform; print $q->hidden(-name=>'state', -default=>'edit_text'); print $q->hidden(-name=>'list', -default=>$q->param('list')); print $q->hidden(-name=>'file', -default=>$q->param('file')); print $q->textarea(-name=>'content', -default=>$content, -rows=>'25', -columns=>'72'); print ''; print $q->submit(-name=>'action', -value=>"[$BUTTON{'savefile'}]"), ' '; print $q->reset(-value=>"[$BUTTON{'resetform'}]"), ' '; print $q->submit(-name=>'action', -value=>"[$BUTTON{'cancel'}]"); print '

', $LANGUAGE{'editfileinfo'}; print $q->endform; print '

' } # ------------------------------------------------------------------------ sub save_text { # Save new text in DIR/text ... my ($list) = new Mail::Ezmlm("$LIST_DIR/$Q::list"); $list->setpart("text/$Q::file", $q->param('content')); } # ------------------------------------------------------------------------ sub webauth { # Read authentication level from webusers file. Format of this file is # somewhat similar to the unix groups file my($listname) = @_; open (USERS, "<$LIST_DIR/webusers") || die "Unable to read webusers file: $!"; while() { if (/^($listname|ALL)\:/i) { if (/(\:\s*|,\s+)((?:$ENV{'REMOTE_USER'})|(?:ALL))\s*(,|$)/) { close USERS; return 0; } } } close USERS; return 1; } # --------------------------------------------------------------------------- sub display_options { my($opts) = shift; my($i, $j); print ""; print ''; $j++; if ($j >= 3) { $j = 0; print ''; } print '
'; foreach $i (grep {/\D/} keys %EZMLM_LABELS) { if ($opts =~ /^\w*$i\w*\s*/) { print $q->checkbox(-name=>$i, -value=>$i, -label=>$EZMLM_LABELS{$i}[0], -on=>'1'); } else { print $q->checkbox(-name=>$i, -value=>$i, -label=>$EZMLM_LABELS{$i}[0]); } print '', $EZMLM_LABELS{$i}[1] , ''; print '
'; } print '
'; print ''; foreach $i (grep {/\d/} keys %EZMLM_LABELS) { print ''; } print '
'; if ($opts =~ /$i (?:'(.+?)')/) { print $q->checkbox(-name=>$i, -value=>$i, -label=>$EZMLM_LABELS{$i}[0], -on=>'1'); } else { print $q->checkbox(-name=>$i, -value=>$i, -label=>$EZMLM_LABELS{$i}[0]); } print '', $EZMLM_LABELS{$i}[1] , ''; print ''; print $q->textfield(-name=>"$i-value", -value=>$1||$EZMLM_LABELS{$i}[2], -size=>30); print '
'; } # --------------------------------------------------------------------------- sub edit_newsletter { # Edit a newsletter configuration my ($file,$subject,$sender,$tree,$issue) = (); my $listaddress = &this_listaddress; my ($list) = new Mail::Ezmlm("$LIST_DIR/$Q::list"); $file="newsletter.html" unless ($file = $list->getpart("newsletter/ficheiro")); $subject="Ediçao XX" unless ($subject = $list->getpart("newsletter/subject-da-edicao")); $sender="$listaddress" unless ($sender = $list->getpart("newsletter/sender")); $tree="/edicaoXX/" unless ($tree = $list->getpart("newsletter/localizacao")); $issue="" unless ($issue = $list->getpart("newsletter/edicao")); $q->delete('state'); print $q->start_multipart_form; print $q->hidden(-name=>'state', -default=>'edit_newsletter'); print $q->hidden(-name=>'list', -default=>$q->param('list')); print $q->hidden(-name=>'file', -default=>$q->param('file')); print '
'; print '

', $LANGUAGE{'newslettertree'}, ': ', $HELPER{'newslettertree'}, ''; print '

', $LANGUAGE{'newsletterhtml'}, ': ', $HELPER{'newsletterhtml'}, ''; print '

', $LANGUAGE{'newslettersubject'}, ': ', $HELPER{'newslettersubject'}, ''; print '

', $LANGUAGE{'newslettersender'}, ': ', $HELPER{'newslettersender'}, ''; print '

', $LANGUAGE{'newsletterissue'}, ': ', $HELPER{'newsletterissue'}, ''; print '

'; # THOU SHALL NOT MESS print '

', $q->textfield(-name=>'newslettertree', -size=>'50', -default=>"$tree"), ''; print '

', "$tree/edicao$issue", ''; print '

', $q->textfield(-name=>'newsletterhtml', -size=>'30', -default=>"$file"), ''; print '

', $q->textfield(-name=>'newslettersubject', -size=>'50', -default=>"$subject"), ''; # THOU SHALL NOT MESS print '

', $q->textbox(-name=>'newslettersender', -size=>'30', -default=>"$sender"), ''; print '

', "$sender", ''; print '

', $q->textfield(-name=>'newsletterissue', -size=>'10', -default=>"$issue"), ''; print '

'; print $q->hidden(-name=>'newslettertree', -default=>$q->param("$tree")); print $q->hidden(-name=>'newslettersender', -default=>$q->param("$sender")); print '

', $q->submit(-name=>'action', -value=>"[$BUTTON{'updateconfiguration'}]"), ' '; print $q->reset(-value=>"[$BUTTON{'resetform'}]"), ' '; print $q->submit(-name=>'action', -value=>"[$BUTTON{'cancel'}]"), ' '; print $q->submit(-name=>'action', -value=>"[$BUTTON{'sendnewsletter'}]"); print $q->endform; } # --------------------------------------------------------------------------- sub sendnewsletter { # Send newsletter my ($list) = new Mail::Ezmlm("$LIST_DIR/$Q::list"); my $listaddress = &this_listaddress; my ($file,$subject,$sender,$tree,$issue) = (); $file="newsletter.html" unless ($file = $list->getpart("newsletter/ficheiro")); $subject="Ediçao XX" unless ($subject = $list->getpart("newsletter/subject-da-edicao")); $sender="$listaddress" unless ($sender = $list->getpart("newsletter/sender")); $tree="/edicaoXX/" unless ($tree = $list->getpart("newsletter/localizacao")); $issue="" unless ($issue = $list->getpart("newsletter/edicao")); print " COMING SOON "; } # --------------------------------------------------------------------------- sub ezmlmcgirc { my($listno); if(open(WWW, "<$EZMLM_CGI_RC")) { while() { last if (($listno) = m{(\d+)(\D)\d+\2$LIST_DIR/$Q::list\2}); } close WWW; return "$EZMLM_CGI_URL/$listno" if(defined($listno)); } return undef; } # --------------------------------------------------------------------------- sub pretty_names { return undef unless($PRETTY_NAMES); my (%pretty, %prettymem); tie %pretty, "DB_File", "$LIST_DIR/$Q::list/webnames"; %prettymem = %pretty; untie %pretty; return \%prettymem; } # ------------------------------------------------------------------------- sub rmtree { # A subroutine to recursively delete a directory (like rm -f). # Based on the one in the perl cookbook :) use File::Find qw(finddepth); File::Find::finddepth sub { # assume that File::Find::name is secure since it only uses data we pass it my($name) = $File::Find::name =~ m{^(.+)$}; if (!-l && -d _) { rmdir($name) or warn "couldn't rmdir $name: $!"; } else { unlink($name) or warn "couldn't unlink $name: $!"; } }, @_; 1; } # ------------------------------------------------------------------------ BEGIN { sub handle_errors { my $msg = shift; print << "EOM";

A fatal error has occoured

Something you did caused this script to bail out. The error message we got was

$msg

Please try what you were doing again, checking everything you entered.
If you still find yourself getting this error, please contact the site administrator quoting the error message above.

EOM } set_message(\&handle_errors); } # ------------------------------------------------------------------------ # End of ezmlm-web.cgi v2.1 # ------------------------------------------------------------------------ __END__ =head1 NAME ezmlm-web - A web configuration interface to ezmlm mailing lists =head1 SYNOPSIS ezmlm-web [B<-c>] [B<-C> EFE] [B<-d> EFE] =head1 DESCRIPTION =over 4 =item B<-c> Disable list configuration =item B<-C> Specify an alternate configuration file given as F If not specified, ezmlm-web checks first in the users home directory, then in F and then the current directory =item B<-d> Specify an alternate directory where lists live. This is now depreciated in favour of using a custom ezmlmwebrc, but is left for backward compatibility. =back =head1 SUID WRAPPER C<#include stdio.h> C C C C<}> =head1 DOCUMENTATION/CONFIGURATION Please refer to the example ezmlmwebrc which is well commented, and to the README file in this distribution. =head1 FILES F<~/.ezmlmwebrc> F F<./ezmlmwebrc> =head1 AUTHOR Guy Antony Halse =head1 BUGS None known yet. Please report bugs to the author. =head1 S ezmlm(5), ezmlm-cgi(1), Mail::Ezmlm(3) http://rucus.ru.ac.za/~guy/ezmlm/ http://www.ezmlm.org/ http://www.qmail.org/ --bg08WKrSYDhXBjb5 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: attachment; filename="ezmlmwebrc.PT" Content-Transfer-Encoding: 8bit # $Id: ezmlmwebrc,v 1.5 2000/09/25 18:25:26 guy Exp $ # Configuration file for ezmlm-web 2.1 # =========================================================================== # This file is not just an ordinary configuration file - it contains valid # perl statements that are executed just like any other perl script. When # editing this file, be careful that it is still valid perl when you have # finished (perl -w ezmlmwebrc ;-) # It is divided into to logical parts. The first part configures the way # ezmlm-web runs, and the second changes the language, etc of ezmlm-web. You # can not arbitarilly exclude any statement, since the script doesn't define # any defaults of its own. You could, however, always split this file up and # include the parts with # # require('/path/to/other/part'); # --------------------------------------------------------------------------- # Where do we store lists on this server ... Try "$HOME_DIR/lists". # This directory will automatically be created if needed. $LIST_DIR = "/servers/virtualdomains/lists.mydomain.com"; # Safe list deletion? # 0 = move list to .list and the .qmails to deleted.qmail/. Recoverable :) # 1 = allow user to delete list completely. No backup, therefore no recovery. $UNSAFE_RM = 0; # Who is the alias user on this system (usually alias ;) $ALIAS_USER = 'alias'; # Where do the qmail control files live on this system ... $QMAIL_BASE = $Mail::Ezmlm::QMAIL_BASE . '/control'; # The url to our web interface - so we can use ezmlm-cgi if necessary $EZMLM_CGI_URL = 'http://listadmin.mydomain.com/'; # Where our ezcgirc file lives (probably /etc/ezmlm/ezcgirc $EZMLM_CGI_RC = '/etc/ezmlm/ezcgirc'; # Do we want to allow ``pretty'' names - ie more human readable ones # This will slow ezmlm-web down a bit for large lists $PRETTY_NAMES = 1; # Do we want to allow the users to be allowed to upload a file containing # lists of email addresses to subscribe? $FILE_UPLOAD = 1; # What switches to we want ezmlm-web to have on as default. The ezmlm-make # defaults are aBDFGHIJKLMNOpQRSTUWX (small means enabled, CAPITALS mean # disabled). The defaults below should be reasonable - I use them ;) $DEFAULT_OPTIONS = 'aBDFGHiJkLMNOpQRSTUWx'; # Where do we find the nice little help icon - by default HELP_ICON_URL # points to resources on http://rucus.ru.ac.za/. This will work, but we # would appreciate it if you changed this to a local site. $HELP_ICON_URL = 'http://mail-int.sl.pt/images/q.gif'; # Header for every page (.= concatinates) $HTML_HEADER = '

Lists Admin - mydomain.com

'; $HTML_HEADER .= '

'; # Footer for every page (.= concatinates) $HTML_FOOTER = '
'; $HTML_FOOTER .= '
'; $HTML_FOOTER .= 'ezmlm-web (v2.1) -- Contactar mydomain.com
'; # What colour do we want the background to be? $HTML_BGCOLOR = '#000000'; # What colour do we want text? $HTML_TEXT = '#0f0f0f'; # What color do we want links? $HTML_LINK = '#3333ff'; # What color to we want visited links? $HTML_VLINK = '#8888ff'; # What is the title of this document? $HTML_TITLE = 'mydomain.com - List Admin'; # --------------------------------------------------------------------------- # The meanings of the various ezmlm-make command line switches. The default # ones match the ezmlm-idx 0.4 default ezmlmrc ... Alter them to suit your # own ezmlmrc. Removing options from this list makes them unavailable # through ezmlm-web - this could be useful for things like -w %EZMLM_LABELS = ( # option => ['Short Name', # 'Long Help Description'], a => ['Arquivadas', 'O sistema arquivará mensagens novas'], b => ['Arquivo Bloqueado', 'Apenas aos moderadores é permitido aceder ao arquivo'], # c => config. This is implicity called, so is not defined here d => ['Digest', 'Constituir uma lista de "digest" das mensagens da lista'], # e => edit. Also implicity called, so not defined here f => ['Prefixo', 'O subject das mensagens sera alterado com este prefixo'], g => ['Arquivo Guardado', 'Pedidos de acesso ao arquivo originados de SENDERs desconhecidos são rejeitados'], h => ['Ajuda na Subscrição', 'As subscrições não precisam de confirmação'], i => ['Indexada', 'Indexada para arquivo acessível via WWW'], j => ['Saída Rápida', 'As dessubscrições não necessitam de confirmação'], k => ['Kill', 'As mensagens originárias de endereços listados em dir/deny/ são rejeitadas'], l => ['Lista de Subscritos', 'Os administradores remotos podem requerer uma lista dos subscritos'], m => ['Moderação das Mensagens', 'Todas as mensagens recebidas são moderadas'], n => ['Edição de Textos', 'É permitida aos administradores remotos a edição de ficheiros em dir/text/'], o => ['Rejeição de Outros', 'Mensagens de endereços que não os dos moderadores serão rejeitadas'], p => ['Publica', 'A lista responderá a pedidos administrativos e a pedidos do arquivo'], q => ['Endereço de Pedidos e Serviços', 'Processar comandos enviados no subject para local-request@host'], r => ['Administração Remota', 'Permitir a administração remota da lista'], s => ['Subscrição Moderada', 'Subscrições para a lista principal e para a digest são moderadas'], t => ['Trailer', 'Adicionar um trailer a todas as mensagens enviadas'], u => ['Apenas de Subscritos', 'Mensagens originárias de remetentes desconhecidos são rejeitadas'], # v => version. I doubt you will really need this ;-) w => ['Remover Warn', 'Remover as invocações do ezmlm-warn(1) da configuração da lista. Parte-se do princípio que o ezmlm-warn(1) será invocado de outra forma'], x => ['Extra', 'Remover certos mimetypes, etc'], # y => not used # z => not used # These all take an extra argument, which is the default value to use 0 => ['Sublista', 'Fazer a lista uma sublista da lista mainlist@host', 'mainlist@host'], # 1 => not used # 2 => not used 3 => ['Do Endereço', 'Substituir o header "From:" da mensagem por "From: fromarg"', 'fromarg'], 4 => ['Opções de Digest', 'Switches para o ezmlm-tstdig(1)', '-t24 -m30 -k64'], 5 => ['Dono da Lista', 'Endereço e-mail do dono da lista', ''], 6 => ['Base de dados SQL', 'Dados para ligação á base de dados SQL. Necessita de suporte para SQL', 'host:port:user:password:datab:table'], 7 => ['Caminho para a Moderação de Mensagens', 'Caminho para a base de dados dos moderadores das mensagens, se a lista tiver sido configurada para moderação de mensagens', '/some/full/path'], 8 => ['Caminho para a Moderação de Subscrições', 'Caminho para a base de dados dos moderadores das subscrições, se a lista tiver sido configurada para moderação de subscrições', '/some/full/path'], 9 => ['Caminho para a Administração Remota', 'Caminho para a base de dados dos administradores, se a lista tiver sido configurada para administração remota', '/some/full/path'] ); # This list defines most of the context sensitive help in ezmlm-web. What # isn't defined here is the options, which are defined above ... You can # alter these if you feel something else would make more sense to your users # Just be careful of what can fit on a screen! %HELPER = ( # These should be self explainitory addaddress => 'Poderá introduzir um endereço conforme o RFC822, incluindo a parte de comentário. Por exemplo Zacarias Albertino ', addaddressfile => 'ou poderá introduzir o nome de um ficheiro de texto contendo múltiplos endereços RFC822, um por linha', moderator => 'Moderadores: Controlam quem se pode subscrever ou enviar mail para uma lista', deny => 'Deny: Uma lista de endereços que estão explicitamente impedidos de enviar mail para a lista', allow => 'Allow: A list of address that are allowed to mail the list even if the configuration otherwise restricts it', digest => 'Digest: Endereços que recebem o digest de todas as mensagens da lista', webarch => 'Ver o arquivo web desta lista', config => 'Alterar as configurações desta lista', listname => 'Nome da lista. É também o nome do subdirectório que contém a lista', listadd => 'Endereço de e-mail da lista. Por defeito vem da configuração do qmail. Apenas deverá ser alterada a parte local (antes da @)', webusers => 'NB! Por enquanto quaisquer utilizadores especificados deverão existir. A criação de utilizadores será adicionada numa versão futura', prefix => 'Texto a adicionar ao subject de todas as mensagens enviadas', headerremove => 'Lista de headers a remover de todas as mensagens enviadas', headeradd => 'Lista de headers a adicionar a todas as mensagens enviadas', mimeremove => 'Qualquer mensagem cujo "Content-Type" coincida com um destes mime types será devolvida ao remetente', allowedit => 'Lista (separada por vírgulas) dos utilizadores, ou ALL (todos os utilizadores válidos)', domains => 'Aos dominios nesta lista é permitido enviar mail para a mailing list', mysqlcreate => 'Isto permite criar as tabelas de MySQL necessárias se a configuração da lista acima assim o exigir', edit_newsletter => 'Clique para editar e enviar a newsletter associada a esta lista', newsletterhtml => 'Nome do ficheiro html que contém a newsletter', newslettersubject => 'Subject da newsletter', newslettersender => 'Sender da newsletter', newslettertree => 'Localização em disco (ou ftp) do ficheiro que contém a newsletter', newsletterissue => 'Número desta edição da newsletter', ); # This defines the captions of each of the buttons in ezmlm-web, and allows # you to configure them for your own language or taste. Since these are used # by the switching algorithm it is important that every button has a unique # caption - ie we can't have two 'Edit' buttons doing different things. %BUTTON = ( # These MUST all be unique! create => 'Criar', createlist => 'Criar Lista', edit => 'Editar', delete => 'Remover', deleteaddress => 'Remover Endereço', addaddress => 'Adicionar Endereço', moderators => 'Moderadores', denylist => 'Lista "Deny"', allowlist => 'Lista "Allow"', digestsubscribers => 'Subscritores do "Digest"', configuration => 'Configuração', yes => 'Sim', no => 'Não', updateconfiguration => 'Actualizar a Configuração', edittexts => 'Editar Textos', editfile => 'Editar Ficheiro', savefile => 'Guardar Ficheiro', webarchive => 'Arquivo Web', selectlist => 'Seleccionar Lista', subscribers => 'Subscritos', search => 'Procurar', domains => 'Dominios', cancel => 'Cancelar', resetform => 'Reset do Form', edit_newsletter => 'Editar Newsletter', sendnewsletter => 'Enviar Newsletter' ); # This defines the fixed text strings that are used in ezmlm-web. By editing # these along with the button labels and help texts, you can convert ezmlm-web # to another language :-) If anyone gets arround to doing complete templates # for other languages I would appreciate a copy so that I can include it in # future releases of ezmlm-web. %LANGUAGE = ( nop => 'Acção por implementar', chooselistinfo => "

  • Escolha a Lista da caixa à esquerda ou clique em [$BUTTON{'create'}].
  • Clique em [$BUTTON{'edit'}] para editar a Lista seleccionada.
  • Clique em [$BUTTON{'delete'}] para remover a Lista seleccionada.
", confirmdelete => 'Confirme a remoção de', # list name subscribersto => 'Subscritos na', # list name subscribers => 'subscritos', selected => 'seleccionados', additionalparts => 'Configuração da Lista', posting => 'Posting', subscription => 'Subscrição', remoteadmin => 'Administração Remota', for => 'de', # as in; moderators for blahlist createnew => 'Criar uma nova Lista', listname => 'Nome da Lista', listaddress => 'Endereço da Lista', listoptions => 'Opções da Lista', allowedtoedit => 'Utilizadores com acesso para edição desta Lista', editconfiguration => 'Editar a configuração da Lista', prefix => 'Prefixo para os subjects das mensagens', headerremove => 'Headers a excluir de todas as mensagens enviadas', headeradd => 'Headers a incluir em todas as mensagens enviadas', mimeremove => 'Mime types a excluir de todas as mensagens enviadas', edittextinfo => "A caixa à esquerda contém uma lista dos ficheiros disponíveis no directório
DIR/text. Estes ficheiros são enviados nas respostas a certos pedidos (via e-mail) dos utilizadores, ou como parte de todas as mensagens enviadas.

Para editar um ficheiro seleccione o seu nome na caixa, de seguida clique em [$BUTTON{'editfile'}].

Clique em [$BUTTON{'cancel'}] quando tiver terminado a edição.", editingfile => 'A editar o ficheiro', editfileinfo => 'ezmlm-manage
<#l#> O nome da Lista
<#A#> O endereço de subscrição
<#R#> O endereço de resposta para os subscritores

ezmlm-store
<#l#> O nome da Lista
<#A#> O endereço de aceitação
<#R#> O endereço de rejeição', mysqlcreate => 'Criar as tabelas para a base de dados MySQL se necessário', newsletterhtml => 'Conteúdo', newslettersubject => 'Subject', newslettersender => 'Sender', newslettertree => 'Localização', newsletterissue => 'Edição', ); # === Configuration file ends === --bg08WKrSYDhXBjb5--