Compare commits

..

No commits in common. 'lang_de' and 'main' have entirely different histories.

  1. 4
      Dockerfile
  2. 2
      pom.xml
  3. 10
      src/main/java/de/srsoftware/widerhall/mail/SmtpClient.java
  4. 50
      src/main/java/de/srsoftware/widerhall/web/Web.java
  5. 129
      src/main/resources/Application.de.translation
  6. 10
      src/test/java/de/srsoftware/widerhall/data/ListMemberTest.java
  7. 2
      static/templates/add_list.st
  8. 22
      static/templates/archive.st
  9. 16
      static/templates/confirmation_mail.st
  10. 2
      static/templates/css.st
  11. 2
      static/templates/edit_list.st
  12. 6
      static/templates/footer.st
  13. 33
      static/templates/frontpage.st
  14. 2
      static/templates/index.st
  15. 40
      static/templates/inspect.st
  16. 43
      static/templates/js.st
  17. 24
      static/templates/list_data_form.st
  18. 14
      static/templates/listadminlist.st
  19. 12
      static/templates/listlist.st
  20. 8
      static/templates/listmembers.st
  21. 10
      static/templates/login.st
  22. 2
      static/templates/navigation.st
  23. 16
      static/templates/new_password_form.st
  24. 10
      static/templates/post.st
  25. 14
      static/templates/register.st
  26. 13
      static/templates/reset-pw.st
  27. 9
      static/templates/reset_link_sent.st
  28. 22
      static/templates/subscribe.st
  29. 8
      static/templates/subscribe_mail.st
  30. 10
      static/templates/unsubscribe.st
  31. 2
      static/templates/userinfo.st
  32. 14
      static/templates/userlist.st

4
Dockerfile

@ -3,10 +3,8 @@ MAINTAINER Stephan Richter <s.richter@srsoftware.de> @@ -3,10 +3,8 @@ MAINTAINER Stephan Richter <s.richter@srsoftware.de>
RUN apk add --no-cache --update bash git maven openjdk17
ENV LC_ALL de_DE.UTF-8
# get the sources
RUN git clone https://git.srsoftware.de/StephanRichter/Widerhall.git -b lang_de
RUN git clone https://git.srsoftware.de/StephanRichter/Widerhall.git
WORKDIR Widerhall
# compile

2
pom.xml

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
<groupId>org.example</groupId>
<artifactId>Widerhall</artifactId>
<version>1.0.5</version>
<version>1.0.4</version>
<build>
<plugins>
<plugin>

10
src/main/java/de/srsoftware/widerhall/mail/SmtpClient.java

