From 848f637cda90b4b511e4fc7d625fa33bb37ad005 Mon Sep 17 00:00:00 2001 From: lars Date: Sun, 25 Dec 2005 15:01:46 +0000 Subject: [PATCH] added a script to check language files README updated fatal error behaviour improved failure behaviour for non-existing listdir changed disable webusers textfield if the file does not exist reduced list per column to 15 --- ezmlm-web-3.0/README | 76 +++++++----- ezmlm-web-3.0/ezmlm-web.cgi | 172 ++++++++++++++------------ ezmlm-web-3.0/htaccess.sample | 10 +- ezmlm-web-3.0/lang/de.hdf | 4 +- ezmlm-web-3.0/lang/en.hdf | 11 +- ezmlm-web-3.0/spec/check_languages.sh | 26 ++++ ezmlm-web-3.0/webusers.sample | 4 +- 7 files changed, 178 insertions(+), 125 deletions(-) create mode 100755 ezmlm-web-3.0/spec/check_languages.sh diff --git a/ezmlm-web-3.0/README b/ezmlm-web-3.0/README index 69f3dd2..fad9033 100644 --- a/ezmlm-web-3.0/README +++ b/ezmlm-web-3.0/README @@ -123,40 +123,53 @@ ezmlm-web v3.0) from http://clearsilver.net. IV. Files ========= -In this distribution you should find eight files; +In this distribution you should find the following files; -README This file. Provides some background information. - Not needed to run ezmlm-web. +README (optional) This file. Provides some background information. -INSTALL Notes on installation. Not needed to run ezmlm-web. +INSTALL (optional) Notes on installation. -CHANGES The change history. Not needed to run ezmlm-web +INSTALL.clearsilver (optional) Notes on the installation of clearsilver. -TODO This file is a list of things I intend doing in future - versions of ezmlm-web. Not needed to run ezmlm-web. +CHANGES (optional) The change history. -ezmlm-web.cgi The ezmlm-web script proper. This program requires that - you have perl5 installed on your machine and that your web - server is capable of running CGI scripts. +UPGRADING (optional) Notes on upgrading ezmlm-web from a previous version. -index.c A C wrapper to allow ezmlm-web.cgi to run suid. Not - strictly necessary if your setup allows perl scripts to - run suid, but I prefer using wrappers anyway. It needs to - be edited and compiled to suit your system. Not needed to - run ezmlm-web. +TODO (optional) This file is a list of things I intend doing in future + versions of ezmlm-web. -ezmlmwebrc This is the configuration file for ezmlm-web. All options - are explained in this example file. You will need this - file to run ezmlm-web. +ezmlm-web.cgi (required) The ezmlm-web cgi script in perl. You will need it :) -htaccess.sample A sample Apache .htaccess file for controlling access to - the mailing lists. If you use another web server, you will - have to work this bit out for yourself. +index.c (recommended) A C wrapper to allow ezmlm-web.cgi to run + suid. Not strictly necessary if your setup allows perl scripts + to run suid, but I prefer using wrappers anyway. It needs to + be edited and compiled to suit your system. Not needed to + run ezmlm-web. -webusers.sample A sample webusers file for multi-level access control. +ezmlmwebrc (required) This is the configuration file for ezmlm-web. + All options are explained in this example file. You will need + this file to run ezmlm-web. -The directory "lang" contains the language files. You will need at least the -one, that you have choosen in "ezmlmwebrc" by the option "HTML_LANGUAGE". +htaccess.sample (recommended) A sample Apache .htaccess file for controlling access to + the mailing lists. If you use another web server, you will + have to work this bit out for yourself. + +webusers.sample (recommended) A sample webusers file for multi-level access control. + +lang (directory, required) It contains the language files. You will need + at least the one, that you have choosen in "ezmlmwebrc" by + the option "HTML_LANGUAGE". + +css (directory, recommended) Here you find available css stylesheet files. + Pick the one you like (for now, there is only one choice :)) and + set it up by pointing the "HTML_CSS_FILE" setting in your + "ezmlmwebrc" to an appropriate URL. + +template (directory, required) The clearsilver template files in this + directory defined the layout of the web interface. You should be able + to adapt them to your needs, if you like. + +spec (directory, optional) Some development specific information. V. Notes @@ -188,30 +201,27 @@ of constraints come into place. - The webusers file is scanned for either the list name (case insensitive) or an ALL (case sensitive) entry. - The list entry (or ALL) is scanned for the current user (as set in - $REMOTE_USER) or an ALL entry. + $REMOTE_USER) or an ALL (user) entry. - If any valid match is made, then the user is allowed to edit the list. Otherwise the user is politely told to go away ;-) If list creation is allowed and the webusers file exists, then the person who -creates the list is the default owner. As of yet there is no way to create users -through the web interface, but I intend to do this eventually. +creates the list is the default owner. There is no way to create users +through the web interface, as this depends on your authentication system. The format of a webusers file is as follows; -list1: user1, user2, user3 -ALL: user1, user2 +list1: user1 user2 user3 +ALL: user1 user2 list2: ALL -ie; listname colon (:) and a comma (,) separated list of users. Spaces are -ignored but each list must appear on a new line. - Once this file exists, the ezmlm-web script will allow the list users to configure their access lists along with any other options. You can permit some users to create lists by adding a line similar to the following to your webusers file: -ALLOW_CREATE: user2, user3 +ALLOW_CREATE: user2 user3 If there is no line starting with "ALLOW_CREATE:" in the webusers file, then no one will be allowed to create lists. This behaviour is new for ezmlm-web diff --git a/ezmlm-web-3.0/ezmlm-web.cgi b/ezmlm-web-3.0/ezmlm-web.cgi index a8dbcb4..b09cb81 100755 --- a/ezmlm-web-3.0/ezmlm-web.cgi +++ b/ezmlm-web-3.0/ezmlm-web.cgi @@ -96,7 +96,7 @@ if(defined($opt_C)) { } elsif(-e "/etc/ezmlm/ezmlmwebrc") { require "/etc/ezmlm/ezmlmwebrc"; # System } else { - die "Unable to read config file"; + &fatal_error("Unable to read config file"); } # Allow suid wrapper to over-ride default list directory ... @@ -119,7 +119,7 @@ if (defined($MAIL_DOMAIN) && ($MAIL_DOMAIN ne '')) { $DEFAULT_HOST = $MAIL_DOMAIN; } else { # Work out default domain name from qmail (for David Summers) - open (GETHOST, "<$QMAIL_BASE/defaultdomain") || open (GETHOST, "<$QMAIL_BASE/me") || die "Unable to read $QMAIL_BASE/me: $!"; + open (GETHOST, "<$QMAIL_BASE/defaultdomain") || open (GETHOST, "<$QMAIL_BASE/me") || &fatal_error("Unable to read $QMAIL_BASE/me: $!"); chomp($DEFAULT_HOST = ); close GETHOST; } @@ -267,9 +267,15 @@ elsif ($action eq '' || $action eq 'list_select') { $error = 'UnknownAction'; } -# read the current state +# read the current state (after the changes are done) &set_pagedata(); +# set default action, if there is no list available and the user is +# allowed to create a new one +if (($action eq '') && (&webauth_create_allowed()) && ($pagedata->getValue('Data.Lists.0','') eq '')) { + $pagename = 'list_create'; +} + # Print page and exit :) ... &output_page; exit; @@ -284,7 +290,9 @@ sub load_hdf { $hdf->readFile($LANGUAGE_DIR . '/' . $HTML_LANGUAGE . '.hdf'); # TODO: check for existence + &fatal_error("Template dir ($TEMPLATE_DIR) not found!") unless (-e $TEMPLATE_DIR); $hdf->setValue("TemplateDir", "$TEMPLATE_DIR/"); + &fatal_error("Language data dir ($LANGUAGE_DIR) not found!") unless (-e $LANGUAGE_DIR); $hdf->setValue("LanguageDir", "$LANGUAGE_DIR/"); $hdf->setValue("ScriptName", $ENV{'SCRIPT_NAME'}); $hdf->setValue("Stylesheet", "$HTML_CSS_FILE"); @@ -306,8 +314,8 @@ sub output_page { $pagedata->setValue('Data.Action', "$pagename"); my $pagefile = $TEMPLATE_DIR . "/main.cs"; - die "main template ($pagefile) not found!" unless (-e "$pagefile"); - die "sub template ($TEMPLATE_DIR/$pagename.cs) not found!" unless (-e "$TEMPLATE_DIR/$pagename.cs"); + &fatal_error("main template ($pagefile) not found!") unless (-e "$pagefile"); + &fatal_error("sub template ($TEMPLATE_DIR/$pagename.cs) not found!") unless (-e "$TEMPLATE_DIR/$pagename.cs"); # print http header print "Content-Type: text/html; charset=utf-8\n\n"; @@ -319,80 +327,86 @@ sub output_page { print $cs->render(); } +# --------------------------------------------------------------------------- + +sub set_pagedata_list_of_lists() +{ + my (@files, $i, $num); + + # Read the list directory for mailing lists. + return (0==0) unless (opendir DIR, $LIST_DIR); + + @files = sort grep !/^\./, readdir DIR; + closedir DIR; + + $num = 0; + # Check that they actually are lists and add good ones to pagedata ... + foreach $i (0 .. $#files) { + if ((-e "$LIST_DIR/$files[$i]/lock") && (&webauth($files[$i]))) { + $pagedata->setValue("Data.Lists." . $num, "$files[$i]"); + $num++; + } + } +} + +# --------------------------------------------------------------------------- sub set_pagedata() { - my (@lists, @files, $i, $item); + my ($hostname, $username); - # Read the list directory for mailing lists. - unless (opendir DIR, $LIST_DIR) { - $warning = 'ListDirAccessDenied'; - return (1==0); + # read available list of lists + &set_pagedata_list_of_lists(); + + # username and hostname + # 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; } - - @files = sort grep !/^\./, readdir DIR; - closedir DIR; - - # Check that they actually are lists and add good ones to pagedata ... - my $num = 0; - foreach $i (0 .. $#files) { - if ((-e "$LIST_DIR/$files[$i]/lock") && (&webauth($files[$i]))) { - $pagedata->setValue("Data.Lists." . $num, "$files[$i]"); - $num++; - } - } - - # list specific configuration - if ($q->param('list') ne '' ) - { - &set_pagedata4list(&get_list_part()); - } else { - &set_pagedata4options($DEFAULT_OPTIONS); - } + if(!defined($hostname)) { + $username = "$USER-" if ($USER ne $ALIAS_USER); + $hostname = $DEFAULT_HOST; + } + $pagedata->setValue("Data.UserName", "$username"); + $pagedata->setValue("Data.HostName", "$hostname"); - # username and hostname - my ($hostname, $username); - # 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; - } - - $pagedata->setValue("Data.UserName", "$username"); - $pagedata->setValue("Data.HostName", "$hostname"); - - - # modules - # TODO: someone should test, if the mysql support works - $pagedata->setValue("Data.Modules.MySQL", ($Mail::Ezmlm::MYSQL_BASE)? 1 : 0); + # modules + # TODO: someone should test, if the mysql support works + $pagedata->setValue("Data.Modules.MySQL", ($Mail::Ezmlm::MYSQL_BASE)? 1 : 0); - # permissions - $pagedata->setValue("Data.Permissions.Create", (&webauth_create_allowed)? 1 : 0 ); - $pagedata->setValue("Data.Permissions.FileUpload", ($FILE_UPLOAD)? 1 : 0); + # permissions + $pagedata->setValue("Data.Permissions.Create", (&webauth_create_allowed)? 1 : 0 ); + $pagedata->setValue("Data.Permissions.FileUpload", ($FILE_UPLOAD)? 1 : 0); - # display webuser textfield? - $pagedata->setValue("Data.WebUser.show", (-e "$WEBUSERS_FILE")? 1 : 0); - # default username for webuser file - $pagedata->setValue("Data.WebUser.UserName", $ENV{'REMOTE_USER'}||'ALL'); + # display webuser textfield? + $pagedata->setValue("Data.WebUser.show", (-e "$WEBUSERS_FILE")? 1 : 0); + # default username for webuser file + $pagedata->setValue("Data.WebUser.UserName", $ENV{'REMOTE_USER'}||'ALL'); + + # list specific configuration + if ($q->param('list') ne '' ) + { + &set_pagedata4list(&get_list_part()); + } else { + &set_pagedata4options($DEFAULT_OPTIONS); + } } +# --------------------------------------------------------------------------- sub set_pagedata4list { my $part_type = shift; my ($list, $listname, $webusers); my ($i, $item, @files); + my ($address, $addr_name, %pretty); $listname = $q->param('list'); @@ -406,14 +420,11 @@ sub set_pagedata4list $pagedata->setValue("Data.List.Name", "$listname"); $pagedata->setValue("Data.List.Address", &this_listaddress); + &set_pagedata4part_list($part_type) if ($part_type ne ''); $i = 0; - my $address; - my $addr_name; - my %pretty; tie %pretty, "DB_File", "$LIST_DIR/$listname/webnames" if ($PRETTY_NAMES); - # TODO: use "pretty" output style for visible mail address foreach $address (sort $list->subscribers($part_type)) { if ($address ne '') { $pagedata->setValue("Data.List.Subscribers." . $i . '.address', "$address"); @@ -468,20 +479,17 @@ sub set_pagedata4list if (opendir DIR, "$listDir/text") { @files = grep !/^\./, readdir DIR; closedir DIR; + $i = 0; + foreach $item (@files) { + $pagedata->setValue("Data.List.Files." . $i, "$item"); + $i++; + } } else { $warning = 'TextDirAccessDenied' if ($warning eq '') } - $i = 0; - my $item; - foreach $item (@files) { - $pagedata->setValue("Data.List.Files." . $i, "$item"); - $i++; - } - # text file specified? - if ($q->param('file') ne '') - { + if (($q->param('file') ne '') && ($q->param('file') =~ m/^[\w-]*$/)) { my ($content); $content = $list->getpart("text/" . $q->param('file')); from_to($content,$TEXT_ENCODE,'utf8'); # by ooyama for multibyte @@ -623,7 +631,7 @@ sub delete_list { $warning = 'UnsafeRemoveListDirFailed'; return (1==0); } - opendir(DIR, "$HOME_DIR") or die "Unable to get directory listing: $!"; + opendir(DIR, "$HOME_DIR") or &fatal_error("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) { @@ -832,7 +840,7 @@ sub create_list { # Check if the list directory exists and create if necessary ... unless ((-e $LIST_DIR) || (mkdir $LIST_DIR, 0700)) { warn "Unable to create directory ($LIST_DIR): $!"; - $error = 'ListDirUnavailable'; + $warning = 'ListDirAccessDenied'; return (1==0); } @@ -1111,7 +1119,6 @@ sub save_text { my ($list) = new Mail::Ezmlm("$LIST_DIR/" . $q->param('list')); my ($content) = $q->param('content'); - # TODO: is "utf8" instead of "utf-8" correct? from_to($content,'utf8',$TEXT_ENCODE); # by ooyama for multibyte unless ($list->setpart("text/" . $q->param('file'), $content)) { $warning = 'SaveFile'; @@ -1211,6 +1218,19 @@ sub rmtree { # ------------------------------------------------------------------------ +sub fatal_error() { + my $text = shift; + + print "Content-Type: text/html; charset=utf-8\n\n"; + print "\n"; + print "ezmlm-web\n"; + print "

