diff --git a/TODO b/TODO index ece0279..791c360 100644 --- a/TODO +++ b/TODO @@ -1,16 +1,20 @@ -"cancel" button during text editing +ezmlm-idx5: modsub and modpost are ignored, if the flag is not set + +check relevance of "t", "f" and "x" flag for idx5 + +"cancel" button during text editing (simple "reset" input button) restore user input after failed list_create (especially options) support for: - * charset - * show log + * show subscription log + * 'mailinglist' (maybe) + * config directory (maybe) allow dynamic addition of user-made config templates (seperate directory, ...) -language switch support +interface language switch support choose basic/expert to disable questions -export subscribers (oder lieber per Mail (ezmlm)?) +export subscribers -use ezmlm-idx 5.0 text file style diff --git a/ezmlm-web.cgi b/ezmlm-web.cgi index b09cb81..b5f6fab 100755 --- a/ezmlm-web.cgi +++ b/ezmlm-web.cgi @@ -262,6 +262,34 @@ elsif ($action eq '' || $action eq 'list_select') { $pagename = 'list_select'; } } +} elsif ($action eq 'textfile_reset') { + # User wants to remove a customized text file (idx >= 5) ... + if (defined($q->param('list')) && defined($q->param('file'))) { + my $list = Mail::Ezmlm->new($LIST_DIR . '/' . $q->param('list')); + if (! &check_filename($q->param('file'))) { + $error = 'InvalidFileName'; + $pagename = 'textfiles'; + } elsif (Mail::Ezmlm->get_version() < 5) { + $warning = 'RequiresIDX5'; + $pagename = 'textfile_edit'; + } elsif ($list->is_text_default($q->param('file'))) { + $warning = 'ResetFileIsDefault'; + $pagename = 'textfile_edit'; + } elsif ($list->reset_text($q->param('file'))) { + $success = 'ResetFile'; + $pagename = 'textfiles'; + } else { + $warning = 'ResetFile'; + $pagename = 'textfile_edit'; + } + } else { + $error = 'ParameterMissing'; + if ($q->param('list')) { + $pagename = 'textfiles'; + } else { + $pagename = 'list_select'; + } + } } else { $pagename = 'list_select'; $error = 'UnknownAction'; @@ -385,6 +413,20 @@ sub set_pagedata() $pagedata->setValue("Data.Permissions.FileUpload", ($FILE_UPLOAD)? 1 : 0); + # ezmlm-idx v5.0 stuff + $pagedata->setValue('Data.areDefaultTextsAvailable', + (Mail::Ezmlm->get_version() >= 5)? 1 : 0); + + # get available languages for all lists + # no results for ezmlm-idx < 5.0 + my $i = 0; + my $item; + foreach $item (sort Mail::Ezmlm->get_available_languages()) { + $pagedata->setValue("Data.AvailableLanguages." . $i, $item); + $i++; + } + + # display webuser textfield? $pagedata->setValue("Data.WebUser.show", (-e "$WEBUSERS_FILE")? 1 : 0); # default username for webuser file @@ -450,7 +492,7 @@ sub set_pagedata4list $pagedata->setValue("Data.List.MimeRemove", "$item"); $item = $list->getpart('mimereject'); $pagedata->setValue("Data.List.MimeReject", "$item"); - $item = $list->getpart('text/trailer'); + $item = $list->get_text_content('trailer'); $pagedata->setValue("Data.List.TrailingText", "$item"); # read message size limits @@ -472,31 +514,48 @@ sub set_pagedata4list # get the names of the textfiles of this list { - my($listDir); - $listDir = $LIST_DIR . '/' . $q->param('list'); + @files = sort $list->get_available_text_files(); + $i = 0; - # Read the list directory for text ... - if (opendir DIR, "$listDir/text") { - @files = grep !/^\./, readdir DIR; - closedir DIR; - $i = 0; - foreach $item (@files) { - $pagedata->setValue("Data.List.Files." . $i, "$item"); - $i++; + foreach $item (@files) { + if ($list->is_text_default($item)) { + $pagedata->setValue('Data.List.DefaultFiles.' . $i , "$item"); + } else { + $pagedata->setValue('Data.List.CustomizedFiles.' . $i , "$item"); } - } else { - $warning = 'TextDirAccessDenied' if ($warning eq '') + $i++; } # text file specified? if (($q->param('file') ne '') && ($q->param('file') =~ m/^[\w-]*$/)) { my ($content); - $content = $list->getpart("text/" . $q->param('file')); + $content = $list->get_text_content($q->param('file')); from_to($content,$TEXT_ENCODE,'utf8'); # by ooyama for multibyte $pagedata->setValue("Data.List.File.Name", $q->param('file')); $pagedata->setValue("Data.List.File.Content", "$content"); + $pagedata->setValue("Data.List.File.isDefault", + $list->is_text_default($q->param('file')) ? 1 : 0); } } + + # get available languages for this list + # no result for ezmlm-idx < 5 + $i = 0; + foreach $item (sort $list->get_available_languages()) { + $pagedata->setValue("Data.List.AvailableLanguages." . $i, $item); + $i++; + } + + # charset of the list + if (Mail::Ezmlm->get_version() >= 5) { + my $charset = $list->getpart('charset'); + $charset =~ s/^#.*$//m; + $pagedata->setValue('Data.List.CharSet', "$charset") if ($charset); + $pagedata->setValue('Data.useCharSet', "1"); + } + + $pagedata->setValue('Data.List.Language', $list->get_lang()); + &set_pagedata4options($list->getconfig); } @@ -504,9 +563,10 @@ sub set_pagedata4list sub set_pagedata4options { my($options) = shift; - my($i, $key, $state, $value, $dir_of_list); + my($i, $list, $key, $state, $value, $dir_of_list); $dir_of_list = $LIST_DIR . '/' . $q->param('list'); + $list = new Mail::Ezmlm("$LIST_DIR/" . $q->param('list')); $i = 0; $key = lc(substr($options,$i,1)); @@ -519,14 +579,17 @@ sub set_pagedata4options { $key = lc(substr($options,$i,1)); } - # the options "t", "p" and "x" are only used to create a default value - # they have no meaning, so we should adapt them to reality - $pagedata->setValue("Data.List.Options.t" , 1) - if (-e "$dir_of_list/text/trailer"); - $pagedata->setValue("Data.List.Options.f" , 1) - if (-e "$dir_of_list/prefix"); - $pagedata->setValue("Data.List.Options.x" , 1) - if ((-e "$dir_of_list/mimeremove") || (-e "$dir_of_list/mimereject")); + if (Mail::Ezmlm->get_version() < 5) { + # for ezmlm-idx < 5.0 the options "t", "p" and "x" are only + # used to create a default value they have no meaning, so we + # should adapt them to reality + $pagedata->setValue("Data.List.Options.t" , 1) + if (defined($list->get_text_content('trailer'))); + $pagedata->setValue("Data.List.Options.f" , 1) + if (-e "$dir_of_list/prefix"); + $pagedata->setValue("Data.List.Options.x" , 1) + if ((-e "$dir_of_list/mimeremove") || (-e "$dir_of_list/mimereject")); + } for ($i=0; $i<9; $i++) { unless (($i eq 1) || ($i eq 2)) { @@ -720,7 +783,7 @@ sub add_address { my($fh) = $q->param('mailaddressfile'); while (<$fh>) { next if (/^\s*$/ or /^#/); # blank, comments - if ( /(\w[\-\w_\.]*)@(\w[\-\w_\.]+)/ ) { + if ( /(\w[\w\.\!\#\$\%\&\'\`\*\+\-\/\=\?\^\{\|\}\~]*)@(\w[\-\w_\.]+)/) { chomp(); push @addresses, "$_"; } else { @@ -736,7 +799,7 @@ sub add_address { $address .= $DEFAULT_HOST if ($q->param('mailaddress_add') =~ /\@$/); # untaint - if ($address =~ m/(\w[\-\w_\.]*)@(\w[\-\w_\.]+)/) { + if ($address =~ m/(\w[\w\.\!\#\$\%\&\'\`\*\+\-\/\=\?\^\{\|\}\~]*)@(\w[\-\w_\.]+)/) { push @addresses, "$address"; } else { warn "invalid address to add: $address to $part"; @@ -752,7 +815,8 @@ sub add_address { foreach $address (@addresses) { ($add) = Mail::Address->parse($address); - if (($add->address() =~ /^\w[\w_-]*\@/) && !($list->issub($add->address(), $part))) { + if (($add->address() =~ m/^(\w[\w\.\!\#\$\%\&\'\`\*\+\-\/\=\?\^\{\|\}\~]*)@(\w[\-\w_\.]+)$/) + && !($list->issub($add->address(), $part))) { # it seems, that we cannot trust the return value of "$list->sub" $list->sub($add->address(), $part); if(defined($add->name()) && $PRETTY_NAMES) { @@ -892,6 +956,14 @@ sub create_list { return (1==0); } + if (defined($q->param('list_language')) && ($q->param('list_language') ne 'default')) { + if (&check_language($list, $q->param('list_language'))) { + $list->set_lang($q->param('list_language')); + } else { + $warning = 'InvalidListLanguage'; + } + } + # handle MySQL stuff if(defined($q->param('setting_state_6')) && $options =~ m/-6\s+/) { $customWarning = $list->errmsg() unless($list->createsql()); @@ -989,9 +1061,9 @@ sub update_config { # remove old one if the checkbox was not active if (defined($q->param('trailing_text'))) { if (defined($q->param('option_t'))) { - $list->setpart('text/trailer', $q->param('trailing_text')); + $list->set_text_content('trailer', $q->param('trailing_text')); } else { - unlink("$dir_of_list/text/trailer"); + $list->reset_text('trailer'); } } @@ -1042,6 +1114,24 @@ sub update_config { # restore the original value, as ezmlm-make always overrides these values :((( $list->setpart('msgsize', "$old_msgsize"); } + + # update language + if (defined($q->param('list_language'))) { + if (&check_language($list, $q->param('list_language'))) { + $list->set_lang($q->param('list_language')); + } else { + $warning = 'InvalidListLanguage'; + } + } + + # update charset + if (defined($q->param('list_charset'))) { + if ($q->param('list_charset') ne '') { + $list->setpart('charset', $q->param('list_charset')); + } else { + unlink "$list->{'LIST_NAME'}/charset" if (-e "$list->{'LIST_NAME'}/charset"); + } + } unless (&update_webusers()) { $warning = 'WebUsersUpdate'; @@ -1120,7 +1210,7 @@ sub save_text { my ($list) = new Mail::Ezmlm("$LIST_DIR/" . $q->param('list')); my ($content) = $q->param('content'); from_to($content,'utf8',$TEXT_ENCODE); # by ooyama for multibyte - unless ($list->setpart("text/" . $q->param('file'), $content)) { + unless ($list->set_text_content($q->param('file'), $content)) { $warning = 'SaveFile'; return (1==0); } @@ -1198,6 +1288,18 @@ sub webauth_create_allowed { # --------------------------------------------------------------------------- +sub check_language { + my ($list, $lang) = @_; + my $found = 0; + my $item; + foreach $item ($list->get_available_languages()) { + $found++ if ($item eq $q->param('list_language')); + } + return ($found > 0); +} + +# --------------------------------------------------------------------------- + sub rmtree { # A subroutine to recursively delete a directory (like rm -f). # Based on the one in the perl cookbook :) diff --git a/lang/de.hdf b/lang/de.hdf index 2b4b714..eecd36a 100644 --- a/lang/de.hdf +++ b/lang/de.hdf @@ -55,6 +55,7 @@ Lang { UpdateConfiguration = Einstellungen speichern EditFile = Datei bearbeiten SaveFile = Datei speichern + ResetFile = Angepassten Textbaustein verwerfen } @@ -91,6 +92,9 @@ Lang { ReservedListName = Dieser Listenname ist ein reserviertes Wort und kann nicht benutzt werden EmptyListName = Es wurde kein Name für die Listen angegeben. InvalidLocalPart = Die gewählte untergeordnete Liste ist ungültig. + RequiresIDX5 = Diese Aktion erfordert ezmlm-idx in der Version 5.0 oder höher. + ResetFileIsDefault = Dieser Textbaustein ist keine angepasste Variante und kann somit nicht zurückgesetzt werden. + ResetFile = Der angepasste Textbaustein konnte nicht entfernt werden. } @@ -101,6 +105,7 @@ Lang { DeleteList = Die Mailingliste wurde gelöscht. UpdateConfig = Die neuen Einstellungen wurden erfolgreich gespeichert. SaveFile = Die Datei wurde gespeichert. + ResetFile = Der angepasste Textbaustein wurde entfernt. Zukünftig wird stattdessen der systemweite Standard-Baustein verwendet. } @@ -134,7 +139,7 @@ Lang { 0 = Diese Liste is nur eine Unterliste 3 = Definiere die Absender-Adresse ausgehender Mails 4 = Eigene Einstellungen zum Versand von Zusammenfassungsmails (ezmlm-tstdig) - 5 = Lege die Mailadresse des Verantwortlichen für diese Liste fest + 5 = Lege die Mailadresse der/des Verantwortlichen für diese Liste fest 6 = Verwende eine SQL-Datenbank 7 = Die Datenbank der Nachrichten-ModeratorInnen befindet sich in einem alternativen Verzeichnis 8 = Die Datenbank der Einschreibe-ModeratorInnen (und Fern-AdministratorInnen) befindet sich in einem alternativen Verzeichnis @@ -179,6 +184,10 @@ Lang { FooterText = eine Web-Oberfläche für NoListsAvailable = Es sind keine passenden Listen vorhanden. ConfirmDelete = Willst du wirklich diese Liste vollständig löschen? + CustomizedFiles = angepasste Dateien + DefaultFiles = vorgegebene Dateien + ListLanguage = Sprache der Liste + ListCharset = Zeichensatz der Liste } @@ -196,8 +205,9 @@ Lang { DigestList = Einige AbonnentInnen deiner Mailingliste sind möglicherweise nicht an jeder einzelnen Nachricht interessiert, sondern ziehen es vor, stattdessen regelmäßig automatisch erstellte Zusammenfassungen zu erhalten. ModList = ModeratorInnen (für die Einschreibung von AbonnentInnen und die Einsendungen an die Liste) und Fern-AdministratorInnen können die Kontrolle über viele wichtige Aspekte der Liste übernehmen (falls du sie dementsprechend konfigurierst). SubscriberList = Die AbonnentInnen der Mailingliste empfangen alle versandten Nachrigten der Liste. Zudem kann es ihnen gestattet sein, Nachrichten direkt oder indirekt zur weiteren Verteilung an die Liste zu senden. Oft ist es anonymen Nutzern gestattet, sich selbständig in die Mailingliste einzuschreiben, ohne die Hilfe eines Administrators in Anspruch nehmen zu müssen. - TextFiles = Das Auswahlfeld beinhaltet die Liste aller verfügbaren Textbausteine im Texte-Verzeichnis der Liste. Diese Textbasuteine werden zur Erstellung der automatischen Antworten der Mailingliste benutzt. + TextFiles = Das Auswahlfeld beinhaltet die Liste aller verfügbaren Textbausteine im Texte-Verzeichnis der Liste. Diese Textbausteine werden zur Erstellung der automatischen Antworten der Mailingliste benutzt. EditTextFile = Passe den Textbaustein an die Erfordernisse der Liste an. Eventuell möchtest du dafür auch einige der reservierten Platzhalter verwenden, die am Ende dieser Seite aufgeführt sind. + ResetTextFile = Der Textbaustein wurde spezifisch an diese Liste angepasst. Um stattdessen den vorgegebenen Baustein der eingestellten Sprache zu verwenden, kannst du diesen listenspezifischen Baustein entfernen. } Legend { @@ -217,7 +227,8 @@ Lang { MembersDigest = Verwaltung der AbonnentInnen der Zusammenfassungen MembersMod = Verwaltung der ModeratorInnen / AdministratorInnen TextFiles = Verfügbare Textbausteine - TextFileEdit = Bearbeite einen Textbaustein + TextFileEdit = Bearbeite den Textbaustein + TextFileReset = Auf die Vorgabe zurücksetzen TextFileInfo = Nützliche Platzhalter AvailableLists = Verfügbare Listen } diff --git a/lang/en.hdf b/lang/en.hdf index 42926e1..e67ee3b 100644 --- a/lang/en.hdf +++ b/lang/en.hdf @@ -54,7 +54,8 @@ Lang { AddAddress = Add address(es) UpdateConfiguration = Update configuration EditFile = Edit file - SaveFile = Save File + SaveFile = Save file + ResetFile = Remove customized file } @@ -91,6 +92,9 @@ Lang { ReservedListName = This listname may not be used as it is reserved for internal purposes EmptyListName = The name of the list may not be empty InvalidLocalPart = The local part of the list address is not valid + RequiresIDX5 = This action requires ezmlm-idx v5.0 or higher. + ResetFileIsDefault = There is no customized text file, that can be removed. + ResetFile = Removal of custimized text file failed. } @@ -101,6 +105,7 @@ Lang { DeleteList = The mailing list was successfully removed. UpdateConfig = The mailing list's configuration was successfully changed. SaveFile = The file was saved. + ResetFile = The customized text file was successfully removed. From now on, the system-wide default text file will be used instead of it. } @@ -179,6 +184,10 @@ Lang { FooterText = a web interface for NoListsAvailable = I could not find any accessible list for you. ConfirmDelete = Do you really want to remove this list completely? + CustomizedFiles = customized files + DefaultFiles = default files + ListLanguage = Language of the list + ListCharset = Charset of the list } @@ -198,6 +207,7 @@ Lang { SubscriberList = Subscribers of a mailing list will receive all outgoing message of the list. They may also be allowed to post messages directly or moderated. Usually anonymous users are able to subscribe and unsubscribe without the help of an administrator - but of course, you may configure this to suit your needs. TextFiles = The selection box contains a list of files available in the DIR/text directory. These files are sent out in response to specfic user requests or as part of all outgoing messages. Edit them as necessary. EditTextFile = Change this text according to your needs. Maybe you would like to use some of the reserved tags, that are described at the bottom of this page. + ResetTextFile = This text file was customized for this list. If you want to use the system-wide default text file of the choosen language instead, you may remove this customized file. } Legend { @@ -218,6 +228,7 @@ Lang { MembersMod = Manage moderators and administrators TextFiles = Available text files TextFileEdit = Edit content of text file + TextFileReset = Discard customized text TextFileInfo = Useful placeholders AvailableLists = Available lists } diff --git a/spec/hdf-spec.txt b/spec/hdf-spec.txt index fc2f4e6..e18f327 100644 --- a/spec/hdf-spec.txt +++ b/spec/hdf-spec.txt @@ -6,11 +6,15 @@ HelpIconURL Config.Title Data.Action +Data.areDefaultTextsAvailable Data.ErrorMessage Data.List.Address +Data.List.CharSet +Data.List.CustomizedFiles.* +Data.List.DefaultFiles.* Data.List.File.Name Data.List.File.Content -Data.List.Files.* +Data.List.File.isDefault Data.List.hasAllowList Data.List.hasDenyList Data.List.hasDigestList @@ -43,5 +47,6 @@ Data.Modules.MySQL Data.Permissions.Create Data.Permissions.FileUpload Data.UserName +Data.useCharSet Data.WebUser.show Data.WebUser.UserName diff --git a/template/config_all.cs b/template/config_all.cs index 938950d..02c83c6 100644 --- a/template/config_all.cs +++ b/template/config_all.cs @@ -143,6 +143,25 @@ + + 0 ?> +
  • +
  • + + + +
  • + +
  • +
  • diff --git a/template/config_main.cs b/template/config_main.cs index af700f3..6b308b8 100644 --- a/template/config_main.cs +++ b/template/config_main.cs @@ -14,6 +14,25 @@ -
    + - -
    - + + + diff --git a/template/textfile_edit.cs b/template/textfile_edit.cs index 2e183e2..c11bdf8 100644 --- a/template/textfile_edit.cs +++ b/template/textfile_edit.cs @@ -6,6 +6,26 @@ + + + +
    + + +
    + +
    + +
    + + + + +
    +
    + + +
    diff --git a/template/textfiles.cs b/template/textfiles.cs index 255fb0d..2aeae72 100644 --- a/template/textfiles.cs +++ b/template/textfiles.cs @@ -13,18 +13,42 @@