@ -41,21 +41,21 @@ public class SmtpClient { @@ -41,21 +41,21 @@ public class SmtpClient {
if (session == null) login();
MimeMessage forward = new MimeMessage(session);
var oldSender = message.getFrom()[0].toString();
{ // drop old (von ... comment)
var pos = subject.indexOf(" (von ");
{ // drop old (from ... comment)
var pos = subject.indexOf(" (from ");
while (pos > 0){
var end = subject.indexOf(')',pos);
if (end < pos) break;
subject = (subject.substring(0,pos)+subject.substring(end+1)).trim();
pos = subject.indexOf(" (von ");
pos = subject.indexOf(" (from ");
}
}
if (newSender != null){
forward.setFrom(newSender);
forward.setSubject(subject+" (von "+oldSender+")","utf-8");
forward.setSubject(subject+" (from "+oldSender+")");
} else {
forward.setFrom(oldSender);
forward.setSubject(subject,"utf-8");
forward.setSubject(subject);
}
if (replyTo != null) forward.setReplyTo(InternetAddress.parse(replyTo));
var recipientType = bcc ? Message.RecipientType.BCC : Message.RecipientType.TO;

50
src/main/java/de/srsoftware/widerhall/web/Web.java

@ -88,7 +88,7 @@ public class Web extends TemplateServlet { @@ -88,7 +88,7 @@ public class Web extends TemplateServlet {
data.put(SMTP_PORT, smtpPort);
if (name == null || name.isBlank() || email == null || email.isBlank()) {
data.put(ERROR, t("List name and address are required!"));
data.put(ERROR, "List name and address are required!");
return loadTemplate(ADD_LIST, data, resp);
}
@ -98,7 +98,7 @@ public class Web extends TemplateServlet { @@ -98,7 +98,7 @@ public class Web extends TemplateServlet {
}
if (imapHost == null || imapHost.isBlank() || imapUser == null || imapUser.isBlank() || imapPass == null || imapPass.isBlank()) {
data.put(ERROR, t("IMAP credentials are required!"));
data.put(ERROR, "IMAP credentials are required!");
return loadTemplate(ADD_LIST, data, resp);
}
@ -112,7 +112,7 @@ public class Web extends TemplateServlet { @@ -112,7 +112,7 @@ public class Web extends TemplateServlet {
}
if (smtpHost == null || smtpHost.isBlank() || smtpUser == null || smtpUser.isBlank() || smtpPass == null || smtpPass.isBlank()) {
data.put(ERROR, t("SMTP credentials are required!"));
data.put(ERROR, "SMTP credentials are required!");
return loadTemplate(ADD_LIST, data, resp);
}
@ -159,7 +159,7 @@ public class Web extends TemplateServlet { @@ -159,7 +159,7 @@ public class Web extends TemplateServlet {
if (listMember != null) {
listMember.sendConfirmationMail(getTemplate("confirmation_mail"));
return loadTemplate(INDEX,Map.of(USER,listMember.user().safeMap(),NOTES,t("Confirmed list subscription!")),resp);
return loadTemplate(INDEX,Map.of(USER,listMember.user().safeMap(),NOTES,"Confirmed list subscription!"),resp);
}
return t("Unknown user or token!");
} catch (Exception e) {
@ -222,7 +222,7 @@ public class Web extends TemplateServlet { @@ -222,7 +222,7 @@ public class Web extends TemplateServlet {
data.put(SMTP_PORT, smtpPort);
if (name == null || name.isBlank() || email == null || email.isBlank()) {
data.put(ERROR, t("List name and address are required!"));
data.put(ERROR, "List name and address are required!");
return loadTemplate(EDIT_LIST, data, resp);
}
@ -232,7 +232,7 @@ public class Web extends TemplateServlet { @@ -232,7 +232,7 @@ public class Web extends TemplateServlet {
}
if (imapHost == null || imapHost.isBlank() || imapUser == null || imapUser.isBlank() || imapPass == null || imapPass.isBlank()) {
data.put(ERROR, t("IMAP credentials are required!"));
data.put(ERROR, "IMAP credentials are required!");
return loadTemplate(EDIT_LIST, data, resp);
}
@ -246,7 +246,7 @@ public class Web extends TemplateServlet { @@ -246,7 +246,7 @@ public class Web extends TemplateServlet {
}
if (smtpHost == null || smtpHost.isBlank() || smtpUser == null || smtpUser.isBlank() || smtpPass == null || smtpPass.isBlank()) {
data.put(ERROR, t("SMTP credentials are required!"));
data.put(ERROR, "SMTP credentials are required!");
return loadTemplate(EDIT_LIST, data, resp);
}
@ -261,7 +261,7 @@ public class Web extends TemplateServlet { @@ -261,7 +261,7 @@ public class Web extends TemplateServlet {
list.update(name,email,imapHost,imapPort,imapUser,imapPass,inbox,smtpHost,smtpPort,smtpUser,smtpPass);
return loadTemplate(ADMIN,data,resp);
} catch (SQLException e) {
LOG.warn("Editing list {} by {} failed!",list.email(),user.email(),e);
LOG.warn("Editing list {} by {} failed",list.email(),user.email(),e);
return t("Editing list {} by {} failed!",list.email(),user.email());
}
}
@ -306,18 +306,18 @@ public class Web extends TemplateServlet { @@ -306,18 +306,18 @@ public class Web extends TemplateServlet {
var pass = req.getParameter(PASSWORD);
var repeat = req.getParameter(PASSWORD_REPEAT);
if (pass == null || pass.isBlank()) {
data.put(ERROR, t("Please set a password!"));
data.put(ERROR, "Please set a password!");
} else if (!pass.equals(repeat)) {
data.put(ERROR, t("Passwords do not match!"));
data.put(ERROR, "Passwords do not match");
} else if (Util.simplePassword(pass)) {
data.put(ERROR, t("Your password is to simple!"));
data.put(ERROR, "Your password is to simple");
} else {
try {
user.setPassword(pass);
data.put(NOTES,t("Your password has been updated!"));
data.put(NOTES,"Your password has been updated!");
return loadTemplate(ADMIN,data,resp);
} catch (SQLException e) {
data.put(ERROR,t("Failed to update password in database!"));
data.put(ERROR,t("Failed to update password in database: {}",e.getMessage()));
}
}
}
@ -376,12 +376,12 @@ public class Web extends TemplateServlet { @@ -376,12 +376,12 @@ public class Web extends TemplateServlet {
if (token != null){
try {
user = User.byToken(req.getParameter(TOKEN));
if (user == null) return loadTemplate(path,Map.of(ERROR,t("Failed to find user for token!")),resp);
if (user == null) return loadTemplate(path,Map.of(ERROR,"Failed to find user for token!"),resp);
user.dropPasswordToken();
req.getSession().setAttribute("user",user);
return redirectTo(NEW_PASSWORD_FORM,resp);
} catch (SQLException sqle){
return loadTemplate(path,Map.of(ERROR,t("Failed to add user for token!")),resp);
return loadTemplate(path,Map.of(ERROR,"Failed to add user for token!"),resp);
}
}
var email = req.getParameter(EMAIL);
@ -462,7 +462,7 @@ public class Web extends TemplateServlet { @@ -462,7 +462,7 @@ public class Web extends TemplateServlet {
private String post(HttpServletRequest req, HttpServletResponse resp) {
var id = req.getParameter(ID);
if (id == null) return t("Could not find email: missing id!");
if (id == null) return t("Could not find email with id!");
try {
var post = Post.load(id);
var map = new HashMap<String,Object>();
@ -527,25 +527,19 @@ public class Web extends TemplateServlet { @@ -527,25 +527,19 @@ public class Web extends TemplateServlet {
if (user != null) {
MailingList list = ListMember.listsOf(user).stream().map(ListMember::list).filter(ml -> ml.hasState(STATE_ENABLED)).findAny().orElse(null);
if (list == null) list = MailingList.listActive().stream().findAny().orElse(null);
if (list == null) throw new NullPointerException(t("no active List found!"));
if (list == null) throw new NullPointerException("no active List found!");
String token = user.generateToken();
var host = Arrays.stream(req.getRequestURL().toString().split("/")).filter(s -> !s.isEmpty() && !s.startsWith("http")).findFirst().orElse("unknwon host");
var link = req.getRequestURL().toString()+"?token="+token;
var subject = t("Reset your password at {}",host);
var text = t("Somebody asked to reset your account password at {}.",host)+
"\n\n"+
t("If that was you, please open the following link in your web browser:")
+"\n\n"
+link+
"\n\n"+
t("If you did not expect this email, please ignore it.");
var text = t("Somebody asked to reset your account password at {}.\n\nIf that was you, please open the following link in your web browser:\n\n{}\n\nIf you did not expect this email, please ignore it.",host,link);
list.sendPasswordReset(email,subject,text);
return loadTemplate("reset_link_sent",null,resp);
}
} catch (Exception e){
return loadTemplate(Util.getPath(req),Map.of(EMAIL,email,ERROR,t("Failed to send reset email:")+e.getMessage()),resp);
return loadTemplate(Util.getPath(req),Map.of(EMAIL,email,ERROR,"Failed to send reset email: "+e.getMessage()),resp);
}
return null;
}
@ -563,12 +557,12 @@ public class Web extends TemplateServlet { @@ -563,12 +557,12 @@ public class Web extends TemplateServlet {
if (list == null){
data.put(ERROR,t("No list provided by form data!"));
data.put(ERROR,"No list provided by form data!");
return loadTemplate(SUBSCRIBE,data,resp);
}
if (name == null || name.isBlank() || email == null || email.isBlank()){
data.put(ERROR,t("Name and email are required fields for list subscription!"));
data.put(ERROR,"Name and email are required fields for list subscription!");
return loadTemplate(SUBSCRIBE,data,resp);
}
if (pass != null && pass.isBlank()) pass = null;
@ -669,7 +663,7 @@ public class Web extends TemplateServlet { @@ -669,7 +663,7 @@ public class Web extends TemplateServlet {
return loadTemplate(INDEX,data,resp);
} catch (SQLException e) {
LOG.warn("Problem during unscubsription of {} from {}:",user.email(),list.email(),e);
data.put(ERROR,t("Failed to unsubscribe!"));
data.put(ERROR,"Failed to unsubscribe!");
return loadTemplate(UNSUBSCRIBE,data,resp);
}
}

129
src/main/resources/Application.de.translation

@ -1,129 +0,0 @@ @@ -1,129 +0,0 @@
[{}] Please confirm your list subscription : [{}] Bitte bestätigen Sie Ihr Listen-Abonnement
[{}] Subscription complete! : [{}] Abonnement abgeschlossen!
[{}]\: test mail : [{}] Test-Mail
'{}' already in database, but with different password! : '{}' gibt es schon in der Datenbank, hat dort aber ein anderes Passwort!
{} is no member of {} : {} ist nicht Mitglied von {}!
{} is not a member of {} : {} ist nicht Mitglied von {}!
'{}' is not a proper port number! : '{}' ist keine gültige Port-Nummer!
'{}' is not a valid email address! : '{}' ist keine gültige Mailadresse!
{} is now a moderator of {} : {} ist nun ein Moderator der Liste {}
archive : Archiv
awaiting confirmation : erwartet Bestätigung
Confirmation of list membership failed! : Bestätigung des Listen-Abonnements fehlgeschlagen!
Confirmed list subscription! : Listen-Mitgliedschaft bestätigt!
Could not find email: missing id! : Konnte Email nicht finden: ID fehlt!
enabled : aktiviert
disabled : deaktiviert
Editing list {} by {} failed! : Bearbeiten der Liste {} durch {} fehlgeschlagen!
Email is required for list un-subscription! : Für das Abbestellen ist eine E-Mail-Adresse erforderlich!
Error reading user database! : Fehler beim Lesen der Nutzer-Datenbank!
Failed to access user database\: {} : Fehler beim Zugriff auf die Nutzer-Datenbank: {}
Failed to create list '{}'\: {} : Erzeugen der Liste '{}' fehlgeschlagen: {}
Failed to create new user\: {} : Erzeugen des neuen Nutzers fehlgeschlagen: {}
Failed to find user for token! : Konnte keinen Nutzer zum Token finden!
Failed to handle request\: {} : Konnte Anfrage nicht verarbeiten: {}
Failed to load file '{}'! : Laden der Datei '{}' fehlgeschlagen!
Failed to load list member for {}/{} : Laden der Mitgliedschaft zu {}/{} fehlgeschlagen!
Failed to load member list '{}' : Laden der Mitglieder-Liste von '{}' fehlgeschlagen!
Failed to load post from file! : Laden der Nachricht aus Datei fehlgeschlagen!
Failed to load template '{}' : Laden der Vorlage '{}' fehlgeschlagen!
Failed to load user for {} : Laden des Nutzers zu {} fehlgeschlagen!
Failed to load user for address {} : Laden des Nutzers für die Adresse {} fehlgeschlagen!
Failed to make {} a moderator of {} : Ernennen von {} zum Moderator von {} fehlgeschlagen!
Failed to make {} a subscriber of {} : Ernennen von {} zum regulären Abonnenten von {} fehlgeschlagen!
Failed to send reset email\: Versenden der Passwort-Zurücksetzen-Mail fehlgeschlagen:
Failed to send email to {} : Senden der Email an {} fehlgeschlagen!
Failed to send request confirmation email\: {} : Senden der Bestätigungs-Email fehlgeschlagen: {}
Failed to send test email to {} : Senden der Test-Email an {} fehlgeschlagen!
Failed to (un)hide mailing list\: : Veröffentlichen/Verstekcen der Mailing-Liste fehlgeschlagen:
Failed to un-subscribe {} from {} : Abbestellen von {} / {} fehlgeschlagen!
Failed to unsubscribe! : Abbestellen der Mailin-Liste fehlgeschlagen!
Failed to update list '{}' : Aktualisieren der Liste '{}' fehlgeschlagen!
Failed to update MailingList! : Aktualisierung der Mailing-Liste fehlgeschlagen!
Failed to update password in database! : Aktualisierung des Passworts in der Datenbank fehlgeschlagen!
Fill all fields, please! : Bitte alle Felder ausfüllen!
File {} does not exist! : Datei {} existiert nicht!
Find the forwarded message in the attachment(s)!\n : Die weitergeleitete Nachricht findest du im Anhang dieser E-Mail!\n
forward_attached : als Anhang weiterleiten
hidden : versteckt
hide_receivers : Empfänger verbergen
If that was you, please open the following link in your web browser\: : Falls Sie das waren, öffnen Sie den folgenden Link in einem Web-Browser:
If you did not expect this email, please ignore it. : Falls Sie diese Email nicht angefordert hatten, können Sie sie einfach ignorieren.
If you received this mail, the SMTP settings of your mailing list are correct. : Wenn Sie diese Nachricht empfangen haben, sind die SMTP-Einstellungen Ihrer Mailing-Liste korrekt.
IMAP credentials are required! : IMAP-Zugangsdaten sind erforderlich!
Invalid or missing token! : Ungültiger oder fehlender Token!
Invalid username/password : Ungültiger Nutzername oder ungültiges Passwort!
Invalid email/password combination! : Ungültige E-Mail-/Passwort-Kombination!
List '{}' requires attention! : Liste '{}' erfordert Aufmerksamkeit!
List {} disabled, closed for subscribers and hidden. Members have been removed. : Liste {} deaktiviert, Abonnement gesperrt, Liste de-publiziert. Mitglieder wurden entfernt.
List email ({}) is not a valid email address! : Listen-E-Mail-Adresse ({}) ist keine gültige E-Mail-Adresse!
List name and address are required! : Name und Adresse der Liste sind notwendige Felder!
made public : veröffentlicht
Mailing list '{}' was {}! : Mailing-Liste '{}' wurde {}!
Missing email address! : Email-Adresse fehlt!
Message deleted : Nachricht gelöscht
missing user email address! : E-Mail-Adresse des Listenmitglieds nicht angegeben!
Missing username or password! : Nutzername oder Passwort fehlen!
moderator : Moderator
Name and email are required fields for list subscription! : Name und E-Mail-Adresse sind für das Abonnieren der Mailingliste erforderlich!
no : nein
no active List found! : keine aktive Verteilerliste gefunden!
No handler for path {}! : Kein Handler für den Pfad '{}'!
no list email provided! : Keine Listen-Email übertragen!
No list provided by form data! : Formular-Daten enthalten keine Liste!
No such user\: {} : Kein solcher Nutzer: {}
No template for path '{}'! : Keine Vorlage für den Pfad '{}' vorhanden!
No valid mailing list provided! : Keine gültige MailingListe übermittelt!
no valid permissions provided! : Keine gültigen Berechtigungen übergeben!
Not logged in! : Nicht eingeloggt!
open_for_guests : Gästbeiträge erlaubt
open_for_subscribers : Selbstregistrierung
original_from : ursprünglicher Absender
owner : Besitzer
Passwords do not match! : Passworte stimmen nicht überein!
Password to short or to simple! : Passwort zu kurz oder zu einfach!
Please set a password! : Bitte geben Sie ein Passwort ein!
Problem during unscubsription of {} from {}\: : Es ist ein Problem beim Austragen von {} aus der Liste {} aufgetreten:
public : öffentlich
Query '{}' failed\: : Query '{}' fehlgeschlagen:
reply_to_list : Antwort an Liste
Reset your password at {} : Passwort auf {} zurücksetzen
Sent confirmation mail to '{}. : Bestätigungs-Email wurde an '{} versendet.
Somebody asked to reset your account password at {}. : Jemand hat eine Passwort-Änderung für Ihren Account auf {} angefordert.
SMTP credentials are required! : SMTP-Zugangsdaten sind erforderlich!
subscriber : Abonniert
Subscription failed\: {} : Abonnieren der Liste fehlgeschlagen: {}
Sucessfully updated MailingList! : Mailing-Liste aktualisiert!
Successfully subscribed '{}' to '{}'. : '{}' hat die Mailingliste '{}' erfolgreich abonniert.
Sucessfully un-subscribed from '{}'. : '{}' erfolgreich abbestellt.
Templates have been reloaded! : Vorlagen wurden neu geladen!
The mailing list you are trying to view does not exist! : Die Mailingliste, auf die Sie zugreifen wollen, gibt es nicht!
This list received an email from {}, who is not member of the list.\nThe email has been moved to the '{}' folder.\nYou may manually forward this message or drop it. : Diese Liste hat eine E-Mail von {} empfangen. Der Absender ist nicht Mitglied der Liste.\nDie Email wurde in den '{}'-Ordner verschoben.\nSie können die Nachricht manuell weiterleiten oder verwerfen.
Unknown user or token! : Nutzer oder Token unbekannt!
Updated user permissions : Nutzer-Berechtigungen aktualisiert
User database is empty. Create admin user first\: : Nutzer-Datenbank ist leer. Admin-Nutzer wird hiermit angelegt:
Was not able to check existence of table {}! : Konnte Existenz der Tabelle {} nicht prüfen!
Was not able to redirect to {} page\: {} : Weiterleitung nach {} fehlgeschlagen: {}
yes : ja
You already are member of this list! : Sie haben diese Liste bereits abonniert!
You are not allowed to access the archive of this list! : Du hast keine Berechtigung, das Archiv dieser Liste anzusehen!
You are not allowed to alter settings of this list! : Du hast keine Berechtigung, die Einstellungen dieser Liste zu ändern!
You are not allowed to alter user permissions! : Sie haben nicht die Berechtigung, um Berechtigungen zu ändern!
You are not allowed to create new mailing lists! : Ihnen ist es nicht gestattet, neue Mailinglisten anzulegen!
You are not allowed to edit '{}' : Du bist nicht berechtigt, '{}' zu bearbeiten!
You are not allowed to edit mods of {} : Es ist dir nicht gestattet, die Moderatoren von {} zu verändern!
You are not allowed to join {}! : Ihnen ist es nicht gestattet, '{}' zu abonnieren!
You are not allowed to list members of '{}' : Es ist dir nicht gestattet, die Mitglieder von '{}' aufzulisten!
You are not allowed to nominate new mods for {} : Es ist dir nicht gestattet, neue Moderatoren für {} zu ernennen!
You are not allowed to remove members of {} : Es ist dir nicht erlaubt, Mitglieder von {} zu entfernen!
You are not allowed to remove the list owner! : Du kannst den Listen-Besitzer nicht entfernen!
You are not allowed to remove this list! : Es ist dir nicht gestattet, diese Liste zu löschen!
You are not allowed to subscribe to '{}'! : Es ist ihnen nicht gestattet, '{}' zu abonnieren!
You are not allowed to test '{}' : Es ist dir nicht gestattet, '{}' zu testen
You are not alter settings of this list! : Es ist Ihnen nicht gestattet, die Einselltungen dieser Mailingliste zu verändern!
You are trying to access a non-existing list! : Du versuchst auf eine nicht existierende Liste zuzugreifen!
You have tried to send a message to the list '{}', which failed. This is because you are not a (privileged) member of this list.\n : Sie haben versucht, eine Nachricht an die Liste '{}' zu senden. Das wurde verweigert, da Sie kein Mitglied der Liste (mit entsprechenden Berechtigungen) sind.\n
You may go to {} and subscribe to the list, then try again. : Sie können zu {} gehen und die Liste abonnieren. Versuchen Sie es danach erneut.
Your message to {} was rejected! : Ihre Nachricht an {} wurde zurückgewiesen!
Your password is to simple! : Ihr Passwort ist zu einfach!
Your password has been updated! : Ihr Passwort wurde aktualisiert!

10
src/test/java/de/srsoftware/widerhall/data/ListMemberTest.java

@ -112,7 +112,7 @@ public class ListMemberTest extends TestCase { @@ -112,7 +112,7 @@ public class ListMemberTest extends TestCase {
public void testSafeMap() {
var user = new User("email","name","salt","hash",null,0);
var lm = new ListMember(null,user,ListMember.STATE_AWAITING_CONFIRMATION,"token");
assertEquals(Map.of(EMAIL,"email",NAME,"name",STATE,"erwartet Bestätigung"),lm.safeMap());
assertEquals(Map.of(EMAIL,"email",NAME,"name",STATE,"awaiting confirmation"),lm.safeMap());
}
public void testStateText() {
@ -121,10 +121,10 @@ public class ListMemberTest extends TestCase { @@ -121,10 +121,10 @@ public class ListMemberTest extends TestCase {
var mod = new ListMember(null,null,ListMember.STATE_MODERATOR,null);
var await = new ListMember(null,null,ListMember.STATE_AWAITING_CONFIRMATION,null);
assertEquals("Abonniert",guest.stateText());
assertEquals("Abonniert, Besitzer, Moderator",owner.stateText());
assertEquals("Abonniert, Moderator",mod.stateText());
assertEquals("erwartet Bestätigung",await.stateText());
assertEquals("subscriber",guest.stateText());
assertEquals("moderator, owner, subscriber",owner.stateText());
assertEquals("moderator, subscriber",mod.stateText());
assertEquals("awaiting confirmation",await.stateText());
}
public void testToken() {

2
static/templates/add_list.st

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
«navigation()»
«userinfo()»
«messages()»
<h1>Widerhall Listen-Erzeugung</h1>
<h1>Widerhall List Creation</h1>
«list_data_form()»
</body>
</html>

22
static/templates/archive.st

@ -5,21 +5,21 @@ @@ -5,21 +5,21 @@
«navigation()»
«userinfo()»
«messages()»
<h1>«data.list»&nbsp; &nbsp;Listen-Archiv</h1>
<h1>«data.list»&nbsp; &nbsp;List Archive</h1>
<fieldset>
<legend>Abonnement</legend>
<a href="subscribe?list=«data.list»">abonnieren</a>
<a href="unsubscribe?list=«data.list»">abbestellen</a>
<legend>Subscription</legend>
<a href="subscribe?list=«data.list»">subscribe</a>
<a href="unsubscribe?list=«data.list»">un-subscribe</a>
</fieldset>
«if(data.month)»
<table>
<tr>
<th>Datum</th>
<th>Absender</th>
<th>Betreff</th>
<th>Date</th>
<th>From</th>
<th>Subject</th>
«if (data.moderator)»
<th>Aktionen</th>
<th>Actions</th>
«endif»
</tr>
</table>
@ -29,8 +29,8 @@ @@ -29,8 +29,8 @@
«else»
<table>
<tr>
<th>Monat</th>
<th>Zahl der Nachrichten</th>
<th>Month</th>
<th>Number of messages</th>
</tr>
</table>
<script type="text/javascript">
@ -39,4 +39,4 @@ @@ -39,4 +39,4 @@
«endif»
«footer()»
</body>
</html>
</html>

16
static/templates/confirmation_mail.st

@ -1,17 +1,17 @@ @@ -1,17 +1,17 @@
Willkommen, «data.user.name»!
Welcome, «data.user.name»!
Du hast die «data.list.name»-Liste erfolgreich abonniert!
You successfully subscribed to the "«data.list.name»" Mailing list!
«if(data.open_list)»
Dabei handelt es sich um eine offene Liste. Das bedeutet, du kannst jederzeit E-Mails an «data.list.email.prefix»@«data.list.email.domain» senden, und wir werden diese an alle anderen Abonnenten weiterleiten.
This is an open list. This means you may, at any time, send emails to «data.list.email.prefix»@«data.list.email.domain» and we will forward your mail to the other subscribers.
«else»
Dabei handelt es sich um eine moderierte Liste. Das bedeutet, du (und alle anderen Abonnenten) empfangen die Mails von den Moderatoren. Wenn du jedoch auf Mails von der Liste antwortest, wird deine Antwort auch nur an die Moderatoren zugestelt!
This is a moderated list. This means, you (and all other subscribers) will receive any mails sent by a moderator. However, if you write (answer) messages to the list, only the moderators will receive your mail.
«endif»
Wenn du ausschließlich dem Absender einer Email, die über die Liste kam, antworten willst, findest du die entsprechende Adresse im Kopf der empfangenen E-Mail.
If you want to answer exclusively to the author of an email you received via the list, you may find the respective address in the head of the received email.
Wenn du die Liste verlassen willst, kannst du jederzeit zu «data.url» gehen um dein Abonnement zu kündigen.
If you wish to leave the list, you may, at any time, go to «data.url» and un-subscribe.
liebe Grüße,
best wishes,
Stephan Richter (der Software-Autor)
Stephan Richter (the software author)

2
static/templates/css.st

@ -21,7 +21,7 @@ form#list_data, @@ -21,7 +21,7 @@ form#list_data,
#login form,
#register form,
#subscribe form{
width: 500px;
width: 450px;
margin: 0 auto;
}

2
static/templates/edit_list.st

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
«navigation()»
«userinfo()»
«messages()»
<h1>Widerhall Listen-Bearbeitung</h1>
<h1>Widerhall List Setup</h1>
«list_data_form()»
«footer()»
</body>

6
static/templates/footer.st

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<div class="footer">
Widerhall Mail-Verteiler.
Version 1.0.5.
Hol dir den Quellcode auf <a target="_blank" href="https://git.srsoftware.de/StephanRichter/Widerhall/src/branch/lang_de">git.srsoftware.de</a>
Widerhall Mail Distributor.
Version 1.0.4.
Get the sources at <a target="_blank" href="https://git.srsoftware.de/StephanRichter/Widerhall">git.srsoftware.de</a>
</div>

33
static/templates/frontpage.st

@ -6,41 +6,40 @@ @@ -6,41 +6,40 @@
<link rel="stylesheet" href="web/css" />
</head>
<body>
<h1>Widerhall Startseite</h1>
Falls du zu den Mailing-Listen willst, <a href="web/index">Gehe zur Seite /web</a>...
<h1>Widerhall front page</h1>
If you are looking for you mailing lists, <a href="web/index">Go to the /web page</a>...
<fieldset>
<legend>Was ist <em>Widerhall</em>?</legend>
<legend>What is <em>Widerhall</em>?</legend>
<p>
Widerhall ist ein in Java geschriebenes Mailing-List-System.
Es erlaubt die Pflege von Mailverteilern mit der Option diese für Jedermann abonnierbar zu machen.
Widerhall is a mailing list system written in Java.
It allows to maintain a set of mailing lists with the option to make (some of) them publicy subscribable.
</p>
</fieldset>
<fieldset>
<legend>Warum sollte ich <em>Widerhall</em> nutzen?</legend>
<legend>Why should I use <em>Widerhall</em>?</legend>
<p>
Im Vergleich mit anderen Mailing-Listen-Systemen ist <em>Widerhall</em> sehr schlank:
</p>
Compared to other mailing list systems, Widerhall is very lightweight:
<p>
Es enthält keinen eigenen Mailserver. Für <em>Widerhall</em> musst du nichtmal einen eigenen Mailserver aufsetzen!
It contains no mailserver stack. It does not even require you to set up a mailserver!
</p>
</fieldset>
<fieldset>
<legend>Wie funktioniert das?</legend>
<legend>How does it work?</legend>
<p>
Bei Widerhall kannst du einfach eine IMAP/SMTP-fähige Emailadresse bei einem beliebigen Anbierter anlegen.
Danach verbindet sich Widerhall mit dem Posteingang der entsprechenden Email-Adresse und wartet auf dort eingehende Nachrichten.
Sobald eine Nachricht empfangen wird, wird diese an alle Abonnenten der Mailing-Liste weitergeleitet.
Widerhall works by just letting you set up any IMAP/SMTP enabled email address with a provider of your choice.
It then connects to the inbox of you selected email address and watches for incoming messages.
Upon message reception, it forwards the message to all subscribers of the mailing list.
</p>
<p>
Das ist alles.
That's it.
</p>
</fieldset>
<fieldset>
<legend>Credits</legend>
Ich bin allen Leuten, die mich beim Schreiben und Testen der Software unterstützt haben sehr dankbar:
I`m very grateful to the people who supported me writing and testing this software:
<ul>
<li>Erik Heinz dafür, dass er sein Wissen um das E-Mail-Protokoll und damit verbundene Fettnäpfchen mit mir geteilt hat</li>
<li>Stefanie Handke für Hinweise zum Design</li>
<li>Erik Heinz for sharing his knowledge on email protocols and pitfalls</li>
<li>Stefanie Handke for pointing me to CSS issues</li>
</ul>
</fieldset>
«footer()»

2
static/templates/index.st

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
«navigation()»
«userinfo()»
«messages()»
<h1>Widerhall Index-Seite</h1>
<h1>Widerhall Index page</h1>
«listlist()»
«footer()»
</body>

40
static/templates/inspect.st

@ -5,62 +5,62 @@ @@ -5,62 +5,62 @@
«navigation()»
«userinfo()»
«messages()»
<h1>Widerhall '«data.list»'-Details</h1>
<h1>Widerhall '«data.list»' Details</h1>
<form method="POST">
<fieldset>
<legend>Einstellungen</legend>
Diese Seite zeigt Konfigurations-Optionen für die Mailingliste. Um Login-Daten zu ändern, gehe zu <a href="edit_list?list=«data.list»">Listenbearbeitung</a>.
<legend>Settings</legend>
This page shows configuration options for the mailing list. To edit login credentials, goto <a href="edit_list?list=«data.list»">edit list</a>
<fieldset>
<legend>Weiterleitungs-Rechte</legend>
<legend>Forward permissions</legend>
<p>
Wem ist es erlaubt, Nachrichten via «data.list» zu verteilen?
Who is allowed to distribute mails via «data.list»?
</p>
Besitzer und Moderatoren
Oweners and Moderators
<label>
<input type="checkbox" name="open_for_subscribers" />
Allen Abonnenten
All subscribers
</label>
<label>
<input type="checkbox" name="open_for_guests" />
Allen (m.a.W.: auch Nicht-Abonnenten, GEFAHR!)
Everyone (i.e. non members, DANGER!)
</label>
</fieldset>
<fieldset>
<legend>Weiterleitungs-Optionen</legend>
<legend>Forward options</legend>
<label>
<input type="checkbox" name="forward_from"/>
Ursprünglichen Absender beim Weiterleiten verwenden
<input type="checkbox" name="forward_from" />
Forward using original sender
</label>
<label>
<input type="checkbox" name="reply_to_list" />
Listen-Adresse im ReplyTo-Header setzen
Set list adddress in "ReplyTo" header
</label>
<label>
<input type="checkbox" name="forward_attached" />
Ursprüngliche Nachricht beim Weiterleiten als Anhang versenden
Append original message as attachment
</label>
<label>
<input type="checkbox" name="hide_receivers" />
Emfänger voreinander verbergen (BCC benutzen)
Hide receivers (using BCC)
</label>
</fieldset>
<fieldset>
<legend>andere Optionen</legend>
<legend>Other options</legend>
<label>
<input type="checkbox" name="archive" />
Nachrichten in öffentlichem Archiv sammeln
Collect messages in public archive
</label>
<label>
<input type="checkbox" name="edit_mods" />
Moderatoren können die Liste der Moderatoren bearbeiten
Moderators may edit list of moderators
</label>
<label>
<input type="checkbox" name="delete_messages" />
Nachrichten nach
<input type="number" name="hold_time" /> Tagen löschen
Delete messages after
<input type="number" name="hold_time" /> days.
</label>
</fieldset>
<button type="submit">Speichern</button>
<button type="submit">Save</button>
</fieldset>
</form>
«listmembers()»

43
static/templates/js.st

@ -3,7 +3,7 @@ function addMod(userEmail,listEmail){ @@ -3,7 +3,7 @@ function addMod(userEmail,listEmail){
}
function addPermission(userEmail,permission){
if (confirm("Wirklich Berechtigung an "+userEmail+" geben?")){
if (confirm("Really give permission to "+userEmail+"?")){
$.post('/api/user/addpermission',{email:userEmail,permissions:permission},reload,'json');
}
}
@ -30,7 +30,7 @@ function dropMod(userEmail,listEmail){ @@ -30,7 +30,7 @@ function dropMod(userEmail,listEmail){
function dropPermission(userEmail,permission){
if (confirm("Wirklich Berechtigung von "+userEmail+" wegnehmen?")){
if (confirm("Really withdraw permission from "+userEmail+"?")){
$.post('/api/user/droppermission',{email:userEmail,permissions:permission},reload,'json');
}
}
@ -93,7 +93,7 @@ function showListArchive(data){ @@ -93,7 +93,7 @@ function showListArchive(data){
$('<td/>').html('<a href="'+url+'">'+post.from_name+'</a>').appendTo(row);
$('<td/>').html('<a href="'+url+'">'+post.subject+'</a>').appendTo(row);
if (moderator){
$('<button/>',{onclick:"dropMail('"+post.id+"');"}).text('Löschen').appendTo($('<td/>')).appendTo(row);
$('<button/>',{onclick:"dropMail('"+post.id+"');"}).text('Delete').appendTo($('<td/>')).appendTo(row);
}
row.appendTo($('#archive table'));
}
@ -145,18 +145,17 @@ function showListOfModeratedLists(data){ @@ -145,18 +145,17 @@ function showListOfModeratedLists(data){
let action = selected.val();
let verb = selected.text();
let list = $(this).attr('name');
if (confirm("Dies wird '"+list+"' "+verb+". Sind Sie sicher?")) self[action+'List'](list);
if (confirm("This will "+verb+" '"+list+"'. Are you sure?")) self[action+'List'](list);
});
$('<option/>').text('Aktionen').appendTo(select);
$('<option/>').text('Actions').appendTo(select);
Object.entries({
'enable':'aktivieren',
'disable':'deaktivieren',
'drop':'löschen',
'hide':'verstecken',
'show':'veröffentlichen',
'test':'testen'
'enable':'enable',
'disable':'disable',
'drop':'drop',
'hide':'hide',
'show':'show',
'test':'test'
}).forEach(([k,v],i) => {
$('<option/>',{value:k}).text(v).appendTo(select)
});
@ -189,8 +188,8 @@ function showListList(data){ @@ -189,8 +188,8 @@ function showListList(data){
}
$('<td/>').text(states.toString()).appendTo(row);
let td = $('<td/>',{class:'actions'});
$('<button/>',{onclick:"subscribeTo('"+email+"');"}).text('abonnieren').appendTo(td);
$('<button/>',{onclick:"unsubscribeFrom('"+email+"');"}).text('abbestellen').appendTo(td);
$('<button/>',{onclick:"subscribeTo('"+email+"');"}).text('subscribe').appendTo(td);
$('<button/>',{onclick:"unsubscribeFrom('"+email+"');"}).text('unsubcribe').appendTo(td);
td.appendTo(row);
row.appendTo('#listlist');
@ -220,10 +219,10 @@ function showMembers(data){ @@ -220,10 +219,10 @@ function showMembers(data){
$('<td/>').text(member.state).appendTo(row);
let col = $('<td/>');
console.log("data",data);
if (member.state.includes("Moderator")) {
if (!member.state.includes("Besitzer")) $('<button/>',{onclick:'dropMod("'+member.email+'","'+list_mail+'")'}).text("- Moderator").appendTo(col);
} else $('<button/>',{onclick:'addMod("'+member.email+'","'+list_mail+'")'}).text("+ Moderator").appendTo(col);
if (!member.state.includes("Besitzer")) $('<button/>',{onclick:'dropMember("'+member.email+'","'+list_mail+'")'}).text("entfernen").appendTo(col);
if (member.state.includes("moderator")) {
if (!member.state.includes("owner")) $('<button/>',{onclick:'dropMod("'+member.email+'","'+list_mail+'")'}).text("- moderator").appendTo(col);
} else $('<button/>',{onclick:'addMod("'+member.email+'","'+list_mail+'")'}).text("+ moderator").appendTo(col);
if (!member.state.includes("owner")) $('<button/>',{onclick:'dropMember("'+member.email+'","'+list_mail+'")'}).text("remove").appendTo(col);
col.appendTo(row);
row.appendTo('#memberlist');
@ -242,14 +241,14 @@ function showUserList(data){ @@ -242,14 +241,14 @@ function showUserList(data){
let permissions = $('<span/>');
if (isAdmin){
if (user.permissions.includes('admin')){
$('<button/>').text("- Admin").click(() => dropPermission(user.email,1)).appendTo(permissions);
$('<button/>').text("- admin").click(() => dropPermission(user.email,1)).appendTo(permissions);
} else {
$('<button/>').text("+ Admin").click(() => addPermission(user.email,1)).appendTo(permissions);
$('<button/>').text("+ admin").click(() => addPermission(user.email,1)).appendTo(permissions);
}
if (user.permissions.includes('create lists')){
$('<button/>').text("- Listen anlegen").click(() => dropPermission(user.email,2)).appendTo(permissions);
$('<button/>').text("- create lists").click(() => dropPermission(user.email,2)).appendTo(permissions);
} else {
$('<button/>').text("+ Listen anlegen").click(() => addPermission(user.email,2)).appendTo(permissions);
$('<button/>').text("+ create lists").click(() => addPermission(user.email,2)).appendTo(permissions);
}
}
permissions.appendTo(row);

24
static/templates/list_data_form.st

@ -1,19 +1,19 @@ @@ -1,19 +1,19 @@
<form id="list_data" method="POST">
<fieldset>
<legend>Listen-Konfiguration</legend>
<legend>List configuration</legend>
<fieldset>
<legend>Basisdaten</legend>
<legend>Basic data</legend>
<label>
<input type="text" name="name" value="«if(data.name)»«data.name»«else»«data.list.name»«endif»" id="name" />
Name der Mailing-Liste
List name
</label>
<label>
<input type="text" name="email" value="«if(data.email)»«data.email»«else»«data.list.email.prefix»@«data.list.email.domain»«endif»" id="email" />
Email-Adresse der ML
List E-Mail Address
</label>
</fieldset>
<fieldset>
<legend>IMAP-Protocoll</legend>
<legend>IMAP protocol</legend>
<label>
<input type="text" name="imap_host" value="«if(data.imap_host)»«data.imap_host»«else»«data.list.imap_host»«endif»" id="imap_host" />
Hostname
@ -24,19 +24,19 @@ @@ -24,19 +24,19 @@
</label>
<label>
<input type="text" name="imap_user" value="«if(data.imap_user)»«data.imap_user»«else»«data.list.imap_user»«endif»" id="imap_user" />
Benutzername
Username
</label>
<label>
<input type="password" name="imap_pass" value="«data.imap_pass»" id="imap_pass" />
Passwort
Password
</label>
<label>
<input type="text" name="inbox" value="«if(data.inbox)»«data.inbox»«else»INBOX«endif»" id="imap_inbox" />
Name des Posteingangs-Ordners
Inbox name
</label>
</fieldset>
<fieldset>
<legend>SMTP-Protocoll</legend>
<legend>SMTP protocol</legend>
<label>
<input type="text" name="smtp_host" value="«if(data.smtp_host)»«data.smtp_host»«else»«data.list.smtp_host»«endif»" id="smtp_host" />
Hostname
@ -47,13 +47,13 @@ @@ -47,13 +47,13 @@
</label>
<label>
<input type="text" name="smtp_user" value="«if(data.smtp_user)»«data.smtp_user»«else»«data.list.smtp_user»«endif»" id="smtp_user" />
Benutzername
Username
</label>
<label>
<input type="password" name="smtp_pass" value="«data.smtp_pass»" id="smtp_pass" />
Passwort
Password
</label>
</fieldset>
<button type="submit">Mailing-Liste speichern</button>
<button type="submit">Save mailing list</button>
</fieldset>
</form>

14
static/templates/listadminlist.st

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<fieldset>
<legend>Liste der (bearbeitbaren) Mailing-Listen</legend>
<legend>List of (editable) mailinglists</legend>
<table id="listlist">
<tr>
<th colspan="4">List</th>
@ -8,18 +8,18 @@ @@ -8,18 +8,18 @@
</tr>
<tr>
<th>Name</th>
<th>Adresse</th>
<th>Status</th>
<th>Letzter Fehler</th>
<th>Aktionen</th>
<th>Address</th>
<th>State</th>
<th>Last error</th>
<th>Actions</th>
<th>Host</th>
<th>Port</th>
<th>Posteingang</th>
<th>Inbox</th>
<th>Host</th>
<th>Port</th>
</tr>
</table>
<a href="add_list">Neue Mailing-Liste anlegen</a>
<a href="add_list">Add new mailing list</a>
<script type="text/javascript">
loadListOfModeratedLists();
</script>

12
static/templates/listlist.st

@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
<fieldset>
<legend>Liste der (frei abonnierbaren) Mailing-Listen</legend>
<legend>List of (public) mailinglists</legend>
<p>
Klicke auf den Name einer Liste, um deren Archiv einzusehen (falls aktiviert).
Click on the name of a list, to see it`s archive (if enabled).
</p>
<table id="listlist">
<tr>
<th>Listen-Name</th>
<th>Listen-Adresse</th>
<th>Status</th>
<th>Aktionen</th>
<th>List Name</th>
<th>List Address</th>
<th>State</th>
<th>Actions</th>
</tr>
</table>
<script type="text/javascript">

8
static/templates/listmembers.st

@ -1,11 +1,11 @@ @@ -1,11 +1,11 @@
<fieldset>
<legend>Abonnenten von «data.list»</legend>
<legend>Members of «data.list»</legend>
<table id="memberlist">
<tr>
<th>Name</th>
<th>E-Mail</th>
<th>Status</th>
<th>Aktionen</th>
<th>Email</th>
<th>State</th>
<th>Actions</th>
</tr>
</table>
<script type="text/javascript">

10
static/templates/login.st

@ -4,19 +4,19 @@ @@ -4,19 +4,19 @@
<body id="login">
«navigation()»
«messages()»
<h1>Widerhall Login</h1>
<h1>Widerhall login</h1>
<form method="POST">
<fieldset>
<legend>Zugangsdaten</legend>
<legend>Login credentials</legend>
<label>
<input type="text" name="email" value="«data.email»" id="email" />
E-Mail Adresse
Email address
</label>
<label>
<input type="password" name="pass" value="" id="password" />
Passwort
Password
</label>
<button type="submit">Einloggen</button>
<button type="submit">Login</button>
</fieldset>
</form>
<a href="reset-pw«if(data.email)»?email=«data.email»«endif»">Forgot password?</a>

2
static/templates/navigation.st

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
<script type="text/javascript">
if ('«data.user.permissions»'.includes('admin')){
$('<a/>',{class:'button',href:'reload'}).text('Templates neu laden').appendTo($('nav'));
$('<a/>',{class:'button',href:'reload'}).text('Reload templates').appendTo($('nav'));
}
</script>
</nav>

16
static/templates/new_password_form.st

@ -6,28 +6,28 @@ @@ -6,28 +6,28 @@
<body id="login">
«navigation()»
«messages()»
<h1>neues Account-Passwort setzen</h1>
<h1>Set new account password</h1>
<form method="POST">
<fieldset>
Hallo «if(data.user.name)»«data.user.name»«else»«data.user.email»«endif»! Du kannst hier ein neues Passwort für deinen Account «data.email» setzen:
<legend>Login-Daten</legend>
Dear «if(data.user.name)»«data.user.name»«else»«data.user.email»«endif», you may now set a new password for your account «data.email»:
<legend>Login credentials</legend>
<label>
<input enabled="false" value="«data.user.email»" />
Email-Adresse
Email address
</label>
<label>
<input type="password" name="password" value="" id="password" />
Passwort
Password
</label>
<label>
<input type="password" name="password-repeat" value="" id="password-repeat" />
Passwort (Wiederholung)
Password (repeat)
</label>
<input type="hidden" name="token" value="«data.token»" />
<button type="submit">neues Passwort speichern</button>
<button type="submit">Save new password</button>
</fieldset>
</form>
<a href="reset-pw">Passwort vergessen?</a>
<a href="reset-pw">Forgot password?</a>
</body>
</html>

10
static/templates/post.st

@ -5,22 +5,22 @@ @@ -5,22 +5,22 @@
«navigation()»
«userinfo()»
«messages()»
<h1>Widerhall-Archiv:</h1>
<h1>Widerhall Archive:</h1>
<table id="post">
<tr>
<th>Datum</th>
<th>Date</th>
<td>«data.date»</td>
</tr>
<tr>
<th>Absender</th>
<th>From</th>
<td>«data.from_name»</td>
</tr>
<tr>
<th>Betreff</th>
<th>Subject</th>
<td>«data.subject»</td>
</tr>
<tr>
<th>Inhalt</th>
<th>Content</th>
<td><pre>«data.text»</pre></td>
</tr>
</table>

14
static/templates/register.st

@ -4,28 +4,28 @@ @@ -4,28 +4,28 @@
<body id="register">
«navigation()»
«userinfo()»
<h1>Widerhall Nutzer-Registrierung</h1>
<h1>Widerhall user registration</h1>
«messages()»
<form method="POST" action="register">
<fieldset>
<legend>Zugangsdaten</legend>
<legend>User credentials</legend>
<label>
<input type="text" name="name" value="«data.name»" id="name" />
Ihr Name
Your name
</label>
<label>
<input type="text" name="email" value="«data.email»" id="email" />
E-Mail-Adresse
E-Mail Address
</label>
<label>
<input type="password" name="pass" value="" id="password" />
Passwort
Password
</label>
<label>
<input type="password" name="pass_repeat" value="" id="password_repeated" />
Passwort (wiederholen)
Password (repeat)
</label>
<button type="submit">Neuen Nutzer speichern</button>
<button type="submit">Save new user</button>
</fieldset>
</form>
«footer()»

13
static/templates/reset-pw.st

@ -4,18 +4,17 @@ @@ -4,18 +4,17 @@
<body id="login">
«navigation()»
«messages()»
<h1>Widerhall Passwort-Hilfe</h1>
<h1>Widerhall password recovery</h1>
<form method="POST">
<fieldset>
<legend>Passwort verloren?</legend>
Falls Sie ihr Passwort vergessen oder verloren haben, geben Sie bitte unten Ihre Emailadresse ein.
Nach dem Klicken des Passwort zurücksetzen-Links bekommen Sie eine Email mit einem Link.
Dieser Link erlaubt es Ihnen, ein neues Passwort zu vergeben.
<legend>Forgot password?</legend>
If you have lost or forgot your password, please enter your email below.
Upon pressing the "Reset password" button, you will be sent an email with a link allowing you to set a new password.
<label>
<input type="text" name="email" value="«data.email»" id="email" />
Email-Adresse
Email address
</label>
<button type="submit">Passwort zurücksetzen</button>
<button type="submit">Reset password</button>
</fieldset>
</form>
</body>

9
static/templates/reset_link_sent.st

@ -5,14 +5,13 @@ @@ -5,14 +5,13 @@
«navigation()»
«messages()»
<h1>Bestätigung</h1>
<h1>Confirmation</h1>
<fieldset>
<legend>
Link gesendet
Link sent
</legend>
Ihnen wurde eine Email gesendet:<br/>
Diese Mail enthält einen Link, welches beweist, dass Sie diese Emailadresse besitzen.
Wenn Sie den empfangenen Link in einem Webbrowser öffnen, können Sie ein neues Passwort vergeben.
An email was sent to you:<br/>
This mail contains a link, that proves you are in control about the resprective mail address. Open the received link in a web browser and you will be able to set a new password.
</fieldset>
</body>
</html>

22
static/templates/subscribe.st

@ -5,32 +5,32 @@ @@ -5,32 +5,32 @@
«navigation()»
«userinfo()»
«messages()»
<h1>Widerhall Abonnieren</h1>
<h1>Widerhall Subscription</h1>
<form method="POST">
<input type="hidden" name="list" value="«data.list»" />
<fieldset>
<legend>Abonnieren von "«data.list»"</legend>
<legend>Suscribe to "«data.list»"</legend>
<label>
<input type="text" name="name" value="«if(data.user)»«data.user.name»«else»«data.name»«endif»">
Name
</label>
<label>
<input type="text" name="email" value="«if(data.user)»«data.user.email»«else»«data.email»«endif»">
E-Mail
Email
</label>
<label>
<input type="password" name="password">
Passwort (optional)
Password (optional)
</label>
<button type="submit">Abonnieren</button>
<button type="submit">Subscribe</button>
</fieldset>
<fieldset>
<legend>Passwort oder nicht?</legend>
<h3>Pro Passwort</h3>
Du brauchst ein Passwort, wenn du verhindern willst, dass außer dir jemand dein Listen-Abo kündigt.
Auch wenn du vorhast, dich zum Listen-Moderator erheben zu lassen, wirst du ein Passwort brauchen.
<h3>Contra Passwort</h3>
Wenn du kein Moderator werden willst, und auch keine Lust hast dir noch ein Passwort zu merken, vergib keines!
<legend>Password or not?</legend>
<h3>pro password</h3>
You will need a password, if you don`t want anybody except you to un-subscribe you from the list.
Also, if you are about to receive a promotion to a list moderator, you will need a password.
<h3>contra password</h3>
If you won't get a promotion, and just don't want to remember another password, don`t set one.
</fieldset>
</form>
«footer()»

8
static/templates/subscribe_mail.st

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
Willkommen beim Abo-Service der Mailing-Liste «list_name»!
Welcome to the "«list_name»" Mailing list subscription!
Jemand wahrscheinlich du selbst hat versucht deine E-Mail bei der Liste zu registrieren!
Falls du das warst, geh bitte zu «url» , um dein Abonnement abzuschließen!
Someone, probably you, tried to register your email address!
If that was you, go to «url» in order to complete your list subscription.
Falls du dich gar nicht bei dieser Liste eintragen wolltest, kannst du die Mail einfach ignorieren.
If you did not wish to subscribe to the list, you may ignore this mail.

10
static/templates/unsubscribe.st

@ -5,19 +5,19 @@ @@ -5,19 +5,19 @@
«navigation()»
«userinfo()»
«messages()»
<h1>Widerhall Abonnieren</h1>
<h1>Widerhall Subscription</h1>
<form method="POST">
<fieldset>
<legend>"«data.list»" abbestellen</legend>
<legend>Un-subscribe from "«data.list»"</legend>
<label>
<input type="text" name="email" value="«if(data.email)»«data.email»«else»«data.user.email»«endif»">
E-Mail
Email
</label>
<label>
<input type="password" name="password">
Passwort (optional)
Password (optional)
</label>
<button type="submit">Abbestellen</button>
<button type="submit">Un-subscribe</button>
</fieldset>
</form>
«footer()»

2
static/templates/userinfo.st

@ -1,3 +1,3 @@ @@ -1,3 +1,3 @@
«if(data.user)»
<div class="user">Als <em>«data.user.name»</em> angemeldet</em></div>
<div class="user">Logged in as <em>«data.user.name»</em></div>
«endif»

14
static/templates/userlist.st

@ -1,15 +1,15 @@ @@ -1,15 +1,15 @@
<fieldset>
<legend>Nutzer-Liste</legend>
<legend>User list</legend>
<table id="userlist">
<tr>
<th>Benutzername</th>
<th>E-Mail</th>
<th>Passwort</th>
<th>Berechtigungen</th>
<th>Aktionen</th>
<th>User name</th>
<th>Email</th>
<th>Password</th>
<th>Permissions</th>
<th>Actions</th>
</tr>
</table>
<a href="register">neuen Nutzer anlegen</a>
<a href="register">Register new user</a>
<script type="text/javascript">
loadUserList();
</script>

Loading…
Cancel
Save