a fatal error occoured!

\n"; + print "

$text

\n"; + print "

check the error log of your web server for details

\n"; + print "\n"; + die "$text"; +} + # ------------------------------------------------------------------------ # End of ezmlm-web.cgi v2.3 # ------------------------------------------------------------------------ diff --git a/ezmlm-web-3.0/htaccess.sample b/ezmlm-web-3.0/htaccess.sample index b381a14..0599b5b 100644 --- a/ezmlm-web-3.0/htaccess.sample +++ b/ezmlm-web-3.0/htaccess.sample @@ -1,9 +1,7 @@ -#$Id: htaccess.sample,v 1.1 2000/01/29 11:35:40 guy Exp $ -# #order deny,allow #deny from all #allow from .ru.ac.za -AuthName "EZ Mailing List Manager -AuthType Basic -AuthUserFile /etc/ezmlm/.htusers -require valid-user +AuthName "EZ Mailing List Manager" +AuthType Basic +AuthUserFile /etc/ezmlm/.htusers +require valid-user diff --git a/ezmlm-web-3.0/lang/de.hdf b/ezmlm-web-3.0/lang/de.hdf index 702202c..2b4b714 100644 --- a/ezmlm-web-3.0/lang/de.hdf +++ b/ezmlm-web-3.0/lang/de.hdf @@ -61,8 +61,7 @@ Lang { ErrorMessage { UnknownAction = Diese Aktion ist undefiniert! ParameterMissing = Diese Aktion benätigt weitere Parameter! - Forbidden = Fehler: dir fehlen die notwendigen Rechte für diese Aktion - ListDirUnavailable = Fehler beim Zugriff auf das Hauptverzeichnis der Listen! + Forbidden = Fehler: dir fehlen die notwendigen Rechte für diese Aktion InvalidFileName = Der Dateiname ist nicht zulässig. UnknownConfigPage = Die gähle Konfigurations-Seite existiert nicht! } @@ -166,6 +165,7 @@ Lang { AcceptanceAddress = die Zustimmungsadresse RejectionAddress = die Ablehnungsadresse } + SuggestDefaultPath = Ansonsten musst du diese Mitglieder per Hand verwalten. PostModPathWarn = Die Nachrichten-ModeratorInnen werden nicht an ihrem üblichen Ort gespeichert. SubModPathWarn = Die Einschreibe-ModeratorInnen werden nicht an ihrem üblichen Ort gespeichert. RemoteAdminPathWarn = Die Fern-AdministratorInnen werden nicht an ihrem üblichen Ort gespeichert. diff --git a/ezmlm-web-3.0/lang/en.hdf b/ezmlm-web-3.0/lang/en.hdf index 2479982..42926e1 100644 --- a/ezmlm-web-3.0/lang/en.hdf +++ b/ezmlm-web-3.0/lang/en.hdf @@ -61,8 +61,7 @@ Lang { ErrorMessage { UnknownAction = this action is undefined ParameterMissing = this action needs one or more parameters - Forbidden = Error: you are not allowed to do this! - ListDirUnavailable = Could not create the list directory! + Forbidden = Error: you are not allowed to do this! InvalidFileName = The name of the file is invalid! UnknownConfigPage = The chosen config page is invalid! } @@ -78,9 +77,9 @@ Lang { ListNameAlreadyExists = There is already a list with this name! ListAddressAlreadyExists = There is already a list with this address! ListDoesNotExist = A list with this name does not exist! - ListDirAccessDenied = Unable to access the list's directory: - TextDirAccessDenied = Unable to access the list's directory of text files: - SafeRemoveRenameDirFailed = Unable to rename list for safe removal: + ListDirAccessDenied = Unable to access the list's directory + TextDirAccessDenied = Unable to access the list's directory of text files + SafeRemoveRenameDirFailed = Unable to rename list for safe removal DotQmailDirAccessDenied = Unable to read the mail user's home directory for .qmail files SafeRemoveMoveDotQmailFailed = Unable to move .qmail files UnsafeRemoveListDirFailed = Unable to delete list @@ -152,7 +151,7 @@ Lang { ListAddress = List Address ListOptions = Basic List Options AllowedToEdit = Users allowed to edit this list via web interface: - HeaderRemove = Headers to strip from all outgoing mail + HeaderRemove = Headers to strip from every outgoing mail HeaderAdd = Headers to add to all outgoing mail MimeRemove = Mime types to strip from all outgoing mail MimeReject = Messages containing any of these mime type will be rejected diff --git a/ezmlm-web-3.0/spec/check_languages.sh b/ezmlm-web-3.0/spec/check_languages.sh new file mode 100755 index 0000000..502dbe9 --- /dev/null +++ b/ezmlm-web-3.0/spec/check_languages.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# +# compare the defined fields of a language file with the english translation +# +# nice for finding unavailable definitions +# +# Parameter: LANGUAGE +# (e.g. "de") +# + +set -u + +LANG_DIR=$(dirname $0)/../lang +DEFAULT_LANG=en +TMP_FILE1=/tmp/$(basename $0)-$$-1 +TMP_FILE2=/tmp/$(basename $0)-$$-2 + +[ $# -ne 1 ] && echo -e "Syntax: $(basename $0) LANGUAGE\n" >&2 && exit 1 + +grep "=" "$LANG_DIR/${DEFAULT_LANG}.hdf" | grep -v "^[[:space:]]*#" | cut -f 1 -d "=" >"$TMP_FILE1" +grep "=" "$LANG_DIR/${1}.hdf" | grep -v "^[[:space:]]*#" | cut -f 1 -d "=" >"$TMP_FILE2" + +diff -wu "$TMP_FILE1" "$TMP_FILE2" + +rm "$TMP_FILE1" "$TMP_FILE2" + diff --git a/ezmlm-web-3.0/webusers.sample b/ezmlm-web-3.0/webusers.sample index b89278f..268caa8 100644 --- a/ezmlm-web-3.0/webusers.sample +++ b/ezmlm-web-3.0/webusers.sample @@ -1,5 +1,5 @@ -comm: guy, arb +comm: guy arb users: arb members: ALL ALL: root -ALLOW_CREATE: root, guy +ALLOW_CREATE: root guy